mirror of
https://github.com/nim-lang/Nim.git
synced 2026-07-20 16:01:29 +00:00
topttree destructor finally works
This commit is contained in:
@@ -164,26 +164,22 @@ proc isHarmlessVar*(s: PSym; c: Con): bool =
|
||||
template interestingSym(s: PSym): bool =
|
||||
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:
|
||||
let s = n[0].sym
|
||||
if sfFromGeneric in s.flags or true:
|
||||
if s.name.s[0] == '=' and not containsOrIncl(alreadyPatched, s.id):
|
||||
patchHead(s.getBody, alreadyPatched)
|
||||
if sfFromGeneric in s.flags and s.name.s[0] == '=' and
|
||||
s.name.s in ["=sink", "=", "=destroy"]:
|
||||
excl(s.flags, sfFromGeneric)
|
||||
patchHead(s.getBody)
|
||||
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:
|
||||
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)
|
||||
|
||||
template patchHead(n: PNode) =
|
||||
when false:
|
||||
var alreadyPatched = initIntSet()
|
||||
patchHead(n, alreadyPatched)
|
||||
patchHead(x)
|
||||
|
||||
proc genSink(t: PType; dest: PNode): PNode =
|
||||
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)
|
||||
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) =
|
||||
## In the semantic pass this is called in strategic places
|
||||
## 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
|
||||
let typ = typ.skipTypes({tyGenericInst, tyAlias})
|
||||
# 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:
|
||||
liftBody(c, typ, attachedDestructor, info)
|
||||
changed = true
|
||||
if typ.assignment == nil:
|
||||
liftBody(c, typ, attachedAsgn, info)
|
||||
changed = true
|
||||
if typ.sink == nil:
|
||||
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 skTemplate: result = semTemplateExpr(c, result, callee, flags)
|
||||
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)
|
||||
activate(c, result)
|
||||
fixAbstractType(c, result)
|
||||
|
||||
@@ -8,6 +8,8 @@ after 20 20'''
|
||||
cmd: '''nim c --newruntime $file'''
|
||||
"""
|
||||
|
||||
{.this: self.}
|
||||
|
||||
type
|
||||
mystring = object
|
||||
len, cap: int
|
||||
@@ -46,10 +48,10 @@ proc `=`*(a: var mystring; b: mystring) =
|
||||
copyMem(a.data, b.data, a.cap+1)
|
||||
|
||||
proc resize(self: var mystring) =
|
||||
if cap == 0: cap = 8
|
||||
else: cap = (cap * 3) shr 1
|
||||
if data == nil: inc allocCount
|
||||
data = cast[type(data)](realloc(data, cap + 1))
|
||||
if self.cap == 0: self.cap = 8
|
||||
else: self.cap = (self.cap * 3) shr 1
|
||||
if self.data == nil: inc allocCount
|
||||
self.data = cast[type(data)](realloc(self.data, self.cap + 1))
|
||||
|
||||
proc add*(self: var mystring; c: char) =
|
||||
if self.len >= self.cap: resize(self)
|
||||
|
||||
@@ -3,7 +3,7 @@ discard """
|
||||
60.0
|
||||
90.0
|
||||
120.0
|
||||
4 1'''
|
||||
4 4'''
|
||||
cmd: '''nim c --newruntime $file'''
|
||||
"""
|
||||
|
||||
@@ -18,8 +18,8 @@ var
|
||||
|
||||
proc `=destroy`*[T](x: var opt[T]) =
|
||||
if x.data != nil:
|
||||
when not supportsCopyMem(T):
|
||||
`=destroy`(x.data[])
|
||||
#when not supportsCopyMem(T):
|
||||
`=destroy`(x.data[])
|
||||
dealloc(x.data)
|
||||
inc deallocCount
|
||||
x.data = nil
|
||||
|
||||
Reference in New Issue
Block a user