Got the DRY object pattern matching style working properly, from Harmony. {name, age}: person now works correctly.

This commit is contained in:
Jeremy Ashkenas
2010-04-25 22:21:53 -04:00
parent 328a14014c
commit a894db35fd
6 changed files with 223 additions and 183 deletions

View File

@@ -127,7 +127,11 @@
], ],
// Assignment when it happens within an object literal. The difference from // Assignment when it happens within an object literal. The difference from
// the ordinary **Assign** is that these allow numbers and strings as keys. // the ordinary **Assign** is that these allow numbers and strings as keys.
AssignObj: [o("Identifier ASSIGN Expression", function() { AssignObj: [o("Identifier", function() {
return new ValueNode($1);
}), o("AlphaNumeric", function() {
return new ValueNode($1);
}), o("Identifier ASSIGN Expression", function() {
return new AssignNode(new ValueNode($1), $3, 'object'); return new AssignNode(new ValueNode($1), $3, 'object');
}), o("AlphaNumeric ASSIGN Expression", function() { }), o("AlphaNumeric ASSIGN Expression", function() {
return new AssignNode(new ValueNode($1), $3, 'object'); return new AssignNode(new ValueNode($1), $3, 'object');

View File

@@ -937,11 +937,18 @@
_a = this.variable.base.objects; _a = this.variable.base.objects;
for (i = 0, _b = _a.length; i < _b; i++) { for (i = 0, _b = _a.length; i < _b; i++) {
obj = _a[i]; obj = _a[i];
// A regular array pattern-match.
idx = i; idx = i;
if (this.variable.is_object()) { if (this.variable.is_object()) {
_c = [obj.value, obj.variable.base]; if (obj instanceof AssignNode) {
obj = _c[0]; // A regular object pattern-match.
idx = _c[1]; _c = [obj.value, obj.variable.base];
obj = _c[0];
idx = _c[1];
} else {
// A shorthand `{a, b, c}: val` pattern-match.
idx = obj;
}
} }
if (!(obj instanceof ValueNode || obj instanceof SplatNode)) { if (!(obj instanceof ValueNode || obj instanceof SplatNode)) {
throw new Error('pattern matching must use only identifiers on the left-hand side.'); throw new Error('pattern matching must use only identifiers on the left-hand side.');

File diff suppressed because one or more lines are too long

View File

@@ -147,6 +147,8 @@ grammar: {
# Assignment when it happens within an object literal. The difference from # Assignment when it happens within an object literal. The difference from
# the ordinary **Assign** is that these allow numbers and strings as keys. # the ordinary **Assign** is that these allow numbers and strings as keys.
AssignObj: [ AssignObj: [
o "Identifier", -> new ValueNode $1
o "AlphaNumeric", -> new ValueNode $1
o "Identifier ASSIGN Expression", -> new AssignNode new ValueNode($1), $3, 'object' o "Identifier ASSIGN Expression", -> new AssignNode new ValueNode($1), $3, 'object'
o "AlphaNumeric ASSIGN Expression", -> new AssignNode new ValueNode($1), $3, 'object' o "AlphaNumeric ASSIGN Expression", -> new AssignNode new ValueNode($1), $3, 'object'
o "Comment" o "Comment"
@@ -448,7 +450,7 @@ grammar: {
o "IN Expression WHEN Expression", -> {source: $2, filter: $4} o "IN Expression WHEN Expression", -> {source: $2, filter: $4}
o "OF Expression WHEN Expression", -> {source: $2, filter: $4, object: true} o "OF Expression WHEN Expression", -> {source: $2, filter: $4, object: true}
o "IN Expression BY Expression", -> {source: $2, step: $4} o "IN Expression BY Expression", -> {source: $2, step: $4}
o "IN Expression WHEN Expression BY Expression", -> {source: $2, filter: $4; step: $6} o "IN Expression WHEN Expression BY Expression", -> {source: $2, filter: $4, step: $6}
o "IN Expression BY Expression WHEN Expression", -> {source: $2, step: $4, filter: $6} o "IN Expression BY Expression WHEN Expression", -> {source: $2, step: $4, filter: $6}
] ]

View File

@@ -690,8 +690,15 @@ exports.AssignNode: class AssignNode extends BaseNode
o.as_statement: true o.as_statement: true
splat: false splat: false
for obj, i in @variable.base.objects for obj, i in @variable.base.objects
# A regular array pattern-match.
idx: i idx: i
[obj, idx]: [obj.value, obj.variable.base] if @variable.is_object() if @variable.is_object()
if obj instanceof AssignNode
# A regular object pattern-match.
[obj, idx]: [obj.value, obj.variable.base]
else
# A shorthand `{a, b, c}: val` pattern-match.
idx: obj
if not (obj instanceof ValueNode or obj instanceof SplatNode) if not (obj instanceof ValueNode or obj instanceof SplatNode)
throw new Error 'pattern matching must use only identifiers on the left-hand side.' throw new Error 'pattern matching must use only identifiers on the left-hand side.'
is_string: idx.value and idx.value.match IS_STRING is_string: idx.value and idx.value.match IS_STRING

View File

@@ -89,8 +89,24 @@ test: {
ok addr.join(', ') is "Street 101, Apt 101, City 101" ok addr.join(', ') is "Street 101, Apt 101, City 101"
# Destructuring against an expression. # Pattern matching against an expression.
[a, b]: if true then [2, 1] else [1, 2] [a, b]: if true then [2, 1] else [1, 2]
ok a is 2 ok a is 2
ok b is 1 ok b is 1
# Pattern matching with object shorthand.
person: {
name: "Bob"
age: 26
dogs: ["Prince", "Bowie"]
}
{name, age, dogs: [first, second]}: person
ok name is "Bob"
ok age is 26
ok first is "Prince"
ok second is "Bowie"