coffee-script 0.2.2 → 0.2.3

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.
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