coffee-script 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2009 Jeremy Ashkenas
1
+ Copyright (c) 2010 Jeremy Ashkenas
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person
4
4
  obtaining a copy of this software and associated documentation
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'coffee-script'
3
- s.version = '0.2.2' # Keep version in sync with coffee-script.rb
3
+ s.version = '0.2.3' # Keep version in sync with coffee-script.rb
4
4
  s.date = '2010-1-10'
5
5
 
6
6
  s.homepage = "http://jashkenas.github.com/coffee-script/"
@@ -0,0 +1,205 @@
1
+ # Examples from _why's Potion, the Readme and "Potion: A Short Pamphlet".
2
+
3
+ # 5 times: "Odelay!" print.
4
+
5
+ print("Odelay!") for i in [1..5]
6
+
7
+
8
+ # add = (x, y): x + y.
9
+ # add(2, 4) string print
10
+
11
+ add: x, y => x + y
12
+ print(add(2, 4))
13
+
14
+
15
+ # loop: 'quaff' print.
16
+
17
+ while true
18
+ print('quaff')
19
+
20
+
21
+ # ('cheese', 'bread', 'mayo') at (1) print
22
+
23
+ print(['cheese', 'bread', 'mayo'][1])
24
+
25
+
26
+ # (language='Potion', pointless=true) at (key='language') print
27
+
28
+ print({language: 'Potion', pointless: true}['language'])
29
+
30
+
31
+ # minus = (x, y): x - y.
32
+ # minus (y=10, x=6)
33
+
34
+ minus: x, y => x - y
35
+ minus(6, 10)
36
+
37
+
38
+ # foods = ('cheese', 'bread', 'mayo')
39
+ # foods (2)
40
+
41
+ foods: ['cheese', 'bread', 'mayo']
42
+ foods[2]
43
+
44
+
45
+ # (dog='canine', cat='feline', fox='vulpine') each (key, val):
46
+ # (key, ' is a ', val) join print.
47
+
48
+ for key, val of {dog: 'canine', cat: 'feline', fox: 'vulpine'}
49
+ print(key + ' is a ' + val)
50
+
51
+
52
+ # Person = class: /name, /age, /sex.
53
+ # Person print = ():
54
+ # ('My name is ', /name, '.') join print.
55
+
56
+ Person: =>
57
+ Person::print: =>
58
+ print('My name is ' + this.name + '.')
59
+
60
+
61
+ # p = Person ()
62
+ # p /name string print
63
+
64
+ p: new Person()
65
+ print(p.name)
66
+
67
+
68
+ # Policeman = Person class (rank): /rank = rank.
69
+ # Policeman print = ():
70
+ # ('My name is ', /name, ' and I'm a ', /rank, '.') join print.
71
+ #
72
+ # Policeman ('Constable') print
73
+
74
+ Policeman: rank => this.rank: rank
75
+ Policeman extends Person
76
+ Policeman::print: =>
77
+ print('My name is ' + this.name + " and I'm a " + this.rank + '.')
78
+
79
+ print(new Policeman('Constable'))
80
+
81
+
82
+ # app = [window (width=200, height=400)
83
+ # [para 'Welcome.', button 'OK']]
84
+ # app first name
85
+
86
+ app = {
87
+ window: {width: 200, height: 200}
88
+ para: 'Welcome.'
89
+ button: 'OK'
90
+ }
91
+ app.window
92
+
93
+
94
+ # x = 1
95
+ # y = 2
96
+ #
97
+ # x = 1, y = 2
98
+
99
+ x: 1
100
+ y: 2
101
+
102
+ x: 1; y: 2
103
+
104
+
105
+ # table = (language='Potion'
106
+ # pointless=true)
107
+
108
+ table: {
109
+ language: 'Potion'
110
+ pointless: yes
111
+ }
112
+
113
+
114
+ # # this foul business...
115
+ # String length = (): 10.
116
+
117
+ # this foul business...
118
+ String::length: => 10
119
+
120
+
121
+ # block = :
122
+ # 'potion' print.
123
+
124
+ block: =>
125
+ print('potion')
126
+
127
+
128
+ # if (age > 100): 'ancient'.
129
+
130
+ if age > 100 then 'ancient'
131
+
132
+
133
+ # author =
134
+ # if (title == 'Jonathan Strange & Mr. Norrell'):
135
+ # 'Susanna Clarke'.
136
+ # elsif (title == 'The Star Diaries'):
137
+ # 'Stanislaw Lem'.
138
+ # elsif (title == 'The Slynx'):
139
+ # 'Tatyana Tolstaya'.
140
+ # else:
141
+ # '... probably Philip K. Dick'.
142
+
143
+ switch author
144
+ when 'Jonathan Strange & Mr. Norrell'
145
+ 'Susanna Clarke'
146
+ when 'The Star Diaries'
147
+ 'Stanislaw Lem'
148
+ when 'The Slynx'
149
+ 'Tatyana Tolstaya'
150
+ else
151
+ '... probably Philip K. Dick'
152
+
153
+
154
+ # count = 8
155
+ # while (count > 0):
156
+ # 'quaff' print
157
+ # count--.
158
+
159
+ count: 8
160
+ while count > 0
161
+ print('quaff')
162
+ count--
163
+
164
+
165
+ # 1 to 5 (a):
166
+ # a string print.
167
+
168
+ print(a) for a in [1..5]
169
+
170
+
171
+ # if (3 ?gender):
172
+ # "Huh? Numbers are sexed? That's amazing." print.
173
+
174
+ if (3).gender?
175
+ print("Huh? Numbers are sexed? That's amazing.")
176
+
177
+
178
+ # HomePage get = (url):
179
+ # session = url query ? at ('session').
180
+
181
+ HomePage::get: url =>
182
+ session: url.query.session if url.query?
183
+
184
+
185
+ # BTree = class: /left, /right.
186
+ # b = BTree ()
187
+ # b /left = BTree ()
188
+ # b /right = BTree ()
189
+
190
+ BTree: =>
191
+ b: new BTree()
192
+ b.left: new BTree()
193
+ b.right: new BTree()
194
+
195
+
196
+ # BTree = class: /left, /right.
197
+ # b = BTree ()
198
+ #
199
+ # if (b ? /left):
200
+ # 'left path found!' print.
201
+
202
+ BTree: =>
203
+ b: new BTree()
204
+
205
+ print('left path found!') if b.left?
@@ -60,7 +60,7 @@
60
60
  return obj.forEach(iterator, context) if obj.forEach
