aboutsummaryrefslogtreecommitdiff
path: root/src/ast.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ast.c')
-rw-r--r--src/ast.c124
1 files changed, 47 insertions, 77 deletions
diff --git a/src/ast.c b/src/ast.c
index 4573d3e..bb8fb2b 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -16,6 +16,7 @@
#include <fwd/ast.h>
#include <fwd/scope.h>
+#include <fwd/tracker.h>
#define VEC_NAME ast_vec
#define VEC_TYPE struct ast *
@@ -25,77 +26,29 @@
#define VEC_TYPE struct type *
#include <conts/vec.h>
-static struct ast_vec nodes;
-static struct type_vec types;
-
-static void destroy_ast_node(struct ast *n)
-{
- if (!n)
- return;
-
- if (n->s)
- free(n->s);
-
- free(n);
-}
-
-static void destroy_type(struct type *n)
-{
- if (!n)
- return;
-
- if (n->id)
- free(n->id);
-
- free(n);
-}
-
-static void destroy_ast_nodes()
-{
- foreach(ast_vec, n, &nodes) {
- destroy_ast_node(*n);
- }
-
- ast_vec_destroy(&nodes);
-}
-
-static void destroy_types()
-{
- foreach(type_vec, t, &types) {
- destroy_type(*t);
- }
-
- type_vec_destroy(&types);
-}
-
-void destroy_allocs()
-{
- destroy_ast_nodes();
- destroy_types();
-}
-
static struct ast *create_empty_ast()
{
- if (ast_vec_uninit(&nodes))
- nodes = ast_vec_create(1);
-
- struct ast *n = calloc(1, sizeof(struct ast));
- if (!n)
+ struct ast *n = callocc(1, sizeof(struct ast));
+ if (!n) {
+ internal_error("failed allocating empty ast node");
return NULL;
+ }
/* just to be safe */
n->k = AST_EMPTY;
- ast_vec_append(&nodes, n);
+ track_ptr(n);
return n;
}
static struct type *create_empty_type()
{
- if (type_vec_uninit(&types))
- types = type_vec_create(1);
+ struct type *n = callocc(1, sizeof(struct type));
+ if (!n) {
+ internal_error("failed allocating empty type node");
+ return NULL;
+ }
- struct type *n = calloc(1, sizeof(struct type));
- type_vec_append(&types, n);
+ track_ptr(n);
return n;
}
@@ -326,23 +279,34 @@ struct ast *clone_ast(struct ast *n)
new->v = n->v;
new->d = n->d;
- if (n->s)
- new->s = strdup(n->s);
+ /* names are handled by pointer tracker, so we can just copy a reference
+ * to the string directly */
+ new->s = n->s;
- if (n->a0)
- new->a0 = clone_ast_list(n->a0);
+ if (n->a0 && !(new->a0 = clone_ast_listc(n->a0))) {
+ internal_error("failed cloning ast a0");
+ return NULL;
+ }
- if (n->a1)
- new->a1 = clone_ast_list(n->a1);
+ if (n->a1 && !(new->a1 = clone_ast_listc(n->a1))) {
+ internal_error("failed cloning ast a1");
+ return NULL;
+ }
- if (n->a2)
- new->a2 = clone_ast_list(n->a2);
+ if (n->a2 && !(new->a2 = clone_ast_listc(n->a2))) {
+ internal_error("failed cloning ast a2");
+ return NULL;
+ }
- if (n->a3)
- new->a3 = clone_ast_list(n->a3);
+ if (n->a3 && !(new->a3 = clone_ast_listc(n->a3))) {
+ internal_error("failed cloning ast a3");
+ return NULL;
+ }
- if (n->t2)
- new->t2 = clone_type_list(n->t2);
+ if (n->t2 && !(new->t2 = clone_type_listc(n->t2))) {
+ internal_error("failed cloning ast t2");
+ return NULL;
+ }
/** @todo rebuild opt group? */
@@ -353,7 +317,9 @@ struct ast *clone_ast_list(struct ast *root)
{
struct ast *n = root, *new_root = NULL, *prev = NULL;
while (n) {
- struct ast *new = clone_ast(n);
+ struct ast *new = clone_astc(n);
+ if (!new)
+ return NULL;
if (prev) prev->n = new;
else new_root = new;
@@ -375,11 +341,13 @@ struct type *clone_type(struct type *type)
return NULL;
new->k = type->k;
- if (type->id)
- new->id = strdup(type->id);
+ /* names are tracked by the tracker, so no need to duplicate */
+ new->id = type->id;
- if (type->t0)
- new->t0 = clone_type_list(type->t0);
+ if (type->t0 && !(new->t0 = clone_type_listc(type->t0))) {
+ internal_error("failed cloning type t0");
+ return NULL;
+ }
new->or = type->or;
new->group = type->group;
@@ -391,7 +359,9 @@ struct type *clone_type_list(struct type *root)
{
struct type *n = root, *new_root = NULL, *prev = NULL;
while (n) {
- struct type *new = clone_type(n);
+ struct type *new = clone_typec(n);
+ if (!new)
+ return NULL;
if (prev) prev->n = new;
else new_root = new;