topttree destructor finally works
This commit is contained in:
parent
b407f083ba
commit
4f2b79a380
5 changed files with 16 additions and 60 deletions
|
|
@ -164,26 +164,22 @@ proc isHarmlessVar*(s: PSym; c: 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)
|
||||||
|
|
||||||
proc patchHead(n: PNode; alreadyPatched: var IntSet) =
|
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
|
||||||
if sfFromGeneric in s.flags or true:
|
if sfFromGeneric in s.flags and s.name.s[0] == '=' and
|
||||||
if s.name.s[0] == '=' and not containsOrIncl(alreadyPatched, s.id):
|
s.name.s in ["=sink", "=", "=destroy"]:
|
||||||
patchHead(s.getBody, alreadyPatched)
|
excl(s.flags, sfFromGeneric)
|
||||||
|
patchHead(s.getBody)
|
||||||
let t = n[1].typ.skipTypes({tyVar, tyGenericInst, tyAlias, tyInferred})
|
let t = n[1].typ.skipTypes({tyVar, tyGenericInst, tyAlias, tyInferred})
|
||||||
template patch(op, field) =
|
template patch(op, field) =
|
||||||
if s.name.s == op and field != nil: #and field != s:
|
if s.name.s == op and field != nil and field != s:
|
||||||
n.sons[0].sym = field
|
n.sons[0].sym = field
|
||||||
patch "=sink", t.sink
|
patch "=sink", t.sink
|
||||||
patch "=", t.assignment
|
patch "=", t.assignment
|
||||||
patch "=destroy", t.destructor
|
patch "=destroy", t.destructor
|
||||||
for x in n:
|
for x in n:
|
||||||
patchHead(x, alreadyPatched)
|
patchHead(x)
|
||||||
|
|
||||||
template patchHead(n: PNode) =
|
|
||||||
when false:
|
|
||||||
var alreadyPatched = initIntSet()
|
|
||||||
patchHead(n, alreadyPatched)
|
|
||||||
|
|
||||||
proc genSink(t: PType; dest: PNode): PNode =
|
proc genSink(t: PType; dest: PNode): PNode =
|
||||||
let t = t.skipTypes({tyGenericInst, tyAlias})
|
let t = t.skipTypes({tyGenericInst, tyAlias})
|
||||||
|
|
|
||||||
|
|
@ -314,24 +314,6 @@ proc overloadedAsgn(c: PContext; dest, src: PNode): PNode =
|
||||||
let a = getAsgnOrLiftBody(c, dest.typ, dest.info)
|
let a = getAsgnOrLiftBody(c, dest.typ, dest.info)
|
||||||
result = newAsgnCall(c, a, dest, src)
|
result = newAsgnCall(c, a, dest, src)
|
||||||
|
|
||||||
proc patchHead(n: PNode; alreadyPatched: var IntSet) =
|
|
||||||
when true:
|
|
||||||
if n.kind in nkCallKinds and n[0].kind == nkSym and n.len > 1:
|
|
||||||
let s = n[0].sym
|
|
||||||
if sfFromGeneric in s.flags:
|
|
||||||
if not containsOrIncl(alreadyPatched, s.id):
|
|
||||||
patchHead(s.getBody, alreadyPatched)
|
|
||||||
let t = n[1].typ.skipTypes({tyVar, tyGenericInst, tyAlias, tyInferred})
|
|
||||||
template patch(op, field) =
|
|
||||||
if s.name.s == op and field != nil and field != s:
|
|
||||||
n.sons[0].sym = field
|
|
||||||
|
|
||||||
patch "=sink", t.sink
|
|
||||||
patch "=", t.assignment
|
|
||||||
patch "=destroy", t.destructor
|
|
||||||
for x in n:
|
|
||||||
patchHead(x, alreadyPatched)
|
|
||||||
|
|
||||||
proc liftTypeBoundOps*(c: PContext; typ: PType; info: TLineInfo) =
|
proc liftTypeBoundOps*(c: PContext; typ: PType; info: TLineInfo) =
|
||||||
## In the semantic pass this is called in strategic places
|
## In the semantic pass this is called in strategic places
|
||||||
## to ensure we lift assignment, destructors and moves properly.
|
## to ensure we lift assignment, destructors and moves properly.
|
||||||
|
|
@ -339,20 +321,9 @@ proc liftTypeBoundOps*(c: PContext; typ: PType; info: TLineInfo) =
|
||||||
if not newDestructors or not hasDestructor(typ): return
|
if not newDestructors or not hasDestructor(typ): return
|
||||||
let typ = typ.skipTypes({tyGenericInst, tyAlias})
|
let typ = typ.skipTypes({tyGenericInst, tyAlias})
|
||||||
# we generate the destructor first so that other operators can depend on it:
|
# we generate the destructor first so that other operators can depend on it:
|
||||||
var changed = false
|
|
||||||
if typ.destructor != nil and typ.destructor.magic == mAsgn:
|
|
||||||
typ.destructor = nil
|
|
||||||
if typ.destructor == nil:
|
if typ.destructor == nil:
|
||||||
liftBody(c, typ, attachedDestructor, info)
|
liftBody(c, typ, attachedDestructor, info)
|
||||||
changed = true
|
|
||||||
if typ.assignment == nil:
|
if typ.assignment == nil:
|
||||||
liftBody(c, typ, attachedAsgn, info)
|
liftBody(c, typ, attachedAsgn, info)
|
||||||
changed = true
|
|
||||||
if typ.sink == nil:
|
if typ.sink == nil:
|
||||||
liftBody(c, typ, attachedSink, info)
|
liftBody(c, typ, attachedSink, info)
|
||||||
changed = true
|
|
||||||
if changed:
|
|
||||||
var alreadyPatched = initIntSet()
|
|
||||||
patchHead(typ.destructor.getBody, alreadyPatched)
|
|
||||||
patchHead(typ.assignment.getBody, alreadyPatched)
|
|
||||||
patchHead(typ.sink.getBody, alreadyPatched)
|
|
||||||
|
|
|
||||||
|
|
@ -664,19 +664,6 @@ proc afterCallActions(c: PContext; n, orig: PNode, flags: TExprFlags): PNode =
|
||||||
of skMacro: result = semMacroExpr(c, result, orig, callee, flags)
|
of skMacro: result = semMacroExpr(c, result, orig, callee, flags)
|
||||||
of skTemplate: result = semTemplateExpr(c, result, callee, flags)
|
of skTemplate: result = semTemplateExpr(c, result, callee, flags)
|
||||||
else:
|
else:
|
||||||
when false:
|
|
||||||
if callee.name.s[0] == '=' and result.len > 1:
|
|
||||||
# careful, do not skip tyDistinct here:
|
|
||||||
let t = result[1].typ.skipTypes({tyVar, tyGenericInst, tyAlias, tyInferred})
|
|
||||||
|
|
||||||
proc patchHead(callee: PSym; name: string; field: PSym; result: PNode) =
|
|
||||||
if callee.name.s == name and field != nil:
|
|
||||||
result.sons[0].sym = field
|
|
||||||
|
|
||||||
patchHead(callee, "=destroy", t.destructor, result)
|
|
||||||
patchHead(callee, "=sink", t.sink, result)
|
|
||||||
patchHead(callee, "=", t.assignment, result)
|
|
||||||
|
|
||||||
semFinishOperands(c, result)
|
semFinishOperands(c, result)
|
||||||
activate(c, result)
|
activate(c, result)
|
||||||
fixAbstractType(c, result)
|
fixAbstractType(c, result)
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@ after 20 20'''
|
||||||
cmd: '''nim c --newruntime $file'''
|
cmd: '''nim c --newruntime $file'''
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
{.this: self.}
|
||||||
|
|
||||||
type
|
type
|
||||||
mystring = object
|
mystring = object
|
||||||
len, cap: int
|
len, cap: int
|
||||||
|
|
@ -46,10 +48,10 @@ proc `=`*(a: var mystring; b: mystring) =
|
||||||
copyMem(a.data, b.data, a.cap+1)
|
copyMem(a.data, b.data, a.cap+1)
|
||||||
|
|
||||||
proc resize(self: var mystring) =
|
proc resize(self: var mystring) =
|
||||||
if cap == 0: cap = 8
|
if self.cap == 0: self.cap = 8
|
||||||
else: cap = (cap * 3) shr 1
|
else: self.cap = (self.cap * 3) shr 1
|
||||||
if data == nil: inc allocCount
|
if self.data == nil: inc allocCount
|
||||||
data = cast[type(data)](realloc(data, cap + 1))
|
self.data = cast[type(data)](realloc(self.data, self.cap + 1))
|
||||||
|
|
||||||
proc add*(self: var mystring; c: char) =
|
proc add*(self: var mystring; c: char) =
|
||||||
if self.len >= self.cap: resize(self)
|
if self.len >= self.cap: resize(self)
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ discard """
|
||||||
60.0
|
60.0
|
||||||
90.0
|
90.0
|
||||||
120.0
|
120.0
|
||||||
4 1'''
|
4 4'''
|
||||||
cmd: '''nim c --newruntime $file'''
|
cmd: '''nim c --newruntime $file'''
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
@ -18,8 +18,8 @@ var
|
||||||
|
|
||||||
proc `=destroy`*[T](x: var opt[T]) =
|
proc `=destroy`*[T](x: var opt[T]) =
|
||||||
if x.data != nil:
|
if x.data != nil:
|
||||||
when not supportsCopyMem(T):
|
#when not supportsCopyMem(T):
|
||||||
`=destroy`(x.data[])
|
`=destroy`(x.data[])
|
||||||
dealloc(x.data)
|
dealloc(x.data)
|
||||||
inc deallocCount
|
inc deallocCount
|
||||||
x.data = nil
|
x.data = nil
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue