Skip to content

Commit 51d616d

Browse files
committed
checkpoint
1 parent 8bfc396 commit 51d616d

File tree

6 files changed

+124
-37
lines changed

6 files changed

+124
-37
lines changed

compiler/parser.nim

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1963,11 +1963,7 @@ proc parseObjectCase(p: var Parser): PNode =
19631963
#| | IND{=} objectBranches)
19641964
result = newNodeP(nkRecCase, p)
19651965
getTokNoInd(p)
1966-
var a = newNodeP(nkIdentDefs, p)
1967-
a.add(identWithPragma(p))
1968-
eat(p, tkColon)
1969-
a.add(parseTypeDesc(p))
1970-
a.add(p.emptyNode)
1966+
var a = parseIdentColonEquals(p, {withPragma})
19711967
result.add(a)
19721968
if p.tok.tokType == tkColon: getTok(p)
19731969
flexComment(p, result)

compiler/semexprs.nim

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2380,6 +2380,25 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
23802380
of mSizeOf:
23812381
markUsed(c, n.info, s)
23822382
result = semSizeof(c, setMs(n, s))
2383+
of mDefault:
2384+
result = semDirectOp(c, n, flags)
2385+
let typ = result[^1].typ.skipTypes({tyTypeDesc})
2386+
if typ.skipTypes(abstractInst).kind == tyObject or
2387+
typ.skipTypes(abstractInst).kind == tyRef and typ.skipTypes(abstractInst)[0].kind == tyObject:
2388+
var asgnExpr = newTree(nkObjConstr, newNodeIT(nkType, result[^1].info, typ))
2389+
asgnExpr.typ = typ
2390+
asgnExpr.sons.add defaultFieldsForTheUninitialized(typ.n)
2391+
result = semObjConstr(c, asgnExpr, flags)
2392+
of mNew:
2393+
result = semDirectOp(c, n, flags)
2394+
let typ = result[^1].typ.skipTypes({tyTypeDesc})
2395+
debug result[^1]
2396+
echo result.renderTree
2397+
if typ.skipTypes(abstractInst).kind == tyRef and typ.skipTypes(abstractInst)[0].kind == tyObject:
2398+
var asgnExpr = newTree(nkObjConstr, newNodeIT(nkType, result[^1].info, typ))
2399+
asgnExpr.typ = typ
2400+
asgnExpr.sons.add defaultFieldsForTheUninitialized(typ.n)
2401+
result = semObjConstr(c, asgnExpr, flags)
23832402
else:
23842403
result = semDirectOp(c, n, flags)
23852404

compiler/semobjconstr.nim

Lines changed: 34 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ type
2929
initNone # None of the fields have been initialized
3030
initConflict # Fields from different branches have been initialized
3131

