fix #1858; Add support for generic templates and macros
Implementation notes: Just after overload resolution, the resolved generic params will be added to the call expression to be later processed in evalTemplate and evalMacroCall. These procs have been modified to handle the increased number of parameters, but one remaining issue is that immediate templates and macros don't go through the same process. The next commit will outlaw the use of generic parameters with such macros.
This commit is contained in:
parent
13a18663d2
commit
5e4ae8dbb4
6 changed files with 109 additions and 44 deletions
|
|
@ -164,7 +164,8 @@ proc getSlotKind(t: PType): TSlotKind =
|
|||
const
|
||||
HighRegisterPressure = 40
|
||||
|
||||
proc getTemp(c: PCtx; typ: PType): TRegister =
|
||||
proc getTemp(c: PCtx; tt: PType): TRegister =
|
||||
let typ = tt.skipTypes({tyStatic})
|
||||
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
|
||||
|
|
@ -685,7 +686,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))
|
||||
c.gABx(n, opc, 0, genType(c, arg.typ.skipTypes({tyStatic})))
|
||||
c.freeTemp(tmp)
|
||||
|
||||
proc genCard(c: PCtx; n: PNode; dest: var TDest) =
|
||||
|
|
@ -1085,7 +1086,8 @@ proc genAddrDeref(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
|
|||
c.freeTemp(tmp)
|
||||
|
||||
proc whichAsgnOpc(n: PNode): TOpcode =
|
||||
case n.typ.skipTypes(abstractRange-{tyTypeDesc}).kind
|
||||
let toSkip = abstractRange-{tyTypeDesc}
|
||||
case n.typ.skipTypes(toSkip).kind
|
||||
of tyBool, tyChar, tyEnum, tyOrdinal, tyInt..tyInt64, tyUInt..tyUInt64:
|
||||
opcAsgnInt
|
||||
of tyString, tyCString:
|
||||
|
|
@ -1559,6 +1561,11 @@ 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:
|
||||
|
|
@ -1690,6 +1697,14 @@ 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]
|
||||
|
|
@ -1761,6 +1776,8 @@ 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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue