# # # 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: 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.. 50: globalError(c.config, info, "generic instantiation too nested") inc(c.instCounter) # careful! we copy the whole AST including the possibly nil body! var n = copyTree(fn.ast) # NOTE: for access of private fields within generics from a different module # we set the friend module: c.friendModules.add(getModule(fn)) let oldMatchedConcept = c.matchedConcept c.matchedConcept = nil let oldScope = c.currentScope while not isTopLevel(c): c.currentScope = c.currentScope.parent result = copySym(fn, nextSymId c.idgen) incl(result.flags, sfFromGeneric) result.owner = fn result.ast = n pushOwner(c, result) # mixin scope: openScope(c) fillMixinScope(c) openScope(c) let gp = n[genericParamsPos] internalAssert c.config, gp.kind == nkGenericParams n[namePos] = newSymNode(result) pushInfoContext(c.config, info, fn.detailedInfo) var entry = TInstantiation.new entry.sym = result # we need to compare both the generic types and the concrete types: # generic[void](), generic[int]() # see ttypeor.nim test. var i = 0 newSeq(entry.concreteTypes, fn.typ.len+gp.len-1) for s in instantiateGenericParamList(c, gp, pt): addDecl(c, s) entry.concreteTypes[i] = s.typ inc i pushProcCon(c, result) instantiateProcType(c, pt, result, info) for j in 1..