make twidgets example green (#11135)

This commit is contained in:
Andreas Rumpf 2019-04-28 13:28:18 +02:00 • committed by GitHub
commit 55aa2129b5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 57 additions and 38 deletions

View file

@ -633,13 +633,19 @@ proc instrTargets*(ins: Instr; loc: PNode): bool =
# use x; question does it affect 'x.f'? Yes. # use x; question does it affect 'x.f'? Yes.
result = aliases(ins.n, loc) or aliases(loc, ins.n) result = aliases(ins.n, loc) or aliases(loc, ins.n)
proc isAnalysableFieldAccess*(n: PNode; owner: PSym): bool = proc isAnalysableFieldAccess*(orig: PNode; owner: PSym): bool =
var n = n var n = orig
while true: while true:
case n.kind case n.kind
of nkDotExpr, nkCheckedFieldExpr, nkHiddenSubConv, nkHiddenStdConv, of nkDotExpr, nkCheckedFieldExpr, nkHiddenSubConv, nkHiddenStdConv,
nkObjDownConv, nkObjUpConv, nkHiddenDeref: nkObjDownConv, nkObjUpConv:
n = n[0] n = n[0]
of nkHiddenDeref, nkDerefExpr:
# We "own" sinkparam[].loc but not ourVar[].location as it is a nasty
# pointer indirection.
n = n[0]
return n.kind == nkSym and n.sym.owner == owner and (isSinkParam(n.sym) or
n.sym.typ.skipTypes(abstractInst-{tyOwned}).kind in {tyOwned, tyVar})
of nkBracketExpr: of nkBracketExpr:
let x = n[0] let x = n[0]
if x.typ != nil and x.typ.skipTypes(abstractInst).kind == tyTuple: if x.typ != nil and x.typ.skipTypes(abstractInst).kind == tyTuple:

View file

@ -316,6 +316,10 @@ proc makePtrType(c: Con, baseType: PType): PType =
result = newType(tyPtr, c.owner) result = newType(tyPtr, c.owner)
addSonSkipIntLit(result, baseType) addSonSkipIntLit(result, baseType)
proc addDestroy(c: var Con; n: PNode) =
# append to front:
c.destroys = newTree(nkStmtList, n, c.destroys)
proc genOp(c: Con; t: PType; kind: TTypeAttachedOp; dest, ri: PNode): PNode = proc genOp(c: Con; t: PType; kind: TTypeAttachedOp; dest, ri: PNode): PNode =
var op = t.attachedOps[kind] var op = t.attachedOps[kind]
@ -731,7 +735,7 @@ proc p(n: PNode; c: var Con): PNode =
c.addTopVar v c.addTopVar v
# make sure it's destroyed at the end of the proc: # make sure it's destroyed at the end of the proc:
if not isUnpackedTuple(it[0].sym): if not isUnpackedTuple(it[0].sym):
c.destroys.add genDestroy(c, v.typ, v) c.addDestroy genDestroy(c, v.typ, v)
if ri.kind != nkEmpty: if ri.kind != nkEmpty:
let r = moveOrCopy(v, ri, c) let r = moveOrCopy(v, ri, c)
result.add r result.add r
@ -750,7 +754,7 @@ proc p(n: PNode; c: var Con): PNode =
sinkExpr.add n sinkExpr.add n
result.add sinkExpr result.add sinkExpr
result.add tmp result.add tmp
c.destroys.add genDestroy(c, n.typ, tmp) c.addDestroy genDestroy(c, n.typ, tmp)
else: else:
result = n result = n
of nkAsgn, nkFastAsgn: of nkAsgn, nkFastAsgn:
@ -814,7 +818,7 @@ proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode =
for i in 1 ..< params.len: for i in 1 ..< params.len:
let param = params[i].sym let param = params[i].sym
if isSinkParam(param) and hasDestructor(param.typ.skipTypes({tySink})): if isSinkParam(param) and hasDestructor(param.typ.skipTypes({tySink})):
c.destroys.add genDestroy(c, param.typ.skipTypes({tyGenericInst, tyAlias, tySink}), params[i]) c.addDestroy genDestroy(c, param.typ.skipTypes({tyGenericInst, tyAlias, tySink}), params[i])
#if optNimV2 in c.graph.config.globalOptions: #if optNimV2 in c.graph.config.globalOptions:
# injectDefaultCalls(n, c) # injectDefaultCalls(n, c)

View file

@ -261,7 +261,7 @@ proc liftIterSym*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
proc freshVarForClosureIter*(g: ModuleGraph; s, owner: PSym): PNode = proc freshVarForClosureIter*(g: ModuleGraph; s, owner: PSym): PNode =
let envParam = getHiddenParam(g, owner) let envParam = getHiddenParam(g, owner)
let obj = envParam.typ.lastSon let obj = envParam.typ.skipTypes({tyOwned, tyRef})
addField(obj, s, g.cache) addField(obj, s, g.cache)
var access = newSymNode(envParam) var access = newSymNode(envParam)
@ -320,15 +320,23 @@ proc getEnvTypeForOwner(c: var DetectionPass; owner: PSym;
rawAddSon(result, obj) rawAddSon(result, obj)
c.ownerToType[owner.id] = result c.ownerToType[owner.id] = result
proc asOwnedRef(c: DetectionPass; t: PType): PType =
if optNimV2 in c.graph.config.globalOptions:
assert t.kind == tyRef
result = newType(tyOwned, t.owner)
result.rawAddSon t
else:
result = t
proc getEnvTypeForOwnerUp(c: var DetectionPass; owner: PSym; proc getEnvTypeForOwnerUp(c: var DetectionPass; owner: PSym;
info: TLineInfo): PType = info: TLineInfo): PType =
var r = c.getEnvTypeForOwner(owner, info) var r = c.getEnvTypeForOwner(owner, info)
result = newType(tyPtr, owner) result = newType(tyPtr, owner)
rawAddSon(result, r.base) rawAddSon(result, r.skipTypes({tyOwned, tyRef}))
proc createUpField(c: var DetectionPass; dest, dep: PSym; info: TLineInfo) = proc createUpField(c: var DetectionPass; dest, dep: PSym; info: TLineInfo) =
let refObj = c.getEnvTypeForOwner(dest, info) # getHiddenParam(dest).typ let refObj = c.getEnvTypeForOwner(dest, info) # getHiddenParam(dest).typ
let obj = refObj.lastSon let obj = refObj.skipTypes({tyOwned, tyRef})
# The assumption here is that gcDestructors means we cannot deal # The assumption here is that gcDestructors means we cannot deal
# with cycles properly, so it's better to produce a weak ref (=ptr) here. # with cycles properly, so it's better to produce a weak ref (=ptr) here.
# This seems to be generally correct but since it's a bit risky it's only # This seems to be generally correct but since it's a bit risky it's only
@ -343,7 +351,7 @@ proc createUpField(c: var DetectionPass; dest, dep: PSym; info: TLineInfo) =
let upIdent = getIdent(c.graph.cache, upName) let upIdent = getIdent(c.graph.cache, upName)
let upField = lookupInRecord(obj.n, upIdent) let upField = lookupInRecord(obj.n, upIdent)
if upField != nil: if upField != nil:
if upField.typ.base != fieldType.base: if upField.typ.skipTypes({tyOwned, tyRef}) != fieldType.skipTypes({tyOwned, tyRef}):
localError(c.graph.config, dep.info, "internal error: up references do not agree") localError(c.graph.config, dep.info, "internal error: up references do not agree")
else: else:
let result = newSym(skField, upIdent, obj.owner, obj.owner.info) let result = newSym(skField, upIdent, obj.owner, obj.owner.info)
@ -414,8 +422,8 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
addClosureParam(c, owner, n.info) addClosureParam(c, owner, n.info)
if interestingIterVar(s): if interestingIterVar(s):
if not c.capturedVars.containsOrIncl(s.id): if not c.capturedVars.containsOrIncl(s.id):
let obj = getHiddenParam(c.graph, owner).typ.lastSon let obj = getHiddenParam(c.graph, owner).typ.skipTypes({tyOwned, tyRef})
#let obj = c.getEnvTypeForOwner(s.owner).lastSon #let obj = c.getEnvTypeForOwner(s.owner).skipTypes({tyOwned, tyRef})
if s.name.id == getIdent(c.graph.cache, ":state").id: if s.name.id == getIdent(c.graph.cache, ":state").id:
obj.n[0].sym.id = -s.id obj.n[0].sym.id = -s.id
@ -440,8 +448,8 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
#echo "capturing ", n.info #echo "capturing ", n.info
# variable 's' is actually captured: # variable 's' is actually captured:
if interestingVar(s) and not c.capturedVars.containsOrIncl(s.id): if interestingVar(s) and not c.capturedVars.containsOrIncl(s.id):
let obj = c.getEnvTypeForOwner(ow, n.info).lastSon let obj = c.getEnvTypeForOwner(ow, n.info).skipTypes({tyOwned, tyRef})
#getHiddenParam(owner).typ.lastSon #getHiddenParam(owner).typ.skipTypes({tyOwned, tyRef})
addField(obj, s, c.graph.cache) addField(obj, s, c.graph.cache)
# create required upFields: # create required upFields:
var w = owner.skipGenericOwner var w = owner.skipGenericOwner
@ -530,14 +538,14 @@ proc setupEnvVar(owner: PSym; d: DetectionPass;
let envVarType = d.ownerToType.getOrDefault(owner.id) let envVarType = d.ownerToType.getOrDefault(owner.id)
if envVarType.isNil: if envVarType.isNil:
localError d.graph.config, owner.info, "internal error: could not determine closure type" localError d.graph.config, owner.info, "internal error: could not determine closure type"
result = newEnvVar(d.graph.cache, owner, envVarType) result = newEnvVar(d.graph.cache, owner, asOwnedRef(d, envVarType))
c.envVars[owner.id] = result c.envVars[owner.id] = result
proc getUpViaParam(g: ModuleGraph; owner: PSym): PNode = proc getUpViaParam(g: ModuleGraph; owner: PSym): PNode =
let p = getHiddenParam(g, owner) let p = getHiddenParam(g, owner)
result = p.newSymNode result = p.newSymNode
if owner.isIterator: if owner.isIterator:
let upField = lookupInRecord(p.typ.lastSon.n, getIdent(g.cache, upName)) let upField = lookupInRecord(p.typ.skipTypes({tyOwned, tyRef}).n, getIdent(g.cache, upName))
if upField == nil: if upField == nil:
localError(g.config, owner.info, "could not find up reference for closure iter") localError(g.config, owner.info, "could not find up reference for closure iter")
else: else:
@ -566,10 +574,10 @@ proc rawClosureCreation(owner: PSym;
# add ``env.param = param`` # add ``env.param = param``
result.add(newAsgnStmt(fieldAccess, newSymNode(local), env.info)) result.add(newAsgnStmt(fieldAccess, newSymNode(local), env.info))
let upField = lookupInRecord(env.typ.lastSon.n, getIdent(d.graph.cache, upName)) let upField = lookupInRecord(env.typ.skipTypes({tyOwned, tyRef}).n, getIdent(d.graph.cache, upName))
if upField != nil: if upField != nil:
let up = getUpViaParam(d.graph, owner) let up = getUpViaParam(d.graph, owner)
if up != nil and upField.typ.base == up.typ.base: if up != nil and upField.typ.skipTypes({tyOwned, tyRef}) == up.typ.skipTypes({tyOwned, tyRef}):
result.add(newAsgnStmt(rawIndirectAccess(env, upField, env.info), result.add(newAsgnStmt(rawIndirectAccess(env, upField, env.info),
up, env.info)) up, env.info))
#elif oldenv != nil and oldenv.typ == upField.typ: #elif oldenv != nil and oldenv.typ == upField.typ:
@ -584,11 +592,11 @@ proc closureCreationForIter(iter: PNode;
let owner = iter.sym.skipGenericOwner let owner = iter.sym.skipGenericOwner
var v = newSym(skVar, getIdent(d.graph.cache, envName), owner, iter.info) var v = newSym(skVar, getIdent(d.graph.cache, envName), owner, iter.info)
incl(v.flags, sfShadowed) incl(v.flags, sfShadowed)
v.typ = getHiddenParam(d.graph, iter.sym).typ v.typ = asOwnedRef(d, getHiddenParam(d.graph, iter.sym).typ)
var vnode: PNode var vnode: PNode
if owner.isIterator: if owner.isIterator:
let it = getHiddenParam(d.graph, owner) let it = getHiddenParam(d.graph, owner)
addUniqueField(it.typ.sons[0], v, d.graph.cache) addUniqueField(it.typ.skipTypes({tyOwned, tyRef}), v, d.graph.cache)
vnode = indirectAccess(newSymNode(it), v, v.info) vnode = indirectAccess(newSymNode(it), v, v.info)
else: else:
vnode = v.newSymNode vnode = v.newSymNode
@ -597,10 +605,10 @@ proc closureCreationForIter(iter: PNode;
result.add(vs) result.add(vs)
result.add(newCall(getSysSym(d.graph, iter.info, "internalNew"), vnode)) result.add(newCall(getSysSym(d.graph, iter.info, "internalNew"), vnode))
let upField = lookupInRecord(v.typ.lastSon.n, getIdent(d.graph.cache, upName)) let upField = lookupInRecord(v.typ.skipTypes({tyOwned, tyRef}).n, getIdent(d.graph.cache, upName))
if upField != nil: if upField != nil:
let u = setupEnvVar(owner, d, c) let u = setupEnvVar(owner, d, c)
if u.typ.base == upField.typ.base: if u.typ.skipTypes({tyOwned, tyRef}) == upField.typ.skipTypes({tyOwned, tyRef}):
result.add(newAsgnStmt(rawIndirectAccess(vnode, upField, iter.info), result.add(newAsgnStmt(rawIndirectAccess(vnode, upField, iter.info),
u, iter.info)) u, iter.info))
else: else:
@ -610,7 +618,7 @@ proc closureCreationForIter(iter: PNode;
proc accessViaEnvVar(n: PNode; owner: PSym; d: DetectionPass; proc accessViaEnvVar(n: PNode; owner: PSym; d: DetectionPass;
c: var LiftingPass): PNode = c: var LiftingPass): PNode =
let access = setupEnvVar(owner, d, c) let access = setupEnvVar(owner, d, c)
let obj = access.typ.sons[0] let obj = access.typ.skipTypes({tyOwned, tyRef})
let field = getFieldFromObj(obj, n.sym) let field = getFieldFromObj(obj, n.sym)
if field != nil: if field != nil:
result = rawIndirectAccess(access, field, n.info) result = rawIndirectAccess(access, field, n.info)
@ -619,7 +627,7 @@ proc accessViaEnvVar(n: PNode; owner: PSym; d: DetectionPass;
result = n result = n
proc getStateField*(g: ModuleGraph; owner: PSym): PSym = proc getStateField*(g: ModuleGraph; owner: PSym): PSym =
getHiddenParam(g, owner).typ.sons[0].n.sons[0].sym getHiddenParam(g, owner).typ.skipTypes({tyOwned, tyRef}).n.sons[0].sym
proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass; proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass;
c: var LiftingPass): PNode c: var LiftingPass): PNode
@ -644,7 +652,7 @@ proc symToClosure(n: PNode; owner: PSym; d: DetectionPass;
while true: while true:
if access.typ == wanted: if access.typ == wanted:
return makeClosure(d.graph, s, access, n.info) return makeClosure(d.graph, s, access, n.info)
let obj = access.typ.sons[0] let obj = access.typ.skipTypes({tyOwned, tyRef})
let upField = lookupInRecord(obj.n, getIdent(d.graph.cache, upName)) let upField = lookupInRecord(obj.n, getIdent(d.graph.cache, upName))
if upField == nil: if upField == nil:
localError(d.graph.config, n.info, "internal error: no environment found") localError(d.graph.config, n.info, "internal error: no environment found")

View file

@ -7,8 +7,8 @@ mygeneric1 constructed
mygeneric1 destroyed mygeneric1 destroyed
---- ----
mygeneric2 constructed mygeneric2 constructed
myobj destroyed
mygeneric2 destroyed mygeneric2 destroyed
myobj destroyed
---- ----
mygeneric3 constructed mygeneric3 constructed
mygeneric1 destroyed mygeneric1 destroyed
@ -20,10 +20,10 @@ mygeneric2 destroyed
---- ----
---- ----
myobj destroyed myobj destroyed
myobj destroyed
myobj destroyed
myobj destroyed
mygeneric1 destroyed mygeneric1 destroyed
myobj destroyed
myobj destroyed
myobj destroyed
--- ---
myobj destroyed myobj destroyed
myobj destroyed myobj destroyed

View file

@ -4,8 +4,8 @@ destroy
destroy destroy
5 5
123 123
destroy Foo: 5 destroy Foo: 123
destroy Foo: 123''' destroy Foo: 5'''
joinable: false joinable: false
""" """

View file

@ -1,8 +1,8 @@
discard """ discard """
cmd: '''nim c --newruntime $file''' cmd: '''nim c --newruntime $file'''
output: '''button output: '''button
clicked!''' clicked!
disabled: "true" 1 1 alloc/dealloc pairs: 0'''
""" """
import core / allocators import core / allocators
@ -41,13 +41,14 @@ iterator unitems*[T](a: seq[owned T]): T {.inline.} =
assert(len(a) == L, "seq modified while iterating over it") assert(len(a) == L, "seq modified while iterating over it")
proc newWindow(): owned Window = proc newWindow(): owned Window =
proc draw(self: Widget) = proc windraw(self: Widget) =
let w = Window(self) let w = Window(self)
for e in unitems(w.elements): for i in 0..<len(w.elements):
let e = Widget(w.elements[i])
let d = (proc(self: Widget))e.drawImpl let d = (proc(self: Widget))e.drawImpl
if not d.isNil: d(e) if not d.isNil: d(e)
result = Window(drawImpl: draw, elements: @[]) result = Window(drawImpl: windraw, elements: @[])
proc draw(w: Widget) = proc draw(w: Widget) =
let d = (proc(self: Widget))w.drawImpl let d = (proc(self: Widget))w.drawImpl
@ -60,14 +61,14 @@ proc main =
var w = newWindow() var w = newWindow()
var b = newButton("button", nil) var b = newButton("button", nil)
#let u: Button = b let u: Button = b
b.onclick = proc () = b.onclick = proc () =
b.caption = "clicked!" b.caption = "clicked!"
w.add b w.add b
w.draw() w.draw()
# simulate button click: # simulate button click:
#u.onclick() u.onclick()
w.draw() w.draw()