Files
kraken/stdlib/type2.krak

284 lines
8.1 KiB
Plaintext
Raw Normal View History

import mem:*
import str:*
import vec:*
import util:*
2018-06-22 23:13:08 -04:00
import tree:*
import ast:*
2018-10-08 00:28:42 -04:00
import binding:*
2018-10-08 00:28:42 -04:00
adt type {
_unknown,
_void,
2018-10-08 00:28:42 -04:00
_template_placeholder,
_ptr: *binding<type>,
_ref: *binding<type>,
2018-06-22 23:13:08 -04:00
_obj: *tree<ast>,
// triple<pair<param_types, return_type>, is_variadic, is raw>
2018-09-22 14:54:52 -04:00
_fun: triple<pair<vec<*binding<type>>, *binding<type>>, bool, bool>,
_bool,
_char,
_uchar,
_short,
_ushort,
_int,
_uint,
_long,
_ulong,
_float,
_double
}
2018-10-08 00:28:42 -04:00
fun unify(t1: *binding<type>, t2: *binding<type>) {
if (is_unknown(t1->bound_to)) {
t1->set(t2->bound_to)
} else if (is_unknown(t2->bound_to)) {
t2->set(t1->bound_to)
} else {
if (shallow_equality(t1->bound_to, t2->bound_to)) {
if (is_fun(t1->bound_to)) {
unify(t1->bound_to->_fun.first.second, t2->bound_to->_fun.first.second)
for (var i = 0; i < t1->bound_to->_fun.first.first.size; i++;)
unify(t1->bound_to->_fun.first.first[i], t2->bound_to->_fun.first.first[i])
}
2018-10-08 00:28:42 -04:00
} else {
error("Doesn't typecheck! Attempted to unify " + to_string(t1->bound_to) + " and " + to_string(t2->bound_to))
}
}
2018-10-08 00:28:42 -04:00
}
fun inst_temp_type(t: *binding<type>, replacements: ref map<*binding<type>, *binding<type>>): *binding<type> {
match (*t->bound_to) {
type::_unknown() error("Unknown in temp type")
type::_ptr(p) {
var cp = inst_temp_type(p, replacements)
if (cp == p)
return t
else
return binding_p(type::_ptr(cp))
}
type::_ref(r) {
var cr = inst_temp_type(r, replacements)
if (cr == r)
return t
else
return binding_p(type::_ref(cr))
}
type::_fun(b) {
// triple<pair<param_types, return_type>, is_variadic, is raw>
var rt = inst_temp_type(b.first.second, replacements)
var pts = b.first.first.map(fun(pt: *binding<type>): *binding<type> return inst_temp_type(pt, replacements);)
if (rt != b.first.second)
return binding_p(type::_fun(make_triple(make_pair(pts, rt), b.second, b.third)))
for (var i = 0; i < pts.size; i++;)
if (pts[i] != b.first.first[i])
return binding_p(type::_fun(make_triple(make_pair(pts, rt), b.second, b.third)))
return t
}
type::_template_placeholder() return replacements[t]
}
return t
}
2018-10-08 00:28:42 -04:00
fun equality(a: *type, b: *type, count_unknown_as_equal: bool): bool {
if (count_unknown_as_equal && (is_unknown(a) || is_unknown(b)))
return true
match(*a) {
type::_ptr(p) {
if (!is_ptr(b))
return false
return equality(p->bound_to, b->_ptr->bound_to, count_unknown_as_equal)
}
type::_ref(r) {
if (!is_ref(b))
return false
return equality(r->bound_to, b->_ref->bound_to, count_unknown_as_equal)
}
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->bound_to, b->_fun.first.second->bound_to, count_unknown_as_equal) )
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]->bound_to, b->_fun.first.first[i]->bound_to, count_unknown_as_equal) )
return false
return true
}
}
2018-10-08 00:28:42 -04:00
return *a == *b
}
fun shallow_equality(a: *type, b: *type):bool {
if (is_ptr(a) != is_ptr(b))
return false
2018-10-08 00:28:42 -04:00
if (is_ptr(a) && is_ptr(b))
return shallow_equality(a->_ptr->bound_to, b->_ptr->bound_to)
match(*a) {
type::_fun(x) {
return is_fun(b) && a->_fun.third == b->_fun.third
}
}
2018-10-08 00:28:42 -04:00
return *a == *b
}
fun to_string(it: *type): str {
match (*it) {
type::_unknown() return str("_unknown")
type::_void() return str("_void")
2018-10-10 01:13:47 -04:00
type::_ptr(p) return "*" + to_string(p->bound_to)
type::_ref(r) return "ref" + to_string(r->bound_to)
2018-10-08 00:28:42 -04:00
type::_obj(b) {
return "_obj(" + to_string(b->data) + ")"
}
type::_fun(b) {
// triple<pair<param_types, return_type>, is_variadic, is raw>
var to_ret = str()
if (b.second)
to_ret += "_run("
else
to_ret += "_fun("
to_ret += str(", ").join(b.first.first.map(fun(pt: *binding<type>): str return to_string(pt->bound_to);))
if (b.third)
to_ret += " ..."
return to_ret + "): " + to_string(b.first.second->bound_to)
}
type::_template_placeholder() return str("_template_placeholder")
type::_bool() return str("_bool")
type::_char() return str("_char")
type::_uchar() return str("_uchar")
type::_short() return str("_short")
type::_ushort() return str("_ushort")
type::_int() return str("_int")
type::_uint() return str("_uint")
type::_long() return str("_long")
type::_ulong() return str("_ulong")
type::_float() return str("_float")
type::_double() return str("_double")
}
return str("impossible type")
}
fun is_unknown(x: *type): bool {
match (*x) {
type::_unknown() return true
}
2018-10-08 00:28:42 -04:00
return false
}
fun is_void(x: *type): bool {
match (*x) {
type::_void() return true
}
2018-10-08 00:28:42 -04:00
return false
}
fun is_ptr(x: *type): bool {
match (*x) {
type::_ptr(p) return true
}
2018-10-08 00:28:42 -04:00
return false
}
fun is_ref(x: *type): bool {
match (*x) {
type::_ref(r) return true
}
2018-10-08 00:28:42 -04:00
return false
}
fun is_obj(x: *type): bool {
match (*x) {
type::_obj() return true
}
2018-10-08 00:28:42 -04:00
return false
}
fun is_fun(x: *type): bool {
match (*x) {
type::_fun(b) return true
}
2018-10-08 00:28:42 -04:00
return false
}
fun is_template_placeholder(x: *type): bool {
match (*x) {
type::_template_placeholder() return true
}
2018-10-08 00:28:42 -04:00
return false
}
fun is_bool(x: *type): bool {
match (*x) {
type::_bool() return true
}
2018-10-08 00:28:42 -04:00
return false
}
fun is_char(x: *type): bool {
match (*x) {
type::_char() return true
}
2018-10-08 00:28:42 -04:00
return false
}
fun is_uchar(x: *type): bool {
match (*x) {
type::_uchar() return true
}
2018-10-08 00:28:42 -04:00
return false
}
fun is_short(x: *type): bool {
match (*x) {
type::_short() return true
}
2018-10-08 00:28:42 -04:00
return false
}
fun is_ushort(x: *type): bool {
match (*x) {
type::_ushort() return true
}
2018-10-08 00:28:42 -04:00
return false
}
fun is_int(x: *type): bool {
match (*x) {
type::_int() return true
}
2018-10-08 00:28:42 -04:00
return false
}
fun is_uint(x: *type): bool {
match (*x) {
type::_uint() return true
}
return false
}
fun is_long(x: *type): bool {
match (*x) {
type::_long() return true
}
2018-10-08 00:28:42 -04:00
return false
}
fun is_ulong(x: *type): bool {
match (*x) {
type::_ulong() return true
}
return false
}
fun is_float(x: *type): bool {
match (*x) {
type::_float() return true
}
return false
}
fun is_double(x: *type): bool {
match (*x) {
type::_double() return true
}
return false
}
fun is_signed(x: *type): bool {
match (*x) {
type::_char() return true
type::_int() return true
type::_long() return true
type::_short() return true
type::_float() return true
type::_double() return true
2018-10-08 00:28:42 -04:00
type::_uchar() return false
type::_ushort() return false
type::_uint() return false
type::_ulong() return false
}
2018-10-08 00:28:42 -04:00
return false
}