jejune 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,107 @@
1
+ #!/usr/bin/ruby
2
+ # encoding: utf-8
3
+ #--
4
+ # Copyright (c) 2010-2011 Kyle C. Yetter
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining
7
+ # a copy of this software and associated documentation files (the
8
+ # "Software"), to deal in the Software without restriction, including
9
+ # without limitation the rights to use, copy, modify, merge, publish,
10
+ # distribute, sublicense, and/or sell copies of the Software, and to
11
+ # permit persons to whom the Software is furnished to do so, subject to
12
+ # the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be
15
+ # included in all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+ #++
25
+
26
+
27
+ module Jejune::Data
28
+ define_string DOC, :outdent
29
+ define_string DDOC, :interpolate, :outdent
30
+ define_string STRING
31
+ define_string DSTRING, :interpolate
32
+
33
+ define_string( 'Q', :interpolate, :outdent )
34
+
35
+ define( 'q', :outdent => true ) do | manager, blob |
36
+ manager.jstring( blob.data, true )
37
+ end
38
+
39
+ define( 'w' ) do | manager, blob |
40
+ manager.split_words( blob.data ).to_json
41
+ end
42
+
43
+ define( 'embed' ) do | manager, blob |
44
+ lib = manager.string_value( blob.data )
45
+ path = manager.find_resource( lib, '', blob.delimiter == '<' ) ||
46
+ manager.find_library( lib, blob.delimiter == '<' )
47
+
48
+ manager.add_dependency( path )
49
+ content = path =~ /\.jjs$/i ? manager.load_file( path ).translate : File.read( path )
50
+ content.to_json
51
+ end
52
+
53
+ define( 'r' ) do | manager, blob |
54
+ data = blob.data
55
+ data.gsub!( /(\\*)(\s)/ ) { $1.length.even? ? $1 : $1[ 1, $1.length ] << $2 }
56
+ data.gsub!( %r(/), '\/' )
57
+ '/' << data << '/' << blob.flags
58
+ end
59
+
60
+ define( 'sass', :outdent => true ) do | manager, blob |
61
+ defined?( gem ) or require 'rubygems'
62
+ begin
63
+ gem 'sass'
64
+ rescue LoadError
65
+ end
66
+ require 'sass'
67
+
68
+ sass_source = manager.string_value( blob.data )
69
+ css = Sass.compile( sass_source )
70
+ blob.flags.include?( 'c' ) and css = manager.compress( css, 'css' )
71
+ manager.jstring( css )
72
+ end
73
+
74
+ define( 'loadSass' ) do | manager, blob |
75
+ lib = manager.string_value( blob.data )
76
+ path = manager.find_resource( lib, 'sass|scss|css|', blob.delimiter == '<' )
77
+ source = File.read( path )
78
+ manager.add_dependency( path )
79
+
80
+ defined?( gem ) or require 'rubygems'
81
+ begin
82
+ gem 'sass'
83
+ rescue LoadError
84
+ end
85
+ require 'sass'
86
+
87
+ css = Sass.compile( source )
88
+ blob.flags.include?( 'c' ) and css = manager.compress( css, 'css' )
89
+ manager.jstring( css )
90
+ end
91
+
92
+ define( 'y', :outdent => true ) do | manager, blob |
93
+ ::JSON.dump( ::YAML.load( blob.data ) )
94
+ end
95
+
96
+ define( 'loadYAML' ) do | manager, blob |
97
+ lib = manager.string_value( blob.data )
98
+ path = manager.find_resource( lib, 'yaml|yml|', blob.delimiter == '<' )
99
+ manager.add_dependency( path )
100
+ YAML.load_file( path ).to_json
101
+ end
102
+
103
+ define( 't', :outdent => true ) do | manager, blob |
104
+ require 'jejune/ejjs'
105
+ Jejune::EJJS.new( blob.data, :line => blob.line, :file => blob.file ).as_eval
106
+ end
107
+ end
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/ruby
2
+ # encoding: utf-8
3
+ #--
4
+ # Copyright (c) 2010-2011 Kyle C. Yetter
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining
7
+ # a copy of this software and associated documentation files (the
8
+ # "Software"), to deal in the Software without restriction, including
9
+ # without limitation the rights to use, copy, modify, merge, publish,
10
+ # distribute, sublicense, and/or sell copies of the Software, and to
11
+ # permit persons to whom the Software is furnished to do so, subject to
12
+ # the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be
15
+ # included in all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+ #++
25
+
26
+ module Jejune
27
+ module Constants
28
+ include TokenData
29
+
30
+ # pseudo-type used by the interpolation parser
31
+ CODE = PROGRAM
32
+
33
+ PROPERTY_DEFINITION_TYPES = Set[ GET, SET, COLON, ARROW ]
34
+ EXPRESSION_TYPES = Set[
35
+ AMP_ASGN, AND, AREF, ARRAY, ASGN, CALL, COLON, COMMA, DECR,
36
+ DELETE, DOT, EQ, EQQ, FALSE, GEQ, GREATER, HAT, HAT_ASGN,
37
+ ID, IN, INCR, INSTANCEOF, ITER, IVAR, LEQ, LESS, LSHIFT,
38
+ LSHIFT_ASGN, MINUS, MINUS_ASGN, MOD, MOD_ASGN, NEQ, NEQQ,
39
+ NEW, NOT, NULL, NUMBER, OBJECT, OR, PIPE, PIPE_ASGN, PLUS,
40
+ PLUS_ASGN, POST_DECR, POST_INCR, QMARK, REGEX, RSHIFT,
41
+ RSHIFT3, RSHIFT3_ASGN, RSHIFT_ASGN, SLASH, SLASH_ASGN, STAR,
42
+ STAR_ASGN, STRING, THIS, TILDE, TRUE, TYPEOF, UNDEFINED,
43
+ VOID, FUNCTION, ARROW, DSTRING, DDOC, DGENERAL, UPLUS, UMINUS
44
+ ]
45
+ PROPERTY_TYPES = Set[ STRING, ID, NUMBER ]
46
+
47
+ CATCH_TYPES = Set[ CATCH, FINALLY ]
48
+ FUNCTION_TYPES = Set[ ARROW, FUNCTION ]
49
+
50
+ OPERATOR_PRECEDENCE = Hash.new do | h, k |
51
+ name = TOKEN_NAMES[ k ] and
52
+ warn( "Jejune Token Type `#{ name }[#{ k }]' is not Jejune::Constants::OPERATOR_PRECEDENCE" )
53
+ h[ k ] = -1
54
+ end
55
+
56
+ op_list = <<-END
57
+ COMMA
58
+ ASGN AMP_ASGN HAT_ASGN LSHIFT_ASGN MINUS_ASGN MOD_ASGN OR_ASGN PIPE_ASGN PLUS_ASGN RSHIFT3_ASGN RSHIFT_ASGN SLASH_ASGN STAR_ASGN
59
+ QMARK
60
+ OR
61
+ AND
62
+ PIPE
63
+ HAT
64
+ AMP
65
+ EQ EQQ NEQ NEQQ
66
+ LESS GREATER LEQ GEQ INSTANCEOF IN
67
+ LSHIFT RSHIFT RSHIFT3
68
+ PLUS MINUS
69
+ STAR SLASH MOD
70
+ DELETE VOID TYPEOF INCR DECR UPLUS UMINUS TILDE NOT
71
+ POST_INCR POST_DECR
72
+ NEW CALL AREF DOT ITER
73
+ THIS IVAR ID NULL TRUE FALSE UNDEFINED STRING DOC REGEX ARRAY OBJECT FUNCTION
74
+ END
75
+
76
+ # use the list above to give each expression node
77
+ # a precedence number for use in situations such
78
+ # as determining whether code needs to be surrounded
79
+ # in parentheses to protect operator precedence in an expression
80
+ op_list.strip.split( $/ ).each_with_index do | line, index |
81
+ for name in line.strip.split( /\s+/ )
82
+ value = TokenData.const_get( name )
83
+ OPERATOR_PRECEDENCE[ value ] = index
84
+ end
85
+ end
86
+
87
+ DELIMS =
88
+ {
89
+ "@"=>"@", "+"=>"+", "`"=>"`", ","=>",", "!"=>"!", "-"=>"-",
90
+ "\""=>"\"", "."=>".", "#"=>"#", ":"=>":", "/"=>"/",
91
+ "$"=>"$", ";"=>";", "%"=>"%", "{"=>"}", "["=>"]", "|"=>"|",
92
+ "\\"=>"\\", "&"=>"&", "<"=>">", "="=>"=", "'"=>"'",
93
+ "~"=>"~", "^"=>"^", "("=>")", "?"=>"?", "*"=>"*"
94
+ }
95
+ OPEN_DELIM = /([#{ Regexp.escape( DELIMS.keys.join( '' ) ) }])/
96
+
97
+ DEFAULT_EXT = "jjs|js|"
98
+ BROWSERS = %w( opera firefox chrome )
99
+ end
100
+ end
101
+
102
+ module Jejune
103
+ include ANTLR3
104
+ RewriteStream = TokenRewriteStream
105
+ end
@@ -0,0 +1,144 @@
1
+ #!/usr/bin/ruby
2
+ # encoding: utf-8
3
+
4
+ #--
5
+ # Copyright (c) 2010-2011 Kyle C. Yetter
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining
8
+ # a copy of this software and associated documentation files (the
9
+ # "Software"), to deal in the Software without restriction, including
10
+ # without limitation the rights to use, copy, modify, merge, publish,
11
+ # distribute, sublicense, and/or sell copies of the Software, and to
12
+ # permit persons to whom the Software is furnished to do so, subject to
13
+ # the following conditions:
14
+ #
15
+ # The above copyright notice and this permission notice shall be
16
+ # included in all copies or substantial portions of the Software.
17
+ #
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
+ #++
26
+
27
+ module Jejune
28
+ module Data
29
+ class Handler
30
+ include Constants
31
+ include Utils
32
+
33
+ attr_reader :type, :processor
34
+
35
+ def initialize( type, options = {}, &processor )
36
+ @type = type
37
+ @string = @outdent = @interpolate = false
38
+ @processor = nil
39
+ configure( options, &processor )
40
+ end
41
+
42
+ def configure( options, &processor )
43
+ @processor = processor || options.fetch( :processor, @processor )
44
+ @interpolate = options.fetch( :interpolate, @interpolate )
45
+ @outdent = options.fetch( :outdent, @outdent )
46
+ @string = options.fetch( :string, @string )
47
+ end
48
+
49
+ def process( manager, blob )
50
+ blob.data = prepare( manager, blob )
51
+ @processor and blob.data = @processor.call( manager, blob )
52
+ return( blob.data )
53
+ end
54
+
55
+ def prepare( manager, blob )
56
+ @interpolate and return manager.interpolate( blob, @outdent )
57
+ source = blob.data
58
+ @outdent and source = manager.outdent( source )
59
+ @string ? blob.delimiter == "'" ? manager.jstring( source, "'" ) : manager.jstring( source ) : source
60
+ end
61
+
62
+ end
63
+
64
+ unless defined?( Blob )
65
+ Blob = Struct.new(
66
+ :type, :data, :delimiter, :prefix,
67
+ :flags, :file, :line, :column
68
+ )
69
+ end
70
+
71
+ class Blob
72
+ include Constants
73
+
74
+ def self.extract( token, type = nil )
75
+ source = token.text
76
+ if source =~ /\A%?\s*(\w*\s*)/
77
+ prefix, source = $&, $'
78
+ signifier = $1.to_s.strip
79
+ type ||= signifier.empty? ? 'Q' : signifier
80
+ else
81
+ prefix = ''
82
+ end
83
+ source =~ OPEN_DELIM or raise( "%p doesn't have a delimiter" % source )
84
+ delimiter, source, closer = $&, $', DELIMS[ $1 ]
85
+
86
+ data, d, flags = source.rpartition( closer )
87
+ new(
88
+ type || delimiter, data,
89
+ delimiter, prefix, flags,
90
+ token.source_name, token.line, token.column
91
+ )
92
+ end
93
+
94
+ def inspect
95
+ '' << prefix << delimiter << data << DELIMS[ delimiter ] << flags
96
+ end
97
+
98
+ def data_column
99
+ column + prefix.length + delimiter.length
100
+ end
101
+ end
102
+
103
+ end
104
+ end
105
+
106
+
107
+ module Jejune
108
+ module Data
109
+ include Constants
110
+ defined?( @@global_handlers ) or @@global_handlers = {}
111
+
112
+ def self.define( type, options = {}, &action )
113
+ @@global_handlers[ type ] = Handler.new( type, options, &action )
114
+ end
115
+
116
+ def self.define_string( type, *opts )
117
+ options = { :string => true }
118
+ for opt in opts
119
+ options[ opt ] = true
120
+ end
121
+ define( type, options )
122
+ end
123
+
124
+
125
+ # lazy attribute reader for
126
+ def data_handlers
127
+ @data_handlers ||= {}
128
+ end
129
+
130
+ def define_handler( type, options = {}, &action )
131
+ @data_handler[ type ] = Handler.new( type, options, &action )
132
+ end
133
+
134
+ def handler_for( blob )
135
+ type = blob.type
136
+ data_handlers.fetch( type ) do
137
+ @@global_handlers.fetch( type ) do
138
+ raise( "no data handler defined for `#{ type }'" )
139
+ end
140
+ end
141
+ end
142
+
143
+ end
144
+ end
@@ -0,0 +1,69 @@
1
+ #!/usr/bin/ruby
2
+ # encoding: utf-8
3
+ #
4
+ # author: Kyle Yetter
5
+ #
6
+
7
+ module Jejune
8
+ class DependencyScanner
9
+ include Constants
10
+ include Utils
11
+
12
+ attr_accessor :manager, :dependency_map, :file_stack, :file
13
+
14
+ def initialize( manager )
15
+ @manager = manager
16
+ @dependency_map = {}
17
+ @file_stack = []
18
+ end
19
+
20
+ def dependencies
21
+ out = {}
22
+ for path, set in @dependency_map
23
+ out[ path ] = set.to_a.sort
24
+ end
25
+ return out
26
+ end
27
+
28
+ def scan( file )
29
+ file = File.expand_path( file )
30
+ deps = @dependency_map[ file ] and return( deps )
31
+
32
+ deps = Set.new
33
+ dir = File.dirname( file )
34
+
35
+ open( file ) do | f |
36
+ f.grep( /^\s*%%\s*(include|require)\s*(\S.*)/ ) do
37
+ type, target = $1, $2.strip
38
+ case type
39
+ when 'require'
40
+ if dep = find_in_path_list( @manager.load_path, target, DEFAULT_EXT )
41
+ deps.add File.expand_path( dep )
42
+ end
43
+ when 'include'
44
+ if dep = find_in_directory( dir, target, DEFAULT_EXT )
45
+ deps.add File.expand_path( dep )
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+ @dependency_map[ file ] = deps
52
+ @file_stack.each do | f |
53
+ @dependency_map[ file ].merge( deps )
54
+ end
55
+
56
+ begin
57
+ @file_stack.push( file )
58
+ deps.grep( /\.jjs$/i ) do | child |
59
+ scan( child )
60
+ end
61
+ ensure
62
+ @file_stack.pop
63
+ end
64
+
65
+ return deps
66
+ end
67
+
68
+ end
69
+ end
@@ -0,0 +1,178 @@
1
+ #!/usr/bin/ruby
2
+ # encoding: utf-8
3
+ #--
4
+ # Copyright (c) 2010-2011 Kyle C. Yetter
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining
7
+ # a copy of this software and associated documentation files (the
8
+ # "Software"), to deal in the Software without restriction, including
9
+ # without limitation the rights to use, copy, modify, merge, publish,
10
+ # distribute, sublicense, and/or sell copies of the Software, and to
11
+ # permit persons to whom the Software is furnished to do so, subject to
12
+ # the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be
15
+ # included in all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+ #++
25
+
26
+ #require 'jejune/lo-fi-lexer'
27
+
28
+ module Jejune
29
+ class EJJS
30
+
31
+ #class Lexer < LoFiLexer::StatefulLexer
32
+ # state :line_start, :go_to => :template do
33
+ # rule( :indentation, /[^\n\r]+?(?=%\|)/ )
34
+ # rule( :comment_line, /(?:[^\n\r%\\]|\\[^\n\r])*%#([\n\r]*)\r?\n/, :text => 1 )
35
+ # delimited( :insert_indented, /%\|=?/, /\r?\n|\z/, :text => :body )
36
+ # delimited( :control_line, '%', /\r?\n|\z/, :text => :body )
37
+ # end
38
+ #
39
+ # state :template do
40
+ # rule( :newline, /\r?\n/, :go_to => :line_start )
41
+ # delimited( :comment, '<%#', '%>', :text => :body )
42
+ # delimited( :insert, '<%=', '%>', :text => :body )
43
+ # delimited( :control, '<%', '%>', :text => :body )
44
+ # rule( :literal, /(?:[^\r\n\\<]|\\[^\r\n]|<(?!%)|\\)+(?=<%|\r?\n|\z)/ )
45
+ # end
46
+ #end # class Lexer
47
+
48
+ module Compile
49
+ module_function
50
+
51
+ def scan( source, options = {} )
52
+ block_given? or return( enum_for( :scan, source, options ) )
53
+
54
+ s = SourceScanner.new( source, options )
55
+ line_start = true
56
+ until s.eos?
57
+ if line_start
58
+ case
59
+ when s.scan( %r< % \# ((?: [^\\\r\n]+ | \\ \r? \n | \\ . )*) (?: \r? \n | \z ) >x )
60
+ yield( :comment_line, s[ 1 ] )
61
+ when s.scan( %r< % ((?: [^\\\r\n]+ | \\ \r? \n | \\ . )*) (?: \r? \n | \z ) >x )
62
+ yield( :control_line, s[ 1 ] )
63
+ else
64
+ line_start = false
65
+ end
66
+ else
67
+ case
68
+ when s.scan( /\r?\n/ )
69
+ line_start = true
70
+ yield( :newline, s.matched )
71
+ when m = s.nested!( '<%#', '%>' )
72
+ content = m[ 3, m.length - 5 ].to_s
73
+ yield( :comment, content )
74
+ when m = s.nested!( '<%=', '%>' )
75
+ content = m[ 3, m.length - 5 ].to_s
76
+ yield( :insert, content )
77
+ when m = s.nested!( '<%', '%>' )
78
+ content = m[ 2, m.length - 4 ].to_s
79
+ yield( :control, content )
80
+ when s.scan( /(?:[^\r\n\\<]|\\[^\r\n]|<(?!%)|\\)+(?=<%|\r?\n|\z)/ )
81
+ text = s.matched
82
+ yield( :literal, text )
83
+ end
84
+ end
85
+
86
+
87
+ end
88
+ end
89
+
90
+ def compile( source, options = {} )
91
+ #lexer = Lexer.new( source.to_s, options )
92
+ var = options.fetch( :variable, '__data__' )
93
+ lines = []
94
+ line = []
95
+ indentation = ''
96
+ previous = nil
97
+ clear_line = false
98
+
99
+ scan( source, options ) do | type, text |
100
+ case type
101
+ when :literal
102
+ line << %(#{ var }.push( #{ str( text ) } ))
103
+ when :comment_line
104
+ line << "//" << text
105
+ clear_line = true
106
+ when :insert
107
+ line << %[#{ var }.push( #{ text } )]
108
+ when :newline
109
+ line << %[#{ var }.push( #{ str( text ) } )]
110
+ clear_line = true
111
+ when :control
112
+ line << text
113
+ when :control_line
114
+ line << text
115
+ clear_line = true
116
+ else
117
+ raise( "BUG: unknown token type `#{ type }' -- this shouldn't happen" )
118
+ end
119
+
120
+ if clear_line
121
+ lines << line.join( '; ' )
122
+ line = []
123
+ indentation = ''
124
+ clear_line = false
125
+ end
126
+ #previous = token.type
127
+ end
128
+
129
+ lines << line.join( '; ' )
130
+ return lines.join( "\n" )
131
+ end
132
+
133
+ def str( text )
134
+ JString.jstring( text )
135
+ end
136
+
137
+ end # module Compile
138
+
139
+ include Compile
140
+
141
+ attr_accessor :file, :line, :source, :parameters, :variable, :name, :js_body
142
+
143
+ def initialize( source, options = nil )
144
+ @source = source
145
+ if options
146
+ @variable = options.fetch( :variable, '__text__' )
147
+ @file = options.fetch( :file, '(erb)' )
148
+ @line = options.fetch( :line, 1 )
149
+ @name = options[ :name ]
150
+ @parameters = options[ :parameters ]
151
+ else
152
+ @variable = '__text__'
153
+ @file = '(ejs)'
154
+ @line = 1
155
+ @name = nil
156
+ @parameters = nil
157
+ end
158
+ jjs_output = compile( source, :variable => @variable, :file => @file, :line => @line )
159
+ @js_body = Jejune.translate( jjs_output, :file => @file, :line => @line )
160
+ end
161
+
162
+ def as_eval
163
+ "(#{ as_function })()"
164
+ end
165
+
166
+ def as_function
167
+ code = "function"
168
+ @name and code << " " << @name
169
+ code << ( @parameters ? @parameters.declaration : '()' )
170
+ code << " { var #{ @variable } = []; "
171
+ @parameters and code << @parameters.parsing_source
172
+ code << @js_body << "; "
173
+ code << "return #{ @variable }.join( '' ) }"
174
+ return code
175
+ end
176
+
177
+ end
178
+ end