typedef struct Expr Expr; typedef struct Typespec Typespec; typedef enum Typespec_Kind{ TS_None, TS_Name, TS_Pointer, TS_Array, TS_Function, }Typespec_Kind; struct Typespec{ Typespec_Kind kind; Typespec *next; Token *pos; union{ Intern_String name; Typespec *base; struct{ Typespec *first; Typespec *last; Typespec *ret; }func; struct{ Typespec *base; Expr *size; }arr; }; }; //----------------------------------------------------------------------------- // 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_Paren, EK_PostfixUnary, EK_Unary, EK_Binary, EK_Ternary, EK_Cast, EK_Field, EK_Call, EK_Index, EK_Sizeof, } Expr_Kind; 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 *type; Expr* expr; } cast; struct{ Intern_String name; Expr *expr; }field; struct { Expr *atom; Expr *first; Expr *last; } call; 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{ Expr_Sizeof_Kind kind; union{ Typespec *type; Expr *expr; }; } size_of; }; }; //----------------------------------------------------------------------------- // Expr //----------------------------------------------------------------------------- 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.type = type; expr->cast.expr = exp; return expr; } function Expr * expr_sizeof_type(Arena *p, Token *token, Typespec *type){ Expr *expr = expr_new(p, EK_Sizeof, token); expr->size_of.kind = SIZEOF_Type; expr->size_of.type = type; return expr; } function Expr * expr_sizeof_expr(Arena *p, Token *token, Expr *in_expr){ Expr *expr = expr_new(p, EK_Sizeof, token); expr->size_of.kind = SIZEOF_Expr; expr->size_of.expr = in_expr; return expr; } function void expr_call_push(Expr *list, Expr *expr){ SLLQueuePush(list->call.first, list->call.last, expr); }