Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add default field support for object in ARC/ORC #20220

Closed
wants to merge 52 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
ad67b71
fresh start
ringabout May 18, 2022
4c00f7a
Merge remote-tracking branch 'upstream/devel' into pr_object_default
ringabout May 18, 2022
dc9c8da
add cpp target
ringabout May 18, 2022
dfa5cc2
Merge branch 'devel' into pr_object_default
ringabout Jun 22, 2022
72f3d8f
Merge branch 'devel' into pr_object_default
ringabout Jul 4, 2022
723e474
Merge branch 'devel' into pr_object_default
ringabout Aug 10, 2022
78279d6
Merge branch 'devel' into pr_object_default
ringabout Aug 13, 2022
222d9f8
add result support
ringabout Aug 14, 2022
6f8d6e9
add nimPreviewRangeDefault
ringabout Aug 14, 2022
2a041c5
reduce
ringabout Aug 14, 2022
1fc40f5
use orc
ringabout Aug 14, 2022
0aaf39b
refactor common parts
ringabout Aug 14, 2022
666f144
add tuple support
ringabout Aug 14, 2022
d76e5fc
add testcase for tuple
ringabout Aug 14, 2022
a94526f
cleanup; fixes nimsuggest tests
ringabout Aug 14, 2022
0808f64
there is something wrong with cpp
ringabout Aug 14, 2022
8a91de7
remove
ringabout Aug 15, 2022
e119505
add support for seqs
ringabout Aug 15, 2022
8013b1c
fixes style
ringabout Aug 15, 2022
05966a6
addd initial distinct support
ringabout Aug 15, 2022
f01519a
Merge branch 'devel' into test-branch
ringabout Aug 15, 2022
d9d1504
remove links
ringabout Aug 15, 2022
bca98b3
Merge branch 'test-branch' of https://github.com/xflywind/Nim into te…
ringabout Aug 15, 2022
53c8baf
typo
ringabout Aug 15, 2022
036952c
fixes tuple defaults
ringabout Aug 15, 2022
5052468
add rangedefault
ringabout Aug 16, 2022
ec8fd15
add cpp support
ringabout Aug 16, 2022
6a5014c
fixes one more bugs
ringabout Aug 16, 2022
fca41d4
add more hasDefaults
ringabout Aug 16, 2022
0754474
fixes ordinal types
ringabout Aug 16, 2022
d0c0da9
add testcase for #16744
ringabout Aug 16, 2022
7de32e8
add testcase for #3608
ringabout Aug 16, 2022
09b6cf9
fixes docgen
ringabout Aug 17, 2022
37877d1
small fix
ringabout Aug 17, 2022
3e83905
recursive
ringabout Aug 17, 2022
9559a1a
fixes
ringabout Aug 17, 2022
e829315
cleanup and remove tuple support
ringabout Aug 17, 2022
3c0001e
fixes nimsuggest
ringabout Aug 17, 2022
bcddfad
fixes generics procs
ringabout Aug 17, 2022
e4c1dba
Merge branch 'devel' into test-branch
ringabout Aug 17, 2022
0cfcff6
refactor
ringabout Aug 17, 2022
d136a1b
increases timeout
ringabout Aug 17, 2022
22962b2
refactor hasDefault
ringabout Aug 17, 2022
4a8b3a8
zero default; disable i386
ringabout Aug 17, 2022
e98b3ca
add tuples back
ringabout Aug 17, 2022
6041db3
fixes bugs
ringabout Aug 17, 2022
c0179df
fixes tuple
ringabout Aug 18, 2022
11dd2e4
add more tests
ringabout Aug 18, 2022
506c07a
fix one more bug regarding tuples
ringabout Aug 18, 2022
e888dd4
more tests and cleanup
ringabout Aug 18, 2022
ff38a2a
remove messy distinct types which must be initialized by original types
ringabout Aug 19, 2022
9484db8
add tests
ringabout Aug 19, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion compiler/ast.nim
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,7 @@ type
nfLastRead # this node is a last read
nfFirstWrite# this node is a first write
nfHasComment # node has a comment
nfUseDefaultField # node has a default value (object constructor)
ringabout marked this conversation as resolved.
Show resolved Hide resolved

TNodeFlags* = set[TNodeFlag]
TTypeFlag* = enum # keep below 32 for efficiency reasons (now: 45)
Expand Down Expand Up @@ -705,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:
Expand Down
2 changes: 1 addition & 1 deletion compiler/ccgexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions compiler/jsgen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down
1 change: 1 addition & 0 deletions compiler/nim.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ define:booting
define:nimcore
define:nimPreviewFloatRoundtrip
define:nimPreviewSlimSystem
define:nimPreviewRangeDefault

#import:"$projectpath/testability"

Expand Down
6 changes: 1 addition & 5 deletions compiler/parser.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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})
ringabout marked this conversation as resolved.
Show resolved Hide resolved
result.add(a)
if p.tok.tokType == tkColon: getTok(p)
flexComment(p, result)
Expand Down
118 changes: 118 additions & 0 deletions compiler/sem.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -535,6 +536,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) =
Expand Down
8 changes: 6 additions & 2 deletions compiler/semexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -900,8 +900,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)
Expand Down Expand Up @@ -2397,6 +2395,12 @@ 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:
ringabout marked this conversation as resolved.
Show resolved Hide resolved
result = semDirectOp(c, n, flags)
let typ = result[^1].typ.skipTypes({tyTypeDesc})
let defaultExpr = defaultNodeField(c, result[^1], typ)
if defaultExpr != nil:
result = defaultExpr
else:
result = semDirectOp(c, n, flags)

Expand Down
2 changes: 2 additions & 0 deletions compiler/seminst.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
25 changes: 23 additions & 2 deletions compiler/semmagic.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -454,6 +456,23 @@ 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 t = typ.skipTypes({tyGenericInst, tyAlias, tySink})[0]
while true:
asgnExpr.sons.add defaultFieldsForTheUninitialized(c, t.n)
let base = t[0]
if base == nil:
break
t = skipTypes(base, skipPtrs)

if asgnExpr.sons.len > 1:
result = newTree(nkAsgn, result[1], asgnExpr)

proc magicsAfterOverloadResolution(c: PContext, n: PNode,
flags: TExprFlags): PNode =
## This is the preferred code point to implement magics.
Expand Down Expand Up @@ -512,6 +531,8 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
result = n
else:
result = plugin(c, n)
of mNew:
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}:
Expand All @@ -536,7 +557,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)
Expand All @@ -562,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
Expand Down
Loading