mirror of
https://github.com/jashkenas/coffeescript.git
synced 2026-02-18 19:34:27 -05:00
Merge branch 'for_destructuring' of git://github.com/StanAngeloff/coffee-script
This commit is contained in:
@@ -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];
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
|
|||||||
12
lib/nodes.js
12
lib/nodes.js
@@ -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) {
|
||||||
|
|||||||
164
lib/parser.js
164
lib/parser.js
File diff suppressed because one or more lines are too long
@@ -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
|
||||||
|
|||||||
@@ -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++"
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user