mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 17:04:41 +00:00
type refactoring: part 2 (#23059)
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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", [
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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])
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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[]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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])
|
||||
|
||||
Reference in New Issue
Block a user