Merge pull request #3211 from marchaefner/issue2181

Fix compilation for conditional assignment
This commit is contained in:
Jeremy Ashkenas
2013-10-20 14:16:38 -07:00
3 changed files with 28 additions and 6 deletions

View File

@@ -1712,15 +1712,24 @@
};
Assign.prototype.compileConditional = function(o) {
var left, right, _ref4;
var fragments, left, right, _ref4;
_ref4 = this.variable.cacheReference(o), left = _ref4[0], right = _ref4[1];
if (!left.properties.length && left.base instanceof Literal && left.base.value !== "this" && !o.scope.check(left.base.value)) {
this.variable.error("the variable \"" + left.base.value + "\" can't be assigned with " + this.context + " because it has not been declared before");
}
if (__indexOf.call(this.context, "?") >= 0) {
o.isExistentialEquals = true;
return new If(new Existence(left), right, {
type: 'if'
}).addElse(new Assign(right, this.value, '=')).compileToFragments(o);
} else {
fragments = new Op(this.context.slice(0, -1), left, new Assign(right, this.value, '=')).compileToFragments(o);
if (o.level <= LEVEL_LIST) {
return fragments;
} else {
return this.wrapInBraces(fragments);
}
}
return new Op(this.context.slice(0, -1), left, new Assign(right, this.value, '=')).compileToFragments(o);
};
Assign.prototype.compileSplice = function(o) {
@@ -2318,7 +2327,7 @@
Op.prototype.compileExistence = function(o) {
var fst, ref;
if (!o.isExistentialEquals && this.first.isComplex()) {
if (this.first.isComplex()) {
ref = new Literal(o.scope.freeVariable('ref'));
fst = new Parens(new Assign(ref, this.first));
} else {

View File

@@ -1240,8 +1240,12 @@ exports.Assign = class Assign extends Base
if not left.properties.length and left.base instanceof Literal and
left.base.value != "this" and not o.scope.check left.base.value
@variable.error "the variable \"#{left.base.value}\" can't be assigned with #{@context} because it has not been declared before"
if "?" in @context then o.isExistentialEquals = true
new Op(@context[...-1], left, new Assign(right, @value, '=')).compileToFragments o
if "?" in @context
o.isExistentialEquals = true
new If(new Existence(left), right, type: 'if').addElse(new Assign(right, @value, '=')).compileToFragments o
else
fragments = new Op(@context[...-1], left, new Assign(right, @value, '=')).compileToFragments o
if o.level <= LEVEL_LIST then fragments else @wrapInBraces fragments
# Compile the assignment from an array splice literal, using JavaScript's
# `Array#splice` method.
@@ -1652,7 +1656,7 @@ exports.Op = class Op extends Base
# Keep reference to the left expression, unless this an existential assignment
compileExistence: (o) ->
if !o.isExistentialEquals and @first.isComplex()
if @first.isComplex()
ref = new Literal o.scope.freeVariable 'ref'
fst = new Parens new Assign ref, @first
else

View File

@@ -81,6 +81,9 @@ test "compound assignment should be careful about caching variables", ->
eq 5, base.five
eq 5, count
eq 5, base().five ?= 6
eq 6, count
test "compound assignment with implicit objects", ->
obj = undefined
obj ?=
@@ -380,3 +383,9 @@ test "#2613: parens on LHS of destructuring", ->
a = {}
[(a).b] = [1, 2, 3]
eq a.b, 1
test "#2181: conditional assignment as a subexpression", ->
a = false
false && a or= true
eq false, a
eq false, not a or= true