add default field support for object in ARC/ORC (#20480)
* fresh start * add cpp target * add result support * add nimPreviewRangeDefault * reduce * use orc * refactor common parts * add tuple support * add testcase for tuple * cleanup; fixes nimsuggest tests * there is something wrong with cpp * remove * add support for seqs * fixes style * addd initial distinct support * remove links * typo * fixes tuple defaults * add rangedefault * add cpp support * fixes one more bugs * add more hasDefaults * fixes ordinal types * add testcase for #16744 * add testcase for #3608 * fixes docgen * small fix * recursive * fixes * cleanup and remove tuple support * fixes nimsuggest * fixes generics procs * refactor * increases timeout * refactor hasDefault * zero default; disable i386 * add tuples back * fixes bugs * fixes tuple * add more tests * fix one more bug regarding tuples * more tests and cleanup * remove messy distinct types which must be initialized by original types * add tests * fixes zero default * fixes grammar * fixes tests * fixes tests * fixes tests * fixes comments * fixes and add testcase * undo default values for results Co-authored-by: flywind <43030857+xflywind@users.noreply.github.com>
This commit is contained in:
parent
6cf0727192
commit
f89ba2c951
23 changed files with 727 additions and 80 deletions
117
compiler/sem.nim
117
compiler/sem.nim
|
|
@ -538,6 +538,123 @@ 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..<caseExpr.len - endsWithElse.int:
|
||||
if caseExpr[i].caseBranchMatchesExpr(matched):
|
||||
return i
|
||||
if endsWithElse:
|
||||
return caseExpr.len - 1
|
||||
|
||||
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}
|
||||
|
||||
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)
|
||||
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,
|
||||
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
|
||||
of nkRecList:
|
||||
for field in recNode:
|
||||
result.add defaultFieldsForTheUninitialized(c, field)
|
||||
of nkRecCase:
|
||||
let discriminator = recNode[0]
|
||||
var selectedBranch: int
|
||||
let defaultValue = discriminator.sym.ast
|
||||
if defaultValue == nil:
|
||||
# None of the branches were explicitly selected by the user and no value
|
||||
# was given to the discrimator. We can assume that it will be initialized
|
||||
# to zero and this will select a particular branch as a result:
|
||||
selectedBranch = recNode.pickCaseBranchIndex newIntNode(nkIntLit#[c.graph]#, 0)
|
||||
else: # Try to use default value
|
||||
selectedBranch = recNode.pickCaseBranchIndex defaultValue
|
||||
result.add newTree(nkExprColonExpr, discriminator, defaultValue)
|
||||
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)
|
||||
elif recType.kind in {tyObject, tyArray, tyTuple}:
|
||||
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): PNode =
|
||||
let aTypSkip = aTyp.skipTypes(defaultFieldsSkipTypes)
|
||||
if aTypSkip.kind == tyObject:
|
||||
let child = defaultFieldsForTheUninitialized(c, aTyp.skipTypes(defaultFieldsSkipTypes).n)
|
||||
if child.len > 0:
|
||||
var asgnExpr = newTree(nkObjConstr, newNodeIT(nkType, a.info, aTyp))
|
||||
asgnExpr.typ = aTyp
|
||||
asgnExpr.sons.add child
|
||||
result = semExpr(c, asgnExpr)
|
||||
elif aTypSkip.kind == tyArray:
|
||||
let child = defaultNodeField(c, a, aTypSkip[1])
|
||||
|
||||
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),
|
||||
semExprWithType(c, child),
|
||||
node
|
||||
))
|
||||
result.typ = aTyp
|
||||
elif aTypSkip.kind == tyTuple:
|
||||
var hasDefault = false
|
||||
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.sons.add children
|
||||
result = semExpr(c, result)
|
||||
|
||||
proc defaultNodeField(c: PContext, a: PNode): PNode =
|
||||
result = defaultNodeField(c, a, a.typ)
|
||||
|
||||
include semtempl, semgnrc, semstmts, semexprs
|
||||
|
||||
proc addCodeForGenerics(c: PContext, n: PNode) =
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue