Skip to content

Commit

Permalink
support async generators with ->>*
Browse files Browse the repository at this point in the history
Also support the more verbose `async function* named-fn` option.
  • Loading branch information
rhendric committed Aug 14, 2018
1 parent b0ddade commit 367c6da
Show file tree
Hide file tree
Showing 10 changed files with 154 additions and 92 deletions.
6 changes: 4 additions & 2 deletions lib/ast.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions lib/grammar.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 2 additions & 6 deletions lib/lexer.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

155 changes: 79 additions & 76 deletions lib/parser.js

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions scripts/test
Expand Up @@ -170,6 +170,11 @@
} else {
files.splice(files.indexOf("async.ls"), 1);
}
if (testSyntax("(async function* () {})")) {
console.log("Testing with async generators.");
} else {
files.splice(files.indexOf("async-generators.ls"), 1);
}

files.forEach(function(file){
var stk, msg, m, ref, num, row, col, that, lines, line;
Expand Down
5 changes: 3 additions & 2 deletions src/ast.ls
Expand Up @@ -2003,10 +2003,11 @@ class exports.Fun extends Node
code = [\function]
if @async
@ctor and @carp "a constructor can't be async"
@generator and @carp "a generator can't be async"
o.in-async = true
code.unshift 'async '
else if @generator
else if not @wrapper
o.in-async = false
if @generator
@ctor and @carp "a constructor can't be a generator"
o.in-generator = true
code.push \*
Expand Down
2 changes: 2 additions & 0 deletions src/grammar.ls
Expand Up @@ -288,6 +288,8 @@ bnf =
, -> (Fun $3, $6, false, false, false, true, false).named $1
o 'ASYNC FUNCTION CALL( ArgList OptComma )CALL Block'
, -> (Fun $4, $7, false, false, false, false, true).named $2
o 'ASYNC GENERATOR CALL( ArgList OptComma )CALL Block'
, -> (Fun $4, $7, false, false, false, true, true).named $2

# The full complement of `if` and `unless` expressions
o 'IF Expression Block Else' -> L 1 2 If $2, $3, $1 is 'unless' .add-else $4
Expand Down
4 changes: 1 addition & 3 deletions src/lexer.ls
Expand Up @@ -1043,9 +1043,7 @@ character = if not JSON? then uxxxx else ->
case 'ID'
break unless val is 'async'
next = tokens[i + 1]
switch next.0
| 'FUNCTION' => token.0 = 'ASYNC'
| 'GENERATOR' => carp 'named generator cannot be async' line
if next.0 in <[ FUNCTION GENERATOR ]> then token.0 = 'ASYNC'
prev = token
continue

Expand Down
56 changes: 56 additions & 0 deletions test/async-generators.ls
@@ -0,0 +1,56 @@
do ->
ag = ->>*
yield await Promise.resolve 1
yield await Promise.resolve 2
ai = ag!
ai.next!then -> eq 1 it.value
ai.next!then -> eq 2 it.value
ai.next!then -> ok it.done

do ->
ag = ->>*
let x = 1
yield await Promise.resolve x
yield await Promise.resolve 2*x
ai = ag!
ai.next!then -> eq 1 it.value
ai.next!then -> eq 2 it.value
ai.next!then -> ok it.done

do ->
async function* ag
yield await Promise.resolve 1
yield await Promise.resolve 2
ai = ag!
ai.next!then -> eq 1 it.value
ai.next!then -> eq 2 it.value
ai.next!then -> ok it.done

# yield from
do ->
first = !->>*
i = await Promise.resolve 0
loop => yield i++
second = !->>* yield from first!
list = second!
for let i to 3 then list.next!then -> eq it.value, i

# This tests that yield and await still work inside the generated closure.
do ->
ag = ->>* [i = 0] ++ while i < 3 then yield await Promise.resolve i++
ai = ag!
ai.next! .then -> eq 0 it.value
ai.next 10 .then -> eq 1 it.value
ai.next 20 .then -> eq 2 it.value
ai.next 30 .then ->
ok it.done
eq '0,10,20,30' ''+it.value

# This tests that the inner function clears both the async and generator flags
# for the closure that is generated within it.
do ->
ag = ->>* -> [i = 0] ++ while i < 3 then i++
ai = ag!
ai.next!then ->
ok it.done
eq '0,0,1,2' ''+it.value!
3 changes: 0 additions & 3 deletions test/async.ls
Expand Up @@ -185,9 +185,6 @@ do ->
y <- obj2.bound!then
eq y, 3

# check that ->>* results in an error at compile time
compile-throws "a generator can't be async" 1 '->>* 3'

# [LiveScript#1019](https://github.com/gkz/LiveScript/issues/1019)
# in `let` blocks
do ->
Expand Down

0 comments on commit 367c6da

Please sign in to comment.