diff options
author | Daniil Yarancev <21169548+Yardanico@users.noreply.github.com> | 2018-06-05 21:25:45 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-06-05 21:25:45 +0300 |
commit | 642641359821b6a63c6cf7edaaa45873b7ea59c7 (patch) | |
tree | 627af3020528cb916b3174bd94304307ca875c77 /tests | |
parent | fb44c522e6173528efa8035ecc459c84887d0167 (diff) | |
parent | 3cbc07ac7877b03c605498760fe198e3200cc197 (diff) | |
download | Nim-642641359821b6a63c6cf7edaaa45873b7ea59c7.tar.gz |
Merge pull request #2 from nim-lang/devel
Update
Diffstat (limited to 'tests')
255 files changed, 4233 insertions, 2891 deletions
diff --git a/tests/array/t7818.nim b/tests/array/t7818.nim new file mode 100644 index 000000000..4e43bff85 --- /dev/null +++ b/tests/array/t7818.nim @@ -0,0 +1,132 @@ +discard """ + output: "OK" +""" + +# bug #7818 +# this is not a macro bug, but array construction bug +# I use macro to avoid object slicing +# see #7712 and #7637 +import macros + +type + Vehicle[T] = object of RootObj + tire: T + Car[T] = object of Vehicle[T] + Bike[T] = object of Vehicle[T] + +macro peek(n: typed): untyped = + let val = getTypeImpl(n).treeRepr + newLit(val) + +block test_t7818: + var v = Vehicle[int](tire: 3) + var c = Car[int](tire: 4) + var b = Bike[int](tire: 2) + + let y = peek([c, b, v]) + let z = peek([v, c, b]) + doAssert(y == z) + +block test_t7906_1: + proc init(x: typedesc, y: int): ref x = + result = new(ref x) + result.tire = y + + var v = init(Vehicle[int], 3) + var c = init(Car[int], 4) + var b = init(Bike[int], 2) + + let y = peek([c, b, v]) + let z = peek([v, c, b]) + doAssert(y == z) + +block test_t7906_2: + var v = Vehicle[int](tire: 3) + var c = Car[int](tire: 4) + var b = Bike[int](tire: 2) + + let y = peek([c.addr, b.addr, v.addr]) + let z = peek([v.addr, c.addr, b.addr]) + doAssert(y == z) + +block test_t7906_3: + type + Animal[T] = object of RootObj + hair: T + Mammal[T] = object of Animal[T] + Monkey[T] = object of Mammal[T] + + var v = Animal[int](hair: 3) + var c = Mammal[int](hair: 4) + var b = Monkey[int](hair: 2) + + let z = peek([c.addr, b.addr, v.addr]) + let y = peek([v.addr, c.addr, b.addr]) + doAssert(y == z) + +type + Fruit[T] = ref object of RootObj + color: T + Apple[T] = ref object of Fruit[T] + Banana[T] = ref object of Fruit[T] + +proc testArray[T](x: array[3, Fruit[T]]): string = + result = "" + for c in x: + result.add $c.color + +proc testOpenArray[T](x: openArray[Fruit[T]]): string = + result = "" + for c in x: + result.add $c.color + +block test_t7906_4: + var v = Fruit[int](color: 3) + var c = Apple[int](color: 4) + var b = Banana[int](color: 2) + + let y = peek([c, b, v]) + let z = peek([v, c, b]) + doAssert(y == z) + +block test_t7906_5: + var a = Fruit[int](color: 1) + var b = Apple[int](color: 2) + var c = Banana[int](color: 3) + + doAssert(testArray([a, b, c]) == "123") + doAssert(testArray([b, c, a]) == "231") + + doAssert(testOpenArray([a, b, c]) == "123") + doAssert(testOpenArray([b, c, a]) == "231") + + doAssert(testOpenArray(@[a, b, c]) == "123") + doAssert(testOpenArray(@[b, c, a]) == "231") + +proc testArray[T](x: array[3, ptr Vehicle[T]]): string = + result = "" + for c in x: + result.add $c.tire + +proc testOpenArray[T](x: openArray[ptr Vehicle[T]]): string = + result = "" + for c in x: + result.add $c.tire + +block test_t7906_6: + var u = Vehicle[int](tire: 1) + var v = Bike[int](tire: 2) + var w = Car[int](tire: 3) + + doAssert(testArray([u.addr, v.addr, w.addr]) == "123") + doAssert(testArray([w.addr, u.addr, v.addr]) == "312") + + doAssert(testOpenArray([u.addr, v.addr, w.addr]) == "123") + doAssert(testOpenArray([w.addr, u.addr, v.addr]) == "312") + + doAssert(testOpenArray(@[u.addr, v.addr, w.addr]) == "123") + doAssert(testOpenArray(@[w.addr, u.addr, v.addr]) == "312") + +echo "OK" + + diff --git a/tests/array/tarray.nim b/tests/array/tarray.nim index 9cfb758e2..5e947e745 100644 --- a/tests/array/tarray.nim +++ b/tests/array/tarray.nim @@ -38,3 +38,15 @@ var found: array[0..filesToCreate.high, bool] echo found.len +# make sure empty arrays are assignable (bug #6853) +const arr1: array[0, int] = [] +const arr2 = [] +let arr3: array[0, string] = [] + +doAssert(arr1.len == 0) +doAssert(arr2.len == 0) +doAssert(arr3.len == 0) + +# Negative array length is not allowed (#6852) +doAssert(not compiles(block: + var arr: array[-1, int])) \ No newline at end of file diff --git a/tests/array/tarraycons_ptr_generic.nim b/tests/array/tarraycons_ptr_generic.nim new file mode 100644 index 000000000..eb89a196f --- /dev/null +++ b/tests/array/tarraycons_ptr_generic.nim @@ -0,0 +1,51 @@ +discard """ + output: '''apple +banana +Fruit +2 +4 +3 +none +skin +paper +''' +""" +type + Fruit = object of RootObj + name: string + Apple = object of Fruit + Banana = object of Fruit + +var + ir = Fruit(name: "Fruit") + ia = Apple(name: "apple") + ib = Banana(name: "banana") + +let x = [ia.addr, ib.addr, ir.addr] +for c in x: echo c.name + +type + Vehicle[T] = object of RootObj + tire: T + Car[T] = object of Vehicle[T] + Bike[T] = object of Vehicle[T] + +var v = Vehicle[int](tire: 3) +var c = Car[int](tire: 4) +var b = Bike[int](tire: 2) + +let y = [b.addr, c.addr, v.addr] +for c in y: echo c.tire + +type + Book[T] = ref object of RootObj + cover: T + Hard[T] = ref object of Book[T] + Soft[T] = ref object of Book[T] + +var bn = Book[string](cover: "none") +var hs = Hard[string](cover: "skin") +var bp = Soft[string](cover: "paper") + +let z = [bn, hs, bp] +for c in z: echo c.cover diff --git a/tests/array/tarraycons_ptr_generic2.nim b/tests/array/tarraycons_ptr_generic2.nim new file mode 100644 index 000000000..fce7af669 --- /dev/null +++ b/tests/array/tarraycons_ptr_generic2.nim @@ -0,0 +1,17 @@ +discard """ + file: "tarraycons_ptr_generic2.nim" + line: 17 + errormsg: "type mismatch: got <ptr Hard[system.string]> but expected 'Book[system.string]'" +""" + +type + Book[T] = ref object of RootObj + cover: T + Hard[T] = ref object of Book[T] + Soft[T] = ref object of Book[T] + +var bn = Book[string](cover: "none") +var hs = Hard[string](cover: "skin") +var bp = Soft[string](cover: "paper") + +let z = [bn, hs.addr, bp] diff --git a/tests/array/tarrayplus.nim b/tests/array/tarrayplus.nim index 33921c0e1..09bae77fd 100644 --- a/tests/array/tarrayplus.nim +++ b/tests/array/tarrayplus.nim @@ -1,5 +1,5 @@ discard """ - errormsg: "type mismatch: got (array[0..2, float], array[0..1, float])" + errormsg: "type mismatch: got <array[0..2, float], array[0..1, float]>" """ proc `+`*[R, T] (v1, v2: array[R, T]): array[R, T] = diff --git a/tests/array/tarrindx.nim b/tests/array/tarrindx.nim index a8d72b338..3bb6b0148 100644 --- a/tests/array/tarrindx.nim +++ b/tests/array/tarrindx.nim @@ -1,3 +1,8 @@ +discard """ + output: '''0 +0''' +""" + # test another strange bug ... (I hate this compiler; it is much too buggy!) proc putEnv(key, val: string) = @@ -11,3 +16,16 @@ proc putEnv(key, val: string) = env[len(key)] = '=' for i in 0..len(val)-1: env[len(key)+1+i] = val[i] + +# bug #7153 +const + UnsignedConst = 1024'u +type + SomeObject* = object + s1: array[UnsignedConst, uint32] + +var + obj: SomeObject + +echo obj.s1[0] +echo obj.s1[0u] diff --git a/tests/array/troofregression2.nim b/tests/array/troofregression2.nim new file mode 100644 index 000000000..a594d8a47 --- /dev/null +++ b/tests/array/troofregression2.nim @@ -0,0 +1,102 @@ +discard """ + output: '''OK +OK +OK +OK +OK +dflfdjkl__abcdefgasfsgdfgsgdfggsdfasdfsafewfkljdsfajs +dflfdjkl__abcdefgasfsgdfgsgdfggsdfasdfsafewfkljdsfajsdf +kgdchlfniambejop +fjpmholcibdgeakn +''' +""" + +import strutils, sequtils, typetraits, os +# bug #6989 + +type Dist = distinct int + +proc mypred[T: Ordinal](x: T): T = T(int(x)-1) +proc cons(x: int): Dist = Dist(x) + +var d: Dist + +template `^+`(s, i: untyped): untyped = + (when i is BackwardsIndex: s.len - int(i) else: int(i)) + +proc `...`*[T, U](a: T, b: U): HSlice[T, U] = + result.a = a + result.b = b + +proc `...`*[T](b: T): HSlice[int, T] = + result.b = b + +template `...<`*(a, b: untyped): untyped = + ## a shortcut for 'a..pred(b)'. + a ... pred(b) + +template check(a, b) = + if $a == b: echo "OK" + else: echo "Failure ", a, " != ", b + +check type(4 ...< 1), "HSlice[system.int, system.int]" + +check type(4 ...< ^1), "HSlice[system.int, system.BackwardsIndex]" +check type(4 ... pred(^1)), "HSlice[system.int, system.BackwardsIndex]" + +check type(4 ... mypred(8)), "HSlice[system.int, system.int]" + +check type(4 ... mypred(^1)), "HSlice[system.int, system.BackwardsIndex]" + +var rot = 8 + +proc bug(s: string): string = + result = s + result = result[result.len - rot .. ^1] & "__" & result[0 ..< ^rot] + +const testStr = "abcdefgasfsgdfgsgdfggsdfasdfsafewfkljdsfajsdflfdjkl" + +echo bug(testStr) +echo testStr[testStr.len - 8 .. testStr.len - 1] & "__" & testStr[0 .. testStr.len - pred(rot)] + + + +var + instructions = readFile(getAppDir() / "troofregression2.txt").split(',') + programs = "abcdefghijklmnop" + +proc dance(dancers: string): string = + result = dancers + for instr in instructions: + let rem = instr[1 .. instr.high] + case instr[0] + of 's': + let rot = rem.parseInt + result = result[result.len - rot .. ^1] & result[0 ..< ^rot] + of 'x': + let + x = rem.split('/') + a = x[0].parseInt + b = x[1].parseInt + swap(result[a], result[b]) + of 'p': + let + a = result.find(rem[0]) + b = result.find(rem[^1]) + result[a] = rem[^1] + result[b] = rem[0] + else: discard + +proc longDance(dancers: string, iterations = 1_000_000_000): string = + var + dancers = dancers + seen = @[dancers] + for i in 1 .. iterations: + dancers = dancers.dance() + if dancers in seen: + return seen[iterations mod i] + seen.add(dancers) + + +echo dance(programs) +echo longDance(programs) diff --git a/tests/array/troofregression2.txt b/tests/array/troofregression2.txt new file mode 100644 index 000000000..793c1744d --- /dev/null +++ b/tests/array/troofregression2.txt @@ -0,0 +1 @@ +x10/0,s2,x6/11,s3,x12/1,s15,pb/m,x4/8,pn/c,x13/9,pj/e,x15/2,s15,x4/9,pp/h,x8/11,s10,x6/15,s15,pd/k,x11/8,s14,x0/6,s14,x1/7,s14,x2/9,pg/l,x0/15,pc/f,x9/12,s12,pi/d,x4/0,s15,x15/13,s10,x1/8,s10,x3/12,s12,pl/n,x6/8,s5,x3/13,s12,x4/6,s14,x1/13,s3,x12/2,s11,x9/1,ph/f,x2/15,s8,x14/4,pl/d,s7,x10/13,pi/h,x9/12,s7,x13/8,pb/d,x6/14,s15,x7/15,s1,pn/p,x4/11,pe/l,x7/12,s6,x6/14,pp/m,x11/10,s15,x13/12,pc/o,x14/10,pl/k,x1/6,s15,x4/14,s13,x6/2,pp/i,x1/10,s1,x12/2,s12,x1/10,pl/m,x0/15,s1,x9/10,s12,x11/3,ph/a,x4/12,s3,x8/2,s9,x10/3,s10,x12/6,s8,x13/4,s10,x1/11,s11,x9/4,s14,x11/13,s8,x1/2,s9,x14/3,pb/m,x15/5,s13,x13/8,pp/i,x2/3,s6,x10/15,s4,pc/h,x7/0,pb/l,x13/8,s2,x5/14,s5,x8/4,s11,pa/h,x2/13,s11,x5/14,s11,x3/4,pm/b,s9,x2/15,s9,x4/0,s6,x9/7,s3,x1/15,s5,x11/5,s10,x9/7,s2,x8/5,po/l,s13,pd/h,x0/2,s11,x14/12,s15,x3/13,pb/i,x0/10,s11,x14/9,s9,pp/c,x1/3,s15,pf/a,x10/6,s8,x9/14,pj/p,x8/3,s12,x10/15,pl/h,x4/14,s14,pa/d,x2/8,s13,x12/10,s2,x13/3,pi/g,s8,x7/8,s2,x15/10,s8,x3/1,s11,x9/4,pk/o,x13/6,s12,x10/0,s6,x5/9,s15,x0/11,s10,x12/13,s4,x11/3,s4,x8/13,pf/n,s4,x7/0,pi/b,x12/8,pg/d,x1/5,s13,x8/10,pk/i,x11/3,s10,x2/4,s13,x6/11,s1,x2/5,pe/n,x13/0,s7,x11/2,s4,x8/14,s8,x4/5,pf/g,x2/13,pe/i,s7,pn/m,x7/6,pj/o,x15/2,s4,x6/12,s14,x10/11,s8,pe/l,x9/12,s3,x11/15,s4,x14/10,pd/m,x11/13,pk/h,s4,x1/8,pc/m,x12/4,s3,x11/3,s2,x15/4,s14,x1/5,ph/o,x8/6,pb/c,x10/13,pg/f,x1/5,pp/a,x2/15,s7,x13/3,s12,x10/1,s11,x0/3,s8,x14/4,s12,x5/15,pe/f,s14,x13/12,s6,x4/11,s13,x3/5,s13,x2/13,pb/p,s10,x11/0,s3,x4/6,s10,x14/2,s15,x10/9,po/e,x4/11,pl/a,s10,x5/12,s15,x2/9,pg/d,x8/11,pb/f,x10/4,s7,x7/2,pp/o,x8/3,s4,x4/12,s5,x11/3,s1,x14/9,pl/e,x11/12,s15,pi/k,s1,x6/1,pe/b,x10/4,pl/a,x7/0,s13,x2/15,pf/k,x4/7,s14,x8/0,s6,x3/7,pm/i,x1/5,pb/l,x9/15,pp/k,x2/1,s5,x6/10,s3,x12/14,s10,x7/0,pi/h,x8/2,s2,pf/g,s2,x7/3,s3,ph/d,x14/13,s2,x1/15,po/m,x11/5,s15,x2/7,s4,x1/10,pj/a,s7,x15/14,po/k,x11/8,s10,pc/a,x6/15,s14,x12/1,s2,x7/9,pf/i,x5/4,pd/e,x11/13,s11,x9/6,pa/g,x13/8,s8,x2/14,s11,x13/9,s10,x7/11,s5,x2/14,s5,x10/7,s13,x0/13,s14,x5/3,s8,x14/15,s9,x4/0,ph/m,x14/1,po/k,x0/4,pf/b,x13/6,s10,x9/12,s1,x13/3,s1,x7/15,s12,pj/o,s12,x9/5,pm/p,x12/6,pk/j,x14/15,pc/n,x13/5,pk/a,x14/12,pn/f,x1/11,pa/p,x7/2,s8,x9/8,s8,pk/d,x2/12,s8,x15/3,pb/c,x14/9,s7,x10/7,s2,x12/11,s9,x2/3,pa/j,s15,x1/0,s9,x14/8,pc/f,x3/1,s4,x14/6,s1,x13/7,pd/o,x10/0,ph/c,x8/7,s3,x11/4,pj/g,x9/2,pp/n,x6/8,pc/k,x3/11,pa/i,x2/0,s6,x15/5,s12,x2/7,pn/b,x3/0,ph/m,s11,x7/1,s4,x5/10,s13,x11/0,pj/g,x13/3,s11,x7/15,s14,x6/0,s13,pk/a,s7,x4/15,pc/m,x13/6,pl/k,x14/1,s4,x15/11,s1,pg/p,x3/5,s13,x2/14,pa/c,x12/15,pi/k,x6/8,s10,x14/15,s5,x12/8,s15,x5/3,s9,x2/4,s14,x8/7,pb/f,x10/4,s10,x5/9,s3,x4/14,s4,x7/2,pd/j,x0/12,po/l,x3/11,pc/h,x9/0,s11,pp/b,x6/12,s3,x14/4,s9,x5/3,s9,x0/12,s1,x10/7,pd/h,x11/6,s8,pp/f,x14/12,s6,pj/i,s11,x11/0,s13,x7/6,pf/b,x15/1,pa/l,s5,x2/5,po/n,x0/3,ph/b,x8/7,s15,x4/12,s4,x14/11,s6,x15/7,pj/p,s7,x12/6,s5,x5/7,s5,x0/3,s15,x6/11,s4,x13/14,s12,x2/1,pf/g,x11/0,s12,x7/3,s12,x10/4,s10,x5/13,s14,x1/6,pp/h,x7/13,pe/i,x4/15,s6,x3/1,s7,x7/5,s13,x1/0,pj/h,x15/5,pc/i,x9/2,s7,x11/0,s2,x4/13,s8,pg/j,x2/11,s15,x8/14,s11,x6/9,pe/h,x2/12,s6,x14/0,s11,pd/b,x11/3,s10,x1/8,s12,x12/0,s13,x8/13,s7,x2/9,pg/c,x10/6,s5,x4/7,s6,x13/12,pm/o,x4/10,pc/n,x7/15,po/i,x11/3,pl/n,x15/5,pb/a,x13/0,pg/e,x1/5,pa/o,x13/0,pj/m,x14/5,s11,x7/8,s6,x15/9,s5,x14/12,s4,x4/3,ph/c,x12/6,pl/j,s11,x10/0,s9,pd/c,x14/15,s5,x11/3,s3,x8/0,s12,x13/9,s8,x5/7,pl/k,s2,x2/11,s7,x14/10,s14,x11/15,pd/a,x14/4,pj/i,x1/6,s10,x0/14,pl/g,x4/6,s9,x15/13,s9,x12/1,s13,x10/8,pi/c,x5/4,po/f,x0/8,pm/l,x5/11,s9,x8/7,pp/n,x15/10,pi/e,x7/9,pa/f,s13,x3/5,s3,x13/1,pb/d,x7/2,s12,x6/12,pc/g,x9/10,s7,x12/1,s7,x6/11,s5,x1/15,s11,x2/12,s3,x14/0,po/b,x5/7,s10,x13/9,pc/f,x7/15,po/a,x14/5,pl/b,x4/2,ph/j,x14/11,s4,x13/5,s15,pi/n,x3/10,s8,x1/13,s11,x10/9,s2,x3/6,s3,x2/15,s6,x10/12,pf/o,x1/13,s13,x11/7,s11,x9/15,pm/n,x2/14,s12,pp/i,x8/3,pm/n,x6/12,pd/o,x9/11,s4,x12/14,pc/g,x10/5,s6,x12/3,s8,pe/h,x8/1,s13,x0/15,pn/c,x7/10,s12,x15/3,s1,x11/9,pb/j,x5/15,pg/d,x13/7,s9,x1/8,pk/j,x9/7,pc/p,s3,x12/5,s6,x10/3,po/e,x1/12,s15,x8/9,s6,pa/n,x4/3,s9,x1/8,s12,x15/5,s2,x3/14,pe/h,x13/1,pf/l,x8/7,s1,x1/14,pd/a,x7/2,pp/m,x8/5,s7,x0/12,pi/b,s11,x11/2,s3,x8/0,s5,x11/3,s2,x15/9,pj/o,x1/5,s9,x8/4,s12,x3/6,pk/a,x11/7,s1,x14/2,pl/f,s3,x12/6,s9,x3/2,s15,x15/6,pk/i,x12/1,pe/d,x6/10,s12,x15/0,pn/a,x9/10,s4,x13/3,s2,x9/6,s4,pm/b,x4/5,s2,x1/3,s2,x13/10,s1,x1/2,s4,x11/0,po/f,x9/4,s4,x1/0,pp/m,x15/4,s7,x5/2,s4,x8/9,s14,x5/13,pb/c,x8/3,pe/d,s11,x14/13,s3,x6/9,s6,x14/1,s10,x4/0,pk/n,x3/2,pb/f,x15/13,s4,x12/4,pj/o,x11/0,s9,x4/5,s8,x3/11,pn/h,x1/6,pd/a,x14/7,s4,x0/3,s4,x5/15,ph/c,s14,x2/14,pk/p,x11/12,s1,x15/14,pg/n,x10/2,s10,x14/6,s15,x3/4,s12,x14/1,pk/f,x6/10,pn/h,x3/4,pc/a,x10/7,pk/j,x13/6,pi/d,x10/12,pl/c,x4/5,s6,x0/3,s5,x8/14,s12,x7/3,pk/n,x11/5,s7,x9/7,s1,x6/4,pg/f,x5/7,s12,x0/12,s11,pi/b,x14/2,s3,x13/7,s14,x0/3,s8,pk/o,s1,x12/5,pi/e,x2/8,s13,x3/12,s5,x10/14,s8,pd/f,s10,x0/5,s3,x2/3,s2,x14/15,s14,pj/n,s4,x0/6,s12,x13/1,pp/c,x5/12,po/j,x10/13,pb/c,x5/11,pd/o,x8/9,pn/b,x11/2,s12,x15/8,pd/p,x14/0,ph/l,x4/2,pi/f,x5/6,s1,x4/0,s10,x12/2,s4,x15/13,pe/m,x4/6,s10,x12/1,pb/c,s10,x6/3,s6,x9/10,s11,x5/12,pj/f,x7/2,pa/d,s7,pl/k,x12/4,s7,x7/2,s10,x3/9,s13,x12/8,s13,x4/1,pf/o,x9/2,s12,x3/15,pa/e,x1/5,s10,x10/6,s1,x3/9,pc/d,x6/0,pf/j,s12,x3/2,s11,x1/14,s5,x7/0,s11,x1/15,ph/k,x8/7,s15,pa/p,x14/2,s4,x0/15,s9,x3/11,s5,x8/15,pn/l,x3/4,s15,x5/13,s5,x4/14,s8,pj/e,s4,x10/8,s7,x2/11,s1,x12/1,s11,x5/15,s3,x6/10,pf/i,s12,x1/13,pe/n,x0/15,s7,x2/14,s2,x15/9,pl/b,x1/7,pj/o,x0/12,s15,x1/9,pk/i,x4/11,pb/d,s7,x8/6,pa/j,x0/3,pi/m,s7,x13/9,pe/d,x10/11,s8,x0/5,s10,x8/13,pk/b,x15/7,pf/c,x2/1,s2,x3/4,pj/h,x10/8,s10,x3/5,s14,x15/1,pc/i,x8/5,pp/e,x6/15,s2,pj/l,x12/9,po/m,x3/8,s9,x4/9,s6,x13/15,s10,x3/10,s3,x5/11,pd/e,x4/15,s6,x1/2,s1,x14/10,pl/c,x2/4,pj/d,x3/9,pi/b,x13/12,s6,x15/2,s6,x4/5,pd/m,x7/15,s12,x2/10,pl/o,x7/15,pi/f,x14/3,s11,x5/7,pk/b,x2/8,pj/e,x9/14,pk/n,s6,x0/5,pl/a,x15/14,s5,x2/4,s9,x12/0,s14,x10/15,pd/h,x3/5,s1,x6/13,s14,x15/9,s11,x4/7,pg/e,x1/0,pi/a,s4,x12/13,s13,x11/1,s4,x10/9,s15,x3/2,pg/e,s1,pl/f,x15/6,s1,x4/13,pa/o,x9/14,pk/e,x7/10,s14,x5/15,s4,x8/0,pc/o,x3/6,s8,x0/13,s4,x10/5,pn/h,x14/6,pc/g,s12,x11/12,s11,x10/5,pk/o,x0/3,s13,x8/14,s13,x7/15,pe/j,x0/12,pc/o,x15/13,s4,pl/i,x14/3,s5,pm/j,x6/15,s15,x10/1,ph/d,x5/2,pl/f,x9/6,s8,x15/3,pa/m,x0/11,s4,x14/2,s8,x10/0,s11,x1/13,s5,x15/2,pd/c,x11/1,s10,x0/5,s12,x1/11,s3,ph/p,x5/15,pb/k,x2/1,pn/m,s9,pj/i,x6/15,pe/o,x1/14,s12,x0/11,s11,x8/1,s7,x6/11,s8,pj/b,x7/15,pl/o,x12/5,pf/i,x13/2,s14,x10/5,s7,x15/7,pj/k,x12/8,pg/l,s1,x13/10,s9,x6/1,s2,x15/2,s11,x9/12,pn/m,x5/0,pa/i,x2/7,s15,pb/m,s12,pi/e,x12/8,s9,x2/1,s2,x0/12,pc/d,x2/11,s8,x8/10,s5,x2/7,pe/g,x10/3,s5,x8/15,s13,pl/a,x13/11,pe/b,x0/10,s13,x14/11,s14,x12/4,pi/h,s9,x14/2,s6,pe/m,x15/5,s4,x1/6,s12,x14/13,s2,x0/11,pp/l,x3/7,po/g,x15/11,s12,x12/14,pp/a,x5/13,s6,x10/1,s6,x9/7,s13,x5/8,s3,x10/1,s11,pb/m,x7/11,s3,x12/8,po/l,x1/2,pp/a,x8/9,s14,pe/b,x2/3,s15,x14/11,s5,pc/j,x12/3,s15,pe/b,x13/10,s9,x1/11,s10,x7/13,s13,x14/9,s2,x2/6,s12,x15/7,s3,x13/0,pa/m,x11/15,s10,x12/9,s9,x13/10,s5,x1/2,s7,x10/6,s15,x9/1,pg/f,s1,pb/k,x8/7,pg/m,x14/1,s13,x4/8,pi/h,x12/14,pa/c,x15/9,s5,x7/0,pp/m,x11/12,pb/n,x8/1,s1,x12/3,s4,x8/0,s15,x13/4,pk/a,x7/2,pg/n,x11/14,pk/e,x9/1,s3,pl/b,x14/3,s10,x10/13,s10,x8/1,pn/o,x14/9,pe/c,x1/12,pb/m,x14/11,po/n,x9/0,s10,x8/2,pb/j,x12/3,ph/l,x8/7,pi/c,x10/6,ph/p,x9/11,s7,x2/14,s14,x8/3,s13,x1/14,s5,x4/0,pf/b,x1/13,pp/j,x8/12,s1,x1/11,s15,x6/5,s6,x13/7,s13,x0/10,pb/k,x4/9,pd/a,x13/5,s5,x11/2,s8,x13/9,s1,x11/0,s3,x3/2,pi/n,x1/15,s14,x6/14,s5,x12/0,pg/h,x10/8,pa/l,x12/7,s8,x3/14,pm/n,x9/7,s13,x15/13,pp/a,x12/10,s4,x5/9,s2,x2/10,s14,x3/5,pg/h,x10/4,s12,x6/9,s10,x11/4,pf/l,x10/13,pi/o,x6/8,s5,pl/d,x3/2,s5,x10/4,s9,x2/1,s10,x8/15,s3,x0/5,s9,x2/7,pb/e,s9,x15/4,pp/j,x8/10,pk/i,s7,x15/4,s7,x6/8,pp/a,x10/3,pd/g,x15/14,s7,x4/0,pb/j,x12/8,s9,x4/0,s6,x11/10,s9,x9/4,s8,x13/3,pc/d,x7/12,s11,x10/8,s11,x13/1,s4,x5/11,s8,x12/0,s6,x11/13,s8,x2/0,s7,x9/12,pl/a,s14,x2/13,ph/f,x6/12,pm/g,x4/8,pi/l,s1,x5/10,pa/d,x1/13,pp/h,x15/5,s9,x14/0,s8,x12/4,pa/c,x3/5,s11,x2/11,s4,x3/0,s2,pi/g,x14/2,pa/d,s15,x3/4,s8,pj/p,x15/10,s14,x4/13,pm/i,s15,x11/8,pj/b,x6/0,s9,x12/13,s14,x3/10,pi/m,x4/6,po/f,x9/14,s2,pd/i,x12/0,s15,pk/g,x11/14,s1,x9/0,pj/f,x8/2,pk/m,x4/14,pb/o,x11/2,pc/d,x8/0,s14,x15/5,s13,pl/e,x6/11,pb/c,x2/0,pj/h,x15/3,s15,x7/2,s5,x10/3,pf/m,x5/11,pi/l,x14/7,pd/j,x13/5,pp/n,x1/12,s13,x6/4,pb/m,x7/12,s8,pk/l,x15/2,pf/p,x5/8,pi/m,x14/13,s10,x3/8,s1,x9/6,s15,x13/3,pe/b,x5/10,s3,x6/4,s9,x8/7,s13,x3/15,pp/j,x11/6,s7,x9/2,pm/b,x0/3,pd/j,x2/14,s4,x15/3,pm/o,x1/5,s15,x4/8,pa/i,x2/9,pn/h,x1/14,pc/i,x5/15,pk/p,x4/7,pg/n,x2/6,s3,x11/4,pb/h,x8/3,s10,x12/13,s5,x14/11,s9,x2/4,s1,x11/1,pg/l,x4/14,s4,x3/12,pn/j,x2/15,pl/p,x7/5,s6,x3/4,s2,x7/5,pf/j,x12/10,pm/c,x2/14,pi/o,x13/1,pd/m,x11/3,s5,x8/15,s7,x1/0,pi/a,x4/6,s13,x15/13,s9,x1/12,s11,x9/15,ph/k,x2/6,pf/e,x5/11,s4,x13/9,s2,pn/b,x4/7,s5,x9/6,s5,x13/1,s4,x7/8,s6,x11/10,s13,x13/1,pp/d,x9/6,pc/g,x13/7,s7,x9/2,s7,x4/11,po/f,x2/7,pd/i,x8/13,s11,x2/10,pp/h,x3/1,pe/n,x0/5,s3,x14/13,s8,x15/11,s14,x7/10,s15,x3/12,pp/j,x1/14,s12,x10/11,po/i,x5/13,pl/n,x4/0,s14,x1/3,s14,x4/14,s6,x2/6,pg/e,x10/3,pc/h,x2/0,s7,x11/4,s8,po/f,x9/1,pa/e,x4/11,s14,x1/3,s13,pn/d,x13/12,s4,x11/7,s7,x12/13,s11,x6/2,s4,x4/0,s7,pm/k,x6/8,s8,x14/13,pn/d,x8/15,s8,x13/9,s13,x12/10,s3,x3/7,s15,x9/1,pf/o,x0/14,pa/p,s9,x4/12,pl/n,x11/9,pg/i,x8/7,pe/n,x4/9,pp/d,x15/3,s5,x10/7,po/m,x12/3,s10,x4/10,pb/f,x15/6,s5,x12/13,po/l,x15/11,s8,x4/7,pj/d,x13/12,pn/g,x11/2,s5,x12/14,pl/h,x9/2,pd/g,x15/8,ph/l,x1/3,s7,x9/2,pp/d,s1,x5/1,s6,x12/7,s1,x9/8,pk/b,x12/11,s13,x8/1,s11,pl/h,x7/9,pe/n,x0/2,s2,x14/5,s4,x2/15,s4,x4/5,pa/b,x3/15,s14,x5/0,s13,x4/15,pg/o,s2,x3/13,s9,x2/15,s10,x10/12,pk/f,s12,x2/8,pl/h,x12/10,pa/o,x7/8,pi/b,x14/4,pa/c,x7/5,s3,x15/2,s6,pd/k,x11/3,s10,pj/m,x4/9,pp/e,s4,x5/15,s10,x11/1,pn/d,x4/15,s13,x1/9,s15,x15/6,s8,x1/11,s4,x0/5,s15,x11/12,s7,x7/10,s9,x13/1,s13,x5/12,s3,pm/h,s15,x10/14,s10,x11/12,pp/c,s14,x0/1,s8,x3/2,s8,x12/13,pe/g,x2/14,s15,x13/8,pd/a,x1/0,s11,x8/13,pm/g,x12/9,pe/j,s15,x4/7,s8,x6/10,pd/f,x2/1,s13,x5/15,s4,x3/12,pb/e,s7,pm/d,x5/7,pi/k,x13/14,pp/o,x12/8,s3,x4/1,pc/b,s12,x12/8,s2,x3/5,pg/h,x6/9,s15,pa/i,x10/1,s8,x13/0,pf/n,x14/1,s14,pk/a,x3/4,s7,x5/0,s13,x1/13,s6,x2/0,pd/g,x7/1,pn/m,x12/6,s6,x5/15,pc/a,x10/0,s4,x6/13,s15,x12/3,s13,x0/5,pl/f,x6/8,s15,x1/0,s15,x11/15,s8,x14/1,pk/o,x0/13,s1,x2/10,pi/d,x15/11,s2,x0/7,s5,x13/6,s8,x8/0,s13,x11/15,s14,x4/8,s2,x0/1,s7,x6/5,pk/j,x13/1,s1,x14/0,s10,x10/12,s5,x6/3,ph/n,x11/2,s2,x7/14,s3,pi/c,x2/0,s9,x12/5,s14,x9/11,pb/e,s4,x15/7,s7,x10/9,ph/g,s3,x0/11,pf/e,x12/8,s5,x1/5,s11,x2/7,s11,x10/6,s14,x7/2,s3,x6/11,s7,x9/5,s9,x6/12,s9,x15/5,pj/b,x0/7,s8,x9/3,s6,x4/15,pi/k,x7/5,pl/f,x9/14,s9,x0/3,s9,x8/4,s15,pd/g,x2/12,pb/p,x13/11,s14,x3/10,s7,x12/8,s6,x1/5,pc/k,x3/12,s3,x8/13,po/l,x6/3,s4,x9/1,pn/f,s11,x5/13,s2,x4/15,pj/k,x12/9,pl/o,x11/14,s11,x15/1,s6,x12/14,s12,pb/h,x2/4,po/g,x6/3,s4,x14/15,pa/b,x1/0,s14,x6/11,s3,x13/0,s7,pp/l,x6/7,s2,x10/5,s9,x12/2,po/k,x9/15,ph/a,x4/8,s6,x1/9,pf/m,x4/12,s5,x5/2,pj/n,x3/15,s3,x1/7,pm/g,x11/12,s3,x10/2,pf/c,x9/6,pa/n,x7/15,s14,x3/4,s8,x15/10,s10,x9/8,pm/l,x3/6,s10,x8/4,s5,x14/15,s14,x1/4,s4,x9/5,s10,x6/13,s7,po/p,x9/12,s2,x13/6,pf/j,x10/1,s3,x11/0,s2,x14/3,pk/a,s10,x5/8,pb/g,s11,pk/a,x6/7,pm/c,x9/14,s8,x12/6,pf/d,x11/8,pm/i,x4/13,pc/a,x8/10,pn/b,x3/12,s7,pg/f,x5/2,pl/b,s5,x8/0,s4,x14/11,pg/p,x3/12,s4,x10/5,pj/o,x13/7,pp/m,x3/10,s8,x9/4,pl/e,x14/10,pi/o,x13/4,s12,x11/8,s7,x0/2,s10,x4/15,s1,x0/10,pe/j,x15/13,pl/c,x6/12,s6,x4/10,ph/i,x12/11,s9,pc/l,s3,x10/2,s12,x6/0,po/f,x2/13,s5,pg/j,x5/6,s8,x3/8,s6,x9/11,pd/i,x5/13,po/p,x2/0,s11,x13/3,pf/j,x1/9,s11,x13/8,s5,x4/12,pl/i,x3/5,pe/h,x4/14,pn/d,x13/15,s13,x4/10,pb/l,x9/7,s10,x14/0,s9,x4/13,pd/n,x14/7,s13,x5/2,pf/g,x4/9,pb/c,s6,x15/12,s7,x5/10,s15,x4/14,po/l,s7,x15/0,ph/a,x14/5,pb/l,x0/10,pc/j,x14/7,s3,x8/12,s11,x15/0,s14,x10/13,s2,x9/1,pb/m,x14/3,s12,x10/8,pg/n,x15/0,s9,x9/10,pi/m,x0/12,s13,x7/6,s11,x15/8,pf/g,x12/2,s7,x6/1,s4,x2/9,pp/i,x14/8,s6,x6/11,pd/g,x2/13,s8,x0/10,pl/e,x3/14,s5,x15/13,s10,x10/11,s6,x12/9,s6,x8/1,pj/i,x2/14,pd/b,x4/3,s9,x6/1,s12,pj/f,x7/15,s12,x13/8,s8,x4/12,s4,x6/2,pb/p,x5/4,pn/f,x10/1,pb/a,s10,x7/13,s7,x0/4,pk/m,x9/3,s9,x14/5,s10,x13/15,s2,x8/2,s7,x1/3,pg/b,x2/0,s11,x3/1,s15,x10/14,s12,x0/6,s11,x8/14,pa/o,x3/7,s11,x5/14,pi/f,x10/6,s13,x14/8,pk/c,x4/3,s12,x9/2,s2,x3/1,s1,x5/15,s8,x3/8,s10,x10/11,s10,x14/3,s3,x15/7,pb/j,x8/11,s9,x5/6,s13,x12/13,s13,x1/10,pd/k,x11/14,s5,x13/10,ph/n,x5/6,s7,x14/11,pa/k,x12/6,s15,x4/15,po/d,x8/12,s7,x2/11,pa/b,x6/12,s9,x3/11,s8,x12/1,pl/e,x10/7,s10,x8/4,s10,x6/12,s13,x8/7,pk/m,x10/12,s9,x8/2,pa/i,x14/9,s12,x6/11,pn/m,x13/1,s12,x14/6,pi/g,x0/11,s2,x6/15,s1,x4/12,s7,x1/11,s2,x7/12,s12,x15/14,pp/h,x8/1,pi/o,x7/13,pc/a,x14/0,s5,x2/7,s8,x5/8,pg/k,x12/10,pj/o,x11/8,pl/d,x6/4,s15,x14/12,pj/k,x15/9,s15,x0/1,pf/o,x8/4,s14,x13/14,s12,x3/15,s1,x0/6,s8,x9/3,pk/n,x2/11,s11,x1/4,pf/c,x6/7,pb/n,x11/14,s9,x7/2,s11,x3/12,pi/d,x9/2,s6,x12/7,s15,x3/11,pc/g,x6/10,pi/e,x0/11,s6,x9/13,s1,x11/1,ph/g,x15/10,pj/a,x14/6,s10,x8/13,s8,x9/0,s5,x13/1,pb/i,x15/2,s6,pp/a,s4,x4/13,pj/h,x7/5,s6,x15/14,pm/o,x4/7,s1,x3/12,pp/a,x11/4,pg/d,s14,x10/13,s15,x1/12,s11,x5/7,pp/k,x12/1,s15,x11/5,s12,x3/6,pl/c,x14/2,s3,x15/4,pb/m,x3/1,pa/h,x5/6,pf/j,s13,x15/10,ph/e,s3,x5/11,pi/f,x15/10,s11,x7/14,pj/a,s12,x6/13,ph/c,x1/12,pg/i,x6/8,pp/f,x10/4,pg/d,x14/6,pp/b,x5/3,s6,x8/11,s10,x9/1,pe/m,x2/14,s3,x7/9,pl/b,x10/2,pf/p,s1,x15/0,pb/j,x9/8,s10,x5/10,s14,x4/2,s8,x12/1,s12,pi/d,x11/13,po/c,x4/10,pi/d,x15/7,s11,x10/8,pj/m,x7/9,pb/d,x8/5,po/f,x7/2,pe/h,x10/13,pb/i,x9/4,pm/l,x6/3,s3,x4/12,s2,pd/o,x8/5,pa/p,s14,x1/14,s1,pi/d,x2/12,pl/o,x1/13,s3,pp/f,x7/9,ph/j,x0/2,pm/e,x11/4,s13,x12/6,pj/b,x3/8,pk/a,x5/6,s10,x10/11,pe/o,x12/9,pj/p,x0/5,s11,x14/9,pe/f,x3/4,pa/p,s14,x6/0,s11,x8/3,pd/f,x11/5,s14,x9/2,s7,pg/n,x0/14,pj/c,x4/3,s11,x14/2,s1,x0/7,s11,x8/2,s13,x12/3,s11,x9/7,s14,x10/2,s9,x1/12,pi/o,x14/3,pc/b,x7/8,s7,x11/14,s4,pp/l,s5,x2/8,s11,x11/9,pk/e,x5/1,s15,x2/14,pb/d,x11/7,s15,x13/15,pk/o,x5/4,s4,x6/2,pc/p,x8/9,pj/f,x5/10,pb/i,x9/8,s10,x6/10,pj/a,s7,x5/8,s2,x13/14,s12,x11/10,s6,x5/4,pb/p,x1/10,pc/d,x6/12,pm/o,x9/15,s4,x14/2,s7,x12/8,s14,x3/1,pp/b,s2,x8/2,s4,x15/0,s14,x7/11,s4,x5/13,s11,x10/7,s8,x2/9,pe/d,x0/1,s13,pm/f,s10,x3/15,ph/l,x9/11,po/e,x15/1,pg/p,x4/0,pn/b,s12,x13/12,pm/l,x6/4,s11,x3/2,s6,x0/4,pe/p,s4,x8/7,s12,x4/3,s11,x12/10,s1,x9/6,s14,x15/13,s14,x0/4,pc/m,x9/7,s9,x11/13,ph/j,x14/1,pc/m,x11/0,ph/o,x4/15,s14,pp/f,s7,pi/b,s10,x11/12,s4,x4/9,s14,x10/13,pg/l,x1/12,pn/f,x5/8,s15,x15/12,ph/m,x14/3,pl/e,x9/5,ph/i,x4/8,s6,x9/11,s10,x13/1,s9,x0/12,pc/k,x13/4,s9,x1/7,s9,x0/15,pb/l,x12/5,pm/p,x0/8,ph/c,x5/7,s8,x11/14,s6,x0/5,pm/g,x1/12,s4,x5/8,pf/c,x6/15,s10,pb/a,x14/5,s1,pj/e,x3/4,s4,x12/15,s8,x13/3,pa/d,s14,x6/9,po/e,x5/13,s10,x12/10,s2,x0/3,pp/b,x5/15,s15,x12/14,s7,x2/7,pj/d,x0/11,pb/l,x14/8,s14,x13/2,s2,x4/7,pp/g,x11/8,s8,x3/9,pb/l,x1/10,s9,x7/0,po/g,x12/15,pd/h,s4,x10/13,s14,pm/g,x5/9,ph/e,x7/4,po/j,x5/9,s13,pg/d,x2/13,pi/n,x7/14,s14,ph/c,s2,x4/3,pl/o,x10/0,pa/k,x12/2,pd/i,x15/1,pl/n,x4/2,pe/j,x14/3,s14,x12/13,pf/n,x5/2,pa/e,s5,x11/14,s2,pc/h,x9/7,pa/d,x14/8,pc/b,x9/3,s1,pe/h,x1/11,s15,x13/2,s10,x14/1,s1,x15/2,s3,x14/7,s14,x15/1,s5,x10/2,s3,x13/15,s9,x1/4,s5,x10/8,s6,x5/14,s7,x7/6,pj/m,x8/14,s6,x10/6,pa/h,x11/13,s7,x12/9,s5,x5/2,pi/d,x6/0,pg/a,s14,x2/14,s13,pd/n,s4,x15/9,s2,x2/12,pa/f,x4/8,pi/d,x6/15,pa/g,x9/13,pc/b,x3/4,s6,x0/10,s10,x13/12,s1,x6/14,s11,x5/11,s5,x8/1,ph/i,s12,x13/11,s6,x9/1,pe/c,x12/10,pl/g,x9/5,s3,x8/3,pe/d,x6/11,s12,x12/10,s4,x8/5,s6,x0/4,s10,x9/13,pg/n,x5/14,s5,x1/6,pc/j,x11/2,s2,x3/8,s11,x5/6,s12,x0/10,pf/a,x3/11,s2,x4/8,pp/e,s7,x5/1,s4,x6/0,s6,x4/1,s6,x15/6,pi/j,x13/10,s14,x8/7,pp/f,x10/2,s12,x0/6,pk/d,x5/13,s1,x2/9,s3,x15/8,pi/b,s14,x10/0,s2,x7/5,s14,x12/15,s3,x13/11,pe/m,x14/0,s11,x4/3,s3,x15/1,po/b,x0/9,pn/f,x5/1,s12,x12/2,s5,x1/5,pg/i,s5,x11/13,pd/m,x9/6,s11,pp/i,x2/3,s15,x5/14,ph/k,x12/2,pg/m,s6,x10/14,pj/n,x12/3,s12,x14/10,s12,x15/9,pg/p,s5,x6/4,s10,x7/10,s9,x3/0,pa/h,x4/12,s13,po/f,x1/8,s9,x13/11,pi/n,x7/14,pp/o,s15,x10/4,pl/d,x1/6,s12,x5/0,s1,x2/9,pa/c,x11/15,s10,x7/1,ph/b,x4/14,s1,x11/8,pn/a,x10/5,pl/j,x11/3,s9,pi/p,x4/0,s7,x15/12,pk/d,x2/7,s5,x10/6,pa/h,x7/12,pe/c,x3/9,pa/d,x11/0,s7,x4/13,s10,x12/15,s14,ph/n,x4/8,pg/d,x5/10,s15,x0/13,pp/c,x5/9,s11,x0/11,s13,x4/15,s11,x13/7,s1,x4/8,s12,x5/7,s6,pj/d,x13/14,pm/e,x2/11,s8,x3/0,pl/i,s11,po/f,x11/12,pe/g,x14/15,pb/f,x4/8,pi/p,s11,x9/2,pn/b,x1/6,s3,x10/15,pa/p,x1/14,pi/h,x0/8,s4,x9/1,pe/d,x5/6,s5,x15/8,pa/n,x4/0,pc/b,s6,x13/12,s10,x4/2,pd/f,x9/5,s1,x3/10,pm/n,s6,x14/4,pk/l,x2/10,pe/n,x1/12,pd/i,x5/6,s7,pn/l,x15/7,s9,x8/11,pi/a,s4,x9/5,s13,x6/8,s6,x4/13,s2,x11/12,pk/l,s7,x10/5,ph/e,x4/2,s3,x14/15,s11,x0/1,pp/l,x7/10,s7,x3/12,s1,x7/6,pc/f,x5/13,pn/e,x10/8,s11,x6/2,pm/f,x8/3,pk/g,x1/9,po/p,x3/5,s2,x2/1,pd/i,x0/5,s3,x7/6,pc/b,x3/0,s11,pf/m,x12/8,s1,x1/3,pe/g,x0/12,s1,x15/5,s13,x6/4,s7,x0/7,s5,x14/9,s3,x10/12,s14,x4/7,s6,x9/15,s3,x10/11,pk/c,x7/4,s6,x8/13,s6,x5/6,s2,x12/14,pn/d,x1/10,pj/b,s14,pd/l,x5/14,s12,po/m,x9/11,pl/f,x15/3,ph/j,s8,x6/11,s8,x1/9,s3,x0/13,pf/o,x2/6,s1,pl/k,x12/4,pp/o,x8/0,pj/n,x4/15,s2,pe/c,x6/13,s3,x0/10,s5,x8/6,s10,x5/12,pf/p,s5,ph/b,x4/15,pl/i,x10/0,pa/g,s14,x3/12,pe/o,s6,x5/6,pl/g,x8/1,s7,x6/12,pp/h,x4/14,s8,x8/11,s6,x12/4,pj/e,x3/8,s15,x9/14,ph/k,x0/3,s9,x14/6,pi/f,x5/15,s13,pd/j,x11/14,s8,x6/5,s11,x3/1,s1,x2/13,s11,x7/1,pa/p,x8/11,s4,x15/6,s14,pg/e,x13/5,s8,x1/10,s8,x8/6,s3,x13/4,s8,x6/8,pj/h,s14,x10/3,pn/b,s12,x4/5,s7,x0/1,s3,x15/4,s5,x5/8,s3,x7/3,pf/c,x5/11,s15,x14/4,s5,pk/d,x0/15,pj/l,s11,x10/7,s8,ph/p,x2/5,s9,x6/9,pi/n,x3/0,pj/p,x11/1,s15,x8/3,pm/g,x9/1,pd/j,x15/3,s14,x0/9,s9,pc/h,x1/6,pl/k,x11/7,s13,x4/13,pe/b,x15/5,pk/d,s13,x8/12,pe/b,x9/1,po/i,x15/2,s11,x11/4,pj/g,x5/12,s10,x10/2,s9,x0/8,s5,x5/6,pn/p,x0/10,s2,x13/14,s2,x7/2,s4,x6/9,s6,x1/14,pj/g,s11,x3/9,s8,x14/13,pi/b,s15,x3/10,pe/f,x13/12,s14,pj/d,x3/2,pm/f,x13/10,pk/j,x5/11,pc/d,x13/8,pp/i,x11/6,s8,x7/0,s14,x3/1,s13,x2/13,s7,x6/8,s2,x7/15,s4,x10/14,s13,pb/n,x2/6,pj/h,x15/10,s14,x13/1,pb/d,x0/5,s10,x14/3,s9,x12/5,s1,x7/4,pn/e,x9/2,pf/k,s2,x12/1,s11,x5/2,s15,x8/7,s4,x12/1,pj/n,x0/7,pf/k,x11/2,s11,x15/3,pe/m,x0/4,s11,x5/8,s4,x10/15,s7,x2/14,s2,x11/5,s9,x7/6,pj/n,x11/13,s5,x2/10,s11,x15/8,s11,x11/13,pi/b,x3/8,pm/e,x9/5,s14,x4/3,s7,po/j,x12/10,s4,x14/0,s15,pi/a,x7/4,pg/n,x3/1,s3,x11/14,ph/m,x13/12,s11,x2/14,s13,x0/10,s11,x9/12,s13,x3/7,s4,x9/12,s15,x5/3,s5,x10/15,s2,x4/13,s14,x9/10,pj/p,x11/2,s14,x5/10,pn/m,x9/7,s3,x8/10,s7,x15/4,ph/f,x9/5,s15,x8/10,pi/g,x9/12,s14,x14/10,po/h,s13,x9/15,pc/n,x12/10,s7,x6/3,s13,x5/13,s8,x8/2,pd/b,s11,x7/12,s12,x10/13,pp/g,x12/9,s1,x11/13,s15,x1/14,pd/c,x0/10,pp/f,x4/15,s2,x12/8,pl/e,x0/6,s10,x4/2,s12,x5/10,s11,x8/7,pm/p,x6/14,s9,x0/11,s4,pc/d,x5/1,pe/k,x4/9,s9,x7/0,pb/j,x8/15,s10,ph/c,s11,x14/5,pe/d,x0/3,pm/g,x6/15,s15,x9/4,pj/e,x0/12,pn/h,x6/1,s4,x7/10,s14,x6/4,s4,x11/9,s9,x4/3,pg/a,x1/11,pc/e,x9/14,s5,x7/4,pg/d,x5/11,pm/n,x9/4,s14,x7/6,pe/l,x8/3,s5,x0/15,pp/g,x7/6,po/c,x14/12,s1,x2/11,s11,x9/0,s10,x5/1,s10,x10/6,s4,x3/13,s15,x10/8,s15,x13/1,s10,x10/5,s3,x9/15,s7,x8/5,pa/i,s14,x4/10,s10,x14/7,ph/p,s3,x2/13,s10,x1/14,s4,x11/0,s13,pb/j,s9,x7/8,pd/e,x1/14,pa/m,x6/2,s15,x15/13,s14,x10/0,s5,x2/4,pp/f,x8/9,pg/h,s3,x11/1,pa/l,x10/0,s3,x15/12,pp/e,x3/4,s8,x5/15,pi/m,x6/2,s8,pk/e,x13/11,pm/n,x2/0,s3,x15/3,s10,pf/i,x7/9,s1,x3/8,s9,x12/2,pn/d,x6/7,pe/j,x9/15,s8,x7/4,s3,x0/14,po/k,x12/7,s7,x13/6,pd/b,x9/8,s15,x7/5,s13,x9/15,pl/a,x5/6,s13,x13/3,s7,pm/c,x14/0,s9,x10/13,pj/b,s8,x4/14,s7,x15/5,s6,x2/4,pd/i,s4,x6/11,pk/h,x3/12,s12,x14/5,s1,x15/6,s3,x3/12,pb/e,x5/8,pm/n,x0/15,pe/b,x1/13,pn/p,x4/12,s11,x15/8,s8,x9/3,pa/b,x13/12,s5,x2/5,s14,x0/14,s3,x3/6,s9,x12/5,pp/e,x15/13,s7,x1/9,pd/o,x7/14,s11,x15/2,s1,x1/4,s13,x0/13,pg/f,x11/6,pl/m,x10/5,ph/k,x14/8,pn/c,x15/6,s12,x11/9,s10,x7/8,pb/d,x2/5,s11,x14/3,pp/g,x6/0,s12,x12/11,s6,x15/6,s7,x11/12,pd/o,x8/3,s9,x5/6,s3,pl/f,x1/2,s7,pp/i,x7/8,s10,x9/2,s13,x5/15,s4,x6/0,s11,x5/10,ph/k,x15/0,s10,x13/8,pd/n,x11/7,pa/f,s12,x2/3,s14,x5/12,pp/m,x3/10,s14,pn/o,x8/13,s1,x4/6,pi/a,x9/1,s7,x2/5,s8,x11/14,s5,x7/6,s7,x12/1,s12,x9/13,pp/k,x0/3,s13,pm/h,x2/9,pn/f,s10,x3/14,s5,x10/6,s7,pc/b,x3/2,pm/p,x12/10,s6,x4/14,s8,x8/9,s7,x13/2,s11,x14/11,pc/g,x6/9,pj/m,x2/3,pl/e,x14/15,po/j,x12/1,s9,x10/3,pc/p,x2/0,s9,x6/5,s13,pi/e,x10/12,s9,x3/6,pk/g,x14/5,s1,x3/2,pf/j,x14/13,s12,x6/9,s6,x13/10,s2,x15/4,s8,x14/1,s11,x3/11,s3,x6/8,s12,x0/14,s2,x1/12,s13,x3/14,pa/n,x12/8,s12,x15/3,s11,x4/8,s3,x10/9,pe/b,x1/14,s9,x3/8,s11,x12/15,s5,pd/i,x7/2,s8,x11/6,s11,x10/9,s3,x15/3,ph/o,x10/2,s7,x0/6,pa/m,s13,x2/9,s10,x11/0,s6,x15/5,s2,x10/14,s12,x6/2,s2,x4/5,s5,pd/c,x0/8,pk/b,x6/3,pi/a,s8,x10/13,pb/g,x8/5,s14,x10/2,pm/n,x7/9,s14,x6/13,s12,x4/5,pi/o,x12/1,pd/b,s12,x13/11,s12,x14/12,pl/h,x4/6,pd/o,x7/3,s3,x2/10,s15,x3/14,pm/n,x10/7,pj/f,x8/14,s5,x2/15,pl/e,x11/8,s12,x2/15,s8,pp/k,x14/13,s15,x9/11,s3,pa/m,x8/13,pj/c,x6/7,pe/p,x1/11,s1,x3/10,s8,x7/12,s5,x0/11,pj/d,x13/2,s12,x6/8,s11,x7/9,s7,x11/15,s6,x2/0,s1,x3/9,s12,x15/7,pn/h,x0/11,s7,pf/a,x12/4,s7,pj/i,x9/3,s2,x1/4,s9,x11/13,s13,x4/12,s7,x3/15,pn/d,x11/10,po/e,x13/5,s8,pd/a,x7/10,s1,x13/3,s15,x9/12,s1,pk/m,x15/13,s13,x12/0,pa/h,x1/8,s5,x9/14,pb/e,x0/8,s12,x2/5,s7,x8/7,pj/c,x4/3,s15,x14/15,pp/b,x7/4,ph/j,x12/15,pd/b,x2/3,pg/p,s11,x11/12,s12,x1/13,s1,x6/7,po/k,x14/10,s12,pj/e,x8/15,pk/g,x9/3,pn/m,x4/10,s15,x2/14,pa/f,x3/9,s7,x4/0,s11,x11/13,s15,pm/i,x7/9,s15,x3/2,s7,x12/0,pa/c,x15/10,pf/n,x6/8,s12,x3/10,pa/m,x5/1,s2,pe/c,x4/7,s4,x6/8,s8,pl/i,x10/11,s3,x3/14,s4,x2/15,ph/k,x1/5,s8,x3/6,pe/p,x11/1,s9,x6/10,s2,x14/8,s6,x5/15,s6,x11/4,pm/i,x7/10,pd/l,x2/11,s9,x8/10,s13,x11/12,pn/a,x14/6,s8,x3/0,pm/o,x13/2,s6,x4/8,s1,x7/2,pd/i,x12/0,pm/c,x11/5,s7,x9/6,pa/o,x0/15,s10,pg/l,s1,x11/13,pk/m,x1/7,s4,po/a,x0/3,s4,x2/1,pk/l,x6/8,s5,x2/9,pc/h,s13,pl/i,x7/5,s4,x3/6,s13,x10/1,pk/o,x11/4,pi/n,x0/6,ph/m,x12/13,s15,x5/3,s3,x15/2,s13,x3/0,pc/k,x1/9,pp/e,x12/4,s10,x3/13,pm/d,x8/10,s2,x0/3,s7,x6/12,pg/h,x8/14,pi/e,s13,x6/1,s2,x14/0,s9,x8/1,pl/o,x5/11,pc/m,x15/9,s10,x4/8,s8,x0/7,s6,x4/2,s9,x12/5,pl/j,x15/7,s11,x1/2,pa/k,x3/9,s11,x12/5,pn/i,x14/9,s13,x1/15,s6,pe/p,x9/12,pb/a,s11,x11/0,s6,x14/6,ph/g,s7,x3/2,pe/c,x6/10,s11,x12/9,pi/p,x1/14,pf/g,x12/2,s11,x5/1,pj/a,x8/7,s6,x2/4,s3,x11/15,s13,x3/2,s5,x9/0,s7,x6/5,s7,x8/10,s5,x0/13,pm/h,x2/5,s11,x9/1,s1,x10/14,s4,x15/6,pn/o,s7,x11/13,ph/k,x6/1,s5,x0/4,pc/p,s15,x6/7,pm/n,x2/9,pb/a,x0/5,s13,x15/2,pm/c,x12/4,pn/b,x13/6,s6,x0/15,s5,x10/7,s6,x1/9,s4,x11/4,s3,pa/k,x7/6,pe/i,s11,x9/12,pl/p,x13/1,pg/n,s6,x12/10,s9,x11/3,s14,x6/5,pl/m,x0/9,pe/h,x11/10,s11,pf/l,s7,pk/h,x14/5,s12,x15/13,s11,x12/4,s4,x8/6,pb/g,x0/10,s12,x2/15,s3,x7/3,s9,po/e,x11/12,pp/i,x14/0,s3,x10/1,pc/n,x15/3,s9,po/h,x7/10,s15,x15/13,s11,x7/2,pb/f,x11/9,s12,x8/14,pc/p,x11/0,s7,x7/1,pf/b,x3/2,s2,x9/7,ph/a,x2/0,s11,x4/14,s1,x13/15,s9,x6/12,s8,x11/13,s3,x7/10,s6,x0/1,pf/c,x8/5,pn/k,x2/7,pf/d,x5/15,s14,x4/10,s13,x2/0,s14,x13/9,s14,x6/2,s13,x12/4,pa/b,x5/13,s5,pg/m,s3,x1/11,s11,x6/4,pn/d,x11/1,pb/c,s15,x5/14,s2,pf/k,x3/7,pa/i,x10/8,s13,x15/1,s6,x10/9,s14,pd/o,x12/14,pi/h,x6/7,s8,x2/8,s9,x7/14,s5,x13/1,s5,x8/9,s10,x10/2,s3,x1/3,s10,x0/10,s2,x12/13,s11,x3/15,s4,x1/14,s14,x6/11,s11,x12/7,s2,x3/6,s2,x9/8,pn/c,x2/1,pf/e,x12/13,s9,x15/7,pd/n,x0/12,po/f,s1,x15/6,s12,x1/4,s8,x11/15,s5,x9/8,s12,x6/0,pm/a,x15/14,pl/o,x10/0,s5,x15/6,s11,x1/11,pe/c,x0/6,pk/l,x15/4,s2,x5/14,s5,x15/13,s9,x1/3,s15,x2/11,s6,x5/3,s5,x4/2,s6,x14/12,pm/o,x8/9,s3,x6/3,pf/n,x2/9,ph/l,x12/0,pj/e,x15/7,s11,pk/b,x2/4,pd/e,s13,x11/7,s6,x12/0,pc/p,x15/6,s13,x3/7,s7,pa/f,x9/12,pi/d,x4/2,s9,x13/15,pa/k,x5/1,pe/n,x11/0,s1,x14/3,pl/j,x4/12,s6,pg/n,s3,pd/b,x5/10,pc/e,x14/3,s6,ph/p,x1/0,s5,x11/4,pk/d,x6/12,s5,x7/3,s7,x14/6,pa/c,x15/5,s14,x13/14,s2,x15/6,s11,x13/11,pg/i,x12/1,s15,x0/13,pa/e,x12/4,po/p,x1/15,pi/c,x7/3,pd/e,x8/12,s13,x6/0,s1,x5/7,pc/k,x2/1,pp/j,x5/3,s13,ph/i,x4/7,pa/m,x8/15,s15,x11/13,s14,x9/2,s1,x6/13,s14,x5/0,pe/c,x1/13,s15,x5/6,s3,x4/9,s12,x0/1,s10,x12/6,s5,x9/3,s6,x5/8,s12,x15/4,s3,x10/3,s2,x5/8,pd/b,x3/13,s10,x6/10,pa/g,x14/1,pe/k,x5/8,s1,x1/11,s13,x10/15,pa/o,x0/1,s13,x5/12,s10,x14/4,pf/j,x5/12,pi/k,x0/3,s12,x10/9,s4,x2/6,pl/f,s7,x11/5,s6,x8/7,pc/k,x0/2,pi/g,x3/9,pd/l,x2/7,pg/c,x6/8,s14,x13/9,pb/o,x4/8,s12,x1/10,s13,x4/13,ph/d,x11/1,pk/m,x9/3,pe/p,x12/4,s13,x13/6,s14,x12/14,s10,x2/1,pb/c,s6,x12/4,s3,x1/2,s8,x3/9,s3,x8/2,s13,x12/1,pa/e,x9/15,pi/j,x11/8,s2,x6/1,s10,x12/5,s15,x8/2,pf/e,x12/4,pb/c,x15/6,s11,x13/11,pl/p,x1/14,s15,x8/3,s9,x10/1,s13,x11/7,s4,x9/2,s6,x8/10,s4,x4/15,pa/n,s15,x1/3,s1,x7/13,s9,x4/9,s10,x11/14,s8,x2/3,ph/k,x13/7,s4,x4/14,s1,x15/13,pj/o,x10/7,s14,x8/6,s13,x14/1,pe/d,x11/12,s14,x9/8,pj/h,x6/13,pm/d,x3/4,s14,pi/o,x1/5,pg/e,x14/3,s6,x2/15,s10,x14/13,s14,pi/a,x11/12,s6,x13/6,pl/j,x15/8,s2,pe/h,x0/10,s15,x14/2,pb/d,x4/6,s2,x5/14,s6,pg/o,s12,x10/13,pe/d,x14/15,s3,x9/1,pg/l,x2/4,s15,x3/10,pp/h,x5/2,s9,x14/0,pg/d,x15/5,s5,x9/11,s15,x1/13,pc/i,x5/15,s6,ph/g,x7/11,s9,x5/13,s15,x2/15,s2,x3/14,pk/o,x4/5,pj/l,x2/1,s15,x11/14,pp/f,x15/13,s4,x8/11,s4,pa/j,s15,x13/10,s15,x7/1,s1,x15/6,pb/c,x5/3,pi/h,x13/12,pg/e,s2,x5/15,pc/b,x4/13,pe/f,x15/2,pd/l,x6/14,s15,x1/13,ph/b,x15/10,s11,pp/a,x5/8,ph/d,x11/9,s15,x5/13,pn/j,s1,x3/7,s9,x9/12,s2,pk/m,x8/2,s6,x12/4,s2,x5/14,pf/b,x15/7,s9,x3/6,pj/e,s4,x1/13,pg/m,x7/12,s12,x8/15,pp/l,x10/13,s6,x12/5,s12,x4/0,pm/n,x10/8,pa/k,x14/9,pp/j,x15/7,ph/d,x11/6,s13,x13/12,s13,x14/15,s8,x4/8,s12,x13/3,s8,x10/9,s2,x7/8,s8,x14/2,s11,x10/11,pc/n,x4/13,pl/j,x5/15,pn/a,x12/0,s10,x8/11,pd/h,x1/15,s9,x0/8,pe/n,x14/12,s15,pa/h,x2/13,s7,x7/9,pg/m,x1/8,s13,x0/5,s8,x15/8,pd/n,x3/12,pm/o,x13/10,s11,x7/3,s12,x12/4,s14,x3/7,s13,x9/1,pk/b,x11/0,s11,pp/e,x4/8,pm/f,x14/5,s14,x4/10,s11,x11/12,s6,x13/2,s4,x10/0,s5,x7/4,s14,x15/1,s12,x2/12,s3,x9/13,s10,x12/3,pb/e,x8/7,pa/m,x10/6,pk/f,x14/7,pg/b,x0/12,s6,x7/3,s14,x8/2,s9,x7/3,s10,x2/6,pp/h,s4,x8/4,pi/f,x3/6,s5,x7/8,pk/l,x12/1,pi/g,s4,x3/7,s13,x2/13,pd/e,s2,x1/0,s8,x6/3,s3,x4/7,s2,x12/13,s4,x7/11,s3,x12/2,s1,x8/13,pk/m,x2/15,s12,x8/0,s4,x14/12,pb/p,x5/8,s11,x14/12,ph/f,x0/2,pe/n,x8/4,s3,x5/2,s10,x8/9,s5,x13/7,po/l,x8/11,pm/h,x1/9,s8,x14/4,s3,x2/6,s5,pk/f,x15/0,ph/g,s12,x12/1,s7,x14/11,pb/a,x12/8,s11,x4/6,s6,x8/9,s3,x2/1,pn/j,x0/9,s6,x15/5,pc/o,x12/4,pi/a,x13/8,pn/p,x7/9,s4,x6/15,pd/f,s2,x5/9,s4,x3/15,s10,ph/o,x0/12,pn/e,x13/14,s15,x4/12,pf/g,x11/0,s14,x15/9,s1,x1/12,pl/k,s13,x14/8,pp/j,x12/5,pl/f,x7/1,s11,x11/9,s9,x8/6,pb/m,s12,x9/2,s13,x7/1,pf/i,x13/11,pg/j,x10/1,s1,x0/14,pi/p,x5/12,s3,x15/3,s8,x13/8,pf/n,x3/4,s12,x10/8,pp/g,x2/11,s6,pa/c,s10,x1/8,pd/m,x6/12,ph/l,x1/11,pd/p,x12/15,s9,x3/2,s14,x7/6,s13,x10/12,s5,x3/6,s9,pb/n,x5/9,s3,x12/13,s8,x11/0,pc/f,x7/14,pa/m,x11/13,s10,x5/14,s4,x2/11,s4,x14/1,s7,x13/8,s5,x12/5,s13,x0/10,s1,x13/4,s9,x11/14,pj/c,x0/10,s3,x1/5,po/b,x13/11,s4,x5/3,s1,x1/6,pk/m,x13/3,s14,x0/5,pj/h,x14/13,s8,x11/5,s11,x8/12,pp/g,x3/2,pl/m,x5/11,s12,x9/10,s1,x1/13,s11,x3/7,pa/p,x2/4,pn/e,x10/9,s4,x1/6,s11,x3/8,s11,x10/5,s1,x8/11,s14,x4/0,s11,x5/8,pf/c,x4/2,pd/m,x12/6,s3,x8/2,s13,pf/l,x6/13,s11,x5/15,pi/e,x6/10,pb/l,x9/5,s14,pe/o,x10/6,pg/d,x11/8,pn/m,x1/2,pf/c,x4/9,pk/m,x5/15,s1,x12/11,pn/i,x14/6,s13,x0/5,s14,x6/8,s4,x12/0,pe/m,x10/15,pc/p,x3/8,pn/e,x11/0,s14,x7/13,s5,x10/14,pa/o,x3/13,s5,x11/10,pf/m,s11,x5/3,s9,x4/8,s9,x3/1,pp/l,x0/4,pc/j,x13/7,s5,x4/2,pa/d,x1/6,pc/l,s13,x7/4,s12,x3/10,pk/a,x14/7,s7,x11/5,s12,pe/j,x13/14,s2,x7/11,s4,x6/10,s10,x5/8,pn/h,x0/2,pb/j,x12/4,po/a,x5/7,pd/l,x0/15,s10,x1/6,s9,pj/h,x2/12,pf/o,x7/13,s11,x14/11,pi/m,x1/15,pf/j,x13/3,pl/k,x2/8,s3,x5/3,s11,pg/f,x13/4,s15,x3/1,pl/h,x12/15,pj/b,s13,x9/2,pl/o,x5/4,pi/f,s9,x2/3,s3,x0/13,s12,x4/12,ph/o,x3/11,pa/p,x7/14,s6,pd/b,s8,x6/0,pp/g,x15/10,pm/l,x6/8,pd/o,x7/12,s7,x8/10,s6,x2/5,s1,x0/10,s8,x5/2,s2,pl/k,x12/14,s14,x15/11,s13,x3/7,ph/n,x9/15,s13,x7/13,pl/m,x9/10,s9,x1/0,s4,x8/2,pk/b,x10/15,s15,x6/14,s8,x13/11,s9,x6/9,pl/m,x1/8,ph/a,x9/2,s6,x5/12,pm/i,x10/6,pd/n,x5/14,s4,x4/15,pa/p,x3/9,s6,x12/5,po/m,x13/0,pf/g,x15/5,s13,pa/c,x8/10,pd/f,x2/14,s13,x11/3,pa/c,x7/0,s15,x4/5,s5,x3/12,s13,x10/8,s14,x5/11,s12,x1/9,s12,x3/2,pe/b,x6/5,s5,x2/8,s11,x7/10,po/k,x4/8,pc/a,s4,x12/11,pj/b,x4/3,s13,x5/0,pk/e,x15/11,pp/f,x10/6,pe/c,x11/8,s3,x9/5,pn/i,s14,x6/10,pp/g,s9,x5/8,po/h,x13/10,s1,x11/2,s6,x9/7,s4,x6/11,s8,x0/15,s12,x14/4,s1,x6/8,pp/m,x9/10,s10,x3/5,s1,x1/13,s8,x0/14,pa/g,s9,x8/1,s1,x4/13,s5,x9/7,pd/f,x6/12,pp/c,x11/5,pb/k,x0/14,ph/m,x4/5,s7,x0/7,pe/p,x10/5,s4,x9/11,s7,pf/m,x13/14,ph/d,x15/7,s2,pc/b,x14/13,pk/g,x3/5,pa/o,x11/2,pg/k,x3/0,pf/a,x1/13,pm/l,x11/4,s13,x13/3,pn/k,x1/5,pc/o,x4/15,s10,pd/h,x1/14,s9,x6/7,pl/f,x13/8,s3,x4/0,pc/m,x3/1,pk/f,s2,x15/14,s9,x5/6,s1,x12/0,pl/c,x7/10,s5,x4/15,pb/m,x8/11,pg/k,x13/3,s5,x12/9,pe/n,s5,x5/2,pl/m,x4/15,pb/i,x1/13,pl/d,x15/12,po/m,x10/14,s10,x0/15,pk/p,x4/8,s12,x10/13,ph/g,x0/1,s11,x4/2,s15,x1/8,pf/b,x6/13,s1,x2/15,po/l,x12/9,s15,x13/6,s5,x14/8,s10,x0/11,pc/g,x12/4,ph/i,x9/5,pk/o,x13/15,pb/m,x11/5,s6,x0/7,pe/c,x6/3,s13,x14/4,ph/b,x9/6,pa/d,x3/4,po/i,x13/14,pl/m,x2/0,s7,x7/12,s5,x4/14,s5,ph/p,x11/7,s13,x9/1,s15,x3/15,s1,x8/6,pa/e,x1/11,s3,pb/c,x5/13,pn/o,x0/12,pb/g,x13/6,po/f,s9,x5/3,s12,x11/10,pb/j,x8/2,pd/g,x5/15,po/f,x8/12,pl/i,x1/9,pb/c,x5/11,s6,x4/2,s14,x0/3,s10,x4/1,s5,x11/13,pi/k,x3/8,s12,x12/5,s5,x13/6,ph/f,x4/7,s15,x2/6,pa/p,x1/12,s15,x7/0,pl/o,x5/4,ph/g,x10/9,s3,x1/8,s15,x10/11,pk/i,x9/14,s9,x0/6,s11,x14/4,s12,pl/a,x5/8,pi/b,x11/3,s10,x6/4,pf/o,x13/7,pb/m,x10/0,pg/k,x7/13,s1,x11/5,s4,x0/13,s5,x4/5,s5,x6/13,pn/h,x9/4,pd/e,x2/11,ph/o,x14/13,pn/d,x4/5,s7,x12/7,pa/p,x15/5,s3,x14/9,s10,x5/6,pj/o,x11/4,pi/a,s1,x2/12,pj/c,x4/14,s11,x8/13,pf/i,x2/9,s1,pn/o,x0/15,pp/i,x5/6,s5,x7/4,s13,pd/k,x15/12,s13,x0/14,ph/j,x15/12,s15,x6/11,s7,x10/1,s1,x4/3,s15,x0/9,s7,x2/15,pb/p,x14/7,s7,x4/12,pa/g,x6/7,s15,x14/11,s15,x7/13,s9,x9/2,pf/p,x6/10,s3,x0/7,ph/l,x1/8,s15,x0/6,s7,x14/15,s15,x7/9,pe/n,x5/15,s10,x10/11,s7,x7/5,s6,x0/4,pm/g,x7/1,s5,x5/9,s10,x10/15,s10,pj/o,x4/6,pg/b,x9/13,s11,x6/5,s4,pn/o,x15/10,s13,pb/f,s15,x14/3,s9,x4/5,s15,x11/8,s6,x1/4,s1,x3/12,s12,x14/0,pc/d,x11/4,s3,x6/12,s2,x8/9,s1,x12/4,s9,pb/m,x7/5,pf/c,x0/3,s11,x9/10,pm/o,x14/4,pe/c,s1,x15/10,pf/j,x13/5,s9,x1/12,pg/p,x0/15,ph/b,x11/1,pd/e,s8,x14/7,pb/p,s3,x11/9,s8,x8/6,po/a,x13/11,s1,x6/0,s7,x3/13,s15,x12/15,s7,x11/0,pm/b,x1/12,s11,x6/8,pg/l,x13/9,ph/c,x11/10,s9,x8/0,s15,x13/14,pp/f,x3/1,s14,x5/2,s9,x9/15,s9,x11/14,pg/k,x7/4,s4,x8/14,s3,x7/13,pe/n,x11/6,s15,x7/10,pa/m,x9/5,pj/e,x4/12,s13,x10/11,pa/m,s14,pf/k,x1/2,s9,x4/9,pg/j,x0/3,s2,x15/4,s6,pf/a,x9/7,s15,x14/5,pd/p,x4/7,pn/i,x1/10,s15,x7/13,s15,x15/10,ph/e,s1,x3/5,s10,x4/15,s7,x14/1,s8,x12/10,s15,x0/4,pi/n,x6/9,s2,x1/0,pd/o,x8/3,s2,x12/15,pk/h,s13,x10/6,pm/n,x15/2,pc/b,x6/9,s8,x7/13,s12,x2/4,pi/o,s2,x7/12,s13,x9/2,pd/p,x4/8,pk/l,s12,pj/o,x5/1,s12,x4/6,s11,ph/d,x14/9,s8,pb/e,x13/7,pi/f,x12/1,s7,x6/14,pe/j,x15/10,s11,x0/2,pg/d,x12/11,pp/b,x14/15,s5,x2/11,s4,x15/8,pm/e,x10/11,pa/d,x4/9,s11,x14/15,pj/b,x8/2,s3,x5/1,pc/f,x11/3,s8,pg/l,x2/9,po/h,x12/14,s4,x2/0,pe/l,x14/8,s9,x3/1,pn/i,x10/12,s6,x15/2,pm/p,x0/4,pa/c,x9/15,s10,ph/j,x14/1,pn/o,x10/13,s13,x7/11,s14,x15/10,s13,x0/6,s14,x7/2,pa/i,x13/3,s15,x8/1,s13,x11/12,s14,x8/10,s7,pk/p,x4/6,s2,pi/b,x8/10,s6,x5/6,s9,x4/7,pc/k,x13/1,s6,x5/12,s12,x1/0,s8,x3/2,s4,x9/5,s1,x1/8,s9,x0/5,po/i,x11/10,pp/f,x7/3,pe/j,x2/12,s1,x9/4,s7,x1/5,s6,x9/8,s12,x14/10,s10,x7/5,s10,x3/10,pm/k,x1/2,pn/i,x14/7,s9,x2/4,pf/g,x7/8,pb/h,x14/12,pk/m,x6/8,pc/f,x13/5,s8,x14/6,s3,x4/13,s3,x5/7,s1,x11/14,s3,x15/7,pa/p,s11,x11/1,s12,x9/14,s2,x10/12,po/l,x13/9,pp/m,x0/8,pi/d,x5/10,s9,x13/11,pe/k,x5/15,s10,x12/6,s15,x8/15,s4,x12/6,po/i,x13/2,pg/a,x10/5,s2,x0/6,pi/p,x3/9,pg/k,x14/5,s12,x10/7,s14,x3/9,s4,x15/4,ph/n,x13/0,s8,x10/7,pl/j,x14/11,pm/k,x12/5,ph/f,x15/13,s1,x0/5,pk/g,x3/8,ph/l,x1/2,s1,x15/5,pk/c,x8/14,s10,x2/15,s12,x10/9,s3,x3/7,s3,pl/a,s11,x8/11,s15,x1/6,s10,x7/13,po/m,s12,x11/3,ph/j,x4/2,pf/m,x14/1,pg/h,x6/12,s6,x5/7,pl/c,x1/13,s5,x5/3,s2,x8/13,pm/o,x0/2,pd/n,x5/4,pp/g,s9,x9/8,s4,x7/4,s11,x15/6,po/m,x1/10,pc/i,s15,x4/6,s3,x9/7,pa/m,s9,x0/13,s11,x2/1,s14,x15/0,s8,x11/6,s4,x9/10,pn/k,s6,x4/14,po/p,x10/15,s9,x4/12,pm/b,x9/7,s13,x1/0,s8,x2/8,s1,x7/5,s8,x8/10,s12,x5/1,s14,x13/2,pd/n,x4/8,pe/j,x3/15,pc/l,x12/6,pi/n,x13/2,pj/d,x8/3,s15,pa/m,x11/10,s11,x8/15,pf/g,x4/0,pd/h,x8/3,pg/j,x6/10,po/h,x3/11,s10,x4/15,s9,x11/1,s6,x8/9,pp/e,x4/11,pd/b,x5/3,s7,x8/14,s14,x5/2,s9,x1/13,po/k,x11/3,pg/a,x12/8,pi/d,x6/11,pn/b,x5/3,s11,x0/6,s9,pc/a,x4/1,pb/p,x9/8,s10,x2/3,s9,pk/a,x4/7,s9,x2/13,s8,x1/11,s7,x3/13,s13,x1/0,s13,x9/15,s5,x8/0,pm/i,s9,x6/12,pb/n,x7/4,pc/d,x6/9,pn/p,s3,x4/14,s4,x10/1,pa/o,s12,x2/14,s4,x6/12,s4,x4/2,pn/d,x15/8,s10,pk/i,x10/7,s4,pb/a,x14/9,s3,x13/11,s12,x12/0,s10,x11/7,s4,x0/4,pl/g,x2/5,s7,x8/10,s1,pn/k,s9,x9/2,s2,x4/6,s9,x8/10,pc/a,s9,x11/7,po/k,x6/4,pj/f,x3/12,s12,x2/10,pp/c,x5/14,s3,pk/e,x3/8,s9,x4/6,s10,x5/10,pg/o,x0/1,pa/l,s11,x3/7,s6,x13/14,s10,x8/12,pk/j,x0/1,pl/d,x3/12,s10,x10/11,s9,x7/15,s9,x3/4,pi/b,x15/0,pm/g,x4/1,s4,x0/15,po/p,s5,x2/6,s9,x13/12,pa/m,x10/14,pb/j,s14,x12/8,pk/n,x3/5,pj/p,x13/14,pi/n,x1/8,pg/l,s13,x5/9,po/j,x3/14,s12,x2/1,pc/l,x9/4,s5,x13/6,ph/f,x5/15,s9,pj/b,x12/10,pg/f,x1/15,pb/a,x5/12,ph/m,x13/3,s15,x11/8,s5,pb/e,x9/7,pa/j,s14,x13/15,s13,x8/10,s2,x14/4,pe/o,x9/12,s13,x8/1,s8,x15/11,s5,x8/5,s13,x14/12,s8,x7/5,s6,x15/9,ph/p,x14/8,s1,x10/13,s10,x8/2,s2,x15/7,pg/f,x0/11,s2,x8/14,s8,x1/13,pd/k,x14/6,s8,x11/10,s6,x0/4,pg/a,x6/14,s4,x5/10,s15,x7/2,pp/m,x9/3,pk/i,x12/15,s15,x6/11,s5,x10/3,s5,x13/6,s10,x0/10,s14,x9/1,pe/c,x11/3,pn/p,s3,x7/13,s8,x6/14,s14,x3/2,ph/a,x13/0,s14,x12/5,s7,x10/13,s11,pg/k,x8/6,s14,pd/c,x4/9,pp/o,x7/13,s12,x12/15,s10,x5/3,pa/j,x7/9,s15,x3/4,s10,x0/7,pn/g,x9/10,pe/b,x15/3,s6,x5/7,s8,x9/1,s7,x3/15,pp/l,x5/1,pj/h,x8/3,s14,pg/o,x0/10,pm/c,x1/3,s5,pl/p,x11/9,s15,x12/14,pk/f,x11/1,pc/a,x2/4,s5,x7/11,ph/d,x9/2,s6,x1/10,s6,x7/3,s10,x10/5,s14,x0/11,po/f,x8/10,s8,pe/c,x3/14,s12,x15/8,po/k,x2/7,s4,x9/13,s6,ph/i,x3/12,s5,x2/10,s11,x0/13,pc/j,x7/3,s11,x6/14,s11,x13/4,s5,x12/15,s8,x10/6,s6,x3/1,s14,x14/8,s13,pn/f,s1,x13/2,s9,x0/14,s3,x6/10,s7,x13/2,s11,x11/0,s12,x9/13,s11,x7/8,s15,x15/0,s2,x8/5,pi/a,x14/10,ph/b,s2,x1/9,s15,pp/g,x13/14,pj/e,x9/12,pc/l,s4,x5/7,s15,x11/2,ph/j,x7/8,pn/o,x2/0,pc/a,x8/9,pd/e,x14/0,s6,x15/2,s4,x4/3,s14,x9/8,s12,x7/11,s12,pc/n,x6/5,po/l,x7/14,s8,x8/4,s10,x13/9,pc/i,x7/12,pd/j,x4/15,s6,po/h,x13/1,s3,x11/8,s5,x15/0,pg/c,x3/11,s15,x14/0,pj/i,x2/7,pp/f,s4,x9/11,s8,x8/10,s8,x7/13,s15,x0/4,pb/l,s4,x3/9,ph/m,s14,x4/13,s14,x14/0,pp/d,x4/5,s13,x12/1,ph/e,x15/7,s14,x13/2,pa/g,x12/9,pc/f,x0/5,s2,x8/3,pp/h,x4/12,s15,x5/2,s15,x11/4,pb/o,x8/12,pd/m,x1/6,s15,x11/9,s5,x10/1,pa/o,x8/3,s7,x9/2,s4,x7/14,pk/d,x12/3,pg/n,x7/9,s10,x0/12,s15,x15/4,s5,x14/2,s6,x4/7,s1,x14/1,pd/e,x2/11,s12,x7/5,s4,x1/15,s14,x0/10,s7,x12/15,pb/m,x2/3,po/j,x7/1,pd/h,s6,x11/15,pb/f,x6/7,pm/d,x9/15,s3,pj/e,x13/7,s15,x8/14,s1,x2/5,ph/p,x12/11,pa/c,x3/5,pg/f,x10/6,pa/k,s8,x2/8,s5,pb/o,x14/15,s6,x12/13,pn/l,x1/10,s7,x3/12,s10,x5/8,pj/h,s1,pm/o,x13/6,s6,x5/14,s6,x8/7,s5,x13/6,pa/d,s11,x1/7,pl/h,x14/6,pb/k,s7,x10/2,s12,x8/5,s5,x14/15,pl/j,x9/11,pi/p,x5/14,pl/k,x10/9,s12,x5/7,pj/p,s13,pn/l,x0/11,s4,x6/10,pm/e,x2/5,pk/p,x6/9,s15,x14/2,s14,x9/4,pm/n,x6/11,s4,x4/8,po/d,x10/15,s11,x9/13,pg/m,x2/1,s4,pb/a,x15/4,s8,x5/3,pm/h,x0/12,s4,x15/4,pc/e,x0/11,pb/g,x9/6,pm/e,x14/3,pb/c,x8/2,pa/n,s4,pb/p,x7/10,pc/m,x12/6,s13,x5/8,pa/l,x10/3,pp/f,x9/15,s1,x10/2,s15,x9/12,pc/i,x4/11,pb/j,x14/13,s13,x2/1,s10,x5/8,pf/e,s10,x7/14,pl/p,x8/1,s8,x10/9,s3,x8/4,pj/d,s4,pf/h,x2/14,pa/g,s11,x13/1,s5,x9/3,s10,x15/12,pk/o,x13/6,s11,x1/9,s12,x4/14,s2,x11/10,pa/e,s1,x9/14,s14,x4/10,s4,x9/8,s8,pm/p,x12/14,s5,po/k,s14,x6/15,pl/d,x0/8,s12,x2/10,pn/b,x1/7,s8,x12/10,pf/o,x0/7,pl/i,x13/4,s2,x0/2,pd/e,x1/14,s1,pn/k,x8/10,s9,x4/9,s6,x1/5,s5,x7/12,s7,x11/8,pp/h,x9/1,pk/o,x7/0,pc/b,x2/9,s7,x6/15,pp/o,x9/11,pl/f,x3/6,s14,pn/m,x5/9,s2,x13/11,pd/p,x8/10,s1,x3/15,s13,x10/5,pe/g,s4,x11/4,pa/d,x6/14,s13,x7/9,s13,x1/8,pc/g,s2,x2/14,s8,x10/4,pn/o,x7/6,s12,x15/0,pc/l,x3/1,pd/b,x15/7,pp/j,x14/11,s1,x3/15,s7,x14/8,pi/d,x10/11,pb/f,x2/6,pg/l,s11,x0/9,s14,x1/14,s4,x11/10,pe/n,x12/13,pl/m,x9/2,s2,pi/e,x14/3,s6,x15/1,s9,x14/4,s7,x8/7,s13,x1/11,po/f,x6/10,s2,x1/5,s10,x6/3,s14,x9/8,pc/g,x4/1,pm/b,x8/0,pn/a,x2/12,pj/l,x10/5,pc/n,x14/6,pk/m,x8/11,s2,x2/1,pf/e,s14,x14/8,s5,x15/5,pa/d,x6/10,pf/e,s8,x3/2,s13,x0/5,pk/o,x1/3,pc/p,x0/15,s10,x1/2,s9,x3/15,s10,x12/10,s3,x8/11,s5,x0/14,s4,x7/3,s8,x0/9,s1,x14/1,ph/n,s4,x2/10,s15,x4/11,s4,x14/12,s3,x13/7,s4,x11/8,pe/m,x10/14,s9,x5/0,pj/a,x12/9,s7,x4/8,s7,x11/7,pg/c,x3/1,s12,x15/4,s3,x6/1,s14,x9/2,pb/n,x6/7,s10,x8/3,s2,x10/7,s5,x11/3,s7,pf/i,x7/8,s3,x9/15,s6,x13/7,s11,x14/6,s2,x5/4,pn/k,s11,x6/13,s13,x12/2,s12,x4/15,ph/m,x8/9,s7,x10/7,s13,po/j,x4/12,s4,x8/15,s14,x6/14,s11,pm/e,s2,x11/13,pn/f,x15/10,pm/p,s1,x14/13,pe/b,x10/2,s15,x1/15,pl/c,s6,x14/7,s9,x10/1,pk/o,x9/14,s13,x11/0,s7,x2/8,pn/p,x6/12,s10,x11/13,s7,x3/2,pc/g,x12/10,s1,x4/11,pb/j,s9,x12/9,s2,x13/4,s10,x6/11,s8,pg/i,x12/7,s6,x0/6,pb/e,x12/10,s9,x5/6,s8,po/j,x12/9,s2,x6/11,s2,x1/14,s12,x7/12,s13,pc/h,x9/2,s10,x5/10,s12,pa/e,x0/11,s8,x1/9,s7,x10/3,pk/h,x1/13,pa/l,x5/2,s2,x0/12,s15,x4/8,s2,x10/2,pg/i,x14/0,s3,x4/1,s10,x5/12,s9,x7/11,s10,x8/12,po/p,x13/6,pg/f,x2/14,pd/l,s1,x4/8,s1,x3/2,pc/i,x12/14,s10,x3/0,ph/d,x4/2,pf/b,x0/6,s14,x5/4,pi/e,x2/12,pb/h,x5/1,s3,x10/4,pd/k,x13/0,s12,x1/10,po/a,s12,x12/6,s4,x13/2,s7,x6/0,s8,x8/14,s8,x1/9,s6,x8/5,s13,pn/b,x9/0,pp/g,x8/13,s10,pl/j,x2/0,s1,x14/11,s10,x4/6,s6,x9/8,pp/i,x1/7,pa/f,x3/15,s10,x8/9,pd/k,x4/3,pa/j,x9/2,pc/b,x8/14,s3,x0/5,s9,pp/h,x15/10,pm/n,x13/6,pd/i,x2/11,s1,x12/3,s11,x6/10,s2,x9/7,pe/h,x1/5,s5,x7/9,pc/b,x14/3,pi/g,x6/2,po/m,x15/13,s2,x0/5,ph/l,x4/6,s9,x14/15,s10,x7/10,s7,x13/8,s13,x5/3,s10,x2/14,pb/i,x12/8,s8,x13/5,pa/n,x7/9,po/c,x5/0,s7,x15/13,s9,x10/5,s12,x9/13,pp/n,x14/2,pl/e,x10/11,s6,x13/3,s6,pb/c,x4/7,po/p,x1/9,pc/n,x5/12,s12,x8/0,s8,x11/2,pk/o,x6/8,s9,x4/9,pp/m,x0/8,pf/k,x1/6,s13,x2/14,ph/p,x11/8,s1,x3/4,s12,pe/f,s9,x13/10,pn/a,x14/7,s9,x8/0,s6,x6/15,s15,x11/4,s5,x15/8,s8,x13/11,s15,x3/12,s9,x10/8,ph/e,x9/0,s14,x13/5,s3,pn/d,x12/4,s10,x3/11,pk/j,x6/15,pf/c,x0/5,s8,x15/10,s3,x12/0,s11,x4/5,pl/e,x13/12,s12,x11/3,s12,x6/0,pa/f,x15/1,s15,x3/8,pn/c,s15,pi/l,x6/2,pd/c,x12/10,s15,x9/1,s4,x0/14,pa/o,x12/11,pn/i,x2/6,pg/l,x3/9,pa/h,s11,x11/14,s7,x10/13,s15,x9/6,pp/e,x4/13,s12,x9/14,s4,x2/0,s14,x6/13,pm/c,x11/12,s7,x0/2,s3,pp/f,x10/11,pn/e,s10,x12/13,s9,x5/9,s14,x1/0,po/c,x14/9,pl/b,x8/7,pc/a,x14/4,s15,x9/6,s13,x14/0,pf/n,x8/2,pp/a,x10/13,s3,x3/6,ph/g,x4/12,pl/o,x1/6,s2,x9/5,s6,x6/3,s3,x5/11,s9,x1/12,s14,x4/6,s7,x12/7,s6,x11/4,pi/g,s13,x10/3,s8,x5/6,pp/f,s14,pl/j,s7,x15/9,s7,po/g,x8/5,s12,x4/1,pd/p,s4,x15/11,s2,pc/g,x8/2,s8,x13/0,ph/k,x11/6,s9,x9/10,pg/a,x6/5,pf/c,x4/15,s2,x1/11,s9,x3/6,s8,x10/12,s1,x7/11,s5,x12/0,s10,x7/4,s14,x1/10,pl/a,x5/7,pn/j,x12/6,pa/i,x5/1,s5,x4/15,pc/b,x5/14,pf/m,x15/4,s4,x7/9,pd/o,x3/13,pf/a,s12,x0/10,pg/j,x7/8,s10,x6/15,s13,x8/10,ph/c,x7/9,s12,x14/10,pl/m,x12/9,pe/k,x4/6,s8,x13/11,s4,x1/8,s8,x6/5,pb/h,x14/15,s4,x1/8,s2,x5/2,pg/l,x0/12,pf/m,x14/1,pi/h,x11/5,s9,x12/6,pa/p,x4/13,s11,x8/11,s2,x6/13,s3,x5/15,s4,x9/10,s4,x11/5,s15,x15/12,s12,pj/f,x0/11,pg/i,x7/2,s1,x10/6,pb/h,x8/0,po/k,x5/10,s5,x15/9,s7,x8/6,s6,x11/7,pi/l,s12,x14/13,s4,x1/0,s2,pf/o,x9/14,s10,x5/1,s12,x6/12,s3,ph/j,x13/3,s5,x8/12,po/a,s11,x15/3,s9,x1/8,pc/i,x5/7,s11,x4/11,s1,x9/3,ph/f,x10/11,s8,x6/7,s12,x9/12,pj/m,x15/6,pf/i,x9/7,s9,x1/6,pl/a,s14,x10/3,s7,x4/15,s8,x7/2,pp/g,x6/4,pk/d,x11/2,pa/h,x13/10,s5,x6/7,pe/c,x4/3,s8,x9/6,s10,x15/8,pa/h,x5/2,po/k,x9/12,s5,x11/6,pj/d,x3/9,pa/i,x14/0,pc/d,x12/10,po/b,x8/2,pg/h,x3/7,s4,x5/4,pk/m,x10/14,s4,x5/13,s1,x1/14,s10,x15/10,pb/o,x9/13,s5,x15/7,s4,x2/13,s7,x5/15,s3,x14/6,s12,x5/12,s5,x9/14,pi/a,x13/11,s9,x3/10,s11,x9/14,s1,x10/11,s8,x2/15,s10,x8/0,s7,x5/1,s8,x8/12,s5,x15/4,s4,x3/0,s10,x1/5,s1,x11/0,pf/m,x1/6,pl/h,x9/11,s2,x0/12,s6,x9/3,s13,x4/5,pc/i,x2/14,s12,pe/j,s5,x15/8,s14,x10/2,s8,x12/11,s15,x1/6,s15,x10/7,s11,x15/13,pi/c,x14/8,pe/m,s14,x15/7,pk/j,x4/12,s3,x14/11,pd/h,x3/1,s15,x5/2,pi/p,x14/13,s1,x7/0,ph/j,x1/2,s6,x13/12,pn/p,x1/14,s6,x10/4,s13,x15/1,s12,x11/3,s10,x8/6,s9,x3/7,pg/f,x9/6,pa/e,x13/10,pc/j,x8/12,pp/n,x11/0,s14,x5/6,s3,pb/d,x2/0,s6,x11/9,pf/m,x13/7,s12,x15/12,s12,x10/3,s15,x11/2,s15,x12/13,s11,x0/14,s10,x8/15,s4,x13/2,s15,x7/12,pa/d,x1/10,pb/j,x5/9,s1,x4/11,pa/o,x2/10,pg/f,x0/5,s14,x8/14,pd/o,x10/13,pc/e,x2/6,pj/p,x5/7,s8,x15/1,s8,x12/4,pb/a,x5/10,s3,x9/7,s14,x1/12,s11,x4/9,pk/i,x14/7,s7,x6/10,s15,x14/1,pp/o,s13,x9/15,pe/n,x3/2,s9,x13/4,s10,x8/5,pk/o,x2/11,s3,x0/10,pm/n,x12/14,pe/a,x11/0,s10,x10/7,s9,x11/8,pi/d,x13/1,pe/p,x2/0,pk/l,x9/1,pf/n,x2/0,pa/p,x14/8,s7,x15/2,s7,x11/13,s8,x5/10,s7,x15/2,s2,x4/8,s13,x1/12,s1,x11/5,s9,pl/m,x2/9,s3,x5/11,pf/j,x1/13,s14,x8/0,pe/n,s10,x6/13,pb/o,x8/15,s11,x11/7,s10,x8/4,pi/g,x12/13,pj/a,s6,x0/3,pf/b,x14/6,s11,x13/7,pl/g,x4/9,s7,x8/7,pj/h,x0/15,s15,x9/2,s14,x11/12,pm/n,x1/14,s12,x5/13,s10,x9/10,pa/c,x12/6,s15,x2/13,s4,x12/15,s7,pg/b,x1/9,pc/o,x12/4,s12,x15/14,s7,x3/6,pa/l,x8/14,pp/h,x12/10,po/a,x8/0,s3,x1/10,s3,x3/8,pg/j,x2/7,s9,x11/14,s10,pn/i,x2/6,po/a,x14/10,s13,x15/4,pe/k,x2/6,s7,x1/8,pi/b,x13/15,s11,x12/10,pl/j,x9/3,ph/k,x2/14,s5,x4/3,pl/n,x15/1,pe/o,x13/9,s6,x7/6,s15,x8/10,s13,x4/12,s8,x5/15,s6,x13/11,pi/n,x1/6,s15,x0/3,s10,x14/11,s8,x8/3,s11,x2/7,pc/p,x10/14,pm/g,x3/13,s2,x15/5,pi/l,x3/0,s13,x11/6,s11,x7/14,s5,x10/8,s10,ph/n,x3/15,s3,x1/0,s12,po/f,x6/15,s6,x1/5,s5,x11/2,s12,ph/g,s1,pn/c,x15/13,s10,x11/10,s1,x15/5,ph/o,x11/1,s4,x3/8,s6,x6/4,s8,x2/15,pk/m,x5/8,pp/b,x3/11,s5,x12/5,s15,x7/2,pl/m,x5/10,s12,pg/i,x9/13,s11,x4/0,s10,x7/14,pf/p,x0/9,s11,x4/8,s8,x11/15,s15,x5/4,pj/e,x8/3,pd/f,x1/10,pe/o,x6/5,pb/d,x11/4,s6,x14/6,pa/p,x7/9,pg/c,x1/5,pd/k,s5,x3/15,s11,x2/6,s12,x8/4,s8,x12/3,s15,x8/15,s1,x12/1,s10,x2/15,s6,x8/5,s12,pi/f,x12/11,s5,x14/4,pp/l,x15/7,s2,x13/14,s5,x1/11,s9,pk/m,s6,x0/7,s4,x13/3,s6,pp/d,x9/10,pj/b,x3/1,s7,x11/13,pe/i,x15/10,s2,x0/8,s2,x15/12,s12,x4/0,s3,x1/8,s1,x12/7,pf/a,x6/15,s2,x11/13,pp/d,x9/6,ph/c,x8/15,pi/a,x5/2,pg/h,x12/8,pc/p,x13/3,s7,x9/12,pm/d,x5/14,pa/j,s13,x15/10,s3,x2/7,pc/e,x11/13,s3,x10/7,s2,x15/12,s12,x0/11,s4,x5/6,s12,x2/11,s10,x3/4,s10,x11/10,ph/a,x6/8,s9,x4/0,s10,x6/3,s14,x2/8,s2,x13/1,s14,x4/2,s14,x13/15,pd/o,x3/0,s7,x13/14,s13,x3/8,pe/i,x7/4,po/g,x1/10,pl/j,x12/6,s14,pb/h,s4,x9/13,pj/f,x7/10,s11,x6/15,s8,x1/9,pg/b,x0/6,s1,pc/o,x11/9,s4,x2/15,s13,x12/3,s2,pd/l,x6/5,s10,x4/9,s10,x11/5,s15,x0/13,s11,x1/4,s10,x9/3,s7,ph/i,x13/14,pk/o,s6,ph/f,x15/9,s12,pm/j,x10/11,pg/a,s10,x8/9,s5,x7/13,s7,x5/4,s7,x13/12,s15,x5/8,s2,x1/7,pj/k,x11/15,pe/a,x3/13,po/b,x6/7,pp/n,x12/2,s3,x7/0,pd/c,x6/13,s2,x15/2,pg/o,x6/8,ph/p,x12/4,s9,x9/6,pc/l,x5/0,pe/f,s10,x9/4,s5,x3/6,pa/l,x9/1,s14,x8/3,s5,x4/15,s14,x7/8,s7,x14/12,s8,pk/i,x10/7,pf/l,x12/15,s13,x10/14,s5,x7/9,s15,pb/d,x1/3,s1,x10/11,s9,x6/14,pj/a,x15/0,s7,x5/8,pi/e,x2/13,s15,x11/14,s8,x9/15,s2,x6/0,s8,x1/7,s9,x5/14,s5,x11/2,s10,pl/k,s7,x13/15,po/h,x14/1,s14,x4/5,pa/f,x9/10,ph/d,x0/13,pp/k,x15/1,s13,x4/7,pm/b,x8/10,s3,x6/3,pe/d,x4/13,s6,x11/3,pc/p,x9/6,pe/a,x11/0,s12,x12/8,pc/g,x7/4,pl/h,x8/11,s9,x0/3,s4,x10/9,s10,pg/k,x15/8,s3,x11/0,s11,x13/15,ph/j,x1/5,pb/d,x11/9,s14,x10/0,s10,x2/7,pi/m,x14/11,s5,x2/4,s8,x13/12,pn/g,x5/14,pb/d,x9/3,s13,x12/4,s7,x11/5,pf/a,x9/1,s9,x11/0,s14,pn/o,x6/10,s11,x13/15,pm/p,x0/11,pc/o,x6/8,s5,x0/10,s1,pa/d,x1/4,s6,x12/7,pc/g,s10,pm/p,x0/2,s7,x10/5,s2,x0/4,s3,x3/5,s7,pd/g,x2/13,pn/l,x0/10,pk/c,s1,x15/11,pp/f,x14/7,s13,x9/4,s10,x3/8,s15,x7/11,pa/i,x13/6,s11,x1/3,s10,x2/0,pn/f,x3/15,pk/a,s6,x9/12,pl/h,x7/3,s7,x0/9,s6,x15/14,s10,x8/2,s12,x10/9,s14,x2/12,s6,x13/15,s12,x2/14,po/j,s7,x12/7,s3,x15/3,pb/n,x6/2,s5,x11/8,s5,x13/4,pi/c,x14/10,s2,x0/12,s4,pf/o,x8/13,s4,x9/6,s1,x5/0,s14,x1/15,s1,x8/9,s9,x13/12,s2,x14/3,s7,x4/7,s3,x10/2,s11,x0/13,pn/d,x6/9,s10,x11/14,s3,x13/6,s2,x7/5,s1,x14/8,pj/b,x10/4,pc/i,x1/13,s12,x15/3,pb/m,x2/13,pc/h,x4/0,pl/d,x1/10,s3,x7/0,s2,x11/3,pp/a,x1/0,ph/b,x15/12,s5,x10/7,s2,x5/9,po/g,x2/15,s6,pl/j,x12/3,s5,x13/4,s13,x15/8,s7,x10/9,ph/c,x4/14,s15,x6/11,s10,x5/13,s1,x4/0,s5,x6/14,s11,x12/8,s5,x13/15,s6,x3/9,pf/j,s2,x13/15,s4,x4/11,pl/d,x1/10,s2,x6/12,s10,x4/11,s11,x2/15,s4,x4/12,s4,x14/15,po/e,x1/5,s6,x8/15,s6,x6/7,s1,x8/11,pb/f,x10/14,pi/g,s6,x8/1,s11,x9/11,pk/a,x15/0,pl/p,x8/14,pd/f,x5/9,pe/n,x14/8,s2,x12/13,s3,x5/3,pc/i,x14/7,pk/d,x8/5,s2,pa/p,x3/13,s1,x1/5,s12,x10/15,s14,x11/8,s11,x14/3,s6,x13/8,s12,x9/14,s14,x1/2,pc/n,x15/4,pe/a,x13/3,s15,x0/1,pj/m,x8/7,pa/n,x4/15,s12,pj/p,s5,x0/12,po/l,x8/13,s1,x14/15,s1,x12/9,s11,x7/6,s13,x1/10,pg/a,x3/9,ph/n,x12/4,s13,pi/k,x7/6,pf/m,s10,x13/14,s6,x1/6,s9,x5/10,s14,x13/2,pd/l,x4/8,s5,x11/6,pk/g,x15/1,ph/j,x8/5,s15,x11/9,pd/e,x14/6,pi/p,x3/4,po/h,x13/5,s7,x2/0,pk/f,x1/10,s14,x11/5,s5,x12/3,pg/m,x0/14,s2,x11/5,s10,x1/13,pj/f,x14/10,s6,x5/7,s9,pl/a,x1/14,s10,x7/9,s6,pm/n,s7,pa/l,x11/2,pp/h,x13/12,pa/l,x6/8,s12,x4/5,s9,x8/3,pg/j,x12/14,pb/a,x6/1,s13,pl/f,x7/8,s13,x0/9,s14,pb/e,x10/8,s11,pd/a,x5/2,s5,x6/8,s11,x1/3,s1,x2/9,s11,x0/10,s13,x9/6,s11,x15/2,s6,pg/f,x3/1,s3,x15/7,s14,x4/11,s6,x2/6,pc/o,s3,x10/3,s15,x4/13,s7,x3/9,s9,x14/10,pm/p,x12/0,pf/a,s3,x4/15,pg/e,x6/7,s9,x15/10,s15,x7/2,pj/b,x6/1,s12,x0/2,po/f,x1/4,s12,pk/c,x9/2,s12,x15/12,ph/a,s6,pf/j,x1/2,s4,pa/d,x0/11,ph/o,x14/6,pc/n,x3/4,s7,x2/12,s7,x6/8,pa/b,x14/12,s15,x13/0,s6,pk/o,x6/10,s11,x5/0,s8,pj/g,s12,x2/8,s5,pd/h,x9/11,s9,x7/0,pm/a,x2/11,s15,pn/b,s2,x13/7,s9,x15/5,s8,x4/8,pp/k,x3/13,s9,x4/15,s10,x11/1,s8,pb/l,x7/10,s1,x3/5,s11,x1/9,s5,pg/d,x14/12,pf/p,x2/13,s7,x6/7,s2,x15/4,pg/a,x11/9,pp/f,x8/10,pb/k,x14/12,s5,x3/6,pc/e,x1/0,s8,pb/g,x3/12,s11,x2/0,s10,x15/9,s15,x13/4,s11,x3/12,s15,x4/6,s2,x7/5,pp/d,x6/13,s13,pb/l,x5/12,s12,x8/6,s11,x1/12,pi/n,x2/8,pf/a,x14/10,s11,pn/l,x11/15,s15,x13/12,s11,x14/0,pm/h,x12/13,s10,x9/0,s5,pa/i,x7/5,s2,x11/9,pc/f,s12,x6/10,pi/g,s13,x9/4,s4,x11/2,ph/o,x8/5,s8,x15/9,s5,x11/12,s9,x2/7,pp/b,x6/4,s4,pe/m,x2/12,s11,x14/6,s11,x8/15,s1,x3/13,ph/k,x15/5,pj/m,x11/14,pn/i,x12/3,s11,x0/10,s6,x12/7,s8,x8/9,s1,x4/10,pf/o,x11/0,pg/a,s5,x10/15,pl/h,s3,x4/2,s14,x3/5,s2,x13/6,pk/b,x5/11,s2,x13/2,pe/p,x14/15,pj/c,x7/10,pg/h,x1/2,pb/p,x15/6,s4,x11/9,s2,x5/4,s4,x13/10,s11,x0/6,s6,x14/3,po/a,x10/6,pj/h,x5/3,pb/d,x10/4,s12,x13/12,pn/p,x1/9,s6,x3/13,s5,x0/11,s6,x9/14,ph/d,x8/3,s7,x0/1,s2,x3/8,s15,x4/13,pl/b,x2/5,pd/p,x0/3,pj/c,x11/6,pg/n,x15/9,po/h,x11/13,pf/p,x0/12,s4,x6/13,pn/o,x9/10,s6,x15/3,pg/f,s11,x11/10,s15,x3/15,pi/b,x11/1,s15,x4/9,s5,x15/3,pc/o,x13/10,s7,x4/8,s10,x1/14,s11,x6/10,pp/b,x8/3,s5,x1/10,s3,pn/j,x9/15,s11,pe/b,x8/5,s9,x0/6,s1,x10/9,s5,pc/n,s14,x0/12,pf/p,x1/15,pk/e,x6/2,pl/b,x12/5,s14,x6/14,s12,x1/7,pg/o,x6/8,pn/l,s6,x14/9,s1,x6/0,s15,x14/5,s11,pf/e,x9/11,pk/n,x7/13,pp/e,s6,x0/10,pj/l,x6/11,po/f,x0/8,s6,x15/11,s8,pj/b,x8/4,s14,x10/2,pi/k,x7/9,s15,x2/13,s13,pm/d,x3/11,pk/c,x9/4,pn/e,x0/8,pc/p,x15/12,pe/g,x10/11,pb/l,x14/4,s14,x13/2,s2,pe/j,x4/1,pn/o,x12/5,pl/i,x1/11,s12,x0/13,ph/m,x15/6,s5,x7/11,s6,x0/9,s13,x11/10,s11,x6/7,s13,x3/15,s9,x8/11,pg/l,x4/5,ph/f,x11/7,s12,pg/p,x5/10,s13,x13/15,s15,x5/8,s10,x6/9,s15,x4/2,s13,x9/6,pe/a,x2/0,pc/l,x14/9,pf/d,x12/5,s11,x2/9,pn/m,x3/11,s6,x1/8,s11,x5/9,s4,x11/0,s1,pc/b,s1,x8/10,pg/f,x15/3,s9,x8/11,pi/n,x5/3,pe/m,x9/10,s10,pc/k,x3/6,s9,x10/1,pf/g,x4/13,pn/a,x12/0,s10,pp/m,x3/10,s12,x6/0,pn/e,x12/9,s12,pg/b,x4/6,s9,x9/2,s6,x0/15,pi/j,s12,x1/5,po/p,x15/11,s4,x12/4,pj/n,x0/8,s12,x13/6,s10,x2/4,pc/d,x11/15,pf/h,x0/8,s15,x5/7,s13,x14/2,s1,pn/l,x12/7,s15,x11/6,pf/j,x7/0,pl/o,x9/2,pc/p,x11/13,s2,x12/15,pd/i,s2,pk/j,x5/4,pb/f,x10/1,s2,x13/11,s8,x2/3,s15,x10/15,s9,x11/1,s14,x2/8,s2,x4/15,pe/l,x6/7,s5,x8/13,s6,x2/5,s8,x7/6,po/i,x8/5,s6,pe/g,x1/15,s6,pf/d,x3/4,pb/m,x8/9,s12,x2/0,s13,x12/13,s7,x1/15,pp/d,x4/3,s15,x13/2,s9,x9/5,pl/h,x15/2,pp/b,x4/9,s10,x0/7,pg/d,x14/11,s2,x8/15,s7,x6/12,s12,x15/0,pk/a,x7/14,pf/j,s8,x15/11,s8,x8/9,pc/o,s8,x12/13,s6,x6/9,pm/a,x5/4,s7,x3/2,s7,x10/13,s5,x1/12,pf/c,x6/9,s2,x8/1,s1,x5/3,ph/l,x14/0,pg/p,x5/4,pa/e,x8/9,pm/o,x14/12,pe/k,x9/10,s1,x0/6,s7,x15/10,pf/g,x8/13,s11,x4/2,pe/m,s11,x7/12,s12,x10/11,s2,x5/13,s11,x12/3,pd/c,x13/4,s7,x0/14,s8,x8/4,pe/n,s15,x13/7,pb/c,x0/1,s9,x5/14,s12,x12/11,pf/m,x2/1,s6,x0/12,s15,x10/4,s5,x13/2,s11,x10/15,pl/e,x1/14,s12,x2/7,s7,x14/12,s3,po/m,x9/8,s2,x4/11,s7,x0/2,s15,x3/9,s3,x15/14,s11,x2/5,s9,x10/6,s11,x15/4,s11,pb/g,x1/10,pi/e,x3/15,s8,x10/8,pg/j,x1/3,pn/a,x12/13,s5,x14/2,pf/c,x3/7,s4,x12/5,s10,x2/8,pg/m,x0/9,s11,x15/7,s3,pi/b,s11,pa/e,x11/6,po/g,x7/1,s14,x10/8,s12,pk/i,x13/11,pb/p,x12/8,s11,x14/2,s10,x6/10,s6,x0/1,s4,x14/3,pi/l,x12/7,pd/e,s5,x1/13,s15,x12/5,s8,x15/0,s12,x3/13,pi/b,x7/11,po/g,x2/3,s8,x5/0,pk/f,x10/13,pp/o,x0/7,pj/l,x12/5,s12,x13/4,s13,x14/3,pc/b,x4/0,pf/l,x5/1,s13,x13/10,pk/g,x8/2,s13,x0/3,s4,x4/2,s9,x10/11,s1,pm/p,x14/2,s6,pe/h,x8/5,s6,x7/11,pb/j,x6/9,s10,x0/7,pa/l,x6/10,s5,x3/15,s12,x5/12,s10,pn/d,x11/13,s6,x9/3,pc/b,s13,x13/12,po/h,x7/8,s12,x15/1,pm/k,x0/4,pj/h,x10/1,s4,x14/6,pe/p,x9/1,pi/f,x11/0,pa/n,x9/13,s7,x15/14,pe/o,x3/0,pa/i,x14/13,s9,x15/8,pk/o,x14/5,s8,x4/11,s5,pn/a,x6/5,pg/j,x14/8,pa/d,x13/15,s10,x10/7,s13,pc/e,x13/8,pg/k,x12/4,pj/n,x7/0,s10,x5/12,s5,x7/14,s7,x11/2,pf/b,x4/15,pe/h,x0/10,pa/o,x13/3,pf/e,s8,x7/5,s12,x9/6,s6,x1/7,s8,x0/6,s15,pd/h,x1/12,pb/e,x11/15,s10,x13/7,pn/c,x6/9,pb/o,x11/14,s5,x9/4,s5,x2/3,s2,x6/14,pg/j,x5/12,pc/b,x15/7,ph/f,x9/14,s14,x2/7,pa/j,x6/8,s4,x9/14,s9,x10/5,s2,x7/9,s9,x6/12,s3,x8/1,pe/n,s15,pl/g,x15/7,s15,x13/3,s12,x14/1,ph/o,s9,x7/10,s6,pi/c,x9/1,pd/f,s4,x0/13,pc/o,x15/2,s10,x9/7,s14,x14/6,s7,x13/12,pp/k,x3/5,s11,x4/6,pg/m,x12/9,pl/b,x13/10,s1,x9/14,pk/j,x4/1,pi/a,x0/10,s6,x4/15,s10,x9/1,s6,x6/14,s6,x0/7,s7,x5/1,s13,x11/0,s4,x10/7,pm/d,x15/14,s5,x5/3,s2,x13/12,pp/e,x14/15,pg/n,x6/10,s3,x7/4,s4,x5/14,pl/j,x7/1,pm/c,x4/6,pg/e,x11/9,s3,x3/6,pa/o,x5/9,s15,x4/0,pn/e,x2/13 \ No newline at end of file diff --git a/tests/assert/tfailedassert.nim b/tests/assert/tfailedassert.nim index f0ca149f8..8b260a3ab 100644 --- a/tests/assert/tfailedassert.nim +++ b/tests/assert/tfailedassert.nim @@ -8,7 +8,7 @@ tfailedassert.nim:27 false assertion from foo """ type - TLineInfo = tuple[filename: string, line: int] + TLineInfo = tuple[filename: string, line: int, column: int] TMyError = object of Exception lineinfo: TLineInfo diff --git a/tests/assign/toverload_asgn1.nim b/tests/assign/toverload_asgn1.nim index dbc3a71c4..01e7e7aa7 100644 --- a/tests/assign/toverload_asgn1.nim +++ b/tests/assign/toverload_asgn1.nim @@ -14,6 +14,7 @@ GenericT[T] '=' bool GenericT[T] '=' bool GenericT[T] '=' bool GenericT[T] '=' bool''' + disabled: "true" """ import typetraits diff --git a/tests/assign/toverload_asgn2.nim b/tests/assign/toverload_asgn2.nim index 243c90494..1104be92b 100644 --- a/tests/assign/toverload_asgn2.nim +++ b/tests/assign/toverload_asgn2.nim @@ -1,6 +1,7 @@ discard """ output: '''i value 88 2aa''' + disabled: "true" """ import moverload_asgn2 diff --git a/tests/async/config.nims b/tests/async/config.nims deleted file mode 100644 index 97c2e0aa4..000000000 --- a/tests/async/config.nims +++ /dev/null @@ -1,2 +0,0 @@ -when defined(upcoming): - patchFile("stdlib", "asyncdispatch", "$lib/upcoming/asyncdispatch") diff --git a/tests/async/hello.txt b/tests/async/hello.txt new file mode 100644 index 000000000..854d6c20a --- /dev/null +++ b/tests/async/hello.txt @@ -0,0 +1 @@ +hello humans! \ No newline at end of file diff --git a/tests/async/t6100.nim b/tests/async/t6100.nim new file mode 100644 index 000000000..b4dc0f146 --- /dev/null +++ b/tests/async/t6100.nim @@ -0,0 +1,15 @@ +discard """ + file: "t6100.nim" + exitcode: 0 + output: "10000000" +""" +import asyncdispatch + +let done = newFuture[int]() +done.complete(1) + +proc asyncSum: Future[int] {.async.} = + for _ in 1..10_000_000: + result += await done + +echo waitFor asyncSum() \ No newline at end of file diff --git a/tests/async/tasync_in_seq_constr.nim b/tests/async/tasync_in_seq_constr.nim index 46ad74451..3d6dae245 100644 --- a/tests/async/tasync_in_seq_constr.nim +++ b/tests/async/tasync_in_seq_constr.nim @@ -1,18 +1,25 @@ discard """ - errormsg: "invalid control flow: 'yield' within a constructor" - line: 16 + output: ''' +@[1, 2, 3, 4] +123 +''' """ # bug #5314, bug #6626 import asyncdispatch -proc bar(): Future[int] {.async.} = - await sleepAsync(500) - result = 3 +proc bar(i: int): Future[int] {.async.} = + await sleepAsync(2) + result = i proc foo(): Future[seq[int]] {.async.} = - await sleepAsync(500) - result = @[1, 2, await bar(), 4] # <--- The bug is here + await sleepAsync(2) + result = @[1, 2, await bar(3), 4] # <--- The bug is here + +proc foo2() {.async.} = + await sleepAsync(2) + echo(await bar(1), await bar(2), await bar(3)) echo waitFor foo() +waitFor foo2() diff --git a/tests/async/tasync_traceback.nim b/tests/async/tasync_traceback.nim index 08f7e7317..618a1dc76 100644 --- a/tests/async/tasync_traceback.nim +++ b/tests/async/tasync_traceback.nim @@ -1,61 +1,7 @@ discard """ exitcode: 0 disabled: "windows" - output: ''' -b failure -Async traceback: - tasync_traceback.nim(97) tasync_traceback - asyncmacro.nim(395) a - asyncmacro.nim(34) a_continue - ## Resumes an async procedure - tasync_traceback.nim(95) aIter - asyncmacro.nim(395) b - asyncmacro.nim(34) b_continue - ## Resumes an async procedure - tasync_traceback.nim(92) bIter - #[ - tasync_traceback.nim(97) tasync_traceback - asyncmacro.nim(395) a - asyncmacro.nim(43) a_continue - ## Resumes an async procedure - asyncfutures.nim(211) callback= - asyncfutures.nim(190) addCallback - asyncfutures.nim(53) callSoon - asyncmacro.nim(34) a_continue - ## Resumes an async procedure - asyncmacro.nim(0) aIter - asyncfutures.nim(304) read - ]# -Exception message: b failure -Exception type: - -bar failure -Async traceback: - tasync_traceback.nim(113) tasync_traceback - asyncdispatch.nim(1492) waitFor - asyncdispatch.nim(1496) poll - ## Processes asynchronous completion events - asyncdispatch.nim(1262) runOnce - asyncdispatch.nim(183) processPendingCallbacks - ## Executes pending callbacks - asyncmacro.nim(34) bar_continue - ## Resumes an async procedure - tasync_traceback.nim(108) barIter - #[ - tasync_traceback.nim(113) tasync_traceback - asyncdispatch.nim(1492) waitFor - asyncdispatch.nim(1496) poll - ## Processes asynchronous completion events - asyncdispatch.nim(1262) runOnce - asyncdispatch.nim(183) processPendingCallbacks - ## Executes pending callbacks - asyncmacro.nim(34) foo_continue - ## Resumes an async procedure - asyncmacro.nim(0) fooIter - asyncfutures.nim(304) read - ]# -Exception message: bar failure -Exception type:''' + output: "Matched" """ import asyncdispatch @@ -87,6 +33,8 @@ import asyncdispatch # tasync_traceback.nim(21) a # tasync_traceback.nim(18) b +var result = "" + proc b(): Future[int] {.async.} = if true: raise newException(OSError, "b failure") @@ -98,8 +46,8 @@ let aFut = a() try: discard waitFor aFut except Exception as exc: - echo exc.msg -echo() + result.add(exc.msg & "\n") +result.add("\n") # From #6803 proc bar(): Future[string] {.async.} = @@ -110,7 +58,69 @@ proc bar(): Future[string] {.async.} = proc foo(): Future[string] {.async.} = return await bar() try: - echo waitFor(foo()) + result.add(waitFor(foo()) & "\n") except Exception as exc: - echo exc.msg -echo() \ No newline at end of file + result.add(exc.msg & "\n") +result.add("\n") + +# Use re to parse the result +import re +const expected = """ +b failure +Async traceback: + tasync_traceback\.nim\(\d+?\)\s+?tasync_traceback + asyncmacro\.nim\(\d+?\)\s+?a + asyncmacro\.nim\(\d+?\)\s+?a_continue + ## Resumes an async procedure + tasync_traceback\.nim\(\d+?\)\s+?aIter + asyncmacro\.nim\(\d+?\)\s+?b + asyncmacro\.nim\(\d+?\)\s+?b_continue + ## Resumes an async procedure + tasync_traceback\.nim\(\d+?\)\s+?bIter + #\[ + tasync_traceback\.nim\(\d+?\)\s+?tasync_traceback + asyncmacro\.nim\(\d+?\)\s+?a + asyncmacro\.nim\(\d+?\)\s+?a_continue + ## Resumes an async procedure + tasync_traceback\.nim\(\d+?\)\s+?aIter + asyncfutures\.nim\(\d+?\)\s+?read + \]# +Exception message: b failure +Exception type: + +bar failure +Async traceback: + tasync_traceback\.nim\(\d+?\)\s+?tasync_traceback + asyncdispatch\.nim\(\d+?\)\s+?waitFor + asyncdispatch\.nim\(\d+?\)\s+?poll + ## Processes asynchronous completion events + asyncdispatch\.nim\(\d+?\)\s+?runOnce + asyncdispatch\.nim\(\d+?\)\s+?processPendingCallbacks + ## Executes pending callbacks + asyncmacro\.nim\(\d+?\)\s+?bar_continue + ## Resumes an async procedure + tasync_traceback\.nim\(\d+?\)\s+?barIter + #\[ + tasync_traceback\.nim\(\d+?\)\s+?tasync_traceback + asyncdispatch\.nim\(\d+?\)\s+?waitFor + asyncdispatch\.nim\(\d+?\)\s+?poll + ## Processes asynchronous completion events + asyncdispatch\.nim\(\d+?\)\s+?runOnce + asyncdispatch\.nim\(\d+?\)\s+?processPendingCallbacks + ## Executes pending callbacks + asyncmacro\.nim\(\d+?\)\s+?foo_continue + ## Resumes an async procedure + tasync_traceback\.nim\(\d+?\)\s+?fooIter + asyncfutures\.nim\(\d+?\)\s+?read + \]# +Exception message: bar failure +Exception type: +""" + +if result.match(re(expected)): + echo("Matched") +else: + echo("Not matched!") + echo() + echo(result) + quit(QuitFailure) diff --git a/tests/async/tasyncawait.nim b/tests/async/tasyncawait.nim index 9fe9507ad..74933f063 100644 --- a/tests/async/tasyncawait.nim +++ b/tests/async/tasyncawait.nim @@ -12,11 +12,11 @@ const var clientCount = 0 -proc sendMessages(client: TAsyncFD) {.async.} = +proc sendMessages(client: AsyncFD) {.async.} = for i in 0 .. <messagesToSend: await send(client, "Message " & $i & "\c\L") -proc launchSwarm(port: TPort) {.async.} = +proc launchSwarm(port: Port) {.async.} = for i in 0 .. <swarmSize: var sock = newAsyncNativeSocket() @@ -24,7 +24,7 @@ proc launchSwarm(port: TPort) {.async.} = await sendMessages(sock) closeSocket(sock) -proc readMessages(client: TAsyncFD) {.async.} = +proc readMessages(client: AsyncFD) {.async.} = while true: var line = await recvLine(client) if line == "": @@ -37,7 +37,7 @@ proc readMessages(client: TAsyncFD) {.async.} = else: doAssert false -proc createServer(port: TPort) {.async.} = +proc createServer(port: Port) {.async.} = var server = newAsyncNativeSocket() block: var name: Sockaddr_in @@ -55,8 +55,8 @@ proc createServer(port: TPort) {.async.} = while true: asyncCheck readMessages(await accept(server)) -asyncCheck createServer(TPort(10335)) -asyncCheck launchSwarm(TPort(10335)) +asyncCheck createServer(Port(10335)) +asyncCheck launchSwarm(Port(10335)) while true: poll() if clientCount == swarmSize: break diff --git a/tests/async/tasyncfile.nim b/tests/async/tasyncfile.nim index 6c0725c88..c7b71a2f7 100644 --- a/tests/async/tasyncfile.nim +++ b/tests/async/tasyncfile.nim @@ -1,4 +1,8 @@ discard """ + output: '''13 +hello humans! +13 +''' file: "tasyncfile.nim" exitcode: 0 """ @@ -41,12 +45,19 @@ proc main() {.async.} = await file.write("test2") file.close() file = openAsync(fn, fmWrite) - await file.write("test3") + await file.write("t3") file.close() file = openAsync(fn, fmRead) let data = await file.readAll() - doAssert data == "test3" + doAssert data == "t3" file.close() + # Issue #7347 + block: + let appDir = getAppDir() + var file = openAsync(appDir & DirSep & "hello.txt") + echo file.getFileSize() + echo await file.readAll() + echo file.getFilePos() waitFor main() diff --git a/tests/async/tasynctry2.nim b/tests/async/tasynctry2.nim index 444a058be..f82b6cfe0 100644 --- a/tests/async/tasynctry2.nim +++ b/tests/async/tasynctry2.nim @@ -1,10 +1,12 @@ discard """ file: "tasynctry2.nim" errormsg: "\'yield\' cannot be used within \'try\' in a non-inlined iterator" - line: 15 + line: 17 """ import asyncdispatch +{.experimental: "oldIterTransf".} + proc foo(): Future[bool] {.async.} = discard proc test5(): Future[int] {.async.} = diff --git a/tests/async/tfuturestream.nim b/tests/async/tfuturestream.nim index 9a8e986a0..d76752b7e 100644 --- a/tests/async/tfuturestream.nim +++ b/tests/async/tfuturestream.nim @@ -18,8 +18,8 @@ var fs = newFutureStream[int]() proc alpha() {.async.} = for i in 0 .. 5: - await sleepAsync(1000) await fs.write(i) + await sleepAsync(1000) echo("Done") fs.complete() diff --git a/tests/async/tgeneric_async.nim b/tests/async/tgeneric_async.nim index af6370181..bab2d1a31 100644 --- a/tests/async/tgeneric_async.nim +++ b/tests/async/tgeneric_async.nim @@ -1,9 +1,40 @@ +discard """ +output: "1\nmessa" +""" -import asyncdispatch +import async -when true: - # bug #2377 - proc test[T](v: T) {.async.} = - echo $v +# bug #2377 +proc test[T](v: T) {.async.} = + echo $v + +asyncCheck test[int](1) + +# More complex case involving typedesc and static params +type + SomeMsg = object + data: string + +template msgId(M: type SomeMsg): int = 1 + +proc recvMsg(): Future[tuple[msgId: int, msgData: string]] {.async.} = + return (1, "message") + +proc read(data: string, T: type SomeMsg, maxBytes: int): T = + result.data = data[0 ..< min(data.len, maxBytes)] + +proc nextMsg*(MsgType: typedesc, + maxBytes: static[int]): Future[MsgType] {.async.} = + const wantedId = MsgType.msgId + + while true: + var (nextMsgId, nextMsgData) = await recvMsg() + if nextMsgId == wantedId: + return nextMsgData.read(MsgType, maxBytes) + +proc main {.async.} = + let msg = await nextMsg(SomeMsg, 5) + echo msg.data + +asyncCheck main() - asyncCheck test[int](1) diff --git a/tests/async/tjsandnativeasync.nim b/tests/async/tjsandnativeasync.nim new file mode 100644 index 000000000..45839899f --- /dev/null +++ b/tests/async/tjsandnativeasync.nim @@ -0,0 +1,30 @@ +discard """ + output: '''hi +bye''' +""" + +import async, times +when defined(js): + proc sleepAsync(t: int): Future[void] = + var promise = newPromise() do(resolve: proc()): + {.emit: """ + setTimeout(function(){ + `resolve`(); + }, `t`); + """.} + result = promise +else: + from asyncdispatch import sleepAsync, waitFor + +proc foo() {.async.} = + echo "hi" + var s = epochTime() + await sleepAsync(500) + var e = epochTime() + doAssert(e - s > 0.1) + echo "bye" + +when defined(js): + discard foo() +else: + waitFor foo() diff --git a/tests/async/tlambda.nim b/tests/async/tlambda.nim index d187c0d50..8f570689b 100644 --- a/tests/async/tlambda.nim +++ b/tests/async/tlambda.nim @@ -1,7 +1,7 @@ # bug 2007 -import asyncdispatch, asyncnet, logging, json, uri, strutils, future +import asyncdispatch, asyncnet, logging, json, uri, strutils, sugar type Builder = ref object @@ -27,7 +27,7 @@ proc newBuild*(onProgress: ProgressCB): Build = result.onProgress = onProgress proc start(build: Build, repo, hash: string) {.async.} = - let path = repo.parseUri().path.toLower() + let path = repo.parseUri().path.toLowerAscii() proc onProgress(builder: Builder, message: string) {.async.} = debug($message) diff --git a/tests/bind/tinvalidbindtypedesc.nim b/tests/bind/tinvalidbindtypedesc.nim index 7704d2cb7..ecdd12603 100644 --- a/tests/bind/tinvalidbindtypedesc.nim +++ b/tests/bind/tinvalidbindtypedesc.nim @@ -1,6 +1,6 @@ discard """ line: 10 - errormsg: "type mismatch: got (type float, string)" + errormsg: "type mismatch: got <type float, string>" """ proc foo(T: typedesc; some: T) = diff --git a/tests/bind/tnicerrorforsymchoice.nim b/tests/bind/tnicerrorforsymchoice.nim index 1431720e0..8c3a99c97 100644 --- a/tests/bind/tnicerrorforsymchoice.nim +++ b/tests/bind/tnicerrorforsymchoice.nim @@ -1,6 +1,6 @@ discard """ line: 18 - errormsg: "type mismatch: got (proc (s: TScgi: ScgiState or AsyncScgiState) | proc (client: AsyncSocket, headers: StringTableRef, input: string){.noSideEffect, gcsafe, locks: 0.}" + errormsg: "type mismatch: got <proc (s: TScgi: ScgiState or AsyncScgiState) | proc (client: AsyncSocket, headers: StringTableRef, input: string){.noSideEffect, gcsafe, locks: 0.}>" """ #bug #442 diff --git a/tests/casestmt/tcaseexpr1.nim b/tests/casestmt/tcaseexpr1.nim index 56acbbc8a..24543f1b8 100644 --- a/tests/casestmt/tcaseexpr1.nim +++ b/tests/casestmt/tcaseexpr1.nim @@ -2,7 +2,7 @@ discard """ file: "tcaseexpr1.nim" line: 29 - errormsg: "type mismatch: got (string) but expected 'int'" + errormsg: "type mismatch: got <string> but expected 'int'" line: 23 errormsg: "not all cases are covered" diff --git a/tests/casestmt/tcasestm.nim b/tests/casestmt/tcasestm.nim index b005d8120..4d32d023f 100644 --- a/tests/casestmt/tcasestm.nim +++ b/tests/casestmt/tcasestm.nim @@ -45,15 +45,24 @@ let a = case str1: echo "no good" quit("quiting") -let b = case str2: - of nil, "": raise newException(ValueError, "Invalid boolean") - elif str2[0] == 'Y': true - elif str2[0] == 'N': false - else: "error".quit(2) +proc toBool(s: string): bool = + case s: + of nil, "": raise newException(ValueError, "Invalid boolean") + elif s[0] == 'Y': true + elif s[0] == 'N': false + else: "error".quit(2) + + +let b = "NN".toBool() doAssert(a == true) doAssert(b == false) +static: + #bug #7407 + let bstatic = "N".toBool() + doAssert(bstatic == false) + var bb: bool doassert(not compiles( bb = case str2: diff --git a/tests/casestmt/tduplicates.nim b/tests/casestmt/tduplicates.nim new file mode 100644 index 000000000..f9fc1cc26 --- /dev/null +++ b/tests/casestmt/tduplicates.nim @@ -0,0 +1,50 @@ +discard """ + output: ''' +OK +OK +OK + ''' +""" + +type Kind = enum A, B +var k = A + +template reject(b) = + static: doAssert(not compiles(b)) + +reject: + var i = 2 + case i + of [1, 1]: discard + else: discard + +reject: + var i = 2 + case i + of 1, { 1..2 }: discard + else: discard + +reject: + var i = 2 + case i + of { 1, 1 }: discard + of { 1, 1 }: discard + else: discard + +reject: + case k + of [A, A]: discard + +var i = 2 +case i +of { 1, 1 }: discard +of { 2, 2 }: echo "OK" +else: discard + +case i +of { 10..30, 15..25, 5..15, 25..35 }: discard +else: echo "OK" + +case k +of {A, A..A}: echo "OK" +of B: discard \ No newline at end of file diff --git a/tests/ccgbugs/mymodule.nim b/tests/ccgbugs/mymodule.nim new file mode 100644 index 000000000..8c78cdf9b --- /dev/null +++ b/tests/ccgbugs/mymodule.nim @@ -0,0 +1,14 @@ +type + MyRefObject* = ref object + s: string + + BaseObj* = ref object of RootObj + ChildObj* = ref object of BaseObj + +proc newMyRefObject*(s: string): MyRefObject = + new(result) + result.s = s + +proc `$`*(o: MyRefObject): string = + o.s + \ No newline at end of file diff --git a/tests/ccgbugs/t7079.nim b/tests/ccgbugs/t7079.nim new file mode 100644 index 000000000..bfa1b77a6 --- /dev/null +++ b/tests/ccgbugs/t7079.nim @@ -0,0 +1,9 @@ +discard """ + action: run + targets: '''c js''' +""" + +import math +let x = -0.0 +doAssert classify(x) == fcNegZero +doAssert classify(1 / -0.0) == fcNegInf \ No newline at end of file diff --git a/tests/ccgbugs/tcodegenbug1.nim b/tests/ccgbugs/tcodegenbug1.nim index 671974087..fce74de0c 100644 --- a/tests/ccgbugs/tcodegenbug1.nim +++ b/tests/ccgbugs/tcodegenbug1.nim @@ -1,3 +1,34 @@ +discard """ + output: '''obj = (inner: (kind: Just, id: 7)) +obj.inner.id = 7 +id = 7 +obj = (inner: (kind: Just, id: 7))''' +""" + +# bug #6960 + +import future +type + Kind = enum None, Just, Huge + Inner = object + case kind: Kind + of None: discard + of Just: id: int + of Huge: a,b,c,d,e,f: string + Outer = object + inner: Inner + + +proc shouldDoNothing(id: int): Inner = + dump id + Inner(kind: Just, id: id) + +var obj = Outer(inner: Inner(kind: Just, id: 7)) +dump obj +dump obj.inner.id +obj.inner = shouldDoNothing(obj.inner.id) +dump obj + import os type diff --git a/tests/ccgbugs/tforward_decl_only.nim b/tests/ccgbugs/tforward_decl_only.nim new file mode 100644 index 000000000..2a867bc3b --- /dev/null +++ b/tests/ccgbugs/tforward_decl_only.nim @@ -0,0 +1,34 @@ +discard """ +ccodecheck: "\\i !@('struct tyObject_MyRefObject'[0-z]+' {')" +output: "hello" +""" + +# issue #7339 +# Test that MyRefObject is only forward declared as it used only by reference + +import mymodule +type AnotherType = object + f: MyRefObject + +let x = AnotherType(f: newMyRefObject("hello")) +echo $x.f + + +# bug #7363 + +type + Foo = object + a: cint + Foo2 = object + b: cint + +proc f(foo: ptr Foo, foo2: ptr Foo2): cint = + if foo != nil: {.emit: "`result` = `foo`->a;".} + if foo2 != nil: {.emit: [result, " = ", foo2[], ".b;"].} + +discard f(nil, nil) + + +# bug #7392 +var x1: BaseObj +var x2 = ChildObj(x1) diff --git a/tests/ccgbugs/tresult_of_array.nim b/tests/ccgbugs/tresult_of_array.nim new file mode 100644 index 000000000..fb5abf18a --- /dev/null +++ b/tests/ccgbugs/tresult_of_array.nim @@ -0,0 +1,29 @@ +discard """ + output: '''false +true +false +[false, false, false] +''' +""" + +# bug #7332 +# resetLoc generate incorrect memset code +# because of array passed as argument decaying into a pointer + +import tables +const tableOfArray = { + "one": [true, false, false], + "two": [false, true, false], + "three": [false, false, true] +}.toTable() +for i in 0..2: + echo tableOfArray["two"][i] + +var seqOfArray = @[ + [true, false, false], + [false, true, false], + [false, false, true] +] +proc crashingProc*[B](t: seq[B], index: Natural): B = + discard +echo seqOfArray.crashingProc(0) diff --git a/tests/clearmsg/ta.nim b/tests/clearmsg/ta.nim index 38449c319..31baae773 100644 --- a/tests/clearmsg/ta.nim +++ b/tests/clearmsg/ta.nim @@ -1,5 +1,5 @@ discard """ - errormsg: "type mismatch: got (mc.typ)" + errormsg: "type mismatch: got <mc.typ>" line: 12 """ diff --git a/tests/closure/tinvalidclosure.nim b/tests/closure/tinvalidclosure.nim index d3f38cde5..4e5f61f06 100644 --- a/tests/closure/tinvalidclosure.nim +++ b/tests/closure/tinvalidclosure.nim @@ -1,6 +1,6 @@ discard """ line: 12 - errormsg: "type mismatch: got (proc (x: int){.gcsafe, locks: 0.})" + errormsg: "type mismatch: got <proc (x: int){.gcsafe, locks: 0.}>" """ proc ugh[T](x: T) {.nimcall.} = diff --git a/tests/collections/tcollections_to_string.nim b/tests/collections/tcollections_to_string.nim index 6cc8a84ff..48b06a6aa 100644 --- a/tests/collections/tcollections_to_string.nim +++ b/tests/collections/tcollections_to_string.nim @@ -85,14 +85,20 @@ block: s.addQuoted('\0') s.addQuoted('\31') s.addQuoted('\127') - s.addQuoted('\255') - doAssert s == "'\\x00''\\x1F''\\x7F''\\xFF'" + doAssert s == "'\\x00''\\x1F''\\x7F'" block: var s = "" s.addQuoted('\\') s.addQuoted('\'') s.addQuoted('\"') doAssert s == """'\\''\'''\"'""" +block: + var s = "" + s.addQuoted("Ã¥") + s.addQuoted("ä") + s.addQuoted("ö") + s.addEscapedChar('\xFF') + doAssert s == """"Ã¥""ä""ö"\xFF""" # Test customized element representation type CustomString = object diff --git a/tests/collections/thashes.nim b/tests/collections/thashes.nim index 76b99313c..5cc3cc8bb 100644 --- a/tests/collections/thashes.nim +++ b/tests/collections/thashes.nim @@ -3,7 +3,7 @@ discard """ """ import tables -from hashes import THash +from hashes import Hash # Test with int block: @@ -66,7 +66,7 @@ block: # The same test with a custom hash(s: string) does # work though. block: - proc hash(x: int): THash {.inline.} = + proc hash(x: int): Hash {.inline.} = echo "overloaded hash" result = x var t = initTable[int, int]() diff --git a/tests/collections/tsets.nim b/tests/collections/tsets.nim index 6139560bd..61e14260a 100644 --- a/tests/collections/tsets.nim +++ b/tests/collections/tsets.nim @@ -1,4 +1,6 @@ import sets +import hashes +import algorithm block setEquality: var @@ -35,7 +37,7 @@ block setWithSequences: doAssert( not s.contains(@[4, 5, 6]) ) block setClearWorked: - var s = initSet[char]() + var s = initSet[char]() for c in "this is a test": s.incl(c) @@ -68,12 +70,54 @@ block orderedSetClearWorked: for c in "eat at joes": s.incl(c) - r = "" + r = "" for c in items(s): add(r, c) doAssert r == "zeat jos" +block hashForHashedSet: + let + seq1 = "This is the test." + seq2 = "the test is This." + s1 = seq1.toSet() + s2 = seq2.toSet() + var hashSeq: seq[Hash] = @[] + doAssert s1 == s2 + doAssert hash(s1) == hash(s2) + +block hashForOrderdSet: + let + str = "This is the test." + rstr = str.reversed - - + var + s1 = initOrderedSet[char]() + s2 = initOrderedSet[char]() + r = initOrderedSet[char]() + expected: Hash + added: seq[char] = @[] + reversed: Hash + radded: seq[char] = @[] + + expected = 0 + for c in str: + if (not (c in added)): + expected = expected !& hash(c) + added.add(c) + s1.incl(c) + s2.incl(c) + expected = !$expected + doAssert hash(s1) == expected + doAssert hash(s1) == hash(s2) + doAssert hash(s1) != hash(r) + + reversed = 0 + for c in rstr: + if (not (c in radded)): + reversed = reversed !& hash(c) + radded.add(c) + r.incl(c) + reversed = !$reversed + doAssert hash(r) == reversed + doAssert hash(s1) != reversed diff --git a/tests/compiles/trecursive_generic_in_compiles.nim b/tests/compiles/trecursive_generic_in_compiles.nim index 77bf0bb02..9c7fd10b3 100644 --- a/tests/compiles/trecursive_generic_in_compiles.nim +++ b/tests/compiles/trecursive_generic_in_compiles.nim @@ -1,6 +1,6 @@ # bug #3313 -import unittest, future - +import unittest, sugar +{.experimental: "notnil".} type ListNodeKind = enum lnkNil, lnkCons diff --git a/tests/concepts/t3330.nim b/tests/concepts/t3330.nim index 722c0a0e0..a4fff7fb3 100644 --- a/tests/concepts/t3330.nim +++ b/tests/concepts/t3330.nim @@ -1,25 +1,48 @@ discard """ -errormsg: "type mismatch: got (Bar[system.int])" +errormsg: "type mismatch: got <Bar[system.int]>" nimout: ''' -t3330.nim(40, 4) Error: type mismatch: got (Bar[system.int]) +t3330.nim(63, 4) Error: type mismatch: got <Bar[system.int]> but expected one of: proc test(foo: Foo[int]) -t3330.nim(25, 8) Hint: Non-matching candidates for add(k, string, T) +t3330.nim(48, 8) Hint: Non-matching candidates for add(k, string, T) proc add(x: var string; y: string) -proc add(result: var string; x: float) + first type mismatch at position: 1 + required type: var string + but expression 'k' is of type: Alias proc add(x: var string; y: char) + first type mismatch at position: 1 + required type: var string + but expression 'k' is of type: Alias proc add(result: var string; x: int64) + first type mismatch at position: 1 + required type: var string + but expression 'k' is of type: Alias +proc add(result: var string; x: float) + first type mismatch at position: 1 + required type: var string + but expression 'k' is of type: Alias proc add(x: var string; y: cstring) + first type mismatch at position: 1 + required type: var string + but expression 'k' is of type: Alias proc add[T](x: var seq[T]; y: openArray[T]) + first type mismatch at position: 1 + required type: var seq[T] + but expression 'k' is of type: Alias proc add[T](x: var seq[T]; y: T) + first type mismatch at position: 1 + required type: var seq[T] + but expression 'k' is of type: Alias -t3330.nim(25, 8) template/generic instantiation from here -t3330.nim(32, 6) Foo: 'bar.value' cannot be assigned to -t3330.nim(25, 8) template/generic instantiation from here -t3330.nim(33, 6) Foo: 'bar.x' cannot be assigned to -''' +t3330.nim(48, 8) template/generic instantiation from here +t3330.nim(55, 6) Foo: 'bar.value' cannot be assigned to +t3330.nim(48, 8) template/generic instantiation from here +t3330.nim(56, 6) Foo: 'bar.x' cannot be assigned to + +expression: test(bar)''' """ + type Foo[T] = concept k add(k, string, T) diff --git a/tests/concepts/texplain.nim b/tests/concepts/texplain.nim index de8ddf890..4925a25b3 100644 --- a/tests/concepts/texplain.nim +++ b/tests/concepts/texplain.nim @@ -26,14 +26,14 @@ texplain.nim(70, 6) ExplainedConcept: undeclared field: '.' texplain.nim(70, 6) ExplainedConcept: expression '.' cannot be called texplain.nim(69, 5) ExplainedConcept: concept predicate failed -texplain.nim(113, 20) Error: type mismatch: got (NonMatchingType) +texplain.nim(113, 20) Error: type mismatch: got <NonMatchingType> but expected one of: proc e(o: ExplainedConcept): int texplain.nim(69, 5) ExplainedConcept: concept predicate failed proc e(i: int): int expression: e(n) -texplain.nim(114, 20) Error: type mismatch: got (NonMatchingType) +texplain.nim(114, 20) Error: type mismatch: got <NonMatchingType> but expected one of: proc r(o: RegularConcept): int texplain.nim(73, 5) RegularConcept: concept predicate failed @@ -45,7 +45,7 @@ texplain.nim(115, 20) Hint: Non-matching candidates for r(y) proc r[T](a: SomeNumber; b: T; c: auto) proc r(i: string): int -texplain.nim(123, 2) Error: type mismatch: got (MatchingType) +texplain.nim(123, 2) Error: type mismatch: got <MatchingType> but expected one of: proc f(o: NestedConcept) texplain.nim(73, 6) RegularConcept: undeclared field: 'foo' @@ -61,7 +61,7 @@ texplain.nim(77, 5) NestedConcept: concept predicate failed expression: f(y) ''' line: 123 - errormsg: "type mismatch: got (MatchingType)" + errormsg: "type mismatch: got <MatchingType>" """ type diff --git a/tests/concepts/tseqofconcept.nim b/tests/concepts/tseqofconcept.nim new file mode 100644 index 000000000..5e44117ea --- /dev/null +++ b/tests/concepts/tseqofconcept.nim @@ -0,0 +1,19 @@ +discard """ +output: "1\n2\n3" +""" + +type + MyConcept = concept x + someProc(x) + + SomeSeq = seq[MyConcept] + +proc someProc(x:int) = echo x + +proc work (s: SomeSeq) = + for item in s: + someProc item + +var s = @[1, 2, 3] +work s + diff --git a/tests/concepts/tstackconcept.nim b/tests/concepts/tstackconcept.nim index 2238dacb6..cb8db566d 100644 --- a/tests/concepts/tstackconcept.nim +++ b/tests/concepts/tstackconcept.nim @@ -31,7 +31,7 @@ type s.pop() is T type ValueType = T - const ValueTypeName = T.name.toUpper + const ValueTypeName = T.name.toUpperAscii proc genericAlgorithm[T](s: var Stack[T], y: T) = static: diff --git a/tests/concepts/twrapconcept.nim b/tests/concepts/twrapconcept.nim index 25a855e34..377b63afe 100644 --- a/tests/concepts/twrapconcept.nim +++ b/tests/concepts/twrapconcept.nim @@ -1,5 +1,5 @@ discard """ - errormsg: "type mismatch: got (string)" + errormsg: "type mismatch: got <string>" line: 21 nimout: "twrapconcept.nim(11, 5) Foo: concept predicate failed" """ @@ -9,7 +9,7 @@ discard """ type Foo = concept foo foo.get is int - + FooWrap[F: Foo] = object foo: F diff --git a/tests/constraints/tconstraints.nim b/tests/constraints/tconstraints.nim index ea3f68fd4..3c9fdc354 100644 --- a/tests/constraints/tconstraints.nim +++ b/tests/constraints/tconstraints.nim @@ -1,6 +1,6 @@ discard """ line: 16 - errormsg: "type mismatch: got (int literal(232))" + errormsg: "type mismatch: got <int literal(232)>" """ proc myGenericProc[T: object|tuple|ptr|ref|distinct](x: T): string = diff --git a/tests/constructors/tinvalid_construction.nim b/tests/constructors/tinvalid_construction.nim index bb3b1bebb..b3e56eec6 100644 --- a/tests/constructors/tinvalid_construction.nim +++ b/tests/constructors/tinvalid_construction.nim @@ -3,12 +3,12 @@ template accept(x) = template reject(x) = static: assert(not compiles(x)) - +{.experimental: "notnil".} type TRefObj = ref object x: int - THasNotNils = object of TObject + THasNotNils = object of RootObj a: TRefObj not nil b: TRefObj not nil c: TRefObj diff --git a/tests/controlflow/tstatret.nim b/tests/controlflow/tstatret.nim index d655f5595..04cac9966 100644 --- a/tests/controlflow/tstatret.nim +++ b/tests/controlflow/tstatret.nim @@ -1,7 +1,7 @@ discard """ file: "tstatret.nim" line: 9 - errormsg: "statement not allowed after" + errormsg: "unreachable statement after 'return'" """ # no statement after return proc main() = diff --git a/tests/converter/tconvert.nim b/tests/converter/tconvert.nim index a37140234..48367a85b 100644 --- a/tests/converter/tconvert.nim +++ b/tests/converter/tconvert.nim @@ -15,6 +15,6 @@ type TFoo = object converter toPtr*(some: var TFoo): ptr TFoo = (addr some) -proc zoot(x: ptr TFoo) = nil +proc zoot(x: ptr TFoo) = discard var x: Tfoo zoot(x) diff --git a/tests/cpp/tcovariancerules.nim b/tests/cpp/tcovariancerules.nim index 9365a3a18..acde1b288 100644 --- a/tests/cpp/tcovariancerules.nim +++ b/tests/cpp/tcovariancerules.nim @@ -13,14 +13,8 @@ cat cat dog dog -dog value -cat value -dog value -cat value dog dog -dog value -cat value dog 1 dog 2 ''' @@ -243,11 +237,12 @@ reject modifiesCovariantArray(dogRefsArray.addr) var dogValues = @[vdog, vdog] var dogValuesArray = [vdog, vdog] -var animalValues = @[Animal(vdog), Animal(vcat)] -var animalValuesArray = [Animal(vdog), Animal(vcat)] +when false: + var animalValues = @[Animal(vdog), Animal(vcat)] + var animalValuesArray = [Animal(vdog), Animal(vcat)] -wantsNonCovariantSeq animalValues -wantsNonCovariantArray animalValuesArray + wantsNonCovariantSeq animalValues + wantsNonCovariantArray animalValuesArray reject wantsNonCovariantSeq(dogRefs) reject modifiesCovariantOperArray(dogRefs) @@ -260,7 +255,6 @@ modifiesDerivedOperArray dogRefs reject modifiesDerivedOperArray(dogValues) reject modifiesDerivedOperArray(animalRefs) -wantsNonCovariantOperArray animalValues reject wantsNonCovariantOperArray(animalRefs) reject wantsNonCovariantOperArray(dogRefs) reject wantsNonCovariantOperArray(dogValues) @@ -300,7 +294,7 @@ reject wantsVarPointer2(pcat) # covariance may be allowed for certain extern types -{.emit: """ +{.emit: """/*TYPESECTION*/ template <class T> struct FN { typedef void (*type)(T); }; template <class T> struct ARR { typedef T DataType[2]; DataType data; }; """.} diff --git a/tests/cpp/tcppraise.nim b/tests/cpp/tcppraise.nim index 7db9c0cfa..f359a2e8b 100644 --- a/tests/cpp/tcppraise.nim +++ b/tests/cpp/tcppraise.nim @@ -3,7 +3,9 @@ discard """ output: '''foo bar Need odd and >= 3 digits## -baz''' +baz +caught +''' """ # bug #1888 @@ -15,3 +17,21 @@ try: except ValueError: echo getCurrentExceptionMsg(), "##" echo "baz" + + +# bug 7232 +try: + discard +except KeyError, ValueError: + echo "except handler" # should not be invoked + + +#bug 7239 +try: + try: + raise newException(ValueError, "asdf") + except KeyError, ValueError: + raise +except: + echo "caught" + diff --git a/tests/cpp/temitlist.nim b/tests/cpp/temitlist.nim index a7a8ebde4..e88bf45bd 100644 --- a/tests/cpp/temitlist.nim +++ b/tests/cpp/temitlist.nim @@ -1,6 +1,7 @@ discard """ targets: "cpp" - output: '''6.0''' + output: '''6.0 +0''' """ # bug #4730 @@ -20,3 +21,16 @@ proc main = echo v[0] main() + +#------------ + +#bug #6837 +type StdString {.importCpp: "std::string", header: "<string>", byref.} = object +proc initString(): StdString {.constructor, importCpp: "std::string(@)", header: "<string>".} +proc size(this: var StdString): csize {.importCpp: "size", header: "<string>".} + +proc f(): csize = + var myString: StdString = initString() + return myString.size() + +echo f() diff --git a/tests/cpp/tvector_iterator.nim b/tests/cpp/tvector_iterator.nim index 9df3754ba..4d686955f 100644 --- a/tests/cpp/tvector_iterator.nim +++ b/tests/cpp/tvector_iterator.nim @@ -2,7 +2,7 @@ discard """ targets: "cpp" """ -{.emit: """ +{.emit: """/*TYPESECTION*/ template <class T> struct Vector { diff --git a/tests/discard/tneedsdiscard.nim b/tests/discard/tneedsdiscard.nim index 509e8233b..8d59e7fec 100644 --- a/tests/discard/tneedsdiscard.nim +++ b/tests/discard/tneedsdiscard.nim @@ -1,6 +1,6 @@ discard """ line: 10 - errormsg: '''expression 'open(f, "arg.txt", fmRead, -1)' is of type 'bool' and has to be discarded''' + errormsg: '''expression 'open(f, "arg.txt", fmRead, -1)' is of type 'bool' and has to be discarded; start of expression here: tneedsdiscard.nim(7, 2)''' """ proc p = diff --git a/tests/distinct/tnil.nim b/tests/distinct/tnil.nim index e60437a1f..759a14657 100644 --- a/tests/distinct/tnil.nim +++ b/tests/distinct/tnil.nim @@ -1,15 +1,11 @@ discard """ file: "tnil.nim" - output: '''0x1 - -nil - -nil - + output: '''1 +0 +0 ''' - disabled: "windows" """ - +{.experimental: "notnil".} type MyPointer = distinct pointer MyString = distinct string @@ -17,7 +13,8 @@ type MyInt = distinct int proc foo(a: MyPointer) = - echo a.repr + # workaround a Windows 'repr' difference: + echo cast[int](a) foo(cast[MyPointer](1)) foo(cast[MyPointer](nil)) diff --git a/tests/effects/teffects4.nim b/tests/effects/teffects4.nim index fd5dd49e2..d0960126f 100644 --- a/tests/effects/teffects4.nim +++ b/tests/effects/teffects4.nim @@ -12,7 +12,7 @@ type EIO2 = ref object of EIO proc q() {.tags: [FIO].} = - nil + discard proc raiser(): int = writeLine stdout, "arg" diff --git a/tests/effects/tgcsafe2.nim b/tests/effects/tgcsafe2.nim index 0b2c090a7..07da4e3f8 100644 --- a/tests/effects/tgcsafe2.nim +++ b/tests/effects/tgcsafe2.nim @@ -1,5 +1,5 @@ discard """ - errormsg: '''type mismatch: got (proc (s: string){.locks: 0.})''' + errormsg: '''type mismatch: got <proc (s: string){.locks: 0.}>''' line: 11 """ #5620 diff --git a/tests/enum/toptions.nim b/tests/enum/toptions.nim index e53acb2b3..da66f0067 100644 --- a/tests/enum/toptions.nim +++ b/tests/enum/toptions.nim @@ -4,7 +4,7 @@ type TOption = enum optNone, optForceFullMake, optBoehmGC, optRefcGC, optRangeCheck, optBoundsCheck, optOverflowCheck, optNilCheck, optAssert, optLineDir, - optWarns, optHints, optDeadCodeElim, optListCmd, optCompileOnly, + optWarns, optHints, optListCmd, optCompileOnly, optSafeCode, # only allow safe code optStyleCheck, optOptimizeSpeed, optOptimizeSize, optGenDynLib, optGenGuiApp, optStackTrace diff --git a/tests/errmsgs/t1154.nim b/tests/errmsgs/t1154.nim new file mode 100644 index 000000000..7fcbf8a27 --- /dev/null +++ b/tests/errmsgs/t1154.nim @@ -0,0 +1,11 @@ +discard """ +errormsg: "invalid type: 'expr' in this context: 'proc (a: varargs[expr])' for proc" +line: 8 +""" + +import typetraits + +proc foo(a:varargs[expr]) = + echo a[0].type.name + +foo(1) diff --git a/tests/errmsgs/t4756.nim b/tests/errmsgs/t4756.nim index 91fc90f4b..262614ba0 100644 --- a/tests/errmsgs/t4756.nim +++ b/tests/errmsgs/t4756.nim @@ -1,5 +1,5 @@ discard """ -errormsg: "type mismatch: got (string, arr: seq[empty])" +errormsg: "type mismatch: got <string, arr: seq[empty]>" line: 15 """ diff --git a/tests/errmsgs/t5167_4.nim b/tests/errmsgs/t5167_4.nim index 3d77fae02..7a263622b 100644 --- a/tests/errmsgs/t5167_4.nim +++ b/tests/errmsgs/t5167_4.nim @@ -1,5 +1,5 @@ discard """ -errormsg: "type mismatch: got (proc [*missing parameters*](x: int) | proc (x: string){.gcsafe, locks: 0.})" +errormsg: "type mismatch: got <proc [*missing parameters*](x: int) | proc (x: string){.gcsafe, locks: 0.}>" line: 19 """ diff --git a/tests/errmsgs/tcant_overload_by_return_type.nim b/tests/errmsgs/tcant_overload_by_return_type.nim new file mode 100644 index 000000000..613a896b4 --- /dev/null +++ b/tests/errmsgs/tcant_overload_by_return_type.nim @@ -0,0 +1,9 @@ +discard """ +errormsg: "overloaded 'x' leads to ambiguous calls" +line: 9 +""" + +# bug #6393 + +proc x(): int = 7 +proc x(): string = "strange" diff --git a/tests/errmsgs/tconceptconstraint.nim b/tests/errmsgs/tconceptconstraint.nim index c1f0b94eb..9ab1708c7 100644 --- a/tests/errmsgs/tconceptconstraint.nim +++ b/tests/errmsgs/tconceptconstraint.nim @@ -2,15 +2,15 @@ discard """ errormsg: "cannot instantiate B" line: 20 nimout: ''' -got: (type string) -but expected: (T: A) +got: <type string> +but expected: <T: A> ''' """ type A = concept c advance(c) - + B[T: A] = object child: ref B[T] diff --git a/tests/errmsgs/tdetailed_position.nim b/tests/errmsgs/tdetailed_position.nim new file mode 100644 index 000000000..ce5b18bbd --- /dev/null +++ b/tests/errmsgs/tdetailed_position.nim @@ -0,0 +1,22 @@ + +discard """ +cmd: "nim check $file" +errormsg: "type mismatch: got <int literal(1), int literal(2), int literal(3)>" +nimout: ''' +but expected one of: +proc main(a, b, c: string) + first type mismatch at position: 1 + required type: string + but expression '1' is of type: int literal(1) + +expression: main(1, 2, 3) +''' +""" + +const + myconst = "abcdefghijklmnopqrstuvwxyz" + +proc main(a, b, c: string) {.deprecated: "use foo " & "instead " & myconst.} = + return + +main(1, 2, 3) diff --git a/tests/errmsgs/tgcsafety.nim b/tests/errmsgs/tgcsafety.nim new file mode 100644 index 000000000..4d192db90 --- /dev/null +++ b/tests/errmsgs/tgcsafety.nim @@ -0,0 +1,30 @@ +discard """ +cmd: "nim check $file" +errormsg: "type mismatch: got <AsyncHttpServer, Port, proc (req: Request): Future[system.void]{.locks: <unknown>.}>" +nimout: ''' +type mismatch: got <AsyncHttpServer, Port, proc (req: Request): Future[system.void]{.locks: <unknown>.}> +but expected one of: +proc serve(server: AsyncHttpServer; port: Port; + callback: proc (request: Request): Future[void]; address = ""): Future[void] + first type mismatch at position: 3 + required type: proc (request: Request): Future[system.void]{.closure, gcsafe.} + but expression 'cb' is of type: proc (req: Request): Future[system.void]{.locks: <unknown>.} + This expression is not GC-safe. Annotate the proc with {.gcsafe.} to get extended error information. + +expression: serve(server, Port(7898), cb) +''' +""" + +# bug #6186 + +import asyncdispatch, asynchttpserver + +var server = newAsyncHttpServer() + +var foo = "foo" +proc cb(req: Request) {.async.} = + var baa = foo & "asds" + await req.respond(Http200, baa) + +asyncCheck server.serve(Port(7898), cb ) +runForever() diff --git a/tests/errmsgs/tgenericconstraint.nim b/tests/errmsgs/tgenericconstraint.nim index 9129d257b..e3093fead 100644 --- a/tests/errmsgs/tgenericconstraint.nim +++ b/tests/errmsgs/tgenericconstraint.nim @@ -2,8 +2,8 @@ discard """ errormsg: "cannot instantiate B" line: 14 nimout: ''' -got: (type int) -but expected: (T: string or float) +got: <type int> +but expected: <T: string or float> ''' """ diff --git a/tests/errmsgs/tinvalidinout.nim b/tests/errmsgs/tinvalidinout.nim index ce7eb6022..1fa3805ee 100644 --- a/tests/errmsgs/tinvalidinout.nim +++ b/tests/errmsgs/tinvalidinout.nim @@ -1,10 +1,10 @@ discard """ cmd: "nim check $file" -errormsg: "The `in` modifier can be used only with imported types" +errormsg: "the 'in' modifier can be used only with imported types" nimout: ''' -tinvalidinout.nim(14, 7) Error: The `out` modifier can be used only with imported types -tinvalidinout.nim(17, 9) Error: The `in` modifier can be used only with imported types -tinvalidinout.nim(18, 9) Error: The `in` modifier can be used only with imported types +tinvalidinout.nim(14, 7) Error: the 'out' modifier can be used only with imported types +tinvalidinout.nim(17, 9) Error: the 'in' modifier can be used only with imported types +tinvalidinout.nim(18, 9) Error: the 'in' modifier can be used only with imported types ''' """ diff --git a/tests/errmsgs/tmake_tuple_visible.nim b/tests/errmsgs/tmake_tuple_visible.nim index 43337c2a9..e059368ad 100644 --- a/tests/errmsgs/tmake_tuple_visible.nim +++ b/tests/errmsgs/tmake_tuple_visible.nim @@ -1,7 +1,7 @@ discard """ - errormsg: '''got (tuple of (type NimEdAppWindow, int))''' + errormsg: '''got <tuple of (type NimEdAppWindow, int)>''' line: 22 - nimout: '''got (tuple of (type NimEdAppWindow, int)) + nimout: '''got <tuple of (type NimEdAppWindow, int)> but expected one of: template xxx(tn: typedesc; i: int)''' """ diff --git a/tests/errmsgs/tnested_empty_seq.nim b/tests/errmsgs/tnested_empty_seq.nim new file mode 100644 index 000000000..ffe8bc3ee --- /dev/null +++ b/tests/errmsgs/tnested_empty_seq.nim @@ -0,0 +1,8 @@ +discard """ + errormsg: "invalid type: 'empty' in this context: 'array[0..0, tuple of (string, seq[empty])]' for var" + line: 8 +""" + +# bug #3948 + +var headers=[("headers", @[])] diff --git a/tests/errmsgs/tproper_stacktrace2.nim b/tests/errmsgs/tproper_stacktrace2.nim index 5f312b870..44b208c87 100644 --- a/tests/errmsgs/tproper_stacktrace2.nim +++ b/tests/errmsgs/tproper_stacktrace2.nim @@ -3,7 +3,7 @@ discard """ exitcode: 1 """ -proc returnsNil(): string = return nil +proc returnsNil(): ref int = return nil iterator fields*(a, b: int): int = if a == b: @@ -17,6 +17,6 @@ proc main(): string = result = "" for i in fields(0, 1): let x = returnsNil() - result &= "string literal " & $x + result &= "string literal " & $x[] echo main() diff --git a/tests/errmsgs/tshow_asgn.nim b/tests/errmsgs/tshow_asgn.nim index 250f786e2..1627c9b71 100644 --- a/tests/errmsgs/tshow_asgn.nim +++ b/tests/errmsgs/tshow_asgn.nim @@ -1,5 +1,5 @@ discard """ - errormsg: "type mismatch: got (int) but expected 'cshort = int16'" + errormsg: "type mismatch: got <int> but expected 'cshort = int16'" line: 12 column: 10 file: "tshow_asgn.nim" diff --git a/tests/errmsgs/twrong_at_operator.nim b/tests/errmsgs/twrong_at_operator.nim new file mode 100644 index 000000000..b6b3d101f --- /dev/null +++ b/tests/errmsgs/twrong_at_operator.nim @@ -0,0 +1,15 @@ +discard """ +errormsg: "type mismatch: got <array[0..0, type int]>" +line: 15 +nimout: ''' +twrong_at_operator.nim(15, 30) Error: type mismatch: got <array[0..0, type int]> +but expected one of: +proc `@`[T](a: openArray[T]): seq[T] +proc `@`[IDX, T](a: array[IDX, T]): seq[T] + +expression: @[int] +''' +""" + +# bug #7331 +var seqOfStrings: seq[int] = @[int] diff --git a/tests/errmsgs/twrongcolon.nim b/tests/errmsgs/twrongcolon.nim new file mode 100644 index 000000000..6f5cc3e5d --- /dev/null +++ b/tests/errmsgs/twrongcolon.nim @@ -0,0 +1,11 @@ +discard """ +errormsg: "in expression '(" +nimout: ''' +Error: in expression '( + 890)': identifier expected, but found '' +''' + +line: 11 +""" + +var n: int : 890 diff --git a/tests/exception/tcpp_imported_exc.nim b/tests/exception/tcpp_imported_exc.nim new file mode 100644 index 000000000..c8349f7d5 --- /dev/null +++ b/tests/exception/tcpp_imported_exc.nim @@ -0,0 +1,134 @@ +discard """ +targets: "cpp" +output: '''caught as std::exception +expected +finally1 +finally2 +finally2 +2 +expected +finally 1 +finally 2 +expected +cpp exception caught +''' +""" + +type + std_exception* {.importcpp: "std::exception", header: "<exception>".} = object + std_runtime_error* {.importcpp: "std::runtime_error", header: "<stdexcept>".} = object + std_string* {.importcpp: "std::string", header: "<string>".} = object + +proc constructStdString(s: cstring): std_string {.importcpp: "std::string(@)", constructor, header: "<string>".} + +proc constructRuntimeError(s: stdstring): std_runtime_error {.importcpp: "std::runtime_error(@)", constructor.} + +proc what(ex: std_runtime_error): cstring {.importcpp: "((char *)#.what())".} + +proc myexception = + raise constructRuntimeError(constructStdString("cpp_exception")) + +try: + myexception() # raise std::runtime_error +except std_exception: + echo "caught as std::exception" + try: + raise constructStdString("x") + except std_exception: + echo "should not happen" + except: + echo "expected" + +doAssert(getCurrentException() == nil) + +proc earlyReturn = + try: + try: + myexception() + finally: + echo "finally1" + except: + return + finally: + echo "finally2" + +earlyReturn() +doAssert(getCurrentException() == nil) + + +try: + block blk1: + try: + raise newException(ValueError, "mmm") + except: + break blk1 +except: + echo "should not happen" +finally: + echo "finally2" + +doAssert(getCurrentException() == nil) + +#-------------------------------------- + +# raise by pointer and also generic type + +type + std_vector {.importcpp"std::vector", header"<vector>".} [T] = object + +proc newVector[T](len: int): ptr std_vector[T] {.importcpp: "new std::vector<'1>(@)".} +proc deleteVector[T](v: ptr std_vector[T]) {.importcpp: "delete @; @ = NIM_NIL;".} +proc len[T](v: std_vector[T]): uint {.importcpp: "size".} + +var v = newVector[int](2) +try: + try: + try: + raise v + except ptr std_vector[int] as ex: + echo len(ex[]) + raise newException(ValueError, "msg5") + except: + echo "should not happen" + finally: + deleteVector(v) +except: + echo "expected" + +doAssert(v == nil) +doAssert(getCurrentException() == nil) + +#-------------------------------------- + +# mix of Nim and imported exceptions +try: + try: + try: + raise newException(KeyError, "msg1") + except KeyError: + raise newException(ValueError, "msg2") + except: + echo "should not happen" + finally: + echo "finally 1" + except: + doAssert(getCurrentExceptionMsg() == "msg2") + raise constructStdString("std::string") + finally: + echo "finally 2" +except: + echo "expected" + + +doAssert(getCurrentException() == nil) + +try: + try: + myexception() + except std_runtime_error as ex: + echo "cpp exception caught" + raise newException(ValueError, "rewritten " & $ex.what()) +except: + doAssert(getCurrentExceptionMsg() == "rewritten cpp_exception") + +doAssert(getCurrentException() == nil) diff --git a/tests/exception/tdont_overwrite_typename.nim b/tests/exception/tdont_overwrite_typename.nim index 147ccc001..6e3ff816f 100644 --- a/tests/exception/tdont_overwrite_typename.nim +++ b/tests/exception/tdont_overwrite_typename.nim @@ -1,4 +1,5 @@ discard """ + targets: "c cpp" output: '''Check passed Check passed''' """ diff --git a/tests/exception/texcas.nim b/tests/exception/texcas.nim index 4b4ebe448..7108e334c 100644 --- a/tests/exception/texcas.nim +++ b/tests/exception/texcas.nim @@ -1,4 +1,5 @@ discard """ + targets: "c cpp" output: '''Hello Hello ''' @@ -21,5 +22,21 @@ proc test2() = testTemplate(Exception) doAssert(not declared(foobar)) + +proc testTryAsExpr(i: int) = + let x = try: i + except ValueError as ex: + echo(ex.msg) + -1 + test[Exception]() -test2() \ No newline at end of file +test2() +testTryAsExpr(5) + +# see bug #7115 +doAssert(not compiles( + try: + echo 1 + except [KeyError as ex1, ValueError as ex2]: + echo 2 +)) diff --git a/tests/exception/tfinally.nim b/tests/exception/tfinally.nim index aa469d9c0..7a218b444 100644 --- a/tests/exception/tfinally.nim +++ b/tests/exception/tfinally.nim @@ -1,6 +1,18 @@ discard """ file: "tfinally.nim" - output: "came\nhere\n3" + output: '''came +here +3 +msg1 +msg2 +finally2 +finally1 +----------- +except1 +finally1 +except2 +finally2 +''' """ # Test return in try statement: @@ -17,3 +29,34 @@ proc main: int = echo main() #OUT came here 3 +#bug 7204 +proc nested_finally = + try: + raise newException(KeyError, "msg1") + except KeyError as ex: + echo ex.msg + try: + raise newException(ValueError, "msg2") + except: + echo getCurrentExceptionMsg() + finally: + echo "finally2" + finally: + echo "finally1" + +nested_finally() + +echo "-----------" +#bug 7414 +try: + try: + raise newException(Exception, "Hello") + except: + echo "except1" + raise + finally: + echo "finally1" +except: + echo "except2" +finally: + echo "finally2" \ No newline at end of file diff --git a/tests/exception/tnestedreturn.nim b/tests/exception/tnestedreturn.nim index 1480764f1..bf26f4903 100644 --- a/tests/exception/tnestedreturn.nim +++ b/tests/exception/tnestedreturn.nim @@ -1,4 +1,5 @@ discard """ + targets: "c cpp" file: "tnestedreturn.nim" output: "A\nB\nC\n" """ diff --git a/tests/exprs/tstmtexprs.nim b/tests/exprs/tstmtexprs.nim index 2a0ec2821..577f314ec 100644 --- a/tests/exprs/tstmtexprs.nim +++ b/tests/exprs/tstmtexprs.nim @@ -81,7 +81,7 @@ semiProblem() # bug #844 import json -proc parseResponse(): PJsonNode = +proc parseResponse(): JsonNode = result = % { "key1": % { "key2": % "value" } } for key, val in result["key1"]: var excMsg = key & "(" diff --git a/tests/flags/tgenscript.nim b/tests/flags/tgenscript.nim new file mode 100644 index 000000000..6a037b5d8 --- /dev/null +++ b/tests/flags/tgenscript.nim @@ -0,0 +1,5 @@ +discard """ + file: "tgenscript.nim" +""" + +echo "--genscript" diff --git a/tests/float/tfloat4.nim b/tests/float/tfloat4.nim index 559c8aaca..68df56be8 100644 --- a/tests/float/tfloat4.nim +++ b/tests/float/tfloat4.nim @@ -48,5 +48,11 @@ doAssert "2.71828182845904523536028747".parseFloat == 2.71828182845904523536028747 doAssert 0.00097656250000000021684043449710088680149056017398834228515625 == "0.00097656250000000021684043449710088680149056017398834228515625".parseFloat +doAssert 0.00998333 == ".00998333".parseFloat +doAssert 0.00128333 == ".00128333".parseFloat +doAssert 999999999999999.0 == "999999999999999.0".parseFloat +doAssert 9999999999999999.0 == "9999999999999999.0".parseFloat +doAssert 0.999999999999999 == ".999999999999999".parseFloat +doAssert 0.9999999999999999 == ".9999999999999999".parseFloat echo("passed all tests.") diff --git a/tests/fragmentation/tfragment_alloc.nim b/tests/fragmentation/tfragment_alloc.nim index 031588d27..5a44b7434 100644 --- a/tests/fragmentation/tfragment_alloc.nim +++ b/tests/fragmentation/tfragment_alloc.nim @@ -15,6 +15,10 @@ proc main = quit "could not serve request!" dealloc p # c_fprintf(stdout, "iteration: %ld size: %ld\n", i, size) + when defined(cpu64): + # bug #7120 + var x = alloc(((1 shl 29) - 4) * 8) + dealloc x main() diff --git a/tests/fragmentation/tfragment_gc.nim b/tests/fragmentation/tfragment_gc.nim index 1781f6610..d387bbea2 100644 --- a/tests/fragmentation/tfragment_gc.nim +++ b/tests/fragmentation/tfragment_gc.nim @@ -1,6 +1,7 @@ discard """ output: '''occupied ok: true total ok: true''' + disabled: "windows" """ import strutils, data @@ -20,11 +21,11 @@ let total = getTotalMem() # Concrete values on Win64: 58.152MiB / 188.285MiB -let occupiedOk = occ < 64 * 1024 * 1024 +let occupiedOk = occ < 82 * 1024 * 1024 if not occupiedOk: echo "occupied ", formatSize(occ) echo "occupied ok: ", occupiedOk -let totalOk = total < 210 * 1024 * 1024 +let totalOk = total < 230 * 1024 * 1024 if not totalOk: echo "total peak memory ", formatSize(total) echo "total ok: ", totalOk diff --git a/tests/gc/gcleak.nim b/tests/gc/gcleak.nim index 4e47db609..8852a8d91 100644 --- a/tests/gc/gcleak.nim +++ b/tests/gc/gcleak.nim @@ -13,11 +13,10 @@ proc MakeObj(): TTestObj = result.x = "Hello" for i in 1 .. 1_000_000: - when defined(gcMarkAndSweep): + when defined(gcMarkAndSweep) or defined(boehmgc): GC_fullcollect() var obj = MakeObj() if getOccupiedMem() > 300_000: quit("still a leak!") # echo GC_getstatistics() echo "no leak: ", getOccupiedMem() - diff --git a/tests/gc/gcleak2.nim b/tests/gc/gcleak2.nim index 101421683..facb8a008 100644 --- a/tests/gc/gcleak2.nim +++ b/tests/gc/gcleak2.nim @@ -16,7 +16,7 @@ proc MakeObj(): TTestObj = proc inProc() = for i in 1 .. 1_000_000: - when defined(gcMarkAndSweep): + when defined(gcMarkAndSweep) or defined(boehmgc): GC_fullcollect() var obj: TTestObj obj = MakeObj() @@ -24,5 +24,3 @@ proc inProc() = inProc() echo "no leak: ", getOccupiedMem() - - diff --git a/tests/gc/gcleak4.nim b/tests/gc/gcleak4.nim index d93a13854..e9b17e557 100644 --- a/tests/gc/gcleak4.nim +++ b/tests/gc/gcleak4.nim @@ -38,7 +38,7 @@ proc newPlus(a, b: ref TExpr): ref TPlusExpr = result.b = b result.op2 = $getOccupiedMem() -const Limit = when compileOption("gc", "markAndSweep"): 5*1024*1024 else: 500_000 +const Limit = when compileOption("gc", "markAndSweep") or compileOption("gc", "boehm"): 5*1024*1024 else: 500_000 for i in 0..100_000: var s: array[0..11, ref TExpr] diff --git a/tests/gc/gctest.nim b/tests/gc/gctest.nim index f5c81f033..7f5260200 100644 --- a/tests/gc/gctest.nim +++ b/tests/gc/gctest.nim @@ -179,24 +179,38 @@ proc main() = write(stdout, "done!\n") var - father: TBNode - s: string -s = "" -s = "" -writeLine(stdout, repr(caseTree())) -father.t.data = @["ha", "lets", "stress", "it"] -father.t.data = @["ha", "lets", "stress", "it"] -var t = buildTree() -write(stdout, repr(t[])) -buildBTree(father) -write(stdout, repr(father)) - -write(stdout, "starting main...\n") -main() - -GC_fullCollect() -# the M&S GC fails with this call and it's unclear why. Definitely something -# we need to fix! -GC_fullCollect() -writeLine(stdout, GC_getStatistics()) -write(stdout, "finished\n") + father {.threadvar.}: TBNode + s {.threadvar.}: string + + fatherAsGlobal: TBNode + +proc start = + s = "" + s = "" + writeLine(stdout, repr(caseTree())) + father.t.data = @["ha", "lets", "stress", "it"] + father.t.data = @["ha", "lets", "stress", "it"] + var t = buildTree() + write(stdout, repr(t[])) + buildBTree(father) + write(stdout, repr(father)) + + write(stdout, "starting main...\n") + main() + + GC_fullCollect() + # the M&S GC fails with this call and it's unclear why. Definitely something + # we need to fix! + #GC_fullCollect() + writeLine(stdout, GC_getStatistics()) + write(stdout, "finished\n") + +fatherAsGlobal.t.data = @["ha", "lets", "stress", "it"] +var tg = buildTree() +buildBTree(fatherAsGlobal) + +var thr: array[8, Thread[void]] +for i in low(thr)..high(thr): + createThread(thr[i], start) +joinThreads(thr) +start() diff --git a/tests/gc/gctest.nim.cfg b/tests/gc/gctest.nim.cfg new file mode 100644 index 000000000..aed303eef --- /dev/null +++ b/tests/gc/gctest.nim.cfg @@ -0,0 +1 @@ +--threads:on diff --git a/tests/generics/module_with_generics.nim b/tests/generics/module_with_generics.nim new file mode 100644 index 000000000..e801a4790 --- /dev/null +++ b/tests/generics/module_with_generics.nim @@ -0,0 +1,14 @@ +type + Base[T] = ref object {.inheritable.} + value*: T + + Derived[T] = ref object of Base[T] + derivedValue*: T + +proc makeDerived*[T](v: T): Derived[T] = + new result + result.value = v + +proc setBaseValue*[T](a: Base[T], value: T) = + a.value = value + diff --git a/tests/generics/t5602_inheritence.nim b/tests/generics/t5602_inheritence.nim index 6d48c796e..ee5ba89d5 100644 --- a/tests/generics/t5602_inheritence.nim +++ b/tests/generics/t5602_inheritence.nim @@ -1,10 +1,11 @@ discard """ output: "seq[float]\n0" + targets: "c cpp" """ # https://github.com/nim-lang/Nim/issues/5602 -import typetraits +import typetraits, module_with_generics type Foo[T] = object of RootObj @@ -16,3 +17,8 @@ proc p[T](f: Foo[T]): T = var s: Bar[float] echo p(s).len # the bug was: p(s) should return seq[float], but returns float instead +# Test overloading and code generation when +# downcasting is required for generic types: +var d = makeDerived(10) +setBaseValue(d, 20) + diff --git a/tests/generics/tcannot_pass_empty_seq_to_generic.nim b/tests/generics/tcannot_pass_empty_seq_to_generic.nim index 5f0363af8..e33dbc10b 100644 --- a/tests/generics/tcannot_pass_empty_seq_to_generic.nim +++ b/tests/generics/tcannot_pass_empty_seq_to_generic.nim @@ -1,5 +1,5 @@ discard """ - errormsg: "type mismatch: got (seq[empty])" + errormsg: "type mismatch: got <seq[empty]>" line: 16 """ diff --git a/tests/generics/tparam_binding.nim b/tests/generics/tparam_binding.nim index 643e9b226..55acb8f06 100644 --- a/tests/generics/tparam_binding.nim +++ b/tests/generics/tparam_binding.nim @@ -1,5 +1,5 @@ discard """ - errormsg: "got (ref Matrix[2, 2, system.float], ref Matrix[2, 1, system.float])" + errormsg: "got <ref Matrix[2, 2, system.float], ref Matrix[2, 1, system.float]>" line: 27 """ diff --git a/tests/generics/tspecial_numeric_inference.nim b/tests/generics/tspecial_numeric_inference.nim new file mode 100644 index 000000000..41a84a5e9 --- /dev/null +++ b/tests/generics/tspecial_numeric_inference.nim @@ -0,0 +1,21 @@ +discard """ + output: '''false''' +""" + +when false: + import typetraits + + proc `@`[T: SomeInteger](x, y: T): T = x + + echo(type(5'i64 @ 6'i32)) + + echo(type(5'i32 @ 6'i64)) + +import sets +# bug #7247 +type + n8 = range[0'i8..127'i8] + +var tab = initSet[n8]() + +echo tab.contains(8) diff --git a/tests/iter/titer2.nim b/tests/iter/titer2.nim index 4a7f76883..f60aed73a 100644 --- a/tests/iter/titer2.nim +++ b/tests/iter/titer2.nim @@ -2,7 +2,12 @@ discard """ output: '''true 3 4 -5''' +5 +0 +1 +2 +3 +4''' cmd: "nim $target --gc:none --hints:on --warnings:off $options $file" """ @@ -55,3 +60,7 @@ echo "true" # bug #1560 for i in @[3, 4, 5]: echo($i) + +# bug #6992 +for i in 0 ..< 5u32: + echo i diff --git a/tests/iter/tobj_iter.nim b/tests/iter/tobj_iter.nim index eb0e37b23..a894755d7 100644 --- a/tests/iter/tobj_iter.nim +++ b/tests/iter/tobj_iter.nim @@ -4,8 +4,6 @@ discard """ # bug #2023 -{.deadCodeElim:on.} - type Obj = object iter: iterator (): int8 {.closure.} diff --git a/tests/iter/tyieldintry.nim b/tests/iter/tyieldintry.nim new file mode 100644 index 000000000..31ec65a83 --- /dev/null +++ b/tests/iter/tyieldintry.nim @@ -0,0 +1,372 @@ +discard """ +targets: "c cpp" +output: "ok" +""" +var closureIterResult = newSeq[int]() + +proc checkpoint(arg: int) = + closureIterResult.add(arg) + +type + TestException = object of Exception + AnotherException = object of Exception + +proc testClosureIterAux(it: iterator(): int, exceptionExpected: bool, expectedResults: varargs[int]) = + closureIterResult.setLen(0) + + var exceptionCaught = false + + try: + for i in it(): + closureIterResult.add(i) + except TestException: + exceptionCaught = true + + if closureIterResult != @expectedResults or exceptionCaught != exceptionExpected: + if closureIterResult != @expectedResults: + echo "Expected: ", @expectedResults + echo "Actual: ", closureIterResult + if exceptionCaught != exceptionExpected: + echo "Expected exception: ", exceptionExpected + echo "Got exception: ", exceptionCaught + doAssert(false) + +proc test(it: iterator(): int, expectedResults: varargs[int]) = + testClosureIterAux(it, false, expectedResults) + +proc testExc(it: iterator(): int, expectedResults: varargs[int]) = + testClosureIterAux(it, true, expectedResults) + +proc raiseException() = + raise newException(TestException, "Test exception!") + +block: + iterator it(): int {.closure.} = + var i = 5 + while i != 0: + yield i + if i == 3: + yield 123 + dec i + + test(it, 5, 4, 3, 123, 2, 1) + +block: + iterator it(): int {.closure.} = + yield 0 + try: + checkpoint(1) + raiseException() + except TestException: + checkpoint(2) + yield 3 + checkpoint(4) + finally: + checkpoint(5) + + checkpoint(6) + + test(it, 0, 1, 2, 3, 4, 5, 6) + +block: + iterator it(): int {.closure.} = + yield 0 + try: + yield 1 + checkpoint(2) + finally: + checkpoint(3) + yield 4 + checkpoint(5) + yield 6 + + test(it, 0, 1, 2, 3, 4, 5, 6) + +block: + iterator it(): int {.closure.} = + yield 0 + try: + yield 1 + raiseException() + yield 2 + finally: + checkpoint(3) + yield 4 + checkpoint(5) + yield 6 + + testExc(it, 0, 1, 3, 4, 5, 6) + +block: + iterator it(): int {.closure.} = + try: + try: + raiseException() + except AnotherException: + yield 123 + finally: + checkpoint(3) + finally: + checkpoint(4) + + testExc(it, 3, 4) + +block: + iterator it(): int {.closure.} = + try: + yield 1 + raiseException() + except AnotherException: + checkpoint(123) + finally: + checkpoint(2) + checkpoint(3) + + testExc(it, 1, 2) + +block: + iterator it(): int {.closure.} = + try: + yield 0 + try: + yield 1 + try: + yield 2 + raiseException() + except AnotherException: + yield 123 + finally: + yield 3 + except AnotherException: + yield 124 + finally: + yield 4 + checkpoint(1234) + except: + yield 5 + checkpoint(6) + finally: + checkpoint(7) + yield 8 + checkpoint(9) + + test(it, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9) + +block: + iterator it(): int {.closure.} = + try: + yield 0 + return 2 + finally: + checkpoint(1) + checkpoint(123) + + test(it, 0, 1) + +block: + iterator it(): int {.closure.} = + try: + try: + yield 0 + raiseException() + finally: + checkpoint(1) + except TestException: + yield 2 + return + finally: + yield 3 + + checkpoint(123) + + test(it, 0, 1, 2, 3) + +block: + iterator it(): int {.closure.} = + try: + try: + yield 0 + raiseException() + finally: + return # Return in finally should stop exception propagation + except AnotherException: + yield 2 + return + finally: + yield 3 + checkpoint(123) + + test(it, 0, 3) + +block: # Yield in yield + iterator it(): int {.closure.} = + template foo(): int = + yield 1 + 2 + + for i in 0 .. 2: + checkpoint(0) + yield foo() + + test(it, 0, 1, 2, 0, 1, 2, 0, 1, 2) + +block: + iterator it(): int {.closure.} = + let i = if true: + yield 0 + 1 + else: + 2 + yield i + + test(it, 0, 1) + +block: + iterator it(): int {.closure.} = + var foo = 123 + let i = try: + yield 0 + raiseException() + 1 + except TestException as e: + assert(e.msg == "Test exception!") + case foo + of 1: + yield 123 + 2 + of 123: + yield 5 + 6 + else: + 7 + yield i + + test(it, 0, 5, 6) + +block: + iterator it(): int {.closure.} = + proc voidFoo(i1, i2, i3: int) = + checkpoint(i1) + checkpoint(i2) + checkpoint(i3) + + proc foo(i1, i2, i3: int): int = + voidFoo(i1, i2, i3) + i3 + + proc bar(i1: int): int = + checkpoint(i1) + + template tryexcept: int = + try: + yield 1 + raiseException() + 123 + except TestException: + yield 2 + checkpoint(3) + 4 + + let e1 = true + + template ifelse1: int = + if e1: + yield 10 + 11 + else: + 12 + + template ifelse2: int = + if ifelse1() == 12: + yield 20 + 21 + else: + yield 22 + 23 + + let i = foo(bar(0), tryexcept, ifelse2) + discard foo(bar(0), tryexcept, ifelse2) + voidFoo(bar(0), tryexcept, ifelse2) + yield i + + test(it, + + # let i = foo(bar(0), tryexcept, ifelse2) + 0, # bar(0) + 1, 2, 3, # tryexcept + 10, # ifelse1 + 22, # ifelse22 + 0, 4, 23, # foo + + # discard foo(bar(0), tryexcept, ifelse2) + 0, # bar(0) + 1, 2, 3, # tryexcept + 10, # ifelse1 + 22, # ifelse22 + 0, 4, 23, # foo + + # voidFoo(bar(0), tryexcept, ifelse2) + 0, # bar(0) + 1, 2, 3, # tryexcept + 10, # ifelse1 + 22, # ifelse22 + 0, 4, 23, # foo + + 23 # i + ) + +block: + iterator it(): int {.closure.} = + checkpoint(0) + for i in 0 .. 1: + try: + yield 1 + raiseException() + except TestException as e: + doAssert(e.msg == "Test exception!") + yield 2 + except AnotherException: + yield 123 + except: + yield 1234 + finally: + yield 3 + checkpoint(4) + yield 5 + + test(it, 0, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5) + +block: + iterator it(): int {.closure.} = + var i = 5 + template foo(): bool = + yield i + true + + while foo(): + dec i + if i == 0: + break + + test(it, 5, 4, 3, 2, 1) + +block: # Short cirquits + iterator it(): int {.closure.} = + template trueYield: bool = + yield 1 + true + + template falseYield: bool = + yield 0 + false + + if trueYield or falseYield: + discard falseYield and trueYield + + if falseYield and trueYield: + checkpoint(123) + + test(it, 1, 0, 0) + + +echo "ok" diff --git a/tests/js/tasync.nim b/tests/js/tasync.nim index 34ef97b8b..318237651 100644 --- a/tests/js/tasync.nim +++ b/tests/js/tasync.nim @@ -1,5 +1,4 @@ discard """ - disabled: true output: ''' x e @@ -18,6 +17,8 @@ proc e: int {.discardable.} = proc x(e: int): Future[void] {.async.} = var s = await y(e) + if e > 2: + return echo s e() diff --git a/tests/js/tasync_pragma.nim b/tests/js/tasync_pragma.nim new file mode 100644 index 000000000..916769fad --- /dev/null +++ b/tests/js/tasync_pragma.nim @@ -0,0 +1,27 @@ +discard """ + output: ''' +0 +t +''' +""" + +import asyncjs, macros + +macro f*(a: untyped): untyped = + assert a.kind == nnkProcDef + result = nnkProcDef.newTree(a.name, a[1], a[2], a.params, a.pragma, a[5], nnkStmtList.newTree()) + let call = quote: + echo 0 + result.body.add(call) + for child in a.body: + result.body.add(child) + #echo result.body.repr + +proc t* {.async, f.} = + echo "t" + +proc t0* {.async.} = + await t() + +discard t0() + diff --git a/tests/js/trepr.nim b/tests/js/trepr.nim index 06dbbca22..366d247c5 100644 --- a/tests/js/trepr.nim +++ b/tests/js/trepr.nim @@ -3,7 +3,7 @@ discard """ """ block ints: - let + let na: int8 = -120'i8 nb: int16 = -32700'i16 nc: int32 = -2147483000'i32 @@ -12,9 +12,9 @@ block ints: pa: int8 = 120'i8 pb: int16 = 32700'i16 pc: int32 = 2147483000'i32 - pd: int64 = 9223372036854775000'i64 + pd: int64 = 9223372036854775000'i64 pe: int = 1234567 - + doAssert(repr(na) == "-120") doAssert(repr(nb) == "-32700") doAssert(repr(nc) == "-2147483000") @@ -27,13 +27,13 @@ block ints: doAssert(repr(pe) == "1234567") block uints: - let + let a: uint8 = 254'u8 b: uint16 = 65300'u16 c: uint32 = 4294967290'u32 # d: uint64 = 18446744073709551610'u64 -> unknown node type e: uint = 1234567 - + doAssert(repr(a) == "254") doAssert(repr(b) == "65300") doAssert(repr(c) == "4294967290") @@ -41,26 +41,26 @@ block uints: doAssert(repr(e) == "1234567") block floats: - let + let a: float32 = 3.4e38'f32 b: float64 = 1.7976931348623157e308'f64 c: float = 1234.567e89 - - when defined js: + + when defined js: doAssert(repr(a) == "3.4e+38") # in C: 3.399999952144364e+038 doAssert(repr(b) == "1.7976931348623157e+308") # in C: 1.797693134862316e+308 doAssert(repr(c) == "1.234567e+92") # in C: 1.234567e+092 block bools: - let + let a: bool = true b: bool = false - - doAssert(repr(a) == "true") + + doAssert(repr(a) == "true") doAssert(repr(b) == "false") block enums: - type + type AnEnum = enum aeA aeB @@ -69,53 +69,59 @@ block enums: heA = -12 heB = 15 heC = 123 - - doAssert(repr(aeA) == "aeA") + + doAssert(repr(aeA) == "aeA") doAssert(repr(aeB) == "aeB") - doAssert(repr(aeC) == "aeC") + doAssert(repr(aeC) == "aeC") doAssert(repr(heA) == "heA") - doAssert(repr(heB) == "heB") + doAssert(repr(heB) == "heB") doAssert(repr(heC) == "heC") +block emums_and_unicode: #6741 + type K = enum Kanji = "æ¼¢å—" + let kanji = Kanji + doAssert(kanji == Kanji, "Enum values are not equal") + doAssert($kanji == $Kanji, "Enum string values are not equal") + block chars: let a = 'a' b = 'z' one = '1' nl = '\x0A' - + doAssert(repr(a) == "'a'") doAssert(repr(b) == "'z'") doAssert(repr(one) == "'1'") doAssert(repr(nl) == "'\\10'") block strings: - let + let a: string = "12345" b: string = "hello,repr" c: string = "hi\nthere" when defined js: # C prepends the pointer, JS does not. doAssert(repr(a) == "\"12345\"") doAssert(repr(b) == "\"hello,repr\"") - doAssert(repr(c) == "\"hi\nthere\"") + doAssert(repr(c) == "\"hi\\10there\"") block sets: let a: set[int16] = {1'i16, 2'i16, 3'i16} b: set[char] = {'A', 'k'} - + doAssert(repr(a) == "{1, 2, 3}") doAssert(repr(b) == "{'A', 'k'}") block ranges: - let + let a: range[0..12] = 6 b: range[-12..0] = -6 doAssert(repr(a) == "6") doAssert(repr(b) == "-6") block tuples: - type + type ATuple = tuple a: int b: float @@ -124,7 +130,7 @@ block tuples: OtherTuple = tuple a: bool b: int8 - + let ot: OtherTuple = (a: true, b: 120'i8) t: ATuple = (a: 42, b: 12.34, c: "tuple", d: ot) @@ -176,7 +182,7 @@ block arrays: o = AObj(x: 42, y: a) c = [o, o, o] d = ["hi", "array", "!"] - + doAssert(repr(a) == "[0.0, 1.0, 2.0]\n") doAssert(repr(b) == "[[0.0, 1.0, 2.0], [0.0, 1.0, 2.0], [0.0, 1.0, 2.0]]\n") doAssert(repr(c) == """ @@ -198,7 +204,7 @@ block seqs: o = AObj(x: 42, y: a) c = @[o, o, o] d = @["hi", "array", "!"] - + doAssert(repr(a) == "@[0.0, 1.0, 2.0]\n") doAssert(repr(b) == "@[@[0.0, 1.0, 2.0], @[0.0, 1.0, 2.0], @[0.0, 1.0, 2.0]]\n") doAssert(repr(c) == """ @@ -210,16 +216,16 @@ y = @[0.0, 1.0, 2.0]]] doAssert(repr(d) == "@[\"hi\", \"array\", \"!\"]\n") block ptrs: - type + type AObj = object x: ptr array[2, AObj] y: int - var + var a = [12.0, 13.0, 14.0] b = addr a[0] c = addr a[2] d = AObj() - + doAssert(repr(a) == "[12.0, 13.0, 14.0]\n") doAssert(repr(b) == "ref 0 --> 12.0\n") doAssert(repr(c) == "ref 2 --> 14.0\n") @@ -229,13 +235,13 @@ y = 0] """) block ptrs: - type + type AObj = object x: ref array[2, AObj] y: int - var + var a = AObj() - + new(a.x) doAssert(repr(a) == """ @@ -248,10 +254,10 @@ y = 0] block procs: proc test(): int = echo "hello" - var + var ptest = test nilproc: proc(): int - + doAssert(repr(test) == "0\n") doAssert(repr(ptest) == "0\n") doAssert(repr(nilproc) == "nil\n") @@ -262,7 +268,7 @@ block bunch: eA, eB, eC B = object a: string - b: seq[char] + b: seq[char] A = object a: uint32 b: int @@ -281,17 +287,17 @@ block bunch: o: tuple[x: B, y: string] p: proc(b: B): ref B q: cstring - + proc refB(b:B):ref B = new result result[] = b - + var aa: A bb: B = B(a: "inner", b: @['o', 'b', 'j']) cc: A = A(a: 12, b: 1, c: 1.2, d: '\0', e: eC, f: "hello", g: {'A'}, h: {2'i16}, - i: ["hello", "world", "array"], + i: ["hello", "world", "array"], j: @["hello", "world", "seq"], k: -1, l: bb, m: refB(bb), n: addr bb, o: (bb, "tuple!"), p: refB, q: "cstringtest" ) @@ -344,12 +350,12 @@ q = "cstringtest"] """) block another: - type - Size1 = enum + type + Size1 = enum s1a, s1b - Size2 = enum + Size2 = enum s2c=0, s2d=20000 - Size3 = enum + Size3 = enum s3e=0, s3f=2000000000 doAssert(repr([s1a, s1b]) == "[s1a, s1b]\n") @@ -357,7 +363,7 @@ block another: doAssert(repr([s3e, s3f]) == "[s3e, s3f]\n") block another2: - + type AnEnum = enum en1, en2, en3, en4, en5, en6 diff --git a/tests/js/tstring_assignment.nim b/tests/js/tstring_assignment.nim index bdd93e6b5..97ffa748f 100644 --- a/tests/js/tstring_assignment.nim +++ b/tests/js/tstring_assignment.nim @@ -1,5 +1,6 @@ discard """ - output: '''true''' + output: '''true +asdfasekjkler''' """ # bug #4471 @@ -9,3 +10,12 @@ when true: s2.setLen(0) # fails - s1.len == 0 echo s1.len == 3 + +# bug #4470 +proc main(s: cstring): string = + result = newString(0) + for i in 0..<s.len: + if s[i] >= 'a' and s[i] <= 'z': + result.add s[i] + +echo main("asdfasekjkleräöü") diff --git a/tests/js/tstringitems.nim b/tests/js/tstringitems.nim index 20aed6e8b..ff016642e 100644 --- a/tests/js/tstringitems.nim +++ b/tests/js/tstringitems.nim @@ -76,3 +76,12 @@ block: # String case of case s of "Привет!": discard else: doAssert(false) + +block: # String cmp + var a, b: string + doAssert(cmp(a, b) == 0) + doAssert(cmp("foo", "foo") == 0) + doAssert(cmp("foobar", "foo") == 3) + doAssert(cmp("foo", "foobar") == -3) + doAssert(cmp("fooz", "foog") == 19) + doAssert(cmp("foog", "fooz") == -19) diff --git a/tests/js/ttimes.nim b/tests/js/ttimes.nim index 63a4bb04f..63972dd76 100644 --- a/tests/js/ttimes.nim +++ b/tests/js/ttimes.nim @@ -17,14 +17,14 @@ block localTime: let a = fromUnix(1_000_000_000) let b = fromUnix(1_500_000_000) -doAssert b - a == 500_000_000 +doAssert b - a == initDuration(seconds = 500_000_000) # Because we can't change the timezone JS uses, we define a simple static timezone for testing. proc staticZoneInfoFromUtc(time: Time): ZonedTime = result.utcOffset = -7200 result.isDst = false - result.adjTime = (time.toUnix + 7200).Time + result.adjTime = time + 7200.seconds proc staticZoneInfoFromTz(adjTime: Time): ZonedTIme = result.utcOffset = -7200 @@ -40,5 +40,4 @@ block timezoneTests: doAssert $dt.utc.inZone(utcPlus2) == $dt doAssert $initDateTime(01, mJan, 1911, 12, 00, 00, utc()) == "1911-01-01T12:00:00+00:00" -# See #6752 -# doAssert $initDateTime(01, mJan, 1900, 12, 00, 00, utc()) == "0023-01-01T12:00:00+00:00" \ No newline at end of file +doAssert $initDateTime(01, mJan, 0023, 12, 00, 00, utc()) == "0023-01-01T12:00:00+00:00" \ No newline at end of file diff --git a/tests/lent/tbasic_lent_check.nim b/tests/lent/tbasic_lent_check.nim new file mode 100644 index 000000000..1d954725b --- /dev/null +++ b/tests/lent/tbasic_lent_check.nim @@ -0,0 +1,17 @@ +discard """ + cmd: "nim c --newRuntime $file" + output: "1" +""" + +proc viewInto(a: array[4, string]): lent string = + result = a[0] + +proc passToVar(x: var string) = + discard + +proc main = + let x = ["1", "2", "3", "4"] + echo viewInto(x) + doAssert(not compiles(passToVar(viewInto(x)))) + +main() diff --git a/tests/let/tlet2.nim b/tests/let/tlet2.nim index 66dd5a55b..2df15fa5c 100644 --- a/tests/let/tlet2.nim +++ b/tests/let/tlet2.nim @@ -1,6 +1,6 @@ discard """ line: "13" - errormsg: "type mismatch: got (int literal(8), int literal(5), int, int)" + errormsg: "type mismatch: got <int literal(8), int literal(5), int, int>" """ proc divmod(a, b: int, res, remainder: var int) = diff --git a/tests/lexer/tunderscores.nim b/tests/lexer/tunderscores.nim index e718fb40a..f64f36977 100644 --- a/tests/lexer/tunderscores.nim +++ b/tests/lexer/tunderscores.nim @@ -1,7 +1,7 @@ discard """ file: "tunderscores.nim" line: 8 - errormsg: "invalid token: _" + errormsg: "invalid token: trailing underscore" """ # Bug #502670 diff --git a/tests/macros/tdumpastgen.nim b/tests/macros/tdumpastgen.nim index faed77225..0a1836886 100644 --- a/tests/macros/tdumpastgen.nim +++ b/tests/macros/tdumpastgen.nim @@ -2,16 +2,33 @@ discard """ msg: '''nnkStmtList.newTree( nnkVarSection.newTree( nnkIdentDefs.newTree( - newIdentNode(!"x"), + newIdentNode("x"), newEmptyNode(), nnkCall.newTree( nnkDotExpr.newTree( - newIdentNode(!"foo"), - newIdentNode(!"create") + newIdentNode("baz"), + newIdentNode("create") ), newLit(56) ) ) + ), + nnkProcDef.newTree( + newIdentNode("foo"), + newEmptyNode(), + newEmptyNode(), + nnkFormalParams.newTree( + newEmptyNode() + ), + newEmptyNode(), + newEmptyNode(), + nnkStmtList.newTree( + newCommentStmtNode("This is a docstring"), + nnkCommand.newTree( + newIdentNode("echo"), + newLit("bar") + ) + ) ) )''' """ @@ -21,5 +38,8 @@ msg: '''nnkStmtList.newTree( import macros dumpAstGen: - var x = foo.create(56) + var x = baz.create(56) + proc foo() = + ## This is a docstring + echo "bar" diff --git a/tests/macros/tforloop_macro1.nim b/tests/macros/tforloop_macro1.nim new file mode 100644 index 000000000..a8f45c7ac --- /dev/null +++ b/tests/macros/tforloop_macro1.nim @@ -0,0 +1,44 @@ +discard """ + output: '''0 1 +1 2 +2 3 +0 1 +1 2 +2 3 +0 1 +1 2 +2 3 +3 5''' +""" + +import macros + +macro mymacro(): untyped = + result = newLit([1, 2, 3]) + +for a, b in mymacro(): + echo a, " ", b + +macro enumerate(x: ForLoopStmt): untyped = + expectKind x, nnkForStmt + # we strip off the first for loop variable and use + # it as an integer counter: + result = newStmtList() + result.add newVarStmt(x[0], newLit(0)) + var body = x[^1] + if body.kind != nnkStmtList: + body = newTree(nnkStmtList, body) + body.add newCall(bindSym"inc", x[0]) + var newFor = newTree(nnkForStmt) + for i in 1..x.len-3: + newFor.add x[i] + # transform enumerate(X) to 'X' + newFor.add x[^2][1] + newFor.add body + result.add newFor + +for a, b in enumerate(items([1, 2, 3])): + echo a, " ", b + +for a2, b2 in enumerate([1, 2, 3, 5]): + echo a2, " ", b2 diff --git a/tests/macros/tgensym.nim b/tests/macros/tgensym.nim index 955168939..1237b8bf7 100644 --- a/tests/macros/tgensym.nim +++ b/tests/macros/tgensym.nim @@ -28,6 +28,7 @@ macro async2(prc: untyped): untyped = # -> iterator nameIter(): FutureBase {.closure.} = <proc_body> # Changing this line to: newIdentNode($prc[0].ident & "Iter") # will make it work. var iteratorNameSym = genSym(nskIterator, $prc[0].ident & "Iter") + assert iteratorNameSym.symKind == nskIterator #var iteratorNameSym = newIdentNode($prc[0].ident & "Iter") var procBody = prc[6].convertReturns(retFutureSym) @@ -42,6 +43,7 @@ macro async2(prc: untyped): untyped = var varNameIter = newVarStmt(varNameIterSym, iteratorNameSym) outerProcBody.add varNameIter var varFirstSym = genSym(nskVar, "first") + assert varFirstSym.symKind == nskVar var varFirst = newVarStmt(varFirstSym, newCall(varNameIterSym)) outerProcBody.add varFirst diff --git a/tests/macros/tmacro1.nim b/tests/macros/tmacro1.nim index ac6bd02a5..ac2bf9094 100644 --- a/tests/macros/tmacro1.nim +++ b/tests/macros/tmacro1.nim @@ -18,5 +18,64 @@ macro test*(a: untyped): untyped = t.b = true t.z = 4.5 + test: "hi" + +import strutils + +template assertNot(arg: untyped): untyped = + assert(not(arg)) + + +proc foo(arg: int): void = + discard + +proc foo(arg: float): void = + discard + +static: + ## test eqIdent + let a = "abc_def" + let b = "abcDef" + let c = "AbcDef" + let d = nnkBracketExpr.newTree() # not an identifier at all + + assert eqIdent( a , b ) + assert eqIdent(newIdentNode(a), b ) + assert eqIdent( a , newIdentNode(b)) + assert eqIdent(newIdentNode(a), newIdentNode(b)) + + assert eqIdent( a , b ) + assert eqIdent(genSym(nskLet, a), b ) + assert eqIdent( a , genSym(nskLet, b)) + assert eqIdent(genSym(nskLet, a), genSym(nskLet, b)) + + assert eqIdent(newIdentNode( a), newIdentNode( b)) + assert eqIdent(genSym(nskLet, a), newIdentNode( b)) + assert eqIdent(newIdentNode( a), genSym(nskLet, b)) + assert eqIdent(genSym(nskLet, a), genSym(nskLet, b)) + + assertNot eqIdent( c , b ) + assertNot eqIdent(newIdentNode(c), b ) + assertNot eqIdent( c , newIdentNode(b)) + assertNot eqIdent(newIdentNode(c), newIdentNode(b)) + + assertNot eqIdent( c , b ) + assertNot eqIdent(genSym(nskLet, c), b ) + assertNot eqIdent( c , genSym(nskLet, b)) + assertNot eqIdent(genSym(nskLet, c), genSym(nskLet, b)) + + assertNot eqIdent(newIdentNode( c), newIdentNode( b)) + assertNot eqIdent(genSym(nskLet, c), newIdentNode( b)) + assertNot eqIdent(newIdentNode( c), genSym(nskLet, b)) + assertNot eqIdent(genSym(nskLet, c), genSym(nskLet, b)) + + # eqIdent on non identifier at all + assertNot eqIdent(a,d) + + # eqIdent on sym choice + let fooSym = bindSym"foo" + assert fooSym.kind in {nnkOpenSymChoice, nnkClosedSymChoice} + assert fooSym.eqIdent("fOO") + assertNot fooSym.eqIdent("bar") diff --git a/tests/macros/tstructuredlogging.nim b/tests/macros/tstructuredlogging.nim new file mode 100644 index 000000000..05bb52a40 --- /dev/null +++ b/tests/macros/tstructuredlogging.nim @@ -0,0 +1,154 @@ +discard """ +output: ''' +main started: a=10, b=inner-b, c=10, d=some-d, x=16, z=20 +exiting: a=12, b=overriden-b, c=100, msg=bye bye, x=16 +''' +""" + +import macros, tables + +template scopeHolder = + 0 # scope revision number + +type + BindingsSet = Table[string, NimNode] + +proc actualBody(n: NimNode): NimNode = + # skip over the double StmtList node introduced in `mergeScopes` + result = n.body + if result.kind == nnkStmtList and result[0].kind == nnkStmtList: + result = result[0] + +iterator bindings(n: NimNode, skip = 0): (string, NimNode) = + for i in skip ..< n.len: + let child = n[i] + if child.kind in {nnkAsgn, nnkExprEqExpr}: + let name = $child[0] + let value = child[1] + yield (name, value) + +proc scopeRevision(scopeHolder: NimNode): int = + # get the revision number from a scopeHolder sym + assert scopeHolder.kind == nnkSym + var revisionNode = scopeHolder.getImpl.actualBody[0] + result = int(revisionNode.intVal) + +proc lastScopeHolder(scopeHolders: NimNode): NimNode = + # get the most recent scopeHolder from a symChoice node + if scopeHolders.kind in {nnkClosedSymChoice, nnkOpenSymChoice}: + var bestScopeRev = 0 + assert scopeHolders.len > 0 + for scope in scopeHolders: + let rev = scope.scopeRevision + if result == nil or rev > bestScopeRev: + result = scope + bestScopeRev = rev + else: + result = scopeHolders + + assert result.kind == nnkSym + +macro mergeScopes(scopeHolders: typed, newBindings: untyped): untyped = + var + bestScope = scopeHolders.lastScopeHolder + bestScopeRev = bestScope.scopeRevision + + var finalBindings = initTable[string, NimNode]() + for k, v in bindings(bestScope.getImpl.actualBody, skip = 1): + finalBindings[k] = v + + for k, v in bindings(newBindings): + finalBindings[k] = v + + var newScopeDefinition = newStmtList(newLit(bestScopeRev + 1)) + + for k, v in finalBindings: + newScopeDefinition.add newAssignment(newIdentNode(k), v) + + result = quote: + template scopeHolder = `newScopeDefinition` + +template scope(newBindings: untyped) {.dirty.} = + mergeScopes(bindSym"scopeHolder", newBindings) + +type + TextLogRecord = object + line: string + + StdoutLogRecord = object + +template setProperty(r: var TextLogRecord, key: string, val: string, isFirst: bool) = + if not first: r.line.add ", " + r.line.add key + r.line.add "=" + r.line.add val + +template setEventName(r: var StdoutLogRecord, name: string) = + stdout.write(name & ": ") + +template setProperty(r: var StdoutLogRecord, key: string, val: auto, isFirst: bool) = + when not isFirst: stdout.write ", " + stdout.write key + stdout.write "=" + stdout.write $val + +template flushRecord(r: var StdoutLogRecord) = + stdout.write "\n" + stdout.flushFile + +macro logImpl(scopeHolders: typed, + logStmtProps: varargs[untyped]): untyped = + let lexicalScope = scopeHolders.lastScopeHolder.getImpl.actualBody + var finalBindings = initOrderedTable[string, NimNode]() + + for k, v in bindings(lexicalScope, skip = 1): + finalBindings[k] = v + + for k, v in bindings(logStmtProps, skip = 1): + finalBindings[k] = v + + finalBindings.sort(system.cmp) + + let eventName = logStmtProps[0] + assert eventName.kind in {nnkStrLit} + let record = genSym(nskVar, "record") + + result = quote: + var `record`: StdoutLogRecord + setEventName(`record`, `eventName`) + + var isFirst = true + for k, v in finalBindings: + result.add newCall(newIdentNode"setProperty", + record, newLit(k), v, newLit(isFirst)) + isFirst = false + + result.add newCall(newIdentNode"flushRecord", record) + +template log(props: varargs[untyped]) {.dirty.} = + logImpl(bindSym"scopeHolder", props) + +scope: + a = 12 + b = "original-b" + +scope: + x = 16 + b = "overriden-b" + +scope: + c = 100 + +proc main = + scope: + c = 10 + + scope: + z = 20 + + log("main started", a = 10, b = "inner-b", d = "some-d") + +main() + +log("exiting", msg = "bye bye") + diff --git a/tests/macros/ttemplatesymbols.nim b/tests/macros/ttemplatesymbols.nim new file mode 100644 index 000000000..8d9c9ec02 --- /dev/null +++ b/tests/macros/ttemplatesymbols.nim @@ -0,0 +1,173 @@ +import + macros, algorithm, strutils + +proc normalProc(x: int) = + echo x + +template templateWithtouParams = + echo 10 + +proc overloadedProc(x: int) = + echo x + +proc overloadedProc(x: string) = + echo x + +proc overloadedProc[T](x: T) = + echo x + +template normalTemplate(x: int) = + echo x + +template overloadedTemplate(x: int) = + echo x + +template overloadedTemplate(x: string) = + echo x + +macro normalMacro(x: int): untyped = + discard + +macro macroWithoutParams: untyped = + discard + +macro inspectSymbol(sym: typed, expected: static[string]): untyped = + if sym.kind == nnkSym: + echo "Symbol node:" + let res = sym.getImpl.repr & "\n" + echo res + # echo "|", res, "|" + # echo "|", expected, "|" + if expected.len > 0: assert res == expected + elif sym.kind in {nnkClosedSymChoice, nnkOpenSymChoice}: + echo "Begin sym choice:" + var results = newSeq[string](0) + for innerSym in sym: + results.add innerSym.getImpl.repr + sort(results, cmp[string]) + let res = results.join("\n") & "\n" + echo res + if expected.len > 0: assert res == expected + echo "End symchoice." + else: + echo "Non-symbol node: ", sym.kind + if expected.len > 0: assert $sym.kind == expected + +macro inspectUntyped(sym: untyped, expected: static[string]): untyped = + let res = sym.repr + echo "Untyped node: ", res + assert res == expected + +inspectSymbol templateWithtouParams, "nnkCommand" + # this template is expanded, because bindSym was not used + # the end result is the template body (nnkCommand) + +inspectSymbol bindSym("templateWithtouParams"), """ +template templateWithtouParams() = + echo 10 + +""" + +inspectSymbol macroWithoutParams, "nnkEmpty" + # Just like the template above, the macro was expanded + +inspectSymbol bindSym("macroWithoutParams"), """ +macro macroWithoutParams(): untyped = + discard + +""" + +inspectSymbol normalMacro, """ +macro normalMacro(x: int): untyped = + discard + +""" + # Since the normalMacro has params, it's automatically + # treated as a symbol here (no need for `bindSym`) + +inspectSymbol bindSym("normalMacro"), """ +macro normalMacro(x: int): untyped = + discard + +""" + +inspectSymbol normalTemplate, """ +template normalTemplate(x: int) = + echo x + +""" + +inspectSymbol bindSym("normalTemplate"), """ +template normalTemplate(x: int) = + echo x + +""" + +inspectSymbol overloadedTemplate, """ +template overloadedTemplate(x: int) = + echo x + +template overloadedTemplate(x: string) = + echo x + +""" + +inspectSymbol bindSym("overloadedTemplate"), """ +template overloadedTemplate(x: int) = + echo x + +template overloadedTemplate(x: string) = + echo x + +""" + +inspectUntyped bindSym("overloadedTemplate"), """bindSym("overloadedTemplate")""" + # binSym is active only in the presense of `typed` params. + # `untyped` params still get the raw AST + +inspectSymbol normalProc, """ +proc normalProc(x: int) = + echo [x] + +""" + +inspectSymbol bindSym("normalProc"), """ +proc normalProc(x: int) = + echo [x] + +""" + +inspectSymbol overloadedProc, """ +proc overloadedProc(x: int) = + echo [x] + +proc overloadedProc(x: string) = + echo [x] + +proc overloadedProc[T](x: T) = + echo x + +""" + # XXX: There seems to be a repr rendering problem above. + # Notice that `echo [x]` + +inspectSymbol overloadedProc[float], """ +proc overloadedProc(x: T) = + echo [x] + +""" + # As expected, when we select a specific generic, the + # AST is no longer a symChoice + +inspectSymbol bindSym("overloadedProc"), """ +proc overloadedProc(x: int) = + echo [x] + +proc overloadedProc(x: string) = + echo [x] + +proc overloadedProc[T](x: T) = + echo x + +""" + diff --git a/tests/macros/twrapiterator.nim b/tests/macros/twrapiterator.nim new file mode 100644 index 000000000..e153ae980 --- /dev/null +++ b/tests/macros/twrapiterator.nim @@ -0,0 +1,19 @@ + +import macros + +# bug #7093 + +macro foobar(arg: untyped): untyped = + let procDef = quote do: + proc foo(): void = + echo "bar" + + + result = newStmtList( + arg, procDef + ) + + echo result.repr + +iterator bar(): int {.foobar.} = + discard diff --git a/tests/manyloc/argument_parser/argument_parser.nim b/tests/manyloc/argument_parser/argument_parser.nim index 97de552e3..1095a893e 100644 --- a/tests/manyloc/argument_parser/argument_parser.nim +++ b/tests/manyloc/argument_parser/argument_parser.nim @@ -174,7 +174,7 @@ template new_parsed_parameter*(tkind: Tparam_kind, expr): Tparsed_parameter = ## parsed_param1 = new_parsed_parameter(PK_FLOAT, 3.41) ## parsed_param2 = new_parsed_parameter(PK_BIGGEST_INT, 2358123 * 23123) ## # The following line doesn't compile due to - ## # type mismatch: got (string) but expected 'int' + ## # type mismatch: got <string> but expected 'int' ## #parsed_param3 = new_parsed_parameter(PK_INT, "231") var result {.gensym.}: Tparsed_parameter result.kind = tkind @@ -209,7 +209,7 @@ proc `$`*(data: Tcommandline_results): string = # - Parse code -template raise_or_quit(exception, message: expr): stmt {.immediate.} = +template raise_or_quit(exception, message: untyped) = ## Avoids repeating if check based on the default quit_on_failure variable. ## ## As a special case, if message has a zero length the call to quit won't @@ -230,15 +230,15 @@ template run_custom_proc(parsed_parameter: Tparsed_parameter, ## ## Pass in the string of the parameter triggering the call. If the if not custom_validator.isNil: + try: + let message = custom_validator(parameter, parsed_parameter) + if not message.isNil and message.len > 0: + raise_or_quit(ValueError, ("Failed to validate value for " & + "parameter $1:\n$2" % [escape(parameter), message])) except: raise_or_quit(ValueError, ("Couldn't run custom proc for " & "parameter $1:\n$2" % [escape(parameter), getCurrentExceptionMsg()])) - let message = custom_validator(parameter, parsed_parameter) - if not message.isNil and message.len > 0: - raise_or_quit(ValueError, ("Failed to validate value for " & - "parameter $1:\n$2" % [escape(parameter), message])) - proc parse_parameter(quit_on_failure: bool, param, value: string, param_kind: Tparam_kind): Tparsed_parameter = diff --git a/tests/manyloc/keineschweine/dependencies/chipmunk/chipmunk.nim b/tests/manyloc/keineschweine/dependencies/chipmunk/chipmunk.nim index 56d3edec4..ac425c7a0 100644 --- a/tests/manyloc/keineschweine/dependencies/chipmunk/chipmunk.nim +++ b/tests/manyloc/keineschweine/dependencies/chipmunk/chipmunk.nim @@ -23,7 +23,6 @@ const Lib = "libchipmunk.so.6.1.1" when defined(MoreNim): {.hint: "MoreNim defined; some Chipmunk functions replaced in Nim".} -{.deadCodeElim: on.} from math import sqrt, sin, cos, arctan2 when defined(CpUseFloat): {.hint: "CpUseFloat defined; using float32 as float".} @@ -389,13 +388,13 @@ type cdecl.} ##cp property emulators -template defGetter(otype: typedesc, memberType: typedesc, memberName: expr, procName: expr): stmt {.immediate.} = +template defGetter(otype: typedesc, memberType: typedesc, memberName, procName: untyped) = proc `get procName`*(obj: otype): memberType {.cdecl.} = return obj.memberName -template defSetter(otype: typedesc, memberType: typedesc, memberName: expr, procName: expr): stmt {.immediate.} = +template defSetter(otype: typedesc, memberType: typedesc, memberName, procName: untyped) = proc `set procName`*(obj: otype, value: memberType) {.cdecl.} = obj.memberName = value -template defProp(otype: typedesc, memberType: typedesc, memberName: expr, procName: expr): stmt {.immediate.} = +template defProp(otype: typedesc, memberType: typedesc, memberName, procName: untyped) = defGetter(otype, memberType, memberName, procName) defSetter(otype, memberType, memberName, procName) @@ -909,7 +908,7 @@ proc getShapes*(arb: PArbiter, a, b: var PShape) {.inline.} = #/ A macro shortcut for defining and retrieving the shapes from an arbiter. #define CP_ARBITER_GET_SHAPES(arb, a, b) cpShape *a, *b; cpArbiterGetShapes(arb, &a, &b); -template getShapes*(arb: PArbiter, name1, name2: expr): stmt {.immediate.} = +template getShapes*(arb: PArbiter, name1, name2: untyped) = var name1, name2: PShape getShapes(arb, name1, name2) @@ -924,7 +923,7 @@ template getShapes*(arb: PArbiter, name1, name2: expr): stmt {.immediate.} = #/ A macro shortcut for defining and retrieving the bodies from an arbiter. #define CP_ARBITER_GET_BODIES(arb, a, b) cpBody *a, *b; cpArbiterGetBodies(arb, &a, &b); -template getBodies*(arb: PArbiter, name1, name2: expr): stmt {.immediate.} = +template getBodies*(arb: PArbiter, name1, name2: untyped) = var name1, name2: PBOdy getBodies(arb, name1, name2) @@ -948,11 +947,11 @@ proc getDepth*(arb: PArbiter; i: cint): CpFloat {. cdecl, importc: "cpArbiterGetDepth", dynlib: Lib.} ##Shapes -template defShapeSetter(memberType: typedesc, memberName: expr, procName: expr, activates: bool): stmt {.immediate.} = +template defShapeSetter(memberType: typedesc, memberName: untyped, procName: untyped, activates: bool) = proc `set procName`*(obj: PShape, value: memberType) {.cdecl.} = if activates and obj.body != nil: obj.body.activate() obj.memberName = value -template defShapeProp(memberType: typedesc, memberName: expr, procName: expr, activates: bool): stmt {.immediate.} = +template defShapeProp(memberType: typedesc, memberName: untyped, procName: untyped, activates: bool) = defGetter(PShape, memberType, memberName, procName) defShapeSetter(memberType, memberName, procName, activates) @@ -1273,11 +1272,11 @@ proc activateBodies(constraint: PConstraint) {.inline.} = # cpConstraintActivateBodies(constraint); \ # constraint->member = value; \ # } -template defConstraintSetter(memberType: typedesc, member: expr, name: expr): stmt {.immediate.} = +template defConstraintSetter(memberType: typedesc, member, name: untyped) = proc `set name`*(constraint: PConstraint, value: memberType) {.cdecl.} = activateBodies(constraint) constraint.member = value -template defConstraintProp(memberType: typedesc, member: expr, name: expr): stmt {.immediate.} = +template defConstraintProp(memberType: typedesc, member, name: untyped) = defGetter(PConstraint, memberType, member, name) defConstraintSetter(memberType, member, name) # CP_DefineConstraintStructGetter(cpSpace*, CP_PRIVATE(space), Space) @@ -1307,18 +1306,18 @@ proc getImpulse*(constraint: PConstraint): CpFloat {.inline.} = # cpConstraintActivateBodies(constraint); \ # ((struct *)constraint)->member = value; \ # } -template constraintCheckCast(constraint: PConstraint, ctype: expr): stmt {.immediate.} = +template constraintCheckCast(constraint: PConstraint, ctype: untyped) = assert(constraint.klass == `ctype getClass`(), "Constraint is the wrong class") -template defCGetter(ctype: expr, memberType: typedesc, member: expr, name: expr): stmt {.immediate.} = +template defCGetter(ctype: untyped, memberType: typedesc, member, name: untyped) = proc `get ctype name`*(constraint: PConstraint): memberType {.cdecl.} = constraintCheckCast(constraint, ctype) result = cast[`P ctype`](constraint).member -template defCSetter(ctype: expr, memberType: typedesc, member: expr, name: expr): stmt {.immediate.} = +template defCSetter(ctype: untyped, memberType: typedesc, member, name: untyped) = proc `set ctype name`*(constraint: PConstraint, value: memberType) {.cdecl.} = constraintCheckCast(constraint, ctype) activateBodies(constraint) cast[`P ctype`](constraint).member = value -template defCProp(ctype: expr, memberType: typedesc, member: expr, name: expr): stmt {.immediate.} = +template defCProp(ctype: untyped, memberType: typedesc, member, name: untyped) = defCGetter(ctype, memberType, member, name) defCSetter(ctype, memberType, member, name) diff --git a/tests/manyloc/keineschweine/dependencies/enet/enet.nim b/tests/manyloc/keineschweine/dependencies/enet/enet.nim index 3c4ce2017..07079f2ea 100644 --- a/tests/manyloc/keineschweine/dependencies/enet/enet.nim +++ b/tests/manyloc/keineschweine/dependencies/enet/enet.nim @@ -20,12 +20,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. const Lib = "libenet.so.1(|.0.3)" -{.deadCodeElim: on.} const ENET_VERSION_MAJOR* = 1 ENET_VERSION_MINOR* = 3 ENET_VERSION_PATCH* = 3 -template ENET_VERSION_CREATE(major, minor, patch: expr): expr = +template ENET_VERSION_CREATE(major, minor, patch: untyped): untyped = (((major) shl 16) or ((minor) shl 8) or (patch)) const @@ -278,22 +277,22 @@ when defined(Linux) or true: dataLength*: csize TENetSocketSet* = Tfd_set ## see if these are different on win32, if not then get rid of these - template ENET_HOST_TO_NET_16*(value: expr): expr = + template ENET_HOST_TO_NET_16*(value: untyped): untyped = (htons(value)) - template ENET_HOST_TO_NET_32*(value: expr): expr = + template ENET_HOST_TO_NET_32*(value: untyped): untyped = (htonl(value)) - template ENET_NET_TO_HOST_16*(value: expr): expr = + template ENET_NET_TO_HOST_16*(value: untyped): untyped = (ntohs(value)) - template ENET_NET_TO_HOST_32*(value: expr): expr = + template ENET_NET_TO_HOST_32*(value: untyped): untyped = (ntohl(value)) - template ENET_SOCKETSET_EMPTY*(sockset: expr): expr = + template ENET_SOCKETSET_EMPTY*(sockset: untyped): untyped = FD_ZERO(addr((sockset))) - template ENET_SOCKETSET_ADD*(sockset, socket: expr): expr = + template ENET_SOCKETSET_ADD*(sockset, socket: untyped): untyped = FD_SET(socket, addr((sockset))) - template ENET_SOCKETSET_REMOVE*(sockset, socket: expr): expr = + template ENET_SOCKETSET_REMOVE*(sockset, socket: untyped): untyped = FD_CLEAR(socket, addr((sockset))) - template ENET_SOCKETSET_CHECK*(sockset, socket: expr): expr = + template ENET_SOCKETSET_CHECK*(sockset, socket: untyped): untyped = FD_ISSET(socket, addr((sockset))) when defined(Windows): @@ -607,7 +606,7 @@ proc protocolCommandSize*(commandNumber: cuchar): csize{. {.pop.} -from hashes import `!$`, `!&`, THash, hash -proc hash*(x: TAddress): THash {.nimcall, noSideEffect.} = +from hashes import `!$`, `!&`, Hash, hash +proc hash*(x: TAddress): Hash {.nimcall, noSideEffect.} = result = !$(hash(x.host.int32) !& hash(x.port.int16)) diff --git a/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim b/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim index 142b190ab..3fb4dc7d9 100644 --- a/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim +++ b/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim @@ -1,15 +1,15 @@ import macros, macro_dsl, estreams from strutils import format -template newLenName(): stmt {.immediate.} = +template newLenName() = let lenName {.inject.} = ^("len"& $lenNames) inc(lenNames) -template defPacketImports*(): stmt {.immediate, dirty.} = +template defPacketImports*() {.dirty.} = import macros, macro_dsl, estreams from strutils import format -macro defPacket*(typeNameN: expr, typeFields: expr): stmt {.immediate.} = +macro defPacket*(typeNameN: untyped, typeFields: untyped): untyped = result = newNimNode(nnkStmtList) let typeName = quoted2ident(typeNameN) @@ -60,7 +60,7 @@ macro defPacket*(typeNameN: expr, typeFields: expr): stmt {.immediate.} = let name = typeFields[i][0] dotName = packetID.dot(name) - resName = newIdentNode(!"result").dot(name) + resName = newIdentNode("result").dot(name) case typeFields[i][1].kind of nnkBracketExpr: #ex: paddedstring[32, '\0'], array[range, type] case $typeFields[i][1][0].ident @@ -141,7 +141,7 @@ macro defPacket*(typeNameN: expr, typeFields: expr): stmt {.immediate.} = const emptyFields = {nnkEmpty, nnkNilLit} var objFields = newNimNode(nnkRecList) - for i in 0.. < len(typeFields): + for i in 0 ..< len(typeFields): let fname = typeFields[i][0] constructorParams.add(newNimNode(nnkIdentDefs).und( fname, @@ -200,7 +200,7 @@ proc iddefs*(a: string; b: NimNode): NimNode {.compileTime.} = proc varTy*(a: NimNode): NimNode {.compileTime.} = result = newNimNode(nnkVarTy).und(a) -macro forwardPacket*(typeName: expr, underlyingType: expr): stmt {.immediate.} = +macro forwardPacket*(typeName: untyped, underlyingType: untyped): untyped = var packetID = ^"p" streamID = ^"s" @@ -234,7 +234,7 @@ macro forwardPacket*(typeName: expr, underlyingType: expr): stmt {.immediate.} = echo "unknown type:", repr(underlyingtype) echo(repr(result)) -template forwardPacketT*(typeName: expr; underlyingType: expr): stmt {.dirty, immediate.} = +template forwardPacketT*(typeName: untyped; underlyingType: untyped) {.dirty.} = proc `read typeName`*(buffer: PBuffer): typeName = #discard readData(s, addr result, sizeof(result)) var res: underlyingType diff --git a/tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim b/tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim index d3a0c701d..33d2a7177 100644 --- a/tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim +++ b/tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim @@ -1,5 +1,5 @@ import macros -{.deadCodeElim: on.} + #Inline macro.add() to allow for easier nesting proc und*(a: NimNode; b: NimNode): NimNode {.compileTime.} = a.add(b) @@ -10,7 +10,7 @@ proc und*(a: NimNode; b: varargs[NimNode]): NimNode {.compileTime.} = proc `^`*(a: string): NimNode {.compileTime.} = ## new ident node - result = newIdentNode(!a) + result = newIdentNode(a) proc `[]`*(a, b: NimNode): NimNode {.compileTime.} = ## new bracket expression: node[node] not to be confused with node[indx] result = newNimNode(nnkBracketExpr).und(a, b) @@ -34,7 +34,7 @@ proc emptyNode*(): NimNode {.compileTime.} = proc dot*(left, right: NimNode): NimNode {.compileTime.} = result = newNimNode(nnkDotExpr).und(left, right) proc prefix*(a: string, b: NimNode): NimNode {.compileTime.} = - result = newNimNode(nnkPrefix).und(newIdentNode(!a), b) + result = newNimNode(nnkPrefix).und(newIdentNode(a), b) proc quoted2ident*(a: NimNode): NimNode {.compileTime.} = if a.kind != nnkAccQuoted: @@ -45,13 +45,13 @@ proc quoted2ident*(a: NimNode): NimNode {.compileTime.} = result = ^pname -macro `?`(a: expr): expr = +macro `?`(a: untyped): untyped = ## Character literal ?A #=> 'A' result = ($a[1].ident)[0].lit ## echo(?F,?a,?t,?t,?y) when isMainModule: - macro foo(x: stmt): stmt = + macro foo(x: untyped) = result = newNimNode(nnkStmtList) result.add(newNimNode(nnkCall).und(!!"echo", "Hello thar".lit)) result.add(newCall("echo", lit("3 * 45 = "), (3.lit.infix("*", 45.lit)))) diff --git a/tests/manyloc/keineschweine/dependencies/nake/nakefile.nim b/tests/manyloc/keineschweine/dependencies/nake/nakefile.nim index bdf2139c9..5490211de 100644 --- a/tests/manyloc/keineschweine/dependencies/nake/nakefile.nim +++ b/tests/manyloc/keineschweine/dependencies/nake/nakefile.nim @@ -7,7 +7,7 @@ task "install", "compile and install nake binary": for index, dir in pairs(path): echo " ", index, ". ", dir echo "Where to install nake binary? (quit with ^C or quit or exit)" - let ans = stdin.readLine().toLower + let ans = stdin.readLine().toLowerAscii var index = 0 case ans of "q", "quit", "x", "exit": diff --git a/tests/manyloc/keineschweine/dependencies/sfml/sfml.nim b/tests/manyloc/keineschweine/dependencies/sfml/sfml.nim index 1524f0eb4..0060bf12b 100644 --- a/tests/manyloc/keineschweine/dependencies/sfml/sfml.nim +++ b/tests/manyloc/keineschweine/dependencies/sfml/sfml.nim @@ -12,7 +12,7 @@ else: LibS = "libcsfml-system.so.2.0" LibW = "libcsfml-window.so.2.0" #{.error: "Platform unsupported".} -{.deadCodeElim: on.} + {.pragma: pf, pure, final.} type PClock* = ptr TClock diff --git a/tests/manyloc/keineschweine/dependencies/sfml/sfml_colors.nim b/tests/manyloc/keineschweine/dependencies/sfml/sfml_colors.nim index 95a760e1f..b4eb1b8f0 100644 --- a/tests/manyloc/keineschweine/dependencies/sfml/sfml_colors.nim +++ b/tests/manyloc/keineschweine/dependencies/sfml/sfml_colors.nim @@ -1,5 +1,5 @@ import sfml -{.deadCodeElim: on.} + let Black*: TColor = color(0, 0, 0) White*: TColor = color(255, 255, 255) diff --git a/tests/manyloc/keineschweine/dependencies/sfml/sfml_vector.nim b/tests/manyloc/keineschweine/dependencies/sfml/sfml_vector.nim index 474d249aa..94c5308a9 100644 --- a/tests/manyloc/keineschweine/dependencies/sfml/sfml_vector.nim +++ b/tests/manyloc/keineschweine/dependencies/sfml/sfml_vector.nim @@ -1,2 +1 @@ import sfml, math, strutils -{.deadCodeElim: on.} diff --git a/tests/manyloc/keineschweine/keineschweine.nim b/tests/manyloc/keineschweine/keineschweine.nim index c0f1bc031..59347ee46 100644 --- a/tests/manyloc/keineschweine/keineschweine.nim +++ b/tests/manyloc/keineschweine/keineschweine.nim @@ -5,7 +5,7 @@ import sg_gui, sg_assets, sound_buffer, enet_client when defined(profiler): import nimprof -{.deadCodeElim: on.} + type PPlayer* = ref TPlayer TPlayer* = object diff --git a/tests/manyloc/keineschweine/lib/estreams.nim b/tests/manyloc/keineschweine/lib/estreams.nim index bdf9b2bf0..00a55c626 100644 --- a/tests/manyloc/keineschweine/lib/estreams.nim +++ b/tests/manyloc/keineschweine/lib/estreams.nim @@ -78,7 +78,7 @@ proc write*(buffer: PBuffer; val: var string) = setLen buffer.data, buffer.pos + length.int copyMem(addr buffer.data[buffer.pos], addr val[0], length.int) inc buffer.pos, length.int -proc write*[T: TNumber|bool|char|byte](buffer: PBuffer; val: T) = +proc write*[T: SomeNumber|bool|char|byte](buffer: PBuffer; val: T) = var v: T shallowCopy v, val writeBE buffer, v diff --git a/tests/manyloc/keineschweine/lib/input_helpers.nim b/tests/manyloc/keineschweine/lib/input_helpers.nim index 1953cb58c..ff1286c8d 100644 --- a/tests/manyloc/keineschweine/lib/input_helpers.nim +++ b/tests/manyloc/keineschweine/lib/input_helpers.nim @@ -5,8 +5,8 @@ type TInputFinishedProc* = proc() TKeyCallback = proc() PKeyClient* = ref object - onKeyDown: TTable[int32, TKeyCallback] - onKeyUp: TTable[int32, TKeyCallback] + onKeyDown: Table[int32, TKeyCallback] + onKeyUp: Table[int32, TKeyCallback] name: string PTextInput* = ref object text*: string @@ -134,5 +134,5 @@ iterator pollEvents*(window: PRenderWindow): PEvent = of EvtMouseButtonReleased: addButtonEvent(event.mouseButton.button, up) of EvtTextEntered: recordText(activeInput, event.text) of EvtMouseMoved: setMousePos(event.mouseMove.x, event.mouseMove.y) - else: nil + else: discard yield(addr event) diff --git a/tests/manyloc/keineschweine/lib/sg_assets.nim b/tests/manyloc/keineschweine/lib/sg_assets.nim index fbc3c9ab8..1e8a99c83 100644 --- a/tests/manyloc/keineschweine/lib/sg_assets.nim +++ b/tests/manyloc/keineschweine/lib/sg_assets.nim @@ -59,7 +59,7 @@ type of Projectile: bullet*: PBulletRecord else: - nil + discard PBulletRecord* = ref TBulletRecord TBulletRecord* = object id*: int16 @@ -115,10 +115,10 @@ var cfg: PZoneSettings SpriteSheets* = initTable[string, PSpriteSheet](64) SoundCache * = initTable[string, PSoundRecord](64) - nameToVehID*: TTable[string, int] - nameToItemID*: TTable[string, int] - nameToObjID*: TTable[string, int] - nameToBulletID*: TTable[string, int] + nameToVehID*: Table[string, int] + nameToItemID*: Table[string, int] + nameToObjID*: Table[string, int] + nameToBulletID*: Table[string, int] activeState = Lobby proc newSprite*(filename: string; errors: var seq[string]): PSpriteSheet @@ -126,7 +126,7 @@ proc load*(ss: PSpriteSheet): bool {.discardable.} proc newSound*(filename: string; errors: var seq[string]): PSoundRecord proc load*(s: PSoundRecord): bool {.discardable.} -proc validateSettings*(settings: PJsonNode; errors: var seq[string]): bool +proc validateSettings*(settings: JsonNode; errors: var seq[string]): bool proc loadSettings*(rawJson: string, errors: var seq[string]): bool proc loadSettingsFromFile*(filename: string, errors: var seq[string]): bool @@ -135,17 +135,17 @@ proc fetchItm*(itm: string): PItemRecord proc fetchObj*(name: string): PObjectRecord proc fetchBullet(name: string): PBulletRecord -proc importLevel(data: PJsonNode; errors: var seq[string]): PLevelSettings -proc importVeh(data: PJsonNode; errors: var seq[string]): PVehicleRecord -proc importObject(data: PJsonNode; errors: var seq[string]): PObjectRecord -proc importItem(data: PJsonNode; errors: var seq[string]): PItemRecord -proc importPhys(data: PJsonNode): TPhysicsRecord -proc importAnim(data: PJsonNode; errors: var seq[string]): PAnimationRecord -proc importHandling(data: PJsonNode): THandlingRecord -proc importBullet(data: PJsonNode; errors: var seq[string]): PBulletRecord -proc importSoul(data: PJsonNode): TSoulRecord -proc importExplosion(data: PJsonNode; errors: var seq[string]): TExplosionRecord -proc importSound*(data: PJsonNode; errors: var seq[string]; fieldName: string = nil): PSoundRecord +proc importLevel(data: JsonNode; errors: var seq[string]): PLevelSettings +proc importVeh(data: JsonNode; errors: var seq[string]): PVehicleRecord +proc importObject(data: JsonNode; errors: var seq[string]): PObjectRecord +proc importItem(data: JsonNode; errors: var seq[string]): PItemRecord +proc importPhys(data: JsonNode): TPhysicsRecord +proc importAnim(data: JsonNode; errors: var seq[string]): PAnimationRecord +proc importHandling(data: JsonNode): THandlingRecord +proc importBullet(data: JsonNode; errors: var seq[string]): PBulletRecord +proc importSoul(data: JsonNode): TSoulRecord +proc importExplosion(data: JsonNode; errors: var seq[string]): TExplosionRecord +proc importSound*(data: JsonNode; errors: var seq[string]; fieldName: string = nil): PSoundRecord ## this is the only pipe between lobby and main.nim proc getActiveState*(): TGameState = @@ -203,7 +203,7 @@ iterator playableVehicles*(): PVehicleRecord = if v.playable: yield v -template allAssets*(body: stmt) {.dirty.}= +template allAssets*(body: untyped) {.dirty.}= block: var assetType = FGraphics for file, asset in pairs(SpriteSheets): @@ -212,7 +212,7 @@ template allAssets*(body: stmt) {.dirty.}= for file, asset in pairs(SoundCache): body -template cacheImpl(procName, cacheName, resultType: expr; body: stmt) {.dirty, immediate.} = +template cacheImpl(procName, cacheName, resultType, body: untyped) {.dirty.} = proc procName*(filename: string; errors: var seq[string]): resulttype = if hasKey(cacheName, filename): return cacheName[filename] @@ -220,7 +220,7 @@ template cacheImpl(procName, cacheName, resultType: expr; body: stmt) {.dirty, i body cacheName[filename] = result -template checkFile(path: expr): stmt {.dirty, immediate.} = +template checkFile(path: untyped) {.dirty.} = if not existsFile(path): errors.add("File missing: "& path) @@ -243,7 +243,7 @@ proc expandPath*(assetType: TAssetType; fileName: string): string = case assetType of FGraphics: result.add "gfx/" of FSound: result.add "sfx/" - else: nil + else: discard result.add fileName proc expandPath*(fc: ScFileChallenge): string {.inline.} = result = expandPath(fc.assetType, fc.file) @@ -280,10 +280,10 @@ else: if not s.soundBuf.isNil: result = true -template addError(e: expr): stmt {.immediate.} = +template addError(e: untyped) = errors.add(e) result = false -proc validateSettings*(settings: PJsonNode, errors: var seq[string]): bool = +proc validateSettings*(settings: JsonNode, errors: var seq[string]): bool = result = true if settings.kind != JObject: addError("Settings root must be an object") @@ -328,10 +328,10 @@ proc loadSettingsFromFile*(filename: string, errors: var seq[string]): bool = result = loadSettings(readFile(filename), errors) proc loadSettings*(rawJson: string, errors: var seq[string]): bool = - var settings: PJsonNode + var settings: JsonNode try: settings = parseJson(rawJson) - except EJsonParsingError: + except JsonParsingError: errors.add("JSON parsing error: "& getCurrentExceptionMsg()) return except: @@ -407,21 +407,21 @@ proc fetchObj*(name: string): PObjectRecord = proc fetchBullet(name: string): PBulletRecord = return cfg.bullets[nameToBulletID[name]] -proc getField(node: PJsonNode, field: string, target: var float) = +proc getField(node: JsonNode, field: string, target: var float) = if not node.hasKey(field): return if node[field].kind == JFloat: target = node[field].fnum elif node[field].kind == JInt: target = node[field].num.float -proc getField(node: PJsonNode, field: string, target: var int) = +proc getField(node: JsonNode, field: string, target: var int) = if not node.hasKey(field): return if node[field].kind == JInt: target = node[field].num.int elif node[field].kind == JFloat: target = node[field].fnum.int -proc getField(node: PJsonNode; field: string; target: var bool) = +proc getField(node: JsonNode; field: string; target: var bool) = if not node.hasKey(field): return case node[field].kind @@ -431,19 +431,19 @@ proc getField(node: PJsonNode; field: string; target: var bool) = target = (node[field].num != 0) of JFloat: target = (node[field].fnum != 0.0) - else: nil + else: discard -template checkKey(node: expr; key: string): stmt = +template checkKey(node: untyped; key: string) = if not hasKey(node, key): return -proc importTrail(data: PJsonNode; errors: var seq[string]): TTrailRecord = +proc importTrail(data: JsonNode; errors: var seq[string]): TTrailRecord = checkKey(data, "trail") result.anim = importAnim(data["trail"], errors) result.timer = 1000.0 getField(data["trail"], "timer", result.timer) result.timer /= 1000.0 -proc importLevel(data: PJsonNode; errors: var seq[string]): PLevelSettings = +proc importLevel(data: JsonNode; errors: var seq[string]): PLevelSettings = new(result) result.size = vec2i(5000, 5000) result.starfield = @[] @@ -456,7 +456,7 @@ proc importLevel(data: PJsonNode; errors: var seq[string]): PLevelSettings = if level.hasKey("starfield"): for star in level["starfield"].items: result.starfield.add(newSprite(star.str, errors)) -proc importPhys(data: PJsonNode): TPhysicsRecord = +proc importPhys(data: JsonNode): TPhysicsRecord = result.radius = 20.0 result.mass = 10.0 @@ -466,7 +466,7 @@ proc importPhys(data: PJsonNode): TPhysicsRecord = phys.getField("mass", result.mass) when not defined(NoChipmunk): result.moment = momentForCircle(result.mass, 0.0, result.radius, VectorZero) * MomentMult -proc importHandling(data: PJsonNode): THandlingRecord = +proc importHandling(data: JsonNode): THandlingRecord = result.thrust = 45.0 result.topSpeed = 100.0 #unused result.reverse = 30.0 @@ -483,7 +483,7 @@ proc importHandling(data: PJsonNode): THandlingRecord = hand.getField("reverse", result.reverse) hand.getField("strafe", result.strafe) hand.getField("rotation", result.rotation) -proc importAnim(data: PJsonNode, errors: var seq[string]): PAnimationRecord = +proc importAnim(data: JsonNode, errors: var seq[string]): PAnimationRecord = new(result) result.angle = 0.0 result.delay = 1000.0 @@ -502,26 +502,26 @@ proc importAnim(data: PJsonNode, errors: var seq[string]): PAnimationRecord = result.angle = radians(result.angle) ## comes in as degrees result.delay /= 1000 ## delay comes in as milliseconds -proc importSoul(data: PJsonNode): TSoulRecord = +proc importSoul(data: JsonNode): TSoulRecord = result.energy = 10000 result.health = 1 checkKey(data, "soul") let soul = data["soul"] soul.getField("energy", result.energy) soul.getField("health", result.health) -proc importExplosion(data: PJsonNode; errors: var seq[string]): TExplosionRecord = +proc importExplosion(data: JsonNode; errors: var seq[string]): TExplosionRecord = checkKey(data, "explode") let expl = data["explode"] result.anim = importAnim(expl, errors) result.sound = importSound(expl, errors, "sound") -proc importSound*(data: PJsonNode; errors: var seq[string]; fieldName: string = nil): PSoundRecord = +proc importSound*(data: JsonNode; errors: var seq[string]; fieldName: string = nil): PSoundRecord = if data.kind == JObject: checkKey(data, fieldName) result = newSound(data[fieldName].str, errors) elif data.kind == JString: result = newSound(data.str, errors) -proc importVeh(data: PJsonNode; errors: var seq[string]): PVehicleRecord = +proc importVeh(data: JsonNode; errors: var seq[string]): PVehicleRecord = new(result) result.playable = false if data.kind != JArray or data.len != 2 or @@ -538,7 +538,7 @@ proc importVeh(data: PJsonNode; errors: var seq[string]): PVehicleRecord = vehdata.getField("playable", result.playable) if result.anim.spriteSheet.isNil and result.playable: result.playable = false -proc importObject(data: PJsonNode; errors: var seq[string]): PObjectRecord = +proc importObject(data: JsonNode; errors: var seq[string]): PObjectRecord = new(result) if data.kind != JArray or data.len != 2: result.name = "(broken)" @@ -546,7 +546,7 @@ proc importObject(data: PJsonNode; errors: var seq[string]): PObjectRecord = result.name = data[0].str result.anim = importAnim(data[1], errors) result.physics = importPhys(data[1]) -proc importItem(data: PJsonNode; errors: var seq[string]): PItemRecord = +proc importItem(data: JsonNode; errors: var seq[string]): PItemRecord = new(result) if data.kind != JArray or data.len != 3: result.name = "(broken)" @@ -562,7 +562,7 @@ proc importItem(data: PJsonNode; errors: var seq[string]): PItemRecord = result.useSound = importSound(data[2], errors, "useSound") - case data[1].str.toLower + case data[1].str.toLowerAscii of "projectile": result.kind = Projectile if data[2]["bullet"].kind == JString: @@ -576,15 +576,15 @@ proc importItem(data: PJsonNode; errors: var seq[string]): PItemRecord = of "ammo": result.kind = Ammo of "utility": - nil + discard else: errors.add "Invalid item type \""&data[1].str&"\" for item "&result.name -proc importBullet(data: PJsonNode; errors: var seq[string]): PBulletRecord = +proc importBullet(data: JsonNode; errors: var seq[string]): PBulletRecord = new(result) result.id = -1 - var bdata: PJsonNode + var bdata: JsonNode if data.kind == JArray: result.name = data[0].str bdata = data[1] diff --git a/tests/manyloc/keineschweine/lib/sg_gui.nim b/tests/manyloc/keineschweine/lib/sg_gui.nim index ffc4e8215..b7448d9df 100644 --- a/tests/manyloc/keineschweine/lib/sg_gui.nim +++ b/tests/manyloc/keineschweine/lib/sg_gui.nim @@ -2,7 +2,7 @@ import sfml, sfml_colors, input_helpers, sg_packets from strutils import countlines -{.deadCodeElim: on.} + type PGuiContainer* = ref TGuiContainer TGuiContainer* = object of TObject diff --git a/tests/manyloc/keineschweine/lib/sg_packets.nim b/tests/manyloc/keineschweine/lib/sg_packets.nim index d84bf72fc..f3a0e8925 100644 --- a/tests/manyloc/keineschweine/lib/sg_packets.nim +++ b/tests/manyloc/keineschweine/lib/sg_packets.nim @@ -4,14 +4,14 @@ defPacketImports() type PacketID* = char -template idpacket(pktName, id, s2c, c2s: expr): stmt {.immediate, dirty.} = +template idpacket(pktName, id, s2c, c2s: untyped) {.dirty.} = let `H pktName`* {.inject.} = id defPacket(`Sc pktName`, s2c) defPacket(`Cs pktName`, c2s) forwardPacketT(uint8, int8) forwardPacketT(uint16, int16) -forwardPacketT(TPort, int16) +forwardPacketT(Port, int16) idPacket(Login, 'a', tuple[id: int32; alias: string; sessionKey: string], @@ -22,7 +22,7 @@ defPacket(CsZoneJoinReq, tuple[session: ScLogin]) defPacket(ScZoneRecord, tuple[ name: string = "", desc: string = "", - ip: string = "", port: TPort = 0.Tport]) + ip: string = "", port: Port = 0.Port]) idPacket(ZoneList, 'z', tuple[network: string = "", zones: seq[ScZoneRecord]], tuple[time: string]) diff --git a/tests/manyloc/keineschweine/server/nim.cfg b/tests/manyloc/keineschweine/server/nim.cfg index fdc45a8e1..211ad3003 100644 --- a/tests/manyloc/keineschweine/server/nim.cfg +++ b/tests/manyloc/keineschweine/server/nim.cfg @@ -1,5 +1,4 @@ debugger = off -deadCodeElim = on path = ".." path = "../genpacket" path = "../helpers" diff --git a/tests/manyloc/nake/nake.nim b/tests/manyloc/nake/nake.nim index 1e88fa73b..728619e47 100644 --- a/tests/manyloc/nake/nake.nim +++ b/tests/manyloc/nake/nake.nim @@ -67,7 +67,7 @@ else: for kind, key, val in getOpt(): case kind of cmdLongOption, cmdShortOption: - case key.tolower + case key.tolowerAscii of "tasks", "t": printTaskList = true else: diff --git a/tests/manyloc/nake/nakefile.nim b/tests/manyloc/nake/nakefile.nim index 2055d7834..3e8609169 100644 --- a/tests/manyloc/nake/nakefile.nim +++ b/tests/manyloc/nake/nakefile.nim @@ -10,7 +10,7 @@ const ExeName = "keineschweine" ServerDefines = "-d:NoSFML -d:NoChipmunk" TestBuildDefines = "-d:escapeMenuTest -d:debugWeps -d:showFPS -d:moreNim -d:debugKeys -d:foo -d:recordMode --forceBuild" - ReleaseDefines = "-d:release --deadCodeElim:on" + ReleaseDefines = "-d:release" ReleaseTestDefines = "-d:debugWeps -d:debugKeys --forceBuild" task "testprofile", "..": @@ -88,7 +88,7 @@ task "download", "download game assets": if existsFile(path): echo "The file already exists\n", "[R]emove [M]ove [Q]uit [S]kip Source: ", GameAssets - case stdin.readLine.toLower + case stdin.readLine.toLowerAscii of "r": removeFile path of "m": @@ -120,7 +120,7 @@ task "download", "download game assets": echo "Download binary libs? Only libs for linux are available currently, enjoy the irony.\n", "[Y]es [N]o Source: ", BinLibs - case stdin.readline.toLower + case stdin.readline.toLowerAscii of "y", "yes": discard ## o_O else: diff --git a/tests/manyloc/standalone/barebone.nim.cfg b/tests/manyloc/standalone/barebone.nim.cfg index bb350ff55..b956bef8e 100644 --- a/tests/manyloc/standalone/barebone.nim.cfg +++ b/tests/manyloc/standalone/barebone.nim.cfg @@ -1,3 +1,2 @@ --os:standalone ---deadCodeElim:on --gc:none diff --git a/tests/metatype/tautotypetrait.nim b/tests/metatype/tautotypetrait.nim new file mode 100644 index 000000000..84cd7b9f3 --- /dev/null +++ b/tests/metatype/tautotypetrait.nim @@ -0,0 +1,14 @@ +discard """ + output: '''(Field0: "string", Field1: "string")''' +""" + +# 7528 +import macros +import typetraits + +macro bar*(n: untyped): typed = + result = newNimNode(nnkStmtList, n) + result.add(newCall("write", newIdentNode("stdout"), n)) + +proc foo0[T](): auto = return (T.name, T.name) +bar foo0[string]() diff --git a/tests/metatype/tbindtypedesc.nim b/tests/metatype/tbindtypedesc.nim index b287aad01..039acfbe9 100644 --- a/tests/metatype/tbindtypedesc.nim +++ b/tests/metatype/tbindtypedesc.nim @@ -46,7 +46,7 @@ type type1 = typedesc type2 = typedesc -proc typePairs(A, B: type1; C, D: type2) = nil +proc typePairs(A, B: type1; C, D: type2) = discard accept typePairs(int, int, TFoo, TFOO) accept typePairs(TBAR, TBar, TBAR, TBAR) @@ -55,7 +55,7 @@ accept typePairs(int, int, string, string) reject typePairs(TBAR, TBar, TBar, TFoo) reject typePairs(string, int, TBAR, TBAR) -proc typePairs2[T: typedesc, U: typedesc](A, B: T; C, D: U) = nil +proc typePairs2[T: typedesc, U: typedesc](A, B: T; C, D: U) = discard accept typePairs2(int, int, TFoo, TFOO) accept typePairs2(TBAR, TBar, TBAR, TBAR) @@ -71,12 +71,12 @@ proc dontBind(a: typedesc, b: typedesc) = accept dontBind(int, float) accept dontBind(TFoo, TFoo) -proc dontBind2(a, b: typedesc) = nil +proc dontBind2(a, b: typedesc) = discard accept dontBind2(int, float) accept dontBind2(TBar, int) -proc bindArg(T: typedesc, U: typedesc, a, b: T, c, d: U) = nil +proc bindArg(T: typedesc, U: typedesc, a, b: T, c, d: U) = discard accept bindArg(int, string, 10, 20, "test", "nest") accept bindArg(int, int, 10, 20, 30, 40) diff --git a/tests/metatype/tstaticparammacro.nim b/tests/metatype/tstaticparammacro.nim index bd3295874..02021185f 100644 --- a/tests/metatype/tstaticparammacro.nim +++ b/tests/metatype/tstaticparammacro.nim @@ -14,7 +14,6 @@ AST b 20Test 20 ''' - disabled: true """ import macros @@ -26,7 +25,7 @@ type const data: Tconfig = (@["aa", "bb"], @[11, 22]) -macro mymacro(data: static[TConfig]) = +macro mymacro(data: static[TConfig]): untyped = echo "letters" for s in items(data.letters): echo s @@ -44,10 +43,10 @@ const a : Ta = @[(11, 22), (33, 44)] b : Tb = (@[55,66], @[77, 88]) -macro mA(data: static[Ta]) = +macro mA(data: static[Ta]): untyped = echo "AST a \n", repr(data) -macro mB(data: static[Tb]) = +macro mB(data: static[Tb]): untyped = echo "AST b \n", repr(data) echo data.e[0] @@ -57,13 +56,15 @@ mB(b) type Foo[N: static[int], Z: static[string]] = object -macro staticIntMacro(f: static[int]) = echo f +macro staticIntMacro(f: static[int]): untyped = + echo f + staticIntMacro 10 var x: Foo[20, "Test"] -macro genericMacro[N; Z: static[string]](f: Foo[N, Z], ll = 3, zz = 12) = +macro genericMacro[N; Z: static[string]](f: Foo[N, Z], ll = 3, zz = 12): untyped = echo N, Z genericMacro x diff --git a/tests/metatype/ttypeselectors.nim b/tests/metatype/ttypeselectors.nim index c29fd15ce..1209fe78f 100644 --- a/tests/metatype/ttypeselectors.nim +++ b/tests/metatype/ttypeselectors.nim @@ -1,4 +1,9 @@ -import macros +discard """ +output: "8\n8\n4" +""" + +import + macros, typetraits template selectType(x: int): typeDesc = when x < 10: @@ -11,6 +16,9 @@ template simpleTypeTempl: typeDesc = macro typeFromMacro: typedesc = string +# The tests below check that the result variable of the +# selected type matches the literal types in the code: + proc t1*(x: int): simpleTypeTempl() = result = "test" @@ -37,3 +45,57 @@ proc t6*(x: type(t3(0))): type(t1(0)) = proc t7*(x: int): type($x) = result = "test" +# This is a more compicated example involving a type +# selection through a macro: +# https://github.com/nim-lang/Nim/issues/7230 + +macro getBase*(bits: static[int]): untyped = + if bits >= 128: + result = newTree(nnkBracketExpr, ident("MpUintBase"), ident("uint64")) + else: + result = newTree(nnkBracketExpr, ident("MpUintBase"), ident("uint32")) + +type + BaseUint* = SomeUnsignedInt or MpUintBase + + MpUintBase*[T] = object + lo*, hi*: T + + ## This gets type mismatch + MpUint*[bits: static[int]] = getBase(bits) + +var m1: MpUint[128] +var m2: MpUint[64] +var m3: getBase(32) + +static: + # assert m1.type.name == "MpUintBase[uint64]" + assert m1.lo.type.name == "uint64" + assert m2.lo.type.name == "uint32" + assert m3.type.name == "MpUintBase[system.uint32]" + +# https://github.com/nim-lang/Nim/issues/7379 + +import macros, typetraits + +macro works(): untyped = + result = getType(int64) + +macro fails(bits: static[int]): untyped = + if bits > 64: + result = getType(int64) + else: + result = getType(int32) + +type + Foo*[bits: static[int]] = works() + Bar*[bits: static[int]] = fails(bits) + +var a: Foo[16] +var b: Bar[256] +var c: Bar[32] + +echo sizeof(a) +echo sizeof(b) +echo sizeof(c) + diff --git a/tests/metatype/tvoid_must_not_match.nim b/tests/metatype/tvoid_must_not_match.nim index 240c3f751..c786c2f16 100644 --- a/tests/metatype/tvoid_must_not_match.nim +++ b/tests/metatype/tvoid_must_not_match.nim @@ -1,5 +1,5 @@ discard """ - errormsg: "type mismatch: got (Future[system.int], void)" + errormsg: "type mismatch: got <Future[system.int], void>" line: 20 """ diff --git a/tests/metatype/typeclassinference.nim b/tests/metatype/typeclassinference.nim index fd2d307a9..c845e04f7 100644 --- a/tests/metatype/typeclassinference.nim +++ b/tests/metatype/typeclassinference.nim @@ -1,7 +1,6 @@ discard """ - errormsg: "type mismatch: got (string) but expected 'ptr'" + errormsg: "type mismatch: got <string> but expected 'ptr'" line: 20 - disabled: true """ import typetraits @@ -12,7 +11,7 @@ type var x = Vec([1, 2, 3]) static: - assert x.type.name == "Vec[static[int](3), int]" + assert x.type.name == "Vec[3, system.int]" var str1: string = "hello, world!" var ptr1: ptr = addr(str1) diff --git a/tests/method/tsimmeth.nim b/tests/method/tsimmeth.nim index 11ff2674f..a057c35b7 100644 --- a/tests/method/tsimmeth.nim +++ b/tests/method/tsimmeth.nim @@ -6,7 +6,7 @@ discard """ import strutils -var x = "hello world!".toLower.toUpper +var x = "hello world!".toLowerAscii.toUpperAscii x.echo() #OUT HELLO WORLD! diff --git a/tests/misc/tidentconcatenations.nim b/tests/misc/tidentconcatenations.nim new file mode 100644 index 000000000..302c51d87 --- /dev/null +++ b/tests/misc/tidentconcatenations.nim @@ -0,0 +1,32 @@ +type + Hash*[bits: static[int]] = object + data*: array[bits div 8, uint8] + +{.emit: """ + +void sha_256(void* input, int input_len, void* output, int output_len) {} +void sha_512(void* input, int input_len, void* output, int output_len) {} + +void keccak_256(void* input, int input_len, void* output, int output_len) {} +void keccak_512(void* input, int input_len, void* output, int output_len) {} + +""".} + +template defineKeccak(bits: untyped) = + proc `extKeccak bits`(output: pointer, outSize: csize, input: pointer, inputSize: csize) {.nodecl, importc: "keccak_" & astToStr(bits).} + +template defineSha(bits: static[int]) = + proc `extSha bits`(output: pointer, outSize: csize, input: pointer, inputSize: csize) {.nodecl, importc: "sha_" & astToStr(bits).} + +template defineHashProcs(bits) = + defineSha(bits) + defineKeccak(bits) + +defineHashProcs(256) +defineHashProcs(512) + +extSha256(nil, 0, nil, 0) +extSha512(nil, 0, nil, 0) +extKeccak256(nil, 0, nil, 0) +extKeccak512(nil, 0, nil, 0) + diff --git a/tests/misc/tinc.nim b/tests/misc/tinc.nim index b74f85591..7819775e3 100644 --- a/tests/misc/tinc.nim +++ b/tests/misc/tinc.nim @@ -1,7 +1,7 @@ discard """ file: "tinc.nim" line: 8 - errormsg: "type mismatch: got (int)" + errormsg: "type mismatch: got <int>" """ var x = 0 diff --git a/tests/misc/tinout.nim b/tests/misc/tinout.nim index 0b2a54d9f..46af2f5de 100644 --- a/tests/misc/tinout.nim +++ b/tests/misc/tinout.nim @@ -1,7 +1,7 @@ discard """ file: "tinout.nim" line: 12 - errormsg: "type mismatch: got (int literal(3))" + errormsg: "type mismatch: got <int literal(3)>" """ # Test in out checking for parameters diff --git a/tests/misc/tinvalidnewseq.nim b/tests/misc/tinvalidnewseq.nim index 89083d8b2..66e9388ef 100644 --- a/tests/misc/tinvalidnewseq.nim +++ b/tests/misc/tinvalidnewseq.nim @@ -1,7 +1,7 @@ discard """ file: "tinvalidnewseq.nim" line: 15 - errormsg: "type mismatch: got (array[0..6, string], int literal(7))" + errormsg: "type mismatch: got <array[0..6, string], int literal(7)>" """ import re, strutils diff --git a/tests/misc/tmemoization.nim b/tests/misc/tmemoization.nim index 180acd89b..840eb3b0d 100644 --- a/tests/misc/tmemoization.nim +++ b/tests/misc/tmemoization.nim @@ -8,7 +8,7 @@ import strutils proc foo(s: static[string]): string = static: echo s - const R = s.toUpper + const R = s.toUpperAscii return R echo foo("test 1") diff --git a/tests/misc/tnolen.nim b/tests/misc/tnolen.nim index dcf6811eb..2831e5048 100644 --- a/tests/misc/tnolen.nim +++ b/tests/misc/tnolen.nim @@ -1,6 +1,6 @@ discard """ line: 8 - errormsg: "type mismatch: got (int literal(3))" + errormsg: "type mismatch: got <int literal(3)>" """ # please finally disallow Len(3) diff --git a/tests/misc/tparseopt.nim b/tests/misc/tparseopt.nim index 1f8375dfd..badbc59ad 100644 --- a/tests/misc/tparseopt.nim +++ b/tests/misc/tparseopt.nim @@ -9,6 +9,17 @@ kind: cmdLongOption key:val -- left: kind: cmdLongOption key:val -- debug:3 kind: cmdShortOption key:val -- l:4 kind: cmdShortOption key:val -- r:2 +parseoptNoVal +kind: cmdLongOption key:val -- left: +kind: cmdLongOption key:val -- debug:3 +kind: cmdShortOption key:val -- l: +kind: cmdShortOption key:val -- r:2 +kind: cmdLongOption key:val -- debug:2 +kind: cmdLongOption key:val -- debug:1 +kind: cmdShortOption key:val -- r:1 +kind: cmdShortOption key:val -- r:0 +kind: cmdShortOption key:val -- l: +kind: cmdShortOption key:val -- r:4 parseopt2 first round kind: cmdLongOption key:val -- left: @@ -40,6 +51,15 @@ block: echo "kind: ", kind, "\tkey:val -- ", key, ":", val block: + echo "parseoptNoVal" + # test NoVal mode with custom cmdline arguments + var argv = "--left --debug:3 -l -r:2 --debug 2 --debug=1 -r1 -r=0 -lr4" + var p = parseopt.initOptParser(argv, + shortNoVal = {'l'}, longNoVal = @["left"]) + for kind, key, val in parseopt.getopt(p): + echo "kind: ", kind, "\tkey:val -- ", key, ":", val + +block: echo "parseopt2" for kind, key, val in parseopt2.getopt(): echo "kind: ", kind, "\tkey:val -- ", key, ":", val diff --git a/tests/misc/tsemfold.nim b/tests/misc/tsemfold.nim new file mode 100644 index 000000000..18c282d9e --- /dev/null +++ b/tests/misc/tsemfold.nim @@ -0,0 +1,23 @@ +discard """ + action: run +""" + +doAssertRaises(OverflowError): discard low(int8) - 1'i8 +doAssertRaises(OverflowError): discard high(int8) + 1'i8 +doAssertRaises(OverflowError): discard abs(low(int8)) +doAssertRaises(DivByZeroError): discard 1 mod 0 +doAssertRaises(DivByZeroError): discard 1 div 0 +doAssertRaises(OverflowError): discard low(int8) div -1'i8 + +doAssertRaises(OverflowError): discard low(int64) - 1'i64 +doAssertRaises(OverflowError): discard high(int64) + 1'i64 + +type E = enum eA, eB +doAssertRaises(OverflowError): discard eA.pred +doAssertRaises(OverflowError): discard eB.succ + +doAssertRaises(OverflowError): discard low(int8) * -1 +doAssertRaises(OverflowError): discard low(int64) * -1 +doAssertRaises(OverflowError): discard high(int8) * 2 +doAssertRaises(OverflowError): discard high(int64) * 2 + diff --git a/tests/misc/tsimplesort.nim b/tests/misc/tsimplesort.nim index 3115863d5..e4a8e0b37 100644 --- a/tests/misc/tsimplesort.nim +++ b/tests/misc/tsimplesort.nim @@ -40,11 +40,11 @@ proc mustRehash(length, counter: int): bool {.inline.} = assert(length > counter) result = (length * 2 < counter * 3) or (length - counter < 4) -proc nextTry(h, maxHash: THash): THash {.inline.} = +proc nextTry(h, maxHash: Hash): Hash {.inline.} = result = ((5 * h) + 1) and maxHash template rawGetImpl() = - var h: THash = hash(key) and high(t.data) # start with real hash value + var h: Hash = hash(key) and high(t.data) # start with real hash value while t.data[h].slot != seEmpty: if t.data[h].key == key and t.data[h].slot == seFilled: return h @@ -52,7 +52,7 @@ template rawGetImpl() = result = -1 template rawInsertImpl() = - var h: THash = hash(key) and high(data) + var h: Hash = hash(key) and high(data) while data[h].slot == seFilled: h = nextTry(h, high(data)) data[h].key = key @@ -162,7 +162,7 @@ iterator values*[A](t: TCountTable[A]): int = if t.data[h].val != 0: yield t.data[h].val proc RawGet[A](t: TCountTable[A], key: A): int = - var h: THash = hash(key) and high(t.data) # start with real hash value + var h: Hash = hash(key) and high(t.data) # start with real hash value while t.data[h].val != 0: if t.data[h].key == key: return h h = nextTry(h, high(t.data)) @@ -181,7 +181,7 @@ proc hasKey*[A](t: TCountTable[A], key: A): bool = proc rawInsert[A](t: TCountTable[A], data: var seq[tuple[key: A, val: int]], key: A, val: int) = - var h: THash = hash(key) and high(data) + var h: Hash = hash(key) and high(data) while data[h].val != 0: h = nextTry(h, high(data)) data[h].key = key data[h].val = val diff --git a/tests/misc/tsimtych.nim b/tests/misc/tsimtych.nim index 27a922f6a..037172bd5 100644 --- a/tests/misc/tsimtych.nim +++ b/tests/misc/tsimtych.nim @@ -1,7 +1,7 @@ discard """ file: "tsimtych.nim" line: 10 - errormsg: "type mismatch: got (bool) but expected \'string\'" + errormsg: "type mismatch: got <bool> but expected \'string\'" """ # Test 2 # Simple type checking diff --git a/tests/misc/tunsignedcmp.nim b/tests/misc/tunsignedcmp.nim index 9ffc0d119..11b67ac5f 100644 --- a/tests/misc/tunsignedcmp.nim +++ b/tests/misc/tunsignedcmp.nim @@ -1,7 +1,17 @@ discard """ output: '''true true -true''' +true +5 +4 +3 +2 +1 +0 +it should stop now +18446744073709551615 +4294967295 +''' """ # bug 1420 @@ -11,3 +21,23 @@ echo x > y # works echo((40'i32) > (30'i32)) echo((40'u32) > (30'u32)) # Error: ordinal type expected + +# bug #4220 + +const count: uint = 5 +var stop_me = false + +for i in countdown(count, 0): + echo i + if stop_me: break + if i == 0: + echo "it should stop now" + stop_me = true + +# bug #3985 +const + HIGHEST_64BIT_UINT = 0xFFFFFFFFFFFFFFFF'u + HIGHEST_32BIT_UINT = 0xFFFFFFFF'u + +echo($HIGHEST_64BIT_UINT) +echo($HIGHEST_32BIT_UINT) diff --git a/tests/misc/tunsignedmisc.nim b/tests/misc/tunsignedmisc.nim index 4b8157ddd..fc02eee19 100644 --- a/tests/misc/tunsignedmisc.nim +++ b/tests/misc/tunsignedmisc.nim @@ -1,5 +1,5 @@ discard """ - errormsg: "number 0x123'u8 out of valid range" + errormsg: "number out of range: '0x123'u8'" """ # Bug #1179 diff --git a/tests/misc/åäö.nim b/tests/misc/åäö.nim new file mode 100644 index 000000000..69bb3e22c --- /dev/null +++ b/tests/misc/åäö.nim @@ -0,0 +1,8 @@ +discard """ + action: run +""" + +# Tests that module names can contain multi byte characters + +let a = 1 +doAssert åäö.a == 1 \ No newline at end of file diff --git a/tests/modules/definitions.nim b/tests/modules/definitions.nim new file mode 100644 index 000000000..edc6eaa6d --- /dev/null +++ b/tests/modules/definitions.nim @@ -0,0 +1,4 @@ +var v*: int +proc p* = echo "proc p called" +template t* = echo "template t expanded" + diff --git a/tests/modules/proxy_module.nim b/tests/modules/proxy_module.nim new file mode 100644 index 000000000..c244688cd --- /dev/null +++ b/tests/modules/proxy_module.nim @@ -0,0 +1,3 @@ +import definitions +export definitions except p + diff --git a/tests/modules/tcanimport.nim b/tests/modules/tcanimport.nim new file mode 100644 index 000000000..bc4e2e53f --- /dev/null +++ b/tests/modules/tcanimport.nim @@ -0,0 +1,19 @@ +discard """ + output: '''ABC +nope''' +""" + +template canImport(x): bool = + compiles: + import x + +when canImport(strutils): + import strutils + echo "abc".toUpperAscii +else: + echo "meh" + +when canImport(none): + echo "what" +else: + echo "nope" diff --git a/tests/namedparams/tnamedparams.nim b/tests/namedparams/tnamedparams.nim index 9a8bd0c2e..8799e8a15 100644 --- a/tests/namedparams/tnamedparams.nim +++ b/tests/namedparams/tnamedparams.nim @@ -1,7 +1,7 @@ discard """ file: "tnamedparams.nim" line: 8 - errormsg: "type mismatch: got (input: string, filename: string, line: int literal(1), col: int literal(23))" + errormsg: "type mismatch: got <input: string, filename: string, line: int literal(1), col: int literal(23)>" """ import pegs diff --git a/tests/namedparams/tnamedparams3.nim b/tests/namedparams/tnamedparams3.nim index d9c79bf98..e736c338c 100644 --- a/tests/namedparams/tnamedparams3.nim +++ b/tests/namedparams/tnamedparams3.nim @@ -1,5 +1,5 @@ discard """ - errormsg: "type mismatch: got (int literal(5), b: bool)" + errormsg: "type mismatch: got <int literal(5), b: bool>" line: 10 """ diff --git a/tests/newconfig/tfoo.nims b/tests/newconfig/tfoo.nims index 8d0ed2c42..3be42c38a 100644 --- a/tests/newconfig/tfoo.nims +++ b/tests/newconfig/tfoo.nims @@ -23,4 +23,58 @@ task default, "default target": setCommand "c" # bug #6327 -discard existsEnv("dummy") +doAssert(existsEnv("dummy") == false) + +# issue #7283 +putEnv("dummy", "myval") +doAssert(existsEnv("dummy") == true) +doAssert(getEnv("dummy") == "myval") + +# issue #7393 +let wd = getCurrentDir() +cd("..") +assert wd != getCurrentDir() +cd(wd) +assert wd == getCurrentDir() + +assert findExe("nim") != "" + +# general tests +mode = ScriptMode.Verbose + +assert getCommand() == "c" +setCommand("cpp") +assert getCommand() == "cpp" +setCommand("c") + +assert cmpic("HeLLO", "hello") == 0 + +assert fileExists("tests/newconfig/tfoo.nims") == true +assert dirExists("tests") == true + +assert existsFile("tests/newconfig/tfoo.nims") == true +assert existsDir("tests") == true + +discard selfExe() + +when defined(windows): + assert toExe("nim") == "nim.exe" + assert toDll("nim") == "nim.dll" +else: + assert toExe("nim") == "nim" + assert toDll("nim") == "libnim.so" + +rmDir("tempXYZ") +assert dirExists("tempXYZ") == false +mkDir("tempXYZ") +assert dirExists("tempXYZ") == true +assert fileExists("tempXYZ/koch.nim") == false +cpFile("koch.nim", "tempXYZ/koch.nim") +assert fileExists("tempXYZ/koch.nim") == true +cpDir("nimsuggest", "tempXYZ/.") +assert dirExists("tempXYZ/tests") == true +assert fileExists("tempXYZ/nimsuggest.nim") == true +rmFile("tempXYZ/koch.nim") +assert fileExists("tempXYZ/koch.nim") == false +rmDir("tempXYZ") +assert dirExists("tempXYZ") == false diff --git a/tests/notnil/tmust_compile.nim b/tests/notnil/tmust_compile.nim index 10da154f0..a32c6c7ec 100644 --- a/tests/notnil/tmust_compile.nim +++ b/tests/notnil/tmust_compile.nim @@ -3,6 +3,7 @@ discard """ """ # bug #6682 +{.experimental: "notnil".} type Fields = enum diff --git a/tests/notnil/tnotnil.nim b/tests/notnil/tnotnil.nim index f65634ed6..e392b155c 100644 --- a/tests/notnil/tnotnil.nim +++ b/tests/notnil/tnotnil.nim @@ -2,7 +2,7 @@ discard """ line: 22 errormsg: "type mismatch" """ - +{.experimental: "notnil".} type PObj = ref TObj not nil TObj = object @@ -15,8 +15,8 @@ type proc p(x: string not nil): int = result = 45 -proc q(x: MyString) = nil -proc q2(x: string) = nil +proc q(x: MyString) = discard +proc q2(x: string) = discard q2(nil) q(nil) diff --git a/tests/notnil/tnotnil1.nim b/tests/notnil/tnotnil1.nim index 73472752c..7f9d02295 100644 --- a/tests/notnil/tnotnil1.nim +++ b/tests/notnil/tnotnil1.nim @@ -4,7 +4,7 @@ discard """ """ import strutils - +{.experimental: "notnil".} type TObj = object @@ -18,13 +18,13 @@ proc q(s: superstring) = echo s proc p2() = - var a: string = "I am not nil" + var a: string = "I am not nil" q(a) # but this should and does not p2() proc q(x: pointer not nil) = - nil + discard proc p() = var x: pointer diff --git a/tests/notnil/tnotnil2.nim b/tests/notnil/tnotnil2.nim index bd6b8b675..6cd08de73 100644 --- a/tests/notnil/tnotnil2.nim +++ b/tests/notnil/tnotnil2.nim @@ -4,14 +4,14 @@ discard """ """ import strutils - +{.experimental: "notnil".} type TObj = object x, y: int proc q(x: pointer not nil) = - nil + discard proc p() = var x: pointer diff --git a/tests/notnil/tnotnil3.nim b/tests/notnil/tnotnil3.nim index b7c7a811d..31a4efef7 100644 --- a/tests/notnil/tnotnil3.nim +++ b/tests/notnil/tnotnil3.nim @@ -5,7 +5,7 @@ discard """ # bug #584 # Testprogram for 'not nil' check - +{.experimental: "notnil".} const testWithResult = true type diff --git a/tests/notnil/tnotnil4.nim b/tests/notnil/tnotnil4.nim index 2fa888357..4fd169827 100644 --- a/tests/notnil/tnotnil4.nim +++ b/tests/notnil/tnotnil4.nim @@ -2,6 +2,8 @@ discard "" type TObj = ref object +{.experimental: "notnil".} + proc check(a: TObj not nil) = echo repr(a) diff --git a/tests/notnil/tnotnil_in_generic.nim b/tests/notnil/tnotnil_in_generic.nim index 357ab2c7c..89d20f182 100644 --- a/tests/notnil/tnotnil_in_generic.nim +++ b/tests/notnil/tnotnil_in_generic.nim @@ -3,6 +3,7 @@ discard """ """ # bug #2216 +{.experimental: "notnil".} type A[T] = ref object diff --git a/tests/notnil/tnotnil_in_objconstr.nim b/tests/notnil/tnotnil_in_objconstr.nim index 7dce98c29..d33709906 100644 --- a/tests/notnil/tnotnil_in_objconstr.nim +++ b/tests/notnil/tnotnil_in_objconstr.nim @@ -2,7 +2,7 @@ discard """ errormsg: "fields not initialized: bar" line: "13" """ - +{.experimental: "notnil".} # bug #2355 type Foo = object diff --git a/tests/objects/tinherentedvalues.nim b/tests/objects/tinherentedvalues.nim index c96a0fd6d..ad7b5f326 100644 --- a/tests/objects/tinherentedvalues.nim +++ b/tests/objects/tinherentedvalues.nim @@ -1,9 +1,7 @@ discard """ - output: '''tbObj of TC false -false + output: '''tbObj of TC true true -5 -false''' +5''' """ # bug #1053 @@ -20,10 +18,10 @@ type proc test(p: TA) = #echo "p of TB ", p of TB if p of TB: - var tbObj = TB(p) + #var tbObj = TB(p) # tbObj is actually no longer compatible with TC: - echo "tbObj of TC ", tbObj of TC + echo "tbObj of TC ", p of TC var v = TC() v.a = 1 @@ -48,8 +46,8 @@ proc isMyObject(obj: TObject) = asd.x = 5 -var asdCopy = TObject(asd) -echo asdCopy of MyObject +#var asdCopy = TObject(asd) +#echo asdCopy of MyObject isMyObject(asd) -isMyObject(asdCopy) +#isMyObject(asdCopy) diff --git a/tests/objects/tobj_asgn_dont_slice.nim b/tests/objects/tobj_asgn_dont_slice.nim new file mode 100644 index 000000000..866b5aecc --- /dev/null +++ b/tests/objects/tobj_asgn_dont_slice.nim @@ -0,0 +1,24 @@ +discard """ + outputsub: '''ObjectAssignmentError''' + exitcode: "1" +""" + +# bug #7637 +type + Fruit = object of RootObj + name*: string + Apple = object of Fruit + Pear = object of Fruit + +method eat(f: Fruit) {.base.} = + raise newException(Exception, "PURE VIRTUAL CALL") + +method eat(f: Apple) = + echo "fruity" + +method eat(f: Pear) = + echo "juicy" + +let basket = [Apple(name:"a"), Pear(name:"b")] + +eat(basket[0]) diff --git a/tests/objects/tobjconstr.nim b/tests/objects/tobjconstr.nim index b7da176aa..7238d10c7 100644 --- a/tests/objects/tobjconstr.nim +++ b/tests/objects/tobjconstr.nim @@ -9,13 +9,14 @@ discard """ (k: kindA, a: (x: "abc", z: [1, 8, 3]), method: ()) (k: kindA, a: (x: "abc", z: [1, 9, 3]), method: ()) (k: kindA, a: (x: "abc", z: [1, 10, 3]), method: ()) -(x: 123) -(x: 123) +(y: 0, x: 123) +(y: 678, x: 123) (z: 89, y: 0, x: 128) (y: 678, x: 123) (y: 678, x: 123) (y: 0, x: 123) -(y: 678, x: 123)''' +(y: 678, x: 123) +(y: 123, x: 678)''' """ type @@ -32,7 +33,6 @@ type `method`: TEmpty # bug #1791 proc `$`[T](s: seq[T]): string = - # XXX why is that not in the stdlib? result = "[" for i, x in s: if i > 0: result.add(", ") @@ -58,7 +58,7 @@ type # inherited fields are ignored, so no fields are set when true: var - o: A + o: B o = B(x: 123) echo o o = B(y: 678, x: 123) @@ -75,3 +75,7 @@ when true: echo b # (y: 0, x: 123) b=B(y: 678, x: 123) echo b # (y: 678, x: 123) + b=B(y: b.x, x: b.y) + echo b # (y: 123, x: 678) + +GC_fullCollect() diff --git a/tests/objects/tobjconstr2.nim b/tests/objects/tobjconstr2.nim index f6805190b..6253edab0 100644 --- a/tests/objects/tobjconstr2.nim +++ b/tests/objects/tobjconstr2.nim @@ -1,3 +1,8 @@ +discard """ + output: '''42 +Foo''' +""" + type TFoo{.exportc.} = object x:int @@ -48,3 +53,5 @@ type NamedGraphic = object of Graphic2 var ngr = NamedGraphic(kind: Koo, radius: 6.9, name: "Foo") echo ngr.name + +GC_fullCollect() diff --git a/tests/objvariant/tadrdisc.nim b/tests/objvariant/tadrdisc.nim index 1afe7d04f..258fb42f3 100644 --- a/tests/objvariant/tadrdisc.nim +++ b/tests/objvariant/tadrdisc.nim @@ -1,7 +1,7 @@ discard """ file: "tadrdisc.nim" line: 20 - errormsg: "type mismatch: got (TKind)" + errormsg: "type mismatch: got <TKind>" """ # Test that the address of a dicriminants cannot be taken diff --git a/tests/objvariant/tcheckedfield1.nim b/tests/objvariant/tcheckedfield1.nim index 56d784a2b..a7f232c5b 100644 --- a/tests/objvariant/tcheckedfield1.nim +++ b/tests/objvariant/tcheckedfield1.nim @@ -6,7 +6,7 @@ discard """ import strutils {.warning[ProveField]: on.} - +{.experimental: "notnil".} type TNodeKind = enum nkBinary, nkTernary, nkStr diff --git a/tests/objvariant/temptycaseobj.nim b/tests/objvariant/temptycaseobj.nim index 5c012746e..53171e054 100644 --- a/tests/objvariant/temptycaseobj.nim +++ b/tests/objvariant/temptycaseobj.nim @@ -1,6 +1,6 @@ discard """ line: 11 - errormsg: "identifier expected, but found 'keyword of'" + errormsg: "identifier expected, but got 'keyword of'" """ type diff --git a/tests/objvariant/tvariantstack.nim b/tests/objvariant/tvariantstack.nim index d81f6e001..0cdde5a20 100644 --- a/tests/objvariant/tvariantstack.nim +++ b/tests/objvariant/tvariantstack.nim @@ -49,4 +49,34 @@ var t = stack.pop() echo "came here" +# another regression: +type + LexerToken* = enum + ltYamlDirective, ltYamlVersion, ltTagDirective, ltTagShorthand, + ltTagUri, ltUnknownDirective, ltUnknownDirectiveParams, ltEmptyLine, + ltDirectivesEnd, ltDocumentEnd, ltStreamEnd, ltIndentation, ltQuotedScalar, + ltScalarPart, ltBlockScalarHeader, ltBlockScalar, ltSeqItemInd, ltMapKeyInd, + ltMapValInd, ltBraceOpen, ltBraceClose, ltBracketOpen, ltBracketClose, + ltComma, ltLiteralTag, ltTagHandle, ltAnchor, ltAlias + +const tokensWithValue = + {ltScalarPart, ltQuotedScalar, ltYamlVersion, ltTagShorthand, ltTagUri, + ltUnknownDirective, ltUnknownDirectiveParams, ltLiteralTag, ltAnchor, + ltAlias, ltBlockScalar} + +type + TokenWithValue = object + case kind: LexerToken + of tokensWithValue: + value: string + of ltIndentation: + indentation: int + of ltTagHandle: + handle, suffix: string + else: discard + +proc sp(v: string): TokenWithValue = + # test.nim(27, 17) Error: a case selecting discriminator 'kind' with value 'ltScalarPart' appears in the object construction, but the field(s) 'value' are in conflict with this value. + TokenWithValue(kind: ltScalarPart, value: v) +let a = sp("test") diff --git a/tests/osproc/tclose.nim b/tests/osproc/tclose.nim new file mode 100644 index 000000000..d466b466a --- /dev/null +++ b/tests/osproc/tclose.nim @@ -0,0 +1,24 @@ +discard """ + exitcode: 0 +""" + +when defined(linux): + import osproc, os + + proc countFds(): int = + result = 0 + for i in walkDir("/proc/self/fd"): + result += 1 + + let initCount = countFds() + + let p = osproc.startProcess("echo", options={poUsePath}) + assert countFds() == initCount + 3 + p.close + assert countFds() == initCount + + let p1 = osproc.startProcess("echo", options={poUsePath}) + discard p1.inputStream + assert countFds() == initCount + 3 + p.close + assert countFds() == initCount diff --git a/tests/osproc/tstdin.nim b/tests/osproc/tstdin.nim index d94c34192..9b49ed786 100644 --- a/tests/osproc/tstdin.nim +++ b/tests/osproc/tstdin.nim @@ -11,9 +11,8 @@ doAssert fileExists(getCurrentDir() / "tests" / "osproc" / filename) var p = startProcess(filename, getCurrentDir() / "tests" / "osproc") p.inputStream.write("5\n") p.inputStream.flush() -while true: - let line = p.outputStream.readLine() - if line != "": - echo line - else: - break + +var line = "" + +while p.outputStream.readLine(line.TaintedString): + echo line diff --git a/tests/overload/tissue966.nim b/tests/overload/tissue966.nim index 2911348cf..d0a723875 100644 --- a/tests/overload/tissue966.nim +++ b/tests/overload/tissue966.nim @@ -1,11 +1,11 @@ discard """ - errormsg: "type mismatch: got (PTest)" + errormsg: "type mismatch: got <PTest>" """ type PTest = ref object -proc test(x: PTest, y: int) = nil +proc test(x: PTest, y: int) = discard var buf: PTest buf.test() diff --git a/tests/overload/toverprc.nim b/tests/overload/toverprc.nim index 112eae096..9be2203f6 100644 --- a/tests/overload/toverprc.nim +++ b/tests/overload/toverprc.nim @@ -11,7 +11,7 @@ proc parseInt(x: float): int {.noSideEffect.} = discard proc parseInt(x: bool): int {.noSideEffect.} = discard proc parseInt(x: float32): int {.noSideEffect.} = discard proc parseInt(x: int8): int {.noSideEffect.} = discard -proc parseInt(x: TFile): int {.noSideEffect.} = discard +proc parseInt(x: File): int {.noSideEffect.} = discard proc parseInt(x: char): int {.noSideEffect.} = discard proc parseInt(x: int16): int {.noSideEffect.} = discard diff --git a/tests/overload/tparam_forwarding.nim b/tests/overload/tparam_forwarding.nim index c1b276bfc..b0eea42c7 100644 --- a/tests/overload/tparam_forwarding.nim +++ b/tests/overload/tparam_forwarding.nim @@ -6,6 +6,10 @@ output: '''baz a b c +x: 1, y: test 1 +x: 2, y: test 2 +x: 10, y: test 3 +x: 4, y: test 4 ''' """ @@ -35,3 +39,15 @@ templateForwarding fooVarargs, "test".len > 3, Foo(x: 10), Foo(x: 100), Foo(x: 1 procForwarding "a", "b", "c" +proc hasKeywordArgs(x = 10, y = "y") = + echo "x: ", x, ", y: ", y + +proc hasRegularArgs(x: int, y: string) = + echo "x: ", x, ", y: ", y + +templateForwarding(hasRegularArgs, true, 1, "test 1") +templateForwarding hasKeywordArgs, true, 2, "test 2" + +templateForwarding(hasKeywordArgs, true, y = "test 3") +templateForwarding hasKeywordArgs, true, y = "test 4", x = 4 + diff --git a/tests/overload/tsystemcmp.nim b/tests/overload/tsystemcmp.nim index 68cbf9fa7..aa761b759 100644 --- a/tests/overload/tsystemcmp.nim +++ b/tests/overload/tsystemcmp.nim @@ -1,12 +1,14 @@ discard """ cmd: r"nim c --hints:on $options --threads:on $file" + output: '''@["", "a", "ha", "hi", "ho", "huu"]''' """ import algorithm # bug #1657 -var modules = @["hi", "ho", "ha", "huu"] +var modules = @["hi", "ho", "", "a", "ha", "huu"] sort(modules, system.cmp) +echo modules type MyType = object diff --git a/tests/parallel/tparfind.nim b/tests/parallel/tparfind.nim index 9de5012f5..4b3610c67 100644 --- a/tests/parallel/tparfind.nim +++ b/tests/parallel/tparfind.nim @@ -4,7 +4,7 @@ discard """ import threadpool, sequtils -{.experimental.} +{.experimental: "parallel".} proc linearFind(a: openArray[int]; x, offset: int): int = for i, y in a: diff --git a/tests/parallel/twaitany.nim b/tests/parallel/twaitany.nim new file mode 100644 index 000000000..69136a3b6 --- /dev/null +++ b/tests/parallel/twaitany.nim @@ -0,0 +1,35 @@ +discard """ + output: '''true''' +""" + +# bug #7638 +import threadpool, os, strformat + +proc timer(d: int): int = + #echo fmt"sleeping {d}" + sleep(d) + #echo fmt"done {d}" + return d + +var durations = [1000, 2000, 3000, 4000, 5000] +var tasks: seq[FlowVarBase] = @[] +var results: seq[int] = @[] + +for i in 0 .. durations.high: + tasks.add spawn timer(durations[i]) + +var index = awaitAny(tasks) +while index != -1: + results.add ^cast[FlowVar[int]](tasks[index]) + tasks.del(index) + #echo repr results + index = awaitAny(tasks) + +doAssert results.len == 5 +doAssert 1000 in results +doAssert 2000 in results +doAssert 3000 in results +doAssert 4000 in results +doAssert 5000 in results +sync() +echo "true" diff --git a/tests/parser/tbraces.nim b/tests/parser/tbraces.nim deleted file mode 100644 index 86c854546..000000000 --- a/tests/parser/tbraces.nim +++ /dev/null @@ -1,432 +0,0 @@ -#? braces - -# -# -# Nim's Runtime Library -# (c) Copyright 2015 Andreas Rumpf -# -# See the file "copying.txt", included in this -# distribution, for details about the copyright. -# - -## This module implements some common generic algorithms. - -type - SortOrder* = enum { ## sort order - Descending, Ascending - } - - -type( - DummyAlias = int - OtherAlias = distinct char - - SomeObject = object of RootObj { ## declaration here - fieldA, fieldB: int - case order: SortOrder { - of Descending {a: string} - of Ascending {b: seq[char]} - } - } - - MyConcept = concept x { - x is int - } -) - -{.deprecated: [TSortOrder: SortOrder].} - - -proc `*`*(x: int, order: SortOrder): int @inline { - ## flips `x` if ``order == Descending``; - ## if ``order == Ascending`` then `x` is returned. - ## `x` is supposed to be the result of a comparator, ie ``< 0`` for - ## *less than*, ``== 0`` for *equal*, ``> 0`` for *greater than*. - var y = order.ord - 1 - result = (x xor y) - y -} - -proc fill*[T](a: var openArray[T], first, last: Natural, value: T) { - ## fills the array ``a[first..last]`` with `value`. - var x = first - while x <= last { - a[x] = value - inc(x) - } -} - -proc fill*[T](a: var openArray[T], value: T) { - ## fills the array `a` with `value`. - fill(a, 0, a.high, value) -} - -proc reverse*[T](a: var openArray[T], first, last: Natural) { - ## reverses the array ``a[first..last]``. - var x = first - var y = last - while x < y { - swap(a[x], a[y]) - dec(y) - inc(x) - } -} - -proc reverse*[T](a: var openArray[T]) { - ## reverses the array `a`. - reverse(a, 0, a.high) -} - -proc reversed*[T](a: openArray[T], first: Natural, last: int): seq[T] { - ## returns the reverse of the array `a[first..last]`. - assert last >= first-1 - var i = last - first - var x = first.int - result = newSeq[T](i + 1) - while i >= 0 { - result[i] = a[x] - dec(i) - inc(x) - } -} - -proc reversed*[T](a: openArray[T]): seq[T] { - ## returns the reverse of the array `a`. - reversed(a, 0, a.high) -} - -proc binarySearch*[T](a: openArray[T], key: T): int { - ## binary search for `key` in `a`. Returns -1 if not found. - var b = len(a) - while result < b { - var mid = (result + b) div 2 - if a[mid] < key { result = mid + 1 } else { b = mid } - } - if result >= len(a) or a[result] != key { result = -1 } -} - -proc smartBinarySearch*[T](a: openArray[T], key: T): int { - ## ``a.len`` must be a power of 2 for this to work. - var step = a.len div 2 - while step > 0 { - if a[result or step] <= key { result = result or step } - step = step shr 1 - } - if a[result] != key { result = -1 } -} - -const ( - onlySafeCode = true -) - -proc lowerBound*[T](a: openArray[T], key: T, cmp: proc(x,y: T): int @closure): int { - ## same as binarySearch except that if key is not in `a` then this - ## returns the location where `key` would be if it were. In other - ## words if you have a sorted sequence and you call - ## insert(thing, elm, lowerBound(thing, elm)) - ## the sequence will still be sorted. - ## - ## `cmp` is the comparator function to use, the expected return values are - ## the same as that of system.cmp. - ## - ## example:: - ## - ## var arr = @[1,2,3,5,6,7,8,9] - ## arr.insert(4, arr.lowerBound(4)) - ## # after running the above arr is `[1,2,3,4,5,6,7,8,9]` - result = a.low - var count = a.high - a.low + 1 - var step, pos: int - while count != 0 { - step = count div 2 - pos = result + step - if cmp(a[pos], key) < 0 { - result = pos + 1 - count -= step + 1 - } else { - count = step - } - } -} - -proc lowerBound*[T](a: openArray[T], key: T): int { lowerBound(a, key, cmp[T]) } -proc merge[T](a, b: var openArray[T], lo, m, hi: int, - cmp: proc (x, y: T): int @closure, order: SortOrder) { - template `<-` (a, b) { - when false { - a = b - } elif onlySafeCode { - shallowCopy(a, b) - } else { - copyMem(addr(a), addr(b), sizeof(T)) - } - } - # optimization: If max(left) <= min(right) there is nothing to do! - # 1 2 3 4 ## 5 6 7 8 - # -> O(n) for sorted arrays. - # On random data this safes up to 40% of merge calls - if cmp(a[m], a[m+1]) * order <= 0 { return } - var j = lo - # copy a[j..m] into b: - assert j <= m - when onlySafeCode { - var bb = 0 - while j <= m { - b[bb] <- a[j] - inc(bb) - inc(j) - } - } else { - copyMem(addr(b[0]), addr(a[j]), sizeof(T)*(m-j+1)) - j = m+1 - } - var i = 0 - var k = lo - # copy proper element back: - while k < j and j <= hi { - if cmp(b[i], a[j]) * order <= 0 { - a[k] <- b[i] - inc(i) - } else { - a[k] <- a[j] - inc(j) - } - inc(k) - } - # copy rest of b: - when onlySafeCode { - while k < j { - a[k] <- b[i] - inc(k) - inc(i) - } - } else { - if k < j { copyMem(addr(a[k]), addr(b[i]), sizeof(T)*(j-k)) } - } -} - -proc sort*[T](a: var openArray[T], - cmp: proc (x, y: T): int @closure, - order = SortOrder.Ascending) { - ## Default Nim sort (an implementation of merge sort). The sorting - ## is guaranteed to be stable and the worst case is guaranteed to - ## be O(n log n). - ## The current implementation uses an iterative - ## mergesort to achieve this. It uses a temporary sequence of - ## length ``a.len div 2``. Currently Nim does not support a - ## sensible default argument for ``cmp``, so you have to provide one - ## of your own. However, the ``system.cmp`` procs can be used: - ## - ## .. code-block:: nim - ## - ## sort(myIntArray, system.cmp[int]) - ## - ## # do not use cmp[string] here as we want to use the specialized - ## # overload: - ## sort(myStrArray, system.cmp) - ## - ## You can inline adhoc comparison procs with the `do notation - ## <manual.html#procedures-do-notation>`_. Example: - ## - ## .. code-block:: nim - ## - ## people.sort do (x, y: Person) -> int: - ## result = cmp(x.surname, y.surname) - ## if result == 0: - ## result = cmp(x.name, y.name) - var n = a.len - var b: seq[T] - newSeq(b, n div 2) - var s = 1 - while s < n { - var m = n-1-s - while m >= 0 { - merge(a, b, max(m-s+1, 0), m, m+s, cmp, order) - dec(m, s*2) - } - s = s*2 - } -} - -proc sorted*[T](a: openArray[T], cmp: proc(x, y: T): int {.closure.}, - order = SortOrder.Ascending): seq[T] { - ## returns `a` sorted by `cmp` in the specified `order`. - result = newSeq[T](a.len) - for i in 0 .. a.high { result[i] = a[i] } - sort(result, cmp, order) -} - -template sortedByIt*(seq1, op: untyped): untyped { - ## Convenience template around the ``sorted`` proc to reduce typing. - ## - ## The template injects the ``it`` variable which you can use directly in an - ## expression. Example: - ## - ## .. code-block:: nim - ## - ## type Person = tuple[name: string, age: int] - ## var - ## p1: Person = (name: "p1", age: 60) - ## p2: Person = (name: "p2", age: 20) - ## p3: Person = (name: "p3", age: 30) - ## p4: Person = (name: "p4", age: 30) - ## people = @[p1,p2,p4,p3] - ## - ## echo people.sortedByIt(it.name) - ## - ## Because the underlying ``cmp()`` is defined for tuples you can do - ## a nested sort like in the following example: - ## - ## .. code-block:: nim - ## - ## echo people.sortedByIt((it.age, it.name)) - ## - var result = sorted(seq1, proc(x, y: type[seq1[0]]): int { - var it {.inject.} = x - let a = op - it = y - let b = op - result = cmp(a, b) - }) - result -} - -proc isSorted*[T](a: openarray[T], - cmp: proc(x, y: T): int {.closure.}, - order = SortOrder.Ascending): bool { - ## Checks to see whether `a` is already sorted in `order` - ## using `cmp` for the comparison. Parameters identical - ## to `sort` - result = true - for i in 0..<len(a)-1 { - case cmp(a[i],a[i+1]) * order > 0 { - of true { return false } - of false {} - } - } -} - -proc product*[T](x: openArray[seq[T]]): seq[seq[T]] { - ## produces the Cartesian product of the array. Warning: complexity - ## may explode. - result = newSeq[seq[T]]() - if x.len == 0 { return } - if x.len == 1 { - result = @x - return - } - var ( - indexes = newSeq[int](x.len) - initial = newSeq[int](x.len) - index = 0 - ) - var next = newSeq[T]() - next.setLen(x.len) - for i in 0..(x.len-1) { - if len(x[i]) == 0 { return } - initial[i] = len(x[i])-1 - } - indexes = initial - while true { - while indexes[index] == -1 { - indexes[index] = initial[index] - index += 1 - if index == x.len { return } - indexes[index] -= 1 - } - for ni, i in indexes { - next[ni] = x[ni][i] - } - var res: seq[T] - shallowCopy(res, next) - result.add(res) - index = 0 - indexes[index] -= 1 - } -} - -proc nextPermutation*[T](x: var openarray[T]): bool {.discardable.} { - ## Calculates the next lexicographic permutation, directly modifying ``x``. - ## The result is whether a permutation happened, otherwise we have reached - ## the last-ordered permutation. - ## - ## .. code-block:: nim - ## - ## var v = @[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] - ## v.nextPermutation() - ## echo v # @[0, 1, 2, 3, 4, 5, 6, 7, 9, 8] - if x.len < 2 { - return false } - - var i = x.high - while i > 0 and x[i-1] >= x[i] { dec i } - if i == 0 { return false } - - var j = x.high - while j >= i and x[j] <= x[i-1] { dec j } - - swap x[j], x[i-1] - x.reverse(i, x.high) - - result = true -} - -proc prevPermutation*[T](x: var openarray[T]): bool @discardable { - ## Calculates the previous lexicographic permutation, directly modifying - ## ``x``. The result is whether a permutation happened, otherwise we have - ## reached the first-ordered permutation. - ## - ## .. code-block:: nim - ## - ## var v = @[0, 1, 2, 3, 4, 5, 6, 7, 9, 8] - ## v.prevPermutation() - ## echo v # @[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] - if x.len < 2 { return false } - - var i = x.high - while i > 0 and x[i-1] <= x[i] { - dec i - } - if i == 0 { return false } - - x.reverse(i, x.high) - - var j = x.high - while j >= i and x[j-1] < x[i-1] { - dec j - } - swap x[i-1], x[j] - - result = true -} - -when isMainModule { - # Tests for lowerBound - var arr = @[1,2,3,5,6,7,8,9] - assert arr.lowerBound(0) == 0 - assert arr.lowerBound(4) == 3 - assert arr.lowerBound(5) == 3 - assert arr.lowerBound(10) == 8 - arr = @[1,5,10] - try { - assert arr.lowerBound(4) == 1 - assert arr.lowerBound(5) == 1 - assert arr.lowerBound(6) == 2 - } except ValueError {} - # Tests for isSorted - var srt1 = [1,2,3,4,4,4,4,5] - var srt2 = ["iello","hello"] - var srt3 = [1.0,1.0,1.0] - var srt4: seq[int] = @[] - assert srt1.isSorted(cmp) == true - assert srt2.isSorted(cmp) == false - assert srt3.isSorted(cmp) == true - var srtseq = newSeq[int]() - assert srtseq.isSorted(cmp) == true - # Tests for reversed - var arr1 = @[0,1,2,3,4] - assert arr1.reversed() == @[4,3,2,1,0] - for i in 0 .. high(arr1) { - assert arr1.reversed(0, i) == arr1.reversed()[high(arr1) - i .. high(arr1)] - assert arr1.reversed(i, high(arr1)) == arr1.reversed()[0 .. high(arr1) - i] - } -} diff --git a/tests/parser/tcommand_as_expr.nim b/tests/parser/tcommand_as_expr.nim index a244c8767..b25ec4bd8 100644 --- a/tests/parser/tcommand_as_expr.nim +++ b/tests/parser/tcommand_as_expr.nim @@ -2,7 +2,10 @@ discard """ output: '''140 5-120-120 359 -77''' +77 +-4 +-1 +-1''' """ #import math import sequtils @@ -25,3 +28,11 @@ let a = [2,4,8].map do (d:int) -> int: d + 1 echo a[0], a[1], a[2] echo(foo 8, foo 8) + +# bug #7582 +proc f(x: int): int = x + +echo f -4 + +echo int -1 # doesn't compile +echo int `-` 1 # compiles diff --git a/tests/parser/tinvcolonlocation1.nim b/tests/parser/tinvcolonlocation1.nim index cacde48bd..2fddab2f8 100644 --- a/tests/parser/tinvcolonlocation1.nim +++ b/tests/parser/tinvcolonlocation1.nim @@ -1,8 +1,8 @@ discard """ file: "tinvcolonlocation1.nim" line: 8 - column: 3 - errormsg: "':' expected" + column: 7 + errormsg: "expected: ':', but got: 'echo'" """ try #<- missing ':' echo "try" diff --git a/tests/parser/tinvcolonlocation2.nim b/tests/parser/tinvcolonlocation2.nim index 2b6a92b9d..4251598b9 100644 --- a/tests/parser/tinvcolonlocation2.nim +++ b/tests/parser/tinvcolonlocation2.nim @@ -1,8 +1,8 @@ discard """ file: "tinvcolonlocation2.nim" line: 11 - column: 1 - errormsg: "':' expected" + column: 8 + errormsg: "expected: ':', but got: 'keyword finally'" """ try: echo "try" diff --git a/tests/parser/tinvcolonlocation3.nim b/tests/parser/tinvcolonlocation3.nim index 2b30b1dbe..a8db658eb 100644 --- a/tests/parser/tinvcolonlocation3.nim +++ b/tests/parser/tinvcolonlocation3.nim @@ -1,8 +1,8 @@ discard """ file: "tinvcolonlocation3.nim" line: 12 - column: 3 - errormsg: "':' expected" + column: 7 + errormsg: "expected: ':', but got: 'echo'" """ try: echo "try" diff --git a/tests/parser/tpostexprblocks.nim b/tests/parser/tpostexprblocks.nim index 3b9c956c2..c27bbf321 100644 --- a/tests/parser/tpostexprblocks.nim +++ b/tests/parser/tpostexprblocks.nim @@ -1,82 +1,82 @@ discard """ nimout: ''' StmtList - Ident ident"foo010" + Ident "foo010" Call - Ident ident"foo020" + Ident "foo020" Call - Ident ident"foo030" - Ident ident"x" + Ident "foo030" + Ident "x" Command - Ident ident"foo040" - Ident ident"x" + Ident "foo040" + Ident "x" Call - Ident ident"foo050" + Ident "foo050" StmtList DiscardStmt Empty Call - Ident ident"foo060" + Ident "foo060" StmtList DiscardStmt Empty Call - Ident ident"foo070" - StrLit test + Ident "foo070" + StrLit "test" StmtList DiscardStmt Empty Call - Ident ident"foo080" - StrLit test + Ident "foo080" + StrLit "test" StmtList DiscardStmt Empty Command - Ident ident"foo090" - StrLit test + Ident "foo090" + StrLit "test" StmtList DiscardStmt Empty Command - Ident ident"foo100" + Ident "foo100" Call - StrLit test + StrLit "test" StmtList DiscardStmt Empty Command - Ident ident"foo101" + Ident "foo101" Call IntLit 10 StmtList DiscardStmt Empty Command - Ident ident"foo110" + Ident "foo110" IntLit 1 Par Infix - Ident ident"+" + Ident "+" IntLit 2 IntLit 3 StmtList DiscardStmt Empty Command - Ident ident"foo120" + Ident "foo120" IntLit 1 Call Par Infix - Ident ident"+" + Ident "+" IntLit 2 IntLit 3 StmtList DiscardStmt Empty Call - Ident ident"foo130" + Ident "foo130" Do Empty Empty @@ -84,7 +84,7 @@ StmtList FormalParams Empty IdentDefs - Ident ident"x" + Ident "x" Empty Empty Empty @@ -93,7 +93,7 @@ StmtList DiscardStmt Empty Call - Ident ident"foo140" + Ident "foo140" Do Empty Empty @@ -101,8 +101,8 @@ StmtList FormalParams Empty IdentDefs - Ident ident"x" - Ident ident"int" + Ident "x" + Ident "int" Empty Empty Empty @@ -110,16 +110,16 @@ StmtList DiscardStmt Empty Call - Ident ident"foo150" + Ident "foo150" Do Empty Empty Empty FormalParams - Ident ident"int" + Ident "int" IdentDefs - Ident ident"x" - Ident ident"int" + Ident "x" + Ident "int" Empty Empty Empty @@ -127,9 +127,9 @@ StmtList DiscardStmt Empty Command - Ident ident"foo160" + Ident "foo160" Call - Ident ident"x" + Ident "x" Do Empty Empty @@ -137,7 +137,7 @@ StmtList FormalParams Empty IdentDefs - Ident ident"y" + Ident "y" Empty Empty Empty @@ -146,7 +146,7 @@ StmtList DiscardStmt Empty Call - Ident ident"foo170" + Ident "foo170" StmtList DiscardStmt Empty @@ -155,7 +155,7 @@ StmtList DiscardStmt Empty Call - Ident ident"foo180" + Ident "foo180" StmtList DiscardStmt Empty @@ -167,9 +167,9 @@ StmtList DiscardStmt Empty Command - Ident ident"foo190" + Ident "foo190" Call - Ident ident"x" + Ident "x" Do Empty Empty @@ -177,7 +177,7 @@ StmtList FormalParams Empty IdentDefs - Ident ident"y" + Ident "y" Empty Empty Empty @@ -190,9 +190,9 @@ StmtList Empty Empty FormalParams - Ident ident"int" + Ident "int" IdentDefs - Ident ident"z" + Ident "z" Empty Empty Empty @@ -205,10 +205,10 @@ StmtList Empty Empty FormalParams - Ident ident"int" + Ident "int" IdentDefs - Ident ident"w" - Ident ident"int" + Ident "w" + Ident "int" Empty Empty Empty @@ -223,10 +223,10 @@ StmtList DiscardStmt Empty Call - Ident ident"foo200" - Ident ident"x" + Ident "foo200" + Ident "x" Call - Ident ident"bar" + Ident "bar" StmtList DiscardStmt Empty @@ -236,53 +236,53 @@ StmtList Empty VarSection IdentDefs - Ident ident"a" + Ident "a" Empty - Ident ident"foo210" + Ident "foo210" VarSection IdentDefs - Ident ident"a" + Ident "a" Empty Call - Ident ident"foo220" + Ident "foo220" VarSection IdentDefs - Ident ident"a" + Ident "a" Empty Call - Ident ident"foo230" - Ident ident"x" + Ident "foo230" + Ident "x" VarSection IdentDefs - Ident ident"a" + Ident "a" Empty Command - Ident ident"foo240" - Ident ident"x" + Ident "foo240" + Ident "x" VarSection IdentDefs - Ident ident"a" + Ident "a" Empty Call - Ident ident"foo250" + Ident "foo250" StmtList DiscardStmt Empty VarSection IdentDefs - Ident ident"a" + Ident "a" Empty Call - Ident ident"foo260" + Ident "foo260" StmtList DiscardStmt Empty VarSection IdentDefs - Ident ident"a" + Ident "a" Empty Call - Ident ident"foo270" + Ident "foo270" StmtList DiscardStmt Empty @@ -292,12 +292,12 @@ StmtList Empty VarSection IdentDefs - Ident ident"a" + Ident "a" Empty Command - Ident ident"foo280" + Ident "foo280" Call - Ident ident"x" + Ident "x" Do Empty Empty @@ -305,7 +305,7 @@ StmtList FormalParams Empty IdentDefs - Ident ident"y" + Ident "y" Empty Empty Empty @@ -318,40 +318,40 @@ StmtList DiscardStmt Empty Asgn - Ident ident"a" - Ident ident"foo290" + Ident "a" + Ident "foo290" Asgn - Ident ident"a" + Ident "a" Call - Ident ident"foo300" + Ident "foo300" Asgn - Ident ident"a" + Ident "a" Call - Ident ident"foo310" - Ident ident"x" + Ident "foo310" + Ident "x" Asgn - Ident ident"a" + Ident "a" Command - Ident ident"foo320" - Ident ident"x" + Ident "foo320" + Ident "x" Asgn - Ident ident"a" + Ident "a" Call - Ident ident"foo330" + Ident "foo330" StmtList DiscardStmt Empty Asgn - Ident ident"a" + Ident "a" Call - Ident ident"foo340" + Ident "foo340" StmtList DiscardStmt Empty Asgn - Ident ident"a" + Ident "a" Call - Ident ident"foo350" + Ident "foo350" StmtList DiscardStmt Empty @@ -360,13 +360,13 @@ StmtList DiscardStmt Empty Asgn - Ident ident"a" + Ident "a" Command - Ident ident"foo360" + Ident "foo360" Call DotExpr - Ident ident"x" - Ident ident"bar" + Ident "x" + Ident "bar" Do Empty Empty @@ -374,7 +374,7 @@ StmtList FormalParams Empty IdentDefs - Ident ident"y" + Ident "y" Empty Empty Empty @@ -388,20 +388,20 @@ StmtList Empty Command DotExpr - Ident ident"foo370" - Ident ident"add" + Ident "foo370" + Ident "add" Call - Ident ident"quote" + Ident "quote" StmtList DiscardStmt Empty Call DotExpr - Ident ident"foo380" - Ident ident"add" + Ident "foo380" + Ident "add" BracketExpr Call - Ident ident"quote" + Ident "quote" StmtList DiscardStmt Empty @@ -540,4 +540,3 @@ dumpTree: foo380.add((quote do: discard )[0]) - diff --git a/tests/parser/tprecedence.nim b/tests/parser/tprecedence.nim index d2c6d0b30..d586f14a3 100644 --- a/tests/parser/tprecedence.nim +++ b/tests/parser/tprecedence.nim @@ -1,6 +1,7 @@ discard """ output: '''holla -true''' +true +defabc 4''' """ # Test top level semicolon works properly: @@ -13,3 +14,8 @@ proc `\*` (x, y: int): int = result = x * y echo 5 \+ 1 \* 9 == 6*9 +proc foo[S, T](x: S, y: T): T = x & y + +proc bar[T](x: T): T = x + +echo "def".foo[:string, string]("abc"), " ", 4.bar[:int] diff --git a/tests/parser/ttypeclasses.nim b/tests/parser/ttypeclasses.nim new file mode 100644 index 000000000..9f487c7a8 --- /dev/null +++ b/tests/parser/ttypeclasses.nim @@ -0,0 +1,17 @@ +discard """ + action: run +""" + +type + R = ref + V = var + D = distinct + P = ptr + +var x: ref int +var y: distinct int +var z: ptr int + +doAssert x is ref +doAssert y is distinct +doAssert z is ptr \ No newline at end of file diff --git a/tests/parser/twhen_in_enum.nim b/tests/parser/twhen_in_enum.nim index d4a3ea56a..3890b686e 100644 --- a/tests/parser/twhen_in_enum.nim +++ b/tests/parser/twhen_in_enum.nim @@ -1,5 +1,5 @@ discard """ - errormsg: "identifier expected, but found 'keyword when'" + errormsg: "identifier expected, but got 'keyword when'" """ # bug #2123 diff --git a/tests/parser/twrongcmdsyntax.nim b/tests/parser/twrongcmdsyntax.nim index affe72c34..c2962bed4 100644 --- a/tests/parser/twrongcmdsyntax.nim +++ b/tests/parser/twrongcmdsyntax.nim @@ -1,5 +1,5 @@ discard """ - errormsg: '''identifier expected, but found 'echo 4''' + errormsg: '''in expression '4 2': identifier expected, but found '4''' line: 6 """ diff --git a/tests/pragmas/custom_pragma.nim b/tests/pragmas/custom_pragma.nim new file mode 100644 index 000000000..9e8f51deb --- /dev/null +++ b/tests/pragmas/custom_pragma.nim @@ -0,0 +1,5 @@ +# imported by tcustom_pragmas to test scoping + +template serializationKey*(s: string) {.pragma.} +template defaultValue*(V: typed) {.pragma.} +template alternativeKey*(s: string = nil, V: typed) {.pragma.} \ No newline at end of file diff --git a/tests/pragmas/tcustom_pragma.nim b/tests/pragmas/tcustom_pragma.nim new file mode 100644 index 000000000..33a4a7e65 --- /dev/null +++ b/tests/pragmas/tcustom_pragma.nim @@ -0,0 +1,140 @@ +import macros + +block: + template myAttr() {.pragma.} + + proc myProc():int {.myAttr.} = 2 + const hasMyAttr = myProc.hasCustomPragma(myAttr) + static: + assert(hasMyAttr) + +block: + template myAttr(a: string) {.pragma.} + + type MyObj = object + myField1, myField2 {.myAttr: "hi".}: int + var o: MyObj + static: + assert o.myField2.hasCustomPragma(myAttr) + assert(not o.myField1.hasCustomPragma(myAttr)) + +import custom_pragma +block: # A bit more advanced case + type + Subfield {.defaultValue: "catman".} = object + c {.serializationKey: "cc".}: float + + MySerializable = object + a {.serializationKey"asdf", defaultValue: 5.} : int + b {.custom_pragma.defaultValue"hello".} : int + field: Subfield + d {.alternativeKey("df", 5).}: float + e {.alternativeKey(V = 5).}: seq[bool] + + proc myproc(x: int, s: string) {.alternativeKey(V = 5), serializationKey"myprocSS".} = + echo x, s + + + var s: MySerializable + + const aDefVal = s.a.getCustomPragmaVal(defaultValue) + static: assert(aDefVal == 5) + + const aSerKey = s.a.getCustomPragmaVal(serializationKey) + static: assert(aSerKey == "asdf") + + const cSerKey = getCustomPragmaVal(s.field.c, serializationKey) + static: assert(cSerKey == "cc") + + const procSerKey = getCustomPragmaVal(myproc, serializationKey) + static: assert(procSerKey == "myprocSS") + + static: assert(hasCustomPragma(myproc, alternativeKey)) + + const hasFieldCustomPragma = s.field.hasCustomPragma(defaultValue) + static: assert(hasFieldCustomPragma == false) + + # pragma on an object + static: + assert Subfield.hasCustomPragma(defaultValue) + assert(Subfield.getCustomPragmaVal(defaultValue) == "catman") + + assert hasCustomPragma(type(s.field), defaultValue) + +block: # ref types + type + Node = object of RootObj + left {.serializationKey:"l".}, right {.serializationKey:"r".}: NodeRef + NodeRef = ref Node + NodePtr = ptr Node + + SpecialNodeRef = ref object of NodeRef + data {.defaultValue"none".}: string + + MyFile {.defaultValue: "closed".} = ref object + path {.defaultValue: "invalid".}: string + + TypeWithoutPragma = object + + var s = NodeRef() + + const + leftSerKey = getCustomPragmaVal(s.left, serializationKey) + rightSerKey = getCustomPragmaVal(s.right, serializationKey) + static: + assert leftSerKey == "l" + assert rightSerKey == "r" + + var specS = SpecialNodeRef() + + const + dataDefVal = hasCustomPragma(specS.data, defaultValue) + specLeftSerKey = hasCustomPragma(specS.left, serializationKey) + static: + assert dataDefVal == true + assert specLeftSerKey == true + + var ptrS = NodePtr(nil) + const + ptrRightSerKey = getCustomPragmaVal(ptrS.right, serializationKey) + static: + assert ptrRightSerKey == "r" + + var f = MyFile() + const + fileDefVal = f.getCustomPragmaVal(defaultValue) + filePathDefVal = f.path.getCustomPragmaVal(defaultValue) + static: + assert fileDefVal == "closed" + assert filePathDefVal == "invalid" + + static: + assert TypeWithoutPragma.hasCustomPragma(defaultValue) == false + +block: + type + VariantKind = enum + variInt, + variFloat + variString + variNestedCase + Variant = object + case kind: VariantKind + of variInt: integer {.serializationKey: "int".}: BiggestInt + of variFloat: floatp: BiggestFloat + of variString: str {.serializationKey: "string".}: string + of variNestedCase: + case nestedKind: VariantKind + of variInt..variNestedCase: nestedItem {.defaultValue: "Nimmers of the world, unite!".}: int + + let vari = Variant(kind: variInt) + + const + hasIntSerKey = vari.integer.hasCustomPragma(serializationKey) + strSerKey = vari.str.getCustomPragmaVal(serializationKey) + nestedItemDefVal = vari.nestedItem.getCustomPragmaVal(defaultValue) + + static: + assert hasIntSerKey + assert strSerKey == "string" + assert nestedItemDefVal == "Nimmers of the world, unite!" \ No newline at end of file diff --git a/tests/pragmas/tnoreturn.nim b/tests/pragmas/tnoreturn.nim index 4d00c6034..bb59b1c71 100644 --- a/tests/pragmas/tnoreturn.nim +++ b/tests/pragmas/tnoreturn.nim @@ -2,13 +2,16 @@ discard """ ccodeCheck: "\\i @'__attribute__((noreturn))' .*" """ -proc noret1*(i: int) {.noreturn.} = +proc noret1*(i: int) {.noreturn.} = echo i -proc noret2*(i: int): void {.noreturn.} = +proc noret2*(i: int): void {.noreturn.} = echo i +noret1(1) +noret2(2) + var p {.used.}: proc(i: int): int doAssert(not compiles( p = proc(i: int): int {.noreturn.} = i # noreturn lambda returns int diff --git a/tests/pragmas/tuserpragma2.nim b/tests/pragmas/tuserpragma2.nim new file mode 100644 index 000000000..bf8844e66 --- /dev/null +++ b/tests/pragmas/tuserpragma2.nim @@ -0,0 +1,11 @@ +discard """ + file: "tuserpragma2.nim" + line: 11 + errormsg: "can raise an unlisted exception: ref Exception" +""" + +# bug #7216 +{.pragma: my_pragma, raises: [].} + +proc test1 {.my_pragma.} = + raise newException(Exception, "msg") diff --git a/tests/proc/tprocredef.nim b/tests/proc/tprocredef.nim index 86ed92b62..4ec771510 100644 --- a/tests/proc/tprocredef.nim +++ b/tests/proc/tprocredef.nim @@ -4,6 +4,6 @@ discard """ errormsg: "redefinition of \'foo\'" """ -proc foo(a: int, b: string) = nil -proc foo(a: int, b: string) = nil +proc foo(a: int, b: string) = discard +proc foo(a: int, b: string) = discard diff --git a/tests/range/tsubrange.nim b/tests/range/tsubrange.nim index 6f88c5a22..914e7c6e7 100644 --- a/tests/range/tsubrange.nim +++ b/tests/range/tsubrange.nim @@ -7,7 +7,7 @@ type TRange = range[0..40] proc p(r: TRange) = - nil + discard var r: TRange diff --git a/tests/realtimeGC/cmain.c b/tests/realtimeGC/cmain.c index e9a46d7ce..0d4bb096a 100644 --- a/tests/realtimeGC/cmain.c +++ b/tests/realtimeGC/cmain.c @@ -1,8 +1,8 @@ - #ifdef WIN #include <windows.h> #else #include <dlfcn.h> +#include <unistd.h> /* for sleep(3) */ #endif #include <stdio.h> #include <stdlib.h> diff --git a/tests/realtimeGC/readme.txt b/tests/realtimeGC/readme.txt index 17e18a5e5..b2e37a1f0 100644 --- a/tests/realtimeGC/readme.txt +++ b/tests/realtimeGC/readme.txt @@ -1,21 +1,21 @@ Test the realtime GC without linking nimrtl.dll/so. Note, this is a long running test, default is 35 minutes. To change the -the run time see RUNTIME in main.nim and main.c. +the run time see RUNTIME in nmain.nim and cmain.c. -You can build shared.nim, main.nim, and main.c by running make (nix systems) -or maike.bat (Windows systems). They both assume GCC and that it's in your -path. Output: shared.(dll/so), camin(.exe), nmain(.exe). +You can build shared.nim, nmain.nim, and cmain.c by running make (nix systems) +or make.bat (Windows systems). They both assume GCC and that it's in your +path. Output: shared.(dll/so), cmain(.exe), nmain(.exe). To run the test: execute either nmain or cmain in a shell window. -To build buy hand: +To build by hand: - build the shared object (shared.nim): - $ nim c shared.nim + $ nim c tests/realtimeGC/shared.nim - build the client executables: - $ nim c -o:nmain main.nim - $ gcc -o cmain main.c -ldl + $ nim c --threads:on tests/realtimeGC/nmain.nim + $ gcc -o tests/realtimeGC/cmain tests/realtimeGC/cmain.c -ldl diff --git a/tests/rodfiles/deadg.nim b/tests/rodfiles/deadg.nim index 587608e14..0aee59bb8 100644 --- a/tests/rodfiles/deadg.nim +++ b/tests/rodfiles/deadg.nim @@ -1,6 +1,3 @@ - -{.deadCodeElim: on.} - proc p1*(x, y: int): int = result = x + y diff --git a/tests/sets/tsets.nim b/tests/sets/tsets.nim index 53a955af8..96d5debc7 100644 --- a/tests/sets/tsets.nim +++ b/tests/sets/tsets.nim @@ -202,3 +202,7 @@ var #import compiler.msgs echo warnUninit in gNotes + +# 7555 +doAssert {-1.int8, -2, -2}.card == 2 +doAssert {1, 2, 2, 3..5, 4..6}.card == 6 \ No newline at end of file diff --git a/tests/statictypes/tcryptodigest.nim b/tests/statictypes/tcryptodigest.nim new file mode 100644 index 000000000..c78a4188a --- /dev/null +++ b/tests/statictypes/tcryptodigest.nim @@ -0,0 +1,44 @@ +discard """ + output: "Digest[128]\nDigest[256]" +""" + +import typetraits + +type + Digest[bits: static[int]] = object + data: array[bits div 8, byte] + + ContextKind = enum + A, B, C + + HashingContext[bits: static[int], kind: static[ContextKind]] = object + ctx: array[bits div 8, byte] + + Hash128 = HashingContext[128, A] + Hash256 = HashingContext[256, B] + + HMAC[HashType] = object + h: HashType + +proc init(c: var HashingContext) = discard +proc update(c: var HashingContext, data: ptr byte, dataLen: uint) = discard +proc finish(c: var HashingContext): Digest[c.bits] = discard + +proc digest(T: typedesc, data: ptr byte, dataLen: uint): Digest[T.bits] = + mixin init, update, finish + + var ctx: T + ctx.init() + ctx.update(data, dataLen) + result = ctx.finish() + +var h = Hash128.digest(nil, 0) +echo h.type.name + +proc finish(hmac: var HMAC): Digest[HMAC.HashType.bits] = + discard + +var hm: HMAC[Hash256] +var d = hm.finish +echo d.type.name + diff --git a/tests/statictypes/tstackmatrix.nim b/tests/statictypes/tstackmatrix.nim new file mode 100644 index 000000000..2509d21f8 --- /dev/null +++ b/tests/statictypes/tstackmatrix.nim @@ -0,0 +1,29 @@ +discard """ + output: "(M: 3, N: 3, fp: ...)" +""" + +# bug #6843 + +type + OrderType = enum colMajor, rowMajor + Matrix[A] = object + M, N: int + fp: ptr A # float pointer + DoubleArray64[M, N: static[int]] = array[M, array[N, float64]] + + +proc stackMatrix[M, N: static[int]](a: var DoubleArray64[M, N], order = colMajor): Matrix[float64] = + Matrix[float64]( + fp: addr a[0][0], + M: (if order == colMajor: N else: M), + N: (if order == colMajor: M else: N) + ) + +var + data = [ + [1'f64, 2, 3], + [4'f64, 5, 6], + [7'f64, 8, 9] + ] + m = stackMatrix(data) +echo m \ No newline at end of file diff --git a/tests/statictypes/tstaticimportcpp.nim b/tests/statictypes/tstaticimportcpp.nim new file mode 100644 index 000000000..0cbbc1df6 --- /dev/null +++ b/tests/statictypes/tstaticimportcpp.nim @@ -0,0 +1,59 @@ +discard """ +targets: "cpp" +output: "[0, 0, 10, 0]\n5\n1.2\n15\ntest\n[0, 0, 20, 0]" +""" + +{.emit: """/*TYPESECTION*/ + +template <int N, class T> +struct GenericIntType { + T data[N]; +}; + +template <class T> +struct GenericTType { + T field; +}; + +struct SimpleStruct { + int field; +}; + + +""" .} + +type + GenericIntType {.importcpp: "GenericIntType<'0, '1>".} [N: static[int]; T] = object + data: array[N, T] + + GenericTType {.importcpp: "GenericTType<'0>".} [T] = object + field: T + + GenInt4 = GenericIntType[4, int] + + SimpleStruct {.importcpp: "SimpleStruct"} = object + field: int + +var + a = GenInt4() + b = SimpleStruct() + c = GenericTType[float]() + d = SimpleStruct(field: 15) + e = GenericTType[string](field: "test") + +a.data[2] = 10 +b.field = 5 +c.field = 1.2 + +echo a.data +echo b.field +echo c.field +echo d.field +echo e.field + +proc plus(a, b: GenInt4): GenInt4 = + for i in 0 ..< result.data.len: + result.data[i] = a.data[i] + b.data[i] + +echo plus(a, a).data + diff --git a/tests/stdlib/talgorithm.nim b/tests/stdlib/talgorithm.nim deleted file mode 100644 index f200e54c5..000000000 --- a/tests/stdlib/talgorithm.nim +++ /dev/null @@ -1,11 +0,0 @@ -import algorithm - -doAssert product[int](newSeq[seq[int]]()) == newSeq[seq[int]](), "empty input" -doAssert product[int](@[newSeq[int](), @[], @[]]) == newSeq[seq[int]](), "bit more empty input" -doAssert product(@[@[1,2]]) == @[@[1,2]], "a simple case of one element" -doAssert product(@[@[1,2], @[3,4]]) == @[@[2,4],@[1,4],@[2,3],@[1,3]], "two elements" -doAssert product(@[@[1,2], @[3,4], @[5,6]]) == @[@[2,4,6],@[1,4,6],@[2,3,6],@[1,3,6], @[2,4,5],@[1,4,5],@[2,3,5],@[1,3,5]], "three elements" -doAssert product(@[@[1,2], @[]]) == newSeq[seq[int]](), "two elements, but one empty" -doAssert lowerBound([1,2,4], 3, system.cmp[int]) == 2 -doAssert lowerBound([1,2,2,3], 4, system.cmp[int]) == 4 -doAssert lowerBound([1,2,3,10], 11) == 4 diff --git a/tests/stdlib/tjsonmacro.nim b/tests/stdlib/tjsonmacro.nim index 2cdd82305..f13d2e5cb 100644 --- a/tests/stdlib/tjsonmacro.nim +++ b/tests/stdlib/tjsonmacro.nim @@ -315,6 +315,36 @@ when isMainModule: doAssert noYearDeser.year.isNone doAssert noYearDeser.engine.name == "V8" + # Issue #7433 + type + Obj2 = object + n1: int + n2: Option[string] + n3: bool + + var j = %*[ { "n1": 4, "n2": "ABC", "n3": true }, + { "n1": 1, "n3": false }, + { "n1": 1, "n2": "XYZ", "n3": false } ] + + let jDeser = j.to(seq[Obj2]) + doAssert jDeser[0].n2.get() == "ABC" + doAssert jDeser[1].n2.isNone() + + # Issue #6902 + type + Obj = object + n1: int + n2: Option[int] + n3: Option[string] + n4: Option[bool] + + var j0 = parseJson("""{"n1": 1, "n2": null, "n3": null, "n4": null}""") + let j0Deser = j0.to(Obj) + doAssert j0Deser.n1 == 1 + doAssert j0Deser.n2.isNone() + doAssert j0Deser.n3.isNone() + doAssert j0Deser.n4.isNone() + # Table[T, Y] support. block: type @@ -380,4 +410,11 @@ when isMainModule: let dataDeser = to(dataParsed, Test1) doAssert dataDeser.a == 1 doAssert dataDeser.f == 6 - doAssert dataDeser.i == 9.9'f32 \ No newline at end of file + doAssert dataDeser.i == 9.9'f32 + + # deserialize directly into a table + block: + let s = """{"a": 1, "b": 2}""" + let t = parseJson(s).to(Table[string, int]) + doAssert t["a"] == 1 + doAssert t["b"] == 2 \ No newline at end of file diff --git a/tests/stdlib/tnet.nim b/tests/stdlib/tnet.nim index e8ada05e7..64d690fc9 100644 --- a/tests/stdlib/tnet.nim +++ b/tests/stdlib/tnet.nim @@ -1,4 +1,4 @@ -import net +import net, nativesockets import unittest suite "isIpAddress tests": @@ -45,3 +45,33 @@ suite "parseIpAddress tests": test "invalid ipv6": expect(ValueError): discard parseIpAddress("gggg:cdba:0000:0000:0000:0000:3257:9652") + +block: # "IpAddress/Sockaddr conversion" + proc test(ipaddrstr: string) = + var ipaddr_1 = parseIpAddress(ipaddrstr) + # echo ipaddrstr, " ", $ipaddr_1 + + doAssert($ipaddrstr == $ipaddr_1) + + var sockaddr: Sockaddr_storage + var socklen: Socklen + var ipaddr_2: IpAddress + var port_2: Port + + toSockAddr(ipaddr_1, Port(0), sockaddr, socklen) + fromSockAddr(sockaddr, socklen, ipaddr_2, port_2) + + doAssert(ipaddrstr == $ipaddr_1) + + doAssert(ipaddr_1 == ipaddr_2) + doAssert($ipaddr_1 == $ipaddr_2) + + + # ipv6 address of example.com + test("2606:2800:220:1:248:1893:25c8:1946") + # ipv6 address of localhost + test("::1") + # ipv4 address of example.com + test("93.184.216.34") + # ipv4 address of localhost + test("127.0.0.1") diff --git a/tests/stdlib/tos.nim b/tests/stdlib/tos.nim index 771dc2456..e6fbb0e51 100644 --- a/tests/stdlib/tos.nim +++ b/tests/stdlib/tos.nim @@ -42,6 +42,7 @@ Raises true true true +true ''' """ # test os path creation, iteration, and deletion @@ -129,3 +130,12 @@ echo fileExists("../dest/a/b/file.txt") echo fileExists("../dest/a/b/c/fileC.txt") removeDir("../dest") + +# Test get/set modification times +# Should support at least microsecond resolution +import times +let tm = fromUnix(0) + 100.microseconds +writeFile("a", "") +setLastModificationTime("a", tm) +echo getLastModificationTime("a") == tm +removeFile("a") \ No newline at end of file diff --git a/tests/stdlib/tparsesql.nim b/tests/stdlib/tparsesql.nim index 3dc949ea1..126020ed6 100644 --- a/tests/stdlib/tparsesql.nim +++ b/tests/stdlib/tparsesql.nim @@ -26,10 +26,9 @@ doAssert $parseSQL("SELECT foo, bar, baz FROM table limit 10") == "select foo, b doAssert $parseSQL("SELECT foo AS bar FROM table") == "select foo as bar from table;" doAssert $parseSQL("SELECT foo AS foo_prime, bar AS bar_prime, baz AS baz_prime FROM table") == "select foo as foo_prime, bar as bar_prime, baz as baz_prime from table;" doAssert $parseSQL("SELECT * FROM table") == "select * from table;" - - -#TODO add count(*) -#doAssert $parseSQL("SELECT COUNT(*) FROM table" +doAssert $parseSQL("SELECT count(*) FROM table") == "select count(*) from table;" +doAssert $parseSQL("SELECT count(*) as 'Total' FROM table") == "select count(*) as 'Total' from table;" +doAssert $parseSQL("SELECT count(*) as 'Total', sum(a) as 'Aggr' FROM table") == "select count(*) as 'Total', sum(a) as 'Aggr' from table;" doAssert $parseSQL(""" SELECT * FROM table @@ -52,6 +51,23 @@ WHERE doAssert $parseSQL(""" SELECT * FROM table +ORDER BY 1 +""") == "select * from table order by 1;" + +doAssert $parseSQL(""" +SELECT * FROM table +GROUP BY 1 +ORDER BY 1 +""") == "select * from table group by 1 order by 1;" + +doAssert $parseSQL(""" +SELECT * FROM table +ORDER BY 1 +LIMIT 100 +""") == "select * from table order by 1 limit 100;" + +doAssert $parseSQL(""" +SELECT * FROM table WHERE a = b and c = d or n is null and not b + 1 = 3 """) == "select * from table where a = b and c = d or n is null and not b + 1 = 3;" @@ -185,7 +201,10 @@ AND Country='USA' ORDER BY CustomerName; """) == "select * from Customers where(CustomerName like 'L%' or CustomerName like 'R%' or CustomerName like 'W%') and Country = 'USA' order by CustomerName;" -# parse keywords as identifires +# parse quoted keywords as identifires doAssert $parseSQL(""" SELECT `SELECT`, `FROM` as `GROUP` FROM `WHERE`; """) == """select "SELECT", "FROM" as "GROUP" from "WHERE";""" +doAssert $parseSQL(""" +SELECT "SELECT", "FROM" as "GROUP" FROM "WHERE"; +""") == """select "SELECT", "FROM" as "GROUP" from "WHERE";""" diff --git a/tests/stdlib/tpegs.nim b/tests/stdlib/tpegs.nim deleted file mode 100644 index e2a5a1715..000000000 --- a/tests/stdlib/tpegs.nim +++ /dev/null @@ -1,1770 +0,0 @@ -discard """ - output: '''this -is -an -example -d -e -f -('keyvalue' 'key'*)''' -""" -# PEGs module turned out to be a good test to detect memory management bugs. - -include "system/inclrtl" - -const - useUnicode = true ## change this to deactivate proper UTF-8 support - -import - strutils - -when useUnicode: - import unicode - -const - InlineThreshold = 5 ## number of leaves; -1 to disable inlining - MaxSubpatterns* = 10 ## defines the maximum number of subpatterns that - ## can be captured. More subpatterns cannot be captured! - -type - TPegKind = enum - pkEmpty, - pkAny, ## any character (.) - pkAnyRune, ## any Unicode character (_) - pkNewLine, ## CR-LF, LF, CR - pkLetter, ## Unicode letter - pkLower, ## Unicode lower case letter - pkUpper, ## Unicode upper case letter - pkTitle, ## Unicode title character - pkWhitespace, ## Unicode whitespace character - pkTerminal, - pkTerminalIgnoreCase, - pkTerminalIgnoreStyle, - pkChar, ## single character to match - pkCharChoice, - pkNonTerminal, - pkSequence, ## a b c ... --> Internal DSL: peg(a, b, c) - pkOrderedChoice, ## a / b / ... --> Internal DSL: a / b or /[a, b, c] - pkGreedyRep, ## a* --> Internal DSL: *a - ## a+ --> (a a*) - pkGreedyRepChar, ## x* where x is a single character (superop) - pkGreedyRepSet, ## [set]* (superop) - pkGreedyAny, ## .* or _* (superop) - pkOption, ## a? --> Internal DSL: ?a - pkAndPredicate, ## &a --> Internal DSL: &a - pkNotPredicate, ## !a --> Internal DSL: !a - pkCapture, ## {a} --> Internal DSL: capture(a) - pkBackRef, ## $i --> Internal DSL: backref(i) - pkBackRefIgnoreCase, - pkBackRefIgnoreStyle, - pkSearch, ## @a --> Internal DSL: !*a - pkCapturedSearch, ## {@} a --> Internal DSL: !*\a - pkRule, ## a <- b - pkList, ## a, b - pkStartAnchor ## ^ --> Internal DSL: startAnchor() - TNonTerminalFlag = enum - ntDeclared, ntUsed - TNonTerminal {.final.} = object ## represents a non terminal symbol - name: string ## the name of the symbol - line: int ## line the symbol has been declared/used in - col: int ## column the symbol has been declared/used in - flags: set[TNonTerminalFlag] ## the nonterminal's flags - rule: TNode ## the rule that the symbol refers to - TNode {.final, shallow.} = object - case kind: TPegKind - of pkEmpty..pkWhitespace: nil - of pkTerminal, pkTerminalIgnoreCase, pkTerminalIgnoreStyle: term: string - of pkChar, pkGreedyRepChar: ch: char - of pkCharChoice, pkGreedyRepSet: charChoice: ref set[char] - of pkNonTerminal: nt: PNonTerminal - of pkBackRef..pkBackRefIgnoreStyle: index: range[0..MaxSubpatterns] - else: sons: seq[TNode] - PNonTerminal* = ref TNonTerminal - - TPeg* = TNode ## type that represents a PEG - -proc term*(t: string): TPeg {.rtl, extern: "npegs$1Str".} = - ## constructs a PEG from a terminal string - if t.len != 1: - result.kind = pkTerminal - result.term = t - else: - result.kind = pkChar - result.ch = t[0] - -proc termIgnoreCase*(t: string): TPeg {. - rtl, extern: "npegs$1".} = - ## constructs a PEG from a terminal string; ignore case for matching - result.kind = pkTerminalIgnoreCase - result.term = t - -proc termIgnoreStyle*(t: string): TPeg {. - rtl, extern: "npegs$1".} = - ## constructs a PEG from a terminal string; ignore style for matching - result.kind = pkTerminalIgnoreStyle - result.term = t - -proc term*(t: char): TPeg {.rtl, extern: "npegs$1Char".} = - ## constructs a PEG from a terminal char - assert t != '\0' - result.kind = pkChar - result.ch = t - -proc charSet*(s: set[char]): TPeg {.rtl, extern: "npegs$1".} = - ## constructs a PEG from a character set `s` - assert '\0' notin s - result.kind = pkCharChoice - new(result.charChoice) - result.charChoice[] = s - -proc len(a: TPeg): int {.inline.} = return a.sons.len -proc add(d: var TPeg, s: TPeg) {.inline.} = add(d.sons, s) - -proc copyPeg(a: TPeg): TPeg = - result.kind = a.kind - case a.kind - of pkEmpty..pkWhitespace: discard - of pkTerminal, pkTerminalIgnoreCase, pkTerminalIgnoreStyle: - result.term = a.term - of pkChar, pkGreedyRepChar: - result.ch = a.ch - of pkCharChoice, pkGreedyRepSet: - new(result.charChoice) - result.charChoice[] = a.charChoice[] - of pkNonTerminal: result.nt = a.nt - of pkBackRef..pkBackRefIgnoreStyle: - result.index = a.index - else: - result.sons = a.sons - -proc addChoice(dest: var TPeg, elem: TPeg) = - var L = dest.len-1 - if L >= 0 and dest.sons[L].kind == pkCharChoice: - # caution! Do not introduce false aliasing here! - case elem.kind - of pkCharChoice: - dest.sons[L] = charSet(dest.sons[L].charChoice[] + elem.charChoice[]) - of pkChar: - dest.sons[L] = charSet(dest.sons[L].charChoice[] + {elem.ch}) - else: add(dest, elem) - else: add(dest, elem) - -template multipleOp(k: TPegKind, localOpt) = - result.kind = k - result.sons = @[] - for x in items(a): - if x.kind == k: - for y in items(x.sons): - localOpt(result, y) - else: - localOpt(result, x) - if result.len == 1: - result = result.sons[0] - -proc `/`*(a: varargs[TPeg]): TPeg {. - rtl, extern: "npegsOrderedChoice".} = - ## constructs an ordered choice with the PEGs in `a` - multipleOp(pkOrderedChoice, addChoice) - -proc addSequence(dest: var TPeg, elem: TPeg) = - var L = dest.len-1 - if L >= 0 and dest.sons[L].kind == pkTerminal: - # caution! Do not introduce false aliasing here! - case elem.kind - of pkTerminal: - dest.sons[L] = term(dest.sons[L].term & elem.term) - of pkChar: - dest.sons[L] = term(dest.sons[L].term & elem.ch) - else: add(dest, elem) - else: add(dest, elem) - -proc sequence*(a: varargs[TPeg]): TPeg {. - rtl, extern: "npegs$1".} = - ## constructs a sequence with all the PEGs from `a` - multipleOp(pkSequence, addSequence) - -proc `?`*(a: TPeg): TPeg {.rtl, extern: "npegsOptional".} = - ## constructs an optional for the PEG `a` - if a.kind in {pkOption, pkGreedyRep, pkGreedyAny, pkGreedyRepChar, - pkGreedyRepSet}: - # a* ? --> a* - # a? ? --> a? - result = a - else: - result.kind = pkOption - result.sons = @[a] - -proc `*`*(a: TPeg): TPeg {.rtl, extern: "npegsGreedyRep".} = - ## constructs a "greedy repetition" for the PEG `a` - case a.kind - of pkGreedyRep, pkGreedyRepChar, pkGreedyRepSet, pkGreedyAny, pkOption: - assert false - # produces endless loop! - of pkChar: - result.kind = pkGreedyRepChar - result.ch = a.ch - of pkCharChoice: - result.kind = pkGreedyRepSet - result.charChoice = a.charChoice # copying a reference suffices! - of pkAny, pkAnyRune: - result.kind = pkGreedyAny - else: - result.kind = pkGreedyRep - result.sons = @[a] - -proc `!*`*(a: TPeg): TPeg {.rtl, extern: "npegsSearch".} = - ## constructs a "search" for the PEG `a` - result.kind = pkSearch - result.sons = @[a] - -proc `!*\`*(a: TPeg): TPeg {.rtl, - extern: "npgegsCapturedSearch".} = - ## constructs a "captured search" for the PEG `a` - result.kind = pkCapturedSearch - result.sons = @[a] - -when false: - proc contains(a: TPeg, k: TPegKind): bool = - if a.kind == k: return true - case a.kind - of pkEmpty, pkAny, pkAnyRune, pkGreedyAny, pkNewLine, pkTerminal, - pkTerminalIgnoreCase, pkTerminalIgnoreStyle, pkChar, pkGreedyRepChar, - pkCharChoice, pkGreedyRepSet: discard - of pkNonTerminal: return true - else: - for i in 0..a.sons.len-1: - if contains(a.sons[i], k): return true - -proc `+`*(a: TPeg): TPeg {.rtl, extern: "npegsGreedyPosRep".} = - ## constructs a "greedy positive repetition" with the PEG `a` - return sequence(a, *a) - -proc `&`*(a: TPeg): TPeg {.rtl, extern: "npegsAndPredicate".} = - ## constructs an "and predicate" with the PEG `a` - result.kind = pkAndPredicate - result.sons = @[a] - -proc `!`*(a: TPeg): TPeg {.rtl, extern: "npegsNotPredicate".} = - ## constructs a "not predicate" with the PEG `a` - result.kind = pkNotPredicate - result.sons = @[a] - -proc any*: TPeg {.inline.} = - ## constructs the PEG `any character`:idx: (``.``) - result.kind = pkAny - -proc anyRune*: TPeg {.inline.} = - ## constructs the PEG `any rune`:idx: (``_``) - result.kind = pkAnyRune - -proc newLine*: TPeg {.inline.} = - ## constructs the PEG `newline`:idx: (``\n``) - result.kind = pkNewline - -proc UnicodeLetter*: TPeg {.inline.} = - ## constructs the PEG ``\letter`` which matches any Unicode letter. - result.kind = pkLetter - -proc UnicodeLower*: TPeg {.inline.} = - ## constructs the PEG ``\lower`` which matches any Unicode lowercase letter. - result.kind = pkLower - -proc UnicodeUpper*: TPeg {.inline.} = - ## constructs the PEG ``\upper`` which matches any Unicode lowercase letter. - result.kind = pkUpper - -proc UnicodeTitle*: TPeg {.inline.} = - ## constructs the PEG ``\title`` which matches any Unicode title letter. - result.kind = pkTitle - -proc UnicodeWhitespace*: TPeg {.inline.} = - ## constructs the PEG ``\white`` which matches any Unicode - ## whitespace character. - result.kind = pkWhitespace - -proc startAnchor*: TPeg {.inline.} = - ## constructs the PEG ``^`` which matches the start of the input. - result.kind = pkStartAnchor - -proc endAnchor*: TPeg {.inline.} = - ## constructs the PEG ``$`` which matches the end of the input. - result = !any() - -proc capture*(a: TPeg): TPeg {.rtl, extern: "npegsCapture".} = - ## constructs a capture with the PEG `a` - result.kind = pkCapture - result.sons = @[a] - -proc backref*(index: range[1..MaxSubPatterns]): TPeg {. - rtl, extern: "npegs$1".} = - ## constructs a back reference of the given `index`. `index` starts counting - ## from 1. - result.kind = pkBackRef - result.index = index-1 - -proc backrefIgnoreCase*(index: range[1..MaxSubPatterns]): TPeg {. - rtl, extern: "npegs$1".} = - ## constructs a back reference of the given `index`. `index` starts counting - ## from 1. Ignores case for matching. - result.kind = pkBackRefIgnoreCase - result.index = index-1 - -proc backrefIgnoreStyle*(index: range[1..MaxSubPatterns]): TPeg {. - rtl, extern: "npegs$1".}= - ## constructs a back reference of the given `index`. `index` starts counting - ## from 1. Ignores style for matching. - result.kind = pkBackRefIgnoreStyle - result.index = index-1 - -proc spaceCost(n: TPeg): int = - case n.kind - of pkEmpty: discard - of pkTerminal, pkTerminalIgnoreCase, pkTerminalIgnoreStyle, pkChar, - pkGreedyRepChar, pkCharChoice, pkGreedyRepSet, - pkAny..pkWhitespace, pkGreedyAny: - result = 1 - of pkNonTerminal: - # we cannot inline a rule with a non-terminal - result = InlineThreshold+1 - else: - for i in 0..n.len-1: - inc(result, spaceCost(n.sons[i])) - if result >= InlineThreshold: break - -proc nonterminal*(n: PNonTerminal): TPeg {. - rtl, extern: "npegs$1".} = - ## constructs a PEG that consists of the nonterminal symbol - assert n != nil - if ntDeclared in n.flags and spaceCost(n.rule) < InlineThreshold: - when false: echo "inlining symbol: ", n.name - result = n.rule # inlining of rule enables better optimizations - else: - result.kind = pkNonTerminal - result.nt = n - -proc newNonTerminal*(name: string, line, column: int): PNonTerminal {. - rtl, extern: "npegs$1".} = - ## constructs a nonterminal symbol - new(result) - result.name = name - result.line = line - result.col = column - -template letters*: TPeg = - ## expands to ``charset({'A'..'Z', 'a'..'z'})`` - charset({'A'..'Z', 'a'..'z'}) - -template digits*: TPeg = - ## expands to ``charset({'0'..'9'})`` - charset({'0'..'9'}) - -template whitespace*: TPeg = - ## expands to ``charset({' ', '\9'..'\13'})`` - charset({' ', '\9'..'\13'}) - -template identChars*: TPeg = - ## expands to ``charset({'a'..'z', 'A'..'Z', '0'..'9', '_'})`` - charset({'a'..'z', 'A'..'Z', '0'..'9', '_'}) - -template identStartChars*: TPeg = - ## expands to ``charset({'A'..'Z', 'a'..'z', '_'})`` - charset({'a'..'z', 'A'..'Z', '_'}) - -template ident*: TPeg = - ## same as ``[a-zA-Z_][a-zA-z_0-9]*``; standard identifier - sequence(charset({'a'..'z', 'A'..'Z', '_'}), - *charset({'a'..'z', 'A'..'Z', '0'..'9', '_'})) - -template natural*: TPeg = - ## same as ``\d+`` - +digits - -# ------------------------- debugging ----------------------------------------- - -proc esc(c: char, reserved = {'\0'..'\255'}): string = - case c - of '\b': result = "\\b" - of '\t': result = "\\t" - of '\c': result = "\\c" - of '\L': result = "\\l" - of '\v': result = "\\v" - of '\f': result = "\\f" - of '\e': result = "\\e" - of '\a': result = "\\a" - of '\\': result = "\\\\" - of 'a'..'z', 'A'..'Z', '0'..'9', '_': result = $c - elif c < ' ' or c >= '\128': result = '\\' & $ord(c) - elif c in reserved: result = '\\' & c - else: result = $c - -proc singleQuoteEsc(c: char): string = return "'" & esc(c, {'\''}) & "'" - -proc singleQuoteEsc(str: string): string = - result = "'" - for c in items(str): add result, esc(c, {'\''}) - add result, '\'' - -proc charSetEscAux(cc: set[char]): string = - const reserved = {'^', '-', ']'} - result = "" - var c1 = 0 - while c1 <= 0xff: - if chr(c1) in cc: - var c2 = c1 - while c2 < 0xff and chr(succ(c2)) in cc: inc(c2) - if c1 == c2: - add result, esc(chr(c1), reserved) - elif c2 == succ(c1): - add result, esc(chr(c1), reserved) & esc(chr(c2), reserved) - else: - add result, esc(chr(c1), reserved) & '-' & esc(chr(c2), reserved) - c1 = c2 - inc(c1) - -proc charSetEsc(cc: set[char]): string = - if card(cc) >= 128+64: - result = "[^" & charSetEscAux({'\1'..'\xFF'} - cc) & ']' - else: - result = '[' & charSetEscAux(cc) & ']' - -proc toStrAux(r: TPeg, res: var string) = - case r.kind - of pkEmpty: add(res, "()") - of pkAny: add(res, '.') - of pkAnyRune: add(res, '_') - of pkLetter: add(res, "\\letter") - of pkLower: add(res, "\\lower") - of pkUpper: add(res, "\\upper") - of pkTitle: add(res, "\\title") - of pkWhitespace: add(res, "\\white") - - of pkNewline: add(res, "\\n") - of pkTerminal: add(res, singleQuoteEsc(r.term)) - of pkTerminalIgnoreCase: - add(res, 'i') - add(res, singleQuoteEsc(r.term)) - of pkTerminalIgnoreStyle: - add(res, 'y') - add(res, singleQuoteEsc(r.term)) - of pkChar: add(res, singleQuoteEsc(r.ch)) - of pkCharChoice: add(res, charSetEsc(r.charChoice[])) - of pkNonTerminal: add(res, r.nt.name) - of pkSequence: - add(res, '(') - toStrAux(r.sons[0], res) - for i in 1 .. high(r.sons): - add(res, ' ') - toStrAux(r.sons[i], res) - add(res, ')') - of pkOrderedChoice: - add(res, '(') - toStrAux(r.sons[0], res) - for i in 1 .. high(r.sons): - add(res, " / ") - toStrAux(r.sons[i], res) - add(res, ')') - of pkGreedyRep: - toStrAux(r.sons[0], res) - add(res, '*') - of pkGreedyRepChar: - add(res, singleQuoteEsc(r.ch)) - add(res, '*') - of pkGreedyRepSet: - add(res, charSetEsc(r.charChoice[])) - add(res, '*') - of pkGreedyAny: - add(res, ".*") - of pkOption: - toStrAux(r.sons[0], res) - add(res, '?') - of pkAndPredicate: - add(res, '&') - toStrAux(r.sons[0], res) - of pkNotPredicate: - add(res, '!') - toStrAux(r.sons[0], res) - of pkSearch: - add(res, '@') - toStrAux(r.sons[0], res) - of pkCapturedSearch: - add(res, "{@}") - toStrAux(r.sons[0], res) - of pkCapture: - add(res, '{') - toStrAux(r.sons[0], res) - add(res, '}') - of pkBackRef: - add(res, '$') - add(res, $r.index) - of pkBackRefIgnoreCase: - add(res, "i$") - add(res, $r.index) - of pkBackRefIgnoreStyle: - add(res, "y$") - add(res, $r.index) - of pkRule: - toStrAux(r.sons[0], res) - add(res, " <- ") - toStrAux(r.sons[1], res) - of pkList: - for i in 0 .. high(r.sons): - toStrAux(r.sons[i], res) - add(res, "\n") - of pkStartAnchor: - add(res, '^') - -proc `$` *(r: TPeg): string {.rtl, extern: "npegsToString".} = - ## converts a PEG to its string representation - result = "" - toStrAux(r, result) - -# --------------------- core engine ------------------------------------------- - -type - TCaptures* {.final.} = object ## contains the captured substrings. - matches: array[0..MaxSubpatterns-1, tuple[first, last: int]] - ml: int - origStart: int - -proc bounds*(c: TCaptures, - i: range[0..MaxSubpatterns-1]): tuple[first, last: int] = - ## returns the bounds ``[first..last]`` of the `i`'th capture. - result = c.matches[i] - -when not useUnicode: - type - Rune = char - template fastRuneAt(s, i, ch) = - ch = s[i] - inc(i) - template runeLenAt(s, i): untyped = 1 - - proc isAlpha(a: char): bool {.inline.} = return a in {'a'..'z','A'..'Z'} - proc isUpper(a: char): bool {.inline.} = return a in {'A'..'Z'} - proc isLower(a: char): bool {.inline.} = return a in {'a'..'z'} - proc isTitle(a: char): bool {.inline.} = return false - proc isWhiteSpace(a: char): bool {.inline.} = return a in {' ', '\9'..'\13'} - -proc rawMatch*(s: string, p: TPeg, start: int, c: var TCaptures): int {. - rtl, extern: "npegs$1".} = - ## low-level matching proc that implements the PEG interpreter. Use this - ## for maximum efficiency (every other PEG operation ends up calling this - ## proc). - ## Returns -1 if it does not match, else the length of the match - case p.kind - of pkEmpty: result = 0 # match of length 0 - of pkAny: - if s[start] != '\0': result = 1 - else: result = -1 - of pkAnyRune: - if s[start] != '\0': - result = runeLenAt(s, start) - else: - result = -1 - of pkLetter: - if s[start] != '\0': - var a: Rune - result = start - fastRuneAt(s, result, a) - if isAlpha(a): dec(result, start) - else: result = -1 - else: - result = -1 - of pkLower: - if s[start] != '\0': - var a: Rune - result = start - fastRuneAt(s, result, a) - if isLower(a): dec(result, start) - else: result = -1 - else: - result = -1 - of pkUpper: - if s[start] != '\0': - var a: Rune - result = start - fastRuneAt(s, result, a) - if isUpper(a): dec(result, start) - else: result = -1 - else: - result = -1 - of pkTitle: - if s[start] != '\0': - var a: Rune - result = start - fastRuneAt(s, result, a) - if isTitle(a): dec(result, start) - else: result = -1 - else: - result = -1 - of pkWhitespace: - if s[start] != '\0': - var a: Rune - result = start - fastRuneAt(s, result, a) - if isWhitespace(a): dec(result, start) - else: result = -1 - else: - result = -1 - of pkGreedyAny: - result = len(s) - start - of pkNewLine: - if s[start] == '\L': result = 1 - elif s[start] == '\C': - if s[start+1] == '\L': result = 2 - else: result = 1 - else: result = -1 - of pkTerminal: - result = len(p.term) - for i in 0..result-1: - if p.term[i] != s[start+i]: - result = -1 - break - of pkTerminalIgnoreCase: - var - i = 0 - a, b: Rune - result = start - while i < len(p.term): - fastRuneAt(p.term, i, a) - fastRuneAt(s, result, b) - if toLower(a) != toLower(b): - result = -1 - break - dec(result, start) - of pkTerminalIgnoreStyle: - var - i = 0 - a, b: Rune - result = start - while i < len(p.term): - while true: - fastRuneAt(p.term, i, a) - if a != Rune('_'): break - while true: - fastRuneAt(s, result, b) - if b != Rune('_'): break - if toLower(a) != toLower(b): - result = -1 - break - dec(result, start) - of pkChar: - if p.ch == s[start]: result = 1 - else: result = -1 - of pkCharChoice: - if contains(p.charChoice[], s[start]): result = 1 - else: result = -1 - of pkNonTerminal: - var oldMl = c.ml - when false: echo "enter: ", p.nt.name - result = rawMatch(s, p.nt.rule, start, c) - when false: echo "leave: ", p.nt.name - if result < 0: c.ml = oldMl - of pkSequence: - var oldMl = c.ml - result = 0 - assert(not isNil(p.sons)) - for i in 0..high(p.sons): - var x = rawMatch(s, p.sons[i], start+result, c) - if x < 0: - c.ml = oldMl - result = -1 - break - else: inc(result, x) - of pkOrderedChoice: - var oldMl = c.ml - for i in 0..high(p.sons): - result = rawMatch(s, p.sons[i], start, c) - if result >= 0: break - c.ml = oldMl - of pkSearch: - var oldMl = c.ml - result = 0 - while start+result < s.len: - var x = rawMatch(s, p.sons[0], start+result, c) - if x >= 0: - inc(result, x) - return - inc(result) - result = -1 - c.ml = oldMl - of pkCapturedSearch: - var idx = c.ml # reserve a slot for the subpattern - inc(c.ml) - result = 0 - while start+result < s.len: - var x = rawMatch(s, p.sons[0], start+result, c) - if x >= 0: - if idx < MaxSubpatterns: - c.matches[idx] = (start, start+result-1) - #else: silently ignore the capture - inc(result, x) - return - inc(result) - result = -1 - c.ml = idx - of pkGreedyRep: - result = 0 - while true: - var x = rawMatch(s, p.sons[0], start+result, c) - # if x == 0, we have an endless loop; so the correct behaviour would be - # not to break. But endless loops can be easily introduced: - # ``(comment / \w*)*`` is such an example. Breaking for x == 0 does the - # expected thing in this case. - if x <= 0: break - inc(result, x) - of pkGreedyRepChar: - result = 0 - var ch = p.ch - while ch == s[start+result]: inc(result) - of pkGreedyRepSet: - result = 0 - while contains(p.charChoice[], s[start+result]): inc(result) - of pkOption: - result = max(0, rawMatch(s, p.sons[0], start, c)) - of pkAndPredicate: - var oldMl = c.ml - result = rawMatch(s, p.sons[0], start, c) - if result >= 0: result = 0 # do not consume anything - else: c.ml = oldMl - of pkNotPredicate: - var oldMl = c.ml - result = rawMatch(s, p.sons[0], start, c) - if result < 0: result = 0 - else: - c.ml = oldMl - result = -1 - of pkCapture: - var idx = c.ml # reserve a slot for the subpattern - inc(c.ml) - result = rawMatch(s, p.sons[0], start, c) - if result >= 0: - if idx < MaxSubpatterns: - c.matches[idx] = (start, start+result-1) - #else: silently ignore the capture - else: - c.ml = idx - of pkBackRef..pkBackRefIgnoreStyle: - if p.index >= c.ml: return -1 - var (a, b) = c.matches[p.index] - var n: TPeg - n.kind = succ(pkTerminal, ord(p.kind)-ord(pkBackRef)) - n.term = s.substr(a, b) - result = rawMatch(s, n, start, c) - of pkStartAnchor: - if c.origStart == start: result = 0 - else: result = -1 - of pkRule, pkList: assert false - -proc match*(s: string, pattern: TPeg, matches: var openarray[string], - start = 0): bool {.rtl, extern: "npegs$1Capture".} = - ## returns ``true`` if ``s[start..]`` matches the ``pattern`` and - ## the captured substrings in the array ``matches``. If it does not - ## match, nothing is written into ``matches`` and ``false`` is - ## returned. - var c: TCaptures - c.origStart = start - result = rawMatch(s, pattern, start, c) == len(s)-start - if result: - for i in 0..c.ml-1: - matches[i] = substr(s, c.matches[i][0], c.matches[i][1]) - -proc match*(s: string, pattern: TPeg, - start = 0): bool {.rtl, extern: "npegs$1".} = - ## returns ``true`` if ``s`` matches the ``pattern`` beginning from ``start``. - var c: TCaptures - c.origStart = start - result = rawMatch(s, pattern, start, c) == len(s)-start - -proc matchLen*(s: string, pattern: TPeg, matches: var openarray[string], - start = 0): int {.rtl, extern: "npegs$1Capture".} = - ## the same as ``match``, but it returns the length of the match, - ## if there is no match, -1 is returned. Note that a match length - ## of zero can happen. It's possible that a suffix of `s` remains - ## that does not belong to the match. - var c: TCaptures - c.origStart = start - result = rawMatch(s, pattern, start, c) - if result >= 0: - for i in 0..c.ml-1: - matches[i] = substr(s, c.matches[i][0], c.matches[i][1]) - -proc matchLen*(s: string, pattern: TPeg, - start = 0): int {.rtl, extern: "npegs$1".} = - ## the same as ``match``, but it returns the length of the match, - ## if there is no match, -1 is returned. Note that a match length - ## of zero can happen. It's possible that a suffix of `s` remains - ## that does not belong to the match. - var c: TCaptures - c.origStart = start - result = rawMatch(s, pattern, start, c) - -proc find*(s: string, pattern: TPeg, matches: var openarray[string], - start = 0): int {.rtl, extern: "npegs$1Capture".} = - ## returns the starting position of ``pattern`` in ``s`` and the captured - ## substrings in the array ``matches``. If it does not match, nothing - ## is written into ``matches`` and -1 is returned. - for i in start .. s.len-1: - if matchLen(s, pattern, matches, i) >= 0: return i - return -1 - # could also use the pattern here: (!P .)* P - -proc findBounds*(s: string, pattern: TPeg, matches: var openarray[string], - start = 0): tuple[first, last: int] {. - rtl, extern: "npegs$1Capture".} = - ## returns the starting position and end position of ``pattern`` in ``s`` - ## and the captured - ## substrings in the array ``matches``. If it does not match, nothing - ## is written into ``matches`` and (-1,0) is returned. - for i in start .. s.len-1: - var L = matchLen(s, pattern, matches, i) - if L >= 0: return (i, i+L-1) - return (-1, 0) - -proc find*(s: string, pattern: TPeg, - start = 0): int {.rtl, extern: "npegs$1".} = - ## returns the starting position of ``pattern`` in ``s``. If it does not - ## match, -1 is returned. - for i in start .. s.len-1: - if matchLen(s, pattern, i) >= 0: return i - return -1 - -iterator findAll*(s: string, pattern: TPeg, start = 0): string = - ## yields all matching captures of pattern in `s`. - var matches: array[0..MaxSubpatterns-1, string] - var i = start - while i < s.len: - var L = matchLen(s, pattern, matches, i) - if L < 0: break - for k in 0..MaxSubPatterns-1: - if isNil(matches[k]): break - yield matches[k] - inc(i, L) - -proc findAll*(s: string, pattern: TPeg, start = 0): seq[string] {. - rtl, extern: "npegs$1".} = - ## returns all matching captures of pattern in `s`. - ## If it does not match, @[] is returned. - accumulateResult(findAll(s, pattern, start)) - -template `=~`*(s: string, pattern: TPeg): untyped = - ## This calls ``match`` with an implicit declared ``matches`` array that - ## can be used in the scope of the ``=~`` call: - ## - ## .. code-block:: nim - ## - ## if line =~ peg"\s* {\w+} \s* '=' \s* {\w+}": - ## # matches a key=value pair: - ## echo("Key: ", matches[0]) - ## echo("Value: ", matches[1]) - ## elif line =~ peg"\s*{'#'.*}": - ## # matches a comment - ## # note that the implicit ``matches`` array is different from the - ## # ``matches`` array of the first branch - ## echo("comment: ", matches[0]) - ## else: - ## echo("syntax error") - ## - when not declaredInScope(matches): - var matches {.inject.}: array[0..MaxSubpatterns-1, string] - match(s, pattern, matches) - -# ------------------------- more string handling ------------------------------ - -proc contains*(s: string, pattern: TPeg, start = 0): bool {. - rtl, extern: "npegs$1".} = - ## same as ``find(s, pattern, start) >= 0`` - return find(s, pattern, start) >= 0 - -proc contains*(s: string, pattern: TPeg, matches: var openArray[string], - start = 0): bool {.rtl, extern: "npegs$1Capture".} = - ## same as ``find(s, pattern, matches, start) >= 0`` - return find(s, pattern, matches, start) >= 0 - -proc startsWith*(s: string, prefix: TPeg, start = 0): bool {. - rtl, extern: "npegs$1".} = - ## returns true if `s` starts with the pattern `prefix` - result = matchLen(s, prefix, start) >= 0 - -proc endsWith*(s: string, suffix: TPeg, start = 0): bool {. - rtl, extern: "npegs$1".} = - ## returns true if `s` ends with the pattern `prefix` - for i in start .. s.len-1: - if matchLen(s, suffix, i) == s.len - i: return true - -proc replacef*(s: string, sub: TPeg, by: string): string {. - rtl, extern: "npegs$1".} = - ## Replaces `sub` in `s` by the string `by`. Captures can be accessed in `by` - ## with the notation ``$i`` and ``$#`` (see strutils.`%`). Examples: - ## - ## .. code-block:: nim - ## "var1=key; var2=key2".replace(peg"{\ident}'='{\ident}", "$1<-$2$2") - ## - ## Results in: - ## - ## .. code-block:: nim - ## - ## "var1<-keykey; val2<-key2key2" - result = "" - var i = 0 - var caps: array[0..MaxSubpatterns-1, string] - while i < s.len: - var x = matchLen(s, sub, caps, i) - if x <= 0: - add(result, s[i]) - inc(i) - else: - addf(result, by, caps) - inc(i, x) - add(result, substr(s, i)) - -proc replace*(s: string, sub: TPeg, by = ""): string {. - rtl, extern: "npegs$1".} = - ## Replaces `sub` in `s` by the string `by`. Captures cannot be accessed - ## in `by`. - result = "" - var i = 0 - var caps: array[0..MaxSubpatterns-1, string] - while i < s.len: - var x = matchLen(s, sub, caps, i) - if x <= 0: - add(result, s[i]) - inc(i) - else: - addf(result, by, caps) - inc(i, x) - add(result, substr(s, i)) - -proc parallelReplace*(s: string, subs: varargs[ - tuple[pattern: TPeg, repl: string]]): string {. - rtl, extern: "npegs$1".} = - ## Returns a modified copy of `s` with the substitutions in `subs` - ## applied in parallel. - result = "" - var i = 0 - var caps: array[0..MaxSubpatterns-1, string] - while i < s.len: - block searchSubs: - for j in 0..high(subs): - var x = matchLen(s, subs[j][0], caps, i) - if x > 0: - addf(result, subs[j][1], caps) - inc(i, x) - break searchSubs - add(result, s[i]) - inc(i) - # copy the rest: - add(result, substr(s, i)) - -proc transformFile*(infile, outfile: string, - subs: varargs[tuple[pattern: TPeg, repl: string]]) {. - rtl, extern: "npegs$1".} = - ## reads in the file `infile`, performs a parallel replacement (calls - ## `parallelReplace`) and writes back to `outfile`. Calls ``quit`` if an - ## error occurs. This is supposed to be used for quick scripting. - var x = readFile(infile) - if not isNil(x): - var f: File - if open(f, outfile, fmWrite): - write(f, x.parallelReplace(subs)) - close(f) - else: - quit("cannot open for writing: " & outfile) - else: - quit("cannot open for reading: " & infile) - -iterator split*(s: string, sep: TPeg): string = - ## Splits the string `s` into substrings. - ## - ## Substrings are separated by the PEG `sep`. - ## Examples: - ## - ## .. code-block:: nim - ## for word in split("00232this02939is39an22example111", peg"\d+"): - ## writeLine(stdout, word) - ## - ## Results in: - ## - ## .. code-block:: nim - ## "this" - ## "is" - ## "an" - ## "example" - ## - var - first = 0 - last = 0 - while last < len(s): - var x = matchLen(s, sep, last) - if x > 0: inc(last, x) - first = last - while last < len(s): - inc(last) - x = matchLen(s, sep, last) - if x > 0: break - if first < last: - yield substr(s, first, last-1) - -proc split*(s: string, sep: TPeg): seq[string] {. - rtl, extern: "npegs$1".} = - ## Splits the string `s` into substrings. - accumulateResult(split(s, sep)) - -# ------------------- scanner ------------------------------------------------- - -type - TModifier = enum - modNone, - modVerbatim, - modIgnoreCase, - modIgnoreStyle - TTokKind = enum ## enumeration of all tokens - tkInvalid, ## invalid token - tkEof, ## end of file reached - tkAny, ## . - tkAnyRune, ## _ - tkIdentifier, ## abc - tkStringLit, ## "abc" or 'abc' - tkCharSet, ## [^A-Z] - tkParLe, ## '(' - tkParRi, ## ')' - tkCurlyLe, ## '{' - tkCurlyRi, ## '}' - tkCurlyAt, ## '{@}' - tkArrow, ## '<-' - tkBar, ## '/' - tkStar, ## '*' - tkPlus, ## '+' - tkAmp, ## '&' - tkNot, ## '!' - tkOption, ## '?' - tkAt, ## '@' - tkBuiltin, ## \identifier - tkEscaped, ## \\ - tkBackref, ## '$' - tkDollar, ## '$' - tkHat ## '^' - - TToken {.final.} = object ## a token - kind: TTokKind ## the type of the token - modifier: TModifier - literal: string ## the parsed (string) literal - charset: set[char] ## if kind == tkCharSet - index: int ## if kind == tkBackref - - TPegLexer {.inheritable.} = object ## the lexer object. - bufpos: int ## the current position within the buffer - buf: cstring ## the buffer itself - lineNumber: int ## the current line number - lineStart: int ## index of last line start in buffer - colOffset: int ## column to add - filename: string - -const - tokKindToStr: array[TTokKind, string] = [ - "invalid", "[EOF]", ".", "_", "identifier", "string literal", - "character set", "(", ")", "{", "}", "{@}", - "<-", "/", "*", "+", "&", "!", "?", - "@", "built-in", "escaped", "$", "$", "^" - ] - -proc HandleCR(L: var TPegLexer, pos: int): int = - assert(L.buf[pos] == '\c') - inc(L.linenumber) - result = pos+1 - if L.buf[result] == '\L': inc(result) - L.lineStart = result - -proc HandleLF(L: var TPegLexer, pos: int): int = - assert(L.buf[pos] == '\L') - inc(L.linenumber) - result = pos+1 - L.lineStart = result - -proc init(L: var TPegLexer, input, filename: string, line = 1, col = 0) = - L.buf = input - L.bufpos = 0 - L.lineNumber = line - L.colOffset = col - L.lineStart = 0 - L.filename = filename - -proc getColumn(L: TPegLexer): int {.inline.} = - result = abs(L.bufpos - L.lineStart) + L.colOffset - -proc getLine(L: TPegLexer): int {.inline.} = - result = L.linenumber - -proc errorStr(L: TPegLexer, msg: string, line = -1, col = -1): string = - var line = if line < 0: getLine(L) else: line - var col = if col < 0: getColumn(L) else: col - result = "$1($2, $3) Error: $4" % [L.filename, $line, $col, msg] - -proc handleHexChar(c: var TPegLexer, xi: var int) = - case c.buf[c.bufpos] - of '0'..'9': - xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('0')) - inc(c.bufpos) - of 'a'..'f': - xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('a') + 10) - inc(c.bufpos) - of 'A'..'F': - xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('A') + 10) - inc(c.bufpos) - else: discard - -proc getEscapedChar(c: var TPegLexer, tok: var TToken) = - inc(c.bufpos) - case c.buf[c.bufpos] - of 'r', 'R', 'c', 'C': - add(tok.literal, '\c') - inc(c.bufpos) - of 'l', 'L': - add(tok.literal, '\L') - inc(c.bufpos) - of 'f', 'F': - add(tok.literal, '\f') - inc(c.bufpos) - of 'e', 'E': - add(tok.literal, '\e') - inc(c.bufpos) - of 'a', 'A': - add(tok.literal, '\a') - inc(c.bufpos) - of 'b', 'B': - add(tok.literal, '\b') - inc(c.bufpos) - of 'v', 'V': - add(tok.literal, '\v') - inc(c.bufpos) - of 't', 'T': - add(tok.literal, '\t') - inc(c.bufpos) - of 'x', 'X': - inc(c.bufpos) - var xi = 0 - handleHexChar(c, xi) - handleHexChar(c, xi) - if xi == 0: tok.kind = tkInvalid - else: add(tok.literal, chr(xi)) - of '0'..'9': - var val = ord(c.buf[c.bufpos]) - ord('0') - inc(c.bufpos) - var i = 1 - while (i <= 3) and (c.buf[c.bufpos] in {'0'..'9'}): - val = val * 10 + ord(c.buf[c.bufpos]) - ord('0') - inc(c.bufpos) - inc(i) - if val > 0 and val <= 255: add(tok.literal, chr(val)) - else: tok.kind = tkInvalid - of '\0'..'\31': - tok.kind = tkInvalid - elif c.buf[c.bufpos] in strutils.Letters: - tok.kind = tkInvalid - else: - add(tok.literal, c.buf[c.bufpos]) - inc(c.bufpos) - -proc skip(c: var TPegLexer) = - var pos = c.bufpos - var buf = c.buf - while true: - case buf[pos] - of ' ', '\t': - inc(pos) - of '#': - while not (buf[pos] in {'\c', '\L', '\0'}): inc(pos) - of '\c': - pos = HandleCR(c, pos) - buf = c.buf - of '\L': - pos = HandleLF(c, pos) - buf = c.buf - else: - break # EndOfFile also leaves the loop - c.bufpos = pos - -proc getString(c: var TPegLexer, tok: var TToken) = - tok.kind = tkStringLit - var pos = c.bufPos + 1 - var buf = c.buf - var quote = buf[pos-1] - while true: - case buf[pos] - of '\\': - c.bufpos = pos - getEscapedChar(c, tok) - pos = c.bufpos - of '\c', '\L', '\0': - tok.kind = tkInvalid - break - elif buf[pos] == quote: - inc(pos) - break - else: - add(tok.literal, buf[pos]) - inc(pos) - c.bufpos = pos - -proc getDollar(c: var TPegLexer, tok: var TToken) = - var pos = c.bufPos + 1 - var buf = c.buf - if buf[pos] in {'0'..'9'}: - tok.kind = tkBackref - tok.index = 0 - while buf[pos] in {'0'..'9'}: - tok.index = tok.index * 10 + ord(buf[pos]) - ord('0') - inc(pos) - else: - tok.kind = tkDollar - c.bufpos = pos - -proc getCharSet(c: var TPegLexer, tok: var TToken) = - tok.kind = tkCharSet - tok.charset = {} - var pos = c.bufPos + 1 - var buf = c.buf - var caret = false - if buf[pos] == '^': - inc(pos) - caret = true - while true: - var ch: char - case buf[pos] - of ']': - inc(pos) - break - of '\\': - c.bufpos = pos - getEscapedChar(c, tok) - pos = c.bufpos - ch = tok.literal[tok.literal.len-1] - of '\C', '\L', '\0': - tok.kind = tkInvalid - break - else: - ch = buf[pos] - inc(pos) - incl(tok.charset, ch) - if buf[pos] == '-': - if buf[pos+1] == ']': - incl(tok.charset, '-') - inc(pos) - else: - inc(pos) - var ch2: char - case buf[pos] - of '\\': - c.bufpos = pos - getEscapedChar(c, tok) - pos = c.bufpos - ch2 = tok.literal[tok.literal.len-1] - of '\C', '\L', '\0': - tok.kind = tkInvalid - break - else: - ch2 = buf[pos] - inc(pos) - for i in ord(ch)+1 .. ord(ch2): - incl(tok.charset, chr(i)) - c.bufpos = pos - if caret: tok.charset = {'\1'..'\xFF'} - tok.charset - -proc getSymbol(c: var TPegLexer, tok: var TToken) = - var pos = c.bufpos - var buf = c.buf - while true: - add(tok.literal, buf[pos]) - inc(pos) - if buf[pos] notin strutils.IdentChars: break - c.bufpos = pos - tok.kind = tkIdentifier - -proc getBuiltin(c: var TPegLexer, tok: var TToken) = - if c.buf[c.bufpos+1] in strutils.Letters: - inc(c.bufpos) - getSymbol(c, tok) - tok.kind = tkBuiltin - else: - tok.kind = tkEscaped - getEscapedChar(c, tok) # may set tok.kind to tkInvalid - -proc getTok(c: var TPegLexer, tok: var TToken) = - tok.kind = tkInvalid - tok.modifier = modNone - setlen(tok.literal, 0) - skip(c) - case c.buf[c.bufpos] - of '{': - inc(c.bufpos) - if c.buf[c.bufpos] == '@' and c.buf[c.bufpos+1] == '}': - tok.kind = tkCurlyAt - inc(c.bufpos, 2) - add(tok.literal, "{@}") - else: - tok.kind = tkCurlyLe - add(tok.literal, '{') - of '}': - tok.kind = tkCurlyRi - inc(c.bufpos) - add(tok.literal, '}') - of '[': - getCharset(c, tok) - of '(': - tok.kind = tkParLe - inc(c.bufpos) - add(tok.literal, '(') - of ')': - tok.kind = tkParRi - inc(c.bufpos) - add(tok.literal, ')') - of '.': - tok.kind = tkAny - inc(c.bufpos) - add(tok.literal, '.') - of '_': - tok.kind = tkAnyRune - inc(c.bufpos) - add(tok.literal, '_') - of '\\': - getBuiltin(c, tok) - of '\'', '"': getString(c, tok) - of '$': getDollar(c, tok) - of '\0': - tok.kind = tkEof - tok.literal = "[EOF]" - of 'a'..'z', 'A'..'Z', '\128'..'\255': - getSymbol(c, tok) - if c.buf[c.bufpos] in {'\'', '"'} or - c.buf[c.bufpos] == '$' and c.buf[c.bufpos+1] in {'0'..'9'}: - case tok.literal - of "i": tok.modifier = modIgnoreCase - of "y": tok.modifier = modIgnoreStyle - of "v": tok.modifier = modVerbatim - else: discard - setLen(tok.literal, 0) - if c.buf[c.bufpos] == '$': - getDollar(c, tok) - else: - getString(c, tok) - if tok.modifier == modNone: tok.kind = tkInvalid - of '+': - tok.kind = tkPlus - inc(c.bufpos) - add(tok.literal, '+') - of '*': - tok.kind = tkStar - inc(c.bufpos) - add(tok.literal, '+') - of '<': - if c.buf[c.bufpos+1] == '-': - inc(c.bufpos, 2) - tok.kind = tkArrow - add(tok.literal, "<-") - else: - add(tok.literal, '<') - of '/': - tok.kind = tkBar - inc(c.bufpos) - add(tok.literal, '/') - of '?': - tok.kind = tkOption - inc(c.bufpos) - add(tok.literal, '?') - of '!': - tok.kind = tkNot - inc(c.bufpos) - add(tok.literal, '!') - of '&': - tok.kind = tkAmp - inc(c.bufpos) - add(tok.literal, '!') - of '@': - tok.kind = tkAt - inc(c.bufpos) - add(tok.literal, '@') - if c.buf[c.bufpos] == '@': - tok.kind = tkCurlyAt - inc(c.bufpos) - add(tok.literal, '@') - of '^': - tok.kind = tkHat - inc(c.bufpos) - add(tok.literal, '^') - else: - add(tok.literal, c.buf[c.bufpos]) - inc(c.bufpos) - -proc arrowIsNextTok(c: TPegLexer): bool = - # the only look ahead we need - var pos = c.bufpos - while c.buf[pos] in {'\t', ' '}: inc(pos) - result = c.buf[pos] == '<' and c.buf[pos+1] == '-' - -# ----------------------------- parser ---------------------------------------- - -type - EInvalidPeg* = object of ValueError ## raised if an invalid - ## PEG has been detected - TPegParser = object of TPegLexer ## the PEG parser object - tok: TToken - nonterms: seq[PNonTerminal] - modifier: TModifier - captures: int - identIsVerbatim: bool - skip: TPeg - -proc pegError(p: TPegParser, msg: string, line = -1, col = -1) = - var e: ref EInvalidPeg - new(e) - e.msg = errorStr(p, msg, line, col) - raise e - -proc getTok(p: var TPegParser) = - getTok(p, p.tok) - if p.tok.kind == tkInvalid: pegError(p, "invalid token") - -proc eat(p: var TPegParser, kind: TTokKind) = - if p.tok.kind == kind: getTok(p) - else: pegError(p, tokKindToStr[kind] & " expected") - -proc parseExpr(p: var TPegParser): TPeg - -proc getNonTerminal(p: var TPegParser, name: string): PNonTerminal = - for i in 0..high(p.nonterms): - result = p.nonterms[i] - if cmpIgnoreStyle(result.name, name) == 0: return - # forward reference: - result = newNonTerminal(name, getLine(p), getColumn(p)) - add(p.nonterms, result) - -proc modifiedTerm(s: string, m: TModifier): TPeg = - case m - of modNone, modVerbatim: result = term(s) - of modIgnoreCase: result = termIgnoreCase(s) - of modIgnoreStyle: result = termIgnoreStyle(s) - -proc modifiedBackref(s: int, m: TModifier): TPeg = - case m - of modNone, modVerbatim: result = backRef(s) - of modIgnoreCase: result = backRefIgnoreCase(s) - of modIgnoreStyle: result = backRefIgnoreStyle(s) - -proc builtin(p: var TPegParser): TPeg = - # do not use "y", "skip" or "i" as these would be ambiguous - case p.tok.literal - of "n": result = newLine() - of "d": result = charset({'0'..'9'}) - of "D": result = charset({'\1'..'\xff'} - {'0'..'9'}) - of "s": result = charset({' ', '\9'..'\13'}) - of "S": result = charset({'\1'..'\xff'} - {' ', '\9'..'\13'}) - of "w": result = charset({'a'..'z', 'A'..'Z', '_', '0'..'9'}) - of "W": result = charset({'\1'..'\xff'} - {'a'..'z','A'..'Z','_','0'..'9'}) - of "a": result = charset({'a'..'z', 'A'..'Z'}) - of "A": result = charset({'\1'..'\xff'} - {'a'..'z', 'A'..'Z'}) - of "ident": result = tpegs.ident - of "letter": result = UnicodeLetter() - of "upper": result = UnicodeUpper() - of "lower": result = UnicodeLower() - of "title": result = UnicodeTitle() - of "white": result = UnicodeWhitespace() - else: pegError(p, "unknown built-in: " & p.tok.literal) - -proc token(terminal: TPeg, p: TPegParser): TPeg = - if p.skip.kind == pkEmpty: result = terminal - else: result = sequence(p.skip, terminal) - -proc primary(p: var TPegParser): TPeg = - case p.tok.kind - of tkAmp: - getTok(p) - return &primary(p) - of tkNot: - getTok(p) - return !primary(p) - of tkAt: - getTok(p) - return !*primary(p) - of tkCurlyAt: - getTok(p) - return !*\primary(p).token(p) - else: discard - case p.tok.kind - of tkIdentifier: - if p.identIsVerbatim: - var m = p.tok.modifier - if m == modNone: m = p.modifier - result = modifiedTerm(p.tok.literal, m).token(p) - getTok(p) - elif not arrowIsNextTok(p): - var nt = getNonTerminal(p, p.tok.literal) - incl(nt.flags, ntUsed) - result = nonTerminal(nt).token(p) - getTok(p) - else: - pegError(p, "expression expected, but found: " & p.tok.literal) - of tkStringLit: - var m = p.tok.modifier - if m == modNone: m = p.modifier - result = modifiedTerm(p.tok.literal, m).token(p) - getTok(p) - of tkCharSet: - if '\0' in p.tok.charset: - pegError(p, "binary zero ('\\0') not allowed in character class") - result = charset(p.tok.charset).token(p) - getTok(p) - of tkParLe: - getTok(p) - result = parseExpr(p) - eat(p, tkParRi) - of tkCurlyLe: - getTok(p) - result = capture(parseExpr(p)).token(p) - eat(p, tkCurlyRi) - inc(p.captures) - of tkAny: - result = any().token(p) - getTok(p) - of tkAnyRune: - result = anyRune().token(p) - getTok(p) - of tkBuiltin: - result = builtin(p).token(p) - getTok(p) - of tkEscaped: - result = term(p.tok.literal[0]).token(p) - getTok(p) - of tkDollar: - result = endAnchor() - getTok(p) - of tkHat: - result = startAnchor() - getTok(p) - of tkBackref: - var m = p.tok.modifier - if m == modNone: m = p.modifier - result = modifiedBackRef(p.tok.index, m).token(p) - if p.tok.index < 0 or p.tok.index > p.captures: - pegError(p, "invalid back reference index: " & $p.tok.index) - getTok(p) - else: - pegError(p, "expression expected, but found: " & p.tok.literal) - getTok(p) # we must consume a token here to prevent endless loops! - while true: - case p.tok.kind - of tkOption: - result = ?result - getTok(p) - of tkStar: - result = *result - getTok(p) - of tkPlus: - result = +result - getTok(p) - else: break - -proc seqExpr(p: var TPegParser): TPeg = - result = primary(p) - while true: - case p.tok.kind - of tkAmp, tkNot, tkAt, tkStringLit, tkCharset, tkParLe, tkCurlyLe, - tkAny, tkAnyRune, tkBuiltin, tkEscaped, tkDollar, tkBackref, - tkHat, tkCurlyAt: - result = sequence(result, primary(p)) - of tkIdentifier: - if not arrowIsNextTok(p): - result = sequence(result, primary(p)) - else: break - else: break - -proc parseExpr(p: var TPegParser): TPeg = - result = seqExpr(p) - while p.tok.kind == tkBar: - getTok(p) - result = result / seqExpr(p) - -proc parseRule(p: var TPegParser): PNonTerminal = - if p.tok.kind == tkIdentifier and arrowIsNextTok(p): - result = getNonTerminal(p, p.tok.literal) - if ntDeclared in result.flags: - pegError(p, "attempt to redefine: " & result.name) - result.line = getLine(p) - result.col = getColumn(p) - getTok(p) - eat(p, tkArrow) - result.rule = parseExpr(p) - incl(result.flags, ntDeclared) # NOW inlining may be attempted - else: - pegError(p, "rule expected, but found: " & p.tok.literal) - -proc rawParse(p: var TPegParser): TPeg = - ## parses a rule or a PEG expression - while p.tok.kind == tkBuiltin: - case p.tok.literal - of "i": - p.modifier = modIgnoreCase - getTok(p) - of "y": - p.modifier = modIgnoreStyle - getTok(p) - of "skip": - getTok(p) - p.skip = ?primary(p) - else: break - if p.tok.kind == tkIdentifier and arrowIsNextTok(p): - result = parseRule(p).rule - while p.tok.kind != tkEof: - discard parseRule(p) - else: - p.identIsVerbatim = true - result = parseExpr(p) - if p.tok.kind != tkEof: - pegError(p, "EOF expected, but found: " & p.tok.literal) - for i in 0..high(p.nonterms): - var nt = p.nonterms[i] - if ntDeclared notin nt.flags: - pegError(p, "undeclared identifier: " & nt.name, nt.line, nt.col) - elif ntUsed notin nt.flags and i > 0: - pegError(p, "unused rule: " & nt.name, nt.line, nt.col) - -proc parsePeg*(pattern: string, filename = "pattern", line = 1, col = 0): TPeg = - ## constructs a TPeg object from `pattern`. `filename`, `line`, `col` are - ## used for error messages, but they only provide start offsets. `parsePeg` - ## keeps track of line and column numbers within `pattern`. - var p: TPegParser - init(TPegLexer(p), pattern, filename, line, col) - p.tok.kind = tkInvalid - p.tok.modifier = modNone - p.tok.literal = "" - p.tok.charset = {} - p.nonterms = @[] - p.identIsVerbatim = false - getTok(p) - result = rawParse(p) - -proc peg*(pattern: string): TPeg = - ## constructs a TPeg object from the `pattern`. The short name has been - ## chosen to encourage its use as a raw string modifier:: - ## - ## peg"{\ident} \s* '=' \s* {.*}" - result = parsePeg(pattern, "pattern") - -proc escapePeg*(s: string): string = - ## escapes `s` so that it is matched verbatim when used as a peg. - result = "" - var inQuote = false - for c in items(s): - case c - of '\0'..'\31', '\'', '"', '\\': - if inQuote: - result.add('\'') - inQuote = false - result.add("\\x") - result.add(toHex(ord(c), 2)) - else: - if not inQuote: - result.add('\'') - inQuote = true - result.add(c) - if inQuote: result.add('\'') - -when isMainModule: - doAssert escapePeg("abc''def'") == r"'abc'\x27\x27'def'\x27" - #doAssert match("(a b c)", peg"'(' @ ')'") - doAssert match("W_HI_Le", peg"\y 'while'") - doAssert(not match("W_HI_L", peg"\y 'while'")) - doAssert(not match("W_HI_Le", peg"\y v'while'")) - doAssert match("W_HI_Le", peg"y'while'") - - doAssert($ +digits == $peg"\d+") - doAssert "0158787".match(peg"\d+") - doAssert "ABC 0232".match(peg"\w+\s+\d+") - doAssert "ABC".match(peg"\d+ / \w+") - - for word in split("00232this02939is39an22example111", peg"\d+"): - writeLine(stdout, word) - - doAssert matchLen("key", ident) == 3 - - var pattern = sequence(ident, *whitespace, term('='), *whitespace, ident) - doAssert matchLen("key1= cal9", pattern) == 11 - - var ws = newNonTerminal("ws", 1, 1) - ws.rule = *whitespace - - var expr = newNonTerminal("expr", 1, 1) - expr.rule = sequence(capture(ident), *sequence( - nonterminal(ws), term('+'), nonterminal(ws), nonterminal(expr))) - - var c: TCaptures - var s = "a+b + c +d+e+f" - doAssert rawMatch(s, expr.rule, 0, c) == len(s) - var a = "" - for i in 0..c.ml-1: - a.add(substr(s, c.matches[i][0], c.matches[i][1])) - doAssert a == "abcdef" - #echo expr.rule - - #const filename = "lib/devel/peg/grammar.txt" - #var grammar = parsePeg(newFileStream(filename, fmRead), filename) - #echo "a <- [abc]*?".match(grammar) - doAssert find("_____abc_______", term("abc"), 2) == 5 - doAssert match("_______ana", peg"A <- 'ana' / . A") - doAssert match("abcs%%%", peg"A <- ..A / .A / '%'") - - if "abc" =~ peg"{'a'}'bc' 'xyz' / {\ident}": - doAssert matches[0] == "abc" - else: - doAssert false - - var g2 = peg"""S <- A B / C D - A <- 'a'+ - B <- 'b'+ - C <- 'c'+ - D <- 'd'+ - """ - doAssert($g2 == "((A B) / (C D))") - doAssert match("cccccdddddd", g2) - doAssert("var1=key; var2=key2".replacef(peg"{\ident}'='{\ident}", "$1<-$2$2") == - "var1<-keykey; var2<-key2key2") - doAssert "var1=key; var2=key2".endsWith(peg"{\ident}'='{\ident}") - - if "aaaaaa" =~ peg"'aa' !. / ({'a'})+": - doAssert matches[0] == "a" - else: - doAssert false - - block: - var matches: array[0..2, string] - if match("abcdefg", peg"c {d} ef {g}", matches, 2): - doAssert matches[0] == "d" - doAssert matches[1] == "g" - else: - doAssert false - - for x in findAll("abcdef", peg"{.}", 3): - echo x - - if "f(a, b)" =~ peg"{[0-9]+} / ({\ident} '(' {@} ')')": - doAssert matches[0] == "f" - doAssert matches[1] == "a, b" - else: - doAssert false - - doAssert match("eine übersicht und außerdem", peg"(\letter \white*)+") - # ß is not a lower cased letter?! - doAssert match("eine übersicht und auerdem", peg"(\lower \white*)+") - doAssert match("EINE ÜBERSICHT UND AUSSERDEM", peg"(\upper \white*)+") - doAssert(not match("456678", peg"(\letter)+")) - - doAssert("var1 = key; var2 = key2".replacef( - peg"\skip(\s*) {\ident}'='{\ident}", "$1<-$2$2") == - "var1<-keykey;var2<-key2key2") - - doAssert match("prefix/start", peg"^start$", 7) - - # tricky test to check for false aliasing: - block: - var a = term"key" - echo($sequence(sequence(a, term"value"), *a)) - diff --git a/tests/stdlib/tstreams3.nim b/tests/stdlib/tstreams3.nim new file mode 100644 index 000000000..b2c9170e3 --- /dev/null +++ b/tests/stdlib/tstreams3.nim @@ -0,0 +1,10 @@ +discard """ + file: "tstreams3.nim" + output: "threw exception" +""" +import streams + +try: + var fs = openFileStream("shouldneverexist.txt") +except IoError: + echo "threw exception" diff --git a/tests/stdlib/tstrformat.nim b/tests/stdlib/tstrformat.nim new file mode 100644 index 000000000..db76899d4 --- /dev/null +++ b/tests/stdlib/tstrformat.nim @@ -0,0 +1,56 @@ +discard """ + action: "run" +""" + +import strformat + +type Obj = object + +proc `$`(o: Obj): string = "foobar" + +var o: Obj +doAssert fmt"{o}" == "foobar" +doAssert fmt"{o:10}" == "foobar " + +# see issue #7933 +var str = "abc" +doAssert fmt">7.1 :: {str:>7.1}" == ">7.1 :: a" +doAssert fmt">7.2 :: {str:>7.2}" == ">7.2 :: ab" +doAssert fmt">7.3 :: {str:>7.3}" == ">7.3 :: abc" +doAssert fmt">7.9 :: {str:>7.9}" == ">7.9 :: abc" +doAssert fmt">7.0 :: {str:>7.0}" == ">7.0 :: " +doAssert fmt" 7.1 :: {str:7.1}" == " 7.1 :: a " +doAssert fmt" 7.2 :: {str:7.2}" == " 7.2 :: ab " +doAssert fmt" 7.3 :: {str:7.3}" == " 7.3 :: abc " +doAssert fmt" 7.9 :: {str:7.9}" == " 7.9 :: abc " +doAssert fmt" 7.0 :: {str:7.0}" == " 7.0 :: " +doAssert fmt"^7.1 :: {str:^7.1}" == "^7.1 :: a " +doAssert fmt"^7.2 :: {str:^7.2}" == "^7.2 :: ab " +doAssert fmt"^7.3 :: {str:^7.3}" == "^7.3 :: abc " +doAssert fmt"^7.9 :: {str:^7.9}" == "^7.9 :: abc " +doAssert fmt"^7.0 :: {str:^7.0}" == "^7.0 :: " +str = "äöüe\u0309\u0319o\u0307\u0359" +doAssert fmt"^7.1 :: {str:^7.1}" == "^7.1 :: ä " +doAssert fmt"^7.2 :: {str:^7.2}" == "^7.2 :: äö " +doAssert fmt"^7.3 :: {str:^7.3}" == "^7.3 :: äöü " +doAssert fmt"^7.0 :: {str:^7.0}" == "^7.0 :: " +# this is actually wrong, but the unicode module has no support for graphemes +doAssert fmt"^7.4 :: {str:^7.4}" == "^7.4 :: äöüe " +doAssert fmt"^7.9 :: {str:^7.9}" == "^7.9 :: äöüe\u0309\u0319o\u0307\u0359" + +# see issue #7932 +doAssert fmt"{15:08}" == "00000015" # int, works +doAssert fmt"{1.5:08}" == "000001.5" # float, works +doAssert fmt"{1.5:0>8}" == "000001.5" # workaround using fill char works for positive floats +doAssert fmt"{-1.5:0>8}" == "0000-1.5" # even that does not work for negative floats +doAssert fmt"{-1.5:08}" == "-00001.5" # works +doAssert fmt"{1.5:+08}" == "+00001.5" # works +doAssert fmt"{1.5: 08}" == " 00001.5" # works + +# only add explicitly requested sign if value != -0.0 (neg zero) +doAssert fmt"{-0.0:g}" == "-0" +doassert fmt"{-0.0:+g}" == "-0" +doassert fmt"{-0.0: g}" == "-0" +doAssert fmt"{0.0:g}" == "0" +doAssert fmt"{0.0:+g}" == "+0" +doAssert fmt"{0.0: g}" == " 0" diff --git a/tests/stdlib/tstrutil.nim b/tests/stdlib/tstrutil.nim index 071dae5a7..6f78a91ac 100644 --- a/tests/stdlib/tstrutil.nim +++ b/tests/stdlib/tstrutil.nim @@ -229,6 +229,24 @@ assert "/1/2/3".rfind('0') == -1 assert(toHex(100i16, 32) == "00000000000000000000000000000064") assert(toHex(-100i16, 32) == "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9C") +assert "".parseHexStr == "" +assert "00Ff80".parseHexStr == "\0\xFF\x80" +try: + discard "00Ff8".parseHexStr + assert false, "Should raise ValueError" +except ValueError: + discard + +try: + discard "0k".parseHexStr + assert false, "Should raise ValueError" +except ValueError: + discard + +assert "".toHex == "" +assert "\x00\xFF\x80".toHex == "00FF80" +assert "0123456789abcdef".parseHexStr.toHex == "0123456789ABCDEF" + assert(' '.repeat(8)== " ") assert(" ".repeat(8) == " ") assert(spaces(8) == " ") diff --git a/tests/stdlib/ttimes.nim b/tests/stdlib/ttimes.nim index a6ac186cc..4ab3ba581 100644 --- a/tests/stdlib/ttimes.nim +++ b/tests/stdlib/ttimes.nim @@ -28,6 +28,12 @@ t.checkFormat("d dd ddd dddd h hh H HH m mm M MM MMM MMMM s" & t.checkFormat("yyyyMMddhhmmss", "20380119031407") +# issue 7620 +let t7620_am = parse("4/15/2017 12:01:02 AM +0", "M/d/yyyy' 'h:mm:ss' 'tt' 'z", utc()) +t7620_am.checkFormat("M/d/yyyy' 'h:mm:ss' 'tt' 'z", "4/15/2017 12:01:02 AM +0") +let t7620_pm = parse("4/15/2017 12:01:02 PM +0", "M/d/yyyy' 'h:mm:ss' 'tt' 'z", utc()) +t7620_pm.checkFormat("M/d/yyyy' 'h:mm:ss' 'tt' 'z", "4/15/2017 12:01:02 PM +0") + let t2 = fromUnix(160070789).utc # Mon 27 Jan 16:06:29 GMT 1975 t2.checkFormat("d dd ddd dddd h hh H HH m mm M MM MMM MMMM s" & " ss t tt y yy yyy yyyy yyyyy z zz zzz", @@ -37,8 +43,8 @@ var t4 = fromUnix(876124714).utc # Mon 6 Oct 08:58:34 BST 1997 t4.checkFormat("M MM MMM MMMM", "10 10 Oct October") # Interval tests -(t4 - initInterval(years = 2)).checkFormat("yyyy", "1995") -(t4 - initInterval(years = 7, minutes = 34, seconds = 24)).checkFormat("yyyy mm ss", "1990 24 10") +(t4 - initTimeInterval(years = 2)).checkFormat("yyyy", "1995") +(t4 - initTimeInterval(years = 7, minutes = 34, seconds = 24)).checkFormat("yyyy mm ss", "1990 24 10") # checking dayOfWeek matches known days doAssert getDayOfWeek(01, mJan, 0000) == dSat @@ -56,33 +62,15 @@ doAssert toUnix(toTime(t4L)) + t4L.utcOffset == toUnix(toTime(t4)) # adding intervals var - a1L = toUnix(toTime(t4L + initInterval(hours = 1))) + t4L.utcOffset + a1L = toUnix(toTime(t4L + initTimeInterval(hours = 1))) + t4L.utcOffset a1G = toUnix(toTime(t4)) + 60 * 60 doAssert a1L == a1G # subtracting intervals -a1L = toUnix(toTime(t4L - initInterval(hours = 1))) + t4L.utcOffset +a1L = toUnix(toTime(t4L - initTimeInterval(hours = 1))) + t4L.utcOffset a1G = toUnix(toTime(t4)) - (60 * 60) doAssert a1L == a1G -# add/subtract TimeIntervals and Time/TimeInfo -doAssert getTime() - 1.seconds == getTime() - 3.seconds + 2.seconds -doAssert getTime() + 65.seconds == getTime() + 1.minutes + 5.seconds -doAssert getTime() + 60.minutes == getTime() + 1.hours -doAssert getTime() + 24.hours == getTime() + 1.days -doAssert getTime() + 13.months == getTime() + 1.years + 1.months -var - ti1 = getTime() + 1.years -ti1 -= 1.years -doAssert ti1 == getTime() -ti1 += 1.days -doAssert ti1 == getTime() + 1.days - -# Bug with adding a day to a Time -let day = 24.hours -let tomorrow = getTime() + day -doAssert tomorrow - getTime() == 60*60*24 - # Comparison between Time objects should be detected by compiler # as 'noSideEffect'. proc cmpTimeNoSideEffect(t1: Time, t2: Time): bool {.noSideEffect.} = @@ -131,6 +119,10 @@ template parseTest(s, f, sExpected: string, ydExpected: int) = echo parsed.yearday, " exp: ", ydExpected check(parsed.yearday == ydExpected) +template parseTestExcp(s, f: string) = + expect ValueError: + let parsed = s.parse(f) + template parseTestTimeOnly(s, f, sExpected: string) = check sExpected in $s.parse(f, utc()) @@ -203,8 +195,8 @@ template runTimezoneTests() = let parsedJan = parse("2016-01-05 04:00:00+01:00", "yyyy-MM-dd HH:mm:sszzz") parsedJul = parse("2016-07-01 04:00:00+01:00", "yyyy-MM-dd HH:mm:sszzz") - doAssert toTime(parsedJan) == fromUnix(1451962800) - doAssert toTime(parsedJul) == fromUnix(1467342000) + doAssert toTime(parsedJan).toUnix == 1451962800 + doAssert toTime(parsedJul).toUnix == 1467342000 suite "ttimes": @@ -216,7 +208,7 @@ suite "ttimes": let orig_tz = getEnv("TZ") var tz_cnt = 0 - for tz_fn in walkFiles(tz_dir & "/*"): + for tz_fn in walkFiles(tz_dir & "/**/*"): if symlinkExists(tz_fn) or tz_fn.endsWith(".tab") or tz_fn.endsWith(".list"): continue @@ -248,19 +240,20 @@ suite "ttimes": var local = fromUnix(1469275200).local var utc = fromUnix(1469275200).utc - let claimedOffset = local.utcOffset + let claimedOffset = initDuration(seconds = local.utcOffset) local.utcOffset = 0 check claimedOffset == utc.toTime - local.toTime test "issue #5704": putEnv("TZ", "Asia/Seoul") let diff = parse("19700101-000000", "yyyyMMdd-hhmmss").toTime - parse("19000101-000000", "yyyyMMdd-hhmmss").toTime - check diff == 2208986872 + check diff == initDuration(seconds = 2208986872) test "issue #6465": putEnv("TZ", "Europe/Stockholm") let dt = parse("2017-03-25 12:00", "yyyy-MM-dd hh:mm") - check $(dt + 1.days) == "2017-03-26T12:00:00+02:00" + check $(dt + initTimeInterval(days = 1)) == "2017-03-26T12:00:00+02:00" + check $(dt + initDuration(days = 1)) == "2017-03-26T13:00:00+02:00" test "datetime before epoch": check $fromUnix(-2147483648).utc == "1901-12-13T20:45:52+00:00" @@ -277,10 +270,79 @@ suite "ttimes": putEnv("TZ", orig_tz) else: - # not on Linux or macosx: run one parseTest only + # not on Linux or macosx: run in the local timezone only test "parseTest": runTimezoneTests() + test "incorrect inputs: empty string": + parseTestExcp("", "yyyy-MM-dd") + + test "incorrect inputs: year": + parseTestExcp("20-02-19", "yyyy-MM-dd") + + test "incorrect inputs: month number": + parseTestExcp("2018-2-19", "yyyy-MM-dd") + + test "incorrect inputs: month name": + parseTestExcp("2018-Fe", "yyyy-MMM-dd") + + test "incorrect inputs: day": + parseTestExcp("2018-02-1", "yyyy-MM-dd") + + test "incorrect inputs: day of week": + parseTestExcp("2018-Feb-Mo", "yyyy-MMM-ddd") + + test "incorrect inputs: hour": + parseTestExcp("2018-02-19 1:30", "yyyy-MM-dd hh:mm") + + test "incorrect inputs: minute": + parseTestExcp("2018-02-19 16:3", "yyyy-MM-dd hh:mm") + + test "incorrect inputs: second": + parseTestExcp("2018-02-19 16:30:0", "yyyy-MM-dd hh:mm:ss") + + test "incorrect inputs: timezone (z)": + parseTestExcp("2018-02-19 16:30:00 ", "yyyy-MM-dd hh:mm:ss z") + + test "incorrect inputs: timezone (zz) 1": + parseTestExcp("2018-02-19 16:30:00 ", "yyyy-MM-dd hh:mm:ss zz") + + test "incorrect inputs: timezone (zz) 2": + parseTestExcp("2018-02-19 16:30:00 +1", "yyyy-MM-dd hh:mm:ss zz") + + test "incorrect inputs: timezone (zzz) 1": + parseTestExcp("2018-02-19 16:30:00 ", "yyyy-MM-dd hh:mm:ss zzz") + + test "incorrect inputs: timezone (zzz) 2": + parseTestExcp("2018-02-19 16:30:00 +01:", "yyyy-MM-dd hh:mm:ss zzz") + + test "incorrect inputs: timezone (zzz) 3": + parseTestExcp("2018-02-19 16:30:00 +01:0", "yyyy-MM-dd hh:mm:ss zzz") + + test "dynamic timezone": + proc staticOffset(offset: int): Timezone = + proc zoneInfoFromTz(adjTime: Time): ZonedTime = + result.isDst = false + result.utcOffset = offset + result.adjTime = adjTime + + proc zoneInfoFromUtc(time: Time): ZonedTime = + result.isDst = false + result.utcOffset = offset + result.adjTime = fromUnix(time.toUnix - offset) + + result.name = "" + result.zoneInfoFromTz = zoneInfoFromTz + result.zoneInfoFromUtc = zoneInfoFromUtc + + let tz = staticOffset(-9000) + let dt = initDateTime(1, mJan, 2000, 12, 00, 00, tz) + check dt.utcOffset == -9000 + check dt.isDst == false + check $dt == "2000-01-01T12:00:00+02:30" + check $dt.utc == "2000-01-01T09:30:00+00:00" + check $dt.utc.inZone(tz) == $dt + test "isLeapYear": check isLeapYear(2016) check (not isLeapYear(2015)) @@ -289,9 +351,79 @@ suite "ttimes": test "subtract months": var dt = initDateTime(1, mFeb, 2017, 00, 00, 00, utc()) - check $(dt - 1.months) == "2017-01-01T00:00:00+00:00" + check $(dt - initTimeInterval(months = 1)) == "2017-01-01T00:00:00+00:00" dt = initDateTime(15, mMar, 2017, 00, 00, 00, utc()) - check $(dt - 1.months) == "2017-02-15T00:00:00+00:00" + check $(dt - initTimeInterval(months = 1)) == "2017-02-15T00:00:00+00:00" dt = initDateTime(31, mMar, 2017, 00, 00, 00, utc()) # This happens due to monthday overflow. It's consistent with Phobos. - check $(dt - 1.months) == "2017-03-03T00:00:00+00:00" \ No newline at end of file + check $(dt - initTimeInterval(months = 1)) == "2017-03-03T00:00:00+00:00" + + test "duration": + let d = initDuration + check d(hours = 48) + d(days = 5) == d(weeks = 1) + let dt = initDateTime(01, mFeb, 2000, 00, 00, 00, 0, utc()) + d(milliseconds = 1) + check dt.nanosecond == convert(Milliseconds, Nanoseconds, 1) + check d(seconds = 1, milliseconds = 500) * 2 == d(seconds = 3) + check d(seconds = 3) div 2 == d(seconds = 1, milliseconds = 500) + check d(milliseconds = 1001).seconds == 1 + check d(seconds = 1, milliseconds = 500) - d(milliseconds = 1250) == + d(milliseconds = 250) + check d(seconds = 1, milliseconds = 1) < d(seconds = 1, milliseconds = 2) + check d(seconds = 1) <= d(seconds = 1) + check d(seconds = 0) - d(milliseconds = 1500) == d(milliseconds = -1500) + check d(milliseconds = -1500) == d(seconds = -1, milliseconds = -500) + check d(seconds = -1, milliseconds = 500) == d(milliseconds = -500) + check initDuration(seconds = 1, nanoseconds = 2) <= + initDuration(seconds = 1, nanoseconds = 3) + check (initDuration(seconds = 1, nanoseconds = 3) <= + initDuration(seconds = 1, nanoseconds = 1)).not + + test "large/small dates": + discard initDateTime(1, mJan, -35_000, 12, 00, 00, utc()) + # with local tz + discard initDateTime(1, mJan, -35_000, 12, 00, 00) + discard initDateTime(1, mJan, 35_000, 12, 00, 00) + # with duration/timeinterval + let dt = initDateTime(1, mJan, 35_000, 12, 00, 00, utc()) + + initDuration(seconds = 1) + check dt.second == 1 + let dt2 = dt + 35_001.years + check $dt2 == "0001-01-01T12:00:01+00:00" + + test "compare datetimes": + var dt1 = now() + var dt2 = dt1 + check dt1 == dt2 + check dt1 <= dt2 + dt2 = dt2 + 1.seconds + check dt1 < dt2 + + test "adding/subtracting TimeInterval": + # add/subtract TimeIntervals and Time/TimeInfo + let now = getTime().utc + check now + convert(Seconds, Nanoseconds, 1).nanoseconds == now + 1.seconds + check now + 1.weeks == now + 7.days + check now - 1.seconds == now - 3.seconds + 2.seconds + check now + 65.seconds == now + 1.minutes + 5.seconds + check now + 60.minutes == now + 1.hours + check now + 24.hours == now + 1.days + check now + 13.months == now + 1.years + 1.months + check toUnix(fromUnix(0) + 2.seconds) == 2 + check toUnix(fromUnix(0) - 2.seconds) == -2 + var ti1 = now + 1.years + ti1 = ti1 - 1.years + check ti1 == now + ti1 = ti1 + 1.days + check ti1 == now + 1.days + + # Bug with adding a day to a Time + let day = 24.hours + let tomorrow = now + day + check tomorrow - now == initDuration(days = 1) + + test "fromWinTime/toWinTime": + check 0.fromUnix.toWinTime.fromWinTime.toUnix == 0 + check (-1).fromWinTime.nanosecond == convert(Seconds, Nanoseconds, 1) - 100 + check -1.fromWinTime.toWinTime == -1 + # One nanosecond is discarded due to differences in time resolution + check initTime(0, 101).toWinTime.fromWinTime.nanosecond == 100 \ No newline at end of file diff --git a/tests/stdlib/tunittestexceptiontype.nim b/tests/stdlib/tunittestexceptiontype.nim new file mode 100644 index 000000000..e05a25409 --- /dev/null +++ b/tests/stdlib/tunittestexceptiontype.nim @@ -0,0 +1,10 @@ +discard """ + exitcode: 1 + outputsub: '''exception type is [ValueError]''' +""" + +import unittest + +suite "exception from test": + test "show exception type": + raise newException(ValueError, "exception type is") diff --git a/tests/stdlib/twchartoutf8.nim b/tests/stdlib/twchartoutf8.nim index b2f68ee32..a6602e3e3 100644 --- a/tests/stdlib/twchartoutf8.nim +++ b/tests/stdlib/twchartoutf8.nim @@ -30,7 +30,6 @@ else: result = newString(size) let res = WideCharToMultiByte(CP_UTF8, 0'i32, cast[LPWCSTR](addr(wc[0])), wclen, cstring(result), size, cstring(nil), LPBOOL(nil)) - result[size] = chr(0) doAssert size == res proc testCP(wc: WideCString, lo, hi: int) = diff --git a/tests/system/alloc.nim b/tests/system/talloc.nim index 7abefec2a..18396041d 100644 --- a/tests/system/alloc.nim +++ b/tests/system/talloc.nim @@ -8,7 +8,7 @@ x.dealloc() x = createU(int, 3) assert x != nil -x.free() +x.dealloc() x = create(int, 4) assert cast[ptr array[4, int]](x)[0] == 0 @@ -18,7 +18,7 @@ assert cast[ptr array[4, int]](x)[3] == 0 x = x.resize(4) assert x != nil -x.free() +x.dealloc() x = cast[ptr int](allocShared(100)) assert x != nil @@ -26,7 +26,7 @@ deallocShared(x) x = createSharedU(int, 3) assert x != nil -x.freeShared() +x.deallocShared() x = createShared(int, 3) assert x != nil @@ -37,7 +37,7 @@ assert cast[ptr array[3, int]](x)[2] == 0 assert x != nil x = cast[ptr int](x.resizeShared(2)) assert x != nil -x.freeShared() +x.deallocShared() x = create(int, 10) assert x != nil @@ -49,4 +49,9 @@ x = createShared(int, 1) assert x != nil x = x.resizeShared(1) assert x != nil -x.freeShared() +x.deallocShared() + +x = cast[ptr int](alloc0(125 shl 23)) +dealloc(x) +x = cast[ptr int](alloc0(126 shl 23)) +dealloc(x) diff --git a/tests/system/talloc2.nim b/tests/system/talloc2.nim new file mode 100644 index 000000000..c8cab78a1 --- /dev/null +++ b/tests/system/talloc2.nim @@ -0,0 +1,37 @@ +const + nmax = 2*1024*1024*1024 + +proc test(n: int) = + var a = alloc0(9999) + var t = cast[ptr UncheckedArray[int8]](alloc(n)) + var b = alloc0(9999) + t[0] = 1 + t[1] = 2 + t[n-2] = 3 + t[n-1] = 4 + dealloc(a) + dealloc(t) + dealloc(b) + +# allocator adds 48 bytes to BigChunk +# BigChunk allocator edges at 2^n * (1 - s) for s = [1..32]/64 +proc test2(n: int) = + let d = n div 256 # cover edges and more + for i in countdown(128,1): + for j in [-4096, -64, -49, -48, -47, -32, 0, 4096]: + let b = n + j - i*d + if b>0 and b<=nmax: + test(b) + #echo b, ": ", getTotalMem(), " ", getOccupiedMem(), " ", getFreeMem() + +proc test3 = + var n = 1 + while n <= nmax: + test2(n) + n *= 2 + n = nmax + while n >= 1: + test2(n) + n = n div 2 + +test3() diff --git a/tests/system/io.nim b/tests/system/tio.nim index b0ccfda9f..3d4df806b 100644 --- a/tests/system/io.nim +++ b/tests/system/tio.nim @@ -1,5 +1,5 @@ import - unittest, osproc, streams, os + unittest, osproc, streams, os, strformat const STRING_DATA = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet." const TEST_FILE = "tests/testdata/string.txt" @@ -23,3 +23,26 @@ suite "io": test "file": check: readFile(TEST_FILE) == STRING_DATA + + +proc verifyFileSize(sz: int64) = + # issue 7121, large file size (2-4GB and >4Gb) + const fn = "tmpfile112358" + let size_in_mb = sz div 1_000_000 + + when defined(windows): + discard execProcess(&"fsutil file createnew {fn} {sz}" ) + else: + discard execProcess(&"dd if=/dev/zero of={fn} bs=1000000 count={size_in_mb}") + + doAssert os.getFileSize(fn) == sz # Verify OS filesize by string + + var f = open(fn) + doAssert f.getFileSize() == sz # Verify file handle filesize + f.close() + + os.removeFile(fn) + +#disable tests for automatic testers +#for s in [50_000_000'i64, 3_000_000_000, 5_000_000_000]: +# verifyFileSize(s) diff --git a/tests/system/tnilconcats.nim b/tests/system/tnilconcats.nim new file mode 100644 index 000000000..ce059b7b0 --- /dev/null +++ b/tests/system/tnilconcats.nim @@ -0,0 +1,25 @@ +discard """ + output: '''@[nil, nil, nil, nil, nil, nil, nil, "meh"]''' + exitcode: "0" +""" + +when true: + var ab: string + ab &= "more" + + doAssert ab == "more" + + var x: seq[string] + + setLen(x, 7) + + x.add "meh" + + var s: string + var z = "abc" + var zz: string + s &= "foo" & z & zz + + doAssert s == "fooabc" + + echo x diff --git a/tests/system/toString.nim b/tests/system/toString.nim index ea9d6b05b..ea10f998c 100644 --- a/tests/system/toString.nim +++ b/tests/system/toString.nim @@ -6,6 +6,7 @@ doAssert "@[23, 45]" == $(@[23, 45]) doAssert "[32, 45]" == $([32, 45]) doAssert """@["", "foo", "bar"]""" == $(@["", "foo", "bar"]) doAssert """["", "foo", "bar"]""" == $(["", "foo", "bar"]) +doAssert """["", "foo", "bar"]""" == $(@["", "foo", "bar"].toOpenArray(0, 2)) # bug #2395 let alphaSet: set[char] = {'a'..'c'} @@ -51,3 +52,59 @@ import strutils let arr = ['H','e','l','l','o',' ','W','o','r','l','d','!','\0'] doAssert $arr == "['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!', '\\x00']" doAssert $cstring(unsafeAddr arr) == "Hello World!" + +proc takes(c: cstring) = + doAssert c == "" + +proc testm() = + var x: string + # nil is mapped to "": + takes(x) + +testm() + +# nil tests +var xx: seq[string] +var yy: string +doAssert xx == @[] +doAssert yy == "" + +proc bar(arg: cstring): void = + doAssert arg[0] == '\0' + +proc baz(arg: openarray[char]): void = + doAssert arg.len == 0 + +proc stringCompare(): void = + var a,b,c,d,e,f,g: string + a.add 'a' + doAssert a == "a" + b.add "bee" + doAssert b == "bee" + b.add g + doAssert b == "bee" + c.add 123.456 + doAssert c == "123.456" + d.add 123456 + doAssert d == "123456" + + doAssert e == "" + doAssert "" == e + doAssert nil == e + doAssert e == nil + doAssert f == g + doAssert "" == "" + doAssert "" == nil + doAssert nil == "" + + g.setLen(10) + doAssert g == "\0\0\0\0\0\0\0\0\0\0" + doAssert "" != "\0\0\0\0\0\0\0\0\0\0" + + var nilstring: string + bar(nilstring) + baz(nilstring) + +stringCompare() +static: + stringCompare() \ No newline at end of file diff --git a/tests/system/params.nim b/tests/system/tparams.nim index 1358212f2..1358212f2 100644 --- a/tests/system/params.nim +++ b/tests/system/tparams.nim diff --git a/tests/system/tsystem_misc.nim b/tests/system/tsystem_misc.nim index ce36895a1..85228e9e7 100644 --- a/tests/system/tsystem_misc.nim +++ b/tests/system/tsystem_misc.nim @@ -1,5 +1,17 @@ discard """ - output:"" + output:'''1 +1 +2 +3 +11 +12 +13 +14 +15 +2 +3 +4 +''' """ # check high/low implementations @@ -20,3 +32,18 @@ doAssert high(float64) > low(float64) # bug #6710 var s = @[1] s.delete(0) + + +proc foo(a: openArray[int]) = + for x in a: echo x + +foo(toOpenArray([1, 2, 3], 0, 0)) + +foo(toOpenArray([1, 2, 3], 0, 2)) + +var arr: array[8..12, int] = [11, 12, 13, 14, 15] + +foo(toOpenArray(arr, 8, 12)) + +var seqq = @[1, 2, 3, 4, 5] +foo(toOpenArray(seqq, 1, 3)) diff --git a/tests/template/i2416.nim b/tests/template/i2416.nim new file mode 100644 index 000000000..4b53cd0ca --- /dev/null +++ b/tests/template/i2416.nim @@ -0,0 +1 @@ +template i2416*() = echo "i2416" diff --git a/tests/template/t2416.nim b/tests/template/t2416.nim new file mode 100644 index 000000000..f73880718 --- /dev/null +++ b/tests/template/t2416.nim @@ -0,0 +1,2 @@ +import i2416 +i2416() diff --git a/tests/template/tgenerictemplates.nim b/tests/template/tgenerictemplates.nim index 2c83bc0ec..142505b1a 100644 --- a/tests/template/tgenerictemplates.nim +++ b/tests/template/tgenerictemplates.nim @@ -11,3 +11,27 @@ template someTemplate[T](): tuple[id: int32, obj: T] = let ret = someTemplate[SomeObj]() +# https://github.com/nim-lang/Nim/issues/7829 +proc inner*[T](): int = + discard + +template outer*[A](): untyped = + inner[A]() + +template outer*[B](x: int): untyped = + inner[B]() + +var i1 = outer[int]() +var i2 = outer[int](i1) + +# https://github.com/nim-lang/Nim/issues/7883 +template t1[T: int|int64](s: string): T = + var t: T + t + +template t1[T: int|int64](x: int, s: string): T = + var t: T + t + +var i3: int = t1[int]("xx") + diff --git a/tests/testament/backend.nim b/tests/testament/backend.nim index 4acef9ca4..385f1171c 100644 --- a/tests/testament/backend.nim +++ b/tests/testament/backend.nim @@ -13,7 +13,7 @@ type CommitId = distinct string proc `$`*(id: MachineId): string {.borrow.} -proc `$`(id: CommitId): string {.borrow.} +#proc `$`(id: CommitId): string {.borrow.} # not used var thisMachine: MachineId diff --git a/tests/testament/categories.nim b/tests/testament/categories.nim index 33b93e3c4..84e536636 100644 --- a/tests/testament/categories.nim +++ b/tests/testament/categories.nim @@ -17,11 +17,12 @@ const rodfilesDir = "tests/rodfiles" proc delNimCache(filename, options: string) = - let dir = nimcacheDir(filename, options) - try: - removeDir(dir) - except OSError: - echo "[Warning] could not delete: ", dir + for target in low(TTarget)..high(TTarget): + let dir = nimcacheDir(filename, options, target) + try: + removeDir(dir) + except OSError: + echo "[Warning] could not delete: ", dir proc runRodFiles(r: var TResults, cat: Category, options: string) = template test(filename: string, clearCacheFirst=false) = @@ -62,6 +63,26 @@ proc compileRodFiles(r: var TResults, cat: Category, options: string) = test "gtkex1", true test "gtkex2" +# --------------------- flags tests ------------------------------------------- + +proc flagTests(r: var TResults, cat: Category, options: string) = + # --genscript + const filename = "tests"/"flags"/"tgenscript" + const genopts = " --genscript" + let nimcache = nimcacheDir(filename, genopts, targetC) + testSpec r, makeTest(filename, genopts, cat) + + when defined(windows): + testExec r, makeTest(filename, " cmd /c cd " & nimcache & + " && compile_tgenscript.bat", cat) + + when defined(linux): + testExec r, makeTest(filename, " sh -c \"cd " & nimcache & + " && sh compile_tgenscript.sh\"", cat) + + # Run + testExec r, makeTest(filename, " " & nimcache / "tgenscript", cat) + # --------------------- DLL generation tests ---------------------------------- proc safeCopyFile(src, dest: string) = @@ -90,7 +111,7 @@ proc runBasicDLLTest(c, r: var TResults, cat: Category, options: string) = # posix relies on crappy LD_LIBRARY_PATH (ugh!): var libpath = getEnv"LD_LIBRARY_PATH".string # Temporarily add the lib directory to LD_LIBRARY_PATH: - putEnv("LD_LIBRARY_PATH", "tests/dll:" & libpath) + putEnv("LD_LIBRARY_PATH", "tests/dll" & (if libpath.len > 0: ":" & libpath else: "")) defer: putEnv("LD_LIBRARY_PATH", libpath) var nimrtlDll = DynlibFormat % "nimrtl" safeCopyFile("lib" / nimrtlDll, "tests/dll" / nimrtlDll) @@ -147,7 +168,7 @@ proc gcTests(r: var TResults, cat: Category, options: string) = test "gcbench" test "gcleak" test "gcleak2" - test "gctest" + testWithoutBoehm "gctest" testWithNone "gctest" test "gcleak3" test "gcleak4" @@ -166,9 +187,9 @@ proc gcTests(r: var TResults, cat: Category, options: string) = proc longGCTests(r: var TResults, cat: Category, options: string) = when defined(windows): - let cOptions = "gcc -ldl -DWIN" + let cOptions = "-ldl -DWIN" else: - let cOptions = "gcc -ldl" + let cOptions = "-ldl" var c = initResults() # According to ioTests, this should compile the file @@ -225,7 +246,8 @@ proc jsTests(r: var TResults, cat: Category, options: string) = "actiontable/tactiontable", "method/tmultim1", "method/tmultim3", "method/tmultim4", "varres/tvarres0", "varres/tvarres3", "varres/tvarres4", - "varres/tvartup", "misc/tints", "misc/tunsignedinc"]: + "varres/tvartup", "misc/tints", "misc/tunsignedinc", + "async/tjsandnativeasync"]: test "tests/" & testfile & ".nim" for testfile in ["strutils", "json", "random", "times", "logging"]: @@ -321,7 +343,7 @@ var nimbleDir = getEnv("NIMBLE_DIR").string if nimbleDir.len == 0: nimbleDir = getHomeDir() / ".nimble" let nimbleExe = findExe("nimble") - packageDir = nimbleDir / "pkgs" + #packageDir = nimbleDir / "pkgs" # not used packageIndex = nimbleDir / "packages.json" proc waitForExitEx(p: Process): int = @@ -405,9 +427,9 @@ proc `&.?`(a, b: string): string = # candidate for the stdlib? result = if b.startswith(a): b else: a & b -proc `&?.`(a, b: string): string = +#proc `&?.`(a, b: string): string = # not used # candidate for the stdlib? - result = if a.endswith(b): a else: a & b + #result = if a.endswith(b): a else: a & b proc processSingleTest(r: var TResults, cat: Category, options, test: string) = let test = "tests" & DirSep &.? cat.string / test @@ -419,13 +441,16 @@ proc processSingleTest(r: var TResults, cat: Category, options, test: string) = proc processCategory(r: var TResults, cat: Category, options: string) = case cat.string.normalize of "rodfiles": - when false: compileRodFiles(r, cat, options) - runRodFiles(r, cat, options) + when false: + compileRodFiles(r, cat, options) + runRodFiles(r, cat, options) of "js": # XXX JS doesn't need to be special anymore jsTests(r, cat, options) of "dll": dllTests(r, cat, options) + of "flags": + flagTests(r, cat, options) of "gc": gcTests(r, cat, options) of "longgc": diff --git a/tests/testament/htmlgen.nim b/tests/testament/htmlgen.nim index bf26a956d..4a888427e 100644 --- a/tests/testament/htmlgen.nim +++ b/tests/testament/htmlgen.nim @@ -121,7 +121,7 @@ proc generateAllTestsContent(outfile: File, allResults: AllTests, proc generateHtml*(filename: string, onlyFailing: bool) = let - currentTime = getTime().getLocalTime() + currentTime = getTime().local() timestring = htmlQuote format(currentTime, "yyyy-MM-dd HH:mm:ss 'UTC'zzz") var outfile = open(filename, fmWrite) diff --git a/tests/testament/tester.nim b/tests/testament/tester.nim index 870f9f865..0185156ec 100644 --- a/tests/testament/tester.nim +++ b/tests/testament/tester.nim @@ -16,7 +16,7 @@ import const resultsFile = "testresults.html" - jsonFile = "testresults.json" + #jsonFile = "testresults.json" # not used Usage = """Usage: tester [options] command [arguments] @@ -71,14 +71,15 @@ proc getFileDir(filename: string): string = if not result.isAbsolute(): result = getCurrentDir() / result -proc nimcacheDir(filename, options: string): string = +proc nimcacheDir(filename, options: string, target: TTarget): string = ## Give each test a private nimcache dir so they don't clobber each other's. - return "nimcache" / (filename & '_' & options.getMD5) + let hashInput = options & $target + return "nimcache" / (filename & '_' & hashInput.getMD5) proc callCompiler(cmdTemplate, filename, options: string, target: TTarget, extraOptions=""): TSpec = - let nimcache = nimcacheDir(filename, options) - let options = options & " --nimCache:" & nimcache.quoteShell & extraOptions + let nimcache = nimcacheDir(filename, options, target) + let options = options & " " & ("--nimCache:" & nimcache).quoteShell & extraOptions let c = parseCmdLine(cmdTemplate % ["target", targetToCmd[target], "options", options, "file", filename.quoteShell, "filedir", filename.getFileDir()]) @@ -149,11 +150,11 @@ proc initResults: TResults = result.skipped = 0 result.data = "" -proc readResults(filename: string): TResults = - result = marshal.to[TResults](readFile(filename).string) +#proc readResults(filename: string): TResults = # not used +# result = marshal.to[TResults](readFile(filename).string) -proc writeResults(filename: string, r: TResults) = - writeFile(filename, $$r) +#proc writeResults(filename: string, r: TResults) = # not used +# writeFile(filename, $$r) proc `$`(x: TResults): string = result = ("Tests passed: $1 / $3 <br />\n" & @@ -211,18 +212,18 @@ proc cmpMsgs(r: var TResults, expected, given: TSpec, test: TTest, target: TTarg elif expected.tfile == "" and extractFilename(expected.file) != extractFilename(given.file) and "internal error:" notin expected.msg: r.addResult(test, target, expected.file, given.file, reFilesDiffer) - elif expected.line != given.line and expected.line != 0 or + elif expected.line != given.line and expected.line != 0 or expected.column != given.column and expected.column != 0: r.addResult(test, target, $expected.line & ':' & $expected.column, - $given.line & ':' & $given.column, + $given.line & ':' & $given.column, reLinesDiffer) elif expected.tfile != "" and extractFilename(expected.tfile) != extractFilename(given.tfile) and "internal error:" notin expected.msg: r.addResult(test, target, expected.tfile, given.tfile, reFilesDiffer) - elif expected.tline != given.tline and expected.tline != 0 or + elif expected.tline != given.tline and expected.tline != 0 or expected.tcolumn != given.tcolumn and expected.tcolumn != 0: r.addResult(test, target, $expected.tline & ':' & $expected.tcolumn, - $given.tline & ':' & $given.tcolumn, + $given.tline & ':' & $given.tcolumn, reLinesDiffer) else: r.addResult(test, target, expected.msg, given.msg, reSuccess) @@ -231,7 +232,7 @@ proc cmpMsgs(r: var TResults, expected, given: TSpec, test: TTest, target: TTarg proc generatedFile(test: TTest, target: TTarget): string = let (_, name, _) = test.name.splitFile let ext = targetToExt[target] - result = nimcacheDir(test.name, test.options) / + result = nimcacheDir(test.name, test.options, target) / (if target == targetJS: "" else: "compiler_") & name.changeFileExt(ext) @@ -293,7 +294,6 @@ proc compilerOutputTests(test: TTest, target: TTarget, given: var TSpec, proc testSpec(r: var TResults, test: TTest, target = targetC) = let tname = test.name.addFileExt(".nim") #echo "TESTING ", tname - inc(r.total) var expected: TSpec if test.action != actionRunNoSpec: expected = parseSpec(tname) @@ -304,12 +304,14 @@ proc testSpec(r: var TResults, test: TTest, target = targetC) = if expected.err == reIgnored: r.addResult(test, target, "", "", reIgnored) inc(r.skipped) + inc(r.total) return if expected.targets == {}: expected.targets.incl(target) for target in expected.targets: + inc(r.total) if target notin targets: r.addResult(test, target, "", "", reIgnored) inc(r.skipped) @@ -334,7 +336,7 @@ proc testSpec(r: var TResults, test: TTest, target = targetC) = var exeFile: string if isJsTarget: let (_, file, _) = splitFile(tname) - exeFile = nimcacheDir(test.name, test.options) / file & ".js" + exeFile = nimcacheDir(test.name, test.options, target) / file & ".js" else: exeFile = changeFileExt(tname, ExeExt) @@ -402,6 +404,21 @@ proc testC(r: var TResults, test: TTest) = if exitCode != 0: given.err = reExitCodesDiffer if given.err == reSuccess: inc(r.passed) +proc testExec(r: var TResults, test: TTest) = + # runs executable or script, just goes by exit code + inc(r.total) + let (outp, errC) = execCmdEx(test.options.strip()) + var given: TSpec + specDefaults(given) + if errC == 0: + given.err = reSuccess + else: + given.err = reExitCodesDiffer + given.msg = outp.string + + if given.err == reSuccess: inc(r.passed) + r.addResult(test, targetC, "", given.msg, given.err) + proc makeTest(test, options: string, cat: Category, action = actionCompile, env: string = ""): TTest = # start with 'actionCompile', will be overwritten in the spec: @@ -425,7 +442,7 @@ include categories # if status: reSuccess else: reOutputsDiffer) proc main() = - os.putenv "NIMTEST_NO_COLOR", "1" + os.putenv "NIMTEST_COLOR", "never" os.putenv "NIMTEST_OUTPUT_LVL", "PRINT_FAILURES" backend.open() @@ -489,7 +506,7 @@ proc main() = else: echo r, r.data backend.close() var failed = r.total - r.passed - r.skipped - if failed > 0: + if failed != 0: echo "FAILURE! total: ", r.total, " passed: ", r.passed, " skipped: ", r.skipped quit(QuitFailure) diff --git a/tests/threads/threadex.nim b/tests/threads/threadex.nim index fb03cbfa8..679bfcb12 100644 --- a/tests/threads/threadex.nim +++ b/tests/threads/threadex.nim @@ -5,9 +5,9 @@ discard """ type TMsgKind = enum mLine, mEof - TMsg = object {.pure, final.} + TMsg = object case k: TMsgKind - of mEof: nil + of mEof: discard of mLine: data: string var diff --git a/tests/threads/tthreadvars.nim b/tests/threads/tthreadvars.nim new file mode 100644 index 000000000..81aa2e5ec --- /dev/null +++ b/tests/threads/tthreadvars.nim @@ -0,0 +1,78 @@ +discard """ +output: ''' +10 +1111 +1222 +3030303 +3060606 +6060606 +6121212 +3030903 +3061206 +3031503 +3061806 +5050505 +5101010 +''' +""" + +import typetraits + +var tls1 {.threadvar.}: int +var g0: int +var g1 {.global.}: int + +proc customInc(x: var int, delta: int) = + x += delta + +customInc(tls1, 10) +echo tls1 + +proc nonGenericProc: int = + var local: int + var nonGenericTls {.threadvar.}: int + var nonGenericGlobal {.global.}: int + var nonGenericMixedPragmas {.global, threadvar.}: int + + customInc local, 1000 + customInc nonGenericTls, 1 + customInc nonGenericGlobal, 10 + customInc nonGenericMixedPragmas, 100 + + return local + nonGenericTls + nonGenericGlobal + nonGenericMixedPragmas + +proc genericProc(T: typedesc): int = + var local: int + var genericTls {.threadvar.}: int + var genericGlobal {.global.}: int + var genericMixedPragmas {.global, threadvar.}: int + + customInc local, T.name.len * 1000000 + customInc genericTls, T.name.len * 1 + customInc genericGlobal, T.name.len * 100 + customInc genericMixedPragmas, T.name.len * 10000 + + return local + genericTls + genericGlobal + genericMixedPragmas + +echo nonGenericProc() +echo nonGenericProc() + +echo genericProc(int) +echo genericProc(int) + +echo genericProc(string) +echo genericProc(string) + +proc echoInThread[T]() {.thread.} = + echo genericProc(T) + echo genericProc(T) + +proc newEchoThread(T: typedesc) = + var t: Thread[void] + createThread(t, echoInThread[T]) + joinThreads(t) + +newEchoThread int +newEchoThread int +newEchoThread float + diff --git a/tests/trmacros/thoist.nim b/tests/trmacros/thoist.nim index 7d14c0abf..657f210a1 100644 --- a/tests/trmacros/thoist.nim +++ b/tests/trmacros/thoist.nim @@ -5,7 +5,7 @@ true''' import pegs -template optPeg{peg(pattern)}(pattern: string{lit}): TPeg = +template optPeg{peg(pattern)}(pattern: string{lit}): Peg = var gl {.global, gensym.} = peg(pattern) gl diff --git a/tests/tuples/tanontuples.nim b/tests/tuples/tanontuples.nim index 49803e5ac..f514670d3 100644 --- a/tests/tuples/tanontuples.nim +++ b/tests/tuples/tanontuples.nim @@ -1,7 +1,10 @@ discard """ - output: '''61, 125''' + output: '''61, 125 +(Field0: 0) (Field0: 13)''' """ +import macros + proc `^` (a, b: int): int = result = 1 for i in 1..b: result = result * a @@ -12,3 +15,12 @@ var n = (56, 3) m = (n[0] + m[1], m[1] ^ n[1]) echo m[0], ", ", m[1] + +# also test we can produce unary anon tuples in a macro: +macro mm(): untyped = + result = newTree(nnkTupleConstr, newLit(13)) + +proc nowTuple(): (int,) = + result = (0,) + +echo nowTuple(), " ", mm() diff --git a/tests/tuples/tuple_with_nil.nim b/tests/tuples/tuple_with_nil.nim index eb265f420..ec48337bd 100644 --- a/tests/tuples/tuple_with_nil.nim +++ b/tests/tuples/tuple_with_nil.nim @@ -353,7 +353,7 @@ proc writeformat(o: var Writer; p: pointer; fmt: Format) = f.baseprefix = true writeformat(o, add, cast[uint](p), f) -proc writeformat(o: var Writer; x: SomeReal; fmt: Format) = +proc writeformat(o: var Writer; x: SomeFloat; fmt: Format) = ## Write real number `x` according to format `fmt` using output ## object `o` and output function `add`. var fmt = fmt @@ -401,8 +401,8 @@ proc writeformat(o: var Writer; x: SomeReal; fmt: Format) = else: len += 4 # exponent # shift y so that 1 <= abs(y) < 2 - if exp > 0: y /= pow(10.SomeReal, abs(exp).SomeReal) - elif exp < 0: y *= pow(10.SomeReal, abs(exp).SomeReal) + if exp > 0: y /= pow(10.SomeFloat, abs(exp).SomeFloat) + elif exp < 0: y *= pow(10.SomeFloat, abs(exp).SomeFloat) elif fmt.typ == ftPercent: len += 1 # percent sign @@ -413,7 +413,7 @@ proc writeformat(o: var Writer; x: SomeReal; fmt: Format) = var mult = 1'i64 for i in 1..prec: mult *= 10 var num = y.int64 - var fr = ((y - num.SomeReal) * mult.SomeReal).int64 + var fr = ((y - num.SomeFloat) * mult.SomeFloat).int64 # build integer part string while num != 0: numstr[numlen] = ('0'.int + (num mod 10)).char diff --git a/tests/typerel/t7600_1.nim b/tests/typerel/t7600_1.nim new file mode 100644 index 000000000..e3a5fefa2 --- /dev/null +++ b/tests/typerel/t7600_1.nim @@ -0,0 +1,18 @@ +discard """ +errormsg: "type mismatch: got <Thin[system.int]>" +nimout: '''t7600_1.nim(18, 6) Error: type mismatch: got <Thin[system.int]> +but expected one of: +proc test[T](x: Paper[T]) + +expression: test tn''' +""" + +type + Paper[T] = ref object of RootObj + thickness: T + Thin[T] = object of Paper[T] + +proc test[T](x: Paper[T]) = discard + +var tn = Thin[int]() +test tn diff --git a/tests/typerel/t7600_2.nim b/tests/typerel/t7600_2.nim new file mode 100644 index 000000000..7badb69cf --- /dev/null +++ b/tests/typerel/t7600_2.nim @@ -0,0 +1,17 @@ +discard """ +errormsg: "type mismatch: got <Thin>" +nimout: '''t7600_2.nim(17, 6) Error: type mismatch: got <Thin> +but expected one of: +proc test(x: Paper) + +expression: test tn''' +""" + +type + Paper = ref object of RootObj + Thin = object of Paper + +proc test(x: Paper) = discard + +var tn = Thin() +test tn diff --git a/tests/typerel/temptynode.nim b/tests/typerel/temptynode.nim index 32148ce13..df308fbc2 100644 --- a/tests/typerel/temptynode.nim +++ b/tests/typerel/temptynode.nim @@ -1,6 +1,6 @@ discard """ line: 16 - errormsg: "type mismatch: got (void)" + errormsg: "type mismatch: got <void>" """ # bug #950 diff --git a/tests/typerel/texplicitcmp.nim b/tests/typerel/texplicitcmp.nim index 8aec9885a..e91ac2ffe 100644 --- a/tests/typerel/texplicitcmp.nim +++ b/tests/typerel/texplicitcmp.nim @@ -18,7 +18,7 @@ proc works() = sort(f, system.cmp[int]) outp(f) -proc weird(json_params: TTable) = +proc weird(json_params: Table) = var f = @[3, 2, 1] # The following line doesn't compile: type mismatch. Why? sort(f, system.cmp[int]) @@ -29,4 +29,4 @@ when isMainModule: sort(t, system.cmp[int]) outp(t) works() - weird(initTable[string, TJsonNode]()) + weird(initTable[string, JsonNode]()) diff --git a/tests/typerel/tgeneric_subtype_regression.nim b/tests/typerel/tgeneric_subtype_regression.nim index e279c0ad4..def5d721e 100644 --- a/tests/typerel/tgeneric_subtype_regression.nim +++ b/tests/typerel/tgeneric_subtype_regression.nim @@ -1,5 +1,5 @@ discard """ - errormsg: "type mismatch: got (FooRef[system.string])" + errormsg: "type mismatch: got <FooRef[system.string]>" line: 15 """ diff --git a/tests/typerel/tno_int_in_bool_context.nim b/tests/typerel/tno_int_in_bool_context.nim index 557759169..a4b4237d2 100644 --- a/tests/typerel/tno_int_in_bool_context.nim +++ b/tests/typerel/tno_int_in_bool_context.nim @@ -1,6 +1,6 @@ discard """ line: 6 - errormsg: "type mismatch: got (int literal(1)) but expected 'bool'" + errormsg: "type mismatch: got <int literal(1)> but expected 'bool'" """ if 1: diff --git a/tests/typerel/tnocontains.nim b/tests/typerel/tnocontains.nim index 4f4951478..a93db2fc3 100644 --- a/tests/typerel/tnocontains.nim +++ b/tests/typerel/tnocontains.nim @@ -1,7 +1,7 @@ discard """ file: "tnocontains.nim" line: 10 - errormsg: "type mismatch: got (string, string)" + errormsg: "type mismatch: got <string, string>" """ # shouldn't compile since it doesn't do what you think it does without diff --git a/tests/typerel/tregionptrs.nim b/tests/typerel/tregionptrs.nim index a8d2e7a6d..9eeded18b 100644 --- a/tests/typerel/tregionptrs.nim +++ b/tests/typerel/tregionptrs.nim @@ -1,6 +1,6 @@ discard """ line: 16 - errormsg: "type mismatch: got (BPtr) but expected 'APtr = ptr[RegionA, int]'" + errormsg: "type mismatch: got <BPtr> but expected 'APtr = ptr[RegionA, int]'" """ type diff --git a/tests/typerel/ttypedesc_as_genericparam1.nim b/tests/typerel/ttypedesc_as_genericparam1.nim index 88c0509b2..9ae464842 100644 --- a/tests/typerel/ttypedesc_as_genericparam1.nim +++ b/tests/typerel/ttypedesc_as_genericparam1.nim @@ -1,6 +1,6 @@ discard """ line: 6 - errormsg: "type mismatch: got (type int)" + errormsg: "type mismatch: got <type int>" """ # bug #3079, #1146 echo repr(int) diff --git a/tests/typerel/ttypelessemptyset.nim b/tests/typerel/ttypelessemptyset.nim index 3e171387b..5f49c33fd 100644 --- a/tests/typerel/ttypelessemptyset.nim +++ b/tests/typerel/ttypelessemptyset.nim @@ -1,5 +1,5 @@ discard """ - errormsg: "internal error: invalid kind for last(tyEmpty)" + errormsg: "internal error: invalid kind for lastOrd(tyEmpty)" """ var q = false discard (if q: {} else: {}) diff --git a/tests/typerel/ttypenoval.nim b/tests/typerel/ttypenoval.nim index eabca48f6..720e5d662 100644 --- a/tests/typerel/ttypenoval.nim +++ b/tests/typerel/ttypenoval.nim @@ -1,7 +1,7 @@ discard """ file: "ttypenoval.nim" line: 38 - errormsg: "type mismatch: got (type int) but expected 'int'" + errormsg: "type mismatch: got <type int> but expected 'int'" """ # A min-heap. diff --git a/tests/types/tparameterizedparent3.nim b/tests/types/tparameterizedparent3.nim index 3fc83cb4d..58aaf80ea 100644 --- a/tests/types/tparameterizedparent3.nim +++ b/tests/types/tparameterizedparent3.nim @@ -1,7 +1,7 @@ discard """ file: "tparameterizedparent3.nim" line: 13 - errormsg: "redefinition of 'color'" + errormsg: "attempt to redefine: 'color'" """ # bug #5264 type diff --git a/tests/types/tparameterizedparent4.nim b/tests/types/tparameterizedparent4.nim index fa8b525c1..a37461bb4 100644 --- a/tests/types/tparameterizedparent4.nim +++ b/tests/types/tparameterizedparent4.nim @@ -1,7 +1,7 @@ discard """ file: "tparameterizedparent4.nim" line: 23 - errormsg: "redefinition of 'grain'" + errormsg: "attempt to redefine: 'grain'" """ # bug #5264 type diff --git a/tests/untestable/tssl.nim b/tests/untestable/tssl.nim new file mode 100644 index 000000000..664ad805c --- /dev/null +++ b/tests/untestable/tssl.nim @@ -0,0 +1,36 @@ +# +# Nim - SSL integration tests +# (c) Copyright 2017 Nim contributors +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# +## Warning: this test performs external networking. +## +## Test with: +## ./bin/nim c -d:ssl -p:. -r tests/untestable/tssl.nim +## ./bin/nim c -d:ssl -p:. --dynlibOverride:ssl --passL:-lcrypto --passL:-lssl -r tests/untestable/tssl.nim +## The compilation is expected to succeed with any new/old version of OpenSSL, +## both with dynamic and static linking. +## The "howsmyssl" test is known to fail with OpenSSL < 1.1 due to insecure +## cypher suites being used. + +import httpclient, os +from strutils import contains, toHex + +from openssl import getOpenSSLVersion + +when isMainModule: + echo "version: 0x" & $getOpenSSLVersion().toHex() + + let client = newHttpClient() + # hacky SSL check + const url = "https://www.howsmyssl.com" + let report = client.getContent(url) + if not report.contains(">Probably Okay</span>"): + let fn = getTempDir() / "sslreport.html" + echo "SSL CHECK ERROR, see " & fn + writeFile(fn, report) + quit(1) + + echo "done" diff --git a/tests/varres/tnewseq_on_result_vart.nim b/tests/varres/tnewseq_on_result_vart.nim new file mode 100644 index 000000000..18935a1d1 --- /dev/null +++ b/tests/varres/tnewseq_on_result_vart.nim @@ -0,0 +1,9 @@ + +discard """ + line: 9 + errormsg: "address of 'result' may not escape its stack frame" +""" +# bug #5113 + +proc makeSeqVar(size: Natural): var seq[int] = + newSeq(result, size) diff --git a/tests/varres/tvarres1.nim b/tests/varres/tvarres1.nim index 849805768..5a5247142 100644 --- a/tests/varres/tvarres1.nim +++ b/tests/varres/tvarres1.nim @@ -1,7 +1,7 @@ discard """ file: "tvarres1.nim" line: 12 - errormsg: "address of 'bla' may not escape its stack frame" + errormsg: "'bla' escapes its stack frame; context: 'bla'" """ var diff --git a/tests/varres/tvarres_via_forwarding.nim b/tests/varres/tvarres_via_forwarding.nim new file mode 100644 index 000000000..8fd3dfcfd --- /dev/null +++ b/tests/varres/tvarres_via_forwarding.nim @@ -0,0 +1,12 @@ +discard """ + line: 10 + errormsg: "'y' escapes its stack frame; context: 'forward(y)'" +""" + +proc forward(x: var int): var int = result = x + +proc foo(): var int = + var y = 9 + result = forward(y) + +echo foo() diff --git a/tests/varres/twrong_parameter.nim b/tests/varres/twrong_parameter.nim new file mode 100644 index 000000000..8a363dd19 --- /dev/null +++ b/tests/varres/twrong_parameter.nim @@ -0,0 +1,16 @@ +discard """ + line: 10 + errormsg: "'x' is not the first parameter; context: 'x.field[0]'" +""" + +type + MyObject = object + field: array[2, int] + +proc forward(abc: int; x: var MyObject): var int = result = x.field[0] + +proc foo(): var int = + var y: MyObject + result = forward(45, y) + +echo foo() diff --git a/tests/vm/tnimnode.nim b/tests/vm/tnimnode.nim index 0614b9807..188bac9bf 100644 --- a/tests/vm/tnimnode.nim +++ b/tests/vm/tnimnode.nim @@ -26,12 +26,12 @@ proc checkNode(arg: NimNode; name: string): void {. compileTime .} = seqAppend.add(arg) # bit this creates a copy arg.add newCall(ident"echo", newLit("Hello World")) - assertEq arg.lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident(ident"echo"), StrLit(Hello World)))""" - assertEq node.lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident(ident"echo"), StrLit(Hello World)))""" - assertEq nodeArray[0].lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident(ident"echo"), StrLit(Hello World)))""" - assertEq nodeSeq[0].lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident(ident"echo"), StrLit(Hello World)))""" - assertEq seqAppend[0].lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident(ident"echo"), StrLit(Hello World)))""" - assertEq seqAppend[1].lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident(ident"echo"), StrLit(Hello World)))""" + assertEq arg.lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident("echo"), StrLit("Hello World")))""" + assertEq node.lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident("echo"), StrLit("Hello World")))""" + assertEq nodeArray[0].lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident("echo"), StrLit("Hello World")))""" + assertEq nodeSeq[0].lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident("echo"), StrLit("Hello World")))""" + assertEq seqAppend[0].lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident("echo"), StrLit("Hello World")))""" + assertEq seqAppend[1].lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident("echo"), StrLit("Hello World")))""" echo "OK" diff --git a/tests/vm/tref.nim b/tests/vm/tref.nim new file mode 100644 index 000000000..517a67fb0 --- /dev/null +++ b/tests/vm/tref.nim @@ -0,0 +1,12 @@ +static: + var + a: ref string + b: ref string + new a + + a[] = "Hello world" + b = a + + b[5] = 'c' + doAssert a[] == "Hellocworld" + doAssert b[] == "Hellocworld" \ No newline at end of file diff --git a/tests/vm/tvmmisc.nim b/tests/vm/tvmmisc.nim index 42a58fa8f..4af824cf4 100644 --- a/tests/vm/tvmmisc.nim +++ b/tests/vm/tvmmisc.nim @@ -1,5 +1,8 @@ # bug #4462 import macros +import os +import ospaths +import strutils block: proc foo(t: typedesc) {.compileTime.} = @@ -18,7 +21,7 @@ block: # #6379 static: import algorithm - + var numArray = [1, 2, 3, 4, -1] numArray.sort(cmp) assert numArray == [-1, 1, 2, 3, 4] @@ -57,10 +60,33 @@ block: result = @[0] result.setLen(2) var tmp: int - - for i in 0 .. <2: + + for i in 0 ..< 2: inc tmp result[i] = tmp const fact1000 = abc() assert fact1000 == @[1, 2] + +# Tests for VM ops +block: + static: + assert "vm" in getProjectPath() + + let b = getEnv("UNSETENVVAR") + assert b == "" + assert existsEnv("UNSERENVVAR") == false + putEnv("UNSETENVVAR", "VALUE") + assert getEnv("UNSETENVVAR") == "VALUE" + assert existsEnv("UNSETENVVAR") == true + + assert fileExists("MISSINGFILE") == false + assert dirExists("MISSINGDIR") == false + +# #7210 +block: + static: + proc f(size: int): int = + var some = newStringOfCap(size) + result = size + doAssert f(4) == 4 \ No newline at end of file |