Merge pull request #3777 from lydell/unary-plus-minus-refs

Fix #3598: Make unary + and - generate _refs
This commit is contained in:
Michael Ficarra
2015-01-09 18:12:52 -08:00
3 changed files with 65 additions and 2 deletions

View File

@@ -2309,7 +2309,7 @@
Op.prototype.isComplex = function() {
var _ref2;
return !(this.isUnary() && ((_ref2 = this.operator) === '+' || _ref2 === '-')) || this.first.isComplex();
return !(this.isUnary() && ((_ref2 = this.operator) === '+' || _ref2 === '-') && this.first instanceof Value && this.first.isSimpleNumber());
};
Op.prototype.isChainable = function() {

View File

@@ -1639,7 +1639,8 @@ exports.Op = class Op extends Base
not @second
isComplex: ->
not (@isUnary() and @operator in ['+', '-']) or @first.isComplex()
not (@isUnary() and @operator in ['+', '-'] and
@first instanceof Value and @first.isSimpleNumber())
# Am I capable of
# [Python-style comparison chaining](http://docs.python.org/reference/expressions.html#notin)?

View File

@@ -370,3 +370,65 @@ test "#3363: Modulo operator coercing order", ->
b = valueOf: -> count += 1
eq 4, a %% b
eq 5, count
test "#3598: Unary + and - coerce the operand once when it is an identifier", ->
# Unary + and - do not generate `_ref`s when the operand is a number, for
# readability. To make sure that they do when the operand is an identifier,
# test that they are consistent with another unary operator as well as another
# complex expression.
# Tip: Making one of the tests temporarily fail lets you easily inspect the
# compiled JavaScript.
assertOneCoercion = (fn) ->
count = 0
value = valueOf: -> count++; 1
fn value
eq 1, count
eq 1, 1 ? 0
eq 1, +1 ? 0
eq -1, -1 ? 0
assertOneCoercion (a) ->
eq 1, +a ? 0
assertOneCoercion (a) ->
eq -1, -a ? 0
assertOneCoercion (a) ->
eq -2, ~a ? 0
assertOneCoercion (a) ->
eq 0.5, a / 2 ? 0
ok -2 <= 1 < 2
ok -2 <= +1 < 2
ok -2 <= -1 < 2
assertOneCoercion (a) ->
ok -2 <= +a < 2
assertOneCoercion (a) ->
ok -2 <= -a < 2
assertOneCoercion (a) ->
ok -2 <= ~a < 2
assertOneCoercion (a) ->
ok -2 <= a / 2 < 2
arrayEq [0], (n for n in [0] by 1)
arrayEq [0], (n for n in [0] by +1)
arrayEq [0], (n for n in [0] by -1)
assertOneCoercion (a) ->
arrayEq [0], (n for n in [0] by +a)
assertOneCoercion (a) ->
arrayEq [0], (n for n in [0] by -a)
assertOneCoercion (a) ->
arrayEq [0], (n for n in [0] by ~a)
assertOneCoercion (a) ->
arrayEq [0], (n for n in [0] by a * 2 / 2)
ok 1 in [0, 1]
ok +1 in [0, 1]
ok -1 in [0, -1]
assertOneCoercion (a) ->
ok +a in [0, 1]
assertOneCoercion (a) ->
ok -a in [0, -1]
assertOneCoercion (a) ->
ok ~a in [0, -2]
assertOneCoercion (a) ->
ok a / 2 in [0, 0.5]