typedef struct Expr Expr; typedef struct Note Note; typedef struct Decl Decl; typedef struct Stmt Stmt; typedef struct Stmt_If Stmt_If; typedef struct Typespec Typespec; typedef struct Typespec_Function_Arg Typespec_Function_Arg; typedef struct Decl_Enum_Child Decl_Enum_Child; typedef struct Decl_Function_Arg Decl_Function_Arg; typedef struct Expr_Compound_Field Expr_Compound_Field; //----------------------------------------------------------------------------- // Expressions //----------------------------------------------------------------------------- typedef enum Expr_Sizeof_Kind{ SIZEOF_Expr, SIZEOF_Type, }Expr_Sizeof_Kind; typedef enum Expr_Kind{ EK_None, EK_Int, EK_String, EK_Identifier, EK_Compound, EK_Paren, EK_PostfixUnary, EK_Unary, EK_Binary, EK_Ternary, EK_Cast, EK_Field, EK_Call, EK_Index, EK_SizeType, EK_SizeExpr, } Expr_Kind; typedef enum Expr_Compound_Kind{ COMPOUND_None, COMPOUND_Default, COMPOUND_Named, COMPOUND_Index, }Expr_Compound_Kind; struct Expr_Compound_Field{ Expr_Compound_Field *next; Expr_Compound_Kind kind; Token *pos; Expr *init; union{ Expr *index; Intern_String name; }; }; struct Expr { Expr_Kind kind; Token *token; Expr *next; union { U64 int_val; Intern_String intern_val; double float_val; struct { Expr *expr; } paren; struct { Typespec *typespec; Expr* expr; } cast; struct{ Intern_String name; Expr *expr; }field; struct{ Typespec *typespec; Expr_Compound_Field *first; Expr_Compound_Field *last; }compound; struct { Expr *atom; Expr_Compound_Field *first; Expr_Compound_Field *last; } call; struct{ }arg; struct { Expr *atom; Expr *index; } index; struct { Token_Kind op; Expr* expr; } unary; struct { Token_Kind op; Expr *expr; } postfix_unary; struct { Token_Kind op; Expr* left; Expr* right; } binary; struct { Expr* cond; Expr* on_true; Expr* on_false; } ternary; struct{ Typespec *typespec; } size_type; struct{ Expr *expr; } size_expr; }; }; //----------------------------------------------------------------------------- // Type specifiers //----------------------------------------------------------------------------- typedef enum Typespec_Kind{ TS_None, TS_Name, TS_Pointer, TS_Array, TS_Function, TS_NamedArgument, }Typespec_Kind; struct Typespec{ Typespec *next; Typespec_Kind kind; Token *pos; union{ Typespec *base; Intern_String name; struct{ Intern_String name; Typespec *base; }named; struct{ Typespec *first; Typespec *last; Typespec *ret; }func; struct{ Typespec *base; Expr *size; }arr; }; }; //----------------------------------------------------------------------------- // Declarations //----------------------------------------------------------------------------- typedef enum Decl_Kind{ DECL_None, DECL_Struct, DECL_Union, DECL_Enum, DECL_Variable, DECL_Typedef, DECL_Function, DECL_List, }Decl_Kind; struct Decl{ Decl_Kind kind; Decl *next; B32 is_incomplete; Decl *prev; // Doubly linked list? Decl *parent; // ? Intern_String name; Token *pos; Note *first_note; Note *last_note; union{ struct{ Decl_Enum_Child *first; Decl_Enum_Child *last; Typespec *typespec; }enum_decl; struct{ Decl *first; Decl *last; }struct_decl; struct{ Typespec *type; Expr *expr; }var_decl; struct{ Typespec *type; }typedef_decl; struct{ Decl_Function_Arg *first; Decl_Function_Arg *last; Typespec *ret; Stmt *body; }func_decl; struct{ Decl *first; Decl *last; }list_decl; }; }; struct Note{ Token *pos; Intern_String name; Expr *expr; Note *next; Note *first; Note *last; }; struct Decl_Function_Arg{ Decl_Function_Arg *next; Token *pos; Intern_String name; Typespec *typespec; }; struct Decl_Enum_Child{ Decl_Enum_Child *next; Intern_String name; Token *pos; Expr *expr; Note *first_note; Note *last_note; }; //----------------------------------------------------------------------------- // Statements //----------------------------------------------------------------------------- typedef enum Stmt_Kind{ STMT_None, STMT_Decl, STMT_Expr, STMT_List, STMT_Return, STMT_If, STMT_For, }Stmt_Kind; struct Stmt_If{ Stmt_If *next; Expr *cond; Stmt *body; }; struct Stmt{ Stmt_Kind kind; Stmt *next; Token *pos; union{ Stmt_If stmt_if; Decl *decl; Expr *expr; struct{ Stmt *first; Stmt *last; }list; struct{ Expr *expr; }ret; }; }; //----------------------------------------------------------------------------- // Expression constructors //----------------------------------------------------------------------------- function Expr * expr_new(Arena *p, Expr_Kind kind, Token *token){ Expr *expr = arena_push_struct(p, Expr); expr->kind = kind; expr->token = token; return expr; } function Expr * expr_int(Arena *p, Token *token){ assert(token->kind == TK_Int); Expr *expr = expr_new(p, EK_Int, token); expr->int_val = token->int_val; return expr; } function Expr * expr_str(Arena *p, Token *token){ assert(token->kind == TK_StringLit); Expr *expr = expr_new(p, EK_String, token); expr->intern_val = token->intern_val; return expr; } function Expr * expr_identifier(Arena *p, Token *token){ assert(token->kind == TK_Identifier); Expr *expr = expr_new(p, EK_Identifier, token); expr->intern_val = token->intern_val; return expr; } function Expr * expr_field(Arena *p, Token *token, Expr *inexpr){ assert(token->kind == TK_Identifier); Expr *expr = expr_new(p, EK_Field, token); expr->field.expr = inexpr; expr->field.name = token->intern_val; return expr; } function Expr * expr_paren(Arena *p, Token *token, Expr *inexpr){ Expr *expr = expr_new(p, EK_Paren, token); expr->paren.expr = inexpr; return expr; } function Expr * expr_postfix_unary(Arena *p, Token *op, Expr *exp){ Expr *expr = expr_new(p, EK_PostfixUnary, op); expr->unary.op = op->kind; expr->unary.expr = exp; return expr; } function Expr * expr_unary(Arena *p, Token *op, Expr *exp){ Expr *expr = expr_new(p, EK_Unary, op); expr->unary.op = op->kind; expr->unary.expr = exp; return expr; } function Expr * expr_binary(Arena *p, Token *op, Expr *left, Expr *right){ Expr *expr = expr_new(p, EK_Binary, op); expr->binary.op = op->kind; expr->binary.left = left; expr->binary.right = right; return expr; } function Expr * expr_ternary(Arena *p, Token *op, Expr *cond, Expr *on_true, Expr *on_false){ Expr *expr = expr_new(p, EK_Ternary, op); expr->ternary.cond = cond; expr->ternary.on_true = on_true; expr->ternary.on_false = on_false; return expr; } function Expr * expr_call(Arena *p, Token *token, Expr *atom){ Expr *expr = expr_new(p, EK_Call, token); expr->call.atom = atom; return expr; } function Expr * expr_index(Arena *p, Token *token, Expr *atom, Expr *index){ Expr *expr = expr_new(p, EK_Index, token); expr->index.atom = atom; expr->index.index = index; return expr; } function Expr * expr_cast(Arena *p, Token *token, Typespec *type, Expr *exp){ Expr *expr = expr_new(p, EK_Cast, token); expr->cast.typespec = type; expr->cast.expr = exp; return expr; } function Expr * expr_size_type(Arena *p, Token *token, Typespec *type){ Expr *expr = expr_new(p, EK_SizeType, token); expr->size_type.typespec = type; return expr; } function Expr * expr_sizeof_expr(Arena *p, Token *token, Expr *in_expr){ Expr *expr = expr_new(p, EK_SizeExpr, token); expr->size_expr.expr = in_expr; return expr; } function Expr * expr_compound(Arena *arena, Token *pos, Typespec *typespec){ Expr *result = expr_new(arena, EK_Compound, pos); result->compound.typespec = typespec; return result; } function Expr_Compound_Field * expr_compound_new(Arena *arena, Expr_Compound_Kind kind, Token *pos, Expr *init){ Expr_Compound_Field *result = arena_push_struct(arena, Expr_Compound_Field); result->kind = kind; result->pos = pos; result->init = init; return result; } function Expr_Compound_Field * expr_compound_default(Arena *arena, Token *pos, Expr *init){ Expr_Compound_Field *result = expr_compound_new(arena, COMPOUND_Default, pos, init); return result; } function Expr_Compound_Field * expr_compound_named(Arena *arena, Token *pos, Intern_String name, Expr *init){ Expr_Compound_Field *result = expr_compound_new(arena, COMPOUND_Named, pos, init); result->name = name; return result; } function Expr_Compound_Field * expr_compound_index(Arena *arena, Token *pos, Expr *index, Expr *init){ Expr_Compound_Field *result = expr_compound_new(arena, COMPOUND_Index, pos, init); result->index = index; return result; } function void expr_call_push(Expr *list, Expr_Compound_Field *field){ SLLQueuePush(list->call.first, list->call.last, field); } function void expr_compound_push(Expr *list, Expr_Compound_Field *field){ SLLQueuePush(list->compound.first, list->compound.last, field); } //----------------------------------------------------------------------------- // Type specifier constructors //----------------------------------------------------------------------------- function Typespec * typespec_new(Arena *p, Typespec_Kind kind, Token *pos){ Typespec *result = arena_push_struct(p, Typespec); result->kind = kind; result->pos = pos; return result; } function Typespec * typespec_name(Arena *p, Token *pos, Intern_String name){ Typespec *result = typespec_new(p, TS_Name, pos); result->name = name; return result; } function Typespec * typespec_pointer(Arena *p, Token *pos, Typespec *base){ Typespec *result = typespec_new(p, TS_Pointer, pos); result->base = base; return result; } function Typespec * typespec_array(Arena *p, Token *pos, Typespec *base, Expr *size){ Typespec *result = typespec_new(p, TS_Array, pos); result->arr.base = base; result->arr.size = size; return result; } function Typespec * typespec_function(Arena *p, Token *pos, Typespec *ret){ Typespec *result = typespec_new(p, TS_Function, pos); result->func.ret = ret; return result; } function Typespec * typespec_named_argument(Arena *arena, Token *pos, Typespec *typespec, Intern_String name){ Typespec *result = typespec_new(arena, TS_NamedArgument, pos); result->named.base = typespec; result->named.name = name; return result; } function void typespec_function_push(Typespec *func, Typespec *arg){ SLLQueuePush(func->func.first, func->func.last, arg); } //----------------------------------------------------------------------------- // Declarations //----------------------------------------------------------------------------- function Decl * decl_new(Arena *p, Decl_Kind kind, Token *pos, Intern_String name){ Decl *result = arena_push_struct(p, Decl); result->kind = kind; result->pos = pos; result->name = name; return result; } function Decl * decl_struct(Arena *p, Decl_Kind kind, Token *pos, Intern_String name){ assert(kind == DECL_Struct || kind == DECL_Union); Decl *result = decl_new(p, kind, pos, name); return result; } function Decl * decl_typedef(Arena *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(Arena *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(Arena *p, Token *pos, Intern_String name, Typespec *typespec, Expr *expr){ Decl *result = decl_new(p, DECL_Variable, pos, name); result->var_decl.type = typespec; result->var_decl.expr = expr; return result; } function Decl * decl_function(Arena *p, Token *pos, Intern_String name, Typespec *ret){ Decl *result = decl_new(p, DECL_Function, pos, name); result->func_decl.ret = ret; return result; } function void decl_func_push(Arena *p, Decl *parent, Token *pos, Intern_String name, Typespec *type){ assert(parent->kind == DECL_Function); Decl_Function_Arg *result = arena_push_struct(p, Decl_Function_Arg); result->name = name; result->typespec = type; result->pos = pos; SLLQueuePush(parent->func_decl.first, parent->func_decl.last, result); } function void decl_enum_push(Arena *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, 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_decl.first, parent->list_decl.last, child); } //----------------------------------------------------------------------------- // Double linked list //----------------------------------------------------------------------------- function void decl_dll_list_push(Decl *l, Decl *node){ if(l->list_decl.first == 0){ l->list_decl.first = l->list_decl.last = node; node->prev = 0; node->next = 0; } else{ l->list_decl.last->next = node; node->prev = l->list_decl.last; node->next = 0; l->list_decl.last = node; } node->parent = l; } function void decl_dll_list_push_front(Decl *l, Decl *node){ if(l->list_decl.first == 0){ l->list_decl.first = l->list_decl.last = node; node->prev = 0; node->next = 0; } else{ node->next = l->list_decl.first; l->list_decl.first->prev = node; node->prev = 0; l->list_decl.first = node; } node->parent = l; } function void decl_list_remove(Decl *l, Decl *node){ if(l->list_decl.first == l->list_decl.last){ assert(node == l->list_decl.last); l->list_decl.first = l->list_decl.last = 0; } else if(l->list_decl.last == node){ l->list_decl.last = l->list_decl.last->prev; l->list_decl.last->next = 0; } else if(l->list_decl.first == node){ l->list_decl.first = l->list_decl.first->next; l->list_decl.first->prev = 0; } else{ node->prev->next = node->next; node->next->prev = node->prev; } node->parent = 0; node->prev = 0; node->next = 0; } function void list_print(Decl *decls){ printf("next:"); for(Decl *n = decls[0].list_decl.first; n; n=n->next){ printf("%d", n->kind); } printf("prev:"); for(Decl *n = decls[0].list_decl.last; n; n=n->prev){ printf("%d", n->kind); } printf("parent:"); for(Decl *n = decls[0].list_decl.first; n; n=n->next){ printf("%d", n->parent->kind); } } function void ast_test(){ Decl decls[16] = {0}; decls[0].kind = 9; decls[1].kind = 1; decls[2].kind = 2; decls[3].kind = 3; decls[4].kind = 4; decl_dll_list_push(decls, decls+1); decl_dll_list_push(decls, decls+2); decl_dll_list_push(decls, decls+3); decl_dll_list_push_front(decls, decls+4); //list_print(decls); decl_list_remove(decls, decls+1); //list_print(decls); decl_list_remove(decls, decls+2); //list_print(decls); decl_list_remove(decls, decls+3); //list_print(decls); decl_list_remove(decls, decls+4); //list_print(decls); assert(decls[0].list_decl.first == 0); assert(decls[0].list_decl.last == 0); }