From fb179cfcf77b13a4ae5a905db851a5a81632c067 Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Mon, 1 Oct 2018 01:19:51 -0400 Subject: [PATCH] Added primitive math ops, and realized when chaining them that overload resolution had to happen for different functions at different times (esp now that we don't just go outside in). Added a iterative resolver to solve the overloads, which iterates over each one and binds the one that only has one option and unifing types based on that, then running through them all again. If progress is not made for a whole iteration, it errors out and shows the first ambigious call. It could show all ambigious calls... --- k.krak | 100 ++++++++++++++++++++++++++++++++++++---------- stdlib/type2.krak | 13 ++++++ 2 files changed, 91 insertions(+), 22 deletions(-) diff --git a/k.krak b/k.krak index 9d57cfc..2705d09 100644 --- a/k.krak +++ b/k.krak @@ -111,6 +111,26 @@ fun main(argc: int, argv: **char): int { binding(type(base_type::_bool(), 0, false)) ), false, false)), 0, false)), vec<*binding>())) } + var math = vec(str("+"), str("-"), str("*"), str("/"), str("&"), str("|"), str("^")) + for (var i = 0; i < math.size; i++;) { + primitive_ops["op" + math[i]] = vec<*tree>() + for (var j = 0; j < number_tower.size; j++;) { + for (var k = 0; k < number_tower.size; k++;) { + var return_type = null>() + if (j > k) { + return_type = number_tower[j] + } else { + return_type = number_tower[k] + } + primitive_ops["op" + math[i]].add(_compiler_intrinsic(math[i], binding(type(base_type::_fun(make_triple(make_pair(vec( + number_tower[j], + number_tower[k] + ), + return_type + ), false, false)), 0, false)), vec<*binding>())) + } + } + } // resolves all binding possibilities for one top level item passes[str("name_possibility_resolve")] = fun(item: *tree) { @@ -241,12 +261,22 @@ fun main(argc: int, argv: **char): int { } var unify: fun(*binding, *binding): void = fun(t1: *binding, t2: *binding) { - if (t1->bound_to->equality(t2->bound_to, false, false) || t1->bound_to->is_unknown()) + /*if (t1->bound_to->equality(t2->bound_to, false, false) || t1->bound_to->is_unknown())*/ + if (t1->bound_to->is_unknown()) { t1->set(t2->bound_to) - else if (t2->bound_to->is_unknown()) + } else if (t2->bound_to->is_unknown()) { t2->set(t1->bound_to) - else - error("Doesn't typecheck! Attempted to unify " + t1->bound_to->to_string() + " and " + t2->bound_to->to_string()) + } else { + if (t1->bound_to->shallow_equality(t2->bound_to)) { + if (t1->bound_to->is_fun()) { + unify(t1->bound_to->base._fun.first.second, t2->bound_to->base._fun.first.second) + for (var i = 0; i < t1->bound_to->base._fun.first.first.size; i++;) + unify(t1->bound_to->base._fun.first.first[i], t2->bound_to->base._fun.first.first[i]) + } + } else { + error("Doesn't typecheck! Attempted to unify " + t1->bound_to->to_string() + " and " + t2->bound_to->to_string()) + } + } } var traverse_for_unify: fun(*tree): void = fun(t: *tree) { t->children.for_each(traverse_for_unify) @@ -271,27 +301,51 @@ fun main(argc: int, argv: **char): int { } traverse_for_unify(item) - var traverse_for_select: fun(*tree): void = fun(t: *tree) { - match (t->data) { - ast::_binding(b) if (!t->data._binding.second->bound()) { - var filtered_options = multiple_binding_options[t].filter(fun(p: *tree): bool return unbound_types[t]->bound_to->equality(get_type(p)->bound_to, false, true);) - if (filtered_options.size == 0) { - println("Attempting to use our inferenced type " + unbound_types[t]->bound_to->to_string() + " to decide what to bind " + to_string(t->data) + " to from options:") - multiple_binding_options[t].for_each(fun(p: *tree) { println("\t" + to_string(p->data) + " of type " + get_type(p)->bound_to->to_string()); }) - error("no options remain after filtering overloads by type for " + to_string(t->data)) - } else if (filtered_options.size > 1) { - println("Attempting to use our inferenced type " + unbound_types[t]->bound_to->to_string() + " to decide what to bind " + to_string(t->data) + " to form options:") - multiple_binding_options[t].for_each(fun(p: *tree) { println("\t" + to_string(p->data) + " of type " + get_type(p)->bound_to->to_string()); }) - println("too many options remain after filtering overloads by type for " + to_string(t->data) + ", they were:") - filtered_options.for_each(fun(p: *tree) { println("\t" + to_string(p->data) + " of type " + get_type(p)->bound_to->to_string()); }) - error("cannot resolve") - } else - set_ast_binding(t, filtered_options[0]) + var more_to_do = true + while (more_to_do) { + more_to_do = false + var work_done = false + var traverse_for_select: fun(*tree): void = fun(t: *tree) { + match (t->data) { + ast::_binding(b) if (!t->data._binding.second->bound()) { + println(to_string(t->data) + " - not bound!") + var filtered_options = multiple_binding_options[t].filter(fun(p: *tree): bool return unbound_types[t]->bound_to->equality(get_type(p)->bound_to, false, true);) + if (filtered_options.size == 0) { + println("Attempting to use our inferenced type " + unbound_types[t]->bound_to->to_string() + " to decide what to bind " + to_string(t->data) + " to from options:") + multiple_binding_options[t].for_each(fun(p: *tree) { println("\t" + to_string(p->data) + " of type " + get_type(p)->bound_to->to_string()); }) + error("no options remain after filtering overloads by type for " + to_string(t->data)) + } else if (filtered_options.size > 1) { + more_to_do = true + } else { + set_ast_binding(t, filtered_options[0]) + unify(unbound_types[t], get_type(filtered_options[0])) + work_done = true + println("wok done! set " + to_string(t->data)) + } + } } + t->children.for_each(traverse_for_select) + } + traverse_for_select(item) + if (!work_done) { + var traverse_for_error: fun(*tree): void = fun(t: *tree) { + match (t->data) { + ast::_binding(b) if (!t->data._binding.second->bound()) { + var filtered_options = multiple_binding_options[t].filter(fun(p: *tree): bool return unbound_types[t]->bound_to->equality(get_type(p)->bound_to, false, true);) + if (filtered_options.size > 1) { + println("Attempting to use our inferenced type " + unbound_types[t]->bound_to->to_string() + " to decide what to bind " + to_string(t->data) + " to form options:") + multiple_binding_options[t].for_each(fun(p: *tree) { println("\t" + to_string(p->data) + " of type " + get_type(p)->bound_to->to_string()); }) + println("too many options remain after filtering overloads by type for " + to_string(t->data) + ", they were:") + filtered_options.for_each(fun(p: *tree) { println("\t" + to_string(p->data) + " of type " + get_type(p)->bound_to->to_string()); }) + error("cannot resolve") + } + } + } + t->children.for_each(traverse_for_error) + } + traverse_for_error(item) } - t->children.for_each(traverse_for_select) } - traverse_for_select(item) } // emit C @@ -415,6 +469,8 @@ fun main(argc: int, argv: **char): int { pass_poset.add_open_dep(make_pair(item, str("emit_C")), make_pair(item, str("name_type_resolve"))) return } + println("Emitting C for:") + print_tree(item, 1) var emit_C: fun(*tree, int): void = fun(t: *tree, level: int) { var idt = str("\t") * level diff --git a/stdlib/type2.krak b/stdlib/type2.krak index 69a1d4d..d667046 100644 --- a/stdlib/type2.krak +++ b/stdlib/type2.krak @@ -81,6 +81,19 @@ obj type (Object) { } return base == other.base } + fun shallow_equality(other: *type):bool { + return shallow_equality(*other) + } + fun shallow_equality(other: ref type):bool { + if (indirection != other.indirection) + return false + match(base) { + base_type::_fun(b) { + return other.is_fun() && base._fun.third == other.base._fun.third + } + } + return base == other.base + } fun to_string(): str { var indr_string = str("") if (is_ref)