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...

This commit is contained in:
Nathan Braswell
2018-10-01 01:19:51 -04:00
parent dea34f0821
commit fb179cfcf7
2 changed files with 91 additions and 22 deletions

74
k.krak
View File

@@ -111,6 +111,26 @@ fun main(argc: int, argv: **char): int {
binding(type(base_type::_bool(), 0, false))
), false, false)), 0, false)), vec<*binding<type>>()))
}
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<ast>>()
for (var j = 0; j < number_tower.size; j++;) {
for (var k = 0; k < number_tower.size; k++;) {
var return_type = null<binding<type>>()
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<type>>()))
}
}
}
// resolves all binding possibilities for one top level item
passes[str("name_possibility_resolve")] = fun(item: *tree<ast>) {
@@ -241,13 +261,23 @@ fun main(argc: int, argv: **char): int {
}
var unify: fun(*binding<type>, *binding<type>): void = fun(t1: *binding<type>, t2: *binding<type>) {
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
} 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<ast>): void = fun(t: *tree<ast>) {
t->children.for_each(traverse_for_unify)
match (t->data) {
@@ -271,27 +301,51 @@ fun main(argc: int, argv: **char): int {
}
traverse_for_unify(item)
var more_to_do = true
while (more_to_do) {
more_to_do = false
var work_done = false
var traverse_for_select: fun(*tree<ast>): void = fun(t: *tree<ast>) {
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<ast>): 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<ast>) { 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<ast>) { 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<ast>) { println("\t" + to_string(p->data) + " of type " + get_type(p)->bound_to->to_string()); })
error("cannot resolve")
} else
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<ast>): void = fun(t: *tree<ast>) {
match (t->data) {
ast::_binding(b) if (!t->data._binding.second->bound()) {
var filtered_options = multiple_binding_options[t].filter(fun(p: *tree<ast>): 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<ast>) { 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<ast>) { 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)
}
}
}
// 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<ast>, int): void = fun(t: *tree<ast>, level: int) {
var idt = str("\t") * level

View File

@@ -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)