summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/semexprs.nim11
-rw-r--r--compiler/vm.nim5
-rw-r--r--testament/important_packages.nim6
-rw-r--r--tests/stdlib/tmacros.nim136
4 files changed, 150 insertions, 8 deletions
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 7454c7f8e..9cf206b4c 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -2203,10 +2203,13 @@ proc semQuoteAst(c: PContext, n: PNode): PNode =
   if ids.len > 0:
     dummyTemplate[paramsPos] = newNodeI(nkFormalParams, n.info)
     dummyTemplate[paramsPos].add getSysSym(c.graph, n.info, "untyped").newSymNode # return type
-    ids.add getSysSym(c.graph, n.info, "untyped").newSymNode # params type
-    ids.add c.graph.emptyNode # no default value
-    dummyTemplate[paramsPos].add newTreeI(nkIdentDefs, n.info, ids)
-
+    dummyTemplate[paramsPos].add newTreeI(nkIdentDefs, n.info, ids[0], getSysSym(c.graph, n.info, "typed").newSymNode, c.graph.emptyNode)
+    for i in 1..<ids.len:
+      let typ = semExprWithType(c, quotes[i+1], {}).typ
+      if tfTriggersCompileTime notin typ.flags:
+        dummyTemplate[paramsPos].add newTreeI(nkIdentDefs, n.info, ids[i], newNodeIT(nkType, n.info, typ), c.graph.emptyNode)
+      else:
+        dummyTemplate[paramsPos].add newTreeI(nkIdentDefs, n.info, ids[i], getSysSym(c.graph, n.info, "typed").newSymNode, c.graph.emptyNode)
   var tmpl = semTemplateDef(c, dummyTemplate)
   quotes[0] = tmpl[namePos]
   # This adds a call to newIdentNode("result") as the first argument to the template call
diff --git a/compiler/vm.nim b/compiler/vm.nim
index 3946be0fd..38b856277 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -10,7 +10,7 @@
 ## This file implements the new evaluation engine for Nim code.
 ## An instruction is 1-3 int32s in memory, it is a register based VM.
 
-
+import semmacrosanity
 import
   std/[strutils, tables, parseutils],
   msgs, vmdef, vmgen, nimsets, types, passes,
@@ -1408,6 +1408,9 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
         for i in 1..rc-1:
           let node = regs[rb+i].regToNode
           node.info = c.debug[pc]
+          if prc.typ[i].kind notin {tyTyped, tyUntyped}:
+            node.annotateType(prc.typ[i], c.config)
+
           macroCall.add(node)
         var a = evalTemplate(macroCall, prc, genSymOwner, c.config, c.cache, c.templInstCounter, c.idgen)
         if a.kind == nkStmtList and a.len == 1: a = a[0]
diff --git a/testament/important_packages.nim b/testament/important_packages.nim
index 0af0eb93e..e59198e67 100644
--- a/testament/important_packages.nim
+++ b/testament/important_packages.nim
@@ -83,7 +83,7 @@ pkg "iterutils"
 pkg "jstin"
 pkg "karax", "nim c -r tests/tester.nim"
 pkg "kdtree", "nimble test -d:nimLegacyRandomInitRand", "https://github.com/jblindsay/kdtree"
-pkg "loopfusion"
+pkg "loopfusion", url = "https://github.com/nim-lang/loop-fusion"
 pkg "lockfreequeues"
 pkg "macroutils"
 pkg "manu"
@@ -115,7 +115,7 @@ pkg "nimpy", "nim c -r tests/nimfrompy.nim"
 pkg "nimquery"
 pkg "nimsl"
 pkg "nimsvg"
-pkg "nimterop", "nimble minitest"
+pkg "nimterop", "nimble minitest", url = "https://github.com/nim-lang/nimterop"
 pkg "nimwc", "nim c nimwc.nim", allowFailure = true
 pkg "nimx", "nim c --threads:on test/main.nim", allowFailure = true
 pkg "nitter", "nim c src/nitter.nim", "https://github.com/zedeus/nitter"
@@ -135,7 +135,7 @@ pkg "protobuf", "nim c -o:protobuff -r src/protobuf.nim"
 pkg "pylib"
 pkg "rbtree"
 pkg "react", "nimble example"
-pkg "regex", "nim c src/regex"
+pkg "regex", "nim c src/regex", url = "https://github.com/nim-lang/nim-regex"
 pkg "result", "nim c -r result.nim"
 pkg "RollingHash", "nim c -r tests/test_cyclichash.nim"
 pkg "rosencrantz", "nim c -o:rsncntz -r rosencrantz.nim"
