cbuilder: implement designated initializers, finish default value braces (#24312)

follows up #24259

This is the remaining missing use of `StructInitializer` in
`getDefaultValue` after #24259 and #24302. The only remaining direct C
code in getDefaultValue is [this
line](922f7dfd71/compiler/ccgexprs.nim (L3525))
which creates a global array variable, which isn't implemented yet. Next
steps would be all remaining variable and `typedef` declarations, then
hopefully we can move on to general statements and expressions.
This commit is contained in:
metagn
2024-10-16 21:48:53 +03:00
committed by GitHub
parent a3aea224c9
commit 4a056b1849
2 changed files with 28 additions and 17 deletions

View File

@@ -77,9 +77,7 @@ type
needsComma: bool
proc initStructInitializer(builder: var Builder, kind: StructInitializerKind): StructInitializer =
## starts building a struct initializer, `orderCompliant = true` means
## built fields must be ordered correctly
assert kind != siNamedStruct, "named struct constructors unimplemented"
## starts building a struct initializer, i.e. braced initializer list
result = StructInitializer(kind: kind, needsComma: false)
if kind != siWrapper:
builder.add("{")
@@ -100,7 +98,11 @@ template addField(builder: var Builder, constr: var StructInitializer, name: str
assert name.len != 0, "name has to be given for struct initializer field"
valueBody
of siNamedStruct:
assert false, "named struct constructors unimplemented"
assert name.len != 0, "name has to be given for struct initializer field"
builder.add(".")
builder.add(name)
builder.add(" = ")
valueBody
proc finishStructInitializer(builder: var Builder, constr: StructInitializer) =
## finishes building a struct initializer

View File

@@ -3289,26 +3289,35 @@ proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode,
break
let selectedBranch = caseObjDefaultBranch(obj, branch)
# XXX siNamedStruct needs to be implemented to replace `res` here
var res = "{"
var branchInit: StructInitializer
let b = lastSon(obj[selectedBranch])
# designated initilization is the only way to init non first element of unions
# branches are allowed to have no members (b.len == 0), in this case they don't need initializer
var fieldName: string = ""
if b.kind == nkRecList and not isEmptyCaseObjectBranch(b):
res.add "._" & mangleRecFieldName(p.module, obj[0].sym) & "_" & $selectedBranch & " = "
res.addStructInitializer(branchInit, kind = siOrderedStruct):
getNullValueAux(p, t, b, constOrNil, res, branchInit, isConst, info)
fieldName = "_" & mangleRecFieldName(p.module, obj[0].sym) & "_" & $selectedBranch
result.addField(init, name = "<anonymous union>"):
# XXX figure out name for the union, see use of `addAnonUnion`
var branchInit: StructInitializer
result.addStructInitializer(branchInit, kind = siNamedStruct):
result.addField(branchInit, name = fieldName):
var branchObjInit: StructInitializer
result.addStructInitializer(branchObjInit, kind = siOrderedStruct):
getNullValueAux(p, t, b, constOrNil, result, branchObjInit, isConst, info)
elif b.kind == nkSym:
res.add "." & mangleRecFieldName(p.module, b.sym) & " = "
res.addStructInitializer(branchInit, kind = siWrapper):
getNullValueAux(p, t, b, constOrNil, res, branchInit, isConst, info)
fieldName = mangleRecFieldName(p.module, b.sym)
result.addField(init, name = "<anonymous union>"):
# XXX figure out name for the union, see use of `addAnonUnion`
var branchInit: StructInitializer
result.addStructInitializer(branchInit, kind = siNamedStruct):
result.addField(branchInit, name = fieldName):
# we need to generate the default value of the single sym,
# to do this create a dummy wrapper initializer and recurse
var branchFieldInit: StructInitializer
result.addStructInitializer(branchFieldInit, kind = siWrapper):
getNullValueAux(p, t, b, constOrNil, result, branchFieldInit, isConst, info)
else:
# no fields, don't initialize
return
result.addField(init, name = "<anonymous union>"):
# XXX figure out name for the union, see use of `addAnonUnion`
result.add res
result.add "}"
of nkSym:
let field = obj.sym