diff options
-rw-r--r-- | compiler/ast.nim | 62 | ||||
-rw-r--r-- | compiler/astalgo.nim | 123 | ||||
-rw-r--r-- | compiler/concepts.nim | 2 | ||||
-rw-r--r-- | compiler/evaltempl.nim | 8 | ||||
-rw-r--r-- | compiler/sem.nim | 2 | ||||
-rw-r--r-- | compiler/semcall.nim | 2 | ||||
-rw-r--r-- | compiler/semdata.nim | 14 | ||||
-rw-r--r-- | compiler/semexprs.nim | 2 | ||||
-rw-r--r-- | compiler/seminst.nim | 20 | ||||
-rw-r--r-- | compiler/semstmts.nim | 2 | ||||
-rw-r--r-- | compiler/semtypinst.nim | 40 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 54 | ||||
-rw-r--r-- | compiler/suggest.nim | 2 | ||||
-rw-r--r-- | compiler/transf.nim | 26 |
14 files changed, 106 insertions, 253 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index a3f17a062..431740543 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -780,10 +780,6 @@ proc hash*(x: ItemId): Hash = type - TIdObj* {.acyclic.} = object of RootObj - itemId*: ItemId - PIdObj* = ref TIdObj - PNode* = ref TNode TNodeSeq* = seq[PNode] PType* = ref TType @@ -886,7 +882,8 @@ type PScope* = ref TScope PLib* = ref TLib - TSym* {.acyclic.} = object of TIdObj # Keep in sync with PackedSym + TSym* {.acyclic.} = object # Keep in sync with PackedSym + itemId*: ItemId # proc and type instantiations are cached in the generic symbol case kind*: TSymKind of routineKinds: @@ -955,11 +952,12 @@ type attachedTrace, attachedDeepCopy - TType* {.acyclic.} = object of TIdObj # \ + TType* {.acyclic.} = object # \ # types are identical iff they have the # same id; there may be multiple copies of a type # in memory! # Keep in sync with PackedType + itemId*: ItemId kind*: TTypeKind # kind of type callConv*: TCallingConvention # for procs flags*: TTypeFlags # flags of the type @@ -991,24 +989,6 @@ type TPairSeq* = seq[TPair] - TIdPair* = object - key*: PIdObj - val*: RootRef - - TIdPairSeq* = seq[TIdPair] - TIdTable* = object # the same as table[PIdent] of PObject - counter*: int - data*: TIdPairSeq - - TIdNodePair* = object - key*: PIdObj - val*: PNode - - TIdNodePairSeq* = seq[TIdNodePair] - TIdNodeTable* = object # the same as table[PIdObj] of PNode - counter*: int - data*: TIdNodePairSeq - TNodePair* = object h*: Hash # because it is expensive to compute! key*: PNode @@ -1146,7 +1126,7 @@ proc getPIdent*(a: PNode): PIdent {.inline.} = const moduleShift = when defined(cpu32): 20 else: 24 -template id*(a: PIdObj): int = +template id*(a: PType | PSym): int = let x = a (x.itemId.module.int shl moduleShift) + x.itemId.item.int @@ -1445,11 +1425,6 @@ proc copyStrTable*(dest: var TStrTable, src: TStrTable) = setLen(dest.data, src.data.len) for i in 0..high(src.data): dest.data[i] = src.data[i] -proc copyIdTable*(dest: var TIdTable, src: TIdTable) = - dest.counter = src.counter - newSeq(dest.data, src.data.len) - for i in 0..high(src.data): dest.data[i] = src.data[i] - proc copyObjectSet*(dest: var TObjectSet, src: TObjectSet) = dest.counter = src.counter setLen(dest.data, src.data.len) @@ -1770,24 +1745,10 @@ proc initStrTable*(): TStrTable = result = TStrTable(counter: 0) newSeq(result.data, StartSize) -proc initIdTable*(): TIdTable = - result = TIdTable(counter: 0) - newSeq(result.data, StartSize) - -proc resetIdTable*(x: var TIdTable) = - x.counter = 0 - # clear and set to old initial size: - setLen(x.data, 0) - setLen(x.data, StartSize) - proc initObjectSet*(): TObjectSet = result = TObjectSet(counter: 0) newSeq(result.data, StartSize) -proc initIdNodeTable*(): TIdNodeTable = - result = TIdNodeTable(counter: 0) - newSeq(result.data, StartSize) - proc initNodeTable*(): TNodeTable = result = TNodeTable(counter: 0) newSeq(result.data, StartSize) @@ -2308,3 +2269,16 @@ const proc isTrue*(n: PNode): bool = n.kind == nkSym and n.sym.kind == skEnumField and n.sym.position != 0 or n.kind == nkIntLit and n.intVal != 0 + +type + TypeMapping* = Table[ItemId, PType] + SymMapping* = Table[ItemId, PSym] + +template idTableGet*(tab: typed; key: PSym | PType): untyped = tab.getOrDefault(key.itemId) +template idTablePut*(tab: typed; key, val: PSym | PType) = tab[key.itemId] = val + +template initSymMapping*(): Table[ItemId, PSym] = initTable[ItemId, PSym]() +template initTypeMapping*(): Table[ItemId, PType] = initTable[ItemId, PType]() + +template resetIdTable*(tab: Table[ItemId, PSym]) = tab.clear() +template resetIdTable*(tab: Table[ItemId, PType]) = tab.clear() diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim index 0fd13de00..851a82e60 100644 --- a/compiler/astalgo.nim +++ b/compiler/astalgo.nim @@ -65,16 +65,6 @@ template mdbg*: bool {.deprecated.} = else: error() -# --------------------------- ident tables ---------------------------------- -proc idTableGet*(t: TIdTable, key: PIdObj): RootRef -proc idTableGet*(t: TIdTable, key: int): RootRef -proc idTablePut*(t: var TIdTable, key: PIdObj, val: RootRef) -proc idTableHasObjectAsKey*(t: TIdTable, key: PIdObj): bool - # checks if `t` contains the `key` (compared by the pointer value, not only - # `key`'s id) -proc idNodeTableGet*(t: TIdNodeTable, key: PIdObj): PNode -proc idNodeTablePut*(t: var TIdNodeTable, key: PIdObj, val: PNode) - # --------------------------------------------------------------------------- proc lookupInRecord*(n: PNode, field: PIdent): PSym @@ -723,119 +713,6 @@ iterator items*(tab: TStrTable): PSym = yield s s = nextIter(it, tab) -proc hasEmptySlot(data: TIdPairSeq): bool = - for h in 0..high(data): - if data[h].key == nil: - return true - result = false - -proc idTableRawGet(t: TIdTable, key: int): int = - var h: Hash - h = key and high(t.data) # start with real hash value - while t.data[h].key != nil: - if t.data[h].key.id == key: - return h - h = nextTry(h, high(t.data)) - result = - 1 - -proc idTableHasObjectAsKey(t: TIdTable, key: PIdObj): bool = - var index = idTableRawGet(t, key.id) - if index >= 0: result = t.data[index].key == key - else: result = false - -proc idTableGet(t: TIdTable, key: PIdObj): RootRef = - var index = idTableRawGet(t, key.id) - if index >= 0: result = t.data[index].val - else: result = nil - -proc idTableGet(t: TIdTable, key: int): RootRef = - var index = idTableRawGet(t, key) - if index >= 0: result = t.data[index].val - else: result = nil - -iterator pairs*(t: TIdTable): tuple[key: int, value: RootRef] = - for i in 0..high(t.data): - if t.data[i].key != nil: - yield (t.data[i].key.id, t.data[i].val) - -proc idTableRawInsert(data: var TIdPairSeq, key: PIdObj, val: RootRef) = - var h: Hash - h = key.id and high(data) - while data[h].key != nil: - assert(data[h].key.id != key.id) - h = nextTry(h, high(data)) - assert(data[h].key == nil) - data[h].key = key - data[h].val = val - -proc idTablePut(t: var TIdTable, key: PIdObj, val: RootRef) = - var - index: int - n: TIdPairSeq - index = idTableRawGet(t, key.id) - if index >= 0: - assert(t.data[index].key != nil) - t.data[index].val = val - else: - if mustRehash(t.data.len, t.counter): - newSeq(n, t.data.len * GrowthFactor) - for i in 0..high(t.data): - if t.data[i].key != nil: - idTableRawInsert(n, t.data[i].key, t.data[i].val) - assert(hasEmptySlot(n)) - swap(t.data, n) - idTableRawInsert(t.data, key, val) - inc(t.counter) - -iterator idTablePairs*(t: TIdTable): tuple[key: PIdObj, val: RootRef] = - for i in 0..high(t.data): - if not isNil(t.data[i].key): yield (t.data[i].key, t.data[i].val) - -proc idNodeTableRawGet(t: TIdNodeTable, key: PIdObj): int = - var h: Hash - h = key.id and high(t.data) # start with real hash value - while t.data[h].key != nil: - if t.data[h].key.id == key.id: - return h - h = nextTry(h, high(t.data)) - result = - 1 - -proc idNodeTableGet(t: TIdNodeTable, key: PIdObj): PNode = - var index: int - index = idNodeTableRawGet(t, key) - if index >= 0: result = t.data[index].val - else: result = nil - -proc idNodeTableRawInsert(data: var TIdNodePairSeq, key: PIdObj, val: PNode) = - var h: Hash - h = key.id and high(data) - while data[h].key != nil: - assert(data[h].key.id != key.id) - h = nextTry(h, high(data)) - assert(data[h].key == nil) - data[h].key = key - data[h].val = val - -proc idNodeTablePut(t: var TIdNodeTable, key: PIdObj, val: PNode) = - var index = idNodeTableRawGet(t, key) - if index >= 0: - assert(t.data[index].key != nil) - t.data[index].val = val - else: - if mustRehash(t.data.len, t.counter): - var n: TIdNodePairSeq - newSeq(n, t.data.len * GrowthFactor) - for i in 0..high(t.data): - if t.data[i].key != nil: - idNodeTableRawInsert(n, t.data[i].key, t.data[i].val) - swap(t.data, n) - idNodeTableRawInsert(t.data, key, val) - inc(t.counter) - -iterator pairs*(t: TIdNodeTable): tuple[key: PIdObj, val: PNode] = - for i in 0..high(t.data): - if not isNil(t.data[i].key): yield (t.data[i].key, t.data[i].val) - proc initIITable(x: var TIITable) = x.counter = 0 newSeq(x.data, StartSize) diff --git a/compiler/concepts.nim b/compiler/concepts.nim index e44b0d1cd..220c7e141 100644 --- a/compiler/concepts.nim +++ b/compiler/concepts.nim @@ -309,7 +309,7 @@ proc conceptMatchNode(c: PContext; n: PNode; m: var MatchCon): bool = # error was reported earlier. result = false -proc conceptMatch*(c: PContext; concpt, arg: PType; bindings: var TIdTable; invocation: PType): bool = +proc conceptMatch*(c: PContext; concpt, arg: PType; bindings: var TypeMapping; invocation: PType): bool = ## Entry point from sigmatch. 'concpt' is the concept we try to match (here still a PType but ## we extract its AST via 'concpt.n.lastSon'). 'arg' is the type that might fullfill the ## concept's requirements. If so, we return true and fill the 'bindings' with pairs of diff --git a/compiler/evaltempl.nim b/compiler/evaltempl.nim index 98c6f4b82..bd0875213 100644 --- a/compiler/evaltempl.nim +++ b/compiler/evaltempl.nim @@ -17,8 +17,8 @@ type owner, genSymOwner: PSym instLines: bool # use the instantiation lines numbers isDeclarative: bool - mapping: TIdTable # every gensym'ed symbol needs to be mapped to some - # new symbol + mapping: SymMapping # every gensym'ed symbol needs to be mapped to some + # new symbol config: ConfigRef ic: IdentCache instID: int @@ -47,7 +47,7 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) = handleParam actual[s.owner.typ.signatureLen + s.position - 1] else: internalAssert c.config, sfGenSym in s.flags or s.kind == skType - var x = PSym(idTableGet(c.mapping, s)) + var x = idTableGet(c.mapping, s) if x == nil: x = copySym(s, c.idgen) # sem'check needs to set the owner properly later, see bug #9476 @@ -186,7 +186,7 @@ proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym; genSymOwner: genSymOwner, config: conf, ic: ic, - mapping: initIdTable(), + mapping: initSymMapping(), instID: instID[], idgen: idgen ) diff --git a/compiler/sem.nim b/compiler/sem.nim index 1ae7d4626..92c21aece 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -530,7 +530,7 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode, # e.g. template foo(T: typedesc): seq[T] # We will instantiate the return type here, because # we now know the supplied arguments - var paramTypes = initIdTable() + var paramTypes = initTypeMapping() for param, value in genericParamsInMacroCall(s, call): var givenType = value.typ # the sym nodes used for the supplied generic arguments for diff --git a/compiler/semcall.nim b/compiler/semcall.nim index 447a67208..c3a2e77a7 100644 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -663,7 +663,7 @@ proc inheritBindings(c: PContext, x: var TCandidate, expectedType: PType) = if t[i] == nil or u[i] == nil: return stackPut(t[i], u[i]) of tyGenericParam: - let prebound = x.bindings.idTableGet(t).PType + let prebound = x.bindings.idTableGet(t) if prebound != nil: continue # Skip param, already bound diff --git a/compiler/semdata.nim b/compiler/semdata.nim index f3d661ff1..12930feca 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -41,7 +41,7 @@ type breakInLoop*: bool # whether we are in a loop without block next*: PProcCon # used for stacking procedure contexts mappingExists*: bool - mapping*: TIdTable + mapping*: Table[ItemId, PSym] caseContext*: seq[tuple[n: PNode, idx: int]] localBindStmts*: seq[PNode] @@ -122,8 +122,6 @@ type converters*: seq[PSym] patterns*: seq[PSym] # sequence of pattern matchers optionStack*: seq[POptionEntry] - symMapping*: TIdTable # every gensym'ed symbol needs to be mapped - # to some new symbol in a generic instantiation libs*: seq[PLib] # all libs used by this module semConstExpr*: proc (c: PContext, n: PNode; expectedType: PType = nil): PNode {.nimcall.} # for the pragmas semExpr*: proc (c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType = nil): PNode {.nimcall.} @@ -138,8 +136,8 @@ type semOverloadedCall*: proc (c: PContext, n, nOrig: PNode, filter: TSymKinds, flags: TExprFlags, expectedType: PType = nil): PNode {.nimcall.} semTypeNode*: proc(c: PContext, n: PNode, prev: PType): PType {.nimcall.} - semInferredLambda*: proc(c: PContext, pt: TIdTable, n: PNode): PNode - semGenerateInstance*: proc (c: PContext, fn: PSym, pt: TIdTable, + semInferredLambda*: proc(c: PContext, pt: Table[ItemId, PType], n: PNode): PNode + semGenerateInstance*: proc (c: PContext, fn: PSym, pt: Table[ItemId, PType], info: TLineInfo): PSym includedFiles*: IntSet # used to detect recursive include files pureEnumFields*: TStrTable # pure enum fields that can be used unambiguously @@ -251,14 +249,14 @@ proc popProcCon*(c: PContext) {.inline.} = c.p = c.p.next proc put*(p: PProcCon; key, val: PSym) = if not p.mappingExists: - p.mapping = initIdTable() + p.mapping = initTable[ItemId, PSym]() p.mappingExists = true #echo "put into table ", key.info - p.mapping.idTablePut(key, val) + p.mapping[key.itemId] = val proc get*(p: PProcCon; key: PSym): PSym = if not p.mappingExists: return nil - result = PSym(p.mapping.idTableGet(key)) + result = p.mapping.getOrDefault(key.itemId) proc getGenSym*(c: PContext; s: PSym): PSym = if sfGenSym notin s.flags: return s diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index d39ec6b71..4d0d43662 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -2418,7 +2418,7 @@ proc instantiateCreateFlowVarCall(c: PContext; t: PType; let sym = magicsys.getCompilerProc(c.graph, "nimCreateFlowVar") if sym == nil: localError(c.config, info, "system needs: nimCreateFlowVar") - var bindings: TIdTable = initIdTable() + var bindings = initTypeMapping() bindings.idTablePut(sym.ast[genericParamsPos][0].typ, t) result = c.semGenerateInstance(c, sym, bindings, info) # since it's an instantiation, we unmark it as a compilerproc. Otherwise diff --git a/compiler/seminst.nim b/compiler/seminst.nim index cfbc678e7..e9b46c382 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -34,7 +34,7 @@ proc pushProcCon*(c: PContext; owner: PSym) = const errCannotInstantiateX = "cannot instantiate: '$1'" -iterator instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable): PSym = +iterator instantiateGenericParamList(c: PContext, n: PNode, pt: TypeMapping): PSym = internalAssert c.config, n.kind == nkGenericParams for a in n.items: internalAssert c.config, a.kind == nkSym @@ -43,7 +43,7 @@ iterator instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable): PSym let symKind = if q.typ.kind == tyStatic: skConst else: skType var s = newSym(symKind, q.name, c.idgen, getCurrOwner(c), q.info) s.flags.incl {sfUsed, sfFromGeneric} - var t = PType(idTableGet(pt, q.typ)) + var t = 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 @@ -92,7 +92,7 @@ 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) = +proc freshGenSyms(c: PContext; n: PNode, owner, orig: PSym, symMap: var SymMapping) = # 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: @@ -100,7 +100,7 @@ proc freshGenSyms(c: PContext; n: PNode, owner, orig: PSym, symMap: var TIdTable 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)) + var x = idTableGet(symMap, s) if x != nil: n.sym = x elif s.owner == nil or s.owner.kind == skPackage: @@ -124,7 +124,7 @@ proc instantiateBody(c: PContext, n, params: PNode, result, orig: PSym) = inc c.inGenericInst # add it here, so that recursive generic procs are possible: var b = n[bodyPos] - var symMap: TIdTable = initIdTable() + var symMap = initSymMapping() if params != nil: for i in 1..<params.len: let param = params[i].sym @@ -174,12 +174,12 @@ proc instGenericContainer(c: PContext, info: TLineInfo, header: PType, allowMetaTypes = false): PType = internalAssert c.config, header.kind == tyGenericInvocation - var cl: TReplTypeVars = TReplTypeVars(symMap: initIdTable(), - localCache: initIdTable(), typeMap: LayeredIdTable(), + var cl: TReplTypeVars = TReplTypeVars(symMap: initSymMapping(), + localCache: initTypeMapping(), typeMap: LayeredIdTable(), info: info, c: c, allowMetaTypes: allowMetaTypes ) - cl.typeMap.topLayer = initIdTable() + cl.typeMap.topLayer = initTypeMapping() # We must add all generic params in scope, because the generic body # may include tyFromExpr nodes depending on these generic params. @@ -217,7 +217,7 @@ proc referencesAnotherParam(n: PNode, p: PSym): bool = if referencesAnotherParam(n[i], p): return true return false -proc instantiateProcType(c: PContext, pt: TIdTable, +proc instantiateProcType(c: PContext, pt: TypeMapping, prc: PSym, info: TLineInfo) = # XXX: Instantiates a generic proc signature, while at the same # time adding the instantiated proc params into the current scope. @@ -332,7 +332,7 @@ proc getLocalPassC(c: PContext, s: PSym): string = for p in n: extractPassc(p) -proc generateInstance(c: PContext, fn: PSym, pt: TIdTable, +proc generateInstance(c: PContext, fn: PSym, pt: TypeMapping, info: TLineInfo): PSym = ## Generates a new instance of a generic procedure. ## The `pt` parameter is a type-unsafe mapping table used to link generic diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 677edbec6..028f06f89 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -1834,7 +1834,7 @@ proc semProcAnnotation(c: PContext, prc: PNode; return result -proc semInferredLambda(c: PContext, pt: TIdTable, n: PNode): PNode = +proc semInferredLambda(c: PContext, pt: TypeMapping, n: PNode): PNode = ## used for resolving 'auto' in lambdas based on their callsite var n = n let original = n[namePos].sym diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim index d1327a3ae..f0ce8d76f 100644 --- a/compiler/semtypinst.nim +++ b/compiler/semtypinst.nim @@ -9,6 +9,8 @@ # This module does the instantiation of generic types. +import std / tables + import ast, astalgo, msgs, types, magicsys, semdata, renderer, options, lineinfos, modulegraphs @@ -64,14 +66,14 @@ proc cacheTypeInst(c: PContext; inst: PType) = type LayeredIdTable* {.acyclic.} = ref object - topLayer*: TIdTable + topLayer*: TypeMapping nextLayer*: LayeredIdTable TReplTypeVars* = object c*: PContext typeMap*: LayeredIdTable # map PType to PType - symMap*: TIdTable # map PSym to PSym - localCache*: TIdTable # local cache for remembering already replaced + symMap*: SymMapping # map PSym to PSym + localCache*: TypeMapping # local cache for remembering already replaced # types during instantiation of meta types # (they are not stored in the global cache) info*: TLineInfo @@ -86,23 +88,23 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType proc replaceTypeVarsS(cl: var TReplTypeVars, s: PSym, t: PType): PSym proc replaceTypeVarsN*(cl: var TReplTypeVars, n: PNode; start=0; expectedType: PType = nil): PNode -proc initLayeredTypeMap*(pt: TIdTable): LayeredIdTable = +proc initLayeredTypeMap*(pt: sink TypeMapping): LayeredIdTable = result = LayeredIdTable() - copyIdTable(result.topLayer, pt) + result.topLayer = pt proc newTypeMapLayer*(cl: var TReplTypeVars): LayeredIdTable = - result = LayeredIdTable(nextLayer: cl.typeMap, topLayer: initIdTable()) + result = LayeredIdTable(nextLayer: cl.typeMap, topLayer: initTable[ItemId, PType]()) proc lookup(typeMap: LayeredIdTable, key: PType): PType = result = nil var tm = typeMap while tm != nil: - result = PType(idTableGet(tm.topLayer, key)) + result = getOrDefault(tm.topLayer, key.itemId) if result != nil: return tm = tm.nextLayer template put(typeMap: LayeredIdTable, key, value: PType) = - idTablePut(typeMap.topLayer, key, value) + typeMap.topLayer[key.itemId] = value template checkMetaInvariants(cl: TReplTypeVars, t: PType) = # noop code when false: @@ -361,7 +363,7 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType = var header = t # search for some instantiation here: if cl.allowMetaTypes: - result = PType(idTableGet(cl.localCache, t)) + result = getOrDefault(cl.localCache, t.itemId) else: result = searchInstTypes(cl.c.graph, t) @@ -400,7 +402,7 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType = if not cl.allowMetaTypes: cacheTypeInst(cl.c, result) else: - idTablePut(cl.localCache, t, result) + cl.localCache[t.itemId] = result let oldSkipTypedesc = cl.skipTypedesc cl.skipTypedesc = true @@ -547,7 +549,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType = # type # Vector[N: static[int]] = array[N, float64] # TwoVectors[Na, Nb: static[int]] = (Vector[Na], Vector[Nb]) - result = PType(idTableGet(cl.localCache, t)) + result = getOrDefault(cl.localCache, t.itemId) if result != nil: return result inc cl.recursionLimit @@ -623,7 +625,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType = of tyGenericInst, tyUserTypeClassInst: bailout() result = instCopyType(cl, t) - idTablePut(cl.localCache, t, result) + cl.localCache[t.itemId] = result for i in FirstGenericParamAt..<result.kidsLen: result[i] = replaceTypeVarsT(cl, result[i]) propagateToOwner(result, result.last) @@ -635,7 +637,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType = result = instCopyType(cl, t) result.size = -1 # needs to be recomputed #if not cl.allowMetaTypes: - idTablePut(cl.localCache, t, result) + cl.localCache[t.itemId] = result for i, resulti in result.ikids: if resulti != nil: @@ -690,11 +692,11 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType = proc initTypeVars*(p: PContext, typeMap: LayeredIdTable, info: TLineInfo; owner: PSym): TReplTypeVars = - result = TReplTypeVars(symMap: initIdTable(), - localCache: initIdTable(), typeMap: typeMap, + result = TReplTypeVars(symMap: initSymMapping(), + localCache: initTypeMapping(), typeMap: typeMap, info: info, c: p, owner: owner) -proc replaceTypesInBody*(p: PContext, pt: TIdTable, n: PNode; +proc replaceTypesInBody*(p: PContext, pt: TypeMapping, n: PNode; owner: PSym, allowMetaTypes = false, fromStaticExpr = false, expectedType: PType = nil): PNode = var typeMap = initLayeredTypeMap(pt) @@ -731,7 +733,7 @@ proc recomputeFieldPositions*(t: PType; obj: PNode; currPosition: var int) = inc currPosition else: discard "cannot happen" -proc generateTypeInstance*(p: PContext, pt: TIdTable, info: TLineInfo, +proc generateTypeInstance*(p: PContext, pt: TypeMapping, info: TLineInfo, t: PType): PType = # Given `t` like Foo[T] # pt: Table with type mappings: T -> int @@ -747,7 +749,7 @@ proc generateTypeInstance*(p: PContext, pt: TIdTable, info: TLineInfo, var position = 0 recomputeFieldPositions(objType, objType.n, position) -proc prepareMetatypeForSigmatch*(p: PContext, pt: TIdTable, info: TLineInfo, +proc prepareMetatypeForSigmatch*(p: PContext, pt: TypeMapping, info: TLineInfo, t: PType): PType = var typeMap = initLayeredTypeMap(pt) var cl = initTypeVars(p, typeMap, info, nil) @@ -756,6 +758,6 @@ proc prepareMetatypeForSigmatch*(p: PContext, pt: TIdTable, info: TLineInfo, result = replaceTypeVarsT(cl, t) popInfoContext(p.config) -template generateTypeInstance*(p: PContext, pt: TIdTable, arg: PNode, +template generateTypeInstance*(p: PContext, pt: TypeMapping, arg: PNode, t: PType): untyped = generateTypeInstance(p, pt, arg.info, t) diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index e831a2856..30ce24500 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -15,7 +15,7 @@ import magicsys, idents, lexer, options, parampatterns, trees, linter, lineinfos, lowerings, modulegraphs, concepts -import std/[intsets, strutils] +import std/[intsets, strutils, tables] when defined(nimPreviewSlimSystem): import std/assertions @@ -55,7 +55,7 @@ type calleeScope*: int # scope depth: # is this a top-level symbol or a nested proc? call*: PNode # modified call - bindings*: TIdTable # maps types to types + bindings*: TypeMapping # maps types to types magic*: TMagic # magic of operation baseTypeMatch: bool # needed for conversions from T to openarray[T] # for example @@ -113,14 +113,14 @@ proc initCandidateAux(ctx: PContext, proc initCandidate*(ctx: PContext, callee: PType): TCandidate = result = initCandidateAux(ctx, callee) result.calleeSym = nil - result.bindings = initIdTable() + result.bindings = initTypeMapping() proc put(c: var TCandidate, key, val: PType) {.inline.} = ## Given: proc foo[T](x: T); foo(4) ## key: 'T' ## val: 'int' (typeof(4)) when false: - let old = PType(idTableGet(c.bindings, key)) + let old = idTableGet(c.bindings, key) if old != nil: echo "Putting ", typeToString(key), " ", typeToString(val), " and old is ", typeToString(old) if typeToString(old) == "float32": @@ -141,7 +141,7 @@ proc initCandidate*(ctx: PContext, callee: PSym, result.diagnostics = @[] # if diagnosticsEnabled: @[] else: nil result.diagnosticsEnabled = diagnosticsEnabled result.magic = result.calleeSym.magic - result.bindings = initIdTable() + result.bindings = initTypeMapping() if binding != nil and callee.kind in routineKinds: var typeParams = callee.ast[genericParamsPos] for i in 1..min(typeParams.len, binding.len-1): @@ -174,7 +174,7 @@ proc copyCandidate(dest: var TCandidate, src: TCandidate) = dest.calleeSym = src.calleeSym dest.call = copyTree(src.call) dest.baseTypeMatch = src.baseTypeMatch - copyIdTable(dest.bindings, src.bindings) + dest.bindings = src.bindings proc typeRel*(c: var TCandidate, f, aOrig: PType, flags: TTypeRelFlags = {}): TTypeRelation @@ -362,7 +362,7 @@ proc concreteType(c: TCandidate, t: PType; f: PType = nil): PType = of tyGenericParam, tyAnything, tyConcept: result = t while true: - result = PType(idTableGet(c.bindings, t)) + result = idTableGet(c.bindings, t) if result == nil: break # it's ok, no match # example code that triggers it: @@ -500,7 +500,7 @@ proc genericParamPut(c: var TCandidate; last, fGenericOrigin: PType) = if fGenericOrigin != nil and last.kind == tyGenericInst and last.kidsLen-1 == fGenericOrigin.kidsLen: for i in FirstGenericParamAt..<fGenericOrigin.kidsLen: - let x = PType(idTableGet(c.bindings, fGenericOrigin[i])) + let x = idTableGet(c.bindings, fGenericOrigin[i]) if x == nil: put(c, fGenericOrigin[i], last[i]) @@ -639,7 +639,7 @@ proc procParamTypeRel(c: var TCandidate; f, a: PType): TTypeRelation = a = a if a.isMetaType: - let aResolved = PType(idTableGet(c.bindings, a)) + let aResolved = idTableGet(c.bindings, a) if aResolved != nil: a = aResolved if a.isMetaType: @@ -763,7 +763,7 @@ proc matchUserTypeClass*(m: var TCandidate; ff, a: PType): PType = typeParamName = ff.base[i-1].sym.name typ = ff[i] param: PSym = nil - alreadyBound = PType(idTableGet(m.bindings, typ)) + alreadyBound = idTableGet(m.bindings, typ) if alreadyBound != nil: typ = alreadyBound @@ -1090,7 +1090,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, case f.kind of tyGenericParam: - var prev = PType(idTableGet(c.bindings, f)) + var prev = idTableGet(c.bindings, f) if prev != nil: candidate = prev of tyFromExpr: let computedType = tryResolvingStaticExpr(c, f.n).typ @@ -1140,7 +1140,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, return res template considerPreviousT(body: untyped) = - var prev = PType(idTableGet(c.bindings, f)) + var prev = idTableGet(c.bindings, f) if prev == nil: body else: return typeRel(c, prev, a, flags) @@ -1265,7 +1265,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, var fRange = f.indexType var aRange = a.indexType if fRange.kind in {tyGenericParam, tyAnything}: - var prev = PType(idTableGet(c.bindings, fRange)) + var prev = idTableGet(c.bindings, fRange) if prev == nil: put(c, fRange, a.indexType) fRange = a @@ -1502,7 +1502,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, else: result = isNone of tyGenericInst: - var prev = PType(idTableGet(c.bindings, f)) + var prev = idTableGet(c.bindings, f) let origF = f var f = if prev == nil: f else: prev @@ -1634,14 +1634,14 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, # # we steal the generic parameters from the tyGenericBody: for i in 1..<f.len: - let x = PType(idTableGet(c.bindings, genericBody[i-1])) + let x = idTableGet(c.bindings, genericBody[i-1]) if x == nil: discard "maybe fine (for e.g. a==tyNil)" elif x.kind in {tyGenericInvocation, tyGenericParam}: internalError(c.c.graph.config, "wrong instantiated type!") else: let key = f[i] - let old = PType(idTableGet(c.bindings, key)) + let old = idTableGet(c.bindings, key) if old == nil: put(c, key, x) elif typeRel(c, old, x, flags + {trDontBind}) == isNone: @@ -1764,7 +1764,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, result = isGeneric of tyGenericParam: let doBindGP = doBind or trBindGenericParam in flags - var x = PType(idTableGet(c.bindings, f)) + var x = idTableGet(c.bindings, f) if x == nil: if c.callee.kind == tyGenericBody and not c.typedescMatched: # XXX: The fact that generic types currently use tyGenericParam for @@ -1828,7 +1828,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, elif doBind: # careful: `trDontDont` (set by `checkGeneric`) is not always respected in this call graph. # typRel having two different modes (binding and non-binding) can make things harder to - # reason about and maintain. Refactoring typeRel to not be responsible for setting, or + # reason about and maintain. Refactoring typeRel to not be responsible for setting, or # at least validating, bindings can have multiple benefits. This is debatable. I'm not 100% sure. # A design that allows a proper complexity analysis of types like `tyOr` would be ideal. concrete = concreteType(c, a, f) @@ -1846,7 +1846,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, result = typeRel(c, x, a, flags) # check if it fits if result > isGeneric: result = isGeneric of tyStatic: - let prev = PType(idTableGet(c.bindings, f)) + let prev = idTableGet(c.bindings, f) if prev == nil: if aOrig.kind == tyStatic: if f.base.kind notin {tyNone, tyGenericParam}: @@ -1899,7 +1899,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, c.inferredTypes.add f f.add a of tyTypeDesc: - var prev = PType(idTableGet(c.bindings, f)) + var prev = idTableGet(c.bindings, f) if prev == nil: # proc foo(T: typedesc, x: T) # when `f` is an unresolved typedesc, `a` could be any @@ -1983,7 +1983,7 @@ proc cmpTypes*(c: PContext, f, a: PType): TTypeRelation = proc getInstantiatedType(c: PContext, arg: PNode, m: TCandidate, f: PType): PType = - result = PType(idTableGet(m.bindings, f)) + result = idTableGet(m.bindings, f) if result == nil: result = generateTypeInstance(c, m.bindings, arg, f) if result == nil: @@ -2200,9 +2200,9 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType, var instantiationCounter = 0 var lastBindingCount = -1 while r in {isBothMetaConvertible, isInferred, isInferredConvertible} and - lastBindingCount != m.bindings.counter and + lastBindingCount != m.bindings.len and instantiationCounter < 100: - lastBindingCount = m.bindings.counter + lastBindingCount = m.bindings.len inc(instantiationCounter) if arg.kind in {nkProcDef, nkFuncDef, nkIteratorDef} + nkLambdaKinds: result = c.semInferredLambda(c, m.bindings, arg) @@ -2359,10 +2359,10 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType, else: # symbol kinds that don't participate in symchoice type disambiguation: let matchSet = {low(TSymKind)..high(TSymKind)} - {skModule, skPackage, skType} - + var best = -1 result = arg - + var actingF = f if f.kind == tyVarargs: if m.calleeSym.kind in {skTemplate, skMacro}: @@ -2398,7 +2398,7 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType, x.calleeSym = m.calleeSym y.calleeSym = m.calleeSym z.calleeSym = m.calleeSym - + for i in 0..<arg.len: if arg[i].sym.kind in matchSet: copyCandidate(z, m) @@ -2783,7 +2783,7 @@ proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) = # proc foo(x: T = 0.0) # foo() if {tfImplicitTypeParam, tfGenericTypeParam} * formal.typ.flags != {}: - let existing = PType(idTableGet(m.bindings, formal.typ)) + let existing = idTableGet(m.bindings, formal.typ) if existing == nil or existing.kind == tyTypeDesc: # see bug #11600: put(m, formal.typ, defaultValue.typ) diff --git a/compiler/suggest.nim b/compiler/suggest.nim index 720418466..21986b4d9 100644 --- a/compiler/suggest.nim +++ b/compiler/suggest.nim @@ -38,7 +38,7 @@ from wordrecg import wDeprecated, wError, wAddr, wYield import std/[algorithm, sets, parseutils, tables] when defined(nimsuggest): - import std/tables, pathutils # importer + import pathutils # importer const sep = '\t' diff --git a/compiler/transf.nim b/compiler/transf.nim index a92527fd1..ab5e9f625 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -18,6 +18,8 @@ # * performs lambda lifting for closure support # * transforms 'defer' into a 'try finally' statement +import std / tables + import options, ast, astalgo, trees, msgs, idents, renderer, types, semfold, magicsys, cgmeth, @@ -38,7 +40,7 @@ import closureiters, lambdalifting type PTransCon = ref object # part of TContext; stackable - mapping: TIdNodeTable # mapping from symbols to nodes + mapping: Table[ItemId, PNode] # mapping from symbols to nodes owner: PSym # current owner forStmt: PNode # current for stmt forLoopBody: PNode # transformed for loop body @@ -76,7 +78,7 @@ proc newTransNode(kind: TNodeKind, n: PNode, proc newTransCon(owner: PSym): PTransCon = assert owner != nil - result = PTransCon(mapping: initIdNodeTable(), owner: owner) + result = PTransCon(mapping: initTable[ItemId, PNode](), owner: owner) proc pushTransCon(c: PTransf, t: PTransCon) = t.next = c.transCon @@ -159,7 +161,7 @@ proc transformSymAux(c: PTransf, n: PNode): PNode = else: b = n while tc != nil: - result = idNodeTableGet(tc.mapping, b.sym) + result = getOrDefault(tc.mapping, b.sym.itemId) if result != nil: # this slightly convoluted way ensures the line info stays correct: if result.kind == nkSym: @@ -194,7 +196,7 @@ proc transformVarSection(c: PTransf, v: PNode): PNode = if vn.kind == nkSym: internalAssert(c.graph.config, it.len == 3) let x = freshVar(c, vn.sym) - idNodeTablePut(c.transCon.mapping, vn.sym, x) + c.transCon.mapping[vn.sym.itemId] = x var defs = newTransNode(nkIdentDefs, it.info, 3) if importantComments(c.graph.config): # keep documentation information: @@ -215,7 +217,7 @@ proc transformVarSection(c: PTransf, v: PNode): PNode = for j in 0..<it.len-2: if it[j].kind == nkSym: let x = freshVar(c, it[j].sym) - idNodeTablePut(c.transCon.mapping, it[j].sym, x) + c.transCon.mapping[it[j].sym.itemId] = x defs[j] = x else: defs[j] = transform(c, it[j]) @@ -256,7 +258,7 @@ proc transformBlock(c: PTransf, n: PNode): PNode = var labl: PSym if c.inlining > 0: labl = newLabel(c, n[0]) - idNodeTablePut(c.transCon.mapping, n[0].sym, newSymNode(labl)) + c.transCon.mapping[n[0].sym.itemId] = newSymNode(labl) else: labl = if n[0].kind != nkEmpty: @@ -328,7 +330,7 @@ proc introduceNewLocalVars(c: PTransf, n: PNode): PNode = of nkProcDef: # todo optimize nosideeffects? result = newTransNode(n) let x = newSymNode(copySym(n[namePos].sym, c.idgen)) - idNodeTablePut(c.transCon.mapping, n[namePos].sym, x) + c.transCon.mapping[n[namePos].sym.itemId] = x result[namePos] = x # we have to copy proc definitions for iters for i in 1..<n.len: result[i] = introduceNewLocalVars(c, n[i]) @@ -759,7 +761,7 @@ proc transformFor(c: PTransf, n: PNode): PNode = let pa = putArgInto(arg, formal.typ) case pa of paDirectMapping: - idNodeTablePut(newC.mapping, formal, arg) + newC.mapping[formal.itemId] = arg of paFastAsgn, paFastAsgnTakeTypeFromArg: var t = formal.typ if pa == paFastAsgnTakeTypeFromArg: @@ -773,10 +775,10 @@ proc transformFor(c: PTransf, n: PNode): PNode = #incl(temp.sym.flags, sfCursor) addVar(v, temp) stmtList.add(newAsgnStmt(c, nkFastAsgn, temp, arg, true)) - idNodeTablePut(newC.mapping, formal, temp) + newC.mapping[formal.itemId] = temp of paVarAsgn: assert(skipTypes(formal.typ, abstractInst).kind in {tyVar, tyLent}) - idNodeTablePut(newC.mapping, formal, arg) + newC.mapping[formal.itemId] = arg # XXX BUG still not correct if the arg has a side effect! of paViaIndirection: let t = formal.typ @@ -787,13 +789,13 @@ proc transformFor(c: PTransf, n: PNode): PNode = var addrExp = newNodeIT(nkHiddenAddr, formal.info, makeVarType(t.owner, t, c.idgen, tyPtr)) addrExp.add(arg) stmtList.add(newAsgnStmt(c, nkFastAsgn, temp, addrExp, true)) - idNodeTablePut(newC.mapping, formal, newDeref(temp)) + newC.mapping[formal.itemId] = newDeref(temp) of paComplexOpenarray: # arrays will deep copy here (pretty bad). var temp = newTemp(c, arg.typ, formal.info) addVar(v, temp) stmtList.add(newAsgnStmt(c, nkFastAsgn, temp, arg, true)) - idNodeTablePut(newC.mapping, formal, temp) + newC.mapping[formal.itemId] = temp let body = transformBody(c.graph, c.idgen, iter, {useCache}+c.flags) pushInfoContext(c.graph.config, n.info) |