diff options
author | Zahary Karadjov <zahary@gmail.com> | 2014-03-16 11:39:53 +0200 |
---|---|---|
committer | Zahary Karadjov <zahary@gmail.com> | 2014-03-16 20:42:06 +0200 |
commit | ac271e76b18110bea8046af64ceccd6b804978dd (patch) | |
tree | 3cecf7bed8b9f5759d766e0ec9e8323277b14b7f /compiler/seminst.nim | |
parent | 7dcf6ff50b03dfd54968383ad5a4258f040eec1b (diff) | |
download | Nim-ac271e76b18110bea8046af64ceccd6b804978dd.tar.gz |
more robust handling of proc signatures containing inter-param type references
Diffstat (limited to 'compiler/seminst.nim')
-rw-r--r-- | compiler/seminst.nim | 69 |
1 files changed, 58 insertions, 11 deletions
diff --git a/compiler/seminst.nim b/compiler/seminst.nim index dca9e3378..3d3227e4e 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -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() |