From ad67b7106ca14a26ae7a2d5fe184134c85a80d93 Mon Sep 17 00:00:00 2001 From: flywind Date: Wed, 18 May 2022 10:35:25 +0800 Subject: [PATCH 01/52] fresh start --- compiler/ast.nim | 12 ++ compiler/parser.nim | 6 +- compiler/semexprs.nim | 12 +- compiler/semmagic.nim | 108 +++++++++++ compiler/semobjconstr.nim | 70 ++++--- compiler/semstmts.nim | 12 ++ compiler/semtypes.nim | 21 ++- compiler/transf.nim | 160 +++++++++++++++- tests/objects/mobject_default_value.nim | 15 ++ tests/objects/tobject_default_value.nim | 238 ++++++++++++++++++++++++ 10 files changed, 614 insertions(+), 40 deletions(-) create mode 100644 tests/objects/mobject_default_value.nim create mode 100644 tests/objects/tobject_default_value.nim diff --git a/compiler/ast.nim b/compiler/ast.nim index d1e5ae2bfe655..d0fcab9b5819e 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -502,6 +502,7 @@ type nfLastRead # this node is a last read nfFirstWrite# this node is a first write nfHasComment # node has a comment + nfUseDefaultField TNodeFlags* = set[TNodeFlag] TTypeFlag* = enum # keep below 32 for efficiency reasons (now: 45) @@ -1453,6 +1454,17 @@ proc newIntTypeNode*(intVal: BiggestInt, typ: PType): PNode = result.intVal = intVal result.typ = typ +proc newFloatTypeNode*(floatVal: BiggestFloat, typ: PType): PNode = + let kind = skipTypes(typ, abstractVarRange).kind + case kind + of tyFloat32: + result = newNode(nkFloat32Lit) + of tyFloat64, tyFloat: + result = newNode(nkFloatLit) + else: doAssert false, $kind + result.floatVal = floatVal + result.typ = typ + proc newIntTypeNode*(intVal: Int128, typ: PType): PNode = # XXX: introduce range check newIntTypeNode(castToInt64(intVal), typ) diff --git a/compiler/parser.nim b/compiler/parser.nim index 52466d9fa0f04..2f89efc560d7c 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -1963,11 +1963,7 @@ proc parseObjectCase(p: var Parser): PNode = #| | IND{=} objectBranches) result = newNodeP(nkRecCase, p) getTokNoInd(p) - var a = newNodeP(nkIdentDefs, p) - a.add(identWithPragma(p)) - eat(p, tkColon) - a.add(parseTypeDesc(p)) - a.add(p.emptyNode) + var a = parseIdentColonEquals(p, {withPragma}) result.add(a) if p.tok.tokType == tkColon: getTok(p) flexComment(p, result) diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 702b47929c7c4..fc703ea858fc4 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -897,8 +897,6 @@ proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode, rawAddSon(typ, result.typ) result.typ = typ -proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode - proc resolveIndirectCall(c: PContext; n, nOrig: PNode; t: PType): TCandidate = initCandidate(c, result, t) @@ -2380,6 +2378,16 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode = of mSizeOf: markUsed(c, n.info, s) result = semSizeof(c, setMs(n, s)) + of mDefault: + result = semDirectOp(c, n, flags) + let typ = result[^1].typ.skipTypes({tyTypeDesc}) + if typ.skipTypes({tyGenericInst, tyAlias, tySink}).kind == tyObject: + var asgnExpr = newTree(nkObjConstr, newNodeIT(nkType, result[^1].info, typ)) + asgnExpr.typ = typ + var hasDefault: bool + asgnExpr.sons.add defaultFieldsForTheUninitialized(c.graph, typ.skipTypes({tyGenericInst, tyAlias, tySink}).n, hasDefault) + if hasDefault: + result = semObjConstr(c, asgnExpr, flags) else: result = semDirectOp(c, n, flags) diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index ed1826fd4ea9b..cb630edb00091 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -10,6 +10,8 @@ # This include file implements the semantic checking for magics. # included from sem.nim +proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode + proc semAddrArg(c: PContext; n: PNode): PNode = let x = semExprWithType(c, n) if x.kind == nkSym: @@ -454,6 +456,95 @@ proc semPrivateAccess(c: PContext, n: PNode): PNode = c.currentScope.allowPrivateAccess.add t.sym result = newNodeIT(nkEmpty, n.info, getSysType(c.graph, n.info, tyVoid)) + +# import nimsets + + + +# proc caseBranchMatchesExpr2(branch, matched: PNode): bool = +# for i in 0 ..< branch.len-1: +# if branch[i].kind == nkRange: +# if overlap(branch[i], matched): return true +# elif exprStructuralEquivalent(branch[i], matched): +# return true + +# proc pickCaseBranch2(caseExpr, matched: PNode): int = +# let endsWithElse = caseExpr[^1].kind == nkElse +# for i in 1..= 4: a = newNodeI(nkRecList, n.info) else: a = newNodeI(nkEmpty, n.info) - if n[^1].kind != nkEmpty: - localError(c.config, n[^1].info, errInitHereNotAllowed) var typ: PType - if n[^2].kind == nkEmpty: + var hasDefaultField = n[^1].kind != nkEmpty + if hasDefaultField: + n[^1] = semConstExpr(c, n[^1]) + typ = n[^1].typ + propagateToOwner(rectype, typ) + elif n[^2].kind == nkEmpty: localError(c.config, n.info, errTypeExpected) typ = errorType(c) else: typ = semTypeNode(c, n[^2], nil) + if c.graph.config.isDefined("nimRangeDefault") and typ.skipTypes(abstractInst).kind in {tyRange, tyOrdinal}: + n[^1] = newIntNode(nkIntLit, firstOrd(c.config, typ)) + n[^1].typ = typ + hasDefaultField = true propagateToOwner(rectype, typ) var fieldOwner = if c.inGenericContext > 0: c.getCurrOwner else: rectype.sym @@ -806,8 +813,12 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int, inc(pos) if containsOrIncl(check, f.name.id): localError(c.config, info, "attempt to redefine: '" & f.name.s & "'") - if a.kind == nkEmpty: father.add newSymNode(f) - else: a.add newSymNode(f) + let fSym = newSymNode(f) + if hasDefaultField: + fSym.sym.ast = n[^1] + fSym.sym.ast.flags.incl nfUseDefaultField + if a.kind == nkEmpty: father.add fSym + else: a.add fSym styleCheckDef(c.config, f) onDef(f.info, f) if a.kind != nkEmpty: father.add a diff --git a/compiler/transf.nim b/compiler/transf.nim index bdd7c680ccd51..b53d897c2570c 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -46,7 +46,7 @@ type module: PSym transCon: PTransCon # top of a TransCon stack inlining: int # > 0 if we are in inlining context (copy vars) - nestedProcs: int # > 0 if we are in a nested proc + genResult: bool contSyms, breakSyms: seq[PSym] # to transform 'continue' and 'break' deferDetected, tooEarly: bool graph: ModuleGraph @@ -927,6 +927,141 @@ proc commonOptimizations*(g: ModuleGraph; idgen: IdGenerator; c: PSym, n: PNode) else: result = n +import nimsets + +proc caseBranchMatchesExpr(branch, matched: PNode): bool = + for i in 0 ..< branch.len-1: + if branch[i].kind == nkRange: + if overlap(branch[i], matched): return true + elif exprStructuralEquivalent(branch[i], matched): + return true + +proc pickCaseBranch(caseExpr, matched: PNode): int = + let endsWithElse = caseExpr[^1].kind == nkElse + for i in 1.. resultPos and c.transCon.owner.ast[resultPos] != nil result = transform(c, n) popTransCon(c) incl(result.flags, nfTransf) diff --git a/tests/objects/mobject_default_value.nim b/tests/objects/mobject_default_value.nim new file mode 100644 index 0000000000000..2245495015075 --- /dev/null +++ b/tests/objects/mobject_default_value.nim @@ -0,0 +1,15 @@ +type + Clean = object + mem: int + Default* = object + poi: int = 12 + clc: Clean + se*: range[0'i32 .. high(int32)] + + NonDefault* = object + poi: int + + PrellDeque*[T] = object + pendingTasks*: range[0'i32 .. high(int32)] + head: T + tail: T diff --git a/tests/objects/tobject_default_value.nim b/tests/objects/tobject_default_value.nim new file mode 100644 index 0000000000000..2a71a4c19817f --- /dev/null +++ b/tests/objects/tobject_default_value.nim @@ -0,0 +1,238 @@ +discard """ + matrix: "-d:nimRangeDefault" + targets: "c js" +""" + +import times + +type + Guess = object + poi: DateTime + +block: + var x: Guess + discard x + + discard Guess() + +import mobject_default_value + +block: + let x = Default() + doAssert x.se == 0'i32 +# echo Default(poi: 12) +# echo Default(poi: 17) + +# echo NonDefault(poi: 77) + +block: + var x: Default + doAssert x.se == 0'i32 + +type + ObjectBase = object of RootObj + value = 12 + + Object = object of ObjectBase + time: float = 1.2 + date: int + scale: range[1..10] + + Object2 = object + name: Object + + Object3 = object + obj: Object2 + + ObjectTuple = tuple + base: ObjectBase + typ: int + obj: Object + + Ref = ref object of ObjectBase + + RefInt = ref object of Ref + data = 73 + +var t {.threadvar.}: Default +# var m1, m2 {.threadvar.}: Default + +block: + doAssert t.se == 0'i32 + +block: + var x: ObjectBase + doAssert x.value == 12 + let y = default(ObjectBase) + doAssert y.value == 12 + +block: + var x: Object + doAssert x.value == 12 + doAssert x.time == 1.2 + doAssert x.scale == 1 + let y = default(Object) + doAssert y.value == 12 + doAssert y.time == 1.2 + doAssert y.scale == 1 + + var x1, x2, x3: Object + doAssert x1.value == 12 + doAssert x1.time == 1.2 + doAssert x1.scale == 1 + doAssert x2.value == 12 + doAssert x2.time == 1.2 + doAssert x2.scale == 1 + doAssert x3.value == 12 + doAssert x3.time == 1.2 + doAssert x3.scale == 1 + +block: + var x: Ref + new(x) + doAssert x.value == 12, "Ref.value = " & $x.value + + var y: RefInt + new(y) + doAssert y.value == 12 + doAssert y.data == 73 + +# block: # object array +# var x: ObjectArray +# echo x + +block: + var x: Object2 + doAssert x.name.value == 12 + doAssert x.name.time == 1.2 + doAssert x.name.scale == 1 + +block: + var x: Object3 + doAssert x.obj.name.value == 12 + doAssert x.obj.name.time == 1.2 + doAssert x.obj.name.scale == 1 + +# block: #seq +# var x = newSeq[Object](10) +# echo x + +block: # array + var x: array[10, Object] + let y = x[0] + doAssert y.value == 12 + doAssert y.time == 1.2 + doAssert y.scale == 1 + +block: # array + var x {.noinit.}: array[10, Object] + discard x + +block: # tuple + var x: ObjectTuple + doAssert x.base.value == 12 + doAssert x.typ == 0 + doAssert x.obj.time == 1.2 + doAssert x.obj.date == 0 + doAssert x.obj.scale == 1 + doAssert x.obj.value == 12 + +type + ObjectArray = object + data: array[10, Object] + +block: + var x: ObjectArray + let y = x.data[0] + doAssert y.value == 12 + doAssert y.time == 1.2 + doAssert y.scale == 1 + + +block: + var x: PrellDeque[int] + doAssert x.pendingTasks == 0 + +type + Color = enum + Red, Blue, Yellow + + ObjectVarint = object + case kind: Color + of Red: + data: int = 10 + of Blue: + fill = "123" + of Yellow: + time = 1.8'f32 + + ObjectVarint1 = object + case kind: Color = Blue + of Red: + data1: int = 10 + of Blue: + fill2 = "123" + cry: float + of Yellow: + time3 = 1.8'f32 + him: int + +block: + var x = ObjectVarint(kind: Red) + doAssert x.kind == Red + doAssert x.data == 10 + +block: + var x = ObjectVarint(kind: Blue) + doAssert x.kind == Blue + doAssert x.fill == "123" + +block: + var x = ObjectVarint(kind: Yellow) + doAssert x.kind == Yellow + doAssert typeof(x.time) is float32 + +block: + var x: ObjectVarint1 + doAssert x.kind == Blue + doAssert x.fill2 == "123" + x.cry = 326 + + +type + ObjectVarint2 = object + case kind: Color + of Red: + data: int = 10 + of Blue: + fill = "123" + of Yellow: + time = 1.8'f32 + + ObjectVarint3 = object + case kind: Color = Blue + of Red: + data1: int = 10 + of Blue: + case name: Color = Blue + of Blue: + go = 12 + else: + temp = 66 + fill2 = "123" + cry: float + of Yellow: + time3 = 1.8'f32 + him: int + +block: + var x: ObjectVarint3 + doAssert x.kind == Blue + doAssert x.name == Blue + doAssert x.go == 12 + +block: + var x = ObjectVarint3(kind: Blue, name: Red, temp: 99) + doAssert x.kind == Blue + doAssert x.name == Red + doAssert x.temp == 99 From dc9c8daeeb7ea1160184f352d23c7de23f82d46a Mon Sep 17 00:00:00 2001 From: flywind Date: Wed, 18 May 2022 15:24:10 +0800 Subject: [PATCH 02/52] add cpp target --- compiler/sem.nim | 158 ++++++++++++++++++++++++ compiler/semexprs.nim | 2 +- compiler/semmagic.nim | 91 +------------- compiler/semobjconstr.nim | 9 -- compiler/semstmts.nim | 2 +- compiler/transf.nim | 155 ++--------------------- lib/system.nim | 5 + tests/objects/tobject_default_value.nim | 18 +-- 8 files changed, 185 insertions(+), 255 deletions(-) diff --git a/compiler/sem.nim b/compiler/sem.nim index 70c57864c5d09..3ecadf3fc5c68 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -535,6 +535,164 @@ proc setGenericParamsMisc(c: PContext; n: PNode) = else: n[miscPos][1] = orig +proc caseBranchMatchesExpr(branch, matched: PNode): bool = + for i in 0 ..< branch.len-1: + if branch[i].kind == nkRange: + if overlap(branch[i], matched): return true + elif exprStructuralEquivalent(branch[i], matched): + return true + +proc pickCaseBranchIndex(caseExpr, matched: PNode): int = + let endsWithElse = caseExpr[^1].kind == nkElse + for i in 1.. Date: Sun, 14 Aug 2022 13:21:34 +0800 Subject: [PATCH 03/52] add result support --- compiler/semstmts.nim | 18 ++++++++++++++++++ compiler/transf.nim | 14 -------------- tests/objects/tobject_default_value.nim | 16 ++++++++++++++++ 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index a8b5ef59f31b0..aef0cee39d7a9 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -1606,6 +1606,19 @@ proc addResult(c: PContext, n: PNode, t: PType, owner: TSymKind) = n.add newSymNode(c.p.resultSym) addParamOrResult(c, c.p.resultSym, owner) +proc addDefaultFieldForResult(c: PContext, n: PNode, t: PType) = + if t != nil and n.len > resultPos and n[resultPos] != nil: + var field = defaultNodeField(c, n[resultPos]) + if field != nil: + field = semExpr(c, field) + if n[bodyPos].kind in {nkStmtList, nkStmtListExpr}: + n[bodyPos].sons.insert(newTree(nkAsgn, n[resultPos], field), 0) + else: + var bodyWithDefaultResult = newNodeIT(nkStmtList, n.info, nil) + bodyWithDefaultResult.add newTree(nkAsgn, n[resultPos], field) + bodyWithDefaultResult.add n[bodyPos] + n[bodyPos] = bodyWithDefaultResult + proc semProcAnnotation(c: PContext, prc: PNode; validPragmas: TSpecialWords): PNode = # Mirrored with semVarMacroPragma @@ -1691,6 +1704,7 @@ proc semInferredLambda(c: PContext, pt: TIdTable, n: PNode): PNode {.nosinks.} = pushProcCon(c, s) addResult(c, n, n.typ[0], skProc) s.ast[bodyPos] = hloBody(c, semProcBody(c, n[bodyPos])) + addDefaultFieldForResult(c, n, n.typ[0]) trackProc(c, s, s.ast[bodyPos]) popProcCon(c) popOwner(c) @@ -2113,6 +2127,8 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, pushProcCon(c, s) addResult(c, n, s.typ[0], skProc) s.ast[bodyPos] = hloBody(c, semProcBody(c, n[bodyPos])) + if s.kind notin {skMacro, skTemplate} and s.magic == mNone: + addDefaultFieldForResult(c, n, s.typ[0]) trackProc(c, s, s.ast[bodyPos]) popProcCon(c) elif efOperand notin flags: @@ -2127,6 +2143,8 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, maybeAddResult(c, s, n) # semantic checking also needed with importc in case used in VM s.ast[bodyPos] = hloBody(c, semProcBody(c, n[bodyPos])) + if s.kind notin {skMacro, skTemplate} and s.magic == mNone: + addDefaultFieldForResult(c, n, s.typ[0]) # unfortunately we cannot skip this step when in 'system.compiles' # context as it may even be evaluated in 'system.compiles': trackProc(c, s, s.ast[bodyPos]) diff --git a/compiler/transf.nim b/compiler/transf.nim index b44c45a6b659a..4b1959024ab3b 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -936,20 +936,6 @@ proc transform(c: PTransf, n: PNode): PNode = oldDeferAnchor = c.deferAnchor c.deferAnchor = n - # if c.genResult: - # c.genResult = false - # result = newNodeIT(nkStmtList, n.info, nil) - # let toInit = c.getCurrOwner().ast[resultPos] - - # if toInit.typ != nil: - # let field = defaultNodeField(c.graph, toInit) - - # if field != nil: - # result.add newTree(nkAsgn, toInit, field) - - # result.add transform(c, n) - # return result - case n.kind of nkSym: result = transformSym(c, n) diff --git a/tests/objects/tobject_default_value.nim b/tests/objects/tobject_default_value.nim index 82e1275edacdc..9c25e9bc08571 100644 --- a/tests/objects/tobject_default_value.nim +++ b/tests/objects/tobject_default_value.nim @@ -66,11 +66,27 @@ block: let y = default(ObjectBase) doAssert y.value == 12 + proc hello(): ObjectBase = + discard + + let z = hello() + doAssert z.value == 12 + block: var x: Object doAssert x.value == 12 doAssert x.time == 1.2 doAssert x.scale == 1 + + proc hello(): Object = + var dummy = 1 + dummy += 18 + + let h1 = hello() + doAssert h1.value == 12 + doAssert h1.time == 1.2 + doAssert h1.scale == 1 + let y = default(Object) doAssert y.value == 12 doAssert y.time == 1.2 From 6f8d6e980b50951d5d07147b7943f81fe7a48f17 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+xflywind@users.noreply.github.com> Date: Sun, 14 Aug 2022 13:26:46 +0800 Subject: [PATCH 04/52] add nimPreviewRangeDefault --- compiler/nim.cfg | 1 + compiler/semtypes.nim | 2 +- tests/objects/tobject_default_value.nim | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/compiler/nim.cfg b/compiler/nim.cfg index 7ed70fb5f2a3f..91771e753ad48 100644 --- a/compiler/nim.cfg +++ b/compiler/nim.cfg @@ -6,6 +6,7 @@ define:booting define:nimcore define:nimPreviewFloatRoundtrip define:nimPreviewSlimSystem +define:nimPreviewRangeDefault #import:"$projectpath/testability" diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 948776d43f7c3..277f8b77c347e 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -788,7 +788,7 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int, typ = errorType(c) else: typ = semTypeNode(c, n[^2], nil) - if c.graph.config.isDefined("nimRangeDefault") and typ.skipTypes(abstractInst).kind in {tyRange, tyOrdinal}: + if c.graph.config.isDefined("nimPreviewRangeDefault") and typ.skipTypes(abstractInst).kind in {tyRange, tyOrdinal}: n[^1] = newIntNode(nkIntLit, firstOrd(c.config, typ)) n[^1].typ = typ hasDefaultField = true diff --git a/tests/objects/tobject_default_value.nim b/tests/objects/tobject_default_value.nim index 9c25e9bc08571..014ba2eb601c2 100644 --- a/tests/objects/tobject_default_value.nim +++ b/tests/objects/tobject_default_value.nim @@ -1,5 +1,5 @@ discard """ - matrix: "-d:nimRangeDefault" + matrix: "-d:nimPreviewRangeDefault" targets: "c cpp js" """ From 2a041c5675282d734d300c27b9e9d852e4edda73 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+xflywind@users.noreply.github.com> Date: Sun, 14 Aug 2022 17:13:33 +0800 Subject: [PATCH 05/52] reduce --- compiler/transf.nim | 3 --- 1 file changed, 3 deletions(-) diff --git a/compiler/transf.nim b/compiler/transf.nim index 4b1959024ab3b..9e6745c5af18e 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -46,7 +46,6 @@ type module: PSym transCon: PTransCon # top of a TransCon stack inlining: int # > 0 if we are in inlining context (copy vars) - genResult: bool contSyms, breakSyms: seq[PSym] # to transform 'continue' and 'break' deferDetected, tooEarly: bool graph: ModuleGraph @@ -935,7 +934,6 @@ proc transform(c: PTransf, n: PNode): PNode = nkBlockStmt, nkBlockExpr}: oldDeferAnchor = c.deferAnchor c.deferAnchor = n - case n.kind of nkSym: result = transformSym(c, n) @@ -1087,7 +1085,6 @@ proc processTransf(c: PTransf, n: PNode, owner: PSym): PNode = # nodes into an empty node. if nfTransf in n.flags: return n pushTransCon(c, newTransCon(owner)) - c.genResult = c.getCurrOwner().kind in routineKinds and c.transCon.owner.ast.len > resultPos and c.transCon.owner.ast[resultPos] != nil result = transform(c, n) popTransCon(c) incl(result.flags, nfTransf) From 1fc40f51b6af01a286fe847652f971767a872cd3 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+xflywind@users.noreply.github.com> Date: Sun, 14 Aug 2022 17:14:09 +0800 Subject: [PATCH 06/52] use orc --- tests/objects/tobject_default_value.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/objects/tobject_default_value.nim b/tests/objects/tobject_default_value.nim index 014ba2eb601c2..01bf8b3b69a2f 100644 --- a/tests/objects/tobject_default_value.nim +++ b/tests/objects/tobject_default_value.nim @@ -1,5 +1,5 @@ discard """ - matrix: "-d:nimPreviewRangeDefault" + matrix: "-d:nimPreviewRangeDefault; -d:nimPreviewRangeDefault --mm:orc" targets: "c cpp js" """ From 0aaf39bf8df930399aca3b9d9e194806736bcf2a Mon Sep 17 00:00:00 2001 From: xflywind <43030857+xflywind@users.noreply.github.com> Date: Sun, 14 Aug 2022 19:37:53 +0800 Subject: [PATCH 07/52] refactor common parts --- compiler/sem.nim | 124 +++++++++++------------- tests/objects/tobject_default_value.nim | 4 - 2 files changed, 56 insertions(+), 72 deletions(-) diff --git a/compiler/sem.nim b/compiler/sem.nim index 3ecadf3fc5c68..5c85561189d9f 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -550,6 +550,59 @@ proc pickCaseBranchIndex(caseExpr, matched: PNode): int = if endsWithElse: return caseExpr.len - 1 +proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode, hasDefault: var bool): seq[PNode] + +proc defaultFieldForArray(c: PContext, recNode: PNode, hasDefault: var bool): PNode = + let recType = recNode.typ.skipTypes({tyGenericInst, tyAlias, tySink}) + var objExpr = newTree(nkObjConstr, newNodeIT(nkType, recNode.info, recType[1])) + objExpr.typ = recType[1].skipTypes({tyGenericInst, tyAlias, tySink}) + var t = objExpr.typ + while true: + objExpr.sons.add defaultFieldsForTheUninitialized(c, t.n, hasDefault) + let base = t[0] + if base == nil: + break + t = skipTypes(base, skipPtrs) + + let node = newNode(nkIntLit) + node.intVal = toInt(lengthOrd(c.graph.config, recType)) + result = newTree(nkCall, newSymNode(getSysSym(c.graph, recNode.info, "newDefaultArray"), recNode.info), + # var asgnExpr = newTree(nkCall, newSymNode(getCompilerProc(c.graph, "newDefaultArray")), + node, + objExpr + ) + result.typ = recNode.typ + result.flags.incl nfUseDefaultField + + # asgnExpr.sons.setLen(toInt(lengthOrd(c, recType))) + # for i in 0.. Date: Sun, 14 Aug 2022 19:41:46 +0800 Subject: [PATCH 08/52] add tuple support --- compiler/sem.nim | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/compiler/sem.nim b/compiler/sem.nim index 5c85561189d9f..8ea07ae918512 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -634,16 +634,16 @@ proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode, hasDefault: v asgnExpr.sons.add defaultFieldsForTheUninitialized(c, recType.n, hasDefault) result.add newTree(nkExprColonExpr, recNode, asgnExpr) elif recType.kind == tyArray and recType[1].skipTypes({tyGenericInst, tyAlias, tySink}).kind == tyObject: - let asgnExpr2 = defaultFieldForArray(c, recNode, hasDefault) - result.add newTree(nkExprColonExpr, recNode, asgnExpr2) + let asgnExpr = defaultFieldForArray(c, recNode, hasDefault) + result.add newTree(nkExprColonExpr, recNode, asgnExpr) # asgnExpr.sons.setLen(toInt(lengthOrd(c.graph.config, recType))) # for i in 0.. Date: Sun, 14 Aug 2022 21:00:29 +0800 Subject: [PATCH 09/52] add testcase for tuple --- compiler/sem.nim | 10 ++------- tests/objects/tobject_default_value.nim | 30 ++++++++++++++++++------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/compiler/sem.nim b/compiler/sem.nim index 8ea07ae918512..cdf6ed872cb92 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -639,8 +639,6 @@ proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode, hasDefault: v # asgnExpr.sons.setLen(toInt(lengthOrd(c.graph.config, recType))) # for i in 0.. Date: Sun, 14 Aug 2022 22:11:03 +0800 Subject: [PATCH 10/52] cleanup; fixes nimsuggest tests --- compiler/sem.nim | 11 +++-------- lib/system.nim | 8 ++++---- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/compiler/sem.nim b/compiler/sem.nim index cdf6ed872cb92..4243b370d3b65 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -565,19 +565,14 @@ proc defaultFieldForArray(c: PContext, recNode: PNode, hasDefault: var bool): PN t = skipTypes(base, skipPtrs) let node = newNode(nkIntLit) - node.intVal = toInt(lengthOrd(c.graph.config, recType)) + node.intVal = toInt64(lengthOrd(c.graph.config, recType)) result = newTree(nkCall, newSymNode(getSysSym(c.graph, recNode.info, "newDefaultArray"), recNode.info), - # var asgnExpr = newTree(nkCall, newSymNode(getCompilerProc(c.graph, "newDefaultArray")), - node, - objExpr + objExpr, + node ) result.typ = recNode.typ result.flags.incl nfUseDefaultField - # asgnExpr.sons.setLen(toInt(lengthOrd(c, recType))) - # for i in 0.. Date: Sun, 14 Aug 2022 23:31:22 +0800 Subject: [PATCH 11/52] there is something wrong with cpp --- lib/system.nim | 4 +-- tests/objects/tobject_default_value.nim | 37 +++++++++++++------------ 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/lib/system.nim b/lib/system.nim index b0f63f46314da..7abcf5b768eac 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -573,8 +573,8 @@ when notJSnotNims and not defined(nimSeqsV2): template space(s: PGenericSeq): int {.dirty.} = s.reserved and not (seqShallowFlag or strlitFlag) -when not defined(nimdoc) and not defined(nimsuggest): - proc newDefaultArray*[T](y: T, N: static int): array[N, T] {.compilerproc.} = +when not defined(nimsuggest): + proc newDefaultArray*[T](y: T, N: static int): array[N, T] = # todo fixme for i in 0..N-1: result[i] = y diff --git a/tests/objects/tobject_default_value.nim b/tests/objects/tobject_default_value.nim index 45ed6ca6da625..401ed4b6a50ea 100644 --- a/tests/objects/tobject_default_value.nim +++ b/tests/objects/tobject_default_value.nim @@ -144,24 +144,25 @@ block: # array var x {.noinit.}: array[10, Object] discard x -block: # tuple - var x: ObjectTuple - doAssert x.base.value == 12 - doAssert x.typ == 0 - doAssert x.obj.time == 1.2 - doAssert x.obj.date == 0 - doAssert x.obj.scale == 1 - doAssert x.obj.value == 12 - -block: # tuple in object - var x: TupleInObject - doAssert x.data.base.value == 12 - doAssert x.data.typ == 0 - doAssert x.data.obj.time == 1.2 - doAssert x.data.obj.date == 0 - doAssert x.data.obj.scale == 1 - doAssert x.data.obj.value == 12 - doAssert x.size == 777 +when not defined(cpp): # todo fixme + block: # tuple + var x: ObjectTuple + doAssert x.base.value == 12 + doAssert x.typ == 0 + doAssert x.obj.time == 1.2 + doAssert x.obj.date == 0 + doAssert x.obj.scale == 1 + doAssert x.obj.value == 12 + + block: # tuple in object + var x: TupleInObject + doAssert x.data.base.value == 12 + doAssert x.data.typ == 0 + doAssert x.data.obj.time == 1.2 + doAssert x.data.obj.date == 0 + doAssert x.data.obj.scale == 1 + doAssert x.data.obj.value == 12 + doAssert x.size == 777 type ObjectArray = object From 8a91de7535bc1cee19feac47cabea58ea5d01f82 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+xflywind@users.noreply.github.com> Date: Mon, 15 Aug 2022 08:18:24 +0800 Subject: [PATCH 12/52] remove --- lib/system.nim | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/system.nim b/lib/system.nim index 7abcf5b768eac..f02149dbdea77 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -573,11 +573,6 @@ when notJSnotNims and not defined(nimSeqsV2): template space(s: PGenericSeq): int {.dirty.} = s.reserved and not (seqShallowFlag or strlitFlag) -when not defined(nimsuggest): - proc newDefaultArray*[T](y: T, N: static int): array[N, T] = # todo fixme - for i in 0..N-1: - result[i] = y - when notJSnotNims: include "system/hti" @@ -3181,3 +3176,7 @@ when notJSnotNims and not defined(nimSeqsV2): moveMem(addr y[0], addr x[0], x.len) assert y == "abcgh" discard + +proc newDefaultArray*[T](y: T, N: static int): array[N, T] = # todo fixme + for i in 0..N-1: + result[i] = y From e119505ab67555f2834bdfc12c99b549030ef11e Mon Sep 17 00:00:00 2001 From: xflywind <43030857+xflywind@users.noreply.github.com> Date: Mon, 15 Aug 2022 10:25:02 +0800 Subject: [PATCH 13/52] add support for seqs --- compiler/semtypes.nim | 23 ++++++++++++----------- lib/system/seqs_v2.nim | 2 ++ tests/objects/tobject_default_value.nim | 18 +++++++++++++++--- 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 277f8b77c347e..c384b4854c746 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -272,17 +272,18 @@ proc semRange(c: PContext, n: PNode, prev: PType): PType = if n.len == 2: if isRange(n[1]): result = semRangeAux(c, n[1], prev) - let n = result.n - if n[0].kind in {nkCharLit..nkUInt64Lit} and n[0].intVal > 0: - incl(result.flags, tfRequiresInit) - elif n[1].kind in {nkCharLit..nkUInt64Lit} and n[1].intVal < 0: - incl(result.flags, tfRequiresInit) - elif n[0].kind in {nkFloatLit..nkFloat64Lit} and - n[0].floatVal > 0.0: - incl(result.flags, tfRequiresInit) - elif n[1].kind in {nkFloatLit..nkFloat64Lit} and - n[1].floatVal < 0.0: - incl(result.flags, tfRequiresInit) + if not isDefined(c.config, "nimPreviewRangeDefault"): + let n = result.n + if n[0].kind in {nkCharLit..nkUInt64Lit} and n[0].intVal > 0: + incl(result.flags, tfRequiresInit) + elif n[1].kind in {nkCharLit..nkUInt64Lit} and n[1].intVal < 0: + incl(result.flags, tfRequiresInit) + elif n[0].kind in {nkFloatLit..nkFloat64Lit} and + n[0].floatVal > 0.0: + incl(result.flags, tfRequiresInit) + elif n[1].kind in {nkFloatLit..nkFloat64Lit} and + n[1].floatVal < 0.0: + incl(result.flags, tfRequiresInit) else: if n[1].kind == nkInfix and considerQuotedIdent(c, n[1][0]).s == "..<": localError(c.config, n[0].info, "range types need to be constructed with '..', '..<' is not supported") diff --git a/lib/system/seqs_v2.nim b/lib/system/seqs_v2.nim index 1194f40efff75..dbc110c27c312 100644 --- a/lib/system/seqs_v2.nim +++ b/lib/system/seqs_v2.nim @@ -125,6 +125,8 @@ proc setLen[T](s: var seq[T], newlen: Natural) = if xu.p == nil or xu.p.cap < newlen: xu.p = cast[typeof(xu.p)](prepareSeqAdd(oldLen, xu.p, newlen - oldLen, sizeof(T), alignof(T))) xu.len = newlen + for i in oldLen.. Date: Mon, 15 Aug 2022 10:45:45 +0800 Subject: [PATCH 14/52] fixes style --- 9cc | 1 + lib/system/seqs_v2.nim | 2 +- netty | 1 + nimble | 1 + pixie | 1 + test.nim | 1 + 6 files changed, 6 insertions(+), 1 deletion(-) create mode 160000 9cc create mode 160000 netty create mode 160000 nimble create mode 160000 pixie create mode 100644 test.nim diff --git a/9cc b/9cc new file mode 160000 index 0000000000000..ea2f4b8bdedef --- /dev/null +++ b/9cc @@ -0,0 +1 @@ +Subproject commit ea2f4b8bdedef70dc9e1dcbf99c255c94e0fa2fe diff --git a/lib/system/seqs_v2.nim b/lib/system/seqs_v2.nim index dbc110c27c312..1ec7dfa1e8282 100644 --- a/lib/system/seqs_v2.nim +++ b/lib/system/seqs_v2.nim @@ -125,7 +125,7 @@ proc setLen[T](s: var seq[T], newlen: Natural) = if xu.p == nil or xu.p.cap < newlen: xu.p = cast[typeof(xu.p)](prepareSeqAdd(oldLen, xu.p, newlen - oldLen, sizeof(T), alignof(T))) xu.len = newlen - for i in oldLen.. Date: Mon, 15 Aug 2022 13:41:03 +0800 Subject: [PATCH 15/52] addd initial distinct support --- compiler/sem.nim | 37 ++++++++++----- compiler/semexprs.nim | 12 +++-- compiler/semmagic.nim | 37 ++++++++------- config/nim.cfg | 1 + tests/objects/tobject_default_value.nim | 63 ++++++++++++++++++++++++- 5 files changed, 114 insertions(+), 36 deletions(-) diff --git a/compiler/sem.nim b/compiler/sem.nim index 4243b370d3b65..3ba4f29ff08b7 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -552,10 +552,12 @@ proc pickCaseBranchIndex(caseExpr, matched: PNode): int = proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode, hasDefault: var bool): seq[PNode] +const defaultFieldsSkipTypes = {tyGenericInst, tyAlias, tySink, tyDistinct} + proc defaultFieldForArray(c: PContext, recNode: PNode, hasDefault: var bool): PNode = - let recType = recNode.typ.skipTypes({tyGenericInst, tyAlias, tySink}) + let recType = recNode.typ.skipTypes(defaultFieldsSkipTypes) var objExpr = newTree(nkObjConstr, newNodeIT(nkType, recNode.info, recType[1])) - objExpr.typ = recType[1].skipTypes({tyGenericInst, tyAlias, tySink}) + objExpr.typ = recType[1].skipTypes(defaultFieldsSkipTypes) var t = objExpr.typ while true: objExpr.sons.add defaultFieldsForTheUninitialized(c, t.n, hasDefault) @@ -574,11 +576,11 @@ proc defaultFieldForArray(c: PContext, recNode: PNode, hasDefault: var bool): PN result.flags.incl nfUseDefaultField proc defaultFieldForTuple(c: PContext, recNode: PNode, hasDefault: var bool): PNode = - let recType = recNode.typ.skipTypes({tyGenericInst, tyAlias, tySink}) + let recType = recNode.typ.skipTypes(defaultFieldsSkipTypes) var tupleExpr = newNodeI(nkTupleConstr, recNode.info) tupleExpr.typ = recType for s in recType.sons: - let sType = s.skipTypes({tyGenericInst, tyAlias, tySink}) + let sType = s.skipTypes(defaultFieldsSkipTypes) if sType.kind == tyObject: var asgnExpr = newTree(nkObjConstr, newNodeIT(nkType, recNode.info, s)) asgnExpr.typ = s @@ -618,17 +620,22 @@ proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode, hasDefault: v result.add defaultFieldsForTheUninitialized(c, recNode[selectedBranch][^1], hasDefault) of nkSym: let field = recNode.sym - let recType = recNode.typ.skipTypes({tyGenericInst, tyAlias, tySink}) + let recType = recNode.typ.skipTypes(defaultFieldsSkipTypes) if field.ast != nil: #Try to use default value result.add newTree(nkExprColonExpr, recNode, field.ast) hasDefault = true elif recType.kind == tyObject: - var asgnExpr = newTree(nkObjConstr, newNodeIT(nkType, recNode.info, recNode.typ)) - asgnExpr.typ = recNode.typ + let recTypeSkipDistinct = recType.skipTypes({tyDistinct}) + var asgnExpr = newTree(nkObjConstr, newNodeIT(nkType, recNode.info, recTypeSkipDistinct)) + asgnExpr.typ = recTypeSkipDistinct asgnExpr.flags.incl nfUseDefaultField asgnExpr.sons.add defaultFieldsForTheUninitialized(c, recType.n, hasDefault) + if recNode.typ.kind == tyDistinct: + asgnExpr = newTree(nkConv, newNodeIT(nkType, recNode.info, recNode.typ), asgnExpr) + asgnExpr.typ = recNode.typ + asgnExpr.flags.incl nfUseDefaultField result.add newTree(nkExprColonExpr, recNode, asgnExpr) - elif recType.kind == tyArray and recType[1].skipTypes({tyGenericInst, tyAlias, tySink}).kind == tyObject: + elif recType.kind == tyArray and recType[1].skipTypes(defaultFieldsSkipTypes).kind == tyObject: let asgnExpr = defaultFieldForArray(c, recNode, hasDefault) result.add newTree(nkExprColonExpr, recNode, asgnExpr) # asgnExpr.sons.setLen(toInt(lengthOrd(c.graph.config, recType))) @@ -653,13 +660,17 @@ proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode, hasDefault: v proc defaultNodeField(c: PContext, a: PNode): PNode = let aTyp = a.typ var hasDefault: bool - if aTyp.skipTypes({tyGenericInst, tyAlias, tySink}).kind == tyObject: - var asgnExpr = newTree(nkObjConstr, newNodeIT(nkType, a.info, aTyp)) - asgnExpr.typ = aTyp - asgnExpr.sons.add defaultFieldsForTheUninitialized(c, aTyp.skipTypes({tyGenericInst, tyAlias, tySink}).n, hasDefault) + if aTyp.skipTypes(defaultFieldsSkipTypes).kind == tyObject: + let aTypSkipDistinct = aTyp.skipTypes({tyDistinct}) + var asgnExpr = newTree(nkObjConstr, newNodeIT(nkType, a.info, aTypSkipDistinct)) + asgnExpr.typ = aTypSkipDistinct + asgnExpr.sons.add defaultFieldsForTheUninitialized(c, aTyp.skipTypes(defaultFieldsSkipTypes).n, hasDefault) if hasDefault: result = asgnExpr - elif aTyp.kind == tyArray and aTyp[1].skipTypes({tyGenericInst, tyAlias, tySink}).kind == tyObject: + if aTyp.kind == tyDistinct: + result = newTree(nkConv, newNodeIT(nkType, a.info, aTyp), result) + result.typ = aTyp + elif aTyp.kind == tyArray and aTyp[1].skipTypes(defaultFieldsSkipTypes).kind == tyObject: let asgnExpr = defaultFieldForArray(c, a, hasDefault) let arrayExpr = semExprWithType(c, asgnExpr) if hasDefault: diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index f14c438d0bdf8..38c0360497e45 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -2398,13 +2398,17 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode = of mDefault: result = semDirectOp(c, n, flags) let typ = result[^1].typ.skipTypes({tyTypeDesc}) - if typ.skipTypes({tyGenericInst, tyAlias, tySink}).kind == tyObject: - var asgnExpr = newTree(nkObjConstr, newNodeIT(nkType, result[^1].info, typ)) - asgnExpr.typ = typ + if typ.skipTypes(defaultFieldsSkipTypes).kind == tyObject: + let typSkipDistinct = typ.skipTypes({tyDistinct}) + var asgnExpr = newTree(nkObjConstr, newNodeIT(nkType, result[^1].info, typSkipDistinct)) + asgnExpr.typ = typSkipDistinct var hasDefault: bool - asgnExpr.sons.add defaultFieldsForTheUninitialized(c, typ.skipTypes({tyGenericInst, tyAlias, tySink}).n, hasDefault) + asgnExpr.sons.add defaultFieldsForTheUninitialized(c, typ.skipTypes(defaultFieldsSkipTypes).n, hasDefault) if hasDefault: result = semObjConstr(c, asgnExpr, flags) + if typ.kind == tyDistinct: + result = newTree(nkConv, newNodeIT(nkType, n.info, typ), result) + result.typ = typ else: result = semDirectOp(c, n, flags) diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index 696bd8130db1d..c6a503a5b2496 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -456,6 +456,24 @@ proc semPrivateAccess(c: PContext, n: PNode): PNode = c.currentScope.allowPrivateAccess.add t.sym result = newNodeIT(nkEmpty, n.info, getSysType(c.graph, n.info, tyVoid)) +proc addDefaultFieldForNew(c: PContext, n: PNode): PNode = + result = n + let typ = result[1].typ # new(x) + if typ.skipTypes({tyGenericInst, tyAlias, tySink}).kind == tyRef and typ.skipTypes({tyGenericInst, tyAlias, tySink})[0].kind == tyObject: + var asgnExpr = newTree(nkObjConstr, newNodeIT(nkType, result[1].info, typ)) + asgnExpr.typ = typ + var hasDefault: bool + var t = typ.skipTypes({tyGenericInst, tyAlias, tySink})[0] + while true: + asgnExpr.sons.add defaultFieldsForTheUninitialized(c, t.n, hasDefault) + let base = t[0] + if base == nil: + break + t = skipTypes(base, skipPtrs) + + if hasDefault: # todo apply default + result = newTree(nkAsgn, result[1], asgnExpr) + proc magicsAfterOverloadResolution(c: PContext, n: PNode, flags: TExprFlags): PNode = ## This is the preferred code point to implement magics. @@ -515,22 +533,7 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode, else: result = plugin(c, n) of mNew: - result = n - let typ = result[^1].typ - if typ.skipTypes({tyGenericInst, tyAlias, tySink}).kind == tyRef and typ.skipTypes({tyGenericInst, tyAlias, tySink})[0].kind == tyObject: - var asgnExpr = newTree(nkObjConstr, newNodeIT(nkType, result[^1].info, typ)) - asgnExpr.typ = typ - var hasDefault: bool - var t = typ.skipTypes({tyGenericInst, tyAlias, tySink})[0] - while true: - asgnExpr.sons.add defaultFieldsForTheUninitialized(c, t.n, hasDefault) - let base = t[0] - if base == nil: - break - t = skipTypes(base, skipPtrs) - - if hasDefault: # todo apply default - result = newTree(nkAsgn, result[^1], asgnExpr) + result = addDefaultFieldForNew(c, n) of mNewFinalize: # Make sure the finalizer procedure refers to a procedure if n[^1].kind == nkSym and n[^1].sym.kind notin {skProc, skFunc}: @@ -555,7 +558,7 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode, discard "already turned this one into a finalizer" else: bindTypeHook(c, turnFinalizerIntoDestructor(c, fin, n.info), n, attachedDestructor) - result = n + result = addDefaultFieldForNew(c, n) of mDestroy: result = n let t = n[1].typ.skipTypes(abstractVar) diff --git a/config/nim.cfg b/config/nim.cfg index 37d12a02d93c6..a9f581fa95c26 100644 --- a/config/nim.cfg +++ b/config/nim.cfg @@ -18,6 +18,7 @@ hint[LineTooLong]=off #hint[XDeclaredButNotUsed]=off threads:on +define:nimPreviewRangeDefault # Examples of how to setup a cross-compiler: # Nim can target architectures and OSes different than the local host diff --git a/tests/objects/tobject_default_value.nim b/tests/objects/tobject_default_value.nim index 0db80466ea55e..d0b4576a0f247 100644 --- a/tests/objects/tobject_default_value.nim +++ b/tests/objects/tobject_default_value.nim @@ -9,12 +9,19 @@ type Guess = object poi: DateTime + GuessDistinct = distinct Guess + block: var x: Guess - discard x - discard Guess() + var y: GuessDistinct + + discard y + + discard GuessDistinct(x) + + import mobject_default_value block: @@ -33,6 +40,11 @@ type ObjectBase = object of RootObj value = 12 + ObjectBaseDistinct = distinct ObjectBase + + DinstinctInObject = object + data: ObjectBaseDistinct + Object = object of ObjectBase time: float = 1.2 date: int @@ -58,6 +70,11 @@ type RefInt = ref object of Ref data = 73 + Ref2 = ref object of ObjectBase + + RefInt2 = ref object of Ref + data = 73 + var t {.threadvar.}: Default # var m1, m2 {.threadvar.}: Default @@ -76,6 +93,23 @@ block: let z = hello() doAssert z.value == 12 +block: + var x: ObjectBaseDistinct + doAssert ObjectBase(x).value == 12 + let y = default(ObjectBaseDistinct) + doAssert ObjectBase(y).value == 12 + + proc hello(): ObjectBaseDistinct = + discard + + let z = hello() + doAssert ObjectBase(z).value == 12 + +block: + var x: DinstinctInObject + + doAssert ObjectBase(x.data).value == 12 + block: var x: Object doAssert x.value == 12 @@ -117,6 +151,19 @@ block: doAssert y.value == 12 doAssert y.data == 73 +block: + var x: Ref2 + new(x, proc (x: Ref2) {.nimcall.} = discard "call Ref") + doAssert x.value == 12, "Ref.value = " & $x.value + + proc call(x: RefInt2) = + discard "call RefInt" + + var y: RefInt2 + new(y, call) + doAssert y.value == 12 + doAssert y.data == 73 + block: var x: Object2 doAssert x.name.value == 12 @@ -264,6 +311,18 @@ type time3 = 1.8'f32 him: int +block: + var x = ObjectVarint2(kind: Blue) + doAssert x.fill == "123" + +block: + proc check: ObjectVarint3 = + discard + var x = check() + doAssert x.kind == Blue + doAssert x.name == Blue + doAssert x.go == 12 + block: var x: ObjectVarint3 doAssert x.kind == Blue From d9d150419fdb4291dac2d75148eb357882f8bb99 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+xflywind@users.noreply.github.com> Date: Mon, 15 Aug 2022 13:47:40 +0800 Subject: [PATCH 16/52] remove links --- 9cc | 1 - netty | 1 - nimble | 1 - pixie | 1 - 4 files changed, 4 deletions(-) delete mode 160000 9cc delete mode 160000 netty delete mode 160000 nimble delete mode 160000 pixie diff --git a/9cc b/9cc deleted file mode 160000 index ea2f4b8bdedef..0000000000000 --- a/9cc +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ea2f4b8bdedef70dc9e1dcbf99c255c94e0fa2fe diff --git a/netty b/netty deleted file mode 160000 index 4e44bf163bb44..0000000000000 --- a/netty +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 4e44bf163bb44558d2dd250423a0924f0143de64 diff --git a/nimble b/nimble deleted file mode 160000 index d13f3b8ce288b..0000000000000 --- a/nimble +++ /dev/null @@ -1 +0,0 @@ -Subproject commit d13f3b8ce288b4dc8c34c219a4e050aaeaf43fc9 diff --git a/pixie b/pixie deleted file mode 160000 index 4afb0e58c45ca..0000000000000 --- a/pixie +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 4afb0e58c45cab2deed6bbf2a6d4253b52ac818d From 53c8bafe05d637e2cba949599dd53fea380fc2a5 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+xflywind@users.noreply.github.com> Date: Mon, 15 Aug 2022 13:49:37 +0800 Subject: [PATCH 17/52] typo --- test.nim | 1 - 1 file changed, 1 deletion(-) delete mode 100644 test.nim diff --git a/test.nim b/test.nim deleted file mode 100644 index c873e4015d851..0000000000000 --- a/test.nim +++ /dev/null @@ -1 +0,0 @@ -echo newDefaultArray(3, int) \ No newline at end of file From 036952c565956ac950d6c4198fd9b26c6dc53c24 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+xflywind@users.noreply.github.com> Date: Mon, 15 Aug 2022 16:26:42 +0800 Subject: [PATCH 18/52] fixes tuple defaults --- compiler/sem.nim | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/compiler/sem.nim b/compiler/sem.nim index 3ba4f29ff08b7..333930a2b5f89 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -581,22 +581,21 @@ proc defaultFieldForTuple(c: PContext, recNode: PNode, hasDefault: var bool): PN tupleExpr.typ = recType for s in recType.sons: let sType = s.skipTypes(defaultFieldsSkipTypes) + # todo handle distinct if sType.kind == tyObject: var asgnExpr = newTree(nkObjConstr, newNodeIT(nkType, recNode.info, s)) asgnExpr.typ = s asgnExpr.sons.add defaultFieldsForTheUninitialized(c, sType.n, hasDefault) tupleExpr.add asgnExpr - elif sType.kind in {tyInt..tyInt64, tyUInt..tyUInt64}: - let asgnExpr = newIntTypeNode(int64(0), sType) - asgnExpr.flags.incl nfUseDefaultField - tupleExpr.add asgnExpr - elif sType.kind in tyFloat..tyFloat64: - let asgnExpr = - if sType.kind == tyFloat32: - newFloatNode(nkFloat32Lit, BiggestFloat(0.0)) - else: - newFloatNode(nkFloatLit, BiggestFloat(0.0)) + else: + let asgnType = newType(tyTypeDesc, nextTypeId(c.idgen), s.owner) + rawAddSon(asgnType, s) + let asgnExpr = newTree(nkCall, + newSymNode(getSysMagic(c.graph, recNode.info, "default", mDefault)), + newNodeIT(nkType, recNode.info, asgnType) + ) asgnExpr.flags.incl nfUseDefaultField + asgnExpr.typ = s tupleExpr.add asgnExpr result = tupleExpr From 50524687973d06db78f4d745e525996bbc66e7c3 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+xflywind@users.noreply.github.com> Date: Tue, 16 Aug 2022 09:33:05 +0800 Subject: [PATCH 19/52] add rangedefault --- tests/config.nims | 1 + tests/js/trepr.nim | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/config.nims b/tests/config.nims index 894c4bea0adc1..437d40635066f 100644 --- a/tests/config.nims +++ b/tests/config.nims @@ -40,3 +40,4 @@ switch("define", "nimPreviewFloatRoundtrip") switch("define", "nimPreviewDotLikeOps") switch("define", "nimPreviewJsonutilsHoleyEnum") switch("define", "nimPreviewHashRef") +switch("define", "nimPreviewRangeDefault") diff --git a/tests/js/trepr.nim b/tests/js/trepr.nim index c63b64d3a71fc..047016aea9735 100644 --- a/tests/js/trepr.nim +++ b/tests/js/trepr.nim @@ -303,7 +303,7 @@ g = {}, h = {}, i = ["", "", ""], j = @[], -k = 0, +k = -12, l = [a = "", b = @[]], m = nil, From ec8fd15d7c19e504a1e543b65b2c5029e7e77c6c Mon Sep 17 00:00:00 2001 From: xflywind <43030857+xflywind@users.noreply.github.com> Date: Tue, 16 Aug 2022 09:39:39 +0800 Subject: [PATCH 20/52] add cpp support --- tests/objects/tobject_default_value.nim | 37 ++++++++++++------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/tests/objects/tobject_default_value.nim b/tests/objects/tobject_default_value.nim index d0b4576a0f247..281cd419d1a72 100644 --- a/tests/objects/tobject_default_value.nim +++ b/tests/objects/tobject_default_value.nim @@ -203,25 +203,24 @@ block: # array var x {.noinit.}: array[10, Object] discard x -when not defined(cpp): # todo fixme - block: # tuple - var x: ObjectTuple - doAssert x.base.value == 12 - doAssert x.typ == 0 - doAssert x.obj.time == 1.2 - doAssert x.obj.date == 0 - doAssert x.obj.scale == 1 - doAssert x.obj.value == 12 - - block: # tuple in object - var x: TupleInObject - doAssert x.data.base.value == 12 - doAssert x.data.typ == 0 - doAssert x.data.obj.time == 1.2 - doAssert x.data.obj.date == 0 - doAssert x.data.obj.scale == 1 - doAssert x.data.obj.value == 12 - doAssert x.size == 777 +block: # tuple + var x: ObjectTuple + doAssert x.base.value == 12 + doAssert x.typ == 0 + doAssert x.obj.time == 1.2 + doAssert x.obj.date == 0 + doAssert x.obj.scale == 1 + doAssert x.obj.value == 12 + +block: # tuple in object + var x: TupleInObject + doAssert x.data.base.value == 12 + doAssert x.data.typ == 0 + doAssert x.data.obj.time == 1.2 + doAssert x.data.obj.date == 0 + doAssert x.data.obj.scale == 1 + doAssert x.data.obj.value == 12 + doAssert x.size == 777 type ObjectArray = object From 6a5014c7ae7b270bf7ed3e3f08cdfbe9a6b106a8 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+xflywind@users.noreply.github.com> Date: Tue, 16 Aug 2022 11:55:47 +0800 Subject: [PATCH 21/52] fixes one more bugs --- compiler/sem.nim | 10 +- lib/system.nim | 2 +- tests/objects/tobject_default_value.nim | 426 +++++++++++++----------- 3 files changed, 234 insertions(+), 204 deletions(-) diff --git a/compiler/sem.nim b/compiler/sem.nim index 333930a2b5f89..d46d11d77aa13 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -568,9 +568,10 @@ proc defaultFieldForArray(c: PContext, recNode: PNode, hasDefault: var bool): PN let node = newNode(nkIntLit) node.intVal = toInt64(lengthOrd(c.graph.config, recType)) - result = newTree(nkCall, newSymNode(getSysSym(c.graph, recNode.info, "newDefaultArray"), recNode.info), - objExpr, - node + result = semExpr(c, newTree(nkCall, newSymNode(getSysSym(c.graph, recNode.info, "newDefaultArray"), recNode.info), + node, + objExpr + ) ) result.typ = recNode.typ result.flags.incl nfUseDefaultField @@ -590,10 +591,11 @@ proc defaultFieldForTuple(c: PContext, recNode: PNode, hasDefault: var bool): PN else: let asgnType = newType(tyTypeDesc, nextTypeId(c.idgen), s.owner) rawAddSon(asgnType, s) - let asgnExpr = newTree(nkCall, + let asgnExpr = semExpr(c, newTree(nkCall, newSymNode(getSysMagic(c.graph, recNode.info, "default", mDefault)), newNodeIT(nkType, recNode.info, asgnType) ) + ) asgnExpr.flags.incl nfUseDefaultField asgnExpr.typ = s tupleExpr.add asgnExpr diff --git a/lib/system.nim b/lib/system.nim index f02149dbdea77..00bd8fe0aa344 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -3177,6 +3177,6 @@ when notJSnotNims and not defined(nimSeqsV2): assert y == "abcgh" discard -proc newDefaultArray*[T](y: T, N: static int): array[N, T] = # todo fixme +proc newDefaultArray*[T](N: static int, y: T): array[N, T] = # todo fixme for i in 0..N-1: result[i] = y diff --git a/tests/objects/tobject_default_value.nim b/tests/objects/tobject_default_value.nim index 281cd419d1a72..f3547aa5d94d1 100644 --- a/tests/objects/tobject_default_value.nim +++ b/tests/objects/tobject_default_value.nim @@ -82,64 +82,45 @@ block: doAssert t.se == 0'i32 block: - var x: ObjectBase - doAssert x.value == 12 - let y = default(ObjectBase) - doAssert y.value == 12 - - proc hello(): ObjectBase = - discard - - let z = hello() - doAssert z.value == 12 - -block: - var x: ObjectBaseDistinct - doAssert ObjectBase(x).value == 12 - let y = default(ObjectBaseDistinct) - doAssert ObjectBase(y).value == 12 - - proc hello(): ObjectBaseDistinct = - discard - - let z = hello() - doAssert ObjectBase(z).value == 12 - -block: - var x: DinstinctInObject - - doAssert ObjectBase(x.data).value == 12 - -block: - var x: Object - doAssert x.value == 12 - doAssert x.time == 1.2 - doAssert x.scale == 1 - - proc hello(): Object = - var dummy = 1 - dummy += 18 + type + Color = enum + Red, Blue, Yellow + + type + ObjectVarint3 = object # fixme it doesn't work with static + case kind: Color = Blue + of Red: + data1: int = 10 + of Blue: + case name: Color = Blue + of Blue: + go = 12 + else: + temp = 66 + fill2 = "123" + cry: float + of Yellow: + time3 = 1.8'f32 + him: int + block: + proc check: ObjectVarint3 = + discard + var x = check() + doAssert x.kind == Blue + doAssert x.name == Blue + doAssert x.go == 12 - let h1 = hello() - doAssert h1.value == 12 - doAssert h1.time == 1.2 - doAssert h1.scale == 1 + block: + var x: ObjectVarint3 + doAssert x.kind == Blue + doAssert x.name == Blue + doAssert x.go == 12 - let y = default(Object) - doAssert y.value == 12 - doAssert y.time == 1.2 - doAssert y.scale == 1 - - var x1, x2, x3: Object - doAssert x1.value == 12 - doAssert x1.time == 1.2 - doAssert x1.scale == 1 - doAssert x2.value == 12 - doAssert x2.time == 1.2 - doAssert x2.scale == 1 - doAssert x3.value == 12 - doAssert x3.time == 1.2 - doAssert x3.scale == 1 + block: + var x = ObjectVarint3(kind: Blue, name: Red, temp: 99) + doAssert x.kind == Blue + doAssert x.name == Red + doAssert x.temp == 99 block: var x: Ref @@ -164,172 +145,219 @@ block: doAssert y.value == 12 doAssert y.data == 73 -block: - var x: Object2 - doAssert x.name.value == 12 - doAssert x.name.time == 1.2 - doAssert x.name.scale == 1 +template main = + block: + var x: ObjectBase + doAssert x.value == 12 + let y = default(ObjectBase) + doAssert y.value == 12 -block: - var x: Object3 - doAssert x.obj.name.value == 12 - doAssert x.obj.name.time == 1.2 - doAssert x.obj.name.scale == 1 + proc hello(): ObjectBase = + discard -when defined(gcArc) or defined(gcOrc): - block: #seq - var x = newSeq[Object](10) - let y = x[0] + let z = hello() + doAssert z.value == 12 + + block: + var x: ObjectBaseDistinct + doAssert ObjectBase(x).value == 12 + let y = default(ObjectBaseDistinct) + doAssert ObjectBase(y).value == 12 + + proc hello(): ObjectBaseDistinct = + discard + + let z = hello() + doAssert ObjectBase(z).value == 12 + + block: + var x: DinstinctInObject + + doAssert ObjectBase(x.data).value == 12 + + block: + var x: Object + doAssert x.value == 12 + doAssert x.time == 1.2 + doAssert x.scale == 1 + + proc hello(): Object = + var dummy = 1 + dummy += 18 + + let h1 = hello() + doAssert h1.value == 12 + doAssert h1.time == 1.2 + doAssert h1.scale == 1 + + let y = default(Object) doAssert y.value == 12 doAssert y.time == 1.2 doAssert y.scale == 1 + var x1, x2, x3: Object + doAssert x1.value == 12 + doAssert x1.time == 1.2 + doAssert x1.scale == 1 + doAssert x2.value == 12 + doAssert x2.time == 1.2 + doAssert x2.scale == 1 + doAssert x3.value == 12 + doAssert x3.time == 1.2 + doAssert x3.scale == 1 + block: - var x: seq[Object] - setLen(x, 5) - let y = x[^1] + var x: Object2 + doAssert x.name.value == 12 + doAssert x.name.time == 1.2 + doAssert x.name.scale == 1 + + block: + var x: Object3 + doAssert x.obj.name.value == 12 + doAssert x.obj.name.time == 1.2 + doAssert x.obj.name.scale == 1 + + when nimvm: + discard "fixme" + else: + when defined(gcArc) or defined(gcOrc): + block: #seq + var x = newSeq[Object](10) + let y = x[0] + doAssert y.value == 12 + doAssert y.time == 1.2 + doAssert y.scale == 1 + + block: + var x: seq[Object] + setLen(x, 5) + let y = x[^1] + doAssert y.value == 12 + doAssert y.time == 1.2 + doAssert y.scale == 1 + + block: # array + var x: array[10, Object] + let y = x[0] doAssert y.value == 12 doAssert y.time == 1.2 doAssert y.scale == 1 -block: # array - var x: array[10, Object] - let y = x[0] - doAssert y.value == 12 - doAssert y.time == 1.2 - doAssert y.scale == 1 - -block: # array - var x {.noinit.}: array[10, Object] - discard x - -block: # tuple - var x: ObjectTuple - doAssert x.base.value == 12 - doAssert x.typ == 0 - doAssert x.obj.time == 1.2 - doAssert x.obj.date == 0 - doAssert x.obj.scale == 1 - doAssert x.obj.value == 12 - -block: # tuple in object - var x: TupleInObject - doAssert x.data.base.value == 12 - doAssert x.data.typ == 0 - doAssert x.data.obj.time == 1.2 - doAssert x.data.obj.date == 0 - doAssert x.data.obj.scale == 1 - doAssert x.data.obj.value == 12 - doAssert x.size == 777 + block: # array + var x {.noinit.}: array[10, Object] + discard x + + block: # tuple + var x: ObjectTuple + doAssert x.base.value == 12 + doAssert x.typ == 0 + doAssert x.obj.time == 1.2 + doAssert x.obj.date == 0 + doAssert x.obj.scale == 1 + doAssert x.obj.value == 12 + + block: # tuple in object + var x: TupleInObject + doAssert x.data.base.value == 12 + doAssert x.data.typ == 0 + doAssert x.data.obj.time == 1.2 + doAssert x.data.obj.date == 0 + doAssert x.data.obj.scale == 1 + doAssert x.data.obj.value == 12 + doAssert x.size == 777 + + type + ObjectArray = object + data: array[10, Object] -type - ObjectArray = object - data: array[10, Object] + block: + var x: ObjectArray + let y = x.data[0] + doAssert y.value == 12 + doAssert y.time == 1.2 + doAssert y.scale == 1 -block: - var x: ObjectArray - let y = x.data[0] - doAssert y.value == 12 - doAssert y.time == 1.2 - doAssert y.scale == 1 + block: + var x: PrellDeque[int] + doAssert x.pendingTasks == 0 -block: - var x: PrellDeque[int] - doAssert x.pendingTasks == 0 + type + Color = enum + Red, Blue, Yellow -type - Color = enum - Red, Blue, Yellow - - ObjectVarint = object - case kind: Color - of Red: - data: int = 10 - of Blue: - fill = "123" - of Yellow: - time = 1.8'f32 - - ObjectVarint1 = object - case kind: Color = Blue - of Red: - data1: int = 10 - of Blue: - fill2 = "123" - cry: float - of Yellow: - time3 = 1.8'f32 - him: int + ObjectVarint = object + case kind: Color + of Red: + data: int = 10 + of Blue: + fill = "123" + of Yellow: + time = 1.8'f32 + + ObjectVarint1 = object + case kind: Color = Blue + of Red: + data1: int = 10 + of Blue: + fill2 = "123" + cry: float + of Yellow: + time3 = 1.8'f32 + him: int -block: - var x = ObjectVarint(kind: Red) - doAssert x.kind == Red - doAssert x.data == 10 + block: + var x = ObjectVarint(kind: Red) + doAssert x.kind == Red + doAssert x.data == 10 -block: - var x = ObjectVarint(kind: Blue) - doAssert x.kind == Blue - doAssert x.fill == "123" + block: + var x = ObjectVarint(kind: Blue) + doAssert x.kind == Blue + doAssert x.fill == "123" -block: - var x = ObjectVarint(kind: Yellow) - doAssert x.kind == Yellow - doAssert typeof(x.time) is float32 + block: + var x = ObjectVarint(kind: Yellow) + doAssert x.kind == Yellow + doAssert typeof(x.time) is float32 -block: - var x: ObjectVarint1 - doAssert x.kind == Blue - doAssert x.fill2 == "123" - x.cry = 326 + block: + var x: ObjectVarint1 + doAssert x.kind == Blue + doAssert x.fill2 == "123" + x.cry = 326 + + type + ObjectVarint2 = object + case kind: Color + of Red: + data: int = 10 + of Blue: + fill = "123" + of Yellow: + time = 1.8'f32 + block: + var x = ObjectVarint2(kind: Blue) + doAssert x.fill == "123" -type - ObjectVarint2 = object - case kind: Color - of Red: - data: int = 10 - of Blue: - fill = "123" - of Yellow: - time = 1.8'f32 - - ObjectVarint3 = object - case kind: Color = Blue - of Red: - data1: int = 10 - of Blue: - case name: Color = Blue - of Blue: - go = 12 - else: - temp = 66 - fill2 = "123" - cry: float - of Yellow: - time3 = 1.8'f32 - him: int -block: - var x = ObjectVarint2(kind: Blue) - doAssert x.fill == "123" +proc main1 = + var my = @[1, 2, 3, 4, 5] + my.setLen(0) + my.setLen(5) + doAssert my == @[0, 0, 0, 0, 0] -block: - proc check: ObjectVarint3 = - discard - var x = check() - doAssert x.kind == Blue - doAssert x.name == Blue - doAssert x.go == 12 +proc main2 = + var my = "hello" + my.setLen(0) + my.setLen(5) + doAssert $(@my) == """@['\x00', '\x00', '\x00', '\x00', '\x00']""" -block: - var x: ObjectVarint3 - doAssert x.kind == Blue - doAssert x.name == Blue - doAssert x.go == 12 +when defined(gcArc) or defined(gcOrc): + main1() + main2() -block: - var x = ObjectVarint3(kind: Blue, name: Red, temp: 99) - doAssert x.kind == Blue - doAssert x.name == Red - doAssert x.temp == 99 +static: main() +main() From fca41d429d53124e1f627dd95f4441ce06bb3a63 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+xflywind@users.noreply.github.com> Date: Tue, 16 Aug 2022 15:30:14 +0800 Subject: [PATCH 22/52] add more hasDefaults --- compiler/sem.nim | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/compiler/sem.nim b/compiler/sem.nim index d46d11d77aa13..927e63f31e6f1 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -631,29 +631,34 @@ proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode, hasDefault: v asgnExpr.typ = recTypeSkipDistinct asgnExpr.flags.incl nfUseDefaultField asgnExpr.sons.add defaultFieldsForTheUninitialized(c, recType.n, hasDefault) - if recNode.typ.kind == tyDistinct: - asgnExpr = newTree(nkConv, newNodeIT(nkType, recNode.info, recNode.typ), asgnExpr) - asgnExpr.typ = recNode.typ - asgnExpr.flags.incl nfUseDefaultField - result.add newTree(nkExprColonExpr, recNode, asgnExpr) + if hasDefault: + if recNode.typ.kind == tyDistinct: + asgnExpr = newTree(nkConv, newNodeIT(nkType, recNode.info, recNode.typ), asgnExpr) + asgnExpr.typ = recNode.typ + asgnExpr.flags.incl nfUseDefaultField + result.add newTree(nkExprColonExpr, recNode, asgnExpr) elif recType.kind == tyArray and recType[1].skipTypes(defaultFieldsSkipTypes).kind == tyObject: let asgnExpr = defaultFieldForArray(c, recNode, hasDefault) - result.add newTree(nkExprColonExpr, recNode, asgnExpr) + if hasDefault: + result.add newTree(nkExprColonExpr, recNode, asgnExpr) # asgnExpr.sons.setLen(toInt(lengthOrd(c.graph.config, recType))) # for i in 0.. Date: Tue, 16 Aug 2022 19:18:57 +0800 Subject: [PATCH 23/52] fixes ordinal types --- compiler/sem.nim | 12 ------------ compiler/semtypes.nim | 2 +- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/compiler/sem.nim b/compiler/sem.nim index 927e63f31e6f1..50478d5a49d3f 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -648,18 +648,6 @@ proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode, hasDefault: v let asgnExpr = defaultFieldForTuple(c, recNode, hasDefault) if hasDefault: result.add newTree(nkExprColonExpr, recNode, asgnExpr) - elif recType.kind in {tyInt..tyInt64, tyUInt..tyUInt64}: - let asgnExpr = newIntTypeNode(int64(0), recType) - asgnExpr.flags.incl nfUseDefaultField - if hasDefault: - result.add newTree(nkExprColonExpr, recNode, - asgnExpr) - elif recType.kind in tyFloat..tyFloat64: - let asgnExpr = newFloatTypeNode(BiggestFloat(0.0), recType) - asgnExpr.flags.incl nfUseDefaultField - if hasDefault: - result.add newTree(nkExprColonExpr, recNode, - asgnExpr) else: doAssert false diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index c384b4854c746..f181cee177d1b 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -789,7 +789,7 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int, typ = errorType(c) else: typ = semTypeNode(c, n[^2], nil) - if c.graph.config.isDefined("nimPreviewRangeDefault") and typ.skipTypes(abstractInst).kind in {tyRange, tyOrdinal}: + if c.graph.config.isDefined("nimPreviewRangeDefault") and typ.skipTypes(abstractInst).kind == tyRange: n[^1] = newIntNode(nkIntLit, firstOrd(c.config, typ)) n[^1].typ = typ hasDefaultField = true From d0c0da9fdd622e9db0070ec1dc58c7337609e7b9 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+xflywind@users.noreply.github.com> Date: Tue, 16 Aug 2022 23:00:39 +0800 Subject: [PATCH 24/52] add testcase for #16744 --- tests/objects/tobject_default_value.nim | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/objects/tobject_default_value.nim b/tests/objects/tobject_default_value.nim index f3547aa5d94d1..2051958332333 100644 --- a/tests/objects/tobject_default_value.nim +++ b/tests/objects/tobject_default_value.nim @@ -146,6 +146,17 @@ block: doAssert y.data == 73 template main = + block: # bug #16744 + type + R = range[1..10] + Obj = object + r: R + + var + rVal: R # Works fine + objVal: Obj + + doAssert objVal.r == 1 block: var x: ObjectBase doAssert x.value == 12 From 7de32e8a7d88e12b72e775b2b3ace00d7bc4923b Mon Sep 17 00:00:00 2001 From: xflywind <43030857+xflywind@users.noreply.github.com> Date: Tue, 16 Aug 2022 23:06:12 +0800 Subject: [PATCH 25/52] add testcase for #3608 --- tests/objects/tobject_default_value.nim | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/objects/tobject_default_value.nim b/tests/objects/tobject_default_value.nim index 2051958332333..aa458a673f1c2 100644 --- a/tests/objects/tobject_default_value.nim +++ b/tests/objects/tobject_default_value.nim @@ -1,5 +1,5 @@ discard """ - matrix: "-d:nimPreviewRangeDefault; -d:nimPreviewRangeDefault --mm:orc" + matrix: "-d:nimPreviewRangeDefault; -d:nimPreviewRangeDefault --warningAsError:ProveInit --mm:orc" targets: "c cpp js" """ @@ -157,6 +157,18 @@ template main = objVal: Obj doAssert objVal.r == 1 + + block: # bug #3608 + type + abc = ref object + w: range[2..100] + + proc createABC(): abc = + new(result) + result.w = 20 + + doAssert createABC().w == 20 + block: var x: ObjectBase doAssert x.value == 12 From 09b6cf9e634fa0310330c9dcee5056447c0d3cc4 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+xflywind@users.noreply.github.com> Date: Wed, 17 Aug 2022 10:24:41 +0800 Subject: [PATCH 26/52] fixes docgen --- compiler/sem.nim | 2 +- compiler/semstmts.nim | 3 ++- lib/system.nim | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/compiler/sem.nim b/compiler/sem.nim index 50478d5a49d3f..8b92ad5197410 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -568,7 +568,7 @@ proc defaultFieldForArray(c: PContext, recNode: PNode, hasDefault: var bool): PN let node = newNode(nkIntLit) node.intVal = toInt64(lengthOrd(c.graph.config, recType)) - result = semExpr(c, newTree(nkCall, newSymNode(getSysSym(c.graph, recNode.info, "newDefaultArray"), recNode.info), + result = semExpr(c, newTree(nkCall, newSymNode(getSysSym(c.graph, recNode.info, "arrayWith"), recNode.info), node, objExpr ) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index aef0cee39d7a9..39816e4b05938 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -1607,7 +1607,8 @@ proc addResult(c: PContext, n: PNode, t: PType, owner: TSymKind) = addParamOrResult(c, c.p.resultSym, owner) proc addDefaultFieldForResult(c: PContext, n: PNode, t: PType) = - if t != nil and n.len > resultPos and n[resultPos] != nil: + if t != nil and n.len > resultPos and n[resultPos] != nil and + c.config.cmd notin cmdDocLike: var field = defaultNodeField(c, n[resultPos]) if field != nil: field = semExpr(c, field) diff --git a/lib/system.nim b/lib/system.nim index 00bd8fe0aa344..886d6c66d99b2 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -3177,6 +3177,7 @@ when notJSnotNims and not defined(nimSeqsV2): assert y == "abcgh" discard -proc newDefaultArray*[T](N: static int, y: T): array[N, T] = # todo fixme +proc arrayWith*[T](N: static int, y: T): array[N, T] = + ## Creates a new array filled with `y`. for i in 0..N-1: result[i] = y From 37877d19a829598551fd4062e9ff208d49b484e2 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+xflywind@users.noreply.github.com> Date: Wed, 17 Aug 2022 13:50:22 +0800 Subject: [PATCH 27/52] small fix --- compiler/jsgen.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index 60d10f58de5df..f91ca02b7728a 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -2274,7 +2274,7 @@ proc genObjConstr(p: PProc, n: PNode, r: var TCompRes) = gen(p, val, a) var f = it[0].sym if f.loc.r == nil: f.loc.r = mangleName(p.module, f) - fieldIDs.incl(lookupFieldAgain(n.typ, f).id) + fieldIDs.incl(lookupFieldAgain(n.typ.skipTypes({tyDistinct}), f).id) let typ = val.typ.skipTypes(abstractInst) if a.typ == etyBaseIndex: From 3e8390558b893f105a30e66ba99fac38db4702a3 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+xflywind@users.noreply.github.com> Date: Wed, 17 Aug 2022 13:50:50 +0800 Subject: [PATCH 28/52] recursive --- compiler/sem.nim | 60 ++++++++++++++++++------------------------- compiler/semstmts.nim | 5 ++-- 2 files changed, 28 insertions(+), 37 deletions(-) diff --git a/compiler/sem.nim b/compiler/sem.nim index 8b92ad5197410..69ddcc9b0b31b 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -551,31 +551,11 @@ proc pickCaseBranchIndex(caseExpr, matched: PNode): int = return caseExpr.len - 1 proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode, hasDefault: var bool): seq[PNode] +proc defaultNodeField(c: PContext, a: PNode): PNode +proc defaultNodeField(c: PContext, a: PNode, aTyp: PType, hasDefault: var bool): PNode const defaultFieldsSkipTypes = {tyGenericInst, tyAlias, tySink, tyDistinct} -proc defaultFieldForArray(c: PContext, recNode: PNode, hasDefault: var bool): PNode = - let recType = recNode.typ.skipTypes(defaultFieldsSkipTypes) - var objExpr = newTree(nkObjConstr, newNodeIT(nkType, recNode.info, recType[1])) - objExpr.typ = recType[1].skipTypes(defaultFieldsSkipTypes) - var t = objExpr.typ - while true: - objExpr.sons.add defaultFieldsForTheUninitialized(c, t.n, hasDefault) - let base = t[0] - if base == nil: - break - t = skipTypes(base, skipPtrs) - - let node = newNode(nkIntLit) - node.intVal = toInt64(lengthOrd(c.graph.config, recType)) - result = semExpr(c, newTree(nkCall, newSymNode(getSysSym(c.graph, recNode.info, "arrayWith"), recNode.info), - node, - objExpr - ) - ) - result.typ = recNode.typ - result.flags.incl nfUseDefaultField - proc defaultFieldForTuple(c: PContext, recNode: PNode, hasDefault: var bool): PNode = let recType = recNode.typ.skipTypes(defaultFieldsSkipTypes) var tupleExpr = newNodeI(nkTupleConstr, recNode.info) @@ -591,11 +571,10 @@ proc defaultFieldForTuple(c: PContext, recNode: PNode, hasDefault: var bool): PN else: let asgnType = newType(tyTypeDesc, nextTypeId(c.idgen), s.owner) rawAddSon(asgnType, s) - let asgnExpr = semExpr(c, newTree(nkCall, + let asgnExpr = newTree(nkCall, newSymNode(getSysMagic(c.graph, recNode.info, "default", mDefault)), newNodeIT(nkType, recNode.info, asgnType) ) - ) asgnExpr.flags.incl nfUseDefaultField asgnExpr.typ = s tupleExpr.add asgnExpr @@ -637,8 +616,8 @@ proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode, hasDefault: v asgnExpr.typ = recNode.typ asgnExpr.flags.incl nfUseDefaultField result.add newTree(nkExprColonExpr, recNode, asgnExpr) - elif recType.kind == tyArray and recType[1].skipTypes(defaultFieldsSkipTypes).kind == tyObject: - let asgnExpr = defaultFieldForArray(c, recNode, hasDefault) + elif recType.kind == tyArray: + let asgnExpr = defaultNodeField(c, recNode, recType, hasDefault) if hasDefault: result.add newTree(nkExprColonExpr, recNode, asgnExpr) # asgnExpr.sons.setLen(toInt(lengthOrd(c.graph.config, recType))) @@ -651,10 +630,9 @@ proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode, hasDefault: v else: doAssert false -proc defaultNodeField(c: PContext, a: PNode): PNode = - let aTyp = a.typ - var hasDefault: bool - if aTyp.skipTypes(defaultFieldsSkipTypes).kind == tyObject: +proc defaultNodeField(c: PContext, a: PNode, aTyp: PType, hasDefault: var bool): PNode = + let aTypSkip = aTyp.skipTypes(defaultFieldsSkipTypes) + if aTypSkip.kind == tyObject: let aTypSkipDistinct = aTyp.skipTypes({tyDistinct}) var asgnExpr = newTree(nkObjConstr, newNodeIT(nkType, a.info, aTypSkipDistinct)) asgnExpr.typ = aTypSkipDistinct @@ -664,16 +642,28 @@ proc defaultNodeField(c: PContext, a: PNode): PNode = if aTyp.kind == tyDistinct: result = newTree(nkConv, newNodeIT(nkType, a.info, aTyp), result) result.typ = aTyp - elif aTyp.kind == tyArray and aTyp[1].skipTypes(defaultFieldsSkipTypes).kind == tyObject: - let asgnExpr = defaultFieldForArray(c, a, hasDefault) - let arrayExpr = semExprWithType(c, asgnExpr) + elif aTypSkip.kind == tyArray: + let child = defaultNodeField(c, a, aTyp[1], hasDefault) + if hasDefault: - result = arrayExpr - elif aTyp.kind == tyTuple: + let node = newNode(nkIntLit) + node.intVal = toInt64(lengthOrd(c.graph.config, aTypSkip)) + result = newTree(nkCall, newSymNode(getSysSym(c.graph, a.info, "arrayWith"), a.info), + node, + semExpr(c, child) + ) + result.typ = aTyp + result.flags.incl nfUseDefaultField + if aTypSkip.kind == tyTuple: let tupleExpr = defaultFieldForTuple(c, a, hasDefault) if hasDefault: result = tupleExpr +proc defaultNodeField(c: PContext, a: PNode): PNode = + let aTyp = a.typ + var hasDefault: bool + defaultNodeField(c, a, a.typ, hasDefault) + include semtempl, semgnrc, semstmts, semexprs proc addCodeForGenerics(c: PContext, n: PNode) = diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 39816e4b05938..cac8112487e6a 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -597,7 +597,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode = var def: PNode = c.graph.emptyNode if a[^1].kind == nkEmpty and symkind == skVar and a[^2].typ != nil: - let m = copyTree(a[0]) + # let m = copyTree(a[0]) # var v = semIdentDef(c, m, symkind, false) # if {sfThread, sfNoInit} * v.flags != {}: # todo var m1, m2 {threadvar} # discard # todo init threadvar properly @@ -1705,7 +1705,8 @@ proc semInferredLambda(c: PContext, pt: TIdTable, n: PNode): PNode {.nosinks.} = pushProcCon(c, s) addResult(c, n, n.typ[0], skProc) s.ast[bodyPos] = hloBody(c, semProcBody(c, n[bodyPos])) - addDefaultFieldForResult(c, n, n.typ[0]) + if s.kind notin {skMacro, skTemplate} and s.magic == mNone: + addDefaultFieldForResult(c, n, n.typ[0]) trackProc(c, s, s.ast[bodyPos]) popProcCon(c) popOwner(c) From 9559a1a067a975225c0bc42575787343cec42090 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+xflywind@users.noreply.github.com> Date: Wed, 17 Aug 2022 14:36:41 +0800 Subject: [PATCH 29/52] fixes --- compiler/sem.nim | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/compiler/sem.nim b/compiler/sem.nim index 69ddcc9b0b31b..b5eb358e76bf1 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -618,7 +618,7 @@ proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode, hasDefault: v result.add newTree(nkExprColonExpr, recNode, asgnExpr) elif recType.kind == tyArray: let asgnExpr = defaultNodeField(c, recNode, recType, hasDefault) - if hasDefault: + if asgnExpr != nil and hasDefault: result.add newTree(nkExprColonExpr, recNode, asgnExpr) # asgnExpr.sons.setLen(toInt(lengthOrd(c.graph.config, recType))) # for i in 0.. Date: Wed, 17 Aug 2022 15:36:32 +0800 Subject: [PATCH 30/52] cleanup and remove tuple support --- compiler/sem.nim | 36 +----------------- compiler/semexprs.nim | 15 ++------ lib/system.nim | 4 +- tests/objects/tobject_default_value.nim | 50 ++++++++++++------------- 4 files changed, 32 insertions(+), 73 deletions(-) diff --git a/compiler/sem.nim b/compiler/sem.nim index b5eb358e76bf1..1a9014e496f6a 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -556,29 +556,6 @@ proc defaultNodeField(c: PContext, a: PNode, aTyp: PType, hasDefault: var bool): const defaultFieldsSkipTypes = {tyGenericInst, tyAlias, tySink, tyDistinct} -proc defaultFieldForTuple(c: PContext, recNode: PNode, hasDefault: var bool): PNode = - let recType = recNode.typ.skipTypes(defaultFieldsSkipTypes) - var tupleExpr = newNodeI(nkTupleConstr, recNode.info) - tupleExpr.typ = recType - for s in recType.sons: - let sType = s.skipTypes(defaultFieldsSkipTypes) - # todo handle distinct - if sType.kind == tyObject: - var asgnExpr = newTree(nkObjConstr, newNodeIT(nkType, recNode.info, s)) - asgnExpr.typ = s - asgnExpr.sons.add defaultFieldsForTheUninitialized(c, sType.n, hasDefault) - tupleExpr.add asgnExpr - else: - let asgnType = newType(tyTypeDesc, nextTypeId(c.idgen), s.owner) - rawAddSon(asgnType, s) - let asgnExpr = newTree(nkCall, - newSymNode(getSysMagic(c.graph, recNode.info, "default", mDefault)), - newNodeIT(nkType, recNode.info, asgnType) - ) - asgnExpr.flags.incl nfUseDefaultField - asgnExpr.typ = s - tupleExpr.add asgnExpr - result = tupleExpr proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode, hasDefault: var bool): seq[PNode] = case recNode.kind @@ -620,13 +597,6 @@ proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode, hasDefault: v let asgnExpr = defaultNodeField(c, recNode, recType, hasDefault) if asgnExpr != nil and hasDefault: result.add newTree(nkExprColonExpr, recNode, asgnExpr) - # asgnExpr.sons.setLen(toInt(lengthOrd(c.graph.config, recType))) - # for i in 0.. Date: Wed, 17 Aug 2022 15:47:04 +0800 Subject: [PATCH 31/52] fixes nimsuggest --- compiler/sem.nim | 4 ++-- compiler/semmagic.nim | 2 +- lib/system.nim | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/sem.nim b/compiler/sem.nim index 1a9014e496f6a..ba489486c766d 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -619,8 +619,8 @@ proc defaultNodeField(c: PContext, a: PNode, aTyp: PType, hasDefault: var bool): let node = newNode(nkIntLit) node.intVal = toInt64(lengthOrd(c.graph.config, aTypSkip)) result = semExpr(c, newTree(nkCall, newSymNode(getSysSym(c.graph, a.info, "arrayWith"), a.info), - node, - semExprWithType(c, child) + semExprWithType(c, child), + node )) result.typ = aTyp result.flags.incl nfUseDefaultField diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index c6a503a5b2496..f47b644ca0b99 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -471,7 +471,7 @@ proc addDefaultFieldForNew(c: PContext, n: PNode): PNode = break t = skipTypes(base, skipPtrs) - if hasDefault: # todo apply default + if hasDefault: result = newTree(nkAsgn, result[1], asgnExpr) proc magicsAfterOverloadResolution(c: PContext, n: PNode, diff --git a/lib/system.nim b/lib/system.nim index de5b3a74d21aa..13708e402a3ae 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -3177,7 +3177,7 @@ when notJSnotNims and not defined(nimSeqsV2): assert y == "abcgh" discard -proc arrayWith*[T](size: static int, y: T): array[size, T] = +proc arrayWith*[T](y: T, size: static int): array[size, T] = ## Creates a new array filled with `y`. for i in 0..size-1: result[i] = y From bcddfad53ce4636198d56286408de1b5a10d2695 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+xflywind@users.noreply.github.com> Date: Wed, 17 Aug 2022 17:29:18 +0800 Subject: [PATCH 32/52] fixes generics procs --- compiler/sem.nim | 15 +++----- compiler/seminst.nim | 2 + compiler/semstmts.nim | 6 +-- lib/system.nim | 2 +- tests/objects/tobject_default_value.nim | 49 ++++++++++++++++--------- 5 files changed, 42 insertions(+), 32 deletions(-) diff --git a/compiler/sem.nim b/compiler/sem.nim index ba489486c766d..743a3e4c49eb6 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -42,6 +42,7 @@ proc semOpAux(c: PContext, n: PNode) proc semParamList(c: PContext, n, genericParams: PNode, s: PSym) proc addParams(c: PContext, n: PNode, kind: TSymKind) proc maybeAddResult(c: PContext, s: PSym, n: PNode) +proc addDefaultFieldForResult(c: PContext, n: PNode, t: PType) proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode proc activate(c: PContext, n: PNode) proc semQuoteAst(c: PContext, n: PNode): PNode @@ -582,16 +583,9 @@ proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode, hasDefault: v result.add newTree(nkExprColonExpr, recNode, field.ast) hasDefault = true elif recType.kind == tyObject: - let recTypeSkipDistinct = recType.skipTypes({tyDistinct}) - var asgnExpr = newTree(nkObjConstr, newNodeIT(nkType, recNode.info, recTypeSkipDistinct)) - asgnExpr.typ = recTypeSkipDistinct - asgnExpr.flags.incl nfUseDefaultField - asgnExpr.sons.add defaultFieldsForTheUninitialized(c, recType.n, hasDefault) - if hasDefault: - if recNode.typ.kind == tyDistinct: - asgnExpr = newTree(nkConv, newNodeIT(nkType, recNode.info, recNode.typ), asgnExpr) - asgnExpr.typ = recNode.typ - asgnExpr.flags.incl nfUseDefaultField + let asgnExpr = defaultNodeField(c, recNode, recNode.typ, hasDefault) + if asgnExpr != nil and hasDefault: + asgnExpr.flags.incl nfUseDefaultField result.add newTree(nkExprColonExpr, recNode, asgnExpr) elif recType.kind == tyArray: let asgnExpr = defaultNodeField(c, recNode, recType, hasDefault) @@ -605,6 +599,7 @@ proc defaultNodeField(c: PContext, a: PNode, aTyp: PType, hasDefault: var bool): if aTypSkip.kind == tyObject: let aTypSkipDistinct = aTyp.skipTypes({tyDistinct}) var asgnExpr = newTree(nkObjConstr, newNodeIT(nkType, a.info, aTypSkipDistinct)) + asgnExpr.flags.incl nfUseDefaultField asgnExpr.typ = aTypSkipDistinct asgnExpr.sons.add defaultFieldsForTheUninitialized(c, aTyp.skipTypes(defaultFieldsSkipTypes).n, hasDefault) if hasDefault: diff --git a/compiler/seminst.nim b/compiler/seminst.nim index 6fae0583d0f99..0be3c13ceac39 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -151,6 +151,8 @@ proc instantiateBody(c: PContext, n, params: PNode, result, orig: PSym) = # As body is a sym to the borrowed proc. b = semProcBody(c, b) result.ast[bodyPos] = hloBody(c, b) + if orig.kind notin {skMacro, skTemplate} and orig.magic == mNone and sfNoInit notin orig.flags: + addDefaultFieldForResult(c, n, orig.typ[0]) excl(result.flags, sfForward) trackProc(c, result, result.ast[bodyPos]) dec c.inGenericInst diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index cac8112487e6a..9994547251f55 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -1705,7 +1705,7 @@ proc semInferredLambda(c: PContext, pt: TIdTable, n: PNode): PNode {.nosinks.} = pushProcCon(c, s) addResult(c, n, n.typ[0], skProc) s.ast[bodyPos] = hloBody(c, semProcBody(c, n[bodyPos])) - if s.kind notin {skMacro, skTemplate} and s.magic == mNone: + if s.kind notin {skMacro, skTemplate} and s.magic == mNone and sfNoInit notin s.flags: addDefaultFieldForResult(c, n, n.typ[0]) trackProc(c, s, s.ast[bodyPos]) popProcCon(c) @@ -2129,7 +2129,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, pushProcCon(c, s) addResult(c, n, s.typ[0], skProc) s.ast[bodyPos] = hloBody(c, semProcBody(c, n[bodyPos])) - if s.kind notin {skMacro, skTemplate} and s.magic == mNone: + if s.kind notin {skMacro, skTemplate} and s.magic == mNone and sfNoInit notin s.flags: addDefaultFieldForResult(c, n, s.typ[0]) trackProc(c, s, s.ast[bodyPos]) popProcCon(c) @@ -2145,7 +2145,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, maybeAddResult(c, s, n) # semantic checking also needed with importc in case used in VM s.ast[bodyPos] = hloBody(c, semProcBody(c, n[bodyPos])) - if s.kind notin {skMacro, skTemplate} and s.magic == mNone: + if s.kind notin {skMacro, skTemplate} and s.magic == mNone and sfNoInit notin s.flags: addDefaultFieldForResult(c, n, s.typ[0]) # unfortunately we cannot skip this step when in 'system.compiles' # context as it may even be evaluated in 'system.compiles': diff --git a/lib/system.nim b/lib/system.nim index 13708e402a3ae..d3a8ef39066fd 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -3177,7 +3177,7 @@ when notJSnotNims and not defined(nimSeqsV2): assert y == "abcgh" discard -proc arrayWith*[T](y: T, size: static int): array[size, T] = +proc arrayWith*[T](y: T, size: static int): array[size, T] {.noinit.} = # ? exempt from default value for result ## Creates a new array filled with `y`. for i in 0..size-1: result[i] = y diff --git a/tests/objects/tobject_default_value.nim b/tests/objects/tobject_default_value.nim index d69b2a13adddf..dfd2189f2294b 100644 --- a/tests/objects/tobject_default_value.nim +++ b/tests/objects/tobject_default_value.nim @@ -156,6 +156,7 @@ template main = rVal: R # Works fine objVal: Obj + doAssert rVal == 0 # it should be 1 doAssert objVal.r == 1 block: # bug #3608 @@ -271,24 +272,25 @@ template main = var x {.noinit.}: array[10, Object] discard x - # block: # tuple - # var x: ObjectTuple - # doAssert x.base.value == 12 - # doAssert x.typ == 0 - # doAssert x.obj.time == 1.2 - # doAssert x.obj.date == 0 - # doAssert x.obj.scale == 1 - # doAssert x.obj.value == 12 - - # block: # tuple in object - # var x: TupleInObject - # doAssert x.data.base.value == 12 - # doAssert x.data.typ == 0 - # doAssert x.data.obj.time == 1.2 - # doAssert x.data.obj.date == 0 - # doAssert x.data.obj.scale == 1 - # doAssert x.data.obj.value == 12 - # doAssert x.size == 777 + when false: + block: # tuple + var x: ObjectTuple + doAssert x.base.value == 12 + doAssert x.typ == 0 + doAssert x.obj.time == 1.2 + doAssert x.obj.date == 0 + doAssert x.obj.scale == 1 + doAssert x.obj.value == 12 + + block: # tuple in object + var x: TupleInObject + doAssert x.data.base.value == 12 + doAssert x.data.typ == 0 + doAssert x.data.obj.time == 1.2 + doAssert x.data.obj.date == 0 + doAssert x.data.obj.scale == 1 + doAssert x.data.obj.value == 12 + doAssert x.size == 777 type ObjectArray = object @@ -365,6 +367,17 @@ template main = var x = ObjectVarint2(kind: Blue) doAssert x.fill == "123" + block: + type + Default = object + id: int = 1 + + proc hello[T](): array[10, T] = + let x = 1 + doAssert result[0].id == x + + doAssert hello[Default]()[^1].id == 1 + proc main1 = var my = @[1, 2, 3, 4, 5] From 0cfcff6db2d8df95a3a8523d644426db79c0d836 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+xflywind@users.noreply.github.com> Date: Wed, 17 Aug 2022 19:57:48 +0800 Subject: [PATCH 33/52] refactor --- compiler/sem.nim | 6 +----- tests/stdlib/tnetconnect.nim | 4 ++-- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/compiler/sem.nim b/compiler/sem.nim index 743a3e4c49eb6..c0dd7b3e6a9d8 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -582,15 +582,11 @@ proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode, hasDefault: v if field.ast != nil: #Try to use default value result.add newTree(nkExprColonExpr, recNode, field.ast) hasDefault = true - elif recType.kind == tyObject: + elif recType.kind in {tyObject, tyArray}: let asgnExpr = defaultNodeField(c, recNode, recNode.typ, hasDefault) if asgnExpr != nil and hasDefault: asgnExpr.flags.incl nfUseDefaultField result.add newTree(nkExprColonExpr, recNode, asgnExpr) - elif recType.kind == tyArray: - let asgnExpr = defaultNodeField(c, recNode, recType, hasDefault) - if asgnExpr != nil and hasDefault: - result.add newTree(nkExprColonExpr, recNode, asgnExpr) else: doAssert false diff --git a/tests/stdlib/tnetconnect.nim b/tests/stdlib/tnetconnect.nim index 3a80df19feb19..f7c8fe411a2b4 100644 --- a/tests/stdlib/tnetconnect.nim +++ b/tests/stdlib/tnetconnect.nim @@ -20,8 +20,8 @@ proc test() = # * Call to 'connect' timed out. [TimeoutError] # * No route to host [OSError] try: - fn("www.nim-lang.org") - except TimeoutError, OSError: fn("www.google.com") + except TimeoutError, OSError: + fn("www.nim-lang.org") test() From d136a1bf9ed9139348e08bb5045f69d763405490 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+xflywind@users.noreply.github.com> Date: Wed, 17 Aug 2022 21:03:13 +0800 Subject: [PATCH 34/52] increases timeout --- tests/stdlib/tnetconnect.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/stdlib/tnetconnect.nim b/tests/stdlib/tnetconnect.nim index f7c8fe411a2b4..8b6ab94f04f4d 100644 --- a/tests/stdlib/tnetconnect.nim +++ b/tests/stdlib/tnetconnect.nim @@ -12,7 +12,7 @@ proc test() = proc fn(url: string) = let socket = newSocket() defer: close(socket) - connect(socket, url, Port(443), 5000) # typically 20 could be enough + connect(socket, url, Port(443), 10000) # typically 20 could be enough send(socket, "GET / HTTP/1.0\nHost: $#\nConnection: close\n\n" % [url]) wrapSocket(ctx, socket) From 22962b23b28d268985227bddf472c7afda650ccc Mon Sep 17 00:00:00 2001 From: xflywind <43030857+xflywind@users.noreply.github.com> Date: Wed, 17 Aug 2022 21:41:14 +0800 Subject: [PATCH 35/52] refactor hasDefault --- compiler/ast.nim | 11 ----------- compiler/sem.nim | 39 ++++++++++++++++++--------------------- compiler/semexprs.nim | 7 +++---- compiler/semmagic.nim | 5 ++--- 4 files changed, 23 insertions(+), 39 deletions(-) diff --git a/compiler/ast.nim b/compiler/ast.nim index 50e8438f0b8dd..b87c9749607f8 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -1434,17 +1434,6 @@ proc newIntTypeNode*(intVal: BiggestInt, typ: PType): PNode = result.intVal = intVal result.typ = typ -proc newFloatTypeNode*(floatVal: BiggestFloat, typ: PType): PNode = - let kind = skipTypes(typ, abstractVarRange).kind - case kind - of tyFloat32: - result = newNode(nkFloat32Lit) - of tyFloat64, tyFloat: - result = newNode(nkFloatLit) - else: doAssert false, $kind - result.floatVal = floatVal - result.typ = typ - proc newIntTypeNode*(intVal: Int128, typ: PType): PNode = # XXX: introduce range check newIntTypeNode(castToInt64(intVal), typ) diff --git a/compiler/sem.nim b/compiler/sem.nim index c0dd7b3e6a9d8..d096f05b47364 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -551,18 +551,18 @@ proc pickCaseBranchIndex(caseExpr, matched: PNode): int = if endsWithElse: return caseExpr.len - 1 -proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode, hasDefault: var bool): seq[PNode] +proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode): seq[PNode] proc defaultNodeField(c: PContext, a: PNode): PNode -proc defaultNodeField(c: PContext, a: PNode, aTyp: PType, hasDefault: var bool): PNode +proc defaultNodeField(c: PContext, a: PNode, aTyp: PType): PNode const defaultFieldsSkipTypes = {tyGenericInst, tyAlias, tySink, tyDistinct} -proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode, hasDefault: var bool): seq[PNode] = +proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode): seq[PNode] = case recNode.kind of nkRecList: for field in recNode: - result.add defaultFieldsForTheUninitialized(c, field, hasDefault) + result.add defaultFieldsForTheUninitialized(c, field) of nkRecCase: let discriminator = recNode[0] var selectedBranch: int @@ -575,38 +575,38 @@ proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode, hasDefault: v else: # Try to use default value selectedBranch = recNode.pickCaseBranchIndex defaultValue result.add newTree(nkExprColonExpr, discriminator, defaultValue) - result.add defaultFieldsForTheUninitialized(c, recNode[selectedBranch][^1], hasDefault) + result.add defaultFieldsForTheUninitialized(c, recNode[selectedBranch][^1]) of nkSym: let field = recNode.sym let recType = recNode.typ.skipTypes(defaultFieldsSkipTypes) if field.ast != nil: #Try to use default value result.add newTree(nkExprColonExpr, recNode, field.ast) - hasDefault = true elif recType.kind in {tyObject, tyArray}: - let asgnExpr = defaultNodeField(c, recNode, recNode.typ, hasDefault) - if asgnExpr != nil and hasDefault: + let asgnExpr = defaultNodeField(c, recNode, recNode.typ) + if asgnExpr != nil: asgnExpr.flags.incl nfUseDefaultField result.add newTree(nkExprColonExpr, recNode, asgnExpr) else: doAssert false -proc defaultNodeField(c: PContext, a: PNode, aTyp: PType, hasDefault: var bool): PNode = +proc defaultNodeField(c: PContext, a: PNode, aTyp: PType): PNode = let aTypSkip = aTyp.skipTypes(defaultFieldsSkipTypes) if aTypSkip.kind == tyObject: - let aTypSkipDistinct = aTyp.skipTypes({tyDistinct}) - var asgnExpr = newTree(nkObjConstr, newNodeIT(nkType, a.info, aTypSkipDistinct)) - asgnExpr.flags.incl nfUseDefaultField - asgnExpr.typ = aTypSkipDistinct - asgnExpr.sons.add defaultFieldsForTheUninitialized(c, aTyp.skipTypes(defaultFieldsSkipTypes).n, hasDefault) - if hasDefault: + let child = defaultFieldsForTheUninitialized(c, aTyp.skipTypes(defaultFieldsSkipTypes).n) + if child.len > 0: + let aTypSkipDistinct = aTyp.skipTypes({tyDistinct}) + var asgnExpr = newTree(nkObjConstr, newNodeIT(nkType, a.info, aTypSkipDistinct)) + asgnExpr.flags.incl nfUseDefaultField + asgnExpr.typ = aTypSkipDistinct + asgnExpr.sons.add child result = semExpr(c, asgnExpr) if aTyp.kind == tyDistinct: result = newTree(nkConv, newNodeIT(nkType, a.info, aTyp), result) result.typ = aTyp elif aTypSkip.kind == tyArray: - let child = defaultNodeField(c, a, aTypSkip[1], hasDefault) + let child = defaultNodeField(c, a, aTypSkip[1]) - if child != nil and hasDefault: + if child != nil: let node = newNode(nkIntLit) node.intVal = toInt64(lengthOrd(c.graph.config, aTypSkip)) result = semExpr(c, newTree(nkCall, newSymNode(getSysSym(c.graph, a.info, "arrayWith"), a.info), @@ -617,10 +617,7 @@ proc defaultNodeField(c: PContext, a: PNode, aTyp: PType, hasDefault: var bool): result.flags.incl nfUseDefaultField proc defaultNodeField(c: PContext, a: PNode): PNode = - var hasDefault: bool - let res = defaultNodeField(c, a, a.typ, hasDefault) - if hasDefault: - result = res + result = defaultNodeField(c, a, a.typ) include semtempl, semgnrc, semstmts, semexprs diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 6a38b2fce2ac3..28bf1be43fb6b 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -2398,10 +2398,9 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode = of mDefault: result = semDirectOp(c, n, flags) let typ = result[^1].typ.skipTypes({tyTypeDesc}) - var hasDefault = false - let res = defaultNodeField(c, result[^1], typ, hasDefault) - if hasDefault and res != nil: - result = res + let defaultExpr = defaultNodeField(c, result[^1], typ) + if defaultExpr != nil: + result = defaultExpr else: result = semDirectOp(c, n, flags) diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index f47b644ca0b99..29c7993b61324 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -462,16 +462,15 @@ proc addDefaultFieldForNew(c: PContext, n: PNode): PNode = if typ.skipTypes({tyGenericInst, tyAlias, tySink}).kind == tyRef and typ.skipTypes({tyGenericInst, tyAlias, tySink})[0].kind == tyObject: var asgnExpr = newTree(nkObjConstr, newNodeIT(nkType, result[1].info, typ)) asgnExpr.typ = typ - var hasDefault: bool var t = typ.skipTypes({tyGenericInst, tyAlias, tySink})[0] while true: - asgnExpr.sons.add defaultFieldsForTheUninitialized(c, t.n, hasDefault) + asgnExpr.sons.add defaultFieldsForTheUninitialized(c, t.n) let base = t[0] if base == nil: break t = skipTypes(base, skipPtrs) - if hasDefault: + if asgnExpr.sons.len > 0: result = newTree(nkAsgn, result[1], asgnExpr) proc magicsAfterOverloadResolution(c: PContext, n: PNode, From 4a8b3a8b69cea85335de6185bec3643cb35daa50 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+xflywind@users.noreply.github.com> Date: Wed, 17 Aug 2022 21:52:06 +0800 Subject: [PATCH 36/52] zero default; disable i386 --- compiler/ast.nim | 2 +- compiler/ccgexprs.nim | 2 +- compiler/jsgen.nim | 2 +- compiler/semmagic.nim | 2 +- compiler/vmgen.nim | 2 +- lib/system.nim | 3 +++ tests/stdlib/tnetconnect.nim | 7 ++++--- 7 files changed, 12 insertions(+), 8 deletions(-) diff --git a/compiler/ast.nim b/compiler/ast.nim index b87c9749607f8..0133e8dd4159c 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -706,7 +706,7 @@ type mInstantiationInfo, mGetTypeInfo, mGetTypeInfoV2, mNimvm, mIntDefine, mStrDefine, mBoolDefine, mRunnableExamples, mException, mBuiltinType, mSymOwner, mUncheckedArray, mGetImplTransf, - mSymIsInstantiationOf, mNodeId, mPrivateAccess + mSymIsInstantiationOf, mNodeId, mPrivateAccess, mZeroDefault # things that we can evaluate safely at compile time, even if not asked for it: diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 4c15101a98283..49913b212d318 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -2436,7 +2436,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = p.module.s[cfsDynLibInit].addf("\t$1 = ($2) hcrGetProc($3, \"$1\");$n", [mangleDynLibProc(prc), getTypeDesc(p.module, prc.loc.t), getModuleDllPath(p.module, prc)]) genCall(p, e, d) - of mDefault: genDefault(p, e, d) + of mDefault, mZeroDefault: genDefault(p, e, d) of mReset: genReset(p, e) of mEcho: genEcho(p, e[1].skipConv) of mArrToSeq: genArrToSeq(p, e, d) diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index f91ca02b7728a..b01cf4992c1b7 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -2164,7 +2164,7 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) = of mNewSeq: genNewSeq(p, n) of mNewSeqOfCap: unaryExpr(p, n, r, "", "[]") of mOf: genOf(p, n, r) - of mDefault: genDefault(p, n, r) + of mDefault, mZeroDefault: genDefault(p, n, r) of mReset, mWasMoved: genReset(p, n) of mEcho: genEcho(p, n, r) of mNLen..mNError, mSlurp, mStaticExec: diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index 29c7993b61324..a7f30876fb486 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -583,7 +583,7 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode, tyAlias, tyUserTypeClassInst}) if seqType.kind == tySequence and seqType.base.requiresInit: message(c.config, n.info, warnUnsafeSetLen, typeToString(seqType.base)) - of mDefault: + of mDefault, mZeroDefault: result = n c.config.internalAssert result[1].typ.kind == tyTypeDesc let constructed = result[1].typ.base diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index aa2bdbe4ccad0..4a0fc96b3ea36 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -1182,7 +1182,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) = c.gABx(n, opcLdNull, d, c.genType(n[1].typ)) c.gABx(n, opcNodeToReg, d, d) c.genAsgnPatch(n[1], d) - of mDefault: + of mDefault, mZeroDefault: if dest < 0: dest = c.getTemp(n.typ) c.gABx(n, ldNullOpcode(n.typ), dest, c.genType(n.typ)) of mOf, mIs: diff --git a/lib/system.nim b/lib/system.nim index d3a8ef39066fd..01ead9e6f9698 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -1007,6 +1007,9 @@ proc default*[T](_: typedesc[T]): T {.magic: "Default", noSideEffect.} = # note: the doc comment also explains why `default` can't be implemented # via: `template default*[T](t: typedesc[T]): T = (var v: T; v)` +func zeroDefault*[T](_: typedesc[T]): T {.magic: "ZeroDefault".} = + ## returns the default value of the type `T`. + proc reset*[T](obj: var T) {.noSideEffect.} = ## Resets an object `obj` to its default value. obj = default(typeof(obj)) diff --git a/tests/stdlib/tnetconnect.nim b/tests/stdlib/tnetconnect.nim index 8b6ab94f04f4d..0fff8fdce143a 100644 --- a/tests/stdlib/tnetconnect.nim +++ b/tests/stdlib/tnetconnect.nim @@ -1,4 +1,5 @@ discard """ + disabled: "i386" matrix: "-d:ssl" """ @@ -12,7 +13,7 @@ proc test() = proc fn(url: string) = let socket = newSocket() defer: close(socket) - connect(socket, url, Port(443), 10000) # typically 20 could be enough + connect(socket, url, Port(443), 5000) # typically 20 could be enough send(socket, "GET / HTTP/1.0\nHost: $#\nConnection: close\n\n" % [url]) wrapSocket(ctx, socket) @@ -20,8 +21,8 @@ proc test() = # * Call to 'connect' timed out. [TimeoutError] # * No route to host [OSError] try: - fn("www.google.com") - except TimeoutError, OSError: fn("www.nim-lang.org") + except TimeoutError, OSError: + fn("www.google.com") test() From e98b3ca72b822d838c319b0cbe2d0f1e04599da4 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+xflywind@users.noreply.github.com> Date: Wed, 17 Aug 2022 22:13:45 +0800 Subject: [PATCH 37/52] add tuples back --- compiler/sem.nim | 29 +++++++++++++- tests/objects/tobject_default_value.nim | 51 ++++++++++++------------- 2 files changed, 53 insertions(+), 27 deletions(-) diff --git a/compiler/sem.nim b/compiler/sem.nim index d096f05b47364..9fd7b4f5ae5d1 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -581,7 +581,7 @@ proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode): seq[PNode] = let recType = recNode.typ.skipTypes(defaultFieldsSkipTypes) if field.ast != nil: #Try to use default value result.add newTree(nkExprColonExpr, recNode, field.ast) - elif recType.kind in {tyObject, tyArray}: + elif recType.kind in {tyObject, tyArray, tyTuple}: let asgnExpr = defaultNodeField(c, recNode, recNode.typ) if asgnExpr != nil: asgnExpr.flags.incl nfUseDefaultField @@ -615,6 +615,33 @@ proc defaultNodeField(c: PContext, a: PNode, aTyp: PType): PNode = )) result.typ = aTyp result.flags.incl nfUseDefaultField + elif aTypSkip.kind == tyTuple: + var hasDefault = false + var children: seq[PNode] + for s in aTypSkip.sons: + let child = defaultNodeField(c, a, s) + if child != nil: + hasDefault = true + children.add child + if hasDefault: + result = newNodeI(nkTupleConstr, a.info) + result.typ = aTyp + var i = 0 + while i < children.len: + let s = children[i] + if s != nil: + result.add s + else: + let asgnType = newType(tyTypeDesc, nextTypeId(c.idgen), aTypSkip[i].owner) + rawAddSon(asgnType, aTypSkip[i]) + let asgnExpr = newTree(nkCall, + newSymNode(getSysMagic(c.graph, a.info, "zeroDefault", mZeroDefault)), + newNodeIT(nkType, a.info, asgnType) + ) + asgnExpr.flags.incl nfUseDefaultField + asgnExpr.typ = aTypSkip[i] + result.add asgnExpr + inc i proc defaultNodeField(c: PContext, a: PNode): PNode = result = defaultNodeField(c, a, a.typ) diff --git a/tests/objects/tobject_default_value.nim b/tests/objects/tobject_default_value.nim index dfd2189f2294b..7fa0c11b08146 100644 --- a/tests/objects/tobject_default_value.nim +++ b/tests/objects/tobject_default_value.nim @@ -56,14 +56,14 @@ type Object3 = object obj: Object2 - # ObjectTuple = tuple - # base: ObjectBase - # typ: int - # obj: Object + ObjectTuple = tuple + base: ObjectBase + typ: int + obj: Object - # TupleInObject = object - # size = 777 - # data: ObjectTuple + TupleInObject = object + size = 777 + data: ObjectTuple Ref = ref object of ObjectBase @@ -272,25 +272,24 @@ template main = var x {.noinit.}: array[10, Object] discard x - when false: - block: # tuple - var x: ObjectTuple - doAssert x.base.value == 12 - doAssert x.typ == 0 - doAssert x.obj.time == 1.2 - doAssert x.obj.date == 0 - doAssert x.obj.scale == 1 - doAssert x.obj.value == 12 - - block: # tuple in object - var x: TupleInObject - doAssert x.data.base.value == 12 - doAssert x.data.typ == 0 - doAssert x.data.obj.time == 1.2 - doAssert x.data.obj.date == 0 - doAssert x.data.obj.scale == 1 - doAssert x.data.obj.value == 12 - doAssert x.size == 777 + block: # tuple + var x: ObjectTuple + doAssert x.base.value == 12 + doAssert x.typ == 0 + doAssert x.obj.time == 1.2 + doAssert x.obj.date == 0 + doAssert x.obj.scale == 1 + doAssert x.obj.value == 12 + + block: # tuple in object + var x: TupleInObject + doAssert x.data.base.value == 12 + doAssert x.data.typ == 0 + doAssert x.data.obj.time == 1.2 + doAssert x.data.obj.date == 0 + doAssert x.data.obj.scale == 1 + doAssert x.data.obj.value == 12 + doAssert x.size == 777 type ObjectArray = object From 6041db33cbf1ecfeaa6c6158b0b2d50ab943ea3d Mon Sep 17 00:00:00 2001 From: xflywind <43030857+xflywind@users.noreply.github.com> Date: Wed, 17 Aug 2022 23:40:10 +0800 Subject: [PATCH 38/52] fixes bugs --- compiler/semmagic.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index a7f30876fb486..2f7fb7b09bdb3 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -470,7 +470,7 @@ proc addDefaultFieldForNew(c: PContext, n: PNode): PNode = break t = skipTypes(base, skipPtrs) - if asgnExpr.sons.len > 0: + if asgnExpr.sons.len > 1: result = newTree(nkAsgn, result[1], asgnExpr) proc magicsAfterOverloadResolution(c: PContext, n: PNode, From c0179dfae9425551375b1487cc49b2832ab0ca2c Mon Sep 17 00:00:00 2001 From: xflywind <43030857+xflywind@users.noreply.github.com> Date: Thu, 18 Aug 2022 15:37:28 +0800 Subject: [PATCH 39/52] fixes tuple --- compiler/sem.nim | 62 ++++++++++++++++++++++++++----------------- compiler/semtypes.nim | 19 +++++++++---- 2 files changed, 51 insertions(+), 30 deletions(-) diff --git a/compiler/sem.nim b/compiler/sem.nim index 9fd7b4f5ae5d1..98a2f2cf346f5 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -557,6 +557,35 @@ proc defaultNodeField(c: PContext, a: PNode, aTyp: PType): PNode const defaultFieldsSkipTypes = {tyGenericInst, tyAlias, tySink, tyDistinct} +proc defaultFieldsForTuple(c: PContext, recNode: PNode, hasDefault: var bool): seq[PNode] = + case recNode.kind + of nkRecList: + for field in recNode: + result.add defaultFieldsForTuple(c, field, hasDefault) + of nkSym: + let field = recNode.sym + let recType = recNode.typ.skipTypes(defaultFieldsSkipTypes) + if field.ast != nil: #Try to use default value + hasDefault = true + result.add newTree(nkExprColonExpr, recNode, field.ast) + elif recType.kind in {tyObject, tyArray, tyTuple}: + let asgnExpr = defaultNodeField(c, recNode, recNode.typ) + if asgnExpr != nil: + hasDefault = true + asgnExpr.flags.incl nfUseDefaultField + result.add newTree(nkExprColonExpr, recNode, asgnExpr) + else: + let asgnType = newType(tyTypeDesc, nextTypeId(c.idgen), recType.owner) + rawAddSon(asgnType, recType) + let asgnExpr = newTree(nkCall, + newSymNode(getSysMagic(c.graph, recNode.info, "zeroDefault", mZeroDefault)), + newNodeIT(nkType, recNode.info, asgnType) + ) + asgnExpr.flags.incl nfUseDefaultField + asgnExpr.typ = recType + result.add newTree(nkExprColonExpr, recNode, asgnExpr) + else: + doAssert false proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode): seq[PNode] = case recNode.kind @@ -617,31 +646,14 @@ proc defaultNodeField(c: PContext, a: PNode, aTyp: PType): PNode = result.flags.incl nfUseDefaultField elif aTypSkip.kind == tyTuple: var hasDefault = false - var children: seq[PNode] - for s in aTypSkip.sons: - let child = defaultNodeField(c, a, s) - if child != nil: - hasDefault = true - children.add child - if hasDefault: - result = newNodeI(nkTupleConstr, a.info) - result.typ = aTyp - var i = 0 - while i < children.len: - let s = children[i] - if s != nil: - result.add s - else: - let asgnType = newType(tyTypeDesc, nextTypeId(c.idgen), aTypSkip[i].owner) - rawAddSon(asgnType, aTypSkip[i]) - let asgnExpr = newTree(nkCall, - newSymNode(getSysMagic(c.graph, a.info, "zeroDefault", mZeroDefault)), - newNodeIT(nkType, a.info, asgnType) - ) - asgnExpr.flags.incl nfUseDefaultField - asgnExpr.typ = aTypSkip[i] - result.add asgnExpr - inc i + if aTypSkip.n != nil: + let children = defaultFieldsForTuple(c, aTypSkip.n, hasDefault) + if hasDefault and children.len > 0: + result = newNodeI(nkTupleConstr, a.info) + result.typ = aTyp + result.flags.incl nfUseDefaultField + result.sons.add children + result = semExpr(c, result) proc defaultNodeField(c: PContext, a: PNode): PNode = result = defaultNodeField(c, a, a.typ) diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index f181cee177d1b..995ab6812f8e5 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -23,7 +23,6 @@ const errXExpectsOneTypeParam = "'$1' expects one type parameter" errArrayExpectsTwoTypeParams = "array expects two type parameters" errInvalidVisibilityX = "invalid visibility: '$1'" - errInitHereNotAllowed = "initialization not allowed here" errXCannotBeAssignedTo = "'$1' cannot be assigned to" errIteratorNotAllowed = "iterators can only be defined at the module's top level" errXNeedsReturnType = "$1 needs a return type" @@ -460,13 +459,19 @@ proc semTuple(c: PContext, n: PNode, prev: PType): PType = var a = n[i] if (a.kind != nkIdentDefs): illFormedAst(a, c.config) checkMinSonsLen(a, 3, c.config) - if a[^2].kind != nkEmpty: + var hasDefaultField = a[^1].kind != nkEmpty + if hasDefaultField: + a[^1] = semConstExpr(c, a[^1]) + typ = a[^1].typ + elif a[^2].kind != nkEmpty: typ = semTypeNode(c, a[^2], nil) + if c.graph.config.isDefined("nimPreviewRangeDefault") and typ.skipTypes(abstractInst).kind == tyRange: + a[^1] = newIntNode(nkIntLit, firstOrd(c.config, typ)) + a[^1].typ = typ + hasDefaultField = true else: localError(c.config, a.info, errTypeExpected) typ = errorType(c) - if a[^1].kind != nkEmpty: - localError(c.config, a[^1].info, errInitHereNotAllowed) for j in 0.. Date: Thu, 18 Aug 2022 15:38:40 +0800 Subject: [PATCH 40/52] add more tests --- tests/objects/tobject_default_value.nim | 126 ++++++++++++++++-------- 1 file changed, 85 insertions(+), 41 deletions(-) diff --git a/tests/objects/tobject_default_value.nim b/tests/objects/tobject_default_value.nim index 7fa0c11b08146..3e5a37bc6c29c 100644 --- a/tests/objects/tobject_default_value.nim +++ b/tests/objects/tobject_default_value.nim @@ -81,46 +81,6 @@ var t {.threadvar.}: Default block: doAssert t.se == 0'i32 -block: - type - Color = enum - Red, Blue, Yellow - - type - ObjectVarint3 = object # fixme it doesn't work with static - case kind: Color = Blue - of Red: - data1: int = 10 - of Blue: - case name: Color = Blue - of Blue: - go = 12 - else: - temp = 66 - fill2 = "123" - cry: float - of Yellow: - time3 = 1.8'f32 - him: int - block: - proc check: ObjectVarint3 = - discard - var x = check() - doAssert x.kind == Blue - doAssert x.name == Blue - doAssert x.go == 12 - - block: - var x: ObjectVarint3 - doAssert x.kind == Blue - doAssert x.name == Blue - doAssert x.go == 12 - - block: - var x = ObjectVarint3(kind: Blue, name: Red, temp: 99) - doAssert x.kind == Blue - doAssert x.name == Red - doAssert x.temp == 99 block: var x: Ref @@ -145,7 +105,7 @@ block: doAssert y.value == 12 doAssert y.data == 73 -template main = +template main {.dirty.} = block: # bug #16744 type R = range[1..10] @@ -366,6 +326,47 @@ template main = var x = ObjectVarint2(kind: Blue) doAssert x.fill == "123" + block: + type + Color = enum + Red, Blue, Yellow + + type + ObjectVarint3 = object # fixme it doesn't work with static + case kind: Color = Blue + of Red: + data1: int = 10 + of Blue: + case name: Color = Blue + of Blue: + go = 12 + else: + temp = 66 + fill2 = "123" + cry: float + of Yellow: + time3 = 1.8'f32 + him: int + block: + proc check: ObjectVarint3 = + discard + var x = check() + doAssert x.kind == Blue + doAssert x.name == Blue + doAssert x.go == 12 + + block: + var x: ObjectVarint3 + doAssert x.kind == Blue + doAssert x.name == Blue + doAssert x.go == 12 + + block: + var x = ObjectVarint3(kind: Blue, name: Red, temp: 99) + doAssert x.kind == Blue + doAssert x.name == Red + doAssert x.temp == 99 + block: type Default = object @@ -377,6 +378,49 @@ template main = doAssert hello[Default]()[^1].id == 1 + block: + type + Default = tuple + id: int = 1 + + Default2 = tuple[id: int = 1] + + var x: Default + proc hello(): Default2 = discard + doAssert hello().id == x.id + + block: + type + Default = tuple + id: int = 1 + obj: ObjectBase + name: string + + Class = object + def: Default + + Member = object + def: Default = (id: 777, obj: ObjectBase(), name: "fine") + + block: + var x: Default + doAssert x.id == 1 + doAssert x.obj == default(ObjectBase) + doAssert x.name == "" + + block: + var x: Class + doAssert x.def == default(Default) + doAssert x.def.id == 1 + doAssert x.def.obj == default(ObjectBase) + doAssert x.def.name == "" + + when not defined(cpp): + block: + var x: Member + doAssert x.def.id == 777 + doAssert x.def.obj == default(ObjectBase) + doAssert x.def.name == "fine" proc main1 = var my = @[1, 2, 3, 4, 5] From 506c07adf59b19a28aff1c788e5e878d39475a77 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+xflywind@users.noreply.github.com> Date: Thu, 18 Aug 2022 17:01:57 +0800 Subject: [PATCH 41/52] fix one more bug regarding tuples --- compiler/sem.nim | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/compiler/sem.nim b/compiler/sem.nim index 98a2f2cf346f5..f6cef30198ee5 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -568,13 +568,15 @@ proc defaultFieldsForTuple(c: PContext, recNode: PNode, hasDefault: var bool): s if field.ast != nil: #Try to use default value hasDefault = true result.add newTree(nkExprColonExpr, recNode, field.ast) - elif recType.kind in {tyObject, tyArray, tyTuple}: - let asgnExpr = defaultNodeField(c, recNode, recNode.typ) - if asgnExpr != nil: - hasDefault = true - asgnExpr.flags.incl nfUseDefaultField - result.add newTree(nkExprColonExpr, recNode, asgnExpr) else: + if recType.kind in {tyObject, tyArray, tyTuple}: + let asgnExpr = defaultNodeField(c, recNode, recNode.typ) + if asgnExpr != nil: + hasDefault = true + asgnExpr.flags.incl nfUseDefaultField + result.add newTree(nkExprColonExpr, recNode, asgnExpr) + return + let asgnType = newType(tyTypeDesc, nextTypeId(c.idgen), recType.owner) rawAddSon(asgnType, recType) let asgnExpr = newTree(nkCall, From e888dd4dde0de556837be934e7eb58900148f6b2 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+xflywind@users.noreply.github.com> Date: Thu, 18 Aug 2022 22:00:16 +0800 Subject: [PATCH 42/52] more tests and cleanup --- compiler/ast.nim | 2 +- compiler/sem.nim | 3 -- tests/objects/tobject_default_value.nim | 60 ++++++++++++++++--------- 3 files changed, 41 insertions(+), 24 deletions(-) diff --git a/compiler/ast.nim b/compiler/ast.nim index 0133e8dd4159c..ad6e7fe8b0062 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -503,7 +503,7 @@ type nfLastRead # this node is a last read nfFirstWrite# this node is a first write nfHasComment # node has a comment - nfUseDefaultField + nfUseDefaultField # node has a default value (object constructor) TNodeFlags* = set[TNodeFlag] TTypeFlag* = enum # keep below 32 for efficiency reasons (now: 45) diff --git a/compiler/sem.nim b/compiler/sem.nim index f6cef30198ee5..bf53818d4cddd 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -627,7 +627,6 @@ proc defaultNodeField(c: PContext, a: PNode, aTyp: PType): PNode = if child.len > 0: let aTypSkipDistinct = aTyp.skipTypes({tyDistinct}) var asgnExpr = newTree(nkObjConstr, newNodeIT(nkType, a.info, aTypSkipDistinct)) - asgnExpr.flags.incl nfUseDefaultField asgnExpr.typ = aTypSkipDistinct asgnExpr.sons.add child result = semExpr(c, asgnExpr) @@ -645,7 +644,6 @@ proc defaultNodeField(c: PContext, a: PNode, aTyp: PType): PNode = node )) result.typ = aTyp - result.flags.incl nfUseDefaultField elif aTypSkip.kind == tyTuple: var hasDefault = false if aTypSkip.n != nil: @@ -653,7 +651,6 @@ proc defaultNodeField(c: PContext, a: PNode, aTyp: PType): PNode = if hasDefault and children.len > 0: result = newNodeI(nkTupleConstr, a.info) result.typ = aTyp - result.flags.incl nfUseDefaultField result.sons.add children result = semExpr(c, result) diff --git a/tests/objects/tobject_default_value.nim b/tests/objects/tobject_default_value.nim index 3e5a37bc6c29c..55a22f6ab97fa 100644 --- a/tests/objects/tobject_default_value.nim +++ b/tests/objects/tobject_default_value.nim @@ -81,29 +81,30 @@ var t {.threadvar.}: Default block: doAssert t.se == 0'i32 +block: # ARC/ORC cannot bind destructors twice, so it cannot + # be moved into main + block: + var x: Ref + new(x) + doAssert x.value == 12, "Ref.value = " & $x.value -block: - var x: Ref - new(x) - doAssert x.value == 12, "Ref.value = " & $x.value - - var y: RefInt - new(y) - doAssert y.value == 12 - doAssert y.data == 73 + var y: RefInt + new(y) + doAssert y.value == 12 + doAssert y.data == 73 -block: - var x: Ref2 - new(x, proc (x: Ref2) {.nimcall.} = discard "call Ref") - doAssert x.value == 12, "Ref.value = " & $x.value + block: + var x: Ref2 + new(x, proc (x: Ref2) {.nimcall.} = discard "call Ref") + doAssert x.value == 12, "Ref.value = " & $x.value - proc call(x: RefInt2) = - discard "call RefInt" + proc call(x: RefInt2) = + discard "call RefInt" - var y: RefInt2 - new(y, call) - doAssert y.value == 12 - doAssert y.data == 73 + var y: RefInt2 + new(y, call) + doAssert y.value == 12 + doAssert y.data == 73 template main {.dirty.} = block: # bug #16744 @@ -129,7 +130,7 @@ template main {.dirty.} = result.w = 20 doAssert createABC().w == 20 - + block: var x: ObjectBase doAssert x.value == 12 @@ -141,6 +142,16 @@ template main {.dirty.} = let z = hello() doAssert z.value == 12 + + block: + var x = new ObjectBase + doAssert x.value == 12 + + proc hello(): ref ObjectBase = + new result + + let z = hello() + doAssert z.value == 12 block: var x: ObjectBaseDistinct @@ -190,12 +201,21 @@ template main {.dirty.} = doAssert x3.time == 1.2 doAssert x3.scale == 1 + block: + var x = new Object + doAssert x[] == default(Object) + block: var x: Object2 doAssert x.name.value == 12 doAssert x.name.time == 1.2 doAssert x.name.scale == 1 + block: + var x: ref Object2 + new x + doAssert x[] == default(Object2) + block: var x: Object3 doAssert x.obj.name.value == 12 From ff38a2ab7f073d87ee24d1be62c2205c5d3dab83 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+xflywind@users.noreply.github.com> Date: Fri, 19 Aug 2022 10:12:16 +0800 Subject: [PATCH 43/52] remove messy distinct types which must be initialized by original types --- compiler/sem.nim | 10 +++------- tests/objects/tobject_default_value.nim | 25 +++++++++++++------------ 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/compiler/sem.nim b/compiler/sem.nim index bf53818d4cddd..63a182ee19701 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -555,7 +555,7 @@ proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode): seq[PNode] proc defaultNodeField(c: PContext, a: PNode): PNode proc defaultNodeField(c: PContext, a: PNode, aTyp: PType): PNode -const defaultFieldsSkipTypes = {tyGenericInst, tyAlias, tySink, tyDistinct} +const defaultFieldsSkipTypes = {tyGenericInst, tyAlias, tySink} proc defaultFieldsForTuple(c: PContext, recNode: PNode, hasDefault: var bool): seq[PNode] = case recNode.kind @@ -625,14 +625,10 @@ proc defaultNodeField(c: PContext, a: PNode, aTyp: PType): PNode = if aTypSkip.kind == tyObject: let child = defaultFieldsForTheUninitialized(c, aTyp.skipTypes(defaultFieldsSkipTypes).n) if child.len > 0: - let aTypSkipDistinct = aTyp.skipTypes({tyDistinct}) - var asgnExpr = newTree(nkObjConstr, newNodeIT(nkType, a.info, aTypSkipDistinct)) - asgnExpr.typ = aTypSkipDistinct + var asgnExpr = newTree(nkObjConstr, newNodeIT(nkType, a.info, aTyp)) + asgnExpr.typ = aTyp asgnExpr.sons.add child result = semExpr(c, asgnExpr) - if aTyp.kind == tyDistinct: - result = newTree(nkConv, newNodeIT(nkType, a.info, aTyp), result) - result.typ = aTyp elif aTypSkip.kind == tyArray: let child = defaultNodeField(c, a, aTypSkip[1]) diff --git a/tests/objects/tobject_default_value.nim b/tests/objects/tobject_default_value.nim index 55a22f6ab97fa..0448e07af0140 100644 --- a/tests/objects/tobject_default_value.nim +++ b/tests/objects/tobject_default_value.nim @@ -153,22 +153,23 @@ template main {.dirty.} = let z = hello() doAssert z.value == 12 - block: - var x: ObjectBaseDistinct - doAssert ObjectBase(x).value == 12 - let y = default(ObjectBaseDistinct) - doAssert ObjectBase(y).value == 12 + when false: + block: + var x: ObjectBaseDistinct + doAssert ObjectBase(x).value == 12 + let y = default(ObjectBaseDistinct) + doAssert ObjectBase(y).value == 12 - proc hello(): ObjectBaseDistinct = - discard + proc hello(): ObjectBaseDistinct = + discard - let z = hello() - doAssert ObjectBase(z).value == 12 + let z = hello() + doAssert ObjectBase(z).value == 12 - block: - var x: DinstinctInObject + block: + var x: DinstinctInObject - doAssert ObjectBase(x.data).value == 12 + doAssert ObjectBase(x.data).value == 12 block: var x: Object From 9484db8d6efadb87aa512c81e13cb5353a1c2555 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+xflywind@users.noreply.github.com> Date: Fri, 19 Aug 2022 10:17:22 +0800 Subject: [PATCH 44/52] add tests --- tests/objects/tobject_default_value.nim | 27 +++++++++++++------------ 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/tests/objects/tobject_default_value.nim b/tests/objects/tobject_default_value.nim index 0448e07af0140..9bd9cf56e112c 100644 --- a/tests/objects/tobject_default_value.nim +++ b/tests/objects/tobject_default_value.nim @@ -153,23 +153,24 @@ template main {.dirty.} = let z = hello() doAssert z.value == 12 - when false: - block: - var x: ObjectBaseDistinct - doAssert ObjectBase(x).value == 12 - let y = default(ObjectBaseDistinct) - doAssert ObjectBase(y).value == 12 + block: + var base: ObjectBase + var x: ObjectBaseDistinct = ObjectBaseDistinct(base) + doAssert ObjectBase(x).value == 12 + let y = ObjectBaseDistinct(default(ObjectBase)) + doAssert ObjectBase(y).value == 12 - proc hello(): ObjectBaseDistinct = - discard + proc hello(): ObjectBaseDistinct = + result = ObjectBaseDistinct(default(ObjectBase)) - let z = hello() - doAssert ObjectBase(z).value == 12 + let z = hello() + doAssert ObjectBase(z).value == 12 - block: - var x: DinstinctInObject + block: + var x: DinstinctInObject + x.data = ObjectBaseDistinct(default(ObjectBase)) - doAssert ObjectBase(x.data).value == 12 + doAssert ObjectBase(x.data).value == 12 block: var x: Object From 0b1542c6c648b423819b5cbc184b4629ecd88aa9 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+ringabout@users.noreply.github.com> Date: Sun, 2 Oct 2022 17:50:19 +0800 Subject: [PATCH 45/52] fixes zero default --- lib/system.nim | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/system.nim b/lib/system.nim index 64dc2e5168470..438b543b57dc2 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -24,6 +24,9 @@ include "system/basic_types" +func zeroDefault*[T](_: typedesc[T]): T {.magic: "ZeroDefault".} = + ## returns the default value of the type `T`. + include "system/compilation" {.push warning[GcMem]: off, warning[Uninit]: off.} @@ -908,8 +911,6 @@ proc default*[T](_: typedesc[T]): T {.magic: "Default", noSideEffect.} = # note: the doc comment also explains why `default` can't be implemented # via: `template default*[T](t: typedesc[T]): T = (var v: T; v)` -func zeroDefault*[T](_: typedesc[T]): T {.magic: "ZeroDefault".} = - ## returns the default value of the type `T`. proc reset*[T](obj: var T) {.noSideEffect.} = ## Resets an object `obj` to its default value. From 1c60bb9101cfeb8a6e6b479cb7a3798df66426ac Mon Sep 17 00:00:00 2001 From: xflywind <43030857+ringabout@users.noreply.github.com> Date: Sun, 2 Oct 2022 17:56:35 +0800 Subject: [PATCH 46/52] fixes grammar --- compiler/parser.nim | 2 +- doc/grammar.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/parser.nim b/compiler/parser.nim index d44a9b5cdc021..9f489766583b6 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -1960,7 +1960,7 @@ proc parseObjectCase(p: var Parser): PNode = #| objectBranches = objectBranch (IND{=} objectBranch)* #| (IND{=} 'elif' expr colcom objectPart)* #| (IND{=} 'else' colcom objectPart)? - #| objectCase = 'case' identWithPragma ':' typeDesc ':'? COMMENT? + #| objectCase = 'case' declColonEquals ':'? COMMENT? #| (IND{>} objectBranches DED #| | IND{=} objectBranches) result = newNodeP(nkRecCase, p) diff --git a/doc/grammar.txt b/doc/grammar.txt index 878a4e5e1f2aa..29a4300b6e60e 100644 --- a/doc/grammar.txt +++ b/doc/grammar.txt @@ -166,7 +166,7 @@ objectBranch = 'of' exprList colcom objectPart objectBranches = objectBranch (IND{=} objectBranch)* (IND{=} 'elif' expr colcom objectPart)* (IND{=} 'else' colcom objectPart)? -objectCase = 'case' identWithPragma ':' typeDesc ':'? COMMENT? +objectCase = 'case' declColonEquals ':'? COMMENT? (IND{>} objectBranches DED | IND{=} objectBranches) objectPart = IND{>} objectPart^+IND{=} DED From a4bb4783fd52e2ae62002f072f4862a2dd326dcf Mon Sep 17 00:00:00 2001 From: xflywind <43030857+ringabout@users.noreply.github.com> Date: Sun, 2 Oct 2022 19:07:23 +0800 Subject: [PATCH 47/52] fixes tests --- compiler/semexprs.nim | 6 ------ compiler/semmagic.nim | 21 +++++++++++++++------ 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index af00da4a5eeef..2956ab4b65a07 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -2397,12 +2397,6 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags; expectedType: P of mSizeOf: markUsed(c, n.info, s) result = semSizeof(c, setMs(n, s)) - of mDefault: - result = semDirectOp(c, n, flags) - let typ = result[^1].typ.skipTypes({tyTypeDesc}) - let defaultExpr = defaultNodeField(c, result[^1], typ) - if defaultExpr != nil: - result = defaultExpr of mArrToSeq, mOpenArrayToSeq: if n.len == 2 and expectedType != nil and ( let expected = expectedType.skipTypes(abstractRange-{tyDistinct}); diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index 7a9fd3f374b36..5cfde46f00073 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -521,6 +521,13 @@ proc semPrivateAccess(c: PContext, n: PNode): PNode = c.currentScope.allowPrivateAccess.add t.sym result = newNodeIT(nkEmpty, n.info, getSysType(c.graph, n.info, tyVoid)) +proc checkDefault(c: PContext, n: PNode): PNode = + result = n + c.config.internalAssert result[1].typ.kind == tyTypeDesc + let constructed = result[1].typ.base + if constructed.requiresInit: + message(c.config, n.info, warnUnsafeDefault, typeToString(constructed)) + proc magicsAfterOverloadResolution(c: PContext, n: PNode, flags: TExprFlags): PNode = ## This is the preferred code point to implement magics. @@ -608,12 +615,14 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode, tyAlias, tyUserTypeClassInst}) if seqType.kind == tySequence and seqType.base.requiresInit: message(c.config, n.info, warnUnsafeSetLen, typeToString(seqType.base)) - of mDefault, mZeroDefault: - result = n - c.config.internalAssert result[1].typ.kind == tyTypeDesc - let constructed = result[1].typ.base - if constructed.requiresInit: - message(c.config, n.info, warnUnsafeDefault, typeToString(constructed)) + of mDefault: + result = checkDefault(c, n) + let typ = result[^1].typ.skipTypes({tyTypeDesc}) + let defaultExpr = defaultNodeField(c, result[^1], typ) + if defaultExpr != nil: + result = defaultExpr + of mZeroDefault: + result = checkDefault(c, n) of mIsolate: if not checkIsolate(n[1]): localError(c.config, n.info, "expression cannot be isolated: " & $n[1]) From c58560f32f40178bad60bfe278e91e28fc7fba19 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+ringabout@users.noreply.github.com> Date: Sun, 2 Oct 2022 20:22:27 +0800 Subject: [PATCH 48/52] fixes tests --- lib/system/seqs_v2.nim | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/system/seqs_v2.nim b/lib/system/seqs_v2.nim index 40fd50b48dc75..f476d0ad13981 100644 --- a/lib/system/seqs_v2.nim +++ b/lib/system/seqs_v2.nim @@ -125,8 +125,9 @@ proc setLen[T](s: var seq[T], newlen: Natural) = if xu.p == nil or xu.p.cap < newlen: xu.p = cast[typeof(xu.p)](prepareSeqAdd(oldLen, xu.p, newlen - oldLen, sizeof(T), alignof(T))) xu.len = newlen + let defaultValue = default(T) for i in oldLen.. Date: Sun, 2 Oct 2022 21:29:52 +0800 Subject: [PATCH 49/52] fixes tests --- lib/system/seqs_v2.nim | 3 +-- tests/errmsgs/t5167_5.nim | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/system/seqs_v2.nim b/lib/system/seqs_v2.nim index f476d0ad13981..40fd50b48dc75 100644 --- a/lib/system/seqs_v2.nim +++ b/lib/system/seqs_v2.nim @@ -125,9 +125,8 @@ proc setLen[T](s: var seq[T], newlen: Natural) = if xu.p == nil or xu.p.cap < newlen: xu.p = cast[typeof(xu.p)](prepareSeqAdd(oldLen, xu.p, newlen - oldLen, sizeof(T), alignof(T))) xu.len = newlen - let defaultValue = default(T) for i in oldLen.. Date: Mon, 3 Oct 2022 19:54:42 +0800 Subject: [PATCH 50/52] fixes comments --- compiler/semstmts.nim | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 32e4a0be1e581..d63a8b1ecff4c 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -613,14 +613,14 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode = var def: PNode = c.graph.emptyNode if a[^1].kind == nkEmpty and symkind == skVar and a[^2].typ != nil: - # let m = copyTree(a[0]) - # var v = semIdentDef(c, m, symkind, false) - # if {sfThread, sfNoInit} * v.flags != {}: # todo var m1, m2 {threadvar} - # discard # todo init threadvar properly - # else: - let field = defaultNodeField(c, a[^2]) - if field != nil: - a[^1] = field + let m = copyTree(a[0]) + var v = semIdentDef(c, m, symkind, false) + if {sfThread, sfNoInit} * v.flags != {}: # todo var m1, m2 {threadvar} + discard # todo init threadvar properly + else: + let field = defaultNodeField(c, a[^2]) + if field != nil: + a[^1] = field if a[^1].kind != nkEmpty: def = semExprWithType(c, a[^1], {}, typ) @@ -689,9 +689,6 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode = addToVarSection(c, result, n, a) continue var v = semIdentDef(c, a[j], symkind, false) - if {sfThread, sfNoInit} * v.flags != {}: - a[^1] = c.graph.emptyNode - def = c.graph.emptyNode styleCheckDef(c, v) onDef(a[j].info, v) if sfGenSym notin v.flags: From ee531738eb2c6e7a65e9b4e106b588df16a5e675 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+ringabout@users.noreply.github.com> Date: Mon, 3 Oct 2022 21:07:30 +0800 Subject: [PATCH 51/52] fixes and add testcase --- compiler/semstmts.nim | 18 ++++++++++-------- tests/objects/tobject_default_value.nim | 17 ++++++++++++++++- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index d63a8b1ecff4c..ea646d01aab0c 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -613,14 +613,10 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode = var def: PNode = c.graph.emptyNode if a[^1].kind == nkEmpty and symkind == skVar and a[^2].typ != nil: - let m = copyTree(a[0]) - var v = semIdentDef(c, m, symkind, false) - if {sfThread, sfNoInit} * v.flags != {}: # todo var m1, m2 {threadvar} - discard # todo init threadvar properly - else: - let field = defaultNodeField(c, a[^2]) - if field != nil: - a[^1] = field + let field = defaultNodeField(c, a[^2]) + if field != nil: + a[^1] = field + field.flags.incl nfUseDefaultField if a[^1].kind != nkEmpty: def = semExprWithType(c, a[^1], {}, typ) @@ -689,6 +685,12 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode = addToVarSection(c, result, n, a) continue var v = semIdentDef(c, a[j], symkind, false) + if a[^1].kind != nkEmpty: + if {sfThread, sfNoInit} * v.flags != {} and + nfUseDefaultField in a[^1].flags: + a[^1] = c.graph.emptyNode + def = c.graph.emptyNode + a[^1].flags.excl nfUseDefaultField styleCheckDef(c, v) onDef(a[j].info, v) if sfGenSym notin v.flags: diff --git a/tests/objects/tobject_default_value.nim b/tests/objects/tobject_default_value.nim index 9bd9cf56e112c..42296e72140a3 100644 --- a/tests/objects/tobject_default_value.nim +++ b/tests/objects/tobject_default_value.nim @@ -1,5 +1,5 @@ discard """ - matrix: "-d:nimPreviewRangeDefault; -d:nimPreviewRangeDefault --warningAsError:ProveInit --mm:orc" + matrix: "-d:nimPreviewRangeDefault --mm:refc; -d:nimPreviewRangeDefault --warningAsError:ProveInit --mm:orc" targets: "c cpp js" """ @@ -444,6 +444,21 @@ template main {.dirty.} = doAssert x.def.obj == default(ObjectBase) doAssert x.def.name == "fine" + block: + var x {.noinit.} = 12 + doAssert x == 12 + + type + Pure = object + id: int = 12 + + var y {.noinit.}: Pure + doAssert y.id == 0 + + var z {.noinit.}: Pure = Pure(id: 77) + doAssert z.id == 77 + + proc main1 = var my = @[1, 2, 3, 4, 5] my.setLen(0) From 7c82f8d8f3d836da61c04836c399747d446ad287 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+ringabout@users.noreply.github.com> Date: Tue, 4 Oct 2022 01:15:56 +0800 Subject: [PATCH 52/52] undo default values for results --- compiler/sem.nim | 1 - compiler/seminst.nim | 2 - compiler/semstmts.nim | 20 ---------- tests/objects/tobject_default_value.nim | 50 ------------------------- 4 files changed, 73 deletions(-) diff --git a/compiler/sem.nim b/compiler/sem.nim index d4283ff4748b7..8f766f126c8e7 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -45,7 +45,6 @@ proc semOpAux(c: PContext, n: PNode) proc semParamList(c: PContext, n, genericParams: PNode, s: PSym) proc addParams(c: PContext, n: PNode, kind: TSymKind) proc maybeAddResult(c: PContext, s: PSym, n: PNode) -proc addDefaultFieldForResult(c: PContext, n: PNode, t: PType) proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode proc activate(c: PContext, n: PNode) proc semQuoteAst(c: PContext, n: PNode): PNode diff --git a/compiler/seminst.nim b/compiler/seminst.nim index e977516b2ac13..bd5eb1ec319c3 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -133,8 +133,6 @@ proc instantiateBody(c: PContext, n, params: PNode, result, orig: PSym) = # As body is a sym to the borrowed proc. b = semProcBody(c, b) result.ast[bodyPos] = hloBody(c, b) - if orig.kind notin {skMacro, skTemplate} and orig.magic == mNone and sfNoInit notin orig.flags: - addDefaultFieldForResult(c, n, orig.typ[0]) excl(result.flags, sfForward) trackProc(c, result, result.ast[bodyPos]) dec c.inGenericInst diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index ea646d01aab0c..27a9c170b4fdd 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -1650,20 +1650,6 @@ proc addResult(c: PContext, n: PNode, t: PType, owner: TSymKind) = n.add newSymNode(c.p.resultSym) addParamOrResult(c, c.p.resultSym, owner) -proc addDefaultFieldForResult(c: PContext, n: PNode, t: PType) = - if t != nil and n.len > resultPos and n[resultPos] != nil and - c.config.cmd notin cmdDocLike: - var field = defaultNodeField(c, n[resultPos]) - if field != nil: - field = semExpr(c, field) - if n[bodyPos].kind in {nkStmtList, nkStmtListExpr}: - n[bodyPos].sons.insert(newTree(nkAsgn, n[resultPos], field), 0) - else: - var bodyWithDefaultResult = newNodeIT(nkStmtList, n.info, nil) - bodyWithDefaultResult.add newTree(nkAsgn, n[resultPos], field) - bodyWithDefaultResult.add n[bodyPos] - n[bodyPos] = bodyWithDefaultResult - proc semProcAnnotation(c: PContext, prc: PNode; validPragmas: TSpecialWords): PNode = # Mirrored with semVarMacroPragma @@ -1749,8 +1735,6 @@ proc semInferredLambda(c: PContext, pt: TIdTable, n: PNode): PNode {.nosinks.} = pushProcCon(c, s) addResult(c, n, n.typ[0], skProc) s.ast[bodyPos] = hloBody(c, semProcBody(c, n[bodyPos], n.typ[0])) - if s.kind notin {skMacro, skTemplate} and s.magic == mNone and sfNoInit notin s.flags: - addDefaultFieldForResult(c, n, n.typ[0]) trackProc(c, s, s.ast[bodyPos]) popProcCon(c) popOwner(c) @@ -2173,8 +2157,6 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, pushProcCon(c, s) addResult(c, n, s.typ[0], skProc) s.ast[bodyPos] = hloBody(c, semProcBody(c, n[bodyPos], s.typ[0])) - if s.kind notin {skMacro, skTemplate} and s.magic == mNone and sfNoInit notin s.flags: - addDefaultFieldForResult(c, n, s.typ[0]) trackProc(c, s, s.ast[bodyPos]) popProcCon(c) elif efOperand notin flags: @@ -2196,8 +2178,6 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, nil # semantic checking also needed with importc in case used in VM s.ast[bodyPos] = hloBody(c, semProcBody(c, n[bodyPos], resultType)) - if s.kind notin {skMacro, skTemplate} and s.magic == mNone and sfNoInit notin s.flags: - addDefaultFieldForResult(c, n, s.typ[0]) # unfortunately we cannot skip this step when in 'system.compiles' # context as it may even be evaluated in 'system.compiles': trackProc(c, s, s.ast[bodyPos]) diff --git a/tests/objects/tobject_default_value.nim b/tests/objects/tobject_default_value.nim index 42296e72140a3..d826566fd5896 100644 --- a/tests/objects/tobject_default_value.nim +++ b/tests/objects/tobject_default_value.nim @@ -131,18 +131,6 @@ template main {.dirty.} = doAssert createABC().w == 20 - block: - var x: ObjectBase - doAssert x.value == 12 - let y = default(ObjectBase) - doAssert y.value == 12 - - proc hello(): ObjectBase = - discard - - let z = hello() - doAssert z.value == 12 - block: var x = new ObjectBase doAssert x.value == 12 @@ -178,15 +166,6 @@ template main {.dirty.} = doAssert x.time == 1.2 doAssert x.scale == 1 - proc hello(): Object = - var dummy = 1 - dummy += 18 - - let h1 = hello() - doAssert h1.value == 12 - doAssert h1.time == 1.2 - doAssert h1.scale == 1 - let y = default(Object) doAssert y.value == 12 doAssert y.time == 1.2 @@ -369,13 +348,6 @@ template main {.dirty.} = of Yellow: time3 = 1.8'f32 him: int - block: - proc check: ObjectVarint3 = - discard - var x = check() - doAssert x.kind == Blue - doAssert x.name == Blue - doAssert x.go == 12 block: var x: ObjectVarint3 @@ -389,28 +361,6 @@ template main {.dirty.} = doAssert x.name == Red doAssert x.temp == 99 - block: - type - Default = object - id: int = 1 - - proc hello[T](): array[10, T] = - let x = 1 - doAssert result[0].id == x - - doAssert hello[Default]()[^1].id == 1 - - block: - type - Default = tuple - id: int = 1 - - Default2 = tuple[id: int = 1] - - var x: Default - proc hello(): Default2 = discard - doAssert hello().id == x.id - block: type Default = tuple