From ca082c29bd9acdddacd349067faa0f51132486f9 Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Wed, 26 Dec 2018 20:34:06 -0500 Subject: [PATCH] Add in a top_level_type_resolve pass so that we properly have all the identifiers in our top level types resolved by the time we get to the meater resolve type passes, which may have to use them for scoping (with access op, etc) --- k.krak | 208 ++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 141 insertions(+), 67 deletions(-) diff --git a/k.krak b/k.krak index 34c8569..5caf1e6 100644 --- a/k.krak +++ b/k.krak @@ -195,6 +195,69 @@ fun main(argc: int, argv: **char): int { ), false, false))), vec<*binding>())))) } + var scope_lookup: fun(*tree, str, bool, *tree, str, str): OptionVecAst = fun(scope: *tree, name: str, is_type: bool, item: *tree, pass: str, pass_dep_on: str): OptionVecAst { + /*println("doing a scope lookup for " + name + " starting from " + to_string(scope->data))*/ + 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 !ast_bound(b.first) { + // Import / parse file if not already + var file_path = ast_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) + printlnerr("syntax_to_ast " + file_path + ":") + print_tree(name_ast_map[file_path], 1) + } + set_ast_binding(b.first, name_ast_map[file_path]) + } + var other_top_level = get_ast_binding(b.first) + if item != null>() { + if !pass_poset.done(make_pair(other_top_level, str("translation_unit_top_type_resolve"))) { + pass_poset.add_open_dep(make_pair(item, pass), make_pair(other_top_level, pass_dep_on)) + return OptionVecAst::None() + } + } + match (scope_lookup(other_top_level, name, is_type, item, pass, pass_dep_on)) { + OptionVecAst::None() return OptionVecAst::None() + OptionVecAst::Some(v) { + to_ret.add_all_unique(v) + } + } + } + ast::_type_def(b) if (is_type && b == name) + to_ret.add_unique(scope->children[i]) + ast::_adt_def(b) if (is_type && b == name) + to_ret.add_unique(scope->children[i]) + ast::_function(b) if (!is_type && b.first == name) + to_ret.add_unique(scope->children[i]) + ast::_compiler_intrinsic(b) if (!is_type && b.first == name) + to_ret.add_unique(scope->children[i]) + ast::_template(b) if (((!is_type && is_function(scope->children[i]->children[0])) + || (!is_type && is_compiler_intrinsic(scope->children[i]->children[0])) + || ( is_type && is_type_def(scope->children[i]->children[0])) + || ( is_type && is_adt_def( scope->children[i]->children[0]))) && b.first == name) + to_ret.add_unique(scope->children[i]) + ast::_identifier(b) if (!is_type && b.first == name) + to_ret.add_unique(scope->children[i]) + ast::_declaration() if (!is_type && scope->children[i]->children[0]->data._identifier.first == name) + to_ret.add_unique(scope->children[i]->children[0]) + } + } + if (scope->parent != null>()) { + match (scope_lookup(scope->parent, name, is_type, item, pass, pass_dep_on)) { + OptionVecAst::None() return OptionVecAst::None() + OptionVecAst::Some(v) to_ret.add_all_unique(v) + } + } + else if (primitive_ops.contains_key(name)) + to_ret.add_all_unique(primitive_ops[name]) + return OptionVecAst::Some(to_ret) + } + passes[str("translation_unit_generative")] = fun(item: *tree) { println("Running translation_unit_generative") if !is_translation_unit(item) { @@ -300,75 +363,79 @@ fun main(argc: int, argv: **char): int { error("Trying to get type of node without one: " + to_string(a->data)) } + passes[str("translation_unit_top_type_resolve")] = fun(item: *tree) { + println("Running translation_unit_top_type_resolve") + if !is_translation_unit(item) { + error("Running translation_unit_top_type_resolve on not a translation unit"); + } + if !pass_poset.done(make_pair(item, str("translation_unit_generative"))) { + pass_poset.add_open_dep(make_pair(item, str("translation_unit_top_type_resolve")), make_pair(item, str("translation_unit_generative"))) + return + } + var quick_bind = fun(binding: *tree, start_scope: *tree, additional_scope: *tree, type_binding: bool): bool { + if !ast_bound(binding) { + match (scope_lookup(start_scope, ast_binding_str(binding), type_binding, item, str("translation_unit_top_type_resolve"), str("translation_unit_generative"))) { + OptionVecAst::None() { + return false; + } + OptionVecAst::Some(options) { + if (options.size < 1) { + error("couldn't find any possibilities for " + ast_binding_str(binding)) + } + println(ast_binding_str(binding) + " resolving at top level to " + to_string(options[0]->data)) + set_ast_binding(binding, options[0]) + } + } + } + return true; + } + var quick_bind_type: fun(*binding, *tree): bool = fun(t: *binding, n: *tree): bool { + match(*t->bound_to) { + type::_obj(b) return quick_bind(b, n, null>(), true) + type::_ptr(p) return quick_bind_type(p, n) + type::_ref(p) return quick_bind_type(p, n) + type::_fun(b) { + for (var i = 0; i < b.first.first.size; i++;) + if (!quick_bind_type(b.first.first[i], n)) + return false + return quick_bind_type(b.first.second, n) + } + } + return true + } + for (var i = 0; i < item->children.size; i++;) { + var child = item->children[i] + match (child->data) { + ast::_template(name_map_pair) { + if is_function(child->children[0]) { + quick_bind_type(get_type(child->children[0]), item) + } + } + ast::_declaration() { + quick_bind_type(get_type(child->children[0]), item) + } + ast::_function(name_type_ext) { + quick_bind_type(get_type(child), item) + } + ast::_compiler_intrinsic(name_type_ext) { + quick_bind_type(get_type(child), item) + } + } + } + + println("post translation_unit_top_type_resolve") + print_tree(item, 1) + } + // resolves all binding possibilities to a single one for one top level item passes[str("name_type_resolve")] = fun(item: *tree) { println("name_type resolve for:") print_tree(item, 1) - var scope_lookup: fun(*tree, str, bool): OptionVecAst = fun(scope: *tree, name: str, is_type: bool): OptionVecAst { - /*println("doing a scope lookup for " + name + " starting from " + to_string(scope->data))*/ - 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 !ast_bound(b.first) { - // Import / parse file if not already - var file_path = ast_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) - printlnerr("syntax_to_ast " + file_path + ":") - print_tree(name_ast_map[file_path], 1) - } - set_ast_binding(b.first, name_ast_map[file_path]) - } - var other_top_level = get_ast_binding(b.first) - if !pass_poset.done(make_pair(other_top_level, str("translation_unit_generative"))) { - pass_poset.add_open_dep(make_pair(item, str("name_type_resolve")), make_pair(other_top_level, str("translation_unit_generative"))) - return OptionVecAst::None() - } - match (scope_lookup(other_top_level, name, is_type)) { - OptionVecAst::None() return OptionVecAst::None() - OptionVecAst::Some(v) { - to_ret.add_all_unique(v) - } - } - } - ast::_type_def(b) if (is_type && b == name) - to_ret.add_unique(scope->children[i]) - ast::_adt_def(b) if (is_type && b == name) - to_ret.add_unique(scope->children[i]) - ast::_function(b) if (!is_type && b.first == name) - to_ret.add_unique(scope->children[i]) - ast::_compiler_intrinsic(b) if (!is_type && b.first == name) - to_ret.add_unique(scope->children[i]) - ast::_template(b) if (((!is_type && is_function(scope->children[i]->children[0])) - || (!is_type && is_compiler_intrinsic(scope->children[i]->children[0])) - || ( is_type && is_type_def(scope->children[i]->children[0])) - || ( is_type && is_adt_def( scope->children[i]->children[0]))) && b.first == name) - to_ret.add_unique(scope->children[i]) - ast::_identifier(b) if (!is_type && b.first == name) - to_ret.add_unique(scope->children[i]) - ast::_declaration() if (!is_type && scope->children[i]->children[0]->data._identifier.first == name) - to_ret.add_unique(scope->children[i]->children[0]) - } - } - if (scope->parent != null>()) { - match (scope_lookup(scope->parent, name, is_type)) { - OptionVecAst::None() return OptionVecAst::None() - OptionVecAst::Some(v) to_ret.add_all_unique(v) - } - } - else if (primitive_ops.contains_key(name)) - to_ret.add_all_unique(primitive_ops[name]) - return OptionVecAst::Some(to_ret) - } var try_to_find_binding_possibilities = fun(binding: *tree, start_scope: *tree, additional_scope: *tree, type_binding: bool): bool { if !ast_bound(binding) && !multiple_binding_options.contains_key(binding) { var all_options = vec<*tree>() - match (scope_lookup(start_scope, ast_binding_str(binding), type_binding)) { + match (scope_lookup(start_scope, ast_binding_str(binding), type_binding, item, str("name_type_resolve"), str("translation_unit_top_type_resolve"))) { OptionVecAst::None() { println("OptionVecAst::None for " + ast_binding_str(binding) + " lookup, returning") return false; @@ -380,7 +447,7 @@ fun main(argc: int, argv: **char): int { } if additional_scope != null>() { println("Additionally looking at scope " + to_string(additional_scope->data) + " for try_to_find_binding_possibilities " + ast_binding_str(binding)) - match (scope_lookup(additional_scope, ast_binding_str(binding), type_binding)) { + match (scope_lookup(additional_scope, ast_binding_str(binding), type_binding, item, str("name_type_resolve"), str("translation_unit_top_type_resolve"))) { OptionVecAst::None() { println("OptionVecAst::None for " + ast_binding_str(binding) + " lookup, returning") return false; @@ -402,22 +469,22 @@ fun main(argc: int, argv: **char): int { println("\t" + to_string(all_options[i]->data)) multiple_binding_options[binding] = all_options } - return true; } + return true; } var handle_type_binding_possibilities: fun(*binding, *tree): bool = fun(t: *binding, n: *tree): bool { match(*t->bound_to) { type::_obj(b) return try_to_find_binding_possibilities(b, n, null>(), true) + type::_ptr(p) return handle_type_binding_possibilities(p, n) + type::_ref(p) return handle_type_binding_possibilities(p, n) type::_fun(b) { - /*b.first.first.for_each(fun(it: *binding) {*/ - /*handle_type_binding_possibilities(it, n)*/ - /*})*/ for (var i = 0; i < b.first.first.size; i++;) if (!handle_type_binding_possibilities(b.first.first[i], n)) return false return handle_type_binding_possibilities(b.first.second, n) } } + return true } var traverse_for_unify: fun(*tree): void = fun(t: *tree) { @@ -470,7 +537,7 @@ fun main(argc: int, argv: **char): int { /*})*/ } ast::_cast(b) if (!handle_type_binding_possibilities(b, t)) - return false + return false; ast::_call(add_scope) { println("call of " + to_string(t->children[0]) + ", that is " + to_string(t->children[0]->data) + " has type " + to_string(get_type(t)->bound_to) + ", and the function has type " + to_string(get_type(t->children[0])->bound_to)) /*get_type(t)*/ @@ -544,6 +611,7 @@ fun main(argc: int, argv: **char): int { } // early bail if we need more passes if !traverse_for_select(item) { + println("bailing early b/c select") return } if (!work_done) { @@ -566,6 +634,8 @@ fun main(argc: int, argv: **char): int { traverse_for_error(item) } } + println("tree after pass (might have added a dependency though)") + print_tree(item, 1) } @@ -689,6 +759,10 @@ fun main(argc: int, argv: **char): int { pass_poset.add_open_dep(make_pair(item, str("depend_and_template_resolve")), make_pair(item, str("name_type_resolve"))) return } + + println("what we've got at template resolve time") + print_tree(item, 1) + var resolve: fun(*tree): void = fun(t: *tree) { var resolve_type: fun(*binding): void = fun(t: *binding) { match (*t->bound_to) {