make twidgets example green (#11135)
This commit is contained in:
parent
a432aedb54
commit
55aa2129b5
6 changed files with 57 additions and 38 deletions
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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")
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue