1
0
Fork 0
mirror of https://github.com/jashkenas/coffeescript.git synced 2022-11-09 12:23:24 -05:00

fixes #1234 ... :: now creates an intermediary "prototype" Access node before any additional property accesses

This commit is contained in:
Gerald Lewis 2011-08-10 21:59:57 -04:00
parent e5b77b180a
commit 29a44b84d5
7 changed files with 33 additions and 26 deletions

View file

@ -135,7 +135,7 @@
o('Identifier', function() { o('Identifier', function() {
return new Value($1); return new Value($1);
}), o('Value Accessor', function() { }), o('Value Accessor', function() {
return $1.push($2); return $1.concat($2);
}), o('Invocation Accessor', function() { }), o('Invocation Accessor', function() {
return new Value($1, [$2]); return new Value($1, [$2]);
}), o('ThisProperty') }), o('ThisProperty')
@ -162,7 +162,7 @@
}), o('?. Identifier', function() { }), o('?. Identifier', function() {
return new Access($2, 'soak'); return new Access($2, 'soak');
}), o(':: Identifier', function() { }), o(':: Identifier', function() {
return new Access($2, 'proto'); return [new Access(new Literal('prototype')), new Access($2)];
}), o('::', function() { }), o('::', function() {
return new Access(new Literal('prototype')); return new Access(new Literal('prototype'));
}), o('Index') }), o('Index')

View file

@ -344,9 +344,6 @@
switch (prev[0]) { switch (prev[0]) {
case '?': case '?':
prev[0] = 'INDEX_SOAK'; prev[0] = 'INDEX_SOAK';
break;
case '::':
prev[0] = 'INDEX_PROTO';
} }
} }
} }

View file

@ -382,6 +382,10 @@
this.properties.push(prop); this.properties.push(prop);
return this; return this;
}; };
Value.prototype.concat = function(props) {
this.properties = this.properties.concat(props);
return this;
};
Value.prototype.hasProperties = function() { Value.prototype.hasProperties = function() {
return !!this.properties.length; return !!this.properties.length;
}; };
@ -686,14 +690,17 @@
function Access(name, tag) { function Access(name, tag) {
this.name = name; this.name = name;
this.name.asKey = true; this.name.asKey = true;
this.proto = tag === 'proto' ? '.prototype' : '';
this.soak = tag === 'soak'; this.soak = tag === 'soak';
} }
Access.prototype.children = ['name']; Access.prototype.children = ['name'];
Access.prototype.compile = function(o) { Access.prototype.compile = function(o) {
var name; var name;
name = this.name.compile(o); name = this.name.compile(o);
return this.proto + (IDENTIFIER.test(name) ? "." + name : "[" + name + "]"); if (IDENTIFIER.test(name)) {
return "." + name;
} else {
return "[" + name + "]";
}
}; };
Access.prototype.isComplex = NO; Access.prototype.isComplex = NO;
return Access; return Access;
@ -705,7 +712,7 @@
} }
Index.prototype.children = ['index']; Index.prototype.children = ['index'];
Index.prototype.compile = function(o) { Index.prototype.compile = function(o) {
return (this.proto ? '.prototype' : '') + ("[" + (this.index.compile(o, LEVEL_PAREN)) + "]"); return "[" + (this.index.compile(o, LEVEL_PAREN)) + "]";
}; };
Index.prototype.isComplex = function() { Index.prototype.isComplex = function() {
return this.index.isComplex(); return this.index.isComplex();
@ -970,11 +977,11 @@
} }
} else { } else {
if (!assign.variable["this"]) { if (!assign.variable["this"]) {
assign.variable = new Value(new Literal(name), [new Access(base, 'proto')]); assign.variable = new Value(new Literal(name), [new Access(new Literal('prototype')), new Access(base)]);
} if (func instanceof Code && func.bound) {
if (func instanceof Code && func.bound && !assign.variable["this"]) { this.boundFuncs.push(base);
this.boundFuncs.push(base); func.bound = false;
func.bound = false; }
} }
} }
} }

View file

