29
29
initNone # None of the fields have been initialized
30
30
initConflict # Fields from different branches have been initialized
31
31
32
+
33
+ proc semConstructFields (c: PContext , n: PNode , constrCtx: var ObjConstrContext ,
34
+ flags: TExprFlags ): tuple [status: InitStatus , defaults: seq [PNode ]]
35
+
32
36
proc mergeInitStatus (existing: var InitStatus , newStatus: InitStatus ) =
33
37
case newStatus
34
38
of initConflict:
@@ -155,18 +159,14 @@ proc collectMissingFields(c: PContext, fieldsRecList: PNode,
155
159
if assignment == nil :
156
160
constrCtx.missingFields.add r.sym
157
161
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 ]] =
164
164
case n.kind
165
165
of nkRecList:
166
166
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
170
170
of nkRecCase:
171
171
template fieldsPresentInBranch (branchIdx: int ): string =
172
172
let branch = n[branchIdx]
@@ -184,17 +184,18 @@ proc semConstructFields(c: PContext, n: PNode,
184
184
185
185
for i in 1 ..< n.len:
186
186
let innerRecords = n[i][^ 1 ]
187
- let status = semConstructFields (c, innerRecords, constrCtx, flags)
187
+ let ( status, defaults) = semConstructFields (c, innerRecords, constrCtx, flags)
188
188
if status notin {initNone, initUnknown}:
189
- mergeInitStatus (result , status)
189
+ result .status.mergeInitStatus status
190
+ result .defaults.add defaults
190
191
if selectedBranch != - 1 :
191
192
let prevFields = fieldsPresentInBranch (selectedBranch)
192
193
let currentFields = fieldsPresentInBranch (i)
193
194
localError (c.config, constrCtx.initExpr.info,
194
195
(" The fields '$1' and '$2' cannot be initialized together, " &
195
196
" because they are from conflicting branches in the case object." ) %
196
197
[prevFields, currentFields])
197
- result = initConflict
198
+ result .status = initConflict
198
199
else :
199
200
selectedBranch = i
200
201
@@ -206,7 +207,7 @@ proc semConstructFields(c: PContext, n: PNode,
206
207
(" cannot prove that it's safe to initialize $1 with " &
207
208
" the runtime value for the discriminator '$2' " ) %
208
209
[fields, discriminator.sym.name.s])
209
- mergeInitStatus (result , initNone)
210
+ mergeInitStatus (result .status , initNone)
210
211
211
212
template wrongBranchError (i) =
212
213
if c.inUncheckedAssignSection == 0 :
@@ -291,11 +292,11 @@ proc semConstructFields(c: PContext, n: PNode,
291
292
292
293
# When a branch is selected with a partial match, some of the fields
293
294
# that were not initialized may be mandatory. We must check for this:
294
- if result == initPartial:
295
+ if result .status == initPartial:
295
296
collectMissingFields branchNode
296
297
297
298
else :
298
- result = initNone
299
+ result .status = initNone
299
300
let discriminatorVal = semConstrField (c, flags + {efPreferStatic},
300
301
discriminator.sym,
301
302
constrCtx.initExpr)
@@ -308,7 +309,7 @@ proc semConstructFields(c: PContext, n: PNode,
308
309
let matchedBranch = n.pickCaseBranch defaultValue
309
310
collectMissingFields matchedBranch
310
311
else :
311
- result = initPartial
312
+ result .status = initPartial
312
313
if discriminatorVal.kind == nkIntLit:
313
314
# When the discriminator is a compile-time value, we also know
314
315
# which branch will be selected:
@@ -318,23 +319,28 @@ proc semConstructFields(c: PContext, n: PNode,
318
319
# All bets are off. If any of the branches has a mandatory
319
320
# fields we must produce an error:
320
321
for i in 1 ..< n.len: collectMissingFields n[i]
321
-
322
322
of nkSym:
323
323
let field = n.sym
324
324
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
327
332
else :
328
333
internalAssert c.config, false
329
334
330
335
proc semConstructTypeAux (c: PContext ,
331
336
constrCtx: var ObjConstrContext ,
332
- flags: TExprFlags ): InitStatus =
333
- result = initUnknown
337
+ flags: TExprFlags ): tuple [status: InitStatus , defaults: seq [ PNode ]] =
338
+ result .status = initUnknown
334
339
var t = constrCtx.typ
335
340
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
338
344
if status in {initPartial, initNone, initUnknown}:
339
345
collectMissingFields c, t.n, constrCtx
340
346
let base = t[0 ]
@@ -378,7 +384,9 @@ proc defaultConstructionError(c: PContext, t: PType, info: TLineInfo) =
378
384
proc semObjConstr (c: PContext , n: PNode , flags: TExprFlags ): PNode =
379
385
var t = semTypeNode (c, n[0 ], nil )
380
386
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]
382
390
383
391
if t == nil :
384
392
return localErrorNode (c, result , " object constructor needs an object type" )
@@ -399,7 +407,8 @@ proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
399
407
# field (if this is a case object, initialized fields in two different
400
408
# branches will be reported as an error):
401
409
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
403
412
var hasError = false # needed to split error detect/report for better msgs
404
413
405
414
# It's possible that the object was not fully initialized while
0 commit comments