Files
spl/stage1/spl_ast.c
T

430 lines
13 KiB
C

#include "spl_ast.h"
const char *spl_ast_kind_name(spl_ast_node_kind_t kind) {
static const char *const names[] = {
#define X(a, b, c) #c,
SPL_AST_KIND_TABLE
#undef X
};
if ((usize)kind < sizeof(names) / sizeof(names[0]))
return names[kind];
return "?";
}
const char *spl_binary_op_name(spl_binary_op_t op) {
static const char *const names[] = {
#define X(a, b, c, name) #name,
SPL_BINARY_OP_TABLE
#undef X
};
if ((usize)op < sizeof(names) / sizeof(names[0]))
return names[op];
return "?";
}
const char *spl_unary_op_name(spl_unary_op_t op) {
switch (op) {
case SPL_UNARY_OP_MINUS:
return "neg";
case SPL_UNARY_OP_NOT:
return "not";
case SPL_UNARY_OP_BIT_NOT:
return "bitnot";
case SPL_UNARY_OP_ADDRESS:
return "addr";
case SPL_UNARY_OP_DEREF:
return "deref";
default:
return "?";
}
}
void spl_ast_init(spl_ast_t *ast, const spl_tok_vec_t *tok_vec) {
ast->input = *tok_vec;
vec_init(ast->node_buckets);
vec_init(ast->str_buckets);
ast->root = 0;
spl_ast_node_t n = {0};
vec_push(ast->node_buckets, n);
}
void spl_ast_drop(spl_ast_t *ast) {
if (!ast)
return;
vec_for(ast->str_buckets, idx) { free(vec_at(ast->str_buckets, idx)); }
vec_free(ast->str_buckets);
vec_for(ast->node_buckets, idx) { vec_free(vec_at(ast->node_buckets, idx).attrs); }
vec_free(ast->node_buckets);
vec_free(ast->input);
ast->root = 0;
}
spl_ast_node_t *spl_ast_node(spl_ast_t *ast, spl_ast_node_ref_t node) {
if (!ast || node == 0 || node >= ast->node_buckets.size)
return NULL;
return &ast->node_buckets.data[node];
}
typedef VEC(char) dump_stack_t;
static void dump_node(spl_ast_t *ast, spl_ast_node_ref_t node_ref, dump_stack_t *stack, bool last);
void spl_ast_dump(spl_ast_t *ast, spl_ast_node_ref_t node) {
if (!ast || !node || node >= ast->node_buckets.size)
return;
dump_stack_t stack;
vec_init(stack);
printf("AST:\n");
dump_node(ast, node, &stack, true);
vec_free(stack);
}
#define dump_vec(_ast, _vec, _stack) \
do { \
vec_for(_vec, _i) { dump_node(_ast, vec_at(_vec, _i), _stack, _i + 1 == vec_size(_vec)); } \
} while (0)
static void dump_node(spl_ast_t *ast, spl_ast_node_ref_t node_ref, dump_stack_t *stack, bool last) {
spl_ast_node_t *node = &ast->node_buckets.data[node_ref];
for (usize i = 0; i < vec_size(*stack); i++)
printf("%s", vec_at(*stack, i) ? " " : "| ");
printf("%s%s #%zu", last ? "`-" : "|-", spl_ast_kind_name(node->kind), node_ref);
if (node->dbg.fname)
printf(" [%d:%d]", node->dbg.line, node->dbg.col);
printf("\n");
vec_push(*stack, last);
switch (node->kind) {
case SPL_AST_ROOT:
if (node->root.members)
dump_node(ast, node->root.members, stack, true);
break;
case SPL_AST_CONTAINER_MEMBERS:
dump_vec(ast, node->container_members.external_tags, stack);
dump_vec(ast, node->container_members.declarations, stack);
break;
case SPL_AST_TAG_ITEM:
case SPL_AST_EXTERNAL_TAG_ITEM:
dump_vec(ast, node->tag_item.args, stack);
break;
case SPL_AST_FN_DECL:
dump_vec(ast, node->fn_decl.tag_list, stack);
dump_vec(ast, node->fn_decl.params, stack);
if (node->fn_decl.ret_type)
dump_node(ast, node->fn_decl.ret_type, stack, false);
if (node->fn_decl.body)
dump_node(ast, node->fn_decl.body, stack, true);
break;
case SPL_AST_VAR_DECL:
case SPL_AST_CONST_DECL:
dump_vec(ast, node->var_const_decl.attr_list, stack);
if (node->var_const_decl.pattern)
dump_node(ast, node->var_const_decl.pattern, stack, false);
if (node->var_const_decl.type)
dump_node(ast, node->var_const_decl.type, stack, false);
if (node->var_const_decl.init_expr)
dump_node(ast, node->var_const_decl.init_expr, stack, true);
break;
case SPL_AST_TYPE_DECL:
if (node->type_decl.type_expr)
dump_node(ast, node->type_decl.type_expr, stack, true);
break;
case SPL_AST_MEMBER_DECL:
dump_vec(ast, node->member_decl.attr_list, stack);
if (node->member_decl.type_expr)
dump_node(ast, node->member_decl.type_expr, stack, false);
if (node->member_decl.init_expr)
dump_node(ast, node->member_decl.init_expr, stack, true);
break;
case SPL_AST_PARAM_DECL:
dump_vec(ast, node->param_decl.attr_list, stack);
if (node->param_decl.type_expr)
dump_node(ast, node->param_decl.type_expr, stack, true);
break;
case SPL_AST_COMPTIME_DECL:
if (node->comptime_decl.body)
dump_node(ast, node->comptime_decl.body, stack, true);
break;
case SPL_AST_TOP_LEVEL_BLOCK:
dump_vec(ast, node->top_level_block.tag_list, stack);
if (node->top_level_block.block)
dump_node(ast, node->top_level_block.block, stack, true);
break;
case SPL_AST_STATEMENT_RET:
if (node->statement_ret.expr)
dump_node(ast, node->statement_ret.expr, stack, true);
break;
case SPL_AST_STATEMENT_BREAK:
if (node->statement_break.label)
dump_node(ast, node->statement_break.label, stack, false);
if (node->statement_break.expr)
dump_node(ast, node->statement_break.expr, stack, true);
break;
case SPL_AST_STATEMENT_CONTINUE:
if (node->statement_continue.label)
dump_node(ast, node->statement_continue.label, stack, true);
break;
case SPL_AST_STATEMENT_DEFER:
case SPL_AST_STATEMENT_COMPTIME:
if (node->statement_defer.body)
dump_node(ast, node->statement_defer.body, stack, true);
break;
case SPL_AST_STATEMENT_DECL:
if (node->statement_decl.decl)
dump_node(ast, node->statement_decl.decl, stack, true);
break;
case SPL_AST_STATEMENT_EXPR:
if (node->statement_expr.expr)
dump_node(ast, node->statement_expr.expr, stack, true);
break;
case SPL_AST_AGGREGATE_MEMBER:
dump_vec(ast, node->aggregate_member.attr_list, stack);
if (node->aggregate_member.type_expr)
dump_node(ast, node->aggregate_member.type_expr, stack, false);
if (node->aggregate_member.init_expr)
dump_node(ast, node->aggregate_member.init_expr, stack, true);
break;
case SPL_AST_STRUCT_INIT_ITEM:
if (node->struct_init_item.expr)
dump_node(ast, node->struct_init_item.expr, stack, true);
break;
case SPL_AST_MATCH_ARM:
if (node->match_arm.pattern)
dump_node(ast, node->match_arm.pattern, stack, false);
if (node->match_arm.body)
dump_node(ast, node->match_arm.body, stack, true);
break;
case SPL_AST_LABEL:
break;
case SPL_AST_EXPR_INT_LIT:
case SPL_AST_EXPR_FLOAT_LIT:
case SPL_AST_EXPR_CHAR_LIT:
case SPL_AST_EXPR_STRING_LIT:
case SPL_AST_EXPR_BOOL_LIT:
case SPL_AST_EXPR_NULL_LIT:
case SPL_AST_EXPR_UNDEFINED_LIT:
case SPL_AST_EXPR_IDENT:
break;
case SPL_AST_EXPR_UNARY:
if (node->unary.operand)
dump_node(ast, node->unary.operand, stack, true);
break;
case SPL_AST_EXPR_BINARY:
if (node->binary.left)
dump_node(ast, node->binary.left, stack, false);
if (node->binary.right)
dump_node(ast, node->binary.right, stack, true);
break;
case SPL_AST_EXPR_CALL:
if (node->call.callee)
dump_node(ast, node->call.callee, stack, false);
dump_vec(ast, node->call.args, stack);
break;
case SPL_AST_EXPR_FIELD:
if (node->field.obj)
dump_node(ast, node->field.obj, stack, true);
break;
case SPL_AST_EXPR_INDEX:
if (node->index.obj)
dump_node(ast, node->index.obj, stack, false);
if (node->index.index)
dump_node(ast, node->index.index, stack, true);
break;
case SPL_AST_EXPR_SLICE:
if (node->slice.obj)
dump_node(ast, node->slice.obj, stack, false);
if (node->slice.begin)
dump_node(ast, node->slice.begin, stack, false);
if (node->slice.end)
dump_node(ast, node->slice.end, stack, true);
break;
case SPL_AST_EXPR_CAST:
if (node->cast.expr)
dump_node(ast, node->cast.expr, stack, false);
if (node->cast.type)
dump_node(ast, node->cast.type, stack, true);
break;
case SPL_AST_EXPR_TUPLE:
dump_vec(ast, node->tuple.elems, stack);
break;
case SPL_AST_EXPR_ARRAY_LIT:
if (node->array_literal.elem_type)
dump_node(ast, node->array_literal.elem_type, stack, false);
dump_vec(ast, node->array_literal.elems, stack);
break;
case SPL_AST_EXPR_AGGREGATE_LIT:
dump_vec(ast, node->aggregate_literal.fields, stack);
break;
case SPL_AST_EXPR_COMPTIME_CALL:
dump_vec(ast, node->comptime_call.args, stack);
break;
case SPL_AST_EXPR_BLOCK:
dump_vec(ast, node->block.stmts, stack);
if (node->block.tail_expr)
dump_node(ast, node->block.tail_expr, stack, true);
break;
case SPL_AST_EXPR_IF:
if (node->if_expr.cond)
dump_node(ast, node->if_expr.cond, stack, false);
if (node->if_expr.then_block)
dump_node(ast, node->if_expr.then_block, stack, false);
if (node->if_expr.else_branch)
dump_node(ast, node->if_expr.else_branch, stack, true);
break;
case SPL_AST_EXPR_IFVAR:
if (node->ifvar_expr.var_decl)
dump_node(ast, node->ifvar_expr.var_decl, stack, false);
if (node->ifvar_expr.then_block)
dump_node(ast, node->ifvar_expr.then_block, stack, false);
if (node->ifvar_expr.else_branch)
dump_node(ast, node->ifvar_expr.else_branch, stack, true);
break;
case SPL_AST_EXPR_WHILE:
if (node->while_expr.label)
dump_node(ast, node->while_expr.label, stack, false);
if (node->while_expr.cond)
dump_node(ast, node->while_expr.cond, stack, false);
if (node->while_expr.body)
dump_node(ast, node->while_expr.body, stack, false);
if (node->while_expr.else_branch)
dump_node(ast, node->while_expr.else_branch, stack, true);
break;
case SPL_AST_EXPR_LOOP:
if (node->loop_expr.label)
dump_node(ast, node->loop_expr.label, stack, false);
if (node->loop_expr.body)
dump_node(ast, node->loop_expr.body, stack, true);
break;
case SPL_AST_EXPR_FOR:
if (node->for_expr.label)
dump_node(ast, node->for_expr.label, stack, false);
dump_vec(ast, node->for_expr.iter_exprs, stack);
if (node->for_expr.pattern)
dump_node(ast, node->for_expr.pattern, stack, false);
if (node->for_expr.body)
dump_node(ast, node->for_expr.body, stack, false);
if (node->for_expr.else_branch)
dump_node(ast, node->for_expr.else_branch, stack, true);
break;
case SPL_AST_EXPR_MATCH:
if (node->match_expr.matched_expr)
dump_node(ast, node->match_expr.matched_expr, stack, false);
dump_vec(ast, node->match_expr.arms, stack);
break;
case SPL_AST_EXPR_FN_TYPE:
dump_vec(ast, node->fn_type.params, stack);
if (node->fn_type.ret_type)
dump_node(ast, node->fn_type.ret_type, stack, true);
break;
case SPL_AST_TYPE_PATH:
break;
case SPL_AST_TYPE_POINTER:
if (node->type_pointer.pointee)
dump_node(ast, node->type_pointer.pointee, stack, true);
break;
case SPL_AST_TYPE_ARRAY:
if (node->type_array.elem_type)
dump_node(ast, node->type_array.elem_type, stack, true);
break;
case SPL_AST_TYPE_SLICE:
if (node->type_slice.elem_type)
dump_node(ast, node->type_slice.elem_type, stack, true);
break;
case SPL_AST_TYPE_FN:
dump_vec(ast, node->type_fn.params, stack);
if (node->type_fn.ret_type)
dump_node(ast, node->type_fn.ret_type, stack, true);
break;
case SPL_AST_TYPE_PAREN:
dump_vec(ast, node->type_paren.types, stack);
break;
case SPL_AST_TYPE_AGGREGATE:
dump_vec(ast, node->type_aggregate.members, stack);
break;
case SPL_AST_TYPE_COMPTIME_CALL:
dump_vec(ast, node->type_comptime_call.args, stack);
break;
case SPL_AST_PATTERN_IDENT:
case SPL_AST_PATTERN_UNDERSCORE:
break;
case SPL_AST_PATTERN_DOT:
if (node->pattern_dot.sub_pattern)
dump_node(ast, node->pattern_dot.sub_pattern, stack, true);
break;
case SPL_AST_PATTERN_TUPLE:
dump_vec(ast, node->pattern_tuple.patterns, stack);
break;
case SPL_AST_PATTERN_LIST:
dump_vec(ast, node->pattern_list.patterns, stack);
break;
case SPL_AST_PATTERN_AGGREGATE:
dump_vec(ast, node->pattern_aggregate.fields, stack);
break;
case SPL_AST_PATTERN_FIELD:
if (node->pattern_field.pattern)
dump_node(ast, node->pattern_field.pattern, stack, true);
break;
default:
break;
}
(void)vec_pop(*stack);
}