type refactoring: part 2 (#23059)

This commit is contained in:
Andreas Rumpf
2023-12-13 10:29:58 +01:00
committed by GitHub
parent df6cb645f7
commit e51e98997b
35 changed files with 422 additions and 430 deletions

View File

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

View File

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

View File

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

View File

@@ -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", [

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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