/* * par2serial-cc: ast.c - AST construction and debug printing */ #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; } /* ── String representations ──────────────────────────────── */ 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]; } /* ── Pretty printer ──────────────────────────────────────── */ 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; } }