Files
corelang/ast.c
Krzosa Karol 042127239e AST idea
2022-05-07 15:48:53 +02:00

578 lines
17 KiB
C

//-----------------------------------------------------------------------------
// Decls
//-----------------------------------------------------------------------------
function Decl *
decl_new(Parser *p, Decl_Kind kind, Token *pos, Intern_String name){
Decl *result = arena_push_struct(&p->main_arena, Decl);
result->kind = kind;
result->pos = pos;
result->name = name;
return result;
}
function Decl *
decl_struct(Parser *p, Decl_Kind kind, Token *pos, Intern_String name, Decl_Struct_Kind struct_kind){
assert(kind == DECL_Struct || kind == DECL_Union);
Decl *result = decl_new(p, kind, pos, name);
result->struct_decl.kind = struct_kind;
return result;
}
function Decl *
decl_typedef(Parser *p, Token *pos, Intern_String name, Typespec *type){
Decl *result = decl_new(p, DECL_Typedef, pos, name);
result->typedef_decl.typespec = type;
return result;
}
function Decl *
decl_enum(Parser *p, Token *pos, Intern_String name, Typespec *typespec){
Decl *result = decl_new(p, DECL_Enum, pos, name);
result->enum_decl.typespec = typespec;
return result;
}
function Decl *
decl_variable(Parser *p, Token *pos, Intern_String name, Typespec *typespec, Expr *expr){
Decl *result = decl_new(p, DECL_Variable, pos, name);
result->variable_decl.type = typespec;
result->variable_decl.expr = expr;
return result;
}
function Decl *
decl_function(Parser *p, Token *pos, Intern_String name, Typespec *ret){
Decl *result = decl_new(p, DECL_Function, pos, name);
result->function_decl.ret = ret;
return result;
}
function void
decl_function_push(Parser *p, Decl *parent, Token *pos, Intern_String name, Typespec *type){
assert(parent->kind == DECL_Function);
Decl_Function_Arg *result = arena_push_struct(&p->main_arena, Decl_Function_Arg);
result->name = name;
result->typespec = type;
result->pos = pos;
SLLQueuePush(parent->function_decl.first, parent->function_decl.last, result);
}
function void
decl_enum_push(Parser *p, Decl *parent, Token *pos, Intern_String name, Expr *expr, Note *notes){
assert(parent->kind == DECL_Enum);
Decl_Enum_Child *child = arena_push_struct(&p->main_arena, Decl_Enum_Child);
child->pos = pos;
child->name = name;
child->expr = expr;
child->first_note = notes->first;
child->last_note = notes->last;
SLLQueuePush(parent->enum_decl.first, parent->enum_decl.last, child);
}
function void
decl_struct_push(Decl *parent, Decl *child){
assert(parent->kind == DECL_Struct || parent->kind == DECL_Union);
SLLQueuePush(parent->struct_decl.first, parent->struct_decl.last, child);
}
function void
decl_list_push(Decl *parent, Decl *child){
assert(parent->kind == DECL_List);
SLLQueuePush(parent->list.first, parent->list.last, child);
}
//-----------------------------------------------------------------------------
// Ops
//-----------------------------------------------------------------------------
function Decl *
decl_struct_find_node(Decl *decl, String string){
for(Decl *n = decl->struct_decl.first; n; n=n->next){
if(string_compare(string, n->name.s)){
return n;
}
}
return 0;
}
//-----------------------------------------------------------------------------
// Notes
//-----------------------------------------------------------------------------
function void
decl_pass_notes(Decl *a, Note *b){
a->first_note = b->first;
a->last_note = b->last;
}
function Note *
note_push_new(Parser *p, Note *parent, Token *pos, Intern_String name, Expr *expr){
Note *result = arena_push_struct(&p->main_arena, Note);
result->pos = pos;
result->name = name;
result->expr = expr;
SLLQueuePush(parent->first, parent->last, result);
return result;
}
function Note *
find_note(Note *first, String string){
for(Note *n = first; n; n=n->next){
if(string_compare(string, n->name.s)){
return n;
}
}
return 0;
}
function String
find_string_note(Note *first, String string, String default_string){
Note *note = find_note(first, string);
if(note){
return note->expr->token->intern_val.s;
}
return default_string;
}
function Note *
decl_find_note(Decl *decl, String string){
return find_note(decl->first_note, string);
}
function String
decl_find_string_note(Decl *decl, String string, String default_string){
return find_string_note(decl->first_note, string, default_string);
}
//-----------------------------------------------------------------------------
// Typespec
//-----------------------------------------------------------------------------
function Typespec *
typespec_new(Parser *p, Typespec_Kind kind, Token *pos){
Typespec *result = arena_push_struct(&p->main_arena, Typespec);
result->kind = kind;
result->pos = pos;
return result;
}
function Typespec *
typespec_name(Parser *p, Token *pos, Intern_String name){
Typespec *result = typespec_new(p, TS_Name, pos);
result->name = name;
return result;
}
function Typespec *
typespec_pointer(Parser *p, Token *pos, Typespec *base){
Typespec *result = typespec_new(p, TS_Pointer, pos);
result->base = base;
return result;
}
function Typespec *
typespec_array(Parser *p, Token *pos, Typespec *base, Expr *size){
Typespec *result = typespec_new(p, TS_Array, pos);
result->array_spec.base = base;
result->array_spec.size = size;
return result;
}
function Typespec *
typespec_function(Parser *p, Token *pos, Typespec *ret){
Typespec *result = typespec_new(p, TS_Function, pos);
result->function_spec.ret = ret;
return result;
}
function void
typespec_function_push(Typespec *func, Typespec *arg){
SLLQueuePush(func->function_spec.first, func->function_spec.last, arg);
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
function Typespec *
typespec_get_func(Typespec *type){
switch(type->kind){
case TS_Name:{return 0;} break;
case TS_Pointer:{return typespec_get_func(type->base);} break;
case TS_Array:{return typespec_get_func(type->array_spec.base);} break;
case TS_Function:{return type;} break;
default: {invalid_codepath;} break;
}
return 0;
}
function Typespec *
typespec_get_name(Typespec *type){
switch(type->kind){
case TS_Name:{return type;} break;
case TS_Pointer:{return typespec_get_name(type->base);} break;
case TS_Array:{return typespec_get_name(type->array_spec.base);} break;
case TS_Function:{return 0;} break;
default: {invalid_codepath;} break;
}
return 0;
}
function String
typespec_require_name_string(Typespec *type){
Typespec *result = typespec_get_name(type);
if(result){
if(result->kind == TS_Name){
return result->name.s;
}
}
invalid_codepath;
return string_empty;
}
//-----------------------------------------------------------------------------
// Pointer Array
//-----------------------------------------------------------------------------
function Pointer_Array
pointer_array_make(Arena *arena){
Pointer_Array result = {
.last = &result.first,
.arena = arena,
};
return result;
}
#define bucket_size (buff_cap(array->first.data))
function void
pointer_array_push(Pointer_Array *array, Pointer p){
if(array->len >= bucket_size){
Pointer_Bucket *bucket = arena_push_struct(array->arena, Pointer_Bucket);
array->last = array->last->next = bucket;
array->len = 0;
array->block += 1;
}
array->last->data[array->len++] = p;
}
function B32
pointer_array_iter_is_end(Pointer_Array *array){
B32 result = array->iter_len == array->len && array->iter_block == array->block;
return result;
}
function Pointer
pointer_array_iter_next(Pointer_Array *array){
if(pointer_array_iter_is_end(array)){
return (Pointer){0};
}
if(array->iter_len >= bucket_size){
array->iter_len = 0;
array->iter_block += 1;
array->iter_bucket = array->iter_bucket->next;
}
Pointer result = array->iter_bucket->data[array->iter_len++];
return result;
}
function Pointer
pointer_array_iter_begin(Pointer_Array *array){
array->iter_len = 0;
array->iter_block = 0;
array->iter_bucket = &array->first;
Pointer result = pointer_array_iter_next(array);
return result;
}
function Pointer
pointer_typespec(Typespec *t){
return (Pointer){.kind = PK_Typespec, .typespec = t};
}
function Pointer
pointer_expr(Expr *t){
return (Pointer){.kind = PK_Expr, .expr = t};
}
function Pointer
pointer_decl(Decl *t){
return (Pointer){.kind = PK_Decl, .decl = t};
}
function Pointer
pointer_stmt(Stmt *t){
return (Pointer){.kind = PK_Stmt, .stmt = t};
}
function Pointer
pointer_enum_child(Decl_Enum_Child *t){
return (Pointer){.kind = PK_Enum_Child, .enum_child = t};
}
function Pointer
pointer_func_arg(Decl_Function_Arg *t){
return (Pointer){.kind = PK_Func_Arg, .func_arg=t};
}
function void
pointer_array_push_typespec(Pointer_Array *array, Typespec *typespec){
pointer_array_push(array, pointer_typespec(typespec));
}
function void
pointer_array_push_decl(Pointer_Array *array, Decl *decl){
pointer_array_push(array, pointer_decl(decl));
}
function void
pointer_array_push_stmt(Pointer_Array *array, Stmt *stmt){
pointer_array_push(array, pointer_stmt(stmt));
}
function void
pointer_array_push_expr(Pointer_Array *array, Expr *expr){
pointer_array_push(array, pointer_expr(expr));
}
function void
pointer_array_push_enum_child(Pointer_Array *array, Decl_Enum_Child *enum_child){
pointer_array_push(array, pointer_enum_child(enum_child));
}
function void
pointer_array_push_func_arg(Pointer_Array *array, Decl_Function_Arg *func_arg){
pointer_array_push(array, pointer_func_arg(func_arg));
}
//-----------------------------------------------------------------------------
// Gather
//-----------------------------------------------------------------------------
function void
gather_try_recurse_typespec(Pointer_Array *array, Typespec *typespec, Gather_Flag gflag, Traversal_Flag tflag);
function void
gather_recurse_expr(Pointer_Array *array, Expr *expr, Gather_Flag gflag, Traversal_Flag tflag){
if(gflag & GATHER_Expr)
pointer_array_push_expr(array, expr);
switch(expr->kind) {
case EK_Atom: {} break;
case EK_Sizeof:{
if(expr->size_of.kind == SIZEOF_Expr){
gather_recurse_expr(array, expr->size_of.expr, gflag, tflag);
}
else{
assert(expr->size_of.kind == SIZEOF_Type);
gather_try_recurse_typespec(array, expr->size_of.type, gflag, tflag);
}
}break;
case EK_Binary:{
gather_recurse_expr(array, expr->binary.left, gflag, tflag);
gather_recurse_expr(array, expr->binary.right, gflag, tflag);
} break;
case EK_Unary:{
gather_recurse_expr(array, expr->unary.expr, gflag, tflag);
} break;
case EK_Ternary:{
gather_recurse_expr(array, expr->ternary.cond, gflag, tflag);
gather_recurse_expr(array, expr->ternary.on_true, gflag, tflag);
gather_recurse_expr(array, expr->ternary.on_false, gflag, tflag);
} break;
case EK_List:{
for(Expr *n = expr->list.first; n; n=n->next){
gather_recurse_expr(array, n, gflag, tflag);
}
}break;
case EK_Cast:{
gather_try_recurse_typespec(array, expr->cast.type, gflag, tflag);
gather_recurse_expr(array, expr->cast.expr, gflag, tflag);
} break;
case EK_Index:{
gather_recurse_expr(array, expr->index.atom, gflag, tflag);
gather_recurse_expr(array, expr->index.index, gflag, tflag);
}break;
case EK_Call:{
gather_recurse_expr(array, expr->call.atom, gflag, tflag);
gather_recurse_expr(array, expr->call.list, gflag, tflag);
}break;
default: {invalid_codepath;} break;
}
}
function void
gather_try_recurse_expr(Pointer_Array *array, Expr *expr, Gather_Flag gflag, Traversal_Flag tflag){
if(expr){
if(tflag & TRAVERS_Expr){
gather_recurse_expr(array, expr, gflag, tflag);
}
else if(gflag & GATHER_Expr){
pointer_array_push_expr(array, expr);
}
}
}
function void
gather_recurse_decl(Pointer_Array *array, Decl *decl, Gather_Flag gflag, Traversal_Flag tflag);
function void
gather_try_recurse_stmt(Pointer_Array *array, Stmt *stmt, Gather_Flag gflag, Traversal_Flag tflag);
function void
gather_recurse_stmt(Pointer_Array *array, Stmt *stmt, Gather_Flag gflag, Traversal_Flag tflag){
switch(stmt->kind) {
case STMT_List: {
for(Stmt *s = stmt->list.first; s; s=s->next){
gather_recurse_stmt(array, s, gflag, tflag);
}
} break;
case STMT_Return:{
gather_try_recurse_expr(array, stmt->ret.expr, gflag, tflag);
} break;
case STMT_If:{
gather_recurse_expr(array, stmt->stmt_if.cond, gflag, tflag);
gather_recurse_stmt(array, stmt->stmt_if.body, gflag, tflag);
for(Stmt_If *s = stmt->stmt_if.next; s; s=s->next){
gather_recurse_stmt(array, s->body, gflag, tflag);
gather_recurse_expr(array, s->cond, gflag, tflag);
}
} break;
case STMT_Expr: {
gather_recurse_expr(array, stmt->expr, gflag, tflag);
} break;
case STMT_Decl: {
gather_recurse_decl(array, stmt->decl, gflag, tflag);
} break;
default: {invalid_codepath;} break;
}
}
function void
gather_try_recurse_stmt(Pointer_Array *array, Stmt *stmt, Gather_Flag gflag, Traversal_Flag tflag){
if(stmt){
if(tflag & TRAVERS_Stmt){
gather_recurse_stmt(array, stmt, gflag, tflag);
}
else if(gflag & GATHER_Stmt){
pointer_array_push_stmt(array, stmt);
}
}
}
function void
gather_recurse_typespec(Pointer_Array *array, Typespec *typespec, Gather_Flag gflag, Traversal_Flag tflag){
if(gflag & GATHER_Typespec)
pointer_array_push_typespec(array, typespec);
switch(typespec->kind) {
case TS_Name: {
} break;
case TS_Pointer: {
gather_recurse_typespec(array, typespec->base, gflag, tflag);
} break;
case TS_Array: {
gather_recurse_typespec(array, typespec->array_spec.base, gflag, tflag);
gather_try_recurse_expr(array, typespec->array_spec.size, gflag, tflag);
} break;
case TS_Function: {
gather_recurse_typespec(array, typespec->function_spec.ret, gflag, tflag);
for(Typespec *n = typespec->function_spec.first; n; n=n->next){
gather_recurse_typespec(array, n, gflag, tflag);
}
} break;
default: {invalid_codepath;} break;
}
}
function void
gather_try_recurse_typespec(Pointer_Array *array, Typespec *typespec, Gather_Flag gflag, Traversal_Flag tflag){
if(typespec){
if(tflag & TRAVERS_Typespec){
gather_recurse_typespec(array, typespec, gflag, tflag);
}
else if(gflag & GATHER_Typespec){
pointer_array_push_typespec(array, typespec);
}
}
}
function void
gather_recurse_decl(Pointer_Array *array, Decl *decl, Gather_Flag gflag, Traversal_Flag tflag){
if(gflag & GATHER_Decl) pointer_array_push_decl(array, decl);
switch(decl->kind){
case DECL_Struct:
case DECL_Union:{
for(Decl *n = decl->struct_decl.first; n; n=n->next){
gather_recurse_decl(array, n, gflag, tflag);
}
} break;
case DECL_Enum:{
gather_try_recurse_typespec(array, decl->enum_decl.typespec, gflag, tflag);
for(Decl_Enum_Child *child = decl->enum_decl.first; child; child=child->next){
if(gflag & GATHER_Enum_Child) pointer_array_push_enum_child(array, child);
gather_try_recurse_expr(array, child->expr, gflag, tflag);
}
}break;
case DECL_Variable:{
gather_try_recurse_typespec(array, decl->variable_decl.type, gflag, tflag);
gather_try_recurse_expr(array, decl->variable_decl.expr, gflag, tflag);
}break;
case DECL_Typedef:{
gather_try_recurse_typespec(array, decl->typedef_decl.type, gflag, tflag);
}break;
case DECL_Function:{
gather_try_recurse_typespec(array, decl->function_decl.ret, gflag, tflag);
for(Decl_Function_Arg *arg = decl->function_decl.first; arg; arg=arg->next){
if(gflag & GATHER_Func_Arg) pointer_array_push_func_arg(array, arg);
gather_try_recurse_typespec(array, arg->typespec, gflag, tflag);
}
gather_try_recurse_stmt(array, decl->function_decl.body, gflag, tflag);
}break;
case DECL_List:{
for(Decl *n = decl->list.first; n; n=n->next){
gather_recurse_decl(array, n, gflag, tflag);
}
}break;
default:invalid_codepath;
}
}
function Pointer_Array
gather(Arena *arena, Decl *decl, Gather_Flag gflag, Traversal_Flag tflag){
Pointer_Array array = pointer_array_make(arena);
gather_recurse_decl(&array, decl, gflag, tflag);
return array;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
function Decl *
decl_deep_copy_recurse(Arena *arena, Decl *decl){
Decl *result = arena_push_struct(arena, Decl);
memory_copy(result, decl, sizeof(*decl));
switch(decl->kind) {
case DECL_Struct:{
}break;
case DECL_Union:{
}break;
case DECL_Enum:{
}break;
case DECL_Variable:{
}break;
case DECL_Typedef:{
}break;
case DECL_Function:{
}break;
case DECL_List:{
}break;
default: {invalid_codepath;} break;
}
return result;
}
function Decl *
decl_deep_copy(Arena *arena){
Decl *result = decl_deep_copy_recurse(arena, decl);
return result;
}