Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

more progress on For loops

  • Loading branch information...
commit 1ca54c334c33ecd26da3da16ea7a8aaeff869330 1 parent 6e7bedb
@maxtaco authored
View
119 lib/coffee-script/nodes.js
@@ -1,5 +1,5 @@
(function() {
- var Access, Arr, Assign, Await, Base, Block, CALL_CONTINUATION, Call, Class, Closure, Code, Comment, CpsCascade, Defer, Existence, Extends, For, IDENTIFIER, IDENTIFIER_STR, IS_STRING, If, In, Index, LEVEL_ACCESS, LEVEL_COND, LEVEL_LIST, LEVEL_OP, LEVEL_PAREN, LEVEL_TOP, Literal, METHOD_DEF, NEGATE, NO, Obj, Op, Param, Parens, RESERVED, Range, Return, SIMPLENUM, Scope, Slice, Slot, Splat, Switch, TAB, THIS, TameLoop, Throw, Try, UTILITIES, Value, While, YES, compact, del, ends, extend, flatten, last, merge, multident, starts, tame, unfoldSoak, utility, _ref;
+ var Access, Arr, Assign, Await, Base, Block, CALL_CONTINUATION, Call, Class, Closure, Code, Comment, CpsCascade, Defer, Existence, Extends, For, IDENTIFIER, IDENTIFIER_STR, IS_STRING, If, In, Index, LEVEL_ACCESS, LEVEL_COND, LEVEL_LIST, LEVEL_OP, LEVEL_PAREN, LEVEL_TOP, Literal, METHOD_DEF, NEGATE, NO, Obj, Op, Param, Parens, RESERVED, Range, Return, SIMPLENUM, Scope, Slice, Slot, Splat, Switch, TAB, THIS, Throw, Try, UTILITIES, Value, While, YES, compact, del, ends, extend, flatten, last, merge, multident, starts, tame, unfoldSoak, utility, _ref;
var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; }, __indexOf = Array.prototype.indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (__hasProp.call(this, i) && this[i] === item) return i; } return -1; };
Scope = require('./scope').Scope;
@@ -1919,6 +1919,35 @@
return false;
};
+ While.prototype.tameWrap = function(d) {
+ var body, break_assign, break_id, cond, condition, continue_assign, continue_block, continue_body, continue_id, inner_k_assign, inner_k_id, k, k_id, outStatements, top_assign, top_block, top_body, top_call, top_func, top_id, top_statements;
+ condition = d.condition;
+ body = d.body;
+ outStatements = [];
+ top_id = new Value(new Literal(tame["const"].t_while));
+ k_id = new Value(new Literal(tame["const"].k));
+ break_id = new Value(new Literal(tame["const"].b_while));
+ inner_k_id = new Value(new Literal(tame["const"].k_while));
+ break_assign = new Assign(break_id, k_id);
+ continue_id = new Value(new Literal(tame["const"].c_while));
+ continue_block = new Block([new Call(top_id, [k_id])]);
+ if (d.step) continue_block.unshift(d.step);
+ continue_body = new Code([], continue_block);
+ continue_assign = new Assign(continue_id, continue_body);
+ inner_k_assign = new Assign(inner_k_id, continue_id);
+ cond = new If(condition, body);
+ cond.addElse(new Block([new Call(break_id, [])]));
+ top_body = new Block([break_assign, continue_assign, inner_k_assign, cond]);
+ top_func = new Code([k_id], top_body);
+ top_assign = new Assign(top_id, top_func);
+ top_call = new Call(top_id, [k_id]);
+ top_statements = [];
+ if (d.init) top_statements = top_statements.concat(d.init);
+ top_statements = top_statements.concat([top_assign, top_call]);
+ if (k = this.needsDummyContinuation()) top_statements.unshift(k);
+ return top_block = new Block(top_statements);
+ };
+
While.prototype.callContinuation = function() {
var k;
k = new Call(new Literal(tame["const"].k_while, []));
@@ -1928,7 +1957,10 @@
While.prototype.compileTame = function(o) {
var b;
if (!this.tameNodeFlag) return null;
- b = TameLoop.wrap(this, this.condition, this.body);
+ b = this.tameWrap({
+ condition: this.condition,
+ body: this.body
+ });
return b.compile(o);
};
@@ -2507,21 +2539,41 @@
For.prototype.children = ['body', 'source', 'guard', 'step'];
For.prototype.compileTame = function(o, d) {
- var b, condition, init, step;
+ var a1, a2, a3, a4, b, body, condition, init, ival, len, len_rhs, len_val, ref, ref_val, ref_val_copy, step;
if (!this.tameNodeFlag) return null;
- if (this.range && d.name) {
- condition = new Op('<', d.name, this.source.base.to);
- console.log("SF " + this.source);
- init = new Assign(d.name, this.source.base.from);
- step = new Op('++', d.name);
- b = TameLoop.wrap(this, {
- condition: condition,
- body: this.body,
- init: init,
- step: step
- });
- return b.compile(o);
- }
+ body = d.body;
+ condition = null;
+ init = [];
+ step = null;
+ if (this.range && this.name) {
+ condition = new Op('<', this.name, this.source.base.to);
+ init = [new Assign(this.name, this.source.base.from)];
+ step = new Op('++', this.name);
+ } else if (!this.range && this.name) {
+ ival = new Value(new Literal(d.ivar));
+ len = o.scope.freeVariable('len');
+ ref = o.scope.freeVariable('ref');
+ ref_val = new Value(new Literal(ref));
+ len_val = new Value(new Literal(len));
+ a1 = new Assign(ref_val, this.source);
+ len_rhs = ref_val.copy().add(new Access(new Value(new Literal("length"))));
+ a2 = new Assign(len_val, len_rhs);
+ a3 = new Assign(ival, new Value(new Literal(0)));
+ init = [a1, a2, a3];
+ condition = new Op('<', ival, len_val);
+ step = new Op('++', ival);
+ ref_val_copy = ref_val.copy();
+ ref_val_copy.add(new Index(ival));
+ a4 = new Assign(this.name, ref_val_copy);
+ body.unshift(a4);
+ }
+ b = this.tameWrap({
+ condition: condition,
+ body: body,
+ init: init,
+ step: step
+ });
+ return b.compile(o);
};
For.prototype.compileNode = function(o) {
@@ -2552,12 +2604,9 @@
defPart = '';
idt1 = this.tab + TAB;
if (code = this.compileTame(o, {
- name: this.name,
- index: this.index,
ivar: ivar,
stepvar: stepvar,
- body: body,
- source: source
+ body: body
})) {
return code;
}
@@ -2885,36 +2934,6 @@
return ifn;
};
- TameLoop = {
- wrap: function(obj, d) {
- var body, break_assign, break_id, cond, condition, continue_assign, continue_block, continue_body, continue_id, inner_k_assign, inner_k_id, k, k_id, outStatements, top_assign, top_block, top_body, top_call, top_func, top_id, top_statements;
- condition = d.condition;
- body = d.body;
- outStatements = [];
- top_id = new Value(new Literal(tame["const"].t_while));
- k_id = new Value(new Literal(tame["const"].k));
- break_id = new Value(new Literal(tame["const"].b_while));
- inner_k_id = new Value(new Literal(tame["const"].k_while));
- break_assign = new Assign(break_id, k_id);
- continue_id = new Value(new Literal(tame["const"].c_while));
- continue_block = new Block([new Call(top_id, [k_id])]);
- if (d.step) continue_block.unshift(d.step);
- continue_body = new Code([], continue_block);
- continue_assign = new Assign(continue_id, continue_body);
- inner_k_assign = new Assign(inner_k_id, continue_id);
- cond = new If(condition, body);
- cond.addElse(new Block([new Call(break_id, [])]));
- top_body = new Block([break_assign, continue_assign, inner_k_assign, cond]);
- top_func = new Code([k_id], top_body);
- top_assign = new Assign(top_id, top_func);
- top_call = new Call(top_id, [k_id]);
- top_statements = [top_assign, top_call];
- if (d.init) top_statements.unshift(d.init);
- if (k = obj.needsDummyContinuation()) top_statements.unshift(k);
- return top_block = new Block(top_statements);
- }
- };
-
UTILITIES = {
"extends": function() {
return "function(child, parent) { for (var key in parent) { if (" + (utility('hasProp')) + ".call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; }";
View
1  lib/coffee-script/parser.js
@@ -1,5 +1,6 @@
/* Jison generated parser */
var parser = (function(){
+undefined
var parser = {trace: function trace() { },
yy: {},
symbols_: {"error":2,"Root":3,"Body":4,"Block":5,"TERMINATOR":6,"Line":7,"Expression":8,"Statement":9,"Return":10,"Throw":11,"Comment":12,"STATEMENT":13,"Await":14,"AWAIT":15,"Value":16,"Invocation":17,"Code":18,"Operation":19,"Assign":20,"If":21,"Try":22,"While":23,"For":24,"Switch":25,"Class":26,"Defer":27,"INDENT":28,"OUTDENT":29,"Identifier":30,"IDENTIFIER":31,"AlphaNumeric":32,"NUMBER":33,"STRING":34,"Literal":35,"JS":36,"REGEX":37,"BOOL":38,"Assignable":39,"=":40,"AssignObj":41,"ObjAssignable":42,":":43,"ThisProperty":44,"RETURN":45,"HERECOMMENT":46,"PARAM_START":47,"ParamList":48,"PARAM_END":49,"FuncGlyph":50,"->":51,"=>":52,"OptComma":53,",":54,"Param":55,"ParamVar":56,"...":57,"Array":58,"Object":59,"Splat":60,"SimpleAssignable":61,"Accessor":62,"Parenthetical":63,"Range":64,"This":65,".":66,"?.":67,"::":68,"Index":69,"INDEX_START":70,"IndexValue":71,"INDEX_END":72,"INDEX_SOAK":73,"Slice":74,"{":75,"AssignList":76,"}":77,"CLASS":78,"EXTENDS":79,"OptFuncExist":80,"Arguments":81,"SUPER":82,"DEFER":83,"FUNC_EXIST":84,"CALL_START":85,"CALL_END":86,"ArgList":87,"THIS":88,"@":89,"[":90,"]":91,"RangeDots":92,"..":93,"Arg":94,"SimpleArgs":95,"TRY":96,"Catch":97,"FINALLY":98,"CATCH":99,"THROW":100,"(":101,")":102,"WhileSource":103,"WHILE":104,"WHEN":105,"UNTIL":106,"Loop":107,"LOOP":108,"ForBody":109,"FOR":110,"ForStart":111,"ForSource":112,"ForVariables":113,"OWN":114,"ForValue":115,"FORIN":116,"FOROF":117,"BY":118,"SWITCH":119,"Whens":120,"ELSE":121,"When":122,"LEADING_WHEN":123,"IfBlock":124,"IF":125,"POST_IF":126,"UNARY":127,"-":128,"+":129,"--":130,"++":131,"?":132,"MATH":133,"SHIFT":134,"COMPARE":135,"LOGIC":136,"RELATION":137,"COMPOUND_ASSIGN":138,"$accept":0,"$end":1},
View
101 src/nodes.coffee
@@ -1560,13 +1560,41 @@ exports.While = class While extends Base
return node if node.jumps loop: yes
no
+ tameWrap : (d) ->
+ condition = d.condition
+ body = d.body
+ outStatements = []
+ top_id = new Value new Literal tame.const.t_while
+ k_id = new Value new Literal tame.const.k
+ break_id = new Value new Literal tame.const.b_while
+ inner_k_id = new Value new Literal tame.const.k_while
+ break_assign = new Assign break_id, k_id
+ continue_id = new Value new Literal tame.const.c_while
+ continue_block = new Block [ new Call top_id, [ k_id ] ]
+ continue_block.unshift d.step if d.step
+ continue_body = new Code [], continue_block
+ continue_assign = new Assign continue_id, continue_body
+ inner_k_assign = new Assign inner_k_id, continue_id
+ cond = new If condition, body
+ cond.addElse new Block [ new Call break_id, [] ]
+ top_body = new Block [ break_assign, continue_assign, inner_k_assign, cond ]
+ top_func = new Code [ k_id ], top_body
+ top_assign = new Assign top_id, top_func
+ top_call = new Call top_id, [ k_id ]
+ top_statements = []
+ top_statements = top_statements.concat d.init if d.init
+ top_statements = top_statements.concat [ top_assign, top_call ]
+ if k = @needsDummyContinuation()
+ top_statements.unshift k
+ top_block = new Block top_statements
+
callContinuation : ->
k = new Call(new Literal tame.const.k_while, [])
@body.push k
compileTame: (o) ->
return null unless @tameNodeFlag
- b = TameLoop.wrap this, @condition, @body
+ b = @tameWrap { @condition, @body }
return b.compile o
# The main difference from a JavaScript *while* is that the CoffeeScript
@@ -2017,13 +2045,39 @@ exports.For = class For extends While
compileTame: (o, d) ->
return null unless @tameNodeFlag
- if @range and d.name
- condition = new Op '<', d.name, @source.base.to
- init = new Assign d.name, @source.base.from
- step = new Op '++', d.name
- b = TameLoop.wrap this, { condition, @body, init, step }
- b.compile o
+ body = d.body
+ condition = null
+ init = []
+ step = null
+
+ # Handle the case of 'for i in [0..10]'
+ if @range and @name
+ condition = new Op '<', @name, @source.base.to
+ init = [ new Assign @name, @source.base.from ]
+ step = new Op '++', @name
+
+ # Handle the case of 'for i,blah in arr'
+ else if ! @range and @name
+ ival = new Value new Literal d.ivar
+ len = o.scope.freeVariable 'len'
+ ref = o.scope.freeVariable 'ref'
+ ref_val = new Value new Literal ref
+ len_val = new Value new Literal len
+ a1 = new Assign ref_val, @source
+ len_rhs = ref_val.copy().add new Access new Value new Literal "length"
+ a2 = new Assign len_val, len_rhs
+ a3 = new Assign ival, new Value new Literal 0
+ init = [ a1, a2, a3 ]
+ condition = new Op '<', ival, len_val
+ step = new Op '++', ival
+ ref_val_copy = ref_val.copy()
+ ref_val_copy.add new Index ival
+ a4 = new Assign @name, ref_val_copy
+ body.unshift a4
+
+ b = @tameWrap { condition, body, init, step }
+ b.compile o
# Welcome to the hairiest method in all of CoffeeScript. Handles the inner
# loop, filtering, stepping, and result saving for array, object, and range
@@ -2051,8 +2105,8 @@ exports.For = class For extends While
defPart = ''
idt1 = @tab + TAB
- return code if code = @compileTame o, {
- @name, @index, ivar, stepvar, body, source }
+ return code if code = @compileTame o, { ivar, stepvar, body }
+
if @range
forPart = source.compile merge(o, {index: ivar, name, @step})
else
@@ -2304,35 +2358,6 @@ unfoldSoak = (o, parent, name) ->
#### Unrolled loops
#
-TameLoop =
-
- wrap : (obj, d) ->
- condition = d.condition
- body = d.body
- outStatements = []
- top_id = new Value new Literal tame.const.t_while
- k_id = new Value new Literal tame.const.k
- break_id = new Value new Literal tame.const.b_while
- inner_k_id = new Value new Literal tame.const.k_while
- break_assign = new Assign break_id, k_id
- continue_id = new Value new Literal tame.const.c_while
- continue_block = new Block [ new Call top_id, [ k_id ] ]
- continue_block.unshift d.step if d.step
- continue_body = new Code [], continue_block
- continue_assign = new Assign continue_id, continue_body
- inner_k_assign = new Assign inner_k_id, continue_id
- cond = new If condition, body
- cond.addElse new Block [ new Call break_id, [] ]
- top_body = new Block [ break_assign, continue_assign, inner_k_assign, cond ]
- top_func = new Code [ k_id ], top_body
- top_assign = new Assign top_id, top_func
- top_call = new Call top_id, [ k_id ]
- top_statements = [ top_assign, top_call ]
- top_statements.unshift d.init if d.init
- if k = obj.needsDummyContinuation()
- top_statements.unshift k
- top_block = new Block top_statements
-
# Constants
# ---------
Please sign in to comment.
Something went wrong with that request. Please try again.