summary refs log tree commit diff stats
path: root/tests/js
diff options
context:
space:
mode:
authorrec <44084068+recloser@users.noreply.github.com>2018-12-04 12:04:27 +0100
committerAndreas Rumpf <rumpf_a@web.de>2018-12-04 12:04:27 +0100
commite3e5ae287f9a10ab9ee350e64982f21c44238594 (patch)
tree7ae04f1401c62ef4b31cbbce5134dfb3555a20e9 /tests/js
parent07744b6e47ef1e83630d628c7d1eae4f3aa5bee5 (diff)
downloadNim-e3e5ae287f9a10ab9ee350e64982f21c44238594.tar.gz
Fix fat pointers, object copying, magic double evals on JS (#9411) [backport]
* Add a test for issue #9389

* Fixes #9389.

* Make object contructors copy objects properly by checking whether the expressions passed to them don't need to be copied.
* Make mArrToSeq implementation actually check if a copy needs to be made.

* Avoid unnecessary copy in mChr impl

* Assume set constructor elements need no copy

* Add a test for issue #9410

* Add a test

* fix passing fat pointers (#9410)

* Enhance tests

* More tests and fixes

* Add more (failing) tests [ci skip]

* Added equality operator for fat pointers, more tests and fixes

* Fix printing uninitialized strings

* Fix mInc, mDec double eval, add more tests

* Tests

* Refactored, fixed multiple evals, revamped the tests, added missing ops

* Fix ups

* Fix #9643 and #9644

* add pointer normalization
Diffstat (limited to 'tests/js')
-rw-r--r--tests/js/t9410.nim454
-rw-r--r--tests/js/tcopying.nim35
2 files changed, 489 insertions, 0 deletions
diff --git a/tests/js/t9410.nim b/tests/js/t9410.nim
new file mode 100644
index 000000000..9aca6d45b
--- /dev/null
+++ b/tests/js/t9410.nim
@@ -0,0 +1,454 @@
+template doAssert(exp: untyped) =
+  when defined(echot9410):
+    let r = exp
+    echo $(instantiationInfo().line) & ":\n  " & astToStr(exp) & "\n  was " & repr(r)
+    when not defined(noassertt9410):
+      system.doAssert r
+  else:
+    when not defined(noassertt9410):
+      system.doAssert exp
+
+template tests =
+  block:
+    var i = 0
+    i = 2
+
+    var y: ptr int
+    doAssert y == nil
+    doAssert isNil(y)
+    y = i.addr
+    y[] = 3
+    doAssert i == 3
+    doAssert i == y[]
+
+    let z = i.addr
+    z[] = 4
+    doAssert i == 4
+    doAssert i == y[] and y[] == z[]
+
+    var hmm = (a: (b: z))
+    var hmmptr = hmm.a.b.addr
+    hmmptr[][] = 5
+
+    doAssert i == 5
+    doAssert y == z
+    doAssert z == hmmptr[]
+    doAssert 5 == y[] and 5 == z[] and 5 == hmmptr[][]
+
+  block:
+    var someint = 500
+
+    let p: ptr int = someint.addr
+    let tup = (f: p)
+    let tcopy = tup
+    var vtcopy = tcopy
+    p[] = 654
+    doAssert p[] == 654
+    doAssert tup.f[] == 654
+    doAssert tcopy.f[] == 654
+    doAssert vtcopy.f[] == 654
+
+  block:
+    var someint = 500
+
+    var p: ptr int = someint.addr
+    let arr = [p]
+    let arrc = arr
+    p[] = 256
+    doAssert someint == 256
+    doAssert p[] == 256
+    doAssert arr[0][] == 256
+    doAssert arrc[0][] == 256
+
+  block:
+    var someref: ref int
+    new(someref)
+    var someref2 = someref
+
+    var tup1 = (f: someref)
+    tup1.f = someref
+    let tup2 = tup1
+
+    someref[] = 543
+
+    proc passref(r: var ref int): var ref int = r
+    new(passref(someref))
+
+    doAssert someref[] == 0
+    doAssert tup1.f[] == 543
+    doAssert tup2.f[] == 543
+    doAssert someref2[] == 543
+
+  block:
+    type Whatever = object
+      i: ref int
+
+    var someref: ref int
+    new(someref)
+    someref[] = 10
+
+    let w = Whatever(i: someref)
+    var wcopy = w
+
+    someref[] = 20
+
+    doAssert w.i[] == 20
+    doAssert someref[] == 20
+    doAssert wcopy.i[] == 20
+    doAssert w.i == wcopy.i
+    #echo w.i[], " ", someref[], " ", wcopy.i[]
+
+  block:
+    var oneseq: ref seq[ref int]
+    new(oneseq)
+    var aref: ref int
+    new(aref)
+    aref[] = 123
+    let arefs = [aref]
+    oneseq[] &= arefs[0]
+    oneseq[] &= aref
+    aref[] = 222
+    new(aref)
+    doAssert oneseq[0] == oneseq[1]
+    doAssert oneseq[0][] == 222
+    doAssert oneseq[1][] == 222
+    doAssert aref[] == 0
+
+  block:
+    var seqs: ref seq[ref seq[ref int]]
+    new(seqs)
+    seqs[] = newSeq[ref seq[ref int]](1)
+    new(seqs[0])
+    seqs[0][] = newSeq[ref int](0)
+
+    var aref: ref int
+    new aref
+    aref[] = 654
+
+    let arefs = [aref]
+    doAssert arefs[0] == aref
+    seqs[0][] &= arefs[0]
+    seqs[0][] &= aref
+    seqs[0][1][] = 456
+    let seqs2 = seqs
+    let same = seqs2[0][0] == seqs2[0][1]
+    doAssert arefs[0] == aref
+    doAssert aref[] == 456
+    doAssert seqs[].len == 1
+    doAssert seqs[0][].len == 2
+    doAssert seqs[0][0][] == 456
+    doAssert seqs[0][1][] == 456
+    doAssert same
+
+  block:
+    type Obj = object
+      x, y: int
+
+    var objrefs: seq[ref Obj] = @[(ref Obj)(nil), nil, nil]
+    objrefs[2].new
+    objrefs[2][] = Obj(x: 123, y: 321)
+    objrefs[1] = objrefs[2]
+    doAssert objrefs[0] == nil
+    doAssert objrefs[1].y == 321
+    doAssert objrefs[2].y == 321
+    doAssert objrefs[1] == objrefs[2]
+
+  block:
+    var refs: seq[ref string] = @[(ref string)(nil), nil, nil]
+    refs[1].new
+    refs[1][] = "it's a ref!"
+    refs[0] = refs[1]
+    refs[2] = refs[1]
+    new(refs[0])
+    doAssert refs[0][] == ""
+    doAssert refs[1][] == "it's a ref!"
+    doAssert refs[2][] == "it's a ref!"
+    doAssert refs[1] == refs[2]
+
+  block:
+    var retaddr_calls = 0
+    proc retaddr(p: var int): var int =
+      retaddr_calls += 1
+      p
+
+    var tfoo_calls = 0
+    proc tfoo(x: var int) =
+      tfoo_calls += 1
+      x += 10
+      var y = x.addr
+      y[] += 20
+      retaddr(x) += 30
+      let z = retaddr(x).addr
+      z[] += 40
+
+    var ints = @[1, 2, 3]
+    tfoo(ints[1])
+    doAssert retaddr_calls == 2
+    doAssert tfoo_calls == 1
+    doAssert ints[1] == 102
+
+    var tbar_calls = 0
+    proc tbar(x: var int): var int =
+      tbar_calls += 1
+      x
+
+    tbar(ints[2]) += 10
+    tbar(ints[2]) *= 2
+    doAssert tbar_calls == 2
+
+    var tqux_calls = 0
+    proc tqux(x: var int): ptr int =
+      tqux_calls += 1
+      x.addr
+
+    discard tqux(ints[2]) == tqux(ints[2])
+    doAssert tqux_calls == 2
+    doAssert isNil(tqux(ints[2])) == false
+    doAssert tqux_calls == 3
+
+    var tseq_calls = 0
+    proc tseq(x: var seq[int]): var seq[int] =
+      tseq_calls += 1
+      x
+
+    tseq(ints) &= 999
+    doAssert tseq_calls == 1
+    doAssert ints == @[1, 102, 26, 999]
+
+    var rawints = @[555]
+    rawints &= 666
+    doAssert rawints == @[555, 666]
+
+    var resetints_calls = 0
+    proc resetInts(): int =
+      resetints_calls += 1
+      ints = @[0, 0, 0]
+      1
+
+    proc incr(x: var int; b: int): var int =
+      x = x + b
+      x
+
+    var q = 0
+    var qp = q.addr
+    qp[] += 123
+    doAssert q == 123
+    # check order of evaluation
+    doAssert (resetInts() + incr(q, tqux(ints[2])[])) == 124
+
+  block: # reset
+    var calls = 0
+    proc passsomething(x: var int): var int =
+      calls += 1
+      x
+
+    var
+      a = 123
+      b = 500
+      c = a.addr
+    reset(passsomething(a))
+    doAssert calls == 1
+    reset(b)
+    doAssert a == b
+    reset(c)
+    doAssert c == nil
+
+  block: # strings
+    var calls = 0
+    proc stringtest(s: var string): var string =
+      calls += 1
+      s
+
+    var somestr: string
+
+    stringtest(somestr) &= 'a'
+    stringtest(somestr) &= 'b'
+    doAssert calls == 2
+    doAssert somestr == "ab"
+    stringtest(somestr) &= "woot!"
+    doAssert somestr == "abwoot!"
+    doAssert calls == 3
+
+    doAssert stringtest(somestr).len == 7
+    doAssert calls == 4
+    doAssert high(stringtest(somestr)) == 6
+    doAssert calls == 5
+
+    var somestr2: string
+    stringtest(somestr2).setLen(stringtest(somestr).len)
+    doAssert calls == 7
+    doAssert somestr2.len == somestr.len
+
+    var somestr3: string
+    doAssert (somestr3 & "foo") == "foo"
+
+    block:
+      var a, b, c, d: string
+      d = a & b & c
+      doAssert d == ""
+      d = stringtest(a) & stringtest(b) & stringtest(c)
+      doAssert calls == 10
+      doAssert d == ""
+
+  block: # seqs
+    var calls = 0
+    proc seqtest(s: var seq[int]): var seq[int] =
+      calls += 1
+      s
+
+    var someseq: seq[int]
+
+    seqtest(someseq) &= 1
+    seqtest(someseq) &= 2
+    doAssert calls == 2
+    doAssert someseq == @[1, 2]
+    seqtest(someseq) &= @[3, 4, 5]
+    doAssert someseq == @[1, 2, 3, 4, 5]
+    doAssert calls == 3
+
+    doAssert seqtest(someseq).len == 5
+    doAssert calls == 4
+    doAssert high(seqtest(someseq)) == 4
+    doAssert calls == 5
+
+    # genArrayAddr
+    doAssert seqtest(someseq)[2] == 3
+    doAssert calls == 6
+
+    seqtest(someseq).setLen(seqtest(someseq).len)
+    doAssert calls == 8
+
+    var somenilseq: seq[int]
+    seqtest(somenilseq).setLen(3)
+    doAssert calls == 9
+    doAssert somenilseq[1] == 0
+
+    someseq = @[1, 2, 3]
+    doAssert (seqtest(someseq) & seqtest(someseq)) == @[1, 2, 3, 1, 2, 3]
+
+
+  block: # mInc, mDec
+    var calls = 0
+    proc someint(x: var int): var int =
+      calls += 1
+      x
+
+    var x = 10
+
+    inc(someint(x))
+    doAssert x == 11
+    doAssert calls == 1
+
+    dec(someint(x))
+    doAssert x == 10
+    doAssert calls == 2
+
+  block: # uints
+    var calls = 0
+    proc passuint(x: var uint32): var uint32 =
+      calls += 1
+      x
+
+    var u: uint32 = 5
+    passuint(u) += 1
+    doAssert u == 6
+    doAssert calls == 1
+
+    passuint(u) -= 1
+    doAssert u == 5
+    doAssert calls == 2
+
+    passuint(u) *= 2
+    doAssert u == 10
+    doAssert calls == 3
+
+  block: # objs
+    type Thing = ref object
+      x, y: int
+
+    var a, b: Thing
+    a = Thing()
+    b = a
+
+    doAssert a == b
+
+    var calls = 0
+    proc passobj(o: var Thing): var Thing =
+      calls += 1
+      o
+
+    passobj(b) = Thing(x: 123)
+    doAssert calls == 1
+    doAssert a != b
+    doAssert b.x == 123
+
+    var passobjptr_calls = 0
+    proc passobjptr(o: var Thing): ptr Thing =
+      passobjptr_calls += 1
+      o.addr
+
+    passobjptr(b)[] = Thing(x: 234)
+    doAssert passobjptr_calls == 1
+    doAssert a != b
+    doAssert b.x == 234
+    passobjptr(b)[].x = 500
+    doAssert b.x == 500
+
+    var pptr = passobjptr(b)
+    pptr.x += 100
+    doAssert b.x == 600
+
+    proc getuninitptr(): ptr int =
+      return
+
+    doAssert getuninitptr() == nil
+
+  block: # pointer casting
+    var obj = (x: 321, y: 543)
+    var x = 500
+
+    var objptr = obj.addr
+    var xptr = x.addr
+
+    var p1, p2: pointer
+    p1 = cast[pointer](objptr)
+    p2 = cast[pointer](xptr)
+    doAssert p1 != p2
+
+    p1 = cast[pointer](objptr)
+    p2 = cast[pointer](objptr)
+    doAssert p1 == p2
+
+    let objptr2 = cast[type(objptr)](p2)
+    doAssert objptr == objptr2
+
+    p1 = cast[pointer](xptr)
+    p2 = cast[pointer](xptr)
+    doAssert p1 == p2
+
+    let xptr2 = cast[type(xptr)](p2)
+    doAssert xptr == xptr2
+
+  when false:
+    block: # openarray
+          # Error: internal error: genAddr: nkStmtListExpr
+      var calls = 0
+      proc getvarint(x: var openarray[int]): var int =
+        calls += 1
+        if true:
+          x[1]
+        else:
+          x[0]
+
+      var arr = [1, 2, 3]
+      getvarint(arr) += 5
+      doAssert calls == 1
+      doAssert arr[1] == 7
+
+proc tests_in_proc =
+  tests
+
+# since pointers are handled differently in global/local contexts
+# let's just run all of them twice
+tests_in_proc()
+tests
diff --git a/tests/js/tcopying.nim b/tests/js/tcopying.nim
index 387df9cd3..c58a080e9 100644
--- a/tests/js/tcopying.nim
+++ b/tests/js/tcopying.nim
@@ -2,6 +2,10 @@ discard """
   output: '''123
 2 9
 2 9
+1 124
+true false
+100 300 100
+1
 '''
 """
 
@@ -35,3 +39,34 @@ block:
     obj.ary2[1] = 9
 
     echo ary1[1], " ", obj.ary2[1]
+
+block:
+    type TestObj = object
+        x, y: int
+
+    let obj = TestObj(x: 1, y: 2)
+    var s = @[obj]
+    s[0].x += 123
+    echo obj.x, " ", s[0].x
+
+block:
+    var nums = {1, 2, 3, 4}
+    let obj = (n: nums)
+    nums.incl 5
+    echo (5 in nums), " ", (5 in obj.n)
+
+block:
+    let tup1 = (a: 100)
+    var tup2 = (t: (t2: tup1))
+    var tup3 = tup1
+    tup2.t.t2.a = 300
+    echo tup1.a, " ", tup2.t.t2.a, " ", tup3.a
+
+block:
+    proc foo(arr: array[2, int]) =
+        var s = @arr
+        s[0] = 500
+
+    var nums = [1, 2]
+    foo(nums)
+    echo nums[0]
\ No newline at end of file