Skip to content

Commit

Permalink
Fixes #5034 illformed AST from getImpl with proc returning value (#17976
Browse files Browse the repository at this point in the history
)

* Fixes 5034

* address comments
  • Loading branch information
DylanModesitt authored May 31, 2021
1 parent 369a7d1 commit 06d50bf
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 4 deletions.
25 changes: 21 additions & 4 deletions compiler/semstmts.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1439,16 +1439,33 @@ proc semBorrow(c: PContext, n: PNode, s: PSym) =
else:
localError(c.config, n.info, errNoSymbolToBorrowFromFound)

proc swapResult(n: PNode, sRes: PSym, dNode: PNode) =
## Swap nodes that are (skResult) symbols to d(estination)Node.
for i in 0..<n.safeLen:
if n[i].kind == nkSym and n[i].sym == sRes:
n[i] = dNode
swapResult(n[i], sRes, dNode)

proc addResult(c: PContext, n: PNode, t: PType, owner: TSymKind) =
template genResSym(s) =
var s = newSym(skResult, getIdent(c.cache, "result"), nextSymId c.idgen,
getCurrOwner(c), n.info)
s.typ = t
incl(s.flags, sfUsed)

if owner == skMacro or t != nil:
if n.len > resultPos and n[resultPos] != nil:
if n[resultPos].sym.kind != skResult or n[resultPos].sym.owner != getCurrOwner(c):
if n[resultPos].sym.kind != skResult:
localError(c.config, n.info, "incorrect result proc symbol")
if n[resultPos].sym.owner != getCurrOwner(c):
# re-write result with new ownership, and re-write the proc accordingly
let sResSym = n[resultPos].sym
genResSym(s)
n[resultPos] = newSymNode(s)
swapResult(n, sResSym, n[resultPos])
c.p.resultSym = n[resultPos].sym
else:
var s = newSym(skResult, getIdent(c.cache, "result"), nextSymId c.idgen, getCurrOwner(c), n.info)
s.typ = t
incl(s.flags, sfUsed)
genResSym(s)
c.p.resultSym = s
n.add newSymNode(c.p.resultSym)
addParamOrResult(c, c.p.resultSym, owner)
Expand Down
31 changes: 31 additions & 0 deletions tests/macros/tmacrogetimpl.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import macros

# bug #5034

macro copyImpl(srsProc: typed, toSym: untyped) =
result = copyNimTree(getImplTransformed(srsProc))
result[0] = ident $toSym.toStrLit()

proc foo1(x: float, one: bool = true): float =
if one:
return 1'f
result = x

proc bar1(what: string): string =
## be a little more adversarial with `skResult`
proc buzz: string =
result = "lightyear"
if what == "buzz":
result = "buzz " & buzz()
else:
result = what
return result

copyImpl(foo1, foo2)
doAssert foo1(1'f) == 1.0
doAssert foo2(10.0, false) == 10.0
doAssert foo2(10.0) == 1.0

copyImpl(bar1, bar2)
doAssert bar1("buzz") == "buzz lightyear"
doAssert bar1("macros") == "macros"

0 comments on commit 06d50bf

Please sign in to comment.