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

@ -314,10 +314,10 @@
num = 0;
pos = string.indexOf(letter);
while (pos !== -1) {
count += 1;
num += 1;
pos = string.indexOf(letter, pos + 1);
}
return count;
return num;
};
// Attempt to match a string against the current chunk, returning the indexed
// match.

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);
})();

View File

@ -246,9 +246,9 @@ lex::count: (string, letter) ->
num: 0
pos: string.indexOf(letter)
while pos isnt -1
count += 1
num += 1
pos: string.indexOf(letter, pos + 1)
count
num
# Attempt to match a string against the current chunk, returning the indexed
# match.

View File

@ -182,7 +182,7 @@ Expressions: exports.Expressions: inherit Node, {
compile: (o) ->
o ||= {}
if o.scope then super(o) else @compile_root(o)
if o.scope then Node::compile.call(this, o) else @compile_root(o)
# Compile each expression in the Expressions body.
compile_node: (o) ->
@ -711,6 +711,37 @@ SplatNode: exports.SplatNode: inherit Node, {
}
# 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: (condition, body) ->
@children:[@condition: condition, @body: body]
this
top_sensitive: ->
true
compile_node: (o) ->
returns: del(o, 'returns')
top: del(o, 'top') and not returns
o.indent: @idt(1)
o.top: true
cond: @condition.compile(o)
set: ''
if not top
rvar: o.scope.free_variable()
set: @idt() + rvar + ' = [];\n'
@body: PushNode.wrap(rvar, @body)
post: if returns then '\n' + @idt() + 'return ' + rvar + ';' else ''
pre: set + @idt() + 'while (' + cond + ')'
return pre + ' null;' + post if not @body
pre + ' {\n' + @body.compile(o) + '\n' + @idt() + '}' + post
}
statement WhileNode