| |
| |
| |
| #include "ast.h" |
|
|
| ASTNode *ast_new(Arena *a, NodeType type, SourceLoc loc) { |
| ASTNode *n = (ASTNode *)arena_alloc(a, sizeof(ASTNode)); |
| memset(n, 0, sizeof(ASTNode)); |
| n->type = type; |
| n->loc = loc; |
| return n; |
| } |
|
|
| ASTType *ast_new_type(Arena *a, TypeKind kind) { |
| ASTType *t = (ASTType *)arena_alloc(a, sizeof(ASTType)); |
| memset(t, 0, sizeof(ASTType)); |
| t->kind = kind; |
| t->array_size = -1; |
| return t; |
| } |
|
|
| ASTType *ast_ptr_type(Arena *a, ASTType *base) { |
| ASTType *t = ast_new_type(a, TYPE_POINTER); |
| t->base = base; |
| return t; |
| } |
|
|
| ASTType *ast_array_type(Arena *a, ASTType *base, int size) { |
| ASTType *t = ast_new_type(a, TYPE_ARRAY); |
| t->base = base; |
| t->array_size = size; |
| return t; |
| } |
|
|
| |
| const char *node_type_str(NodeType t) { |
| static const char *names[] = { |
| [NODE_PROGRAM]="Program", [NODE_FUNC_DECL]="FuncDecl", |
| [NODE_VAR_DECL]="VarDecl", [NODE_PARAM]="Param", |
| [NODE_STRUCT_DECL]="StructDecl", |
| [NODE_BLOCK]="Block", [NODE_EXPR_STMT]="ExprStmt", |
| [NODE_IF]="If", [NODE_WHILE]="While", [NODE_DO_WHILE]="DoWhile", |
| [NODE_FOR]="For", [NODE_RETURN]="Return", |
| [NODE_BREAK]="Break", [NODE_CONTINUE]="Continue", |
| [NODE_BINARY]="Binary", [NODE_UNARY]="Unary", |
| [NODE_POSTFIX]="Postfix", [NODE_ASSIGN]="Assign", |
| [NODE_TERNARY]="Ternary", [NODE_CALL]="Call", |
| [NODE_INDEX]="Index", [NODE_MEMBER]="Member", |
| [NODE_ARROW]="Arrow", [NODE_CAST]="Cast", |
| [NODE_SIZEOF]="Sizeof", [NODE_IDENT]="Ident", |
| [NODE_INT_LIT]="IntLit", [NODE_FLOAT_LIT]="FloatLit", |
| [NODE_STRING_LIT]="StringLit", [NODE_CHAR_LIT]="CharLit", |
| [NODE_COMMA_EXPR]="CommaExpr", |
| [NODE_ADDR_OF]="AddrOf", [NODE_DEREF]="Deref", |
| [NODE_PARALLEL_FOR]="ParallelFor", |
| [NODE_PARALLEL_REDUCE]="ParallelReduce", |
| [NODE_PARALLEL_SCAN]="ParallelScan", |
| [NODE_PARALLEL_MAP]="ParallelMap", |
| [NODE_BARRIER]="Barrier", |
| [NODE_SHARED_DECL]="SharedDecl", |
| [NODE_TILE_HINT]="TileHint", |
| [NODE_SIMD_HINT]="SimdHint", |
| [NODE_MEMORY_LAYOUT]="MemoryLayout", |
| [NODE_ATOMIC_ADD]="AtomicAdd", |
| [NODE_ATOMIC_CAS]="AtomicCAS", |
| [NODE_PREPROC]="Preproc", |
| }; |
| if (t >= 0 && t < NODE_TYPE_COUNT && names[t]) return names[t]; |
| return "Unknown"; |
| } |
|
|
| const char *op_type_str(OpType op) { |
| static const char *ops[] = { |
| [OP_ADD]="+", [OP_SUB]="-", [OP_MUL]="*", [OP_DIV]="/", [OP_MOD]="%", |
| [OP_AND]="&", [OP_OR]="|", [OP_XOR]="^", [OP_NOT]="~", [OP_LNOT]="!", |
| [OP_LSHIFT]="<<", [OP_RSHIFT]=">>", |
| [OP_EQ]="==", [OP_NEQ]="!=", [OP_LT]="<", [OP_GT]=">", |
| [OP_LE]="<=", [OP_GE]=">=", [OP_LAND]="&&", [OP_LOR]="||", |
| [OP_NEG]="-", [OP_POS]="+", [OP_INC]="++", [OP_DEC]="--", |
| [OP_POST_INC]="(post)++", [OP_POST_DEC]="(post)--", |
| [OP_ASSIGN]="=", |
| [OP_ADD_ASSIGN]="+=", [OP_SUB_ASSIGN]="-=", |
| [OP_MUL_ASSIGN]="*=", [OP_DIV_ASSIGN]="/=", |
| [OP_MOD_ASSIGN]="%=", [OP_AND_ASSIGN]="&=", |
| [OP_OR_ASSIGN]="|=", [OP_XOR_ASSIGN]="^=", |
| [OP_LSHIFT_ASSIGN]="<<=", [OP_RSHIFT_ASSIGN]=">>=", |
| [OP_COMMA]=",", |
| }; |
| return ops[op]; |
| } |
|
|
| |
| static void indent(int level) { |
| for (int i = 0; i < level; i++) printf(" "); |
| } |
|
|
| void ast_print(ASTNode *node, int ind) { |
| if (!node) { indent(ind); printf("(null)\n"); return; } |
| indent(ind); |
| printf("%s", node_type_str(node->type)); |
|
|
| switch (node->type) { |
| case NODE_PROGRAM: |
| printf(" (%zu decls)\n", node->program.decls.len); |
| for (size_t i = 0; i < node->program.decls.len; i++) |
| ast_print(node->program.decls.data[i], ind + 1); |
| break; |
|
|
| case NODE_FUNC_DECL: |
| printf(" '%s' (%zu params)\n", node->func.name, node->func.params.len); |
| for (size_t i = 0; i < node->func.params.len; i++) |
| ast_print(node->func.params.data[i], ind + 1); |
| if (node->func.body) |
| ast_print(node->func.body, ind + 1); |
| break; |
|
|
| case NODE_VAR_DECL: |
| printf(" '%s'", node->var.name); |
| if (node->var.init) { printf(" =\n"); ast_print(node->var.init, ind + 1); } |
| else printf("\n"); |
| break; |
|
|
| case NODE_PARAM: |
| printf(" '%s'\n", node->param.name); |
| break; |
|
|
| case NODE_BLOCK: |
| printf(" (%zu stmts)\n", node->block.stmts.len); |
| for (size_t i = 0; i < node->block.stmts.len; i++) |
| ast_print(node->block.stmts.data[i], ind + 1); |
| break; |
|
|
| case NODE_IF: |
| printf("\n"); |
| indent(ind + 1); printf("cond:\n"); ast_print(node->if_stmt.cond, ind + 2); |
| indent(ind + 1); printf("then:\n"); ast_print(node->if_stmt.then_body, ind + 2); |
| if (node->if_stmt.else_body) { |
| indent(ind + 1); printf("else:\n"); ast_print(node->if_stmt.else_body, ind + 2); |
| } |
| break; |
|
|
| case NODE_FOR: |
| printf("\n"); |
| if (node->for_stmt.init) { indent(ind+1); printf("init:\n"); ast_print(node->for_stmt.init, ind+2); } |
| if (node->for_stmt.cond) { indent(ind+1); printf("cond:\n"); ast_print(node->for_stmt.cond, ind+2); } |
| if (node->for_stmt.step) { indent(ind+1); printf("step:\n"); ast_print(node->for_stmt.step, ind+2); } |
| indent(ind+1); printf("body:\n"); ast_print(node->for_stmt.body, ind+2); |
| break; |
|
|
| case NODE_WHILE: |
| case NODE_DO_WHILE: |
| printf("\n"); |
| ast_print(node->while_stmt.cond, ind + 1); |
| ast_print(node->while_stmt.body, ind + 1); |
| break; |
|
|
| case NODE_RETURN: |
| printf("\n"); |
| if (node->ret.value) ast_print(node->ret.value, ind + 1); |
| break; |
|
|
| case NODE_EXPR_STMT: |
| printf("\n"); |
| ast_print(node->expr_stmt.expr, ind + 1); |
| break; |
|
|
| case NODE_BINARY: |
| printf(" '%s'\n", op_type_str(node->binary.op)); |
| ast_print(node->binary.left, ind + 1); |
| ast_print(node->binary.right, ind + 1); |
| break; |
|
|
| case NODE_UNARY: |
| printf(" '%s'\n", op_type_str(node->unary.op)); |
| ast_print(node->unary.operand, ind + 1); |
| break; |
|
|
| case NODE_ASSIGN: |
| printf(" '%s'\n", op_type_str(node->assign.op)); |
| ast_print(node->assign.target, ind + 1); |
| ast_print(node->assign.value, ind + 1); |
| break; |
|
|
| case NODE_CALL: |
| printf("\n"); |
| indent(ind + 1); printf("func:\n"); ast_print(node->call.func, ind + 2); |
| for (size_t i = 0; i < node->call.args.len; i++) { |
| indent(ind + 1); printf("arg %zu:\n", i); |
| ast_print(node->call.args.data[i], ind + 2); |
| } |
| break; |
|
|
| case NODE_INDEX: |
| printf("\n"); |
| ast_print(node->index.array, ind + 1); |
| ast_print(node->index.index, ind + 1); |
| break; |
|
|
| case NODE_IDENT: |
| printf(" '%s'\n", node->ident.name); |
| break; |
|
|
| case NODE_INT_LIT: |
| printf(" %ld\n", (long)node->int_lit.value); |
| break; |
|
|
| case NODE_FLOAT_LIT: |
| printf(" %g\n", node->float_lit.value); |
| break; |
|
|
| case NODE_STRING_LIT: |
| printf(" \"%s\"\n", node->string_lit.value); |
| break; |
|
|
| case NODE_PARALLEL_FOR: |
| printf(" iter='%s'\n", node->par_for.iter_var); |
| indent(ind+1); printf("lo:\n"); ast_print(node->par_for.lo, ind+2); |
| indent(ind+1); printf("hi:\n"); ast_print(node->par_for.hi, ind+2); |
| indent(ind+1); printf("body:\n"); ast_print(node->par_for.body, ind+2); |
| break; |
|
|
| case NODE_PARALLEL_REDUCE: |
| printf(" accum='%s' iter='%s'\n", node->par_reduce.accum_var, node->par_reduce.iter_var); |
| indent(ind+1); printf("lo:\n"); ast_print(node->par_reduce.lo, ind+2); |
| indent(ind+1); printf("hi:\n"); ast_print(node->par_reduce.hi, ind+2); |
| indent(ind+1); printf("body:\n"); ast_print(node->par_reduce.body, ind+2); |
| break; |
|
|
| case NODE_TILE_HINT: |
| printf(" target='%s' size=%d\n", node->tile_hint.target, node->tile_hint.tile_size); |
| break; |
|
|
| case NODE_SIMD_HINT: |
| printf(" target='%s'\n", node->simd_hint.target); |
| break; |
|
|
| case NODE_PREPROC: |
| printf(" '%s'\n", node->preproc.text); |
| break; |
|
|
| default: |
| printf("\n"); |
| break; |
| } |
| } |
|
|