From 0f653770a467db9711710c759df3b9b91dad80be Mon Sep 17 00:00:00 2001 From: Timothee Cour Date: Wed, 25 Nov 2020 11:48:10 -0800 Subject: [PATCH] fix #14339, #13511, #14420: fixes limited VM support for addr (#16002) * fix #14339: fixes limited VM support for addr * strengthen test * reference bug #16003 * also fixes #13511 * also fixes #14420 --- compiler/vm.nim | 7 ++- tests/macros/tmacros_various.nim | 25 +++++++++ tests/misc/taddr.nim | 80 +++++++++++++++++++++++++++ tests/stdlib/tcritbits.nim | 92 +++++++++++++++++--------------- 4 files changed, 160 insertions(+), 44 deletions(-) diff --git a/compiler/vm.nim b/compiler/vm.nim index a6478f3f06fc0..17bbe65fc9845 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -746,10 +746,13 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = regs[ra].regAddr = addr(regs[rb]) of opcAddrNode: decodeB(rkNodeAddr) - if regs[rb].kind == rkNode: + case regs[rb].kind + of rkNode: regs[ra].nodeAddr = addr(regs[rb].node) + of rkNodeAddr: # bug #14339 + regs[ra].nodeAddr = regs[rb].nodeAddr else: - stackTrace(c, tos, pc, "limited VM support for 'addr'") + stackTrace(c, tos, pc, "limited VM support for 'addr', got kind: " & $regs[rb].kind) of opcLdDeref: # a = b[] let ra = instr.regA diff --git a/tests/macros/tmacros_various.nim b/tests/macros/tmacros_various.nim index 05683083753ca..00d74cb5c97a9 100644 --- a/tests/macros/tmacros_various.nim +++ b/tests/macros/tmacros_various.nim @@ -245,3 +245,28 @@ xbenchmark: discard inputtest fastSHA("hey") + +block: # bug #13511 + type + Builder = ref object + components: seq[Component] + Component = object + + proc add(builder: var Builder, component: Component) {.compileTime.} = + builder.components.add(component) + + macro debugAst(arg: typed): untyped = + ## just for debugging purpose. + discard arg.treeRepr + return arg + + static: + var component = Component() + var builder = Builder() + + template foo(): untyped = + ## WAS: this doc comment causes compilation failure. + builder + + debugAst: + add(foo(), component) diff --git a/tests/misc/taddr.nim b/tests/misc/taddr.nim index 49a5777986641..d743d4b4a4d9e 100644 --- a/tests/misc/taddr.nim +++ b/tests/misc/taddr.nim @@ -123,3 +123,83 @@ block: block: # pending bug #15959 when false: proc byLent2[T](a: T): lent type(a[0]) = a[0] + +proc test14420() = # bug #14420 + # s/proc/template/ would hit bug #16005 + block: + type Foo = object + x: float + + proc fn(a: var Foo): var float = + ## WAS: discard <- turn this into a comment (or a `discard`) and error disappears + # result = a.x # this works + a.x # WAS: Error: limited VM support for 'addr' + + proc fn2(a: var Foo): var float = + result = a.x # this works + a.x # WAS: Error: limited VM support for 'addr' + + var a = Foo() + discard fn(a) + discard fn2(a) + + block: + proc byLent2[T](a: T): lent T = + runnableExamples: discard + a + proc byLent3[T](a: T): lent T = + runnableExamples: discard + result = a + var a = 10 + let x3 = byLent3(a) # works + let x2 = byLent2(a) # WAS: Error: internal error: genAddr: nkStmtListExpr + + block: + type MyOption[T] = object + case has: bool + of true: + value: T + of false: + discard + func some[T](val: T): MyOption[T] = + result = MyOption[T](has: true, value: val) + func get[T](opt: MyOption[T]): lent T = + doAssert opt.has + # result = opt.value # this was ok + opt.value # this had the bug + let x = some(10) + doAssert x.get() == 10 + +template test14339() = # bug #14339 + block: + type + Node = ref object + val: int + proc bar(c: Node): var int = + var n = c # was: Error: limited VM support for 'addr' + c.val + var a = Node() + discard a.bar() + block: + type + Node = ref object + val: int + proc bar(c: Node): var int = + var n = c + doAssert n.val == n[].val + n.val + var a = Node(val: 3) + a.bar() = 5 + when nimvm: + doAssert a.val == 5 + else: + when not defined(js): # pending bug #16003 + doAssert a.val == 5 + +template main = + # xxx wrap all other tests here like that so they're also tested in VM + test14420() + test14339() + +static: main() +main() diff --git a/tests/stdlib/tcritbits.nim b/tests/stdlib/tcritbits.nim index 51cbb7bf21ef8..4b05cd95034b6 100644 --- a/tests/stdlib/tcritbits.nim +++ b/tests/stdlib/tcritbits.nim @@ -1,61 +1,69 @@ -import sequtils, critbits +import std/[sequtils,critbits] +template main = + var r: CritBitTree[void] + r.incl "abc" + r.incl "xyz" + r.incl "def" + r.incl "definition" + r.incl "prefix" + r.incl "foo" -var r: CritBitTree[void] -r.incl "abc" -r.incl "xyz" -r.incl "def" -r.incl "definition" -r.incl "prefix" -r.incl "foo" + doAssert r.contains"def" -doAssert r.contains"def" + r.excl "def" + assert r.missingOrExcl("foo") == false + assert "foo" notin toSeq(r.items) -r.excl "def" -assert r.missingOrExcl("foo") == false -assert "foo" notin toSeq(r.items) + assert r.missingOrExcl("foo") == true -assert r.missingOrExcl("foo") == true + assert toSeq(r.items) == @["abc", "definition", "prefix", "xyz"] -assert toSeq(r.items) == @["abc", "definition", "prefix", "xyz"] + assert toSeq(r.itemsWithPrefix("de")) == @["definition"] + var c = CritBitTree[int]() -assert toSeq(r.itemsWithPrefix("de")) == @["definition"] -var c = CritBitTree[int]() + c.inc("a") + assert c["a"] == 1 -c.inc("a") -assert c["a"] == 1 + c.inc("a", 4) + assert c["a"] == 5 -c.inc("a", 4) -assert c["a"] == 5 + c.inc("a", -5) + assert c["a"] == 0 -c.inc("a", -5) -assert c["a"] == 0 + c.inc("b", 2) + assert c["b"] == 2 -c.inc("b", 2) -assert c["b"] == 2 + c.inc("c", 3) + assert c["c"] == 3 -c.inc("c", 3) -assert c["c"] == 3 + c.inc("a", 1) + assert c["a"] == 1 -c.inc("a", 1) -assert c["a"] == 1 + var cf = CritBitTree[float]() -var cf = CritBitTree[float]() + cf.incl("a", 1.0) + assert cf["a"] == 1.0 -cf.incl("a", 1.0) -assert cf["a"] == 1.0 + cf.incl("b", 2.0) + assert cf["b"] == 2.0 -cf.incl("b", 2.0) -assert cf["b"] == 2.0 + cf.incl("c", 3.0) + assert cf["c"] == 3.0 -cf.incl("c", 3.0) -assert cf["c"] == 3.0 + assert cf.len == 3 + cf.excl("c") + assert cf.len == 2 -assert cf.len == 3 -cf.excl("c") -assert cf.len == 2 + var cb: CritBitTree[string] + cb.incl("help", "help") + for k in cb.keysWithPrefix("helpp"): + doAssert false, "there is no prefix helpp" -var cb: CritBitTree[string] -cb.incl("help", "help") -for k in cb.keysWithPrefix("helpp"): - doAssert false, "there is no prefix helpp" + block: # bug #14339 + var strings: CritBitTree[int] + discard strings.containsOrIncl("foo", 3) + doAssert strings["foo"] == 3 + +main() +static: main()