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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
|
discard """
outputsub: "finished"
"""
# Test the garbage collector.
import
strutils
type
PNode = ref TNode
TNode {.final.} = object
le, ri: PNode
data: string
TTable {.final.} = object
counter, max: int
data: seq[string]
TBNode {.final.} = object
other: PNode # a completely different tree
data: string
sons: seq[TBNode] # directly embedded!
t: TTable
TCaseKind = enum nkStr, nkWhole, nkList
PCaseNode = ref TCaseNode
TCaseNode {.final.} = object
case kind: TCaseKind
of nkStr: data: string
of nkList: sons: seq[PCaseNode]
else: unused: seq[string]
TIdObj* = object of TObject
id*: int # unique id; use this for comparisons and not the pointers
PIdObj* = ref TIdObj
PIdent* = ref TIdent
TIdent*{.acyclic.} = object of TIdObj
s*: string
next*: PIdent # for hash-table chaining
h*: int # hash value of s
var
flip: int
proc newCaseNode(data: string): PCaseNode =
new(result)
if flip == 0:
result.kind = nkStr
result.data = data
else:
result.kind = nkWhole
result.unused = @["", "abc", "abdc"]
flip = 1 - flip
proc newCaseNode(a, b: PCaseNode): PCaseNode =
new(result)
result.kind = nkList
result.sons = @[a, b]
proc caseTree(lvl: int = 0): PCaseNode =
if lvl == 3: result = newCaseNode("data item")
else: result = newCaseNode(caseTree(lvl+1), caseTree(lvl+1))
proc finalizeBNode(n: TBNode) = writeln(stdout, n.data)
proc finalizeNode(n: PNode) =
assert(n != nil)
write(stdout, "finalizing: ")
if isNil(n.data): writeln(stdout, "nil!")
else: writeln(stdout, n.data)
var
id: int = 1
proc buildTree(depth = 1): PNode =
if depth == 7: return nil
new(result, finalizeNode)
result.le = buildTree(depth+1)
result.ri = buildTree(depth+1)
result.data = $id
inc(id)
proc returnTree(): PNode =
writeln(stdout, "creating id: " & $id)
new(result, finalizeNode)
result.data = $id
new(result.le, finalizeNode)
result.le.data = $id & ".1"
new(result.ri, finalizeNode)
result.ri.data = $id & ".2"
inc(id)
# now create a cycle:
writeln(stdout, "creating id (cyclic): " & $id)
var cycle: PNode
new(cycle, finalizeNode)
cycle.data = $id
cycle.le = cycle
cycle.ri = cycle
inc(id)
#writeln(stdout, "refcount: " & $refcount(cycle))
#writeln(stdout, "refcount le: " & $refcount(cycle.le))
#writeln(stdout, "refcount ri: " & $refcount(cycle.ri))
proc printTree(t: PNode) =
if t == nil: return
writeln(stdout, "printing")
writeln(stdout, t.data)
printTree(t.le)
printTree(t.ri)
proc unsureNew(result: var PNode) =
writeln(stdout, "creating unsure id: " & $id)
new(result, finalizeNode)
result.data = $id
new(result.le, finalizeNode)
result.le.data = $id & ".a"
new(result.ri, finalizeNode)
result.ri.data = $id & ".b"
inc(id)
proc setSons(n: var TBNode) =
n.sons = @[] # free memory of the sons
n.t.data = @[]
var
m: seq[string]
m = @[]
setLen(m, len(n.t.data) * 2)
for i in 0..high(m):
m[i] = "..."
n.t.data = m
proc buildBTree(father: var TBNode) =
father.data = "father"
father.other = nil
father.sons = @[]
for i in 1..10:
write(stdout, "next iteration!\n")
var n: TBNode
n.other = returnTree()
n.data = "B node: " & $i
if i mod 2 == 0: n.sons = @[] # nil and [] need to be handled correctly!
add father.sons, n
father.t.counter = 0
father.t.max = 3
father.t.data = @["ha", "lets", "stress", "it"]
setSons(father)
proc getIdent(identifier: cstring, length: int, h: int): PIdent =
new(result)
result.h = h
result.s = newString(length)
proc main() =
discard getIdent("addr", 4, 0)
discard getIdent("hall", 4, 0)
discard getIdent("echo", 4, 0)
discard getIdent("huch", 4, 0)
var
father: TBNode
for i in 1..1_00:
buildBTree(father)
for i in 1..1_00:
var t = returnTree()
var t2: PNode
unsureNew(t2)
write(stdout, "now building bigger trees: ")
var t2: PNode
for i in 1..100:
t2 = buildTree()
printTree(t2)
write(stdout, "now test sequences of strings:")
var s: seq[string] = @[]
for i in 1..100:
add s, "hohoho" # test reallocation
writeln(stdout, s[89])
write(stdout, "done!\n")
var
father: TBNode
s: string
s = ""
s = ""
writeln(stdout, repr(caseTree()))
father.t.data = @["ha", "lets", "stress", "it"]
father.t.data = @["ha", "lets", "stress", "it"]
var t = buildTree()
write(stdout, repr(t[]))
buildBTree(father)
write(stdout, repr(father))
write(stdout, "starting main...\n")
main()
GC_fullCollect()
# the M&S GC fails with this call and it's unclear why. Definitely something
# we need to fix!
GC_fullCollect()
writeln(stdout, GC_getStatistics())
write(stdout, "finished\n")
|