diff options
author | ringabout <43030857+ringabout@users.noreply.github.com> | 2024-09-09 20:20:40 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-09 14:20:40 +0200 |
commit | 3a55bae53fe80728ce625dd5366aee5da9cf6463 (patch) | |
tree | 0f1855da16e640c1d20037d2b66f117d06105c4b | |
parent | fcee829d85605d6d401f15966a283b0041631308 (diff) | |
download | Nim-3a55bae53fe80728ce625dd5366aee5da9cf6463.tar.gz |
enable closures tests for JS & implement `finished` for JS (#23521)
-rw-r--r-- | changelog.md | 3 | ||||
-rw-r--r-- | compiler/jsgen.nim | 22 | ||||
-rw-r--r-- | lib/system.nim | 10 | ||||
-rw-r--r-- | tests/closure/t8550.nim | 1 | ||||
-rw-r--r-- | tests/closure/tnested.nim | 35 | ||||
-rw-r--r-- | tests/iter/t1550.nim | 4 | ||||
-rw-r--r-- | tests/iter/t21306.nim | 4 | ||||
-rw-r--r-- | tests/iter/t2771.nim | 4 | ||||
-rw-r--r-- | tests/iter/tanoniter1.nim | 1 | ||||
-rw-r--r-- | tests/iter/tclosureiters.nim | 22 | ||||
-rw-r--r-- | tests/iter/titer11.nim | 1 | ||||
-rw-r--r-- | tests/iter/titer12.nim | 1 | ||||
-rw-r--r-- | tests/iter/titer_issues.nim | 1 |
13 files changed, 80 insertions, 29 deletions
diff --git a/changelog.md b/changelog.md index 67b6c74f8..46bc1a872 100644 --- a/changelog.md +++ b/changelog.md @@ -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:" diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index 91862777a..713944def 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -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" diff --git a/lib/system.nim b/lib/system.nim index aeeda831f..5f4847b7d 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -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; """.} diff --git a/tests/closure/t8550.nim b/tests/closure/t8550.nim index 153246f08..a07f45cdc 100644 --- a/tests/closure/t8550.nim +++ b/tests/closure/t8550.nim @@ -1,4 +1,5 @@ discard """ + targets: "c js" output: "@[\"42\"]" """ diff --git a/tests/closure/tnested.nim b/tests/closure/tnested.nim index 31963ea86..ec5af9b13 100644 --- a/tests/closure/tnested.nim +++ b/tests/closure/tnested.nim @@ -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() diff --git a/tests/iter/t1550.nim b/tests/iter/t1550.nim index 8ad96f0da..c971943ee 100644 --- a/tests/iter/t1550.nim +++ b/tests/iter/t1550.nim @@ -1,3 +1,7 @@ +discard """ + targets: "c js" +""" + type A[T] = iterator(x: T): T {.gcsafe, closure.} diff --git a/tests/iter/t21306.nim b/tests/iter/t21306.nim index 43fea9c80..4d0396294 100644 --- a/tests/iter/t21306.nim +++ b/tests/iter/t21306.nim @@ -1,3 +1,7 @@ +discard """ + targets: "c js" +""" + # bug #21306 type FutureState {.pure.} = enum diff --git a/tests/iter/t2771.nim b/tests/iter/t2771.nim index 49befb0a9..71a8a9dcd 100644 --- a/tests/iter/t2771.nim +++ b/tests/iter/t2771.nim @@ -1,3 +1,7 @@ +discard """ + targets: "c js" +""" + template t1(i: int): int= i+1 template t2(i: int): int= diff --git a/tests/iter/tanoniter1.nim b/tests/iter/tanoniter1.nim index 9f0d0a74b..fee16497f 100644 --- a/tests/iter/tanoniter1.nim +++ b/tests/iter/tanoniter1.nim @@ -1,4 +1,5 @@ discard """ + targets: "c js" output: '''1 2 3 diff --git a/tests/iter/tclosureiters.nim b/tests/iter/tclosureiters.nim index 85611373c..4a2639852 100644 --- a/tests/iter/tclosureiters.nim +++ b/tests/iter/tclosureiters.nim @@ -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) - -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.} = diff --git a/tests/iter/titer11.nim b/tests/iter/titer11.nim index 2b39c74f7..153b3c29a 100644 --- a/tests/iter/titer11.nim +++ b/tests/iter/titer11.nim @@ -1,4 +1,5 @@ discard """ +targets: "c js" output: ''' [ 1 diff --git a/tests/iter/titer12.nim b/tests/iter/titer12.nim index f7fc64da4..f264a0e82 100644 --- a/tests/iter/titer12.nim +++ b/tests/iter/titer12.nim @@ -1,4 +1,5 @@ discard """ +targets: "c js" output: ''' Selecting 2 1.0 diff --git a/tests/iter/titer_issues.nim b/tests/iter/titer_issues.nim index b553251b5..c82b3902d 100644 --- a/tests/iter/titer_issues.nim +++ b/tests/iter/titer_issues.nim @@ -1,4 +1,5 @@ discard """ + target: "c js" output: ''' 0 1 |