more robust handling of proc signatures containing inter-param type references
This commit is contained in:
parent
7dcf6ff50b
commit
ac271e76b1
6 changed files with 106 additions and 30 deletions
|
|
@ -85,19 +85,21 @@ proc freshGenSyms(n: PNode, owner: PSym, symMap: var TIdTable) =
|
|||
|
||||
proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind)
|
||||
|
||||
proc addProcDecls(c: PContext, fn: PSym) =
|
||||
# get the proc itself in scope (e.g. for recursion)
|
||||
addDecl(c, fn)
|
||||
|
||||
for i in 1 .. <fn.typ.n.len:
|
||||
var param = fn.typ.n.sons[i].sym
|
||||
param.owner = fn
|
||||
addParamOrResult(c, param, fn.kind)
|
||||
|
||||
maybeAddResult(c, fn, fn.ast)
|
||||
|
||||
proc instantiateBody(c: PContext, n: PNode, result: PSym) =
|
||||
if n.sons[bodyPos].kind != nkEmpty:
|
||||
inc c.inGenericInst
|
||||
# add it here, so that recursive generic procs are possible:
|
||||
addDecl(c, result)
|
||||
pushProcCon(c, result)
|
||||
# add params to scope
|
||||
for i in 1 .. <result.typ.n.len:
|
||||
var param = result.typ.n.sons[i].sym
|
||||
param.owner = result
|
||||
addParamOrResult(c, param, result.kind)
|
||||
# debug result.typ.n
|
||||
maybeAddResult(c, result, n)
|
||||
var b = n.sons[bodyPos]
|
||||
var symMap: TIdTable
|
||||
initIdTable symMap
|
||||
|
|
@ -107,7 +109,6 @@ proc instantiateBody(c: PContext, n: PNode, result: PSym) =
|
|||
n.sons[bodyPos] = transformBody(c.module, b, result)
|
||||
#echo "code instantiated ", result.name.s
|
||||
excl(result.flags, sfForward)
|
||||
popProcCon(c)
|
||||
dec c.inGenericInst
|
||||
|
||||
proc fixupInstantiatedSymbols(c: PContext, s: PSym) =
|
||||
|
|
@ -116,9 +117,12 @@ proc fixupInstantiatedSymbols(c: PContext, s: PSym) =
|
|||
var oldPrc = c.generics[i].inst.sym
|
||||
pushInfoContext(oldPrc.info)
|
||||
openScope(c)
|
||||
pushProcCon(c, oldPrc)
|
||||
addProcDecls(c, oldPrc)
|
||||
var n = oldPrc.ast
|
||||
n.sons[bodyPos] = copyTree(s.getBody)
|
||||
instantiateBody(c, n, oldPrc)
|
||||
popProcCon(c)
|
||||
closeScope(c)
|
||||
popInfoContext()
|
||||
|
||||
|
|
@ -144,6 +148,47 @@ proc instGenericContainer(c: PContext, info: TLineInfo, header: PType,
|
|||
proc instGenericContainer(c: PContext, n: PNode, header: PType): PType =
|
||||
result = instGenericContainer(c, n.info, header)
|
||||
|
||||
proc instantiateProcType(c: PContext, pt: TIdTable,
|
||||
prc: PSym, info: TLineInfo) =
|
||||
# XXX: Instantiates a generic proc signature, while at the same
|
||||
# time adding the instantiated proc params into the current scope.
|
||||
# This is necessary, because the instantiation process may refer to
|
||||
# these params in situations like this:
|
||||
# proc foo[Container](a: Container, b: a.type.Item): type(b.x)
|
||||
#
|
||||
# Alas, doing this here is probably not enough, because another
|
||||
# proc signature could appear in the params:
|
||||
# proc foo[T](a: proc (x: T, b: type(x.y))
|
||||
#
|
||||
# The solution would be to move this logic into semtypinst, but
|
||||
# at this point semtypinst have to become part of sem, because it
|
||||
# will need to use openScope, addDecl, etc
|
||||
#
|
||||
pushInfoContext(info)
|
||||
var cl = initTypeVars(c, pt, info)
|
||||
var result = instCopyType(cl, prc.typ)
|
||||
addDecl(c, prc)
|
||||
let originalParams = result.n
|
||||
result.n = originalParams.shallowCopy
|
||||
|
||||
for i in 1 .. <result.len:
|
||||
result.sons[i] = replaceTypeVarsT(cl, result.sons[i])
|
||||
propagateToOwner(result, result.sons[i])
|
||||
let param = replaceTypeVarsN(cl, originalParams[i])
|
||||
internalAssert param.kind == nkSym
|
||||
result.n.sons[i] = param
|
||||
addDecl(c, param.sym)
|
||||
|
||||
result.sons[0] = replaceTypeVarsT(cl, result.sons[0])
|
||||
result.n.sons[0] = originalParams[0].copyTree
|
||||
|
||||
eraseVoidParams(result)
|
||||
skipIntLiteralParams(result)
|
||||
|
||||
prc.typ = result
|
||||
maybeAddResult(c, prc, prc.ast)
|
||||
popInfoContext()
|
||||
|
||||
proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||
info: TLineInfo): PSym =
|
||||
# no need to instantiate generic templates/macros:
|
||||
|
|
@ -171,7 +216,8 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
|||
var entry = TInstantiation.new
|
||||
entry.sym = result
|
||||
instantiateGenericParamList(c, n.sons[genericParamsPos], pt, entry[])
|
||||
result.typ = generateTypeInstance(c, pt, info, fn.typ)
|
||||
pushProcCon(c, result)
|
||||
instantiateProcType(c, pt, result, info)
|
||||
n.sons[genericParamsPos] = ast.emptyNode
|
||||
var oldPrc = genericCacheGet(fn, entry[])
|
||||
if oldPrc == nil:
|
||||
|
|
@ -186,6 +232,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
|||
paramsTypeCheck(c, result.typ)
|
||||
else:
|
||||
result = oldPrc
|
||||
popProcCon(c)
|
||||
popInfoContext()
|
||||
closeScope(c) # close scope for parameters
|
||||
popOwner()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue