summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/semexprs.nim18
-rw-r--r--compiler/semstmts.nim33
-rw-r--r--tests/macros/tmacros_issues.nim17
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