mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 08:54:53 +00:00
types refactoring; WIP (#23086)
This commit is contained in:
@@ -1602,6 +1602,14 @@ proc signatureLen*(t: PType): int {.inline.} =
|
||||
proc paramsLen*(t: PType): int {.inline.} =
|
||||
result = t.sons.len - 1
|
||||
|
||||
proc genericParamsLen*(t: PType): int {.inline.} =
|
||||
assert t.kind == tyGenericInst
|
||||
result = t.sons.len - 2 # without 'head' and 'body'
|
||||
|
||||
proc genericInvocationParamsLen*(t: PType): int {.inline.} =
|
||||
assert t.kind == tyGenericInvocation
|
||||
result = t.sons.len - 1 # without 'head'
|
||||
|
||||
proc kidsLen*(t: PType): int {.inline.} =
|
||||
result = t.sons.len
|
||||
|
||||
@@ -1611,17 +1619,34 @@ proc hasElementType*(t: PType): bool {.inline.} = t.sons.len > 0
|
||||
proc isEmptyTupleType*(t: PType): bool {.inline.} = t.sons.len == 0
|
||||
proc isSingletonTupleType*(t: PType): bool {.inline.} = t.sons.len == 1
|
||||
|
||||
proc genericConstraint*(t: PType): PType {.inline.} = t.sons[0]
|
||||
|
||||
iterator genericInstParams*(t: PType): (bool, PType) =
|
||||
for i in 1..<t.sons.len-1:
|
||||
yield (i!=1, t.sons[i])
|
||||
|
||||
iterator genericInstParamPairs*(a, b: PType): (int, PType, PType) =
|
||||
for i in 1..<min(a.sons.len, b.sons.len)-1:
|
||||
yield (i-1, a.sons[i], b.sons[i])
|
||||
|
||||
iterator genericInvocationParams*(t: PType): (bool, PType) =
|
||||
for i in 1..<t.sons.len:
|
||||
yield (i!=1, t.sons[i])
|
||||
|
||||
iterator genericBodyParams*(t: PType): (bool, PType) =
|
||||
iterator genericInvocationAndBodyElements*(a, b: PType): (PType, PType) =
|
||||
for i in 1..<a.sons.len:
|
||||
yield (a.sons[i], b.sons[i-1])
|
||||
|
||||
iterator genericInvocationParamPairs*(a, b: PType): (bool, PType, PType) =
|
||||
for i in 1..<a.sons.len:
|
||||
if i >= b.sons.len:
|
||||
yield (false, nil, nil)
|
||||
else:
|
||||
yield (true, a.sons[i], b.sons[i])
|
||||
|
||||
iterator genericBodyParams*(t: PType): (int, PType) =
|
||||
for i in 0..<t.sons.len-1:
|
||||
yield (i!=0, t.sons[i])
|
||||
yield (i, t.sons[i])
|
||||
|
||||
iterator userTypeClassInstParams*(t: PType): (bool, PType) =
|
||||
for i in 1..<t.sons.len-1:
|
||||
@@ -1676,6 +1701,11 @@ proc newSons*(father: PNode, length: int) =
|
||||
proc newSons*(father: PType, length: int) =
|
||||
setLen(father.sons, length)
|
||||
|
||||
proc truncateInferredTypeCandidates*(t: PType) {.inline.} =
|
||||
assert t.kind == tyInferred
|
||||
if t.sons.len > 1:
|
||||
setLen(t.sons, 1)
|
||||
|
||||
proc assignType*(dest, src: PType) =
|
||||
dest.kind = src.kind
|
||||
dest.flags = src.flags
|
||||
@@ -2041,7 +2071,7 @@ proc skipGenericOwner*(s: PSym): PSym =
|
||||
## symbol. This proc skips such owners and goes straight to the owner
|
||||
## of the generic itself (the module or the enclosing proc).
|
||||
result = if s.kind == skModule:
|
||||
s
|
||||
s
|
||||
elif s.kind in skProcKinds and sfFromGeneric in s.flags and s.owner.kind != skModule:
|
||||
s.owner.owner
|
||||
else:
|
||||
|
||||
@@ -45,38 +45,11 @@ proc lineInfoToStr*(conf: ConfigRef; info: TLineInfo): string =
|
||||
result.addYamlString(toFilename(conf, info))
|
||||
result.addf ", $1, $2]", [toLinenumber(info), toColumn(info)]
|
||||
|
||||
proc treeToYamlAux(
|
||||
res: var string;
|
||||
conf: ConfigRef;
|
||||
n: PNode;
|
||||
marker: var IntSet;
|
||||
indent, maxRecDepth: int;
|
||||
)
|
||||
proc treeToYamlAux(res: var string; conf: ConfigRef; n: PNode; marker: var IntSet; indent, maxRecDepth: int)
|
||||
proc symToYamlAux(res: var string; conf: ConfigRef; n: PSym; marker: var IntSet; indent, maxRecDepth: int)
|
||||
proc typeToYamlAux(res: var string; conf: ConfigRef; n: PType; marker: var IntSet; indent, maxRecDepth: int)
|
||||
|
||||
proc symToYamlAux(
|
||||
res: var string;
|
||||
conf: ConfigRef;
|
||||
n: PSym;
|
||||
marker: var IntSet;
|
||||
indent, maxRecDepth: int;
|
||||
)
|
||||
|
||||
proc typeToYamlAux(
|
||||
res: var string;
|
||||
conf: ConfigRef;
|
||||
n: PType;
|
||||
marker: var IntSet;
|
||||
indent, maxRecDepth: int;
|
||||
)
|
||||
|
||||
proc symToYamlAux(
|
||||
res: var string;
|
||||
conf: ConfigRef;
|
||||
n: PSym;
|
||||
marker: var IntSet;
|
||||
indent: int;
|
||||
maxRecDepth: int;
|
||||
) =
|
||||
proc symToYamlAux(res: var string; conf: ConfigRef; n: PSym; marker: var IntSet; indent: int; maxRecDepth: int) =
|
||||
if n == nil:
|
||||
res.add("null")
|
||||
elif containsOrIncl(marker, n.id):
|
||||
@@ -106,14 +79,7 @@ proc symToYamlAux(
|
||||
res.addf("\n$1lode: $2", [istr])
|
||||
res.treeToYamlAux(conf, n.loc.lode, marker, indent + 1, maxRecDepth - 1)
|
||||
|
||||
proc typeToYamlAux(
|
||||
res: var string;
|
||||
conf: ConfigRef;
|
||||
n: PType;
|
||||
marker: var IntSet;
|
||||
indent: int;
|
||||
maxRecDepth: int;
|
||||
) =
|
||||
proc typeToYamlAux(res: var string; conf: ConfigRef; n: PType; marker: var IntSet; indent: int; maxRecDepth: int) =
|
||||
if n == nil:
|
||||
res.add("null")
|
||||
elif containsOrIncl(marker, n.id):
|
||||
@@ -130,20 +96,14 @@ proc typeToYamlAux(
|
||||
res.addf("\n$1callconv: $2", [istr, makeYamlString($n.callConv)])
|
||||
res.addf("\n$1size: $2", [istr, $(n.size)])
|
||||
res.addf("\n$1align: $2", [istr, $(n.align)])
|
||||
if n.len > 0:
|
||||
if n.hasElementType:
|
||||
res.addf("\n$1sons:")
|
||||
for i in 0..<n.len:
|
||||
for a in n.kids:
|
||||
res.addf("\n - ")
|
||||
res.typeToYamlAux(conf, n[i], marker, indent + 1, maxRecDepth - 1)
|
||||
res.typeToYamlAux(conf, a, marker, indent + 1, maxRecDepth - 1)
|
||||
|
||||
proc treeToYamlAux(
|
||||
res: var string;
|
||||
conf: ConfigRef;
|
||||
n: PNode;
|
||||
marker: var IntSet;
|
||||
indent: int;
|
||||
maxRecDepth: int;
|
||||
) =
|
||||
proc treeToYamlAux(res: var string; conf: ConfigRef; n: PNode; marker: var IntSet; indent: int;
|
||||
maxRecDepth: int) =
|
||||
if n == nil:
|
||||
res.add("null")
|
||||
else:
|
||||
@@ -178,23 +138,17 @@ proc treeToYamlAux(
|
||||
res.addf("\n$1typ: ", [istr])
|
||||
res.typeToYamlAux(conf, n.typ, marker, indent + 1, maxRecDepth)
|
||||
|
||||
proc treeToYaml*(
|
||||
conf: ConfigRef; n: PNode; indent: int = 0; maxRecDepth: int = -1
|
||||
): string =
|
||||
proc treeToYaml*(conf: ConfigRef; n: PNode; indent: int = 0; maxRecDepth: int = -1): string =
|
||||
var marker = initIntSet()
|
||||
result = newStringOfCap(1024)
|
||||
result.treeToYamlAux(conf, n, marker, indent, maxRecDepth)
|
||||
|
||||
proc typeToYaml*(
|
||||
conf: ConfigRef; n: PType; indent: int = 0; maxRecDepth: int = -1
|
||||
): string =
|
||||
proc typeToYaml*(conf: ConfigRef; n: PType; indent: int = 0; maxRecDepth: int = -1): string =
|
||||
var marker = initIntSet()
|
||||
result = newStringOfCap(1024)
|
||||
result.typeToYamlAux(conf, n, marker, indent, maxRecDepth)
|
||||
|
||||
proc symToYaml*(
|
||||
conf: ConfigRef; n: PSym; indent: int = 0; maxRecDepth: int = -1
|
||||
): string =
|
||||
proc symToYaml*(conf: ConfigRef; n: PSym; indent: int = 0; maxRecDepth: int = -1): string =
|
||||
var marker = initIntSet()
|
||||
result = newStringOfCap(1024)
|
||||
result.symToYamlAux(conf, n, marker, indent, maxRecDepth)
|
||||
|
||||
@@ -63,7 +63,7 @@ proc searchObjCaseImpl(obj: PNode; field: PSym): PNode =
|
||||
|
||||
proc searchObjCase(t: PType; field: PSym): PNode =
|
||||
result = searchObjCaseImpl(t.n, field)
|
||||
if result == nil and t.len > 0:
|
||||
if result == nil and t.baseClass != nil:
|
||||
result = searchObjCase(t.baseClass.skipTypes({tyAlias, tyGenericInst, tyRef, tyPtr}), field)
|
||||
doAssert result != nil
|
||||
|
||||
|
||||
@@ -276,7 +276,7 @@ proc addToArgList(result, n: PNode) =
|
||||
|
||||
proc applyRule*(c: PContext, s: PSym, n: PNode): PNode =
|
||||
## returns a tree to semcheck if the rule triggered; nil otherwise
|
||||
var ctx = TPatternContext(owner: s, c: c, formals: s.typ.len-1)
|
||||
var ctx = TPatternContext(owner: s, c: c, formals: s.typ.paramsLen)
|
||||
var m = matchStmtList(ctx, s.ast[patternPos], n)
|
||||
if isNil(m): return nil
|
||||
# each parameter should have been bound; we simply setup a call and
|
||||
|
||||
@@ -144,7 +144,7 @@ proc commonType*(c: PContext; x, y: PType): PType =
|
||||
elif b.kind == tyTyped: result = b
|
||||
elif a.kind == tyTypeDesc:
|
||||
# turn any concrete typedesc into the abstract typedesc type
|
||||
if a.len == 0: result = a
|
||||
if not a.hasElementType: result = a
|
||||
else:
|
||||
result = newType(tyTypeDesc, c.idgen, a.owner)
|
||||
rawAddSon(result, newType(tyNone, c.idgen, a.owner))
|
||||
@@ -153,17 +153,17 @@ proc commonType*(c: PContext; x, y: PType): PType =
|
||||
# check for seq[empty] vs. seq[int]
|
||||
let idx = ord(b.kind == tyArray)
|
||||
if a[idx].kind == tyEmpty: return y
|
||||
elif a.kind == tyTuple and b.kind == tyTuple and a.len == b.len:
|
||||
elif a.kind == tyTuple and b.kind == tyTuple and sameTupleLengths(a, b):
|
||||
var nt: PType = nil
|
||||
for i in 0..<a.len:
|
||||
let aEmpty = isEmptyContainer(a[i])
|
||||
let bEmpty = isEmptyContainer(b[i])
|
||||
for i, aa, bb in tupleTypePairs(a, b):
|
||||
let aEmpty = isEmptyContainer(aa)
|
||||
let bEmpty = isEmptyContainer(bb)
|
||||
if aEmpty != bEmpty:
|
||||
if nt.isNil:
|
||||
nt = copyType(a, c.idgen, a.owner)
|
||||
copyTypeProps(c.graph, c.idgen.module, nt, a)
|
||||
|
||||
nt[i] = if aEmpty: b[i] else: a[i]
|
||||
nt[i] = if aEmpty: bb else: aa
|
||||
if not nt.isNil: result = nt
|
||||
#elif b[idx].kind == tyEmpty: return x
|
||||
elif a.kind == tyRange and b.kind == tyRange:
|
||||
@@ -503,7 +503,7 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
|
||||
else:
|
||||
var retType = s.typ.returnType
|
||||
if retType.kind == tyTypeDesc and tfUnresolved in retType.flags and
|
||||
retType.len == 1:
|
||||
retType.hasElementType:
|
||||
# bug #11941: template fails(T: type X, v: auto): T
|
||||
# does not mean we expect a tyTypeDesc.
|
||||
retType = retType.skipModifier
|
||||
|
||||
@@ -581,7 +581,7 @@ proc inheritBindings(c: PContext, x: var TCandidate, expectedType: PType) =
|
||||
## Helper proc to inherit bound generic parameters from expectedType into x.
|
||||
## Does nothing if 'inferGenericTypes' isn't in c.features.
|
||||
if inferGenericTypes notin c.features: return
|
||||
if expectedType == nil or x.callee[0] == nil: return # required for inference
|
||||
if expectedType == nil or x.callee.returnType == nil: return # required for inference
|
||||
|
||||
var
|
||||
flatUnbound: seq[PType] = @[]
|
||||
@@ -593,14 +593,14 @@ proc inheritBindings(c: PContext, x: var TCandidate, expectedType: PType) =
|
||||
## skips types and puts the skipped version on stack
|
||||
# It might make sense to skip here one by one. It's not part of the main
|
||||
# type reduction because the right side normally won't be skipped
|
||||
const toSkip = { tyVar, tyLent, tyStatic, tyCompositeTypeClass, tySink }
|
||||
const toSkip = {tyVar, tyLent, tyStatic, tyCompositeTypeClass, tySink}
|
||||
let
|
||||
x = a.skipTypes(toSkip)
|
||||
y = if a.kind notin toSkip: b
|
||||
else: b.skipTypes(toSkip)
|
||||
typeStack.add((x, y))
|
||||
|
||||
stackPut(x.callee[0], expectedType)
|
||||
stackPut(x.callee.returnType, expectedType)
|
||||
|
||||
while typeStack.len() > 0:
|
||||
let (t, u) = typeStack.pop()
|
||||
@@ -608,10 +608,11 @@ proc inheritBindings(c: PContext, x: var TCandidate, expectedType: PType) =
|
||||
continue
|
||||
case t.kind
|
||||
of ConcreteTypes, tyGenericInvocation, tyUncheckedArray:
|
||||
# XXX This logic makes no sense for `tyUncheckedArray`
|
||||
# nested, add all the types to stack
|
||||
let
|
||||
startIdx = if u.kind in ConcreteTypes: 0 else: 1
|
||||
endIdx = min(u.len() - startIdx, t.len())
|
||||
endIdx = min(u.kidsLen() - startIdx, t.kidsLen())
|
||||
|
||||
for i in startIdx ..< endIdx:
|
||||
# early exit with current impl
|
||||
@@ -749,7 +750,7 @@ proc explicitGenericSym(c: PContext, n: PNode, s: PSym): PNode =
|
||||
proc setGenericParams(c: PContext, n, expectedParams: PNode) =
|
||||
## sems generic params in subscript expression
|
||||
for i in 1..<n.len:
|
||||
let
|
||||
let
|
||||
constraint =
|
||||
if expectedParams != nil and i <= expectedParams.len:
|
||||
expectedParams[i - 1].typ
|
||||
|
||||
@@ -181,8 +181,7 @@ proc instGenericContainer(c: PContext, info: TLineInfo, header: PType,
|
||||
# perhaps the code can be extracted in a shared function.
|
||||
openScope(c)
|
||||
let genericTyp = header.base
|
||||
for i in 0..<genericTyp.len - 1:
|
||||
let genParam = genericTyp[i]
|
||||
for i, genParam in genericBodyParams(genericTyp):
|
||||
var param: PSym
|
||||
|
||||
template paramSym(kind): untyped =
|
||||
@@ -234,18 +233,18 @@ proc instantiateProcType(c: PContext, pt: TIdTable,
|
||||
var result = instCopyType(cl, prc.typ)
|
||||
let originalParams = result.n
|
||||
result.n = originalParams.shallowCopy
|
||||
for i in 1..<result.len:
|
||||
for i, resulti in paramTypes(result):
|
||||
# twrong_field_caching requires these 'resetIdTable' calls:
|
||||
if i > 1:
|
||||
if i > FirstParamAt:
|
||||
resetIdTable(cl.symMap)
|
||||
resetIdTable(cl.localCache)
|
||||
|
||||
# take a note of the original type. If't a free type or static parameter
|
||||
# we'll need to keep it unbound for the `fitNode` operation below...
|
||||
var typeToFit = result[i]
|
||||
var typeToFit = resulti
|
||||
|
||||
let needsStaticSkipping = result[i].kind == tyFromExpr
|
||||
result[i] = replaceTypeVarsT(cl, result[i])
|
||||
let needsStaticSkipping = resulti.kind == tyFromExpr
|
||||
result[i] = replaceTypeVarsT(cl, resulti)
|
||||
if needsStaticSkipping:
|
||||
result[i] = result[i].skipTypes({tyStatic})
|
||||
|
||||
@@ -295,7 +294,7 @@ proc instantiateProcType(c: PContext, pt: TIdTable,
|
||||
resetIdTable(cl.symMap)
|
||||
resetIdTable(cl.localCache)
|
||||
cl.isReturnType = true
|
||||
result[0] = replaceTypeVarsT(cl, result[0])
|
||||
result.setReturnType replaceTypeVarsT(cl, result.returnType)
|
||||
cl.isReturnType = false
|
||||
result.n[0] = originalParams[0].copyTree
|
||||
if result[0] != nil:
|
||||
@@ -377,15 +376,15 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||
# generic[void](), generic[int]()
|
||||
# see ttypeor.nim test.
|
||||
var i = 0
|
||||
newSeq(entry.concreteTypes, fn.typ.len+gp.len-1)
|
||||
newSeq(entry.concreteTypes, fn.typ.paramsLen+gp.len)
|
||||
for s in instantiateGenericParamList(c, gp, pt):
|
||||
addDecl(c, s)
|
||||
entry.concreteTypes[i] = s.typ
|
||||
inc i
|
||||
pushProcCon(c, result)
|
||||
instantiateProcType(c, pt, result, info)
|
||||
for j in 1..<result.typ.len:
|
||||
entry.concreteTypes[i] = result.typ[j]
|
||||
for _, param in paramTypes(result.typ):
|
||||
entry.concreteTypes[i] = param
|
||||
inc i
|
||||
if tfTriggersCompileTime in result.typ.flags:
|
||||
incl(result.flags, sfCompileTime)
|
||||
|
||||
@@ -337,7 +337,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:
|
||||
if s.typ != nil and s.typ.paramsLen > 0:
|
||||
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
|
||||
@@ -407,7 +407,7 @@ 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.firstParamType != nil:
|
||||
if s.typ != nil and s.typ.paramsLen > 0 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
|
||||
|
||||
@@ -566,8 +566,8 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||
result.add(']')
|
||||
of tyGenericBody:
|
||||
result = typeToString(t.typeBodyImpl) & '['
|
||||
for needsComma, a in t.genericBodyParams:
|
||||
if needsComma: result.add(", ")
|
||||
for i, a in t.genericBodyParams:
|
||||
if i > 0: result.add(", ")
|
||||
result.add(typeToString(a, preferTypeName))
|
||||
result.add(']')
|
||||
of tyTypeDesc:
|
||||
|
||||
@@ -2486,12 +2486,12 @@ proc evalMacroCall*(module: PSym; idgen: IdGenerator; g: ModuleGraph; templInstC
|
||||
tos.slots[0] = TFullReg(kind: rkNode, node: newNodeI(nkEmpty, n.info))
|
||||
|
||||
# setup parameters:
|
||||
for i in 1..<sym.typ.len:
|
||||
tos.slots[i] = setupMacroParam(n[i], sym.typ[i])
|
||||
for i, param in paramTypes(sym.typ):
|
||||
tos.slots[i-FirstParamAt+1] = setupMacroParam(n[i-FirstParamAt+1], param)
|
||||
|
||||
let gp = sym.ast[genericParamsPos]
|
||||
for i in 0..<gp.len:
|
||||
let idx = sym.typ.len + i
|
||||
let idx = sym.typ.signatureLen + i
|
||||
if idx < n.len:
|
||||
tos.slots[idx] = setupMacroParam(n[idx], gp[i].sym.typ)
|
||||
else:
|
||||
|
||||
@@ -10,7 +10,7 @@ proc dispatch(x: Base, params: ...) =
|
||||
]#
|
||||
var base = methods[0].ast[dispatcherPos].sym
|
||||
result = base
|
||||
var paramLen = base.typ.len
|
||||
var paramLen = base.typ.signatureLen
|
||||
var body = newNodeI(nkStmtList, base.info)
|
||||
|
||||
var disp = newNodeI(nkIfStmt, base.info)
|
||||
|
||||
Reference in New Issue
Block a user