Self-compiler: now does while loops

This commit is contained in:
Jeremy Ashkenas
2010-02-09 22:05:17 -05:00
parent fd80d784f4
commit 8e3e06a6e9
4 changed files with 70 additions and 7 deletions

View File

@@ -1,5 +1,5 @@
(function(){
var AccessorNode, ArrayNode, AssignNode, CallNode, ClosureNode, CodeNode, CommentNode, Expressions, ExtendsNode, IndexNode, LiteralNode, Node, ObjectNode, PushNode, RangeNode, ReturnNode, SliceNode, SplatNode, TAB, TRAILING_WHITESPACE, ThisNode, ValueNode, any, compact, del, dup, flatten, inherit, merge, statement;
var AccessorNode, ArrayNode, AssignNode, CallNode, ClosureNode, CodeNode, CommentNode, Expressions, ExtendsNode, IndexNode, LiteralNode, Node, ObjectNode, PushNode, RangeNode, ReturnNode, SliceNode, SplatNode, TAB, TRAILING_WHITESPACE, ThisNode, ValueNode, WhileNode, any, compact, del, dup, flatten, inherit, merge, statement;
var __hasProp = Object.prototype.hasOwnProperty;
process.mixin(require('./scope'));
// The abstract base class for all CoffeeScript nodes.
@@ -372,7 +372,7 @@
compile: function compile(o) {
o = o || {
};
return o.scope ? compile.__superClass__.constructor.call(this, o) : this.compile_root(o);
return o.scope ? Node.prototype.compile.call(this, o) : this.compile_root(o);
},
// Compile each expression in the Expressions body.
compile_node: function compile_node(o) {
@@ -998,4 +998,36 @@
return "Array.prototype.slice.call(" + this.name + ', ' + this.index + ')';
}
}));
// A while loop, the only sort of low-level loop exposed by CoffeeScript. From
// it, all other loops can be manufactured.
WhileNode = (exports.WhileNode = inherit(Node, {
constructor: function constructor(condition, body) {
this.children = [(this.condition = condition), (this.body = body)];
return this;
},
top_sensitive: function top_sensitive() {
return true;
},
compile_node: function compile_node(o) {
var cond, post, pre, returns, rvar, set, top;
returns = del(o, 'returns');
top = del(o, 'top') && !returns;
o.indent = this.idt(1);
o.top = true;
cond = this.condition.compile(o);
set = '';
if (!top) {
rvar = o.scope.free_variable();
set = this.idt() + rvar + ' = [];\n';
this.body = PushNode.wrap(rvar, this.body);
}
post = returns ? '\n' + this.idt() + 'return ' + rvar + ';' : '';
pre = set + this.idt() + 'while (' + cond + ')';
if (!this.body) {
return pre + ' null;' + post;
}
return pre + ' {\n' + this.body.compile(o) + '\n' + this.idt() + '}' + post;
}
}));
statement(WhileNode);
})();