adding conditional while loops with while ... when

This commit is contained in:
Jeremy Ashkenas 2010-02-23 22:53:43 -05:00
parent 4d146bacb1
commit 4eeb8c4bd2
7 changed files with 90 additions and 65 deletions

View File

@ -414,13 +414,20 @@
return new ParentheticalNode($2);
})
],
// The condition for a while loop.
WhileSource: [o("WHILE Expression", function() {
return new WhileNode($2);
}), o("WHILE Expression WHEN Expression", function() {
return new WhileNode($2, {
filter: $4
});
})
],
// The while loop. (there is no do..while).
While: [o("WHILE Expression Block", function() {
return new WhileNode($2, $3);
}), o("WHILE Expression", function() {
return new WhileNode($2, null);
}), o("Expression WHILE Expression", function() {
return new WhileNode($3, Expressions.wrap([$1]));
While: [o("WhileSource Block", function() {
return $1.add_body($2);
}), o("Expression WhileSource", function() {
return $2.add_body($1);
})
],
// Array comprehensions, including guard and current index.

View File

@ -891,8 +891,13 @@
// it, all other loops can be manufactured.
WhileNode = (exports.WhileNode = inherit(Node, {
type: 'While',
constructor: function constructor(condition, body) {
this.children = [(this.condition = condition), (this.body = body)];
constructor: function constructor(condition, opts) {
this.children = [(this.condition = condition)];
this.filter = opts && opts.filter;
return this;
},
add_body: function add_body(body) {
this.children.push((this.body = body));
return this;
},
top_sensitive: function top_sensitive() {
@ -909,13 +914,18 @@
if (!top) {
rvar = o.scope.free_variable();
set = this.idt() + rvar + ' = [];\n';
this.body = PushNode.wrap(rvar, this.body);
if (this.body) {
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;
}
if (this.filter) {
this.body = Expressions.wrap([new IfNode(this.filter, this.body)]);
}
return pre + ' {\n' + this.body.compile(o) + '\n' + this.idt() + '}' + post;
}
}));

File diff suppressed because one or more lines are too long

View File

@ -360,11 +360,16 @@ grammar: {
o "( Expression )", -> new ParentheticalNode($2)
]
# The condition for a while loop.
WhileSource: [
o "WHILE Expression", -> new WhileNode($2)
o "WHILE Expression WHEN Expression", -> new WhileNode($2, {filter : $4})
]
# The while loop. (there is no do..while).
While: [
o "WHILE Expression Block", -> new WhileNode($2, $3)
o "WHILE Expression", -> new WhileNode($2, null)
o "Expression WHILE Expression", -> new WhileNode($3, Expressions.wrap([$1]))
o "WhileSource Block", -> $1.add_body $2
o "Expression WhileSource", -> $2.add_body $1
]
# Array comprehensions, including guard and current index.
@ -384,10 +389,8 @@ grammar: {
ForSource: [
o "IN Expression", -> {source: $2}
o "OF Expression", -> {source: $2, object: true}
o "ForSource WHEN Expression", ->
$1.filter: $3; $1
o "ForSource BY Expression", ->
$1.step: $3; $1
o "ForSource WHEN Expression", -> $1.filter: $3; $1
o "ForSource BY Expression", -> $1.step: $3; $1
]
# Switch/When blocks.
@ -406,8 +409,7 @@ grammar: {
When: [
o "LEADING_WHEN SimpleArgs Block", -> new IfNode($2, $3, null, {statement: true})
o "LEADING_WHEN SimpleArgs Block TERMINATOR", -> new IfNode($2, $3, null, {statement: true})
o "Comment TERMINATOR When", ->
$3.comment: $1; $3
o "Comment TERMINATOR When", -> $3.comment: $1; $3
]
# The most basic form of "if".

View File

@ -701,8 +701,13 @@ SplatNode: exports.SplatNode: inherit Node, {
WhileNode: exports.WhileNode: inherit Node, {
type: 'While'
constructor: (condition, body) ->
@children:[@condition: condition, @body: body]
constructor: (condition, opts) ->
@children:[@condition: condition]
@filter: opts and opts.filter
this
add_body: (body) ->
@children.push @body: body
this
top_sensitive: ->
@ -718,10 +723,11 @@ WhileNode: exports.WhileNode: inherit Node, {
if not top
rvar: o.scope.free_variable()
set: @idt() + rvar + ' = [];\n'
@body: PushNode.wrap(rvar, @body)
@body: PushNode.wrap(rvar, @body) if @body
post: if returns then '\n' + @idt() + 'return ' + rvar + ';' else ''
pre: set + @idt() + 'while (' + cond + ')'
return pre + ' null;' + post if not @body
@body: Expressions.wrap([new IfNode(@filter, @body)]) if @filter
pre + ' {\n' + @body.compile(o) + '\n' + @idt() + '}' + post
}

View File

@ -26,12 +26,6 @@ reg: /\\/
ok reg(str) and str is '\\'
i: 10
while i -= 1
ok i is 0
money$: 'dollars'
ok money$ is 'dollars'

View File

@ -1,9 +1,3 @@
i: 100
while i -= 1
ok i is 0
i: 5
list: while i -= 1
i * 2
@ -25,4 +19,12 @@ results: while func 1
assert()
i
ok results.join(' ') is '4 3 2 1'
ok results.join(' ') is '4 3 2 1'
i: 10
results: while i -= 1 when i % 2 is 0
i * 2
ok results.join(' ') is '16 12 8 4'