minor refactorings for better destructors
This commit is contained in:
parent
4eaa2bf15d
commit
8780d25e03
7 changed files with 51 additions and 17 deletions
|
|
@ -1081,7 +1081,7 @@ proc newSym*(symKind: TSymKind, name: PIdent, owner: PSym,
|
||||||
result.info = info
|
result.info = info
|
||||||
result.options = gOptions
|
result.options = gOptions
|
||||||
result.owner = owner
|
result.owner = owner
|
||||||
result.offset = - 1
|
result.offset = -1
|
||||||
result.id = getID()
|
result.id = getID()
|
||||||
when debugIds:
|
when debugIds:
|
||||||
registerId(result)
|
registerId(result)
|
||||||
|
|
|
||||||
|
|
@ -13,5 +13,5 @@
|
||||||
const
|
const
|
||||||
MaxSetElements* = 1 shl 16 # (2^16) to support unicode character sets?
|
MaxSetElements* = 1 shl 16 # (2^16) to support unicode character sets?
|
||||||
VersionAsString* = system.NimVersion
|
VersionAsString* = system.NimVersion
|
||||||
RodFileVersion* = "1222" # modify this if the rod-format changes!
|
RodFileVersion* = "1223" # modify this if the rod-format changes!
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -336,10 +336,13 @@ proc decodeType(r: PRodReader, info: TLineInfo): PType =
|
||||||
if r.s[r.pos] == '\17':
|
if r.s[r.pos] == '\17':
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
result.assignment = rrGetSym(r, decodeVInt(r.s, r.pos), info)
|
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)
|
inc(r.pos)
|
||||||
let x = decodeVInt(r.s, r.pos)
|
let x = decodeVInt(r.s, r.pos)
|
||||||
doAssert r.s[r.pos] == '\19'
|
doAssert r.s[r.pos] == '\20'
|
||||||
inc(r.pos)
|
inc(r.pos)
|
||||||
let y = rrGetSym(r, decodeVInt(r.s, r.pos), info)
|
let y = rrGetSym(r, decodeVInt(r.s, r.pos), info)
|
||||||
result.methods.safeAdd((x, y))
|
result.methods.safeAdd((x, y))
|
||||||
|
|
|
||||||
|
|
@ -245,10 +245,14 @@ proc encodeType(w: PRodWriter, t: PType, result: var string) =
|
||||||
add(result, '\17')
|
add(result, '\17')
|
||||||
encodeVInt(t.assignment.id, result)
|
encodeVInt(t.assignment.id, result)
|
||||||
pushSym(w, t.assignment)
|
pushSym(w, t.assignment)
|
||||||
for i, s in items(t.methods):
|
if t.sink != nil:
|
||||||
add(result, '\18')
|
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')
|
add(result, '\19')
|
||||||
|
encodeVInt(i, result)
|
||||||
|
add(result, '\20')
|
||||||
encodeVInt(s.id, result)
|
encodeVInt(s.id, result)
|
||||||
pushSym(w, s)
|
pushSym(w, s)
|
||||||
encodeLoc(w, t.loc, result)
|
encodeLoc(w, t.loc, result)
|
||||||
|
|
|
||||||
|
|
@ -92,13 +92,13 @@ proc newAsgnStmt(le, ri: PNode): PNode =
|
||||||
result.sons[0] = le
|
result.sons[0] = le
|
||||||
result.sons[1] = ri
|
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 = newNodeIT(nkCall, x.info, op.typ.sons[0])
|
||||||
result.add(newSymNode(op))
|
result.add(newSymNode(op))
|
||||||
result.add x
|
result.add x
|
||||||
|
|
||||||
proc newDeepCopyCall(op: PSym; x, y: PNode): PNode =
|
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 =
|
proc considerOverloadedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool =
|
||||||
case c.kind
|
case c.kind
|
||||||
|
|
@ -107,7 +107,7 @@ proc considerOverloadedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool =
|
||||||
if op != nil:
|
if op != nil:
|
||||||
markUsed(c.info, op, c.c.graph.usageSym)
|
markUsed(c.info, op, c.c.graph.usageSym)
|
||||||
styleCheckUse(c.info, op)
|
styleCheckUse(c.info, op)
|
||||||
body.add newDestructorCall(op, x)
|
body.add newOpCall(op, x)
|
||||||
result = true
|
result = true
|
||||||
of attachedAsgn:
|
of attachedAsgn:
|
||||||
if tfHasAsgn in t.flags:
|
if tfHasAsgn in t.flags:
|
||||||
|
|
|
||||||
|
|
@ -1277,9 +1277,30 @@ proc maybeAddResult(c: PContext, s: PSym, n: PNode) =
|
||||||
proc semOverride(c: PContext, s: PSym, n: PNode) =
|
proc semOverride(c: PContext, s: PSym, n: PNode) =
|
||||||
case s.name.s.normalize
|
case s.name.s.normalize
|
||||||
of "destroy", "=destroy":
|
of "destroy", "=destroy":
|
||||||
doDestructorStuff(c, s, n)
|
if newDestructors:
|
||||||
if not newDestructors and not experimentalMode(c):
|
let t = s.typ
|
||||||
localError n.info, "use the {.experimental.} pragma to enable destructors"
|
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)
|
incl(s.flags, sfUsed)
|
||||||
of "deepcopy", "=deepcopy":
|
of "deepcopy", "=deepcopy":
|
||||||
if s.typ.len == 2 and
|
if s.typ.len == 2 and
|
||||||
|
|
|
||||||
|
|
@ -357,11 +357,17 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType =
|
||||||
assert newbody.kind in {tyRef, tyPtr}
|
assert newbody.kind in {tyRef, tyPtr}
|
||||||
assert newbody.lastSon.typeInst == nil
|
assert newbody.lastSon.typeInst == nil
|
||||||
newbody.lastSon.typeInst = result
|
newbody.lastSon.typeInst = result
|
||||||
let asgn = newbody.assignment
|
template typeBound(field) =
|
||||||
if asgn != nil and sfFromGeneric notin asgn.flags:
|
let opr = newbody.field
|
||||||
# '=' needs to be instantiated for generics when the type is constructed:
|
if opr != nil and sfFromGeneric notin opr.flags:
|
||||||
newbody.assignment = cl.c.instTypeBoundOp(cl.c, asgn, result, cl.info,
|
# '=' needs to be instantiated for generics when the type is constructed:
|
||||||
attachedAsgn, 1)
|
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
|
let methods = skipTypes(bbody, abstractPtrs).methods
|
||||||
for col, meth in items(methods):
|
for col, meth in items(methods):
|
||||||
# we instantiate the known methods belonging to that type, this causes
|
# we instantiate the known methods belonging to that type, this causes
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue