mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-19 22:10:33 +00:00
@@ -416,7 +416,6 @@ proc allRoots(n: PNode; result: var seq[(PSym, int)]; level: int) =
|
||||
proc destMightOwn(c: var Partitions; dest: var VarIndex; n: PNode) =
|
||||
## Analyse if 'n' is an expression that owns the data, if so mark 'dest'
|
||||
## with 'ownsData'.
|
||||
if n.typ == nil: return
|
||||
case n.kind
|
||||
of nkEmpty, nkCharLit..nkNilLit:
|
||||
# primitive literals including the empty are harmless:
|
||||
@@ -475,30 +474,31 @@ proc destMightOwn(c: var Partitions; dest: var VarIndex; n: PNode) =
|
||||
destMightOwn(c, dest, n[0])
|
||||
|
||||
of nkCallKinds:
|
||||
if hasDestructor(n.typ):
|
||||
# calls do construct, what we construct must be destroyed,
|
||||
# so dest cannot be a cursor:
|
||||
dest.flags.incl ownsData
|
||||
elif n.typ.kind in {tyLent, tyVar}:
|
||||
# we know the result is derived from the first argument:
|
||||
var roots: seq[(PSym, int)]
|
||||
allRoots(n[1], roots, RootEscapes)
|
||||
for r in roots:
|
||||
connect(c, dest.sym, r[0], n[1].info)
|
||||
if n.typ != nil:
|
||||
if hasDestructor(n.typ):
|
||||
# calls do construct, what we construct must be destroyed,
|
||||
# so dest cannot be a cursor:
|
||||
dest.flags.incl ownsData
|
||||
elif n.typ.kind in {tyLent, tyVar}:
|
||||
# we know the result is derived from the first argument:
|
||||
var roots: seq[(PSym, int)]
|
||||
allRoots(n[1], roots, RootEscapes)
|
||||
for r in roots:
|
||||
connect(c, dest.sym, r[0], n[1].info)
|
||||
|
||||
else:
|
||||
let magic = if n[0].kind == nkSym: n[0].sym.magic else: mNone
|
||||
# this list is subtle, we try to answer the question if after 'dest = f(src)'
|
||||
# there is a connection betwen 'src' and 'dest' so that mutations to 'src'
|
||||
# also reflect 'dest':
|
||||
if magic in {mNone, mMove, mSlice, mAppendStrCh, mAppendStrStr, mAppendSeqElem, mArrToSeq}:
|
||||
for i in 1..<n.len:
|
||||
# we always have to assume a 'select(...)' like mechanism.
|
||||
# But at least we do filter out simple POD types from the
|
||||
# list of dependencies via the 'hasDestructor' check for
|
||||
# the root's symbol.
|
||||
if hasDestructor(n[i].typ.skipTypes({tyVar, tySink, tyLent, tyGenericInst, tyAlias})):
|
||||
destMightOwn(c, dest, n[i])
|
||||
else:
|
||||
let magic = if n[0].kind == nkSym: n[0].sym.magic else: mNone
|
||||
# this list is subtle, we try to answer the question if after 'dest = f(src)'
|
||||
# there is a connection betwen 'src' and 'dest' so that mutations to 'src'
|
||||
# also reflect 'dest':
|
||||
if magic in {mNone, mMove, mSlice, mAppendStrCh, mAppendStrStr, mAppendSeqElem, mArrToSeq}:
|
||||
for i in 1..<n.len:
|
||||
# we always have to assume a 'select(...)' like mechanism.
|
||||
# But at least we do filter out simple POD types from the
|
||||
# list of dependencies via the 'hasDestructor' check for
|
||||
# the root's symbol.
|
||||
if hasDestructor(n[i].typ.skipTypes({tyVar, tySink, tyLent, tyGenericInst, tyAlias})):
|
||||
destMightOwn(c, dest, n[i])
|
||||
|
||||
else:
|
||||
# something we cannot handle:
|
||||
|
||||
@@ -8,7 +8,7 @@ doing shady stuff...
|
||||
192.168.0.1
|
||||
192.168.0.1
|
||||
192.168.0.1'''
|
||||
cmd: '''nim c --gc:arc --expandArc:newTarget --expandArc:delete --expandArc:p1 --expandArc:tt --hint:Performance:off --assertions:off --expandArc:extractConfig --expandArc:mergeShadowScope $file'''
|
||||
cmd: '''nim c --gc:arc --expandArc:newTarget --expandArc:delete --expandArc:p1 --expandArc:tt --hint:Performance:off --assertions:off --expandArc:extractConfig --expandArc:mergeShadowScope --expandArc:check $file'''
|
||||
nimout: '''--expandArc: newTarget
|
||||
|
||||
var
|
||||
@@ -127,6 +127,36 @@ block :tmp:
|
||||
:tmpD
|
||||
inc(i, 1)
|
||||
`=destroy`(shadowScope)
|
||||
-- end of expandArc ------------------------
|
||||
--expandArc: check
|
||||
|
||||
var par
|
||||
this.isValid = fileExists(this.value)
|
||||
if dirExists(this.value):
|
||||
var :tmpD
|
||||
par = (dir:
|
||||
wasMoved(:tmpD)
|
||||
`=copy`(:tmpD, this.value)
|
||||
:tmpD, front: "") else:
|
||||
var
|
||||
:tmpD_1
|
||||
:tmpD_2
|
||||
:tmpD_3
|
||||
par = (dir_1: parentDir(this.value), front_1:
|
||||
wasMoved(:tmpD_1)
|
||||
`=copy`(:tmpD_1,
|
||||
:tmpD_3 = splitPath do:
|
||||
wasMoved(:tmpD_2)
|
||||
`=copy`(:tmpD_2, this.value)
|
||||
:tmpD_2
|
||||
:tmpD_3.tail)
|
||||
:tmpD_1)
|
||||
`=destroy`(:tmpD_3)
|
||||
if dirExists(par.dir):
|
||||
`=sink`(this.matchDirs, getSubDirs(par.dir, par.front))
|
||||
else:
|
||||
`=sink`(this.matchDirs, [])
|
||||
`=destroy`(par)
|
||||
-- end of expandArc ------------------------'''
|
||||
"""
|
||||
|
||||
@@ -322,3 +352,22 @@ proc mergeShadowScope*(c: PContext) =
|
||||
c.addInterfaceDecl(sym)
|
||||
|
||||
mergeShadowScope(PContext(currentScope: Scope(parent: Scope())))
|
||||
|
||||
type
|
||||
Foo = ref object
|
||||
isValid*: bool
|
||||
value*: string
|
||||
matchDirs*: seq[string]
|
||||
|
||||
proc getSubDirs(parent, front: string): seq[string] = @[]
|
||||
|
||||
method check(this: Foo) {.base.} =
|
||||
this.isValid = fileExists(this.value)
|
||||
let par = if dirExists(this.value): (dir: this.value, front: "")
|
||||
else: (dir: parentDir(this.value), front: splitPath(this.value).tail)
|
||||
if dirExists(par.dir):
|
||||
this.matchDirs = getSubDirs(par.dir, par.front)
|
||||
else:
|
||||
this.matchDirs = @[]
|
||||
|
||||
check(Foo())
|
||||
|
||||
Reference in New Issue
Block a user