summary refs log tree commit diff stats
path: root/tests/destructor/ttuple.nim
diff options
context:
space:
mode:
Diffstat (limited to 'tests/destructor/ttuple.nim')
-rw-r--r--tests/destructor/ttuple.nim130
1 files changed, 130 insertions, 0 deletions
diff --git a/tests/destructor/ttuple.nim b/tests/destructor/ttuple.nim
new file mode 100644
index 000000000..d0ea72c60
--- /dev/null
+++ b/tests/destructor/ttuple.nim
@@ -0,0 +1,130 @@
+
+discard """
+   output: '''5.0 10.0
+=destroy
+=destroy
+'''
+"""
+
+type
+  MyOpt[T] = object
+    case has: bool:
+      of true: val: T
+      of false: nil
+
+  MyVal = object
+    f: ptr float
+
+proc `=destroy`(x: var MyVal) =
+  if x.f != nil:
+    dealloc(x.f)
+
+proc `=sink`(x1: var MyVal, x2: Myval) =
+  if x1.f != x2.f:
+    `=destroy`(x1)
+    x1.f = x2.f
+
+proc `=`(x1: var MyVal, x2: Myval) =
+  if x1.f != x2.f:
+    `=destroy`(x1)
+    x1.f = create(float)
+    x1.f[] = x2.f[]
+
+proc newVal(x: float): MyVal =
+  result.f = create(float)
+  result.f[] = x
+
+template getIt[T, R](self: MyOpt[T], body: untyped, default: R): R =
+  if self.has:
+    template it: untyped {.inject.} = self.val
+    body
+  else:
+    default
+
+proc myproc(h: MyOpt[float]) =
+  let (a, b) = h.getIt((newVal(it), newVal(it * 2)), (newVal(1.0), newVal(1.0)))
+  echo a.f[], " ", b.f[]
+
+let h = MyOpt[float](has: true, val: 5.0)
+myproc(h)
+
+
+#-------------------------------------------------------------
+type
+  MyObject* = object
+    len*: int
+    amount: UncheckedArray[float]
+
+  MyObjPtr* = ptr MyObject
+
+  MyObjContainer* {.byref.} = object
+    size1: int
+    size2: int
+    data: ptr UncheckedArray[MyObjPtr]
+
+ 
+proc size1*(m: MyObjContainer): int {.inline.} = m.size1
+proc size2*(m: MyObjContainer): int {.inline.} = m.size2
+
+proc allocateMyObjPtr(size2: int): MyObjPtr =
+  cast[MyObjPtr](allocShared(sizeof(MyObject) + sizeof(float) * size2.int))
+
+proc `=destroy`*(m: var MyObjContainer) {.inline.} =
+  if m.data != nil:
+    for i in 0..<m.size1:
+      if m.data[i] != nil:
+        deallocShared(m.data[i])
+        m.data[i] = nil
+    deallocShared(m.data)
+    echo "=destroy"
+    m.data = nil
+
+proc `=sink`*(m: var MyObjContainer, m2: MyObjContainer) {.inline.} =
+  if m.data != m2.data:
+    `=destroy`(m)
+  m.size1 = m2.size1
+  m.size2 = m2.size2  
+  m.data = m2.data
+
+
+proc `=`*(m: var MyObjContainer, m2: MyObjContainer) {.error.}
+  ## non copyable
+
+func newMyObjContainer*(size2: Natural): MyObjContainer =
+  result.size2 = size2
+
+proc push(m: var MyObjContainer, cf: MyObjPtr) =
+  ## Add MyObjPtr to MyObjContainer, shallow copy
+  m.size1.inc
+  m.data = cast[ptr UncheckedArray[MyObjPtr]](reallocShared(m.data, m.size1 * sizeof(MyObjPtr)))
+  m.data[m.size1 - 1] = cf
+
+ 
+proc add*(m: var MyObjContainer, amount: float) =
+  assert m.size2 > 0, "MyObjContainer is not initialized, use newMyObjContainer() to initialize object before use"
+  let cf = allocateMyObjPtr(m.size2)
+  for i in 0..<m.size2:
+    cf.amount[i.int] = amount
+
+  m.push(cf)
+
+proc add*(dest: var MyObjContainer, src: sink MyObjContainer) =
+  # merge containers
+
+  for i in 0..<src.size1:
+    dest.push src.data[i]
+    src.data[i] = nil
+
+ 
+proc test = 
+  var cf1 = newMyObjContainer(100)
+  cf1.add(1)
+  cf1.add(2)
+
+  var cf3 = newMyObjContainer(100)
+  cf3.add(2)
+  cf3.add(3)
+
+  cf1.add(cf3)
+
+test()