//----------------------------------------------------------------------------- // 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.type = 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; } //----------------------------------------------------------------------------- // Statements //----------------------------------------------------------------------------- function Stmt * stmt_new(Parser *p, Stmt_Kind kind, Token *pos){ Stmt *result = arena_push_struct(&p->main_arena, Stmt); result->kind = kind; result->pos = pos; return result; } function Stmt * stmt_decl(Parser *p, Token *pos, Decl *decl){ Stmt *result = stmt_new(p, STMT_Decl, pos); result->decl = decl; return result; } function Stmt * stmt_expr(Parser *p, Token *pos, Expr *expr){ Stmt *result = stmt_new(p, STMT_Expr, pos); result->expr = expr; return result; } function Stmt * stmt_list(Parser *p, Token *pos){ Stmt *result = stmt_new(p, STMT_List, pos); return result; } function Stmt * stmt_return(Parser *p, Token *pos, Expr *expr){ Stmt *result = stmt_new(p, STMT_Return, pos); result->ret.expr = expr; return result; } function Stmt * stmt_if(Parser *p, Token *pos, Stmt *body, Expr *cond){ Stmt *result = stmt_new(p, STMT_If, pos); result->stmt_if.cond = cond; result->stmt_if.body = body; return result; } function void stmt_push(Stmt *stmt, Stmt *child){ SLLQueuePush(stmt->list.first, stmt->list.last, child); } //----------------------------------------------------------------------------- // 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; }