# # # The Nim Compiler # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. # # This module implements the instantiation of generic procs. # included from sem.nim proc addObjFieldsToLocalScope(c: PContext; n: PNode) = template rec(n) = addObjFieldsToLocalScope(c, n) case n.kind of nkRecList: for i in 0.. 0: rec n[0] for i in 1.. 1: let arg = params[1].sym if arg.name.id == c.selfName.id: c.p.selfSym = arg arg.flags.incl sfIsSelf var t = c.p.selfSym.typ.skipTypes(abstractPtrs) while t.kind == tyObject: addObjFieldsToLocalScope(c, t.n) if t[0] == nil: break t = t[0].skipTypes(skipPtrs) proc pushProcCon*(c: PContext; owner: PSym) = rawPushProcCon(c, owner) rawHandleSelf(c, owner) const errCannotInstantiateX = "cannot instantiate: '$1'" iterator instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable): PSym = internalAssert c.config, n.kind == nkGenericParams for i, a in n.pairs: internalAssert c.config, a.kind == nkSym var q = a.sym if q.typ.kind in {tyTypeDesc, tyGenericParam, tyStatic, tyConcept}+tyTypeClasses: let symKind = if q.typ.kind == tyStatic: skConst else: skType var s = newSym(symKind, q.name, nextSymId(c.idgen), getCurrOwner(c), q.info) s.flags.incl {sfUsed, sfFromGeneric} var t = PType(idTableGet(pt, q.typ)) if t == nil: if tfRetType in q.typ.flags: # keep the generic type and allow the return type to be bound # later by semAsgn in return type inference scenario t = q.typ else: localError(c.config, a.info, errCannotInstantiateX % s.name.s) t = errorType(c) elif t.kind in {tyGenericParam, tyConcept}: localError(c.config, a.info, errCannotInstantiateX % q.name.s) t = errorType(c) elif t.kind == tyGenericInvocation: #t = instGenericContainer(c, a, t) t = generateTypeInstance(c, pt, a, t) #t = ReplaceTypeVarsT(cl, t) s.typ = t if t.kind == tyStatic: s.ast = t.n yield s proc sameInstantiation(a, b: TInstantiation): bool = if a.concreteTypes.len == b.concreteTypes.len: for i in 0..a.concreteTypes.high: if not compareTypes(a.concreteTypes[i], b.concreteTypes[i], flags = {ExactTypeDescValues, ExactGcSafety, PickyCAliases}): return result = true proc genericCacheGet(g: ModuleGraph; genericSym: PSym, entry: TInstantiation; id: CompilesId): PSym = for inst in procInstCacheItems(g, genericSym): if (inst.compilesId == 0 or inst.compilesId == id) and sameInstantiation(entry, inst[]): return inst.sym when false: proc `$`(x: PSym): string = result = x.name.s & " " & " id " & $x.id proc freshGenSyms(c: PContext; n: PNode, owner, orig: PSym, symMap: var TIdTable) = # we need to create a fresh set of gensym'ed symbols: #if n.kind == nkSym and sfGenSym in n.sym.flags: # if n.sym.owner != orig: # echo "symbol ", n.sym.name.s, " orig ", orig, " owner ", n.sym.owner if n.kind == nkSym and sfGenSym in n.sym.flags: # and # (n.sym.owner == orig or n.sym.owner.kind in {skPackage}): let s = n.sym var x = PSym(idTableGet(symMap, s)) if x != nil: n.sym = x elif s.owner == nil or s.owner.kind == skPackage: #echo "copied this ", s.name.s x = copySym(s, nextSymId c.idgen) x.owner = owner idTablePut(symMap, s, x) n.sym = x else: for i in 0.. 1: resetIdTable(cl.symMap) resetIdTable(cl.localCache) # take a note of the original type. If't a free type or static parameter # we'll need to keep it unbound for the `fitNode` operation below... var typeToFit = result[i] let needsStaticSkipping = result[i].kind == tyFromExpr result[i] = replaceTypeVarsT(cl, result[i]) if needsStaticSkipping: result[i] = result[i].skipTypes({tyStatic}) # ...otherwise, we use the instantiated type in `fitNode` if (typeToFit.kind != tyTypeDesc or typeToFit.base.kind != tyNone) and (typeToFit.kind != tyStatic): typeToFit = result[i] internalAssert c.config, originalParams[i].kind == nkSym let oldParam = originalParams[i].sym let param = copySym(oldParam, nextSymId c.idgen) param.owner = prc param.typ = result[i] # The default value is instantiated and fitted against the final # concrete param type. We avoid calling `replaceTypeVarsN` on the # call head symbol, because this leads to infinite recursion. if oldParam.ast != nil: var def = oldParam.ast.copyTree if def.kind == nkCall: for i in 1..pre { line-height: 125%; } td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } .highlight .hll { background-color: #ffffcc } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb