destructors: lift type bound operations for case and distinct objects (#10238)
This commit is contained in:
parent
87232a38e4
commit
44b4e289d6
2 changed files with 92 additions and 27 deletions
|
|
@ -49,6 +49,14 @@ proc liftBodyObj(c: var TLiftCtx; n, body, x, y: PNode) =
|
||||||
liftBodyAux(c, f.typ, body, x.dotField(f), y.dotField(f))
|
liftBodyAux(c, f.typ, body, x.dotField(f), y.dotField(f))
|
||||||
of nkNilLit: discard
|
of nkNilLit: discard
|
||||||
of nkRecCase:
|
of nkRecCase:
|
||||||
|
if c.kind in {attachedSink, attachedAsgn, attachedDeepCopy}:
|
||||||
|
## the value needs to be destroyed before we assign the selector
|
||||||
|
## or the value is lost
|
||||||
|
let prevKind = c.kind
|
||||||
|
c.kind = attachedDestructor
|
||||||
|
liftBodyObj(c, n, body, x, y)
|
||||||
|
c.kind = prevKind
|
||||||
|
|
||||||
# copy the selector:
|
# copy the selector:
|
||||||
liftBodyObj(c, n[0], body, x, y)
|
liftBodyObj(c, n[0], body, x, y)
|
||||||
# we need to generate a case statement:
|
# we need to generate a case statement:
|
||||||
|
|
@ -66,7 +74,6 @@ proc liftBodyObj(c: var TLiftCtx; n, body, x, y: PNode) =
|
||||||
liftBodyObj(c, n[i].lastSon, branch.sons[L-1], x, y)
|
liftBodyObj(c, n[i].lastSon, branch.sons[L-1], x, y)
|
||||||
caseStmt.add(branch)
|
caseStmt.add(branch)
|
||||||
body.add(caseStmt)
|
body.add(caseStmt)
|
||||||
localError(c.c.config, c.info, "cannot lift assignment operator to 'case' object")
|
|
||||||
of nkRecList:
|
of nkRecList:
|
||||||
for t in items(n): liftBodyObj(c, t, body, x, y)
|
for t in items(n): liftBodyObj(c, t, body, x, y)
|
||||||
else:
|
else:
|
||||||
|
|
@ -235,11 +242,12 @@ proc liftBodyAux(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
discard considerOverloadedOp(c, t, body, x, y)
|
discard considerOverloadedOp(c, t, body, x, y)
|
||||||
else:
|
else:
|
||||||
defaultOp(c, t, body, x, y)
|
defaultOp(c, t, body, x, y)
|
||||||
of tyObject, tyDistinct:
|
of tyObject:
|
||||||
if not considerOverloadedOp(c, t, body, x, y):
|
if not considerOverloadedOp(c, t, body, x, y):
|
||||||
if t.sons[0] != nil:
|
liftBodyObj(c, t.n, body, x, y)
|
||||||
liftBodyAux(c, t.sons[0].skipTypes(skipPtrs), body, x, y)
|
of tyDistinct:
|
||||||
if t.kind == tyObject: liftBodyObj(c, t.n, body, x, y)
|
if not considerOverloadedOp(c, t, body, x, y):
|
||||||
|
liftBodyAux(c, t.sons[0].skipTypes(skipPtrs), body, x, y)
|
||||||
of tyTuple:
|
of tyTuple:
|
||||||
liftBodyTup(c, t, body, x, y)
|
liftBodyTup(c, t, body, x, y)
|
||||||
of tyProc:
|
of tyProc:
|
||||||
|
|
@ -279,8 +287,36 @@ proc addParam(procType: PType; param: PSym) =
|
||||||
addSon(procType.n, newSymNode(param))
|
addSon(procType.n, newSymNode(param))
|
||||||
rawAddSon(procType, param.typ)
|
rawAddSon(procType, param.typ)
|
||||||
|
|
||||||
|
proc liftBodyDistinctType(c: PContext; typ: PType; kind: TTypeAttachedOp; info: TLineInfo): PSym =
|
||||||
|
assert typ.kind == tyDistinct
|
||||||
|
let baseType = typ[0]
|
||||||
|
case kind
|
||||||
|
of attachedAsgn:
|
||||||
|
if baseType.assignment == nil:
|
||||||
|
discard liftBody(c, baseType, kind, info)
|
||||||
|
typ.assignment = baseType.assignment
|
||||||
|
result = typ.assignment
|
||||||
|
of attachedSink:
|
||||||
|
if baseType.sink == nil:
|
||||||
|
discard liftBody(c, baseType, kind, info)
|
||||||
|
typ.sink = baseType.sink
|
||||||
|
result = typ.sink
|
||||||
|
of attachedDeepCopy:
|
||||||
|
if baseType.deepCopy == nil:
|
||||||
|
discard liftBody(c, baseType, kind, info)
|
||||||
|
typ.deepCopy = baseType.deepCopy
|
||||||
|
result = typ.deepCopy
|
||||||
|
of attachedDestructor:
|
||||||
|
if baseType.destructor == nil:
|
||||||
|
discard liftBody(c, baseType, kind, info)
|
||||||
|
typ.destructor = baseType.destructor
|
||||||
|
result = typ.destructor
|
||||||
|
|
||||||
proc liftBody(c: PContext; typ: PType; kind: TTypeAttachedOp;
|
proc liftBody(c: PContext; typ: PType; kind: TTypeAttachedOp;
|
||||||
info: TLineInfo): PSym =
|
info: TLineInfo): PSym =
|
||||||
|
if typ.kind == tyDistinct:
|
||||||
|
return liftBodyDistinctType(c, typ, kind, info)
|
||||||
|
|
||||||
var a: TLiftCtx
|
var a: TLiftCtx
|
||||||
a.info = info
|
a.info = info
|
||||||
a.c = c
|
a.c = c
|
||||||
|
|
|
||||||
|
|
@ -7,21 +7,28 @@ mygeneric1 constructed
|
||||||
mygeneric1 destroyed
|
mygeneric1 destroyed
|
||||||
----
|
----
|
||||||
mygeneric2 constructed
|
mygeneric2 constructed
|
||||||
mygeneric2 destroyed
|
|
||||||
myobj destroyed
|
myobj destroyed
|
||||||
|
mygeneric2 destroyed
|
||||||
----
|
----
|
||||||
mygeneric3 constructed
|
mygeneric3 constructed
|
||||||
mygeneric1 destroyed
|
mygeneric1 destroyed
|
||||||
----
|
----
|
||||||
mygeneric1 destroyed
|
mydistinctObj constructed
|
||||||
|
myobj destroyed
|
||||||
|
mygeneric2 destroyed
|
||||||
|
------------------
|
||||||
|
----
|
||||||
----
|
----
|
||||||
myobj destroyed
|
myobj destroyed
|
||||||
----
|
mygeneric1 destroyed
|
||||||
----
|
myobj destroyed
|
||||||
|
myobj destroyed
|
||||||
|
myobj destroyed
|
||||||
|
---
|
||||||
|
myobj destroyed
|
||||||
|
myobj destroyed
|
||||||
myobj destroyed
|
myobj destroyed
|
||||||
'''
|
'''
|
||||||
cmd: '''nim c --newruntime $file'''
|
|
||||||
disabled: "true"
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
@ -29,6 +36,11 @@ type
|
||||||
x, y: int
|
x, y: int
|
||||||
p: pointer
|
p: pointer
|
||||||
|
|
||||||
|
proc `=destroy`(o: var TMyObj) =
|
||||||
|
if o.p != nil: dealloc o.p
|
||||||
|
echo "myobj destroyed"
|
||||||
|
|
||||||
|
type
|
||||||
TMyGeneric1[T] = object
|
TMyGeneric1[T] = object
|
||||||
x: T
|
x: T
|
||||||
|
|
||||||
|
|
@ -36,37 +48,40 @@ type
|
||||||
x: A
|
x: A
|
||||||
y: B
|
y: B
|
||||||
|
|
||||||
|
proc `=destroy`(o: var TMyGeneric1[int]) =
|
||||||
|
echo "mygeneric1 destroyed"
|
||||||
|
|
||||||
|
proc `=destroy`[A, B](o: var TMyGeneric2[A, B]) =
|
||||||
|
echo "mygeneric2 destroyed"
|
||||||
|
|
||||||
|
type
|
||||||
TMyGeneric3[A, B, C] = object
|
TMyGeneric3[A, B, C] = object
|
||||||
x: A
|
x: A
|
||||||
y: B
|
y: B
|
||||||
z: C
|
z: C
|
||||||
|
|
||||||
TObjKind = enum A, B, C, D
|
TDistinctObjX = distinct TMyGeneric3[TMyObj, TMyGeneric2[int, int], int]
|
||||||
|
TDistinctObj = TDistinctObjX
|
||||||
|
|
||||||
|
TObjKind = enum Z, A, B, C, D
|
||||||
|
|
||||||
TCaseObj = object
|
TCaseObj = object
|
||||||
|
z: TMyGeneric3[TMyObj, float, int]
|
||||||
case kind: TObjKind
|
case kind: TObjKind
|
||||||
|
of Z: discard
|
||||||
of A:
|
of A:
|
||||||
x: TMyGeneric1[int]
|
x: TMyGeneric1[int]
|
||||||
of B, C:
|
of B, C:
|
||||||
y: TMyObj
|
y: TMyObj
|
||||||
else:
|
else:
|
||||||
case innerKind: TObjKind
|
case innerKind: TObjKind
|
||||||
|
of Z: discard
|
||||||
of A, B, C:
|
of A, B, C:
|
||||||
p: TMyGeneric3[int, float, string]
|
p: TMyGeneric3[int, float, string]
|
||||||
of D:
|
of D:
|
||||||
q: TMyGeneric3[TMyObj, int, int]
|
q: TMyGeneric3[TMyObj, int, int]
|
||||||
r: string
|
r: string
|
||||||
|
|
||||||
proc `=destroy`(o: var TMyObj) =
|
|
||||||
if o.p != nil: dealloc o.p
|
|
||||||
echo "myobj destroyed"
|
|
||||||
|
|
||||||
proc `=destroy`(o: var TMyGeneric1[int]) =
|
|
||||||
echo "mygeneric1 destroyed"
|
|
||||||
|
|
||||||
proc `=destroy`[A, B](o: var TMyGeneric2[A, B]) =
|
|
||||||
echo "mygeneric2 destroyed"
|
|
||||||
|
|
||||||
proc open: TMyObj =
|
proc open: TMyObj =
|
||||||
# allow for superfluous ()
|
# allow for superfluous ()
|
||||||
result = (TMyObj(x: 1, y: 2, p: alloc(3)))
|
result = (TMyObj(x: 1, y: 2, p: alloc(3)))
|
||||||
|
|
@ -95,6 +110,12 @@ proc mygeneric3 =
|
||||||
|
|
||||||
echo "mygeneric3 constructed"
|
echo "mygeneric3 constructed"
|
||||||
|
|
||||||
|
proc mydistinctObj =
|
||||||
|
var x = TMyGeneric3[TMyObj, TMyGeneric2[int, int], int](
|
||||||
|
x: open(), y: TMyGeneric2[int, int](x: 5, y: 15), z: 20)
|
||||||
|
|
||||||
|
echo "mydistinctObj constructed"
|
||||||
|
|
||||||
echo "----"
|
echo "----"
|
||||||
myobj()
|
myobj()
|
||||||
|
|
||||||
|
|
@ -107,9 +128,11 @@ mygeneric2[int](10)
|
||||||
echo "----"
|
echo "----"
|
||||||
mygeneric3()
|
mygeneric3()
|
||||||
|
|
||||||
|
echo "----"
|
||||||
|
mydistinctObj()
|
||||||
|
|
||||||
proc caseobj =
|
proc caseobj =
|
||||||
block:
|
block:
|
||||||
echo "----"
|
|
||||||
var o1 = TCaseObj(kind: A, x: TMyGeneric1[int](x: 10))
|
var o1 = TCaseObj(kind: A, x: TMyGeneric1[int](x: 10))
|
||||||
|
|
||||||
block:
|
block:
|
||||||
|
|
@ -121,10 +144,16 @@ proc caseobj =
|
||||||
var o3 = TCaseObj(kind: D, innerKind: B, r: "test",
|
var o3 = TCaseObj(kind: D, innerKind: B, r: "test",
|
||||||
p: TMyGeneric3[int, float, string](x: 10, y: 1.0, z: "test"))
|
p: TMyGeneric3[int, float, string](x: 10, y: 1.0, z: "test"))
|
||||||
|
|
||||||
block:
|
|
||||||
echo "----"
|
|
||||||
var o4 = TCaseObj(kind: D, innerKind: D, r: "test",
|
|
||||||
q: TMyGeneric3[TMyObj, int, int](x: open(), y: 1, z: 0))
|
|
||||||
|
|
||||||
|
echo "------------------"
|
||||||
caseobj()
|
caseobj()
|
||||||
|
|
||||||
|
proc caseobj_test_sink: TCaseObj =
|
||||||
|
# check that lifted sink can destroy case val correctly
|
||||||
|
result = TCaseObj(kind: D, innerKind: D, r: "test",
|
||||||
|
q: TMyGeneric3[TMyObj, int, int](x: open(), y: 1, z: 0))
|
||||||
|
result = TCaseObj(kind: B, y: open())
|
||||||
|
|
||||||
|
|
||||||
|
echo "---"
|
||||||
|
discard caseobj_test_sink()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue