diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2023-12-13 10:29:58 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-12-13 10:29:58 +0100 |
commit | e51e98997ba0aae748ff51eea8133e83370a7df5 (patch) | |
tree | 6df6ec97662bf49d13cda7d33f1b451f9e45aa98 | |
parent | df6cb645f7834de0c43afe2deb023c3e01093503 (diff) | |
download | Nim-e51e98997ba0aae748ff51eea8133e83370a7df5.tar.gz |
type refactoring: part 2 (#23059)
35 files changed, 422 insertions, 430 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index ae38e55a5..ab46a02d6 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -1505,9 +1505,12 @@ proc setReturnType*(n, r: PType) {.inline.} = n.sons[0] = r proc setIndexType*(n, idx: PType) {.inline.} = n.sons[0] = idx proc firstParamType*(n: PType): PType {.inline.} = n.sons[1] +proc firstGenericParam*(n: PType): PType {.inline.} = n.sons[1] proc typeBodyImpl*(n: PType): PType {.inline.} = n.sons[^1] +proc genericHead*(n: PType): PType {.inline.} = n.sons[0] + proc skipTypes*(t: PType, kinds: TTypeKinds): PType = ## Used throughout the compiler code to test whether a type tree contains or ## doesn't contain a specific type/types - it is often the case that only the @@ -1579,26 +1582,19 @@ iterator items*(t: PType): PType = iterator pairs*(n: PType): tuple[i: int, n: PType] = for i in 0..<n.sons.len: yield (i, n.sons[i]) -proc newType*(kind: TTypeKind, idgen: IdGenerator; owner: PSym, sons: seq[PType] = @[]): PType = +proc newType*(kind: TTypeKind; idgen: IdGenerator; owner: PSym; son: sink PType = nil): PType = let id = nextTypeId idgen result = PType(kind: kind, owner: owner, size: defaultSize, align: defaultAlignment, itemId: id, - uniqueId: id, sons: sons) + uniqueId: id, sons: @[]) + if son != nil: result.sons.add son when false: if result.itemId.module == 55 and result.itemId.item == 2: echo "KNID ", kind writeStackTrace() -when false: - template newType*(kind: TTypeKind, id: IdGenerator; owner: PSym, parent: PType): PType = - newType(kind, id, owner, parent.sons) - -proc setSons*(dest: PType; sons: seq[PType]) {.inline.} = dest.sons = sons - -when false: - proc newType*(prev: PType, sons: seq[PType]): PType = - result = prev - result.sons = sons +proc setSons*(dest: PType; sons: sink seq[PType]) {.inline.} = dest.sons = sons +proc setSon*(dest: PType; son: sink PType) {.inline.} = dest.sons = @[son] proc mergeLoc(a: var TLoc, b: TLoc) = if a.k == low(typeof(a.k)): a.k = b.k @@ -2029,23 +2025,21 @@ proc toVar*(typ: PType; kind: TTypeKind; idgen: IdGenerator): PType = ## returned. Otherwise ``typ`` is simply returned as-is. result = typ if typ.kind != kind: - result = newType(kind, idgen, typ.owner) - rawAddSon(result, typ) + result = newType(kind, idgen, typ.owner, typ) proc toRef*(typ: PType; idgen: IdGenerator): PType = ## If ``typ`` is a tyObject then it is converted into a `ref <typ>` and ## returned. Otherwise ``typ`` is simply returned as-is. result = typ if typ.skipTypes({tyAlias, tyGenericInst}).kind == tyObject: - result = newType(tyRef, idgen, typ.owner) - rawAddSon(result, typ) + result = newType(tyRef, idgen, typ.owner, typ) proc toObject*(typ: PType): PType = ## If ``typ`` is a tyRef then its immediate son is returned (which in many ## cases should be a ``tyObject``). ## Otherwise ``typ`` is simply returned as-is. let t = typ.skipTypes({tyAlias, tyGenericInst}) - if t.kind == tyRef: t.last + if t.kind == tyRef: t.elementType else: typ proc toObjectFromRefPtrGeneric*(typ: PType): PType = @@ -2075,11 +2069,7 @@ proc isImportedException*(t: PType; conf: ConfigRef): bool = return false let base = t.skipTypes({tyAlias, tyPtr, tyDistinct, tyGenericInst}) - - if base.sym != nil and {sfCompileToCpp, sfImportc} * base.sym.flags != {}: - result = true - else: - result = false + result = base.sym != nil and {sfCompileToCpp, sfImportc} * base.sym.flags != {} proc isInfixAs*(n: PNode): bool = return n.kind == nkInfix and n[0].kind == nkIdent and n[0].ident.id == ord(wAs) diff --git a/compiler/astmsgs.nim b/compiler/astmsgs.nim index a9027126a..c990b36e8 100644 --- a/compiler/astmsgs.nim +++ b/compiler/astmsgs.nim @@ -5,7 +5,7 @@ import options, ast, msgs proc typSym*(t: PType): PSym = result = t.sym if result == nil and t.kind == tyGenericInst: # this might need to be refined - result = t[0].sym + result = t.genericHead.sym proc addDeclaredLoc*(result: var string, conf: ConfigRef; sym: PSym) = result.add " [$1 declared in $2]" % [sym.kind.toHumanStr, toFileLineCol(conf, sym.info)] diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim index c2887f00a..175100ff4 100644 --- a/compiler/ccgcalls.nim +++ b/compiler/ccgcalls.nim @@ -218,7 +218,7 @@ proc openArrayLoc(p: BProc, formalType: PType, n: PNode; result: var Rope) = for i in 0..<q.len-1: genStmts(p, q[i]) q = q.lastSon - let (x, y) = genOpenArraySlice(p, q, formalType, n.typ[0]) + let (x, y) = genOpenArraySlice(p, q, formalType, n.typ.elementType) result.add x & ", " & y else: var a = initLocExpr(p, if n.kind == nkHiddenStdConv: n[1] else: n) diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 750398092..7757c9419 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -3277,7 +3277,7 @@ proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode, proc getNullValueAuxT(p: BProc; orig, t: PType; obj, constOrNil: PNode, result: var Rope; count: var int; isConst: bool, info: TLineInfo) = - var base = t[0] + var base = t.baseClass let oldRes = result let oldcount = count if base != nil: @@ -3426,7 +3426,7 @@ proc genBracedInit(p: BProc, n: PNode; isConst: bool; optionalType: PType; resul genConstSimpleList(p, n, isConst, data) let payload = getTempName(p.module) - let ctype = getTypeDesc(p.module, typ[0]) + let ctype = getTypeDesc(p.module, typ.elementType) let arrLen = n.len appcg(p.module, cfsStrData, "static $5 $1 $3[$2] = $4;$n", [ diff --git a/compiler/ccgtrav.nim b/compiler/ccgtrav.nim index 288398e32..d4db16018 100644 --- a/compiler/ccgtrav.nim +++ b/compiler/ccgtrav.nim @@ -126,7 +126,7 @@ proc genTraverseProcSeq(c: TTraversalClosure, accessor: Rope, typ: PType) = lineF(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) {$n", [i.r, lenExpr(c.p, a)]) let oldLen = p.s(cpsStmts).len - genTraverseProc(c, "$1$3[$2]" % [accessor, i.r, dataField(c.p)], typ[0]) + genTraverseProc(c, "$1$3[$2]" % [accessor, i.r, dataField(c.p)], typ.elementType) if p.s(cpsStmts).len == oldLen: # do not emit dummy long loops for faster debug builds: p.s(cpsStmts) = oldCode @@ -154,11 +154,11 @@ proc genTraverseProc(m: BModule, origTyp: PType; sig: SigHash): Rope = if typ.kind == tySequence: genTraverseProcSeq(c, "a".rope, typ) else: - if skipTypes(typ[0], typedescInst+{tyOwned}).kind == tyArray: + if skipTypes(typ.elementType, typedescInst+{tyOwned}).kind == tyArray: # C's arrays are broken beyond repair: - genTraverseProc(c, "a".rope, typ[0]) + genTraverseProc(c, "a".rope, typ.elementType) else: - genTraverseProc(c, "(*a)".rope, typ[0]) + genTraverseProc(c, "(*a)".rope, typ.elementType) let generatedProc = "$1 {$n$2$3$4}\n" % [header, p.s(cpsLocals), p.s(cpsInit), p.s(cpsStmts)] diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index 751a1fecb..3d7aa3088 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -324,7 +324,7 @@ proc getSimpleTypeDesc(m: BModule; typ: PType): Rope = of tyNil: result = typeNameOrLiteral(m, typ, "void*") of tyInt..tyUInt64: result = typeNameOrLiteral(m, typ, NumericalTypeToStr[typ.kind]) - of tyDistinct, tyRange, tyOrdinal: result = getSimpleTypeDesc(m, typ[0]) + of tyDistinct, tyRange, tyOrdinal: result = getSimpleTypeDesc(m, typ.skipModifier) of tyStatic: if typ.n != nil: result = getSimpleTypeDesc(m, skipModifier typ) else: @@ -884,13 +884,13 @@ proc resolveStarsInCppType(typ: PType, idx, stars: int): PType = proc getOpenArrayDesc(m: BModule; t: PType, check: var IntSet; kind: TypeDescKind): Rope = let sig = hashType(t, m.config) if kind == dkParam: - result = getTypeDescWeak(m, t[0], check, kind) & "*" + result = getTypeDescWeak(m, t.elementType, check, kind) & "*" else: result = cacheGetType(m.typeCache, sig) if result == "": result = getTypeName(m, t, sig) m.typeCache[sig] = result - let elemType = getTypeDescWeak(m, t[0], check, kind) + let elemType = getTypeDescWeak(m, t.elementType, check, kind) m.s[cfsTypes].addf("typedef struct {$n$2* Field0;$nNI Field1;$n} $1;$n", [result, elemType]) diff --git a/compiler/cgen.nim b/compiler/cgen.nim index b6456a7b8..b18ddb63c 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -1199,7 +1199,7 @@ proc genProcAux*(m: BModule, prc: PSym) = fillLoc(resNode.sym.loc, locParam, resNode, "this", OnHeap) else: fillResult(p.config, resNode, prc.typ) - assignParam(p, res, prc.typ[0]) + assignParam(p, res, prc.typ.returnType) # We simplify 'unsureAsgn(result, nil); unsureAsgn(result, x)' # to 'unsureAsgn(result, x)' # Sketch why this is correct: If 'result' points to a stack location diff --git a/compiler/jstypes.nim b/compiler/jstypes.nim index a1698edf6..d980f9989 100644 --- a/compiler/jstypes.nim +++ b/compiler/jstypes.nim @@ -146,7 +146,7 @@ proc genTypeInfo(p: PProc, typ: PType): Rope = [result, rope(ord(t.kind))] prepend(p.g.typeInfo, s) p.g.typeInfo.addf("$1.base = $2;$n", - [result, genTypeInfo(p, t[1])]) + [result, genTypeInfo(p, t.elementType)]) of tyEnum: genEnumInfo(p, t, result) of tyObject: genObjectInfo(p, t, result) of tyTuple: genTupleInfo(p, t, result) diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim index 0ed4c436f..2c9c4cb32 100644 --- a/compiler/lowerings.nim +++ b/compiler/lowerings.nim @@ -255,7 +255,7 @@ proc newDotExpr*(obj, b: PSym): PNode = proc indirectAccess*(a: PNode, b: ItemId, info: TLineInfo): PNode = # returns a[].b as a node var deref = newNodeI(nkHiddenDeref, info) - deref.typ = a.typ.skipTypes(abstractInst)[0] + deref.typ = a.typ.skipTypes(abstractInst).elementType var t = deref.typ.skipTypes(abstractInst) var field: PSym while true: @@ -278,7 +278,7 @@ proc indirectAccess*(a: PNode, b: ItemId, info: TLineInfo): PNode = proc indirectAccess*(a: PNode, b: string, info: TLineInfo; cache: IdentCache): PNode = # returns a[].b as a node var deref = newNodeI(nkHiddenDeref, info) - deref.typ = a.typ.skipTypes(abstractInst)[0] + deref.typ = a.typ.skipTypes(abstractInst).elementType var t = deref.typ.skipTypes(abstractInst) var field: PSym let bb = getIdent(cache, b) @@ -306,7 +306,7 @@ proc getFieldFromObj*(t: PType; v: PSym): PSym = assert t.kind == tyObject result = lookupInRecord(t.n, v.itemId) if result != nil: break - t = t[0] + t = t.baseClass if t == nil: break t = t.skipTypes(skipPtrs) @@ -325,7 +325,7 @@ proc genAddrOf*(n: PNode; idgen: IdGenerator; typeKind = tyPtr): PNode = proc genDeref*(n: PNode; k = nkHiddenDeref): PNode = result = newNodeIT(k, n.info, - n.typ.skipTypes(abstractInst)[0]) + n.typ.skipTypes(abstractInst).elementType) result.add n proc callCodegenProc*(g: ModuleGraph; name: string; @@ -344,7 +344,7 @@ proc callCodegenProc*(g: ModuleGraph; name: string; if optionalArgs != nil: for i in 1..<optionalArgs.len-2: result.add optionalArgs[i] - result.typ = sym.typ[0] + result.typ = sym.typ.returnType proc newIntLit*(g: ModuleGraph; info: TLineInfo; value: BiggestInt): PNode = result = nkIntLit.newIntNode(value) diff --git a/compiler/nir/ast2ir.nim b/compiler/nir/ast2ir.nim index 1730181f3..907d45013 100644 --- a/compiler/nir/ast2ir.nim +++ b/compiler/nir/ast2ir.nim @@ -2397,9 +2397,9 @@ proc genParams(c: var ProcCon; params: PNode; prc: PSym): PSym = result = resNode.sym # get result symbol c.code.addSummon toLineInfo(c, result.info), toSymId(c, result), typeToIr(c.m, result.typ), SummonResult - elif prc.typ.len > 0 and not isEmptyType(prc.typ[0]) and not isCompileTimeOnly(prc.typ[0]): + elif prc.typ.len > 0 and not isEmptyType(prc.typ.returnType) and not isCompileTimeOnly(prc.typ.returnType): # happens for procs without bodies: - let t = typeToIr(c.m, prc.typ[0]) + let t = typeToIr(c.m, prc.typ.returnType) let tmp = allocTemp(c, t) c.code.addSummon toLineInfo(c, params.info), tmp, t, SummonResult diff --git a/compiler/nir/types2ir.nim b/compiler/nir/types2ir.nim index aa8bcc12f..cdadc4f0d 100644 --- a/compiler/nir/types2ir.nim +++ b/compiler/nir/types2ir.nim @@ -84,9 +84,9 @@ proc objectToIr(c: var TypesCon; g: var TypeGraph; n: PNode; fieldTypes: Table[I assert false, "unknown node kind: " & $n.kind proc objectToIr(c: var TypesCon; g: var TypeGraph; t: PType): TypeId = - if t[0] != nil: + if t.baseClass != nil: # ensure we emitted the base type: - discard typeToIr(c, g, t[0]) + discard typeToIr(c, g, t.baseClass) var unionId = 0 var fieldTypes = initTable[ItemId, TypeId]() @@ -96,8 +96,8 @@ proc objectToIr(c: var TypesCon; g: var TypeGraph; t: PType): TypeId = g.addSize c.conf.getSize(t) g.addAlign c.conf.getAlign(t) - if t[0] != nil: - g.addNominalType(ObjectTy, mangle(c, t[0])) + if t.baseClass != nil: + g.addNominalType(ObjectTy, mangle(c, t.baseClass)) else: g.addBuiltinType VoidId # object does not inherit if not lacksMTypeField(t): diff --git a/compiler/pipelines.nim b/compiler/pipelines.nim index 91f3428be..7f318d6f1 100644 --- a/compiler/pipelines.nim +++ b/compiler/pipelines.nim @@ -196,7 +196,7 @@ proc processPipelineModule*(graph: ModuleGraph; module: PSym; idgen: IdGenerator if graph.dispatchers.len > 0: let ctx = preparePContext(graph, module, idgen) for disp in getDispatchers(graph): - let retTyp = disp.typ[0] + let retTyp = disp.typ.returnType if retTyp != nil: # TODO: properly semcheck the code of dispatcher? createTypeBoundOps(graph, ctx, retTyp, disp.ast.info, idgen) diff --git a/compiler/sem.nim b/compiler/sem.nim index d63fa56c9..47b9600f5 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -548,7 +548,7 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode, else: result = semExpr(c, result, flags, expectedType) result = fitNode(c, retType, result, result.info) - #globalError(s.info, errInvalidParamKindX, typeToString(s.typ[0])) + #globalError(s.info, errInvalidParamKindX, typeToString(s.typ.returnType)) dec(c.config.evalTemplateCounter) discard c.friendModules.pop() diff --git a/compiler/semcall.nim b/compiler/semcall.nim index 6904e6bbc..c9f407b12 100644 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -518,7 +518,7 @@ proc instGenericConvertersArg*(c: PContext, a: PNode, x: TCandidate) = let finalCallee = generateInstance(c, s, x.bindings, a.info) a[0].sym = finalCallee a[0].typ = finalCallee.typ - #a.typ = finalCallee.typ[0] + #a.typ = finalCallee.typ.returnType proc instGenericConvertersSons*(c: PContext, n: PNode, x: TCandidate) = assert n.kind in nkCallKinds @@ -735,7 +735,7 @@ proc explicitGenericSym(c: PContext, n: PNode, s: PSym): PNode = if formal.kind == tyStatic and arg.kind != tyStatic: let evaluated = c.semTryConstExpr(c, n[i]) if evaluated != nil: - arg = newTypeS(tyStatic, c, sons = @[evaluated.typ]) + arg = newTypeS(tyStatic, c, son = evaluated.typ) arg.n = evaluated let tm = typeRel(m, formal, arg) if tm in {isNone, isConvertible}: return nil @@ -821,7 +821,7 @@ proc searchForBorrowProc(c: PContext, startScope: PScope, fn: PSym): tuple[s: PS ]# t = skipTypes(param.typ, desiredTypes) isDistinct = t.kind == tyDistinct or param.typ.kind == tyDistinct - if t.kind == tyGenericInvocation and t[0].last.kind == tyDistinct: + if t.kind == tyGenericInvocation and t.genericHead.last.kind == tyDistinct: result.state = bsGeneric return if isDistinct: hasDistinct = true diff --git a/compiler/semdata.nim b/compiler/semdata.nim index e56cfc944..c066e3a7b 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -396,12 +396,11 @@ proc addToLib*(lib: PLib, sym: PSym) = # LocalError(sym.info, errInvalidPragma) sym.annex = lib -proc newTypeS*(kind: TTypeKind, c: PContext, sons: seq[PType] = @[]): PType = - result = newType(kind, c.idgen, getCurrOwner(c), sons = sons) +proc newTypeS*(kind: TTypeKind; c: PContext; son: sink PType = nil): PType = + result = newType(kind, c.idgen, getCurrOwner(c), son = son) proc makePtrType*(owner: PSym, baseType: PType; idgen: IdGenerator): PType = - result = newType(tyPtr, idgen, owner) - addSonSkipIntLit(result, baseType, idgen) + result = newType(tyPtr, idgen, owner, skipIntLit(baseType, idgen)) proc makePtrType*(c: PContext, baseType: PType): PType = makePtrType(getCurrOwner(c), baseType, c.idgen) @@ -414,15 +413,13 @@ proc makeTypeWithModifier*(c: PContext, if modifier in {tyVar, tyLent, tyTypeDesc} and baseType.kind == modifier: result = baseType else: - result = newTypeS(modifier, c) - addSonSkipIntLit(result, baseType, c.idgen) + result = newTypeS(modifier, c, skipIntLit(baseType, c.idgen)) proc makeVarType*(c: PContext, baseType: PType; kind = tyVar): PType = if baseType.kind == kind: result = baseType else: - result = newTypeS(kind, c) - addSonSkipIntLit(result, baseType, c.idgen) + result = newTypeS(kind, c, skipIntLit(baseType, c.idgen)) proc makeTypeSymNode*(c: PContext, typ: PType, info: TLineInfo): PNode = let typedesc = newTypeS(tyTypeDesc, c) @@ -438,31 +435,35 @@ proc makeTypeFromExpr*(c: PContext, n: PNode): PType = assert n != nil result.n = n -proc newTypeWithSons*(owner: PSym, kind: TTypeKind, sons: seq[PType]; - idgen: IdGenerator): PType = - result = newType(kind, idgen, owner, sons = sons) +when false: + proc newTypeWithSons*(owner: PSym, kind: TTypeKind, sons: seq[PType]; + idgen: IdGenerator): PType = + result = newType(kind, idgen, owner, sons = sons) -proc newTypeWithSons*(c: PContext, kind: TTypeKind, - sons: seq[PType]): PType = - result = newType(kind, c.idgen, getCurrOwner(c), sons = sons) + proc newTypeWithSons*(c: PContext, kind: TTypeKind, + sons: seq[PType]): PType = + result = newType(kind, c.idgen, getCurrOwner(c), sons = sons) proc makeStaticExpr*(c: PContext, n: PNode): PNode = result = newNodeI(nkStaticExpr, n.info) result.sons = @[n] result.typ = if n.typ != nil and n.typ.kind == tyStatic: n.typ - else: newTypeWithSons(c, tyStatic, @[n.typ]) + else: newTypeS(tyStatic, c, n.typ) proc makeAndType*(c: PContext, t1, t2: PType): PType = - result = newTypeS(tyAnd, c, sons = @[t1, t2]) + result = newTypeS(tyAnd, c) + result.rawAddSon t1 + result.rawAddSon t2 propagateToOwner(result, t1) propagateToOwner(result, t2) result.flags.incl((t1.flags + t2.flags) * {tfHasStatic}) result.flags.incl tfHasMeta proc makeOrType*(c: PContext, t1, t2: PType): PType = - if t1.kind != tyOr and t2.kind != tyOr: - result = newTypeS(tyOr, c, sons = @[t1, t2]) + result = newTypeS(tyOr, c) + result.rawAddSon t1 + result.rawAddSon t2 else: result = newTypeS(tyOr, c) template addOr(t1) = @@ -478,7 +479,7 @@ proc makeOrType*(c: PContext, t1, t2: PType): PType = result.flags.incl tfHasMeta proc makeNotType*(c: PContext, t1: PType): PType = - result = newTypeS(tyNot, c, sons = @[t1]) + result = newTypeS(tyNot, c, son = t1) propagateToOwner(result, t1) result.flags.incl(t1.flags * {tfHasStatic}) result.flags.incl tfHasMeta @@ -489,7 +490,7 @@ proc nMinusOne(c: PContext; n: PNode): PNode = # Remember to fix the procs below this one when you make changes! proc makeRangeWithStaticExpr*(c: PContext, n: PNode): PType = let intType = getSysType(c.graph, n.info, tyInt) - result = newTypeS(tyRange, c, sons = @[intType]) + result = newTypeS(tyRange, c, son = intType) if n.typ != nil and n.typ.n == nil: result.flags.incl tfUnresolved result.n = newTreeI(nkRange, n.info, newIntTypeNode(0, intType), @@ -549,9 +550,8 @@ proc makeTypeDesc*(c: PContext, typ: PType): PType = if typ.kind == tyTypeDesc and not isSelf(typ): result = typ else: - result = newTypeS(tyTypeDesc, c) + result = newTypeS(tyTypeDesc, c, skipIntLit(typ, c.idgen)) incl result.flags, tfCheckedForDestructor - result.addSonSkipIntLit(typ, c.idgen) proc symFromType*(c: PContext; t: PType, info: TLineInfo): PSym = if t.sym != nil: return t.sym diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index d20ac92ca..c39bbc683 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -345,7 +345,7 @@ proc semConv(c: PContext, n: PNode; flags: TExprFlags = {}, expectedType: PType if targetType.kind in {tySink, tyLent} or isOwnedSym(c, n[0]): let baseType = semTypeNode(c, n[1], nil).skipTypes({tyTypeDesc}) - let t = newTypeS(targetType.kind, c, @[baseType]) + let t = newTypeS(targetType.kind, c, baseType) if targetType.kind == tyOwned: t.flags.incl tfHasOwned result = newNodeI(nkType, n.info) @@ -467,7 +467,7 @@ proc fixupStaticType(c: PContext, n: PNode) = # apply this measure only in code that is enlightened to work # with static types. if n.typ.kind != tyStatic: - n.typ = newTypeWithSons(getCurrOwner(c), tyStatic, @[n.typ], c.idgen) + n.typ = newTypeS(tyStatic, c, n.typ) n.typ.n = n # XXX: cycles like the one here look dangerous. # Consider using `n.copyTree` @@ -901,7 +901,7 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode = if n[i].typ.isNil or n[i].typ.kind != tyStatic or tfUnresolved notin n[i].typ.flags: break maybeLabelAsStatic - n.typ = newTypeWithSons(c, tyStatic, @[n.typ]) + n.typ = newTypeS(tyStatic, c, n.typ) n.typ.flags.incl tfUnresolved # optimization pass: not necessary for correctness of the semantic pass @@ -1032,7 +1032,7 @@ proc afterCallActions(c: PContext; n, orig: PNode, flags: TExprFlags; expectedTy result = magicsAfterOverloadResolution(c, result, flags, expectedType) when false: if result.typ != nil and - not (result.typ.kind == tySequence and result.typ[0].kind == tyEmpty): + not (result.typ.kind == tySequence and result.elementType.kind == tyEmpty): liftTypeBoundOps(c, result.typ, n.info) #result = patchResolvedTypeBoundOp(c, result) if c.matchedConcept == nil: @@ -1263,7 +1263,7 @@ proc readTypeParameter(c: PContext, typ: PType, discard if typ.kind != tyUserTypeClass: - let ty = if typ.kind == tyCompositeTypeClass: typ[1].skipGenericAlias + let ty = if typ.kind == tyCompositeTypeClass: typ.firstGenericParam.skipGenericAlias else: typ.skipGenericAlias let tbody = ty[0] for s in 0..<tbody.len-1: @@ -1292,7 +1292,7 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode = onUse(n.info, s) let typ = skipTypes(s.typ, abstractInst-{tyTypeDesc}) case typ.kind - of tyNil, tyChar, tyInt..tyInt64, tyFloat..tyFloat128, + of tyNil, tyChar, tyInt..tyInt64, tyFloat..tyFloat128, tyTuple, tySet, tyUInt..tyUInt64: if s.magic == mNone: result = inlineConst(c, n, s) else: result = newSymNode(s, n.info) @@ -2066,7 +2066,7 @@ proc semYield(c: PContext, n: PNode): PNode = semYieldVarResult(c, n, restype) else: localError(c.config, n.info, errCannotReturnExpr) - elif c.p.owner.typ[0] != nil: + elif c.p.owner.typ.returnType != nil: localError(c.config, n.info, errGenerated, "yield statement must yield a value") proc considerQuotedIdentOrDot(c: PContext, n: PNode, origin: PNode = nil): PIdent = @@ -3132,7 +3132,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType let modifier = n.modifierTypeKindOfNode if modifier != tyNone: var baseType = semExpr(c, n[0]).typ.skipTypes({tyTypeDesc}) - result.typ = c.makeTypeDesc(c.newTypeWithSons(modifier, @[baseType])) + result.typ = c.makeTypeDesc(newTypeS(modifier, c, baseType)) return var typ = semTypeNode(c, n, nil).skipTypes({tyTypeDesc}) result.typ = makeTypeDesc(c, typ) diff --git a/compiler/seminst.nim b/compiler/seminst.nim index 085769bdd..c64c120d6 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -133,7 +133,7 @@ proc instantiateBody(c: PContext, n, params: PNode, result, orig: PSym) = if result.kind == skMacro: sysTypeFromName(c.graph, n.info, "NimNode") elif not isInlineIterator(result.typ): - result.typ[0] + result.typ.returnType else: nil b = semProcBody(c, b, resultType) @@ -315,8 +315,8 @@ proc fillMixinScope(c: PContext) = addSym(c.currentScope, n.sym) p = p.next -proc getLocalPassC(c: PContext, s: PSym): string = - if s.ast == nil or s.ast.len == 0: return "" +proc getLocalPassC(c: PContext, s: PSym): string = + if s.ast == nil or s.ast.len == 0: return "" result = "" template extractPassc(p: PNode) = if p.kind == nkPragma and p[0][0].ident == c.cache.getIdent"localpassc": @@ -325,7 +325,7 @@ proc getLocalPassC(c: PContext, s: PSym): string = for n in s.ast: for p in n: extractPassc(p) - + proc generateInstance(c: PContext, fn: PSym, pt: TIdTable, info: TLineInfo): PSym = ## Generates a new instance of a generic procedure. @@ -354,7 +354,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable, let passc = getLocalPassC(c, producer) if passc != "": #pass the local compiler options to the consumer module too extccomp.addLocalCompileOption(c.config, passc, toFullPathConsiderDirty(c.config, c.module.info.fileIndex)) - result.owner = c.module + result.owner = c.module else: result.owner = fn result.ast = n diff --git a/compiler/semmacrosanity.nim b/compiler/semmacrosanity.nim index 9e84e7c62..01b79c1bc 100644 --- a/compiler/semmacrosanity.nim +++ b/compiler/semmacrosanity.nim @@ -78,11 +78,11 @@ proc annotateType*(n: PNode, t: PType; conf: ConfigRef) = of nkStrKinds: for i in left..right: bracketExpr.add newIntNode(nkCharLit, BiggestInt n[0].strVal[i]) - annotateType(bracketExpr[^1], t[0], conf) + annotateType(bracketExpr[^1], x.elementType, conf) of nkBracket: for i in left..right: bracketExpr.add n[0][i] - annotateType(bracketExpr[^1], t[0], conf) + annotateType(bracketExpr[^1], x.elementType, conf) else: globalError(conf, n.info, "Incorrectly generated tuple constr") n[] = bracketExpr[] diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index bf8375adf..c36a9ede1 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -132,7 +132,7 @@ proc uninstantiate(t: PType): PType = result = case t.kind of tyMagicGenerics: t of tyUserDefinedGenerics: t.base - of tyCompositeTypeClass: uninstantiate t[1] + of tyCompositeTypeClass: uninstantiate t.firstGenericParam else: t proc getTypeDescNode(c: PContext; typ: PType, sym: PSym, info: TLineInfo): PNode = @@ -140,6 +140,14 @@ proc getTypeDescNode(c: PContext; typ: PType, sym: PSym, info: TLineInfo): PNode rawAddSon(resType, typ) result = toNode(resType, info) +proc buildBinaryPredicate(kind: TTypeKind; c: PContext; context: PSym; a, b: sink PType): PType = + result = newType(kind, c.idgen, context) + result.rawAddSon a + result.rawAddSon b + +proc buildNotPredicate(c: PContext; context: PSym; a: sink PType): PType = + result = newType(tyNot, c.idgen, context, a) + proc evalTypeTrait(c: PContext; traitCall: PNode, operand: PType, context: PSym): PNode = const skippedTypes = {tyTypeDesc, tyAlias, tySink} let trait = traitCall[0] @@ -149,20 +157,17 @@ proc evalTypeTrait(c: PContext; traitCall: PNode, operand: PType, context: PSym) template operand2: PType = traitCall[2].typ.skipTypes({tyTypeDesc}) - template typeWithSonsResult(kind, sons): PNode = - newTypeWithSons(context, kind, sons, c.idgen).toNode(traitCall.info) - if operand.kind == tyGenericParam or (traitCall.len > 2 and operand2.kind == tyGenericParam): return traitCall ## too early to evaluate let s = trait.sym.name.s case s of "or", "|": - return typeWithSonsResult(tyOr, @[operand, operand2]) + return buildBinaryPredicate(tyOr, c, context, operand, operand2).toNode(traitCall.info) of "and": - return typeWithSonsResult(tyAnd, @[operand, operand2]) + return buildBinaryPredicate(tyAnd, c, context, operand, operand2).toNode(traitCall.info) of "not": - return typeWithSonsResult(tyNot, @[operand]) + return buildNotPredicate(c, context, operand).toNode(traitCall.info) of "typeToString": var prefer = preferTypeName if traitCall.len >= 2: @@ -532,7 +537,7 @@ proc semNewFinalize(c: PContext; n: PNode): PNode = result = addDefaultFieldForNew(c, n) proc semPrivateAccess(c: PContext, n: PNode): PNode = - let t = n[1].typ[0].toObjectFromRefPtrGeneric + let t = n[1].typ.elementType.toObjectFromRefPtrGeneric if t.kind == tyObject: assert t.sym != nil c.currentScope.allowPrivateAccess.add t.sym @@ -668,7 +673,8 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode, result = semPrivateAccess(c, n) of mArrToSeq: result = n - if result.typ != nil and expectedType != nil and result.typ.kind == tySequence and expectedType.kind == tySequence and result.typ[0].kind == tyEmpty: + if result.typ != nil and expectedType != nil and result.typ.kind == tySequence and + expectedType.kind == tySequence and result.typ.elementType.kind == tyEmpty: result.typ = expectedType # type inference for empty sequence # bug #21377 of mEnsureMove: result = n diff --git a/compiler/semobjconstr.nim b/compiler/semobjconstr.nim index ae254f45b..96f7658df 100644 --- a/compiler/semobjconstr.nim +++ b/compiler/semobjconstr.nim @@ -413,7 +413,7 @@ proc semConstructTypeAux(c: PContext, result.defaults.add defaults if status in {initPartial, initNone, initUnknown}: discard collectMissingFields(c, t.n, constrCtx, result.defaults) - let base = t[0] + let base = t.baseClass if base == nil or base.id == t.id or base.kind in {tyRef, tyPtr} and base.elementType.id == t.id: break diff --git a/compiler/semparallel.nim b/compiler/semparallel.nim index d5fc72760..e9ba04e8b 100644 --- a/compiler/semparallel.nim +++ b/compiler/semparallel.nim @@ -406,7 +406,7 @@ proc transformSlices(g: ModuleGraph; idgen: IdGenerator; n: PNode): PNode = if op.name.s == "[]" and op.fromSystem: result = copyNode(n) var typ = newType(tyOpenArray, idgen, result.typ.owner) - typ.add result.typ[0] + typ.add result.typ.elementType result.typ = typ let opSlice = newSymNode(createMagic(g, idgen, "slice", mSlice)) opSlice.typ = getSysType(g, n.info, tyInt) @@ -441,7 +441,7 @@ proc transformSpawn(g: ModuleGraph; idgen: IdGenerator; owner: PSym; n, barrier: if result.isNil: result = newNodeI(nkStmtList, n.info) result.add n - let t = b[1][0].typ[0] + let t = b[1][0].typ.returnType if spawnResult(t, true) == srByVar: result.add wrapProcForSpawn(g, idgen, owner, m, b.typ, barrier, it[0]) it[^1] = newNodeI(nkEmpty, it.info) @@ -450,7 +450,7 @@ proc transformSpawn(g: ModuleGraph; idgen: IdGenerator; owner: PSym; n, barrier: if result.isNil: result = n of nkAsgn, nkFastAsgn, nkSinkAsgn: let b = n[1] - if getMagic(b) == mSpawn and (let t = b[1][0].typ[0]; + if getMagic(b) == mSpawn and (let t = b[1][0].typ.returnType; spawnResult(t, true) == srByVar): let m = transformSlices(g, idgen, b) return wrapProcForSpawn(g, idgen, owner, m, b.typ, barrier, n[0]) diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index 448f4d26a..8fc218955 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -24,9 +24,6 @@ when defined(useDfa): import liftdestructors include sinkparameter_inference - -import std/options as opt - #[ Second semantic checking pass over the AST. Necessary because the old way had some inherent problems. Performs: @@ -94,29 +91,26 @@ const errXCannotBeAssignedTo = "'$1' cannot be assigned to" errLetNeedsInit = "'let' symbol requires an initialization" -proc getObjDepth(t: PType): Option[tuple[depth: int, root: ItemId]] = +proc getObjDepth(t: PType): (int, ItemId) = var x = t - var res: tuple[depth: int, root: ItemId] - res.depth = -1 + result = (-1, default(ItemId)) var stack = newSeq[ItemId]() while x != nil: x = skipTypes(x, skipPtrs) if x.kind != tyObject: - return none(tuple[depth: int, root: ItemId]) + return (-3, default(ItemId)) stack.add x.itemId - x = x[0] - inc(res.depth) - res.root = stack[^2] - result = some(res) + x = x.baseClass + inc(result[0]) + result[1] = stack[^2] proc collectObjectTree(graph: ModuleGraph, n: PNode) = for section in n: if section.kind == nkTypeDef and section[^1].kind in {nkObjectTy, nkRefTy, nkPtrTy}: let typ = section[^1].typ.skipTypes(skipPtrs) - if typ.len > 0 and typ[0] != nil: - let depthItem = getObjDepth(typ) - if isSome(depthItem): - let (depthLevel, root) = depthItem.unsafeGet + if typ.kind == tyObject and typ.baseClass != nil: + let (depthLevel, root) = getObjDepth(typ) + if depthLevel != -3: if depthLevel == 1: graph.objectTree[root] = @[] else: diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 3104f3158..22e863c5c 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -1343,7 +1343,7 @@ proc typeSectionLeftSidePass(c: PContext, n: PNode) = inc i proc checkCovariantParamsUsages(c: PContext; genericType: PType) = - var body = genericType[^1] + var body = genericType.typeBodyImpl proc traverseSubTypes(c: PContext; t: PType): bool = template error(msg) = localError(c.config, genericType.sym.info, msg) @@ -1360,7 +1360,7 @@ proc checkCovariantParamsUsages(c: PContext; genericType: PType) = for field in t.n: subresult traverseSubTypes(c, field.typ) of tyArray: - return traverseSubTypes(c, t[1]) + return traverseSubTypes(c, t.elementType) of tyProc: for subType in t: if subType != nil: @@ -1368,9 +1368,9 @@ proc checkCovariantParamsUsages(c: PContext; genericType: PType) = if result: error("non-invariant type param used in a proc type: " & $t) of tySequence: - return traverseSubTypes(c, t[0]) + return traverseSubTypes(c, t.elementType) of tyGenericInvocation: - let targetBody = t[0] + let targetBody = t.genericHead for i in 1..<t.len: let param = t[i] if param.kind == tyGenericParam: @@ -1439,7 +1439,11 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) = # we fill it out later. For magic generics like 'seq', it won't be filled # so we use tyNone instead of nil to not crash for strange conversions # like: mydata.seq - rawAddSon(s.typ, newTypeS(tyNone, c)) + if s.typ.kind in {tyOpenArray, tyVarargs} and s.typ.len == 1: + # XXX investigate why `tySequence` cannot be added here for now. + discard + else: + rawAddSon(s.typ, newTypeS(tyNone, c)) s.ast = a inc c.inGenericContext var body = semTypeNode(c, a[2], s.typ) @@ -1544,7 +1548,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) = proc checkForMetaFields(c: PContext; n: PNode) = proc checkMeta(c: PContext; n: PNode; t: PType) = if t != nil and t.isMetaType and tfGenericTypeParam notin t.flags: - if t.kind == tyBuiltInTypeClass and t.len == 1 and t[0].kind == tyProc: + if t.kind == tyBuiltInTypeClass and t.len == 1 and t.elementType.kind == tyProc: localError(c.config, n.info, ("'$1' is not a concrete type; " & "for a callback without parameters use 'proc()'") % t.typeToString) else: @@ -1873,20 +1877,20 @@ proc whereToBindTypeHook(c: PContext; t: PType): PType = proc bindDupHook(c: PContext; s: PSym; n: PNode; op: TTypeAttachedOp) = let t = s.typ var noError = false - let cond = t.len == 2 and t[0] != nil + let cond = t.len == 2 and t.returnType != nil if cond: - var obj = t[1] + var obj = t.firstParamType while true: incl(obj.flags, tfHasAsgn) if obj.kind in {tyGenericBody, tyGenericInst}: obj = obj.skipModifier - elif obj.kind == tyGenericInvocation: obj = obj[0] + elif obj.kind == tyGenericInvocation: obj = obj.genericHead else: break - var res = t[0] + var res = t.returnType while true: if res.kind in {tyGenericBody, tyGenericInst}: res = res.skipModifier - elif res.kind == tyGenericInvocation: res = res[0] + elif res.kind == tyGenericInvocation: res = res.genericHead else: break if obj.kind in {tyObject, tyDistinct, tySequence, tyString} and sameType(obj, res): @@ -1915,21 +1919,21 @@ proc bindTypeHook(c: PContext; s: PSym; n: PNode; op: TTypeAttachedOp; suppressV var noError = false let cond = case op of attachedWasMoved: - t.len == 2 and t[0] == nil and t[1].kind == tyVar + t.len == 2 and t.returnType == nil and t.firstParamType.kind == tyVar of attachedTrace: - t.len == 3 and t[0] == nil and t[1].kind == tyVar and t[2].kind == tyPointer + t.len == 3 and t.returnType == nil and t.firstParamType.kind == tyVar and t[2].kind == tyPointer else: - t.len >= 2 and t[0] == nil + t.len >= 2 and t.returnType == nil if cond: - var obj = t[1].skipTypes({tyVar}) + var obj = t.firstParamType.skipTypes({tyVar}) while true: incl(obj.flags, tfHasAsgn) if obj.kind in {tyGenericBody, tyGenericInst}: obj = obj.skipModifier - elif obj.kind == tyGenericInvocation: obj = obj[0] + elif obj.kind == tyGenericInvocation: obj = obj.genericHead else: break if obj.kind in {tyObject, tyDistinct, tySequence, tyString}: - if (not suppressVarDestructorWarning) and op == attachedDestructor and t[1].kind == tyVar: + if (not suppressVarDestructorWarning) and op == attachedDestructor and t.firstParamType.kind == tyVar: message(c.config, n.info, warnDeprecated, "A custom '=destroy' hook which takes a 'var T' parameter is deprecated; it should take a 'T' parameter") obj = canonType(c, obj) let ao = getAttachedOp(c.graph, obj, op) @@ -1976,7 +1980,7 @@ proc semOverride(c: PContext, s: PSym, n: PNode) = var t = s.typ.firstParamType.skipTypes(abstractInst).elementType.skipTypes(abstractInst) while true: if t.kind == tyGenericBody: t = t.typeBodyImpl - elif t.kind == tyGenericInvocation: t = t[0] + elif t.kind == tyGenericInvocation: t = t.genericHead else: break if t.kind in {tyObject, tyDistinct, tyEnum, tySequence, tyString}: if getAttachedOp(c.graph, t, attachedDeepCopy).isNil: @@ -2004,18 +2008,18 @@ proc semOverride(c: PContext, s: PSym, n: PNode) = if name == "=": message(c.config, n.info, warnDeprecated, "Overriding `=` hook is deprecated; Override `=copy` hook instead") let t = s.typ - if t.len == 3 and t[0] == nil and t[1].kind == tyVar: - var obj = t[1][0] + if t.len == 3 and t.returnType == nil and t.firstParamType.kind == tyVar: + var obj = t.firstParamType.elementType while true: incl(obj.flags, tfHasAsgn) if obj.kind == tyGenericBody: obj = obj.skipModifier - elif obj.kind == tyGenericInvocation: obj = obj[0] + elif obj.kind == tyGenericInvocation: obj = obj.genericHead else: break var objB = t[2] while true: if objB.kind == tyGenericBody: objB = objB.skipModifier elif objB.kind in {tyGenericInvocation, tyGenericInst}: - objB = objB[0] + objB = objB.genericHead else: break if obj.kind in {tyObject, tyDistinct, tySequence, tyString} and sameType(obj, objB): # attach these ops to the canonical tySequence @@ -2132,7 +2136,7 @@ proc semMethodPrototype(c: PContext; s: PSym; n: PNode) = for col in 1..<tt.len: let t = tt[col] if t != nil and t.kind == tyGenericInvocation: - var x = skipTypes(t[0], {tyVar, tyLent, tyPtr, tyRef, tyGenericInst, + var x = skipTypes(t.genericHead, {tyVar, tyLent, tyPtr, tyRef, tyGenericInst, tyGenericInvocation, tyGenericBody, tyAlias, tySink, tyOwned}) if x.kind == tyObject and t.len-1 == n[genericParamsPos].len: @@ -2446,7 +2450,7 @@ proc semIterator(c: PContext, n: PNode): PNode = if result.kind != n.kind: return var s = result[namePos].sym var t = s.typ - if t[0] == nil and s.typ.callConv != ccClosure: + if t.returnType == nil and s.typ.callConv != ccClosure: localError(c.config, n.info, "iterator needs a return type") # iterators are either 'inline' or 'closure'; for backwards compatibility, # we require first class iterators to be marked with 'closure' explicitly @@ -2501,7 +2505,7 @@ proc semConverterDef(c: PContext, n: PNode): PNode = if result.kind != nkConverterDef: return var s = result[namePos].sym var t = s.typ - if t[0] == nil: localError(c.config, n.info, errXNeedsReturnType % "converter") + if t.returnType == nil: localError(c.config, n.info, errXNeedsReturnType % "converter") if t.len != 2: localError(c.config, n.info, "a converter takes exactly one argument") addConverterDef(c, LazySym(sym: s)) diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index e27713522..337714142 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -38,12 +38,12 @@ const errNoGenericParamsAllowedForX = "no generic parameters allowed for $1" errInOutFlagNotExtern = "the '$1' modifier can be used only with imported types" -proc newOrPrevType(kind: TTypeKind, prev: PType, c: PContext, sons: seq[PType]): PType = +proc newOrPrevType(kind: TTypeKind, prev: PType, c: PContext, son: sink PType): PType = if prev == nil or prev.kind == tyGenericBody: - result = newTypeS(kind, c, sons = sons) + result = newTypeS(kind, c, son) else: result = prev - result.setSons(sons) + result.setSon(son) if result.kind == tyForward: result.kind = kind #if kind == tyError: result.flags.incl tfCheckedForDestructor @@ -426,7 +426,7 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType = # ensure we only construct a tyArray when there was no error (bug #3048): # bug #6682: Do not propagate initialization requirements etc for the # index type: - result = newOrPrevType(tyArray, prev, c, @[indx]) + result = newOrPrevType(tyArray, prev, c, indx) addSonSkipIntLit(result, base, c.idgen) else: localError(c.config, n.info, errArrayExpectsTwoTypeParams) @@ -556,14 +556,14 @@ proc checkForOverlap(c: PContext, t: PNode, currentEx, branchIndex: int) = if overlap(t[i][j].skipConv, ex): localError(c.config, ex.info, errDuplicateCaseLabel) -proc semBranchRange(c: PContext, t, a, b: PNode, covered: var Int128): PNode = - checkMinSonsLen(t, 1, c.config) +proc semBranchRange(c: PContext, n, a, b: PNode, covered: var Int128): PNode = + checkMinSonsLen(n, 1, c.config) let ac = semConstExpr(c, a) let bc = semConstExpr(c, b) if ac.kind in {nkStrLit..nkTripleStrLit} or bc.kind in {nkStrLit..nkTripleStrLit}: localError(c.config, b.info, "range of string is invalid") - let at = fitNode(c, t[0].typ, ac, ac.info).skipConvTakeType - let bt = fitNode(c, t[0].typ, bc, bc.info).skipConvTakeType + let at = fitNode(c, n[0].typ, ac, ac.info).skipConvTakeType + let bt = fitNode(c, n[0].typ, bc, bc.info).skipConvTakeType result = newNodeI(nkRange, a.info) result.add(at) @@ -576,19 +576,19 @@ proc semCaseBranchRange(c: PContext, t, b: PNode, checkSonsLen(b, 3, c.config) result = semBranchRange(c, t, b[1], b[2], covered) -proc semCaseBranchSetElem(c: PContext, t, b: PNode, +proc semCaseBranchSetElem(c: PContext, n, b: PNode, covered: var Int128): PNode = if isRange(b): checkSonsLen(b, 3, c.config) - result = semBranchRange(c, t, b[1], b[2], covered) + result = semBranchRange(c, n, b[1], b[2], covered) elif b.kind == nkRange: checkSonsLen(b, 2, c.config) - result = semBranchRange(c, t, b[0], b[1], covered) + result = semBranchRange(c, n, b[0], b[1], covered) else: - result = fitNode(c, t[0].typ, b, b.info) + result = fitNode(c, n[0].typ, b, b.info) inc(covered) -proc semCaseBranch(c: PContext, t, branch: PNode, branchIndex: int, +proc semCaseBranch(c: PContext, n, branch: PNode, branchIndex: int, covered: var Int128) = let lastIndex = branch.len - 2 for i in 0..lastIndex: @@ -596,22 +596,22 @@ proc semCaseBranch(c: PContext, t, branch: PNode, branchIndex: int, if b.kind == nkRange: branch[i] = b elif isRange(b): - branch[i] = semCaseBranchRange(c, t, b, covered) + branch[i] = semCaseBranchRange(c, n, b, covered) else: # constant sets and arrays are allowed: # set expected type to selector type for type inference # even if it can be a different type like a set or array - var r = semConstExpr(c, b, expectedType = t[0].typ) + var r = semConstExpr(c, b, expectedType = n[0].typ) if r.kind in {nkCurly, nkBracket} and r.len == 0 and branch.len == 2: # discarding ``{}`` and ``[]`` branches silently delSon(branch, 0) return elif r.kind notin {nkCurly, nkBracket} or r.len == 0: - checkMinSonsLen(t, 1, c.config) - var tmp = fitNode(c, t[0].typ, r, r.info) + checkMinSonsLen(n, 1, c.config) + var tmp = fitNode(c, n[0].typ, r, r.info) # the call to fitNode may introduce a call to a converter if tmp.kind == nkHiddenCallConv or - (tmp.kind == nkHiddenStdConv and t[0].typ.kind == tyCstring): + (tmp.kind == nkHiddenStdConv and n[0].typ.kind == tyCstring): tmp = semConstExpr(c, tmp) branch[i] = skipConv(tmp) inc(covered) @@ -620,18 +620,18 @@ proc semCaseBranch(c: PContext, t, branch: PNode, branchIndex: int, r = deduplicate(c.config, r) # first element is special and will overwrite: branch[i]: - branch[i] = semCaseBranchSetElem(c, t, r[0], covered) + branch[i] = semCaseBranchSetElem(c, n, r[0], covered) # other elements have to be added to ``branch`` for j in 1..<r.len: - branch.add(semCaseBranchSetElem(c, t, r[j], covered)) + branch.add(semCaseBranchSetElem(c, n, r[j], covered)) # caution! last son of branch must be the actions to execute: swap(branch[^2], branch[^1]) - checkForOverlap(c, t, i, branchIndex) + checkForOverlap(c, n, i, branchIndex) # Elements added above needs to be checked for overlaps. for i in lastIndex.succ..<branch.len - 1: - checkForOverlap(c, t, i, branchIndex) + checkForOverlap(c, n, i, branchIndex) proc toCover(c: PContext, t: PType): Int128 = let t2 = skipTypes(t, abstractVarRange-{tyTypeDesc}) @@ -723,7 +723,7 @@ proc semRecordCase(c: PContext, n: PNode, check: var IntSet, pos: var int, of tyFloat..tyFloat128, tyError: discard of tyRange: - if skipTypes(typ[0], abstractInst).kind in shouldChckCovered: + if skipTypes(typ.elementType, abstractInst).kind in shouldChckCovered: chckCovered = true of tyForward: errorUndeclaredIdentifier(c, n[0].info, typ.sym.name.s) @@ -1018,11 +1018,11 @@ proc semAnyRef(c: PContext; n: PNode; kind: TTypeKind; prev: PType): PType = case wrapperKind of tyOwned: if optOwnedRefs in c.config.globalOptions: - let t = newTypeS(tyOwned, c, @[result]) + let t = newTypeS(tyOwned, c, result) t.flags.incl tfHasOwned result = t of tySink: - let t = newTypeS(tySink, c, @[result]) + let t = newTypeS(tySink, c, result) result = t else: discard if result.kind == tyRef and c.config.selectedGC in {gcArc, gcOrc, gcAtomicArc}: @@ -1117,7 +1117,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode, let base = (if lifted != nil: lifted else: paramType.base) if base.isMetaType and procKind == skMacro: localError(c.config, info, errMacroBodyDependsOnGenericTypes % paramName) - result = addImplicitGeneric(c, c.newTypeWithSons(tyStatic, @[base]), + result = addImplicitGeneric(c, newTypeS(tyStatic, c, base), paramTypId, info, genericParams, paramName) if result != nil: result.flags.incl({tfHasStatic, tfUnresolved}) @@ -1129,7 +1129,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode, paramTypId.id == getIdent(c.cache, "type").id): # XXX Why doesn't this check for tyTypeDesc instead? paramTypId = nil - let t = c.newTypeWithSons(tyTypeDesc, @[paramType.base]) + let t = newTypeS(tyTypeDesc, c, paramType.base) incl t.flags, tfCheckedForDestructor result = addImplicitGeneric(c, t, paramTypId, info, genericParams, paramName) else: @@ -1160,8 +1160,8 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode, # Maybe there is another better place to associate # the seq type class with the seq identifier. if paramType.kind == tySequence and paramType.elementType.kind == tyNone: - let typ = c.newTypeWithSons(tyBuiltInTypeClass, - @[newTypeS(paramType.kind, c)]) + let typ = newTypeS(tyBuiltInTypeClass, c, + newTypeS(paramType.kind, c)) result = addImplicitGeneric(c, typ, paramTypId, info, genericParams, paramName) else: result = nil @@ -1192,9 +1192,9 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode, let x = instGenericContainer(c, paramType.sym.info, result, allowMetaTypes = true) - result = newTypeWithSons(c, tyCompositeTypeClass, @[paramType, x]) - #result = newTypeS(tyCompositeTypeClass, c) - #for i in 0..<x.len: result.rawAddSon(x[i]) + result = newTypeS(tyCompositeTypeClass, c) + result.rawAddSon paramType + result.rawAddSon x result = addImplicitGeneric(c, result, paramTypId, info, genericParams, paramName) of tyGenericInst: @@ -1353,7 +1353,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, # which will prevent other types from matching - clearly a very # surprising behavior. We must instead fix the expected type of # the proc to be the unbound typedesc type: - typ = newTypeWithSons(c, tyTypeDesc, @[newTypeS(tyNone, c)]) + typ = newTypeS(tyTypeDesc, c, newTypeS(tyNone, c)) typ.flags.incl tfCheckedForDestructor else: @@ -1509,7 +1509,7 @@ proc trySemObjectTypeForInheritedGenericInst(c: PContext, n: PNode, t: PType): b check = initIntSet() pos = 0 let - realBase = t[0] + realBase = t.baseClass base = skipTypesOrNil(realBase, skipPtrs) result = true if base.isNil: @@ -1693,8 +1693,8 @@ proc semTypeClass(c: PContext, n: PNode, prev: PType): PType = inherited = n[2] var owner = getCurrOwner(c) - var candidateTypeSlot = newTypeWithSons(owner, tyAlias, @[c.errorType], c.idgen) - result = newOrPrevType(tyUserTypeClass, prev, c, sons = @[candidateTypeSlot]) + var candidateTypeSlot = newTypeS(tyAlias, c, c.errorType) + result = newOrPrevType(tyUserTypeClass, prev, c, son = candidateTypeSlot) result.flags.incl tfCheckedForDestructor result.n = n @@ -1857,7 +1857,7 @@ proc semTypeIdent(c: PContext, n: PNode): PSym = # it's not bound when it's used multiple times in the # proc signature for example if c.inGenericInst > 0: - let bound = result.typ[0].sym + let bound = result.typ.elementType.sym if bound != nil: return bound return result if result.typ.sym == nil: @@ -2296,7 +2296,7 @@ proc processMagicType(c: PContext, m: PSym) = else: localError(c.config, m.info, errTypeExpected) proc semGenericConstraints(c: PContext, x: PType): PType = - result = newTypeWithSons(c, tyGenericParam, @[x]) + result = newTypeS(tyGenericParam, c, x) proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode = @@ -2322,8 +2322,8 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode = typ = semTypeNode(c, constraint, nil) if typ.kind != tyStatic or typ.len == 0: if typ.kind == tyTypeDesc: - if typ[0].kind == tyNone: - typ = newTypeWithSons(c, tyTypeDesc, @[newTypeS(tyNone, c)]) + if typ.elementType.kind == tyNone: + typ = newTypeS(tyTypeDesc, c, newTypeS(tyNone, c)) incl typ.flags, tfCheckedForDestructor else: typ = semGenericConstraints(c, typ) @@ -2332,7 +2332,7 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode = def = semConstExpr(c, def) if typ == nil: if def.typ.kind != tyTypeDesc: - typ = newTypeWithSons(c, tyStatic, @[def.typ]) + typ = newTypeS(tyStatic, c, def.typ) else: # the following line fixes ``TV2*[T:SomeNumber=TR] = array[0..1, T]`` # from manyloc/named_argument_bug/triengine: diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim index b514cc8fa..58d684a8f 100644 --- a/compiler/semtypinst.nim +++ b/compiler/semtypinst.nim @@ -343,7 +343,7 @@ proc instCopyType*(cl: var TReplTypeVars, t: PType): PType = proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType = # tyGenericInvocation[A, tyGenericInvocation[A, B]] # is difficult to handle: - var body = t[0] + var body = t.genericHead if body.kind != tyGenericBody: internalError(cl.c.config, cl.info, "no generic body") var header = t @@ -379,7 +379,7 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType = else: header = instCopyType(cl, t) - result = newType(tyGenericInst, cl.c.idgen, t[0].owner, sons = @[header[0]]) + result = newType(tyGenericInst, cl.c.idgen, t.genericHead.owner, son = header.genericHead) result.flags = header.flags # be careful not to propagate unnecessary flags here (don't use rawAddSon) # ugh need another pass for deeply recursive generic types (e.g. PActor) @@ -469,8 +469,8 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType = proc eraseVoidParams*(t: PType) = # transform '(): void' into '()' because old parts of the compiler really # don't deal with '(): void': - if t[0] != nil and t[0].kind == tyVoid: - t[0] = nil + if t.returnType != nil and t.returnType.kind == tyVoid: + t.setReturnType nil for i in 1..<t.len: # don't touch any memory unless necessary @@ -496,8 +496,8 @@ proc skipIntLiteralParams*(t: PType; idgen: IdGenerator) = # when the typeof operator is used on a static input # param, the results gets infected with static as well: - if t[0] != nil and t[0].kind == tyStatic: - t[0] = t[0].base + if t.returnType != nil and t.returnType.kind == tyStatic: + t.setReturnType t.returnType.skipModifier proc propagateFieldFlags(t: PType, n: PNode) = # This is meant for objects and tuples @@ -585,7 +585,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType = # return tyStatic values to let anyone make # use of this knowledge. The patching here # won't be necessary then. - result = newTypeS(tyStatic, cl.c, sons = @[n.typ]) + result = newTypeS(tyStatic, cl.c, son = n.typ) result.n = n else: result = n.typ @@ -601,8 +601,8 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType = result = makeTypeDesc(cl.c, result) elif tfUnresolved in t.flags or cl.skipTypedesc: result = result.base - elif t[0].kind != tyNone: - result = makeTypeDesc(cl.c, replaceTypeVarsT(cl, t[0])) + elif t.elementType.kind != tyNone: + result = makeTypeDesc(cl.c, replaceTypeVarsT(cl, t.elementType)) of tyUserTypeClass, tyStatic: result = t @@ -667,8 +667,8 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType = result = t # Slow path, we have some work to do - if t.kind == tyRef and t.len > 0 and t[0].kind == tyObject and t[0].n != nil: - discard replaceObjBranches(cl, t[0].n) + if t.kind == tyRef and t.len > 0 and t.elementType.kind == tyObject and t.elementType.n != nil: + discard replaceObjBranches(cl, t.elementType.n) elif result.n != nil and t.kind == tyObject: # Invalidate the type size as we may alter its structure @@ -703,8 +703,8 @@ when false: popInfoContext(p.config) proc recomputeFieldPositions*(t: PType; obj: PNode; currPosition: var int) = - if t != nil and t.len > 0 and t[0] != nil: - let b = skipTypes(t[0], skipPtrs) + if t != nil and t.len > 0 and t.baseClass != nil: + let b = skipTypes(t.baseClass, skipPtrs) recomputeFieldPositions(b, b.n, currPosition) case obj.kind of nkRecList: diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 1cfb630e3..38cc66637 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -361,7 +361,7 @@ proc concreteType(c: TCandidate, t: PType; f: PType = nil): PType = if c.isNoCall: result = t else: result = nil of tySequence, tySet: - if t[0].kind == tyEmpty: result = nil + if t.elementType.kind == tyEmpty: result = nil else: result = t of tyGenericParam, tyAnything, tyConcept: result = t @@ -512,7 +512,7 @@ proc isObjectSubtype(c: var TCandidate; a, f, fGenericOrigin: PType): int = while t != nil and not sameObjectTypes(f, t): if t.kind != tyObject: # avoid entering generic params etc return -1 - t = t[0] + t = t.baseClass if t == nil: break last = t t = skipTypes(t, skipPtrs) @@ -563,7 +563,7 @@ proc isGenericSubtype(c: var TCandidate; a, f: PType, d: var int, fGenericOrigin # XXX sameObjectType can return false here. Need to investigate # why that is but sameObjectType does way too much work here anyway. while t != nil and r.sym != t.sym and askip == fskip: - t = t[0] + t = t.baseClass if t == nil: break last = t t = t.skipToObject(askip) @@ -787,7 +787,7 @@ proc matchUserTypeClass*(m: var TCandidate; ff, a: PType): PType = else: param = paramSym skType param.typ = if typ.isMetaType: - c.newTypeWithSons(tyInferred, @[typ]) + newTypeS(tyInferred, c, typ) else: makeTypeDesc(c, typ) @@ -941,7 +941,7 @@ proc inferStaticParam*(c: var TCandidate, lhs: PNode, rhs: BiggestInt): bool = else: discard elif lhs.kind == nkSym and lhs.typ.kind == tyStatic and lhs.typ.n == nil: - var inferred = newTypeWithSons(c.c, tyStatic, @[lhs.typ.elementType]) + var inferred = newTypeS(tyStatic, c.c, lhs.typ.elementType) inferred.n = newIntNode(nkIntLit, rhs) put(c, lhs.typ, inferred) if c.c.matchedConcept != nil: @@ -1868,7 +1868,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, typeRel(c, f.last, aOrig.n.typ, flags) else: isGeneric if result != isNone: - var boundType = newTypeWithSons(c.c, tyStatic, @[aOrig.n.typ]) + var boundType = newTypeS(tyStatic, c.c, aOrig.n.typ) boundType.n = aOrig.n put(c, f, boundType) else: @@ -2004,7 +2004,7 @@ proc implicitConv(kind: TNodeKind, f: PType, arg: PNode, m: TCandidate, if result.typ == nil: internalError(c.graph.config, arg.info, "implicitConv") result.add c.graph.emptyNode if arg.typ != nil and arg.typ.kind == tyLent: - let a = newNodeIT(nkHiddenDeref, arg.info, arg.typ[0]) + let a = newNodeIT(nkHiddenDeref, arg.info, arg.typ.elementType) a.add arg result.add a else: @@ -2117,8 +2117,8 @@ proc incMatches(m: var TCandidate; r: TTypeRelation; convMatch = 1) = of isNone: discard template matchesVoidProc(t: PType): bool = - (t.kind == tyProc and t.len == 1 and t[0] == nil) or - (t.kind == tyBuiltInTypeClass and t[0].kind == tyProc) + (t.kind == tyProc and t.len == 1 and t.returnType == nil) or + (t.kind == tyBuiltInTypeClass and t.elementType.kind == tyProc) proc paramTypesMatchAux(m: var TCandidate, f, a: PType, argSemantized, argOrig: PNode): PNode = @@ -2151,7 +2151,7 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType, if evaluated != nil: # Don't build the type in-place because `evaluated` and `arg` may point # to the same object and we'd end up creating recursive types (#9255) - let typ = newTypeS(tyStatic, c, sons = @[evaluated.typ]) + let typ = newTypeS(tyStatic, c, son = evaluated.typ) typ.n = evaluated arg = copyTree(arg) # fix #12864 arg.typ = typ @@ -2456,7 +2456,7 @@ proc arrayConstr(c: PContext, info: TLineInfo): PType = proc incrIndexType(t: PType) = assert t.kind == tyArray - inc t[0].n[1].intVal + inc t.indexType.n[1].intVal template isVarargsUntyped(x): untyped = x.kind == tyVarargs and x[0].kind == tyUntyped diff --git a/compiler/spawn.nim b/compiler/spawn.nim index b140729a8..972d49d3e 100644 --- a/compiler/spawn.nim +++ b/compiler/spawn.nim @@ -16,7 +16,7 @@ from trees import getMagic, getRoot proc callProc(a: PNode): PNode = result = newNodeI(nkCall, a.info) result.add a - result.typ = a.typ[0] + result.typ = a.typ.returnType # we have 4 cases to consider: # - a void proc --> nothing to do @@ -141,10 +141,10 @@ proc createWrapperProc(g: ModuleGraph; f: PNode; threadParam, argsParam: PSym; if spawnKind == srByVar: body.add newAsgnStmt(genDeref(threadLocalProm.newSymNode), call) elif fv != nil: - let fk = flowVarKind(g.config, fv.typ[1]) + let fk = flowVarKind(g.config, fv.typ.firstGenericParam) if fk == fvInvalid: localError(g.config, f.info, "cannot create a flowVar of type: " & - typeToString(fv.typ[1])) + typeToString(fv.typ.firstGenericParam)) body.add newAsgnStmt(indirectAccess(threadLocalProm.newSymNode, if fk == fvGC: "data" else: "blob", fv.info, g.cache), call) if fk == fvGC: @@ -193,7 +193,7 @@ proc createCastExpr(argsParam: PSym; objType: PType; idgen: IdGenerator): PNode result.typ.rawAddSon(objType) template checkMagicProcs(g: ModuleGraph, n: PNode, formal: PNode) = - if (formal.typ.kind == tyVarargs and formal.typ[0].kind in {tyTyped, tyUntyped}) or + if (formal.typ.kind == tyVarargs and formal.typ.elementType.kind in {tyTyped, tyUntyped}) or formal.typ.kind in {tyTyped, tyUntyped}: localError(g.config, n.info, "'spawn'ed function cannot have a 'typed' or 'untyped' parameter") diff --git a/compiler/suggest.nim b/compiler/suggest.nim index 802da1c3e..4f90fe00b 100644 --- a/compiler/suggest.nim +++ b/compiler/suggest.nim @@ -327,7 +327,7 @@ proc fieldVisible*(c: PContext, f: PSym): bool {.inline.} = proc getQuality(s: PSym): range[0..100] = result = 100 if s.typ != nil and s.typ.len > 1: - var exp = s.typ[1].skipTypes({tyGenericInst, tyVar, tyLent, tyAlias, tySink}) + var exp = s.typ.firstParamType.skipTypes({tyGenericInst, tyVar, tyLent, tyAlias, tySink}) if exp.kind == tyVarargs: exp = elemType(exp) if exp.kind in {tyUntyped, tyTyped, tyGenericParam, tyAnything}: result = 50 @@ -396,17 +396,17 @@ proc suggestVar(c: PContext, n: PNode, outputs: var Suggestions) = wholeSymTab(nameFits(c, it, n), ideCon) proc typeFits(c: PContext, s: PSym, firstArg: PType): bool {.inline.} = - if s.typ != nil and s.typ.len > 1 and s.typ[1] != nil: + if s.typ != nil and s.typ.len > 1 and s.typ.firstParamType != nil: # special rule: if system and some weird generic match via 'tyUntyped' # or 'tyGenericParam' we won't list it either to reduce the noise (nobody # wants 'system.`-|` as suggestion let m = s.getModule() if m != nil and sfSystemModule in m.flags: if s.kind == skType: return - var exp = s.typ[1].skipTypes({tyGenericInst, tyVar, tyLent, tyAlias, tySink}) + var exp = s.typ.firstParamType.skipTypes({tyGenericInst, tyVar, tyLent, tyAlias, tySink}) if exp.kind == tyVarargs: exp = elemType(exp) if exp.kind in {tyUntyped, tyTyped, tyGenericParam, tyAnything}: return - result = sigmatch.argtypeMatches(c, s.typ[1], firstArg) + result = sigmatch.argtypeMatches(c, s.typ.firstParamType, firstArg) else: result = false @@ -476,13 +476,13 @@ proc suggestFieldAccess(c: PContext, n, field: PNode, outputs: var Suggestions) var t = typ while t != nil: suggestSymList(c, t.n, field, n.info, outputs) - t = t[0] + t = t.baseClass elif typ.kind == tyObject: var t = typ while true: suggestObject(c, t.n, field, n.info, outputs) - if t[0] == nil: break - t = skipTypes(t[0], skipPtrs) + if t.baseClass == nil: break + t = skipTypes(t.baseClass, skipPtrs) elif typ.kind == tyTuple and typ.n != nil: # All tuple fields are in scope # So go through each field and add it to the suggestions (If it passes the filter) @@ -761,11 +761,11 @@ proc suggestPragmas*(c: PContext, n: PNode) = # Now show suggestions for user pragmas for pragma in c.userPragmas: - var pm = default(PrefixMatch) - if filterSym(pragma, n, pm): - outputs &= symToSuggest(c.graph, pragma, isLocal=true, ideSug, info, - pragma.getQuality, pm, c.inTypeContext > 0, 0, - extractDocs=false) + var pm = default(PrefixMatch) + if filterSym(pragma, n, pm): + outputs &= symToSuggest(c.graph, pragma, isLocal=true, ideSug, info, + pragma.getQuality, pm, c.inTypeContext > 0, 0, + extractDocs=false) produceOutput(outputs, c.config) if outputs.len > 0: diff --git a/compiler/typeallowed.nim b/compiler/typeallowed.nim index e82de29f3..04dbc69c5 100644 --- a/compiler/typeallowed.nim +++ b/compiler/typeallowed.nim @@ -73,7 +73,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind, elif isOutParam(t) and kind != skParam: result = t else: - var t2 = skipTypes(t[0], abstractInst-{tyTypeDesc, tySink}) + var t2 = skipTypes(t.elementType, abstractInst-{tyTypeDesc, tySink}) case t2.kind of tyVar, tyLent: if taHeap notin flags: result = t2 # ``var var`` is illegal on the heap @@ -99,8 +99,8 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind, for i in 1..<t.len: if result != nil: break result = typeAllowedAux(marker, t[i], skParam, c, f-{taIsOpenArray}) - if result.isNil and t[0] != nil: - result = typeAllowedAux(marker, t[0], skResult, c, flags) + if result.isNil and t.returnType != nil: + result = typeAllowedAux(marker, t.returnType, skResult, c, flags) of tyTypeDesc: if kind in {skVar, skLet, skConst} and taProcContextIsNotMacro in flags: result = t @@ -142,13 +142,13 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind, if (kind != skParam or taIsOpenArray in flags) and views notin c.features: result = t else: - result = typeAllowedAux(marker, t[0], kind, c, flags+{taIsOpenArray}) + result = typeAllowedAux(marker, t.elementType, kind, c, flags+{taIsOpenArray}) of tyVarargs: # you cannot nest openArrays/sinks/etc. if kind != skParam or taIsOpenArray in flags: result = t else: - result = typeAllowedAux(marker, t[0], kind, c, flags+{taIsOpenArray}) + result = typeAllowedAux(marker, t.elementType, kind, c, flags+{taIsOpenArray}) of tySink: # you cannot nest openArrays/sinks/etc. if kind != skParam or taIsOpenArray in flags or t.elementType.kind in {tySink, tyLent, tyVar}: @@ -164,7 +164,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind, if t.elementType.kind != tyEmpty: result = typeAllowedAux(marker, t.elementType, kind, c, flags+{taHeap}) elif kind in {skVar, skLet}: - result = t[0] + result = t.elementType of tyArray: if t.elementType.kind == tyTypeDesc: result = t.elementType @@ -178,9 +178,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind, of tyPtr: result = typeAllowedAux(marker, t.elementType, kind, c, flags+{taHeap}) of tySet: - for i in 0..<t.len: - result = typeAllowedAux(marker, t[i], kind, c, flags) - if result != nil: break + result = typeAllowedAux(marker, t.elementType, kind, c, flags) of tyObject, tyTuple: if kind in {skProc, skFunc, skConst} and t.kind == tyObject and t.baseClass != nil and taIsDefaultField notin flags: @@ -199,7 +197,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind, # prevent cascading errors: result = nil of tyOwned: - if t.len == 1 and t[0].skipTypes(abstractInst).kind in {tyRef, tyPtr, tyProc}: + if t.len == 1 and t.skipModifier.skipTypes(abstractInst).kind in {tyRef, tyPtr, tyProc}: result = typeAllowedAux(marker, t.skipModifier, kind, c, flags+{taHeap}) else: result = t diff --git a/compiler/types.nim b/compiler/types.nim index 8166db6ae..eef85f36a 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -110,8 +110,8 @@ proc invalidGenericInst*(f: PType): bool = proc isPureObject*(typ: PType): bool = var t = typ - while t.kind == tyObject and t[0] != nil: - t = t[0].skipTypes(skipPtrs) + while t.kind == tyObject and t.baseClass != nil: + t = t.baseClass.skipTypes(skipPtrs) result = t.sym != nil and sfPure in t.sym.flags proc isUnsigned*(t: PType): bool = @@ -272,8 +272,8 @@ proc searchTypeForAux(t: PType, predicate: TTypePredicate, if result: return case t.kind of tyObject: - if t[0] != nil: - result = searchTypeForAux(t[0].skipTypes(skipPtrs), predicate, marker) + if t.baseClass != nil: + result = searchTypeForAux(t.baseClass.skipTypes(skipPtrs), predicate, marker) if not result: result = searchTypeNodeForAux(t.n, predicate, marker) of tyGenericInst, tyDistinct, tyAlias, tySink: result = searchTypeForAux(skipModifier(t), predicate, marker) @@ -295,7 +295,7 @@ proc containsObject*(t: PType): bool = result = searchTypeFor(t, isObjectPredicate) proc isObjectWithTypeFieldPredicate(t: PType): bool = - result = t.kind == tyObject and t[0] == nil and + result = t.kind == tyObject and t.baseClass == nil and not (t.sym != nil and {sfPure, sfInfixCall} * t.sym.flags != {}) and tfFinal notin t.flags @@ -548,8 +548,8 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string = result = t.sym.name.s else: result = t.sym.name.s & " literal(" & $t.n.intVal & ")" - elif t.kind == tyAlias and t[0].kind != tyAlias: - result = typeToString(t[0]) + elif t.kind == tyAlias and t.elementType.kind != tyAlias: + result = typeToString(t.elementType) elif prefer in {preferResolved, preferMixed}: case t.kind of IntegralTypes + {tyFloat..tyFloat128} + {tyString, tyCstring}: @@ -590,13 +590,13 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string = else: result = "int literal(" & $t.n.intVal & ")" of tyGenericInst, tyGenericInvocation: - result = typeToString(t[0]) & '[' + result = typeToString(t.genericHead) & '[' for i in 1..<t.len-ord(t.kind != tyGenericInvocation): if i > 1: result.add(", ") result.add(typeToString(t[i], preferGenericArg)) result.add(']') of tyGenericBody: - result = typeToString(t.last) & '[' + result = typeToString(t.typeBodyImpl) & '[' for i in 0..<t.len-1: if i > 0: result.add(", ") result.add(typeToString(t[i], preferTypeName)) @@ -881,8 +881,8 @@ proc lastOrd*(conf: ConfigRef; t: PType): Int128 = case t.kind of tyBool: result = toInt128(1'u) of tyChar: result = toInt128(255'u) - of tySet, tyVar: result = lastOrd(conf, t[0]) - of tyArray: result = lastOrd(conf, t[0]) + of tySet, tyVar: result = lastOrd(conf, t.elementType) + of tyArray: result = lastOrd(conf, t.indexType) of tyRange: assert(t.n != nil) # range directly given: assert(t.n.kind == nkRange) @@ -1810,8 +1810,8 @@ proc isException*(t: PType): bool = var t = t.skipTypes(abstractInst) while t.kind == tyObject: if t.sym != nil and t.sym.magic == mException: return true - if t[0] == nil: break - t = skipTypes(t[0], abstractPtrs) + if t.baseClass == nil: break + t = skipTypes(t.baseClass, abstractPtrs) return false proc isDefectException*(t: PType): bool = diff --git a/compiler/varpartitions.nim b/compiler/varpartitions.nim index 957497bb6..44d38ebff 100644 --- a/compiler/varpartitions.nim +++ b/compiler/varpartitions.nim @@ -407,8 +407,8 @@ proc allRoots(n: PNode; result: var seq[(PSym, int)]; level: int) = if typ != nil and i < typ.len: assert(typ.n[i].kind == nkSym) let paramType = typ.n[i].typ - if not paramType.isCompileTimeOnly and not typ[0].isEmptyType and - canAlias(paramType, typ[0]): + if not paramType.isCompileTimeOnly and not typ.returnType.isEmptyType and + canAlias(paramType, typ.returnType): allRoots(it, result, RootEscapes) else: allRoots(it, result, RootEscapes) diff --git a/compiler/vm.nim b/compiler/vm.nim index 1584b2893..6b00ff9d3 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -507,7 +507,7 @@ proc setLenSeq(c: PCtx; node: PNode; newLen: int; info: TLineInfo) = setLen(node.sons, newLen) if oldLen < newLen: for i in oldLen..<newLen: - node[i] = getNullValue(typ[0], info, c.config) + node[i] = getNullValue(typ.elementType, info, c.config) const errNilAccess = "attempt to access a nil address" diff --git a/compiler/vmdeps.nim b/compiler/vmdeps.nim index d85caa281..b58ae109f 100644 --- a/compiler/vmdeps.nim +++ b/compiler/vmdeps.nim @@ -107,19 +107,19 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo; of tyUncheckedArray: result = newNodeIT(nkBracketExpr, if t.n.isNil: info else: t.n.info, t) result.add atomicType("UncheckedArray", mUncheckedArray) - result.add mapTypeToAst(t[0], info) + result.add mapTypeToAst(t.elementType, info) of tyArray: result = newNodeIT(nkBracketExpr, if t.n.isNil: info else: t.n.info, t) result.add atomicType("array", mArray) - if inst and t[0].kind == tyRange: + if inst and t.indexType.kind == tyRange: var rng = newNodeX(nkInfix) rng.add newIdentNode(getIdent(cache, ".."), info) - rng.add t[0].n[0].copyTree - rng.add t[0].n[1].copyTree + rng.add t.indexType.n[0].copyTree + rng.add t.indexType.n[1].copyTree result.add rng else: - result.add mapTypeToAst(t[0], info) - result.add mapTypeToAst(t[1], info) + result.add mapTypeToAst(t.indexType, info) + result.add mapTypeToAst(t.elementType, info) of tyTypeDesc: if t.base != nil: result = newNodeIT(nkBracketExpr, if t.n.isNil: info else: t.n.info, t) @@ -140,7 +140,7 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo; else: result = newNodeX(nkBracketExpr) #result.add mapTypeToAst(t.last, info) - result.add mapTypeToAst(t[0], info) + result.add mapTypeToAst(t.genericHead, info) for i in 1..<t.len-1: result.add mapTypeToAst(t[i], info) else: @@ -174,11 +174,11 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo; if objectDef.kind == nkRefTy: objectDef = objectDef[0] result.add objectDef[0].copyTree # copy object pragmas - if t[0] == nil: + if t.baseClass == nil: result.add newNodeI(nkEmpty, info) else: # handle parent object var nn = newNodeX(nkOfInherit) - nn.add mapTypeToAst(t[0], info) + nn.add mapTypeToAst(t.baseClass, info) result.add nn if t.n.len > 0: result.add objectNode(cache, t.n, idgen) @@ -217,19 +217,19 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo; of tyPtr: if inst: result = newNodeX(nkPtrTy) - result.add mapTypeToAst(t[0], info) + result.add mapTypeToAst(t.elementType, info) else: result = mapTypeToBracket("ptr", mPtr, t, info) of tyRef: if inst: result = newNodeX(nkRefTy) - result.add mapTypeToAst(t[0], info) + result.add mapTypeToAst(t.elementType, info) else: result = mapTypeToBracket("ref", mRef, t, info) of tyVar: if inst: result = newNodeX(nkVarTy) - result.add mapTypeToAst(t[0], info) + result.add mapTypeToAst(t.elementType, info) else: result = mapTypeToBracket("var", mVar, t, info) of tyLent: result = mapTypeToBracket("lent", mBuiltinType, t, info) @@ -239,10 +239,10 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo; if inst: result = newNodeX(nkProcTy) var fp = newNodeX(nkFormalParams) - if t[0] == nil: + if t.returnType == nil: fp.add newNodeI(nkEmpty, info) else: - fp.add mapTypeToAst(t[0], t.n[0].info) + fp.add mapTypeToAst(t.returnType, t.n[0].info) for i in 1..<t.len: fp.add newIdentDefs(t.n[i], t[i]) result.add fp diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index 7ef231f57..9667daa3d 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -2053,7 +2053,7 @@ proc genObjConstr(c: PCtx, n: PNode, dest: var TDest) = if dest < 0: dest = c.getTemp(n.typ) let t = n.typ.skipTypes(abstractRange+{tyOwned}-{tyTypeDesc}) if t.kind == tyRef: - c.gABx(n, opcNew, dest, c.genType(t[0])) + c.gABx(n, opcNew, dest, c.genType(t.elementType)) else: c.gABx(n, opcLdNull, dest, c.genType(n.typ)) for i in 1..<n.len: diff --git a/compiler/vtables.nim b/compiler/vtables.nim index eeacc7b47..b9b13badc 100644 --- a/compiler/vtables.nim +++ b/compiler/vtables.nim @@ -1,167 +1,167 @@ -import ast, modulegraphs, magicsys, lineinfos, options, cgmeth, types -import std/[algorithm, tables, intsets, assertions] - - - -proc genVTableDispatcher(g: ModuleGraph; methods: seq[PSym]; index: int): PSym = -#[ -proc dispatch(x: Base, params: ...) = - cast[proc bar(x: Base, params: ...)](x.vTable[index])(x, params) -]# - var base = methods[0].ast[dispatcherPos].sym - result = base - var paramLen = base.typ.len - var body = newNodeI(nkStmtList, base.info) - - var disp = newNodeI(nkIfStmt, base.info) - - var vTableAccess = newNodeIT(nkBracketExpr, base.info, base.typ) - let nimGetVTableSym = getCompilerProc(g, "nimGetVTable") - let ptrPNimType = nimGetVTableSym.typ.n[1].sym.typ - - var nTyp = base.typ.n[1].sym.typ - var dispatchObject = newSymNode(base.typ.n[1].sym) - if nTyp.kind == tyObject: - dispatchObject = newTree(nkAddr, dispatchObject) - else: - if g.config.backend != backendCpp: # TODO: maybe handle ptr? - if nTyp.kind == tyVar and nTyp.skipTypes({tyVar}).kind != tyObject: - dispatchObject = newTree(nkDerefExpr, dispatchObject) - - var getVTableCall = newTree(nkCall, - newSymNode(nimGetVTableSym), - dispatchObject, - newIntNode(nkIntLit, index) - ) - getVTableCall.typ = base.typ - var vTableCall = newNodeIT(nkCall, base.info, base.typ[0]) - var castNode = newTree(nkCast, - newNodeIT(nkType, base.info, base.typ), - getVTableCall) - - castNode.typ = base.typ - vTableCall.add castNode - for col in 1..<paramLen: - let param = base.typ.n[col].sym - vTableCall.add newSymNode(param) - - var ret: PNode - if base.typ[0] != nil: - var a = newNodeI(nkFastAsgn, base.info) - a.add newSymNode(base.ast[resultPos].sym) - a.add vTableCall - ret = newNodeI(nkReturnStmt, base.info) - ret.add a - else: - ret = vTableCall - - if base.typ.n[1].sym.typ.skipTypes(abstractInst).kind in {tyRef, tyPtr}: - let ifBranch = newNodeI(nkElifBranch, base.info) - let boolType = getSysType(g, unknownLineInfo, tyBool) - var isNil = getSysMagic(g, unknownLineInfo, "isNil", mIsNil) - let checkSelf = newNodeIT(nkCall, base.info, boolType) - checkSelf.add newSymNode(isNil) - checkSelf.add newSymNode(base.typ.n[1].sym) - ifBranch.add checkSelf - ifBranch.add newTree(nkCall, - newSymNode(getCompilerProc(g, "chckNilDisp")), newSymNode(base.typ.n[1].sym)) - let elseBranch = newTree(nkElifBranch, ret) - disp.add ifBranch - disp.add elseBranch - else: - disp = ret - - body.add disp - body.flags.incl nfTransf # should not be further transformed - result.ast[bodyPos] = body - -proc containGenerics(base: PType, s: seq[tuple[depth: int, value: PType]]): bool = - result = tfHasMeta in base.flags - for i in s: - if tfHasMeta in i.value.flags: - result = true - break - -proc collectVTableDispatchers*(g: ModuleGraph) = - var itemTable = initTable[ItemId, seq[LazySym]]() - var rootTypeSeq = newSeq[PType]() - var rootItemIdCount = initCountTable[ItemId]() - for bucket in 0..<g.methods.len: - var relevantCols = initIntSet() - if relevantCol(g.methods[bucket].methods, 1): incl(relevantCols, 1) - sortBucket(g.methods[bucket].methods, relevantCols) - let base = g.methods[bucket].methods[^1] - let baseType = base.typ.firstParamType.skipTypes(skipPtrs-{tyTypeDesc}) - if baseType.itemId in g.objectTree and not containGenerics(baseType, g.objectTree[baseType.itemId]): - let methodIndexLen = g.bucketTable[baseType.itemId] - if baseType.itemId notin itemTable: # once is enough - rootTypeSeq.add baseType - itemTable[baseType.itemId] = newSeq[LazySym](methodIndexLen) - - sort(g.objectTree[baseType.itemId], cmp = proc (x, y: tuple[depth: int, value: PType]): int = - if x.depth >= y.depth: 1 - else: -1 - ) - - for item in g.objectTree[baseType.itemId]: - if item.value.itemId notin itemTable: - itemTable[item.value.itemId] = newSeq[LazySym](methodIndexLen) - - var mIndex = 0 # here is the correpsonding index - if baseType.itemId notin rootItemIdCount: - rootItemIdCount[baseType.itemId] = 1 - else: - mIndex = rootItemIdCount[baseType.itemId] - rootItemIdCount.inc(baseType.itemId) - for idx in 0..<g.methods[bucket].methods.len: - let obj = g.methods[bucket].methods[idx].typ.firstParamType.skipTypes(skipPtrs) - itemTable[obj.itemId][mIndex] = LazySym(sym: g.methods[bucket].methods[idx]) - g.addDispatchers genVTableDispatcher(g, g.methods[bucket].methods, mIndex) - else: # if the base object doesn't have this method - g.addDispatchers genIfDispatcher(g, g.methods[bucket].methods, relevantCols, g.idgen) - -proc sortVTableDispatchers*(g: ModuleGraph) = - var itemTable = initTable[ItemId, seq[LazySym]]() - var rootTypeSeq = newSeq[ItemId]() - var rootItemIdCount = initCountTable[ItemId]() - for bucket in 0..<g.methods.len: - var relevantCols = initIntSet() - if relevantCol(g.methods[bucket].methods, 1): incl(relevantCols, 1) - sortBucket(g.methods[bucket].methods, relevantCols) - let base = g.methods[bucket].methods[^1] - let baseType = base.typ.firstParamType.skipTypes(skipPtrs-{tyTypeDesc}) - if baseType.itemId in g.objectTree and not containGenerics(baseType, g.objectTree[baseType.itemId]): - let methodIndexLen = g.bucketTable[baseType.itemId] - if baseType.itemId notin itemTable: # once is enough - rootTypeSeq.add baseType.itemId - itemTable[baseType.itemId] = newSeq[LazySym](methodIndexLen) - - sort(g.objectTree[baseType.itemId], cmp = proc (x, y: tuple[depth: int, value: PType]): int = - if x.depth >= y.depth: 1 - else: -1 - ) - - for item in g.objectTree[baseType.itemId]: - if item.value.itemId notin itemTable: - itemTable[item.value.itemId] = newSeq[LazySym](methodIndexLen) - - var mIndex = 0 # here is the correpsonding index - if baseType.itemId notin rootItemIdCount: - rootItemIdCount[baseType.itemId] = 1 - else: - mIndex = rootItemIdCount[baseType.itemId] - rootItemIdCount.inc(baseType.itemId) - for idx in 0..<g.methods[bucket].methods.len: - let obj = g.methods[bucket].methods[idx].typ.firstParamType.skipTypes(skipPtrs) - itemTable[obj.itemId][mIndex] = LazySym(sym: g.methods[bucket].methods[idx]) - - for baseType in rootTypeSeq: - g.setMethodsPerType(baseType, itemTable[baseType]) - for item in g.objectTree[baseType]: - let typ = item.value.skipTypes(skipPtrs) - let idx = typ.itemId - for mIndex in 0..<itemTable[idx].len: - if itemTable[idx][mIndex].sym == nil: - let parentIndex = typ[0].skipTypes(skipPtrs).itemId - itemTable[idx][mIndex] = itemTable[parentIndex][mIndex] - g.setMethodsPerType(idx, itemTable[idx]) +import ast, modulegraphs, magicsys, lineinfos, options, cgmeth, types +import std/[algorithm, tables, intsets, assertions] + + + +proc genVTableDispatcher(g: ModuleGraph; methods: seq[PSym]; index: int): PSym = +#[ +proc dispatch(x: Base, params: ...) = + cast[proc bar(x: Base, params: ...)](x.vTable[index])(x, params) +]# + var base = methods[0].ast[dispatcherPos].sym + result = base + var paramLen = base.typ.len + var body = newNodeI(nkStmtList, base.info) + + var disp = newNodeI(nkIfStmt, base.info) + + var vTableAccess = newNodeIT(nkBracketExpr, base.info, base.typ) + let nimGetVTableSym = getCompilerProc(g, "nimGetVTable") + let ptrPNimType = nimGetVTableSym.typ.n[1].sym.typ + + var nTyp = base.typ.n[1].sym.typ + var dispatchObject = newSymNode(base.typ.n[1].sym) + if nTyp.kind == tyObject: + dispatchObject = newTree(nkAddr, dispatchObject) + else: + if g.config.backend != backendCpp: # TODO: maybe handle ptr? + if nTyp.kind == tyVar and nTyp.skipTypes({tyVar}).kind != tyObject: + dispatchObject = newTree(nkDerefExpr, dispatchObject) + + var getVTableCall = newTree(nkCall, + newSymNode(nimGetVTableSym), + dispatchObject, + newIntNode(nkIntLit, index) + ) + getVTableCall.typ = base.typ + var vTableCall = newNodeIT(nkCall, base.info, base.typ.returnType) + var castNode = newTree(nkCast, + newNodeIT(nkType, base.info, base.typ), + getVTableCall) + + castNode.typ = base.typ + vTableCall.add castNode + for col in 1..<paramLen: + let param = base.typ.n[col].sym + vTableCall.add newSymNode(param) + + var ret: PNode + if base.typ.returnType != nil: + var a = newNodeI(nkFastAsgn, base.info) + a.add newSymNode(base.ast[resultPos].sym) + a.add vTableCall + ret = newNodeI(nkReturnStmt, base.info) + ret.add a + else: + ret = vTableCall + + if base.typ.n[1].sym.typ.skipTypes(abstractInst).kind in {tyRef, tyPtr}: + let ifBranch = newNodeI(nkElifBranch, base.info) + let boolType = getSysType(g, unknownLineInfo, tyBool) + var isNil = getSysMagic(g, unknownLineInfo, "isNil", mIsNil) + let checkSelf = newNodeIT(nkCall, base.info, boolType) + checkSelf.add newSymNode(isNil) + checkSelf.add newSymNode(base.typ.n[1].sym) + ifBranch.add checkSelf + ifBranch.add newTree(nkCall, + newSymNode(getCompilerProc(g, "chckNilDisp")), newSymNode(base.typ.n[1].sym)) + let elseBranch = newTree(nkElifBranch, ret) + disp.add ifBranch + disp.add elseBranch + else: + disp = ret + + body.add disp + body.flags.incl nfTransf # should not be further transformed + result.ast[bodyPos] = body + +proc containGenerics(base: PType, s: seq[tuple[depth: int, value: PType]]): bool = + result = tfHasMeta in base.flags + for i in s: + if tfHasMeta in i.value.flags: + result = true + break + +proc collectVTableDispatchers*(g: ModuleGraph) = + var itemTable = initTable[ItemId, seq[LazySym]]() + var rootTypeSeq = newSeq[PType]() + var rootItemIdCount = initCountTable[ItemId]() + for bucket in 0..<g.methods.len: + var relevantCols = initIntSet() + if relevantCol(g.methods[bucket].methods, 1): incl(relevantCols, 1) + sortBucket(g.methods[bucket].methods, relevantCols) + let base = g.methods[bucket].methods[^1] + let baseType = base.typ.firstParamType.skipTypes(skipPtrs-{tyTypeDesc}) + if baseType.itemId in g.objectTree and not containGenerics(baseType, g.objectTree[baseType.itemId]): + let methodIndexLen = g.bucketTable[baseType.itemId] + if baseType.itemId notin itemTable: # once is enough + rootTypeSeq.add baseType + itemTable[baseType.itemId] = newSeq[LazySym](methodIndexLen) + + sort(g.objectTree[baseType.itemId], cmp = proc (x, y: tuple[depth: int, value: PType]): int = + if x.depth >= y.depth: 1 + else: -1 + ) + + for item in g.objectTree[baseType.itemId]: + if item.value.itemId notin itemTable: + itemTable[item.value.itemId] = newSeq[LazySym](methodIndexLen) + + var mIndex = 0 # here is the correpsonding index + if baseType.itemId notin rootItemIdCount: + rootItemIdCount[baseType.itemId] = 1 + else: + mIndex = rootItemIdCount[baseType.itemId] + rootItemIdCount.inc(baseType.itemId) + for idx in 0..<g.methods[bucket].methods.len: + let obj = g.methods[bucket].methods[idx].typ.firstParamType.skipTypes(skipPtrs) + itemTable[obj.itemId][mIndex] = LazySym(sym: g.methods[bucket].methods[idx]) + g.addDispatchers genVTableDispatcher(g, g.methods[bucket].methods, mIndex) + else: # if the base object doesn't have this method + g.addDispatchers genIfDispatcher(g, g.methods[bucket].methods, relevantCols, g.idgen) + +proc sortVTableDispatchers*(g: ModuleGraph) = + var itemTable = initTable[ItemId, seq[LazySym]]() + var rootTypeSeq = newSeq[ItemId]() + var rootItemIdCount = initCountTable[ItemId]() + for bucket in 0..<g.methods.len: + var relevantCols = initIntSet() + if relevantCol(g.methods[bucket].methods, 1): incl(relevantCols, 1) + sortBucket(g.methods[bucket].methods, relevantCols) + let base = g.methods[bucket].methods[^1] + let baseType = base.typ.firstParamType.skipTypes(skipPtrs-{tyTypeDesc}) + if baseType.itemId in g.objectTree and not containGenerics(baseType, g.objectTree[baseType.itemId]): + let methodIndexLen = g.bucketTable[baseType.itemId] + if baseType.itemId notin itemTable: # once is enough + rootTypeSeq.add baseType.itemId + itemTable[baseType.itemId] = newSeq[LazySym](methodIndexLen) + + sort(g.objectTree[baseType.itemId], cmp = proc (x, y: tuple[depth: int, value: PType]): int = + if x.depth >= y.depth: 1 + else: -1 + ) + + for item in g.objectTree[baseType.itemId]: + if item.value.itemId notin itemTable: + itemTable[item.value.itemId] = newSeq[LazySym](methodIndexLen) + + var mIndex = 0 # here is the correpsonding index + if baseType.itemId notin rootItemIdCount: + rootItemIdCount[baseType.itemId] = 1 + else: + mIndex = rootItemIdCount[baseType.itemId] + rootItemIdCount.inc(baseType.itemId) + for idx in 0..<g.methods[bucket].methods.len: + let obj = g.methods[bucket].methods[idx].typ.firstParamType.skipTypes(skipPtrs) + itemTable[obj.itemId][mIndex] = LazySym(sym: g.methods[bucket].methods[idx]) + + for baseType in rootTypeSeq: + g.setMethodsPerType(baseType, itemTable[baseType]) + for item in g.objectTree[baseType]: + let typ = item.value.skipTypes(skipPtrs) + let idx = typ.itemId + for mIndex in 0..<itemTable[idx].len: + if itemTable[idx][mIndex].sym == nil: + let parentIndex = typ.baseClass.skipTypes(skipPtrs).itemId + itemTable[idx][mIndex] = itemTable[parentIndex][mIndex] + g.setMethodsPerType(idx, itemTable[idx]) |