61
61
  if _.isArray(obj) or _.isArguments(obj)
62
62
  return iterator.call(context, obj[i], i, obj) for i in [0...obj.length]
63
- iterator.call(context, val, key, obj) for key, val ino obj
63
+ iterator.call(context, val, key, obj) for key, val of obj
64
64
  catch e
65
65
  throw e if e isnt breaker
66
66
  obj
@@ -148,7 +148,7 @@
148
148
  # based on '==='.
149
149
  _.include: obj, target =>
150
150
  return _.indexOf(obj, target) isnt -1 if _.isArray(obj)
151
- for key, val ino obj
151
+ for key, val of obj
152
152
  return true if val is target
153
153
  false
154
154
 
@@ -380,7 +380,7 @@
380
380
  # Retrieve the names of an object's properties.
381
381
  _.keys: obj =>
382
382
  return _.range(0, obj.length) if _.isArray(obj)
383
- key for key, val ino obj
383
+ key for key, val of obj
384
384
 
385
385
 
386
386
  # Retrieve the values of an object's properties.
@@ -395,7 +395,7 @@
395
395
 
396
396
  # Extend a given object with all of the properties in a source object.
397
397
  _.extend: destination, source =>
398
- for key, val ino source
398
+ for key, val of source
399
399
  destination[key]: val
400
400
  destination
401
401
 
data/lib/coffee-script.rb CHANGED
@@ -10,7 +10,7 @@ require "coffee_script/parse_error"
10
10
  # Namespace for all CoffeeScript internal classes.
11
11
  module CoffeeScript
12
12
 
13
- VERSION = '0.2.2' # Keep in sync with the gemspec.
13
+ VERSION = '0.2.3' # Keep in sync with the gemspec.
14
14
 