@ -138,7 +138,7 @@ case 61:this.$ = new yy.Splat($$[$0-1]);
break; break;
case 62:this.$ = new yy.Value($$[$0]); case 62:this.$ = new yy.Value($$[$0]);
break; break;
case 63:this.$ = $$[$0-1].push($$[$0]); case 63:this.$ = $$[$0-1].concat($$[$0]);
break; break;
case 64:this.$ = new yy.Value($$[$0-1], [$$[$0]]); case 64:this.$ = new yy.Value($$[$0-1], [$$[$0]]);
break; break;
@ -164,7 +164,7 @@ case 74:this.$ = new yy.Access($$[$0]);
break; break;
case 75:this.$ = new yy.Access($$[$0], 'soak'); case 75:this.$ = new yy.Access($$[$0], 'soak');
break; break;
case 76:this.$ = new yy.Access($$[$0], 'proto'); case 76:this.$ = [new yy.Access(new yy.Literal('prototype')), new yy.Access($$[$0])];
break; break;
case 77:this.$ = new yy.Access(new yy.Literal('prototype')); case 77:this.$ = new yy.Access(new yy.Literal('prototype'));
break; break;

View file

@ -217,7 +217,7 @@ grammar =
# Variables and properties that can be assigned to. # Variables and properties that can be assigned to.
SimpleAssignable: [ SimpleAssignable: [
o 'Identifier', -> new Value $1 o 'Identifier', -> new Value $1
o 'Value Accessor', -> $1.push $2 o 'Value Accessor', -> $1.concat $2
o 'Invocation Accessor', -> new Value $1, [$2] o 'Invocation Accessor', -> new Value $1, [$2]
o 'ThisProperty' o 'ThisProperty'
] ]
@ -244,7 +244,7 @@ grammar =
Accessor: [ Accessor: [
o '. Identifier', -> new Access $2 o '. Identifier', -> new Access $2
o '?. Identifier', -> new Access $2, 'soak' o '?. Identifier', -> new Access $2, 'soak'
o ':: Identifier', -> new Access $2, 'proto' o ':: Identifier', -> [(new Access new Literal 'prototype'), new Access $2]
o '::', -> new Access new Literal 'prototype' o '::', -> new Access new Literal 'prototype'
o 'Index' o 'Index'
] ]

View file

@ -336,7 +336,6 @@ exports.Lexer = class Lexer
tag = 'INDEX_START' tag = 'INDEX_START'
switch prev[0] switch prev[0]
when '?' then prev[0] = 'INDEX_SOAK' when '?' then prev[0] = 'INDEX_SOAK'
when '::' then prev[0] = 'INDEX_PROTO'
@token tag, value @token tag, value
value.length value.length

View file

@ -344,10 +344,15 @@ exports.Value = class Value extends Base
children: ['base', 'properties'] children: ['base', 'properties']
# Add a property access to the list. # Add a property `Access` to the list.
push: (prop) -> push: (prop) ->
@properties.push prop @properties.push prop
this this
# Add multiple property `Access`s to the list.
concat: (props) ->
@properties = @properties.concat props
this
hasProperties: -> hasProperties: ->
!!@properties.length !!@properties.length
@ -596,14 +601,13 @@ exports.Extends = class Extends extends Base
exports.Access = class Access extends Base exports.Access = class Access extends Base
constructor: (@name, tag) -> constructor: (@name, tag) ->
@name.asKey = yes @name.asKey = yes
@proto = if tag is 'proto' then '.prototype' else ''
@soak = tag is 'soak' @soak = tag is 'soak'
children: ['name'] children: ['name']
compile: (o) -> compile: (o) ->
name = @name.compile o name = @name.compile o
@proto + if IDENTIFIER.test name then ".#{name}" else "[#{name}]" if IDENTIFIER.test name then ".#{name}" else "[#{name}]"
isComplex: NO isComplex: NO
@ -616,7 +620,7 @@ exports.Index = class Index extends Base
children: ['index'] children: ['index']
compile: (o) -> compile: (o) ->
(if @proto then '.prototype' else '') + "[#{ @index.compile o, LEVEL_PAREN }]" "[#{ @index.compile o, LEVEL_PAREN }]"
isComplex: -> isComplex: ->
@index.isComplex() @index.isComplex()
@ -857,10 +861,10 @@ exports.Class = class Class extends Base
assign = new Assign new Literal(@externalCtor), func assign = new Assign new Literal(@externalCtor), func
else else
unless assign.variable.this unless assign.variable.this
assign.variable = new Value(new Literal(name), [new Access(base, 'proto')]) assign.variable = new Value(new Literal(name), [(new Access new Literal 'prototype'), new Access base ])
if func instanceof Code and func.bound and not assign.variable.this if func instanceof Code and func.bound
@boundFuncs.push base @boundFuncs.push base
func.bound = no func.bound = no
assign assign
compact exprs compact exprs