This commit is contained in:
Araq 2015-03-12 00:27:49 +01:00
commit 5a21892da0
6 changed files with 345 additions and 280 deletions

View file

@ -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:

View file

@ -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

View file

@ -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:

View 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()

View file

@ -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