summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ast.nim4
-rw-r--r--compiler/evaltempl.nim50
-rw-r--r--compiler/semcall.nim17
-rw-r--r--compiler/seminst.nim25
-rw-r--r--compiler/vm.nim32
-rw-r--r--compiler/vmgen.nim23
6 files changed, 43 insertions, 108 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index a071060d4..883b68d71 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -1341,10 +1341,6 @@ proc skipTypes*(t: PType, kinds: TTypeKinds): PType =
   result = t
   while result.kind in kinds: result = lastSon(result)
 
-proc safeSkipTypes*(t: PType, kinds: TTypeKinds): PType =
-  result = if t != nil: t.skipTypes(kinds)
-           else: nil
-
 proc isGCedMem*(t: PType): bool {.inline.} =
   result = t.kind in {tyString, tyRef, tySequence} or
            t.kind == tyProc and t.callConv == ccClosure
diff --git a/compiler/evaltempl.nim b/compiler/evaltempl.nim
index ecb898d8a..78cc691c0 100644
--- a/compiler/evaltempl.nim
+++ b/compiler/evaltempl.nim
@@ -25,22 +25,16 @@ proc copyNode(ctx: TemplCtx, a, b: PNode): PNode =
   if ctx.instLines: result.info = b.info
 
 proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
-  template handleParam(param) =
-    let x = param
-    if x.kind == nkArgList:
-      for y in items(x): result.add(y)
-    else:
-      result.add copyTree(x)
-
   case templ.kind
   of nkSym:
     var s = templ.sym
     if s.owner.id == c.owner.id:
-      case s.kind
-      of skParam:
-        handleParam actual.sons[s.position]
-      of skGenericParam:
-        handleParam actual.sons[s.owner.typ.len + s.position - 1]
+      if s.kind == skParam:
+        let x = actual.sons[s.position]
+        if x.kind == nkArgList:
+          for y in items(x): result.add(y)
+        else:
+          result.add copyTree(x)
       else:
         internalAssert sfGenSym in s.flags
         var x = PSym(idTableGet(c.mapping, s))
@@ -62,31 +56,21 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
 proc evalTemplateArgs(n: PNode, s: PSym): PNode =
   # if the template has zero arguments, it can be called without ``()``
   # `n` is then a nkSym or something similar
-  var totalParams = case n.kind
-    of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit: <n.len
-    else: 0
-
-  var
-    genericParams = s.ast[genericParamsPos].len
-    expectedRegularParams = <s.typ.len
-    givenRegularParams = totalParams - genericParams
-
-  if totalParams > expectedRegularParams + genericParams:
-    globalError(n.info, errWrongNumberOfArguments)
+  var a: int
+  case n.kind
+  of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit:
+    a = sonsLen(n)
+  else: a = 0
+  var f = s.typ.sonsLen
+  if a > f: globalError(n.info, errWrongNumberOfArguments)
 
   result = newNodeI(nkArgList, n.info)
-  for i in 1 .. givenRegularParams:
-    result.addSon n.sons[i]
-
-  for i in givenRegularParams+1 .. expectedRegularParams:
-    let default = s.typ.n.sons[i].sym.ast
-    if default.kind == nkEmpty:
+  for i in countup(1, f - 1):
+    var arg = if i < a: n.sons[i] else: copyTree(s.typ.n.sons[i].sym.ast)
+    if arg == nil or arg.kind == nkEmpty:
       localError(n.info, errWrongNumberOfArguments)
-    result.addSon default.copyTree
+    addSon(result, arg)
 
-  for i in 1 .. genericParams:
-    result.addSon n.sons[givenRegularParams + i]
-  
 var evalTemplateCounter* = 0
   # to prevent endless recursion in templates instantiation
 
diff --git a/compiler/semcall.nim b/compiler/semcall.nim
index 961c61c57..a712cc195 100644
--- a/compiler/semcall.nim
+++ b/compiler/semcall.nim
@@ -283,21 +283,8 @@ proc semResolvedCall(c: PContext, n: PNode, x: TCandidate): PNode =
     if containsGenericType(result.typ) or x.fauxMatch == tyUnknown:
       result.typ = newTypeS(x.fauxMatch, c)
     return
-  let gp = finalCallee.ast.sons[genericParamsPos]
-  if gp.kind != nkEmpty:
-    if x.calleeSym.kind notin {skMacro, skTemplate}:
-      finalCallee = generateInstance(c, x.calleeSym, x.bindings, n.info)
-    else:
-      # For macros and templates, the resolved generic params
-      # are added as normal params.
-      for s in instantiateGenericParamList(c, gp, x.bindings):
-        case s.kind
-          of skConst:
-            x.call.add s.ast
-          of skType:
-            x.call.add newSymNode(s, n.info)
-          else:
-            internalAssert false
+  if finalCallee.ast.sons[genericParamsPos].kind != nkEmpty:
+    finalCallee = generateInstance(c, x.calleeSym, x.bindings, n.info)
   result = x.call
   instGenericConvertersSons(c, result, x)
   result.sons[0] = newSymNode(finalCallee, result.sons[0].info)
diff --git a/compiler/seminst.nim b/compiler/seminst.nim
index dd60e0881..81a4465c5 100644
--- a/compiler/seminst.nim
+++ b/compiler/seminst.nim
@@ -10,10 +10,14 @@
 # This module implements the instantiation of generic procs.
 # included from sem.nim
 
-iterator instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable): PSym =
-  internalAssert n.kind == nkGenericParams
+proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable,
+                                 entry: var TInstantiation) = 
+  if n.kind != nkGenericParams: 
+    internalError(n.info, "instantiateGenericParamList; no generic params")
+  newSeq(entry.concreteTypes, n.len)
   for i, a in n.pairs:
-    internalAssert a.kind == nkSym
+    if a.kind != nkSym: 
+      internalError(a.info, "instantiateGenericParamList; no symbol")
     var q = a.sym
     if q.typ.kind notin {tyTypeDesc, tyGenericParam, tyStatic, tyIter}+tyTypeClasses:
       continue
@@ -38,7 +42,8 @@ iterator instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable): PSym
       #t = ReplaceTypeVarsT(cl, t)
     s.typ = t
     if t.kind == tyStatic: s.ast = t.n
-    yield s
+    addDecl(c, s)
+    entry.concreteTypes[i] = t
 
 proc sameInstantiation(a, b: TInstantiation): bool =
   if a.concreteTypes.len == b.concreteTypes.len:
@@ -191,7 +196,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
   ## The `pt` parameter is a type-unsafe mapping table used to link generic
   ## parameters to their concrete types within the generic instance.
   # no need to instantiate generic templates/macros:
-  internalAssert fn.kind notin {skMacro, skTemplate}
+  if fn.kind in {skTemplate, skMacro}: return fn
   # generates an instantiated proc
   if c.instCounter > 1000: internalError(fn.ast.info, "nesting too deep")
   inc(c.instCounter)
@@ -208,18 +213,12 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
   result.ast = n
   pushOwner(result)
   openScope(c)
-  let gp = n.sons[genericParamsPos]
-  internalAssert gp.kind != nkEmpty
+  internalAssert n.sons[genericParamsPos].kind != nkEmpty
   n.sons[namePos] = newSymNode(result)
   pushInfoContext(info)
   var entry = TInstantiation.new
   entry.sym = result
-  newSeq(entry.concreteTypes, gp.len)
-  var i = 0
-  for s in instantiateGenericParamList(c, gp, pt):
-    addDecl(c, s)
-    entry.concreteTypes[i] = s.typ
-    inc i
+  instantiateGenericParamList(c, n.sons[genericParamsPos], pt, entry[])
   pushProcCon(c, result)
   instantiateProcType(c, pt, result, info)
   n.sons[genericParamsPos] = ast.emptyNode
diff --git a/compiler/vm.nim b/compiler/vm.nim
index 912cf3331..f69b9281d 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -1417,20 +1417,12 @@ proc evalStaticStmt*(module: PSym, e: PNode, prc: PSym) =
 proc setupCompileTimeVar*(module: PSym, n: PNode) =
   discard evalConstExprAux(module, nil, n, emStaticStmt)
 
-proc setupMacroParam(x: PNode, typ: PType): TFullReg =
-  case typ.kind
-  of tyStatic:
-    putIntoReg(result, x)
-  of tyTypeDesc:
-    putIntoReg(result, x)
-  else:
-    result.kind = rkNode
-    var n = x
-    if n.kind in {nkHiddenSubConv, nkHiddenStdConv}: n = n.sons[1]
-    n = n.canonValue
-    n.flags.incl nfIsRef
-    n.typ = x.typ
-    result.node = n
+proc setupMacroParam(x: PNode): PNode =
+  result = x
+  if result.kind in {nkHiddenSubConv, nkHiddenStdConv}: result = result.sons[1]
+  result = canonValue(result)
+  result.flags.incl nfIsRef
+  result.typ = x.typ
 
 var evalMacroCounter: int
 
@@ -1450,7 +1442,6 @@ proc evalMacroCall*(module: PSym, n, nOrig: PNode, sym: PSym): PNode =
 
   c.callsite = nOrig
   let start = genProc(c, sym)