diff --git a/tests/stdlib/tmacros.nim b/tests/stdlib/tmacros.nim
index c054b66c7..a03bcca2d 100644
--- a/tests/stdlib/tmacros.nim
+++ b/tests/stdlib/tmacros.nim
@@ -175,3 +175,139 @@ block getCustomPragmaValGeneric:
   var f: Foo[string]
   doAssert f.getCustomPragmaVal(examplePragma) == 42
   doAssert f.x.getCustomPragmaVal(examplePragma) == 25
+
+block: # bug #21326
+  macro foo(body: untyped): untyped =
+    let a = body.lineInfoObj()
+    let aLit = a.newLit
+    result = quote do:
+      doAssert $`a` == $`aLit`
+
+  foo:
+    let c = 1
+
+  template name(a: LineInfo): untyped =
+    discard a # `aLit` works though
+
+  macro foo3(body: untyped): untyped =
+    let a = body.lineInfoObj()
+    # let ax = newLit(a)
+    result = getAst(name(a))
+
+  foo3:
+    let c = 1
+
+block: # bug #7375
+  macro fails(b: static[bool]): untyped =
+    doAssert b == false
+    result = newStmtList()
+
+  macro foo(): untyped =
+
+    var b = false
+
+    ## Fails
+    result = quote do:
+      fails(`b`)
+
+  foo()
+
+  macro someMacro(): untyped =
+    template tmpl(boolean: bool) =
+      when boolean:
+        discard "it's true!"
+      else:
+        doAssert false
+    result = getAst(tmpl(true))
+
+  someMacro()
+
+block:
+  macro foo(): untyped =
+    result = quote do: `littleEndian`
+
+  doAssert littleEndian == foo()
+
+block:
+  macro eqSym(x, y: untyped): untyped =
+    let eq = $x == $y # Unfortunately eqIdent compares to string.
+    result = quote do: `eq`
+
+  var r, a, b: int
+
+  template fma(result: var int, a, b: int, op: untyped) =
+    # fused multiple-add
+    when eqSym(op, `+=`):
+      discard "+="
+    else:
+      discard "+"
+
+  fma(r, a, b, `+=`)
+
+block:
+  template test(boolArg: bool) =
+    static:
+      doAssert typeof(boolArg) is bool
+    let x: bool = boolArg # compile error here, because boolArg became an int
+
+  macro testWrapped1(boolArg: bool): untyped =
+    # forwarding boolArg directly works
+    result = getAst(test(boolArg))
+
+  macro testWrapped2(boolArg: bool): untyped =
+    # forwarding boolArg via a local variable also works
+    let b = boolArg
+    result = getAst(test(b))
+
+  macro testWrapped3(boolArg: bool): untyped =
+    # but using a literal `true` as a local variable will be converted to int
+    let b = true
+    result = getAst(test(b))
+
+  test(true) # ok
+  testWrapped1(true) # ok
+  testWrapped2(true) # ok
+  testWrapped3(true) 
+
+block:
+  macro foo(): untyped =
+    var s = { 'a', 'b' }
+    quote do:              
+      let t = `s`         
+      doAssert $typeof(t) == "set[char]"
+
+  foo()
+
+block: # bug #9607
+  proc fun1(info:LineInfo): string = "bar"
+  proc fun2(info:int): string = "bar"
+
+  macro echoL(args: varargs[untyped]): untyped =
+    let info = args.lineInfoObj
+    let fun1 = bindSym"fun1"
+    let fun2 = bindSym"fun2"
+
+    # this would work instead
+    # result = newCall(bindSym"fun2", info.line.newLit)
+
+    result = quote do:
+
+      # BUG1: ???(0, 0) Error: internal error: genLiteral: ty is nil
+      `fun1`(`info`)
+
+  macro echoM(args: varargs[untyped]): untyped =
+    let info = args.lineInfoObj
+    let fun1 = bindSym"fun1"
+    let fun2 = bindSym"fun2"
+
+    # this would work instead
+    # result = newCall(bindSym"fun2", info.line.newLit)
+
+    result = quote do:
+
+      # BUG1: ???(0, 0) Error: internal error: genLiteral: ty is nil
+      `fun2`(`info`.line)
+
+
+  doAssert echoL() == "bar"
+  doAssert echoM() == "bar"