33 if (program !=
nullptr) {
42 if (stmt ==
nullptr) {
45 std::visit([
this](
const auto& s) { this->visit(s); }, stmt->
value);
49 if (expr ==
nullptr) {
53 std::visit([
this](
const auto& e) { this->visit(e); }, expr->value);
56void ASTPrinter::indent() { indent_level++; }
58void ASTPrinter::unindent() { indent_level--; }
61void ASTPrinter::visit(
const ExprStmt& stmt) {
64 print(stmt.expr.get());
68void ASTPrinter::visit(
const AssignStmt& stmt) {
69 line(
"AssignStmt: {}", stmt.name.value);
72 std::string type_name = std::string(
enum_name(stmt.symbol->type));
73 line(
"Symbol: {} (type: {})", stmt.symbol->name, type_name);
79 print(stmt.value.get());
85 line(
"ArrayAssignStmt:");
89 print(stmt.target.get());
93 print(stmt.value.get());
98void ASTPrinter::visit(
const BlockStmt& stmt) {
101 for (
const auto& s : stmt.statements) {
107void ASTPrinter::visit(
const IfStmt& stmt) {
112 print(stmt.condition.get());
116 print(stmt.then_branch.get());
118 if (stmt.else_branch) {
121 print(stmt.else_branch.get());
127void ASTPrinter::visit(
const WhileStmt& stmt) {
132 print(stmt.condition.get());
136 print(stmt.body.get());
141void ASTPrinter::visit(
const ReturnStmt& stmt) {
145 print(stmt.value.get());
150void ASTPrinter::visit(
const LabelStmt& stmt) {
151 line(
"LabelStmt: {}", stmt.name.value);
154 line(
"Symbol: {}", stmt.symbol->name);
159void ASTPrinter::visit(
const GotoStmt& stmt) {
160 line(
"GotoStmt: {}", stmt.label.value);
161 if (stmt.target_label_symbol) {
163 line(
"Target Symbol: {}", stmt.target_label_symbol->name);
166 if (stmt.condition) {
170 print(stmt.condition.get());
176void ASTPrinter::visit(
const GlobalDecl& stmt) {
177 std::string mode_name = std::string(
enum_name(stmt.mode));
178 line(
"GlobalDecl: mode={}", mode_name);
181 for (
const auto& g : stmt.globals) {
182 line(
"Global: {}", g.value);
189 line(
"FunctionDef: {}", stmt.name.value);
192 line(
"Symbol: {}", stmt.symbol->name);
196 if (!stmt.params.empty()) {
199 for (
const auto& p : stmt.params) {
200 std::string type_name = std::string(
enum_name(p.type));
201 line(
"Param: {} (type: {})", p.name.value, type_name);
205 if (stmt.global_decl) {
206 visit(*stmt.global_decl);
218void ASTPrinter::visit(
const NumberExpr& expr) {
219 line(
"NumberExpr: {}", expr.value.value);
223 line(
"VariableExpr: {}", expr.name.value);
226 std::string type_name = std::string(
enum_name(expr.symbol->type));
227 line(
"Symbol: {} (type: {})", expr.symbol->name, type_name);
232void ASTPrinter::visit(
const UnaryExpr& expr) {
233 line(
"UnaryExpr: {}", expr.op.value);
235 print(expr.right.get());
239void ASTPrinter::visit(
const BinaryExpr& expr) {
240 line(
"BinaryExpr: {}", expr.op.value);
244 print(expr.left.get());
248 print(expr.right.get());
254 line(
"TernaryExpr:");
258 print(expr.cond.get());
262 print(expr.true_expr.get());
266 print(expr.false_expr.get());
271void ASTPrinter::visit(
const CallExpr& expr) {
272 line(
"CallExpr: {}", expr.callee);
273 if (expr.resolved_signature !=
nullptr) {
275 line(
"Resolved to user function: {}", expr.resolved_signature->name);
278 if (expr.resolved_builtin !=
nullptr) {
280 line(
"Resolved to builtin: {}", expr.resolved_builtin->name);
283 if (expr.resolved_def !=
nullptr) {
285 line(
"Resolved def: {}", expr.resolved_def->name.value);
288 if (!expr.args.empty()) {
292 for (
const auto& arg : expr.args) {
301 line(
"PropAccessExpr: {}.{}", expr.clip.value, expr.prop.value);
305 line(
"StaticRelPixelAccessExpr: {}[{},{}]{}", expr.clip.value,
306 expr.offset_x.value, expr.offset_y.value, expr.boundary_suffix);
310 line(
"FrameDimensionExpr: {}.{}",
"frame", expr.dimension_name);
314 print(expr.plane_index_expr.get());
320 line(
"ArrayAccessExpr:");
321 if (expr.array_symbol) {
323 line(
"Array Symbol: {}", expr.array_symbol->name);
329 print(expr.array.get());
333 print(expr.index.get());
consteval std::string_view enum_name()
std::string print(const Program *program)
std::vector< std::unique_ptr< Stmt > > statements