From 84032eece046527ee6f365db9ad6498f466b2247 Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Mon, 4 Jan 2016 00:38:59 -0500 Subject: [PATCH] Fix case_statement/lambda-close-over-variables bug, rename ast_node file to make ast_node:: unambigious, change test_ast to test_compiler and add a little skeleton c_generator file --- include/RemovalTransformation.h | 4 +- src/ASTTransformation.cpp | 6 +++ stdlib/{ast_node.krak => ast_nodes.krak} | 24 ++++++--- stdlib/ast_transformation.krak | 9 +++- stdlib/c_generator.krak | 54 +++++++++++++++++++++ stdlib/importer.krak | 2 +- tests/{test_ast.krak => test_compiler.krak} | 8 ++- 7 files changed, 95 insertions(+), 12 deletions(-) rename stdlib/{ast_node.krak => ast_nodes.krak} (96%) create mode 100644 stdlib/c_generator.krak rename tests/{test_ast.krak => test_compiler.krak} (88%) diff --git a/include/RemovalTransformation.h b/include/RemovalTransformation.h index 15d3586..8667e6b 100644 --- a/include/RemovalTransformation.h +++ b/include/RemovalTransformation.h @@ -36,11 +36,13 @@ NodeTree* RemovalTransformation::transform(NodeTree* from) { while(!toProcess.empty()) { NodeTree* node = toProcess.front(); toProcess.pop(); + if (!node) + continue; std::vector*> children = node->getChildren(); for (int i = 0; i < children.size(); i++) { if (children[i]->getData() == toRemove) node->removeChild(children[i]); - else + else if (children[i]) toProcess.push(children[i]); } } diff --git a/src/ASTTransformation.cpp b/src/ASTTransformation.cpp index cec2d58..a1c0a30 100644 --- a/src/ASTTransformation.cpp +++ b/src/ASTTransformation.cpp @@ -1070,6 +1070,12 @@ std::set*> ASTTransformation::findVariablesToClose(NodeTreegetDataRef()->type == case_statement) { + // don't try to close over the variant specifier itself, only its statement child + auto recClosed = findVariablesToClose(func, stat->getChildren().back(), scope); + closed.insert(recClosed.begin(), recClosed.end()); + return closed; + } if (stat->getDataRef()->type == function_call && (stat->getDataRef()->symbol.getName() == "." || stat->getDataRef()->symbol.getName() == "->")) { // only search on the left side of access operators like . and -> auto recClosed = findVariablesToClose(func, stat->getChildren()[1], scope); diff --git a/stdlib/ast_node.krak b/stdlib/ast_nodes.krak similarity index 96% rename from stdlib/ast_node.krak rename to stdlib/ast_nodes.krak index caf3b2e..6f6e4ed 100644 --- a/stdlib/ast_node.krak +++ b/stdlib/ast_nodes.krak @@ -272,12 +272,14 @@ fun ast_statement_ptr(): *ast_node { } obj statement (Object) { var scope: map> + var child: *ast_node fun construct(): *statement { scope.construct() return this } fun copy_construct(old: *statement) { scope.copy_construct(&old->scope) + child = old->child } fun destruct() { scope.destruct() @@ -287,7 +289,7 @@ obj statement (Object) { copy_construct(&other) } fun operator==(other: ref statement): bool { - return true + return child == other.child } } fun ast_if_statement_ptr(): *ast_node { @@ -584,22 +586,24 @@ fun ast_if_comp_ptr(): *ast_node { } obj if_comp (Object) { var wanted_generator: string + var statement: *ast_node fun construct(): *if_comp { wanted_generator.construct() return this } fun copy_construct(old: *if_comp) { wanted_generator.copy_construct(&old->wanted_generator) + statement = old->statement } fun destruct() { wanted_generator.destruct() } - fun operator=(other: ref if_comp) { + fun operator=(other: if_comp) { destruct() copy_construct(&other) } - fun operator==(other: ref if_comp): bool { - return wanted_generator == other.wanted_generator + fun operator==(other: if_comp): bool { + return wanted_generator == other.wanted_generator && statement == other.statement } } fun ast_simple_passthrough_ptr(): *ast_node { @@ -610,22 +614,26 @@ fun ast_simple_passthrough_ptr(): *ast_node { } obj simple_passthrough (Object) { var scope: map> + var passthrough_str: string fun construct(): *simple_passthrough { scope.construct() + passthrough_str.construct() return this } fun copy_construct(old: *simple_passthrough) { scope.copy_construct(&old->scope) + passthrough_str.copy_construct(&old->passthrough_str) } fun destruct() { scope.destruct() + passthrough_str.destruct() } fun operator=(other: ref simple_passthrough) { destruct() copy_construct(&other) } fun operator==(other: ref simple_passthrough): bool { - return true + return scope == other.scope && passthrough_str == other.passthrough_str } } fun ast_function_call_ptr(): *ast_node { @@ -690,7 +698,7 @@ fun get_ast_children(node: *ast_node): vector<*ast_node> { ast_node::adt_def(backing) return vector<*ast_node>() ast_node::function(backing) return vector<*ast_node>() ast_node::code_block(backing) return backing.children - ast_node::statement(backing) return vector<*ast_node>() + ast_node::statement(backing) return vector<*ast_node>(backing.child) ast_node::if_statement(backing) return vector<*ast_node>() ast_node::match_statement(backing) return vector<*ast_node>() ast_node::case_statement(backing) return vector<*ast_node>() @@ -702,7 +710,7 @@ fun get_ast_children(node: *ast_node): vector<*ast_node> { ast_node::defer_statement(backing) return vector<*ast_node>() ast_node::assignment_statement(backing) return vector<*ast_node>() ast_node::declaration_statement(backing) return vector<*ast_node>() - ast_node::if_comp(backing) return vector<*ast_node>() + ast_node::if_comp(backing) return vector<*ast_node>(backing.statement) ast_node::simple_passthrough(backing) return vector<*ast_node>() ast_node::function_call(backing) return vector<*ast_node>() ast_node::value(backing) return vector<*ast_node>() @@ -730,7 +738,7 @@ fun get_ast_name(node: *ast_node): string { ast_node::assignment_statement(backing) return string("assignment_statement") ast_node::declaration_statement(backing) return string("declaration_statement") ast_node::if_comp(backing) return string("if_comp: ") + backing.wanted_generator - ast_node::simple_passthrough(backing) return string("simple_passthrough") + ast_node::simple_passthrough(backing) return string("simple_passthrough: , string:") + backing.passthrough_str ast_node::function_call(backing) return string("function_call") ast_node::value(backing) return string("value") } diff --git a/stdlib/ast_transformation.krak b/stdlib/ast_transformation.krak index 7678738..0ce3cf2 100644 --- a/stdlib/ast_transformation.krak +++ b/stdlib/ast_transformation.krak @@ -8,7 +8,7 @@ import string:* import mem:* import io:* import importer:* -import ast_node:* +import ast_nodes:* /*Importer * importer;*/ /*NodeTree* builtin_trans_unit; // the top scope for language level stuff*/ @@ -101,13 +101,20 @@ obj ast_transformation (Object) { fun transform_if_comp(node: *tree, scope: *ast_node): *ast_node { var new_if_comp = ast_if_comp_ptr() new_if_comp->if_comp.wanted_generator = concat_symbol_tree(get_node("identifier", node)) + new_if_comp->if_comp.statement = transform_statement(get_node("statement", node), scope) return new_if_comp } fun transform_simple_passthrough(node: *tree, scope: *ast_node): *ast_node { var new_passthrough = ast_simple_passthrough_ptr() // setup passthrough params and string + new_passthrough->simple_passthrough.passthrough_str = concat_symbol_tree(get_node("triple_quoted_string", node)) return new_passthrough } + fun transform_statement(node: *tree, scope: *ast_node): *ast_node { + var new_statement = ast_statement_ptr() + new_statement->statement.child = transform(node->children[0], scope) + return new_statement + } } fun concat_symbol_tree(node: *tree): string { diff --git a/stdlib/c_generator.krak b/stdlib/c_generator.krak new file mode 100644 index 0000000..001a196 --- /dev/null +++ b/stdlib/c_generator.krak @@ -0,0 +1,54 @@ +import io:* +import mem:* +import map:* +import string:* +import util:* +import tree:* +import symbol:* +import ast_nodes:* + + +obj c_generator (Object) { + fun construct(): *c_generator { + return this + } + fun copy_construct(old: *c_generator) { + } + fun operator=(other: ref c_generator) { + destruct() + copy_construct(&other) + } + fun destruct() { + } + fun generate(name_ast_map: map,*ast_node>>): pair { + var linker_string:string = "" + var prequal: string = "#include \n#include \n#include \n" + var plain_typedefs: string = "" + var top_level_c_passthrough: string = "" + var variable_extern_declarations: string = "" + var structs: string = "" + var function_typedef_string_pre: string = "" + var function_typedef_string: string = "" + var function_prototypes: string = "" + var variable_declarations: string = "" + + + // poset generation into structs string + // iterate through asts + name_ast_map.for_each(fun(name: string, tree_pair: pair<*tree,*ast_node>) { + // iterate through children for each ast + // assert translation_unit? + tree_pair.second->translation_unit.children.for_each(fun(child: *ast_node) { + match (*child) { + ast_node::if_comp(backing) top_level_c_passthrough += "got an if_comp\n" + ast_node::simple_passthrough(backing) top_level_c_passthrough += "got a simple_passthrough\n" + } + }) + }) + + var function_definitions: string = "" + return make_pair(prequal+plain_typedefs+top_level_c_passthrough+variable_extern_declarations+structs+function_typedef_string_pre+function_typedef_string+function_prototypes+variable_declarations+function_definitions, linker_string) + } +} + + diff --git a/stdlib/importer.krak b/stdlib/importer.krak index efe6d00..fb9adbb 100644 --- a/stdlib/importer.krak +++ b/stdlib/importer.krak @@ -7,7 +7,7 @@ import util:* import string:* import mem:* import io:* -import ast_node:* +import ast_nodes:* import ast_transformation:* import parser:* diff --git a/tests/test_ast.krak b/tests/test_compiler.krak similarity index 88% rename from tests/test_ast.krak rename to tests/test_compiler.krak index 1a92b23..0d5565f 100644 --- a/tests/test_ast.krak +++ b/tests/test_compiler.krak @@ -7,6 +7,7 @@ import util:* import symbol:* import tree:* import serialize:* +import c_generator:* fun main():int { @@ -72,10 +73,15 @@ fun main():int { /*println(ast_to_dot(ast))*/ /*write_file(string("ast.dot"), ast_to_dot(ast))*/ + var kraken_file_name = string("to_parse.krak") var parse.construct(gram): parser var ast_pass.construct(): ast_transformation var importer.construct(parse, ast_pass): importer - importer.import(string("to_parse.krak")) + importer.import(kraken_file_name) + var c_generator.construct(): c_generator + var c_output_pair = c_generator.generate(importer.name_ast_map) + write_file(kraken_file_name + ".c", c_output_pair.first) + println(string("linker string: ") + c_output_pair.second) return 0 }