Merge branch 'for_destructuring' of git://github.com/StanAngeloff/coffee-script

This commit is contained in:
Jeremy Ashkenas
2010-04-26 23:34:07 -04:00
6 changed files with 151 additions and 87 deletions

View File

@@ -448,12 +448,20 @@
return new ForNode($4, $3, $2[0], $2[1]); return new ForNode($4, $3, $2[0], $2[1]);
}) })
], ],
// An array of all accepted values for a variable inside the loop. This
// enables support for pattern matching.
ForValue: [o("Identifier"), o("Array", function() {
return new ValueNode($1);
}), o("Object", function() {
return new ValueNode($1);
})
],
// An array or range comprehension has variables for the current element and // An array or range comprehension has variables for the current element and
// (optional) reference to the current index. Or, *key, value*, in the case // (optional) reference to the current index. Or, *key, value*, in the case
// of object comprehensions. // of object comprehensions.
ForVariables: [o("Identifier", function() { ForVariables: [o("ForValue", function() {
return [$1]; return [$1];
}), o("Identifier , Identifier", function() { }), o("ForValue , ForValue", function() {
return [$1, $3]; return [$1, $3];
}) })
], ],

View File

@@ -1464,6 +1464,10 @@
this.name = _b[0]; this.name = _b[0];
this.index = _b[1]; this.index = _b[1];
} }
this.pattern = this.name instanceof ValueNode;
if (this.index instanceof ValueNode) {
throw new Error('index cannot be a pattern matching expression');
}
this.children = compact([this.body, this.source, this.filter]); this.children = compact([this.body, this.source, this.filter]);
this.returns = false; this.returns = false;
return this; return this;
@@ -1494,7 +1498,7 @@
scope = o.scope; scope = o.scope;
name = this.name && this.name.compile(o); name = this.name && this.name.compile(o);
index = this.index && this.index.compile(o); index = this.index && this.index.compile(o);
if (name) { if (name && !this.pattern) {
scope.find(name); scope.find(name);
} }
if (index) { if (index) {
@@ -1519,7 +1523,11 @@
svar = scope.free_variable(); svar = scope.free_variable();
index_var = null; index_var = null;
source_part = ("" + svar + " = " + (this.source.compile(o)) + ";\n" + this.tab); source_part = ("" + svar + " = " + (this.source.compile(o)) + ";\n" + this.tab);
if (name) { if (this.pattern) {
o.indent = this.idt(1);
o.top = true;
var_part = new AssignNode(this.name, literal(("" + svar + "[" + ivar + "]"))).compile(o) + "\n";
} else if (name) {
var_part = ("" + body_dent + name + " = " + svar + "[" + ivar + "];\n"); var_part = ("" + body_dent + name + " = " + svar + "[" + ivar + "];\n");
} }
if (!this.object) { if (!this.object) {

File diff suppressed because one or more lines are too long

View File

@@ -433,12 +433,20 @@ grammar: {
o "FOR ForVariables ForSource Block", -> new ForNode $4, $3, $2[0], $2[1] o "FOR ForVariables ForSource Block", -> new ForNode $4, $3, $2[0], $2[1]
] ]
# An array of all accepted values for a variable inside the loop. This
# enables support for pattern matching.
ForValue: [
o "Identifier"
o "Array", -> new ValueNode $1
o "Object", -> new ValueNode $1
]
# An array or range comprehension has variables for the current element and # An array or range comprehension has variables for the current element and
# (optional) reference to the current index. Or, *key, value*, in the case # (optional) reference to the current index. Or, *key, value*, in the case
# of object comprehensions. # of object comprehensions.
ForVariables: [ ForVariables: [
o "Identifier", -> [$1] o "ForValue", -> [$1]
o "Identifier , Identifier", -> [$1, $3] o "ForValue , ForValue", -> [$1, $3]
] ]
# The source of a comprehension is an array or object with an optional filter # The source of a comprehension is an array or object with an optional filter

View File

@@ -1080,6 +1080,8 @@ exports.ForNode: class ForNode extends BaseNode
@step: source.step @step: source.step
@object: !!source.object @object: !!source.object
[@name, @index]: [@index, @name] if @object [@name, @index]: [@index, @name] if @object
@pattern: @name instanceof ValueNode
throw new Error('index cannot be a pattern matching expression') if @index instanceof ValueNode
@children: compact [@body, @source, @filter] @children: compact [@body, @source, @filter]
@returns: false @returns: false
@@ -1105,7 +1107,7 @@ exports.ForNode: class ForNode extends BaseNode
scope: o.scope scope: o.scope
name: @name and @name.compile o name: @name and @name.compile o
index: @index and @index.compile o index: @index and @index.compile o
scope.find name if name scope.find name if name and not @pattern
scope.find index if index scope.find index if index
body_dent: @idt 1 body_dent: @idt 1
rvar: scope.free_variable() unless top_level rvar: scope.free_variable() unless top_level
@@ -1121,7 +1123,12 @@ exports.ForNode: class ForNode extends BaseNode
svar: scope.free_variable() svar: scope.free_variable()
index_var: null index_var: null
source_part: "$svar = ${ @source.compile(o) };\n$@tab" source_part: "$svar = ${ @source.compile(o) };\n$@tab"
var_part: "$body_dent$name = $svar[$ivar];\n" if name if @pattern
o.indent: @idt 1
o.top: true
var_part: new AssignNode(@name, literal("$svar[$ivar]")).compile(o) + "\n"
else
var_part: "$body_dent$name = $svar[$ivar];\n" if name
if not @object if not @object
lvar: scope.free_variable() lvar: scope.free_variable()
step_part: if @step then "$ivar += ${ @step.compile(o) }" else "$ivar++" step_part: if @step then "$ivar += ${ @step.compile(o) }" else "$ivar++"

View File

@@ -110,3 +110,30 @@ ok name is "Bob"
ok age is 26 ok age is 26
ok first is "Prince" ok first is "Prince"
ok second is "Bowie" ok second is "Bowie"
# Pattern matching within for..loops
persons: {
George: { name: "Bob" },
Bob: { name: "Alice" }
Christopher: { name: "Stan" }
}
join1: "$key: $name" for key, { name } of persons
deepEqual join1, ["George: Bob", "Bob: Alice", "Christopher: Stan"]
persons: [
{ name: "Bob", parent: { name: "George" } },
{ name: "Alice", parent: { name: "Bob" } },
{ name: "Stan", parent: { name: "Christopher" } }
]
join2: "$parent: $name" for { name, parent: { name: parent } } in persons
deepEqual join1, join2
persons: [['Bob', ['George']], ['Alice', ['Bob']], ['Stan', ['Christopher']]]
join3: "$parent: $name" for [name, [parent]] in persons
deepEqual join2, join3