Skip to content

Commit 99b7826

Browse files
helixbassGeoffreyBooth
authored andcommitted
While AST (#5161)
* updated grammar * tests * add tests
1 parent 806a442 commit 99b7826

File tree

9 files changed

+648
-44
lines changed

9 files changed

+648
-44
lines changed

lib/coffeescript/grammar.js

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

lib/coffeescript/nodes.js

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

lib/coffeescript/parser.js

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

lib/coffeescript/rewriter.js

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

src/grammar.coffee

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -679,14 +679,14 @@ grammar =
679679
While: [
680680
o 'WhileSource Block', -> $1.addBody $2
681681
o 'WhileLineSource Block', -> $1.addBody $2
682-
o 'Statement WhileSource', -> $2.addBody LOC(1) Block.wrap([$1])
683-
o 'Expression WhileSource', -> $2.addBody LOC(1) Block.wrap([$1])
682+
o 'Statement WhileSource', -> (Object.assign $2, postfix: yes).addBody LOC(1) Block.wrap([$1])
683+
o 'Expression WhileSource', -> (Object.assign $2, postfix: yes).addBody LOC(1) Block.wrap([$1])
684684
o 'Loop', -> $1
685685
]
686686

687687
Loop: [
688-
o 'LOOP Block', -> new While(LOC(1) new BooleanLiteral 'true').addBody $2
689-
o 'LOOP Expression', -> new While(LOC(1) new BooleanLiteral 'true').addBody LOC(2) Block.wrap [$2]
688+
o 'LOOP Block', -> new While(LOC(1)(new BooleanLiteral 'true'), isLoop: yes).addBody $2
689+
o 'LOOP Expression', -> new While(LOC(1)(new BooleanLiteral 'true'), isLoop: yes).addBody LOC(2) Block.wrap [$2]
690690
]
691691

692692
# Array, object, and range comprehensions, at the most generic level.

src/nodes.coffee

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3832,12 +3832,9 @@ exports.Elision = class Elision extends Base
38323832
# it, all other loops can be manufactured. Useful in cases where you need more
38333833
# flexibility or more speed than a comprehension can provide.
38343834
exports.While = class While extends Base
3835-
constructor: (condition, options) ->
3835+
constructor: (@condition, {@invert, @guard, @isLoop} = {}) ->
38363836
super()
38373837

3838-
@condition = if options?.invert then condition.invert() else condition
3839-
@guard = options?.guard
3840-
38413838
children: ['condition', 'guard', 'body']
38423839

38433840
isStatement: YES
@@ -3878,12 +3875,26 @@ exports.While = class While extends Base
38783875
else
38793876
body = Block.wrap [new If @guard, body] if @guard
38803877
body = [].concat @makeCode("\n"), (body.compileToFragments o, LEVEL_TOP), @makeCode("\n#{@tab}")
3881-
answer = [].concat @makeCode(set + @tab + "while ("), @condition.compileToFragments(o, LEVEL_PAREN),
3878+
answer = [].concat @makeCode(set + @tab + "while ("), @processedCondition().compileToFragments(o, LEVEL_PAREN),
38823879
@makeCode(") {"), body, @makeCode("}")
38833880
if @returns
38843881
answer.push @makeCode "\n#{@tab}return #{rvar};"
38853882
answer
38863883

3884+
processedCondition: ->
3885+
@processedConditionCache ?= if @invert then @condition.invert() else @condition
3886+
3887+
astType: -> 'WhileStatement'
3888+
3889+
astProperties: (o) ->
3890+
return
3891+
test: @condition.ast o, LEVEL_PAREN
3892+
body: @body.ast o, LEVEL_TOP
3893+
guard: @guard?.ast(o) ? null
3894+
inverted: !!@invert
3895+
postfix: !!@postfix
3896+
loop: !!@isLoop
3897+
38873898
#### Op
38883899

38893900
# Simple Arithmetic and logical operations. Performs some conversion from

src/rewriter.coffee

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,9 @@ exports.Rewriter = class Rewriter
511511
@scanTokens (token, i, tokens) ->
512512
return 1 if token[2]
513513
return 1 unless token.generated or token.explicit
514+
if token.fromThen and token[0] is 'INDENT'
515+
token[2] = token.origin[2]
516+
return 1
514517
if token[0] is '{' and nextLocation=tokens[i + 1]?[2]
515518
{first_line: line, first_column: column, range: [rangeIndex]} = nextLocation
516519
else if prevLocation = tokens[i - 1]?[2]

test/abstract_syntax_tree.coffee

Lines changed: 118 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1775,22 +1775,125 @@ test "AST as expected for Elision node", ->
17751775
type: 'StringLiteral'
17761776
value: 'asdfqwer'
17771777

1778-
# test "AST as expected for While node", ->
1779-
# testExpression 'loop 1',
1780-
# type: 'While'
1781-
# condition:
1782-
# type: 'BooleanLiteral'
1783-
# value: 'true'
1784-
# originalValue: 'true' # TODO: This should probably be changed for Prettier.
1785-
# body:
1786-
# type: 'Value'
1778+
test "AST as expected for While node", ->
1779+
testStatement 'loop 1',
1780+
type: 'WhileStatement'
1781+
test:
1782+
type: 'BooleanLiteral'
1783+
value: true
1784+
body:
1785+
type: 'BlockStatement'
1786+
body: [
1787+
type: 'ExpressionStatement'
1788+
expression: NUMBER 1
1789+
]
1790+
guard: null
1791+
inverted: no
1792+
postfix: no
1793+
loop: yes
17871794

1788-
# testExpression 'while 1 < 2 then',
1789-
# type: 'While'
1790-
# condition:
1791-
# type: 'Op'
1792-
# body:
1793-
# type: 'Block'
1795+
testStatement 'while 1 < 2 then',
1796+
type: 'WhileStatement'
1797+
test:
1798+
type: 'BinaryExpression'
1799+
body:
1800+
type: 'BlockStatement'
1801+
body: []
1802+
guard: null
1803+
inverted: no
1804+
postfix: no
1805+
loop: no
1806+
1807+
testStatement 'while 1 < 2 then fn()',
1808+
type: 'WhileStatement'
1809+
test:
1810+
type: 'BinaryExpression'
1811+
body:
1812+
type: 'BlockStatement'
1813+
body: [
1814+
type: 'ExpressionStatement'
1815+
expression:
1816+
type: 'CallExpression'
1817+
]
1818+
guard: null
1819+
inverted: no
1820+
postfix: no
1821+
loop: no
1822+
1823+
testStatement '''
1824+
x() until y
1825+
''',
1826+
type: 'WhileStatement'
1827+
test: ID 'y'
1828+
body:
1829+
type: 'BlockStatement'
1830+
body: [
1831+
type: 'ExpressionStatement'
1832+
expression:
1833+
type: 'CallExpression'
1834+
]
1835+
guard: null
1836+
inverted: yes
1837+
postfix: yes
1838+
loop: no
1839+
1840+
testStatement '''
1841+
until x when y
1842+
z++
1843+
''',
1844+
type: 'WhileStatement'
1845+
test: ID 'x'
1846+
body:
1847+
type: 'BlockStatement'
1848+
body: [
1849+
type: 'ExpressionStatement'
1850+
expression:
1851+
type: 'UpdateExpression'
1852+
]
1853+
guard: ID 'y'
1854+
inverted: yes
1855+
postfix: no
1856+
loop: no
1857+
1858+
testStatement '''
1859+
x while y when z
1860+
''',
1861+
type: 'WhileStatement'
1862+
test: ID 'y'
1863+
body:
1864+
type: 'BlockStatement'
1865+
body: [
1866+
type: 'ExpressionStatement'
1867+
expression: ID 'x'
1868+
]
1869+
guard: ID 'z'
1870+
inverted: no
1871+
postfix: yes
1872+
loop: no
1873+
1874+
testStatement '''
1875+
loop
1876+
a()
1877+
b++
1878+
''',
1879+
type: 'WhileStatement'
1880+
test:
1881+
type: 'BooleanLiteral'
1882+
body:
1883+
type: 'BlockStatement'
1884+
body: [
1885+
type: 'ExpressionStatement'
1886+
expression:
1887+
type: 'CallExpression'
1888+
,
1889+
type: 'ExpressionStatement'
1890+
expression:
1891+
type: 'UpdateExpression'
1892+
]
1893+
guard: null
1894+
inverted: no
1895+
postfix: no
1896+
loop: yes
17941897

17951898
test "AST as expected for Op node", ->
17961899
testExpression 'a <= 2',

0 commit comments

Comments
 (0)