destructors: preparations for upcoming changes
This commit is contained in:
parent
7ee825a6e5
commit
45d74f4081
8 changed files with 27 additions and 8 deletions
|
|
@ -1663,3 +1663,5 @@ when false:
|
||||||
if n.isNil: return true
|
if n.isNil: return true
|
||||||
for i in 0 ..< n.safeLen:
|
for i in 0 ..< n.safeLen:
|
||||||
if n[i].containsNil: return true
|
if n[i].containsNil: return true
|
||||||
|
|
||||||
|
template hasDestructor*(t: PType): bool = tfHasAsgn in t.flags
|
||||||
|
|
|
||||||
|
|
@ -95,8 +95,6 @@ import
|
||||||
intsets, ast, astalgo, msgs, renderer, magicsys, types, idents, trees,
|
intsets, ast, astalgo, msgs, renderer, magicsys, types, idents, trees,
|
||||||
strutils, options, dfa, lowerings
|
strutils, options, dfa, lowerings
|
||||||
|
|
||||||
template hasDestructor(t: PType): bool = tfHasAsgn in t.flags
|
|
||||||
|
|
||||||
const
|
const
|
||||||
InterestingSyms = {skVar, skResult, skLet}
|
InterestingSyms = {skVar, skResult, skLet}
|
||||||
|
|
||||||
|
|
@ -253,6 +251,7 @@ proc p(n: PNode; c: var Con): PNode =
|
||||||
result = copyNode(n)
|
result = copyNode(n)
|
||||||
recurse(n, result)
|
recurse(n, result)
|
||||||
of nkAsgn, nkFastAsgn:
|
of nkAsgn, nkFastAsgn:
|
||||||
|
# XXX if special, call special operator
|
||||||
if n[0].kind == nkSym and interestingSym(n[0].sym):
|
if n[0].kind == nkSym and interestingSym(n[0].sym):
|
||||||
result = moveOrCopy(n[0], n[1], c)
|
result = moveOrCopy(n[0], n[1], c)
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@ proc considerOverloadedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool =
|
||||||
styleCheckUse(c.info, op)
|
styleCheckUse(c.info, op)
|
||||||
body.add newOpCall(op, x)
|
body.add newOpCall(op, x)
|
||||||
result = true
|
result = true
|
||||||
of attachedAsgn:
|
of attachedAsgn, attachedSink:
|
||||||
if tfHasAsgn in t.flags:
|
if tfHasAsgn in t.flags:
|
||||||
var op: PSym
|
var op: PSym
|
||||||
if sameType(t, c.asgnForType):
|
if sameType(t, c.asgnForType):
|
||||||
|
|
@ -285,3 +285,13 @@ proc getAsgnOrLiftBody(c: PContext; typ: PType; info: TLineInfo): PSym =
|
||||||
proc overloadedAsgn(c: PContext; dest, src: PNode): PNode =
|
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 liftTypeBoundOps*(c: PContext; typ: PType) =
|
||||||
|
## In the semantic pass this is called in strategic places
|
||||||
|
## to ensure we lift assignment, destructors and moves properly.
|
||||||
|
## Since this is done in the sem* routines generics already have
|
||||||
|
## been resolved for us and do not complicate the logic any further.
|
||||||
|
## We have to ensure that the 'tfHasDesctructor' flags bubbles up
|
||||||
|
## in the generic instantiations though.
|
||||||
|
## The later 'destroyer' pass depends on it.
|
||||||
|
if not newDestructors or not hasDestructor(typ): return
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,7 @@ type
|
||||||
|
|
||||||
TTypeAttachedOp* = enum
|
TTypeAttachedOp* = enum
|
||||||
attachedAsgn,
|
attachedAsgn,
|
||||||
|
attachedSink,
|
||||||
attachedDeepCopy,
|
attachedDeepCopy,
|
||||||
attachedDestructor
|
attachedDestructor
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -670,6 +670,7 @@ proc afterCallActions(c: PContext; n, orig: PNode, flags: TExprFlags): PNode =
|
||||||
analyseIfAddressTakenInCall(c, result)
|
analyseIfAddressTakenInCall(c, result)
|
||||||
if callee.magic != mNone:
|
if callee.magic != mNone:
|
||||||
result = magicsAfterOverloadResolution(c, result, flags)
|
result = magicsAfterOverloadResolution(c, result, flags)
|
||||||
|
if result.typ != nil: liftTypeBoundOps(c, result.typ)
|
||||||
if c.matchedConcept == nil:
|
if c.matchedConcept == nil:
|
||||||
result = evalAtCompileTime(c, result)
|
result = evalAtCompileTime(c, result)
|
||||||
|
|
||||||
|
|
@ -1390,6 +1391,8 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
|
||||||
if tfHasAsgn in lhs.typ.flags and not lhsIsResult and
|
if tfHasAsgn in lhs.typ.flags and not lhsIsResult and
|
||||||
mode != noOverloadedAsgn:
|
mode != noOverloadedAsgn:
|
||||||
return overloadedAsgn(c, lhs, n.sons[1])
|
return overloadedAsgn(c, lhs, n.sons[1])
|
||||||
|
else:
|
||||||
|
liftTypeBoundOps(c, lhs.typ)
|
||||||
|
|
||||||
fixAbstractType(c, n)
|
fixAbstractType(c, n)
|
||||||
asgnToResultVar(c, n, n.sons[0], n.sons[1])
|
asgnToResultVar(c, n, n.sons[0], n.sons[1])
|
||||||
|
|
|
||||||
|
|
@ -553,6 +553,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
||||||
# this can only happen for errornous var statements:
|
# this can only happen for errornous var statements:
|
||||||
if typ == nil: continue
|
if typ == nil: continue
|
||||||
typeAllowedCheck(a.info, typ, symkind)
|
typeAllowedCheck(a.info, typ, symkind)
|
||||||
|
liftTypeBoundOps(c, typ)
|
||||||
var tup = skipTypes(typ, {tyGenericInst, tyAlias})
|
var tup = skipTypes(typ, {tyGenericInst, tyAlias})
|
||||||
if a.kind == nkVarTuple:
|
if a.kind == nkVarTuple:
|
||||||
if tup.kind != tyTuple:
|
if tup.kind != tyTuple:
|
||||||
|
|
|
||||||
|
|
@ -363,11 +363,7 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType =
|
||||||
# '=' needs to be instantiated for generics when the type is constructed:
|
# '=' needs to be instantiated for generics when the type is constructed:
|
||||||
newbody.field = cl.c.instTypeBoundOp(cl.c, opr, result, cl.info,
|
newbody.field = cl.c.instTypeBoundOp(cl.c, opr, result, cl.info,
|
||||||
attachedAsgn, 1)
|
attachedAsgn, 1)
|
||||||
# we need to produce the destructor first here because generated '='
|
if not newDestructors: typeBound(assignment)
|
||||||
# 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
|
||||||
|
|
|
||||||
|
|
@ -292,6 +292,13 @@ when defined(nimArrIdx):
|
||||||
proc `[]=`*[I: Ordinal;T,S](a: T; i: I;
|
proc `[]=`*[I: Ordinal;T,S](a: T; i: I;
|
||||||
x: S) {.noSideEffect, magic: "ArrPut".}
|
x: S) {.noSideEffect, magic: "ArrPut".}
|
||||||
proc `=`*[T](dest: var T; src: T) {.noSideEffect, magic: "Asgn".}
|
proc `=`*[T](dest: var T; src: T) {.noSideEffect, magic: "Asgn".}
|
||||||
|
when defined(nimNewRuntime):
|
||||||
|
template `=destroy`*[T](x: var T) =
|
||||||
|
## generic `destructor`:idx: implementation that can be overriden.
|
||||||
|
discard
|
||||||
|
template `=sink`*[T](x: var T; y: T) =
|
||||||
|
## generic `sink`:idx: implementation that can be overriden.
|
||||||
|
shallowCopy(x, y)
|
||||||
|
|
||||||
type
|
type
|
||||||
Slice*[T] = object ## builtin slice type
|
Slice*[T] = object ## builtin slice type
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue