diff options
Diffstat (limited to 'boot')
| -rw-r--r-- | boot/tests/parse/basic.cskt | 2 | ||||
| -rw-r--r-- | boot/visit.c | 317 |
2 files changed, 178 insertions, 141 deletions
diff --git a/boot/tests/parse/basic.cskt b/boot/tests/parse/basic.cskt index fcc6af0..a59aff6 100644 --- a/boot/tests/parse/basic.cskt +++ b/boot/tests/parse/basic.cskt @@ -9,6 +9,6 @@ main = fun () int { >>> -(expr (binary = (expr (name main)) (expr (function (returns (type name int)) (block +(expr (binary = (expr (name main)) (expr (function (returns (type name int)) (block (return (expr (binary + (expr 1) (expr 2)))) ))))) \ No newline at end of file diff --git a/boot/visit.c b/boot/visit.c index 500fb5a..3cc3e55 100644 --- a/boot/visit.c +++ b/boot/visit.c @@ -501,28 +501,59 @@ struct Tree_Printer { uint indentation_level; FILE* output; + bool did_print_last_visit; }; +#define TREE_PRINTER_PREAMBLE \ + DATA_FOR_VISIT(struct Tree_Printer, printer); \ + tree_printer_reset_print_state(printer); + +void +tree_printer_out(struct Tree_Printer* printer, const ascii* format, ...) +{ + va_list args; + va_start(args, format); + vfprintf(printer->output, format, args); + va_end(args); + + printer->did_print_last_visit = true; +} + +#define PRINT(...) tree_printer_out(printer, __VA_ARGS__) +#define PRINT_WHITESPACE_IF_NEEDED(s) \ + do { \ + if (printer->did_print_last_visit) { PRINT(s); } \ + tree_printer_reset_print_state(printer); \ + } while (0) + +void +tree_printer_reset_print_state(struct Tree_Printer* printer) +{ + printer->did_print_last_visit = false; +} + void tree_printer_indent(struct Tree_Printer* printer) { - for (uint i = 0; i < printer->indentation_level; ++i) fprintf(printer->output, "\t"); + for (uint i = 0; i < printer->indentation_level; ++i) PRINT("\t"); } void printer_visit_tree(struct Visit* visit, struct Tree* tree) { - DATA_FOR_VISIT(struct Tree_Printer, printer); + TREE_PRINTER_PREAMBLE + FOR_EACH (struct Statement*, statement, tree->top_level_statements) { VISIT(visit_statement, statement); - fprintf(printer->output, "\n"); + PRINT("\n"); } } void printer_visit_statement(struct Visit* visit, struct Statement* statement) { - DATA_FOR_VISIT(struct Tree_Printer, printer); + TREE_PRINTER_PREAMBLE + tree_printer_indent(printer); walk_statement(visit, statement); } @@ -530,67 +561,67 @@ printer_visit_statement(struct Visit* visit, struct Statement* statement) void printer_visit_statement_declaration(struct Visit* visit, struct Statement* stmt) { - DATA_FOR_VISIT(struct Tree_Printer, printer); + TREE_PRINTER_PREAMBLE if (stmt->value.declaration.kind == STATEMENT_DECLARATION_VARIABLE) - fprintf(printer->output, "(variable "); + PRINT("(variable "); else if (stmt->value.declaration.kind == STATEMENT_DECLARATION_CONSTANT) - fprintf(printer->output, "(constant "); + PRINT("(constant "); VISIT(visit_bare_declaration_node, &stmt->value.declaration.inner); - fprintf(printer->output, ")"); + PRINT(")"); } void printer_visit_statement_conditional(struct Visit* visit, struct Statement* stmt) { - DATA_FOR_VISIT(struct Tree_Printer, printer); + TREE_PRINTER_PREAMBLE - fprintf(printer->output, "(conditional"); + PRINT("(conditional"); for (uint i = 0; i < stmt->value.conditional.condition_count; ++i) { const struct Statement_Conditional_Branch* branch = &stmt->value.conditional.conditions[i]; - fprintf(printer->output, " "); + PRINT(" "); if (branch->when) { - fprintf(printer->output, "(when "); + PRINT("(when "); VISIT(visit_expression, branch->when); - fprintf(printer->output, ") "); + PRINT(") "); } else { - fprintf(printer->output, "(always) "); + PRINT("(always) "); } VISIT(visit_block_node, (struct Block_Node*)&branch->then); } - fprintf(printer->output, ")"); + PRINT(")"); } void printer_visit_statement_loop(struct Visit* visit, struct Statement* stmt) { - DATA_FOR_VISIT(struct Tree_Printer, printer); + TREE_PRINTER_PREAMBLE - fprintf(printer->output, "(loop "); + PRINT("(loop "); switch (stmt->value.loop.style) { case STATEMENT_LOOP_STYLE_C: - fprintf(printer->output, "c-style "); + PRINT("c-style "); VISIT(visit_bare_declaration_node, &stmt->value.loop.declaration); - fprintf(printer->output, " (condition "); + PRINT(" (condition "); VISIT(visit_expression, stmt->value.loop.condition); - fprintf(printer->output, ") (iteration "); + PRINT(") (iteration "); VISIT(visit_expression, stmt->value.loop.iteration); - fprintf(printer->output, ") "); + PRINT(") "); break; case STATEMENT_LOOP_STYLE_FOR_EACH: - fprintf(printer->output, "for-each "); + PRINT("for-each "); VISIT(visit_bare_declaration_node, &stmt->value.loop.declaration); - fprintf(printer->output, " "); + PRINT(" "); break; case STATEMENT_LOOP_STYLE_WHILE: - fprintf(printer->output, "while (condition "); + PRINT("while (condition "); VISIT(visit_expression, stmt->value.loop.condition); - fprintf(printer->output, ") "); + PRINT(") "); break; case STATEMENT_LOOP_STYLE_ENDLESS: - fprintf(printer->output, "endless "); + PRINT("endless "); break; default: fprintf(stderr, "unexpected loop style in `printer_visit_statement_loop`"); @@ -598,258 +629,256 @@ printer_visit_statement_loop(struct Visit* visit, struct Statement* stmt) } VISIT(visit_block_node, &stmt->value.loop.body); - fprintf(printer->output, ")"); + PRINT(")"); } void printer_visit_statement_return(struct Visit* visit, struct Statement* stmt) { - DATA_FOR_VISIT(struct Tree_Printer, printer); + TREE_PRINTER_PREAMBLE - fprintf(printer->output, "(return"); + PRINT("(return"); if (stmt->value.return_value.value) { - fprintf(printer->output, " "); + PRINT(" "); VISIT(visit_expression, stmt->value.return_value.value); } - fprintf(printer->output, ")"); + PRINT(")"); } void printer_visit_statement_break(struct Visit* visit, struct Statement* stmt) { - DATA_FOR_VISIT(struct Tree_Printer, printer); + TREE_PRINTER_PREAMBLE - fprintf(printer->output, "(break)"); + PRINT("(break)"); } void printer_visit_statement_continue(struct Visit* visit, struct Statement* stmt) { - DATA_FOR_VISIT(struct Tree_Printer, printer); + TREE_PRINTER_PREAMBLE - fprintf(printer->output, "(continue)"); + PRINT("(continue)"); } void printer_visit_statement_defer(struct Visit* visit, struct Statement* stmt) { - DATA_FOR_VISIT(struct Tree_Printer, printer); + TREE_PRINTER_PREAMBLE - fprintf(printer->output, "(defer "); + PRINT("(defer "); if (stmt->value.defer.expression) { VISIT(visit_expression, stmt->value.defer.expression); } else { VISIT(visit_block_node, &stmt->value.defer.block); } - fprintf(printer->output, ")"); + PRINT(")"); } void printer_visit_expression(struct Visit* visit, struct Expression* expression) { - DATA_FOR_VISIT(struct Tree_Printer, printer); - fprintf(printer->output, "(expr "); + TREE_PRINTER_PREAMBLE + PRINT("(expr "); walk_expression(visit, expression); - fprintf(printer->output, ")"); + PRINT(")"); } void printer_visit_expression_integer_literal(struct Visit* visit, struct Expression* expr) { - DATA_FOR_VISIT(struct Tree_Printer, printer); + TREE_PRINTER_PREAMBLE - fprintf(printer->output, "%ld", expr->value.integer_literal.value); + PRINT("%ld", expr->value.integer_literal.value); } void printer_visit_expression_float_literal(struct Visit* visit, struct Expression* expr) { - DATA_FOR_VISIT(struct Tree_Printer, printer); + TREE_PRINTER_PREAMBLE - fprintf(printer->output, "%lf", expr->value.float_literal.value); + PRINT("%lf", expr->value.float_literal.value); } void printer_visit_expression_string_literal(struct Visit* visit, struct Expression* expr) { - DATA_FOR_VISIT(struct Tree_Printer, printer); + TREE_PRINTER_PREAMBLE - fprintf(printer->output, "\"%s\"", expr->value.string_literal.value.data); + PRINT("\"%s\"", expr->value.string_literal.value.data); } void printer_visit_expression_boolean_literal(struct Visit* visit, struct Expression* expr) { - DATA_FOR_VISIT(struct Tree_Printer, printer); + TREE_PRINTER_PREAMBLE - fprintf(printer->output, "%s", expr->value.bool_literal.value ? "true" : "false"); + PRINT("%s", expr->value.bool_literal.value ? "true" : "false"); } void printer_visit_expression_name(struct Visit* visit, struct Expression* expr) { - DATA_FOR_VISIT(struct Tree_Printer, printer); + TREE_PRINTER_PREAMBLE - fprintf(printer->output, "(name %s)", expr->value.name.name.data); + PRINT("(name %s)", expr->value.name.name.data); } void printer_visit_expression_unary_operation(struct Visit* visit, struct Expression* expr) { - DATA_FOR_VISIT(struct Tree_Printer, printer); + TREE_PRINTER_PREAMBLE - fprintf(printer->output, "(unary %s ", - unary_operation_to_string(expr->value.unary_operator.operation)); + PRINT("(unary %s ", unary_operation_to_string(expr->value.unary_operator.operation)); VISIT(visit_expression, expr->value.unary_operator.operand); - fprintf(printer->output, ")"); + PRINT(")"); } void printer_visit_expression_binary_operation(struct Visit* visit, struct Expression* expr) { - DATA_FOR_VISIT(struct Tree_Printer, printer); + TREE_PRINTER_PREAMBLE - fprintf(printer->output, "(binary %s ", - binary_operation_to_string(expr->value.binary_operator.operation)); + PRINT("(binary %s ", binary_operation_to_string(expr->value.binary_operator.operation)); VISIT(visit_expression, expr->value.binary_operator.left_operand); - fprintf(printer->output, " "); + PRINT(" "); VISIT(visit_expression, expr->value.binary_operator.right_operand); - fprintf(printer->output, ")"); + PRINT(")"); } void printer_visit_expression_group(struct Visit* visit, struct Expression* expr) { - DATA_FOR_VISIT(struct Tree_Printer, printer); + TREE_PRINTER_PREAMBLE - fprintf(printer->output, "(group "); + PRINT("(group "); VISIT(visit_expression, expr->value.group.inner_expression); - fprintf(printer->output, ")"); + PRINT(")"); } void printer_visit_expression_call_or_construct(struct Visit* visit, struct Expression* expr) { - DATA_FOR_VISIT(struct Tree_Printer, printer); + TREE_PRINTER_PREAMBLE struct Expression_Call_Or_Construct* coc = &expr->value.call_or_construct; - fprintf(printer->output, "(call/construct "); + PRINT("(call/construct "); VISIT(visit_expression, coc->subject); uint i = 0; FOR_EACH (struct Expression*, argument, coc->arguments) { struct String name = string_array_at(&coc->argument_names, i++); if (name.data && name.data[0] != '\0') { - fprintf(printer->output, " (named arg '%s' ", name.data); + PRINT(" (named arg '%s' ", name.data); } else { - fprintf(printer->output, " (arg "); + PRINT(" (arg "); } VISIT(visit_expression, argument); - fprintf(printer->output, ")"); + PRINT(")"); } - fprintf(printer->output, ")"); + PRINT(")"); } void printer_visit_expression_subscript(struct Visit* visit, struct Expression* expr) { - DATA_FOR_VISIT(struct Tree_Printer, printer); + TREE_PRINTER_PREAMBLE - fprintf(printer->output, "(subscript "); + PRINT("(subscript "); VISIT(visit_expression, expr->value.subscript.subject); - fprintf(printer->output, " "); + PRINT(" "); VISIT(visit_expression, expr->value.subscript.index); - fprintf(printer->output, ")"); + PRINT(")"); } void printer_visit_expression_member(struct Visit* visit, struct Expression* expr) { - DATA_FOR_VISIT(struct Tree_Printer, printer); + TREE_PRINTER_PREAMBLE - fprintf(printer->output, "(member of "); + PRINT("(member of "); VISIT(visit_expression, expr->value.member.subject); - fprintf(printer->output, " named %s)", expr->value.member.name.data); + PRINT(" named %s)", expr->value.member.name.data); } void printer_visit_expression_increment_decrement(struct Visit* visit, struct Expression* expr) { - DATA_FOR_VISIT(struct Tree_Printer, printer); + TREE_PRINTER_PREAMBLE const struct Expression_Increment_Decrement* inc_dec = &expr->value.increment_decrement; const ascii* prefix_or_postfix = inc_dec->prefix ? "prefix" : "postfix"; - fprintf(printer->output, "(increment/decrement %s %s ", - increment_decrement_operation_to_string(inc_dec->operation), prefix_or_postfix); + PRINT("(increment/decrement %s %s ", + increment_decrement_operation_to_string(inc_dec->operation), prefix_or_postfix); VISIT(visit_expression, inc_dec->subject); - fprintf(printer->output, ")"); + PRINT(")"); } void printer_visit_expression_function(struct Visit* visit, struct Expression* expr) { - DATA_FOR_VISIT(struct Tree_Printer, printer); + TREE_PRINTER_PREAMBLE struct Expression_Function* fun = &expr->value.function; - fprintf(printer->output, "(function "); + PRINT("(function "); VISIT(visit_function_header_node, &fun->header); - fprintf(printer->output, " "); + PRINT_WHITESPACE_IF_NEEDED(" "); VISIT(visit_block_node, (struct Block_Node*)&fun->body); - fprintf(printer->output, ")"); + PRINT(")"); } void printer_visit_type_node(struct Visit* visit, struct Type_Node* node) { - DATA_FOR_VISIT(struct Tree_Printer, printer); - fprintf(printer->output, "(type "); + TREE_PRINTER_PREAMBLE + PRINT("(type "); walk_type_node(visit, node); - fprintf(printer->output, ")"); + PRINT(")"); } void printer_visit_type_node_name(struct Visit* visit, struct Type_Node* node) { - DATA_FOR_VISIT(struct Tree_Printer, printer); + TREE_PRINTER_PREAMBLE - fprintf(printer->output, "name %s", node->value.name.name.data); + PRINT("name %s", node->value.name.name.data); } void printer_visit_type_node_array(struct Visit* visit, struct Type_Node* node) { - DATA_FOR_VISIT(struct Tree_Printer, printer); + TREE_PRINTER_PREAMBLE - fprintf(printer->output, "array of "); + PRINT("array of "); VISIT(visit_type_node, node->value.array.element_type); } void printer_visit_type_node_reference(struct Visit* visit, struct Type_Node* node) { - DATA_FOR_VISIT(struct Tree_Printer, printer); + TREE_PRINTER_PREAMBLE - fprintf(printer->output, "reference to "); + PRINT("reference to "); VISIT(visit_type_node, node->value.reference.referenced_type); } void printer_visit_type_node_maybe(struct Visit* visit, struct Type_Node* node) { - DATA_FOR_VISIT(struct Tree_Printer, printer); + TREE_PRINTER_PREAMBLE - fprintf(printer->output, "maybe "); + PRINT("maybe "); VISIT(visit_type_node, node->value.maybe.inner_type); } void printer_visit_type_node_tuple(struct Visit* visit, struct Type_Node* node) { - DATA_FOR_VISIT(struct Tree_Printer, printer); + TREE_PRINTER_PREAMBLE - fprintf(printer->output, "tuple"); + PRINT("tuple"); FOR_EACH (struct Type_Node*, current, node->value.tuple.head) { - fprintf(printer->output, " "); + PRINT(" "); VISIT(visit_type_node, current); } } @@ -857,31 +886,31 @@ printer_visit_type_node_tuple(struct Visit* visit, struct Type_Node* node) void printer_visit_type_node_map(struct Visit* visit, struct Type_Node* node) { - DATA_FOR_VISIT(struct Tree_Printer, printer); + TREE_PRINTER_PREAMBLE - fprintf(printer->output, "map "); + PRINT("map "); VISIT(visit_type_node, node->value.map.key_type); - fprintf(printer->output, " = "); + PRINT(" = "); VISIT(visit_type_node, node->value.map.value_type); } void printer_visit_type_node_function(struct Visit* visit, struct Type_Node* node) { - DATA_FOR_VISIT(struct Tree_Printer, printer); + TREE_PRINTER_PREAMBLE - fprintf(printer->output, "function "); + PRINT("function "); VISIT(visit_function_header_node, &node->value.function.header); } void printer_visit_type_node_structure(struct Visit* visit, struct Type_Node* node) { - DATA_FOR_VISIT(struct Tree_Printer, printer); + TREE_PRINTER_PREAMBLE - fprintf(printer->output, "structure"); + PRINT("structure"); FOR_EACH (struct Type_Node*, current, node->value.structure.fields) { - fprintf(printer->output, " (field %s) ", current->value_name.data); + PRINT(" (field %s) ", current->value_name.data); VISIT(visit_type_node, current); } } @@ -889,16 +918,16 @@ printer_visit_type_node_structure(struct Visit* visit, struct Type_Node* node) void printer_visit_type_node_variant(struct Visit* visit, struct Type_Node* node) { - DATA_FOR_VISIT(struct Tree_Printer, printer); + TREE_PRINTER_PREAMBLE - fprintf(printer->output, "variant"); + PRINT("variant"); FOR_EACH (struct Type_Node*, current, node->value.variant.variants) { if (current->type == TYPE_NODE_NONE) { - fprintf(printer->output, " (variant %s)", current->value_name.data); + PRINT(" (variant %s)", current->value_name.data); } else { - fprintf(printer->output, " (variant %s of ", current->value_name.data); + PRINT(" (variant %s of ", current->value_name.data); VISIT(visit_type_node, current); - fprintf(printer->output, ")"); + PRINT(")"); } } } @@ -906,104 +935,106 @@ printer_visit_type_node_variant(struct Visit* visit, struct Type_Node* node) void printer_visit_type_node_class(struct Visit* visit, struct Type_Node* node) { - DATA_FOR_VISIT(struct Tree_Printer, printer); + TREE_PRINTER_PREAMBLE - fprintf(printer->output, "class"); + PRINT("class"); FOR_EACH (struct Type_Node*, current, node->value.class.methods) { - fprintf(printer->output, " (method %s ", current->value_name.data); + PRINT(" (method %s ", current->value_name.data); VISIT(visit_function_header_node, ¤t->value.function.header); - fprintf(printer->output, ")"); + PRINT(")"); } } void printer_visit_block_node(struct Visit* visit, struct Block_Node* node) { - DATA_FOR_VISIT(struct Tree_Printer, printer); + TREE_PRINTER_PREAMBLE - fprintf(printer->output, "(block \n"); + PRINT("(block\n"); printer->indentation_level++; FOR_EACH (struct Statement*, statement, node->statements) { VISIT(visit_statement, statement); - fprintf(printer->output, "\n"); + PRINT("\n"); } printer->indentation_level--; tree_printer_indent(printer); - fprintf(printer->output, ")"); + PRINT(")"); } void printer_visit_bare_declaration_node(struct Visit* visit, struct Bare_Declaration_Node* node) { - DATA_FOR_VISIT(struct Tree_Printer, printer); + TREE_PRINTER_PREAMBLE - fprintf(printer->output, "(declaration "); - STRING_ARRAY_FOR_EACH (i, name, node->names) { fprintf(printer->output, "%s ", name.data); } + PRINT("(declaration "); + STRING_ARRAY_FOR_EACH (i, name, node->names) { PRINT("%s ", name.data); } if (node->type && node->type->type != TYPE_NODE_NONE) { VISIT(visit_type_node, node->type); - fprintf(printer->output, " "); + PRINT(" "); } if (node->initializer) { - fprintf(printer->output, "(initializer "); + PRINT("(initializer "); VISIT(visit_expression, node->initializer); - fprintf(printer->output, ")"); + PRINT(")"); } - fprintf(printer->output, ")"); + PRINT(")"); } void printer_visit_function_header(struct Visit* visit, struct Function_Header_Node* header) { - DATA_FOR_VISIT(struct Tree_Printer, printer); + TREE_PRINTER_PREAMBLE FOR_EACH (struct Type_Node*, current, header->parameters_type_and_name) { - if (current != header->parameters_type_and_name) fprintf(printer->output, " "); + if (current != header->parameters_type_and_name) PRINT(" "); if (current->value_name.data && current->value_name.data[0] != '\0') - fprintf(printer->output, "(param %s) ", current->value_name.data); + PRINT("(param %s) ", current->value_name.data); else - fprintf(printer->output, "(param) "); + PRINT("(param) "); VISIT(visit_type_node, current); } + PRINT_WHITESPACE_IF_NEEDED(" "); + if (header->return_type) { - fprintf(printer->output, " (returns "); + PRINT("(returns "); VISIT(visit_type_node, header->return_type); - fprintf(printer->output, ")"); + PRINT(")"); } } void printer_visit_pragma_node(struct Visit* visit, struct Pragma_Node* node) { - DATA_FOR_VISIT(struct Tree_Printer, printer); + TREE_PRINTER_PREAMBLE const ascii* pragma_name = pragma_type_to_string(node->type); - fprintf(printer->output, "(pragma %s", pragma_name); + PRINT("(pragma %s", pragma_name); for (uint ai = 0; ai < node->argument_count; ++ai) { struct Pragma_Argument* arg = &node->arguments[ai]; switch (arg->type) { case PRAGMA_ARGUMENT_NUMBER: - fprintf(printer->output, " (number %ld)", arg->value.number); + PRINT(" (number %ld)", arg->value.number); break; case PRAGMA_ARGUMENT_DECIMAL: - fprintf(printer->output, " (decimal %lf)", arg->value.decimal); + PRINT(" (decimal %lf)", arg->value.decimal); break; case PRAGMA_ARGUMENT_NAME_OR_STRING: - fprintf(printer->output, " (name/string '%s')", arg->value.name_or_string.data); + PRINT(" (name/string '%s')", arg->value.name_or_string.data); break; default: failure("unexpected pragma argument type in `printer_visit_pragma_node`"); } } - fprintf(printer->output, ")"); + PRINT(")"); if (node->next) { - fprintf(printer->output, " "); + PRINT(" "); VISIT(visit_pragma_node, node->next); } } @@ -1056,8 +1087,14 @@ struct Visit_Table printer_visit_functions = { void tree_printer(struct Tree* tree) { - struct Tree_Printer printer = { .indentation_level = 0, .output = stdout }; + struct Tree_Printer printer = { + .indentation_level = 0, .output = stdout, .did_print_last_visit = false + }; struct Visit visit = { .table = &printer_visit_functions, .user_data = &printer }; walk(&visit, tree); } + +#undef PRINT +#undef PRINT_WHITESPACE_IF_NEEDED +#undef TREE_PRINTER_PREAMBLE |
