Destructors: move into nkTupleConstr and move on tuple unpacking (#9776)
This commit is contained in:
parent
f8fa94cb20
commit
962b2e4b39
3 changed files with 96 additions and 9 deletions
|
|
@ -261,6 +261,11 @@ proc isLastRead(n: PNode; c: var Con): bool =
|
||||||
template interestingSym(s: PSym): bool =
|
template interestingSym(s: PSym): bool =
|
||||||
s.owner == c.owner and s.kind in InterestingSyms and hasDestructor(s.typ)
|
s.owner == c.owner and s.kind in InterestingSyms and hasDestructor(s.typ)
|
||||||
|
|
||||||
|
template isUnpackedTuple(s: PSym): bool =
|
||||||
|
## we move out all elements of unpacked tuples,
|
||||||
|
## hence unpacked tuples themselves don't need to be destroyed
|
||||||
|
s.kind == skTemp and s.typ.kind == tyTuple
|
||||||
|
|
||||||
proc patchHead(n: PNode) =
|
proc patchHead(n: PNode) =
|
||||||
if n.kind in nkCallKinds and n[0].kind == nkSym and n.len > 1:
|
if n.kind in nkCallKinds and n[0].kind == nkSym and n.len > 1:
|
||||||
let s = n[0].sym
|
let s = n[0].sym
|
||||||
|
|
@ -446,6 +451,13 @@ proc moveOrCopy(dest, ri: PNode; c: var Con): PNode =
|
||||||
ri2.add pArg(ri[i], c, i < L and parameters[i].kind == tySink)
|
ri2.add pArg(ri[i], c, i < L and parameters[i].kind == tySink)
|
||||||
#recurse(ri, ri2)
|
#recurse(ri, ri2)
|
||||||
result.add ri2
|
result.add ri2
|
||||||
|
of nkBracketExpr:
|
||||||
|
if ri[0].kind == nkSym and isUnpackedTuple(ri[0].sym):
|
||||||
|
# unpacking of tuple: move out the elements
|
||||||
|
result = genSink(c, dest.typ, dest, ri)
|
||||||
|
else:
|
||||||
|
result = genCopy(c, dest.typ, dest, ri)
|
||||||
|
result.add p(ri, c)
|
||||||
of nkObjConstr:
|
of nkObjConstr:
|
||||||
result = genSink(c, dest.typ, dest, ri)
|
result = genSink(c, dest.typ, dest, ri)
|
||||||
let ri2 = copyTree(ri)
|
let ri2 = copyTree(ri)
|
||||||
|
|
@ -454,6 +466,17 @@ proc moveOrCopy(dest, ri: PNode; c: var Con): PNode =
|
||||||
# so these all act like 'sink' parameters:
|
# so these all act like 'sink' parameters:
|
||||||
ri2[i].sons[1] = pArg(ri[i][1], c, isSink = true)
|
ri2[i].sons[1] = pArg(ri[i][1], c, isSink = true)
|
||||||
result.add ri2
|
result.add ri2
|
||||||
|
of nkTupleConstr:
|
||||||
|
result = genSink(c, dest.typ, dest, ri)
|
||||||
|
let ri2 = copyTree(ri)
|
||||||
|
for i in 0..<ri.len:
|
||||||
|
# everything that is passed to an tuple constructor is consumed,
|
||||||
|
# so these all act like 'sink' parameters:
|
||||||
|
if ri[i].kind == nkExprColonExpr:
|
||||||
|
ri2[i].sons[1] = pArg(ri[i][1], c, isSink = true)
|
||||||
|
else:
|
||||||
|
ri2[i] = pArg(ri[i], c, isSink = true)
|
||||||
|
result.add ri2
|
||||||
of nkSym:
|
of nkSym:
|
||||||
if ri.sym.kind != skParam and isLastRead(ri, c):
|
if ri.sym.kind != skParam and isLastRead(ri, c):
|
||||||
# Rule 3: `=sink`(x, z); wasMoved(z)
|
# Rule 3: `=sink`(x, z); wasMoved(z)
|
||||||
|
|
@ -483,7 +506,7 @@ proc p(n: PNode; c: var Con): PNode =
|
||||||
if it.kind == nkVarTuple and hasDestructor(ri.typ):
|
if it.kind == nkVarTuple and hasDestructor(ri.typ):
|
||||||
let x = lowerTupleUnpacking(c.graph, it, c.owner)
|
let x = lowerTupleUnpacking(c.graph, it, c.owner)
|
||||||
result.add p(x, c)
|
result.add p(x, c)
|
||||||
elif it.kind == nkIdentDefs and hasDestructor(it[0].typ):
|
elif it.kind == nkIdentDefs and hasDestructor(it[0].typ) and not isUnpackedTuple(it[0].sym):
|
||||||
for j in 0..L-2:
|
for j in 0..L-2:
|
||||||
let v = it[j]
|
let v = it[j]
|
||||||
doAssert v.kind == nkSym
|
doAssert v.kind == nkSym
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,26 @@
|
||||||
discard """
|
discard """
|
||||||
exitcode: 0
|
exitcode: 0
|
||||||
output: '''assingment
|
output: ""
|
||||||
assingment
|
|
||||||
assingment
|
|
||||||
assingment
|
|
||||||
'''
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
type
|
type
|
||||||
Foo* = object
|
Foo* = object
|
||||||
boo: int
|
boo: int
|
||||||
|
|
||||||
|
var sink_counter = 0
|
||||||
|
var assign_counter = 0
|
||||||
|
|
||||||
|
proc `=sink`(dest: var Foo, src: Foo) =
|
||||||
|
sink_counter.inc
|
||||||
|
|
||||||
proc `=`(dest: var Foo, src: Foo) =
|
proc `=`(dest: var Foo, src: Foo) =
|
||||||
debugEcho "assingment"
|
assign_counter.inc
|
||||||
|
|
||||||
proc test(): auto =
|
proc test(): auto =
|
||||||
var a,b : Foo
|
var a,b : Foo
|
||||||
return (a, b)
|
return (a, b, Foo(boo: 5))
|
||||||
|
|
||||||
var (a, b) = test()
|
var (a, b, _) = test()
|
||||||
|
|
||||||
|
doAssert: assign_counter == 0
|
||||||
|
doAssert: sink_counter == 9
|
||||||
|
|
@ -60,3 +60,62 @@ for x in getPony():
|
||||||
# XXX this needs to be enabled once top level statements
|
# XXX this needs to be enabled once top level statements
|
||||||
# produce destructor calls again.
|
# produce destructor calls again.
|
||||||
#echo "Pony is dying!"
|
#echo "Pony is dying!"
|
||||||
|
|
||||||
|
|
||||||
|
#------------------------------------------------------------
|
||||||
|
#-- Move into tuple constructor and move on tuple unpacking
|
||||||
|
#------------------------------------------------------------
|
||||||
|
|
||||||
|
type
|
||||||
|
MySeqNonCopyable* = object
|
||||||
|
len: int
|
||||||
|
data: ptr UncheckedArray[float]
|
||||||
|
|
||||||
|
proc `=destroy`*(m: var MySeqNonCopyable) {.inline.} =
|
||||||
|
if m.data != nil:
|
||||||
|
deallocShared(m.data)
|
||||||
|
m.data = nil
|
||||||
|
|
||||||
|
proc `=`*(m: var MySeqNonCopyable, m2: MySeqNonCopyable) {.error.}
|
||||||
|
|
||||||
|
proc `=sink`*(m: var MySeqNonCopyable, m2: MySeqNonCopyable) {.inline.} =
|
||||||
|
if m.data != m2.data:
|
||||||
|
if m.data != nil:
|
||||||
|
`=destroy`(m)
|
||||||
|
m.len = m2.len
|
||||||
|
m.data = m2.data
|
||||||
|
|
||||||
|
proc len*(m: MySeqNonCopyable): int {.inline.} = m.len
|
||||||
|
|
||||||
|
proc `[]`*(m: MySeqNonCopyable; i: int): float {.inline.} =
|
||||||
|
m.data[i.int]
|
||||||
|
|
||||||
|
proc `[]=`*(m: var MySeqNonCopyable; i, val: float) {.inline.} =
|
||||||
|
m.data[i.int] = val
|
||||||
|
|
||||||
|
proc setTo(s: var MySeqNonCopyable, val: float) =
|
||||||
|
for i in 0..<s.len.int:
|
||||||
|
s.data[i] = val
|
||||||
|
|
||||||
|
proc newMySeq*(size: int, initial_value = 0.0): MySeqNonCopyable =#
|
||||||
|
result.len = size
|
||||||
|
if size > 0:
|
||||||
|
result.data = cast[ptr UncheckedArray[float]](createShared(float, size))
|
||||||
|
|
||||||
|
result.setTo(initial_value)
|
||||||
|
|
||||||
|
proc myfunc(x, y: int): (MySeqNonCopyable, MySeqNonCopyable) =
|
||||||
|
result = (newMySeq(x, 1.0), newMySeq(y, 5.0))
|
||||||
|
|
||||||
|
proc myfunc2(x, y: int): tuple[a: MySeqNonCopyable, b:int, c:MySeqNonCopyable] =
|
||||||
|
(a: newMySeq(x, 1.0), b:0, c:newMySeq(y, 5.0))
|
||||||
|
|
||||||
|
let (seq1, seq2) = myfunc(2, 3)
|
||||||
|
doAssert seq1.len == 2
|
||||||
|
doAssert seq1[0] == 1.0
|
||||||
|
doAssert seq2.len == 3
|
||||||
|
doAssert seq2[0] == 5.0
|
||||||
|
|
||||||
|
var (seq3, i, _) = myfunc2(2, 3)
|
||||||
|
doAssert seq3.len == 2
|
||||||
|
doAssert seq3[0] == 1.0
|
||||||
Loading…
Add table
Add a link
Reference in a new issue