aboutsummaryrefslogtreecommitdiff
path: root/src/ast.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ast.c')
-rw-r--r--src/ast.c2019
1 files changed, 404 insertions, 1615 deletions
diff --git a/src/ast.c b/src/ast.c
index e77714c..18a98bc 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -15,585 +15,162 @@
#include <math.h>
#include <ek/ast.h>
+#include <ek/vec.h>
#include <ek/scope.h>
-static struct {
- size_t n;
- size_t s;
- struct ast_node **v;
-} ast_nodes = {0};
+static struct vec nodes = {0};
+static struct vec types = {0};
-static void destroy_ast_node(struct ast_node *node)
+static void destroy_ast_node(struct ast *n)
{
- if (!node)
+ if (!n)
return;
- switch (node->node_type) {
- case AST_ID: free((void *)AST_ID(node).id); break;
- case AST_CONST:
- if (AST_CONST(node).kind == AST_CONST_STRING)
- free((void *)AST_CONST(node).str);
- break;
- default:
- }
-
- free(node);
-}
-
-void destroy_ast_nodes()
-{
- for (size_t i = 0; i < ast_nodes.n; ++i)
- destroy_ast_node(ast_nodes.v[i]);
-
- free(ast_nodes.v);
-}
-
-/* eventually we might want to pass in a context or something */
-static struct ast_node *create_ast_node()
-{
- if (ast_nodes.s == 0) {
- ast_nodes.s = 1;
- ast_nodes.n = 0;
- ast_nodes.v = calloc(1, sizeof(struct ast_node *));
- }
-
- else if (ast_nodes.n >= ast_nodes.s) {
- ast_nodes.s *= 2;
- ast_nodes.v =
- realloc(ast_nodes.v,
- ast_nodes.s * sizeof(struct ast_node *));
- }
-
- struct ast_node *n = calloc(1, sizeof(struct ast_node));
- ast_nodes.v[ast_nodes.n++] = n;
- return n;
-}
-
-/** @todo alloc should maybe also keep track of all nodes in a vector or
- * something and mass free all AST at a time to keep my sanity */
-#define ALLOC_NODE(n, type) \
- struct ast_node *n = create_ast_node(); \
- if (!n) { \
- fprintf(stderr, "failed allocating" type "\n"); \
- return NULL; \
- }
-
-#define DESTROY_LIST(x) \
- { \
- struct ast_node *prev = x, *cur; \
- if (prev) \
- do { \
- cur = prev->next; \
- destroy_ast_node(prev); \
- } while ((prev = cur)); \
- }
-
-struct ast_node *gen_arr_access(struct ast_node *base, struct ast_node *idx,
- struct src_loc loc)
-{
- ALLOC_NODE(n, "arr_access");
- n->node_type = AST_ARR_ACCESS;
- AST_ARR_ACCESS(n).base = base;
- AST_ARR_ACCESS(n).idx = idx;
- n->loc = loc;
- return n;
-}
-
-struct ast_node *gen_macro_expand(struct ast_node *id, struct ast_node *args,
- struct src_loc loc)
-{
- ALLOC_NODE(n, "macro_expand");
- n->node_type = AST_MACRO_EXPAND;
- AST_MACRO_EXPAND(n).id = id;
- AST_MACRO_EXPAND(n).args = args;
- n->loc = loc;
- return n;
-}
-
-struct ast_node *gen_type_expand(struct ast_node *id,
- struct ast_node *args,
- struct src_loc loc)
-{
- ALLOC_NODE(n, "type_expand");
- n->node_type = AST_TYPE_EXPAND;
- AST_TYPE_EXPAND(n).id = id;
- AST_TYPE_EXPAND(n).args = args;
- n->loc = loc;
- return n;
-}
-
-struct ast_node *gen_binop(enum ast_binops op,
- struct ast_node *left,
- struct ast_node *right,
- struct src_loc loc)
-{
- ALLOC_NODE(n, "binop");
- n->node_type = AST_BINOP;
- AST_BINOP(n).op = op;
- AST_BINOP(n).left = left;
- AST_BINOP(n).right = right;
- n->loc = loc;
- return n;
-}
-
-struct ast_node *gen_unop(enum ast_unops op, struct ast_node *expr,
- struct src_loc loc)
-{
- ALLOC_NODE(n, "unop");
- n->node_type = AST_UNOP;
- AST_UNOP(n).op = op;
- AST_UNOP(n).expr = expr;
- n->loc = loc;
- return n;
-}
-
-struct ast_node *gen_call(struct ast_node *expr, struct ast_node *args,
- struct src_loc loc)
-{
- ALLOC_NODE(n, "call");
- n->node_type = AST_CALL;
- AST_CALL(n).expr = expr;
- AST_CALL(n).args = args;
- n->loc = loc;
- return n;
-}
-
-struct ast_node *gen_id(const char *id, struct src_loc loc)
-{
- ALLOC_NODE(n, "id");
- n->node_type = AST_ID;
- AST_ID(n).id = id;
- n->loc = loc;
- return n;
-}
-
-struct ast_node *gen_assign(struct ast_node *to, struct ast_node *from,
- struct src_loc loc)
-{
- ALLOC_NODE(n, "assign");
- n->node_type = AST_ASSIGN;
- AST_ASSIGN(n).to = to;
- AST_ASSIGN(n).from = from;
- n->loc = loc;
- return n;
-}
-
-struct ast_node *gen_init(struct ast_node *body, struct src_loc loc)
-{
- ALLOC_NODE(n, "struct init");
- n->node_type = AST_INIT;
- AST_INIT(n).body = body;
- n->loc = loc;
- return n;
-}
+ if (n->s)
+ free(n->s);
-struct ast_node *gen_int(long long integer, struct src_loc loc)
-{
- ALLOC_NODE(n, "int");
- n->node_type = AST_CONST;
- AST_CONST(n).kind = AST_CONST_INTEGER;
- AST_CONST(n).integer = integer;
- n->loc = loc;
- return n;
-}
-
-struct ast_node *gen_string(const char *str, struct src_loc loc)
-{
- ALLOC_NODE(n, "string");
- n->node_type = AST_CONST;
- AST_CONST(n).kind = AST_CONST_STRING;
- AST_CONST(n).str = str;
- n->loc = loc;
- return n;
-}
-
-struct ast_node *gen_while(struct ast_node *cond, struct ast_node *body,
- struct src_loc loc)
-{
- ALLOC_NODE(n, "while");
- n->node_type = AST_WHILE;
- AST_WHILE(n).cond = cond;
- AST_WHILE(n).body = body;
- n->loc = loc;
- return n;
-}
-
-struct ast_node *gen_for(struct ast_node *pre, struct ast_node *cond,
- struct ast_node *post, struct ast_node *body,
- struct src_loc loc)
-{
- ALLOC_NODE(n, "for");
- n->node_type = AST_FOR;
- AST_FOR(n).pre = pre;
- AST_FOR(n).cond = cond;
- AST_FOR(n).post = post;
- AST_FOR(n).body = body;
- n->loc = loc;
- return n;
-}
-
-struct ast_node *gen_return(struct ast_node *expr, struct src_loc loc)
-{
- ALLOC_NODE(n, "return");
- n->node_type = AST_RETURN;
- AST_RETURN(n).expr = expr;
- n->loc = loc;
- return n;
-}
-
-struct ast_node *gen_goto(struct ast_node *label, struct src_loc loc)
-{
- ALLOC_NODE(n, "goto");
- n->node_type = AST_GOTO;
- AST_GOTO(n).label = label;
- n->loc = loc;
- return n;
-}
-
-struct ast_node *gen_dot(struct ast_node *expr, struct ast_node *id,
- struct src_loc loc)
-{
- ALLOC_NODE(n, "dot");
- n->node_type = AST_DOT;
- AST_DOT(n).expr = expr;
- AST_DOT(n).id = id;
- n->loc = loc;
- return n;
+ free(n);
}
-struct ast_node *gen_label(struct ast_node *id, struct src_loc loc)
+static void destroy_type(struct type *n)
{
- ALLOC_NODE(n, "label");
- n->node_type = AST_LABEL;
- AST_LABEL(n).id = id;
- n->loc = loc;
- return n;
-}
-
-struct ast_node *gen_ctrl(enum ast_ctrl_kind kind, struct src_loc loc)
-{
- ALLOC_NODE(n, "ctrl");
- n->node_type = AST_CTRL;
- AST_CTRL(n).kind = kind;
- n->loc = loc;
- return n;
-}
-
-struct ast_node *gen_fetch(struct ast_node *id, struct ast_node *type,
- struct src_loc loc)
-{
- ALLOC_NODE(n, "fetch");
- n->node_type = AST_FETCH;
- AST_FETCH(n).id = id;
- AST_FETCH(n).type = type;
- n->loc = loc;
- return n;
-}
-
-struct ast_node *gen_macro_construct(struct ast_node *id,
- struct ast_node *params,
- struct ast_node *body,
- struct src_loc loc)
-{
- ALLOC_NODE(n, "macro_construct");
- n->node_type = AST_MACRO_CONSTRUCT;
- AST_MACRO_CONSTRUCT(n).id = id;
- AST_MACRO_CONSTRUCT(n).params = params;
- AST_MACRO_CONSTRUCT(n).body = body;
- n->loc = loc;
- return n;
-}
-
-struct ast_node *gen_if(struct ast_node *cond, struct ast_node *body,
- struct ast_node *els, struct src_loc loc)
-{
- ALLOC_NODE(n, "if");
- n->node_type = AST_IF;
- AST_IF(n).cond = cond;
- AST_IF(n).body = body;
- AST_IF(n).els = els;
- n->loc = loc;
- return n;
-}
+ if (!n)
+ return;
-struct ast_node *gen_switch(struct ast_node *cond, struct ast_node *cases,
- struct src_loc loc)
-{
- ALLOC_NODE(n, "switch");
- n->node_type = AST_SWITCH;
- AST_SWITCH(n).cond = cond;
- AST_SWITCH(n).cases = cases;
- n->loc = loc;
- return n;
-}
+ if (n->id)
+ free(n->id);
-struct ast_node *gen_case(struct ast_node *cond, struct ast_node *body,
- struct src_loc loc)
-{
- ALLOC_NODE(n, "case");
- /* TODO: a macro to map proc name to node type would make sure I don't
- * make any dumb mixups... */
- n->node_type = AST_CASE;
- AST_CASE(n).cond = cond;
- AST_CASE(n).body = body;
- /* TODO: where should I check the fallthrough flag? In the
- * actualization stage, I guess */
- n->loc = loc;
- return n;
+ free(n);
}
-struct ast_node *gen_primitive(enum ast_primitive type, struct ast_node *def,
- struct src_loc loc)
-{
- ALLOC_NODE(n, "primitive");
- n->node_type = AST_TYPE;
- AST_TYPE(n).kind = AST_TYPE_PRIMITIVE;
- AST_PRIMITIVE_TYPE(n).type = type;
- AST_PRIMITIVE_TYPE(n).def = def;
- n->loc = loc;
- return n;
-}
-
-struct ast_node *gen_type(enum ast_type_kind kind,
- struct ast_node *t0,
- struct ast_node *t1,
- struct src_loc loc)
+void destroy_ast_nodes()
{
- ALLOC_NODE(n, "type");
- n->node_type = AST_TYPE;
- AST_TYPE(n).kind = kind;
- n->loc = loc;
-
- switch (kind) {
- case AST_TYPE_TRAIT:
- AST_TRAIT_TYPE(n).def = t0;
- break;
-
- case AST_TYPE_ID:
- AST_ID_TYPE(n).id = t0;
- break;
-
- case AST_TYPE_CONSTRUCT:
- AST_CONSTRUCT_TYPE(n).id = t0;
- AST_CONSTRUCT_TYPE(n).args = t1;
- break;
-
- case AST_TYPE_ARR:
- AST_ARR_TYPE(n).size = t0;
- AST_ARR_TYPE(n).base = t1;
- break;
-
- case AST_TYPE_POINTER:
- AST_PTR_TYPE(n).base = t0;
- break;
-
- case AST_TYPE_STRUCT:
- AST_STRUCT_TYPE(n).def = t0;
- break;
-
- case AST_TYPE_ENUM:
- AST_ENUM_TYPE(n).def = t0;
- break;
-
- case AST_TYPE_SIGN:
- AST_SIGN_TYPE(n).params = t0;
- AST_SIGN_TYPE(n).ret = t1;
- break;
-
- default: abort();
+ foreach_vec(ni, nodes) {
+ struct ast *n = vect_at(struct ast *, nodes, ni);
+ destroy_ast_node(n);
}
- return n;
-}
-
-struct ast_node *gen_block(struct ast_node *body, struct src_loc loc)
-{
- ALLOC_NODE(n, "block");
- n->node_type = AST_BLOCK;
- AST_BLOCK(n).body = body;
- n->loc = loc;
- return n;
-}
-
-struct ast_node *gen_sizeof(struct ast_node *expr, struct src_loc loc)
-{
- ALLOC_NODE(n, "sizeof");
- n->node_type = AST_SIZEOF;
- AST_SIZEOF(n).expr = expr;
- n->loc = loc;
- return n;
-}
-
-struct ast_node *gen_as(struct ast_node *type, struct src_loc loc)
-{
- ALLOC_NODE(n, "as");
- n->node_type = AST_AS;
- AST_AS(n).type = type;
- n->loc = loc;
- return n;
-}
-
-struct ast_node *gen_defer(struct ast_node *expr, struct src_loc loc)
-{
- ALLOC_NODE(n, "defer");
- n->node_type = AST_DEFER;
- AST_DEFER(n).expr = expr;
- n->loc = loc;
- return n;
+ vec_destroy(&nodes);
}
-void destroy_defer(struct ast_node *defer)
+void destroy_types()
{
- assert(defer->node_type == AST_DEFER);
- destroy_ast_node(AST_DEFER(defer).expr);
- free(defer);
-}
+ foreach_vec(ti, types) {
+ struct type *t = vect_at(struct type *, types, ti);
+ destroy_type(t);
+ }
-struct ast_node *gen_var(struct ast_node *id, struct ast_node *type,
- struct ast_node *init, struct src_loc loc)
-{
- ALLOC_NODE(n, "var");
- n->node_type = AST_VAR;
- AST_VAR(n).id = id;
- AST_VAR(n).type = type;
- AST_VAR(n).init = init;
- n->loc = loc;
- return n;
+ vec_destroy(&types);
}
-struct ast_node *gen_proc(struct ast_node *id, struct ast_node *sign,
- struct ast_node *body, struct src_loc loc)
+void destroy_allocs()
{
- ALLOC_NODE(n, "proc");
- n->node_type = AST_PROC;
- AST_PROC(n).id = id;
- AST_PROC(n).sign = sign;
- AST_PROC(n).body = body;
- n->loc = loc;
- return n;
+ destroy_ast_nodes();
+ destroy_types();
}
-struct ast_node *gen_struct(struct ast_node *id,
- struct ast_node *generics, struct ast_node *body,
- struct src_loc loc)
+static struct ast *create_empty_ast()
{
- ALLOC_NODE(n, "struct");
- n->node_type = AST_STRUCT;
- AST_STRUCT(n).id = id;
- AST_STRUCT(n).generics = generics;
- AST_STRUCT(n).body = body;
- n->loc = loc;
- return n;
-}
+ if (vec_uninit(nodes)) {
+ nodes = vec_create(sizeof(struct ast *));
+ }
-struct ast_node *gen_enum(struct ast_node *id, struct ast_node *type,
- struct ast_node *body, struct src_loc loc)
-{
- ALLOC_NODE(n, "enum");
- n->node_type = AST_ENUM;
- AST_ENUM(n).id = id;
- AST_ENUM(n).type = type;
- AST_ENUM(n).body = body;
- n->loc = loc;
+ struct ast *n = calloc(1, sizeof(struct ast));
+ /* just to be safe */
+ n->k = AST_EMPTY;
+ vect_append(struct ast *, nodes, &n);
return n;
}
-struct ast_node *gen_cast(struct ast_node *expr, struct ast_node *type,
- struct src_loc loc)
+static struct type *create_empty_type()
{
- ALLOC_NODE(n, "cast");
- n->node_type = AST_CAST;
- AST_CAST(n).expr = expr;
- AST_CAST(n).type = type;
- n->loc = loc;
- return n;
-}
+ if (vec_uninit(types)) {
+ types = vec_create(sizeof(struct type *));
+ }
-struct ast_node *gen_val(struct ast_node *id, struct ast_node *val,
- struct src_loc loc)
-{
- ALLOC_NODE(n, "val");
- n->node_type = AST_VAL;
- AST_VAL(n).id = id;
- AST_VAL(n).val = val;
- n->loc = loc;
+ struct type *n = calloc(1, sizeof(struct type));
+ /* just to be safe */
+ n->k = TYPE_VOID;
+ vect_append(struct ast *, types, &n);
return n;
}
-struct ast_node *gen_alias(struct ast_node *id, struct ast_node *type,
- struct src_loc loc)
+struct ast *gen_ast(enum ast_kind kind,
+ struct ast *a0,
+ struct ast *a1,
+ struct ast *a2,
+ struct ast *a3,
+ struct type *t2,
+ char *s,
+ long long v,
+ struct src_loc loc)
{
- ALLOC_NODE(n, "alias");
- n->node_type = AST_ALIAS;
- AST_ALIAS(n).id = id;
- AST_ALIAS(n).type = type;
+ struct ast *n = create_empty_ast();
+ n->k = kind;
+ n->a0 = a0;
+ n->a1 = a1;
+ n->a2 = a2;
+ n->a3 = a3;
+ n->t2 = t2;
+ n->s = s;
+ n->v = v;
n->loc = loc;
return n;
}
-struct ast_node *gen_trait(struct ast_node *id,
- struct ast_node *params,
- struct ast_node *raw_body,
- struct ast_node *body,
- struct src_loc loc)
+struct type *tgen_type(enum type_kind kind,
+ struct type *t0,
+ struct type *t1,
+ struct ast *d,
+ struct ast *a,
+ char *id,
+ struct src_loc loc)
{
- ALLOC_NODE(n, "trait");
- n->node_type = AST_TRAIT;
- AST_TRAIT(n).id = id;
- AST_TRAIT(n).params = params;
- AST_TRAIT(n).body = body;
- AST_TRAIT(n).raw_body = raw_body;
+ struct type *n = create_empty_type();
+ n->k = kind;
+ n->t0 = t0;
+ n->t1 = t1;
+ n->d = d;
+ n->a = a;
+ n->id = id;
n->loc = loc;
return n;
}
-struct ast_node *gen_import(const char *file, struct src_loc loc)
+void ast_set_flags(struct ast *node, enum ast_flags flags)
{
- ALLOC_NODE(n, "import");
- n->node_type = AST_IMPORT;
- AST_IMPORT(n).file = file;
- n->loc = loc;
- return n;
+ node->f |= flags;
}
-struct ast_node *gen_embed(const char *file, struct src_loc loc)
+void ast_clear_flags(struct ast *node, enum ast_flags flags)
{
- ALLOC_NODE(n, "embed");
- n->node_type = AST_EMBED;
- AST_EMBED(n).file = file;
- n->loc = loc;
- return n;
+ node->f &= ~(flags);
}
-struct ast_node *gen_empty()
+unsigned ast_flags(struct ast *node, enum ast_flags flags)
{
- ALLOC_NODE(n, "empty");
- n->node_type = AST_EMPTY;
- /* TODO: location? */
- return n;
+ return node->f & flags;
}
-void ast_set_flags(struct ast_node *node, enum ast_flag flags)
+void ast_append(struct ast *list, struct ast *elem)
{
- node->flags |= flags;
-}
+ struct ast *cur = list;
+ while (cur->n)
+ cur = cur->n;
-void ast_clear_flags(struct ast_node *node, enum ast_flag flags)
-{
- node->flags &= ~(flags);
+ cur->n = elem;
}
-void ast_append(struct ast_node *list, struct ast_node *elem)
+void type_append(struct type *list, struct type *elem)
{
- struct ast_node *cur = list;
- while (cur->next)
- cur = cur->next;
+ struct type *cur = list;
+ while (cur->n)
+ cur = cur->n;
- cur->next = elem;
+ cur->n = elem;
}
-
-static const char *binop_symbol(int op)
+static const char *binop_symbol(enum ast_kind op)
{
switch (op) {
case AST_ADD: return "+";
@@ -618,18 +195,20 @@ static const char *binop_symbol(int op)
case AST_GE: return ">=";
case AST_NE: return "!=";
case AST_EQ: return "==";
+ default:
}
return "UNKNOWN";
}
-static const char *unop_symbol(int op)
+static const char *unop_symbol(enum ast_kind op)
{
switch (op) {
case AST_NEG: return "-";
case AST_LNOT: return "!";
case AST_REF: return "&";
case AST_DEREF: return "*";
+ default:
}
return "UNKNOWN";
@@ -641,19 +220,19 @@ static void dump(int depth, const char *fmt, ...)
va_start(args, fmt);
printf("//");
for (int i = 0; i < depth; ++i)
- putchar('\t');
+ printf(" ");
vprintf(fmt, args);
va_end(args);
}
-static void dump_flags(struct ast_node *node)
+static void dump_flags(struct ast *node)
{
if (node->scope)
printf(" %zu:", node->scope->number);
- enum ast_flag flags = node->flags;
+ enum ast_flags flags = node->f;
if (flags & AST_FLAG_MUTABLE)
printf(" MUT");
@@ -679,1252 +258,462 @@ static void dump_flags(struct ast_node *node)
printf(" FALLTHROUGH");
}
-const char *primitive_str(enum ast_primitive type)
+const char *primitive_str(struct type *type)
{
- switch (type) {
- case AST_VOID: return "void";
- case AST_I9: return "i9";
- case AST_I27: return "i27";
- case AST_BOOL: return "bool";
+ switch (type->k) {
+ case TYPE_VOID: return "void";
+ case TYPE_I9: return "i9";
+ case TYPE_I27: return "i27";
+ case TYPE_BOOL: return "bool";
default: return "unimp";
}
return "unimp";
}
-static void __dump_ast(int depth, struct ast_node *node)
+void ast_dump(int depth, struct ast *n)
{
- switch (node->node_type) {
- case AST_FETCH:
- dump(depth, "{FETCH:");
- dump_flags(node);
- putchar('\n');
-
- dump_ast(depth + 1, AST_FETCH(node).id);
- dump_ast(depth + 1, AST_FETCH(node).type);
-
- dump(depth, "}\n");
- break;
-
- case AST_ASSIGN:
- dump(depth, "{ASSIGN:");
- dump_flags(node);
- putchar('\n');
-
- dump_ast(depth + 1, AST_ASSIGN(node).to);
- dump_ast(depth + 1, AST_ASSIGN(node).from);
-
- dump(depth, "}\n");
- break;
-
- case AST_INIT:
- dump(depth, "{INIT:");
- dump_flags(node);
- putchar('\n');
-
- dump_ast(depth + 1, AST_INIT(node).body);
-
- dump(depth, "}\n");
- break;
-
- case AST_SIZEOF:
- dump(depth, "{SIZEOF:");
- dump_flags(node);
- putchar('\n');
-
- dump_ast(depth + 1, AST_SIZEOF(node).expr);
-
- dump(depth, "}\n");
- break;
-
- case AST_DOT:
- dump(depth, "{DOT:");
- dump_flags(node);
- putchar('\n');
-
- dump_ast(depth + 1, AST_DOT(node).expr);
- dump_ast(depth + 1, AST_DOT(node).id);
-
- dump(depth, "}\n");
- break;
-
- case AST_GOTO:
- dump(depth, "{GOTO:");
- dump_flags(node);
- putchar('\n');
-
- dump_ast(depth + 1, AST_GOTO(node).defers);
- dump_ast(depth + 1, AST_GOTO(node).label);
-
- dump(depth, "}\n");
- break;
-
- case AST_LABEL:
- dump(depth, "{LABEL:");
- dump_flags(node);
- putchar('\n');
-
- dump_ast(depth + 1, AST_LABEL(node).id);
-
- dump(depth, "}\n");
- break;
-
- case AST_BINOP:
- dump(depth, "{BINOP:");
- dump_flags(node);
- printf(" %s\n", binop_symbol(AST_BINOP(node).op));
-
- dump_ast(depth + 1, AST_BINOP(node).left);
- dump_ast(depth + 1, AST_BINOP(node).right);
-
- dump(depth, "}\n");
- break;
-
- case AST_UNOP:
- dump(depth, "{UNOP:");
- dump_flags(node);
- printf(" %s\n", unop_symbol(AST_UNOP(node).op));
-
- dump_ast(depth + 1, AST_UNOP(node).expr);
-
- dump(depth, "}\n");
- break;
-
- case AST_CALL:
- dump(depth, "{CALL:");
- dump_flags(node);
- putchar('\n');
-
- dump_ast(depth + 1, AST_CALL(node).expr);
- dump_ast(depth + 1, AST_CALL(node).args);
-
- dump(depth, "}\n");
- break;
-
- case AST_DEFER:
- dump(depth, "{DEFER:");
- dump_flags(node);
- putchar('\n');
-
- dump_ast(depth + 1, AST_DEFER(node).expr);
-
- dump(depth, "}\n");
- break;
-
- case AST_CAST:
- dump(depth, "{CAST:");
- dump_flags(node);
- putchar('\n');
-
- dump_ast(depth + 1, AST_CAST(node).expr);
- dump_ast(depth + 1, AST_CAST(node).type);
-
- dump(depth, "}\n");
- break;
-
- case AST_MACRO_CONSTRUCT:
- dump(depth, "{MACRO_CONSTRUCT:");
- dump_flags(node);
- putchar('\n');
-
- dump_ast(depth + 1, AST_MACRO_CONSTRUCT(node).id);
- dump_ast(depth + 1, AST_MACRO_CONSTRUCT(node).params);
- dump_ast(depth + 1, AST_MACRO_CONSTRUCT(node).body);
-
- dump(depth, "}\n");
- break;
-
- case AST_MACRO_EXPAND:
- dump(depth, "{MACRO_EXPAND:");
- dump_flags(node);
- putchar('\n');
-
- dump_ast(depth + 1, AST_MACRO_EXPAND(node).id);
- dump_ast(depth + 1, AST_MACRO_EXPAND(node).args);
-
- dump(depth, "}\n");
- break;
-
- case AST_PROC:
- dump(depth, "{PROC:");
- dump_flags(node);
- putchar('\n');
-
- dump_ast(depth + 1, AST_PROC(node).id);
- dump_ast(depth + 1, AST_PROC(node).sign);
- dump_ast(depth + 1, AST_PROC(node).body);
-
- dump(depth, "}\n");
- break;
-
- case AST_VAR:
- dump(depth, "{VAR:");
- dump_flags(node);
- putchar('\n');
-
- dump_ast(depth + 1, AST_VAR(node).id);
- dump_ast(depth + 1, AST_VAR(node).type);
- dump_ast(depth + 1, AST_VAR(node).init);
-
- dump(depth, "}\n");
- break;
-
- case AST_ID:
- dump(depth, "{ID:");
- dump_flags(node);
- printf(" %s}\n", AST_ID(node).id);
- break;
-
- case AST_AS:
- dump(depth, "{AS:");
- dump_flags(node);
- putchar('\n');
-
- dump_ast(depth + 1, AST_AS(node).type);
- dump(depth, "}\n");
- break;
-
- case AST_BLOCK:
- dump(depth, "{BLOCK:");
- dump_flags(node);
- putchar('\n');
-
- dump_ast(depth + 1, AST_BLOCK(node).body);
- dump_ast(depth + 1, AST_BLOCK(node).defers);
-
- dump(depth, "}\n");
- break;
-
- case AST_RETURN:
- dump(depth, "{RETURN:");
- dump_flags(node);
- putchar('\n');
-
- dump_ast(depth + 1, AST_RETURN(node).defers);
- dump_ast(depth + 1, AST_RETURN(node).expr);
-
- dump(depth, "}\n");
- break;
-
- case AST_TYPE:
- dump(depth, "{TYPE:");
- dump_flags(node);
-
- switch (node->_type.kind) {
- case AST_TYPE_PRIMITIVE:
- printf(" PRIMITIVE %s\n",
- primitive_str(AST_PRIMITIVE_TYPE(node).type));
- break;
-
- case AST_TYPE_TRAIT: {
- printf(" TRAIT\n");
- struct ast_node *def = AST_TRAIT_TYPE(node).def;
- /* this should be enough, avoid print loops */
- dump_ast(depth + 1, AST_TRAIT(def).id);
- break;
- }
-
- case AST_TYPE_CONSTRUCT: {
- printf(" CONSTRUCT\n");
- dump_ast(depth + 1, AST_CONSTRUCT_TYPE(node).id);
- dump_ast(depth + 1, AST_CONSTRUCT_TYPE(node).args);
- break;
- }
-
- case AST_TYPE_ID:
- printf(" ID\n");
- dump_ast(depth + 1, AST_ID_TYPE(node).id);
- break;
-
- case AST_TYPE_ARR:
- printf(" ARR\n");
- dump_ast(depth + 1, AST_ARR_TYPE(node).size);
- dump_ast(depth + 1, AST_ARR_TYPE(node).base);
- break;
-
- case AST_TYPE_POINTER:
- printf(" PTR\n");
- dump_ast(depth + 1, AST_PTR_TYPE(node).base);
- break;
-
- case AST_TYPE_STRUCT: {
- printf(" STRUCT\n");
- struct ast_node *def = AST_STRUCT_TYPE(node).def;
- /* oh yeah, struc is at least right now just an ID that
- * we can use to fetch the actual struct with. */
- dump_ast(depth + 1, AST_STRUCT(def).id);
- break;
- }
-
- case AST_TYPE_ENUM: {
- printf(" ENUM\n");
- struct ast_node *def = AST_ENUM_TYPE(node).def;
- dump_ast(depth + 1, AST_ENUM(def).id);
- break;
- }
-
- case AST_TYPE_SIGN:
- printf(" SIGN\n");
- dump_ast(depth + 1, AST_SIGN_TYPE(node).params);
- dump_ast(depth + 1, AST_SIGN_TYPE(node).ret);
- break;
- }
-
- dump_ast(depth + 1, AST_TYPE(node).next);
-
- dump(depth, "}\n");
- break;
-
- case AST_EMPTY:
- dump(depth, "{EMPTY:");
- dump_flags(node);
- printf("}\n");
- break;
-
- case AST_FOR:
- dump(depth, "{FOR:");
- dump_flags(node);
- putchar('\n');
-
- dump_ast(depth + 1, AST_FOR(node).pre);
- dump_ast(depth + 1, AST_FOR(node).cond);
- dump_ast(depth + 1, AST_FOR(node).post);
- dump_ast(depth + 1, AST_FOR(node).body);
-
- dump(depth, "}\n");
- break;
-
- case AST_WHILE:
- dump(depth, "{WHILE:");
- dump_flags(node);
- putchar('\n');
-
- dump_ast(depth + 1, AST_WHILE(node).cond);
- dump_ast(depth + 1, AST_WHILE(node).body);
-
- dump(depth, "}\n");
- break;
-
- case AST_CTRL:
- dump(depth, "{CTRL:");
- dump_flags(node);
- switch(AST_CTRL(node).kind) {
- case AST_CTRL_BREAK: printf(" BREAK"); break;
- case AST_CTRL_CONTINUE: printf(" CONTINUE"); break;
- }
- printf("}\n");
- break;
-
- case AST_IF:
- dump(depth, "{IF:");
- dump_flags(node);
- putchar('\n');
-
- dump_ast(depth + 1, AST_IF(node).cond);
- dump_ast(depth + 1, AST_IF(node).body);
- dump_ast(depth + 1, AST_IF(node).els);
-
- dump(depth, "}\n");
- break;
-
- case AST_IMPORT:
- dump(depth, "{IMPORT:");
- dump_flags(node);
- printf(" %s}\n", AST_IMPORT(node).file);
- break;
-
- case AST_EMBED:
- dump(depth, "{EMBED:");
- dump_flags(node);
- printf(" %s}\n", AST_EMBED(node).file);
- break;
-
- case AST_ENUM:
- dump(depth, "{ENUM:");
- dump_flags(node);
- putchar('\n');
-
- dump_ast(depth + 1, AST_ENUM(node).id);
- dump_ast(depth + 1, AST_ENUM(node).type);
- dump_ast(depth + 1, AST_ENUM(node).body);
-
- dump(depth, "}\n");
- break;
-
- case AST_STRUCT:
- dump(depth, "{STRUCT:");
- dump_flags(node);
- putchar('\n');
-
- dump_ast(depth + 1, AST_STRUCT(node).id);
- dump_ast(depth + 1, AST_STRUCT(node).generics);
- dump_ast(depth + 1, AST_STRUCT(node).body);
-
- dump(depth, "}\n");
- break;
-
- case AST_VAL:
- dump(depth, "{VAL:");
- dump_flags(node);
- putchar('\n');
-
- dump_ast(depth + 1, AST_VAL(node).id);
- dump_ast(depth + 1, AST_VAL(node).val);
-
- dump(depth, "}\n");
- break;
-
- case AST_SWITCH:
- dump(depth, "{SWITCH:");
- dump_flags(node);
- putchar('\n');
-
- dump_ast(depth + 1, AST_SWITCH(node).cond);
- dump_ast(depth + 1, AST_SWITCH(node).cases);
-
- dump(depth, "}\n");
- break;
+ if (!n) {
+ dump(depth, "{NULL}\n");
+ return;
+ }
- case AST_CASE:
- dump(depth, "{CASE:");
- dump_flags(node);
- putchar('\n');
+#define DUMP(x) case x: dump(depth, #x); break;
+ switch (n->k) {
+ DUMP(AST_FETCH);
+ DUMP(AST_INIT);
+ DUMP(AST_ASSIGN);
+ DUMP(AST_CALL);
+ DUMP(AST_ARR);
+ DUMP(AST_SIZEOF);
+ DUMP(AST_CAST);
+ DUMP(AST_DEFER);
+ DUMP(AST_MACRO_DEF);
+ DUMP(AST_MACRO_EXPAND);
+ DUMP(AST_TYPE_EXPAND);
+ DUMP(AST_PROC_DEF);
+ DUMP(AST_GOTO);
+ DUMP(AST_LABEL);
+ DUMP(AST_VAR_DEF);
+ DUMP(AST_FOR);
+ DUMP(AST_EMBED);
+ DUMP(AST_DOT);
+ DUMP(AST_WHILE);
+ DUMP(AST_DO_WHILE);
+ DUMP(AST_BREAK);
+ DUMP(AST_CONTINUE);
+ DUMP(AST_RETURN);
+ DUMP(AST_ALIAS_DEF);
+ DUMP(AST_TRAIT_DEF);
+ DUMP(AST_STRUCT_DEF);
+ DUMP(AST_IF);
+ DUMP(AST_BLOCK);
+ DUMP(AST_IMPORT);
+ DUMP(AST_ENUM_DEF);
+ DUMP(AST_VAL);
+ DUMP(AST_SWITCH);
+ DUMP(AST_CASE);
+ DUMP(AST_ID);
+ DUMP(AST_AS);
+ DUMP(AST_EMPTY);
+ DUMP(AST_ADD);
+ DUMP(AST_SUB);
+ DUMP(AST_MUL);
+ DUMP(AST_DIV);
+ DUMP(AST_REM);
+ DUMP(AST_LAND);
+ DUMP(AST_LOR);
+ DUMP(AST_LSHIFT);
+ DUMP(AST_RSHIFT);
+ DUMP(AST_ASSIGN_ADD);
+ DUMP(AST_ASSIGN_SUB);
+ DUMP(AST_ASSIGN_MUL);
+ DUMP(AST_ASSIGN_DIV);
+ DUMP(AST_ASSIGN_REM);
+ DUMP(AST_ASSIGN_LSHIFT);
+ DUMP(AST_ASSIGN_RSHIFT);
+ DUMP(AST_LT);
+ DUMP(AST_GT);
+ DUMP(AST_LE);
+ DUMP(AST_GE);
+ DUMP(AST_NE);
+ DUMP(AST_EQ);
+ DUMP(AST_NEG);
+ DUMP(AST_LNOT);
+ DUMP(AST_NOT);
+ DUMP(AST_REF);
+ DUMP(AST_DEREF);
+ DUMP(AST_CONST_INT);
+ DUMP(AST_CONST_CHAR);
+ DUMP(AST_CONST_BOOL);
+ DUMP(AST_CONST_STR);
+ }
+#undef DUMP
- dump_ast(depth + 1, AST_CASE(node).cond);
- dump_ast(depth + 1, AST_CASE(node).body);
+ depth++;
- dump(depth, "}\n");
- break;
+ if (n->t)
+ type_dump_list(n->t);
- case AST_CONST:
- dump(depth, "{CONST:");
- dump_flags(node);
- switch (node->_const.kind) {
- case AST_CONST_INTEGER:
- printf(" %lli", AST_CONST(node).integer);
- break;
- case AST_CONST_STRING:
- printf(" \"%s\"", AST_CONST(node).str);
- break;
- }
- printf("}\n");
- break;
+ printf("\n");
- case AST_ALIAS:
- dump(depth, "{ALIAS:");
- dump_flags(node);
- putchar('\n');
+ if (n->s)
+ dump(depth, "%s\n", n->s);
- dump_ast(depth + 1, AST_ALIAS(node).id);
- dump_ast(depth + 1, AST_ALIAS(node).type);
+ if (n->k == AST_CONST_INT)
+ dump(depth, "%lli\n", n->v);
- dump(depth, "}\n");
- break;
+ if (n->a0)
+ ast_dump_list(depth, n->a0);
- case AST_TRAIT:
- dump(depth, "{TRAIT:");
- dump_flags(node);
- putchar('\n');
+ if (n->a1)
+ ast_dump_list(depth, n->a1);
- dump_ast(depth + 1, AST_TRAIT(node).id);
- dump_ast(depth + 1, AST_TRAIT(node).body);
+ if (n->a2)
+ ast_dump_list(depth, n->a2);
- dump(depth, "}\n");
- break;
+ if (n->a3)
+ ast_dump_list(depth, n->a3);
- default:
- dump(depth, "{UNIMP}\n");
+ if (n->t2) {
+ type_dump_list(n->t2); printf("\n");
}
}
-void dump_ast_node(int depth, struct ast_node *n)
+void ast_dump_list(int depth, struct ast *root)
{
- if (!n) {
+ if (!root) {
dump(depth, "{NULL}\n");
return;
}
- __dump_ast(depth, n);
+ foreach_node(n, root) {
+ ast_dump(depth, n);
+ }
}
-void dump_ast(int depth, struct ast_node *root)
+void type_dump(struct type *n)
{
- if (!root) {
- dump(depth, "{NULL}\n");
+ if (!n) {
+ printf(" {NULL}");
return;
}
- struct ast_node *n = root;
- do {
- dump_ast_node(depth, n);
- } while ((n = n->next));
+ printf(" ");
+
+#define DUMP(x) case x: printf(#x); break;
+ switch (n->k) {
+ DUMP(TYPE_VOID);
+ DUMP(TYPE_BOOL);
+ DUMP(TYPE_I9);
+ DUMP(TYPE_I27);
+ DUMP(TYPE_STR);
+ DUMP(TYPE_PTR);
+ DUMP(TYPE_ID);
+ DUMP(TYPE_CONSTRUCT);
+ DUMP(TYPE_STRUCT);
+ DUMP(TYPE_ENUM);
+ DUMP(TYPE_CALLABLE);
+ DUMP(TYPE_TRAIT);
+ }
}
-struct ast_node *clone_ast_node(struct ast_node *node)
+void type_dump_list(struct type *root)
{
- if (!node)
- return NULL;
-
- assert(node->node_type);
- struct ast_node *new = NULL;
- switch (node->node_type) {
- case AST_ARR_ACCESS:
- new = gen_arr_access(
- clone_ast_node(AST_ARR_ACCESS(node).base),
- clone_ast_node(AST_ARR_ACCESS(node).idx),
- node->loc);
- break;
-
- case AST_TYPE_EXPAND:
- new = gen_type_expand(
- clone_ast_node(AST_TYPE_EXPAND(node).id),
- clone_ast_node(AST_TYPE_EXPAND(node).args),
- node->loc);
- break;
-
- case AST_FETCH:
- new = gen_fetch(clone_ast_node(AST_FETCH(node).id),
- clone_ast_node(AST_FETCH(node).type),
- node->loc);
- break;
-
- case AST_ASSIGN:
- new = gen_assign(clone_ast_node(AST_ASSIGN(node).to),
- clone_ast_node(AST_ASSIGN(node).from),
- node->loc);
- break;
-
- case AST_INIT: new = gen_init(clone_ast_node(AST_INIT(node).body),
- node->loc);
- break;
-
- case AST_SIZEOF: new = gen_sizeof(clone_ast_node(AST_SIZEOF(node).expr),
- node->loc);
- break;
-
- case AST_DOT: new = gen_dot(clone_ast_node(AST_DOT(node).expr),
- clone_ast_node(AST_DOT(node).id),
- node->loc);
- break;
-
- case AST_AS: new = gen_as(clone_ast_node(AST_AS(node).type), node->loc);
- break;
-
- case AST_GOTO: new = gen_goto(clone_ast_node(AST_GOTO(node).label),
- node->loc);
- break;
-
- case AST_LABEL: new = gen_label(clone_ast_node(AST_LABEL(node).id),
- node->loc);
- break;
-
- case AST_BINOP: new = gen_binop(AST_BINOP(node).op,
- clone_ast_node(AST_BINOP(node).left),
- clone_ast_node(AST_BINOP(node).right),
- node->loc);
- break;
-
- case AST_UNOP: new = gen_unop(AST_UNOP(node).op,
- clone_ast_node(AST_UNOP(node).expr),
- node->loc);
- break;
-
- case AST_CALL: new = gen_call(clone_ast_node(AST_CALL(node).expr),
- clone_ast_node(AST_CALL(node).args),
- node->loc);
- break;
-
- case AST_DEFER: new = gen_defer(clone_ast_node(AST_DEFER(node).expr),
- node->loc);
- break;
-
- case AST_MACRO_CONSTRUCT: new = gen_macro_construct(
- clone_ast_node(AST_MACRO_CONSTRUCT(node).id),
- clone_ast_node(AST_MACRO_CONSTRUCT(node).params),
- clone_ast_node(AST_MACRO_CONSTRUCT(node).body),
- node->loc);
- break;
-
- case AST_MACRO_EXPAND: new = gen_macro_expand(
- clone_ast_node(AST_MACRO_EXPAND(node).id),
- clone_ast_node(AST_MACRO_EXPAND(node).args),
- node->loc);
- break;
-
- case AST_CAST: new = gen_cast(clone_ast_node(AST_CAST(node).expr),
- clone_ast_node(AST_CAST(node).type),
- node->loc);
- break;
-
- case AST_PROC: new = gen_proc(clone_ast_node(AST_PROC(node).id),
- clone_ast_node(AST_PROC(node).sign),
- clone_ast_node(AST_PROC(node).body),
- node->loc);
- break;
-
- case AST_VAR: new = gen_var(clone_ast_node(AST_VAR(node).id),
- clone_ast_node(AST_VAR(node).type),
- clone_ast_node(AST_VAR(node).init),
- node->loc);
- break;
-
- case AST_FOR: new = gen_for(clone_ast_node(AST_FOR(node).pre),
- clone_ast_node(AST_FOR(node).cond),
- clone_ast_node(AST_FOR(node).post),
- clone_ast_node(AST_FOR(node).body),
- node->loc);
- break;
-
- case AST_WHILE: new = gen_while(clone_ast_node(AST_WHILE(node).cond),
- clone_ast_node(AST_WHILE(node).body),
- node->loc);
- break;
-
- case AST_CTRL: new = gen_ctrl(AST_CTRL(node).kind, node->loc);
- break;
-
- case AST_RETURN: new = gen_return(clone_ast_node(AST_RETURN(node).expr),
- node->loc);
- break;
-
- case AST_TYPE:
- switch (node->_type.kind) {
- case AST_TYPE_PRIMITIVE:
- new = gen_primitive(AST_PRIMITIVE_TYPE(node).type,
- AST_PRIMITIVE_TYPE(node).def,
- node->loc);
- break;
-
- case AST_TYPE_TRAIT:
- new = gen_type(AST_TYPE_TRAIT,
- AST_TRAIT_TYPE(node).def,
- NULL,
- node->loc);
- break;
-
- case AST_TYPE_CONSTRUCT:
- new = gen_type(AST_TYPE_CONSTRUCT,
- clone_ast_node(AST_CONSTRUCT_TYPE(
- node).id),
- clone_ast_node(AST_CONSTRUCT_TYPE(
- node).args),
- node->loc);
- break;
-
- case AST_TYPE_ID:
- new = gen_type(AST_TYPE_ID,
- clone_ast_node(AST_ID_TYPE(node).id),
- NULL,
- node->loc);
- break;
-
- case AST_TYPE_ARR:
- new = gen_type(AST_TYPE_ARR,
- clone_ast_node(AST_ARR_TYPE(node).size),
- clone_ast_node(AST_ARR_TYPE(node).base),
- node->loc);
- break;
-
- case AST_TYPE_POINTER:
- new = gen_type(AST_TYPE_POINTER,
- clone_ast_node(AST_PTR_TYPE(node).base),
- NULL,
- node->loc);
- break;
-
- case AST_TYPE_STRUCT:
- new = gen_type(AST_TYPE_STRUCT,
- AST_STRUCT_TYPE(node).def,
- NULL, node->loc);
- break;
-
- case AST_TYPE_ENUM:
- new = gen_type(AST_TYPE_ENUM,
- AST_ENUM_TYPE(node).def,
- NULL,
- node->loc);
- break;
-
- case AST_TYPE_SIGN:
- new = gen_type(AST_TYPE_SIGN,
- clone_ast_node(AST_SIGN_TYPE(
- node).params),
- clone_ast_node(AST_SIGN_TYPE(node).ret),
- node->loc);
- break;
-
- }
-
- assert(new);
- AST_TYPE(new).next = clone_ast_node(AST_TYPE(node).next);
- break;
-
- case AST_BLOCK:
- /* TODO: should defers also be cloned? Probably? */
- new = gen_block(clone_ast_node(AST_BLOCK(node).body),
- node->loc);
- break;
-
- case AST_IMPORT:
- new = gen_import(strdup(AST_IMPORT(node).file), node->loc);
- break;
-
- case AST_EMBED:
- new = gen_embed(strdup(AST_EMBED(node).file), node->loc);
- break;
-
- case AST_ENUM:
- new = gen_enum(clone_ast_node(AST_ENUM(node).id),
- clone_ast_node(AST_ENUM(node).type),
- clone_ast_node(AST_ENUM(node).body),
- node->loc);
- break;
-
- case AST_STRUCT:
- new = gen_struct(clone_ast_node(AST_STRUCT(node).id),
- clone_ast_node(AST_STRUCT(node).generics),
- clone_ast_node(AST_STRUCT(node).body),
- node->loc);
- break;
-
- case AST_VAL:
- new = gen_val(clone_ast_node(AST_VAL(node).id),
- clone_ast_node(AST_VAL(node).val),
- node->loc);
- break;
-
- case AST_SWITCH:
- new = gen_switch(clone_ast_node(AST_SWITCH(node).cond),
- clone_ast_node(AST_SWITCH(node).cases),
- node->loc);
- break;
+ if (!root)
+ return;
- case AST_CASE:
- new = gen_case(clone_ast_node(AST_CASE(node).cond),
- clone_ast_node(AST_CASE(node).body),
- node->loc);
- break;
+ foreach_type(t, root) {
+ type_dump(t);
+ }
+}
- case AST_CONST:
- switch (node->_const.kind) {
- case AST_CONST_INTEGER:
- new = gen_int(AST_CONST(node).integer, node->loc);
- break;
+struct ast *clone_ast(struct ast *n)
+{
+ if (!n)
+ return NULL;
- case AST_CONST_STRING:
- new = gen_string(strdup(AST_CONST(node).str),
- node->loc);
- break;
- }
- break;
+ assert(n->k);
+ struct ast *new = create_empty_ast();
+ new->scope = n->scope;
+ new->uses = n->uses;
+ new->loc = n->loc;
+ new->k = n->k;
+ new->v = n->v;
+ new->f = n->f;
- case AST_ID:
- new = gen_id(strdup(AST_ID(node).id), node->loc);
- break;
+ if (n->t)
+ new->t = clone_type_list(n->t);
- case AST_EMPTY:
- new = gen_empty();
- break;
+ if (n->s)
+ new->s = strdup(n->s);
- case AST_ALIAS:
- new = gen_alias(clone_ast_node(AST_ALIAS(node).id),
- clone_ast_node(AST_ALIAS(node).type),
- node->loc);
- break;
+ if (n->a0)
+ new->a0 = clone_ast_list(n->a0);
- case AST_TRAIT:
- new = gen_trait(clone_ast_node(AST_TRAIT(node).id),
- clone_ast_node(AST_TRAIT(node).params),
- clone_ast_node(AST_TRAIT(node).raw_body),
- clone_ast_node(AST_TRAIT(node).body),
- node->loc);
- break;
+ if (n->a1)
+ new->a1 = clone_ast_list(n->a1);
- case AST_IF:
- new = gen_if(clone_ast_node(AST_IF(node).cond),
- clone_ast_node(AST_IF(node).body),
- clone_ast_node(AST_IF(node).els),
- node->loc);
- break;
- }
+ if (n->a2)
+ new->a2 = clone_ast_list(n->a2);
- /* if we run out of memory, this assert is likely a bit dumb... */
- assert(new);
- new->scope = node->scope;
- new->flags = node->flags;
- new->uses = node->uses;
- new->loc = node->loc;
- new->next = clone_ast_node(node->next);
+ if (n->a3)
+ new->a3 = clone_ast_list(n->a3);
- if (node->type != node)
- node->type = clone_ast_node(node->type);
- else
- node->type = node;
+ if (n->t2)
+ new->t2 = clone_type_list(n->t2);
return new;
}
-unsigned ast_flags(struct ast_node *node, enum ast_flag flags)
-{
- return node->flags & flags;
-}
-
-static int call_on_assign(int (*call)(struct ast_node *,
- void *), struct ast_node *node,
- void *data)
-{
- int ret = 0;
- ret |= call(AST_ASSIGN(node).to, data);
- ret |= call(AST_ASSIGN(node).from, data);
- return ret;
-}
-
-static int call_on_init(int (*call)(struct ast_node *,
- void *), struct ast_node *node, void *data)
-{
- return call(AST_INIT(node).body, data);
-}
-
-static int call_on_sizeof(int (*call)(struct ast_node *,
- void *), struct ast_node *node,
- void *data)
+struct type *clone_type(struct type *n)
{
- return call(AST_SIZEOF(node).expr, data);
-}
+ if (!n)
+ return NULL;
-static int call_on_dot(int (*call)(struct ast_node *,
- void *), struct ast_node *node, void *data)
-{
- int ret = 0;
- ret |= call(AST_DOT(node).expr, data);
- ret |= call(AST_DOT(node).id, data);
- return ret;
-}
+ assert(n->k);
+ struct type *new = create_empty_type();
+ new->scope = n->scope;
+ new->loc = n->loc;
+ new->k = n->k;
+ new->a = n->a;
+ new->d = n->d;
-static int call_on_as(int (*call)(struct ast_node *,
- void *), struct ast_node *node, void *data)
-{
- return call(AST_AS(node).type, data);
-}
+ if (n->id)
+ new->id = strdup(n->id);
-static int call_on_cast(int (*call)(struct ast_node *,
- void *), struct ast_node *node, void *data)
-{
- int ret = 0;
- ret |= call(AST_CAST(node).expr, data);
- ret |= call(AST_CAST(node).type, data);
- return ret;
-}
+ if (n->t0)
+ new->t0 = clone_type_list(n->t0);
-static int call_on_defer(int (*call)(struct ast_node *,
- void *), struct ast_node *node, void *data)
-{
- return call(AST_DEFER(node).expr, data);
-}
+ if (n->t1)
+ new->t1 = clone_type_list(n->t1);
-static int call_on_var(int (*call)(struct ast_node *,
- void *), struct ast_node *node, void *data)
-{
- int ret = 0;
- ret |= call(AST_VAR(node).id, data);
- ret |= call(AST_VAR(node).type, data);
- ret |= call(AST_VAR(node).init, data);
- return ret;
-}
-
-static int call_on_for(int (*call)(struct ast_node *,
- void *), struct ast_node *node, void *data)
-{
- int ret = 0;
- ret |= call(node->_for.pre, data);
- ret |= call(node->_for.cond, data);
- ret |= call(node->_for.post, data);
- ret |= call(node->_for.body, data);
- return ret;
+ return new;
}
-static int call_on_while(int (*call)(struct ast_node *,
- void *), struct ast_node *node, void *data)
+struct ast *clone_ast_list(struct ast *root)
{
- int ret = 0;
- ret |= call(node->_while.cond, data);
- ret |= call(node->_while.body, data);
- return ret;
-}
+ struct ast *n = root, *new_root = NULL, *prev = NULL;
+ while (n) {
+ struct ast *new = clone_ast(n);
-static int call_on_return(int (*call)(struct ast_node *,
- void *), struct ast_node *node,
- void *data)
-{
- return call(node->_return.expr, data);
-}
+ if (prev) prev->n = new;
+ else new_root = new;
-static int call_on_alias(int (*call)(struct ast_node *,
- void *), struct ast_node *node, void *data)
-{
- int ret = 0;
- ret |= call(node->_alias.id, data);
- ret |= call(node->_alias.type, data);
- return ret;
-}
+ prev = new;
+ n = n->n;
+ }
-static int call_on_trait(int (*call)(struct ast_node *,
- void *), struct ast_node *node, void *data)
-{
- int ret = 0;
- ret |= call(node->_trait.id, data);
- ret |= call(node->_trait.body, data);
- return ret;
+ return new_root;
}
-static int call_on_if(int (*call)(struct ast_node *,
- void *), struct ast_node *node, void *data)
+struct type *clone_type_list(struct type *root)
{
- int ret = 0;
- ret |= call(node->_if.cond, data);
- ret |= call(node->_if.body, data);
- ret |= call(node->_if.els, data);
- return ret;
-}
+ struct type *n = root, *new_root = NULL, *prev = NULL;
+ while (n) {
+ struct type *new = clone_type(n);
-static int call_on_enum(int (*call)(struct ast_node *,
- void *), struct ast_node *node, void *data)
-{
- int ret = 0;
- ret |= call(node->_enum.id, data);
- ret |= call(node->_enum.type, data);
- ret |= call(node->_enum.body, data);
- return ret;
-}
+ if (prev) prev->n = new;
+ else new_root = new;
-static int call_on_struct(int (*call)(struct ast_node *,
- void *), struct ast_node *node,
- void *data)
-{
- int ret = 0;
- ret |= call(node->_struct.id, data);
- ret |= call(node->_struct.generics, data);
- ret |= call(node->_struct.body, data);
- return ret;
-}
+ prev = new;
+ n = n->n;
+ }
-static int call_on_val(int (*call)(struct ast_node *,
- void *), struct ast_node *node, void *data)
-{
- int ret = 0;
- ret |= call(node->_val.id, data);
- ret |= call(node->_val.val, data);
- return ret;
+ return new_root;
}
-static int call_on_switch(int (*call)(struct ast_node *,
- void *), struct ast_node *node,
- void *data)
+int type_visit(type_callback_t before, type_callback_t after, struct type *n, void *d)
{
int ret = 0;
- ret |= call(node->_switch.cond, data);
- ret |= call(node->_switch.cases, data);
- return ret;
-}
+ if (!n)
+ return ret;
-static int call_on_case(int (*call)(struct ast_node *,
- void *), struct ast_node *node, void *data)
-{
- int ret = 0;
- ret |= call(node->_case.cond, data);
- ret |= call(node->_case.body, data);
- return ret;
-}
+ if (before && (ret = before(n, d)))
+ return ret;
-static int call_on_type_id(int (*call)(struct ast_node *,
- void *), struct ast_node *node,
- void *data)
-{
- return call(AST_ID_TYPE(node).id, data);
-}
+ if (n->t0 && (ret = type_visit_list(before, after, n->t0, d)))
+ return ret;
-static int call_on_type_arr(int (*call)(struct ast_node *,
- void *), struct ast_node *node,
- void *data)
-{
- return call(AST_ARR_TYPE(node).size, data);
-}
+ if (n->t1 && (ret = type_visit_list(before, after, n->t1, d)))
+ return ret;
-static int call_on_type_sign(int (*call)(struct ast_node *,
- void *), struct ast_node *node,
- void *data)
-{
- int ret = 0;
- ret |= call(AST_SIGN_TYPE(node).params, data);
- ret |= call(AST_SIGN_TYPE(node).ret, data);
- return ret;
-}
+ if (after && (ret = after(n, d)))
+ return ret;
-static int call_on_type_construct(int (*call)(struct ast_node *, void *),
- struct ast_node *node, void *data)
-{
- int ret = 0;
- ret |= call(AST_CONSTRUCT_TYPE(node).id, data);
- ret |= call(AST_CONSTRUCT_TYPE(node).args, data);
return ret;
}
-static int call_on_type_pointer(int (*call)(struct ast_node *, void *),
- struct ast_node *node, void *data)
-{
- return call(AST_PTR_TYPE(node).base, data);
-}
-
-static int call_on_type(int (*call)(struct ast_node *, void *),
- struct ast_node *node, void *data)
+int ast_visit(ast_callback_t before, ast_callback_t after, struct ast *n, void *d)
{
int ret = 0;
- switch (AST_TYPE(node).kind) {
- case AST_TYPE_ENUM: break;
- case AST_TYPE_TRAIT: break;
- case AST_TYPE_ID: ret = call_on_type_id(call, node, data); break;
- case AST_TYPE_ARR: ret = call_on_type_arr(call, node, data); break;
- case AST_TYPE_STRUCT: break;
- case AST_TYPE_SIGN: ret = call_on_type_sign(call, node, data); break;
- case AST_TYPE_CONSTRUCT: ret = call_on_type_construct(call, node, data);
- break;
- case AST_TYPE_POINTER: ret = call_on_type_pointer(call, node, data);
- break;
- case AST_TYPE_PRIMITIVE: break;
- }
-
- return ret;
-}
-
-static int call_on_goto(int (*call)(struct ast_node *,
- void *), struct ast_node *node, void *data)
-{
- return call(AST_GOTO(node).label, data);
-}
-
-static int call_on_label(int (*call)(struct ast_node *,
- void *), struct ast_node *node, void *data)
-{
- return call(AST_LABEL(node).id, data);
-}
+ if (!n)
+ return ret;
-static int call_on_binop(int (*call)(struct ast_node *,
- void *), struct ast_node *node, void *data)
-{
- int ret = 0;
- ret |= call(AST_BINOP(node).left, data);
- ret |= call(AST_BINOP(node).right, data);
- return ret;
-}
+ if (before && (ret = before(n, d)))
+ return ret;
-static int call_on_unop(int (*call)(struct ast_node *,
- void *), struct ast_node *node, void *data)
-{
- return call(AST_UNOP(node).expr, data);
-}
+ if (n->a0 && (ret = ast_visit_list(before, after, n->a0, d)))
+ return ret;
-static int call_on_call(int (*call)(struct ast_node *,
- void *), struct ast_node *node, void *data)
-{
- int ret = 0;
- ret |= call(AST_CALL(node).expr, data);
- ret |= call(AST_CALL(node).args, data);
- return ret;
-}
+ if (n->a1 && (ret = ast_visit_list(before, after, n->a1, d)))
+ return ret;
-static int call_on_macro_construct(int (*call)(struct ast_node *,
- void *), struct ast_node *node,
- void *data)
-{
- int ret = 0;
- ret |= call(AST_MACRO_CONSTRUCT(node).id, data);
- ret |= call(AST_MACRO_CONSTRUCT(node).params, data);
- ret |= call(AST_MACRO_CONSTRUCT(node).body, data);
- return ret;
-}
+ if (n->a2 && (ret = ast_visit_list(before, after, n->a2, d)))
+ return ret;
-static int call_on_proc(int (*call)(struct ast_node *,
- void *), struct ast_node *node, void *data)
-{
- int ret = 0;
- ret |= call(node->_proc.id, data);
- ret |= call(node->_proc.sign, data);
- ret |= call(node->_proc.body, data);
- return ret;
-}
+ if (n->a3 && (ret = ast_visit_list(before, after, n->a3, d)))
+ return ret;
-static int call_on_block(int (*call)(struct ast_node *,
- void *), struct ast_node *node, void *data)
-{
- return call(node->_block.body, data);
-}
+ if (after && (ret = after(n, d)))
+ return ret;
-static int call_on_fetch(int (*call)(struct ast_node *,
- void *), struct ast_node *node, void *data)
-{
- int ret = 0;
- ret |= call(node->_fetch.id, data);
- ret |= call(node->_fetch.type, data);
return ret;
}
-static int call_on_macro_expand(int (*call)(struct ast_node *,
- void *), struct ast_node *node,
- void *data)
+int ast_visit_list(ast_callback_t before, ast_callback_t after, struct ast *l, void *d)
{
int ret = 0;
- ret |= call(node->_macro_expand.id, data);
- ret |= call(node->_macro_expand.args, data);
- return ret;
-}
+ foreach_node(n, l) {
+ if ((ret = ast_visit(before, after, n, d)))
+ return ret;
+ }
-static int call_on_type_expand(int (*call)(struct ast_node *,
- void *),
- struct ast_node *type_expand, void *data)
-{
- int ret = 0;
- ret |= call(AST_TYPE_EXPAND(type_expand).id, data);
- ret |= call(AST_TYPE_EXPAND(type_expand).args, data);
return ret;
}
-/* I guess this works, but it's not exactly optimal as the caller sort of has to
- * know when to continue to call on, and when it would cause an infinite loop.
- * I.e. a call on an ID that is forwarded results in an infinite loop.
- *
- * Maybe add in something like ast_continue_call_on() that can check for the
- * user if there's any point in continuing?
- */
-int ast_call_on(int (*call)(struct ast_node *,
- void *), struct ast_node *node, void *data)
+int type_visit_list(type_callback_t before, type_callback_t after, struct type *l, void *d)
{
int ret = 0;
- if (!node)
- return ret;
-
- switch (node->node_type) {
- case AST_ARR_ACCESS:
- case AST_TYPE_EXPAND: ret = call_on_type_expand(call, node, data);
- break;
- case AST_FETCH: ret = call_on_fetch(call, node, data); break;
- case AST_ASSIGN: ret = call_on_assign(call, node, data); break;
- case AST_INIT: ret = call_on_init(call, node, data); break;
- case AST_SIZEOF: ret = call_on_sizeof(call, node, data); break;
- case AST_DOT: ret = call_on_dot(call, node, data); break;
- case AST_AS: ret = call_on_as(call, node, data); break;
- case AST_CAST: ret = call_on_cast(call, node, data); break;
- case AST_DEFER: ret = call_on_defer(call, node, data); break;
- case AST_VAR: ret = call_on_var(call, node, data); break;
- case AST_FOR: ret = call_on_for(call, node, data); break;
- case AST_WHILE: ret = call_on_while(call, node, data); break;
- case AST_RETURN: ret = call_on_return(call, node, data); break;
- case AST_ALIAS: ret = call_on_alias(call, node, data); break;
- case AST_TRAIT: ret = call_on_trait(call, node, data); break;
- case AST_IF: ret = call_on_if(call, node, data); break;
- case AST_ENUM: ret = call_on_enum(call, node, data); break;
- case AST_STRUCT: ret = call_on_struct(call, node, data); break;
- case AST_VAL: ret = call_on_val(call, node, data); break;
- case AST_SWITCH: ret = call_on_switch(call, node, data); break;
- case AST_CASE: ret = call_on_case(call, node, data); break;
- case AST_TYPE: ret = call_on_type(call, node, data); break;
- case AST_GOTO: ret = call_on_goto(call, node, data); break;
- case AST_LABEL: ret = call_on_label(call, node, data); break;
- case AST_BINOP: ret = call_on_binop(call, node, data); break;
- case AST_UNOP: ret = call_on_unop(call, node, data); break;
- case AST_CALL: ret = call_on_call(call, node, data); break;
- case AST_MACRO_CONSTRUCT: ret =
- call_on_macro_construct(call, node, data); break;
- case AST_MACRO_EXPAND: ret = call_on_macro_expand(call, node, data);
- break;
- case AST_PROC: ret = call_on_proc(call, node, data); break;
- case AST_BLOCK: ret = call_on_block(call, node, data); break;
- case AST_EMBED: break;
- case AST_CTRL: break;
- case AST_IMPORT: break;
- case AST_CONST: break;
- case AST_ID: break;
- case AST_EMPTY: break;
+ foreach_type(n, l) {
+ if ((ret = type_visit(before, after, n, d)))
+ return ret;
}
- ret |= call(node->next, data);
return ret;
}
-size_t ast_list_len(struct ast_node *node)
+size_t ast_list_len(struct ast *node)
{
size_t count = 0;
while (node) {
count++;
- node = node->next;
+ node = node->n;
}
return count;
}
-struct ast_node *ast_last_node(struct ast_node *list)
+struct ast *ast_last(struct ast *list)
{
if (!list)
return NULL;
- while (list->next)
- list = list->next;
+ while (list->n)
+ list = list->n;
return list;
}
-struct ast_node *ast_block_last(struct ast_node *block)
+struct ast *ast_block_last(struct ast *block)
{
- struct ast_node *b = ast_last_node(block);
- if (b && b->node_type == AST_BLOCK)
- return ast_block_last(b->_block.body);
+ struct ast *b = ast_last(block);
+ if (b && b->k == AST_BLOCK)
+ return ast_block_last(block_body(b));
return b;
}
-int same_id(struct ast_node *id1, struct ast_node *id2)
+int same_id(char *id1, char *id2)
{
- assert(id1->node_type == AST_ID);
- assert(id2->node_type == AST_ID);
- return equiv_nodes(id1, id2);
+ return strcmp(id1, id2) == 0;
}
-int equiv_nodes(struct ast_node *n1, struct ast_node *n2)
+int equiv_types(struct type *n1, struct type *n2)
{
- if (n1->node_type != n2->node_type)
+ if (n1 == n2)
+ return 1;
+
+ if (n1 && !n2)
return 0;
- switch (n1->node_type) {
- case AST_ID:
- if (strcmp(AST_ID(n1).id, AST_ID(n2).id) != 0)
- return 0;
+ if (!n1 && n2)
+ return 0;
- break;
- default:
- internal_error("unimplemented equivalency");
+ if (n1->k != n2->k)
+ return 0;
+
+ if (n1->id && strcmp(n1->id, n2->id) != 0)
+ return 0;
+
+ if (n1->t0 && !equiv_type_lists(n1->t0, n2->t0))
+ return 0;
+
+ if (n1->t1 && !equiv_type_lists(n1->t1, n2->t1))
return 0;
- }
return 1;
}
-int equiv_node_chains(struct ast_node *c1, struct ast_node *c2)
+int equiv_nodes(struct ast *n1, struct ast *n2)
{
- if (c1 && !c2)
+ if (n1 && !n2)
return 0;
- if (!c1 && c2)
+
+ if (!n1 && n2)
return 0;
- if (!c1 && !c2)
+ if (!n1 && !n2)
return 1;
+ if (n1->k != n2->k)
+ return 0;
+
+ if (n1->s && strcmp(n1->s, n2->s) != 0)
+ return 0;
+
+ if (n1->a0 && !equiv_node_lists(n1->a0, n2->a0))
+ return 0;
+
+ if (n1->a1 && !equiv_node_lists(n1->a1, n2->a1))
+ return 0;
+
+ if (n1->a2 && !equiv_node_lists(n1->a2, n2->a2))
+ return 0;
+
+ if (n1->a3 && !equiv_node_lists(n1->a3, n2->a3))
+ return 0;
+
+ if (n1->t2 && !equiv_type_lists(n1->t2, n2->t2))
+ return 0;
+
+ return 1;
+}
+
+int equiv_node_lists(struct ast *c1, struct ast *c2)
+{
do {
if (!equiv_nodes(c1, c2))
return 0;
- c1 = c1->next;
- c2 = c2->next;
+ c1 = c1->n;
+ c2 = c2->n;
} while (c1 && c2);
return 1;
}
+
+int equiv_type_lists(struct type *t1, struct type *t2)
+{
+ do {
+ if (!equiv_types(t1, t2))
+ return 0;
+
+ t1 = t1->n;
+ t2 = t2->n;
+
+ } while (t1 && t2);
+
+ return 1;
+}