32+
33+
proc semConstructFields(c: PContext, n: PNode, constrCtx: var ObjConstrContext,
34+
flags: TExprFlags): tuple[status: InitStatus, defaults: seq[PNode]]
35+
3236
proc mergeInitStatus(existing: var InitStatus, newStatus: InitStatus) =
3337
case newStatus
3438
of initConflict:
@@ -155,18 +159,14 @@ proc collectMissingFields(c: PContext, fieldsRecList: PNode,
155159
if assignment == nil:
156160
constrCtx.missingFields.add r.sym
157161

158-
159-
proc semConstructFields(c: PContext, n: PNode,
160-
constrCtx: var ObjConstrContext,
161-
flags: TExprFlags): InitStatus =
162-
result = initUnknown
163-
162+
proc semConstructFields(c: PContext, n: PNode, constrCtx: var ObjConstrContext,
163+
flags: TExprFlags): tuple[status: InitStatus, defaults: seq[PNode]] =
164164
case n.kind
165165
of nkRecList:
166166
for field in n:
167-
let status = semConstructFields(c, field, constrCtx, flags)
168-
mergeInitStatus(result, status)
169-
167+
let (subSt, subDf) = semConstructFields(c, field, constrCtx, flags)
168+
result.status.mergeInitStatus subSt
169+
result.defaults.add subDf
170170
of nkRecCase:
171171
template fieldsPresentInBranch(branchIdx: int): string =
172172
let branch = n[branchIdx]
@@ -184,17 +184,18 @@ proc semConstructFields(c: PContext, n: PNode,
184184

185185
for i in 1..<n.len:
186186
let innerRecords = n[i][^1]
187-
let status = semConstructFields(c, innerRecords, constrCtx, flags)
187+
let (status, defaults) = semConstructFields(c, innerRecords, constrCtx, flags)
188188
if status notin {initNone, initUnknown}:
189-
mergeInitStatus(result, status)
189+
result.status.mergeInitStatus status
190+
result.defaults.add defaults
190191
if selectedBranch != -1:
191192
let prevFields = fieldsPresentInBranch(selectedBranch)
192193
let currentFields = fieldsPresentInBranch(i)
193194
localError(c.config, constrCtx.initExpr.info,
194195
("The fields '$1' and '$2' cannot be initialized together, " &
195196
"because they are from conflicting branches in the case object.") %
196197
[prevFields, currentFields])
197-
result = initConflict
198+
result.status = initConflict
198199
else:
199200
selectedBranch = i
200201

@@ -206,7 +207,7 @@ proc semConstructFields(c: PContext, n: PNode,
206207
("cannot prove that it's safe to initialize $1 with " &
207208
"the runtime value for the discriminator '$2' ") %
208209
[fields, discriminator.sym.name.s])
209-
mergeInitStatus(result, initNone)
210+
mergeInitStatus(result.status, initNone)
210211

211212
template wrongBranchError(i) =
212213
if c.inUncheckedAssignSection == 0:
@@ -291,11 +292,11 @@ proc semConstructFields(c: PContext, n: PNode,
291292

292293
# When a branch is selected with a partial match, some of the fields
293294
# that were not initialized may be mandatory. We must check for this:
294-
if result == initPartial:
295+
if result.status == initPartial:
295296
collectMissingFields branchNode
296297

297298
else:
298-
result = initNone
299+
result.status = initNone
299300
let discriminatorVal = semConstrField(c, flags + {efPreferStatic},
300301
discriminator.sym,
301302
constrCtx.initExpr)
@@ -308,7 +309,7 @@ proc semConstructFields(c: PContext, n: PNode,
308309
let matchedBranch = n.pickCaseBranch defaultValue
309310
collectMissingFields matchedBranch
310311
else:
311-
result = initPartial
312+
result.status = initPartial
312313
if discriminatorVal.kind == nkIntLit:
313314
# When the discriminator is a compile-time value, we also know
314315
# which branch will be selected:
@@ -318,23 +319,28 @@ proc semConstructFields(c: PContext, n: PNode,
318319
# All bets are off. If any of the branches has a mandatory
319320
# fields we must produce an error:
320321
for i in 1..<n.len: collectMissingFields n[i]
321-
322322
of nkSym:
323323
let field = n.sym
324324
let e = semConstrField(c, flags, field, constrCtx.initExpr)
325-
result = if e != nil: initFull else: initNone
326-
325+
if e != nil:
326+
result.status = initFull
327+
elif field.ast != nil:
328+
result.status = initUnknown
329+
result.defaults.add newTree(nkExprColonExpr, n, field.ast)
330+
else:
331+
result.status = initNone
327332
else:
328333
internalAssert c.config, false
329334

330335
proc semConstructTypeAux(c: PContext,
331336
constrCtx: var ObjConstrContext,
332-
flags: TExprFlags): InitStatus =
333-
result = initUnknown
337+
flags: TExprFlags): tuple[status: InitStatus, defaults: seq[PNode]] =
338+
result.status = initUnknown
334339
var t = constrCtx.typ
335340
while true:
336-
let status = semConstructFields(c, t.n, constrCtx, flags)
337-
mergeInitStatus(result, status)
341+
let (status, defaults) = semConstructFields(c, t.n, constrCtx, flags)
342+
result.status.mergeInitStatus status
343+
result.defaults.add defaults
338344
if status in {initPartial, initNone, initUnknown}:
339345
collectMissingFields c, t.n, constrCtx
340346
let base = t[0]
@@ -378,7 +384,9 @@ proc defaultConstructionError(c: PContext, t: PType, info: TLineInfo) =
378384
proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
379385
var t = semTypeNode(c, n[0], nil)
380386
result = newNodeIT(nkObjConstr, n.info, t)
381-
for child in n: result.add child
387+
result.add newNodeIT(nkType, n.info, t) #This will contain the default values to be added in transf
388+
for i in 1..<n.len:
389+
result.add n[i]
382390

383391
if t == nil:
384392
return localErrorNode(c, result, "object constructor needs an object type")
@@ -399,7 +407,8 @@ proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
399407
# field (if this is a case object, initialized fields in two different
400408
# branches will be reported as an error):
401409
var constrCtx = initConstrContext(t, result)
402-
let initResult = semConstructTypeAux(c, constrCtx, flags)
410+
let (initResult, defaults) = semConstructTypeAux(c, constrCtx, flags)
411+
result[0].sons.add defaults
403412
var hasError = false # needed to split error detect/report for better msgs
404413

405414
# It's possible that the object was not fully initialized while

compiler/semstmts.nim

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,14 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
594594
var typFlags: TTypeAllowedFlags
595595

596596
var def: PNode = c.graph.emptyNode
597+
if a[^1].kind == nkEmpty and symkind == skVar and a[^2].typ != nil:
598+
let aTyp = a[^2].typ
599+
if aTyp.skipTypes({tyGenericInst, tyAlias, tySink}).kind == tyObject:
600+
var asgnExpr = newTree(nkObjConstr, newNodeIT(nkType, a[^2].info, aTyp))
601+
asgnExpr.typ = aTyp
602+
asgnExpr.sons.add defaultFieldsForTheUninitialized(aTyp.skipTypes({tyGenericInst, tyAlias, tySink}).n)
603+
a[^1] = asgnExpr
604+
597605
if a[^1].kind != nkEmpty:
598606
def = semExprWithType(c, a[^1], {})
599607

compiler/semtypes.nim

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -777,12 +777,17 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
777777
var a: PNode
778778
if father.kind != nkRecList and n.len >= 4: a = newNodeI(nkRecList, n.info)
779779
else: a = newNodeI(nkEmpty, n.info)
780-
if n[^1].kind != nkEmpty:
781-
localError(c.config, n[^1].info, errInitHereNotAllowed)
782780
var typ: PType
781+
782+
let hasDefaultField = n[^1].kind != nkEmpty
783783
if n[^2].kind == nkEmpty:
784-
localError(c.config, n.info, errTypeExpected)
785-
typ = errorType(c)
784+
if hasDefaultField:
785+
n[^1] = semConstExpr(c, n[^1])
786+
typ = n[^1].typ
787+
propagateToOwner(rectype, typ)
788+
else:
789+
localError(c.config, n.info, errTypeExpected)
790+
typ = errorType(c)
786791
else:
787792
typ = semTypeNode(c, n[^2], nil)
788793
propagateToOwner(rectype, typ)
@@ -806,8 +811,11 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
806811
inc(pos)
807812
if containsOrIncl(check, f.name.id):
808813
localError(c.config, info, "attempt to redefine: '" & f.name.s & "'")
809-
if a.kind == nkEmpty: father.add newSymNode(f)
810-
else: a.add newSymNode(f)
814+
let fSym = newSymNode(f)
815+
if hasDefaultField:
816+
fSym.sym.ast = n[^1]
817+
if a.kind == nkEmpty: father.add fSym
818+
else: a.add fSym
811819
styleCheckDef(c.config, f)
812820
onDef(f.info, f)
813821
if a.kind != nkEmpty: father.add a

compiler/transf.nim

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ type
4646
module: PSym
4747
transCon: PTransCon # top of a TransCon stack
4848
inlining: int # > 0 if we are in inlining context (copy vars)
49-
nestedProcs: int # > 0 if we are in a nested proc
49+
genResult: bool
5050
contSyms, breakSyms: seq[PSym] # to transform 'continue' and 'break'
5151
deferDetected, tooEarly: bool
5252
graph: ModuleGraph
@@ -927,6 +927,32 @@ proc commonOptimizations*(g: ModuleGraph; idgen: IdGenerator; c: PSym, n: PNode)
927927
else:
928928
result = n
929929

930+
proc defaultFieldsForTheUninitialized*(recNode: PNode): seq[PNode] =
931+
case recNode.kind
932+
of nkRecList:
933+
for field in recNode:
934+
result.add defaultFieldsForTheUninitialized(field)
935+
of nkRecCase:
936+
discard
937+
# let discriminator = recNode[0]
938+
# var selectedBranch: int
939+
# let defaultValue = discriminator.sym.ast
940+
# if defaultValue == nil:
941+
# # None of the branches were explicitly selected by the user and no value
942+
# # was given to the discrimator. We can assume that it will be initialized
943+
# # to zero and this will select a particular branch as a result:
944+
# selectedBranch = recNode.pickCaseBranch newIntNode(nkIntLit#[c.graph]#, 0)
945+
# else: # Try to use default value
946+
# selectedBranch = recNode.pickCaseBranch defaultValue
947+
# result.add newTree(nkExprColonExpr, discriminator, defaultValue)
948+
# result.add defaultFieldsForTheUninitialized(recNode[selectedBranch][^1])
949+
of nkSym:
950+
let field = recNode.sym
951+
if field.ast != nil: #Try to use default value
952+
result.add newTree(nkExprColonExpr, recNode, field.ast)
953+
else:
954+
assert false
955+
930956
proc transform(c: PTransf, n: PNode): PNode =
931957
when false:
932958
var oldDeferAnchor: PNode
@@ -935,6 +961,19 @@ proc transform(c: PTransf, n: PNode): PNode =
935961
nkBlockStmt, nkBlockExpr}:
936962
oldDeferAnchor = c.deferAnchor
937963
c.deferAnchor = n
964+
965+
if c.genResult:
966+
c.genResult = false
967+
result = newNodeIT(nkStmtList, n.info, nil)
968+
let toInit = c.getCurrOwner().ast[resultPos]
969+
if toInit.typ != nil and toInit.typ.skipTypes({tyGenericInst, tyAlias, tySink}).kind == tyObject:
970+
var asgnExpr = newTree(nkObjConstr, newNodeIT(nkType, toInit.info, toInit.typ))
971+
asgnExpr.typ = toInit.typ
972+
asgnExpr.sons.add defaultFieldsForTheUninitialized(toInit.typ.skipTypes({tyGenericInst, tyAlias, tySink}).n)
973+
result.add transform(c, newTree(nkAsgn, toInit, asgnExpr))
974+
result.add transform(c, n)
975+
return result
976+
938977
case n.kind
939978
of nkSym:
940979
result = transformSym(c, n)
@@ -1052,6 +1091,13 @@ proc transform(c: PTransf, n: PNode): PNode =
10521091
result = n
10531092
of nkExceptBranch:
10541093
result = transformExceptBranch(c, n)
1094+
of nkObjConstr:
1095+
result = n
1096+
if result.typ.skipTypes(abstractInst).kind == tyObject or
1097+
result.typ.skipTypes(abstractInst).kind == tyRef and result.typ.skipTypes(abstractInst)[0].kind == tyObject:
1098+
result.sons.add result[0].sons
1099+
result[0] = newNodeIT(nkType, result.info, result.typ)
1100+
result = transformSons(c, result)
10551101
of nkCheckedFieldExpr:
10561102
result = transformSons(c, n)
10571103
if result[0].kind != nkDotExpr:
@@ -1079,6 +1125,7 @@ proc processTransf(c: PTransf, n: PNode, owner: PSym): PNode =
10791125
# nodes into an empty node.
10801126
if nfTransf in n.flags: return n
10811127
pushTransCon(c, newTransCon(owner))
1128+
c.genResult = c.getCurrOwner().kind in routineKinds and c.transCon.owner.ast.len > resultPos and c.transCon.owner.ast[resultPos] != nil
10821129
result = transform(c, n)
10831130
popTransCon(c)
10841131
incl(result.flags, nfTransf)

0 commit comments

Comments
 (0)