diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2023-12-17 18:43:52 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-12-17 18:43:52 +0100 |
commit | fe18ec5dc089831c6ea634ade211d8d0dadfec86 (patch) | |
tree | bba4a9600c3c53face21ad6cdec45be54f01ca65 /compiler | |
parent | 9b08abaa0574c32f414c09bb4ef183739003884d (diff) | |
download | Nim-fe18ec5dc089831c6ea634ade211d8d0dadfec86.tar.gz |
types refactoring; WIP (#23086)
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/ast.nim | 36 | ||||
-rw-r--r-- | compiler/astyaml.nim | 76 | ||||
-rw-r--r-- | compiler/enumtostr.nim | 2 | ||||
-rw-r--r-- | compiler/patterns.nim | 2 | ||||
-rw-r--r-- | compiler/sem.nim | 14 | ||||
-rw-r--r-- | compiler/semcall.nim | 11 | ||||
-rw-r--r-- | compiler/seminst.nim | 21 | ||||
-rw-r--r-- | compiler/suggest.nim | 4 | ||||
-rw-r--r-- | compiler/types.nim | 4 | ||||
-rw-r--r-- | compiler/vm.nim | 6 | ||||
-rw-r--r-- | compiler/vtables.nim | 2 |
11 files changed, 81 insertions, 97 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index ce86d7369..06b6cd357 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -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: diff --git a/compiler/astyaml.nim b/compiler/astyaml.nim index b098d92b9..c7e090cd3 100644 --- a/compiler/astyaml.nim +++ b/compiler/astyaml.nim @@ -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 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 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: 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) - -proc treeToYamlAux( - res: var string; - conf: ConfigRef; - n: PNode; - marker: var IntSet; - indent: int; - maxRecDepth: int; -) = + 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) = 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) diff --git a/compiler/enumtostr.nim b/compiler/enumtostr.nim index 908c48ccb..dc516d2e5 100644 --- a/compiler/enumtostr.nim +++ b/compiler/enumtostr.nim @@ -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 diff --git a/compiler/patterns.nim b/compiler/patterns.nim index 04d8593cc..32ec7fb53 100644 --- a/compiler/patterns.nim +++ b/compiler/patterns.nim @@ -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 diff --git a/compiler/sem.nim b/compiler/sem.nim index 47b9600f5..1ae7d4626 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -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 diff --git a/compiler/semcall.nim b/compiler/semcall.nim index f6beb1aeb..ff3479b92 100644 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -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 diff --git a/compiler/seminst.nim b/compiler/seminst.nim index c64c120d6..64452441b 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -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) diff --git a/compiler/suggest.nim b/compiler/suggest.nim index 9e0fc13e4..5eb2c03ab 100644 --- a/compiler/suggest.nim +++ b/compiler/suggest.nim @@ -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 diff --git a/compiler/types.nim b/compiler/types.nim index 7d7d3349d..04f953f79 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -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: diff --git a/compiler/vm.nim b/compiler/vm.nim index 7063a7268..88419d5dd 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -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: diff --git a/compiler/vtables.nim b/compiler/vtables.nim index b9b13badc..928c64dd5 100644 --- a/compiler/vtables.nim +++ b/compiler/vtables.nim @@ -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) |