static const char* node_str[] = { [NODE_BUILTIN] = "BUILTIN", [NODE_NUMBER] = "NUMBER", [NODE_BOOL] = "BOOL", [NODE_STRING] = "STRING", [NODE_SYMBOL] = "SYMBOL", [NODE_TYPE] = "TYPE", [NODE_DEF] = "DEF", [NODE_SET] = "SET", [NODE_FUN] = "FUN", [NODE_BLOCK] = "BLOCK", [NODE_IF] = "IF", [NODE_FUNCALL] = "FUNCALL", }; void viz_node(Node *node) { if (node == NULL) { return; } printf("%zu [width=2.5,shape=Mrecord,label=\"", node->id); printf(" %s -- [%4ld:%-4ld] ", node_str[node->type], node->line, node->col); if (node->expr_type != NULL) { printf("| T: "); sv_write(&node->expr_type->name); } switch (node->type) { case NODE_NUMBER: { printf("| Value: "); if (node->number.negative) { printf("-"); } if (node->number.fractional != 0) { printf("%zu.%zu", node->number.integral, node->number.fractional); } else { printf("%zu", node->number.integral); } printf("\"];\n"); } break; case NODE_SYMBOL: case NODE_TYPE: case NODE_STRING: { printf(" | Value: "); sv_write(&node->string); printf("\"];\n"); } break; case NODE_BOOL: { printf(" | Value: "); if (node->boolean) { printf("true"); } else { printf("false"); } printf("\"];\n"); } break; case NODE_BUILTIN: { printf(" | Name: %s", token_str[node->builtin.type]); printf(" | Args: "); printf("\"];\n"); size_t n_args = array_size(node->builtin.args); for (size_t i = 0; i < n_args; ++i) { viz_node(node->builtin.args[i]); printf("%zu:args:e->%zu:top:w;\n", node->id, node->builtin.args[i]->id); } } break; case NODE_DEF: { printf(" | Name: "); sv_write(&node->def.symbol->string); printf(" | Type: "); sv_write(&node->def.type->string); printf(" | Expr: "); printf("\"];\n"); viz_node(node->def.value); printf("%zu:val:e->%zu:top:w;\n", node->id, node->def.value->id); } break; case NODE_SET: { printf(" | Name: "); sv_write(&node->set.symbol->string); printf(" | Expr: "); printf("\"];\n"); viz_node(node->set.value); printf("%zu:val:e->%zu:top:w;\n", node->id, node->def.value->id); } break; case NODE_BLOCK: { printf(" | Exprs: "); printf("\"];\n"); size_t n_expr = array_size(node->block.expr); for (size_t i = 0; i < n_expr; ++i) { viz_node(node->block.expr[i]); printf("%zu:expr:e->%zu:top:w;\n", node->id, node->block.expr[i]->id); } } break; case NODE_IF: { printf(" | Cond: "); printf(" | ExprTrue:"); if (node->ifexpr.expr_false != NULL) { printf(" | ExprFalse: "); } printf("\"];\n"); viz_node(node->ifexpr.cond); printf("%zu:cond:e->%zu:top:w;\n", node->id, node->ifexpr.cond->id); viz_node(node->ifexpr.expr_true); printf("%zu:t:e->%zu:top:w;\n", node->id, node->ifexpr.expr_true->id); if (node->ifexpr.expr_false != NULL) { viz_node(node->ifexpr.expr_false); printf("%zu:f:e->%zu:top:w;\n", node->id, node->ifexpr.expr_false->id); } } break; case NODE_FUN: { printf(" | Name: "); sv_write(&node->fun.name->string); printf(" | Type: "); printf("("); size_t n_params = array_size(node->fun.param_names); for (size_t i = 0; i < n_params; ++i) { printf(":"); sv_write(&node->fun.param_types[i]->string); if (i < n_params - 1) { printf(" "); } } printf("):"); sv_write(&node->fun.return_type->string); if (n_params > 0) { printf(" | Parameters: ("); for (size_t i = 0; i < n_params; ++i) { sv_write(&node->fun.param_names[i]->string); if (i < n_params - 1) { printf(" "); } } printf(")"); } printf(" | Body: "); printf("\"];\n"); viz_node(node->fun.body); printf("%zu:bod:e->%zu:top:w;\n", node->id, node->fun.body->id); } break; case NODE_FUNCALL: { printf(" | Name: "); sv_write(&node->funcall.name->string); printf(" | Args: "); printf("\"];\n"); size_t n_args = array_size(node->funcall.args); for (size_t i = 0; i < n_args; ++i) { viz_node(node->funcall.args[i]); printf("%zu:args:e->%zu:top:w;\n", node->id, node->funcall.args[i]->id); } } break; } } void viz_ast(ParseTree *parse_tree) { if (parse_tree == NULL) { return; } printf("digraph ast {\n"); printf("rankdir=LR;\n"); printf("ranksep=\"0.95 equally\";\n"); printf("nodesep=\"0.5 equally\";\n"); printf("overlap=scale;\n"); for (size_t i = 0; i < array_size(parse_tree->roots); ++i) { printf("subgraph %zu {\n", i); Node *root = parse_tree->roots[array_size(parse_tree->roots) - 1 - i]; viz_node(root); printf("}\n"); } printf("}\n"); }