1 //
2 //  Copyright (C) 2011-2019  Nick Gasson
3 //
4 //  This program is free software: you can redistribute it and/or modify
5 //  it under the terms of the GNU General Public License as published by
6 //  the Free Software Foundation, either version 3 of the License, or
7 //  (at your option) any later version.
8 //
9 //  This program is distributed in the hope that it will be useful,
10 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 //  GNU General Public License for more details.
13 //
14 //  You should have received a copy of the GNU General Public License
15 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 //
17 
18 #include "tree.h"
19 #include "util.h"
20 #include "array.h"
21 #include "object.h"
22 #include "common.h"
23 
24 #include <assert.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <ctype.h>
28 
29 static const imask_t has_map[T_LAST_TREE_KIND] = {
30    // T_ENTITY
31    (I_IDENT | I_PORTS | I_GENERICS | I_CONTEXT | I_DECLS | I_STMTS | I_ATTRS),
32 
33    // T_ARCH
34    (I_IDENT | I_IDENT2 | I_DECLS | I_STMTS | I_CONTEXT | I_REF | I_ATTRS),
35 
36    // T_PORT_DECL
37    (I_IDENT | I_VALUE | I_TYPE | I_SUBKIND | I_CLASS | I_ATTRS | I_FLAGS),
38 
39    // T_FCALL
40    (I_IDENT | I_PARAMS | I_TYPE | I_REF | I_ATTRS | I_FLAGS),
41 
42    // T_LITERAL
43    (I_SUBKIND | I_TYPE | I_IVAL | I_DVAL | I_CHARS | I_FLAGS),
44 
45    // T_SIGNAL_DECL
46    (I_IDENT | I_VALUE | I_TYPE | I_NETS | I_ATTRS | I_FLAGS),
47 
48    // T_VAR_DECL
49    (I_IDENT | I_VALUE | I_TYPE | I_ATTRS | I_FLAGS),
50 
51    // T_PROCESS
52    (I_IDENT | I_DECLS | I_STMTS | I_TRIGGERS | I_ATTRS | I_FLAGS),
53 
54    // T_REF
55    (I_IDENT | I_TYPE | I_REF | I_ATTRS | I_FLAGS),
56 
57    // T_WAIT
58    (I_IDENT | I_VALUE | I_DELAY | I_TRIGGERS | I_ATTRS),
59 
60    // T_TYPE_DECL
61    (I_IDENT | I_VALUE | I_TYPE | I_OPS | I_ATTRS),
62 
63    // T_VAR_ASSIGN
64    (I_IDENT | I_VALUE | I_TARGET | I_ATTRS),
65 
66    // T_PACKAGE
67    (I_IDENT | I_DECLS | I_CONTEXT | I_ATTRS),
68 
69    // T_SIGNAL_ASSIGN
70    (I_IDENT | I_TARGET | I_WAVES | I_REJECT | I_ATTRS),
71 
72    // T_QUALIFIED
73    (I_IDENT | I_VALUE | I_TYPE),
74 
75    // T_ENUM_LIT
76    (I_IDENT | I_TYPE | I_POS | I_ATTRS),
77 
78    // T_CONST_DECL
79    (I_IDENT | I_VALUE | I_TYPE | I_ATTRS | I_FLAGS),
80 
81    // T_FUNC_DECL
82    (I_IDENT | I_VALUE | I_PORTS | I_TYPE | I_ATTRS | I_FLAGS),
83 
84    // T_ELAB
85    (I_IDENT | I_DECLS | I_STMTS | I_CONTEXT | I_ATTRS),
86 
87    // T_AGGREGATE
88    (I_TYPE | I_ASSOCS | I_FLAGS),
89 
90    // T_ASSERT
91    (I_IDENT | I_VALUE | I_SEVERITY | I_MESSAGE | I_ATTRS),
92 
93    // T_ATTR_REF
94    (I_NAME | I_VALUE | I_IDENT | I_PARAMS | I_TYPE | I_ATTRS),
95 
96    // T_ARRAY_REF
97    (I_VALUE | I_PARAMS | I_TYPE | I_FLAGS | I_ATTRS),
98 
99    // T_ARRAY_SLICE
100    (I_VALUE | I_TYPE | I_RANGES),
101 
102    // T_INSTANCE
103    (I_IDENT | I_IDENT2 | I_PARAMS | I_GENMAPS | I_REF | I_CLASS | I_SPEC
104     | I_ATTRS),
105 
106    // T_IF
107    (I_IDENT | I_VALUE | I_STMTS | I_ELSES | I_ATTRS),
108 
109    // T_NULL
110    (I_IDENT),
111 
112    // T_PACK_BODY
113    (I_IDENT | I_DECLS | I_CONTEXT | I_ATTRS),
114 
115    // T_FUNC_BODY
116    (I_IDENT | I_DECLS | I_STMTS | I_PORTS | I_TYPE | I_ATTRS | I_FLAGS),
117 
118    // T_RETURN
119    (I_IDENT | I_VALUE | I_ATTRS),
120 
121    // T_CASSIGN
122    (I_IDENT | I_TARGET | I_CONDS | I_FLAGS),
123 
124    // T_WHILE
125    (I_IDENT | I_VALUE | I_STMTS | I_ATTRS),
126 
127    // T_WAVEFORM
128    (I_VALUE | I_DELAY),
129 
130    // T_ALIAS
131    (I_IDENT | I_VALUE | I_TYPE | I_ATTRS),
132 
133    // T_FOR
134    (I_IDENT | I_IDENT2 | I_DECLS | I_STMTS | I_RANGES | I_ATTRS),
135 
136    // T_ATTR_DECL
137    (I_IDENT | I_TYPE | I_ATTRS),
138 
139    // T_ATTR_SPEC
140    (I_IDENT | I_VALUE | I_IDENT2 | I_CLASS | I_ATTRS),
141 
142    // T_PROC_DECL
143    (I_IDENT | I_PORTS | I_TYPE | I_ATTRS),
144 
145    // T_PROC_BODY
146    (I_IDENT | I_DECLS | I_STMTS | I_PORTS | I_TYPE | I_ATTRS),
147 
148    // T_EXIT
149    (I_IDENT | I_VALUE | I_IDENT2 | I_ATTRS),
150 
151    // T_PCALL
152    (I_IDENT | I_IDENT2 | I_PARAMS | I_REF | I_ATTRS),
153 
154    // T_CASE
155    (I_IDENT | I_VALUE | I_ASSOCS | I_ATTRS),
156 
157    // T_BLOCK
158    (I_IDENT | I_DECLS | I_STMTS | I_ATTRS),
159 
160    // T_COND
161    (I_VALUE | I_WAVES | I_REJECT),
162 
163    // T_CONCAT
164    (I_PARAMS | I_TYPE),
165 
166    // T_TYPE_CONV
167    (I_PARAMS | I_TYPE | I_REF | I_FLAGS),
168 
169    // T_SELECT
170    (I_IDENT | I_VALUE | I_ASSOCS | I_FLAGS),
171 
172    // T_COMPONENT
173    (I_IDENT | I_PORTS | I_GENERICS | I_ATTRS),
174 
175    // T_IF_GENERATE
176    (I_IDENT | I_VALUE | I_DECLS | I_STMTS | I_ATTRS),
177 
178    // T_FOR_GENERATE
179    (I_IDENT | I_IDENT2 | I_DECLS | I_STMTS | I_REF | I_RANGES | I_ATTRS),
180 
181    // T_FILE_DECL
182    (I_IDENT | I_VALUE | I_TYPE | I_FILE_MODE | I_ATTRS),
183 
184    // T_OPEN
185    (I_TYPE),
186 
187    // T_FIELD_DECL
188    (I_IDENT | I_TYPE | I_ATTRS),
189 
190    // T_RECORD_REF
191    (I_IDENT | I_VALUE | I_TYPE | I_ATTRS),
192 
193    // T_ALL
194    (I_VALUE | I_TYPE),
195 
196    // T_NEW
197    (I_VALUE | I_TYPE),
198 
199    // T_CASSERT
200    (I_IDENT | I_VALUE | I_SEVERITY | I_MESSAGE | I_FLAGS),
201 
202    // T_CPCALL
203    (I_IDENT | I_IDENT2 | I_PARAMS | I_REF),
204 
205    // T_UNIT_DECL
206    (I_IDENT | I_VALUE | I_TYPE),
207 
208    // T_NEXT
209    (I_IDENT | I_VALUE | I_IDENT2 | I_ATTRS),
210 
211    // T_GENVAR
212    (I_IDENT | I_TYPE | I_ATTRS),
213 
214    // T_PARAM
215    (I_VALUE | I_POS | I_SUBKIND | I_NAME),
216 
217    // T_ASSOC
218    (I_VALUE | I_POS | I_NAME | I_RANGES | I_SUBKIND),
219 
220    // T_USE
221    (I_IDENT | I_IDENT2),
222 
223    // T_HIER
224    (I_IDENT | I_SUBKIND | I_IDENT2 | I_ATTRS),
225 
226    // T_SPEC
227    (I_IDENT | I_IDENT2 | I_VALUE),
228 
229    // T_BINDING
230    (I_PARAMS | I_GENMAPS | I_IDENT | I_IDENT2 | I_CLASS),
231 
232    // T_LIBRARY
233    (I_IDENT),
234 
235    // T_DESIGN_UNIT
236    (I_CONTEXT),
237 
238    // T_CONFIGURATION
239    (I_IDENT | I_IDENT2 | I_DECLS),
240 
241    // T_PROT_BODY
242    (I_IDENT | I_TYPE | I_DECLS | I_ATTRS),
243 
244    // T_CONTEXT
245    (I_CONTEXT | I_IDENT),
246 
247    // T_CTXREF
248    (I_IDENT | I_REF),
249 
250    // T_CONSTRAINT
251    (I_SUBKIND | I_RANGES),
252 
253    // T_BLOCK_CONFIG
254    (I_DECLS | I_IDENT | I_VALUE | I_RANGES),
255 
256    // T_PRAGMA
257    (I_TEXT),
258 };
259 
260 static const char *kind_text_map[T_LAST_TREE_KIND] = {
261    "T_ENTITY",       "T_ARCH",          "T_PORT_DECL",  "T_FCALL",
262    "T_LITERAL",      "T_SIGNAL_DECL",   "T_VAR_DECL",   "T_PROCESS",
263    "T_REF",          "T_WAIT",          "T_TYPE_DECL",  "T_VAR_ASSIGN",
264    "T_PACKAGE",      "T_SIGNAL_ASSIGN", "T_QUALIFIED",  "T_ENUM_LIT",
265    "T_CONST_DECL",   "T_FUNC_DECL",     "T_ELAB",       "T_AGGREGATE",
266    "T_ASSERT",       "T_ATTR_REF",      "T_ARRAY_REF",  "T_ARRAY_SLICE",
267    "T_INSTANCE",     "T_IF",            "T_NULL",       "T_PACK_BODY",
268    "T_FUNC_BODY",    "T_RETURN",        "T_CASSIGN",    "T_WHILE",
269    "T_WAVEFORM",     "T_ALIAS",         "T_FOR",        "T_ATTR_DECL",
270    "T_ATTR_SPEC",    "T_PROC_DECL",     "T_PROC_BODY",  "T_EXIT",
271    "T_PCALL",        "T_CASE",          "T_BLOCK",      "T_COND",
272    "T_CONCAT",       "T_TYPE_CONV",     "T_SELECT",     "T_COMPONENT",
273    "T_IF_GENERATE",  "T_FOR_GENERATE",  "T_FILE_DECL",  "T_OPEN",
274    "T_FIELD_DECL",   "T_RECORD_REF",    "T_ALL",        "T_NEW",
275    "T_CASSERT",      "T_CPCALL",        "T_UNIT_DECL",  "T_NEXT",
276    "T_GENVAR",       "T_PARAM",         "T_ASSOC",      "T_USE",
277    "T_HIER",         "T_SPEC",          "T_BINDING",    "T_LIBRARY",
278    "T_DESIGN_UNIT",  "T_CONFIGURATION", "T_PROT_BODY",  "T_CONTEXT",
279    "T_CTXREF",       "T_CONSTRAINT",    "T_BLOCK_CONFIG", "T_PRAGMA",
280 };
281 
282 static const change_allowed_t change_allowed[] = {
283    { T_REF,         T_FCALL         },
284    { T_REF,         T_PCALL         },
285    { T_ARRAY_REF,   T_FCALL         },
286    { T_FCALL,       T_ARRAY_REF     },
287    { T_FCALL,       T_PCALL         },
288    { T_FCALL,       T_TYPE_CONV     },
289    { T_REF,         T_RECORD_REF    },
290    { T_ARRAY_REF,   T_ARRAY_SLICE   },
291    { T_ASSERT,      T_CASSERT       },
292    { T_DESIGN_UNIT, T_ENTITY        },
293    { T_DESIGN_UNIT, T_PACKAGE       },
294    { T_DESIGN_UNIT, T_PACK_BODY     },
295    { T_DESIGN_UNIT, T_ARCH          },
296    { T_DESIGN_UNIT, T_CONFIGURATION },
297    { T_DESIGN_UNIT, T_CONTEXT       },
298    { T_FUNC_DECL,   T_FUNC_BODY     },
299    { T_PROC_DECL,   T_PROC_BODY     },
300    { T_REF,         T_ARRAY_SLICE   },
301    { T_FCALL,       T_CPCALL        },
302    { T_REF,         T_CPCALL        },
303    { T_ATTR_REF,    T_ARRAY_REF     },
304    { -1,            -1              }
305 };
306 
307 struct tree {
308    object_t object;
309 };
310 
311 static const tree_kind_t stmt_kinds[] = {
312    T_PROCESS, T_WAIT,        T_VAR_ASSIGN,   T_SIGNAL_ASSIGN,
313    T_ASSERT,  T_INSTANCE,    T_IF,           T_NULL,
314    T_RETURN,  T_CASSIGN,     T_WHILE,        T_FOR,
315    T_EXIT,    T_PCALL,       T_CASE,         T_BLOCK,
316    T_SELECT,  T_IF_GENERATE, T_FOR_GENERATE, T_CPCALL,
317    T_CASSERT, T_NEXT,        T_PRAGMA,
318 };
319 
320 static tree_kind_t expr_kinds[] = {
321    T_FCALL,     T_LITERAL,   T_REF,       T_QUALIFIED,
322    T_AGGREGATE, T_ATTR_REF,  T_ARRAY_REF, T_ARRAY_SLICE,
323    T_CONCAT,    T_TYPE_CONV, T_OPEN,      T_RECORD_REF,
324    T_ALL,       T_NEW
325 };
326 
327 static tree_kind_t decl_kinds[] = {
328    T_PORT_DECL,  T_SIGNAL_DECL, T_VAR_DECL,   T_TYPE_DECL,
329    T_CONST_DECL, T_FUNC_DECL,   T_FUNC_BODY,  T_ALIAS,
330    T_ATTR_DECL,  T_ATTR_SPEC,   T_PROC_DECL,  T_PROC_BODY,
331    T_COMPONENT,  T_FILE_DECL,   T_FIELD_DECL, T_UNIT_DECL,
332    T_GENVAR,     T_HIER,        T_SPEC,       T_BINDING,
333    T_USE,        T_PROT_BODY,   T_BLOCK_CONFIG
334 };
335 
336 object_class_t tree_object = {
337    .name           = "tree",
338    .change_allowed = change_allowed,
339    .has_map        = has_map,
340    .kind_text_map  = kind_text_map,
341    .tag            = OBJECT_TAG_TREE,
342    .last_kind      = T_LAST_TREE_KIND,
343    .gc_roots       = { T_ARCH, T_ENTITY, T_PACKAGE, T_ELAB, T_PACK_BODY,
344                        T_CONTEXT },
345    .gc_num_roots   = 5
346 };
347 
tree_kind_in(tree_t t,const tree_kind_t * list,size_t len)348 static bool tree_kind_in(tree_t t, const tree_kind_t *list, size_t len)
349 {
350    for (size_t i = 0; i < len; i++) {
351       if (t->object.kind == list[i])
352          return true;
353    }
354 
355    return false;
356 }
357 
tree_assert_kind(tree_t t,const tree_kind_t * list,size_t len,const char * what)358 static void tree_assert_kind(tree_t t, const tree_kind_t *list, size_t len,
359                              const char *what)
360 {
361    LCOV_EXCL_START
362    if (unlikely(!tree_kind_in(t, list, len)))
363       fatal_trace("tree kind %s is not %s",
364                   tree_kind_str(t->object.kind), what);
365    LCOV_EXCL_STOP
366 }
367 
tree_assert_stmt(tree_t t)368 static void tree_assert_stmt(tree_t t)
369 {
370    tree_assert_kind(t, stmt_kinds, ARRAY_LEN(stmt_kinds), "a statement");
371 }
372 
tree_assert_expr(tree_t t)373 static void tree_assert_expr(tree_t t)
374 {
375    tree_assert_kind(t, expr_kinds, ARRAY_LEN(expr_kinds), "an expression");
376 }
377 
tree_assert_decl(tree_t t)378 static void tree_assert_decl(tree_t t)
379 {
380    tree_assert_kind(t, decl_kinds, ARRAY_LEN(decl_kinds), "a declaration");
381 }
382 
tree_new(tree_kind_t kind)383 tree_t tree_new(tree_kind_t kind)
384 {
385    return (tree_t)object_new(&tree_object, kind);
386 }
387 
tree_gc(void)388 void tree_gc(void)
389 {
390    object_gc();
391 }
392 
tree_loc(tree_t t)393 const loc_t *tree_loc(tree_t t)
394 {
395    assert(t != NULL);
396 
397    return &t->object.loc;
398 }
399 
tree_set_loc(tree_t t,const loc_t * loc)400 void tree_set_loc(tree_t t, const loc_t *loc)
401 {
402    assert(t != NULL);
403    assert(loc != NULL);
404 
405    t->object.loc = *loc;
406 }
407 
tree_ident(tree_t t)408 ident_t tree_ident(tree_t t)
409 {
410    item_t *item = lookup_item(&tree_object, t, I_IDENT);
411    assert(item->ident != NULL);
412    return item->ident;
413 }
414 
tree_has_ident(tree_t t)415 bool tree_has_ident(tree_t t)
416 {
417    return lookup_item(&tree_object, t, I_IDENT)->ident != NULL;
418 }
419 
tree_set_ident(tree_t t,ident_t i)420 void tree_set_ident(tree_t t, ident_t i)
421 {
422    lookup_item(&tree_object, t, I_IDENT)->ident = i;
423 }
424 
tree_ident2(tree_t t)425 ident_t tree_ident2(tree_t t)
426 {
427    item_t *item = lookup_item(&tree_object, t, I_IDENT2);
428    assert(item->ident != NULL);
429    return item->ident;
430 }
431 
tree_set_ident2(tree_t t,ident_t i)432 void tree_set_ident2(tree_t t, ident_t i)
433 {
434    lookup_item(&tree_object, t, I_IDENT2)->ident = i;
435 }
436 
tree_has_ident2(tree_t t)437 bool tree_has_ident2(tree_t t)
438 {
439    return lookup_item(&tree_object, t, I_IDENT2)->ident != NULL;
440 }
441 
tree_kind(tree_t t)442 tree_kind_t tree_kind(tree_t t)
443 {
444    assert(t != NULL);
445    return t->object.kind;
446 }
447 
tree_change_kind(tree_t t,tree_kind_t kind)448 void tree_change_kind(tree_t t, tree_kind_t kind)
449 {
450    object_change_kind(&tree_object, &(t->object), kind);
451 }
452 
tree_ports(tree_t t)453 unsigned tree_ports(tree_t t)
454 {
455    return lookup_item(&tree_object, t, I_PORTS)->tree_array.count;
456 }
457 
tree_port(tree_t t,unsigned n)458 tree_t tree_port(tree_t t, unsigned n)
459 {
460    item_t *item = lookup_item(&tree_object, t, I_PORTS);
461    return tree_array_nth(&(item->tree_array), n);
462 }
463 
tree_add_port(tree_t t,tree_t d)464 void tree_add_port(tree_t t, tree_t d)
465 {
466    tree_assert_decl(d);
467    tree_array_add(&(lookup_item(&tree_object, t, I_PORTS)->tree_array), d);
468 }
469 
tree_subkind(tree_t t)470 unsigned tree_subkind(tree_t t)
471 {
472    item_t *item = lookup_item(&tree_object, t, I_SUBKIND);
473    return item->ival;
474 }
475 
tree_set_subkind(tree_t t,unsigned sub)476 void tree_set_subkind(tree_t t, unsigned sub)
477 {
478    lookup_item(&tree_object, t, I_SUBKIND)->ival = sub;
479 }
480 
tree_generics(tree_t t)481 unsigned tree_generics(tree_t t)
482 {
483    return lookup_item(&tree_object, t, I_GENERICS)->tree_array.count;
484 }
485 
tree_generic(tree_t t,unsigned n)486 tree_t tree_generic(tree_t t, unsigned n)
487 {
488    item_t *item = lookup_item(&tree_object, t, I_GENERICS);
489    return tree_array_nth(&(item->tree_array), n);
490 }
491 
tree_add_generic(tree_t t,tree_t d)492 void tree_add_generic(tree_t t, tree_t d)
493 {
494    tree_assert_decl(d);
495    tree_array_add(&(lookup_item(&tree_object, t, I_GENERICS)->tree_array), d);
496 }
497 
tree_type(tree_t t)498 type_t tree_type(tree_t t)
499 {
500    item_t *item = lookup_item(&tree_object, t, I_TYPE);
501    assert(item->type != NULL);
502    return item->type;
503 }
504 
tree_set_type(tree_t t,type_t ty)505 void tree_set_type(tree_t t, type_t ty)
506 {
507    lookup_item(&tree_object, t, I_TYPE)->type = ty;
508 }
509 
tree_has_type(tree_t t)510 bool tree_has_type(tree_t t)
511 {
512    return lookup_item(&tree_object, t, I_TYPE)->type != NULL;
513 }
514 
tree_params(tree_t t)515 unsigned tree_params(tree_t t)
516 {
517    return lookup_item(&tree_object, t, I_PARAMS)->tree_array.count;
518 }
519 
tree_param(tree_t t,unsigned n)520 tree_t tree_param(tree_t t, unsigned n)
521 {
522    item_t *item = lookup_item(&tree_object, t, I_PARAMS);
523    return tree_array_nth(&(item->tree_array), n);
524 }
525 
tree_add_param(tree_t t,tree_t e)526 void tree_add_param(tree_t t, tree_t e)
527 {
528    assert(tree_kind(e) == T_PARAM);
529    tree_assert_expr(tree_value(e));
530 
531    tree_array_t *array = &(lookup_item(&tree_object, t, I_PARAMS)->tree_array);
532 
533    if (tree_subkind(e) == P_POS)
534       tree_set_pos(e, array->count);
535 
536    tree_array_add(array, e);
537 }
538 
tree_genmaps(tree_t t)539 unsigned tree_genmaps(tree_t t)
540 {
541    return lookup_item(&tree_object, t, I_GENMAPS)->tree_array.count;
542 }
543 
tree_genmap(tree_t t,unsigned n)544 tree_t tree_genmap(tree_t t, unsigned n)
545 {
546    item_t *item = lookup_item(&tree_object, t, I_GENMAPS);
547    return tree_array_nth(&(item->tree_array), n);
548 }
549 
tree_add_genmap(tree_t t,tree_t e)550 void tree_add_genmap(tree_t t, tree_t e)
551 {
552    tree_assert_expr(tree_value(e));
553 
554    tree_array_t *array = &(lookup_item(&tree_object, t, I_GENMAPS)->tree_array);
555 
556    if (tree_subkind(e) == P_POS)
557       tree_set_pos(e, array->count);
558 
559    tree_array_add(&(lookup_item(&tree_object, t, I_GENMAPS)->tree_array), e);
560 }
561 
tree_ival(tree_t t)562 int64_t tree_ival(tree_t t)
563 {
564    assert((t->object.kind == T_LITERAL) && (tree_subkind(t) == L_INT));
565    return lookup_item(&tree_object, t, I_IVAL)->ival;
566 }
567 
tree_set_ival(tree_t t,int64_t i)568 void tree_set_ival(tree_t t, int64_t i)
569 {
570    assert((t->object.kind == T_LITERAL) && (tree_subkind(t) == L_INT));
571    lookup_item(&tree_object, t, I_IVAL)->ival = i;
572 }
573 
tree_dval(tree_t t)574 double tree_dval(tree_t t)
575 {
576    assert((t->object.kind == T_LITERAL) && (tree_subkind(t) == L_REAL));
577    return lookup_item(&tree_object, t, I_DVAL)->dval;
578 }
579 
tree_set_dval(tree_t t,double d)580 void tree_set_dval(tree_t t, double d)
581 {
582    assert((t->object.kind == T_LITERAL) && (tree_subkind(t) == L_REAL));
583    lookup_item(&tree_object, t, I_DVAL)->dval = d;
584 }
585 
tree_flags(tree_t t)586 tree_flags_t tree_flags(tree_t t)
587 {
588    return lookup_item(&tree_object, t, I_FLAGS)->ival;
589 }
590 
tree_set_flag(tree_t t,tree_flags_t mask)591 void tree_set_flag(tree_t t, tree_flags_t mask)
592 {
593    lookup_item(&tree_object, t, I_FLAGS)->ival |= mask;
594 }
595 
tree_chars(tree_t t)596 unsigned tree_chars(tree_t t)
597 {
598    assert((t->object.kind == T_LITERAL) && (tree_subkind(t) == L_STRING));
599    return lookup_item(&tree_object, t, I_CHARS)->ident_array.count;
600 }
601 
tree_char(tree_t t,unsigned n)602 tree_t tree_char(tree_t t, unsigned n)
603 {
604    assert((t->object.kind == T_LITERAL) && (tree_subkind(t) == L_STRING));
605    item_t *item = lookup_item(&tree_object, t, I_CHARS);
606    return tree_array_nth(&(item->tree_array), n);
607 }
608 
tree_add_char(tree_t t,tree_t ref)609 void tree_add_char(tree_t t, tree_t ref)
610 {
611    assert((t->object.kind == T_LITERAL) && (tree_subkind(t) == L_STRING));
612    tree_array_add(&(lookup_item(&tree_object, t, I_CHARS)->tree_array), ref);
613 }
614 
tree_has_value(tree_t t)615 bool tree_has_value(tree_t t)
616 {
617    return lookup_item(&tree_object, t, I_VALUE)->tree != NULL;
618 }
619 
tree_value(tree_t t)620 tree_t tree_value(tree_t t)
621 {
622    item_t *item = lookup_item(&tree_object, t, I_VALUE);
623    assert(item->tree != NULL);
624    return item->tree;
625 }
626 
tree_set_value(tree_t t,tree_t v)627 void tree_set_value(tree_t t, tree_t v)
628 {
629    if ((v != NULL) && (t->object.kind != T_ASSOC) && (t->object.kind != T_SPEC))
630       tree_assert_expr(v);
631    lookup_item(&tree_object, t, I_VALUE)->tree = v;
632 }
633 
tree_decls(tree_t t)634 unsigned tree_decls(tree_t t)
635 {
636    return lookup_item(&tree_object, t, I_DECLS)->tree_array.count;
637 }
638 
tree_decl(tree_t t,unsigned n)639 tree_t tree_decl(tree_t t, unsigned n)
640 {
641    item_t *item = lookup_item(&tree_object, t, I_DECLS);
642    return tree_array_nth(&(item->tree_array), n);
643 }
644 
tree_add_decl(tree_t t,tree_t d)645 void tree_add_decl(tree_t t, tree_t d)
646 {
647    tree_assert_decl(d);
648    tree_array_add(&(lookup_item(&tree_object, t, I_DECLS)->tree_array), d);
649 }
650 
tree_stmts(tree_t t)651 unsigned tree_stmts(tree_t t)
652 {
653    return lookup_item(&tree_object, t, I_STMTS)->tree_array.count;
654 }
655 
tree_stmt(tree_t t,unsigned n)656 tree_t tree_stmt(tree_t t, unsigned n)
657 {
658    item_t *item = lookup_item(&tree_object, t, I_STMTS);
659    return tree_array_nth(&(item->tree_array), n);
660 }
661 
tree_add_stmt(tree_t t,tree_t s)662 void tree_add_stmt(tree_t t, tree_t s)
663 {
664    tree_assert_stmt(s);
665    tree_array_add(&(lookup_item(&tree_object, t, I_STMTS)->tree_array), s);
666 }
667 
tree_waveforms(tree_t t)668 unsigned tree_waveforms(tree_t t)
669 {
670    return lookup_item(&tree_object, t, I_WAVES)->tree_array.count;
671 }
672 
tree_waveform(tree_t t,unsigned n)673 tree_t tree_waveform(tree_t t, unsigned n)
674 {
675    item_t *item = lookup_item(&tree_object, t, I_WAVES);
676    return tree_array_nth(&(item->tree_array), n);
677 }
678 
tree_add_waveform(tree_t t,tree_t w)679 void tree_add_waveform(tree_t t, tree_t w)
680 {
681    assert(w->object.kind == T_WAVEFORM);
682    tree_array_add(&(lookup_item(&tree_object, t, I_WAVES)->tree_array), w);
683 }
684 
tree_else_stmts(tree_t t)685 unsigned tree_else_stmts(tree_t t)
686 {
687    return lookup_item(&tree_object, t, I_ELSES)->tree_array.count;
688 }
689 
tree_else_stmt(tree_t t,unsigned n)690 tree_t tree_else_stmt(tree_t t, unsigned n)
691 {
692    item_t *item = lookup_item(&tree_object, t, I_ELSES);
693    return tree_array_nth(&(item->tree_array), n);
694 }
695 
tree_add_else_stmt(tree_t t,tree_t s)696 void tree_add_else_stmt(tree_t t, tree_t s)
697 {
698    tree_assert_stmt(s);
699    tree_array_add(&(lookup_item(&tree_object, t, I_ELSES)->tree_array), s);
700 }
701 
tree_conds(tree_t t)702 unsigned tree_conds(tree_t t)
703 {
704    return lookup_item(&tree_object, t, I_CONDS)->tree_array.count;
705 }
706 
tree_cond(tree_t t,unsigned n)707 tree_t tree_cond(tree_t t, unsigned n)
708 {
709    item_t *item = lookup_item(&tree_object, t, I_CONDS);
710    return tree_array_nth(&(item->tree_array), n);
711 }
712 
tree_add_cond(tree_t t,tree_t c)713 void tree_add_cond(tree_t t, tree_t c)
714 {
715    assert(c->object.kind == T_COND);
716    tree_array_add(&(lookup_item(&tree_object, t, I_CONDS)->tree_array), c);
717 }
718 
tree_has_delay(tree_t t)719 bool tree_has_delay(tree_t t)
720 {
721    return lookup_item(&tree_object, t, I_DELAY)->tree != NULL;
722 }
723 
tree_delay(tree_t t)724 tree_t tree_delay(tree_t t)
725 {
726    item_t *item = lookup_item(&tree_object, t, I_DELAY);
727    assert(item->tree != NULL);
728    return item->tree;
729 }
730 
tree_set_delay(tree_t t,tree_t d)731 void tree_set_delay(tree_t t, tree_t d)
732 {
733    tree_assert_expr(d);
734    lookup_item(&tree_object, t, I_DELAY)->tree = d;
735 }
736 
tree_triggers(tree_t t)737 unsigned tree_triggers(tree_t t)
738 {
739    return lookup_item(&tree_object, t, I_TRIGGERS)->tree_array.count;
740 }
741 
tree_trigger(tree_t t,unsigned n)742 tree_t tree_trigger(tree_t t, unsigned n)
743 {
744    item_t *item = lookup_item(&tree_object, t, I_TRIGGERS);
745    return tree_array_nth(&(item->tree_array), n);
746 }
747 
tree_add_trigger(tree_t t,tree_t s)748 void tree_add_trigger(tree_t t, tree_t s)
749 {
750    tree_assert_expr(s);
751    tree_array_add(&(lookup_item(&tree_object, t, I_TRIGGERS)->tree_array), s);
752 }
753 
tree_ops(tree_t t)754 unsigned tree_ops(tree_t t)
755 {
756    return lookup_item(&tree_object, t, I_OPS)->tree_array.count;
757 }
758 
tree_op(tree_t t,unsigned n)759 tree_t tree_op(tree_t t, unsigned n)
760 {
761    return tree_array_nth(&(lookup_item(&tree_object, t, I_OPS)->tree_array), n);
762 }
763 
tree_add_op(tree_t t,tree_t s)764 void tree_add_op(tree_t t, tree_t s)
765 {
766    assert((s->object.kind == T_FUNC_DECL) || (s->object.kind == T_PROC_DECL));
767    tree_array_add(&(lookup_item(&tree_object, t, I_OPS)->tree_array), s);
768 }
769 
tree_target(tree_t t)770 tree_t tree_target(tree_t t)
771 {
772    item_t *item = lookup_item(&tree_object, t, I_TARGET);
773    assert(item->tree != NULL);
774    return item->tree;
775 }
776 
tree_set_target(tree_t t,tree_t lhs)777 void tree_set_target(tree_t t, tree_t lhs)
778 {
779    lookup_item(&tree_object, t, I_TARGET)->tree = lhs;
780 }
781 
tree_ref(tree_t t)782 tree_t tree_ref(tree_t t)
783 {
784    item_t *item = lookup_item(&tree_object, t, I_REF);
785    assert(item->tree != NULL);
786    return item->tree;
787 }
788 
tree_has_ref(tree_t t)789 bool tree_has_ref(tree_t t)
790 {
791    return lookup_item(&tree_object, t, I_REF)->tree != NULL;
792 }
793 
tree_set_ref(tree_t t,tree_t decl)794 void tree_set_ref(tree_t t, tree_t decl)
795 {
796    lookup_item(&tree_object, t, I_REF)->tree = decl;
797 }
798 
tree_spec(tree_t t)799 tree_t tree_spec(tree_t t)
800 {
801    item_t *item = lookup_item(&tree_object, t, I_SPEC);
802    assert(item->tree != NULL);
803    return item->tree;
804 }
805 
tree_has_spec(tree_t t)806 bool tree_has_spec(tree_t t)
807 {
808    return lookup_item(&tree_object, t, I_SPEC)->tree != NULL;
809 }
810 
tree_set_spec(tree_t t,tree_t s)811 void tree_set_spec(tree_t t, tree_t s)
812 {
813    lookup_item(&tree_object, t, I_SPEC)->tree = s;
814 }
815 
tree_contexts(tree_t t)816 unsigned tree_contexts(tree_t t)
817 {
818    return lookup_item(&tree_object, t, I_CONTEXT)->tree_array.count;
819 }
820 
tree_context(tree_t t,unsigned n)821 tree_t tree_context(tree_t t, unsigned n)
822 {
823    item_t *item = lookup_item(&tree_object, t, I_CONTEXT);
824    return tree_array_nth(&(item->tree_array), n);
825 }
826 
tree_add_context(tree_t t,tree_t ctx)827 void tree_add_context(tree_t t, tree_t ctx)
828 {
829    assert(ctx->object.kind == T_USE || ctx->object.kind == T_LIBRARY
830           || ctx->object.kind == T_CTXREF || ctx->object.kind == T_PRAGMA);
831    tree_array_add(&(lookup_item(&tree_object, t, I_CONTEXT)->tree_array), ctx);
832 }
833 
tree_assocs(tree_t t)834 unsigned tree_assocs(tree_t t)
835 {
836    return lookup_item(&tree_object, t, I_ASSOCS)->tree_array.count;
837 }
838 
tree_assoc(tree_t t,unsigned n)839 tree_t tree_assoc(tree_t t, unsigned n)
840 {
841    item_t *item = lookup_item(&tree_object, t, I_ASSOCS);
842    return tree_array_nth(&(item->tree_array), n);
843 }
844 
tree_add_assoc(tree_t t,tree_t a)845 void tree_add_assoc(tree_t t, tree_t a)
846 {
847    assert(a->object.kind == T_ASSOC);
848 
849    tree_array_t *array = &(lookup_item(&tree_object, t, I_ASSOCS)->tree_array);
850 
851    if (tree_subkind(a) == A_POS)
852       tree_set_pos(a, array->count);
853 
854    tree_array_add(array, a);
855 }
856 
tree_nets(tree_t t)857 unsigned tree_nets(tree_t t)
858 {
859    return lookup_item(&tree_object, t, I_NETS)->netid_array.count;
860 }
861 
tree_net(tree_t t,unsigned n)862 netid_t tree_net(tree_t t, unsigned n)
863 {
864    item_t *item = lookup_item(&tree_object, t, I_NETS);
865    netid_t nid = netid_array_nth(&(item->netid_array), n);
866    assert(nid != NETID_INVALID);
867    return nid;
868 }
869 
tree_add_net(tree_t t,netid_t n)870 void tree_add_net(tree_t t, netid_t n)
871 {
872    netid_array_add(&(lookup_item(&tree_object, t, I_NETS)->netid_array), n);
873 }
874 
tree_change_net(tree_t t,unsigned n,netid_t i)875 void tree_change_net(tree_t t, unsigned n, netid_t i)
876 {
877    item_t *item = lookup_item(&tree_object, t, I_NETS);
878 
879    if (n >= item->netid_array.count)
880       netid_array_resize(&(item->netid_array), n + 1, 0xff);
881 
882    item->netid_array.items[n] = i;
883 }
884 
tree_severity(tree_t t)885 tree_t tree_severity(tree_t t)
886 {
887    item_t *item = lookup_item(&tree_object, t, I_SEVERITY);
888    assert(item->tree != NULL);
889    return item->tree;
890 }
891 
tree_set_severity(tree_t t,tree_t s)892 void tree_set_severity(tree_t t, tree_t s)
893 {
894    tree_assert_expr(s);
895    lookup_item(&tree_object, t, I_SEVERITY)->tree = s;
896 }
897 
tree_message(tree_t t)898 tree_t tree_message(tree_t t)
899 {
900    item_t *item = lookup_item(&tree_object, t, I_MESSAGE);
901    assert(item->tree != NULL);
902    return item->tree;
903 }
904 
tree_has_message(tree_t t)905 bool tree_has_message(tree_t t)
906 {
907    return lookup_item(&tree_object, t, I_MESSAGE)->tree != NULL;
908 }
909 
tree_set_message(tree_t t,tree_t m)910 void tree_set_message(tree_t t, tree_t m)
911 {
912    tree_assert_expr(m);
913    lookup_item(&tree_object, t, I_MESSAGE)->tree = m;
914 }
915 
tree_add_range(tree_t t,range_t r)916 void tree_add_range(tree_t t, range_t r)
917 {
918    range_array_add(&(lookup_item(&tree_object, t, I_RANGES)->range_array), r);
919 }
920 
tree_range(tree_t t,unsigned n)921 range_t tree_range(tree_t t, unsigned n)
922 {
923    item_t *item = lookup_item(&tree_object, t, I_RANGES);
924    return range_array_nth(&(item->range_array), n);
925 }
926 
tree_ranges(tree_t t)927 unsigned tree_ranges(tree_t t)
928 {
929    return lookup_item(&tree_object, t, I_RANGES)->range_array.count;
930 }
931 
tree_change_range(tree_t t,unsigned n,range_t r)932 void tree_change_range(tree_t t, unsigned n, range_t r)
933 {
934    item_t *item = lookup_item(&tree_object, t, I_RANGES);
935    assert(n < item->range_array.count);
936    item->range_array.items[n] = r;
937 }
938 
tree_text(tree_t t)939 char *tree_text(tree_t t)
940 {
941    return lookup_item(&tree_object, t, I_TEXT)->text;
942 }
943 
tree_set_text(tree_t t,const char * text)944 void tree_set_text(tree_t t, const char *text)
945 {
946    lookup_item(&tree_object, t, I_TEXT)->text = xstrdup(text);
947 }
948 
tree_pos(tree_t t)949 unsigned tree_pos(tree_t t)
950 {
951    return lookup_item(&tree_object, t, I_POS)->ival;
952 }
953 
tree_set_pos(tree_t t,unsigned pos)954 void tree_set_pos(tree_t t, unsigned pos)
955 {
956    lookup_item(&tree_object, t, I_POS)->ival = pos;
957 }
958 
tree_class(tree_t t)959 class_t tree_class(tree_t t)
960 {
961    return lookup_item(&tree_object, t, I_CLASS)->ival;
962 }
963 
tree_set_class(tree_t t,class_t c)964 void tree_set_class(tree_t t, class_t c)
965 {
966    lookup_item(&tree_object, t, I_CLASS)->ival = c;
967 }
968 
tree_reject(tree_t t)969 tree_t tree_reject(tree_t t)
970 {
971    item_t *item = lookup_item(&tree_object, t, I_REJECT);
972    assert(item->tree != NULL);
973    return item->tree;
974 }
975 
tree_set_reject(tree_t t,tree_t r)976 void tree_set_reject(tree_t t, tree_t r)
977 {
978    tree_assert_expr(r);
979    lookup_item(&tree_object, t, I_REJECT)->tree = r;
980 }
981 
tree_has_reject(tree_t t)982 bool tree_has_reject(tree_t t)
983 {
984    return lookup_item(&tree_object, t, I_REJECT)->tree != NULL;
985 }
986 
tree_name(tree_t t)987 tree_t tree_name(tree_t t)
988 {
989    item_t *item = lookup_item(&tree_object, t, I_NAME);
990    assert(item->tree != NULL);
991    return item->tree;
992 }
993 
tree_set_name(tree_t t,tree_t n)994 void tree_set_name(tree_t t, tree_t n)
995 {
996    tree_assert_expr(n);
997    lookup_item(&tree_object, t, I_NAME)->tree = n;
998 }
999 
tree_file_mode(tree_t t)1000 tree_t tree_file_mode(tree_t t)
1001 {
1002    return lookup_item(&tree_object, t, I_FILE_MODE)->tree;
1003 }
1004 
tree_set_file_mode(tree_t t,tree_t m)1005 void tree_set_file_mode(tree_t t, tree_t m)
1006 {
1007    lookup_item(&tree_object, t, I_FILE_MODE)->tree = m;
1008 }
1009 
tree_visit(tree_t t,tree_visit_fn_t fn,void * context)1010 unsigned tree_visit(tree_t t, tree_visit_fn_t fn, void *context)
1011 {
1012    assert(t != NULL);
1013 
1014    object_visit_ctx_t ctx = {
1015       .count      = 0,
1016       .postorder  = fn,
1017       .preorder   = NULL,
1018       .context    = context,
1019       .kind       = T_LAST_TREE_KIND,
1020       .generation = object_next_generation(),
1021       .deep       = false
1022    };
1023 
1024    object_visit(&(t->object), &ctx);
1025 
1026    return ctx.count;
1027 }
1028 
tree_visit_only(tree_t t,tree_visit_fn_t fn,void * context,tree_kind_t kind)1029 unsigned tree_visit_only(tree_t t, tree_visit_fn_t fn,
1030                          void *context, tree_kind_t kind)
1031 {
1032    assert(t != NULL);
1033 
1034    object_visit_ctx_t ctx = {
1035       .count      = 0,
1036       .postorder  = fn,
1037       .preorder   = NULL,
1038       .context    = context,
1039       .kind       = kind,
1040       .generation = object_next_generation(),
1041       .deep       = false
1042    };
1043 
1044    object_visit(&(t->object), &ctx);
1045 
1046    return ctx.count;
1047 }
1048 
tree_write_begin(fbuf_t * f)1049 tree_wr_ctx_t tree_write_begin(fbuf_t *f)
1050 {
1051    return (tree_wr_ctx_t)object_write_begin(f);
1052 }
1053 
tree_write_end(tree_wr_ctx_t ctx)1054 void tree_write_end(tree_wr_ctx_t ctx)
1055 {
1056    object_write_end((object_wr_ctx_t *)ctx);
1057 }
1058 
tree_write(tree_t t,tree_wr_ctx_t ctx)1059 void tree_write(tree_t t, tree_wr_ctx_t ctx)
1060 {
1061    object_write(&(t->object), (object_wr_ctx_t *)ctx);
1062 }
1063 
tree_read(tree_rd_ctx_t ctx)1064 tree_t tree_read(tree_rd_ctx_t ctx)
1065 {
1066    return (tree_t)object_read((object_rd_ctx_t *)ctx, OBJECT_TAG_TREE);
1067 }
1068 
tree_read_begin(fbuf_t * f,const char * fname)1069 tree_rd_ctx_t tree_read_begin(fbuf_t *f, const char *fname)
1070 {
1071    return (tree_rd_ctx_t)object_read_begin(f, fname);
1072 }
1073 
tree_read_end(tree_rd_ctx_t ctx)1074 void tree_read_end(tree_rd_ctx_t ctx)
1075 {
1076    object_read_end((object_rd_ctx_t *)ctx);
1077 }
1078 
tree_find_attr(tree_t t,ident_t name,attr_kind_t kind)1079 static attr_t *tree_find_attr(tree_t t, ident_t name, attr_kind_t kind)
1080 {
1081    assert(t != NULL);
1082    assert(name != NULL);
1083 
1084    item_t *item = lookup_item(&tree_object, t, I_ATTRS);
1085    for (unsigned i = 0; i < item->attrs.num; i++) {
1086       if ((item->attrs.table[i].kind == kind)
1087           && (item->attrs.table[i].name == name))
1088          return &(item->attrs.table[i]);
1089    }
1090 
1091    return NULL;
1092 }
1093 
tree_add_attr(tree_t t,ident_t name,attr_kind_t kind)1094 static attr_t *tree_add_attr(tree_t t, ident_t name, attr_kind_t kind)
1095 {
1096    assert(t != NULL);
1097    assert(name != NULL);
1098 
1099    attr_t *a = tree_find_attr(t, name, kind);
1100    if (a != NULL)
1101       return a;
1102 
1103    item_t *item = lookup_item(&tree_object, t, I_ATTRS);
1104 
1105    if (item->attrs.table == NULL) {
1106       item->attrs.alloc = 8;
1107       item->attrs.table = xmalloc(sizeof(attr_t) * item->attrs.alloc);
1108    }
1109    else if (item->attrs.alloc == item->attrs.num) {
1110       item->attrs.alloc *= 2;
1111       item->attrs.table = xrealloc(item->attrs.table,
1112                                    sizeof(attr_t) * item->attrs.alloc);
1113    }
1114 
1115    unsigned i = item->attrs.num++;
1116    item->attrs.table[i].kind = kind;
1117    item->attrs.table[i].name = name;
1118 
1119    return &(item->attrs.table[i]);
1120 }
1121 
tree_remove_attr(tree_t t,ident_t name)1122 void tree_remove_attr(tree_t t, ident_t name)
1123 {
1124    assert(t != NULL);
1125    assert(name != NULL);
1126 
1127    item_t *item = lookup_item(&tree_object, t, I_ATTRS);
1128 
1129    unsigned i;
1130    for (i = 0; (i < item->attrs.num)
1131            && (item->attrs.table[i].name != name); i++)
1132       ;
1133 
1134    if (i == item->attrs.num)
1135       return;
1136 
1137    for (; i + 1 < item->attrs.num; i++)
1138       item->attrs.table[i] = item->attrs.table[i + 1];
1139 
1140    item->attrs.num--;
1141 }
1142 
tree_add_attr_str(tree_t t,ident_t name,ident_t str)1143 void tree_add_attr_str(tree_t t, ident_t name, ident_t str)
1144 {
1145    tree_add_attr(t, name, A_STRING)->sval = str;
1146 }
1147 
tree_attr_str(tree_t t,ident_t name)1148 ident_t tree_attr_str(tree_t t, ident_t name)
1149 {
1150    attr_t *a = tree_find_attr(t, name, A_STRING);
1151    return a ? a->sval : NULL;
1152 }
1153 
tree_add_attr_int(tree_t t,ident_t name,int n)1154 void tree_add_attr_int(tree_t t, ident_t name, int n)
1155 {
1156    tree_add_attr(t, name, A_INT)->ival = n;
1157 }
1158 
tree_attr_int(tree_t t,ident_t name,int def)1159 int tree_attr_int(tree_t t, ident_t name, int def)
1160 {
1161    attr_t *a = tree_find_attr(t, name, A_INT);
1162    return a ? a->ival : def;
1163 }
1164 
tree_add_attr_ptr(tree_t t,ident_t name,void * ptr)1165 void tree_add_attr_ptr(tree_t t, ident_t name, void *ptr)
1166 {
1167    tree_add_attr(t, name, A_PTR)->pval = ptr;
1168 }
1169 
tree_attr_ptr(tree_t t,ident_t name)1170 void *tree_attr_ptr(tree_t t, ident_t name)
1171 {
1172    attr_t *a = tree_find_attr(t, name, A_PTR);
1173    return a ? a->pval : NULL;
1174 }
1175 
tree_attr_tree(tree_t t,ident_t name)1176 tree_t tree_attr_tree(tree_t t, ident_t name)
1177 {
1178    attr_t *a = tree_find_attr(t, name, A_TREE);
1179    return a ? a->tval : NULL;
1180 }
1181 
tree_add_attr_tree(tree_t t,ident_t name,tree_t val)1182 void tree_add_attr_tree(tree_t t, ident_t name, tree_t val)
1183 {
1184    assert(val != NULL);
1185    tree_add_attr(t, name, A_TREE)->tval = val;
1186 }
1187 
tree_rewrite(tree_t t,tree_rewrite_fn_t fn,void * context)1188 tree_t tree_rewrite(tree_t t, tree_rewrite_fn_t fn, void *context)
1189 {
1190    object_rewrite_ctx_t ctx = {
1191       .index      = 0,
1192       .generation = object_next_generation(),
1193       .fn         = fn,
1194       .context    = context
1195    };
1196 
1197    tree_t result = (tree_t)object_rewrite(&(t->object), &ctx);
1198    free(ctx.cache);
1199    return result;
1200 }
1201 
tree_copy(tree_t t,tree_copy_fn_t fn,void * context)1202 tree_t tree_copy(tree_t t, tree_copy_fn_t fn, void *context)
1203 {
1204    object_copy_ctx_t ctx = {
1205       .generation = object_next_generation(),
1206       .index      = 0,
1207       .callback   = fn,
1208       .context    = context,
1209       .copied     = NULL
1210    };
1211 
1212    object_copy_mark(&(t->object), &ctx);
1213 
1214    if (t->object.index == UINT32_MAX)
1215       return t;   // Nothing to copy
1216 
1217    ctx.copied = xcalloc(sizeof(void *) * ctx.index);
1218 
1219    tree_t copy = (tree_t)object_copy_sweep(&(t->object), &ctx);
1220 
1221    free(ctx.copied);
1222    return copy;
1223 }
1224 
tree_kind_str(tree_kind_t t)1225 const char *tree_kind_str(tree_kind_t t)
1226 {
1227    return kind_text_map[t];
1228 }
1229