-  # c.echoCode start
 
   var tos = PStackFrame(prc: sym, comesFrom: 0, next: nil)
   let maxSlots = sym.offset
@@ -1466,14 +1457,9 @@ proc evalMacroCall*(module: PSym, n, nOrig: PNode, sym: PSym): PNode =
   tos.slots[0].kind = rkNode
   tos.slots[0].node = newNodeIT(nkEmpty, n.info, sym.typ.sons[0])
   # setup parameters:
-  for i in 1.. <sym.typ.len:
-    tos.slots[i] = setupMacroParam(n.sons[i], sym.typ.sons[i])
-
-  let gp = sym.ast[genericParamsPos]
-  for i in 0 .. <gp.len:
-    let idx = sym.typ.len + i
-    tos.slots[idx] = setupMacroParam(n.sons[idx], gp[i].sym.typ)
-
+  for i in 1 .. < min(tos.slots.len, L):
+    tos.slots[i].kind = rkNode
+    tos.slots[i].node = setupMacroParam(n.sons[i])
   # temporary storage:
   #for i in L .. <maxSlots: tos.slots[i] = newNode(nkEmpty)
   result = rawExecute(c, start, tos).regToNode
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index c233724fa..120120879 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -164,8 +164,7 @@ proc getSlotKind(t: PType): TSlotKind =
 const
   HighRegisterPressure = 40
 
-proc getTemp(c: PCtx; tt: PType): TRegister =
-  let typ = tt.safeSkipTypes({tyStatic})
+proc getTemp(c: PCtx; typ: PType): TRegister =
   let c = c.prc
   # we prefer the same slot kind here for efficiency. Unfortunately for
   # discardable return types we may not know the desired type. This can happen
@@ -686,7 +685,7 @@ proc genConv(c: PCtx; n, arg: PNode; dest: var TDest; opc=opcConv) =
   if dest < 0: dest = c.getTemp(n.typ)
   c.gABC(n, opc, dest, tmp)
   c.gABx(n, opc, 0, genType(c, n.typ))
-  c.gABx(n, opc, 0, genType(c, arg.typ.skipTypes({tyStatic})))
+  c.gABx(n, opc, 0, genType(c, arg.typ))
   c.freeTemp(tmp)
 
 proc genCard(c: PCtx; n: PNode; dest: var TDest) =
@@ -1086,8 +1085,7 @@ proc genAddrDeref(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
     c.freeTemp(tmp)
 
 proc whichAsgnOpc(n: PNode): TOpcode =
-  let toSkip = abstractRange-{tyTypeDesc}
-  case n.typ.skipTypes(toSkip).kind
+  case n.typ.skipTypes(abstractRange-{tyTypeDesc}).kind
   of tyBool, tyChar, tyEnum, tyOrdinal, tyInt..tyInt64, tyUInt..tyUInt64:
     opcAsgnInt
   of tyString, tyCString:
@@ -1561,11 +1559,6 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
         c.gABx(n, opcLdConst, dest, lit)
     of skType:
       genTypeLit(c, s.typ, dest)
-    of skGenericParam:
-      if c.prc.sym.kind == skMacro:
-        genRdVar(c, n, dest, flags)
-      else:
-        internalError(n.info, "cannot generate code for: " & s.name.s)
     else:
       internalError(n.info, "cannot generate code for: " & s.name.s)
   of nkCallKinds:
@@ -1697,14 +1690,6 @@ proc genParams(c: PCtx; params: PNode) =
     c.prc.slots[i] = (inUse: true, kind: slotFixedLet)
   c.prc.maxSlots = max(params.len, 1)
 
-proc genGenericParams(c: PCtx; gp: PNode) =
-  var base = c.prc.maxSlots
-  for i in 0.. <gp.len:
-    var param = gp.sons[i].sym
-    param.position = base + i # XXX: fix this earlier; make it consistent with templates
-    c.prc.slots[base + i] = (inUse: true, kind: slotFixedLet)
-  c.prc.maxSlots = base + gp.len
-
 proc finalJumpTarget(c: PCtx; pc, diff: int) =
   internalAssert(-0x7fff < diff and diff < 0x7fff)
   let oldInstr = c.code[pc]
@@ -1776,8 +1761,6 @@ proc genProc(c: PCtx; s: PSym): int =
     c.prc = p
     # iterate over the parameters and allocate space for them:
     genParams(c, s.typ.n)
-    if s.kind == skMacro and s.ast[genericParamsPos].kind != nkEmpty:
-      genGenericParams(c, s.ast[genericParamsPos])
     if tfCapturesEnv in s.typ.flags:
       #let env = s.ast.sons[paramsPos].lastSon.sym
       #assert env.position == 2