diff options
-rw-r--r-- | compiler/semexprs.nim | 18 | ||||
-rw-r--r-- | compiler/semstmts.nim | 33 | ||||
-rw-r--r-- | tests/macros/tmacros_issues.nim | 17 |
3 files changed, 44 insertions, 24 deletions
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 80e04ead4..d6b146800 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1754,17 +1754,21 @@ proc semReturn(c: PContext, n: PNode): PNode = if c.p.owner.kind in {skConverter, skMethod, skProc, skFunc, skMacro} or (not c.p.owner.typ.isNil and isClosureIterator(c.p.owner.typ)): if n[0].kind != nkEmpty: - # transform ``return expr`` to ``result = expr; return`` - if c.p.resultSym != nil: + if n[0].kind == nkAsgn and n[0][0].kind == nkSym and c.p.resultSym == n[0][0].sym: + discard "return is already transformed" + elif c.p.resultSym != nil: + # transform ``return expr`` to ``result = expr; return`` var a = newNodeI(nkAsgn, n[0].info) a.add newSymNode(c.p.resultSym) a.add n[0] - n[0] = semAsgn(c, a) - # optimize away ``result = result``: - if n[0][1].kind == nkSym and n[0][1].sym == c.p.resultSym: - n[0] = c.graph.emptyNode - else: + n[0] = a + else: localError(c.config, n.info, errNoReturnTypeDeclared) + return + result[0] = semAsgn(c, n[0]) + # optimize away ``result = result``: + if result[0][1].kind == nkSym and result[0][1].sym == c.p.resultSym: + result[0] = c.graph.emptyNode else: localError(c.config, n.info, "'return' not allowed here") diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 53d381f5d..abf2cc0b6 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -1430,16 +1430,19 @@ proc semBorrow(c: PContext, n: PNode, s: PSym) = else: localError(c.config, n.info, errNoSymbolToBorrowFromFound) -proc addResult(c: PContext, t: PType, info: TLineInfo, owner: TSymKind) = +proc addResult(c: PContext, n: PNode, t: PType, owner: TSymKind) = if owner == skMacro or t != nil: - var s = newSym(skResult, getIdent(c.cache, "result"), getCurrOwner(c), info) - s.typ = t - incl(s.flags, sfUsed) - addParamOrResult(c, s, owner) - c.p.resultSym = s - -proc addResultNode(c: PContext, n: PNode) = - if c.p.resultSym != nil: n.add newSymNode(c.p.resultSym) + if n.len > resultPos and n[resultPos] != nil: + if n[resultPos].sym.kind != skResult or n[resultPos].sym.owner != getCurrOwner(c): + localError(c.config, n.info, "incorrect result proc symbol") + c.p.resultSym = n[resultPos].sym + else: + var s = newSym(skResult, getIdent(c.cache, "result"), getCurrOwner(c), n.info) + s.typ = t + incl(s.flags, sfUsed) + c.p.resultSym = s + n.add newSymNode(c.p.resultSym) + addParamOrResult(c, c.p.resultSym, owner) proc copyExcept(n: PNode, i: int): PNode = result = copyNode(n) @@ -1563,8 +1566,7 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode = # XXX not good enough; see tnamedparamanonproc.nim if gp.len == 0 or (gp.len == 1 and tfRetType in gp[0].typ.flags): pushProcCon(c, s) - addResult(c, s.typ[0], n.info, skProc) - addResultNode(c, n) + addResult(c, n, s.typ[0], skProc) s.ast[bodyPos] = hloBody(c, semProcBody(c, n[bodyPos])) trackProc(c, s, s.ast[bodyPos]) popProcCon(c) @@ -1606,8 +1608,7 @@ proc semInferredLambda(c: PContext, pt: TIdTable, n: PNode): PNode {.nosinks.} = pushOwner(c, s) addParams(c, params, skProc) pushProcCon(c, s) - addResult(c, n.typ[0], n.info, skProc) - addResultNode(c, n) + addResult(c, n, n.typ[0], skProc) s.ast[bodyPos] = hloBody(c, semProcBody(c, n[bodyPos])) trackProc(c, s, s.ast[bodyPos]) popProcCon(c) @@ -1637,11 +1638,9 @@ proc activate(c: PContext, n: PNode) = proc maybeAddResult(c: PContext, s: PSym, n: PNode) = if s.kind == skMacro: let resultType = sysTypeFromName(c.graph, n.info, "NimNode") - addResult(c, resultType, n.info, s.kind) - addResultNode(c, n) + addResult(c, n, resultType, s.kind) elif s.typ[0] != nil and not isInlineIterator(s.typ): - addResult(c, s.typ[0], n.info, s.kind) - addResultNode(c, n) + addResult(c, n, s.typ[0], s.kind) proc canonType(c: PContext, t: PType): PType = if t.kind == tySequence: diff --git a/tests/macros/tmacros_issues.nim b/tests/macros/tmacros_issues.nim index f53429888..3d992a27f 100644 --- a/tests/macros/tmacros_issues.nim +++ b/tests/macros/tmacros_issues.nim @@ -480,3 +480,20 @@ func expMin: float func expMin: float {.aadMin.} = 1 echo expMin() + + +# issue #15389 +block double_sem_for_procs: + + macro aad(fns: varargs[typed]): typed = + result = newStmtList() + for fn in fns: + result.add fn + + func exp(x: float): float {.aad.} = + var x1 = min(max(x, -708.4), 709.8) + if x1 > 0.0: + return x1 + 1.0 + result = 10.0 + + discard exp(5.0) \ No newline at end of file |