more robust handling of proc signatures containing inter-param type references

This commit is contained in:
Zahary Karadjov 2014-03-16 11:39:53 +02:00
commit ac271e76b1
6 changed files with 106 additions and 30 deletions

View file

@ -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()