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