Enchancing pattern matching with @vars ... issue #721

This commit is contained in:
Jeremy Ashkenas 2010-10-04 22:10:10 -04:00
parent 8eb283df2c
commit d1bca6364a
7 changed files with 220 additions and 175 deletions

View File

@ -88,7 +88,7 @@
AssignObj: [
o("Identifier", function() {
return new ValueNode($1);
}), o("AlphaNumeric"), o("Identifier : Expression", function() {
}), o("AlphaNumeric"), o("ThisProperty"), o("Identifier : Expression", function() {
return new AssignNode(new ValueNode($1), $3, 'object');
}), o("AlphaNumeric : Expression", function() {
return new AssignNode(new ValueNode($1), $3, 'object');
@ -309,7 +309,7 @@
],
ThisProperty: [
o("@ Identifier", function() {
return new ValueNode(new LiteralNode('this'), [new AccessorNode($2)]);
return new ValueNode(new LiteralNode('this'), [new AccessorNode($2)], 'this');
})
],
Range: [

View File

@ -300,11 +300,14 @@
return ReturnNode;
})();
exports.ValueNode = (function() {
ValueNode = function(_arg, _arg2) {
ValueNode = function(_arg, _arg2, tag) {
this.properties = _arg2;
this.base = _arg;
ValueNode.__super__.constructor.call(this);
this.properties || (this.properties = []);
if (tag) {
this.tags[tag] = true;
}
return this;
};
__extends(ValueNode, BaseNode);
@ -798,7 +801,9 @@
join = '';
}
indent = prop instanceof CommentNode ? '' : this.idt(1);
if (!(prop instanceof AssignNode || prop instanceof CommentNode)) {
if (prop instanceof ValueNode && prop.tags['this']) {
prop = new AssignNode(prop.properties[0].name, prop, 'object');
} else if (!(prop instanceof AssignNode) && !(prop instanceof CommentNode)) {
prop = new AssignNode(prop, prop, 'object');
}
return indent + prop.compile(o) + join;
@ -1018,7 +1023,11 @@
if (obj instanceof AssignNode) {
_ref2 = [obj.value, obj.variable.base], obj = _ref2[0], idx = _ref2[1];
} else {
idx = obj;
if (obj.tags['this']) {
idx = obj.properties[0].name;
} else {
idx = obj;
}
}
}
if (!(obj instanceof ValueNode || obj instanceof SplatNode)) {

File diff suppressed because one or more lines are too long

View File

@ -149,6 +149,7 @@ grammar =
AssignObj: [
o "Identifier", -> new ValueNode $1
o "AlphaNumeric"
o "ThisProperty"
o "Identifier : Expression", -> new AssignNode new ValueNode($1), $3, 'object'
o "AlphaNumeric : Expression", -> new AssignNode new ValueNode($1), $3, 'object'
o "Identifier : INDENT Expression OUTDENT", -> new AssignNode new ValueNode($1), $4, 'object'
@ -340,7 +341,7 @@ grammar =
# A reference to a property on *this*.
ThisProperty: [
o "@ Identifier", -> new ValueNode new LiteralNode('this'), [new AccessorNode($2)]
o "@ Identifier", -> new ValueNode new LiteralNode('this'), [new AccessorNode($2)], 'this'
]
# The CoffeeScript range literal.

View File

@ -294,9 +294,10 @@ exports.ValueNode = class ValueNode extends BaseNode
children: ['base', 'properties']
# A **ValueNode** has a base and a list of property accesses.
constructor: (@base, @properties) ->
constructor: (@base, @properties, tag) ->
super()
@properties or= []
@tags[tag] = yes if tag
# Add a property access to the list.
push: (prop) ->
@ -713,7 +714,10 @@ exports.ObjectNode = class ObjectNode extends BaseNode
join = "\n" if (prop is lastNoncom) or (prop instanceof CommentNode)
join = '' if i is @properties.length - 1
indent = if prop instanceof CommentNode then '' else @idt 1
prop = new AssignNode prop, prop, 'object' unless prop instanceof AssignNode or prop instanceof CommentNode
if prop instanceof ValueNode and prop.tags['this']
prop = new AssignNode prop.properties[0].name, prop, 'object'
else if prop not instanceof AssignNode and prop not instanceof CommentNode
prop = new AssignNode prop, prop, 'object'
indent + prop.compile(o) + join
props = props.join('')
obj = '{' + (if props then '\n' + props + '\n' + @idt() else '') + '}'
@ -900,8 +904,12 @@ exports.AssignNode = class AssignNode extends BaseNode
# A regular object pattern-match.
[obj, idx] = [obj.value, obj.variable.base]
else
# A shorthand `{a, b, c} = val` pattern-match.
idx = obj
if obj.tags['this']
# A shorthand `{@a, @b, @c} = val` pattern-match.
idx = obj.properties[0].name
else
# A shorthand `{a, b, c} = val` pattern-match.
idx = obj
unless obj instanceof ValueNode or obj instanceof SplatNode
throw new Error 'pattern matching must use only identifiers on the left-hand side.'
accessClass = if isObject and IDENTIFIER.test(idx.value) then AccessorNode else IndexNode

View File

@ -249,3 +249,14 @@ ok b is 100
eq '\\`', `
"\\\`"
`
# Shorthand objects with property references.
obj =
one: 1
two: 2
func: -> {@one, @two}
result = obj.func()
ok result.one is 1
ok result.two is 2

View File

@ -142,3 +142,17 @@ ok a is 101
[x] = {0: y} = {'0': z} = [Math.random()]
ok x is y is z, 'destructuring in multiple'
# Destructuring into an object.
obj =
func: (list, object) ->
[@one, @two] = list
{@a, @b} = object
obj.func [1, 2], a: 'a', b: 'b'
eq obj.one, 1
eq obj.two, 2
eq obj.a, 'a'
eq obj.b, 'b'