diff --git a/k.krak b/k.krak index 4d1aad4..554dfd9 100644 --- a/k.krak +++ b/k.krak @@ -87,32 +87,95 @@ fun main(argc: int, argv: **char): int { var name_ast_map = map>() var passes = map): void>() - // resolves all reachable imports - passes[str("import")] = fun(import_binding: *tree) { - var file_path = binding_str(import_binding) - println("Running import resolver for " + file_path) - if (!name_ast_map.contains_key(file_path)) { - printerr(file_path + ", ") - var parse_tree = parse.parse_input(read_file(file_path), file_path) - trim(parse_tree) - name_ast_map[file_path] = syntax_to_ast(file_path, parse_tree, import_paths) - } - set_bindings(import_binding, name_ast_map[file_path]) - - name_ast_map[file_path]->children.for_each(fun(n: *tree) { - match (n->data) { - ast::_import(b) { - pass_poset.add_close_dep(make_pair(import_binding, str("import")), make_pair(b.first, str("import"))) + // resolves all binding possibilities for one top level item + passes[str("name_possibility_resolve")] = fun(item: *tree) { + println("Running name possibility resolver?") + var scope_lookup: fun(*tree, str, bool): vec<*tree> = fun(scope: *tree, name: str, is_type: bool): vec<*tree> { + var to_ret = vec<*tree>() + for (var i = 0; i < scope->children.size; i++;) { + match(scope->children[i]->data) { + ast::_import(b) if b.second.contains(name) || b.second.contains(str("*")) { + if !bound(b.first) { + // Import / parse file if not already + var file_path = binding_str(b.first) + if (!name_ast_map.contains_key(file_path)) { + printerr(file_path + ", ") + var parse_tree = parse.parse_input(read_file(file_path), file_path) + trim(parse_tree) + name_ast_map[file_path] = syntax_to_ast(file_path, parse_tree, import_paths) + } + set_binding(b.first, name_ast_map[file_path]) + } + to_ret += scope_lookup(get_binding(b.first), name, is_type) + } + ast::_type_def(b) if (is_type && b == name) + to_ret += scope->children[i] + ast::_adt_def(b) if (is_type && b == name) + to_ret += scope->children[i] + ast::_function(b) if (!is_type && b.first == name) + to_ret += scope->children[i] + ast::_template(b) if (!is_type && b.first == name) + to_ret += scope->children[i] + ast::_identifier(b) if (!is_type && b.first == name) + to_ret += scope->children[i] + ast::_declaration() if (!is_type && scope->children[i]->children[0]->data._identifier.first == name) + to_ret += scope->children[i]->children[0] } } - }) + if (scope->parent != null>()) + return to_ret + scope_lookup(scope->parent, name, is_type) + return to_ret + } + var try_binding = fun(binding: *tree, start_scope: *tree, type_binding: bool) { + if !bound(binding) { + var options = scope_lookup(start_scope, binding->data._binding.first, type_binding) + if (options.size != 1) + error("Do not have exactly one option for scope lookup of " + binding->data._binding.first) + set_binding(binding, options[0]) + } + } + var handle_type: fun(*type, *tree): void = fun(t: *type, n: *tree) { + match(t->base) { + base_type::_obj(b) try_binding(b, n, true) + base_type::_fun(b) { + b.first.first.for_each(fun(it: *type) { + handle_type(it, n) + }) + handle_type(b.first.second, n) + } + } + } + var traverse_for_bindings: fun(*tree): void = fun(t: *tree) { + match (t->data) { + // TODO: Handle type binding lookup + ast::_identifier(b) handle_type(b.second, t) + /*_binding: triple, *tree>,*/ + ast::_function(b) handle_type(b.second, t) + ast::_compiler_intrinsic(b) b.second.for_each(fun(ty: *type) { + handle_type(ty, t) + }) + ast::_cast(b) handle_type(b, t) + /*_value: pair*/ + ast::_binding(b) try_binding(t, t, false) + } + t->children.for_each(traverse_for_bindings) + } + traverse_for_bindings(item) + } + + // resolves all binding possibilities for one top level item + passes[str("name_type_resolve")] = fun(item: *tree) { + println("Running name type resolver?") + // just temp + pass_poset.add_close_dep(make_pair(item, str("name_type_resolve")), make_pair(item, str("name_possibility_resolve"))) } // emit C var C_str = str() - passes[str("emit_C")] = fun(import_binding: *tree) { - if !pass_poset.done(make_pair(import_binding, str("import"))) { - pass_poset.add_open_dep(make_pair(import_binding, str("emit_C")), make_pair(import_binding, str("import"))) + var C_func_declaration_str = str() + passes[str("emit_C")] = fun(item: *tree) { + if !pass_poset.done(make_pair(item, str("name_type_resolve"))) { + pass_poset.add_open_dep(make_pair(item, str("emit_C")), make_pair(item, str("name_type_resolve"))) return } @@ -122,25 +185,34 @@ fun main(argc: int, argv: **char): int { error("type is ref in to_c_type") match(t->base) { base_type::_unknown() error("unknown in to_c_type") - base_type::_void() return "void" + ind + base_type::_void() return "void" + ind base_type::_obj(b) error("ob in to_c_type unimplemented") base_type::_fun(b) error("fun in to_c_type unimplemented") base_type::_template_placeholder() error("template_placeholder in to_c_type") - base_type::_bool() return "bool" + ind - base_type::_char() return "char" + ind - base_type::_uchar() return "usigned char" + ind - base_type::_short() return "short" + ind - base_type::_ushort() return "unsigned short" + ind - base_type::_int() return "int" + ind - base_type::_uint() return "unsigned int" + ind - base_type::_long() return "long" + ind - base_type::_ulong() return "unsigned long" + ind - base_type::_float() return "float" + ind - base_type::_double() return "double" + ind + base_type::_bool() return "bool" + ind + base_type::_char() return "char" + ind + base_type::_uchar() return "usigned char" + ind + base_type::_short() return "short" + ind + base_type::_ushort() return "unsigned short" + ind + base_type::_int() return "int" + ind + base_type::_uint() return "unsigned int" + ind + base_type::_long() return "long" + ind + base_type::_ulong() return "unsigned long" + ind + base_type::_float() return "float" + ind + base_type::_double() return "double" + ind } error("fell through to_c_type") } + var emit_name = fun(x: *tree): void { + match(x->data) { + ast::_identifier(b) { C_str += b.first; return; } + ast::_type_def(b) { C_str += b; return; } + ast::_function(b) { C_str += b.first; return; } + } + error("cannot emit_name of thing: " + to_string(x->data)) + } + var emit_C: fun(*tree, int): void = fun(t: *tree, level: int) { var idt = str("\t") * level match (t->data) { @@ -150,41 +222,60 @@ fun main(argc: int, argv: **char): int { C_str += ";\n" }) } - ast::_import(b) { - pass_poset.add_close_dep(make_pair(import_binding, str("emit_C")), make_pair(b.first, str("emit_C"))) - } + ast::_import(b) { } ast::_identifier(b) { C_str += idt + b.first; } - ast::_binding(b) { error("binding gen unimplemented"); } + ast::_binding(b) { + if (is_top_level_item(b.third)) + pass_poset.add_close_dep(make_pair(item, str("emit_C")), make_pair(b.third, str("emit_C"))) + emit_name(b.third) + } ast::_type_def(b) { error("type_def gen unimplemented"); } ast::_adt_def(b) { error("no adt_def should remain at C emit"); } ast::_function(b) { var fun_name = b.first var fun_type = b.second + var is_ext = b.third var return_type = fun_type->base._fun.first.second var parameter_types = fun_type->base._fun.first.first var is_variadic = fun_type->base._fun.second var is_raw = fun_type->base._fun.third - C_str += to_c_type(return_type) + " " + fun_name + " (" + // TODO check is_ext for name mangling + C_str += to_c_type(return_type) + " " + fun_name + "(" + C_func_declaration_str += to_c_type(return_type) + " " + fun_name + "(" for (var i = 0; i < parameter_types.size; i++;) { - if (i != 0) - C_str += ", " - C_str += to_c_type(parameter_types[i]) + " " + if (i != 0) { + C_str += ", " + C_func_declaration_str += ", " + } + C_str += to_c_type(parameter_types[i]) + " " + C_func_declaration_str += to_c_type(parameter_types[i]) emit_C(t->children[i], 0) } if (is_variadic) { - if (parameter_types.size != 0) + if (parameter_types.size != 0) { C_str += ", " - C_str += "..." + C_func_declaration_str += ", " + } + C_str += "..." + C_func_declaration_str += "..." } - C_str += ") {\n" + C_str += ") {\n" + C_func_declaration_str += ");\n" for (var i = parameter_types.size; i < t->children.size; i++;) { emit_C(t->children[i], level+1) C_str += ";\n" } - C_str += "}" + C_str += "}\n" } ast::_template(b) { /* template should be ignored */ } - ast::_declaration() { error("declaration gen unimplemented"); } + ast::_declaration() { + C_str += idt + to_c_type(t->children[0]->data._identifier.second) + " " + emit_name(t->children[0]) + if (t->children.size > 1) { + C_str += " = " + emit_C(t->children[1], 0) + } + } ast::_assignment() { error("assignment gen unimplemented"); } ast::_block() { C_str += idt + "{\n" @@ -192,7 +283,7 @@ fun main(argc: int, argv: **char): int { emit_C(c, level+1) C_str += ";\n" }) - C_str += idt + "}\n" + C_str += idt + "}" } ast::_if() { error("if gen unimplemented"); } ast::_match() { error("no match should remain at C emit"); } @@ -209,25 +300,54 @@ fun main(argc: int, argv: **char): int { ast::_break() { C_str += idt + "break"; } ast::_continue() { C_str += idt + "continue"; } ast::_defer() { error("no defer should remain at C emit"); } - ast::_call() { error("call gen unimplemented"); } + ast::_call() { + emit_C(t->children[0], level) + C_str += "(" + for (var i = 1; i < t->children.size; i++;) { + if (i != 1) + C_str += ", " + emit_C(t->children[1], level+1) + } + C_str += ")" + } ast::_compiler_intrinsic(b) { error("compiler_intrinsic gen unimplemented"); } ast::_cast(b) { error("cast gen unimplemented"); } ast::_value(b) { C_str += idt + b.first; } } } - var file_path = binding_str(import_binding) - println("Running emit C for " + file_path) - emit_C(name_ast_map[file_path], 0) + emit_C(item, 0) } - var top_binding = make_binding(kraken_file_name) - pass_poset.add_job(make_pair(top_binding, str("emit_C"))) + // We construct our real main entry function and add an emit_C pass for it, + // starting generation of the entire program + var real_main = _function( + str("main"), + type(base_type::_fun(make_triple(make_pair(vec( + type(base_type::_int(), 0, false), + type(base_type::_char(), 2, false) + ), + type(base_type::_int(), 0, false) + ), false, false)), 0, false), + true, vec( + _identifier(str("argc"), type(base_type::_int(), 0, false)), + _identifier(str("argv"), type(base_type::_char(), 2, false)), + _return(vec(_call(vec(make_binding("fmain"))))) + ) + ) + var top_unit = _translation_unit(str(), vec( + _import(make_binding(kraken_file_name), set(str("*")), vec( + _identifier(kraken_file_name, type(base_type::_void(), 0, false)) + )), + real_main + )) + pass_poset.add_job(make_pair(real_main, str("emit_C"))) pass_poset.run(fun(file_pass: pair<*tree, str>) { printlnerr("doing pass new style " + file_pass.second + " on " + to_string(file_pass.first->data)) passes[file_pass.second](file_pass.first) }) + C_str = C_func_declaration_str + "\n" + C_str println() println() @@ -252,44 +372,6 @@ fun main(argc: int, argv: **char): int { return 0 } -var bindings: *vec<*tree> -fun make_binding(s: str): *tree { - var binding = _binding(s, vec<*type>(), null>()) - if (bindings == null>>()) - bindings = new>>()->construct() - bindings->add(binding) - return binding -} -fun set_bindings(binding: *tree, to: *tree) { - match(binding->data) { - ast::_binding(b) { - var from = b.third - // don't set null, that will set all unbound ones - if (from == null>()) { - b.third = to - return - } - for (var i = 0; i < bindings->size; i++;) - if (bindings->get(i)->data._binding.third == from) - bindings->get(i)->data._binding.third = to - return - } - } - error("trying to set bindings on not a binding") -} -fun bound(binding: *tree): bool { - match(binding->data) { - ast::_binding(b) return b.third != null>() - } - error("Trying to check bound for not a binding") -} -fun binding_str(binding: *tree): str { - match(binding->data) { - ast::_binding(b) return b.first - } - error("Trying to get name for not a binding") -} - fun parse_type(syntax: *tree): *type { var is_ref = get_node("\"ref\"", syntax) != null>() var indr = 0 @@ -373,7 +455,7 @@ fun syntax_to_ast(file_name: str, syntax: *tree, import_paths: ref vec): *type return i->data._identifier.second;), return_type), false, false)), 0, false) - var n = _function(concat(get_node("func_identifier", syntax)), function_type, parameters + body) + var n = _function(concat(get_node("func_identifier", syntax)), function_type, false, parameters + body) var template = get_node("template_dec", syntax) if (template == null>()) { return n diff --git a/stdlib/adt_lower.krak b/stdlib/adt_lower.krak index 3c80f75..1d1b63e 100644 --- a/stdlib/adt_lower.krak +++ b/stdlib/adt_lower.krak @@ -151,6 +151,8 @@ fun adt_lower(name_ast_map: *map,*ast_node>>, ast_to_syn block->code_block.children.add(_assign(holder, make_operator_call("&", vec(value)))) backing.cases.for_each(fun(case_stmt: *ast_node) { var option = case_stmt->case_statement.option + if (!get_ast_scope(get_ast_type(value)->type_def)->contains_key(str("flag"))) + error("trying to get flag from struct without it - are you matching on not an adt? - ") var flag = get_from_scope(get_ast_type(value)->type_def, "flag") var data = get_from_scope(get_ast_type(value)->type_def, "data") var option_num = -7 diff --git a/stdlib/ast.krak b/stdlib/ast.krak index d887574..286253a 100644 --- a/stdlib/ast.krak +++ b/stdlib/ast.krak @@ -13,7 +13,7 @@ adt ast { _binding: triple, *tree>, _type_def: str, _adt_def: str, - _function: pair, + _function: triple, _template: pair>, _declaration, _assignment, @@ -40,7 +40,7 @@ fun to_string(a: ref ast): str { ast::_binding(b) return str("_binding(") + b.first + "->" + to_string(b.third) + ")" ast::_type_def(b) return str("_type_def(") + b + ")" ast::_adt_def(b) return str("_adt_def(") + b + ")" - ast::_function(b) return str("_function(") + b.first + ": " + deref_to_string(b.second) + ")" + ast::_function(b) return str("_function(") + b.first + ": " + deref_to_string(b.second) + ", ext?:" + to_string(b.third) + ")" ast::_template(b) return str("_template(") + b.first + "[" + str(",").join(b.second.data) + "])" ast::_declaration() return str("_declaration") ast::_assignment() return str("_assignment") @@ -81,8 +81,8 @@ fun _identifier(p1: str, p2: *type): *tree { fun _binding(p1: str, p2: vec<*type>, p3: *tree): *tree { return new>()->construct(ast::_binding(make_triple(p1, p2, p3))) } -fun _function(p1: str, p2: *type): *tree { - return new>()->construct(ast::_function(make_pair(p1, p2))) +fun _function(p1: str, p2: *type, p3: bool): *tree { + return new>()->construct(ast::_function(make_triple(p1, p2, p3))) } fun _template(p1: str, p2: set): *tree { return new>()->construct(ast::_template(make_pair(p1, p2))) @@ -156,8 +156,8 @@ fun _identifier(p1: str, p2: *type, c: ref vec<*tree>): *tree { fun _binding(p1: str, p2: vec<*type>, p3: *tree, c: ref vec<*tree>): *tree { return new>()->construct(ast::_binding(make_triple(p1, p2, p3)), c) } -fun _function(p1: str, p2: *type, c: ref vec<*tree>): *tree { - return new>()->construct(ast::_function(make_pair(p1, p2)), c) +fun _function(p1: str, p2: *type, p3: bool, c: ref vec<*tree>): *tree { + return new>()->construct(ast::_function(make_triple(p1, p2, p3)), c) } fun _template(p1: str, p2: set, c: ref vec<*tree>): *tree { return new>()->construct(ast::_template(make_pair(p1, p2)), c) @@ -207,3 +207,81 @@ fun _defer(c: ref vec<*tree>): *tree { fun _call(c: ref vec<*tree>): *tree { return new>()->construct(ast::_call(), c) } + + + +fun is_translation_unit(i: *tree): bool { match(i->data) { ast::_translation_unit(b) return true; } return false; } +fun is_import(i: *tree): bool { match(i->data) { ast::_import(b) return true; } return false; } +fun is_identifier(i: *tree): bool { match(i->data) { ast::_identifier(b) return true; } return false; } +fun is_binding(i: *tree): bool { match(i->data) { ast::_binding(b) return true; } return false; } +fun is_type_def(i: *tree): bool { match(i->data) { ast::_type_def(b) return true; } return false; } +fun is_adt_def(i: *tree): bool { match(i->data) { ast::_adt_def(b) return true; } return false; } +fun is_function(i: *tree): bool { match(i->data) { ast::_function(b) return true; } return false; } +fun is_template(i: *tree): bool { match(i->data) { ast::_template(b) return true; } return false; } +fun is_declaration(i: *tree): bool { match(i->data) { ast::_declaration() return true; } return false; } +fun is_assignment(i: *tree): bool { match(i->data) { ast::_assignment() return true; } return false; } +fun is_block(i: *tree): bool { match(i->data) { ast::_block() return true; } return false; } +fun is_if(i: *tree): bool { match(i->data) { ast::_if() return true; } return false; } +fun is_match(i: *tree): bool { match(i->data) { ast::_match() return true; } return false; } +fun is_case(i: *tree): bool { match(i->data) { ast::_case() return true; } return false; } +fun is_while(i: *tree): bool { match(i->data) { ast::_while() return true; } return false; } +fun is_for(i: *tree): bool { match(i->data) { ast::_for() return true; } return false; } +fun is_return(i: *tree): bool { match(i->data) { ast::_return() return true; } return false; } +fun is_break(i: *tree): bool { match(i->data) { ast::_break() return true; } return false; } +fun is_continue(i: *tree): bool { match(i->data) { ast::_continue() return true; } return false; } +fun is_defer(i: *tree): bool { match(i->data) { ast::_defer() return true; } return false; } +fun is_call(i: *tree): bool { match(i->data) { ast::_call() return true; } return false; } +fun is_compiler_intrinsic(i: *tree): bool { match(i->data) { ast::_compiler_intrinsic(b) return true; } return false; } +fun is_cast(i: *tree): bool { match(i->data) { ast::_cast(b) return true; } return false; } +fun is_value(i: *tree): bool { match(i->data) { ast::_value(b) return true; } return false; } + +fun is_top_level_item(i: *tree): bool { return i->parent != null>() && is_translation_unit(i->parent); } + +var bindings: *vec<*tree> +fun make_binding(s: *char): *tree { + return make_binding(str(s)) +} +fun make_binding(s: str): *tree { + var binding = _binding(s, vec<*type>(), null>()) + if (bindings == null>>()) + bindings = new>>()->construct() + bindings->add(binding) + return binding +} +fun get_binding(binding: *tree): *tree { + match(binding->data) { + ast::_binding(b) { + return b.third + } + } + error("trying to get binding on not a binding") +} +fun set_binding(binding: *tree, to: *tree) { + match(binding->data) { + ast::_binding(b) { + var from = b.third + // don't set null, that will set all unbound ones + if (from == null>()) { + b.third = to + return + } + for (var i = 0; i < bindings->size; i++;) + if (bindings->get(i)->data._binding.third == from) + bindings->get(i)->data._binding.third = to + return + } + } + error("trying to set binding on not a binding") +} +fun bound(binding: *tree): bool { + match(binding->data) { + ast::_binding(b) return b.third != null>() + } + error("Trying to check bound for not a binding") +} +fun binding_str(binding: *tree): str { + match(binding->data) { + ast::_binding(b) return b.first + } + error("Trying to get name for not a binding") +} diff --git a/stdlib/tree.krak b/stdlib/tree.krak index fb3cd27..58a85dd 100644 --- a/stdlib/tree.krak +++ b/stdlib/tree.krak @@ -3,21 +3,28 @@ import vec obj tree (Object) { var data: T + var parent: *tree var children: vec::vec<*tree> fun construct(dataIn: T): *tree { mem::maybe_copy_construct(&data, &dataIn) + parent = mem::null>() children.construct() return this } fun construct(dataIn: T, c: ref vec::vec<*tree>): *tree { mem::maybe_copy_construct(&data, &dataIn) + parent = mem::null>() children.copy_construct(&c) + children.for_each(fun(i: *tree) { + i->parent = this + }) return this } // Some of these don't really make much sense considering this tree is all about // heap allocated pointers. Best to have it for saftey, though fun copy_construct(old: *tree) { mem::maybe_copy_construct(&data, &old->data) + parent = old->parent children.copy_construct(&old->children) } // ditto