diff options
-rw-r--r-- | compiler/semexprs.nim | 11 | ||||
-rw-r--r-- | compiler/vm.nim | 5 | ||||
-rw-r--r-- | testament/important_packages.nim | 6 | ||||
-rw-r--r-- | tests/stdlib/tmacros.nim | 136 |
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" |