summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2017-06-03 21:08:32 +0200
committerAndreas Rumpf <rumpf_a@web.de>2017-06-03 21:08:32 +0200
commit42c9bb3acedd524be23263a8217f34d0100779d9 (patch)
treef00768910ef07d6392a33a30ef77dcebe27f6a3b
parentd1f5e3b110e92270cfb84218874834054bd7ee64 (diff)
downloadNim-42c9bb3acedd524be23263a8217f34d0100779d9.tar.gz
fixes #5933
-rw-r--r--compiler/jsgen.nim19
-rw-r--r--tests/js/tseqops.nim51
2 files changed, 68 insertions, 2 deletions
diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim
index be7443dac..b31c3a6a7 100644
--- a/compiler/jsgen.nim
+++ b/compiler/jsgen.nim
@@ -944,7 +944,15 @@ proc genAsgn(p: PProc, n: PNode) =
 
 proc genFastAsgn(p: PProc, n: PNode) =
   genLineDir(p, n)
-  genAsgnAux(p, n.sons[0], n.sons[1], noCopyNeeded=true)
+  # 'shallowCopy' always produced 'noCopyNeeded = true' here but this is wrong
+  # for code like
+  #  while j >= pos:
+  #    dest[i].shallowCopy(dest[j])
+  # See bug #5933. So we try to be more compatible with the C backend semantics
+  # here for 'shallowCopy'. This is an educated guess and might require further
+  # changes later:
+  let noCopy = n[0].typ.skipTypes(abstractInst).kind in {tySequence, tyString}
+  genAsgnAux(p, n.sons[0], n.sons[1], noCopyNeeded=noCopy)
 
 proc genSwap(p: PProc, n: PNode) =
   var a, b: TCompRes
@@ -1841,7 +1849,14 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
       else: binaryExpr(p, n, r, "subInt", "$1 = subInt($1, $2)")
   of mSetLengthStr:
     binaryExpr(p, n, r, "", "$1.length = $2+1; $1[$1.length-1] = 0" | "$1 = substr($1, 0, $2)")
-  of mSetLengthSeq: binaryExpr(p, n, r, "", "$1.length = $2" | "$1 = array_slice($1, 0, $2)")
+  of mSetLengthSeq:
+    var x, y: TCompRes
+    gen(p, n.sons[1], x)
+    gen(p, n.sons[2], y)
+    let t = skipTypes(n.sons[1].typ, abstractVar).sons[0]
+    r.res = """if ($1.length < $2) { for (var i=$1.length;i<$2;++i) $1.push($3); }
+               else { $1.length = $2; }""" % [x.rdLoc, y.rdLoc, createVar(p, t, false)]
+    r.kind = resExpr
   of mCard: unaryExpr(p, n, r, "SetCard", "SetCard($1)")
   of mLtSet: binaryExpr(p, n, r, "SetLt", "SetLt($1, $2)")
   of mLeSet: binaryExpr(p, n, r, "SetLe", "SetLe($1, $2)")
diff --git a/tests/js/tseqops.nim b/tests/js/tseqops.nim
new file mode 100644
index 000000000..d10e1ca6a
--- /dev/null
+++ b/tests/js/tseqops.nim
@@ -0,0 +1,51 @@
+discard """
+  output: '''(x: 0, y: 0)
+(x: 5, y: 0)
+@[(x: 2, y: 4), (x: 4, y: 5), (x: 4, y: 5)]
+@[(a: 3, b: 3), (a: 1, b: 1), (a: 2, b: 2)]
+'''
+"""
+
+# bug #4139
+
+type
+  TestO = object
+    x, y: int
+
+proc onLoad() =
+  var test: seq[TestO] = @[]
+  var foo = TestO(x: 0, y: 0)
+  test.add(foo)
+  foo.x = 5
+  echo(test[0])
+  echo foo
+
+onLoad()
+
+# 'setLen' bug (part of bug #5933)
+type MyObj = object
+  x: cstring
+  y: int
+
+proc foo(x: var seq[MyObj]) =
+  let L = x.len
+  x.setLen L + 1
+  x[L] = x[1]
+
+var s = @[MyObj(x: "2", y: 4), MyObj(x: "4", y: 5)]
+foo(s)
+echo s
+
+# bug  #5933
+import sequtils
+
+type
+  Test = object
+    a: cstring
+    b: int
+
+var test = @[Test(a: "1", b: 1), Test(a: "2", b: 2)]
+
+test.insert(@[Test(a: "3", b: 3)], 0)
+
+echo test