From 4f4032c0537c2d4ab1722863b4f90b7085c5d30c Mon Sep 17 00:00:00 2001 From: satyr Date: Mon, 1 Nov 2010 10:42:42 +0900 Subject: [PATCH 1/2] fixed a bug that compound assignments were declaring variables --- lib/nodes.js | 4 ++-- src/nodes.coffee | 5 +++-- test/test_assignment.coffee | 4 ++++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/nodes.js b/lib/nodes.js index a4919e63..2832f555 100644 --- a/lib/nodes.js +++ b/lib/nodes.js @@ -927,7 +927,7 @@ if (!this.variable.isAssignable()) { throw SyntaxError("\"" + (this.variable.compile(o)) + "\" cannot be assigned."); } - if (!(isValue && (this.variable.hasProperties() || this.variable.namespaced))) { + if (!(this.context || isValue && (this.variable.namespaced || this.variable.hasProperties()))) { o.scope.find(name); } val = name + (" " + (this.context || '=') + " ") + val; @@ -1001,7 +1001,7 @@ Assign.prototype.compileConditional = function(o) { var _ref2, left, rite; _ref2 = this.variable.cacheReference(o), left = _ref2[0], rite = _ref2[1]; - return new Op(this.context.slice(0, -1), left, new Assign(rite, this.value)).compile(o); + return new Op(this.context.slice(0, -1), left, new Assign(rite, this.value, '=')).compile(o); }; return Assign; })(); diff --git a/src/nodes.coffee b/src/nodes.coffee index 0ded8aa0..e1122e78 100644 --- a/src/nodes.coffee +++ b/src/nodes.coffee @@ -764,7 +764,8 @@ exports.Assign = class Assign extends Base return "#{name}: #{val}" if @context is 'object' unless @variable.isAssignable() throw SyntaxError "\"#{ @variable.compile o }\" cannot be assigned." - o.scope.find name unless isValue and (@variable.hasProperties() or @variable.namespaced) + o.scope.find name unless @context or + isValue and (@variable.namespaced or @variable.hasProperties()) val = name + " #{ @context or '=' } " + val if o.level <= LEVEL_LIST then val else "(#{val})" @@ -833,7 +834,7 @@ exports.Assign = class Assign extends Base # more than once. compileConditional: (o) -> [left, rite] = @variable.cacheReference o - return new Op(@context.slice(0, -1), left, new Assign(rite, @value)).compile o + new Op(@context.slice(0, -1), left, new Assign(rite, @value, '=')).compile o #### Code diff --git a/test/test_assignment.coffee b/test/test_assignment.coffee index 820fcdf5..cf1fc958 100644 --- a/test/test_assignment.coffee +++ b/test/test_assignment.coffee @@ -64,3 +64,7 @@ eq val, 'value' for nonref in ['""', '0', 'f()'] try ok not CoffeeScript.compile "{k: #{nonref}} = v" catch e then eq e.message, "\"#{nonref}\" cannot be assigned." + + +# Compound assignments should not declare. +eq Math, (-> Math or= 0)() From 56391df34571db00ec03ea048b7eadc0a05f0005 Mon Sep 17 00:00:00 2001 From: satyr Date: Tue, 2 Nov 2010 02:51:46 +0900 Subject: [PATCH 2/2] dynakeys: optimized and fixed a bug in caching --- lib/nodes.js | 36 ++++++++++++++++++++---------------- src/nodes.coffee | 23 ++++++++++++----------- 2 files changed, 32 insertions(+), 27 deletions(-) diff --git a/lib/nodes.js b/lib/nodes.js index 2832f555..f5fdb836 100644 --- a/lib/nodes.js +++ b/lib/nodes.js @@ -661,15 +661,16 @@ __extends(Obj, Base); Obj.prototype.children = ['properties']; Obj.prototype.compileNode = function(o) { - var _i, _len, _len2, _ref2, _ref3, _result, i, indent, join, lastNoncom, nonComments, obj, prop, props; + var _i, _len, _len2, _ref2, _ref3, _result, i, idt, indent, join, lastNoncom, nonComments, obj, prop, props, rest; _ref2 = this.properties; for (i = 0, _len = _ref2.length; i < _len; i++) { prop = _ref2[i]; if ((prop.variable || prop).base instanceof Parens) { - return this.compileDynamic(o, i); + rest = this.properties.splice(i); + break; } } - o.indent = this.idt(1); + o.indent = idt = this.idt(1); nonComments = ((function() { _ref3 = this.properties; _result = []; @@ -688,7 +689,7 @@ for (i = 0, _len2 = _ref3.length; i < _len2; i++) { prop = _ref3[i]; join = i === this.properties.length - 1 ? '' : prop === lastNoncom || prop instanceof Comment ? '\n' : ',\n'; - indent = prop instanceof Comment ? '' : this.idt(1); + indent = prop instanceof Comment ? '' : idt; if (prop instanceof Value && prop.tags["this"]) { prop = new Assign(prop.properties[0].name, prop, 'object'); } else if (!(prop instanceof Assign) && !(prop instanceof Comment)) { @@ -699,16 +700,17 @@ return _result; }).call(this); props = props.join(''); - obj = "{" + (props ? '\n' + props + '\n' + this.idt() : '') + "}"; + obj = "{" + (props && '\n' + props + '\n' + this.tab) + "}"; + if (rest) { + return this.compileDynamic(o, obj, rest); + } return this.tags.front ? "(" + obj + ")" : obj; }; - Obj.prototype.compileDynamic = function(o, idx) { - var _len, _ref2, _ref3, acc, code, i, key, obj, prop, ref, val; - obj = o.scope.freeVariable('obj'); - code = "" + obj + " = " + (new Obj(this.properties.slice(0, idx)).compile(o)) + ", "; - _ref2 = this.properties.slice(idx); - for (i = 0, _len = _ref2.length; i < _len; i++) { - prop = _ref2[i]; + Obj.prototype.compileDynamic = function(o, code, props) { + var _len, _ref2, acc, i, key, oref, prop, ref, val; + code = "" + (oref = o.scope.freeVariable('obj')) + " = " + code + ", "; + for (i = 0, _len = props.length; i < _len; i++) { + prop = props[i]; if (prop instanceof Comment) { code += prop.compile(o) + ' '; continue; @@ -719,13 +721,15 @@ val = prop.value.compile(o, LEVEL_LIST); } else { acc = prop.base; - _ref3 = acc.cache(o, LEVEL_LIST, ref), key = _ref3[0], val = _ref3[1]; - ref = val; + _ref2 = acc.cache(o, LEVEL_LIST, ref), key = _ref2[0], val = _ref2[1]; + if (key !== val) { + ref = val; + } } key = acc instanceof Literal && IDENTIFIER.test(key) ? '.' + key : '[' + key + ']'; - code += "" + obj + key + " = " + val + ", "; + code += "" + oref + key + " = " + val + ", "; } - code += obj; + code += oref; return o.level <= LEVEL_PAREN ? code : "(" + code + ")"; }; Obj.prototype.assigns = function(name) { diff --git a/src/nodes.coffee b/src/nodes.coffee index e1122e78..d3ea7834 100644 --- a/src/nodes.coffee +++ b/src/nodes.coffee @@ -563,8 +563,9 @@ exports.Obj = class Obj extends Base compileNode: (o) -> for prop, i in @properties when (prop.variable or prop).base instanceof Parens - return @compileDynamic o, i - o.indent = @idt 1 + rest = @properties.splice i + break + o.indent = idt = @idt 1 nonComments = (prop for prop in @properties when prop not instanceof Comment) lastNoncom = last nonComments props = for prop, i in @properties @@ -574,20 +575,20 @@ exports.Obj = class Obj extends Base '\n' else ',\n' - indent = if prop instanceof Comment then '' else @idt 1 + indent = if prop instanceof Comment then '' else idt if prop instanceof Value and prop.tags.this prop = new Assign prop.properties[0].name, prop, 'object' else if prop not instanceof Assign and prop not instanceof Comment prop = new Assign prop, prop, 'object' indent + prop.compile(o) + join props = props.join '' - obj = "{#{ if props then '\n' + props + '\n' + @idt() else '' }}" + obj = "{#{ props and '\n' + props + '\n' + @tab }}" + return @compileDynamic o, obj, rest if rest if @tags.front then "(#{obj})" else obj - compileDynamic: (o, idx) -> - obj = o.scope.freeVariable 'obj' - code = "#{obj} = #{ new Obj(@properties.slice 0, idx).compile o }, " - for prop, i in @properties.slice idx + compileDynamic: (o, code, props) -> + code = "#{ oref = o.scope.freeVariable 'obj' } = #{code}, " + for prop, i in props if prop instanceof Comment code += prop.compile(o) + ' ' continue @@ -598,13 +599,13 @@ exports.Obj = class Obj extends Base else acc = prop.base [key, val] = acc.cache o, LEVEL_LIST, ref - ref = val + ref = val if key isnt val key = if acc instanceof Literal and IDENTIFIER.test key '.' + key else '[' + key + ']' - code += "#{obj}#{key} = #{val}, " - code += obj + code += "#{oref}#{key} = #{val}, " + code += oref if o.level <= LEVEL_PAREN then code else "(#{code})" assigns: (name) ->