mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 08:54:53 +00:00
enable closures tests for JS & implement finished for JS (#23521)
This commit is contained in:
@@ -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.
|
||||
@@ -51,6 +53,7 @@
|
||||
let baz = a # error
|
||||
```
|
||||
|
||||
|
||||
## Standard library additions and changes
|
||||
|
||||
[//]: # "Changes:"
|
||||
|
||||
@@ -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)
|
||||
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
""".}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
discard """
|
||||
targets: "c js"
|
||||
output: "@[\"42\"]"
|
||||
"""
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
discard """
|
||||
targets: "c js"
|
||||
output: '''
|
||||
foo88
|
||||
23 24foo 88
|
||||
@@ -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()
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
discard """
|
||||
targets: "c js"
|
||||
"""
|
||||
|
||||
type
|
||||
A[T] = iterator(x: T): T {.gcsafe, closure.}
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
discard """
|
||||
targets: "c js"
|
||||
"""
|
||||
|
||||
# bug #21306
|
||||
type
|
||||
FutureState {.pure.} = enum
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
discard """
|
||||
targets: "c js"
|
||||
"""
|
||||
|
||||
template t1(i: int): int=
|
||||
i+1
|
||||
template t2(i: int): int=
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
discard """
|
||||
targets: "c js"
|
||||
output: '''1
|
||||
2
|
||||
3
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
discard """
|
||||
targets: "c js"
|
||||
output: '''0
|
||||
1
|
||||
2
|
||||
@@ -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)
|
||||
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
|
||||
for i in love():
|
||||
echo i
|
||||
else:
|
||||
echo 0
|
||||
|
||||
# bug #18474
|
||||
iterator pairs(): (int, int) {.closure.} =
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
discard """
|
||||
targets: "c js"
|
||||
output: '''
|
||||
[
|
||||
1
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
discard """
|
||||
targets: "c js"
|
||||
output: '''
|
||||
Selecting 2
|
||||
1.0
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
discard """
|
||||
target: "c js"
|
||||
output: '''
|
||||
0
|
||||
1
|
||||
|
||||
Reference in New Issue
Block a user