binding epochs compile, but segfault. too late tonight to keep going

This commit is contained in:
Nathan Braswell
2019-01-06 01:06:15 -05:00
parent 06df819e72
commit c2495a04f8
4 changed files with 555 additions and 519 deletions

View File

@@ -40,52 +40,52 @@ adt type {
_double
}
fun has_unknown(t: *binding<type>): bool {
match (*t->bound_to) {
fun has_unknown(t: *binding<type>, epoch: binding_epoch): bool {
match (*t->get_bound_to(epoch)) {
type::_unknown() return true
type::_ptr(p) return has_unknown(p)
type::_obj(o) return o->data._binding.second.any_true(fun(inner_t: *binding<type>): bool return has_unknown(inner_t);)
type::_fun(f) return has_unknown(f.first.second.second) || f.first.first.any_true(fun(p: pair<ref_type, *binding<type>>): bool return has_unknown(p.second);)
type::_ptr(p) return has_unknown(p, epoch)
type::_obj(o) return o->data._binding.second.any_true(fun(inner_t: *binding<type>): bool return has_unknown(inner_t, epoch);)
type::_fun(f) return has_unknown(f.first.second.second, epoch) || f.first.first.any_true(fun(p: pair<ref_type, *binding<type>>): bool return has_unknown(p.second, epoch);)
}
return false
}
fun unify(t1: *binding<type>, t2: *binding<type>) {
println("attempting to unify " + to_string(t1->bound_to) + " and " + to_string(t2->bound_to))
if (is_unknown(t1->bound_to)) {
t1->set(t2->bound_to)
} else if (is_unknown(t2->bound_to)) {
t2->set(t1->bound_to)
fun unify(t1: *binding<type>, t2: *binding<type>, epoch: binding_epoch) {
println("attempting to unify " + to_string(t1->get_bound_to(epoch)) + " and " + to_string(t2->get_bound_to(epoch)))
if (is_unknown(t1->get_bound_to(epoch))) {
t1->set(t2->get_bound_to(epoch), epoch)
} else if (is_unknown(t2->get_bound_to(epoch))) {
t2->set(t1->get_bound_to(epoch), epoch)
} else {
if (shallow_equality(t1->bound_to, t2->bound_to)) {
if (is_fun(t1->bound_to)) {
unify(t1->bound_to->_fun.first.second.second, t2->bound_to->_fun.first.second.second)
if (shallow_equality(t1->get_bound_to(epoch), t2->get_bound_to(epoch), epoch)) {
if (is_fun(t1->get_bound_to(epoch))) {
unify(t1->get_bound_to(epoch)->_fun.first.second.second, t2->get_bound_to(epoch)->_fun.first.second.second, epoch)
// unify ref_types
if (t1->bound_to->_fun.first.second.first == ref_type::_unknown())
t1->bound_to->_fun.first.second.first = t2->bound_to->_fun.first.second.first
if (t2->bound_to->_fun.first.second.first == ref_type::_unknown())
t2->bound_to->_fun.first.second.first = t1->bound_to->_fun.first.second.first
if (t1->get_bound_to(epoch)->_fun.first.second.first == ref_type::_unknown())
t1->get_bound_to(epoch)->_fun.first.second.first = t2->get_bound_to(epoch)->_fun.first.second.first
if (t2->get_bound_to(epoch)->_fun.first.second.first == ref_type::_unknown())
t2->get_bound_to(epoch)->_fun.first.second.first = t1->get_bound_to(epoch)->_fun.first.second.first
// might be veradic...
for (var i = 0; i < t1->bound_to->_fun.first.first.size && i < t2->bound_to->_fun.first.first.size; i++;) {
unify(t1->bound_to->_fun.first.first[i].second, t2->bound_to->_fun.first.first[i].second)
if (t1->bound_to->_fun.first.first[i].first == ref_type::_unknown())
t1->bound_to->_fun.first.first[i].first = t2->bound_to->_fun.first.first[i].first
if (t2->bound_to->_fun.first.first[i].first == ref_type::_unknown())
t2->bound_to->_fun.first.first[i].first = t1->bound_to->_fun.first.first[i].first
for (var i = 0; i < t1->get_bound_to(epoch)->_fun.first.first.size && i < t2->get_bound_to(epoch)->_fun.first.first.size; i++;) {
unify(t1->get_bound_to(epoch)->_fun.first.first[i].second, t2->get_bound_to(epoch)->_fun.first.first[i].second, epoch)
if (t1->get_bound_to(epoch)->_fun.first.first[i].first == ref_type::_unknown())
t1->get_bound_to(epoch)->_fun.first.first[i].first = t2->get_bound_to(epoch)->_fun.first.first[i].first
if (t2->get_bound_to(epoch)->_fun.first.first[i].first == ref_type::_unknown())
t2->get_bound_to(epoch)->_fun.first.first[i].first = t1->get_bound_to(epoch)->_fun.first.first[i].first
}
} else if (is_ptr(t1->bound_to)) {
unify(t1->bound_to->_ptr, t2->bound_to->_ptr)
} else if (is_obj(t1->bound_to)) {
for (var i = 0; i < t1->bound_to->_obj->data._binding.second.size; i++;) {
unify(t1->bound_to->_obj->data._binding.second[i], t2->bound_to->_obj->data._binding.second[i])
} else if (is_ptr(t1->get_bound_to(epoch))) {
unify(t1->get_bound_to(epoch)->_ptr, t2->get_bound_to(epoch)->_ptr, epoch)
} else if (is_obj(t1->get_bound_to(epoch))) {
for (var i = 0; i < t1->get_bound_to(epoch)->_obj->data._binding.second.size; i++;) {
unify(t1->get_bound_to(epoch)->_obj->data._binding.second[i], t2->get_bound_to(epoch)->_obj->data._binding.second[i], epoch)
}
}
} else {
error("Doesn't typecheck! Attempted to unify " + to_string(t1->bound_to) + " and " + to_string(t2->bound_to))
error("Doesn't typecheck! Attempted to unify " + to_string(t1->get_bound_to(epoch)) + " and " + to_string(t2->get_bound_to(epoch)))
}
}
}
fun shallow_equality(a: *type, b: *type):bool {
fun shallow_equality(a: *type, b: *type, epoch: binding_epoch):bool {
if (is_ptr(a) != is_ptr(b))
return false
if (is_ptr(a) && is_ptr(b))
@@ -95,7 +95,7 @@ fun shallow_equality(a: *type, b: *type):bool {
return is_fun(b) && a->_fun.third == b->_fun.third
}
type::_obj(x) {
return is_obj(b) && (get_ast_binding(x) == get_ast_binding(b->_obj) || ((!ast_bound(x) || !ast_bound(b->_obj))
return is_obj(b) && (get_ast_binding(x, epoch) == get_ast_binding(b->_obj, epoch) || ((!ast_bound(x) || !ast_bound(b->_obj))
&& x->data._binding.second.size == b->_obj->data._binding.second.size
&& x->data._binding.first == b->_obj->data._binding.first))
}
@@ -103,32 +103,32 @@ fun shallow_equality(a: *type, b: *type):bool {
return *a == *b
}
fun inst_temp_type(t: *binding<type>, replacements: ref map<*binding<type>, *binding<type>>): *binding<type> {
match (*t->bound_to) {
fun inst_temp_type(t: *binding<type>, replacements: ref map<*binding<type>, *binding<type>>, epoch: binding_epoch): *binding<type> {
match (*t->get_bound_to(epoch)) {
type::_unknown() error("Unknown in temp type")
type::_obj(o) {
var binding_types = o->data._binding.second.map(fun(b: *binding<type>): *binding<type> return inst_temp_type(b, replacements);)
var binding_types = o->data._binding.second.map(fun(b: *binding<type>): *binding<type> return inst_temp_type(b, replacements, epoch);)
for (var i = 0; i < o->data._binding.second.size; i++;) {
if (o->data._binding.second[i] != binding_types[i])
return binding_p(type::_obj(_binding(o->data._binding.first, binding_types, o->data._binding.third)))
return binding_p(type::_obj(_binding(o->data._binding.first, binding_types, o->data._binding.third)), epoch)
}
}
type::_ptr(p) {
var cp = inst_temp_type(p, replacements)
var cp = inst_temp_type(p, replacements, epoch)
if (cp == p)
return t
else
return binding_p(type::_ptr(cp))
return binding_p(type::_ptr(cp), epoch)
}
type::_fun(b) {
// triple<pair<param_types, return_type>, is_variadic, is raw>
var rt = make_pair(b.first.second.first, inst_temp_type(b.first.second.second, replacements))
var pts = b.first.first.map(fun(pt: pair<ref_type, *binding<type>>): pair<ref_type, *binding<type>> return make_pair(pt.first, inst_temp_type(pt.second, replacements));)
var rt = make_pair(b.first.second.first, inst_temp_type(b.first.second.second, replacements, epoch))
var pts = b.first.first.map(fun(pt: pair<ref_type, *binding<type>>): pair<ref_type, *binding<type>> return make_pair(pt.first, inst_temp_type(pt.second, replacements, epoch));)
if (rt.second != b.first.second.second)
return binding_p(type::_fun(make_triple(make_pair(pts, rt), b.second, b.third)))
return binding_p(type::_fun(make_triple(make_pair(pts, rt), b.second, b.third)), epoch)
for (var i = 0; i < pts.size; i++;)
if (pts[i].second != b.first.first[i].second)
return binding_p(type::_fun(make_triple(make_pair(pts, rt), b.second, b.third)))
return binding_p(type::_fun(make_triple(make_pair(pts, rt), b.second, b.third)), epoch)
return t
}
type::_template_placeholder() return replacements[t]
@@ -136,7 +136,7 @@ fun inst_temp_type(t: *binding<type>, replacements: ref map<*binding<type>, *bin
return t
}
fun equality(a: *type, b: *type, count_unknown_as_equal: bool): bool {
fun equality(a: *type, b: *type, count_unknown_as_equal: bool, epoch: binding_epoch): bool {
/*println("equality of " + to_string(a) + " and " + to_string(b))*/
if (count_unknown_as_equal && (is_unknown(a) || is_unknown(b)))
return true
@@ -144,12 +144,12 @@ fun equality(a: *type, b: *type, count_unknown_as_equal: bool): bool {
type::_obj(x) {
if (!is_obj(b))
return false
if (get_ast_binding(x) == get_ast_binding(b->_obj))
if (get_ast_binding(x, epoch) == get_ast_binding(b->_obj, epoch))
return true
if (!count_unknown_as_equal || (ast_bound(x) && ast_bound(b->_obj)) || x->data._binding.first != b->_obj->data._binding.first || x->data._binding.second.size != b->_obj->data._binding.second.size)
return false
for (var i = 0; i < x->data._binding.second.size; i++;) {
if (!equality(x->data._binding.second[i]->bound_to, b->_obj->data._binding.second[i]->bound_to, count_unknown_as_equal))
if (!equality(x->data._binding.second[i]->get_bound_to(epoch), b->_obj->data._binding.second[i]->get_bound_to(epoch), count_unknown_as_equal, epoch))
return false
}
return true
@@ -157,17 +157,17 @@ fun equality(a: *type, b: *type, count_unknown_as_equal: bool): bool {
type::_ptr(p) {
if (!is_ptr(b))
return false
return equality(p->bound_to, b->_ptr->bound_to, count_unknown_as_equal)
return equality(p->get_bound_to(epoch), b->_ptr->get_bound_to(epoch), count_unknown_as_equal, epoch)
}
type::_fun(i) {
if ( !(is_fun(b) && a->_fun.second == b->_fun.second && a->_fun.third == b->_fun.third) )
return false
if ( !equality(a->_fun.first.second.second->bound_to, b->_fun.first.second.second->bound_to, count_unknown_as_equal) )
if ( !equality(a->_fun.first.second.second->get_bound_to(epoch), b->_fun.first.second.second->get_bound_to(epoch), count_unknown_as_equal, epoch) )
return false
if ( !(a->_fun.first.first.size == b->_fun.first.first.size) )
return false
for (var i = 0; i < a->_fun.first.first.size; i++;)
if ( !equality(a->_fun.first.first[i].second->bound_to, b->_fun.first.first[i].second->bound_to, count_unknown_as_equal) )
if ( !equality(a->_fun.first.first[i].second->get_bound_to(epoch), b->_fun.first.first[i].second->get_bound_to(epoch), count_unknown_as_equal, epoch) )
return false
return true
}
@@ -178,7 +178,7 @@ fun to_string(it: *type): str {
match (*it) {
type::_unknown() return str("_unknown")
type::_void() return str("_void")
type::_ptr(p) return "*" + to_string(p->bound_to)
type::_ptr(p) return "* pre_ref:" + to_string(p->get_bound_to(binding_epoch::pre_ref())) + "/post_ref" + to_string(p->get_bound_to(binding_epoch::post_ref()))
type::_obj(b) {
return "_obj(" + to_string(b->data) + ")"
}
@@ -189,10 +189,10 @@ fun to_string(it: *type): str {
to_ret += "_run("
else
to_ret += "_fun("
to_ret += str(", ").join(b.first.first.map(fun(pt: pair<ref_type, *binding<type>>): str return to_string(pt.first) + to_string(pt.second->bound_to);))
to_ret += str(", ").join(b.first.first.map(fun(pt: pair<ref_type, *binding<type>>): str return to_string(pt.first) + "pre_ref:" + to_string(pt.second->get_bound_to(binding_epoch::pre_ref())) + "/post_ref" + to_string(pt.second->get_bound_to(binding_epoch::post_ref()));))
if (b.third)
to_ret += " ..."
return to_ret + "): " + to_string(b.first.second.first) + to_string(b.first.second.second->bound_to)
return to_ret + "): " + to_string(b.first.second.first) + "* pre_ref:" + to_string(b.first.second.second->get_bound_to(binding_epoch::pre_ref())) + "/post_ref:" + to_string(b.first.second.second->get_bound_to(binding_epoch::post_ref()))
}
type::_template_placeholder() return str("_template_placeholder")
type::_bool() return str("_bool")