coffee-script 0.3.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,1050 +0,0 @@
1
- module CoffeeScript
2
-
3
- # The abstract base class for all CoffeeScript nodes.
4
- # All nodes are implement a "compile_node" method, which performs the
5
- # code generation for that node. To compile a node, call the "compile"
6
- # method, which wraps "compile_node" in some extra smarts, to know when the
7
- # generated code should be wrapped up in a closure. An options hash is passed
8
- # and cloned throughout, containing messages from higher in the AST,
9
- # information about the current scope, and indentation level.
10
- class Node
11
- # Tabs are two spaces for pretty-printing.
12
- TAB = ' '
13
-
14
- # Tag this node as a statement, meaning that it can't be used directly as
15
- # the result of an expression.
16
- def self.statement
17
- class_eval "def statement?; true; end"
18
- end
19
-
20
- # Tag this node as a statement that cannot be transformed into an expression.
21
- # (break, continue, etc.) It doesn't make sense to try to transform it.
22
- def self.statement_only
23
- statement
24
- class_eval "def statement_only?; true; end"
25
- end
26
-
27
- # This node needs to know if it's being compiled as a top-level statement,
28
- # in order to compile without special expression conversion.
29
- def self.top_sensitive
30
- class_eval "def top_sensitive?; true; end"
31
- end
32
-
33
- # Provide a quick implementation of a children method.
34
- def self.children(*attributes)
35
- attr_reader(*attributes)
36
- attrs = attributes.map {|a| "[@#{a}]" }.join(', ')
37
- class_eval "def children; [#{attrs}].flatten.compact; end"
38
- end
39
-
40
- def write(code)
41
- puts "#{self.class.to_s}:\n#{@options.inspect}\n#{code}\n\n" if ENV['VERBOSE']
42
- code
43
- end
44
-
45
- # This is extremely important -- we convert JS statements into expressions
46
- # by wrapping them in a closure, only if it's possible, and we're not at
47
- # the top level of a block (which would be unnecessary), and we haven't
48
- # already been asked to return the result.
49
- def compile(o={})
50
- @options = o.dup
51
- @indent = o[:indent]
52
- top = self.top_sensitive? ? @options[:top] : @options.delete(:top)
53
- closure = statement? && !statement_only? && !top && !@options[:return] && !self.is_a?(CommentNode)
54
- closure &&= !contains? {|n| n.statement_only? }
55
- closure ? compile_closure(@options) : compile_node(@options)
56
- end
57
-
58
- # Statements converted into expressions share scope with their parent
59
- # closure, to preserve JavaScript-style lexical scope.
60
- def compile_closure(o={})
61
- @indent = o[:indent]
62
- ClosureNode.wrap(self).compile(o.merge(:shared_scope => o[:scope]))
63
- end
64
-
65
- # Quick short method for the current indentation level, plus tabbing in.
66
- def idt(tabs=0)
67
- @indent + (TAB * tabs)
68
- end
69
-
70
- # Does this node, or any of it's children, contain a node of a certain kind?
71
- def contains?(&block)
72
- children.each do |node|
73
- return true if yield(node)
74
- return true if node.is_a?(Node) && node.contains?(&block)
75
- end
76
- false
77
- end
78
-
79
- # Default implementations of the common node methods.
80
- def unwrap; self; end
81
- def children; []; end
82
- def statement?; false; end
83
- def statement_only?; false; end
84
- def top_sensitive?; false; end
85
- end
86
-
87
- # A collection of nodes, each one representing an expression.
88
- class Expressions < Node
89
- statement
90
- children :expressions
91
- attr_accessor :function
92
-
93
- TRAILING_WHITESPACE = /\s+$/
94
-
95
- # Wrap up a node as an Expressions, unless it already is.
96
- def self.wrap(*nodes)
97
- return nodes[0] if nodes.length == 1 && nodes[0].is_a?(Expressions)
98
- Expressions.new(*nodes)
99
- end
100
-
101
- def initialize(*nodes)
102
- @expressions = nodes.flatten
103
- end
104
-
105
- # Tack an expression on to the end of this expression list.
106
- def <<(node)
107
- @expressions << node
108
- self
109
- end
110
-
111
- # Tack an expression on to the beginning of this expression list.
112
- def unshift(node)
113
- @expressions.unshift(node)
114
- self
115
- end
116
-
117
- # If this Expressions consists of a single node, pull it back out.
118
- def unwrap
119
- @expressions.length == 1 ? @expressions.first : self
120
- end
121
-
122
- # Is this an empty block of code?
123
- def empty?
124
- @expressions.empty?
125
- end
126
-
127
- # Is the node last in this block of expressions.
128
- def last?(node)
129
- @last_index ||= @expressions.last.is_a?(CommentNode) ? -2 : -1
130
- node == @expressions[@last_index]
131
- end
132
-
133
- def compile(o={})
134
- o[:scope] ? super(o) : compile_root(o)
135
- end
136
-
137
- # Compile each expression in the Expressions body.
138
- def compile_node(options={})
139
- write(@expressions.map {|n| compile_expression(n, options.dup) }.join("\n"))
140
- end
141
-
142
- # If this is the top-level Expressions, wrap everything in a safety closure.
143
- def compile_root(o={})
144
- indent = o[:no_wrap] ? '' : TAB
145
- @indent = indent
146
- o.merge!(:indent => indent, :scope => Scope.new(nil, self, nil))
147
- code = o[:globals] ? compile_node(o) : compile_with_declarations(o)
148
- code.gsub!(TRAILING_WHITESPACE, '')
149
- write(o[:no_wrap] ? code : "(function(){\n#{code}\n})();")
150
- end
151
-
152
- # Compile the expressions body, with declarations of all inner variables
153
- # at the top.
154
- def compile_with_declarations(o={})
155
- code = compile_node(o)
156
- args = self.contains? {|n| n.is_a?(ValueNode) && n.arguments? }
157
- argv = args && o[:scope].check('arguments') ? '' : 'var '
158
- code = "#{idt}#{argv}arguments = Array.prototype.slice.call(arguments, 0);\n#{code}" if args
159
- code = "#{idt}var #{o[:scope].compiled_assignments};\n#{code}" if o[:scope].assignments?(self)
160
- code = "#{idt}var #{o[:scope].compiled_declarations};\n#{code}" if o[:scope].declarations?(self)
161
- write(code)
162
- end
163
-
164
- # Compiles a single expression within the expression list.
165
- def compile_expression(node, o)
166
- @indent = o[:indent]
167
- stmt = node.statement?
168
- # We need to return the result if this is the last node in the expressions body.
169
- returns = o.delete(:return) && last?(node) && !node.statement_only?
170
- # Return the regular compile of the node, unless we need to return the result.
171
- return "#{stmt ? '' : idt}#{node.compile(o.merge(:top => true))}#{stmt ? '' : ';'}" unless returns
172
- # If it's a statement, the node knows how to return itself.
173
- return node.compile(o.merge(:return => true)) if node.statement?
174
- # If it's not part of a constructor, we can just return the value of the expression.
175
- return "#{idt}return #{node.compile(o)};" unless o[:scope].function && o[:scope].function.constructor?
176
- # It's the last line of a constructor, add a safety check.
177
- temp = o[:scope].free_variable
178
- "#{idt}#{temp} = #{node.compile(o)};\n#{idt}return #{o[:scope].function.name} === this.constructor ? this : #{temp};"
179
- end
180
-
181
- end
182
-
183
- # Literals are static values that have a Ruby representation, eg.: a string, a number,
184
- # true, false, nil, etc.
185
- class LiteralNode < Node
186
- children :value
187
-
188
- # Values of a literal node that much be treated as a statement -- no
189
- # sense returning or assigning them.
190
- STATEMENTS = ['break', 'continue']
191
-
192
- # Wrap up a compiler-generated string as a LiteralNode.
193
- def self.wrap(string)
194
- self.new(Value.new(string))
195
- end
196
-
197
- def initialize(value)
198
- @value = value
199
- end
200
-
201
- def statement?
202
- STATEMENTS.include?(@value.to_s)
203
- end
204
- alias_method :statement_only?, :statement?
205
-
206
- def compile_node(o)
207
- indent = statement? ? idt : ''
208
- ending = statement? ? ';' : ''
209
- "#{indent}#{@value}#{ending}"
210
- end
211
- end
212
-
213
- # Return an expression, or wrap it in a closure and return it.
214
- class ReturnNode < Node
215
- statement_only
216
- children :expression
217
-
218
- def initialize(expression)
219
- @expression = expression
220
- end
221
-
222
- def compile_node(o)
223
- return write(@expression.compile(o.merge(:return => true))) if @expression.statement?
224
- compiled = @expression.compile(o)
225
- write(@expression.statement? ? "#{compiled}\n#{idt}return null;" : "#{idt}return #{compiled};")
226
- end
227
- end
228
-
229
- # Pass through CoffeeScript comments into JavaScript comments at the
230
- # same position.
231
- class CommentNode < Node
232
- statement
233
-
234
- def initialize(lines)
235
- @lines = lines.value
236
- end
237
-
238
- def compile_node(o={})
239
- delimiter = "\n#{idt}//"
240
- write("#{delimiter}#{@lines.join(delimiter)}")
241
- end
242
-
243
- end
244
-
245
- # Node for a function invocation. Takes care of converting super() calls into
246
- # calls against the prototype's function of the same name.
247
- class CallNode < Node
248
- children :variable, :arguments
249
-
250
- def initialize(variable, arguments=[])
251
- @variable, @arguments = variable, arguments
252
- @prefix = ''
253
- end
254
-
255
- def new_instance
256
- @prefix = "new "
257
- self
258
- end
259
-
260
- def <<(argument)
261
- @arguments << argument
262
- self
263
- end
264
-
265
- # Compile a vanilla function call.
266
- def compile_node(o)
267
- return write(compile_splat(o)) if @arguments.any? {|a| a.is_a?(SplatNode) }
268
- args = @arguments.map{|a| a.compile(o) }.join(', ')
269
- return write(compile_super(args, o)) if @variable == 'super'
270
- write("#{@prefix}#{@variable.compile(o)}(#{args})")
271
- end
272
-
273
- # Compile a call against the superclass's implementation of the current function.
274
- def compile_super(args, o)
275
- methname = o[:scope].function.name
276
- arg_part = args.empty? ? '' : ", #{args}"
277
- meth = o[:scope].function.proto ?
278
- "#{o[:scope].function.proto}.__superClass__.#{methname}" :
279
- "#{methname}.__superClass__.constructor"
280
- "#{meth}.call(this#{arg_part})"
281
- end
282
-
283
- # Compile a function call being passed variable arguments.
284
- def compile_splat(o)
285
- meth = @variable.compile(o)
286
- obj = @variable.source || 'this'
287
- args = @arguments.map do |arg|
288
- code = arg.compile(o)
289
- code = arg.is_a?(SplatNode) ? code : "[#{code}]"
290
- arg.equal?(@arguments.first) ? code : ".concat(#{code})"
291
- end
292
- "#{@prefix}#{meth}.apply(#{obj}, #{args.join('')})"
293
- end
294
-
295
- # If the code generation wished to use the result of a function call
296
- # in multiple places, ensure that the function is only ever called once.
297
- def compile_reference(o)
298
- reference = o[:scope].free_variable
299
- call = ParentheticalNode.new(AssignNode.new(reference, self))
300
- return call, reference
301
- end
302
- end
303
-
304
- # Node to extend an object's prototype with an ancestor object.
305
- # After goog.inherits from the Closure Library.
306
- class ExtendsNode < Node
307
- children :sub_object, :super_object
308
- statement
309
-
310
- def initialize(sub_object, super_object)
311
- @sub_object, @super_object = sub_object, super_object
312
- end
313
-
314
- # Hooking one constructor into another's prototype chain.
315
- def compile_node(o={})
316
- constructor = o[:scope].free_variable
317
- sub, sup = @sub_object.compile(o), @super_object.compile(o)
318
- "#{idt}#{constructor} = function(){};\n#{idt}" +
319
- "#{constructor}.prototype = #{sup}.prototype;\n#{idt}" +
320
- "#{sub}.__superClass__ = #{sup}.prototype;\n#{idt}" +
321
- "#{sub}.prototype = new #{constructor}();\n#{idt}" +
322
- "#{sub}.prototype.constructor = #{sub};"
323
- end
324
-
325
- end
326
-
327
- # A value, indexed or dotted into, or vanilla.
328
- class ValueNode < Node
329
- children :base, :properties
330
- attr_reader :last, :source
331
-
332
- # Soak up undefined properties and call attempts.
333
- SOAK = " == undefined ? undefined : "
334
-
335
- def initialize(base, properties=[])
336
- @base, @properties = base, [properties].flatten
337
- end
338
-
339
- def <<(other)
340
- @properties << other
341
- self
342
- end
343
-
344
- def properties?
345
- return !@properties.empty? || @base.is_a?(ThisNode)
346
- end
347
-
348
- def array?
349
- @base.is_a?(ArrayNode) && !properties?
350
- end
351
-
352
- def object?
353
- @base.is_a?(ObjectNode) && !properties?
354
- end
355
-
356
- def splice?
357
- properties? && @properties.last.is_a?(SliceNode)
358
- end
359
-
360
- def arguments?
361
- @base.to_s == 'arguments'
362
- end
363
-
364
- def unwrap
365
- @properties.empty? ? @base : self
366
- end
367
-
368
- # Values are statements if their base is a statement.
369
- def statement?
370
- @base.is_a?(Node) && @base.statement? && !properties?
371
- end
372
-
373
- def compile_node(o)
374
- soaked = false
375
- only = o.delete(:only_first)
376
- props = only ? @properties[0...-1] : @properties
377
- baseline = @base.compile(o)
378
- parts = [baseline.dup]
379
- props.each do |prop|
380
- if prop.is_a?(AccessorNode) && prop.soak
381
- soaked = true
382
- if @base.is_a?(CallNode) && prop == props.first
383
- temp = o[:scope].free_variable
384
- parts[-1] = "(#{temp} = #{baseline})#{SOAK}#{baseline = temp.to_s + prop.compile(o)}"
385
- else
386
- parts[-1] << "#{SOAK}#{baseline += prop.compile(o)}"
387
- end
388
- else
389
- part = prop.compile(o)
390
- baseline += part
391
- parts << part
392
- end
393
- end
394
- @last = parts.last
395
- @source = parts.length > 1 ? parts[0...-1].join('') : nil
396
- code = parts.join('').gsub(')())', '()))')
397
- write(soaked ? "(#{code})" : code)
398
- end
399
- end
400
-
401
- # A dotted accessor into a part of a value, or the :: shorthand for
402
- # an accessor into the object's prototype.
403
- class AccessorNode < Node
404
- children :name
405
- attr_reader :soak
406
-
407
- def initialize(name, tag=nil)
408
- @name = name
409
- @prototype = tag == :prototype
410
- @soak = tag == :soak
411
- end
412
-
413
- def compile_node(o)
414
- proto = @prototype ? "prototype." : ''
415
- write(".#{proto}#{@name}")
416
- end
417
- end
418
-
419
- # An indexed accessor into a part of an array or object.
420
- class IndexNode < Node
421
- children :index
422
-
423
- def initialize(index)
424
- @index = index
425
- end
426
-
427
- def compile_node(o)
428
- write("[#{@index.compile(o)}]")
429
- end
430
- end
431
-
432
- # A this-reference, using '@'.
433
- class ThisNode < Node
434
- def initialize(property=nil)
435
- @property = property
436
- end
437
-
438
- def compile_node(o)
439
- prop = @property ? ".#{@property}" : ''
440
- write("this#{prop}")
441
- end
442
- end
443
-
444
- # A range literal. Ranges can be used to extract portions (slices) of arrays,
445
- # or to specify a range for array comprehensions.
446
- class RangeNode < Node
447
- children :from, :to
448
-
449
- def initialize(from, to, exclusive=false)
450
- @from, @to, @exclusive = from, to, exclusive
451
- end
452
-
453
- def exclusive?
454
- @exclusive
455
- end
456
-
457
- def compile_variables(o)
458
- @indent = o[:indent]
459
- @from_var, @to_var = o[:scope].free_variable, o[:scope].free_variable
460
- from_val, to_val = @from.compile(o), @to.compile(o)
461
- write("#{@from_var} = #{from_val}; #{@to_var} = #{to_val};\n#{idt}")
462
- end
463
-
464
- def compile_node(o)
465
- return compile_array(o) unless o[:index]
466
- idx, step = o.delete(:index), o.delete(:step)
467
- vars = "#{idx}=#{@from_var}"
468
- step = step ? step.compile(o) : '1'
469
- equals = @exclusive ? '' : '='
470
- compare = "(#{@from_var} <= #{@to_var} ? #{idx} <#{equals} #{@to_var} : #{idx} >#{equals} #{@to_var})"
471
- incr = "(#{@from_var} <= #{@to_var} ? #{idx} += #{step} : #{idx} -= #{step})"
472
- write("#{vars}; #{compare}; #{incr}")
473
- end
474
-
475
- # Expand the range into the equivalent array, if it's not being used as
476
- # part of a comprehension, slice, or splice.
477
- # TODO: This generates pretty ugly code ... shrink it.
478
- def compile_array(o)
479
- body = Expressions.wrap(LiteralNode.wrap('i'))
480
- arr = Expressions.wrap(ForNode.new(body, {:source => ValueNode.new(self)}, Value.new('i')))
481
- ParentheticalNode.new(CallNode.new(CodeNode.new([], arr))).compile(o)
482
- end
483
-
484
- end
485
-
486
- # An array slice literal. Unlike JavaScript's Array#slice, the second parameter
487
- # specifies the index of the end of the slice (just like the first parameter)
488
- # is the index of the beginning.
489
- class SliceNode < Node
490
- children :range
491
-
492
- def initialize(range)
493
- @range = range
494
- end
495
-
496
- def compile_node(o)
497
- from = @range.from.compile(o)
498
- to = @range.to.compile(o)
499
- plus_part = @range.exclusive? ? '' : ' + 1'
500
- write(".slice(#{from}, #{to}#{plus_part})")
501
- end
502
- end
503
-
504
- # Setting the value of a local variable, or the value of an object property.
505
- class AssignNode < Node
506
- top_sensitive
507
- children :variable, :value
508
-
509
- PROTO_ASSIGN = /\A(\S+)\.prototype/
510
- LEADING_DOT = /\A\.(prototype\.)?/
511
-
512
- def initialize(variable, value, context=nil)
513
- @variable, @value, @context = variable, value, context
514
- end
515
-
516
- def compile_node(o)
517
- top = o.delete(:top)
518
- return compile_pattern_match(o) if statement?
519
- return compile_splice(o) if value? && @variable.splice?
520
- stmt = o.delete(:as_statement)
521
- name = @variable.compile(o)
522
- last = value? ? @variable.last.to_s.sub(LEADING_DOT, '') : name
523
- proto = name[PROTO_ASSIGN, 1]
524
- if @value.is_a?(CodeNode)
525
- @value.name = last if last.match(Lexer::IDENTIFIER)
526
- @value.proto = proto if proto
527
- end
528
- return write("#{name}: #{@value.compile(o)}") if @context == :object
529
- o[:scope].find(name) unless value? && @variable.properties?
530
- val = "#{name} = #{@value.compile(o)}"
531
- return write("#{idt}#{val};") if stmt
532
- val = "(#{val})" if !top || o[:return]
533
- val = "#{idt}return #{val}" if o[:return]
534
- write(val)
535
- end
536
-
537
- def value?
538
- @variable.is_a?(ValueNode)
539
- end
540
-
541
- def statement?
542
- value? && (@variable.array? || @variable.object?)
543
- end
544
-
545
- # Implementation of recursive pattern matching, when assigning array or
546
- # object literals to a value. Peeks at their properties to assign inner names.
547
- # See: http://wiki.ecmascript.org/doku.php?id=harmony:destructuring
548
- def compile_pattern_match(o)
549
- val_var = o[:scope].free_variable
550
- assigns = ["#{idt}#{val_var} = #{@value.compile(o)};"]
551
- o.merge!(:top => true, :as_statement => true)
552
- @variable.base.objects.each_with_index do |obj, i|
553
- obj, i = obj.value, obj.variable.base if @variable.object?
554
- access_class = @variable.array? ? IndexNode : AccessorNode
555
- if obj.is_a?(SplatNode)
556
- val = LiteralNode.wrap(obj.compile_value(o, val_var, @variable.base.objects.index(obj)))
557
- else
558
- val = ValueNode.new(val_var, [access_class.new(Value.new(i.to_s))])
559
- end
560
- assigns << AssignNode.new(obj, val).compile(o)
561
- end
562
- write(assigns.join("\n"))
563
- end
564
-
565
- def compile_splice(o)
566
- var = @variable.compile(o.merge(:only_first => true))
567
- range = @variable.properties.last.range
568
- plus = range.exclusive? ? '' : ' + 1'
569
- from = range.from.compile(o)
570
- to = "#{range.to.compile(o)} - #{from}#{plus}"
571
- write("#{var}.splice.apply(#{var}, [#{from}, #{to}].concat(#{@value.compile(o)}))")
572
- end
573
- end
574
-
575
- # Simple Arithmetic and logical operations. Performs some conversion from
576
- # CoffeeScript operations into their JavaScript equivalents.
577
- class OpNode < Node
578
- children :first, :second
579
- attr_reader :operator
580
- attr_accessor :second
581
-
582
- CONVERSIONS = {
583
- :== => "===",
584
- :'!=' => "!==",
585
- :and => '&&',
586
- :or => '||',
587
- :is => '===',
588
- :isnt => "!==",
589
- :not => '!'
590
- }
591
- CHAINABLE = [:<, :>, :>=, :<=, :===, :'!===']
592
- ASSIGNMENT = [:'||=', :'&&=', :'?=']
593
- PREFIX_OPERATORS = [:typeof, :delete]
594
-
595
- def initialize(operator, first, second=nil, flip=false)
596
- @first, @second, @flip = first, second, flip
597
- @operator = CONVERSIONS[operator.to_sym] || operator
598
- end
599
-
600
- def unary?
601
- @second.nil?
602
- end
603
-
604
- def chainable?
605
- CHAINABLE.include?(operator.to_sym)
606
- end
607
-
608
- def compile_node(o)
609
- return write(compile_chain(o)) if chainable? && @first.unwrap.is_a?(OpNode) && @first.unwrap.chainable?
610
- return write(compile_assignment(o)) if ASSIGNMENT.include?(@operator.to_sym)
611
- return write(compile_unary(o)) if unary?
612
- return write(compile_existence(o)) if @operator == '?'
613
- write("#{@first.compile(o)} #{@operator} #{@second.compile(o)}")
614
- end
615
-
616
- # Mimic Python's chained comparisons. See:
617
- # http://docs.python.org/reference/expressions.html#notin
618
- def compile_chain(o)
619
- shared = @first.unwrap.second
620
- @first.second, shared = *shared.compile_reference(o) if shared.is_a?(CallNode)
621
- "(#{@first.compile(o)}) && (#{shared.compile(o)} #{@operator} #{@second.compile(o)})"
622
- end
623
-
624
- def compile_assignment(o)
625
- first, second = @first.compile(o), @second.compile(o)
626
- o[:scope].find(first) if @first.unwrap.is_a?(Value)
627
- sym = @operator[0..1]
628
- return "#{first} = #{ExistenceNode.compile_test(o, @first)} ? #{first} : #{second}" if @operator == '?='
629
- "#{first} = #{first} #{sym} #{second}"
630
- end
631
-
632
- def compile_existence(o)
633
- first, second = @first.compile(o), @second.compile(o)
634
- "#{ExistenceNode.compile_test(o, @first)} ? #{first} : #{second}"
635
- end
636
-
637
- def compile_unary(o)
638
- space = PREFIX_OPERATORS.include?(@operator.to_sym) ? ' ' : ''
639
- parts = [@operator.to_s, space, @first.compile(o)]
640
- parts.reverse! if @flip
641
- parts.join('')
642
- end
643
- end
644
-
645
- # A function definition. The only node that creates a new Scope.
646
- # A CodeNode does not have any children -- they're within the new scope.
647
- class CodeNode < Node
648
- top_sensitive
649
- attr_reader :params, :body, :bound
650
- attr_accessor :name, :proto
651
-
652
- # Constructor functions start with an uppercase letter, by convention.
653
- UPPERCASE = /[A-Z]/
654
-
655
- def initialize(params, body, tag=nil)
656
- @params = params
657
- @body = body
658
- @bound = tag == :boundfunc
659
- end
660
-
661
- def constructor?
662
- @name && @name[0..0][UPPERCASE]
663
- end
664
-
665
- def compile_node(o)
666
- shared_scope = o.delete(:shared_scope)
667
- top = o.delete(:top)
668
- o[:scope] = shared_scope || Scope.new(o[:scope], @body, self)
669
- o[:return] = true
670
- o[:top] = true
671
- o[:indent] = idt(@bound ? 2 : 1)
672
- o.delete(:no_wrap)
673
- o.delete(:globals)
674
- if @params.last.is_a?(SplatNode)
675
- splat = @params.pop
676
- splat.index = @params.length
677
- @body.unshift(splat)
678
- end
679
- @params.each {|id| o[:scope].parameter(id.to_s) }
680
- code = @body.empty? ? "" : "\n#{@body.compile_with_declarations(o)}\n"
681
- name_part = @name ? " #{@name}" : ''
682
- func = "function#{@bound ? '' : name_part}(#{@params.join(', ')}) {#{code}#{idt(@bound ? 1 : 0)}}"
683
- func = "(#{func})" if top && !@bound
684
- return write(func) unless @bound
685
- inner = "(function#{name_part}() {\n#{idt(2)}return __func.apply(__this, arguments);\n#{idt(1)}});"
686
- write("(function(__this) {\n#{idt(1)}var __func = #{func};\n#{idt(1)}return #{inner}\n#{idt}})(this)")
687
- end
688
- end
689
-
690
- # A splat, either as a parameter to a function, an argument to a call,
691
- # or in a destructuring assignment.
692
- class SplatNode < Node
693
- children :name
694
- attr_accessor :index
695
-
696
- def initialize(name)
697
- @name = name
698
- end
699
-
700
- def compile_node(o={})
701
- write(@index ? compile_param(o) : @name.compile(o))
702
- end
703
-
704
- def compile_param(o)
705
- o[:scope].find(@name)
706
- "#{@name} = Array.prototype.slice.call(arguments, #{@index})"
707
- end
708
-
709
- def compile_value(o, name, index)
710
- "Array.prototype.slice.call(#{name}, #{index})"
711
- end
712
-
713
- end
714
-
715
- # An object literal.
716
- class ObjectNode < Node
717
- children :properties
718
- alias_method :objects, :properties
719
-
720
- def initialize(properties = [])
721
- @properties = properties
722
- end
723
-
724
- # All the mucking about with commas is to make sure that CommentNodes and
725
- # AssignNodes get interleaved correctly, with no trailing commas or
726
- # commas affixed to comments. TODO: Extract this and add it to ArrayNode.
727
- def compile_node(o)
728
- o[:indent] = idt(1)
729
- joins = Hash.new("\n")
730
- non_comments = @properties.select {|p| !p.is_a?(CommentNode) }
731
- non_comments.each {|p| joins[p] = p == non_comments.last ? "\n" : ",\n" }
732
- props = @properties.map { |prop|
733
- join = joins[prop]
734
- join = '' if prop == @properties.last
735
- indent = prop.is_a?(CommentNode) ? '' : idt(1)
736
- "#{indent}#{prop.compile(o)}#{join}"
737
- }.join('')
738
- write("{\n#{props}\n#{idt}}")
739
- end
740
- end
741
-
742
- # An array literal.
743
- class ArrayNode < Node
744
- children :objects
745
-
746
- def initialize(objects=[])
747
- @objects = objects
748
- end
749
-
750
- def compile_node(o)
751
- o[:indent] = idt(1)
752
- objects = @objects.map { |obj|
753
- code = obj.compile(o)
754
- obj.is_a?(CommentNode) ? "\n#{code}\n#{o[:indent]}" :
755
- obj == @objects.last ? code : "#{code}, "
756
- }.join('')
757
- ending = objects.include?("\n") ? "\n#{idt}]" : ']'
758
- write("[#{objects}#{ending}")
759
- end
760
- end
761
-
762
- # A faux-node that is never created by the grammar, but is used during
763
- # code generation to generate a quick "array.push(value)" tree of nodes.
764
- class PushNode
765
- def self.wrap(array, expressions)
766
- expr = expressions.unwrap
767
- return expressions if expr.statement_only? || expr.contains? {|n| n.statement_only? }
768
- Expressions.wrap(CallNode.new(
769
- ValueNode.new(LiteralNode.new(array), [AccessorNode.new(Value.new('push'))]),
770
- [expr]
771
- ))
772
- end
773
- end
774
-
775
- # A faux-node used to wrap an expressions body in a closure.
776
- class ClosureNode
777
- def self.wrap(expressions, statement=false)
778
- func = ParentheticalNode.new(CodeNode.new([], Expressions.wrap(expressions)))
779
- call = CallNode.new(ValueNode.new(func, AccessorNode.new(Value.new('call'))), [Value.new('this')])
780
- statement ? Expressions.wrap(call) : call
781
- end
782
- end
783
-
784
- # A while loop, the only sort of low-level loop exposed by CoffeeScript. From
785
- # it, all other loops can be manufactured.
786
- class WhileNode < Node
787
- top_sensitive
788
- children :condition, :body
789
- statement
790
-
791
- def initialize(condition, body)
792
- @condition, @body = condition, body
793
- end
794
-
795
- def compile_node(o)
796
- returns = o.delete(:return)
797
- top = o.delete(:top) && !returns
798
- o[:indent] = idt(1)
799
- o[:top] = true
800
- cond = @condition.compile(o)
801
- set = ''
802
- if !top
803
- rvar = o[:scope].free_variable
804
- set = "#{idt}#{rvar} = [];\n"
805
- @body = PushNode.wrap(rvar, @body)
806
- end
807
- post = returns ? "\n#{idt}return #{rvar};" : ''
808
- return write("#{set}#{idt}while (#{cond}) null;#{post}") if @body.nil?
809
- write("#{set}#{idt}while (#{cond}) {\n#{@body.compile(o)}\n#{idt}}#{post}")
810
- end
811
- end
812
-
813
- # The replacement for the for loop is an array comprehension (that compiles)
814
- # into a for loop. Also acts as an expression, able to return the result
815
- # of the comprehenion. Unlike Python array comprehensions, it's able to pass
816
- # the current index of the loop as a second parameter.
817
- class ForNode < Node
818
- top_sensitive
819
- children :body, :source, :filter
820
- attr_reader :name, :index, :step
821
- statement
822
-
823
- def initialize(body, source, name, index=nil)
824
- @body, @name, @index = body, name, index
825
- @source = source[:source]
826
- @filter = source[:filter]
827
- @step = source[:step]
828
- @object = !!source[:object]
829
- @name, @index = @index, @name if @object
830
- end
831
-
832
- def compile_node(o)
833
- top_level = o.delete(:top) && !o[:return]
834
- range = @source.is_a?(ValueNode) && @source.base.is_a?(RangeNode) && @source.properties.empty?
835
- source = range ? @source.base : @source
836
- scope = o[:scope]
837
- name_found = @name && scope.find(@name)
838
- index_found = @index && scope.find(@index)
839
- body_dent = idt(1)
840
- rvar = scope.free_variable unless top_level
841
- svar = scope.free_variable
842
- ivar = range ? name : @index ? @index : scope.free_variable
843
- var_part = ''
844
- body = Expressions.wrap(@body)
845
- if range
846
- index_var = scope.free_variable
847
- source_part = source.compile_variables(o)
848
- for_part = "#{index_var}=0, #{source.compile(o.merge(:index => ivar, :step => @step))}, #{index_var}++"
849
- else
850
- index_var = nil
851
- source_part = "#{svar} = #{@source.compile(o)};\n#{idt}"
852
- step_part = @step ? "#{ivar} += #{@step.compile(o)}" : "#{ivar}++"
853
- for_part = @object ? "#{ivar} in #{svar}" : "#{ivar} = 0; #{ivar} < #{svar}.length; #{step_part}"
854
- var_part = "#{body_dent}#{@name} = #{svar}[#{ivar}];\n" if @name
855
- # body.unshift(AssignNode.new(@name, ValueNode.new(svar, [IndexNode.new(ivar)]))) if @name
856
- end
857
- set_result = rvar ? "#{idt}#{rvar} = []; " : idt
858
- return_result = rvar || ''
859
- body = ClosureNode.wrap(body, true) if top_level && contains? {|n| n.is_a? CodeNode }
860
- body = PushNode.wrap(rvar, body) unless top_level
861
- if o[:return]
862
- return_result = "return #{return_result}" if o[:return]
863
- o.delete(:return)
864
- body = IfNode.new(@filter, body, nil, :statement => true) if @filter
865
- elsif @filter
866
- body = Expressions.wrap(IfNode.new(@filter, body))
867
- end
868
- if @object
869
- o[:scope].assign("__hasProp", "Object.prototype.hasOwnProperty", true)
870
- body = Expressions.wrap(IfNode.new(
871
- CallNode.new(
872
- ValueNode.new(LiteralNode.wrap("__hasProp"), [AccessorNode.new(Value.new('call'))]),
873
- [LiteralNode.wrap(svar), LiteralNode.wrap(ivar)]
874
- ),
875
- Expressions.wrap(body), nil, {:statement => true}
876
- ))
877
- end
878
-
879
- return_result = "\n#{idt}#{return_result};" unless top_level
880
- body = body.compile(o.merge(:indent => body_dent, :top => true))
881
- vars = range ? @name : "#{@name}, #{ivar}"
882
- return write(set_result + source_part + "for (#{for_part}) {\n#{var_part}#{body}\n#{idt}}\n#{idt}#{return_result}")
883
- end
884
- end
885
-
886
- # A try/catch/finally block.
887
- class TryNode < Node
888
- children :try, :recovery, :finally
889
- attr_reader :error
890
- statement
891
-
892
- def initialize(try, error, recovery, finally=nil)
893
- @try, @error, @recovery, @finally = try, error, recovery, finally
894
- end
895
-
896
- def compile_node(o)
897
- o[:indent] = idt(1)
898
- o[:top] = true
899
- error_part = @error ? " (#{@error}) " : ' '
900
- catch_part = @recovery && " catch#{error_part}{\n#{@recovery.compile(o)}\n#{idt}}"
901
- finally_part = @finally && " finally {\n#{@finally.compile(o.merge(:return => nil))}\n#{idt}}"
902
- write("#{idt}try {\n#{@try.compile(o)}\n#{idt}}#{catch_part}#{finally_part}")
903
- end
904
- end
905
-
906
- # Throw an exception.
907
- class ThrowNode < Node
908
- children :expression
909
- statement_only
910
-
911
- def initialize(expression)
912
- @expression = expression
913
- end
914
-
915
- def compile_node(o)
916
- write("#{idt}throw #{@expression.compile(o)};")
917
- end
918
- end
919
-
920
- # Check an expression for existence (meaning not null or undefined).
921
- class ExistenceNode < Node
922
- children :expression
923
-
924
- def self.compile_test(o, variable)
925
- first, second = variable, variable
926
- first, second = *variable.compile_reference(o) if variable.is_a?(CallNode)
927
- "(typeof #{first.compile(o)} !== \"undefined\" && #{second.compile(o)} !== null)"
928
- end
929
-
930
- def initialize(expression)
931
- @expression = expression
932
- end
933
-
934
- def compile_node(o)
935
- write(ExistenceNode.compile_test(o, @expression))
936
- end
937
- end
938
-
939
- # An extra set of parentheses, supplied by the script source.
940
- # You can't wrap parentheses around bits that get compiled into JS statements,
941
- # unfortunately.
942
- class ParentheticalNode < Node
943
- children :expressions
944
-
945
- def initialize(expressions, line=nil)
946
- @expressions = expressions.unwrap
947
- @line = line
948
- end
949
-
950
- def compile_node(o)
951
- compiled = @expressions.compile(o)
952
- compiled = compiled[0...-1] if compiled[-1..-1] == ';'
953
- write("(#{compiled})")
954
- end
955
- end
956
-
957
- # If/else statements. Switch/whens get compiled into these. Acts as an
958
- # expression by pushing down requested returns to the expression bodies.
959
- # Single-expression IfNodes are compiled into ternary operators if possible,
960
- # because ternaries are first-class returnable assignable expressions.
961
- class IfNode < Node
962
- children :condition, :body, :else_body
963
-
964
- def initialize(condition, body, else_body=nil, tags={})
965
- @condition = condition
966
- @body = body && body.unwrap
967
- @else_body = else_body && else_body.unwrap
968
- @tags = tags
969
- @multiple = true if @condition.is_a?(Array)
970
- @condition = OpNode.new("!", ParentheticalNode.new(@condition)) if @tags[:invert]
971
- end
972
-
973
- def <<(else_body)
974
- eb = else_body.unwrap
975
- @else_body ? @else_body << eb : @else_body = eb
976
- self
977
- end
978
-
979
- def add_comment(comment)
980
- @comment = comment
981
- self
982
- end
983
-
984
- def force_statement
985
- @tags[:statement] = true
986
- self
987
- end
988
-
989
- # Rewrite a chain of IfNodes with their switch condition for equality.
990
- def rewrite_condition(expression)
991
- @condition = @multiple ? @condition.map {|c| OpNode.new("is", expression, c) } :
992
- OpNode.new("is", expression, @condition)
993
- @else_body.rewrite_condition(expression) if chain?
994
- self
995
- end
996
-
997
- # Rewrite a chain of IfNodes to add a default case as the final else.
998
- def add_else(exprs)
999
- chain? ? @else_body.add_else(exprs) : @else_body = (exprs && exprs.unwrap)
1000
- self
1001
- end
1002
-
1003
- # If the else_body is an IfNode itself, then we've got an if-else chain.
1004
- def chain?
1005
- @chain ||= @else_body && @else_body.is_a?(IfNode)
1006
- end
1007
-
1008
- # The IfNode only compiles into a statement if either of the bodies needs
1009
- # to be a statement.
1010
- def statement?
1011
- @is_statement ||= !!(@comment || @tags[:statement] || @body.statement? || (@else_body && @else_body.statement?))
1012
- end
1013
-
1014
- def compile_condition(o)
1015
- [@condition].flatten.map {|c| c.compile(o) }.join(' || ')
1016
- end
1017
-
1018
- def compile_node(o)
1019
- write(statement? ? compile_statement(o) : compile_ternary(o))
1020
- end
1021
-
1022
- # Compile the IfNode as a regular if-else statement. Flattened chains
1023
- # force sub-else bodies into statement form.
1024
- def compile_statement(o)
1025
- child = o.delete(:chain_child)
1026
- cond_o = o.dup
1027
- cond_o.delete(:return)
1028
- o[:indent] = idt(1)
1029
- o[:top] = true
1030
- if_dent = child ? '' : idt
1031
- com_dent = child ? idt : ''
1032
- prefix = @comment ? @comment.compile(cond_o) + "\n#{com_dent}" : ''
1033
- body = Expressions.wrap(@body).compile(o)
1034
- if_part = "#{prefix}#{if_dent}if (#{compile_condition(cond_o)}) {\n#{body}\n#{idt}}"
1035
- return if_part unless @else_body
1036
- else_part = chain? ?
1037
- " else #{@else_body.compile(o.merge(:indent => idt, :chain_child => true))}" :
1038
- " else {\n#{Expressions.wrap(@else_body).compile(o)}\n#{idt}}"
1039
- if_part + else_part
1040
- end
1041
-
1042
- # Compile the IfNode into a ternary operator.
1043
- def compile_ternary(o)
1044
- if_part = "#{@condition.compile(o)} ? #{@body.compile(o)}"
1045
- else_part = @else_body ? "#{@else_body.compile(o)}" : 'null'
1046
- "#{if_part} : #{else_part}"
1047
- end
1048
- end
1049
-
1050
- end