summary refs log tree commit diff stats
path: root/tests/destructor/tbintree.nim
diff options
context:
space:
mode:
Diffstat (limited to 'tests/destructor/tbintree.nim')
-rw-r--r--tests/destructor/tbintree.nim97
1 files changed, 97 insertions, 0 deletions
diff --git a/tests/destructor/tbintree.nim b/tests/destructor/tbintree.nim
new file mode 100644
index 000000000..12ba052cf
--- /dev/null
+++ b/tests/destructor/tbintree.nim
@@ -0,0 +1,97 @@
+discard """
+  output: '''10.0
+60.0
+90.0
+120.0
+4 1'''
+  cmd: '''nim c --newruntime $file'''
+"""
+
+import typetraits
+
+type
+  opt[T] = object
+    data: ptr T
+
+var
+  allocCount, deallocCount: int
+
+proc `=destroy`*[T](x: var opt[T]) =
+  if x.data != nil:
+    when not supportsCopyMem(T):
+      `=destroy`(x.data)
+    dealloc(x.data)
+    inc deallocCount
+    x.data = nil
+
+proc `=`*[T](a: var opt[T]; b: opt[T]) =
+  if a.data == b.data: return
+  if a.data != nil:
+    dealloc(a.data)
+    inc deallocCount
+    a.data = nil
+  if b.data != nil:
+    a.data = cast[type(a.data)](alloc(sizeof(T)))
+    inc allocCount
+    when supportsCopyMem(T):
+      copyMem(a.data, b.data, sizeof(T))
+    else:
+      a.data[] = b.data[]
+
+proc `=sink`*[T](a: var opt[T]; b: opt[T]) =
+  if a.data != nil and a.data != b.data:
+    dealloc(a.data)
+    inc deallocCount
+  a.data = b.data
+
+proc createOpt*[T](x: T): opt[T] =
+  result.data = cast[type(result.data)](alloc(sizeof(T)))
+  inc allocCount
+  result.data[] = x
+
+template `[]`[T](x: opt[T]): T =
+  assert x.p != nil, "attempt to read from moved/destroyed value"
+  x.p[]
+
+template `?=`[T](it: untyped; x: opt[T]): bool =
+  template it: untyped {.inject.} = x.data[]
+  if x.data != nil:
+    true
+  else:
+    false
+
+type
+  Tree = object
+    data: float
+    le, ri: opt[Tree]
+
+proc createTree(data: float): Tree =
+  result.data = data
+
+proc insert(t: var opt[Tree]; newVal: float) =
+  if it ?= t:
+    if it.data > newVal:
+      insert(it.le, newVal)
+    elif it.data < newVal:
+      insert(it.ri, newVal)
+    else:
+      discard "already in the tree"
+  else:
+    t = createOpt(Tree(data: newVal))
+
+proc write(t: opt[Tree]) =
+  if it ?= t:
+    write(it.le)
+    write stdout, it.data, "\n"
+    write(it.ri)
+
+proc main =
+  var t: opt[Tree]
+  insert t, 60.0
+  insert t, 90.0
+  insert t, 10.0
+  insert t, 120.0
+  write t
+
+main()
+echo allocCount, " ", deallocCount