#ifndef NCTREF_AST_H #define NCTREF_AST_H #include"types.h" #include"lexer.h" #include"vartable.h" #pragma pack(push, 1) #ifdef __GNUC__ #define ENUMPAK __attribute__((packed)) #else #define ENUMPAK #endif #define GEN_ENUM(x) x, #define GEN_STRI(x) #x, #define AST_KINDS(K) \ K(AST_CHUNK) \ K(AST_STMT_DECL) \ K(AST_TYPE_IDENTIFIER) \ K(AST_EXPR_PRIMITIVE) \ K(AST_STMT_IF) \ K(AST_EXPR_BINARY_OP) \ K(AST_EXPR_VAR) \ K(AST_EXPR_STACK_POINTER) \ K(AST_TYPE_POINTER) \ K(AST_EXPR_UNARY_OP) \ K(AST_STMT_LOOP) \ K(AST_STMT_BREAK) \ K(AST_STMT_CONTINUE) \ K(AST_EXPR_CALL) \ K(AST_STMT_EXPR) \ K(AST_STMT_ASSIGN) \ K(AST_STMT_EXT_ALIGN) \ K(AST_EXPR_STRING_LITERAL) \ K(AST_EXPR_CAST) \ K(AST_EXPR_ARRAY) \ K(AST_EXPR_FUNC) \ K(AST_STMT_EXT_ORG) \ K(AST_STMT_EXT_SECTION) \ K(AST_STMT_RETURN) \ K(AST_EXPR_EXT_SALLOC) \ K(AST_EXPR_DOT) \ K(AST_EXPR_EXT_SIZEOF) typedef enum ENUMPAK { AST_KINDS(GEN_ENUM) } ASTKind; extern const char *AST_KIND_STR[]; typedef enum ENUMPAK { BINOP_ADD = 0, BINOP_SUB = 1, BINOP_BITWISE_AND = 2, BINOP_BITWISE_OR = 3, BINOP_BITWISE_XOR = 4, BINOP_SIMPLES = 5, BINOP_MUL = 5, BINOP_DIV = 6, BINOP_2OPS = 7, BINOP_MULHI = 7, BINOP_MOD = 8, BINOP_EQUAL = 9, BINOP_NEQUAL = 10, BINOP_LESS = 11, BINOP_GREATER = 12, BINOP_LEQUAL = 13, BINOP_GEQUAL = 14, BINOP_WTF = 999, } BinaryOp; static inline int binop_is_comparison(BinaryOp op) { return op == BINOP_EQUAL || op == BINOP_NEQUAL || op == BINOP_LESS || op == BINOP_GREATER || op == BINOP_LEQUAL || op == BINOP_GEQUAL; } static inline int binop_is_commutative(BinaryOp op) { return op == BINOP_ADD || op == BINOP_MUL || op == BINOP_MULHI || op == BINOP_EQUAL || op == BINOP_NEQUAL || op == BINOP_BITWISE_AND || op == BINOP_BITWISE_OR || op == BINOP_BITWISE_XOR; } static inline BinaryOp binop_comp_opposite(BinaryOp op) { if(op == BINOP_EQUAL) { return BINOP_NEQUAL; } else if(op == BINOP_NEQUAL) { return BINOP_EQUAL; } else if(op == BINOP_LESS) { return BINOP_GEQUAL; } else if(op == BINOP_GREATER) { return BINOP_LEQUAL; } else if(op == BINOP_LEQUAL) { return BINOP_GREATER; } else if(op == BINOP_GEQUAL) { return BINOP_LESS; } return BINOP_WTF; } typedef enum ENUMPAK { UNOP_DEREF = 0, UNOP_NEGATE = 1, UNOP_BITWISE_NOT = 2, UNOP_REF = 3, } UnaryOp; union AST; typedef struct { ASTKind nodeKind; uint16_t row; uint16_t col; } ASTBase; typedef struct { ASTBase; Type *type; } ASTExpr; typedef struct { ASTExpr; int val; } ASTExprPrimitive; typedef struct { ASTExpr; union AST *operands[2]; BinaryOp operator; } ASTExprBinaryOp; typedef struct { ASTExpr; UnaryOp operator; union AST *operand; } ASTExprUnaryOp; typedef struct { ASTExpr; ScopeItem *thing; } ASTExprVar; typedef struct { ASTExpr; union AST *what; union AST **args; } ASTExprCall; typedef struct { ASTExpr; size_t length; char *data; } ASTExprStringLiteral; typedef struct { ASTExpr; } ASTExprStackPointer; typedef struct { ASTExpr; union AST *chunk; // Necessary for when the parser jumps to a generic function Scope *scope; Token *rangeTokens; size_t startTokI; size_t endTokI; } ASTExprFunc; typedef struct { ASTBase; size_t size; } ASTType; typedef struct { ASTType; Token identifier; } ASTTypeIdentifier; typedef struct { ASTType; union AST *child; int levels; } ASTTypePointer; typedef struct { ASTBase; union AST *next; } ASTStmt; typedef struct { ASTStmt; ScopeItem *thing; union AST *expression; } ASTStmtDecl; typedef struct { ASTBase; /* Flattened variable array for global register allocation */ size_t varCount; ScopeItem **vars; /* extern symbol array */ size_t externCount; ScopeItem **externs; union AST *statementFirst; union AST *statementLast; size_t stackReservation; /* NULL unless this is a top-level chunk belonging to a function */ Type *functionType; } ASTChunk; typedef struct { ASTStmt; union AST *expression; union AST *then; } ASTStmtIf; typedef struct { ASTStmt; union AST *body; } ASTStmtLoop; typedef struct { ASTStmt; } ASTStmtBreak; typedef struct { ASTStmt; } ASTStmtContinue; typedef struct { ASTStmt; union AST *expr; } ASTStmtExpr; typedef struct { ASTStmt; union AST *what; union AST *to; } ASTStmtAssign; typedef struct { ASTStmt; int val; } ASTStmtExtAlign; typedef struct { ASTExpr; union AST *what; Type *to; char reinterpretation; /* 1 = as, 0 = to */ } ASTExprCast; typedef struct { ASTExpr; union AST **items; } ASTExprArray; typedef struct { ASTExpr; Type *size; } ASTExprExtSalloc; typedef struct { ASTExpr; union AST *a; const char *b; } ASTExprDot; typedef struct { ASTStmt; size_t val; } ASTStmtExtOrg; typedef struct { ASTStmt; Token name; } ASTStmtExtSection; typedef struct { ASTStmt; union AST *val; } ASTStmtReturn; typedef struct { ASTExpr; // One of these will be NULL union AST *ofExpr; Type *ofType; } ASTExprExtSizeOf; typedef union AST { ASTBase; ASTChunk chunk; ASTStmt statement; ASTStmtDecl stmtDecl; ASTStmtIf stmtIf; ASTStmtLoop stmtLoop; ASTStmtBreak stmtBreak; ASTStmtContinue stmtContinue; ASTStmtExpr stmtExpr; ASTStmtAssign stmtAssign; ASTStmtReturn stmtReturn; ASTExpr expression; ASTExprPrimitive exprPrim; ASTExprBinaryOp exprBinOp; ASTExprUnaryOp exprUnOp; ASTExprVar exprVar; ASTExprCall exprCall; ASTStmtExtAlign stmtExtAlign; ASTExprStringLiteral exprStrLit; ASTExprCast exprCast; ASTExprArray exprArray; ASTExprFunc exprFunc; ASTExprDot exprDot; ASTExprExtSalloc exprExtSalloc; ASTStmtExtOrg stmtExtOrg; ASTStmtExtSection stmtExtSection; ASTExprExtSizeOf exprExtSizeOf; } AST; #pragma pack(pop) typedef void(*GenericVisitorHandler)(AST**, AST*, AST*, AST*, AST*, void*); void generic_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chu, AST *tlc, void *ud, GenericVisitorHandler preHandler, GenericVisitorHandler postHandler); int ast_expression_equal(AST*, AST*); int ast_stmt_is_after(const AST *chunk, const AST *s1, const AST *s2); void ast_usedef_reset(AST *chu); char *ast_dump(AST *tlc); AST *ast_deep_copy(AST*); AST *ast_cast_expr(AST *what, Type *to); void ast_spill_to_stack(AST *tlc, ScopeItem *vte); void ast_typecheck(AST *tlc); void ast_grow_stack_frame(AST *tlc, size_t bytes); __attribute__((format(printf, 1, 2))) char *malp(const char *fmt, ...); #endif