Skip to content

Commit

Permalink
fix yields and awaits inside various let blocks
Browse files Browse the repository at this point in the history
fix for #1019, #1021 and #1023
  • Loading branch information
pepkin88 authored and rhendric committed Jul 30, 2018
1 parent 7b91a13 commit 8ac8bb4
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 23 deletions.
43 changes: 28 additions & 15 deletions lib/ast.js

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

22 changes: 15 additions & 7 deletions src/ast.ls
Expand Up @@ -1001,15 +1001,26 @@ class exports.Call extends Node
++index
node <<< back: (args[index] = fun)body

@let = (args, body, generator = false) ->
@let = (args, body) ->
has-yield = false
has-await = false
body.traverse-children (child) ->
if child instanceof Yield
switch child.op
| \yield \yieldfrom => has-yield := true
| \await => has-await := true
return true if has-yield and has-await
params = for a, i in args
if a.op is \= and not a.logic and a.right
args[i] = that
continue if i is 0 and gotThis = a.left.value is \this
a.left
else Var a.var-name! || a.carp 'invalid "let" argument'
gotThis or args.unshift Literal \this
@block Fun(params, body, null, null, null, generator), args, \.call
body = @block Fun(params, body, null, null, null, has-yield, has-await), args, \.call
if has-yield || has-await
Block Yield if has-yield then \yieldfrom else \await, body
else body

#### List
# An abstract node for a list of comma-separated items.
Expand Down Expand Up @@ -2508,8 +2519,6 @@ class exports.For extends While
show: -> ((@kind || []) ++ @index).join ' '

add-body: (body) ->
has-yield = !!body.traverse-children (child) ->
return true if child instanceof Yield
if @let
@item = Literal \.. if delete @ref
@item = that if @item?rewrite-shorthand!
Expand All @@ -2518,14 +2527,13 @@ class exports.For extends While
..push Assign that, Literal \item$$ if @item
body = Block if @guard
assigned = [Var name for assignments when ..assigns! for name in that]
assignments.concat [If delete @guard, Call.let assigned, body, has-yield]
assignments.concat [If delete @guard, Call.let assigned, body]
else
Call.let assignments, body, has-yield
Call.let assignments, body

super body

if @let
@body := Block Yield \yieldfrom, body if has-yield
delete @index
delete @item
this
Expand Down
32 changes: 32 additions & 0 deletions test/async.ls
Expand Up @@ -187,3 +187,35 @@ do ->

# 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 ->
x = ->>
let a = Promise.resolve 1
await a

y <- x!then!
eq y, 1

# [LiveScript#1021](https://github.com/gkz/LiveScript/issues/1021)
# in for..let loops
do ->
x = ->>
for let v in [Promise.resolve 1; Promise.resolve 2]
await v

y <- x!then!
eq "#y" '1,2'

# [LiveScript#1023](https://github.com/gkz/LiveScript/issues/1023)
# Loop guards (`when`, `case`, `|`) didn't work with `for..let` loops with `yield` in their bodies
do ->
x = (keys) ->>
pr = Promise~resolve
obj = {a: pr 1; b: pr 2; c: pr 3}
for own let k, v of obj when k in keys
await v

y <- x(<[ a c ]>).then!
eq "#y", '1,3'
24 changes: 23 additions & 1 deletion test/generators.ls
Expand Up @@ -62,7 +62,7 @@ first = ->*
second = ->*
yield from first!
list = second!
for i to 3
for i to 3
{value} = list.next!
eq value, i

Expand Down Expand Up @@ -173,3 +173,25 @@ eq 6 g8_result[2]()

# splats should expand generators (https://github.com/gkz/LiveScript/issues/963)
eq '0,1,2' "#{[...f!]}"

# [LiveScript#1019](https://github.com/gkz/LiveScript/issues/1019)
# in `let` blocks
fn = ->*
let a = 1
yield a
eq 1 fn!next!value

# [LiveScript#1023](https://github.com/gkz/LiveScript/issues/1023)
# Loop guards (`when`, `case`, `|`) didn't work with `for..let` loops with `yield` in their bodies
fn = (remainder) ->*
obj = a: 1, b: 2, c: 3, d: 4
for own let k, v of obj when v % 2 == remainder
yield v
gen = fn 0
eq 2 gen.next!value
eq 4 gen.next!value
eq true gen.next!done
gen = fn 1
eq 1 gen.next!value
eq 3 gen.next!value
eq true gen.next!done

0 comments on commit 8ac8bb4

Please sign in to comment.