Skip to content

Commit 195a46a

Browse files
Fix #4877: Exponentiation operators (#4881)
* 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
1 parent e5aa758 commit 195a46a

File tree

6 files changed

+27
-41
lines changed

6 files changed

+27
-41
lines changed

lib/coffeescript/nodes.js

Lines changed: 3 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/nodes.coffee

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2222,9 +2222,9 @@ exports.Assign = class Assign extends Base
22222222

22232223
return @compileSplice o if @variable.isSplice()
22242224
return @compileConditional o if @context in ['||=', '&&=', '?=']
2225-
return @compileSpecialMath o if @context in ['**=', '//=', '%%=']
2225+
return @compileSpecialMath o if @context in ['//=', '%%=']
22262226

2227-
unless @context
2227+
if not @context or @context is '**='
22282228
varBase = @variable.unwrapAll()
22292229
unless varBase.isAssignable()
22302230
@variable.error "'#{@variable.compile o}' can't be assigned"
@@ -2548,7 +2548,7 @@ exports.Assign = class Assign extends Base
25482548
fragments = new Op(@context[...-1], left, new Assign(right, @value, '=')).compileToFragments o
25492549
if o.level <= LEVEL_LIST then fragments else @wrapInParentheses fragments
25502550

2551-
# Convert special math assignment operators like `a **= b` to the equivalent
2551+
# Convert special math assignment operators like `a //= b` to the equivalent
25522552
# extended form `a = a ** b` and then compiles that.
25532553
compileSpecialMath: (o) ->
25542554
[left, right] = @variable.cacheReference o
@@ -3253,7 +3253,6 @@ exports.Op = class Op extends Base
32533253
return @compileChain o if isChain
32543254
switch @operator
32553255
when '?' then @compileExistence o, @second.isDefaultValue
3256-
when '**' then @compilePower o
32573256
when '//' then @compileFloorDivision o
32583257
when '%%' then @compileModulo o
32593258
else
@@ -3320,11 +3319,6 @@ exports.Op = class Op extends Base
33203319
parts.push [@makeCode ")"] if o.level >= LEVEL_PAREN
33213320
@joinFragmentArrays parts, ''
33223321

3323-
compilePower: (o) ->
3324-
# Make a Math.pow call
3325-
pow = new Value new IdentifierLiteral('Math'), [new Access new PropertyName 'pow']
3326-
new Call(pow, [@first, @second]).compileToFragments o
3327-
33283322
compileFloorDivision: (o) ->
33293323
floor = new Value new IdentifierLiteral('Math'), [new Access new PropertyName 'floor']
33303324
second = if @second.shouldCache() then new Parens @second else @second

test/exponentiation.coffee

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# The `**` and `**=` operators are only supported in Node 7.5+, so the tests
2+
# for these exponentiation operators are split out into their own file to be
3+
# loaded only by supported runtimes.
4+
5+
test "exponentiation operator", ->
6+
eq 27, 3 ** 3
7+
8+
test "exponentiation operator has higher precedence than other maths operators", ->
9+
eq 55, 1 + 3 ** 3 * 2
10+
eq -4, -2 ** 2
11+
eq 0, (!2) ** 2
12+
13+
test "exponentiation operator is right associative", ->
14+
eq 2, 2 ** 1 ** 3
15+
16+
test "exponentiation operator compound assignment", ->
17+
a = 2
18+
a **= 3
19+
eq 8, a

test/generators.coffee

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ test "`throw` can be yielded", ->
168168
throws -> x.next()
169169

170170
test "symbolic operators has precedence over the `yield`", ->
171-
symbolic = '+ - * / << >> & | || && ** ^ // or and'.split ' '
171+
symbolic = '+ - * / << >> & | || && ^ // or and'.split ' '
172172
compound = ("#{op}=" for op in symbolic)
173173
relations = '< > == != <= >= is isnt'.split ' '
174174

test/interpolation.coffee

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ eq 'multiline nested "interpolations" work', """multiline #{
139139
140140
eq 'function(){}', "#{->}".replace /\s/g, ''
141141
ok /^a[\s\S]+b$/.test "a#{=>}b"
142-
ok /^a[\s\S]+b$/.test "a#{ (x) -> x ** 2 }b"
142+
ok /^a[\s\S]+b$/.test "a#{ (x) -> x %% 2 }b"
143143
144144
# Regular Expression Interpolation
145145

test/operators.coffee

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -305,24 +305,6 @@ test "#2508: Existential access of the prototype", ->
305305
eq NonExistent?::nothing, undefined
306306
ok Object?::toString
307307

308-
test "power operator", ->
309-
eq 27, 3 ** 3
310-
311-
test "power operator has higher precedence than other maths operators", ->
312-
eq 55, 1 + 3 ** 3 * 2
313-
eq -4, -2 ** 2
314-
eq false, !2 ** 2
315-
eq 0, (!2) ** 2
316-
eq -2, ~1 ** 5
317-
318-
test "power operator is right associative", ->
319-
eq 2, 2 ** 1 ** 3
320-
321-
test "power operator compound assignment", ->
322-
a = 2
323-
a **= 3
324-
eq 8, a
325-
326308
test "floor division operator", ->
327309
eq 2, 7 // 3
328310
eq -3, -7 // 3

0 commit comments

Comments
 (0)