summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2014-06-26 20:51:44 +0200
committerAndreas Rumpf <rumpf_a@web.de>2014-06-26 20:51:44 +0200
commit8c93d3e1f9ddedc83d1fc90c5b938343cfe1d36f (patch)
tree6eac2d9d42faa1469f5099db20d3c52f8f04fde3
parentf793523ade7aa48dcf13ede123a0a434e39e54e0 (diff)
parentbdd3b6c612a29723954f62e242888eedee0b35e4 (diff)
downloadNim-8c93d3e1f9ddedc83d1fc90c5b938343cfe1d36f.tar.gz
Merge pull request #1306 from flyx/devel
Fixed handling swap in vmgen
-rw-r--r--compiler/vmgen.nim10
-rw-r--r--lib/pure/collections/sets.nim49
-rw-r--r--tests/sets/tsets3.nim81
3 files changed, 136 insertions, 4 deletions
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index 186d27ae4..305ea7f9e 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -787,10 +787,12 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
     c.freeTemp(tmp)
   of mSwap: 
     unused(n, dest)
-    var d = c.genx(n.sons[1])
-    var tmp = c.genx(n.sons[2])
-    c.gABC(n, opcSwap, d, tmp)
-    c.freeTemp(tmp)
+    var
+      d1 = c.genx(n.sons[1])
+      d2 = c.genx(n.sons[2])
+    c.gABC(n, opcSwap, d1, d2)
+    c.genAsgnPatch(n.sons[1], d1)
+    c.genAsgnPatch(n.sons[2], d2)
   of mIsNil: genUnaryABC(c, n, dest, opcIsNil)
   of mCopyStr:
     if dest < 0: dest = c.getTemp(n.typ)
diff --git a/lib/pure/collections/sets.nim b/lib/pure/collections/sets.nim
index bc249ed63..380a33c5b 100644
--- a/lib/pure/collections/sets.nim
+++ b/lib/pure/collections/sets.nim
@@ -112,6 +112,10 @@ proc incl*[A](s: var TSet[A], key: A) =
   ## includes an element `key` in `s`.
   inclImpl()
 
+proc incl*[A](s: var TSet[A], other: TSet[A]) =
+  ## includes everything in `other` in `s`
+  for item in other: incl(s, item)
+
 proc excl*[A](s: var TSet[A], key: A) =
   ## excludes `key` from the set `s`.
   var index = rawGet(s, key)
@@ -119,6 +123,10 @@ proc excl*[A](s: var TSet[A], key: A) =
     s.data[index].slot = seDeleted
     dec(s.counter)
 
+proc excl*[A](s: var TSet[A], other: TSet[A]) =
+  ## excludes everything in `other` from `s`.
+  for item in other: excl(s, item)
+
 proc containsOrIncl*[A](s: var TSet[A], key: A): bool =
   ## returns true if `s` contains `key`, otherwise `key` is included in `s`
   ## and false is returned.
@@ -147,6 +155,43 @@ proc `$`*[A](s: TSet[A]): string =
   ## The `$` operator for hash sets.
   dollarImpl()
 
+proc union*[A](s1, s2: TSet[A]): TSet[A] =
+  ## returns a new set of all items that are contained in at
+  ## least one of `l` and `r`
+  result = s1
+  incl(result, s2)
+
+proc intersection*[A](s1, s2: TSet[A]): TSet[A] =
+  ## returns a new set of all items that are contained in both `l` and `r`
+  result = initSet[A](min(s1.data.len, s2.data.len))
+  for item in s1:
+    if item in s2: incl(result, item)
+
+proc symmetricDifference*[A](s1, s2: TSet[A]): TSet[A] =
+  ## returns a new set of all items that are contained in either
+  ## `l` or `r`, but not both
+  result = s1
+  for item in s2:
+    if containsOrIncl(result, item): excl(result, item)
+
+proc `or`*[A](s1, s2: TSet[A]): TSet[A] {.inline.} =
+  ## alias for `union`
+  result = union(s1, s2)
+
+proc `and`*[A](s1, s2: TSet[A]): TSet[A] {.inline.} =
+  ## alias for `intersection`
+  result = intersection(s1, s2)
+
+proc `xor`*[A](s1, s2: TSet[A]): TSet[A] {.inline.} =
+  ## alias for `symmetricDifference`
+  result = symmetricDifference(s1, s2)
+
+proc disjoint*[A](s1, s2: TSet[A]): bool =
+  ## returns true iff `l` and `r` have no items in common
+  for item in s1:
+    if item in s2: return false
+  return true
+
 # ------------------------------ ordered set ------------------------------
 
 type
@@ -211,6 +256,10 @@ proc incl*[A](s: var TOrderedSet[A], key: A) =
   ## includes an element `key` in `s`.
   inclImpl()
 
+proc incl*[A](s: var TSet[A], other: TOrderedSet[A]) =
+  ## includes everything in `other` in `s`
+  for item in other: incl(s, item)
+
 proc containsOrIncl*[A](s: var TOrderedSet[A], key: A): bool =
   ## returns true if `s` contains `key`, otherwise `key` is included in `s`
   ## and false is returned.
diff --git a/tests/sets/tsets3.nim b/tests/sets/tsets3.nim
new file mode 100644
index 000000000..5d14a1d8f
--- /dev/null
+++ b/tests/sets/tsets3.nim
@@ -0,0 +1,81 @@
+include sets
+
+let
+  s1: TSet[int] = toSet([1, 2, 4, 8, 16])
+  s2: TSet[int] = toSet([1, 2, 3, 5, 8])
+  s3: TSet[int] = toSet([3, 5, 7])
+
+block union:
+  let
+    s1_s2 = union(s1, s2)
+    s1_s3 = s1 or s3
+    s2_s3 = s2 or s3
+
+  assert s1_s2.len == 7
+  assert s1_s3.len == 8
+  assert s2_s3.len == 6
+
+  for i in s1:
+    assert i in s1_s2
+    assert i in s1_s3
+  for i in s2:
+    assert i in s1_s2
+    assert i in s2_s3
+  for i in s3:
+    assert i in s1_s3
+    assert i in s2_s3
+
+  assert((s1 or s1) == s1)
+  assert((s2 or s1) == s1_s2)
+
+block intersection:
+  let
+    s1_s2 = intersection(s1, s2)
+    s1_s3 = intersection(s1, s3)
+    s2_s3 = s2 and s3
+
+  assert s1_s2.len == 3
+  assert s1_s3.len == 0
+  assert s2_s3.len == 2
+
+  for i in s1_s2:
+    assert i in s1
+    assert i in s2
+  for i in s1_s3:
+    assert i in s1
+    assert i in s3
+  for i in s2_s3:
+    assert i in s2
+    assert i in s3
+
+  assert((s2 and s2) == s2)
+  assert((s3 and s2) == s2_s3)
+
+block symmetricDifference:
+  let
+    s1_s2 = symmetricDifference(s1, s2)
+    s1_s3 = s1 xor s3
+    s2_s3 = s2 xor s3
+
+  assert s1_s2.len == 4
+  assert s1_s3.len == 8
+  assert s2_s3.len == 4
+
+  for i in s1:
+    assert i in s1_s2 xor i in s2
+    assert i in s1_s3 xor i in s3
+  for i in s2:
+    assert i in s1_s2 xor i in s1
+    assert i in s2_s3 xor i in s3
+  for i in s3:
+    assert i in s1_s3 xor i in s1
+    assert i in s2_s3 xor i in s2
+
+  assert((s3 xor s3) == initSet[int]())
+  assert((s3 xor s1) == s1_s3)
+
+block disjoint:
+  assert(not disjoint(s1, s2))
+  assert disjoint(s1, s3)
+  assert(not disjoint(s2, s3))
+  assert(not disjoint(s2, s2))
\ No newline at end of file