destructors: internal compiler refactoring
This commit is contained in:
parent
fb3681b425
commit
750f50b6c0
7 changed files with 77 additions and 103 deletions
|
|
@ -877,6 +877,13 @@ type
|
||||||
|
|
||||||
TTypeSeq* = seq[PType]
|
TTypeSeq* = seq[PType]
|
||||||
TLockLevel* = distinct int16
|
TLockLevel* = distinct int16
|
||||||
|
|
||||||
|
TTypeAttachedOp* = enum ## as usual, order is important here
|
||||||
|
attachedDestructor,
|
||||||
|
attachedAsgn,
|
||||||
|
attachedSink,
|
||||||
|
attachedDeepCopy
|
||||||
|
|
||||||
TType* {.acyclic.} = object of TIdObj # \
|
TType* {.acyclic.} = object of TIdObj # \
|
||||||
# types are identical iff they have the
|
# types are identical iff they have the
|
||||||
# same id; there may be multiple copies of a type
|
# same id; there may be multiple copies of a type
|
||||||
|
|
@ -897,12 +904,7 @@ type
|
||||||
owner*: PSym # the 'owner' of the type
|
owner*: PSym # the 'owner' of the type
|
||||||
sym*: PSym # types have the sym associated with them
|
sym*: PSym # types have the sym associated with them
|
||||||
# it is used for converting types to strings
|
# it is used for converting types to strings
|
||||||
destructor*: PSym # destructor. warning: nil here may not necessary
|
attachedOps*: array[TTypeAttachedOp, PSym] # destructors, etc.
|
||||||
# mean that there is no destructor.
|
|
||||||
# see instantiateDestructor in semdestruct.nim
|
|
||||||
deepCopy*: PSym # overriden 'deepCopy' operation
|
|
||||||
assignment*: PSym # overriden '=' operation
|
|
||||||
sink*: PSym # overriden '=sink' operation
|
|
||||||
methods*: seq[(int,PSym)] # attached methods
|
methods*: seq[(int,PSym)] # attached methods
|
||||||
size*: BiggestInt # the size of the type in bytes
|
size*: BiggestInt # the size of the type in bytes
|
||||||
# -1 means that the size is unkwown
|
# -1 means that the size is unkwown
|
||||||
|
|
@ -1275,6 +1277,7 @@ const
|
||||||
UnspecifiedLockLevel* = TLockLevel(-1'i16)
|
UnspecifiedLockLevel* = TLockLevel(-1'i16)
|
||||||
MaxLockLevel* = 1000'i16
|
MaxLockLevel* = 1000'i16
|
||||||
UnknownLockLevel* = TLockLevel(1001'i16)
|
UnknownLockLevel* = TLockLevel(1001'i16)
|
||||||
|
AttachedOpToStr*: array[TTypeAttachedOp, string] = ["=destroy", "=", "=sink", "=deepcopy"]
|
||||||
|
|
||||||
proc `$`*(x: TLockLevel): string =
|
proc `$`*(x: TLockLevel): string =
|
||||||
if x.ord == UnspecifiedLockLevel.ord: result = "<unspecified>"
|
if x.ord == UnspecifiedLockLevel.ord: result = "<unspecified>"
|
||||||
|
|
@ -1341,10 +1344,7 @@ proc assignType*(dest, src: PType) =
|
||||||
dest.n = src.n
|
dest.n = src.n
|
||||||
dest.size = src.size
|
dest.size = src.size
|
||||||
dest.align = src.align
|
dest.align = src.align
|
||||||
dest.destructor = src.destructor
|
dest.attachedOps = src.attachedOps
|
||||||
dest.deepCopy = src.deepCopy
|
|
||||||
dest.sink = src.sink
|
|
||||||
dest.assignment = src.assignment
|
|
||||||
dest.lockLevel = src.lockLevel
|
dest.lockLevel = src.lockLevel
|
||||||
# this fixes 'type TLock = TSysLock':
|
# this fixes 'type TLock = TSysLock':
|
||||||
if src.sym != nil:
|
if src.sym != nil:
|
||||||
|
|
@ -1831,3 +1831,7 @@ proc addParam*(procType: PType; param: PSym) =
|
||||||
param.position = procType.len-1
|
param.position = procType.len-1
|
||||||
addSon(procType.n, newSymNode(param))
|
addSon(procType.n, newSymNode(param))
|
||||||
rawAddSon(procType, param.typ)
|
rawAddSon(procType, param.typ)
|
||||||
|
|
||||||
|
template destructor*(t: PType): PSym = t.attachedOps[attachedDestructor]
|
||||||
|
template assignment*(t: PType): PSym = t.attachedOps[attachedAsgn]
|
||||||
|
template asink*(t: PType): PSym = t.attachedOps[attachedSink]
|
||||||
|
|
|
||||||
|
|
@ -1346,10 +1346,10 @@ proc genTypeInfo(m: BModule, t: PType; info: TLineInfo): Rope =
|
||||||
# results are not deterministic!
|
# results are not deterministic!
|
||||||
genTupleInfo(m, t, origType, result, info)
|
genTupleInfo(m, t, origType, result, info)
|
||||||
else: internalError(m.config, "genTypeInfo(" & $t.kind & ')')
|
else: internalError(m.config, "genTypeInfo(" & $t.kind & ')')
|
||||||
if t.deepCopy != nil:
|
if t.attachedOps[attachedDeepCopy] != nil:
|
||||||
genDeepCopyProc(m, t.deepCopy, result)
|
genDeepCopyProc(m, t.attachedOps[attachedDeepCopy], result)
|
||||||
elif origType.deepCopy != nil:
|
elif origType.attachedOps[attachedDeepCopy] != nil:
|
||||||
genDeepCopyProc(m, origType.deepCopy, result)
|
genDeepCopyProc(m, origType.attachedOps[attachedDeepCopy], result)
|
||||||
result = prefixTI.rope & result & ")".rope
|
result = prefixTI.rope & result & ")".rope
|
||||||
|
|
||||||
proc genTypeSection(m: BModule, n: PNode) =
|
proc genTypeSection(m: BModule, n: PNode) =
|
||||||
|
|
|
||||||
|
|
@ -136,7 +136,7 @@ to do it.
|
||||||
import
|
import
|
||||||
intsets, ast, astalgo, msgs, renderer, magicsys, types, idents, trees,
|
intsets, ast, astalgo, msgs, renderer, magicsys, types, idents, trees,
|
||||||
strutils, options, dfa, lowerings, tables, modulegraphs, msgs,
|
strutils, options, dfa, lowerings, tables, modulegraphs, msgs,
|
||||||
lineinfos, parampatterns
|
lineinfos, parampatterns, sighashes
|
||||||
|
|
||||||
const
|
const
|
||||||
InterestingSyms = {skVar, skResult, skLet, skForVar, skTemp}
|
InterestingSyms = {skVar, skResult, skLet, skForVar, skTemp}
|
||||||
|
|
@ -314,24 +314,34 @@ proc makePtrType(c: Con, baseType: PType): PType =
|
||||||
result = newType(tyPtr, c.owner)
|
result = newType(tyPtr, c.owner)
|
||||||
addSonSkipIntLit(result, baseType)
|
addSonSkipIntLit(result, baseType)
|
||||||
|
|
||||||
template genOp(opr, opname, ri) =
|
proc genOp(c: Con; t: PType; kind: TTypeAttachedOp; dest, ri: PNode): PNode =
|
||||||
let op = opr
|
var op = t.attachedOps[kind]
|
||||||
|
|
||||||
|
when false:
|
||||||
|
if op == nil:
|
||||||
|
# give up and find the canonical type instead:
|
||||||
|
let h = sighashes.hashType(t, {CoType, CoConsiderOwned})
|
||||||
|
let canon = c.graph.canonTypes.getOrDefault(h)
|
||||||
|
if canon != nil:
|
||||||
|
op = canon.attachedOps[kind]
|
||||||
|
|
||||||
if op == nil:
|
if op == nil:
|
||||||
globalError(c.graph.config, dest.info, "internal error: '" & opname &
|
globalError(c.graph.config, dest.info, "internal error: '" & AttachedOpToStr[kind] &
|
||||||
"' operator not found for type " & typeToString(t))
|
"' operator not found for type " & typeToString(t))
|
||||||
elif op.ast[genericParamsPos].kind != nkEmpty:
|
elif op.ast[genericParamsPos].kind != nkEmpty:
|
||||||
globalError(c.graph.config, dest.info, "internal error: '" & opname &
|
globalError(c.graph.config, dest.info, "internal error: '" & AttachedOpToStr[kind] &
|
||||||
"' operator is generic")
|
"' operator is generic")
|
||||||
if sfError in op.flags: checkForErrorPragma(c, t, ri, opname)
|
if sfError in op.flags: checkForErrorPragma(c, t, ri, AttachedOpToStr[kind])
|
||||||
let addrExp = newNodeIT(nkHiddenAddr, dest.info, makePtrType(c, dest.typ))
|
let addrExp = newNodeIT(nkHiddenAddr, dest.info, makePtrType(c, dest.typ))
|
||||||
addrExp.add(dest)
|
addrExp.add(dest)
|
||||||
result = newTree(nkCall, newSymNode(op), addrExp)
|
result = newTree(nkCall, newSymNode(op), addrExp)
|
||||||
|
|
||||||
proc genSink(c: Con; t: PType; dest, ri: PNode): PNode =
|
proc genSink(c: Con; t: PType; dest, ri: PNode): PNode =
|
||||||
let t = t.skipTypes({tyGenericInst, tyAlias, tySink})
|
let t = t.skipTypes({tyGenericInst, tyAlias, tySink})
|
||||||
let op = if t.sink != nil: t.sink else: t.assignment
|
let k = if t.attachedOps[attachedSink] != nil: attachedSink
|
||||||
if op != nil:
|
else: attachedAsgn
|
||||||
genOp(op, "=sink", ri)
|
if t.attachedOps[k] != nil:
|
||||||
|
result = genOp(c, t, k, dest, ri)
|
||||||
else:
|
else:
|
||||||
# in rare cases only =destroy exists but no sink or assignment
|
# in rare cases only =destroy exists but no sink or assignment
|
||||||
# (see Pony object in tmove_objconstr.nim)
|
# (see Pony object in tmove_objconstr.nim)
|
||||||
|
|
@ -342,15 +352,15 @@ proc genCopy(c: Con; t: PType; dest, ri: PNode): PNode =
|
||||||
if tfHasOwned in t.flags:
|
if tfHasOwned in t.flags:
|
||||||
checkForErrorPragma(c, t, ri, "=")
|
checkForErrorPragma(c, t, ri, "=")
|
||||||
let t = t.skipTypes({tyGenericInst, tyAlias, tySink})
|
let t = t.skipTypes({tyGenericInst, tyAlias, tySink})
|
||||||
genOp(t.assignment, "=", ri)
|
result = genOp(c, t, attachedAsgn, dest, ri)
|
||||||
|
|
||||||
proc genCopyNoCheck(c: Con; t: PType; dest, ri: PNode): PNode =
|
proc genCopyNoCheck(c: Con; t: PType; dest, ri: PNode): PNode =
|
||||||
let t = t.skipTypes({tyGenericInst, tyAlias, tySink})
|
let t = t.skipTypes({tyGenericInst, tyAlias, tySink})
|
||||||
genOp(t.assignment, "=", ri)
|
result = genOp(c, t, attachedAsgn, dest, ri)
|
||||||
|
|
||||||
proc genDestroy(c: Con; t: PType; dest: PNode): PNode =
|
proc genDestroy(c: Con; t: PType; dest: PNode): PNode =
|
||||||
let t = t.skipTypes({tyGenericInst, tyAlias, tySink})
|
let t = t.skipTypes({tyGenericInst, tyAlias, tySink})
|
||||||
genOp(t.destructor, "=destroy", nil)
|
result = genOp(c, t, attachedDestructor, dest, nil)
|
||||||
|
|
||||||
proc addTopVar(c: var Con; v: PNode) =
|
proc addTopVar(c: var Con; v: PNode) =
|
||||||
c.topLevelVars.add newTree(nkIdentDefs, v, c.emptyNode, c.emptyNode)
|
c.topLevelVars.add newTree(nkIdentDefs, v, c.emptyNode, c.emptyNode)
|
||||||
|
|
|
||||||
|
|
@ -197,7 +197,7 @@ proc considerUserDefinedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool =
|
||||||
assert t.typeInst != nil
|
assert t.typeInst != nil
|
||||||
# patch generic destructor:
|
# patch generic destructor:
|
||||||
op = c.c.instTypeBoundOp(c.c, op, t.typeInst, c.info, attachedAsgn, 1)
|
op = c.c.instTypeBoundOp(c.c, op, t.typeInst, c.info, attachedAsgn, 1)
|
||||||
t.destructor = op
|
t.attachedOps[attachedDestructor] = op
|
||||||
|
|
||||||
markUsed(c.graph.config, c.info, op, c.graph.usageSym)
|
markUsed(c.graph.config, c.info, op, c.graph.usageSym)
|
||||||
onUse(c.info, op)
|
onUse(c.info, op)
|
||||||
|
|
@ -207,9 +207,9 @@ proc considerUserDefinedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool =
|
||||||
of attachedAsgn:
|
of attachedAsgn:
|
||||||
result = considerAsgnOrSink(c, t, body, x, y, t.assignment)
|
result = considerAsgnOrSink(c, t, body, x, y, t.assignment)
|
||||||
of attachedSink:
|
of attachedSink:
|
||||||
result = considerAsgnOrSink(c, t, body, x, y, t.sink)
|
result = considerAsgnOrSink(c, t, body, x, y, t.asink)
|
||||||
of attachedDeepCopy:
|
of attachedDeepCopy:
|
||||||
let op = t.deepCopy
|
let op = t.attachedOps[attachedDeepCopy]
|
||||||
if op != nil:
|
if op != nil:
|
||||||
markUsed(c.graph.config, c.info, op, c.graph.usageSym)
|
markUsed(c.graph.config, c.info, op, c.graph.usageSym)
|
||||||
onUse(c.info, op)
|
onUse(c.info, op)
|
||||||
|
|
@ -323,8 +323,8 @@ proc useSeqOrStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
body.add moveCall
|
body.add moveCall
|
||||||
# alternatively we could do this:
|
# alternatively we could do this:
|
||||||
when false:
|
when false:
|
||||||
doAssert t.sink != nil
|
doAssert t.asink != nil
|
||||||
body.add newAsgnCall(c.graph, t.sink, x, y)
|
body.add newAsgnCall(c.graph, t.asink, x, y)
|
||||||
of attachedDestructor:
|
of attachedDestructor:
|
||||||
doAssert t.destructor != nil
|
doAssert t.destructor != nil
|
||||||
body.add destructorCall(c.graph, t.destructor, x)
|
body.add destructorCall(c.graph, t.destructor, x)
|
||||||
|
|
@ -502,27 +502,10 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
proc produceSymDistinctType(c: PContext; typ: PType; kind: TTypeAttachedOp; info: TLineInfo): PSym =
|
proc produceSymDistinctType(c: PContext; typ: PType; kind: TTypeAttachedOp; info: TLineInfo): PSym =
|
||||||
assert typ.kind == tyDistinct
|
assert typ.kind == tyDistinct
|
||||||
let baseType = typ[0]
|
let baseType = typ[0]
|
||||||
case kind
|
if baseType.attachedOps[kind] == nil:
|
||||||
of attachedAsgn:
|
discard produceSym(c, baseType, kind, info)
|
||||||
if baseType.assignment == nil:
|
typ.attachedOps[kind] = baseType.attachedOps[kind]
|
||||||
discard produceSym(c, baseType, kind, info)
|
result = typ.attachedOps[kind]
|
||||||
typ.assignment = baseType.assignment
|
|
||||||
result = typ.assignment
|
|
||||||
of attachedSink:
|
|
||||||
if baseType.sink == nil:
|
|
||||||
discard produceSym(c, baseType, kind, info)
|
|
||||||
typ.sink = baseType.sink
|
|
||||||
result = typ.sink
|
|
||||||
of attachedDeepCopy:
|
|
||||||
if baseType.deepCopy == nil:
|
|
||||||
discard produceSym(c, baseType, kind, info)
|
|
||||||
typ.deepCopy = baseType.deepCopy
|
|
||||||
result = typ.deepCopy
|
|
||||||
of attachedDestructor:
|
|
||||||
if baseType.destructor == nil:
|
|
||||||
discard produceSym(c, baseType, kind, info)
|
|
||||||
typ.destructor = baseType.destructor
|
|
||||||
result = typ.destructor
|
|
||||||
|
|
||||||
proc produceSym(c: PContext; typ: PType; kind: TTypeAttachedOp;
|
proc produceSym(c: PContext; typ: PType; kind: TTypeAttachedOp;
|
||||||
info: TLineInfo): PSym =
|
info: TLineInfo): PSym =
|
||||||
|
|
@ -536,11 +519,7 @@ proc produceSym(c: PContext; typ: PType; kind: TTypeAttachedOp;
|
||||||
a.c = c
|
a.c = c
|
||||||
let g = c.graph
|
let g = c.graph
|
||||||
let body = newNodeI(nkStmtList, info)
|
let body = newNodeI(nkStmtList, info)
|
||||||
let procname = case kind
|
let procname = getIdent(g.cache, AttachedOpToStr[kind])
|
||||||
of attachedAsgn: getIdent(g.cache, "=")
|
|
||||||
of attachedSink: getIdent(g.cache, "=sink")
|
|
||||||
of attachedDeepCopy: getIdent(g.cache, "=deepcopy")
|
|
||||||
of attachedDestructor: getIdent(g.cache, "=destroy")
|
|
||||||
|
|
||||||
result = newSym(skProc, procname, typ.owner, info)
|
result = newSym(skProc, procname, typ.owner, info)
|
||||||
a.fn = result
|
a.fn = result
|
||||||
|
|
@ -557,11 +536,7 @@ proc produceSym(c: PContext; typ: PType; kind: TTypeAttachedOp;
|
||||||
result.typ.addParam src
|
result.typ.addParam src
|
||||||
|
|
||||||
# register this operation already:
|
# register this operation already:
|
||||||
case kind
|
typ.attachedOps[kind] = result
|
||||||
of attachedAsgn: typ.assignment = result
|
|
||||||
of attachedSink: typ.sink = result
|
|
||||||
of attachedDeepCopy: typ.deepCopy = result
|
|
||||||
of attachedDestructor: typ.destructor = result
|
|
||||||
|
|
||||||
var tk: TTypeKind
|
var tk: TTypeKind
|
||||||
if optNimV2 in c.graph.config.globalOptions:
|
if optNimV2 in c.graph.config.globalOptions:
|
||||||
|
|
@ -636,23 +611,15 @@ proc createTypeBoundOps(c: PContext; orig: PType; info: TLineInfo) =
|
||||||
# 5. We have a (custom) generic destructor.
|
# 5. We have a (custom) generic destructor.
|
||||||
let typ = canon.skipTypes({tyGenericInst, tyAlias})
|
let typ = canon.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:
|
||||||
if typ.destructor == nil:
|
for k in attachedDestructor..attachedSink:
|
||||||
discard produceSym(c, typ, attachedDestructor, info)
|
if typ.attachedOps[k] == nil:
|
||||||
else:
|
discard produceSym(c, typ, k, info)
|
||||||
inst(typ.destructor, typ)
|
else:
|
||||||
if typ.assignment == nil:
|
inst(typ.attachedOps[k], typ)
|
||||||
discard produceSym(c, typ, attachedAsgn, info)
|
|
||||||
else:
|
|
||||||
inst(typ.assignment, typ)
|
|
||||||
if typ.sink == nil:
|
|
||||||
discard produceSym(c, typ, attachedSink, info)
|
|
||||||
else:
|
|
||||||
inst(typ.sink, typ)
|
|
||||||
|
|
||||||
if overwrite:
|
if overwrite:
|
||||||
orig.destructor = typ.destructor
|
for k in attachedDestructor..attachedSink:
|
||||||
orig.assignment = typ.assignment
|
orig.attachedOps[k] = typ.attachedOps[k]
|
||||||
orig.sink = typ.sink
|
|
||||||
|
|
||||||
if not isTrival(orig.destructor):
|
if not isTrival(orig.destructor):
|
||||||
#or not isTrival(orig.assignment) or
|
#or not isTrival(orig.assignment) or
|
||||||
|
|
|
||||||
|
|
@ -72,12 +72,6 @@ type
|
||||||
|
|
||||||
TExprFlags* = set[TExprFlag]
|
TExprFlags* = set[TExprFlag]
|
||||||
|
|
||||||
TTypeAttachedOp* = enum
|
|
||||||
attachedAsgn,
|
|
||||||
attachedSink,
|
|
||||||
attachedDeepCopy,
|
|
||||||
attachedDestructor
|
|
||||||
|
|
||||||
PContext* = ref TContext
|
PContext* = ref TContext
|
||||||
TContext* = object of TPassContext # a context represents a module
|
TContext* = object of TPassContext # a context represents a module
|
||||||
enforceVoidContext*: PType
|
enforceVoidContext*: PType
|
||||||
|
|
|
||||||
|
|
@ -1568,7 +1568,7 @@ proc semOverride(c: PContext, s: PSym, n: PNode) =
|
||||||
if obj.kind in {tyObject, tyDistinct, tySequence, tyString}:
|
if obj.kind in {tyObject, tyDistinct, tySequence, tyString}:
|
||||||
obj = canonType(c, obj)
|
obj = canonType(c, obj)
|
||||||
if obj.destructor.isNil:
|
if obj.destructor.isNil:
|
||||||
obj.destructor = s
|
obj.attachedOps[attachedDestructor] = s
|
||||||
else:
|
else:
|
||||||
prevDestructor(c, obj.destructor, obj, n.info)
|
prevDestructor(c, obj.destructor, obj, n.info)
|
||||||
noError = true
|
noError = true
|
||||||
|
|
@ -1592,7 +1592,7 @@ proc semOverride(c: PContext, s: PSym, n: PNode) =
|
||||||
elif t.kind == tyGenericInvocation: t = t.sons[0]
|
elif t.kind == tyGenericInvocation: t = t.sons[0]
|
||||||
else: break
|
else: break
|
||||||
if t.kind in {tyObject, tyDistinct, tyEnum, tySequence, tyString}:
|
if t.kind in {tyObject, tyDistinct, tyEnum, tySequence, tyString}:
|
||||||
if t.deepCopy.isNil: t.deepCopy = s
|
if t.attachedOps[attachedDeepCopy].isNil: t.attachedOps[attachedDeepCopy] = s
|
||||||
else:
|
else:
|
||||||
localError(c.config, n.info, errGenerated,
|
localError(c.config, n.info, errGenerated,
|
||||||
"cannot bind another 'deepCopy' to: " & typeToString(t))
|
"cannot bind another 'deepCopy' to: " & typeToString(t))
|
||||||
|
|
@ -1631,11 +1631,11 @@ proc semOverride(c: PContext, s: PSym, n: PNode) =
|
||||||
# attach these ops to the canonical tySequence
|
# attach these ops to the canonical tySequence
|
||||||
obj = canonType(c, obj)
|
obj = canonType(c, obj)
|
||||||
#echo "ATTACHING TO ", obj.id, " ", s.name.s, " ", cast[int](obj)
|
#echo "ATTACHING TO ", obj.id, " ", s.name.s, " ", cast[int](obj)
|
||||||
let opr = if s.name.s == "=": addr(obj.assignment) else: addr(obj.sink)
|
let k = if name == "=": attachedAsgn else: attachedSink
|
||||||
if opr[].isNil:
|
if obj.attachedOps[k].isNil:
|
||||||
opr[] = s
|
obj.attachedOps[k] = s
|
||||||
else:
|
else:
|
||||||
prevDestructor(c, opr[], obj, n.info)
|
prevDestructor(c, obj.attachedOps[k], obj, n.info)
|
||||||
if obj.owner.getModule != s.getModule:
|
if obj.owner.getModule != s.getModule:
|
||||||
localError(c.config, n.info, errGenerated,
|
localError(c.config, n.info, errGenerated,
|
||||||
"type bound operation `" & name & "` can be defined only in the same module with its type (" & obj.typeToString() & ")")
|
"type bound operation `" & name & "` can be defined only in the same module with its type (" & obj.typeToString() & ")")
|
||||||
|
|
@ -1828,7 +1828,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||||
|
|
||||||
if sfOverriden in s.flags or s.name.s[0] == '=': semOverride(c, s, n)
|
if sfOverriden in s.flags or s.name.s[0] == '=': semOverride(c, s, n)
|
||||||
if s.name.s[0] in {'.', '('}:
|
if s.name.s[0] in {'.', '('}:
|
||||||
if s.name.s in [".", ".()", ".="] and {destructor, dotOperators} * c.features == {}:
|
if s.name.s in [".", ".()", ".="] and {Feature.destructor, dotOperators} * c.features == {}:
|
||||||
localError(c.config, n.info, "the overloaded " & s.name.s &
|
localError(c.config, n.info, "the overloaded " & s.name.s &
|
||||||
" operator has to be enabled with {.experimental: \"dotOperators\".}")
|
" operator has to be enabled with {.experimental: \"dotOperators\".}")
|
||||||
elif s.name.s == "()" and callOperator notin c.features:
|
elif s.name.s == "()" and callOperator notin c.features:
|
||||||
|
|
|
||||||
|
|
@ -380,13 +380,13 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType =
|
||||||
if newbody.isGenericAlias: newbody = newbody.skipGenericAlias
|
if newbody.isGenericAlias: newbody = newbody.skipGenericAlias
|
||||||
rawAddSon(result, newbody)
|
rawAddSon(result, newbody)
|
||||||
checkPartialConstructedType(cl.c.config, cl.info, newbody)
|
checkPartialConstructedType(cl.c.config, cl.info, newbody)
|
||||||
let dc = newbody.deepCopy
|
let dc = newbody.attachedOps[attachedDeepCopy]
|
||||||
if not cl.allowMetaTypes:
|
if not cl.allowMetaTypes:
|
||||||
if dc != nil and sfFromGeneric notin newbody.deepCopy.flags:
|
if dc != nil and sfFromGeneric notin newbody.attachedOps[attachedDeepCopy].flags:
|
||||||
# 'deepCopy' needs to be instantiated for
|
# 'deepCopy' needs to be instantiated for
|
||||||
# generics *when the type is constructed*:
|
# generics *when the type is constructed*:
|
||||||
newbody.deepCopy = cl.c.instTypeBoundOp(cl.c, dc, result, cl.info,
|
newbody.attachedOps[attachedDeepCopy] = cl.c.instTypeBoundOp(cl.c, dc, result, cl.info,
|
||||||
attachedDeepCopy, 1)
|
attachedDeepCopy, 1)
|
||||||
if bodyIsNew and newbody.typeInst == nil:
|
if bodyIsNew and newbody.typeInst == nil:
|
||||||
#doassert newbody.typeInst == nil
|
#doassert newbody.typeInst == nil
|
||||||
newbody.typeInst = result
|
newbody.typeInst = result
|
||||||
|
|
@ -592,7 +592,8 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
|
||||||
skipIntLiteralParams(result)
|
skipIntLiteralParams(result)
|
||||||
|
|
||||||
of tySequence:
|
of tySequence:
|
||||||
if cl.isReturnType and cl.c.config.selectedGc == gcDestructors and result.destructor.isNil and
|
if cl.isReturnType and cl.c.config.selectedGc == gcDestructors and
|
||||||
|
result.attachedOps[attachedDestructor].isNil and
|
||||||
result[0].kind != tyEmpty and optNimV2 notin cl.c.config.globalOptions:
|
result[0].kind != tyEmpty and optNimV2 notin cl.c.config.globalOptions:
|
||||||
let s = cl.c.graph.sysTypes[tySequence]
|
let s = cl.c.graph.sysTypes[tySequence]
|
||||||
var old = copyType(s, s.owner, keepId=false)
|
var old = copyType(s, s.owner, keepId=false)
|
||||||
|
|
@ -601,9 +602,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
|
||||||
old.n = nil
|
old.n = nil
|
||||||
old.flags = {tfHasAsgn}
|
old.flags = {tfHasAsgn}
|
||||||
old.addSonSkipIntLit result[0]
|
old.addSonSkipIntLit result[0]
|
||||||
result.destructor = old.destructor
|
result.attachedOps = old.attachedOps
|
||||||
result.assignment = old.assignment
|
|
||||||
result.sink = old.sink
|
|
||||||
cl.c.typesWithOps.add((result, old))
|
cl.c.typesWithOps.add((result, old))
|
||||||
|
|
||||||
else: discard
|
else: discard
|
||||||
|
|
@ -619,19 +618,19 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
|
||||||
result.n = replaceObjBranches(cl, result.n)
|
result.n = replaceObjBranches(cl, result.n)
|
||||||
|
|
||||||
template typeBound(c, newty, oldty, field, info) =
|
template typeBound(c, newty, oldty, field, info) =
|
||||||
let opr = newty.field
|
let opr = newty.attachedOps[field]
|
||||||
if opr != nil and sfFromGeneric notin opr.flags:
|
if opr != nil and sfFromGeneric notin opr.flags:
|
||||||
# '=' needs to be instantiated for generics when the type is constructed:
|
# '=' needs to be instantiated for generics when the type is constructed:
|
||||||
#echo "DESTROY: instantiating ", astToStr(field), " for ", typeToString(oldty)
|
#echo "DESTROY: instantiating ", astToStr(field), " for ", typeToString(oldty)
|
||||||
newty.field = c.instTypeBoundOp(c, opr, oldty, info, attachedAsgn, 1)
|
newty.attachedOps[field] = c.instTypeBoundOp(c, opr, oldty, info, attachedAsgn, 1)
|
||||||
|
|
||||||
proc instAllTypeBoundOp*(c: PContext, info: TLineInfo) =
|
proc instAllTypeBoundOp*(c: PContext, info: TLineInfo) =
|
||||||
var i = 0
|
var i = 0
|
||||||
while i < c.typesWithOps.len:
|
while i < c.typesWithOps.len:
|
||||||
let (newty, oldty) = c.typesWithOps[i]
|
let (newty, oldty) = c.typesWithOps[i]
|
||||||
typeBound(c, newty, oldty, destructor, info)
|
typeBound(c, newty, oldty, attachedDestructor, info)
|
||||||
typeBound(c, newty, oldty, sink, info)
|
typeBound(c, newty, oldty, attachedSink, info)
|
||||||
typeBound(c, newty, oldty, assignment, info)
|
typeBound(c, newty, oldty, attachedAsgn, info)
|
||||||
inc i
|
inc i
|
||||||
setLen(c.typesWithOps, 0)
|
setLen(c.typesWithOps, 0)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue