Template functions (instantiated implicitly) work!

This commit is contained in:
Nathan Braswell
2018-10-09 23:00:57 -04:00
parent 39ecf24e69
commit 379d9f612e
6 changed files with 91 additions and 47 deletions

77
k.krak
View File

@@ -236,41 +236,6 @@ fun main(argc: int, argv: **char): int {
traverse_for_bindings(item)
}
var inst_temp_type: fun(*binding<type>, map<*binding<type>, *binding<type>>): *binding<type> = fun(t: *binding<type>, replacements: ref map<*binding<type>, *binding<type>>): *binding<type> {
println("Insting 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
}
var binding_types = map<*tree<ast>, *binding<type>>()
var get_type: fun(*tree<ast>): *binding<type> = fun(a: *tree<ast>): *binding<type> {
match(a->data) {
@@ -319,6 +284,8 @@ fun main(argc: int, argv: **char): int {
pass_poset.add_open_dep(make_pair(item, str("name_type_resolve")), make_pair(item, str("name_possibility_resolve")))
return
}
println("name_type resolve for:")
print_tree(item, 1)
var traverse_for_unify: fun(*tree<ast>): void = fun(t: *tree<ast>) {
t->children.for_each(traverse_for_unify)
@@ -523,11 +490,11 @@ fun main(argc: int, argv: **char): int {
})
}
ast::_import(b) { }
ast::_identifier(b) { C_str += idt + b.first; }
ast::_identifier(b) { C_str += idt + get_c_name(t); }
ast::_binding(b) {
var bound_to = get_ast_binding(t)
if (is_top_level_item(bound_to)) {
if (is_template(bound_to) {
if (is_template(bound_to)) {
if (!instantiated_map.contains_key(bound_to))
instantiated_map[bound_to] = set<pair<*binding<type>, *tree<ast>>>()
var binding_type = get_type(t)
@@ -539,22 +506,43 @@ fun main(argc: int, argv: **char): int {
unify(binding_type, inst_temp_type(get_type(bound_to->children[0]), inst_map))
// shouldn't cache by binding, but by all insted
var already_inst = instantiated_map[bound_to].filter(fun(p: pair<*binding<type>, *tree<ast>>): bool return equality(binding_type, p.first, false);)
var already_inst = instantiated_map[bound_to].filter(fun(p: pair<*binding<type>, *tree<ast>>): bool return equality(binding_type->bound_to, p.first->bound_to, false);)
if (already_inst.size() > 1) {
error("already inst > 1, should be impossible")
} else if (already_inst.size() == 1) {
pass_poset.add_close_dep(make_pair(item, str("emit_C")), make_pair(already_inst.single(), str("emit_C")))
pass_poset.add_close_dep(make_pair(item, str("emit_C")), make_pair(already_inst.single().second, str("emit_C")))
set_single_ast_binding(t, already_inst.single().second)
} else {
var inst_copy = copy_ast(bound_to->children[0], TYPE_INSTING_LAMBDA?)
println("Copying tree to instantiate template!")
var inst_copy = bound_to->children[0]->clone(fun(a: ref ast): ast {
match (a) {
ast::_identifier(b) return ast::_identifier(make_pair(b.first, inst_temp_type(b.second, inst_map)))
ast::_binding(b) return ast::_binding(make_triple(b.first,
b.second.map(fun(bd: *binding<type>): *binding<type> return inst_temp_type(bd, inst_map);),
binding<tree<ast>>()))
ast::_function(b) return ast::_function(make_triple(b.first, inst_temp_type(b.second, inst_map), b.third))
ast::_compiler_intrinsic(b) return ast::_compiler_intrinsic(make_triple(
b.first,
inst_temp_type(b.second, inst_map),
b.third.map(fun(bd: *binding<type>): *binding<type> return inst_temp_type(bd, inst_map);)))
ast::_cast(b) return ast::ast::_cast(inst_temp_type(b, inst_map))
ast::_value(b) return ast::_value(make_pair(b.first, inst_temp_type(b.second, inst_map)))
/*_template: pair<str, map<str, *binding<type>>>,*/
}
return a
})
// add inst copy as a child of template?
bound_to->add_child(inst_copy)
// unify copy'd types with inst types
println("inst from:")
print_tree(bound_to->children[0], 1)
println("inst to:")
print_tree(inst_copy, 1)
// save it in our insted map so we don't instantate more than once per types
instantiated_map[bound_to].add(make_pair(binding_type, inst_copy))
pass_poset.add_close_dep(make_pair(item, str("emit_C")), make_pair(inst_copy, str("emit_C")))
set_single_ast_binding(t, inst_copy)
}
} else {
pass_poset.add_close_dep(make_pair(item, str("emit_C")), make_pair(bound_to, str("emit_C")))
@@ -563,7 +551,8 @@ fun main(argc: int, argv: **char): int {
} else if (is_identifier(bound_to) && is_declaration(bound_to->parent) && is_top_level_item(bound_to->parent)) {
pass_poset.add_close_dep(make_pair(item, str("emit_C")), make_pair(bound_to->parent, str("emit_C")))
}
C_str += idt + get_c_name(bound_to)
// bound_to might have changed from binding
C_str += idt + get_c_name(get_ast_binding(t))
}
ast::_type_def(b) { error("type_def gen unimplemented"); }
ast::_adt_def(b) { error("no adt_def should remain at C emit"); }

View File

@@ -274,6 +274,15 @@ fun set_ast_binding(binding: *tree<ast>, to: *tree<ast>) {
}
error("trying to set binding on not a binding")
}
fun set_single_ast_binding(binding: *tree<ast>, to: *tree<ast>) {
match(binding->data) {
ast::_binding(b) {
b.third->set_single(to)
return
}
}
error("trying to set binding on not a binding")
}
fun ast_bound(binding: *tree<ast>): bool {
match(binding->data) {
ast::_binding(b) return b.third->bound()

View File

@@ -58,6 +58,9 @@ obj binding<T> (Object) {
if ( ((bindings->get(i)) cast *binding<T>)->bound_to == from)
((bindings->get(i)) cast *binding<T>)->bound_to = to
}
fun set_single(to: *T) {
bound_to = to
}
fun to_string(): str {
/*return "binding(" + to_string(bound_to) + ")"*/
return "binding(" + deref_to_string(bound_to) + ")"

View File

@@ -57,7 +57,7 @@ obj set<T> (Object, Serializable) {
return data.size
}
fun single(): T {
if (size() != 1)k
if (size() != 1)
util::error("trying to single with size != 1")
return data[0]
}

View File

@@ -5,13 +5,13 @@ obj tree<T> (Object) {
var data: T
var parent: *tree<T>
var children: vec::vec<*tree<T>>
fun construct(dataIn: T): *tree<T> {
fun construct(dataIn: ref T): *tree<T> {
mem::maybe_copy_construct(&data, &dataIn)
parent = mem::null<tree<T>>()
children.construct()
return this
}
fun construct(dataIn: T, c: ref vec::vec<*tree<T>>): *tree<T> {
fun construct(dataIn: ref T, c: ref vec::vec<*tree<T>>): *tree<T> {
mem::maybe_copy_construct(&data, &dataIn)
parent = mem::null<tree<T>>()
children.copy_construct(&c)
@@ -39,5 +39,15 @@ obj tree<T> (Object) {
mem::maybe_destruct(&data)
children.destruct()
}
fun add_child(c: *tree<T>) {
children.add(c)
c->parent = this
}
fun clone(): *tree<T> {
return mem::new<tree<T>>()->construct(data, children.map(fun(c: *tree<T>): *tree<T> return c->clone();))
}
fun clone(f: fun(ref T): T): *tree<T> {
return mem::new<tree<T>>()->construct(f(data), children.map(fun(c: *tree<T>): *tree<T> return c->clone(f);))
}
}

View File

@@ -46,6 +46,39 @@ fun unify(t1: *binding<type>, t2: *binding<type>) {
}
}
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
}
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