summary refs log tree commit diff stats
path: root/tests/template/tparams_gensymed.nim
diff options
context:
space:
mode:
Diffstat (limited to 'tests/template/tparams_gensymed.nim')
-rw-r--r--tests/template/tparams_gensymed.nim275
1 files changed, 274 insertions, 1 deletions
diff --git a/tests/template/tparams_gensymed.nim b/tests/template/tparams_gensymed.nim
index b19ed7afc..b559c2d9e 100644
--- a/tests/template/tparams_gensymed.nim
+++ b/tests/template/tparams_gensymed.nim
@@ -8,6 +8,15 @@ output: '''
 1
 2
 3
+wth
+3
+2
+1
+0
+(total: 6)
+S1
+5
+abc
 '''
 """
 # bug #1915
@@ -64,7 +73,7 @@ proc concreteProc(x: int) =
   forStatic i, 0..3:
     echo i
 
-proc genericProc(x: any) =
+proc genericProc(x: auto) =
   forStatic i, 0..3:
     echo i
 
@@ -130,3 +139,267 @@ template test() =
       doAssert(foo.len == 3)
 
 test()
+
+# regression found in PMunch's parser generator
+
+proc namedcall(arg: string) =
+  discard
+
+macro m(): untyped =
+  result = quote do:
+    (proc (arg: string) =
+      namedcall(arg = arg)
+      echo arg)
+
+let meh = m()
+meh("wth")
+
+
+macro foo(body: untyped): untyped =
+  result = body
+
+template baz(): untyped =
+  foo:
+    proc bar2(b: int): int =
+      echo b
+      if b > 0: b + bar2(b = b - 1)
+      else: 0
+  echo (total: bar2(3))
+
+baz()
+
+# bug #12121
+macro state_machine_enum(states: varargs[untyped]) =
+  result = nnkTypeSection.newTree(
+    nnkTypeDef.newTree(
+      nnkPragmaExpr.newTree(ident("State"), nnkPragma.newTree(ident("pure"))),
+      newEmptyNode(),
+      nnkEnumTy.newTree(newEmptyNode())
+    )
+  )
+
+  for s in states:
+    expectKind(s, nnkIdent)
+    result[0][2].add s
+
+template mystate_machine(body: untyped) =
+  state_machine_enum(S1, S2, S3)
+  var state_stack: seq[State]
+  template state_current(): State {.inject, used.} =
+    state_stack[^1]
+  template state_push(state_name) {.inject, used.} =
+    state_stack.add State.state_name
+  template state_pop(n = 1) {.inject, used.} =
+    state_stack.setLen(state_stack.len - n)
+  body
+
+mystate_machine:
+  state_push(S1)
+  echo state_current()
+  state_pop()
+
+# bug #15075
+block: #Doesn't work
+  template genGenTempl: untyped =
+    proc loop(locals: int)
+    proc loop(locals: int) = discard
+  genGenTempl()
+  let pool = loop
+
+block: #Doesn't work
+  macro genGenMacro: untyped =
+    quote do:
+      proc loop(locals: int)
+      proc loop(locals: int) = discard
+  genGenMacro()
+  let pool = loop
+
+block: #This works
+  proc loop(locals: int)
+  proc loop(locals: int) = discard
+  let pool = loop
+
+#Now somewhat recursive:
+type Cont = ref object of RootObj
+  fn*: proc(c: Cont): Cont {.nimcall.}
+
+block: #Doesn't work
+  template genGenTempl(): untyped =
+    proc loop(locals: Cont): Cont
+    proc loop(locals: Cont): Cont =
+      return Cont(fn: loop)
+    proc doServer(): Cont =
+      return Cont(fn: loop)
+  genGenTempl()
+  discard doServer()
+
+block: #Doesn't work
+  macro genGenMacro(): untyped =
+    quote:
+      proc loop(locals: Cont): Cont
+      proc loop(locals: Cont): Cont =
+        return Cont(fn: loop)
+      proc doServer(): Cont =
+        return Cont(fn: loop)
+  genGenMacro()
+  discard doServer()
+
+block: #This works
+  proc loop(locals: Cont): Cont
+  proc loop(locals: Cont): Cont =
+    return Cont(fn: loop)
+  proc doServer(): Cont =
+    return Cont(fn: loop)
+  discard doServer()
+
+#And fully recursive:
+block: #Doesn't work
+  template genGenTempl: untyped =
+    proc loop(locals: int)
+    proc loop(locals: int) = loop(locals)
+  genGenTempl()
+  let pool = loop
+
+block: #Doesn't work
+  macro genGenMacro: untyped =
+    quote do:
+      proc loop(locals: int)
+      proc loop(locals: int) = loop(locals)
+  genGenMacro()
+  let pool = loop
+
+block: #This works
+  proc loop(locals: int)
+  proc loop(locals: int) = loop(locals)
+  let pool = loop
+
+block:
+  template genAndCallLoop: untyped =
+    proc loop() {.gensym.}
+    proc loop() {.gensym.} =
+      discard
+    loop()
+  genAndCallLoop
+
+block: #Fully recursive and gensymmed:
+  template genGenTempl: untyped =
+    proc loop(locals: int) {.gensym.}
+    proc loop(locals: int) {.gensym.} = loop(locals)
+    let pool = loop
+  genGenTempl()
+
+block: #Make sure gensymmed symbol doesn't overwrite the forward decl
+  proc loop()
+  proc loop() = discard
+  template genAndCallLoop: untyped =
+    proc loop() {.gensym.} =
+      discard
+    loop()
+  genAndCallLoop()
+
+template genLoopDecl: untyped =
+  proc loop()
+template genLoopDef: untyped =
+  proc loop() = discard
+block:
+  genLoopDecl
+  genLoopDef
+  loop()
+block:
+  proc loop()
+  genLoopDef
+  loop()
+block:
+  genLoopDecl
+  proc loop() = discard
+  loop()
+
+block: #Gensymmed sym sharing forward decl
+  macro genGenMacro: untyped =
+    let sym = genSym(nskProc, "loop")
+    nnkStmtList.newTree(
+      newProc(sym, body = newEmptyNode()),
+      newCall(sym),
+      newProc(sym, body = newStmtList()),
+    )
+  genGenMacro
+
+# inject pragma on params
+
+template test(procname, body: untyped): untyped = 
+  proc procname(data {.inject.}: var int = 0) =
+    body
+
+test(hello):
+  echo data
+  data = 3
+
+var data = 5
+
+hello(data)
+
+# bug #5691
+
+template bar(x: typed) = discard
+macro barry(x: typed) = discard
+
+var a = 0
+
+bar:
+  var a = 10
+
+barry:
+  var a = 20
+
+bar:
+  var b = 10
+
+barry:
+  var b = 20
+
+var b = 30
+
+# template bar(x: static int) = discard
+#You may think that this should work:
+# bar((var c = 1; echo "hey"; c))
+# echo c
+#But it must not! Since this would be incorrect:
+# bar((var b = 3; const c = 1; echo "hey"; c))
+# echo b # <- b wouldn't exist
+
+discard not (let xx = 1; true)
+discard xx
+
+template barrel(a: typed): untyped = a
+
+barrel:
+  var aa* = 1
+  var bb = 3
+  export bb
+
+# Test declaredInScope within params
+template test1: untyped =
+  when not declaredInScope(thing):
+    var thing {.inject.}: int
+
+proc chunkedReadLoop =
+  test1
+  test1
+
+template test2: untyped =
+  when not not not declaredInScope(thing):
+    var thing {.inject.}: int
+
+proc chunkedReadLoop2 =
+  test2
+  test2
+
+test1(); test2()
+
+block: # bug #22846
+  template foo2(x: proc (y: string)) =
+    let f = x
+    f("abc")
+
+  foo2(proc (y: string) = echo y)
+