summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorringabout <43030857+ringabout@users.noreply.github.com>2024-09-09 20:20:40 +0800
committerGitHub <noreply@github.com>2024-09-09 14:20:40 +0200
commit3a55bae53fe80728ce625dd5366aee5da9cf6463 (patch)
tree0f1855da16e640c1d20037d2b66f117d06105c4b
parentfcee829d85605d6d401f15966a283b0041631308 (diff)
downloadNim-3a55bae53fe80728ce625dd5366aee5da9cf6463.tar.gz
enable closures tests for JS & implement `finished` for JS (#23521)
-rw-r--r--changelog.md3
-rw-r--r--compiler/jsgen.nim22
-rw-r--r--lib/system.nim10
-rw-r--r--tests/closure/t8550.nim1
-rw-r--r--tests/closure/tnested.nim35
-rw-r--r--tests/iter/t1550.nim4
-rw-r--r--tests/iter/t21306.nim4
-rw-r--r--tests/iter/t2771.nim4
-rw-r--r--tests/iter/tanoniter1.nim1
-rw-r--r--tests/iter/tclosureiters.nim22
-rw-r--r--tests/iter/titer11.nim1
-rw-r--r--tests/iter/titer12.nim1
-rw-r--r--tests/iter/titer_issues.nim1
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