fixes #2287
This commit is contained in:
parent
970e98718d
commit
5a21892da0
6 changed files with 345 additions and 280 deletions
|
|
@ -194,8 +194,12 @@ proc lowBound*(x: PNode): PNode =
|
|||
result.info = x.info
|
||||
|
||||
proc highBound*(x: PNode): PNode =
|
||||
result = if x.typ.skipTypes(abstractInst).kind == tyArray:
|
||||
nkIntLit.newIntNode(lastOrd(x.typ))
|
||||
let typ = x.typ.skipTypes(abstractInst)
|
||||
result = if typ.kind in {tyArrayConstr, tyArray}:
|
||||
nkIntLit.newIntNode(lastOrd(typ))
|
||||
elif typ.kind == tySequence and x.kind == nkSym and
|
||||
x.sym.kind == skConst:
|
||||
nkIntLit.newIntNode(x.sym.ast.len-1)
|
||||
else:
|
||||
opAdd.buildCall(opLen.buildCall(x), minusOne())
|
||||
result.info = x.info
|
||||
|
|
@ -214,12 +218,23 @@ proc reassociation(n: PNode): PNode =
|
|||
result = opAdd.buildCall(result[1][1], result[1][2] |*| result[2])
|
||||
else: discard
|
||||
|
||||
proc pred(n: PNode): PNode =
|
||||
if n.kind in {nkCharLit..nkUInt64Lit} and n.intVal != low(BiggestInt):
|
||||
result = copyNode(n)
|
||||
dec result.intVal
|
||||
else:
|
||||
result = n
|
||||
|
||||
proc canon*(n: PNode): PNode =
|
||||
# XXX for now only the new code in 'semparallel' uses this
|
||||
if n.safeLen >= 1:
|
||||
result = shallowCopy(n)
|
||||
for i in 0 .. < n.len:
|
||||
result.sons[i] = canon(n.sons[i])
|
||||
elif n.kind == nkSym and n.sym.kind == skLet and
|
||||
n.sym.ast.getMagic in (someEq + someAdd + someMul + someMin +
|
||||
someMax + someHigh + {mUnaryLt} + someSub + someLen):
|
||||
result = n.sym.ast.copyTree
|
||||
else:
|
||||
result = n
|
||||
case result.getMagic
|
||||
|
|
@ -231,20 +246,26 @@ proc canon*(n: PNode): PNode =
|
|||
of someHigh:
|
||||
# high == len+(-1)
|
||||
result = opAdd.buildCall(opLen.buildCall(result[1]), minusOne())
|
||||
of mUnaryMinusI, mUnaryMinusI64:
|
||||
of mUnaryLt:
|
||||
result = buildCall(opAdd, result[1], newIntNode(nkIntLit, -1))
|
||||
of someSub:
|
||||
# x - 4 --> x + (-4)
|
||||
result = negate(result[1], result[2], result)
|
||||
of someLen:
|
||||
result.sons[0] = opLen.newSymNode
|
||||
of someLt:
|
||||
# x < y same as x <= y-1:
|
||||
let y = n[2].canon
|
||||
let p = pred(y)
|
||||
let minus = if p != y: p else: opAdd.buildCall(y, minusOne()).canon
|
||||
result = opLe.buildCall(n[1].canon, minus)
|
||||
else: discard
|
||||
|
||||
result = skipConv(result)
|
||||
result = reassociation(result)
|
||||
# most important rule: (x-4) < a.len --> x < a.len+4
|
||||
# most important rule: (x-4) <= a.len --> x <= a.len+4
|
||||
case result.getMagic
|
||||
of someLe, someLt:
|
||||
of someLe:
|
||||
let x = result[1]
|
||||
let y = result[2]
|
||||
if x.kind in nkCallKinds and x.len == 3 and x[2].isValue and
|
||||
|
|
@ -402,13 +423,6 @@ proc valuesUnequal(a, b: PNode): bool =
|
|||
if a.isValue and b.isValue:
|
||||
result = not sameValue(a, b)
|
||||
|
||||
proc pred(n: PNode): PNode =
|
||||
if n.kind in {nkCharLit..nkUInt64Lit} and n.intVal != low(BiggestInt):
|
||||
result = copyNode(n)
|
||||
dec result.intVal
|
||||
else:
|
||||
result = n
|
||||
|
||||
proc impliesEq(fact, eq: PNode): TImplication =
|
||||
let (loc, val) = if isLocation(eq.sons[1]): (1, 2) else: (2, 1)
|
||||
|
||||
|
|
@ -671,6 +685,7 @@ proc pleViaModel(model: TModel; aa, bb: PNode): TImplication
|
|||
|
||||
proc ple(m: TModel; a, b: PNode): TImplication =
|
||||
template `<=?`(a,b): expr = ple(m,a,b) == impYes
|
||||
|
||||
# 0 <= 3
|
||||
if a.isValue and b.isValue:
|
||||
return if leValue(a, b): impYes else: impNo
|
||||
|
|
@ -744,16 +759,21 @@ proc pleViaModelRec(m: var TModel; a, b: PNode): TImplication =
|
|||
# mark as used:
|
||||
m[i] = nil
|
||||
if ple(m, a, x) == impYes:
|
||||
if ple(m, y, b) == impYes: return impYes
|
||||
if ple(m, y, b) == impYes:
|
||||
return impYes
|
||||
#if pleViaModelRec(m, y, b): return impYes
|
||||
# fact: 16 <= i
|
||||
# x y
|
||||
# question: i <= 15? no!
|
||||
result = impliesLe(fact, a, b)
|
||||
if result != impUnknown: return result
|
||||
if sameTree(y, a):
|
||||
result = ple(m, b, x)
|
||||
if result != impUnknown: return result
|
||||
if result != impUnknown:
|
||||
return result
|
||||
when false:
|
||||
# given: x <= y; y==a; x <= a this means: a <= b if x <= b
|
||||
if sameTree(y, a):
|
||||
result = ple(m, b, x)
|
||||
if result != impUnknown:
|
||||
return result
|
||||
|
||||
proc pleViaModel(model: TModel; aa, bb: PNode): TImplication =
|
||||
# compute replacements:
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ proc renderModule*(n: PNode, filename: string, renderFlags: TRenderFlags = {})
|
|||
proc renderTree*(n: PNode, renderFlags: TRenderFlags = {}): string
|
||||
proc initTokRender*(r: var TSrcGen, n: PNode, renderFlags: TRenderFlags = {})
|
||||
proc getNextTok*(r: var TSrcGen, kind: var TTokType, literal: var string)
|
||||
|
||||
proc `$`*(n: PNode): string = n.renderTree
|
||||
# implementation
|
||||
# We render the source code in a two phases: The first
|
||||
# determines how long the subtree will likely be, the second
|
||||
|
|
|
|||
|
|
@ -152,6 +152,7 @@ proc transformVarSection(c: PTransf, v: PNode): PTransNode =
|
|||
defs[0] = newSymNode(newVar).PTransNode
|
||||
defs[1] = it.sons[1].PTransNode
|
||||
defs[2] = transform(c, it.sons[2])
|
||||
newVar.ast = defs[2].PNode
|
||||
result[i] = defs
|
||||
else:
|
||||
if it.kind != nkVarTuple:
|
||||
|
|
|
|||
41
tests/parallel/tsimple_array_checks.nim
Normal file
41
tests/parallel/tsimple_array_checks.nim
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
# bug #2287
|
||||
|
||||
import threadPool
|
||||
|
||||
# If `nums` is an array instead of seq,
|
||||
# NONE of the iteration ways below work (including high / len-1)
|
||||
let nums = @[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
|
||||
proc log(n:int) =
|
||||
echo n
|
||||
|
||||
proc main =
|
||||
parallel:
|
||||
for n in nums: # Error: cannot prove: i <= len(nums) + -1
|
||||
spawn log(n)
|
||||
#for i in 0 .. <nums.len: # Error: cannot prove: i <= len(nums) + -1
|
||||
#for i in 0 .. nums.len-1: # WORKS!
|
||||
#for i in 0 .. <nums.len: # WORKS!
|
||||
# spawn log(nums[i])
|
||||
|
||||
# Array needs explicit size to work, probably related to issue #2287
|
||||
#const a: array[0..5, int] = [1,2,3,4,5,6]
|
||||
|
||||
#const a = [1,2,3,4,5,6] # Doesn't work
|
||||
const a = @[1,2,3,4,5,6] # Doesn't work
|
||||
proc f(n: int) = echo "Hello ", n
|
||||
|
||||
proc maino =
|
||||
parallel:
|
||||
# while loop doesn't work:
|
||||
var i = 0
|
||||
while i < a.high:
|
||||
#for i in countup(0, a.high-1, 2):
|
||||
spawn f(a[i])
|
||||
spawn f(a[i+1])
|
||||
i += 2
|
||||
|
||||
maino() # Doesn't work outside a proc
|
||||
|
||||
when isMainModule:
|
||||
main()
|
||||
1
todo.txt
1
todo.txt
|
|
@ -54,6 +54,7 @@ Bugs
|
|||
- VM: ptr/ref T cannot work in general
|
||||
- scopes are still broken for generic instantiation!
|
||||
- blocks can "export" an identifier but the CCG generates {} for them ...
|
||||
- ConcreteTypes in a 'case' means we don't check for duplicated case branches
|
||||
|
||||
|
||||
version 0.9.x
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue