diff options
Diffstat (limited to 'tests/destructor/ttuple.nim')
-rw-r--r-- | tests/destructor/ttuple.nim | 130 |
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() |