Skip to content

Commit

Permalink
enable closures tests for JS & implement finished for JS (nim-lang#…
Browse files Browse the repository at this point in the history
  • Loading branch information
ringabout authored Sep 9, 2024
1 parent fcee829 commit 3a55bae
Show file tree
Hide file tree
Showing 13 changed files with 80 additions and 29 deletions.
3 changes: 3 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

- JS backend now supports lambda lifting for closures. Use `--legacy:jsNoLambdaLifting` to emulate old behavior.

- JS backend now supports closure iterators.

- `owner` in `std/macros` is deprecated.

- Ambiguous type symbols in generic procs and templates now generate symchoice nodes.
Expand Down Expand Up @@ -51,6 +53,7 @@
let baz = a # error
```


## Standard library additions and changes

[//]: # "Changes:"
Expand Down
22 changes: 12 additions & 10 deletions compiler/jsgen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,17 @@ template unaryExpr(p: PProc, n: PNode, r: var TCompRes, magic, frmt: string) =
r.res = frmt % [a, tmp]
r.kind = resExpr

proc genBreakState(p: PProc, n: PNode, r: var TCompRes) =
var a: TCompRes = default(TCompRes)
# mangle `:state` properly somehow
if n.kind == nkClosure:
gen(p, n[1], a)
r.res = "(($1).HEX3Astate < 0)" % [rdLoc(a)]
else:
gen(p, n, a)
r.res = "((($1.ClE_0).HEX3Astate) < 0)" % [rdLoc(a)]
r.kind = resExpr

proc arithAux(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
var
x, y: TCompRes = default(TCompRes)
Expand Down Expand Up @@ -3054,16 +3065,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
of nkGotoState, nkState:
globalError(p.config, n.info, "not implemented")
of nkBreakState:
var a: TCompRes = default(TCompRes)
if n[0].kind == nkClosure:
gen(p, n[0][1], a)
let sym = n[0][1].typ[0].n[0].sym
r.res = "(($1).$2 < 0)" % [rdLoc(a), mangleName(p.module, sym)]
else:
gen(p, n[0], a)
let sym = n[0].typ[0].n[0].sym
r.res = "((($1.ClE_0).$2) < 0)" % [rdLoc(a), mangleName(p.module, sym)]
r.kind = resExpr
genBreakState(p, n[0], r)
of nkPragmaBlock: gen(p, n.lastSon, r)
of nkComesFrom:
discard "XXX to implement for better stack traces"
Expand Down
10 changes: 8 additions & 2 deletions lib/system.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2350,8 +2350,14 @@ when notJSnotNims:
`result` = `x`.ClE_0;
""".}

proc finished*[T: iterator {.closure.}](x: T): bool {.noSideEffect, inline, magic: "Finished".} =
## It can be used to determine if a first class iterator has finished.
proc finished*[T: iterator {.closure.}](x: T): bool {.noSideEffect, inline, magic: "Finished".} =
## It can be used to determine if a first class iterator has finished.
when defined(js):
# TODO: mangle `:state`
{.emit: """
`result` = (`x`.ClE_0).HEX3Astate < 0;
""".}
else:
{.emit: """
`result` = ((NI*) `x`.ClE_0)[1] < 0;
""".}
Expand Down
1 change: 1 addition & 0 deletions tests/closure/t8550.nim
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
discard """
targets: "c js"
output: "@[\"42\"]"
"""

Expand Down
35 changes: 27 additions & 8 deletions tests/closure/tnested.nim
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
discard """
targets: "c js"
output: '''
foo88
23 24foo 88
Expand Down Expand Up @@ -183,14 +184,32 @@ block tclosure2:

import typetraits

proc myDiscard[T](a: T) = discard
block:
proc myDiscard[T](a: T) = discard

proc foo() =
let a = 5
let f = (proc() =
myDiscard (proc() = echo a)
)
echo name(typeof(f))
proc foo() =
let a = 5
let f = (proc() =
myDiscard (proc() = echo a)
)
echo name(typeof(f))

foo()
foo()


block:
iterator foo: int {.closure.} =
yield 1
yield 2
yield 3

proc pork =
let call = foo
for i in call():
discard i

let call2 = foo
while not finished(call2):
discard call2()

pork()
4 changes: 4 additions & 0 deletions tests/iter/t1550.nim
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
discard """
targets: "c js"
"""

type
A[T] = iterator(x: T): T {.gcsafe, closure.}

Expand Down
4 changes: 4 additions & 0 deletions tests/iter/t21306.nim
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
discard """
targets: "c js"
"""

# bug #21306
type
FutureState {.pure.} = enum
Expand Down
4 changes: 4 additions & 0 deletions tests/iter/t2771.nim
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
discard """
targets: "c js"
"""

template t1(i: int): int=
i+1
template t2(i: int): int=
Expand Down
1 change: 1 addition & 0 deletions tests/iter/tanoniter1.nim
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
discard """
targets: "c js"
output: '''1
2
3
Expand Down
22 changes: 13 additions & 9 deletions tests/iter/tclosureiters.nim
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
discard """
targets: "c js"
output: '''0
1
2
Expand Down Expand Up @@ -152,15 +153,18 @@ iterator filesIt(path: string): auto {.closure.} =
yield prefix / f

# bug #13815
var love = iterator: int {.closure.} =
yield cast[type(
block:
var a = 0
yield a
a)](0)

for i in love():
echo i
when not defined(js):
var love = iterator: int {.closure.} =
yield cast[type(
block:
var a = 0
yield a
a)](0)

for i in love():
echo i
else:
echo 0

# bug #18474
iterator pairs(): (int, int) {.closure.} =
Expand Down
1 change: 1 addition & 0 deletions tests/iter/titer11.nim
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
discard """
targets: "c js"
output: '''
[
1
Expand Down
1 change: 1 addition & 0 deletions tests/iter/titer12.nim
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
discard """
targets: "c js"
output: '''
Selecting 2
1.0
Expand Down
1 change: 1 addition & 0 deletions tests/iter/titer_issues.nim
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
discard """
target: "c js"
output: '''
0
1
Expand Down

0 comments on commit 3a55bae

Please sign in to comment.