minor refactorings for better destructors

This commit is contained in:
Andreas Rumpf
2017-10-14 09:32:57 +02:00
parent 4eaa2bf15d
commit 8780d25e03
7 changed files with 51 additions and 17 deletions

View File

@@ -1081,7 +1081,7 @@ proc newSym*(symKind: TSymKind, name: PIdent, owner: PSym,
result.info = info
result.options = gOptions
result.owner = owner
result.offset = - 1
result.offset = -1
result.id = getID()
when debugIds:
registerId(result)

View File

@@ -13,5 +13,5 @@
const
MaxSetElements* = 1 shl 16 # (2^16) to support unicode character sets?
VersionAsString* = system.NimVersion
RodFileVersion* = "1222" # modify this if the rod-format changes!
RodFileVersion* = "1223" # modify this if the rod-format changes!

View File

@@ -336,10 +336,13 @@ proc decodeType(r: PRodReader, info: TLineInfo): PType =
if r.s[r.pos] == '\17':
inc(r.pos)
result.assignment = rrGetSym(r, decodeVInt(r.s, r.pos), info)
while r.s[r.pos] == '\18':
if r.s[r.pos] == '\18':
inc(r.pos)
result.sink = rrGetSym(r, decodeVInt(r.s, r.pos), info)
while r.s[r.pos] == '\19':
inc(r.pos)
let x = decodeVInt(r.s, r.pos)
doAssert r.s[r.pos] == '\19'
doAssert r.s[r.pos] == '\20'
inc(r.pos)
let y = rrGetSym(r, decodeVInt(r.s, r.pos), info)
result.methods.safeAdd((x, y))

View File

@@ -245,10 +245,14 @@ proc encodeType(w: PRodWriter, t: PType, result: var string) =
add(result, '\17')
encodeVInt(t.assignment.id, result)
pushSym(w, t.assignment)
for i, s in items(t.methods):
if t.sink != nil:
add(result, '\18')
encodeVInt(i, result)
encodeVInt(t.sink.id, result)
pushSym(w, t.sink)
for i, s in items(t.methods):
add(result, '\19')
encodeVInt(i, result)
add(result, '\20')
encodeVInt(s.id, result)
pushSym(w, s)
encodeLoc(w, t.loc, result)

View File

@@ -92,13 +92,13 @@ proc newAsgnStmt(le, ri: PNode): PNode =
result.sons[0] = le
result.sons[1] = ri
proc newDestructorCall(op: PSym; x: PNode): PNode =
proc newOpCall(op: PSym; x: PNode): PNode =
result = newNodeIT(nkCall, x.info, op.typ.sons[0])
result.add(newSymNode(op))
result.add x
proc newDeepCopyCall(op: PSym; x, y: PNode): PNode =
result = newAsgnStmt(x, newDestructorCall(op, y))
result = newAsgnStmt(x, newOpCall(op, y))
proc considerOverloadedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool =
case c.kind
@@ -107,7 +107,7 @@ proc considerOverloadedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool =
if op != nil:
markUsed(c.info, op, c.c.graph.usageSym)
styleCheckUse(c.info, op)
body.add newDestructorCall(op, x)
body.add newOpCall(op, x)
result = true
of attachedAsgn:
if tfHasAsgn in t.flags:

View File

@@ -1277,9 +1277,30 @@ proc maybeAddResult(c: PContext, s: PSym, n: PNode) =
proc semOverride(c: PContext, s: PSym, n: PNode) =
case s.name.s.normalize
of "destroy", "=destroy":
doDestructorStuff(c, s, n)
if not newDestructors and not experimentalMode(c):
localError n.info, "use the {.experimental.} pragma to enable destructors"
if newDestructors:
let t = s.typ
var noError = false
if t.len == 2 and t.sons[0] == nil and t.sons[1].kind == tyVar:
var obj = t.sons[1].sons[0]
while true:
incl(obj.flags, tfHasAsgn)
if obj.kind == tyGenericBody: obj = obj.lastSon
elif obj.kind == tyGenericInvocation: obj = obj.sons[0]
else: break
if obj.kind in {tyObject, tyDistinct}:
if obj.destructor.isNil:
obj.destructor = s
else:
localError(n.info, errGenerated,
"cannot bind another '" & s.name.s & "' to: " & typeToString(obj))
noError = true
if not noError:
localError(n.info, errGenerated,
"signature for '" & s.name.s & "' must be proc[T: object](x: var T)")
else:
doDestructorStuff(c, s, n)
if not experimentalMode(c):
localError n.info, "use the {.experimental.} pragma to enable destructors"
incl(s.flags, sfUsed)
of "deepcopy", "=deepcopy":
if s.typ.len == 2 and

View File

@@ -357,11 +357,17 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType =
assert newbody.kind in {tyRef, tyPtr}
assert newbody.lastSon.typeInst == nil
newbody.lastSon.typeInst = result
let asgn = newbody.assignment
if asgn != nil and sfFromGeneric notin asgn.flags:
# '=' needs to be instantiated for generics when the type is constructed:
newbody.assignment = cl.c.instTypeBoundOp(cl.c, asgn, result, cl.info,
attachedAsgn, 1)
template typeBound(field) =
let opr = newbody.field
if opr != nil and sfFromGeneric notin opr.flags:
# '=' needs to be instantiated for generics when the type is constructed:
newbody.field = cl.c.instTypeBoundOp(cl.c, opr, result, cl.info,
attachedAsgn, 1)
# we need to produce the destructor first here because generated '='
# and '=sink' operators can rely on it:
if newDestructors: typeBound(destructor)
typeBound(assignment)
typeBound(sink)
let methods = skipTypes(bbody, abstractPtrs).methods
for col, meth in items(methods):
# we instantiate the known methods belonging to that type, this causes