mirror of
https://github.com/jashkenas/coffeescript.git
synced 2022-11-09 12:23:24 -05:00
* Passthrough exponentiation operator; remove tests that are invalid JavaScript * Treat **= as a passthrough assignment * Get tests passing in Node 6 * Improve scoping * Move exponentiation tests into their own file, now that it's filtered out by Cakefile * Restore original test
This commit is contained in:
parent
e5aa758dda
commit
195a46ab77
6 changed files with 27 additions and 41 deletions
|
@ -3318,11 +3318,11 @@
|
||||||
if ((ref1 = this.context) === '||=' || ref1 === '&&=' || ref1 === '?=') {
|
if ((ref1 = this.context) === '||=' || ref1 === '&&=' || ref1 === '?=') {
|
||||||
return this.compileConditional(o);
|
return this.compileConditional(o);
|
||||||
}
|
}
|
||||||
if ((ref2 = this.context) === '**=' || ref2 === '//=' || ref2 === '%%=') {
|
if ((ref2 = this.context) === '//=' || ref2 === '%%=') {
|
||||||
return this.compileSpecialMath(o);
|
return this.compileSpecialMath(o);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!this.context) {
|
if (!this.context || this.context === '**=') {
|
||||||
varBase = this.variable.unwrapAll();
|
varBase = this.variable.unwrapAll();
|
||||||
if (!varBase.isAssignable()) {
|
if (!varBase.isAssignable()) {
|
||||||
this.variable.error(`'${this.variable.compile(o)}' can't be assigned`);
|
this.variable.error(`'${this.variable.compile(o)}' can't be assigned`);
|
||||||
|
@ -3791,7 +3791,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert special math assignment operators like `a **= b` to the equivalent
|
// Convert special math assignment operators like `a //= b` to the equivalent
|
||||||
// extended form `a = a ** b` and then compiles that.
|
// extended form `a = a ** b` and then compiles that.
|
||||||
compileSpecialMath(o) {
|
compileSpecialMath(o) {
|
||||||
var left, right;
|
var left, right;
|
||||||
|
@ -4800,8 +4800,6 @@
|
||||||
switch (this.operator) {
|
switch (this.operator) {
|
||||||
case '?':
|
case '?':
|
||||||
return this.compileExistence(o, this.second.isDefaultValue);
|
return this.compileExistence(o, this.second.isDefaultValue);
|
||||||
case '**':
|
|
||||||
return this.compilePower(o);
|
|
||||||
case '//':
|
case '//':
|
||||||
return this.compileFloorDivision(o);
|
return this.compileFloorDivision(o);
|
||||||
case '%%':
|
case '%%':
|
||||||
|
@ -4903,13 +4901,6 @@
|
||||||
return this.joinFragmentArrays(parts, '');
|
return this.joinFragmentArrays(parts, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
compilePower(o) {
|
|
||||||
var pow;
|
|
||||||
// Make a Math.pow call
|
|
||||||
pow = new Value(new IdentifierLiteral('Math'), [new Access(new PropertyName('pow'))]);
|
|
||||||
return new Call(pow, [this.first, this.second]).compileToFragments(o);
|
|
||||||
}
|
|
||||||
|
|
||||||
compileFloorDivision(o) {
|
compileFloorDivision(o) {
|
||||||
var div, floor, second;
|
var div, floor, second;
|
||||||
floor = new Value(new IdentifierLiteral('Math'), [new Access(new PropertyName('floor'))]);
|
floor = new Value(new IdentifierLiteral('Math'), [new Access(new PropertyName('floor'))]);
|
||||||
|
|
|
@ -2222,9 +2222,9 @@ exports.Assign = class Assign extends Base
|
||||||
|
|
||||||
return @compileSplice o if @variable.isSplice()
|
return @compileSplice o if @variable.isSplice()
|
||||||
return @compileConditional o if @context in ['||=', '&&=', '?=']
|
return @compileConditional o if @context in ['||=', '&&=', '?=']
|
||||||
return @compileSpecialMath o if @context in ['**=', '//=', '%%=']
|
return @compileSpecialMath o if @context in ['//=', '%%=']
|
||||||
|
|
||||||
unless @context
|
if not @context or @context is '**='
|
||||||
varBase = @variable.unwrapAll()
|
varBase = @variable.unwrapAll()
|
||||||
unless varBase.isAssignable()
|
unless varBase.isAssignable()
|
||||||
@variable.error "'#{@variable.compile o}' can't be assigned"
|
@variable.error "'#{@variable.compile o}' can't be assigned"
|
||||||
|
@ -2548,7 +2548,7 @@ exports.Assign = class Assign extends Base
|
||||||
fragments = new Op(@context[...-1], left, new Assign(right, @value, '=')).compileToFragments o
|
fragments = new Op(@context[...-1], left, new Assign(right, @value, '=')).compileToFragments o
|
||||||
if o.level <= LEVEL_LIST then fragments else @wrapInParentheses fragments
|
if o.level <= LEVEL_LIST then fragments else @wrapInParentheses fragments
|
||||||
|
|
||||||
# Convert special math assignment operators like `a **= b` to the equivalent
|
# Convert special math assignment operators like `a //= b` to the equivalent
|
||||||
# extended form `a = a ** b` and then compiles that.
|
# extended form `a = a ** b` and then compiles that.
|
||||||
compileSpecialMath: (o) ->
|
compileSpecialMath: (o) ->
|
||||||
[left, right] = @variable.cacheReference o
|
[left, right] = @variable.cacheReference o
|
||||||
|
@ -3253,7 +3253,6 @@ exports.Op = class Op extends Base
|
||||||
return @compileChain o if isChain
|
return @compileChain o if isChain
|
||||||
switch @operator
|
switch @operator
|
||||||
when '?' then @compileExistence o, @second.isDefaultValue
|
when '?' then @compileExistence o, @second.isDefaultValue
|
||||||
when '**' then @compilePower o
|
|
||||||
when '//' then @compileFloorDivision o
|
when '//' then @compileFloorDivision o
|
||||||
when '%%' then @compileModulo o
|
when '%%' then @compileModulo o
|
||||||
else
|
else
|
||||||
|
@ -3320,11 +3319,6 @@ exports.Op = class Op extends Base
|
||||||
parts.push [@makeCode ")"] if o.level >= LEVEL_PAREN
|
parts.push [@makeCode ")"] if o.level >= LEVEL_PAREN
|
||||||
@joinFragmentArrays parts, ''
|
@joinFragmentArrays parts, ''
|
||||||
|
|
||||||
compilePower: (o) ->
|
|
||||||
# Make a Math.pow call
|
|
||||||
pow = new Value new IdentifierLiteral('Math'), [new Access new PropertyName 'pow']
|
|
||||||
new Call(pow, [@first, @second]).compileToFragments o
|
|
||||||
|
|
||||||
compileFloorDivision: (o) ->
|
compileFloorDivision: (o) ->
|
||||||
floor = new Value new IdentifierLiteral('Math'), [new Access new PropertyName 'floor']
|
floor = new Value new IdentifierLiteral('Math'), [new Access new PropertyName 'floor']
|
||||||
second = if @second.shouldCache() then new Parens @second else @second
|
second = if @second.shouldCache() then new Parens @second else @second
|
||||||
|
|
19
test/exponentiation.coffee
Normal file
19
test/exponentiation.coffee
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# The `**` and `**=` operators are only supported in Node 7.5+, so the tests
|
||||||
|
# for these exponentiation operators are split out into their own file to be
|
||||||
|
# loaded only by supported runtimes.
|
||||||
|
|
||||||
|
test "exponentiation operator", ->
|
||||||
|
eq 27, 3 ** 3
|
||||||
|
|
||||||
|
test "exponentiation operator has higher precedence than other maths operators", ->
|
||||||
|
eq 55, 1 + 3 ** 3 * 2
|
||||||
|
eq -4, -2 ** 2
|
||||||
|
eq 0, (!2) ** 2
|
||||||
|
|
||||||
|
test "exponentiation operator is right associative", ->
|
||||||
|
eq 2, 2 ** 1 ** 3
|
||||||
|
|
||||||
|
test "exponentiation operator compound assignment", ->
|
||||||
|
a = 2
|
||||||
|
a **= 3
|
||||||
|
eq 8, a
|
|
@ -168,7 +168,7 @@ test "`throw` can be yielded", ->
|
||||||
throws -> x.next()
|
throws -> x.next()
|
||||||
|
|
||||||
test "symbolic operators has precedence over the `yield`", ->
|
test "symbolic operators has precedence over the `yield`", ->
|
||||||
symbolic = '+ - * / << >> & | || && ** ^ // or and'.split ' '
|
symbolic = '+ - * / << >> & | || && ^ // or and'.split ' '
|
||||||
compound = ("#{op}=" for op in symbolic)
|
compound = ("#{op}=" for op in symbolic)
|
||||||
relations = '< > == != <= >= is isnt'.split ' '
|
relations = '< > == != <= >= is isnt'.split ' '
|
||||||
|
|
||||||
|
|
|
@ -139,7 +139,7 @@ eq 'multiline nested "interpolations" work', """multiline #{
|
||||||
|
|
||||||
eq 'function(){}', "#{->}".replace /\s/g, ''
|
eq 'function(){}', "#{->}".replace /\s/g, ''
|
||||||
ok /^a[\s\S]+b$/.test "a#{=>}b"
|
ok /^a[\s\S]+b$/.test "a#{=>}b"
|
||||||
ok /^a[\s\S]+b$/.test "a#{ (x) -> x ** 2 }b"
|
ok /^a[\s\S]+b$/.test "a#{ (x) -> x %% 2 }b"
|
||||||
|
|
||||||
# Regular Expression Interpolation
|
# Regular Expression Interpolation
|
||||||
|
|
||||||
|
|
|
@ -305,24 +305,6 @@ test "#2508: Existential access of the prototype", ->
|
||||||
eq NonExistent?::nothing, undefined
|
eq NonExistent?::nothing, undefined
|
||||||
ok Object?::toString
|
ok Object?::toString
|
||||||
|
|
||||||
test "power operator", ->
|
|
||||||
eq 27, 3 ** 3
|
|
||||||
|
|
||||||
test "power operator has higher precedence than other maths operators", ->
|
|
||||||
eq 55, 1 + 3 ** 3 * 2
|
|
||||||
eq -4, -2 ** 2
|
|
||||||
eq false, !2 ** 2
|
|
||||||
eq 0, (!2) ** 2
|
|
||||||
eq -2, ~1 ** 5
|
|
||||||
|
|
||||||
test "power operator is right associative", ->
|
|
||||||
eq 2, 2 ** 1 ** 3
|
|
||||||
|
|
||||||
test "power operator compound assignment", ->
|
|
||||||
a = 2
|
|
||||||
a **= 3
|
|
||||||
eq 8, a
|
|
||||||
|
|
||||||
test "floor division operator", ->
|
test "floor division operator", ->
|
||||||
eq 2, 7 // 3
|
eq 2, 7 // 3
|
||||||
eq -3, -7 // 3
|
eq -3, -7 // 3
|
||||||
|
|
Loading…
Reference in a new issue