15
15
  # Compile a script (String or IO) to JavaScript.
16
16
  def self.compile(script, options={})
@@ -208,13 +208,13 @@
208
208
  </dict>
209
209
  <dict>
210
210
  <key>match</key>
211
- <string>\b(break|by|catch|continue|else|finally|for|if|return|switch|then|throw|try|unless|when|while)\b</string>
211
+ <string>\b(break|by|catch|continue|else|finally|for|in|of|if|return|switch|then|throw|try|unless|when|while)\b</string>
212
212
  <key>name</key>
213
213
  <string>keyword.control.coffee</string>
214
214
  </dict>
215
215
  <dict>
216
216
  <key>match</key>
217
- <string>\b([a-zA-Z$_](\w|\$|:)*)(\:)\s</string>
217
+ <string>\b([a-zA-Z$_](\w|\$|:|\.)*)(\:)\s</string>
218
218
  <key>name</key>
219
219
  <string>variable.assignment.coffee</string>
220
220
  <key>captures</key>
@@ -263,7 +263,7 @@
263
263
  </dict>
264
264
  <dict>
265
265
  <key>match</key>
266
- <string>!|%|&amp;|\*|\/|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|&lt;=|&gt;=|&lt;&lt;=|&gt;&gt;=|&gt;&gt;&gt;=|&lt;&gt;|&lt;|&gt;|!|&amp;&amp;|\?|\|\||\:|\*=|(?&lt;!\()/=|%=|\+=|\-=|&amp;=|\^=|\b(in|ino|instanceof|new|delete|typeof|and|or|is|isnt|not)\b</string>
266
+ <string>!|%|&amp;|\*|\/|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|&lt;=|&gt;=|&lt;&lt;=|&gt;&gt;=|&gt;&gt;&gt;=|&lt;&gt;|&lt;|&gt;|!|&amp;&amp;|\?|\|\||\:|\*=|(?&lt;!\()/=|%=|\+=|\-=|&amp;=|\^=|\b(instanceof|new|delete|typeof|and|or|is|isnt|not)\b</string>
267
267
  <key>name</key>
268
268
  <string>keyword.operator.coffee</string>
269
269
  </dict>
@@ -8,7 +8,7 @@ token IDENTIFIER PROPERTY_ACCESS PROTOTYPE_ACCESS
8
8
  token CODE PARAM NEW RETURN
9
9
  token TRY CATCH FINALLY THROW
10
10
  token BREAK CONTINUE
11
- token FOR IN INO BY WHEN WHILE
11
+ token FOR IN OF BY WHEN WHILE
12
12
  token SWITCH LEADING_WHEN
13
13
  token DELETE INSTANCEOF TYPEOF
14
14
  token SUPER EXTENDS
@@ -34,7 +34,7 @@ prechigh
34
34
  left '.'
35
35
  right INDENT
36
36
  left OUTDENT
37
- right WHEN LEADING_WHEN IN INO BY
37
+ right WHEN LEADING_WHEN IN OF BY
38
38
  right THROW FOR NEW SUPER
39
39
  left EXTENDS
40
40
  left ASSIGN '||=' '&&='
@@ -361,7 +361,7 @@ rule
361
361
  # The source of the array comprehension can optionally be filtered.
362
362
  ForSource:
363
363
  IN Expression { result = {:source => val[1]} }
364
- | INO Expression { result = {:source => val[1], :object => true} }
364
+ | OF Expression { result = {:source => val[1], :object => true} }
365
365
  | ForSource
366
366
  WHEN Expression { result = val[0].merge(:filter => val[2]) }
367
367
  | ForSource
@@ -12,7 +12,7 @@ module CoffeeScript
12
12
  "new", "return",
13
13
  "try", "catch", "finally", "throw",
14
14
  "break", "continue",
15
- "for", "in", "ino", "by", "where", "while",
15
+ "for", "in", "of", "by", "where", "while",
16
16
  "switch", "when",
17
17
  "super", "extends",
18
18
  "arguments",
@@ -20,17 +20,13 @@
20
20
  // Run a simple REPL, round-tripping to the CoffeeScript compiler for every
21
21
  // command.
22
22
  exports.run = function run(args) {
23
- var __a, __b, i, result;
23
+ var __a, i, path, result;
24
24
  if (args.length) {
25
25
  __a = args;
26
- __b = function(path, i) {
26
+ for (i=0; i<__a.length; i++) {
27
+ path = __a[i];
27
28
  exports.evalCS(File.read(path));
28
29
  delete args[i];
29
- };
30
- if (__a instanceof Array) {
31
- for (i=0; i<__a.length; i++) __b(__a[i], i);
32
- } else {
33
- for (i in __a) { if (__a.hasOwnProperty(i)) __b(__a[i], i); }
34
30
  }
35
31
  return true;
36
32
  }
@@ -1,6 +1,12 @@
1
1
  module CoffeeScript
2
2
 
3
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.
4
10
  class Node
5
11
  # Tabs are two spaces for pretty-printing.
6
12
  TAB = ' '
@@ -41,7 +47,7 @@ module CoffeeScript
41
47
  "(function() {\n#{compile_node(o.merge(:return => true))}\n#{indent}})()"
42
48
  end
43
49
 
44
- # Quick method for the current indentation level, plus tabs out.
50
+ # Quick short method for the current indentation level, plus tabbing in.
45
51
  def idt(tabs=0)
46
52
  @indent + (TAB * tabs)
47
53
  end
@@ -57,7 +63,8 @@ module CoffeeScript
57
63
  statement
58
64
  attr_reader :expressions
59
65
 
60
- STRIP_TRAILING_WHITESPACE = /\s+$/
66
+ TRAILING_WHITESPACE = /\s+$/
67
+ UPPERCASE = /[A-Z]/
61
68
 
62
69
  # Wrap up a node as an Expressions, unless it already is.
63
70
  def self.wrap(*nodes)
@@ -69,12 +76,13 @@ module CoffeeScript
69
76
  @expressions = nodes.flatten
70
77
  end
71
78
 
72
- # Tack an expression onto the end of this node.
79
+ # Tack an expression on to the end of this expression list.
73
80
  def <<(node)
74
81
  @expressions << node
75
82
  self
76
83
  end
77
84
 
85
+ # Tack an expression on to the beginning of this expression list.
78
86
  def unshift(node)
79
87
  @expressions.unshift(node)
80
88
  self
@@ -91,36 +99,19 @@ module CoffeeScript
91
99
  node == @expressions[@last_index]
92
100
  end
93
101
 
102
+ # Determine if this is the expressions body within a constructor function.
103
+ # Constructors are capitalized by CoffeeScript convention.
104
+ def constructor?(o)
105
+ o[:top] && o[:last_assign] && o[:last_assign][0..0][UPPERCASE]
106
+ end
107
+
94
108
  def compile(o={})
95
109
  o[:scope] ? super(o) : compile_root(o)
96
110
  end
97
111
 
98
- # The extra fancy is to handle pushing down returns to the final lines of
99
- # inner statements. Variables first defined within the Expressions body
100
- # have their declarations pushed up top of the closest scope.
112
+ # Compile each expression in the Expressions body.
101
113
  def compile_node(options={})
102
- compiled = @expressions.map do |node|
103
- o = options.dup
104
- @indent = o[:indent]
105
- returns = o.delete(:return)
106
- if last?(node) && returns && !node.statement_only?
107
- if node.statement?
108
- node.compile(o.merge(:return => true))
109
- else
110
- if o[:top] && o[:last_assign] && o[:last_assign][0..0][/[A-Z]/]
111
- temp = o[:scope].free_variable
112
- "#{idt}#{temp} = #{node.compile(o)};\n#{idt}return #{o[:last_assign]} === this.constructor ? this : #{temp};"
113
- else
114
- "#{idt}return #{node.compile(o)};"
115
- end
116
- end
117
- else
118
- ending = node.statement? ? '' : ';'
119
- indent = node.statement? ? '' : idt
120
- "#{indent}#{node.compile(o.merge(:top => true))}#{ending}"
121
- end
122
- end
123
- write(compiled.join("\n"))
114
+ write(@expressions.map {|n| compile_expression(n, options.dup) }.join("\n"))
124
115
  end
125
116
 
126
117
  # If this is the top-level Expressions, wrap everything in a safety closure.
@@ -129,15 +120,33 @@ module CoffeeScript
129
120
  @indent = indent
130
121
  o.merge!(:indent => indent, :scope => Scope.new(nil, self))
131
122
  code = o[:globals] ? compile_node(o) : compile_with_declarations(o)
132
- code.gsub!(STRIP_TRAILING_WHITESPACE, '')
133
- o[:no_wrap] ? code : "(function(){\n#{code}\n})();"
123
+ code.gsub!(TRAILING_WHITESPACE, '')
124
+ write(o[:no_wrap] ? code : "(function(){\n#{code}\n})();")
134
125
  end
135
126
 
127
+ # Compile the expressions body, with declarations of all inner variables
128
+ # at the top.
136
129
  def compile_with_declarations(o={})
137
130
  code = compile_node(o)
138
- decls = ''
139
- decls = "#{idt}var #{o[:scope].declared_variables.join(', ')};\n" if o[:scope].declarations?(self)
140
- decls + code
131
+ return code unless o[:scope].declarations?(self)
132
+ write("#{idt}var #{o[:scope].declared_variables.join(', ')};\n#{code}")
133
+ end
134
+
135
+ # Compiles a single expression within the expression list.
136
+ def compile_expression(node, o)
137
+ @indent = o[:indent]
138
+ stmt = node.statement?
139
+ # We need to return the result if this is the last node in the expressions body.
140
+ returns = o.delete(:return) && last?(node) && !node.statement_only?
141
+ # Return the regular compile of the node, unless we need to return the result.
142
+ return "#{stmt ? '' : idt}#{node.compile(o.merge(:top => true))}#{stmt ? '' : ';'}" unless returns
143
+ # If it's a statement, the node knows how to return itself.
144
+ return node.compile(o.merge(:return => true)) if node.statement?
145
+ # If it's not part of a constructor, we can just return the value of the expression.
146
+ return "#{idt}return #{node.compile(o)};" unless constructor?(o)
147
+ # It's the last line of a constructor, add a safety check.
148
+ temp = o[:scope].free_variable
149
+ "#{idt}#{temp} = #{node.compile(o)};\n#{idt}return #{o[:last_assign]} === this.constructor ? this : #{temp};"
141
150
  end
142
151
 
143
152
  end
@@ -145,14 +154,18 @@ module CoffeeScript
145
154
  # Literals are static values that have a Ruby representation, eg.: a string, a number,
146
155
  # true, false, nil, etc.
147
156
  class LiteralNode < Node
157
+
158
+ # Values of a literal node that much be treated as a statement -- no
159
+ # sense returning or assigning them.
148
160
  STATEMENTS = ['break', 'continue']
149
161
 
150
- CONVERSIONS = {
151
- 'arguments' => 'Array.prototype.slice.call(arguments, 0)'
152
- }
162
+ # If we get handed a literal reference to an arguments object, convert
163
+ # it to an array.
164
+ ARG_ARRAY = 'Array.prototype.slice.call(arguments, 0)'
153
165
 
154
166
  attr_reader :value
155
167
 
168
+ # Wrap up a compiler-generated string as a LiteralNode.
156
169
  def self.wrap(string)
157
170
  self.new(Value.new(string))
158
171
  end
@@ -167,14 +180,14 @@ module CoffeeScript
167
180
  alias_method :statement_only?, :statement?
168
181
 
169
182
  def compile_node(o)
170
- val = CONVERSIONS[@value.to_s] || @value.to_s
183
+ @value = ARG_ARRAY if @value.to_s.to_sym == :arguments
171
184
  indent = statement? ? idt : ''
172
185
  ending = statement? ? ';' : ''
173
- write("#{indent}#{val}#{ending}")
186
+ write "#{indent}#{@value}#{ending}"
174
187
  end
175
188
  end
176
189
 
177
- # Try to return your expression, or tell it to return itself.
190
+ # Return an expression, or wrap it in a closure and return it.
178
191
  class ReturnNode < Node
179
192
  statement_only
180
193
 
@@ -202,8 +215,7 @@ module CoffeeScript
202
215
 
203
216
  def compile_node(o={})
204
217
  delimiter = "\n#{idt}//"
205
- comment = "#{delimiter}#{@lines.join(delimiter)}"
206
- write(comment)
218
+ write("#{delimiter}#{@lines.join(delimiter)}")
207
219
  end
208
220
 
209
221
  end
@@ -238,6 +250,7 @@ module CoffeeScript
238
250
  @arguments << argument
239
251
  end
240
252
 
253
+ # Compile a vanilla function call.
241
254
  def compile_node(o)
242
255
  return write(compile_splat(o)) if splat?
243
256
  args = @arguments.map{|a| a.compile(o) }.join(', ')
@@ -245,6 +258,7 @@ module CoffeeScript
245
258
  write("#{prefix}#{@variable.compile(o)}(#{args})")
246
259
  end
247
260
 
261
+ # Compile a call against the superclass's implementation of the current function.
248
262
  def compile_super(args, o)
249
263
  methname = o[:last_assign]
250
264
  arg_part = args.empty? ? '' : ", #{args}"
@@ -253,6 +267,7 @@ module CoffeeScript
253
267
  "#{meth}.call(this#{arg_part})"
254
268
  end
255
269
 
270
+ # Compile a function call being passed variable arguments.
256
271
  def compile_splat(o)
257
272
  meth = @variable.compile(o)
258
273
  obj = @variable.source || 'this'
@@ -275,6 +290,7 @@ module CoffeeScript
275
290
  @sub_object, @super_object = sub_object, super_object
276
291
  end
277
292
 
293
+ # Hooking one constructor into another's prototype chain.
278
294
  def compile_node(o={})
279
295
  constructor = o[:scope].free_variable
280
296
  sub, sup = @sub_object.compile(o), @super_object.compile(o)
@@ -289,10 +305,10 @@ module CoffeeScript
289
305
 
290
306
  # A value, indexed or dotted into, or vanilla.
291
307
  class ValueNode < Node
292
- attr_reader :literal, :properties, :last, :source
308
+ attr_reader :base, :properties, :last, :source
293
309
 
294
- def initialize(literal, properties=[])
295
- @literal, @properties = literal, properties
310
+ def initialize(base, properties=[])
311
+ @base, @properties = base, properties
296
312
  end
297
313
 
298
314
  def <<(other)
@@ -304,23 +320,23 @@ module CoffeeScript
304
320
  return !@properties.empty?
305
321
  end
306
322
 
323
+ # Values are statements if their base is a statement.
307
324
  def statement?
308
- @literal.is_a?(Node) && @literal.statement? && !properties?
325
+ @base.is_a?(Node) && @base.statement? && !properties?
309
326
  end
310
327
 
311
328
  def compile_node(o)
312
329
  only = o.delete(:only_first)
313
330
  props = only ? @properties[0...-1] : @properties
314
- parts = [@literal, props].flatten.map do |val|
315
- val.respond_to?(:compile) ? val.compile(o) : val.to_s
316
- end
331
+ parts = [@base, props].flatten.map {|val| val.compile(o) }
317
332
  @last = parts.last
318
333
  @source = parts.length > 1 ? parts[0...-1].join('') : nil
319
334
  write(parts.join(''))
320
335
  end
321
336
  end
322
337
 
323
- # A dotted accessor into a part of a value.
338
+ # A dotted accessor into a part of a value, or the :: shorthand for
339
+ # an accessor into the object's prototype.
324
340
  class AccessorNode < Node
325
341
  attr_reader :name
326
342
 
@@ -360,14 +376,6 @@ module CoffeeScript
360
376
  @exclusive
361
377
  end
362
378
 
363
- def less_operator
364
- @exclusive ? '<' : '<='
365
- end
366
-
367
- def greater_operator
368
- @exclusive ? '>' : '>='
369
- end
370
-
371
379
  def compile_variables(o)
372
380
  @indent = o[:indent]
373
381
  @from_var, @to_var = o[:scope].free_variable, o[:scope].free_variable
@@ -376,12 +384,13 @@ module CoffeeScript
376
384
  end
377
385
 
378
386
  def compile_node(o)
387
+ return compile_array(o) unless o[:index]
379
388
  idx, step = o.delete(:index), o.delete(:step)
380
- return compile_array(o) unless idx
381
- vars = "#{idx}=#{@from_var}"
382
- step = step ? step.compile(o) : '1'
383
- compare = "(#{@from_var} <= #{@to_var} ? #{idx} #{less_operator} #{@to_var} : #{idx} #{greater_operator} #{@to_var})"
384
- incr = "(#{@from_var} <= #{@to_var} ? #{idx} += #{step} : #{idx} -= #{step})"
389
+ vars = "#{idx}=#{@from_var}"
390
+ step = step ? step.compile(o) : '1'
391
+ equals = @exclusive ? '' : '='
392
+ compare = "(#{@from_var} <= #{@to_var} ? #{idx} <#{equals} #{@to_var} : #{idx} >#{equals} #{@to_var})"
393
+ incr = "(#{@from_var} <= #{@to_var} ? #{idx} += #{step} : #{idx} -= #{step})"
385
394
  write("#{vars}; #{compare}; #{incr}")
386
395
  end
387
396
 
@@ -640,8 +649,8 @@ module CoffeeScript
640
649
 
641
650
  def compile_node(o)
642
651
  top_level = o.delete(:top) && !o[:return]
643
- range = @source.is_a?(ValueNode) && @source.literal.is_a?(RangeNode) && @source.properties.empty?
644
- source = range ? @source.literal : @source
652
+ range = @source.is_a?(ValueNode) && @source.base.is_a?(RangeNode) && @source.properties.empty?
653
+ source = range ? @source.base : @source
645
654
  scope = o[:scope]
646
655
  name_found = @name && scope.find(@name)
647
656
  index_found = @index && scope.find(@index)
@@ -657,8 +666,7 @@ module CoffeeScript
657
666
  else
658
667
  index_var = nil
659
668
  source_part = "#{svar} = #{source.compile(o)};\n#{idt}"
660
- for_part = "#{ivar}=0; #{ivar}<#{svar}.length; #{ivar}++"
661
- for_part = "#{ivar} in #{svar}" if @object
669
+ for_part = @object ? "#{ivar} in #{svar}" : "#{ivar}=0; #{ivar}<#{svar}.length; #{ivar}++"
662
670
  var_part = @name ? "#{body_dent}#{@name} = #{svar}[#{ivar}];\n" : ''
663
671
  end
664
672
  body = @body
@@ -1002,7 +1002,7 @@ racc_token_table = {
1002
1002
  :CONTINUE => 26,
1003
1003
  :FOR => 27,
1004
1004
  :IN => 28,
1005
- :INO => 29,
1005
+ :OF => 29,
1006
1006
  :BY => 30,
1007
1007
  :WHEN => 31,
1008
1008
  :WHILE => 32,
@@ -1120,7 +1120,7 @@ Racc_token_to_s_table = [
1120
1120
  "CONTINUE",
1121
1121
  "FOR",
1122
1122
  "IN",
1123
- "INO",
1123
+ "OF",
1124
1124
  "BY",
1125
1125
  "WHEN",
1126
1126
  "WHILE",
@@ -18,6 +18,10 @@ module CoffeeScript
18
18
  to_str.to_sym
19
19
  end
20
20
 
21
+ def compile(o={})
22
+ to_s
23
+ end
24
+
21
25
  def inspect
22
26
  @value.inspect
23
27
  end
data/package.json CHANGED
@@ -5,5 +5,5 @@
5
5
  "description": "Unfancy JavaScript",
6
6
  "keywords": ["javascript", "language"],
7
7
  "author": "Jeremy Ashkenas",
8
- "version": "0.2.2"
8
+ "version": "0.2.3"
9
9
  }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: coffee-script
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Ashkenas
@@ -26,6 +26,7 @@ files:
26
26
  - examples/code.coffee
27
27
  - examples/documents.coffee
28
28
  - examples/poignant.coffee
29
+ - examples/potion.coffee
29
30
  - examples/syntax_errors.coffee
30
31
  - examples/underscore.coffee
31
32
  - lib/coffee-script.rb