diff options
Diffstat (limited to 'tests/vm')
97 files changed, 3279 insertions, 240 deletions
diff --git a/tests/vm/meta.nim b/tests/vm/meta.nim index 2aa01b5b3..32a441f27 100644 --- a/tests/vm/meta.nim +++ b/tests/vm/meta.nim @@ -39,7 +39,7 @@ proc newIdent*(node: NimNode): Ident = raise newException(ValueError, msg) proc render*(i: Ident): NimNode {.compileTime.} = - if i.name == nil: + if i.name == "": return newNimNode(nnkEmpty) if i.exported: @@ -67,7 +67,7 @@ proc newBracket*(node: NimNode): Bracket = raise newException(ValueError, msg) # Field procs -proc newField*(identifier: Ident, type_name: string, default: string = nil): Field = +proc newField*(identifier: Ident, type_name: string, default: string = ""): Field = result.identifier = identifier result.type_name = type_name result.default = default @@ -84,7 +84,7 @@ proc newField*(node: NimNode): Field = of nnkIdent: result.default = $(node[2]) else: - result.default = nil + result.default = "" else: let msg = "newField cannot initialize from node kind: " & $(node.kind) raise newException(ValueError, msg) @@ -102,7 +102,7 @@ proc newFieldSeq*(node: NimNode): FieldSeq = of nnkIdent: default = $(default_node) else: - default = nil + default = "" for i in 0..node.len - 3: let name = newIdent(node[i]) result.add(newField(name, type_name, default)) @@ -115,8 +115,8 @@ proc newFieldSeq*(node: NimNode): FieldSeq = proc render*(f: Field): NimNode {.compileTime.} = let identifier = f.identifier.render() - let type_name = if f.type_name != nil: ident(f.type_name) else: newEmptyNode() - let default = if f.default != nil: ident(f.default) else: newEmptyNode() + let type_name = if f.type_name != "": ident(f.type_name) else: newEmptyNode() + let default = if f.default != "": ident(f.default) else: newEmptyNode() newIdentDefs(identifier, type_name, default) proc render*(fs: FieldSeq): NimNode {.compileTime.} = @@ -127,7 +127,7 @@ proc render*(fs: FieldSeq): NimNode {.compileTime.} = # TypeDef procs proc newTypeDef*(identifier: Ident, is_ref = false, object_type = "object", - base_type: string = nil): TypeDef {.compileTime.} = + base_type: string = ""): TypeDef {.compileTime.} = result.identifier = identifier result.fields = @[] result.is_ref = is_ref @@ -165,7 +165,7 @@ proc render*(typedef: TypeDef): NimNode {.compileTime.} = result.add(newEmptyNode()) let object_node = newNimNode(nnkObjectTy) object_node.add(newEmptyNode()) - if typedef.base_type == nil: + if typedef.base_type == "": object_node.add(newEmptyNode()) else: var base_type = newNimNode(nnkOfInherit) @@ -195,8 +195,8 @@ proc render*(typeseq: TypeDefSeq): NimNode {.compileTime.} = for typedef in typeseq: result.add(typedef.render()) -proc newProc*(identifier: Ident, params: FieldSeq = nil, - returns: Ident, generics: FieldSeq = nil): Proc = +proc newProc*(identifier: Ident, params: FieldSeq = @[], + returns: Ident, generics: FieldSeq = @[]): Proc = result.identifier = identifier result.params = params result.returns = returns @@ -209,7 +209,7 @@ proc newProc*(node: NimNode): Proc = case node[2].kind: of nnkGenericParams: result.generics = newFieldSeq(node[2]) - else: result.generics = nil + else: result.generics = @[] let formal_params = node[3] case formal_params[0].kind: of nnkIdent: diff --git a/tests/vm/mevalffi.nim b/tests/vm/mevalffi.nim new file mode 100644 index 000000000..ad8f8b62b --- /dev/null +++ b/tests/vm/mevalffi.nim @@ -0,0 +1,71 @@ +# re-enable for windows once libffi can be installed in koch.nim +# With win32 (not yet win64), libffi on windows works and this test passes. + +when defined(linux) or defined(bsd): + {.passL: "-lm".} # for exp +proc c_exp(a: float64): float64 {.importc: "exp", header: "<math.h>".} + +proc c_printf(frmt: cstring): cint {.importc: "printf", header: "<stdio.h>", varargs, discardable.} + +const snprintfName = when defined(windows): "_snprintf" else: "snprintf" +proc c_snprintf*(str: cstring, size: csize_t, format: cstring): cint {.importc: snprintfName, header: "<stdio.h>", varargs .} + +proc c_malloc(size: csize_t): pointer {.importc:"malloc", header: "<stdlib.h>".} +proc c_free(p: pointer) {.importc:"free", header: "<stdlib.h>".} + +proc fun() = + block: # c_exp + var x = 0.3 + let b = c_exp(x) + let b2 = int(b*1_000_000) # avoids floating point equality + doAssert b2 == 1349858 + doAssert c_exp(0.3) == c_exp(x) + const x2 = 0.3 + doAssert c_exp(x2) == c_exp(x) + + block: # c_printf + c_printf("foo\n") + c_printf("foo:%d\n", 100) + c_printf("foo:%d\n", 101.cint) + c_printf("foo:%d:%d\n", 102.cint, 103.cint) + let temp = 104.cint + c_printf("foo:%d:%d:%d\n", 102.cint, 103.cint, temp) + var temp2 = 105.cint + c_printf("foo:%g:%s:%d:%d\n", 0.03, "asdf", 103.cint, temp2) + + block: # c_snprintf, c_malloc, c_free + let n: uint = 50 + var buffer2 = cstring(cast[ptr char](c_malloc(n))) + + var s: cstring = "foobar" + var age: cint = 25 + let num = c_snprintf(buffer2, n, "s1:%s s2:%s age:%d pi:%g", s, s, age, 3.14) + let numExp = 34 + doAssert num == numExp + c_printf("ret=[%s]\n", buffer2) + c_free(buffer2) + + block: # c_printf bug + var a = 123 + var a2 = a.addr + #[ + bug: different behavior between CT RT in this case: + at CT, shows foo2:a=123 + at RT, shows foo2:a=<address as int> + ]# + if false: + c_printf("foo2:a=%d\n", a2) + + +static: + fun() +fun() + +when not defined nimEvalffiStderrWorkaround: + import system/ansi_c + block: + proc fun2()= + c_fprintf(cstderr, "hello world stderr\n") + write(stderr, "hi stderr\n") + static: fun2() + fun2() diff --git a/tests/vm/mscriptcompiletime.nim b/tests/vm/mscriptcompiletime.nim new file mode 100644 index 000000000..ed7e7c029 --- /dev/null +++ b/tests/vm/mscriptcompiletime.nim @@ -0,0 +1,7 @@ +# bug.nim +var bar* {.compileTime.} = 1 + +proc dummy = discard + +static: + inc bar \ No newline at end of file diff --git a/tests/vm/t11637.nim b/tests/vm/t11637.nim new file mode 100644 index 000000000..c061c6641 --- /dev/null +++ b/tests/vm/t11637.nim @@ -0,0 +1,52 @@ +type Foo = ref object + val: int + +proc `+`(a, b: Foo): Foo = + Foo(val: a.val + b.val) + +proc `*`(a: Foo, b: int): Foo = + Foo(val: a.val * b) + +proc `+=`(a: var Foo, b: Foo) = + a = Foo( + val: a.val + b.val + ) + +proc foobar(a, b, c: Foo): tuple[bar, baz, buzz: Foo] = + + let foo = a + b + c + result.bar = foo * 2 + + result.baz = foo * 3 + result.buzz = result.baz + + result.buzz += a * 10000 + result.baz += b + result.buzz += b + + +block: # Compile-Time + let + a {.compileTime.} = Foo(val: 1) + b {.compileTime.} = Foo(val: 2) + c {.compileTime.} = Foo(val: 3) + r {.compileTime.} = foobar(a, b, c) + + static: + doAssert r.bar.val == 12 + doAssert r.baz.val == 20 + doAssert r.buzz.val == 10020 + +#################################### + +block: # Run-time + let + a = Foo(val: 1) + b = Foo(val: 2) + c = Foo(val: 3) + r = foobar(a, b, c) + + # Expected values + doAssert r.bar.val == 12 + doAssert r.baz.val == 20 + doAssert r.buzz.val == 10020 diff --git a/tests/vm/t17039.nim b/tests/vm/t17039.nim new file mode 100644 index 000000000..f92c93f30 --- /dev/null +++ b/tests/vm/t17039.nim @@ -0,0 +1,10 @@ +type + Obj1 = object + case kind: bool + of false: + field: seq[int] + else: discard + +static: + var obj1 = Obj1() + obj1.field.add(@[]) diff --git a/tests/vm/t17121.nim b/tests/vm/t17121.nim new file mode 100644 index 000000000..bf2d6423f --- /dev/null +++ b/tests/vm/t17121.nim @@ -0,0 +1,9 @@ +discard """ + errormsg: "cannot 'importc' variable at compile time; c_printf" +""" + +proc c_printf*(frmt: cstring): cint {.importc: "printf", header: "<stdio.h>", varargs, discardable.} = + ## foo bar + runnableExamples: discard +static: + let a = c_printf("abc\n") diff --git a/tests/vm/t18103.nim b/tests/vm/t18103.nim new file mode 100644 index 000000000..8622ab290 --- /dev/null +++ b/tests/vm/t18103.nim @@ -0,0 +1,35 @@ +discard """ + targets: "c cpp" + matrix: "--mm:refc; --mm:arc" +""" + +import base64, complex, sequtils, math, sugar + +type + + FP = float + T = object + index: int + arg: FP + val: Complex[FP] + M = object + alpha, beta: FP + +func a(s: openArray[T], model: M): seq[T] = + let f = (tn: int) => model.alpha + FP(tn) * model.beta; + return mapIt s: + block: + let s = it.val * rect(1.0, - f(it.index)) + T(index: it.index, arg: phase(s), val: s) + +proc b(): float64 = + var s = toSeq(0..10).mapIt(T(index: it, arg: 1.0, val: complex.complex(1.0))) + discard a(s, M(alpha: 1, beta: 1)) + return 1.0 + +func cc(str: cstring, offset: ptr[cdouble]): cint {.exportc.} = + offset[] = b() + return 0 + +static: + echo b() diff --git a/tests/vm/t19075.nim b/tests/vm/t19075.nim new file mode 100644 index 000000000..89ca9cb19 --- /dev/null +++ b/tests/vm/t19075.nim @@ -0,0 +1,19 @@ +discard """ + timeout: 10 + joinable: false +""" + +# bug #19075 +const size = 50_000 + +const stuff = block: + var a: array[size, int] + a + +const zeugs = block: + var zeugs: array[size, int] + for i in 0..<size: + zeugs[i] = stuff[i] + zeugs + +doAssert zeugs[0] == 0 \ No newline at end of file diff --git a/tests/vm/t19199.nim b/tests/vm/t19199.nim new file mode 100644 index 000000000..6ae48cb54 --- /dev/null +++ b/tests/vm/t19199.nim @@ -0,0 +1,6 @@ +# bug #19199 +proc mikasa(x: float) = doAssert x == 42 + +static: + mikasa 42.uint.float +mikasa 42.uint.float diff --git a/tests/vm/t20746.nim b/tests/vm/t20746.nim new file mode 100644 index 000000000..bfad269ef --- /dev/null +++ b/tests/vm/t20746.nim @@ -0,0 +1,13 @@ +discard """ + timeout: 10 + joinable: false + output: "fine" +""" + +func addString(): string = + let x = newString(1000000) + for i in 0..<1000000: + discard x[i] + +const translationTable = addString() +echo "fine" diff --git a/tests/vm/t21704.nim b/tests/vm/t21704.nim new file mode 100644 index 000000000..27f4f5b06 --- /dev/null +++ b/tests/vm/t21704.nim @@ -0,0 +1,69 @@ +discard """ +matrix: "--hints:off" +nimout: ''' +Found 2 tests to run. +Found 3 benches to compile. + + --passC:-Wno-stringop-overflow --passL:-Wno-stringop-overflow + + --passC:-Wno-stringop-overflow --passL:-Wno-stringop-overflow + + --passC:-Wno-stringop-overflow --passL:-Wno-stringop-overflow +''' +""" +# bug #21704 +import std/strformat + +const testDesc: seq[string] = @[ + "tests/t_hash_sha256_vs_openssl.nim", + "tests/t_cipher_chacha20.nim" +] +const benchDesc = [ + "bench_sha256", + "bench_hash_to_curve", + "bench_ethereum_bls_signatures" +] + +proc setupTestCommand(flags, path: string): string = + return "nim c -r " & + flags & + &" --nimcache:nimcache/{path} " & # Commenting this out also solves the issue + path + +proc testBatch(commands: var string, flags, path: string) = + commands &= setupTestCommand(flags, path) & '\n' + +proc setupBench(benchName: string): string = + var runFlags = if false: " -r " + else: " " # taking this branch is needed to trigger the bug + + echo runFlags # Somehow runflags isn't reset in corner cases + runFlags &= " --passC:-Wno-stringop-overflow --passL:-Wno-stringop-overflow " + echo runFlags + + return "nim c " & + runFlags & + &" benchmarks/{benchName}.nim" + +proc buildBenchBatch(commands: var string, benchName: string) = + let command = setupBench(benchName) + commands &= command & '\n' + +proc addTestSet(cmdFile: var string) = + echo "Found " & $testDesc.len & " tests to run." + + for path in testDesc: + var flags = "" # This is important + cmdFile.testBatch(flags, path) + +proc addBenchSet(cmdFile: var string) = + echo "Found " & $benchDesc.len & " benches to compile." + for bd in benchDesc: + cmdFile.buildBenchBatch(bd) + +proc task_bug() = + var cmdFile: string + cmdFile.addTestSet() # Comment this out and there is no bug + cmdFile.addBenchSet() + +static: task_bug() diff --git a/tests/vm/t2574.nim b/tests/vm/t2574.nim new file mode 100644 index 000000000..4332667b4 --- /dev/null +++ b/tests/vm/t2574.nim @@ -0,0 +1,14 @@ +discard """ + errormsg: "cannot call method eval at compile time" + line: 14 +""" + +type + PExpr = ref object of RootObj + +method eval(e: PExpr): int = + discard + +static: + let x = PExpr() + discard x.eval diff --git a/tests/vm/t9622.nim b/tests/vm/t9622.nim new file mode 100644 index 000000000..fada8fe59 --- /dev/null +++ b/tests/vm/t9622.nim @@ -0,0 +1,30 @@ +discard """ + targets: "c cpp" + matrix: "--mm:refc; --mm:arc" +""" + +type + GlobNodeKind = enum + LiteralIdent, + Group + + GlobNode = object + case kind: GlobNodeKind + of LiteralIdent: + value: string + of Group: + values: seq[string] + + PathSegment = object + children: seq[GlobNode] + + GlobPattern = seq[PathSegment] + +proc parseImpl(): GlobPattern = + if result.len == 0: + result.add PathSegment() + result[^1].children.add GlobNode(kind: LiteralIdent) + +block: + const pattern = parseImpl() + doAssert $pattern == """@[(children: @[(kind: LiteralIdent, value: "")])]""" diff --git a/tests/vm/tableinstatic.nim b/tests/vm/tableinstatic.nim index b0d24b477..934c3a8dd 100644 --- a/tests/vm/tableinstatic.nim +++ b/tests/vm/tableinstatic.nim @@ -2,7 +2,7 @@ discard """ nimout: '''0 0 0 -{"hallo": "123", "welt": "456"}''' +''' """ import tables @@ -35,4 +35,4 @@ static: otherTable["hallo"] = "123" otherTable["welt"] = "456" - echo otherTable + doAssert otherTable == {"hallo": "123", "welt": "456"}.newTable diff --git a/tests/vm/taddrof.nim b/tests/vm/taddrof.nim new file mode 100644 index 000000000..bbe9345d2 --- /dev/null +++ b/tests/vm/taddrof.nim @@ -0,0 +1,110 @@ +discard """ +nimout: ''' +true +true +[nil, nil, nil, nil] +[MyObjectRef(123, 321), nil, nil, nil] +['A', '\x00', '\x00', '\x00'] +MyObjectRef(123, 321) +(key: 8, val: 0) +''' +output: ''' +true +true +[nil, nil, nil, nil] +[MyObjectRef(123, 321), nil, nil, nil] +['A', '\x00', '\x00', '\x00'] +MyObjectRef(123, 321) +''' +""" + +type + MyObjectRef = ref object + a,b: int + + MyContainerObject = ref object + member: MyObjectRef + + MySuperContainerObject = ref object + member: MyContainerObject + arr: array[4, MyObjectRef] + + MyOtherObject = ref object + case kind: bool + of true: + member: MyObjectRef + else: + discard + +proc `$`(arg: MyObjectRef): string = + result = "MyObjectRef(" + result.addInt arg.a + result.add ", " + result.addInt arg.b + result.add ")" + +proc foobar(dst: var MyObjectRef) = + dst = new(MyObjectRef) + dst.a = 123 + dst.b = 321 + +proc changeChar(c: var char) = + c = 'A' + +proc test() = + # when it comes from a var, it works + var y: MyObjectRef + foobar(y) + echo y != nil + # when it comes from a member, it fails on VM + var x = new(MyContainerObject) + foobar(x.member) + echo x.member != nil + + # when it comes from an array, it fails on VM + var arr: array[4, MyObjectRef] + echo arr + foobar(arr[0]) + echo arr + + var arr2: array[4, char] + changeChar(arr2[0]) + echo arr2 + + + var z = MyOtherObject(kind: true) + foobar(z.member) + echo z.member + + # this still doesn't work + # var sc = new(MySuperContainerObject) + # sc.member = new(MyContainerObject) + # foobar(sc.member.member) + # echo sc.member.member + # foobar(sc.arr[1]) + # echo sc.arr + + #var str = "---" + #changeChar(str[1]) + #echo str + +test() +static: + test() + +type T = object + f: seq[tuple[key, val: int]] + +proc foo(s: var seq[tuple[key, val: int]]; i: int) = + s[i].key = 4*i + # r4 = addr(s[i]) + # r4[0] = 4*i + +proc bar() = + var s: T + s.f = newSeq[tuple[key, val: int]](3) + foo(s.f, 2) + echo s.f[2] + +static: + bar() diff --git a/tests/vm/tanonproc.nim b/tests/vm/tanonproc.nim index c5cb57d75..1176c104e 100644 --- a/tests/vm/tanonproc.nim +++ b/tests/vm/tanonproc.nim @@ -4,7 +4,7 @@ discard """ # bug #3561 -import macros, future, strutils +import macros, sugar, strutils type Option[T] = ref object @@ -42,7 +42,7 @@ proc getOrElse[T](o: Option[T], def: T): T = proc quoteStr(s: string): Option[string] = s.some.notEmpty.map(v => "`" & v & "`") -macro str(s: string): typed = +macro str(s: string): void = let x = s.strVal let y = quoteStr(x) let sn = newStrLitNode(y.getOrElse("NONE")) diff --git a/tests/vm/tbitops.nim b/tests/vm/tbitops.nim new file mode 100644 index 000000000..90d463ec9 --- /dev/null +++ b/tests/vm/tbitops.nim @@ -0,0 +1,45 @@ +discard """ +output: "" +""" + +import strutils + +const x = [1'i32, -1, -10, 10, -10, 10, -20, 30, -40, 50, 7 shl 28, -(7 shl 28), 7 shl 28, -(7 shl 28)] +const y = [-1'i32, 1, -10, -10, 10, 10, -20, -30, 40, 50, 1 shl 30, 1 shl 30, -(1 shl 30), -(1 shl 30)] + +const res_xor = block: + var tmp: seq[int64] + for i in 0 ..< x.len: + tmp.add(int64(x[i] xor y[i])) + tmp + +const res_and = block: + var tmp: seq[int64] + for i in 0 ..< x.len: + tmp.add(int64(x[i] and y[i])) + tmp + +const res_or = block: + var tmp: seq[int64] + for i in 0 ..< x.len: + tmp.add(int64(x[i] or y[i])) + tmp + +const res_not = block: + var tmp: seq[int64] + for i in 0 ..< x.len: + tmp.add(not x[i]) + tmp + +let xx = x +let yy = y + +for i in 0..<xx.len: + let z_xor = int64(xx[i] xor yy[i]) + let z_and = int64(xx[i] and yy[i]) + let z_or = int64(xx[i] or yy[i]) + let z_not = int64(not xx[i]) + doAssert(z_xor == res_xor[i], $i & ": " & $res_xor[i] & " " & $z_xor) + doAssert(z_and == res_and[i], $i & ": " & $res_and[i] & " " & $z_and) + doAssert(z_or == res_or[i], $i & ": " & $res_or[i] & " " & $z_or) + doAssert(z_not == res_not[i], $i & ": " & $res_not[i] & " " & $z_not) diff --git a/tests/vm/tcastint.nim b/tests/vm/tcastint.nim index 7b9ddd7d9..c306e4a31 100644 --- a/tests/vm/tcastint.nim +++ b/tests/vm/tcastint.nim @@ -1,8 +1,5 @@ -discard """ - file: "tcastint.nim" - output: "OK" -""" - +import macros +from stdtest/testutils import disableVM type Dollar = distinct int XCoord = distinct int32 @@ -14,6 +11,12 @@ proc `==`(x, y: XCoord): bool {.borrow.} proc dummy[T](x: T): T = x +template roundTrip(a, T) = + let a2 = a # sideeffect safe + let b = cast[T](a2) + let c = cast[type(a2)](b) + doAssert c == a2 + proc test() = let U8 = 0b1011_0010'u8 let I8 = 0b1011_0010'i8 @@ -101,20 +104,206 @@ proc test() = doAssert(cast[int](digit) == raw) doAssert(cast[Digit](raw) == digit) - when defined nimvm: - doAssert(not compiles(cast[float](I64A))) - doAssert(not compiles(cast[float32](I64A))) + block: + roundTrip(I64A, float) + roundTrip(I8, uint16) + roundTrip(I8, uint32) + roundTrip(I8, uint64) + doAssert cast[uint16](I8) == 65458'u16 + doAssert cast[uint32](I8) == 4294967218'u32 + doAssert cast[uint64](I8) == 18446744073709551538'u64 + doAssert cast[uint32](I64A) == 2571663889'u32 + doAssert cast[uint16](I64A) == 31249 + doAssert cast[char](I64A).ord == 17 + doAssert compiles(cast[float32](I64A)) + + disableVM: # xxx Error: VM does not support 'cast' from tyInt64 to tyFloat32 + doAssert cast[uint32](cast[float32](I64A)) == 2571663889'u32 + +const prerecordedResults = [ + # cast to char + "\0", "\255", + "\0", "\255", + "\0", "\255", + "\0", "\255", + "\0", "\255", + "\128", "\127", + "\0", "\255", + "\0", "\255", + "\0", "\255", + # cast to uint8 + "0", "255", + "0", "255", + "0", "255", + "0", "255", + "0", "255", + "128", "127", + "0", "255", + "0", "255", + "0", "255", + # cast to uint16 + "0", "255", + "0", "255", + "0", "65535", + "0", "65535", + "0", "65535", + "65408", "127", + "32768", "32767", + "0", "65535", + "0", "65535", + # cast to uint32 + "0", "255", + "0", "255", + "0", "65535", + "0", "4294967295", + "0", "4294967295", + "4294967168", "127", + "4294934528", "32767", + "2147483648", "2147483647", + "0", "4294967295", + # cast to uint64 + "0", "255", + "0", "255", + "0", "65535", + "0", "4294967295", + "0", "18446744073709551615", + "18446744073709551488", "127", + "18446744073709518848", "32767", + "18446744071562067968", "2147483647", + "9223372036854775808", "9223372036854775807", + # cast to int8 + "0", "-1", + "0", "-1", + "0", "-1", + "0", "-1", + "0", "-1", + "-128", "127", + "0", "-1", + "0", "-1", + "0", "-1", + # cast to int16 + "0", "255", + "0", "255", + "0", "-1", + "0", "-1", + "0", "-1", + "-128", "127", + "-32768", "32767", + "0", "-1", + "0", "-1", + # cast to int32 + "0", "255", + "0", "255", + "0", "65535", + "0", "-1", + "0", "-1", + "-128", "127", + "-32768", "32767", + "-2147483648", "2147483647", + "0", "-1", + # cast to int64 + "0", "255", + "0", "255", + "0", "65535", + "0", "4294967295", + "0", "-1", + "-128", "127", + "-32768", "32767", + "-2147483648", "2147483647", + "-9223372036854775808", "9223372036854775807", +] + +proc free_integer_casting() = + # cast from every integer type to every type and ensure same + # behavior in vm and execution time. + macro bar(arg: untyped) = + result = newStmtList() + var i = 0 + for it1 in arg: + let typA = it1[0] + for it2 in arg: + let lowB = it2[1] + let highB = it2[2] + let castExpr1 = nnkCast.newTree(typA, lowB) + let castExpr2 = nnkCast.newTree(typA, highB) + let lit1 = newLit(prerecordedResults[i*2]) + let lit2 = newLit(prerecordedResults[i*2+1]) + result.add quote do: + doAssert($(`castExpr1`) == `lit1`) + doAssert($(`castExpr2`) == `lit2`) + i += 1 + + bar([ + (char, '\0', '\255'), + (uint8, 0'u8, 0xff'u8), + (uint16, 0'u16, 0xffff'u16), + (uint32, 0'u32, 0xffffffff'u32), + (uint64, 0'u64, 0xffffffffffffffff'u64), + (int8, 0x80'i8, 0x7f'i8), + (int16, 0x8000'i16, 0x7fff'i16), + (int32, 0x80000000'i32, 0x7fffffff'i32), + (int64, 0x8000000000000000'i64, 0x7fffffffffffffff'i64) + ]) + +proc test_float_cast = + + const + exp_bias = 1023'i64 + exp_shift = 52 + exp_mask = 0x7ff'i64 shl exp_shift + mantissa_mask = 0xfffffffffffff'i64 + + let f = 8.0 + let fx = cast[int64](f) + let exponent = ((fx and exp_mask) shr exp_shift) - exp_bias + let mantissa = fx and mantissa_mask + doAssert(exponent == 3, $exponent) + doAssert(mantissa == 0, $mantissa) + + # construct 2^N float, where N is integer + let x = -2'i64 + let xx = (x + exp_bias) shl exp_shift + let xf = cast[float](xx) + doAssert(xf == 0.25, $xf) + +proc test_float32_cast = + + const + exp_bias = 127'i32 + exp_shift = 23 + exp_mask = 0x7f800000'i32 + mantissa_mask = 0x007ffff'i32 + + let f = -0.5'f32 + let fx = cast[int32](f) + let exponent = ((fx and exp_mask) shr exp_shift) - exp_bias + let mantissa = fx and mantissa_mask + doAssert(exponent == -1, $exponent) + doAssert(mantissa == 0, $mantissa) - doAssert(not compiles(cast[char](I64A))) - doAssert(not compiles(cast[uint16](I64A))) - doAssert(not compiles(cast[uint32](I64A))) + # construct 2^N float32 where N is integer + let x = 4'i32 + let xx = (x + exp_bias) shl exp_shift + let xf = cast[float32](xx) + doAssert(xf == 16.0'f32, $xf) - doAssert(not compiles(cast[uint16](I8))) - doAssert(not compiles(cast[uint32](I8))) - doAssert(not compiles(cast[uint64](I8))) +proc test_float32_castB() = + let a: float32 = -123.125 + let b = cast[int32](a) + let c = cast[uint32](a) + doAssert b == -1024049152 + doAssert cast[uint64](b) == 18446744072685502464'u64 + doAssert c == 3270918144'u32 + # ensure the unused bits in the internal representation don't have + # any surprising content. + doAssert cast[uint64](c) == 3270918144'u64 -test() -static: +template main() = test() + test_float_cast() + test_float32_cast() + free_integer_casting() + test_float32_castB() -echo "OK" +static: main() +main() diff --git a/tests/vm/tcgemptycallarg.nim b/tests/vm/tcgemptycallarg.nim new file mode 100644 index 000000000..1bedb5070 --- /dev/null +++ b/tests/vm/tcgemptycallarg.nim @@ -0,0 +1,3 @@ +static: + doAssertRaises(ValueError): + raise newException(ValueError, "Yes") diff --git a/tests/vm/tclosureiterator.nim b/tests/vm/tclosureiterator.nim new file mode 100644 index 000000000..c909392d5 --- /dev/null +++ b/tests/vm/tclosureiterator.nim @@ -0,0 +1,9 @@ +discard """ + errormsg: "Closure iterators are not supported by VM!" +""" + +iterator iter*(): int {.closure.} = + yield 3 + +static: + var x = iter diff --git a/tests/vm/tcnstseq.nim b/tests/vm/tcnstseq.nim new file mode 100644 index 000000000..5679a6e37 --- /dev/null +++ b/tests/vm/tcnstseq.nim @@ -0,0 +1,68 @@ +discard """ +output: ''' +AngelikaAnneAnnaAnkaAnja +AngelikaAnneAnnaAnkaAnja +AngelikaAnneAnnaAnkaAnja +onetwothree +onetwothree +onetwothree +one1two2three3 +''' +""" +# Test the new implicit conversion from sequences to arrays in a constant +# context. + +import strutils + + +block t1: + const + myWords = "Angelika Anne Anna Anka Anja".split() + + for x in items(myWords): + write(stdout, x) #OUT AngelikaAnneAnnaAnkaAnja + echo "" + + +block t2: + const + myWords = @["Angelika", "Anne", "Anna", "Anka", "Anja"] + + for i in 0 .. high(myWords): + write(stdout, myWords[i]) #OUT AngelikaAnneAnnaAnkaAnja + echo "" + + +block t3: + for w in items(["Angelika", "Anne", "Anna", "Anka", "Anja"]): + write(stdout, w) #OUT AngelikaAnneAnnaAnkaAnja + echo "" + + +block t2656: + iterator it1(args: seq[string]): string = + for s in args: yield s + iterator it2(args: seq[string]): string {.closure.} = + for s in args: yield s + iterator it3(args: openArray[string]): string {.closure.} = + for s in args: yield s + iterator it4(args: openArray[(string, string)]): string {.closure.} = + for s1, s2 in items(args): yield s1 & s2 + + block: + const myConstSeq = @["one", "two", "three"] + for s in it1(myConstSeq): + stdout.write s + echo "" + for s in it2(myConstSeq): + stdout.write s + echo "" + for s in it3(myConstSeq): + stdout.write s + echo "" + + block: + const myConstSeq = @[("one", "1"), ("two", "2"), ("three", "3")] + for s in it4(myConstSeq): + stdout.write s + echo "" diff --git a/tests/vm/tcompilesetting.nim b/tests/vm/tcompilesetting.nim new file mode 100644 index 000000000..d6c08e70f --- /dev/null +++ b/tests/vm/tcompilesetting.nim @@ -0,0 +1,18 @@ +discard """ +cmd: "nim c --nimcache:build/myNimCache --nimblePath:myNimblePath --gc:arc $file" +joinable: false +""" + +import std/[strutils,compilesettings] +from std/os import fileExists, `/` + +template main = + doAssert querySetting(nimcacheDir) == nimcacheDir.querySetting + doAssert "myNimCache" in nimcacheDir.querySetting + doAssert "myNimblePath" in nimblePaths.querySettingSeq[0] + doAssert querySetting(backend) == "c" + doAssert fileExists(libPath.querySetting / "system.nim") + doAssert querySetting(mm) == "arc" + +static: main() +main() diff --git a/tests/vm/tcompiletimerange.nim b/tests/vm/tcompiletimerange.nim new file mode 100644 index 000000000..cd675b4a3 --- /dev/null +++ b/tests/vm/tcompiletimerange.nim @@ -0,0 +1,28 @@ +discard """ +""" + +# issue #8199 + +const rangesGCHoldEnabled = true # not defined(rangesDisableGCHold) + +type + # A view into immutable array + Range*[T] {.shallow.} = object + when rangesGCHoldEnabled: + gcHold: seq[T] # 0 + start: ptr T # 1 + mLen: int32 # 2 + +type + BytesRange* = Range[byte] + NibblesRange* = object + bytes: BytesRange + +const + zeroBytesRange* = BytesRange() + +proc initNibbleRange*(bytes: BytesRange): NibblesRange = + result.bytes = bytes + +const + zeroNibblesRange* = initNibbleRange(zeroBytesRange) diff --git a/tests/vm/tcompiletimesideeffects.nim b/tests/vm/tcompiletimesideeffects.nim new file mode 100644 index 000000000..4cd57b3bd --- /dev/null +++ b/tests/vm/tcompiletimesideeffects.nim @@ -0,0 +1,42 @@ +discard """ + output: +''' +@[0, 1, 2] +@[3, 4, 5] +@[0, 1, 2] +3 +4 +''' +""" + +template runNTimes(n: int, f : untyped) : untyped = + var accum: seq[type(f)] + for i in 0..n-1: + accum.add(f) + accum + +var state {.compileTime.} : int = 0 +proc fill(): int {.compileTime.} = + result = state + inc state + +# invoke fill() at compile time as a compile time expression +const C1 = runNTimes(3, fill()) +echo C1 + +# invoke fill() at compile time as a set of compile time statements +const C2 = + block: + runNTimes(3, fill()) +echo C2 + +# invoke fill() at compile time after a compile time reset of state +const C3 = + block: + state = 0 + runNTimes(3, fill()) +echo C3 + +# evaluate fill() at compile time and use the results at runtime +echo fill() +echo fill() diff --git a/tests/vm/tcompiletimetable.nim b/tests/vm/tcompiletimetable.nim index e78c06536..1db490f1a 100644 --- a/tests/vm/tcompiletimetable.nim +++ b/tests/vm/tcompiletimetable.nim @@ -1,9 +1,16 @@ discard """ - nimout: '''2 + nimout: ''' +2 3 4:2 Got Hi -Got Hey''' +Got Hey +''' + output:''' +a +b +c +''' """ # bug #404 @@ -47,3 +54,9 @@ addStuff("Hey"): echo "Hey" addStuff("Hi"): echo "Hi" dump() +# ensure .compileTime vars can be used at runtime: +import macros + +var xzzzz {.compileTime.}: array[3, string] = ["a", "b", "c"] + +for i in 0..high(xzzzz): echo xzzzz[i] diff --git a/tests/vm/tcomponent.nim b/tests/vm/tcomponent.nim index e7962e7ab..b509bc5d7 100644 --- a/tests/vm/tcomponent.nim +++ b/tests/vm/tcomponent.nim @@ -11,7 +11,7 @@ FOO: blah''' import macros, sequtils, tables import strutils -import future, meta +import sugar, meta type Component = object diff --git a/tests/vm/tconst.nim b/tests/vm/tconst.nim new file mode 100644 index 000000000..5cfe7533e --- /dev/null +++ b/tests/vm/tconst.nim @@ -0,0 +1,58 @@ +discard """ + targets: "c cpp js" +""" + +import std/strutils + +template forceConst(a: untyped): untyped = + ## Force evaluation at CT, but `static(a)` is simpler + const ret = a + ret + +proc isNimVm(): bool = + when nimvm: result = true + else: result = false + +block: + doAssert forceConst(isNimVm()) + doAssert not isNimVm() + doAssert forceConst(isNimVm()) == static(isNimVm()) + doAssert forceConst(isNimVm()) == isNimVm().static + +template main() = + # xxx merge more const related tests here + const ct = CompileTime + # refs https://github.com/timotheecour/Nim/issues/718, apparently `CompileTime` + # isn't cached, which seems surprising. + block: + const + a = """ + Version $1| + Compiled at: $2, $3 + """ % [NimVersion & spaces(44-len(NimVersion)), CompileDate, ct] + let b = $a + doAssert ct in b, $(b, ct) + doAssert NimVersion in b + + block: # Test for fix on broken const unpacking + template mytemp() = + const + (x, increment) = (4, true) + a = 100 + discard (x, increment, a) + mytemp() + + block: # bug #12334 + block: + const b: cstring = "foo" + var c = b + doAssert c == "foo" + block: + const a = "foo" + const b: cstring = a + var c = b + doAssert c == "foo" + + +static: main() +main() diff --git a/tests/vm/tconstarrayresem.nim b/tests/vm/tconstarrayresem.nim new file mode 100644 index 000000000..6701cfe4d --- /dev/null +++ b/tests/vm/tconstarrayresem.nim @@ -0,0 +1,29 @@ +# issue #23010 + +type + Result[T, E] = object + case oResult: bool + of false: + discard + of true: + vResult: T + + Opt[T] = Result[T, void] + +template ok[T, E](R: type Result[T, E], x: untyped): R = + R(oResult: true, vResult: x) + +template c[T](v: T): Opt[T] = Opt[T].ok(v) + +type + FixedBytes[N: static[int]] = distinct array[N, byte] + + H = object + d: FixedBytes[2] + +const b = default(H) +template g(): untyped = + const t = default(H) + b + +discard c(g()) diff --git a/tests/vm/tconsteval.nim b/tests/vm/tconsteval.nim deleted file mode 100644 index f4260495a..000000000 --- a/tests/vm/tconsteval.nim +++ /dev/null @@ -1,31 +0,0 @@ -discard """ -""" - -import strutils - -const - HelpText = """ -+-----------------------------------------------------------------+ -| Maintenance program for Nim | -| Version $1| -| (c) 2012 Andreas Rumpf | -+-----------------------------------------------------------------+ -Compiled at: $2, $3 - -Usage: - koch [options] command [options for command] -Options: - --force, -f, -B, -b forces rebuild - --help, -h shows this help and quits -Possible Commands: - boot [options] bootstraps with given command line options - clean cleans Nim project; removes generated files - web generates the website - csource [options] builds the C sources for installation - zip builds the installation ZIP package - inno builds the Inno Setup installer -""" % [NimVersion & spaces(44-len(NimVersion)), - CompileDate, CompileTime] - -echo HelpText - diff --git a/tests/vm/tconstobj.nim b/tests/vm/tconstobj.nim index 38fcdd844..7dc20a0ba 100644 --- a/tests/vm/tconstobj.nim +++ b/tests/vm/tconstobj.nim @@ -1,10 +1,13 @@ discard """ - output: '''(name: "hello") -(-1, 0)''' + output: ''' +(name: "hello") +(-1, 0) +(FirstName: "James", LastName: "Franco") +[1, 2, 3] +''' """ # bug #2774, bug #3195 - type Foo = object name: string @@ -14,7 +17,6 @@ const fooArray = [ echo fooArray[0] - type Position = object x, y: int @@ -34,3 +36,60 @@ const ] echo offset[1] + +# bug #1547 +import tables + +type Person* = object + FirstName*: string + LastName*: string + +let people = { + "001": Person(FirstName: "James", LastName: "Franco") +}.toTable() + +echo people["001"] + +# Object downconversion should not copy + +type + SomeBaseObj {.inheritable.} = object of RootObj + txt : string + InheritedFromBase = object of SomeBaseObj + other : string + +proc initBase(sbo: var SomeBaseObj) = + sbo.txt = "Initialized string from base" + +static: + var ifb2: InheritedFromBase + initBase(SomeBaseObj(ifb2)) + echo repr(ifb2) + doAssert(ifb2.txt == "Initialized string from base") + +static: # issue #11861 + var ifb2: InheritedFromBase + initBase(ifb2) + doAssert(ifb2.txt == "Initialized string from base") + + +static: # issue #15662 + proc a(T: typedesc) = echo T.type + a((int, int)) + +# bug #16069 +type + E = enum + val1, val2 + Obj = object + case k: E + of val1: + x: array[3, int] + of val2: + y: uint32 + +const + foo = [1, 2, 3] + arr = Obj(k: val1, x: foo) + +echo arr.x diff --git a/tests/vm/tconstprocassignments.nim b/tests/vm/tconstprocassignments.nim new file mode 100644 index 000000000..0e2d2ed16 --- /dev/null +++ b/tests/vm/tconstprocassignments.nim @@ -0,0 +1,18 @@ +discard """ + output: ''' +100 +100 +''' +""" + +proc f():int {.compileTime.} = 100 + +const F = f +echo F() + +const G = proc ():int = + let x = f + let y = x + y() + +echo G() diff --git a/tests/vm/tconstresem.nim b/tests/vm/tconstresem.nim new file mode 100644 index 000000000..4526cb891 --- /dev/null +++ b/tests/vm/tconstresem.nim @@ -0,0 +1,10 @@ +block: # issue #19849 + type + Vec2[T] = object + x, y: T + Vec2i = Vec2[int] + template getX(p: Vec2i): int = p.x + let x = getX: + const t = Vec2i(x: 1, y: 2) + t + doAssert x == 1 diff --git a/tests/vm/tconstscope1.nim b/tests/vm/tconstscope1.nim new file mode 100644 index 000000000..41c45a28f --- /dev/null +++ b/tests/vm/tconstscope1.nim @@ -0,0 +1,5 @@ +# issue #5395 + +const a = (var b = 3; b) +echo b #[tt.Error + ^ undeclared identifier: 'b']# diff --git a/tests/vm/tconstscope2.nim b/tests/vm/tconstscope2.nim new file mode 100644 index 000000000..d858e96c2 --- /dev/null +++ b/tests/vm/tconstscope2.nim @@ -0,0 +1,5 @@ +const + a = (var x = 3; x) + # should we allow this? + b = x #[tt.Error + ^ undeclared identifier: 'x']# diff --git a/tests/vm/tconsttable.nim b/tests/vm/tconsttable.nim index 64a74a59d..152a33cba 100644 --- a/tests/vm/tconsttable.nim +++ b/tests/vm/tconsttable.nim @@ -17,3 +17,18 @@ x = "ah" echo foo[x] x = "possible." echo foo[x] + +block: # bug #19840 + const testBytes = [byte 0xD8, 0x08, 0xDF, 0x45, 0x00, 0x3D, 0x00, 0x52, 0x00, 0x61] + var tempStr = "__________________" + + tempStr.prepareMutation + copyMem(addr tempStr[0], addr testBytes[0], testBytes.len) + +block: # bug #22389 + func foo(): ptr UncheckedArray[byte] = + const bar = [77.byte] + cast[ptr UncheckedArray[byte]](addr bar[0]) + + doAssert foo()[0] == 77 + diff --git a/tests/vm/tconsttable2.nim b/tests/vm/tconsttable2.nim index e07734eb5..5a392fb66 100644 --- a/tests/vm/tconsttable2.nim +++ b/tests/vm/tconsttable2.nim @@ -1,5 +1,5 @@ discard """ - msg: '''61''' + nimout: '''61''' """ # bug #2297 diff --git a/tests/vm/tconvaddr.nim b/tests/vm/tconvaddr.nim new file mode 100644 index 000000000..9762a9e59 --- /dev/null +++ b/tests/vm/tconvaddr.nim @@ -0,0 +1,49 @@ +block: # issue #24097 + type Foo = distinct int + proc foo(x: var Foo) = + int(x) += 1 + proc bar(x: var int) = + x += 1 + static: + var x = Foo(1) + int(x) = int(x) + 1 + doAssert x.int == 2 + int(x) += 1 + doAssert x.int == 3 + foo(x) + doAssert x.int == 4 + bar(int(x)) # need vmgen flags propagated for this + doAssert x.int == 5 + type Bar = object + x: Foo + static: + var obj = Bar(x: Foo(1)) + int(obj.x) = int(obj.x) + 1 + doAssert obj.x.int == 2 + int(obj.x) += 1 + doAssert obj.x.int == 3 + foo(obj.x) + doAssert obj.x.int == 4 + bar(int(obj.x)) # need vmgen flags propagated for this + doAssert obj.x.int == 5 + static: + var arr = @[Foo(1)] + int(arr[0]) = int(arr[0]) + 1 + doAssert arr[0].int == 2 + int(arr[0]) += 1 + doAssert arr[0].int == 3 + foo(arr[0]) + doAssert arr[0].int == 4 + bar(int(arr[0])) # need vmgen flags propagated for this + doAssert arr[0].int == 5 + proc testResult(): Foo = + result = Foo(1) + int(result) = int(result) + 1 + doAssert result.int == 2 + int(result) += 1 + doAssert result.int == 3 + foo(result) + doAssert result.int == 4 + bar(int(result)) # need vmgen flags propagated for this + doAssert result.int == 5 + doAssert testResult().int == 5 diff --git a/tests/vm/teval1.nim b/tests/vm/teval1.nim index 0eaa050da..0316ea238 100644 --- a/tests/vm/teval1.nim +++ b/tests/vm/teval1.nim @@ -1,3 +1,8 @@ + +discard """ +nimout: "##" +""" + import macros proc testProc: string {.compileTime.} = @@ -14,9 +19,24 @@ when true: const x = testProc() -echo "##", x, "##" +doAssert x == "" # bug #1310 static: - var i, j: set[int8] = {} - var k = i + j + var i, j: set[int8] = {} + var k = i + j + +type + Obj = object + x: int + +converter toObj(x: int): Obj = Obj(x: x) + +# bug #10514 +block: + const + b: Obj = 42 + bar = [b] + + let i_runtime = 0 + doAssert bar[i_runtime] == b diff --git a/tests/vm/texception.nim b/tests/vm/texception.nim new file mode 100644 index 000000000..65a781281 --- /dev/null +++ b/tests/vm/texception.nim @@ -0,0 +1,14 @@ +proc someFunc() = + try: + raise newException(ValueError, "message") + except ValueError as err: + doAssert err.name == "ValueError" + doAssert err.msg == "message" + raise + +static: + try: + someFunc() + except: + discard + \ No newline at end of file diff --git a/tests/vm/texcl.nim b/tests/vm/texcl.nim index e23a423fe..41975f27b 100644 --- a/tests/vm/texcl.nim +++ b/tests/vm/texcl.nim @@ -18,7 +18,7 @@ proc initOpts(): set[nlOptions] = const cOpts = initOpts() -macro nlo(): typed = +macro nlo() = nlOpts.incl(nloNone) nlOpts.excl(nloDebug) result = newEmptyNode() diff --git a/tests/vm/textensionmap.nim b/tests/vm/textensionmap.nim index 5d4b25d01..7ada1880d 100644 --- a/tests/vm/textensionmap.nim +++ b/tests/vm/textensionmap.nim @@ -10,4 +10,4 @@ const EXTENSIONMAP = { "c": @["*.c", "*.h"], }.toTable() -const EXTENSIONS = toSet(concat(toSeq(EXTENSIONMAP.values()))) +const EXTENSIONS = toHashSet(concat(toSeq(EXTENSIONMAP.values()))) diff --git a/tests/vm/tfarjump.nim b/tests/vm/tfarjump.nim new file mode 100644 index 000000000..f5798b8d2 --- /dev/null +++ b/tests/vm/tfarjump.nim @@ -0,0 +1,14 @@ +# Test a VM relative jump with an offset larger then 32767 instructions. + +import macros + +static: + var a = 0 + macro foo(): untyped = + let s = newStmtList() + for i in 1..6554: + s.add nnkCommand.newTree(ident("inc"), ident("a")) + quote do: + if true: + `s` + foo() diff --git a/tests/vm/tfibconst.nim b/tests/vm/tfibconst.nim new file mode 100644 index 000000000..cca6dd84f --- /dev/null +++ b/tests/vm/tfibconst.nim @@ -0,0 +1,43 @@ +discard """ + nimout: ''' +Fibonacci sequence: 0, 1, 1, 2, 3 +Sequence continues: 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610 +''' +""" + + +import strformat + +var fib_n {.compileTime.}: int +var fib_prev {.compileTime.}: int +var fib_prev_prev {.compileTime.}: int + +proc next_fib(): int {.compileTime.} = + let fib = if fib_n < 2: + fib_n + else: + fib_prev_prev + fib_prev + inc(fib_n) + fib_prev_prev = fib_prev + fib_prev = fib + fib + +const f0 = next_fib() +const f1 = next_fib() +const f2 = next_fib() +const f3 = next_fib() +const f4 = next_fib() + +static: + echo fmt"Fibonacci sequence: {f0}, {f1}, {f2}, {f3}, {f4}" + +const fib_continues = block: + var result = fmt"Sequence continues: " + for i in 0..10: + if i > 0: + add(result, ", ") + add(result, $next_fib()) + result + +static: + echo fib_continues \ No newline at end of file diff --git a/tests/vm/tfile_rw.nim b/tests/vm/tfile_rw.nim new file mode 100644 index 000000000..439886e49 --- /dev/null +++ b/tests/vm/tfile_rw.nim @@ -0,0 +1,22 @@ +# test file read write in vm + +import os, strutils + +const filename = splitFile(currentSourcePath).dir / "tfile_rw.txt" + +const mytext = "line1\nline2\nline3" +static: + writeFile(filename, mytext) +const myfile_str = staticRead(filename) +const myfile_str2 = readFile(filename) +const myfile_str_seq = readLines(filename, 3) + +static: + doAssert myfile_str == mytext + doAssert myfile_str2 == mytext + doAssert myfile_str_seq[0] == "line1" + doAssert myfile_str_seq[1] == "line2" + doAssert myfile_str_seq.join("\n") == mytext + + +removeFile(filename) diff --git a/tests/vm/tforwardproc.nim b/tests/vm/tforwardproc.nim index 727ac6641..bcd929f0e 100644 --- a/tests/vm/tforwardproc.nim +++ b/tests/vm/tforwardproc.nim @@ -14,4 +14,4 @@ proc initArray(): array[10, int] = for f in 0..<10: result[f] = 3 -when isMainModule: echo repr(someTable) +when true: echo repr(someTable) diff --git a/tests/vm/tgenericcompiletimeproc.nim b/tests/vm/tgenericcompiletimeproc.nim new file mode 100644 index 000000000..08099ebbe --- /dev/null +++ b/tests/vm/tgenericcompiletimeproc.nim @@ -0,0 +1,36 @@ +block: # issue #10753 + proc foo(x: int): int {.compileTime.} = x + const a = foo(123) + doAssert foo(123) == a + + proc bar[T](x: T): T {.compileTime.} = x + const b = bar(123) + doAssert bar(123) == b + const c = bar("abc") + doAssert bar("abc") == c + +block: # issue #22021 + proc foo(x: static int): int {.compileTime.} = x + 1 + doAssert foo(123) == 124 + +block: # issue #19365 + proc f[T](x: static T): T {.compileTime.} = x + x + doAssert f(123) == 246 + doAssert f(1.0) == 2.0 + +block: + # don't fold compile time procs in typeof + proc fail[T](x: T): T {.compileTime.} = + doAssert false + x + doAssert typeof(fail(123)) is typeof(123) + proc p(x: int): int = x + + type Foo = typeof(p(fail(123))) + +block: # issue #24150, related regression + proc w(T: type): T {.compileTime.} = default(ptr T)[] + template y(v: auto): auto = typeof(v) is int + discard compiles(y(w int)) + proc s(): int {.compileTime.} = discard + discard s() diff --git a/tests/vm/tgloballetfrommacro.nim b/tests/vm/tgloballetfrommacro.nim new file mode 100644 index 000000000..4be09b56e --- /dev/null +++ b/tests/vm/tgloballetfrommacro.nim @@ -0,0 +1,13 @@ +discard """ +errormsg: "cannot evaluate at compile time: BUILTIN_NAMES" +line: 11 +""" + +import sets + +let BUILTIN_NAMES = toHashSet(["int8", "int16", "int32", "int64"]) + +macro test*(): bool = + echo "int64" notin BUILTIN_NAMES + +echo test() diff --git a/tests/vm/tgorge.nim b/tests/vm/tgorge.nim index 694754f41..1f77d2c95 100644 --- a/tests/vm/tgorge.nim +++ b/tests/vm/tgorge.nim @@ -1,8 +1,17 @@ +discard """ +disabled: "windows" +""" + +# If your os is windows and this test fails for you locally, please +# check what is going wrong. + import os template getScriptDir(): string = parentDir(instantiationInfo(-1, true).filename) +# See also simpler test in Nim/tests/vm/tvmops.nim for a simpler +# cross platform way. block gorge: const execName = when defined(windows): "tgorge.bat" else: "./tgorge.sh" diff --git a/tests/vm/tgorge.sh b/tests/vm/tgorge.sh index ba47afeae..ba47afeae 100644..100755 --- a/tests/vm/tgorge.sh +++ b/tests/vm/tgorge.sh diff --git a/tests/vm/tgorgeex.sh b/tests/vm/tgorgeex.sh index 36ba0a02f..36ba0a02f 100644..100755 --- a/tests/vm/tgorgeex.sh +++ b/tests/vm/tgorgeex.sh diff --git a/tests/vm/tinheritance.nim b/tests/vm/tinheritance.nim index d465e22b9..2a98ed923 100644 --- a/tests/vm/tinheritance.nim +++ b/tests/vm/tinheritance.nim @@ -1,6 +1,7 @@ discard """ - msg: '''Hello fred , managed by sally -Hello sally , managed by bob''' + nimout: '''Hello fred, managed by sally +Hello sally, managed by bob +0''' """ # bug #3973 @@ -10,20 +11,84 @@ type ecCode2 Person* = object of RootObj - name* : string + name*: string last_name*: string Employee* = object of Person - empl_code* : EmployeeCode - mgr_name* : string + empl_code*: EmployeeCode + mgr_name*: string proc test() = var empl1 = Employee(name: "fred", last_name: "smith", mgr_name: "sally", empl_code: ecCode1) empl2 = Employee(name: "sally", last_name: "jones", mgr_name: "bob", empl_code: ecCode2) - echo "Hello ", empl1.name, " , managed by ", empl1.mgr_name - echo "Hello ", empl2.name, " , managed by ", empl2.mgr_name + echo "Hello ", empl1.name, ", managed by ", empl1.mgr_name + echo "Hello ", empl2.name, ", managed by ", empl2.mgr_name static: test() + +#---------------------------------------------- +# Bugs #9701 and #9702 +type + MyKind = enum + kA, kB, kC + + Base = ref object of RootObj + x: string + + A = ref object of Base + a: string + + B = ref object of Base + b: string + + C = ref object of B + c: string + +template check_templ(n: Base, k: MyKind) = + if k == kA: doAssert(n of A) else: doAssert(not (n of A)) + if k in {kB, kC}: doAssert(n of B) else: doAssert(not (n of B)) + if k == kC: doAssert(n of C) else: doAssert(not (n of C)) + doAssert(n of Base) + +proc check_proc(n: Base, k: MyKind) = + if k == kA: doAssert(n of A) else: doAssert(not (n of A)) + if k in {kB, kC}: doAssert(n of B) else: doAssert(not (n of B)) + if k == kC: doAssert(n of C) else: doAssert(not (n of C)) + doAssert(n of Base) + +static: + let aa = new(A) + check_templ(aa, kA) + check_proc(aa, kA) + let bb = new(B) + check_templ(bb, kB) + check_proc(bb, kB) + let cc = new(C) + check_templ(cc, kC) + check_proc(cc, kC) + +let aa = new(A) +check_templ(aa, kA) +check_proc(aa, kA) +let bb = new(B) +check_templ(bb, kB) +check_proc(bb, kB) +let cc = new(C) +check_templ(cc, kC) +check_proc(cc, kC) + +type + BBar = object of RootObj + bbarField: set[char] + xbarField: string + d, e: int + FooBar = object of BBar + a: int + b: string + +static: + var fb: FooBar + echo fb.a diff --git a/tests/vm/tissues.nim b/tests/vm/tissues.nim new file mode 100644 index 000000000..f0ae6c296 --- /dev/null +++ b/tests/vm/tissues.nim @@ -0,0 +1,76 @@ +import macros + +block t9043: # bug #9043 + proc foo[N: static[int]](dims: array[N, int]): string = + const N1 = N + const N2 = dims.len + const ret = $(N, dims.len, N1, N2) + static: doAssert ret == $(N, dims.len, N1, N2) + ret + + doAssert foo([1, 2]) == "(2, 2, 2, 2)" + +block t4952: + proc doCheck(tree: NimNode) = + let res: tuple[n: NimNode] = (n: tree) + assert: tree.kind == res.n.kind + for sub in tree: + doCheck(sub) + + macro id(body: untyped): untyped = + doCheck(body) + + id(foo((i: int))) + + static: + let tree = newTree(nnkExprColonExpr) + let t = (n: tree) + doAssert: t.n.kind == tree.kind + + +# bug #19909 +type + SinglyLinkedList[T] = ref object + SinglyLinkedListObj[T] = ref object + + +proc addMoved[T](a, b: var SinglyLinkedList[T]) = + if a.addr != b.addr: discard + +proc addMoved[T](a, b: var SinglyLinkedListObj[T]) = + if a.addr != b.addr: discard + +proc main = + var a: SinglyLinkedList[int]; new a + var b: SinglyLinkedList[int]; new b + a.addMoved b + + var a0: SinglyLinkedListObj[int] + var b0: SinglyLinkedListObj[int] + a0.addMoved b0 + +static: main() + + +# bug #18641 + +type A = object + ha1: int +static: + var a = A() + var a2 = a.addr + a2.ha1 = 11 + doAssert a2.ha1 == 11 + a.ha1 = 12 + doAssert a.ha1 == 12 + doAssert a2.ha1 == 12 # ok +static: + proc fn() = + var a = A() + var a2 = a.addr + a2.ha1 = 11 + doAssert a2.ha1 == 11 + a.ha1 = 12 + doAssert a.ha1 == 12 + doAssert a2.ha1 == 12 # fails + fn() diff --git a/tests/vm/tmanyregs.nim b/tests/vm/tmanyregs.nim new file mode 100644 index 000000000..711c69285 --- /dev/null +++ b/tests/vm/tmanyregs.nim @@ -0,0 +1,16 @@ +import macros + +# Generate a proc with more then 255 registers. Should not generate an error at +# compile time + +static: + macro mkFoo() = + let ss = newStmtList() + for i in 1..256: + ss.add parseStmt "var x" & $i & " = " & $i + ss.add parseStmt "inc x" & $i + quote do: + proc foo() = + `ss` + mkFoo() + foo() diff --git a/tests/vm/tmaxloopiterations.nim b/tests/vm/tmaxloopiterations.nim new file mode 100644 index 000000000..c256df518 --- /dev/null +++ b/tests/vm/tmaxloopiterations.nim @@ -0,0 +1,15 @@ +discard """ +errormsg: "interpretation requires too many iterations; if you are sure this is not a bug in your code" +""" + +# issue #9829 + +macro foo(): untyped = + let lines = ["123", "5423"] + var idx = 0 + while idx < lines.len(): + if lines[idx].len() < 1: + inc(idx) + continue + +foo() diff --git a/tests/vm/tmisc_vm.nim b/tests/vm/tmisc_vm.nim new file mode 100644 index 000000000..1ad830b5f --- /dev/null +++ b/tests/vm/tmisc_vm.nim @@ -0,0 +1,459 @@ +discard """ + targets: "c js" + output: ''' +[127, 127, 0, 255][127, 127, 0, 255] +(data: 1) +(2, 1) +(2, 1) +(2, 1) +(f0: 5) +''' + + nimout: '''caught Exception +main:begin +main:end +@[{0}] +(width: 0, height: 0, path: "") +@[(width: 0, height: 0, path: ""), (width: 0, height: 0, path: "")] +Done! +foo4 +foo4 +foo4 +(a: 0, b: 0) +(a: 0, b: 0) +(a: 0, b: 0) +z1 m: (lo: 12) +z2 a: (lo: 3) +x1 a: (lo: 3) +x2 a: (lo: 6) +x3 a: (lo: 0) +z3 a: (lo: 3) +x1 a: (lo: 3) +x2 a: (lo: 6) +x3 a: (lo: 0) +(2, 1) +(2, 1) +(2, 1) +(f0: 5) +''' +""" +import std/sets + +#bug #1009 +type + TAggRgba8* = array[4, byte] + +template R*(self: TAggRgba8): byte = self[0] +template G*(self: TAggRgba8): byte = self[1] +template B*(self: TAggRgba8): byte = self[2] +template A*(self: TAggRgba8): byte = self[3] + +template `R=`*(self: TAggRgba8, val: byte) = + self[0] = val +template `G=`*(self: TAggRgba8, val: byte) = + self[1] = val +template `B=`*(self: TAggRgba8, val: byte) = + self[2] = val +template `A=`*(self: TAggRgba8, val: byte) = + self[3] = val + +proc ABGR*(val: int | int64): TAggRgba8 = + var V = val + result.R = byte(V and 0xFF) + V = V shr 8 + result.G = byte(V and 0xFF) + V = V shr 8 + result.B = byte(V and 0xFF) + result.A = byte((V shr 8) and 0xFF) + +const + c1 = ABGR(0xFF007F7F) +echo ABGR(0xFF007F7F).repr, c1.repr + + +# bug 8740 + +static: + try: + raise newException(ValueError, "foo") + except Exception: + echo "caught Exception" + except Defect: + echo "caught Defect" + except ValueError: + echo "caught ValueError" + +# bug #10538 + +block: + proc fun1(): seq[int] = + try: + try: + result.add(1) + return + except: + result.add(-1) + finally: + result.add(2) + finally: + result.add(3) + result.add(4) + + let x1 = fun1() + const x2 = fun1() + doAssert(x1 == x2) + +# bug #11610 +proc simpleTryFinally()= + try: + echo "main:begin" + finally: + echo "main:end" + +static: simpleTryFinally() + +# bug #10981 + +proc main = + for i in 0..<15: + var someSets = @[initHashSet[int]()] + someSets[^1].incl(0) # <-- segfaults + if i == 0: + echo someSets + +static: + main() + +# bug #7261 +const file = """ +sprites.png +size: 1024,1024 +format: RGBA8888 +filter: Linear,Linear +repeat: none +char/slide_down + rotate: false + xy: 730, 810 + size: 204, 116 + orig: 204, 116 + offset: 0, 0 + index: -1 +""" + +type + AtlasPage = object + width, height: int + path: string + + CtsStream = object + data: string + pos: int + +proc atEnd(stream: CtsStream): bool = + stream.pos >= stream.data.len + +proc readChar(stream: var CtsStream): char = + if stream.atEnd: + result = '\0' + else: + result = stream.data[stream.pos] + inc stream.pos + +proc readLine(s: var CtsStream, line: var string): bool = + # This is pretty much copied from the standard library: + line.setLen(0) + while true: + var c = readChar(s) + if c == '\c': + c = readChar(s) + break + elif c == '\L': break + elif c == '\0': + if line.len > 0: break + else: return false + line.add(c) + result = true + +proc peekLine(s: var CtsStream, line: var string): bool = + let oldPos = s.pos + result = s.readLine(line) + s.pos = oldPos + +proc initCtsStream(data: string): CtsStream = + CtsStream( + pos: 0, + data: data + ) + +# ******************** +# Interesting stuff happens here: +# ******************** + +proc parseAtlas(stream: var CtsStream) = + var pages = @[AtlasPage(), AtlasPage()] + var line = "" + + block: + let page = addr pages[^1] + discard stream.peekLine(line) + discard stream.peekLine(line) + echo page[] + echo pages + +static: + var stream = initCtsStream(file) + parseAtlas(stream) + echo "Done!" + + +# bug #12244 + +type + Apple = object + data: int + +func what(x: var Apple) = + x = Apple(data: 1) + +func oh_no(): Apple = + what(result) + +const + vmCrash = oh_no() + +debugEcho vmCrash + + +# bug #12310 + +proc someTransform(s: var array[8, uint64]) = + var s1 = 5982491417506315008'u64 + s[1] += s1 + +static: + var state: array[8, uint64] + state[1] = 7105036623409894663'u64 + someTransform(state) + + doAssert state[1] == 13087528040916209671'u64 + +import macros +# bug #12670 + +macro fooImpl(arg: untyped) = + result = quote do: + `arg` + +proc foo(): string {.compileTime.} = + fooImpl: + result = "foo" + result.addInt 4 + +static: + echo foo() + echo foo() + echo foo() + +# bug #12488 +type + MyObject = object + a,b: int + MyObjectRef = ref MyObject + +static: + let x1 = new(MyObject) + echo x1[] + let x2 = new(MyObjectRef) + echo x2[] + let x3 = new(ref MyObject) # cannot generate VM code for ref MyObject + echo x3[] + +# bug #19464 +type + Wrapper = object + inner: int + +proc assign(r: var Wrapper, a: Wrapper) = + r = a + +proc myEcho(a: Wrapper) = + var tmp = a + assign(tmp, Wrapper(inner: 0)) # this shouldn't modify `a` + doAssert a.inner == 1 + +static: + var result: Wrapper + assign(result, Wrapper(inner: 1)) + myEcho(result) + +when true: + # bug #15974 + type Foo = object + f0: int + + proc fn(a: var Foo) = + var s: Foo + a = Foo(f0: 2) + s = a + doAssert s.f0 == 2 + a = Foo(f0: 3) + doAssert s.f0 == 2 + + proc test2()= + var a = Foo(f0: 1) + fn(a) + + static: test2() + test2() + +# bug #12551 +type + StUint = object + lo: uint64 + +func `+=`(x: var Stuint, y: Stuint) = + x.lo += y.lo + +func `-`(x, y: Stuint): Stuint = + result.lo = x.lo - y.lo + +func `+`(x, y: Stuint): Stuint = + result.lo = x.lo + y.lo + +func `-=`(x: var Stuint, y: Stuint) = + x = x - y + +func `<`(x, y: Stuint): bool= + x.lo < y.lo + +func `==`(x, y: Stuint): bool = + x.lo == y.lo + +func `<=`(x, y: Stuint): bool = + x.lo <= y.lo + +proc div3n2n(r: var Stuint, b: Stuint) = + var d: Stuint + r = d + r += b + +func div2n1n(r: var Stuint, b: Stuint) = + div3n2n(r, b) + +func divmodBZ(x, y: Stuint, r: var Stuint)= + div2n1n(r, y) + r.lo = 3 + +func `mod`(x, y: Stuint): Stuint = + divmodBZ(x, y, result) + +func doublemod_internal(a, m: Stuint): Stuint = + result = a + if a >= m - a: + result -= m + result += a + +func mulmod_internal(a, b, m: Stuint): Stuint = + var (a, b) = (a, b) + swap(a, b) + debugEcho "x1 a: ", a + a = doublemod_internal(a, m) + debugEcho "x2 a: ", a + a = doublemod_internal(a, m) + debugEcho "x3 a: ", a + +func powmod_internal(a, m: Stuint): Stuint = + var a = a + debugEcho "z1 m: ", m + debugEcho "z2 a: ", a + result = mulmod_internal(result, a, m) + debugEcho "z3 a: ", a + a = mulmod_internal(a, a, m) + +func powmod*(a, m: Stuint) = + discard powmod_internal(a mod m, m) + +static: + var x = Stuint(lo: high(uint64)) + var y = Stuint(lo: 12) + + powmod(x, y) + +# bug #16780 +when true: + template swap*[T](a, b: var T) = + var a2 = addr(a) + var b2 = addr(b) + var aOld = a2[] + a2[] = b2[] + b2[] = aOld + + proc rather = + block: + var a = 1 + var b = 2 + swap(a, b) + echo (a,b) + + block: + type Foo = ref object + x: int + var a = Foo(x:1) + var b = Foo(x:2) + swap(a, b) + echo (a.x, b.x) + + block: + type Foo = object + x: int + var a = Foo(x:1) + var b = Foo(x:2) + swap(a, b) + echo (a.x,b.x) + + static: rather() + rather() + +# bug #16020 +when true: + block: + type Foo = object + f0: int + proc main= + var f = Foo(f0: 3) + var f2 = f.addr + f2[].f0 += 1 + f2.f0 += 1 + echo f + static: main() + main() + +import tables, strutils + +# bug #14553 +const PpcPatterns = @[("aaaa", "bbbb"), ("aaaaa", "bbbbb"), ("aaaaaa", "bbbbbb"), ("aaaaaaa", "bbbbbbb"), ("aaaaaaaa", "bbbbb")] + +static: + var + needSecondIdentifier = initTable[uint32, seq[(string, string)]]() + + for (name, pattern) in PpcPatterns: + let + firstPart = 0'u32 + lastPart = "test" + + needSecondIdentifier.mgetOrPut(firstPart, @[]).add((name, pattern)) + + doAssert needSecondIdentifier[0] == @[("aaaa", "bbbb"), ("aaaaa", "bbbbb"), ("aaaaaa", "bbbbbb"), ("aaaaaaa", "bbbbbbb"), ("aaaaaaaa", "bbbbb")] + +# bug #17864 +macro transform*(fn: typed) = + quote do: + `fn` + +var map: Table[string, HashSet[string]] +proc publish*(): void {.transform.} = + map["k"] = init_hash_set[string]() + map["k"].incl "d" + +publish() diff --git a/tests/vm/tmitems.nim b/tests/vm/tmitems_vm.nim index a0e64d6aa..787d52cc6 100644 --- a/tests/vm/tmitems.nim +++ b/tests/vm/tmitems_vm.nim @@ -1,5 +1,5 @@ discard """ - msg: '''13''' + nimout: '''13''' output: '''3 3 3''' @@ -7,7 +7,7 @@ discard """ # bug #3731 var list {.compileTime.} = newSeq[int]() -macro calc*(): typed = +macro calc*(): void = list.add(1) for c in list.mitems: c = 13 @@ -19,7 +19,7 @@ calc() # bug #3859 import macros -macro m: typed = +macro m: void = var s = newseq[NimNode](3) # var s: array[3,NimNode] # not working either for i in 0..<s.len: s[i] = newLit(3) # works diff --git a/tests/vm/tnewseqofcap.nim b/tests/vm/tnewseqofcap.nim new file mode 100644 index 000000000..a7dc07aa6 --- /dev/null +++ b/tests/vm/tnewseqofcap.nim @@ -0,0 +1,14 @@ +const + foo = @["aaa", "bbb", "ccc"] + +proc myTuple: tuple[n: int, bar: seq[string]] = + result.n = 42 + result.bar = newSeqOfCap[string](foo.len) + for f in foo: + result.bar.add(f) + +# It works if you change the below `const` to `let` +const + (n, bar) = myTuple() + +doAssert bar == @["aaa", "bbb", "ccc"] \ No newline at end of file diff --git a/tests/vm/tnilclosurecall.nim b/tests/vm/tnilclosurecall.nim new file mode 100644 index 000000000..449865b9c --- /dev/null +++ b/tests/vm/tnilclosurecall.nim @@ -0,0 +1,8 @@ +discard """ + errormsg: "attempt to call nil closure" + line: 8 +""" + +static: + let x: proc () = nil + x() diff --git a/tests/vm/tnilclosurecallstacktrace.nim b/tests/vm/tnilclosurecallstacktrace.nim new file mode 100644 index 000000000..879060e8e --- /dev/null +++ b/tests/vm/tnilclosurecallstacktrace.nim @@ -0,0 +1,23 @@ +discard """ + action: reject + nimout: ''' +stack trace: (most recent call last) +tnilclosurecallstacktrace.nim(23, 6) tnilclosurecallstacktrace +tnilclosurecallstacktrace.nim(20, 6) baz +tnilclosurecallstacktrace.nim(17, 6) bar +tnilclosurecallstacktrace.nim(14, 4) foo +tnilclosurecallstacktrace.nim(14, 4) Error: attempt to call nil closure +''' +""" + +proc foo(x: proc ()) = + x() + +proc bar(x: proc ()) = + foo(x) + +proc baz(x: proc ()) = + bar(x) + +static: + baz(nil) diff --git a/tests/vm/tnilref.nim b/tests/vm/tnilref.nim new file mode 100644 index 000000000..5e27cf0cb --- /dev/null +++ b/tests/vm/tnilref.nim @@ -0,0 +1,7 @@ +discard """ + errormsg: "attempt to access a nil address" +""" + +static: + var s: ref int + s[] = 1 \ No newline at end of file diff --git a/tests/vm/tnimnode.nim b/tests/vm/tnimnode.nim index 188bac9bf..f1c4d5e5a 100644 --- a/tests/vm/tnimnode.nim +++ b/tests/vm/tnimnode.nim @@ -4,19 +4,17 @@ proc assertEq(arg0,arg1: string): void = if arg0 != arg1: raiseAssert("strings not equal:\n" & arg0 & "\n" & arg1) -static: - # a simple assignment of stmtList to another variable - var node: NimNode - # an assignment of stmtList into an array - var nodeArray: array[1, NimNode] - # an assignment of stmtList into a seq - var nodeSeq = newSeq[NimNode](2) - +# a simple assignment of stmtList to another variable +var node {.compileTime.}: NimNode +# an assignment of stmtList into an array +var nodeArray {.compileTime.}: array[1, NimNode] +# an assignment of stmtList into a seq +var nodeSeq {.compileTime.} = newSeq[NimNode](2) proc checkNode(arg: NimNode; name: string): void {. compileTime .} = echo "checking ", name - assertEq arg.lispRepr , "StmtList(DiscardStmt(Empty()))" + assertEq arg.lispRepr, """(StmtList (DiscardStmt (Empty)))""" node = arg nodeArray = [arg] @@ -26,19 +24,19 @@ 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("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")))""" + 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" -static: - # the root node that is used to generate the Ast - var stmtList: NimNode +# the root node that is used to generate the Ast +var stmtList {.compileTime.}: NimNode +static: stmtList = newStmtList(nnkDiscardStmt.newTree(newEmptyNode())) checkNode(stmtList, "direct construction") diff --git a/tests/vm/tnocompiletimefunc.nim b/tests/vm/tnocompiletimefunc.nim new file mode 100644 index 000000000..a95648c0f --- /dev/null +++ b/tests/vm/tnocompiletimefunc.nim @@ -0,0 +1,14 @@ +discard """ + errormsg: "request to generate code for .compileTime proc: foo" +""" + +# ensure compileTime funcs can't be called from runtime + +func foo(a: int): int {.compileTime.} = + a * a + +proc doAThing(): int = + for i in 0..2: + result += foo(i) + +echo doAThing() diff --git a/tests/vm/tnocompiletimefunclambda.nim b/tests/vm/tnocompiletimefunclambda.nim new file mode 100644 index 000000000..d134eea40 --- /dev/null +++ b/tests/vm/tnocompiletimefunclambda.nim @@ -0,0 +1,6 @@ +discard """ + errormsg: "request to generate code for .compileTime proc: :anonymous" +""" + +let a = func(a: varargs[int]) {.compileTime, closure.} = + discard a[0] \ No newline at end of file diff --git a/tests/vm/tnoreturn.nim b/tests/vm/tnoreturn.nim new file mode 100644 index 000000000..d4f8601a9 --- /dev/null +++ b/tests/vm/tnoreturn.nim @@ -0,0 +1,32 @@ +block: # issue #22216 + type + Result[T, E] = object + case oVal: bool + of false: + eVal: E + of true: + vVal: T + + func raiseResultDefect(m: string) {.noreturn, noinline.} = + raise (ref Defect)(msg: m) + + template withAssertOk(self: Result, body: untyped): untyped = + case self.oVal + of false: + raiseResultDefect("Trying to access value with err Result") + else: + body + + func value[T, E](self: Result[T, E]): T {.inline.} = + withAssertOk(self): + self.vVal + + const + x = Result[int, string](oVal: true, vVal: 123) + z = x.value() + + let + xx = Result[int, string](oVal: true, vVal: 123) + zz = x.value() + + doAssert z == zz diff --git a/tests/vm/topenarrays.nim b/tests/vm/topenarrays.nim new file mode 100644 index 000000000..375d2523d --- /dev/null +++ b/tests/vm/topenarrays.nim @@ -0,0 +1,89 @@ +proc mutate(a: var openarray[int]) = + var i = 0 + for x in a.mitems: + x = i + inc i + +proc mutate(a: var openarray[char]) = + var i = 1 + for ch in a.mitems: + ch = 'a' + + +static: + var a = [10, 20, 30] + assert a.toOpenArray(1, 2).len == 2 + + mutate(a) + assert a.toOpenArray(0, 2) == [0, 1, 2] + assert a.toOpenArray(0, 0) == [0] + assert a.toOpenArray(1, 2) == [1, 2] + assert "Hello".toOpenArray(1, 4) == "ello" + var str = "Hello" + str.toOpenArray(2, 4).mutate() + assert str.toOpenArray(0, 4).len == 5 + assert str.toOpenArray(0, 0).len == 1 + assert str.toOpenArray(0, 0).high == 0 + assert str == "Heaaa" + assert str.toOpenArray(0, 4) == "Heaaa" + + var arr: array[3..4, int] = [1, 2] + assert arr.toOpenArray(3, 4) == [1, 2] + assert arr.toOpenArray(3, 4).len == 2 + assert arr.toOpenArray(3, 3).high == 0 + + assert arr.toOpenArray(3, 4).toOpenArray(0, 0) == [1] + + +proc doThing(s: static openArray[int]) = discard + +doThing([10, 20, 30].toOpenArray(0, 0)) + +# bug #19969 +proc f(): array[1, byte] = + var a: array[1, byte] + result[0..0] = a.toOpenArray(0, 0) + +doAssert static(f()) == [byte(0)] + + +# bug #15952 +proc main1[T](a: openArray[T]) = discard +proc main2[T](a: var openArray[T]) = discard + +proc main = + var a = [1,2,3,4,5] + main1(a.toOpenArray(1,3)) + main2(a.toOpenArray(1,3)) +static: main() +main() + +# bug #16306 +{.experimental: "views".} +proc test(x: openArray[int]): tuple[id: int] = + let y: openArray[int] = toOpenArray(x, 0, 2) + result = (y[0],) +template fn= + doAssert test([0,1,2,3,4,5]).id == 0 +fn() # ok +static: fn() + + +block: # bug #22095 + type + StUint = object + limbs: array[4, uint64] + + func shlAddMod(a: var openArray[uint64]) = + a[0] = 10 + + func divRem(r: var openArray[uint64]) = + shlAddMod(r.toOpenArray(0, 3)) + + func fn(): StUint = + divRem(result.limbs) + + const + z = fn() + + doAssert z.limbs[0] == 10 diff --git a/tests/vm/toverflowopcaddimmint.nim b/tests/vm/toverflowopcaddimmint.nim index c36b9ed9b..4ff614e5b 100644 --- a/tests/vm/toverflowopcaddimmint.nim +++ b/tests/vm/toverflowopcaddimmint.nim @@ -7,5 +7,5 @@ static: var x = int64.high discard x + 1 - assert false + doAssert false p() diff --git a/tests/vm/toverflowopcaddint.nim b/tests/vm/toverflowopcaddint.nim index 6d96afc78..d494245b1 100644 --- a/tests/vm/toverflowopcaddint.nim +++ b/tests/vm/toverflowopcaddint.nim @@ -8,5 +8,5 @@ static: x = int64.high y = 1 discard x + y - assert false + doAssert false p() diff --git a/tests/vm/toverflowopcmulint.nim b/tests/vm/toverflowopcmulint.nim index 81b3234ba..936eea6c2 100644 --- a/tests/vm/toverflowopcmulint.nim +++ b/tests/vm/toverflowopcmulint.nim @@ -5,7 +5,7 @@ discard """ static: proc p = var - x = 1 shl 62 + x = 1'i64 shl 62 discard x * 2 - assert false + doAssert false p() diff --git a/tests/vm/toverflowopcsubimmint.nim b/tests/vm/toverflowopcsubimmint.nim index 09d6f745b..08356590c 100644 --- a/tests/vm/toverflowopcsubimmint.nim +++ b/tests/vm/toverflowopcsubimmint.nim @@ -6,5 +6,5 @@ static: proc p = var x = int64.low discard x - 1 - assert false + doAssert false p() diff --git a/tests/vm/toverflowopcsubint.nim b/tests/vm/toverflowopcsubint.nim index 8d114f200..74e34c6a4 100644 --- a/tests/vm/toverflowopcsubint.nim +++ b/tests/vm/toverflowopcsubint.nim @@ -8,5 +8,5 @@ static: x = int64.low y = 1 discard x - y - assert false + doAssert false p() diff --git a/tests/vm/tquadplus.nim b/tests/vm/tquadplus.nim index 552e8fef7..acf20cd96 100644 --- a/tests/vm/tquadplus.nim +++ b/tests/vm/tquadplus.nim @@ -1,8 +1,5 @@ # bug #1023 -discard """ - output: "1 == 1" -""" type Quadruple = tuple[a, b, c, d: int] @@ -14,4 +11,4 @@ const B = (a: 0, b: -2, c: 1, d: 0) C = A + B -echo C.d, " == ", (A+B).d +doAssert $C.d & " == " & $(A+B).d == "1 == 1" diff --git a/tests/vm/tref.nim b/tests/vm/tref.nim index 517a67fb0..e70305225 100644 --- a/tests/vm/tref.nim +++ b/tests/vm/tref.nim @@ -9,4 +9,63 @@ static: b[5] = 'c' doAssert a[] == "Hellocworld" - doAssert b[] == "Hellocworld" \ No newline at end of file + doAssert b[] == "Hellocworld" + + proc notGlobal() = + var + a: ref string + b: ref string + new a + + a[] = "Hello world" + b = a + + b[5] = 'c' + doAssert a[] == "Hellocworld" + doAssert b[] == "Hellocworld" + notGlobal() + +static: # bug 6081 + block: + type Obj = object + field: ref int + var i: ref int + new(i) + var r = Obj(field: i) + var rr = r + r.field = nil + doAssert rr.field != nil + + proc foo() = # Proc to avoid special global logic + var s: seq[ref int] + var i: ref int + new(i) + s.add(i) + var head = s[0] + s[0] = nil + doAssert head != nil + + foo() + +static: + + block: # global alias + var s: ref int + new(s) + var ss = s + s[] = 1 + doAssert ss[] == 1 + +static: # bug #8402 + type R = ref object + var empty: R + let otherEmpty = empty + +block: + # fix https://github.com/timotheecour/Nim/issues/88 + template fun() = + var s = @[10,11,12] + var a = s[0].addr + a[] += 100 # was giving SIGSEGV + doAssert a[] == 110 + static: fun() diff --git a/tests/vm/treset.nim b/tests/vm/treset.nim new file mode 100644 index 000000000..32fbc7f04 --- /dev/null +++ b/tests/vm/treset.nim @@ -0,0 +1,50 @@ +static: + type Obj = object + field: int + var o = Obj(field: 1) + reset(o) + doAssert o.field == 0 + + var x = 4 + reset(x) + doAssert x == 0 + +static: + type ObjB = object + field: int + var o = ObjB(field: 1) + o = default(ObjB) + doAssert o.field == 0 + +static: + var i = 2 + reset(i) + doAssert i == 0 + +static: + var i = new int + reset(i) + doAssert i.isNil + +static: + var s = @[1, 2, 3] + reset(s) + doAssert s == @[] + +static: + proc f() = + var i = 2 + reset(i) + doAssert i == 0 + f() + +proc main = + var y = [1, 2, 3, 4] + y = default(array[4, int]) + for a in y: doAssert(a == 0) + + var x = 4 + x = default(int) + doAssert x == 0 + +main() diff --git a/tests/vm/trgba.nim b/tests/vm/trgba.nim deleted file mode 100644 index 923ea1b2e..000000000 --- a/tests/vm/trgba.nim +++ /dev/null @@ -1,36 +0,0 @@ -discard """ - output: '''[127, 127, 0, 255] -[127, 127, 0, 255] -''' -""" - -#bug #1009 -type - TAggRgba8* = array[4, byte] - -template R*(self: TAggRgba8): byte = self[0] -template G*(self: TAggRgba8): byte = self[1] -template B*(self: TAggRgba8): byte = self[2] -template A*(self: TAggRgba8): byte = self[3] - -template `R=`*(self: TAggRgba8, val: byte) = - self[0] = val -template `G=`*(self: TAggRgba8, val: byte) = - self[1] = val -template `B=`*(self: TAggRgba8, val: byte) = - self[2] = val -template `A=`*(self: TAggRgba8, val: byte) = - self[3] = val - -proc ABGR*(val: int| int64): TAggRgba8 = - var V = val - result.R = byte(V and 0xFF) - V = V shr 8 - result.G = byte(V and 0xFF) - V = V shr 8 - result.B = byte(V and 0xFF) - result.A = byte((V shr 8) and 0xFF) - -const - c1 = ABGR(0xFF007F7F) -echo ABGR(0xFF007F7F).repr, c1.repr diff --git a/tests/vm/triangle_array.nim b/tests/vm/triangle_array.nim index 054c66f22..0704239c6 100644 --- a/tests/vm/triangle_array.nim +++ b/tests/vm/triangle_array.nim @@ -1,7 +1,3 @@ -discard """ - output: "56" -""" - # bug #1781 proc initCombinations: array[11, array[11, int]] = @@ -14,4 +10,4 @@ proc initCombinations: array[11, array[11, int]] = result[6][6 .. 10] = [52,53,54,55,56] const combinations = initCombinations() -echo combinations[6][10] +doAssert combinations[6][10] == 56 diff --git a/tests/vm/tscriptcompiletime.nims b/tests/vm/tscriptcompiletime.nims new file mode 100644 index 000000000..daec54bf7 --- /dev/null +++ b/tests/vm/tscriptcompiletime.nims @@ -0,0 +1,9 @@ +discard """ + cmd: "nim e $file" +""" + +import mscriptcompiletime + +macro foo = + doAssert bar == 2 +foo() diff --git a/tests/vm/tseq_badinit.nim b/tests/vm/tseq_badinit.nim index 15889d60e..5fa223c85 100644 --- a/tests/vm/tseq_badinit.nim +++ b/tests/vm/tseq_badinit.nim @@ -22,14 +22,14 @@ template test(typename, default: untyped) = result = newSeq[typename]() result.add(default) result.setLen(3) - for i in 0 .. <2: + for i in 0 ..< 2: result[i] = default const constval = `abc typename`() doAssert(constval == `abc typename`()) proc `arr typename`(): array[4, typename] = - for i in 0 .. <2: + for i in 0 ..< 2: result[i] = default const constarr = `arr typename`() doAssert(constarr == `arr typename`()) diff --git a/tests/vm/tsetlen.nim b/tests/vm/tsetlen.nim new file mode 100644 index 000000000..9fd30f331 --- /dev/null +++ b/tests/vm/tsetlen.nim @@ -0,0 +1,30 @@ +type Foo = object + index: int + +block: + proc fun[T]() = + var foo: T + var n = 10 + + var foos: seq[T] + foos.setLen n + + n.inc + foos.setLen n + + for i in 0 ..< n: + let temp = foos[i] + when T is object: + doAssert temp.index == 0 + when T is ref object: + doAssert temp == nil + doAssert temp == foo + + static: + fun[Foo]() + fun[int]() + fun[float]() + fun[string]() + fun[(int, string)]() + fun[ref Foo]() + fun[seq[int]]() diff --git a/tests/vm/tsignaturehash.nim b/tests/vm/tsignaturehash.nim new file mode 100644 index 000000000..972ec6fb0 --- /dev/null +++ b/tests/vm/tsignaturehash.nim @@ -0,0 +1,20 @@ +# test sym digest is computable at compile time + +import macros, algorithm +import ../../dist/checksums/src/checksums/md5 + +macro testmacro(s: typed{nkSym}): string = + let s = getMD5(signaturehash(s) & " - " & symBodyHash(s)) + result = newStrLitNode(s) + +macro testmacro(s: typed{nkOpenSymChoice|nkClosedSymChoice}): string = + var str = "" + for sym in s: + str &= symBodyHash(sym) + result = newStrLitNode(getMD5(str)) + +# something recursive and/or generic +discard testmacro(testmacro) +discard testmacro(`[]`) +discard testmacro(binarySearch) +discard testmacro(sort) diff --git a/tests/vm/tsimpleglobals.nim b/tests/vm/tsimpleglobals.nim index 27bfdce50..7ab665070 100644 --- a/tests/vm/tsimpleglobals.nim +++ b/tests/vm/tsimpleglobals.nim @@ -1,5 +1,5 @@ discard """ - msg: "abc xyz bb" + nimout: "abc xyz bb" """ # bug #2473 diff --git a/tests/vm/tslow_tables.nim b/tests/vm/tslow_tables.nim new file mode 100644 index 000000000..e40187f18 --- /dev/null +++ b/tests/vm/tslow_tables.nim @@ -0,0 +1,30 @@ +discard """ + timeout: "7" + action: "compile" + nimout: '''create +search +done''' +""" + +# bug #12195 + +import tables + +type Flop = object + a: array[128, int] # <-- compile time is proportional to array size + +proc hop(): bool = + var v: Table[int, Flop] + + echo "create" + for i in 1..1000: + v.add i, Flop() + + echo "search" + for i in 1..1000: + discard contains(v, i) + + echo "done" + +const r {.used.} = hop() + diff --git a/tests/vm/tslurp.nim b/tests/vm/tslurp.nim index 027db45d6..d762eb079 100644 --- a/tests/vm/tslurp.nim +++ b/tests/vm/tslurp.nim @@ -4,9 +4,9 @@ template getScriptDir(): string = parentDir(instantiationInfo(-1, true).filename) const - relRes = slurp"../../readme.txt" - absRes = slurp(parentDir(parentDir(getScriptDir())) / "readme.txt") - -echo relRes -echo absRes + relRes = slurp"./tslurp.nim" + absRes = slurp(getScriptDir() / "tslurp.nim") +doAssert relRes.len > 200 +doAssert absRes.len > 200 +doAssert relRes == absRes diff --git a/tests/vm/tstaticprintseq.nim b/tests/vm/tstaticprintseq.nim index 246a0211b..f4aab6b7e 100644 --- a/tests/vm/tstaticprintseq.nim +++ b/tests/vm/tstaticprintseq.nim @@ -1,5 +1,5 @@ discard """ - msg: '''1 + nimout: '''1 2 3 1 @@ -24,7 +24,7 @@ bb const s = @[1,2,3] -macro foo: typed = +macro foo() = for e in s: echo e @@ -55,7 +55,7 @@ static: var m2: TData = data for x in m2.numbers: echo x -macro ff(d: static[TData]): typed = +macro ff(d: static[TData]) = for x in d.letters: echo x diff --git a/tests/vm/tstring_openarray.nim b/tests/vm/tstring_openarray.nim index 1b8a1304c..9318344f8 100644 --- a/tests/vm/tstring_openarray.nim +++ b/tests/vm/tstring_openarray.nim @@ -12,16 +12,16 @@ proc set_all[T](s: var openArray[T]; val: T) = for i in 0..<s.len: s[i] = val -proc test() = - var a0 = "hello_world" - var a1 = [1,2,3,4,5,6,7,8,9] - var a2 = @[1,2,3,4,5,6,7,8,9] - a0.set_all('i') - a1.set_all(4) - a2.set_all(4) - doAssert a0 == "iiiiiiiiiii" - doAssert a1 == [4,4,4,4,4,4,4,4,4] - doAssert a2 == @[4,4,4,4,4,4,4,4,4] +proc main() = + var a0 = "hello_world" + var a1 = [1,2,3,4,5,6,7,8,9] + var a2 = @[1,2,3,4,5,6,7,8,9] + a0.set_all('i') + a1.set_all(4) + a2.set_all(4) + doAssert a0 == "iiiiiiiiiii" + doAssert a1 == [4,4,4,4,4,4,4,4,4] + doAssert a2 == @[4,4,4,4,4,4,4,4,4] const constval0 = "hello".map(proc(x: char): char = x) const constval1 = [1,2,3,4].map(proc(x: int): int = x) @@ -29,6 +29,5 @@ const constval1 = [1,2,3,4].map(proc(x: int): int = x) doAssert("hello".map(proc(x: char): char = x) == constval0) doAssert([1,2,3,4].map(proc(x: int): int = x) == constval1) -test() -static: - test() +static: main() +main() diff --git a/tests/vm/tstringnil.nim b/tests/vm/tstringnil.nim index 39e4040dc..d5dd4f4c9 100644 --- a/tests/vm/tstringnil.nim +++ b/tests/vm/tstringnil.nim @@ -20,16 +20,16 @@ proc buildSuiteContents(suiteName, suiteDesc, suiteBloc: NimNode): tuple[tests: var testObj = SuiteTest() if suiteName.kind == nnkNilLit: - testObj.suiteName = nil + testObj.suiteName = "" else: testObj.suiteName = $suiteName if suiteDesc.kind == nnkNilLit: - testObj.suiteDesc = nil + testObj.suiteDesc = "" else: testObj.suiteDesc = suiteDesc.strVal testObj.testName = $child[1] # should not ever be nil if child[2].kind == nnkNilLit: - testObj.testDesc = nil + testObj.testDesc = "" else: testObj.testDesc = child[2].strVal testObj.testBlock = child[1] @@ -46,5 +46,5 @@ macro suite(suiteName, suiteDesc, suiteBloc: untyped): typed = # Test above suite basics, "Description of such": - test(t5, nil): - assert false + test(t5, ""): + doAssert false diff --git a/tests/vm/tswap.nim b/tests/vm/tswap.nim index 2219be9ca..bdbe5528c 100644 --- a/tests/vm/tswap.nim +++ b/tests/vm/tswap.nim @@ -1,9 +1,11 @@ discard """ -msg: ''' +nimout: ''' x.data = @[10] y = @[11] x.data = @[11] -y = @[10]''' +y = @[10] +@[3, 2, 1] +''' """ # bug #2946 @@ -22,3 +24,11 @@ proc testSwap(): int {.compiletime.} = result = 99 const something = testSwap() + +# bug #15463 +block: + static: + var s = @[1, 2, 3] + swap(s[0], s[2]) + + echo s diff --git a/tests/vm/ttouintconv.nim b/tests/vm/ttouintconv.nim index 5f8884e80..8c43a3adb 100644 --- a/tests/vm/ttouintconv.nim +++ b/tests/vm/ttouintconv.nim @@ -1,7 +1,7 @@ import macros discard """ -msg: ''' +nimout: ''' 8 9 17 239 255 61439 65534 65535 @@ -20,7 +20,7 @@ msg: ''' #bug #2514 -macro foo(): typed = +macro foo() = var x = 8'u8 var y = 9'u16 var z = 17'u32 @@ -58,7 +58,7 @@ macro foo(): typed = var zz = 0x7FFFFFFF'u32 echo zz -macro foo2(): typed = +macro foo2() = var xx = 0x7FFFFFFFFFFFFFFF echo xx @@ -69,9 +69,16 @@ macro foo2(): typed = echo zz var ww = -9 - var vv = ww.uint - var kk = vv.uint32 + var vv = cast[uint](ww) + var kk = cast[uint32](vv) echo kk foo() foo2() + +block: + const neg5VM = block: + let x = -5'i8 + uint64(x) + let y = -5'i8 + doAssert uint64(y) == neg5VM diff --git a/tests/vm/ttypedesc.nim b/tests/vm/ttypedesc.nim new file mode 100644 index 000000000..d799e5adb --- /dev/null +++ b/tests/vm/ttypedesc.nim @@ -0,0 +1,31 @@ +block: # issue #15760 + type + Banana = object + SpecialBanana = object + + proc getName(_: type Banana): string = "Banana" + proc getName(_: type SpecialBanana): string = "SpecialBanana" + + proc x[T](): string = + const n = getName(T) # this one works + result = n + + proc y(T: type): string = + const n = getName(T) # this one failed to compile + result = n + + doAssert x[SpecialBanana]() == "SpecialBanana" + doAssert y(SpecialBanana) == "SpecialBanana" + +import macros + +block: # issue #23112 + type Container = object + foo: string + + proc canBeImplicit(t: typedesc) {.compileTime.} = + let tDesc = getType(t) + doAssert tDesc.kind == nnkObjectTy + + static: + canBeImplicit(Container) diff --git a/tests/vm/tunsupportedintfloatcast.nim b/tests/vm/tunsupportedintfloatcast.nim new file mode 100644 index 000000000..d65f10d86 --- /dev/null +++ b/tests/vm/tunsupportedintfloatcast.nim @@ -0,0 +1,3 @@ +static: + echo cast[int32](12.0) #[tt.Error + ^ VM does not support 'cast' from tyFloat with size 8 to tyInt32 with size 4 due to different sizes]# diff --git a/tests/vm/tvarsection.nim b/tests/vm/tvarsection.nim new file mode 100644 index 000000000..cd34bd02e --- /dev/null +++ b/tests/vm/tvarsection.nim @@ -0,0 +1,11 @@ +var + a {.compileTime.} = 2 + b = -1 + c {.compileTime.} = 3 + d = "abc" + +static: + doAssert a == 2 + doAssert c == 3 + +doAssert ($b & $d) == "-1abc" diff --git a/tests/vm/tvmmisc.nim b/tests/vm/tvmmisc.nim index 4af824cf4..6aeac5529 100644 --- a/tests/vm/tvmmisc.nim +++ b/tests/vm/tvmmisc.nim @@ -1,9 +1,7 @@ -# bug #4462 import macros import os -import ospaths -import strutils +# bug #4462 block: proc foo(t: typedesc) {.compileTime.} = assert sameType(getType(t), getType(int)) @@ -11,27 +9,27 @@ block: static: foo(int) -# #4412 +# bug #4412 block: proc default[T](t: typedesc[T]): T {.inline.} = discard static: var x = default(type(0)) -# #6379 -static: - import algorithm +# bug #6379 +import algorithm +static: var numArray = [1, 2, 3, 4, -1] numArray.sort(cmp) - assert numArray == [-1, 1, 2, 3, 4] + doAssert numArray == [-1, 1, 2, 3, 4] var str = "cba" str.sort(cmp) - assert str == "abc" + doAssert str == "abc" -# #6086 -import math, sequtils, future +# bug #6086 +import math, sequtils, sugar block: proc f: int = @@ -44,7 +42,7 @@ block: var a = f() const b = f() - assert a == b + doAssert a == b block: proc f(): seq[char] = @@ -52,7 +50,7 @@ block: var runTime = f() const compTime = f() - assert runTime == compTime + doAssert runTime == compTime # #6083 block: @@ -66,27 +64,733 @@ block: result[i] = tmp const fact1000 = abc() - assert fact1000 == @[1, 2] + doAssert fact1000 == @[1, 2] # Tests for VM ops block: static: - assert "vm" in getProjectPath() + # for joint test, the project path is different, so I disabled it: + when false: + doAssert "vm" in getProjectPath() let b = getEnv("UNSETENVVAR") - assert b == "" - assert existsEnv("UNSERENVVAR") == false + doAssert b == "" + doAssert existsEnv("UNSERENVVAR") == false putEnv("UNSETENVVAR", "VALUE") - assert getEnv("UNSETENVVAR") == "VALUE" - assert existsEnv("UNSETENVVAR") == true + doAssert getEnv("UNSETENVVAR") == "VALUE" + doAssert existsEnv("UNSETENVVAR") == true - assert fileExists("MISSINGFILE") == false - assert dirExists("MISSINGDIR") == false + doAssert fileExists("MISSINGFILE") == false + doAssert dirExists("MISSINGDIR") == false + doAssert fileExists(currentSourcePath()) + doAssert dirExists(currentSourcePath().parentDir) -# #7210 +# bug #7210 block: static: proc f(size: int): int = var some = newStringOfCap(size) result = size - doAssert f(4) == 4 \ No newline at end of file + doAssert f(4) == 4 + +# bug #6689 +block: + static: + proc foo(): int = 0 + var f: proc(): int + doAssert f.isNil + f = foo + doAssert(not f.isNil) + +block: + static: + var x: ref ref int + new(x) + doAssert(not x.isNil) + +# bug #7871 +static: + type Obj = object + field: int + var s = newSeq[Obj](1) + var o = Obj() + s[0] = o + o.field = 2 + doAssert s[0].field == 0 + +# bug #8125 +static: + let def_iter_var = ident("it") + +# bug #8142 +static: + type Obj = object + names: string + + proc pushName(o: var Obj) = + var s = "" + s.add("FOOBAR") + o.names.add(s) + + var o = Obj() + o.names = "" + o.pushName() + o.pushName() + doAssert o.names == "FOOBARFOOBAR" + +# bug #8154 +import parseutils + +static: + type Obj = object + i: int + + proc foo(): Obj = + discard parseInt("1", result.i, 0) + + static: + doAssert foo().i == 1 + +# bug #10333 +block: + const + encoding: auto = [ + ["", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"], + ["", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"], + ["", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"], + ["", "M", "MM", "MMM", "--", "-", "--", "---", "----", "--"], + ] + doAssert encoding.len == 4 + +# bug #10886 + +proc tor(): bool = + result = true + result = false or result + +proc tand(): bool = + result = false + result = true and result + +const + ctor = tor() + ctand = not tand() + +static: + doAssert ctor + doAssert ctand + +block: # bug #13081 + type Kind = enum + k0, k1, k2, k3 + + type Foo = object + x0: float + case kind: Kind + of k0: discard + of k1: x1: int + of k2: x2: string + of k3: x3: string + + const j1 = Foo(x0: 1.2, kind: k1, x1: 12) + const j2 = Foo(x0: 1.3, kind: k2, x2: "abc") + const j3 = Foo(x0: 1.3, kind: k3, x3: "abc2") + static: + doAssert $j1 == "(x0: 1.2, kind: k1, x1: 12)" + doAssert $j2 == """(x0: 1.3, kind: k2, x2: "abc")""" + doAssert $j3 == """(x0: 1.3, kind: k3, x3: "abc2")""" + doAssert $j1 == "(x0: 1.2, kind: k1, x1: 12)" + doAssert $j2 == """(x0: 1.3, kind: k2, x2: "abc")""" + doAssert $j3 == """(x0: 1.3, kind: k3, x3: "abc2")""" + + doAssert j1.x1 == 12 + static: + doAssert j1.x1 == 12 + +block: # bug #15595 + proc fn0()=echo 0 + proc fn1()=discard + proc main= + var local = 0 + proc fn2()=echo local + var a0 = fn0 + var a1 = fn1 + var a2 = fn2 + var a3: proc() + var a4: proc() + doAssert a0 == fn0 # bugfix + doAssert a1 == fn1 # ditto + doAssert a2 == fn2 # ditto + + doAssert fn0 != fn1 + + doAssert a2 != nil + doAssert a3 == nil # bugfix + + doAssert a3 == a4 # bugfix + static: main() + main() + +block: # issue #20543 + type F = proc() + const myArray = block: + var r: array[1, F] + r[0] = nil + r + doAssert isNil(myArray[0]) + +# bug #15363 +import sequtils + +block: + func identity(a: bool): bool = a + + var a: seq[bool] = static: + newSeq[bool](0).mapIt(it) # segfaults + var b: seq[bool] = static: + newSeq[bool](0).filterIt(it) # does not segfault + var c: seq[bool] = static: + newSeq[bool](0).map(identity) # does not segfault + var d: seq[bool] = static: + newSeq[bool](0).map(proc (a: bool): bool = false) # segfaults + var e: seq[bool] = static: + newSeq[bool](0).filter(identity) # does not segfault + var f: seq[bool] = static: + newSeq[bool](0).filter(proc (a: bool): bool = false) # segfaults + + doAssert a == @[] + doAssert b == @[] + doAssert c == @[] + doAssert d == @[] + doAssert e == @[] + doAssert f == @[] + + +block: # bug #18310 + macro t() : untyped = + let + x = nnkTupleConstr.newTree(newLit(1)) + y = nnkTupleConstr.newTree(newLit(2)) + doAssert not (x == y) # not using != intentionally + doAssert not(cast[int](x) == cast[int](y)) + doAssert not(system.`==`(x, y)) + doAssert system.`==`(x, x) + t() + +block: # bug #10815 + type + Opcode = enum + iChar, iSet + + Inst = object + case code: Opcode + of iChar: + c: char + of iSet: + cs: set[char] + + Patt = seq[Inst] + + + proc `$`(p: Patt): string = + discard + + proc P(): Patt = + result.add Inst(code: iSet) + + const a = P() + doAssert $a == "" + +import tables + +block: # bug #8007 + type + CostKind = enum + Fixed, + Dynamic + + Cost = object + case kind*: CostKind + of Fixed: + cost*: int + of Dynamic: + handler*: proc(value: int): int {.nimcall.} + + proc foo(value: int): int {.nimcall.} = + sizeof(value) + + const a: array[2, Cost] =[ + Cost(kind: Fixed, cost: 999), + Cost(kind: Dynamic, handler: foo) + ] + + # OK with arrays & object variants + doAssert $a == "[(kind: Fixed, cost: 999), (kind: Dynamic, handler: ...)]" + + const b: Table[int, Cost] = { + 0: Cost(kind: Fixed, cost: 999), + 1: Cost(kind: Dynamic, handler: foo) + }.toTable + + # KO with Tables & object variants + # echo b # {0: (kind: Fixed, cost: 0), 1: (kind: Dynamic, handler: ...)} # <----- wrong behaviour + doAssert $b == "{0: (kind: Fixed, cost: 999), 1: (kind: Dynamic, handler: ...)}" + + const c: Table[int, int] = { + 0: 100, + 1: 999 + }.toTable + + # OK with Tables and primitive int + doAssert $c == "{0: 100, 1: 999}" + + # For some reason the following gives + # Error: invalid type for const: Cost + const d0 = Cost(kind: Fixed, cost: 999) + + # OK with seq & object variants + const d = @[Cost(kind: Fixed, cost: 999), Cost(kind: Dynamic, handler: foo)] + doAssert $d == "@[(kind: Fixed, cost: 999), (kind: Dynamic, handler: ...)]" + +block: # bug #14340 + block: + proc opl3EnvelopeCalcSin0() = discard + type EnvelopeSinfunc = proc() {.nimcall.} # todo: fixme + # const EnvelopeCalcSin0 = opl3EnvelopeCalcSin0 # ok + const EnvelopeCalcSin0: EnvelopeSinfunc = opl3EnvelopeCalcSin0 # was bug + const envelopeSin = [EnvelopeCalcSin0] + var a = 0 + envelopeSin[a]() + + block: + type Mutator = proc() {.noSideEffect, gcsafe.} + proc mutator0() = discard + const mTable = [Mutator(mutator0)] + var i=0 + mTable[i]() + +block: # VM wrong register free causes errors in unrelated code + block: # bug #15597 + #[ + Error: unhandled exception: 'sym' is not accessible using discriminant 'kind' of type 'TNode' [FieldDefect] + in /Users/timothee/git_clone/nim/Nim_prs/compiler/vm.nim(1176) rawExecute + in opcIndCall + in let prc = if not isClosure: bb.sym else: bb[0].sym + ]# + proc bar2(head: string): string = "asdf" + proc zook(u1: int) = discard + + type PathEntry = object + kind: int + path: string + + iterator globOpt(): int = + var u1: int + + zook(u1) + zook(u1) + zook(u1) + zook(u1) + zook(u1) + zook(u1) + zook(u1) + zook(u1) + zook(u1) + zook(u1) + zook(u1) + zook(u1) + zook(u1) + zook(u1) + + var entry = PathEntry() + entry.path = bar2("") + if false: + echo "here2" + + proc processAux(a: float) = discard + + template bar(iter: untyped): untyped = + var ret: float + for x in iter: break + ret + + proc main() = + processAux(bar(globOpt())) + static: main() + + block: # ditto + # D20201024T133245 + type Deque = object + proc initDeque2(initialSize: int = 4): Deque = Deque() + proc len2(a: Deque): int = 2 + proc baz(dir: string): bool = true + proc bar2(head: string): string = "asdf" + proc bar3(path: var string) = path = path + + type PathEntry = object + kind: int + path: string + + proc initGlobOpt(dir: string, a1=false,a2=false,a3=false,a4=false): string = dir + + iterator globOpt(dir: string): int = + var stack = initDeque2() + doAssert baz("") + let z = stack.len2 + if stack.len2 >= 0: + var entry = PathEntry() + let current = if true: stack.len2 else: stack.len2 + entry.path = bar2("") + bar3(entry.path) + if false: + echo "here2" # comment here => you get same error as https://github.com/nim-lang/Nim/issues/15704 + + proc processAux(a: float) = discard + + template bar(iter: untyped): untyped = + var ret: float + for x in iter: break + ret + proc main() = + processAux(bar(globOpt(initGlobOpt(".")))) + static: main() + + block: # bug #15704 + #[ + Error: attempt to access a nil address kind: rkFloat + ]# + type Deque = object + proc initDeque2(initialSize: int = 4): Deque = Deque() + proc len2(a: Deque): int = 2 + + proc baz(dir: string): bool = true + proc bar2(head: string): string = "asdf" + proc bar3(path: var string) = path = path + + type PathEntry = object + kind: int + path: string + depth: int + + proc initGlobOpt(dir: string, a1=false,a2=false,a3=false,a4=false): string = + dir + + iterator globOpt(dir: string): int = + var stack = initDeque2() + doAssert baz("") + let z = stack.len2 + var a5: int + if stack.len2 >= 0: + var entry = PathEntry() + if false: + echo "here" + let current = if true: stack.len2 else: stack.len2 + entry.depth = 1 + entry.path = bar2("") + bar3(entry.path) + proc processAux(a: float) = discard + template bar(iter: untyped): untyped = + var ret: float + for x in iter: + break + ret + const dir = "." + proc main() = + processAux(bar(globOpt(initGlobOpt(dir)))) + static: main() + +block: # bug #8015 + block: + type Foo = object + case b: bool + of false: v1: int + of true: v2: int + const t = [Foo(b: false, v1: 1), Foo(b: true, v2: 2)] + doAssert $t == "[(b: false, v1: 1), (b: true, v2: 2)]" + doAssert $t[0] == "(b: false, v1: 1)" # was failing + + block: + type + CostKind = enum + Fixed, + Dynamic + + Cost = object + case kind*: CostKind + of Fixed: + cost*: int + of Dynamic: + handler*: proc(): int {.nimcall.} + + proc foo1(): int {.nimcall.} = + 100 + + proc foo2(): int {.nimcall.} = + 200 + + # Change to `let` and it doesn't crash + const costTable = [ + 0: Cost(kind: Fixed, cost: 999), + 1: Cost(kind: Dynamic, handler: foo1), + 2: Cost(kind: Dynamic, handler: foo2) + ] + + doAssert $costTable[0] == "(kind: Fixed, cost: 999)" + doAssert costTable[1].handler() == 100 + doAssert costTable[2].handler() == 200 + + # Now trying to carry the table as an object field + type + Wrapper = object + table: array[3, Cost] + + proc procNewWrapper(): Wrapper = + result.table = costTable + + # Alternatively, change to `const` and it doesn't crash + let viaProc = procNewWrapper() + + doAssert viaProc.table[1].handler != nil + doAssert viaProc.table[2].handler != nil + doAssert $viaProc.table[0] == "(kind: Fixed, cost: 999)" + doAssert viaProc.table[1].handler() == 100 + doAssert viaProc.table[2].handler() == 200 + + +# bug #19198 + +block: + type + Foo[n: static int] = int + +block: + static: + let x = int 1 + doAssert $(x.type) == "int" # Foo + +block: + static: + let x = int 1 + let y = x + 1 + # Error: unhandled exception: value out of range: -8 notin 0 .. 65535 [RangeDefect] + doAssert y == 2 + + +type Atom* = object + bar: int + +proc main() = # bug #12994 + var s: seq[Atom] + var atom: Atom + var checked = 0 + for i in 0..<2: + atom.bar = 5 + s.add atom + atom.reset + if i == 0: + checked += 1 + doAssert $s == "@[(bar: 5)]" + else: + checked += 1 + doAssert $s == "@[(bar: 5), (bar: 5)]" + doAssert checked == 2 + +static: main() +main() + +# bug #19201 +proc foo(s: sink string) = doAssert s.len == 3 + +static: + foo("abc") + + +static: + for i in '1' .. '2': # bug #10938 + var s: set[char] + doAssert s == {} + incl(s, i) + + for _ in 0 ..< 3: # bug #13312 + var s: string + s.add("foo") + doAssert s == "foo" + + for i in 1 .. 5: # bug #13918 + var arr: array[3, int] + var val: int + doAssert arr == [0, 0, 0] and val == 0 + for j in 0 ..< len(arr): + arr[j] = i + val = i + +# bug #20985 +let a = block: + var groups: seq[seq[int]] + for i in 0 ..< 3: + var group: seq[int] + for j in 0 ..< 3: + group.add j + groups.add group + groups + +const b = block: + var groups: seq[seq[int]] + for i in 0 ..< 3: + var group: seq[int] + for j in 0 ..< 3: + group.add j + groups.add group + groups + +doAssert a == @[@[0, 1, 2], @[0, 1, 2], @[0, 1, 2]] +doAssert b == @[@[0, 1, 2], @[0, 1, 2], @[0, 1, 2]] + +macro m1(s: string): int = + var ProcID {.global, compileTime.}: int + inc(ProcID) + result = newLit(ProcID) + +proc macroGlobal = + doAssert m1("Macro argument") == 1 + doAssert m1("Macro argument") == 2 + doAssert m1("Macro argument") == 3 + +static: macroGlobal() +macroGlobal() + +block: # bug #10108 + template reject(x) = + static: doAssert(not compiles(x)) + + static: + let x: int = 2 + proc deliver_x(): int = x + var y2 = deliver_x() + discard y2 + reject: + const c5 = deliver_x() + +block: # bug #7590 + proc doInit[T]():auto= + var a: T + return a + + proc fun2[T](tup1:T)= + const tup0=doInit[T]() + + # var tup=tup0 #ok + const tup=tup0 #causes bug + + doAssert tup is tuple + doAssert tup[0] is tuple + for ai in tup.fields: + doAssert ai is tuple, "BUG2" + + # const c=(foo:(bar1: 0.0)) + const c=(foo:(bar1:"foo1")) + fun2(c) + +block: # bug #21708 + type + Tup = tuple[name: string] + + const X: array[2, Tup] = [(name: "foo",), (name: "bar",)] + + static: + let s = X[0] + doAssert s[0] == "foo" + +block: + proc swap[T](x: var T): T = + result = x + x = default(T) + + proc merge[T](a, b: var openArray[T]) = + a[0] = swap b[0] + + static: + var x = "abc" + var y = "356" + merge(x, y) + doAssert x == "3bc" + +block: # bug #22190 + type + EVMFork = enum + Berlin + Istanbul + Shanghai + + const + Vm2OpAllForks = + {EVMFork.low .. EVMFork.high} + + vm2OpExecBlockData = [(forks: Vm2OpAllForks)] + + proc mkOpTable(selected: EVMFork): bool = + selected notin vm2OpExecBlockData[0].forks + + const + tab = mkOpTable(Berlin) + + doAssert not tab + +block: # issue #22524 + const cnst = cstring(nil) + doAssert cnst.isNil + doAssert cnst == nil + let b = cnst + doAssert b.isNil + doAssert b == nil + + let a = static: cstring(nil) + doAssert a.isNil + + static: + var x: cstring + doAssert x.isNil + doAssert x == nil + doAssert x != "" + +block: # issue #15730 + const s: cstring = "" + doAssert s != nil + + static: + let s: cstring = "" + doAssert not s.isNil + doAssert s != nil + doAssert s == "" + +static: # more nil cstring issues + let x = cstring(nil) + doAssert x.len == 0 + +block: # bug #23925 + type Foo = enum A = -1 + proc foo = + doAssert cast[Foo](-1) == A + doAssert ord(A) == -1 + + static: foo() + foo() + + type E = enum + e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 e10 e11 e12 e13 e14 e15 e16 e17 e18 e19 e20 + e21 e22 e23 e24 e25 e26 e27 e28 e29 e30 e31 e32 e33 e34 e35 e36 e37 e38 + e39 e40 e41 e42 e43 e44 e45 e46 e47 e48 e49 e50 e51 e52 e53 e54 e55 e56 + e57 e58 e59 e60 e61 e62 e63 e64 e65 e66 e67 e68 e69 e70 e71 e72 e73 e74 + e75 e76 e77 e78 e79 e80 e81 e82 e83 e84 e85 e86 e87 e88 e89 e90 e91 e92 + e93 e94 e95 e96 e97 e98 e99 e100 e101 e102 e103 e104 e105 e106 e107 e108 + e109 e110 e111 e112 e113 e114 e115 e116 e117 e118 e119 e120 e121 e122 + e123 e124 e125 e126 e127 e128 + proc bar = + doAssert cast[E](int(e128)) == e128 + + static: bar() + bar() + +static: # bug #21353 + var s: proc () = default(proc ()) + doAssert s == nil diff --git a/tests/vm/tvmops.nim b/tests/vm/tvmops.nim new file mode 100644 index 000000000..3d8d5a9ac --- /dev/null +++ b/tests/vm/tvmops.nim @@ -0,0 +1,46 @@ +discard """ + targets: "c cpp js" +""" + +#[ +test for vmops.nim +]# +import os +import math +import strutils + +static: + # TODO: add more tests + block: #getAppFilename, gorgeEx, gorge + const nim = getCurrentCompilerExe() + let ret = gorgeEx(nim & " --version") + doAssert ret.exitCode == 0 + doAssert ret.output.contains "Nim Compiler" + let ret2 = gorgeEx(nim & " --nonxistent") + doAssert ret2.exitCode != 0 + let output3 = gorge(nim & " --version") + doAssert output3.contains "Nim Compiler" + + block: + const key = "D20181210T175037" + const val = "foo" + putEnv(key, val) + doAssert existsEnv(key) + doAssert getEnv(key) == val + + block: + # sanity check (we probably don't need to test for all ops) + const a1 = arcsin 0.3 + let a2 = arcsin 0.3 + doAssert a1 == a2 + + block bitxor: + let x = -1'i32 + let y = 1'i32 + doAssert (x xor y) == -2 + +block: + # Check against bugs like #9176 + doAssert getCurrentCompilerExe() == getCurrentCompilerExe().static + if false: #pending #9176 + doAssert gorgeEx("nonxistent") == gorgeEx("nonxistent").static diff --git a/tests/vm/tvmopsDanger.nim b/tests/vm/tvmopsDanger.nim new file mode 100644 index 000000000..966feffe6 --- /dev/null +++ b/tests/vm/tvmopsDanger.nim @@ -0,0 +1,13 @@ +discard """ + cmd: "nim c --experimental:vmopsDanger -r $file" +""" +when defined(nimPreviewSlimSystem): + import std/assertions +import std/[times, os] + +const foo = getTime() +let bar = foo +doAssert bar > low(Time) + +static: # bug #23932 + doAssert getCurrentDir().len > 0 diff --git a/tests/vm/twrong_concat.nim b/tests/vm/twrong_concat.nim index 538ea2527..59a10bdb9 100644 --- a/tests/vm/twrong_concat.nim +++ b/tests/vm/twrong_concat.nim @@ -1,7 +1,3 @@ -discard """ - output: '''success''' -""" - # bug #3804 #import sequtils @@ -23,6 +19,4 @@ static: sameBug(objs) # sameBug(objs) echo objs[0].field - assert(objs[0].field == "hello") # fails, because (objs[0].field == "hello bug") - mutated! - -echo "success" + doAssert(objs[0].field == "hello") # fails, because (objs[0].field == "hello bug") - mutated! diff --git a/tests/vm/twrongarray.nim b/tests/vm/twrongarray.nim index c1514d0e9..7f24290e2 100644 --- a/tests/vm/twrongarray.nim +++ b/tests/vm/twrongarray.nim @@ -14,4 +14,4 @@ when false: proc two(dummy: int, size: int) = var x: array[size * 1, int] # compiles, but shouldn't? - #assert(x.len == size) # just for fun + # doAssert(x.len == size) # just for fun diff --git a/tests/vm/tyaytypedesc.nim b/tests/vm/tyaytypedesc.nim index a3ad9b707..8cb402bff 100644 --- a/tests/vm/tyaytypedesc.nim +++ b/tests/vm/tyaytypedesc.nim @@ -1,7 +1,3 @@ -discard """ - output: "ntWhitespace" -""" - # bug #3357 type NodeType* = enum @@ -10,7 +6,7 @@ type NodeType* = enum type TokenType* = enum ttWhitespace -proc enumTable*[A, B, C](a: openarray[tuple[key: A, val: B]], ret: typedesc[C]): C = +proc enumTable*[A, B, C](a: openArray[tuple[key: A, val: B]], ret: typedesc[C]): C = for item in a: result[item.key] = item.val @@ -18,4 +14,4 @@ const tokenTypeToNodeType = { ttWhitespace: ntWhitespace, }.enumTable(array[ttWhitespace..ttWhitespace, NodeType]) -echo tokenTypeToNodeType[ttWhitespace] +doAssert tokenTypeToNodeType[ttWhitespace] == ntWhitespace diff --git a/tests/vm/tzero_extend.nim b/tests/vm/tzero_extend.nim index a79105531..418dbc486 100644 --- a/tests/vm/tzero_extend.nim +++ b/tests/vm/tzero_extend.nim @@ -5,22 +5,22 @@ proc get_values(): (seq[int8], seq[int16], seq[int32]) = let i8 = -3'i8 let i16 = -3'i16 let i32 = -3'i32 - doAssert i8.ze == 0xFD - doAssert i8.ze64 == 0xFD - doAssert i16.ze == 0xFFFD - doAssert i16.ze64 == 0xFFFD + doAssert int(cast[uint8](i8)) == 0xFD + doAssert int64(cast[uint8](i8)) == 0xFD + doAssert int(cast[uint16](i16)) == 0xFFFD + doAssert int64(cast[uint16](i16)) == 0xFFFD result[0] = @[]; result[1] = @[]; result[2] = @[] for offset in RANGE: - let i8 = -(1 shl 9) + offset - let i16 = -(1 shl 17) + offset - let i32 = -(1 shl 33) + offset + let i8 = -(1'i64 shl 9) + offset + let i16 = -(1'i64 shl 17) + offset + let i32 = -(1'i64 shl 33) + offset # higher bits are masked. these should be exactly equal to offset. - result[0].add i8.toU8 - result[1].add i16.toU16 - result[2].add i32.toU32 + result[0].add cast[int8](cast[uint64](i8)) + result[1].add cast[int16](cast[uint64](i16)) + result[2].add cast[int32](cast[uint64](i32)) # these values this computed by VM |