From ebb12a7f3125829ced4f4339db2e098fadcfd525 Mon Sep 17 00:00:00 2001 From: saem Date: Wed, 26 Jul 2023 15:12:44 -0700 Subject: [PATCH 1/5] formatting --- compiler/sem/semstmts.nim | 12 +----------- compiler/sem/semtypes.nim | 18 ------------------ 2 files changed, 1 insertion(+), 29 deletions(-) diff --git a/compiler/sem/semstmts.nim b/compiler/sem/semstmts.nim index 5b365811b81..96f7acaba41 100644 --- a/compiler/sem/semstmts.nim +++ b/compiler/sem/semstmts.nim @@ -1789,7 +1789,6 @@ proc typeDefLeftSidePass(c: PContext, typeSection: PNode, i: int) = if pkg.isNil or pkg.kind != skPackage: localReport(c.config, name.info, reportStr( rsemUnknownPackageName, pkgName.s)) - else: let typsym = c.graph.packageTypes.strTableGet(typName) if typsym.isNil: @@ -1805,7 +1804,6 @@ proc typeDefLeftSidePass(c: PContext, typeSection: PNode, i: int) = else: localReport(c.config, name.info, reportSym( rsemTypeCannotBeForwarded, typsym)) - s = typsym else: s = semIdentDef(c, name, skType) @@ -1821,7 +1819,6 @@ proc typeDefLeftSidePass(c: PContext, typeSection: PNode, i: int) = # check if we got any errors and if so report them for e in ifErrorWalkErrors(c.config, name[1]): localReport(c.config, e) - if sfForward in s.flags: # check if the symbol already exists: let pkg = c.module.owner @@ -1836,12 +1833,10 @@ proc typeDefLeftSidePass(c: PContext, typeSection: PNode, i: int) = else: localReport(c.config, name.info, reportSymbols( rsemDoubleCompletionOf, @[typsym, s])) - s = typsym # add it here, so that recursive types are possible: if sfGenSym notin s.flags: addInterfaceDecl(c, s) - elif s.owner == nil: s.owner = getCurrOwner(c) @@ -1863,7 +1858,6 @@ proc typeSectionLeftSidePass(c: PContext, n: PNode) = if a.kind == nkCommentStmt: continue if a.kind != nkTypeDef: semReportIllformedAst(c.config, a, {nkTypeDef}) - typeDefLeftSidePass(c, n, i) proc checkCovariantParamsUsages(c: PContext; genericType: PType) = @@ -1940,14 +1934,12 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) = if a.kind == nkCommentStmt: continue if a.kind != nkTypeDef: semReportIllformedAst(c.config, a, {nkTypeDef}) - checkSonsLen(a, 3, c.config) let name = typeSectionTypeName(c, a[0]) var s = name.sym if s.magic == mNone and a[2].kind == nkEmpty: localReport(c.config, a.info, reportSym( rsemImplementationExpected, s)) - if s.magic != mNone: processMagicType(c, s) @@ -1997,12 +1989,10 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) = # process the type's body: pushOwner(c, s) var t = semTypeNode(c, a[2], s.typ) - if t.kind == tyError and t.n.isError: # we've got a tyError with a report in n # xxx: we should probably propagate tyError like nkError c.config.localReport(t.n) - if s.typ == nil: s.typ = t elif t != s.typ and (s.typ == nil or s.typ.kind != tyAlias): @@ -2015,7 +2005,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) = # final pass if a[2].kind in nkCallKinds: incl a[2].flags, nfSem # bug #10548 - + if sfExportc in s.flags and s.typ.kind == tyAlias: localReport(c.config, name.info, reportSym( rsemUnexpectedExportcInAlias, s)) diff --git a/compiler/sem/semtypes.nim b/compiler/sem/semtypes.nim index 108314efe51..f162d42942d 100644 --- a/compiler/sem/semtypes.nim +++ b/compiler/sem/semtypes.nim @@ -430,7 +430,6 @@ proc semTypeIdent(c: PContext, n: PNode): PSym = result = qualifiedLookUp(c, n, {checkAmbiguity, checkUndeclared}) if result.isError: markUsed(c, n.info, result) - # XXX: move to propagating nkError, skError, and tyError localReport(c.config, result.ast) elif result != nil: @@ -447,7 +446,6 @@ proc semTypeIdent(c: PContext, n: PNode): PSym = if result.typ.sym == nil: let err = newError(c.config, n, PAstDiag(kind: adSemTypeExpected)) localReport(c.config, err) - return errorSym(c, n, err) result = result.typ.sym.copySym(nextSymId c.idgen) result.typ = exactReplica(result.typ) @@ -479,7 +477,6 @@ proc semTypeIdent(c: PContext, n: PNode): PSym = let err = newError(c.config, n, PAstDiag(kind: adSemTypeExpected)) if result.kind != skError: localReport(c.config, err) - return errorSym(c, n, err) if result.typ.kind != tyGenericParam: # XXX get rid of this hack! @@ -523,17 +520,14 @@ proc semTuple(c: PContext, n: PNode, prev: PType): PType = c.config.globalReport(reportAst( rsemIllformedAst, a, str = "Expected identDefs for node, but found " & $a.kind)) - checkMinSonsLen(a, 3, c.config) if a[^2].kind != nkEmpty: typ = semTypeNode(c, a[^2], nil) else: localReport(c.config, a, reportSem rsemTypeExpected) typ = errorType(c) - if a[^1].kind != nkEmpty: localReport(c.config, a[^1], reportSem rsemInitHereNotAllowed) - for j in 0 ..< a.len - 2: let fieldNode = newSymGNode(skField, a[j], c) @@ -547,9 +541,7 @@ proc semTuple(c: PContext, n: PNode, prev: PType): PType = else: result.n.add newSymNode(field) addSonSkipIntLit(result, typ, c.idgen) - styleCheckDef(c.config, a[j].info, field) - if result.n.len == 0: result.n = nil if isTupleRecursive(result): localReport(c.config, n.info, reportTyp( @@ -862,7 +854,6 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int, var it = n[i] if it == nil: semReportIllformedAst(c.config, n, "nil") - var idx = 1 case it.kind of nkElifBranch: @@ -880,7 +871,6 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int, else: semReportIllformedAst( c.config, n, "Expected elifBranch of else, but found" & $it.kind) - if c.inGenericContext > 0: # use a new check intset here for each branch: var newCheck: IntSet @@ -936,12 +926,10 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int, inc(pos) if containsOrIncl(check, f.name.id): localReport(c.config, info, reportSym(rsemRedefinitionOf, f)) - if a.kind == nkEmpty: father.add newSymNode(f) else: a.add newSymNode(f) - styleCheckDef(c.config, f) if a.kind != nkEmpty: father.add a of nkSym: @@ -950,7 +938,6 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int, # There is no branch validity check here if containsOrIncl(check, n.sym.name.id): localReport(c.config, n.info, reportSym(rsemRedefinitionOf, n.sym)) - father.add n of nkEmpty: if father.kind in {nkElse, nkOfBranch}: @@ -1026,7 +1013,6 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType; flags: TTypeFlags): PType if concreteBase.kind != tyError: localReport(c.config, n[1].info, reportTyp( rsemExpectNonFinalForBase, realBase)) - base = nil realBase = nil c.config.internalAssert(n.kind == nkObjectTy, n.info, "semObjectNode") @@ -1049,7 +1035,6 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType; flags: TTypeFlags): PType # check if we got any errors and if so report them for e in ifErrorWalkErrors(c.config, n[0]): localReport(c.config, e) - if base == nil and tfInheritable notin result.flags: incl(result.flags, tfFinal) @@ -2142,7 +2127,6 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = var base = semTypeNode(c, n[1], nil) if base.kind in {tyVar, tyLent}: localReport(c.config, n.info, reportTyp(rsemVarVarNotAllowed, prev)) - base = base[0] addSonSkipIntLit(result, base, c.idgen) of mRef: result = semAnyRef(c, n, tyRef, prev) @@ -2177,7 +2161,6 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = if s.typ == nil: if s.kind != skError: localReport(c.config, n, reportSem rsemTypeExpected) - result = newOrPrevType(tyError, prev, c) elif s.kind == skParam and s.typ.kind == tyTypeDesc: c.config.internalAssert s.typ.base.kind != tyNone and prev == nil @@ -2216,7 +2199,6 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = else: if s.kind != skError: localReport(c.config, n.info, reportSym(rsemTypeExpected, s)) - result = newOrPrevType(tyError, prev, c) of nkObjectTy: result = semObjectNode(c, n, prev, {}) of nkTupleTy: result = semTuple(c, n, prev) From 5e104da7842fd3cf26da61d9c1ef7936cafa8338 Mon Sep 17 00:00:00 2001 From: saem Date: Wed, 26 Jul 2023 15:17:11 -0700 Subject: [PATCH 2/5] For tuples without names create a anonymous sym as an owner. This means all fields in a tuple will have a shared owner, allowing for querying for reflection or code-gen. This required modifying `semAnonTuple` and `semTuple` procedures in the `semtypes` module. Now these procedures check to see if an owning symbol already exists and if not an anonymous one is created. --- compiler/sem/semstmts.nim | 2 ++ compiler/sem/semtypes.nim | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/compiler/sem/semstmts.nim b/compiler/sem/semstmts.nim index 96f7acaba41..d0e27ade8bb 100644 --- a/compiler/sem/semstmts.nim +++ b/compiler/sem/semstmts.nim @@ -1962,6 +1962,8 @@ 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 + # xxx: this proxy type and passing `nil` to `semTypeNode`'s previous type + # all seem like bad ideas rawAddSon(s.typ, newTypeS(tyNone, c)) s.ast = a inc c.inGenericContext diff --git a/compiler/sem/semtypes.nim b/compiler/sem/semtypes.nim index f162d42942d..be561db182e 100644 --- a/compiler/sem/semtypes.nim +++ b/compiler/sem/semtypes.nim @@ -497,6 +497,17 @@ proc semAnonTuple(c: PContext, n: PNode, prev: PType): PType = if n.len == 0: localReport(c.config, n, reportSem rsemTypeExpected) result = newOrPrevType(tyTuple, prev, c) + let setupOwner = c.inGenericContext == 0 and result.sym.isNil + if setupOwner: + # xxx: instead of "AnonType" maybe generate a name from the field + # names+types with some caching so the same structures have the same + # names/symbols. + let sym = newSym(skType, getIdent(c.cache, "AnonType"), + nextSymId c.idgen, c.getCurrOwner(), n.info) + sym.flags.incl sfAnon + sym.typ = result + result.owner = sym + pushOwner(c, sym) for it in n: let t = semTypeNode(c, it, nil).skipIntLit(c.idgen) if prev != nil and prev.aliasesType(t): @@ -505,6 +516,8 @@ proc semAnonTuple(c: PContext, n: PNode, prev: PType): PType = break else: rawAddSon(result, t) + if setupOwner: + popOwner(c) proc semTuple(c: PContext, n: PNode, prev: PType): PType = # TODO: replace with a node returning variant that can in band errors @@ -512,6 +525,17 @@ proc semTuple(c: PContext, n: PNode, prev: PType): PType = var typ: PType result = newOrPrevType(tyTuple, prev, c) result.n = newNodeI(nkRecList, n.info) + let setupOwner = c.inGenericContext == 0 and result.sym.isNil + if setupOwner: + # xxx: instead of "AnonType" maybe generate a name from the field + # names+types with some caching so the same structures have the same + # names/symbols. + let sym = newSym(skType, getIdent(c.cache, "AnonType"), + nextSymId c.idgen, c.getCurrOwner(), n.info) + sym.flags.incl sfAnon + sym.typ = result + result.owner = sym + pushOwner(c, sym) var check = initIntSet() var counter = 0 for i in ord(n.kind == nkBracketExpr).. Date: Thu, 27 Jul 2023 13:55:13 -0700 Subject: [PATCH 3/5] refactor(sem): move `newAnonSym` to `sem` move `newAnonSym` from the module `semexprs` to `sem`, allowing it to be reused in `semtypes`. --- compiler/sem/sem.nim | 9 +++++++++ compiler/sem/semexprs.nim | 3 --- compiler/sem/semtypes.nim | 7 ++----- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/compiler/sem/sem.nim b/compiler/sem/sem.nim index 6e6ce291fdf..f34306ecf65 100644 --- a/compiler/sem/sem.nim +++ b/compiler/sem/sem.nim @@ -746,6 +746,15 @@ proc semConstBoolExpr(c: PContext, n: PNode): PNode = proc semGenericStmt(c: PContext, n: PNode): PNode proc semConceptBody(c: PContext, n: PNode): PNode +proc newAnonSym(c: PContext, kind: TSymKind, info: TLineInfo): PSym = + ## creates an anonymous symbol of the given `kind` + let id = + case kind + of skType: getIdent(c.cache, "AnonType") + else: c.cache.idAnon + result = newSym(kind, id, nextSymId c.idgen, getCurrOwner(c), info) + result.flags.incl sfAnon + include semtypes, semtempl, semgnrc, semstmts, semexprs proc semStmtAndGenerateGenerics(c: PContext, n: PNode): PNode = diff --git a/compiler/sem/semexprs.nim b/compiler/sem/semexprs.nim index a1881d75dc4..6e090032e25 100644 --- a/compiler/sem/semexprs.nim +++ b/compiler/sem/semexprs.nim @@ -2582,9 +2582,6 @@ proc expectString(c: PContext, n: PNode): string = else: localReport(c.config, n, reportSem rsemStringLiteralExpected) -proc newAnonSym(c: PContext; kind: TSymKind, info: TLineInfo): PSym = - result = newSym(kind, c.cache.idAnon, nextSymId c.idgen, getCurrOwner(c), info) - proc semExpandToAst(c: PContext, n: PNode): PNode = let macroCall = n[1] diff --git a/compiler/sem/semtypes.nim b/compiler/sem/semtypes.nim index be561db182e..e0147a2c42f 100644 --- a/compiler/sem/semtypes.nim +++ b/compiler/sem/semtypes.nim @@ -502,8 +502,7 @@ proc semAnonTuple(c: PContext, n: PNode, prev: PType): PType = # xxx: instead of "AnonType" maybe generate a name from the field # names+types with some caching so the same structures have the same # names/symbols. - let sym = newSym(skType, getIdent(c.cache, "AnonType"), - nextSymId c.idgen, c.getCurrOwner(), n.info) + let sym = newAnonSym(c, skType, n.info) sym.flags.incl sfAnon sym.typ = result result.owner = sym @@ -530,9 +529,7 @@ proc semTuple(c: PContext, n: PNode, prev: PType): PType = # xxx: instead of "AnonType" maybe generate a name from the field # names+types with some caching so the same structures have the same # names/symbols. - let sym = newSym(skType, getIdent(c.cache, "AnonType"), - nextSymId c.idgen, c.getCurrOwner(), n.info) - sym.flags.incl sfAnon + let sym = newAnonSym(c, skType, n.info) sym.typ = result result.owner = sym pushOwner(c, sym) From f9cb940068aa5ea921d7458f7b7adbef86639cd0 Mon Sep 17 00:00:00 2001 From: saem Date: Thu, 27 Jul 2023 14:46:46 -0700 Subject: [PATCH 4/5] formatting --- compiler/sem/semtypes.nim | 33 +++++++++------------------------ 1 file changed, 9 insertions(+), 24 deletions(-) diff --git a/compiler/sem/semtypes.nim b/compiler/sem/semtypes.nim index e0147a2c42f..2b2192f5ada 100644 --- a/compiler/sem/semtypes.nim +++ b/compiler/sem/semtypes.nim @@ -753,22 +753,17 @@ iterator processBranchVals(b: PNode): int = proc toLiterals*(vals: IntSet, t: PType): seq[PNode] = let t = t.skipTypes(abstractRange) - var enumSymOffset = 0 for val in vals: - case t.kind: - of tyEnum, tyBool: - while t.n[enumSymOffset].sym.position < val: - inc(enumSymOffset) - - result &= t.n[enumSymOffset] - - of tyChar: - result.add newIntNode(nkCharLit, BiggestInt(val)) - - else: - result.add newIntNode(nkIntLit, BiggestInt(val)) - + case t.kind + of tyEnum, tyBool: + while t.n[enumSymOffset].sym.position < val: + inc(enumSymOffset) + result &= t.n[enumSymOffset] + of tyChar: + result.add newIntNode(nkCharLit, BiggestInt(val)) + else: + result.add newIntNode(nkIntLit, BiggestInt(val)) proc toEnumFields(vals: IntSet, t: PType): seq[PSym] = block: @@ -783,10 +778,8 @@ proc missingInts(c: PContext, n: PNode): IntSet = for i in 1.. 0x00007FFF: var rep = SemReport( @@ -854,7 +846,6 @@ proc semRecordCase(c: PContext, n: PNode, check: var IntSet, pos: var int, c.config, n, "Expected ofBranch or else for object case statement, but found" & $n[i].kind) - delSon(b, b.len - 1) semRecordNodeAux(c, lastSon(n[i]), check, pos, b, rectype, hasCaseFields = true) if chckCovered and covered != toCover(c, a[0].typ): @@ -864,7 +855,6 @@ proc semRecordCase(c: PContext, n: PNode, check: var IntSet, pos: var int, nodes: formatMissingBranches(c, a))) else: localReport(c.config, a, reportSem rsemMissingCaseBranches) - father.add a proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int, @@ -1081,8 +1071,6 @@ proc semAnyRef(c: PContext; n: PNode; kind: TTypeKind; prev: PType): PType = if t.kind == tyVoid: localReport(c.config, n.info, reportTyp( rsemTVoidNotAllowed, t, str = kind.toHumanStr)) - - result = newOrPrevType(kind, prev, c) var isNilable = false var wrapperKind = tyNone @@ -1100,7 +1088,6 @@ proc semAnyRef(c: PContext; n: PNode; kind: TTypeKind; prev: PType): PType = tyError, tyObject}: localReport(c.config, n[i], reportSem rsemExpectedObjectForRegion) addSonSkipIntLit(result, region, c.idgen) - else: localReport(c.config, n.info, reportSem(rsemPtrRegionIsDeprecated)) addSonSkipIntLit(result, region, c.idgen) @@ -1583,7 +1570,6 @@ proc semObjectTypeForInheritedGenericInst(c: PContext, n: PNode, t: PType) = base = skipTypesOrNil(realBase, skipPtrs) if base.isNil: localReport(c.config, n.info, reportTyp(rsemIllegalRecursion, t)) - else: let concreteBase = skipGenericInvocation(base) if concreteBase.kind == tyObject and tfFinal notin concreteBase.flags: @@ -1916,7 +1902,6 @@ proc semTypeOf2(c: PContext; n: PNode; prev: PType): PType = ast: n, location: some(n.info), kind: rvmCannotEvaluateAtComptime)) - else: m = mode.intVal From 4b280ff15f38186ececa0c1d1ad64eb2cec4fb46 Mon Sep 17 00:00:00 2001 From: saem Date: Thu, 27 Jul 2023 14:49:50 -0700 Subject: [PATCH 5/5] fix(sem): missing discriminant too large error if a discriminant was too large for a variant an error was both not logged nor did it cause compilation to fail --- compiler/sem/semtypes.nim | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/sem/semtypes.nim b/compiler/sem/semtypes.nim index 2b2192f5ada..63b7bcebbb9 100644 --- a/compiler/sem/semtypes.nim +++ b/compiler/sem/semtypes.nim @@ -828,6 +828,7 @@ proc semRecordCase(c: PContext, n: PNode, check: var IntSet, pos: var int, # - got: firstOrd(c.config, typ)), typ: typ, sym: a[0].sym) + localReport(c.config, n.info, rep) for i in 1..