coffee-script 0.3.2 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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