#include #include "ast.h" void dump_tokens (token_t *tokens) { while (tokens->type != TOKEN_END_OF_FILE) { if (tokens->type == TOKEN_STRING_LITERAL) { g_print ("token: |%s| (string)\n", tokens->string_literal.value); } else { g_print ("token: |%s| %s\n", tokens->common.string, tokens->type == TOKEN_IDENTIFIER? " (id)" : ""); } tokens++; } } static void dump_expression (ast_expression_t *expr); static void dump_definition (ast_definition_t *def); static void dump_parameters (ast_variable_definition_t **parameters); static void dump_statement (ast_statement_t *statement); static void dump_binary_expression (ast_binary_expression_t *binary) { typedef struct ops_t ops_t; struct ops_t { ast_binary_operator_t op; const char str[4]; }; const ops_t ops [] = { { AST_ASSIGN, "=" }, { AST_PLUS, "+" }, { AST_MINUS, "-" }, { AST_TIMES, "*" }, { AST_DIVIDE, "/" }, { AST_MOD, "%" }, { AST_GT, ">" }, { AST_GTE, ">=" }, { AST_LT, "<" }, { AST_LTE, "<=" }, { AST_RSHIFT, ">>" }, { AST_LSHIFT, "<<" }, { AST_OR, "||" }, { AST_AND, "&&" }, { AST_BOR, "|" }, { AST_BXOR, "^" }, { AST_BAND, "&" }, { AST_EQUAL, "==" }, { AST_NOT_EQUAL, "!=" }, }; guint i; g_print ("("); dump_expression (binary->left); for (i = 0; i < G_N_ELEMENTS (ops); ++i) { if (ops[i].op == binary->operator) { g_print (" %s ", ops[i].str); break; } } dump_expression (binary->right); g_print (")"); } static void dump_unary_expression (ast_unary_expression_t *unary) { const char *op = NULL; gboolean post = FALSE; g_print ("("); switch (unary->operator) { case AST_UNARY_MINUS: op = "-"; break; case AST_UNARY_PLUS: op = "+"; break; case AST_UNARY_BNEG: op = "~"; break; case AST_UNARY_NOT: op = "!"; break; case AST_POSTFIX_DEC: op = "--"; post = TRUE; break; case AST_POSTFIX_INC: op = "++"; post = TRUE; break; case AST_PREFIX_INC: op = "++"; break; case AST_PREFIX_DEC: op = "--"; break; } g_assert (op); if (!post) g_print (op); dump_expression (unary->expr); if (post) g_print (op); g_print (")"); } static void dump_expression (ast_expression_t *expr) { int i; switch (expr->common.type) { case AST_INT_LITERAL_EXPRESSION: g_print ("%d", expr->int_literal.value); break; case AST_FLOAT_LITERAL_EXPRESSION: g_print ("%f", expr->float_literal.value); break; case AST_STRING_LITERAL_EXPRESSION: g_print ("\"%s\"", expr->string_literal.value); break; case AST_BOOL_LITERAL_EXPRESSION: g_print ("%s", expr->bool_literal.value? "true" : "false"); break; case AST_NULL_EXPRESSION: g_print ("null"); break; case AST_THIS_EXPRESSION: g_print ("this"); break; case AST_IDENTIFIER_EXPRESSION: g_print ("%s", expr->identifier.name); break; case AST_UNARY_EXPRESSION: dump_unary_expression (&expr->unary); break; case AST_BINARY_EXPRESSION: dump_binary_expression (&expr->binary); break; case AST_TERNARY_EXPRESSION: g_print ("("); dump_expression (expr->ternary.cond); g_print (" ? "); dump_expression (expr->ternary.then_expr); g_print (" : "); dump_expression (expr->ternary.else_expr); g_print (")"); break; case AST_LAMBDA_EXPRESSION: g_print ("fn ("); dump_parameters (expr->lambda.function->parameters); g_print (") -> "); dump_type_spec (expr->lambda.function->return_type); dump_statement (expr->lambda.function->body); break; case AST_CALL_EXPRESSION: g_print ("("); dump_expression (expr->call.callee); g_print (" ("); for (i = 0; expr->call.args[i] != NULL; ++i) { dump_expression (expr->call.args[i]); g_print (", "); } g_print (")) "); break; case AST_STATEMENT_EXPRESSION: g_print ("[["); dump_statement (expr->statement.statement); g_print ("]]"); dump_expression (expr->statement.expression); break; case AST_NEW_EXPRESSION: g_print ("new "); dump_type_spec (expr->new.type); g_print ("("); for (i = 0; expr->new.args[i] != NULL; ++i) { dump_expression (expr->new.args[i]); g_print (", "); } g_print (") "); break; case AST_DEFINITION_EXPRESSION: dump_definition (expr->definition.definition); g_print (" = "); dump_expression (expr->definition.initializer); break; case AST_BLOCK_EXPRESSION: g_print ("{[ "); dump_expression (expr->block.body); g_print ("]} "); break; case AST_DOT_EXPRESSION: dump_expression (expr->dot.left); g_print ("."); g_print ("%s", expr->dot.name); break; case AST_INDEX_EXPRESSION: dump_expression (expr->index.left); g_print ("["); dump_expression (expr->index.right); g_print ("]"); break; case AST_VOID_EXPRESSION: break; } } static void dump_case (ast_case_t *case_) { switch (case_->common.type) { case AST_EXPRESSION_CASE: g_print ("case "); dump_expression (case_->expression.expr); g_print (":"); break; case AST_DEFAULT_CASE: g_print ("default:"); break; } dump_statement (case_->common.statement); } static void dump_statement (ast_statement_t *statement) { int i; switch (statement->common.type) { case AST_DEFINITION_STATEMENT: dump_definition (statement->definition.def); break; case AST_PRINT_STATEMENT: g_print ("print "); for (i = 0; statement->print.exprs[i]; ++i) { dump_expression (statement->print.exprs[i]); g_print (", "); } g_print ("; "); break; case AST_LOOP_STATEMENT: g_print (" ("); dump_statement (statement->loop.init); g_print ("; "); dump_expression (statement->loop.condition); g_print ("; "); dump_statement (statement->loop.increment); g_print (") "); dump_statement (statement->loop.body); break; case AST_IF_STATEMENT: g_print ("if ("); dump_expression (statement->if_.condition); g_print (") {"); dump_statement (statement->if_.then_part); g_print ("} else {"); dump_statement (statement->if_.else_part); g_print ("} "); break; case AST_SWITCH_STATEMENT: g_print ("switch ("); dump_expression (statement->switch_.condition); g_print (") {"); for (i = 0; statement->switch_.cases[i] != NULL; ++i) dump_case (statement->switch_.cases[i]); g_print (" } "); break; case AST_EXPRESSION_STATEMENT: dump_expression (statement->expression.expr); g_print ("; "); break; case AST_COMPOUND_STATEMENT: dump_statement (statement->compound.first); dump_statement (statement->compound.second); break; case AST_BLOCK_STATEMENT: g_print (" { "); dump_statement (statement->block.body); g_print (" } "); break; case AST_GOTO_STATEMENT: g_print ("goto "); dump_expression (statement->goto_.target); g_print (";"); break; case AST_BREAK_STATEMENT: g_print ("break;"); break; case AST_CONTINUE_STATEMENT: g_print ("continue;"); break; case AST_LABEL_STATEMENT: g_print ("@%s:", statement->label.label); break; case AST_RETURN_STATEMENT: g_print ("return "); dump_expression (statement->return_.expr); g_print ("; "); break; case AST_EMPTY_STATEMENT: g_print ("; "); break; } } static void dump_parameters (ast_variable_definition_t **parameters) { int i; for (i = 0; parameters[i] != NULL; ++i) { g_print ("%s : ", parameters[i]->name); dump_type_spec (parameters[i]->type_spec); g_print (", "); } } static void dump_definition (ast_definition_t *definition) { switch (definition->common.type) { case AST_FUNCTION_DEFINITION: g_print ("%s (", definition->function.name); dump_parameters (definition->function.parameters); g_print (") -> "); dump_type_spec (definition->function.return_type); dump_statement (definition->function.body); break; case AST_VARIABLE_DEFINITION: g_print ("%s : ", definition->variable.name); dump_type_spec (definition->variable.type_spec); g_print ("; "); break; case AST_CLASS_DEFINITION: g_print ("class %s { ", definition->class.name); dump_statement (definition->class.statement); g_print (" } "); break; case AST_TYPE_DEFINITION: g_print ("typedef %s = ", definition->type.name); dump_type_spec (definition->type.type_spec); g_print ("; "); break; case AST_LABEL_DEFINITION: break; } } void dump_type_spec (ast_type_spec_t *type_spec) { int i; ast_type_spec_t *arg; switch (type_spec->common.type) { case AST_INT32_TYPE: g_print ("int32"); break; case AST_DOUBLE_TYPE: g_print ("double"); break; case AST_BOOL_TYPE: g_print ("bool"); break; case AST_VOID_TYPE: g_print ("void"); break; case AST_STRING_TYPE: g_print ("string"); break; case AST_NULL_TYPE: g_assert_not_reached(); break; case AST_IDENTIFIER_TYPE: g_print ("%s", type_spec->identifier.name); break; case AST_OBJECT_TYPE: g_print ("%s", type_spec->object.class->name); break; case AST_INFERRED_TYPE: break; case AST_ARRAY_TYPE: g_print ("array["); dump_type_spec (type_spec->array.child_type); g_print ("]"); break; case AST_LABEL_TYPE: g_print ("label"); break; case AST_FUNCTION_TYPE: g_print ("fn ("); for (i = 0; type_spec->function.args[i]; ++i) { arg = type_spec->function.args[i]; g_print ("v%d: ", i); dump_type_spec (arg); g_print (", "); } g_print (")"); g_print (" -> "); dump_type_spec (type_spec->function.return_); break; } } void dump_program (ast_program_t *program) { g_print ("'pretty' print\n"); dump_statement (program->statement); g_print ("\n"); } static void real_dump_graph (node_t *node) { while (node) { const char *text; switch (node->common.type) { case NODE_GOTO: g_print ("%p goto %p\n", node, node->goto_.label); break; case NODE_DYN_GOTO: g_print (" dyn goto\n"); break; case NODE_DYN_LABEL: g_print ("%p dyn label (%p)\n", node, node->dyn_label.label); break; case NODE_IF: if (node->if_.sense) text = "if_true"; else text = "if_false"; g_print (" %s -> %p\n", text, node->if_.taken); break; case NODE_BINOP: g_print (" binop\n"); break; case NODE_PROLOG: g_print (" prolog\n"); break; case NODE_FUN_REF: g_print (" fun_ref\n"); break; case NODE_UNARY: g_print (" unary op\n"); break; case NODE_LITERAL: g_print (" literal %s\n", value_to_string (&node->literal.value, node->literal.type_spec)); break; case NODE_PRINT: g_print (" print %d\n", node->print.n_exprs); break; case NODE_TO_STRING: g_print (" to_string\n"); break; case NODE_POP: g_print (" pop\n"); break; case NODE_DUP: g_print (" dup\n"); break; case NODE_RETURN: g_print (" return\n"); break; case NODE_STORE: g_print (" store %s\n", node->store.definition->name); break; case NODE_STORE_IND: g_print (" store_ind\n"); break; case NODE_STORE_ARRAY: g_print (" store_array\n"); break; case NODE_LOAD: g_print ("%p load %s\n", node, node->load.definition->name); break; case NODE_LOAD_IND: g_print (" load_ind\n"); break; case NODE_LOAD_ARRAY: g_print ("%p load_array\n", node); break; case NODE_NOP: g_print ("%p nop\n", node); break; case NODE_INIT: g_print (" init\n"); break; case NODE_LABEL: g_print ("%p label", node); if (ast_is (node->common.ast, AST_STATEMENT, AST_LABEL_STATEMENT)) g_print (" [%s]", node->common.ast->statement.label.label); g_print ("\n"); break; case NODE_CALL: g_print (" call\n"); break; case NODE_CLOSURE: g_print (" closure (%s)\n", node->closure.function->name); break; case NODE_DYN_CLOSURE: g_print (" dyn_closure (%s)\n", node->dyn_closure.function->name); break; case NODE_NEW: g_print (" new %s\n", node->new.class->name); break; case NODE_NEW_ARRAY: g_print (" new "); dump_type_spec ((ast_type_spec_t *)node->new_array.array); g_print ("\n"); break; case NODE_THIS: g_print (" this\n"); break; } node = node->common.next; } } void dump_graph (ast_program_t *program) { int i; g_print ("\nGraph:\n"); g_print ("*** main:\n"); real_dump_graph (program->enter); for (i = 0; program->functions[i] != NULL; ++i) { ast_function_definition_t *function = program->functions[i]; g_print ("\n*** %s:\n", function->name); real_dump_graph (function->enter); } }