From 79065c032fa5fefd233ebaa08ec00e8027fc1bc6 Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Mon, 4 Jan 2016 02:00:06 -0500 Subject: [PATCH] We have a VERY SILL KRAKEN COMPILER\! simple_passthroughs are now emitted by the c_generator and test_compiler has been extended to write the C to a file and then call cc on it, so the self-hosted Kraken compiler can compile its very first thing\! (though that thing is a hello world C program written entirely in a simple_passthrough... --- stdlib/ast_nodes.krak | 138 +++++++++++++++++++++++++++++++++ stdlib/ast_transformation.krak | 4 +- stdlib/c_generator.krak | 20 ++++- stdlib/os.krak | 19 +++++ tests/test_compiler.krak | 7 +- tests/to_import.krak | 4 + 6 files changed, 186 insertions(+), 6 deletions(-) create mode 100644 stdlib/os.krak diff --git a/stdlib/ast_nodes.krak b/stdlib/ast_nodes.krak index 6f6e4ed..8545c8a 100644 --- a/stdlib/ast_nodes.krak +++ b/stdlib/ast_nodes.krak @@ -53,6 +53,12 @@ fun ast_translation_unit_ptr(name: string): *ast_node { ptr->copy_construct(&ast_node::translation_unit(obj_var)) return ptr } +fun is_translation_unit(node: *ast_node): bool { + match(*node) { + ast_node::translation_unit(backing) return true + } + return false +} obj translation_unit (Object) { var scope: map> var children: vector<*ast_node> @@ -87,6 +93,12 @@ fun ast_import_ptr(name: string): *ast_node { ptr->copy_construct(&ast_node::import(to_ret)) return ptr } +fun is_import(node: *ast_node): bool { + match(*node) { + ast_node::import(backing) return true + } + return false +} obj import (Object) { var scope: map> var imported: set @@ -124,6 +136,12 @@ fun ast_identifier_ptr(name: string): *ast_node { ptr->copy_construct(&ast_node::identifier(to_ret)) return ptr } +fun is_identifier(node: *ast_node): bool { + match(*node) { + ast_node::identifier(backing) return true + } + return false +} obj identifier (Object) { var name: string var scope: map> @@ -154,6 +172,12 @@ fun ast_type_def_ptr(name: string): *ast_node { ptr->copy_construct(&ast_node::type_def(to_ret)) return ptr } +fun is_type_def(node: *ast_node): bool { + match(*node) { + ast_node::type_def(backing) return true + } + return false +} obj type_def (Object) { var scope: map> var name: string @@ -184,6 +208,12 @@ fun ast_adt_def_ptr(name: string): *ast_node { ptr->copy_construct(&ast_node::adt_def(to_ret)) return ptr } +fun is_adt_def(node: *ast_node): bool { + match(*node) { + ast_node::adt_def(backing) return true + } + return false +} obj adt_def (Object) { var scope: map> var name: string @@ -214,6 +244,12 @@ fun ast_function_ptr(): *ast_node { ptr->copy_construct(&ast_node::function(to_ret)) return ptr } +fun is_function(node: *ast_node): bool { + match(*node) { + ast_node::function(backing) return true + } + return false +} obj function (Object) { var scope: map> fun construct(): *function { @@ -240,6 +276,12 @@ fun ast_code_block_ptr(): *ast_node { ptr->copy_construct(&ast_node::code_block(to_ret)) return ptr } +fun is_code_block(node: *ast_node): bool { + match(*node) { + ast_node::code_block(backing) return true + } + return false +} obj code_block (Object) { var scope: map> var children: vector<*ast_node> @@ -270,6 +312,12 @@ fun ast_statement_ptr(): *ast_node { ptr->copy_construct(&ast_node::statement(to_ret)) return ptr } +fun is_statement(node: *ast_node): bool { + match(*node) { + ast_node::statement(backing) return true + } + return false +} obj statement (Object) { var scope: map> var child: *ast_node @@ -298,6 +346,12 @@ fun ast_if_statement_ptr(): *ast_node { ptr->copy_construct(&ast_node::if_statement(to_ret)) return ptr } +fun is_if_statement(node: *ast_node): bool { + match(*node) { + ast_node::if_statement(backing) return true + } + return false +} obj if_statement (Object) { var scope: map> fun construct(): *if_statement { @@ -324,6 +378,12 @@ fun ast_match_statement_ptr(): *ast_node { ptr->copy_construct(&ast_node::match_statement(to_ret)) return ptr } +fun is_match_statement(node: *ast_node): bool { + match(*node) { + ast_node::match_statement(backing) return true + } + return false +} obj match_statement (Object) { var scope: map> fun construct(): *match_statement { @@ -350,6 +410,12 @@ fun ast_case_statement_ptr(): *ast_node { ptr->copy_construct(&ast_node::case_statement(to_ret)) return ptr } +fun is_case_statement(node: *ast_node): bool { + match(*node) { + ast_node::case_statement(backing) return true + } + return false +} obj case_statement (Object) { var scope: map> fun construct(): *case_statement { @@ -376,6 +442,12 @@ fun ast_while_loop_ptr(): *ast_node { ptr->copy_construct(&ast_node::while_loop(to_ret)) return ptr } +fun is_while_loop(node: *ast_node): bool { + match(*node) { + ast_node::while_loop(backing) return true + } + return false +} obj while_loop (Object) { var scope: map> fun construct(): *while_loop { @@ -402,6 +474,12 @@ fun ast_for_loop_ptr(): *ast_node { ptr->copy_construct(&ast_node::for_loop(to_ret)) return ptr } +fun is_for_loop(node: *ast_node): bool { + match(*node) { + ast_node::for_loop(backing) return true + } + return false +} obj for_loop (Object) { var scope: map> fun construct(): *for_loop { @@ -428,6 +506,12 @@ fun ast_return_statement_ptr(): *ast_node { ptr->copy_construct(&ast_node::return_statement(to_ret)) return ptr } +fun is_return_statement(node: *ast_node): bool { + match(*node) { + ast_node::return_statement(backing) return true + } + return false +} obj return_statement (Object) { var scope: map> fun construct(): *return_statement { @@ -454,6 +538,12 @@ fun ast_break_statement_ptr(): *ast_node { ptr->copy_construct(&ast_node::break_statement(to_ret)) return ptr } +fun is_break_statement(node: *ast_node): bool { + match(*node) { + ast_node::break_statement(backing) return true + } + return false +} obj break_statement (Object) { var scope: map> fun construct(): *break_statement { @@ -480,6 +570,12 @@ fun ast_continue_statement_ptr(): *ast_node { ptr->copy_construct(&ast_node::continue_statement(to_ret)) return ptr } +fun is_continue_statement(node: *ast_node): bool { + match(*node) { + ast_node::continue_statement(backing) return true + } + return false +} obj continue_statement (Object) { var scope: map> fun construct(): *continue_statement { @@ -506,6 +602,12 @@ fun ast_defer_statement_ptr(): *ast_node { ptr->copy_construct(&ast_node::defer_statement(to_ret)) return ptr } +fun is_defer_statement(node: *ast_node): bool { + match(*node) { + ast_node::defer_statement(backing) return true + } + return false +} obj defer_statement (Object) { var scope: map> fun construct(): *defer_statement { @@ -532,6 +634,12 @@ fun ast_assignment_statement_ptr(): *ast_node { ptr->copy_construct(&ast_node::assignment_statement(to_ret)) return ptr } +fun is_assignment_statement(node: *ast_node): bool { + match(*node) { + ast_node::assignment_statement(backing) return true + } + return false +} obj assignment_statement (Object) { var scope: map> fun construct(): *assignment_statement { @@ -558,6 +666,12 @@ fun ast_declaration_statement_ptr(): *ast_node { ptr->copy_construct(&ast_node::declaration_statement(to_ret)) return ptr } +fun is_declaration_statement(node: *ast_node): bool { + match(*node) { + ast_node::declaration_statement(backing) return true + } + return false +} obj declaration_statement (Object) { var scope: map> fun construct(): *declaration_statement { @@ -584,6 +698,12 @@ fun ast_if_comp_ptr(): *ast_node { ptr->copy_construct(&ast_node::if_comp(to_ret)) return ptr } +fun is_if_comp(node: *ast_node): bool { + match(*node) { + ast_node::if_comp(backing) return true + } + return false +} obj if_comp (Object) { var wanted_generator: string var statement: *ast_node @@ -612,6 +732,12 @@ fun ast_simple_passthrough_ptr(): *ast_node { ptr->copy_construct(&ast_node::simple_passthrough(to_ret)) return ptr } +fun is_simple_passthrough(node: *ast_node): bool { + match(*node) { + ast_node::simple_passthrough(backing) return true + } + return false +} obj simple_passthrough (Object) { var scope: map> var passthrough_str: string @@ -642,6 +768,12 @@ fun ast_function_call_ptr(): *ast_node { ptr->copy_construct(&ast_node::function_call(to_ret)) return ptr } +fun is_function_call(node: *ast_node): bool { + match(*node) { + ast_node::function_call(backing) return true + } + return false +} obj function_call (Object) { var scope: map> fun construct(): *function_call { @@ -668,6 +800,12 @@ fun ast_value_ptr(): *ast_node { ptr->copy_construct(&ast_node::value(to_ret)) return ptr } +fun is_value(node: *ast_node): bool { + match(*node) { + ast_node::value(backing) return true + } + return false +} obj value (Object) { var scope: map> fun construct(): *value { diff --git a/stdlib/ast_transformation.krak b/stdlib/ast_transformation.krak index 0ce3cf2..b14c186 100644 --- a/stdlib/ast_transformation.krak +++ b/stdlib/ast_transformation.krak @@ -80,6 +80,8 @@ obj ast_transformation (Object) { return transform_if_comp(node, scope) } else if (name == "simple_passthrough") { return transform_simple_passthrough(node, scope) + } else if (name == "statement") { + return transform_statement(node, scope) } print("FAILED TO TRANSFORM: "); println(concat_symbol_tree(node)) return null() @@ -107,7 +109,7 @@ obj ast_transformation (Object) { 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)) + new_passthrough->simple_passthrough.passthrough_str = concat_symbol_tree(get_node("triple_quoted_string", node)).slice(3,-4) return new_passthrough } fun transform_statement(node: *tree, scope: *ast_node): *ast_node { diff --git a/stdlib/c_generator.krak b/stdlib/c_generator.krak index 001a196..0387505 100644 --- a/stdlib/c_generator.krak +++ b/stdlib/c_generator.krak @@ -20,7 +20,7 @@ obj c_generator (Object) { } fun destruct() { } - fun generate(name_ast_map: map,*ast_node>>): pair { + fun generate_c(name_ast_map: map,*ast_node>>): pair { var linker_string:string = "" var prequal: string = "#include \n#include \n#include \n" var plain_typedefs: string = "" @@ -40,8 +40,12 @@ obj c_generator (Object) { // 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" + // should really check the genrator + ast_node::if_comp(backing) { + if (is_simple_passthrough(backing.statement->statement.child)) + top_level_c_passthrough += generate_simple_passthrough(backing.statement->statement.child) + } + ast_node::simple_passthrough(backing) top_level_c_passthrough += generate_simple_passthrough(child) } }) }) @@ -49,6 +53,16 @@ obj c_generator (Object) { 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) } + fun generate_simple_passthrough(node: *ast_node): string { + // deal with all the passthrough params + return node->simple_passthrough.passthrough_str + } + // for now, anyway + fun generate(node: *ast_node): string { + match (*node) { + ast_node::simple_passthrough(backing) return generate_simple_passthrough(node) + } + } } diff --git a/stdlib/os.krak b/stdlib/os.krak new file mode 100644 index 0000000..e85f4d5 --- /dev/null +++ b/stdlib/os.krak @@ -0,0 +1,19 @@ +import string:* +import mem:* + +fun system(call_string: string):int { + var c_call_string = call_string.toCharArray() + var result = system(c_call_string) + delete(c_call_string) + return result +} +fun system(call_string: *char): int { + __if_comp__ __C__ { + simple_passthrough(call_string::) """ + return system(call_string); + """ + } +} + + + diff --git a/tests/test_compiler.krak b/tests/test_compiler.krak index 0d5565f..b9fab02 100644 --- a/tests/test_compiler.krak +++ b/tests/test_compiler.krak @@ -8,6 +8,7 @@ import symbol:* import tree:* import serialize:* import c_generator:* +import os:* fun main():int { @@ -79,9 +80,11 @@ fun main():int { var importer.construct(parse, ast_pass): importer 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) + var c_output_pair = c_generator.generate_c(importer.name_ast_map) + var kraken_c_output_name = kraken_file_name + ".c" + write_file(kraken_c_output_name, c_output_pair.first) println(string("linker string: ") + c_output_pair.second) + system(string("cc -g -O3 -std=c99 ") + kraken_c_output_name + " -o " + kraken_file_name + ".exe") return 0 } diff --git a/tests/to_import.krak b/tests/to_import.krak index 9cca5b7..d4f451f 100644 --- a/tests/to_import.krak +++ b/tests/to_import.krak @@ -1,6 +1,10 @@ __if_comp__ __C__ simple_passthrough """ #include + int main() { + printf("hello world! (of selfhosting! (silly selfhosting for now))\n"); + return 0; + } """ var a = 1 var b = 2