summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2016-05-29 23:58:25 +0200
committerAndreas Rumpf <rumpf_a@web.de>2016-05-29 23:58:25 +0200
commite52044660d63832d9f2aaf81323f86e13e48cc01 (patch)
tree84bb73a2e9a7a1ed86b314be9eb8c6e45c07161a /compiler
parentd72758143044c73744aa93c7a1767ac3f2f1cd79 (diff)
parent47e45dee7e9157212995c5769b93713f5a4dd14b (diff)
downloadNim-e52044660d63832d9f2aaf81323f86e13e48cc01.tar.gz
Merge branch 'patch/fix-3496-generic-tmpl-args' of https://github.com/nanoant/Nim into nanoant-patch/fix-3496-generic-tmpl-args
Diffstat (limited to 'compiler')
-rw-r--r--compiler/semdata.nim2
-rw-r--r--compiler/semexprs.nim60
2 files changed, 57 insertions, 5 deletions
diff --git a/compiler/semdata.nim b/compiler/semdata.nim
index b25f72f2d..91a1ebf86 100644
--- a/compiler/semdata.nim
+++ b/compiler/semdata.nim
@@ -47,7 +47,7 @@ type
     efLValue, efWantIterator, efInTypeof,
     efWantStmt, efAllowStmt, efDetermineType,
     efAllowDestructor, efWantValue, efOperand, efNoSemCheck,
-    efNoProcvarCheck, efFromHlo
+    efNoProcvarCheck, efNoEvaluateGeneric, efInCall, efFromHlo
   TExprFlags* = set[TExprFlag]
 
   TTypeAttachedOp* = enum
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 7135dcf34..4fcedced5 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -732,10 +732,34 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
       for i in countup(1, sonsLen(n) - 1): addSon(result, n.sons[i])
       return semExpr(c, result, flags)
   else:
-    n.sons[0] = semExpr(c, n.sons[0])
+    n.sons[0] = semExpr(c, n.sons[0], {efInCall})
     let t = n.sons[0].typ
     if t != nil and t.kind == tyVar:
       n.sons[0] = newDeref(n.sons[0])
+    elif n.sons[0].kind == nkBracketExpr:
+      checkMinSonsLen(n.sons[0], 2)
+      # We received untransformed bracket expression coming from macroOrTmpl[].
+      # Transform it to macro or template call, where first come normal
+      # arguments, next come generic template arguments.
+      if n.sons[0].sons[0].kind == nkSym:
+        let s = n.sons[0].sons[0].sym
+        if s.kind in {skMacro, skTemplate}:
+          var sons = newSeq[PNode]()
+          sons.add n.sons[0].sons[0]
+          # Normal arguments:
+          for i in 1..<n.len:
+            sons.add n.sons[i]
+          # Generic template arguments from bracket expression:
+          for i in 1..<n.sons[0].len:
+            sons.add n.sons[0].sons[i]
+          n.sons = sons
+          # FIXME: Shouldn't we check sfImmediate and call semDirectOp?
+          # However passing to semDirectOp doesn't work here.
+          case s.kind
+          of skMacro: result = semMacroExpr(c, n, n, s, flags)
+          of skTemplate: result = semTemplateExpr(c, n, s, flags)
+          else: discard
+          return
   let nOrig = n.copyTree
   semOpAux(c, n)
   var t: PType = nil
@@ -965,8 +989,20 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
       else: result = newSymNode(s, n.info)
     else:
       result = newSymNode(s, n.info)
-  of skMacro: result = semMacroExpr(c, n, n, s, flags)
-  of skTemplate: result = semTemplateExpr(c, n, s, flags)
+  of skMacro:
+    if efNoEvaluateGeneric in flags and s.ast[genericParamsPos].len > 0:
+      markUsed(n.info, s)
+      styleCheckUse(n.info, s)
+      result = newSymNode(s, n.info)
+    else:
+      result = semMacroExpr(c, n, n, s, flags)
+  of skTemplate:
+    if efNoEvaluateGeneric in flags and s.ast[genericParamsPos].len > 0:
+      markUsed(n.info, s)
+      styleCheckUse(n.info, s)
+      result = newSymNode(s, n.info)
+    else:
+      result = semTemplateExpr(c, n, s, flags)
   of skParam:
     markUsed(n.info, s)
     styleCheckUse(n.info, s)
@@ -1193,7 +1229,9 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
     result.add(x[0])
     return
   checkMinSonsLen(n, 2)
-  n.sons[0] = semExprWithType(c, n.sons[0], {efNoProcvarCheck})
+  # make sure we don't evaluate generic macros/templates
+  n.sons[0] = semExprWithType(c, n.sons[0],
+                              {efNoProcvarCheck, efNoEvaluateGeneric})
   let arr = skipTypes(n.sons[0].typ, {tyGenericInst, tyVar, tyPtr, tyRef})
   case arr.kind
   of tyArray, tyOpenArray, tyVarargs, tyArrayConstr, tySequence, tyString,
@@ -1240,6 +1278,20 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
       # type parameters: partial generic specialization
       n.sons[0] = semSymGenericInstantiation(c, n.sons[0], s)
       result = explicitGenericInstantiation(c, n, s)
+    elif s != nil and s.kind in {skMacro, skTemplate}:
+      if efInCall in flags:
+        # We are processing macroOrTmpl[] in macroOrTmpl[](...) call.
+        # Return as is, so it can be transformed into complete macro or
+        # template call in semIndirectOp caller.
+        result = n
+      else:
+        # We are processing macroOrTmpl[] not in call. Transform it to the
+        # macro or template call with generic arguments here.
+        n.kind = nkCall
+        case s.kind
+        of skMacro: result = semMacroExpr(c, n, n, s, flags)
+        of skTemplate: result = semTemplateExpr(c, n, s, flags)
+        else: discard
     elif s != nil and s.kind == skType:
       result = symNodeFromType(c, semTypeNode(c, n, nil), n.info)
     else: