summary refs log tree commit diff stats
path: root/tests/destructor/topttree.nim
blob: 21b283be007e6b10806fefb684c95ee49422637b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
discard """
  output: '''10.0
60.0
90.0
120.0
10.0
60.0
90.0
120.0
8 8'''
  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 t.data != nil:
    if newVal < t.data[].data:
      insert(t.data[].le, newVal)
    elif t.data[].data < newVal:
      insert(t.data[].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 use(t: opt[Tree]) = discard

proc main =
  var t: opt[Tree]
  insert t, 60.0
  insert t, 90.0
  insert t, 10.0
  insert t, 120.0
  write t
  let copy = t
  write copy
  use t

main()
echo allocCount, " ", deallocCount