refactoring: no inheritance for PType/PSym (#23403)

This commit is contained in:
Andreas Rumpf
2024-03-14 19:23:18 +01:00
committed by GitHub
parent 51837e8127
commit 7657a637b8
14 changed files with 106 additions and 253 deletions

View File

@@ -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()

View File

@@ -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)

View File

@@ -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

View File

@@ -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
)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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)

View File

@@ -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'

View File

@@ -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)