explicit types for generic routines
This commit is contained in:
parent
e90665bff2
commit
6c20509121
25 changed files with 411 additions and 343 deletions
|
|
@ -1,29 +1,28 @@
|
|||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2009 Andreas Rumpf
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
# This module does the instantiation of generic procs and types.
|
||||
|
||||
proc generateInstance(c: PContext, fn: PSym, pt: TIdTable, info: TLineInfo): PSym
|
||||
proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||
info: TLineInfo): PSym
|
||||
# generates an instantiated proc
|
||||
proc searchInstTypes(tab: TIdTable, key: PType): PType =
|
||||
var
|
||||
t: PType
|
||||
match: bool
|
||||
# returns nil if we need to declare this type
|
||||
result = PType(IdTableGet(tab, key))
|
||||
if (result == nil) and (tab.counter > 0):
|
||||
# we have to do a slow linear search because types may need
|
||||
# to be compared by their structure:
|
||||
for h in countup(0, high(tab.data)):
|
||||
t = PType(tab.data[h].key)
|
||||
var t = PType(tab.data[h].key)
|
||||
if t != nil:
|
||||
if key.containerId == t.containerID:
|
||||
match = true
|
||||
var match = true
|
||||
for j in countup(0, sonsLen(t) - 1):
|
||||
# XXX sameType is not really correct for nested generics?
|
||||
if not sameType(t.sons[j], key.sons[j]):
|
||||
|
|
@ -39,20 +38,16 @@ proc containsGenericType(t: PType): bool =
|
|||
result = iterOverType(t, containsGenericTypeIter, nil)
|
||||
|
||||
proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable) =
|
||||
var
|
||||
s, q: PSym
|
||||
t: PType
|
||||
a: PNode
|
||||
if (n.kind != nkGenericParams):
|
||||
InternalError(n.info, "instantiateGenericParamList; no generic params")
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
a = n.sons[i]
|
||||
var a = n.sons[i]
|
||||
if a.kind != nkSym:
|
||||
InternalError(a.info, "instantiateGenericParamList; no symbol")
|
||||
q = a.sym
|
||||
var q = a.sym
|
||||
if not (q.typ.kind in {tyTypeDesc, tyGenericParam}): continue
|
||||
s = newSym(skType, q.name, getCurrOwner())
|
||||
t = PType(IdTableGet(pt, q.typ))
|
||||
var s = newSym(skType, q.name, getCurrOwner())
|
||||
var t = PType(IdTableGet(pt, q.typ))
|
||||
if t == nil: liMessage(a.info, errCannotInstantiateX, s.name.s)
|
||||
if (t.kind == tyGenericParam):
|
||||
InternalError(a.info, "instantiateGenericParamList: " & q.name.s)
|
||||
|
|
@ -60,27 +55,26 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable) =
|
|||
addDecl(c, s)
|
||||
|
||||
proc GenericCacheGet(c: PContext, genericSym, instSym: PSym): PSym =
|
||||
var a, b: PSym
|
||||
result = nil
|
||||
for i in countup(0, sonsLen(c.generics) - 1):
|
||||
if c.generics.sons[i].kind != nkExprEqExpr:
|
||||
InternalError(genericSym.info, "GenericCacheGet")
|
||||
a = c.generics.sons[i].sons[0].sym
|
||||
var a = c.generics.sons[i].sons[0].sym
|
||||
if genericSym.id == a.id:
|
||||
b = c.generics.sons[i].sons[1].sym
|
||||
var b = c.generics.sons[i].sons[1].sym
|
||||
if equalParams(b.typ.n, instSym.typ.n) == paramsEqual:
|
||||
#if gVerbosity > 0 then
|
||||
# MessageOut('found in cache: ' + getProcHeader(instSym));
|
||||
return b
|
||||
|
||||
proc GenericCacheAdd(c: PContext, genericSym, instSym: PSym) =
|
||||
var n: PNode
|
||||
n = newNode(nkExprEqExpr)
|
||||
var n = newNode(nkExprEqExpr)
|
||||
addSon(n, newSymNode(genericSym))
|
||||
addSon(n, newSymNode(instSym))
|
||||
addSon(c.generics, n)
|
||||
|
||||
proc generateInstance(c: PContext, fn: PSym, pt: TIdTable, info: TLineInfo): PSym =
|
||||
proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||
info: TLineInfo): PSym =
|
||||
# generates an instantiated proc
|
||||
var
|
||||
oldPrc, oldMod: PSym
|
||||
|
|
@ -89,8 +83,8 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable, info: TLineInfo): PSy
|
|||
if c.InstCounter > 1000: InternalError(fn.ast.info, "nesting too deep")
|
||||
inc(c.InstCounter)
|
||||
oldP = c.p # restore later
|
||||
# NOTE: for access of private fields within generics from a different module
|
||||
# and other identifiers we fake the current module temporarily!
|
||||
# NOTE: for access of private fields within generics from a different module
|
||||
# and other identifiers we fake the current module temporarily!
|
||||
oldMod = c.module
|
||||
c.module = getModule(fn)
|
||||
result = copySym(fn, false)
|
||||
|
|
@ -151,8 +145,6 @@ type
|
|||
proc ReplaceTypeVarsT(cl: var TReplTypeVars, t: PType): PType
|
||||
proc ReplaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym
|
||||
proc ReplaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode =
|
||||
var length: int
|
||||
result = nil
|
||||
if n != nil:
|
||||
result = copyNode(n)
|
||||
result.typ = ReplaceTypeVarsT(cl, n.typ)
|
||||
|
|
@ -162,7 +154,7 @@ proc ReplaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode =
|
|||
of nkSym:
|
||||
result.sym = ReplaceTypeVarsS(cl, n.sym)
|
||||
else:
|
||||
length = sonsLen(n)
|
||||
var length = sonsLen(n)
|
||||
if length > 0:
|
||||
newSons(result, length)
|
||||
for i in countup(0, length - 1):
|
||||
|
|
@ -172,7 +164,7 @@ proc ReplaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym =
|
|||
if s == nil:
|
||||
return nil
|
||||
result = PSym(idTableGet(cl.symMap, s))
|
||||
if (result == nil):
|
||||
if result == nil:
|
||||
result = copySym(s, false)
|
||||
incl(result.flags, sfFromGeneric)
|
||||
idTablePut(cl.symMap, s, result)
|
||||
|
|
@ -229,8 +221,9 @@ proc ReplaceTypeVarsT(cl: var TReplTypeVars, t: PType): PType =
|
|||
result.sons[i] = ReplaceTypeVarsT(cl, result.sons[i])
|
||||
result.n = ReplaceTypeVarsN(cl, result.n)
|
||||
if result.Kind in GenericTypes:
|
||||
liMessage(cl.info, errCannotInstantiateX, TypeToString(t, preferName)) #writeln(output, ropeToStr(Typetoyaml(result)));
|
||||
#checkConstructedType(cl.info, result);
|
||||
liMessage(cl.info, errCannotInstantiateX, TypeToString(t, preferName))
|
||||
#writeln(output, ropeToStr(Typetoyaml(result)))
|
||||
#checkConstructedType(cl.info, result)
|
||||
|
||||
proc instGenericContainer(c: PContext, n: PNode, header: PType): PType =
|
||||
var cl: TReplTypeVars
|
||||
|
|
@ -240,7 +233,8 @@ proc instGenericContainer(c: PContext, n: PNode, header: PType): PType =
|
|||
cl.c = c
|
||||
result = ReplaceTypeVarsT(cl, header)
|
||||
|
||||
proc generateTypeInstance(p: PContext, pt: TIdTable, arg: PNode, t: PType): PType =
|
||||
proc generateTypeInstance(p: PContext, pt: TIdTable, arg: PNode,
|
||||
t: PType): PType =
|
||||
var cl: TReplTypeVars
|
||||
InitIdTable(cl.symMap)
|
||||
copyIdTable(cl.typeMap, pt)
|
||||
|
|
@ -251,4 +245,9 @@ proc generateTypeInstance(p: PContext, pt: TIdTable, arg: PNode, t: PType): PTyp
|
|||
popInfoContext()
|
||||
|
||||
proc partialSpecialization(c: PContext, n: PNode, s: PSym): PNode =
|
||||
for i in 1..sonsLen(n)-1:
|
||||
n.sons[i].typ = semTypeNode(c, n.sons[i], nil)
|
||||
# we cannot check for the proper number of type parameters because in
|
||||
# `f[a,b](x, y)` `f` is not resolved yet properly.
|
||||
# XXX: BUG this should be checked somehow!
|
||||
result = n
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue