Skip to content

Commit

Permalink
fixes nim-lang#21326; fixes nim-lang#7375; fixes nim-lang#11986; fixes
Browse files Browse the repository at this point in the history
…nim-lang#9607; rework quote do; `getAst` uses type info to annotate the type of quoted variables; no more type erasures for quoted variables (nim-lang#21433)

* fixes nim-lang#21326; getAst uses type info to annotateType quoted variables

* simplify logics; sem types first

* fixes important packages

* add testcases

* tiny
  • Loading branch information
ringabout authored and capocasa committed Mar 31, 2023
1 parent 2c060ca commit c0391d5
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 8 deletions.
11 changes: 7 additions & 4 deletions compiler/semexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 4 additions & 1 deletion compiler/vm.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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]
Expand Down
6 changes: 3 additions & 3 deletions testament/important_packages.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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"
Expand All @@ -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"
Expand Down
136 changes: 136 additions & 0 deletions tests/stdlib/tmacros.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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"

0 comments on commit c0391d5

Please sign in to comment.