* fixes #17033 [backport:1.4] * make test robust against stdlib gensym things * cleanup assertions.nim to make topt_no_cursor easier to get right
This commit is contained in:
parent
b9994925f5
commit
f32ffb6ed8
3 changed files with 105 additions and 9 deletions
|
|
@ -57,6 +57,7 @@ type
|
||||||
ownsData,
|
ownsData,
|
||||||
preventCursor,
|
preventCursor,
|
||||||
isReassigned,
|
isReassigned,
|
||||||
|
isConditionallyReassigned,
|
||||||
viewDoesMutate,
|
viewDoesMutate,
|
||||||
viewBorrowsFromConst
|
viewBorrowsFromConst
|
||||||
|
|
||||||
|
|
@ -98,6 +99,7 @@ type
|
||||||
goals: set[Goal]
|
goals: set[Goal]
|
||||||
unanalysableMutation: bool
|
unanalysableMutation: bool
|
||||||
inAsgnSource, inConstructor, inNoSideEffectSection: int
|
inAsgnSource, inConstructor, inNoSideEffectSection: int
|
||||||
|
inConditional, inLoop: int
|
||||||
owner: PSym
|
owner: PSym
|
||||||
g: ModuleGraph
|
g: ModuleGraph
|
||||||
|
|
||||||
|
|
@ -748,6 +750,13 @@ proc traverse(c: var Partitions; n: PNode) =
|
||||||
else:
|
else:
|
||||||
for child in n: traverse(c, child)
|
for child in n: traverse(c, child)
|
||||||
|
|
||||||
|
proc markAsReassigned(c: var Partitions; vid: int) {.inline.} =
|
||||||
|
c.s[vid].flags.incl isReassigned
|
||||||
|
if c.inConditional > 0 and c.inLoop > 0:
|
||||||
|
# bug #17033: live ranges with loops and conditionals are too
|
||||||
|
# complex for our current analysis, so we prevent the cursorfication.
|
||||||
|
c.s[vid].flags.incl isConditionallyReassigned
|
||||||
|
|
||||||
proc computeLiveRanges(c: var Partitions; n: PNode) =
|
proc computeLiveRanges(c: var Partitions; n: PNode) =
|
||||||
# first pass: Compute live ranges for locals.
|
# first pass: Compute live ranges for locals.
|
||||||
# **Watch out!** We must traverse the tree like 'traverse' does
|
# **Watch out!** We must traverse the tree like 'traverse' does
|
||||||
|
|
@ -777,7 +786,7 @@ proc computeLiveRanges(c: var Partitions; n: PNode) =
|
||||||
if n[1].kind == nkSym and (c.s[vid].reassignedTo == 0 or c.s[vid].reassignedTo == n[1].sym.id):
|
if n[1].kind == nkSym and (c.s[vid].reassignedTo == 0 or c.s[vid].reassignedTo == n[1].sym.id):
|
||||||
c.s[vid].reassignedTo = n[1].sym.id
|
c.s[vid].reassignedTo = n[1].sym.id
|
||||||
else:
|
else:
|
||||||
c.s[vid].flags.incl isReassigned
|
markAsReassigned(c, vid)
|
||||||
|
|
||||||
of nkSym:
|
of nkSym:
|
||||||
dec c.abstractTime
|
dec c.abstractTime
|
||||||
|
|
@ -804,7 +813,7 @@ proc computeLiveRanges(c: var Partitions; n: PNode) =
|
||||||
if not paramType.isCompileTimeOnly and paramType.kind == tyVar:
|
if not paramType.isCompileTimeOnly and paramType.kind == tyVar:
|
||||||
let vid = variableId(c, it.sym)
|
let vid = variableId(c, it.sym)
|
||||||
if vid >= 0:
|
if vid >= 0:
|
||||||
c.s[vid].flags.incl isReassigned
|
markAsReassigned(c, vid)
|
||||||
|
|
||||||
of nkAddr, nkHiddenAddr:
|
of nkAddr, nkHiddenAddr:
|
||||||
computeLiveRanges(c, n[0])
|
computeLiveRanges(c, n[0])
|
||||||
|
|
@ -822,7 +831,13 @@ proc computeLiveRanges(c: var Partitions; n: PNode) =
|
||||||
# while cond:
|
# while cond:
|
||||||
# mutate(graph)
|
# mutate(graph)
|
||||||
# connect(graph, cursorVar)
|
# connect(graph, cursorVar)
|
||||||
|
inc c.inLoop
|
||||||
for child in n: computeLiveRanges(c, child)
|
for child in n: computeLiveRanges(c, child)
|
||||||
|
inc c.inLoop
|
||||||
|
of nkElifBranch, nkElifExpr, nkElse, nkOfBranch:
|
||||||
|
inc c.inConditional
|
||||||
|
for child in n: computeLiveRanges(c, child)
|
||||||
|
dec c.inConditional
|
||||||
else:
|
else:
|
||||||
for child in n: computeLiveRanges(c, child)
|
for child in n: computeLiveRanges(c, child)
|
||||||
|
|
||||||
|
|
@ -896,7 +911,8 @@ proc computeCursors*(s: PSym; n: PNode; g: ModuleGraph) =
|
||||||
var par = computeGraphPartitions(s, n, g, {cursorInference})
|
var par = computeGraphPartitions(s, n, g, {cursorInference})
|
||||||
for i in 0 ..< par.s.len:
|
for i in 0 ..< par.s.len:
|
||||||
let v = addr(par.s[i])
|
let v = addr(par.s[i])
|
||||||
if v.flags * {ownsData, preventCursor} == {} and v.sym.kind notin {skParam, skResult} and
|
if v.flags * {ownsData, preventCursor, isConditionallyReassigned} == {} and
|
||||||
|
v.sym.kind notin {skParam, skResult} and
|
||||||
v.sym.flags * {sfThread, sfGlobal} == {} and hasDestructor(v.sym.typ) and
|
v.sym.flags * {sfThread, sfGlobal} == {} and hasDestructor(v.sym.typ) and
|
||||||
v.sym.typ.skipTypes({tyGenericInst, tyAlias}).kind != tyOwned:
|
v.sym.typ.skipTypes({tyGenericInst, tyAlias}).kind != tyOwned:
|
||||||
let rid = root(par, i)
|
let rid = root(par, i)
|
||||||
|
|
|
||||||
|
|
@ -86,13 +86,11 @@ template assert*(cond: untyped, msg = "") =
|
||||||
##
|
##
|
||||||
## No code will be generated for `assert` when passing `-d:danger` (implied by `--assertions:off`).
|
## No code will be generated for `assert` when passing `-d:danger` (implied by `--assertions:off`).
|
||||||
## See `command line switches <nimc.html#compiler-usage-commandminusline-switches>`_.
|
## See `command line switches <nimc.html#compiler-usage-commandminusline-switches>`_.
|
||||||
const expr = astToStr(cond)
|
assertImpl(cond, msg, astToStr(cond), compileOption("assertions"))
|
||||||
assertImpl(cond, msg, expr, compileOption("assertions"))
|
|
||||||
|
|
||||||
template doAssert*(cond: untyped, msg = "") =
|
template doAssert*(cond: untyped, msg = "") =
|
||||||
## Similar to `assert <#assert.t,untyped,string>`_ but is always turned on regardless of `--assertions`.
|
## Similar to `assert <#assert.t,untyped,string>`_ but is always turned on regardless of `--assertions`.
|
||||||
const expr = astToStr(cond)
|
assertImpl(cond, msg, astToStr(cond), true)
|
||||||
assertImpl(cond, msg, expr, true)
|
|
||||||
|
|
||||||
template onFailedAssert*(msg, code: untyped): untyped {.dirty.} =
|
template onFailedAssert*(msg, code: untyped): untyped {.dirty.} =
|
||||||
## Sets an assertion failure handler that will intercept any assert
|
## Sets an assertion failure handler that will intercept any assert
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,12 @@ discard """
|
||||||
doing shady stuff...
|
doing shady stuff...
|
||||||
3
|
3
|
||||||
6
|
6
|
||||||
(@[1], @[2])'''
|
(@[1], @[2])
|
||||||
cmd: '''nim c --gc:arc --expandArc:newTarget --expandArc:delete --expandArc:p1 --expandArc:tt --hint:Performance:off $file'''
|
192.168.0.1
|
||||||
|
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 $file'''
|
||||||
nimout: '''--expandArc: newTarget
|
nimout: '''--expandArc: newTarget
|
||||||
|
|
||||||
var
|
var
|
||||||
|
|
@ -78,6 +82,31 @@ try:
|
||||||
finally:
|
finally:
|
||||||
`=destroy`(:tmpD_2)
|
`=destroy`(:tmpD_2)
|
||||||
`=destroy_1`(a)
|
`=destroy_1`(a)
|
||||||
|
-- end of expandArc ------------------------
|
||||||
|
--expandArc: extractConfig
|
||||||
|
|
||||||
|
var lan_ip
|
||||||
|
try:
|
||||||
|
lan_ip = ""
|
||||||
|
block :tmp:
|
||||||
|
var line
|
||||||
|
var i = 0
|
||||||
|
let L = len(txt)
|
||||||
|
block :tmp_1:
|
||||||
|
while i < L:
|
||||||
|
var splitted
|
||||||
|
try:
|
||||||
|
line = txt[i]
|
||||||
|
splitted = split(line, " ", -1)
|
||||||
|
if splitted[0] == "opt":
|
||||||
|
`=copy`(lan_ip, splitted[1])
|
||||||
|
echo [lan_ip]
|
||||||
|
echo [splitted[1]]
|
||||||
|
inc(i, 1)
|
||||||
|
finally:
|
||||||
|
`=destroy`(splitted)
|
||||||
|
finally:
|
||||||
|
`=destroy_1`(lan_ip)
|
||||||
-- end of expandArc ------------------------'''
|
-- end of expandArc ------------------------'''
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
@ -194,3 +223,56 @@ proc plus(input: string) =
|
||||||
(rvalue, rnext) = rresult
|
(rvalue, rnext) = rresult
|
||||||
|
|
||||||
plus("123;")
|
plus("123;")
|
||||||
|
|
||||||
|
func substrEq(s: string, pos: int, substr: string): bool =
|
||||||
|
var i = 0
|
||||||
|
var length = substr.len
|
||||||
|
while i < length and pos+i < s.len and s[pos+i] == substr[i]:
|
||||||
|
inc i
|
||||||
|
return i == length
|
||||||
|
|
||||||
|
template stringHasSep(s: string, index: int, sep: string): bool =
|
||||||
|
s.substrEq(index, sep)
|
||||||
|
|
||||||
|
template splitCommon(s, sep, maxsplit, sepLen) =
|
||||||
|
var last = 0
|
||||||
|
var splits = maxsplit
|
||||||
|
|
||||||
|
while last <= len(s):
|
||||||
|
var first = last
|
||||||
|
while last < len(s) and not stringHasSep(s, last, sep):
|
||||||
|
inc(last)
|
||||||
|
if splits == 0: last = len(s)
|
||||||
|
yield substr(s, first, last-1)
|
||||||
|
if splits == 0: break
|
||||||
|
dec(splits)
|
||||||
|
inc(last, sepLen)
|
||||||
|
|
||||||
|
iterator split(s: string, sep: string, maxsplit = -1): string =
|
||||||
|
splitCommon(s, sep, maxsplit, sep.len)
|
||||||
|
|
||||||
|
template accResult(iter: untyped) =
|
||||||
|
result = @[]
|
||||||
|
for x in iter: add(result, x)
|
||||||
|
|
||||||
|
func split*(s: string, sep: string, maxsplit = -1): seq[string] =
|
||||||
|
accResult(split(s, sep, maxsplit))
|
||||||
|
|
||||||
|
|
||||||
|
let txt = @["opt 192.168.0.1", "static_lease 192.168.0.1"]
|
||||||
|
|
||||||
|
# bug #17033
|
||||||
|
|
||||||
|
proc extractConfig() =
|
||||||
|
var lan_ip = ""
|
||||||
|
|
||||||
|
for line in txt:
|
||||||
|
let splitted = line.split(" ")
|
||||||
|
if splitted[0] == "opt":
|
||||||
|
lan_ip = splitted[1] # "borrow" is conditional and inside a loop.
|
||||||
|
# Not good enough...
|
||||||
|
# we need a flag that live-ranges are disjoint
|
||||||
|
echo lan_ip
|
||||||
|
echo splitted[1] # Without this line everything works
|
||||||
|
|
||||||
|
extractConfig()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue