summary refs log tree commit diff stats
path: root/compiler/semexprs.nim
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/semexprs.nim')
-rw-r--r--compiler/semexprs.nim60
1 files changed, 56 insertions, 4 deletions
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index f1016595a..7b3697f8d 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -102,8 +102,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)
@@ -806,10 +818,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
@@ -1157,7 +1193,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,
@@ -1204,6 +1242,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: