typedef struct Expr Expr; typedef struct Note Note; typedef struct Stmt_If Stmt_If; typedef struct Typespec Typespec; typedef struct Decl_Enum_Child Decl_Enum_Child; typedef struct Expr_Compound_Field Expr_Compound_Field; typedef struct AST AST; typedef struct AST_Parent AST_Parent; //----------------------------------------------------------------------------- // 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; }; }; //----------------------------------------------------------------------------- // Abstract Syntax Tree, declarations, statements all in one //----------------------------------------------------------------------------- typedef enum AST_Kind:U32{ AST_None, AST_Decl_Enum_Child, AST_Decl_Var, AST_Decl_Const, AST_Decl_Typedef, AST_Decl_Func_Arg, AST_Decl_Variable, AST_Stmt_ElseIf, AST_Stmt_Else, AST_Stmt_Init, AST_Stmt_Expr, AST_Stmt_Assign, AST_Stmt_Return, AST_Stmt_For, AST_Stmt_Defer, AST_Decl_Struct, // First Parent, First Struct AST_Decl_SubStruct, AST_Decl_SubUnion, AST_Decl_Union, // Last Struct AST_Decl_Enum, AST_Decl_Func, AST_Note, AST_Note_List, AST_Stmt_Block, AST_Stmt_If, AST_Stmt_Decl, AST_Program,// Last Parent AST_FirstParent = AST_Decl_Struct, AST_LastParent = AST_Program, AST_FirstStruct = AST_Decl_Struct, AST_LastStruct = AST_Decl_Union, }AST_Kind; typedef enum AST_Flags{ AST_Flags_None, AST_Flags_Ordered = 1 }AST_Flags; //----------------------------------------------------------------------------- // Inheritence like macro helpers //----------------------------------------------------------------------------- // AST - 48 Bytes // AST_Parent - 64 Bytes #define AST_FIELDS AST_Kind kind; AST_Flags flags; AST *next, *prev; AST_Parent *notes; AST_Parent *parent; Token *pos #define AST_PARENT_FIELDS AST *first, *last #define AST_UNION union{ struct{ AST_FIELDS; }; AST ast; } #define AST_PARENT_UNION union{ struct{ AST_FIELDS; AST_PARENT_FIELDS; }; AST_Parent child; } //----------------------------------------------------------------------------- // Base classes //----------------------------------------------------------------------------- struct AST{AST_FIELDS;}; typedef struct AST_Parent{ AST_UNION; AST_PARENT_FIELDS; } AST_Parent; //----------------------------------------------------------------------------- // Declarations //----------------------------------------------------------------------------- typedef AST_Parent Note_List; typedef AST_Parent Program; typedef struct Note{ AST_PARENT_UNION; Intern_String name; Expr *expr; }Note; typedef struct Decl_Struct{ AST_PARENT_UNION; Intern_String name; }Decl_Struct; typedef struct Decl_Func_Arg{ AST_UNION; Intern_String name; Typespec *typespec; }Decl_Func_Arg; typedef struct Decl_Enum_Child{ AST_UNION; Intern_String name; Expr *expr; }Decl_Enum_Child; typedef struct Decl_Enum{ AST_PARENT_UNION; Typespec *typespec; Intern_String name; }Decl_Enum; typedef AST_Parent Stmt_Block; typedef struct Decl_Func{ AST_PARENT_UNION; Intern_String name; Typespec *ret; Stmt_Block *body; B32 is_incomplete; }Decl_Func; typedef struct Decl_Typedef{ AST_PARENT_UNION; Typespec *typespec; Intern_String name; }Decl_Typedef; typedef struct Decl_Var{ AST_PARENT_UNION; Typespec *typespec; Intern_String name; Expr *expr; }Decl_Var; typedef struct Decl_Const{ AST_PARENT_UNION; Typespec *typespec; Intern_String name; Expr *expr; }Decl_Const; //----------------------------------------------------------------------------- // Statements //----------------------------------------------------------------------------- typedef Stmt_If Stmt_If; struct Stmt_If{ AST_PARENT_UNION; Expr *condition; Stmt_Block *body; }; typedef struct Stmt_ElseIf{ AST_UNION; Expr *condition; Stmt_Block *body; }Stmt_ElseIf; typedef struct Stmt_Else{ AST_UNION; Stmt_Block *body; }Stmt_Else; typedef struct Stmt_Return{ AST_UNION; Expr *expr; } Stmt_Return; typedef struct Stmt_Init{ AST_UNION; Intern_String name; Typespec *typespec; Expr *expr; }Stmt_Init; typedef struct Stmt_Assign{ AST_UNION; Token_Kind op; Expr *left; Expr *right; }Stmt_Assign; typedef struct Stmt_Expr{ AST_UNION; Expr *expr; }Stmt_Expr; typedef struct Stmt_Defer{ AST_UNION; Stmt_Block *body; }Stmt_Defer; typedef struct Stmt_For{ AST_UNION; AST *on_begin; Expr*condition; AST *on_iter; Stmt_Block *body; }Stmt_For; //----------------------------------------------------------------------------- // 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_Integer); 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); } //----------------------------------------------------------------------------- // Double linked list //----------------------------------------------------------------------------- function void ast_remove(AST *node){ AST_Parent *l = node->parent; assert(l); if (l->first==l->last){ assert(node==l->last); l->first=l->last=0; } else if (l->last==node){ l->last=l->last->prev; l->last->next=0; } else if (l->first==node){ l->first=l->first->next; l->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 ast_push_last(AST_Parent *l, AST *node){ if (l->first==0){ l->first=l->last=node; node->prev=0; node->next=0; } else { l->last->next=node; node->prev=l->last; node->next=0; l->last=node; } node->parent=l; } function void ast_push_first(AST_Parent *l, AST *node){ if(l->first == 0){ l->first = l->last = node; node->prev = 0; node->next = 0; } else { node->next = l->first; l->first->prev = node; node->prev = 0; l->first = node; } node->parent = l; } function void ast_push_after(AST *in_list, AST *node){ AST_Parent *parent = in_list->parent; assert(parent); assert(parent->first && parent->last); node->prev = in_list; if(in_list == parent->last){ in_list->next = node; parent->last = node; } else { node->next = in_list->next; in_list->next = node; node->next->prev = node; } node->parent=parent; } function void ast_push_before(AST *in_list, AST *node){ AST_Parent *parent = in_list->parent; assert(parent); assert(parent->first && parent->last); node->next = in_list; if(parent->first == in_list){ in_list->prev = node; parent->first = node; } else{ node->prev = in_list->prev; in_list->prev = node; node->prev->next = node; } node->parent = parent; } //----------------------------------------------------------------------------- // AST Constructors //----------------------------------------------------------------------------- #define ast_parent_new(arena, T, pos) (T *)ast__parent_new(arena, sizeof(T), AST_##T, pos) #define ast_new(arena, T, pos) (T *)ast__new(arena, sizeof(T), AST_##T, pos) function B32 ast_kind_is_parent(AST_Kind kind){ B32 result = kind >= AST_FirstParent && kind <= AST_LastParent; return result; } function B32 ast_kind_is_struct(AST_Kind kind){ B32 result = kind >= AST_FirstStruct && kind <= AST_LastStruct; return result; } function AST * ast__new(Arena *p, SizeU size, AST_Kind kind, Token *pos){ assert(!ast_kind_is_parent(kind)); AST *result = arena_push_size(p, size); result->pos = pos; result->kind = kind; return result; } function AST_Parent * ast__parent_new(Arena *p, SizeU size, AST_Kind kind, Token *pos){ assert(ast_kind_is_parent(kind)); AST_Parent *result = arena_push_size(p, size); result->pos = pos; result->kind = kind; return result; } //----------------------------------------------------------------------------- // Notes //----------------------------------------------------------------------------- function Note * note_push_new(Arena *p, AST_Parent *parent, Token *pos, Intern_String name, Expr *expr){ Note *result = ast_parent_new(p, Note, pos); result->name = name; result->expr = expr; ast_push_last(parent, (AST *)result); return result; } function Note_List * note_list(Arena *p, Token *pos){ Note_List *result = ast_parent_new(p, Note_List, pos); return result; } #define ast_push_copy(a,p,T) arena_push_copy(a, p, sizeof(T)) function AST * ast_shallow_copy(Arena *a, AST *ast){ AST *result = 0; switch(ast->kind){ case AST_Note_List: { result = ast_push_copy(a, ast, Note_List); } break; default: invalid_codepath; } return result; } //----------------------------------------------------------------------------- // Declarations //----------------------------------------------------------------------------- function Decl_Struct * decl_struct(Arena *p, AST_Kind kind, Token *pos, Intern_String name){ assert(ast_kind_is_struct(kind)); Decl_Struct *result = ast_parent_new(p, Decl_Struct, pos); result->name = name; return result; } function Decl_Typedef * decl_typedef(Arena *p, Token *pos, Intern_String name, Typespec *type){ Decl_Typedef *result = ast_new(p, Decl_Typedef, pos); result->typespec = type; result->name = name; return result; } function Decl_Const * decl_const(Arena *arena, Token *pos, Intern_String name, Expr *expr, Typespec *typespec){ Decl_Const *result = ast_new(arena, Decl_Const, pos); result->expr = expr; result->name = name; result->typespec = typespec; return result; } function Decl_Enum * decl_enum(Arena *p, Token *pos, Intern_String name, Typespec *typespec){ Decl_Enum *result = ast_parent_new(p, Decl_Enum, pos); result->name = name; result->typespec = typespec; return result; } function Decl_Var * decl_variable(Arena *arena, Token *pos, Intern_String name, Expr *expr, Typespec *typespec, Note_List *notes){ Decl_Var *result = ast_new(arena, Decl_Var, pos); result->expr = expr; result->name = name; result->typespec = typespec; result->notes = notes; return result; } function Decl_Func * decl_function(Arena *p, Token *pos, Intern_String name, Typespec *ret){ Decl_Func *result = ast_parent_new(p, Decl_Func, pos); result->ret = ret; result->name = name; return result; } function Decl_Func_Arg * decl_func_arg(Arena *arena, Token *pos, Intern_String name, Typespec *type){ Decl_Func_Arg *result = ast_new(arena, Decl_Func_Arg, pos); result->name = name; result->typespec = type; return result; } function Decl_Enum_Child * decl_enum_child(Arena *p, Token *pos, Intern_String name, Expr *expr, Note_List *note){ Decl_Enum_Child *result = ast_new(p, Decl_Enum_Child, pos); result->name = name; result->expr = expr; result->notes = (AST_Parent *)note; return result; } function void decl_func_push(Arena *p, Decl_Func *parent, Token *pos, Intern_String name, Typespec *type){ assert(parent->kind == AST_Decl_Func); Decl_Func_Arg *func_arg = decl_func_arg(p, pos, name, type); ast_push_last((AST_Parent *)parent, (AST *)func_arg); } function void decl_enum_push(Arena *p, Decl_Enum *parent, Token *pos, Intern_String name, Expr *expr, Note_List *notes){ assert(parent->kind == AST_Decl_Enum); Decl_Enum_Child *child = decl_enum_child(p, pos, name, expr, notes); ast_push_last((AST_Parent *)parent, (AST *)child); } function void decl_struct_push(Decl_Struct *parent, AST *child){ assert(ast_kind_is_struct(parent->kind)); ast_push_last((AST_Parent *)parent, child); } function Program * ast_program(Arena *arena, Token *token){ Program *result = ast_parent_new(arena, Program, token); return result; } function void ast_program_push(AST_Parent *parent, AST *child){ assert(parent->kind == AST_Program); ast_push_last((AST_Parent *)parent, child); } //----------------------------------------------------------------------------- // Statements //----------------------------------------------------------------------------- function Stmt_Block * stmt_block(Arena *arena, Token *pos){ Stmt_Block *result = ast_parent_new(arena, Stmt_Block, pos); return result; } function Stmt_If * stmt_if(Arena *arena, Token *pos, Expr *condition){ Stmt_If *result = ast_parent_new(arena, Stmt_If, pos); result->condition = condition; result->body = stmt_block(arena, pos); return result; } function Stmt_ElseIf * stmt_else_if_push(Arena *arena, Stmt_If *parent, Token *pos, Expr *condition){ Stmt_ElseIf *result = ast_new(arena, Stmt_ElseIf, pos); result->condition = condition; result->body = stmt_block(arena, pos); ast_push_last((AST_Parent *)parent, (AST *)result); return result; } function Stmt_Else * stmt_else_push(Arena *arena, Stmt_If *parent, Token *pos){ Stmt_Else *result = ast_new(arena, Stmt_Else, pos); result->body = stmt_block(arena, pos); ast_push_last((AST_Parent *)parent, (AST *)result); return result; } function Stmt_Init * stmt_init(Arena *arena, Token *pos, Intern_String name, Typespec *typespec, Expr *expr){ Stmt_Init *result = ast_new(arena, Stmt_Init, pos); result->typespec = typespec; result->expr = expr; result->name = name; return result; } function Stmt_Assign * stmt_assign(Arena *arena, Token *pos, Token_Kind op, Expr *left, Expr *right){ Stmt_Assign *result = ast_new(arena, Stmt_Assign, pos); result->op = op; result->left = left; result->right = right; return result; } function Stmt_Expr * stmt_expr(Arena *arena, Token *pos, Expr *expr){ Stmt_Expr *result = ast_new(arena, Stmt_Expr, pos); result->expr = expr; return result; } function Stmt_Return * stmt_return(Arena *arena, Token *pos, Expr *expr){ Stmt_Return *result = ast_new(arena, Stmt_Return, pos); result->expr = expr; return result; } function Stmt_For * stmt_for(Arena *arena, Token *pos, Token *pos_block, AST *on_begin, Expr *condition, AST *on_iter){ Stmt_For *result = ast_new(arena, Stmt_For, pos); result->on_iter = on_iter; result->on_begin = on_begin; result->condition = condition; result->body = stmt_block(arena, pos_block); return result; } function Stmt_Defer * stmt_defer(Arena *arena, Token *pos){ Stmt_Defer *result = ast_new(arena, Stmt_Defer, pos); result->body = stmt_block(arena, pos); return result; } //----------------------------------------------------------------------------- // Test stuff //----------------------------------------------------------------------------- function void list_print(AST_Parent *decls){ printf("\n"); printf("next:"); for(AST *n = decls->first; n; n=n->next){ printf("%d", n->kind); } printf("prev:"); for(AST *n = decls->last; n; n=n->prev){ printf("%d", n->kind); } printf("parent:"); for(AST *n = decls->first; n; n=n->next){ printf("%d", n->parent->kind); } } function void ast_test(){ printf("\nAST_Size = %u", (U32)sizeof(AST)); printf("\nAST_Parent_Size = %u", (U32)sizeof(AST_Parent)); printf("\nAST_Struct_Size = %u", (U32)sizeof(Decl_Struct)); printf("\nAST_Func_Size = %u", (U32)sizeof(Decl_Func)); AST_Parent parent = {0}; AST decls[16] = {0}; parent.kind = 0; for(int i = 0; i < buff_cap(decls); i++){ decls[i].kind = i+1; } ast_push_last(&parent, decls); ast_push_last(&parent, decls+1); ast_push_last(&parent, decls+2); //ast_push_before(decls, decls+3); //ast_push_before(decls, decls+4); //ast_push_after(decls, decls+5); //ast_push_after(decls+5, decls+6); list_print(&parent); /* ast_remove(decls); ast_remove(decls+1); ast_remove(decls+2); ast_remove(decls+3); ast_remove(decls+4); ast_remove(decls+5); ast_remove(decls+6); assert(parent.first == 0); assert(parent.last == 0); */ }