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
|
result.info = x.info
|
||||||
|
|
||||||
proc highBound*(x: PNode): PNode =
|
proc highBound*(x: PNode): PNode =
|
||||||
result = if x.typ.skipTypes(abstractInst).kind == tyArray:
|
let typ = x.typ.skipTypes(abstractInst)
|
||||||
nkIntLit.newIntNode(lastOrd(x.typ))
|
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:
|
else:
|
||||||
opAdd.buildCall(opLen.buildCall(x), minusOne())
|
opAdd.buildCall(opLen.buildCall(x), minusOne())
|
||||||
result.info = x.info
|
result.info = x.info
|
||||||
|
|
@ -214,12 +218,23 @@ proc reassociation(n: PNode): PNode =
|
||||||
result = opAdd.buildCall(result[1][1], result[1][2] |*| result[2])
|
result = opAdd.buildCall(result[1][1], result[1][2] |*| result[2])
|
||||||
else: discard
|
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 =
|
proc canon*(n: PNode): PNode =
|
||||||
# XXX for now only the new code in 'semparallel' uses this
|
# XXX for now only the new code in 'semparallel' uses this
|
||||||
if n.safeLen >= 1:
|
if n.safeLen >= 1:
|
||||||
result = shallowCopy(n)
|
result = shallowCopy(n)
|
||||||
for i in 0 .. < n.len:
|
for i in 0 .. < n.len:
|
||||||
result.sons[i] = canon(n.sons[i])
|
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:
|
else:
|
||||||
result = n
|
result = n
|
||||||
case result.getMagic
|
case result.getMagic
|
||||||
|
|
@ -231,20 +246,26 @@ proc canon*(n: PNode): PNode =
|
||||||
of someHigh:
|
of someHigh:
|
||||||
# high == len+(-1)
|
# high == len+(-1)
|
||||||
result = opAdd.buildCall(opLen.buildCall(result[1]), minusOne())
|
result = opAdd.buildCall(opLen.buildCall(result[1]), minusOne())
|
||||||
of mUnaryMinusI, mUnaryMinusI64:
|
of mUnaryLt:
|
||||||
result = buildCall(opAdd, result[1], newIntNode(nkIntLit, -1))
|
result = buildCall(opAdd, result[1], newIntNode(nkIntLit, -1))
|
||||||
of someSub:
|
of someSub:
|
||||||
# x - 4 --> x + (-4)
|
# x - 4 --> x + (-4)
|
||||||
result = negate(result[1], result[2], result)
|
result = negate(result[1], result[2], result)
|
||||||
of someLen:
|
of someLen:
|
||||||
result.sons[0] = opLen.newSymNode
|
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
|
else: discard
|
||||||
|
|
||||||
result = skipConv(result)
|
result = skipConv(result)
|
||||||
result = reassociation(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
|
case result.getMagic
|
||||||
of someLe, someLt:
|
of someLe:
|
||||||
let x = result[1]
|
let x = result[1]
|
||||||
let y = result[2]
|
let y = result[2]
|
||||||
if x.kind in nkCallKinds and x.len == 3 and x[2].isValue and
|
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:
|
if a.isValue and b.isValue:
|
||||||
result = not sameValue(a, b)
|
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 =
|
proc impliesEq(fact, eq: PNode): TImplication =
|
||||||
let (loc, val) = if isLocation(eq.sons[1]): (1, 2) else: (2, 1)
|
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 =
|
proc ple(m: TModel; a, b: PNode): TImplication =
|
||||||
template `<=?`(a,b): expr = ple(m,a,b) == impYes
|
template `<=?`(a,b): expr = ple(m,a,b) == impYes
|
||||||
|
|
||||||
# 0 <= 3
|
# 0 <= 3
|
||||||
if a.isValue and b.isValue:
|
if a.isValue and b.isValue:
|
||||||
return if leValue(a, b): impYes else: impNo
|
return if leValue(a, b): impYes else: impNo
|
||||||
|
|
@ -744,16 +759,21 @@ proc pleViaModelRec(m: var TModel; a, b: PNode): TImplication =
|
||||||
# mark as used:
|
# mark as used:
|
||||||
m[i] = nil
|
m[i] = nil
|
||||||
if ple(m, a, x) == impYes:
|
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
|
#if pleViaModelRec(m, y, b): return impYes
|
||||||
# fact: 16 <= i
|
# fact: 16 <= i
|
||||||
# x y
|
# x y
|
||||||
# question: i <= 15? no!
|
# question: i <= 15? no!
|
||||||
result = impliesLe(fact, a, b)
|
result = impliesLe(fact, a, b)
|
||||||
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):
|
if sameTree(y, a):
|
||||||
result = ple(m, b, x)
|
result = ple(m, b, x)
|
||||||
if result != impUnknown: return result
|
if result != impUnknown:
|
||||||
|
return result
|
||||||
|
|
||||||
proc pleViaModel(model: TModel; aa, bb: PNode): TImplication =
|
proc pleViaModel(model: TModel; aa, bb: PNode): TImplication =
|
||||||
# compute replacements:
|
# compute replacements:
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,8 @@ proc renderModule*(n: PNode, filename: string, renderFlags: TRenderFlags = {})
|
||||||
proc renderTree*(n: PNode, renderFlags: TRenderFlags = {}): string
|
proc renderTree*(n: PNode, renderFlags: TRenderFlags = {}): string
|
||||||
proc initTokRender*(r: var TSrcGen, n: PNode, renderFlags: TRenderFlags = {})
|
proc initTokRender*(r: var TSrcGen, n: PNode, renderFlags: TRenderFlags = {})
|
||||||
proc getNextTok*(r: var TSrcGen, kind: var TTokType, literal: var string)
|
proc getNextTok*(r: var TSrcGen, kind: var TTokType, literal: var string)
|
||||||
|
|
||||||
|
proc `$`*(n: PNode): string = n.renderTree
|
||||||
# implementation
|
# implementation
|
||||||
# We render the source code in a two phases: The first
|
# We render the source code in a two phases: The first
|
||||||
# determines how long the subtree will likely be, the second
|
# 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[0] = newSymNode(newVar).PTransNode
|
||||||
defs[1] = it.sons[1].PTransNode
|
defs[1] = it.sons[1].PTransNode
|
||||||
defs[2] = transform(c, it.sons[2])
|
defs[2] = transform(c, it.sons[2])
|
||||||
|
newVar.ast = defs[2].PNode
|
||||||
result[i] = defs
|
result[i] = defs
|
||||||
else:
|
else:
|
||||||
if it.kind != nkVarTuple:
|
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
|
- VM: ptr/ref T cannot work in general
|
||||||
- scopes are still broken for generic instantiation!
|
- scopes are still broken for generic instantiation!
|
||||||
- blocks can "export" an identifier but the CCG generates {} for them ...
|
- 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
|
version 0.9.x
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue