1
0
Fork 0
mirror of https://github.com/jashkenas/coffeescript.git synced 2022-11-09 12:23:24 -05:00

big commit -- adding back object comprehensions, using 'ino', versus 'in' for array comprehensions, fixing bug with dollar signs in identifiers

This commit is contained in:
Jeremy Ashkenas 2010-01-10 15:52:23 -05:00
parent 13fc8aea04
commit 902febb43a
18 changed files with 200 additions and 58 deletions

View file

@ -2,5 +2,5 @@ alert(
try try
nonexistent / undefined nonexistent / undefined
catch error catch error
"The error is: " + error "Caught an error: " + error
) )

View file

@ -0,0 +1,3 @@
years_old: {max: 10, ida: 9, tim: 11}
ages: child + " is " + age for child, age ino years_old

View file

@ -1,3 +1,6 @@
for i in [0...eggs.length] by 12 countdown: num for num in [10..1]
dozen_eggs: eggs[i...i+12]
deliver(new egg_carton(dozen)) egg_delivery: =>
for i in [0...eggs.length] by 12
dozen_eggs: eggs[i...i+12]
deliver(new egg_carton(dozen))

View file

@ -399,12 +399,14 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
<p> <p>
If you know the start and end of your loop, or would like to step through If you know the start and end of your loop, or would like to step through
in fixed-size increments, you can use a range to specify the start and in fixed-size increments, you can use a range to specify the start and
end of your comprehension: end of your comprehension. (The long line-breaking "for" definitions in
the compiled JS below allow ranges to count downwards, as well as upwards).
</p> </p>
<%= code_for('range_comprehensions') %> <%= code_for('range_comprehensions', 'countdown') %>
<p> <p>
Comprehensions can also be used to iterate over the values and keys in Comprehensions can also be used to iterate over the keys and values in
an object: an object. Use <tt>ino</tt> to signal comprehension over an object instead
of an array.
</p> </p>
<%= code_for('object_comprehensions', 'ages.join(", ")') %> <%= code_for('object_comprehensions', 'ages.join(", ")') %>

View file

@ -1,5 +1,5 @@
(function(){ (function(){
var __a, __b, __c, __d, __e, __f, __g, lunch; var __a, __b, __c, __d, __e, __f, __g, food, lunch, roid, roid2;
// Eat lunch. // Eat lunch.
lunch = (function() { lunch = (function() {
__c = []; __a = ['toast', 'cheese', 'wine']; __c = []; __a = ['toast', 'cheese', 'wine'];

View file

@ -1,5 +1,5 @@
(function(){ (function(){
var __a, __b, globals, name; var __a, __b, globals, name, property;
// The first ten global properties. // The first ten global properties.
globals = ((function() { globals = ((function() {
__b = []; __a = window; __b = []; __a = window;

View file

@ -3,7 +3,7 @@
try { try {
return nonexistent / undefined; return nonexistent / undefined;
} catch (error) { } catch (error) {
return "The error is: " + error; return "Caught an error: " + error;
} }
})()); })());
})(); })();

View file

@ -0,0 +1,18 @@
(function(){
var __a, __b, age, ages, child, years_old;
years_old = {
max: 10,
ida: 9,
tim: 11
};
ages = (function() {
__b = []; __a = years_old;
for (child in __a) {
age = __a[child];
if (__a.hasOwnProperty(child)) {
__b.push(child + " is " + age);
}
}
return __b;
})();
})();

View file

@ -1,5 +1,5 @@
(function(){ (function(){
var __a, __b, __c, cubed_list, list, math, number, opposite_day, race, square; var __a, __b, __c, cubed_list, list, math, num, number, opposite_day, race, square;
// Assignment: // Assignment:
number = 42; number = 42;
opposite_day = true; opposite_day = true;

View file

@ -1,8 +1,21 @@
(function(){ (function(){
var __a, __b, __c, __d, dozen_eggs; var __a, __b, __c, __d, __e, countdown, egg_delivery, num;
__c = 0; __d = eggs.length; countdown = (function() {
for (__b=0, i=__c; (__c <= __d ? i < __d : i > __d); (__c <= __d ? i += 12 : i -= 12), __b++) { __b = []; __d = 10; __e = 1;
dozen_eggs = eggs.slice(i, i + 12); for (__c=0, num=__d; (__d <= __e ? num <= __e : num >= __e); (__d <= __e ? num += 1 : num -= 1), __c++) {
deliver(new egg_carton(dozen)); __b.push(num);
} }
return __b;
})();
egg_delivery = function egg_delivery() {
var __f, __g, __h, __i, __j, dozen_eggs, i;
__g = []; __i = 0; __j = eggs.length;
for (__h=0, i=__i; (__i <= __j ? i < __j : i > __j); (__i <= __j ? i += 12 : i -= 12), __h++) {
__g.push((function() {
dozen_eggs = eggs.slice(i, i + 12);
return deliver(new egg_carton(dozen));
})());
}
return __g;
};
})(); })();

View file

@ -30,7 +30,7 @@
breaker: if typeof(StopIteration) is 'undefined' then '__break__' else StopIteration breaker: if typeof(StopIteration) is 'undefined' then '__break__' else StopIteration
# Create a safe reference to the Underscore object for reference below. # Create a safe reference to the Underscore object forreference below.
_: root._: obj => new wrapper(obj) _: root._: obj => new wrapper(obj)
@ -60,7 +60,7 @@
return obj.forEach(iterator, context) if obj.forEach return obj.forEach(iterator, context) if obj.forEach
if _.isArray(obj) or _.isArguments(obj) if _.isArray(obj) or _.isArguments(obj)
return iterator.call(context, obj[i], i, obj) for i in [0...obj.length] return iterator.call(context, obj[i], i, obj) for i in [0...obj.length]
iterator.call(context, val, key, obj) for val, key in obj iterator.call(context, val, key, obj) for key, val ino obj
catch e catch e
throw e if e isnt breaker throw e if e isnt breaker
obj obj
@ -148,7 +148,7 @@
# based on '==='. # based on '==='.
_.include: obj, target => _.include: obj, target =>
return _.indexOf(obj, target) isnt -1 if _.isArray(obj) return _.indexOf(obj, target) isnt -1 if _.isArray(obj)
for val in obj for key, val ino obj
return true if val is target return true if val is target
false false
@ -380,7 +380,7 @@
# Retrieve the names of an object's properties. # Retrieve the names of an object's properties.
_.keys: obj => _.keys: obj =>
return _.range(0, obj.length) if _.isArray(obj) return _.range(0, obj.length) if _.isArray(obj)
key for val, key in obj key for key, val ino obj
# Retrieve the values of an object's properties. # Retrieve the values of an object's properties.
@ -395,7 +395,7 @@
# Extend a given object with all of the properties in a source object. # Extend a given object with all of the properties in a source object.
_.extend: destination, source => _.extend: destination, source =>
for val, key in source for key, val ino source
destination[key]: val destination[key]: val
destination destination
@ -564,8 +564,9 @@
_.each(_.functions(_)) name => _.each(_.functions(_)) name =>
method: _[name] method: _[name]
wrapper.prototype[name]: => wrapper.prototype[name]: =>
unshift.call(arguments, this._wrapped) args: _.toArray(arguments)
result(method.apply(_, arguments), this._chain) unshift.call(args, this._wrapped)
result(method.apply(_, args), this._chain)
# Add all mutator Array functions to the wrapper. # Add all mutator Array functions to the wrapper.

View file

@ -103,7 +103,7 @@ alert(<span class="String"><span class="String">&quot;</span>I knew it!<span cla
<span class="Comment"><span class="Comment">#</span> Array comprehensions:</span> <span class="Comment"><span class="Comment">#</span> Array comprehensions:</span>
cubed_list<span class="Keyword">:</span> math.cube(num) <span class="Keyword">for</span> num <span class="Keyword">in</span> list cubed_list<span class="Keyword">:</span> math.cube(num) <span class="Keyword">for</span> num <span class="Keyword">in</span> list
</pre><pre class="idle"><span class="Storage">var</span> __a, __b, __c, cubed_list, list, math, number, opposite_day, race, square; </pre><pre class="idle"><span class="Storage">var</span> __a, __b, __c, cubed_list, list, math, num, number, opposite_day, race, square;
<span class="Comment"><span class="Comment">//</span> Assignment:</span> <span class="Comment"><span class="Comment">//</span> Assignment:</span>
number <span class="Keyword">=</span> <span class="Number">42</span>; number <span class="Keyword">=</span> <span class="Number">42</span>;
opposite_day <span class="Keyword">=</span> <span class="BuiltInConstant">true</span>; opposite_day <span class="Keyword">=</span> <span class="BuiltInConstant">true</span>;
@ -144,7 +144,7 @@ cubed_list <span class="Keyword">=</span> (<span class="Storage">function</span>
} }
<span class="Keyword">return</span> __c; <span class="Keyword">return</span> __c;
})(); })();
</pre><button onclick='javascript: var __a, __b, __c, cubed_list, list, math, number, opposite_day, race, square; </pre><button onclick='javascript: var __a, __b, __c, cubed_list, list, math, num, number, opposite_day, race, square;
// Assignment: // Assignment:
number = 42; number = 42;
opposite_day = true; opposite_day = true;
@ -694,7 +694,7 @@ lunch<span class="Keyword">:</span> eat(food) <span class="Keyword">for</span> f
<span class="Keyword">for</span> roid <span class="Keyword">in</span> asteroids <span class="Keyword">for</span> roid <span class="Keyword">in</span> asteroids
<span class="Keyword">for</span> roid2 <span class="Keyword">in</span> asteroids <span class="Keyword">when</span> roid <span class="Keyword">isnt</span> roid2 <span class="Keyword">for</span> roid2 <span class="Keyword">in</span> asteroids <span class="Keyword">when</span> roid <span class="Keyword">isnt</span> roid2
roid.explode() <span class="Keyword">if</span> roid.overlaps(roid2) roid.explode() <span class="Keyword">if</span> roid.overlaps(roid2)
</pre><pre class="idle"><span class="Storage">var</span> __a, __b, __c, __d, __e, __f, __g, lunch; </pre><pre class="idle"><span class="Storage">var</span> __a, __b, __c, __d, __e, __f, __g, food, lunch, roid, roid2;
<span class="Comment"><span class="Comment">//</span> Eat lunch.</span> <span class="Comment"><span class="Comment">//</span> Eat lunch.</span>
lunch <span class="Keyword">=</span> (<span class="Storage">function</span>() { lunch <span class="Keyword">=</span> (<span class="Storage">function</span>() {
__c <span class="Keyword">=</span> []; __a <span class="Keyword">=</span> [<span class="String"><span class="String">'</span>toast<span class="String">'</span></span>, <span class="String"><span class="String">'</span>cheese<span class="String">'</span></span>, <span class="String"><span class="String">'</span>wine<span class="String">'</span></span>]; __c <span class="Keyword">=</span> []; __a <span class="Keyword">=</span> [<span class="String"><span class="String">'</span>toast<span class="String">'</span></span>, <span class="String"><span class="String">'</span>cheese<span class="String">'</span></span>, <span class="String"><span class="String">'</span>wine<span class="String">'</span></span>];
@ -722,23 +722,95 @@ __d <span class="Keyword">=</span> asteroids;
<p> <p>
If you know the start and end of your loop, or would like to step through If you know the start and end of your loop, or would like to step through
in fixed-size increments, you can use a range to specify the start and in fixed-size increments, you can use a range to specify the start and
end of your comprehension: end of your comprehension. (The long line-breaking "for" definitions in
the compiled JS below allow ranges to count downwards, as well as upwards).
</p> </p>
<div class='code'><pre class="idle"><span class="Keyword">for</span> i <span class="Keyword">in</span> [<span class="Number">0</span>...eggs.length] <span class="Keyword">by</span> <span class="Number">12</span> <div class='code'><pre class="idle">countdown<span class="Keyword">:</span> num <span class="Keyword">for</span> num <span class="Keyword">in</span> [<span class="Number">10</span>..<span class="Number">1</span>]
dozen_eggs<span class="Keyword">:</span> eggs[i...i<span class="Keyword">+</span><span class="Number">12</span>]
deliver(<span class="Keyword">new</span> <span class="TypeName">egg_carton</span>(dozen)) <span class="FunctionName">egg_delivery</span><span class="Keyword">:</span> <span class="Storage">=&gt;</span>
</pre><pre class="idle"><span class="Storage">var</span> __a, __b, __c, __d, dozen_eggs; <span class="Keyword">for</span> i <span class="Keyword">in</span> [<span class="Number">0</span>...eggs.length] <span class="Keyword">by</span> <span class="Number">12</span>
__c <span class="Keyword">=</span> <span class="Number">0</span>; __d <span class="Keyword">=</span> eggs.<span class="LibraryConstant">length</span>; dozen_eggs<span class="Keyword">:</span> eggs[i...i<span class="Keyword">+</span><span class="Number">12</span>]
<span class="Keyword">for</span> (__b<span class="Keyword">=</span><span class="Number">0</span>, i<span class="Keyword">=</span>__c; (__c <span class="Keyword">&lt;=</span> __d ? i <span class="Keyword">&lt;</span> __d : i <span class="Keyword">&gt;</span> __d); (__c <span class="Keyword">&lt;=</span> __d ? i <span class="Keyword">+</span><span class="Keyword">=</span> <span class="Number">12</span> : i <span class="Keyword">-</span><span class="Keyword">=</span> <span class="Number">12</span>), __b<span class="Keyword">++</span>) { deliver(<span class="Keyword">new</span> <span class="TypeName">egg_carton</span>(dozen))
dozen_eggs <span class="Keyword">=</span> eggs.<span class="LibraryFunction">slice</span>(i, i <span class="Keyword">+</span> <span class="Number">12</span>); </pre><pre class="idle"><span class="Storage">var</span> __a, __b, __c, __d, __e, countdown, egg_delivery, num;
deliver(<span class="Keyword">new</span> <span class="TypeName">egg_carton</span>(dozen)); countdown <span class="Keyword">=</span> (<span class="Storage">function</span>() {
} __b <span class="Keyword">=</span> []; __d <span class="Keyword">=</span> <span class="Number">10</span>; __e <span class="Keyword">=</span> <span class="Number">1</span>;
</pre><br class='clear' /></div> <span class="Keyword">for</span> (__c<span class="Keyword">=</span><span class="Number">0</span>, num<span class="Keyword">=</span>__d; (__d <span class="Keyword">&lt;=</span> __e ? num <span class="Keyword">&lt;=</span> __e : num <span class="Keyword">&gt;=</span> __e); (__d <span class="Keyword">&lt;=</span> __e ? num <span class="Keyword">+</span><span class="Keyword">=</span> <span class="Number">1</span> : num <span class="Keyword">-</span><span class="Keyword">=</span> <span class="Number">1</span>), __c<span class="Keyword">++</span>) {
__b.<span class="LibraryFunction">push</span>(num);
}
<span class="Keyword">return</span> __b;
})();
egg_delivery <span class="Keyword">=</span> <span class="Storage">function</span> <span class="FunctionName">egg_delivery</span>() {
<span class="Storage">var</span> __f, __g, __h, __i, __j, dozen_eggs, i;
__g <span class="Keyword">=</span> []; __i <span class="Keyword">=</span> <span class="Number">0</span>; __j <span class="Keyword">=</span> eggs.<span class="LibraryConstant">length</span>;
<span class="Keyword">for</span> (__h<span class="Keyword">=</span><span class="Number">0</span>, i<span class="Keyword">=</span>__i; (__i <span class="Keyword">&lt;=</span> __j ? i <span class="Keyword">&lt;</span> __j : i <span class="Keyword">&gt;</span> __j); (__i <span class="Keyword">&lt;=</span> __j ? i <span class="Keyword">+</span><span class="Keyword">=</span> <span class="Number">12</span> : i <span class="Keyword">-</span><span class="Keyword">=</span> <span class="Number">12</span>), __h<span class="Keyword">++</span>) {
__g.<span class="LibraryFunction">push</span>((<span class="Storage">function</span>() {
dozen_eggs <span class="Keyword">=</span> eggs.<span class="LibraryFunction">slice</span>(i, i <span class="Keyword">+</span> <span class="Number">12</span>);
<span class="Keyword">return</span> deliver(<span class="Keyword">new</span> <span class="TypeName">egg_carton</span>(dozen));
})());
}
<span class="Keyword">return</span> __g;
};
</pre><button onclick='javascript: var __a, __b, __c, __d, __e, countdown, egg_delivery, num;
countdown = (function() {
__b = []; __d = 10; __e = 1;
for (__c=0, num=__d; (__d <= __e ? num <= __e : num >= __e); (__d <= __e ? num += 1 : num -= 1), __c++) {
__b.push(num);
}
return __b;
})();
egg_delivery = function egg_delivery() {
var __f, __g, __h, __i, __j, dozen_eggs, i;
__g = []; __i = 0; __j = eggs.length;
for (__h=0, i=__i; (__i <= __j ? i < __j : i > __j); (__i <= __j ? i += 12 : i -= 12), __h++) {
__g.push((function() {
dozen_eggs = eggs.slice(i, i + 12);
return deliver(new egg_carton(dozen));
})());
}
return __g;
};
;alert(countdown);'>run: countdown</button><br class='clear' /></div>
<p> <p>
Comprehensions can also be used to iterate over the values and keys in Comprehensions can also be used to iterate over the keys and values in
an object: an object. Use <tt>ino</tt> to signal comprehension over an object instead
of an array.
</p> </p>
<div class='code'><pre class="idle">years_old<span class="Keyword">:</span> {max<span class="Keyword">:</span> <span class="Number">10</span>, ida<span class="Keyword">:</span> <span class="Number">9</span>, tim<span class="Keyword">:</span> <span class="Number">11</span>}
ages<span class="Keyword">:</span> child <span class="Keyword">+</span> <span class="String"><span class="String">&quot;</span> is <span class="String">&quot;</span></span> <span class="Keyword">+</span> age <span class="Keyword">for</span> child, age ino years_old
</pre><pre class="idle"><span class="Storage">var</span> __a, __b, age, ages, child, years_old;
years_old <span class="Keyword">=</span> {
max: <span class="Number">10</span>,
ida: <span class="Number">9</span>,
tim: <span class="Number">11</span>
};
ages <span class="Keyword">=</span> (<span class="Storage">function</span>() {
__b <span class="Keyword">=</span> []; __a <span class="Keyword">=</span> years_old;
<span class="Keyword">for</span> (child <span class="Keyword">in</span> __a) {
age <span class="Keyword">=</span> __a[child];
<span class="Keyword">if</span> (__a.hasOwnProperty(child)) {
__b.<span class="LibraryFunction">push</span>(child <span class="Keyword">+</span> <span class="String"><span class="String">&quot;</span> is <span class="String">&quot;</span></span> <span class="Keyword">+</span> age);
}
}
<span class="Keyword">return</span> __b;
})();
</pre><button onclick='javascript: var __a, __b, age, ages, child, years_old;
years_old = {
max: 10,
ida: 9,
tim: 11
};
ages = (function() {
__b = []; __a = years_old;
for (child in __a) {
age = __a[child];
if (__a.hasOwnProperty(child)) {
__b.push(child + " is " + age);
}
}
return __b;
})();
;alert(ages.join(", "));'>run: ages.join(", ")</button><br class='clear' /></div>
<p id="slice_splice"> <p id="slice_splice">
<b class="header">Array Slicing and Splicing with Ranges</b> <b class="header">Array Slicing and Splicing with Ranges</b>
@ -841,7 +913,7 @@ six = (one = 1) + (two = 2) + (three = 3);
<div class='code'><pre class="idle"><span class="Comment"><span class="Comment">#</span> The first ten global properties.</span> <div class='code'><pre class="idle"><span class="Comment"><span class="Comment">#</span> The first ten global properties.</span>
globals<span class="Keyword">:</span> (name <span class="Keyword">for</span> property, name <span class="Keyword">in</span> window)[<span class="Number">0</span>...<span class="Number">10</span>] globals<span class="Keyword">:</span> (name <span class="Keyword">for</span> property, name <span class="Keyword">in</span> window)[<span class="Number">0</span>...<span class="Number">10</span>]
</pre><pre class="idle"><span class="Storage">var</span> __a, __b, globals, name; </pre><pre class="idle"><span class="Storage">var</span> __a, __b, globals, name, property;
<span class="Comment"><span class="Comment">//</span> The first ten global properties.</span> <span class="Comment"><span class="Comment">//</span> The first ten global properties.</span>
globals <span class="Keyword">=</span> ((<span class="Storage">function</span>() { globals <span class="Keyword">=</span> ((<span class="Storage">function</span>() {
__b <span class="Keyword">=</span> []; __a <span class="Keyword">=</span> <span class="LibraryClassType">window</span>; __b <span class="Keyword">=</span> []; __a <span class="Keyword">=</span> <span class="LibraryClassType">window</span>;
@ -851,7 +923,7 @@ globals <span class="Keyword">=</span> ((<span class="Storage">function</span>()
} }
<span class="Keyword">return</span> __b; <span class="Keyword">return</span> __b;
})()).<span class="LibraryFunction">slice</span>(<span class="Number">0</span>, <span class="Number">10</span>); })()).<span class="LibraryFunction">slice</span>(<span class="Number">0</span>, <span class="Number">10</span>);
</pre><button onclick='javascript: var __a, __b, globals, name; </pre><button onclick='javascript: var __a, __b, globals, name, property;
// The first ten global properties. // The first ten global properties.
globals = ((function() { globals = ((function() {
__b = []; __a = window; __b = []; __a = window;
@ -870,20 +942,20 @@ globals = ((function() {
<span class="Keyword">try</span> <span class="Keyword">try</span>
nonexistent <span class="Keyword">/</span> <span class="BuiltInConstant">undefined</span> nonexistent <span class="Keyword">/</span> <span class="BuiltInConstant">undefined</span>
<span class="Keyword">catch</span> error <span class="Keyword">catch</span> error
<span class="String"><span class="String">&quot;</span>The error is: <span class="String">&quot;</span></span> <span class="Keyword">+</span> error <span class="String"><span class="String">&quot;</span>Caught an error: <span class="String">&quot;</span></span> <span class="Keyword">+</span> error
) )
</pre><pre class="idle"><span class="LibraryFunction">alert</span>((<span class="Storage">function</span>() { </pre><pre class="idle"><span class="LibraryFunction">alert</span>((<span class="Storage">function</span>() {
<span class="Keyword">try</span> { <span class="Keyword">try</span> {
<span class="Keyword">return</span> nonexistent / undefined; <span class="Keyword">return</span> nonexistent / undefined;
} <span class="Keyword">catch</span> (error) { } <span class="Keyword">catch</span> (error) {
<span class="Keyword">return</span> <span class="String"><span class="String">&quot;</span>The error is: <span class="String">&quot;</span></span> <span class="Keyword">+</span> error; <span class="Keyword">return</span> <span class="String"><span class="String">&quot;</span>Caught an error: <span class="String">&quot;</span></span> <span class="Keyword">+</span> error;
} }
})()); })());
</pre><button onclick='javascript: alert((function() { </pre><button onclick='javascript: alert((function() {
try { try {
return nonexistent / undefined; return nonexistent / undefined;
} catch (error) { } catch (error) {
return "The error is: " + error; return "Caught an error: " + error;
} }
})()); })());
;'>run</button><br class='clear' /></div> ;'>run</button><br class='clear' /></div>

View file

@ -214,7 +214,7 @@
</dict> </dict>
<dict> <dict>
<key>match</key> <key>match</key>
<string>\b([a-zA-Z$_]\w*)(\:)\s</string> <string>\b([a-zA-Z$_](\w|\$)*)(\:)\s</string>
<key>name</key> <key>name</key>
<string>variable.assignment.coffee</string> <string>variable.assignment.coffee</string>
<key>captures</key> <key>captures</key>
@ -224,7 +224,7 @@
<key>name</key> <key>name</key>
<string>entity.name.function.coffee</string> <string>entity.name.function.coffee</string>
</dict> </dict>
<key>2</key> <key>3</key>
<dict> <dict>
<key>name</key> <key>name</key>
<string>keyword.operator.coffee</string> <string>keyword.operator.coffee</string>
@ -263,7 +263,7 @@
</dict> </dict>
<dict> <dict>
<key>match</key> <key>match</key>
<string>!|\$|%|&amp;|\*|\/|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|&lt;=|&gt;=|&lt;&lt;=|&gt;&gt;=|&gt;&gt;&gt;=|&lt;&gt;|&lt;|&gt;|!|&amp;&amp;|\?|\|\||\:|\*=|(?&lt;!\()/=|%=|\+=|\-=|&amp;=|\^=|\b(in|instanceof|new|delete|typeof|and|or|is|isnt|not)\b</string> <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>
<key>name</key> <key>name</key>
<string>keyword.operator.coffee</string> <string>keyword.operator.coffee</string>
</dict> </dict>

View file

@ -8,7 +8,7 @@ token IDENTIFIER PROPERTY_ACCESS
token CODE PARAM NEW RETURN token CODE PARAM NEW RETURN
token TRY CATCH FINALLY THROW token TRY CATCH FINALLY THROW
token BREAK CONTINUE token BREAK CONTINUE
token FOR IN BY WHEN WHILE token FOR IN INO BY WHEN WHILE
token SWITCH LEADING_WHEN token SWITCH LEADING_WHEN
token DELETE INSTANCEOF TYPEOF token DELETE INSTANCEOF TYPEOF
token SUPER EXTENDS token SUPER EXTENDS
@ -34,7 +34,7 @@ prechigh
left '.' left '.'
right INDENT right INDENT
left OUTDENT left OUTDENT
right WHEN LEADING_WHEN IN BY right WHEN LEADING_WHEN IN INO BY
right THROW FOR NEW SUPER right THROW FOR NEW SUPER
left EXTENDS left EXTENDS
left ASSIGN '||=' '&&=' left ASSIGN '||=' '&&='
@ -360,6 +360,7 @@ rule
# The source of the array comprehension can optionally be filtered. # The source of the array comprehension can optionally be filtered.
ForSource: ForSource:
IN Expression { result = {:source => val[1]} } IN Expression { result = {:source => val[1]} }
| INO Expression { result = {:source => val[1], :object => true} }
| ForSource | ForSource
WHEN Expression { result = val[0].merge(:filter => val[2]) } WHEN Expression { result = val[0].merge(:filter => val[2]) }
| ForSource | ForSource

View file

@ -12,14 +12,14 @@ module CoffeeScript
"new", "return", "new", "return",
"try", "catch", "finally", "throw", "try", "catch", "finally", "throw",
"break", "continue", "break", "continue",
"for", "in", "by", "where", "while", "for", "in", "ino", "by", "where", "while",
"switch", "when", "switch", "when",
"super", "extends", "super", "extends",
"arguments", "arguments",
"delete", "instanceof", "typeof"] "delete", "instanceof", "typeof"]
# Token matching regexes. # Token matching regexes.
IDENTIFIER = /\A([a-zA-Z$_]\w*)/ IDENTIFIER = /\A([a-zA-Z$_](\w|\$)*)/
NUMBER = /\A(\b((0(x|X)[0-9a-fA-F]+)|([0-9]+(\.[0-9]+)?(e[+\-]?[0-9]+)?)))\b/i NUMBER = /\A(\b((0(x|X)[0-9a-fA-F]+)|([0-9]+(\.[0-9]+)?(e[+\-]?[0-9]+)?)))\b/i
STRING = /\A(""|''|"(.*?)([^\\]|\\\\)"|'(.*?)([^\\]|\\\\)')/m STRING = /\A(""|''|"(.*?)([^\\]|\\\\)"|'(.*?)([^\\]|\\\\)')/m
JS = /\A(``|`(.*?)([^\\]|\\\\)`)/m JS = /\A(``|`(.*?)([^\\]|\\\\)`)/m

View file

@ -153,6 +153,10 @@ module CoffeeScript
attr_reader :value attr_reader :value
def self.wrap(string)
self.new(Value.new(string))
end
def initialize(value) def initialize(value)
@value = value @value = value
end end
@ -384,7 +388,7 @@ module CoffeeScript
# part of a comprehension, slice, or splice. # part of a comprehension, slice, or splice.
# TODO: This generates pretty ugly code ... shrink it. # TODO: This generates pretty ugly code ... shrink it.
def compile_array(o) def compile_array(o)
body = Expressions.wrap(LiteralNode.new(Value.new('i'))) body = Expressions.wrap(LiteralNode.wrap('i'))
arr = Expressions.wrap(ForNode.new(body, {:source => ValueNode.new(self)}, Value.new('i'))) arr = Expressions.wrap(ForNode.new(body, {:source => ValueNode.new(self)}, Value.new('i')))
ParentheticalNode.new(CallNode.new(CodeNode.new([], arr))).compile(o) ParentheticalNode.new(CallNode.new(CodeNode.new([], arr))).compile(o)
end end
@ -629,6 +633,8 @@ module CoffeeScript
@source = source[:source] @source = source[:source]
@filter = source[:filter] @filter = source[:filter]
@step = source[:step] @step = source[:step]
@object = !!source[:object]
@name, @index = @index, @name if @object
end end
def compile_node(o) def compile_node(o)
@ -636,6 +642,7 @@ module CoffeeScript
range = @source.is_a?(ValueNode) && @source.literal.is_a?(RangeNode) && @source.properties.empty? range = @source.is_a?(ValueNode) && @source.literal.is_a?(RangeNode) && @source.properties.empty?
source = range ? @source.literal : @source source = range ? @source.literal : @source
scope = o[:scope] scope = o[:scope]
scope.find(@name)
index_found = @index && scope.find(@index) index_found = @index && scope.find(@index)
body_dent = idt(1) body_dent = idt(1)
svar = scope.free_variable svar = scope.free_variable
@ -650,6 +657,7 @@ module CoffeeScript
index_var = nil index_var = nil
source_part = "#{svar} = #{source.compile(o)};\n#{idt}" source_part = "#{svar} = #{source.compile(o)};\n#{idt}"
for_part = "#{ivar}=0; #{ivar}<#{svar}.length; #{ivar}++" for_part = "#{ivar}=0; #{ivar}<#{svar}.length; #{ivar}++"
for_part = "#{@index} in #{svar}" if @object
var_part = "#{body_dent}#{@name} = #{svar}[#{ivar}];\n" var_part = "#{body_dent}#{@name} = #{svar}[#{ivar}];\n"
end end
body = @body body = @body
@ -659,7 +667,7 @@ module CoffeeScript
body = Expressions.wrap(body) body = Expressions.wrap(body)
else else
body = Expressions.wrap(CallNode.new( body = Expressions.wrap(CallNode.new(
ValueNode.new(LiteralNode.new(rvar), [AccessorNode.new('push')]), [@body.unwrap] ValueNode.new(LiteralNode.new(rvar), [AccessorNode.new('push')]), [body.unwrap]
)) ))
end end
if o[:return] if o[:return]
@ -667,7 +675,15 @@ module CoffeeScript
o.delete(:return) o.delete(:return)
body = IfNode.new(@filter, body, nil, :statement => true) if @filter body = IfNode.new(@filter, body, nil, :statement => true) if @filter
elsif @filter elsif @filter
body = Expressions.wrap(IfNode.new(@filter, @body)) body = Expressions.wrap(IfNode.new(@filter, body))
end
if @object
body = Expressions.wrap(IfNode.new(
CallNode.new(ValueNode.new(LiteralNode.wrap(svar), [AccessorNode.new(Value.new('hasOwnProperty'))]), [LiteralNode.wrap(@index)]),
Expressions.wrap(body),
nil,
{:statement => true}
))
end end
return_result = "\n#{idt}#{return_result};" unless top_level return_result = "\n#{idt}#{return_result};" unless top_level

View file

@ -4,6 +4,14 @@ results: n * 2 for n in nums
print(results.join(',') is '2,18') print(results.join(',') is '2,18')
obj: {one: 1, two: 2, three: 3}
names: key + '!' for key, value ino obj
odds: key + '!' for key, value ino obj when value % 2 isnt 0
print(names.join(' ') is "one! two! three!")
print(odds.join(' ') is "one! three!")
evens: for num in [1, 2, 3, 4, 5, 6] when num % 2 is 0 evens: for num in [1, 2, 3, 4, 5, 6] when num % 2 is 0
num *= -1 num *= -1
num -= 2 num -= 2

View file

@ -29,4 +29,9 @@ print(reg(str) and str is '\\')
i: 10 i: 10
while i -= 1 while i -= 1
print(i is 0) print(i is 0)
money$: 'dollars'
print(money$ is 'dollars')