From c2495a04f84490397f8908bd7156ad1532afd87b Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Sun, 6 Jan 2019 01:06:15 -0500 Subject: [PATCH] binding epochs compile, but segfault. too late tonight to keep going --- k.krak | 859 ++++++++++++++++++++++---------------------- stdlib/ast.krak | 24 +- stdlib/binding.krak | 89 +++-- stdlib/type2.krak | 102 +++--- 4 files changed, 555 insertions(+), 519 deletions(-) diff --git a/k.krak b/k.krak index bc6bea3..b29b9a7 100644 --- a/k.krak +++ b/k.krak @@ -97,16 +97,16 @@ fun main(argc: int, argv: **char): int { var multiple_binding_options = map<*tree, vec<*tree>>() var primitive_ops.construct(): map>> - var number_tower = vec(binding_p(type::_char()), - binding_p(type::_uchar()), - binding_p(type::_short()), - binding_p(type::_ushort()), - binding_p(type::_int()), - binding_p(type::_uint()), - binding_p(type::_long()), - binding_p(type::_ulong()), - binding_p(type::_float()), - binding_p(type::_double())) + var number_tower = vec(binding_p(type::_char(), binding_epoch::pre_ref()), + binding_p(type::_uchar(), binding_epoch::pre_ref()), + binding_p(type::_short(), binding_epoch::pre_ref()), + binding_p(type::_ushort(), binding_epoch::pre_ref()), + binding_p(type::_int(), binding_epoch::pre_ref()), + binding_p(type::_uint(), binding_epoch::pre_ref()), + binding_p(type::_long(), binding_epoch::pre_ref()), + binding_p(type::_ulong(), binding_epoch::pre_ref()), + binding_p(type::_float(), binding_epoch::pre_ref()), + binding_p(type::_double(), binding_epoch::pre_ref())) var comparators = vec(str("=="), str("<="), str(">="), str("!="), str("<"), str(">")) for (var i = 0; i < comparators.size; i++;) { primitive_ops["op" + comparators[i]] = vec<*tree>() @@ -116,8 +116,8 @@ fun main(argc: int, argv: **char): int { make_pair(ref_type::_notref(), number_tower[j]), make_pair(ref_type::_notref(), number_tower[k]) ), - make_pair(ref_type::_notref(), binding_p(type::_bool())) - ), false, false))), vec<*binding>())) + make_pair(ref_type::_notref(), binding_p(type::_bool(), binding_epoch::pre_ref())) + ), false, false)), binding_epoch::pre_ref()), vec<*binding>())) } var math = vec(str("+"), str("-"), str("*"), str("/"), str("&"), str("|"), str("^")) for (var i = 0; i < math.size; i++;) { @@ -135,7 +135,7 @@ fun main(argc: int, argv: **char): int { make_pair(ref_type::_notref(), number_tower[k]) ), make_pair(ref_type::_notref(), return_type) - ), false, false))), vec<*binding>())) + ), false, false)), binding_epoch::pre_ref()), vec<*binding>())) } } } @@ -150,50 +150,50 @@ fun main(argc: int, argv: **char): int { make_pair(ref_type::_notref(), number_tower[j]), make_pair(ref_type::_notref(), number_tower[k]) ), - make_pair(ref_type::_notref(), binding_p(type::_void())) - ), false, false))), vec<*binding>())) + make_pair(ref_type::_notref(), binding_p(type::_void(), binding_epoch::pre_ref())) + ), false, false)), binding_epoch::pre_ref()), vec<*binding>())) } } } math.remove(math.size-1) // address of - var template_type = binding_p(type::_template_placeholder()) + var template_type = binding_p(type::_template_placeholder(), binding_epoch::pre_ref()) primitive_ops[str("op&")].add(_template(str("&"), map(str("T"), template_type), vec(_compiler_intrinsic(str("&"), binding_p(type::_fun(make_triple(make_pair(vec( make_pair(ref_type::_notref(), template_type) ), - make_pair(ref_type::_notref(), binding_p(type::_ptr(template_type))) - ), false, false))), vec<*binding>())))) + make_pair(ref_type::_notref(), binding_p(type::_ptr(template_type), binding_epoch::pre_ref())) + ), false, false)), binding_epoch::pre_ref()), vec<*binding>())))) // dereference - var template_type = binding_p(type::_template_placeholder()) + var template_type = binding_p(type::_template_placeholder(), binding_epoch::pre_ref()) primitive_ops[str("op*")].add(_template(str("*"), map(str("T"), template_type), vec(_compiler_intrinsic(str("*"), binding_p(type::_fun(make_triple(make_pair(vec( - make_pair(ref_type::_notref(), binding_p(type::_ptr(template_type))) + make_pair(ref_type::_notref(), binding_p(type::_ptr(template_type), binding_epoch::pre_ref())) ), make_pair(ref_type::_notref(), template_type) - ), false, false))), vec<*binding>())))) + ), false, false)), binding_epoch::pre_ref()), vec<*binding>())))) for (var i = 0; i < number_tower.size - 2; i++;) { - var template_type = binding_p(type::_template_placeholder()) + var template_type = binding_p(type::_template_placeholder(), binding_epoch::pre_ref()) primitive_ops[str("op+")].add(_template(str("+"), map(str("T"), template_type), vec(_compiler_intrinsic(str("+"), binding_p(type::_fun(make_triple(make_pair(vec( make_pair(ref_type::_notref(), number_tower[i]), - make_pair(ref_type::_notref(), binding_p(type::_ptr(template_type))) + make_pair(ref_type::_notref(), binding_p(type::_ptr(template_type), binding_epoch::pre_ref())) ), - make_pair(ref_type::_notref(), binding_p(type::_ptr(template_type))) - ), false, false))), vec<*binding>())))) + make_pair(ref_type::_notref(), binding_p(type::_ptr(template_type), binding_epoch::pre_ref())) + ), false, false)), binding_epoch::pre_ref()), vec<*binding>())))) primitive_ops[str("op+")].add(_template(str("+"), map(str("T"), template_type), vec(_compiler_intrinsic(str("+"), binding_p(type::_fun(make_triple(make_pair(vec( - make_pair(ref_type::_notref(), binding_p(type::_ptr(template_type))), + make_pair(ref_type::_notref(), binding_p(type::_ptr(template_type), binding_epoch::pre_ref())), make_pair(ref_type::_notref(), number_tower[i]) ), - make_pair(ref_type::_notref(), binding_p(type::_ptr(template_type))) - ), false, false))), vec<*binding>())))) + make_pair(ref_type::_notref(), binding_p(type::_ptr(template_type), binding_epoch::pre_ref())) + ), false, false)), binding_epoch::pre_ref()), vec<*binding>())))) // note only ptr-1, not 1-ptr to match C... primitive_ops[str("op-")].add(_template(str("-"), map(str("T"), template_type), vec(_compiler_intrinsic(str("-"), binding_p(type::_fun(make_triple(make_pair(vec( - make_pair(ref_type::_notref(), binding_p(type::_ptr(template_type))), + make_pair(ref_type::_notref(), binding_p(type::_ptr(template_type), binding_epoch::pre_ref())), make_pair(ref_type::_notref(), number_tower[i]) ), - make_pair(ref_type::_notref(), binding_p(type::_ptr(template_type))) - ), false, false))), vec<*binding>())))) + make_pair(ref_type::_notref(), binding_p(type::_ptr(template_type), binding_epoch::pre_ref())) + ), false, false)), binding_epoch::pre_ref()), vec<*binding>())))) } var scope_lookup: fun(*tree, str, bool, *tree, str, str): OptionVecAst = fun(scope: *tree, name: str, is_type: bool, item: *tree, pass: str, pass_dep_on: str): OptionVecAst { @@ -213,9 +213,9 @@ fun main(argc: int, argv: **char): int { printlnerr("syntax_to_ast " + file_path + ":") print_tree(name_ast_map[file_path], 1) } - set_ast_binding(b.first, name_ast_map[file_path]) + set_ast_binding(b.first, name_ast_map[file_path], binding_epoch::pre_ref()) } - var other_top_level = get_ast_binding(b.first) + var other_top_level = get_ast_binding(b.first, binding_epoch::pre_ref()) if item != null>() { if !pass_poset.done(make_pair(other_top_level, str("translation_unit_top_type_resolve"))) { pass_poset.add_open_dep(make_pair(item, pass), make_pair(other_top_level, pass_dep_on)) @@ -276,12 +276,12 @@ fun main(argc: int, argv: **char): int { var ident_name = ident->data._identifier.first var ident_type = ident->data._identifier.second var type_def_binding = make_ast_binding(name) - set_ast_binding(type_def_binding, child) + set_ast_binding(type_def_binding, child, binding_epoch::pre_ref()) item->add_child(_compiler_intrinsic(ident_name, binding_p(type::_fun(make_triple(make_pair(vec( - make_pair(ref_type::_notref(), binding_p(type::_obj(type_def_binding))) + make_pair(ref_type::_notref(), binding_p(type::_obj(type_def_binding), binding_epoch::pre_ref())) ), make_pair(ref_type::_notref(), ident_type) - ), false, false))), vec<*binding>())) + ), false, false)), binding_epoch::pre_ref()), vec<*binding>())) println("adding compiler intrinsic to do " + name + "." + ident_name) } } @@ -297,19 +297,19 @@ fun main(argc: int, argv: **char): int { var ident_name = ident->data._identifier.first // the map retains the order - var new_template_type_map = name_map_pair.second.associate(fun(n: str, t: *binding): pair> return make_pair(n, binding_p(type::_template_placeholder()));) + var new_template_type_map = name_map_pair.second.associate(fun(n: str, t: *binding): pair> return make_pair(n, binding_p(type::_template_placeholder(), binding_epoch::pre_ref()));) var new_ident_type = inst_temp_type(ident->data._identifier.second, name_map_pair.second.associate(fun(n: str, t: *binding): pair<*binding, *binding> - return make_pair(t, new_template_type_map[n]);)) + return make_pair(t, new_template_type_map[n]);), binding_epoch::pre_ref()) var type_def_binding = make_ast_binding(name, new_template_type_map.values) // do we need to set the binding to the template? /*set_ast_binding(type_def_binding, child)*/ item->add_child(_template(ident_name, new_template_type_map, vec(_compiler_intrinsic(ident_name, binding_p(type::_fun(make_triple(make_pair(vec( - make_pair(ref_type::_notref(), binding_p(type::_obj(type_def_binding))) + make_pair(ref_type::_notref(), binding_p(type::_obj(type_def_binding), binding_epoch::pre_ref())) ), make_pair(ref_type::_notref(), new_ident_type) - ), false, false))), vec<*binding>())))) + ), false, false)), binding_epoch::pre_ref()), vec<*binding>())))) println("adding compiler intrinsic to do " + name + "." + ident_name) } } @@ -323,44 +323,44 @@ fun main(argc: int, argv: **char): int { } var binding_types = map<*tree, *binding>() - var get_type: fun(*tree): *binding = fun(a: *tree): *binding { + var get_type: fun(*tree, binding_epoch): *binding = fun(a: *tree, epoch: binding_epoch): *binding { var get_template_type: fun(*tree, vec<*binding>): *binding = fun(a: *tree, inst_with: vec<*binding>): *binding { var i = 0 - return inst_temp_type(get_type(a->children[0]), a->data._template.second.associate(fun(k: str, v: *binding): pair<*binding, *binding> { + return inst_temp_type(get_type(a->children[0], binding_epoch::pre_ref()), a->data._template.second.associate(fun(k: str, v: *binding): pair<*binding, *binding> { if (i < inst_with.size) return make_pair(v, inst_with[i]) else - return make_pair(v, binding_p(type::_unknown())) - })) + return make_pair(v, binding_p(type::_unknown(), epoch)) + }), binding_epoch::pre_ref()) } match(a->data) { ast::_identifier(b) return b.second ast::_binding(b) if (binding_types.contains_key(a)) { - if ast_bound(a) && has_unknown(binding_types[a]) { + if ast_bound(a) && has_unknown(binding_types[a], epoch) { var t = null>() - var bound_to = get_ast_binding(a) + var bound_to = get_ast_binding(a, epoch) if (is_template(bound_to)) { t = get_template_type(bound_to, b.second) - unify(binding_types[a], t) + unify(binding_types[a], t, epoch) } else { - t = get_type(bound_to) - unify(binding_types[a], t) + t = get_type(bound_to, epoch) + unify(binding_types[a], t, epoch) } } return binding_types[a] } else { if (ast_bound(a)) { var t = null>() - var bound_to = get_ast_binding(a) + var bound_to = get_ast_binding(a, epoch) if (is_template(bound_to)) { t = get_template_type(bound_to, b.second) } else { - t = get_type(bound_to) + t = get_type(bound_to, epoch) } binding_types[a] = t return t } else { - var new_type = binding_p(type::_unknown()) + var new_type = binding_p(type::_unknown(), epoch) binding_types[a] = new_type return new_type } @@ -369,18 +369,18 @@ fun main(argc: int, argv: **char): int { ast::_template(b) return get_template_type(a, vec<*binding>()) ast::_compiler_intrinsic(b) return b.second ast::_call(add_scope) { - var t = get_type(a->children[0]) - if (is_fun(t->bound_to)) - return t->bound_to->_fun.first.second.second - if (is_unknown(t->bound_to)) { - var return_type = make_pair(ref_type::_unknown(), binding_p(type::_unknown())) + var t = get_type(a->children[0], epoch) + if (is_fun(t->get_bound_to(epoch))) + return t->get_bound_to(epoch)->_fun.first.second.second + if (is_unknown(t->get_bound_to(epoch))) { + var return_type = make_pair(ref_type::_unknown(), binding_p(type::_unknown(), epoch)) var parameter_types = vec>>() for (var i = 1; i < a->children.size; i++;) - parameter_types.add(make_pair(ref_type::_unknown(), get_type(a->children[i]))) - t->set(type::_fun(make_triple(make_pair(parameter_types, return_type), false, false))) + parameter_types.add(make_pair(ref_type::_unknown(), get_type(a->children[i], epoch))) + t->set(type::_fun(make_triple(make_pair(parameter_types, return_type), false, false)), epoch) return return_type.second } - error("Trying to get type of call where type of first child is not function, but " + to_string(t->bound_to)) + error("Trying to get type of call where type of first child is not function, but " + to_string(t->get_bound_to(epoch))) } ast::_cast(b) return b ast::_value(b) return b.second @@ -408,14 +408,14 @@ fun main(argc: int, argv: **char): int { error("couldn't find any possibilities for " + ast_binding_str(binding)) } println(ast_binding_str(binding) + " resolving at top level to " + to_string(options[0]->data)) - set_ast_binding(binding, options[0]) + set_ast_binding(binding, options[0], binding_epoch::pre_ref()) } } } return true; } var quick_bind_type: fun(*binding, *tree): bool = fun(t: *binding, n: *tree): bool { - match(*t->bound_to) { + match(*t->get_bound_to(binding_epoch::pre_ref())) { type::_obj(b) return quick_bind(b, n, null>(), true) type::_ptr(p) return quick_bind_type(p, n) type::_fun(b) { @@ -432,17 +432,17 @@ fun main(argc: int, argv: **char): int { match (child->data) { ast::_template(name_map_pair) { if is_function(child->children[0]) { - quick_bind_type(get_type(child->children[0]), item) + quick_bind_type(get_type(child->children[0], binding_epoch::pre_ref()), item) } } ast::_declaration() { - quick_bind_type(get_type(child->children[0]), item) + quick_bind_type(get_type(child->children[0], binding_epoch::pre_ref()), item) } ast::_function(name_type_ext) { - quick_bind_type(get_type(child), item) + quick_bind_type(get_type(child, binding_epoch::pre_ref()), item) } ast::_compiler_intrinsic(name_type_ext) { - quick_bind_type(get_type(child), item) + quick_bind_type(get_type(child, binding_epoch::pre_ref()), item) } } } @@ -486,7 +486,7 @@ fun main(argc: int, argv: **char): int { error("Could not find any options for scope lookup of " + ast_binding_str(binding)) } else if (all_options.size == 1) { println(ast_binding_str(binding) + " resolved to a single!") - set_ast_binding(binding, all_options[0]) + set_ast_binding(binding, all_options[0], binding_epoch::pre_ref()) } else { println(ast_binding_str(binding) + " found to have " + all_options.size + " options!") for (var i = 0; i < all_options.size; i++;) @@ -497,7 +497,7 @@ fun main(argc: int, argv: **char): int { return true; } var handle_type_binding_possibilities: fun(*binding, *tree): bool = fun(t: *binding, n: *tree): bool { - match(*t->bound_to) { + match(*t->get_bound_to(binding_epoch::pre_ref())) { type::_obj(b) return try_to_find_binding_possibilities(b, n, null>(), true) type::_ptr(p) return handle_type_binding_possibilities(p, n) type::_fun(b) { @@ -514,15 +514,15 @@ fun main(argc: int, argv: **char): int { t->children.for_each(traverse_for_unify) match (t->data) { // even if we have nothing to unify it with, we call get_type on all bindings so that it gets put in the binding map - ast::_binding(b) get_type(t) + ast::_binding(b) get_type(t, binding_epoch::pre_ref()) ast::_declaration() if (t->children.size > 1) - unify(get_type(t->children[0]), get_type(t->children[1])) + unify(get_type(t->children[0], binding_epoch::pre_ref()), get_type(t->children[1], binding_epoch::pre_ref()), binding_epoch::pre_ref()) ast::_call(add_scope) { println("traverse_for_unify call - " + to_string(t->data)) // we call get type to make sure if it is unknown it is transformed into a function version - get_type(t) + get_type(t, binding_epoch::pre_ref()) println("\tpast first get_type") - var fun_type = get_type(t->children[0])->bound_to + var fun_type = get_type(t->children[0], binding_epoch::pre_ref())->get_bound_to(binding_epoch::pre_ref()) println("\tpast second get_type") if (!is_fun(fun_type)) error("trying to call not a function type: " + to_string(fun_type)) @@ -530,10 +530,10 @@ fun main(argc: int, argv: **char): int { error("trying to call function with type wrong number of params (" + to_string(fun_type->_fun.first.first.size) + " vs " + to_string(t->children.size - 1) + "): " + to_string(fun_type)) println("\titerating through children, matching their type with the param type") for (var i = 1; i < t->children.size; i++;) - unify(fun_type->_fun.first.first[i-1].second, get_type(t->children[i])) + unify(fun_type->_fun.first.first[i-1].second, get_type(t->children[i], binding_epoch::pre_ref()), binding_epoch::pre_ref()) } ast::_return() if (t->children.size > 0) - unify(get_type(get_ancestor_satisfying(t, fun(t: *tree): bool return is_function(t);))->bound_to->_fun.first.second.second, get_type(t->children[0])) + unify(get_type(get_ancestor_satisfying(t, fun(t: *tree): bool return is_function(t);), binding_epoch::pre_ref())->get_bound_to(binding_epoch::pre_ref())->_fun.first.second.second, get_type(t->children[0], binding_epoch::pre_ref()), binding_epoch::pre_ref()) } } traverse_for_unify(item) @@ -564,13 +564,13 @@ fun main(argc: int, argv: **char): int { ast::_cast(b) if (!handle_type_binding_possibilities(b, t)) return false; ast::_call(add_scope) { - println("call of " + to_string(t->children[0]) + ", that is " + to_string(t->children[0]->data) + " has type " + to_string(get_type(t)->bound_to) + ", and the function has type " + to_string(get_type(t->children[0])->bound_to)) + println("call of " + to_string(t->children[0]) + ", that is " + to_string(t->children[0]->data) + " has type " + to_string(get_type(t, binding_epoch::pre_ref())->get_bound_to(binding_epoch::pre_ref())) + ", and the function has type " + to_string(get_type(t->children[0], binding_epoch::pre_ref())->get_bound_to(binding_epoch::pre_ref()))) /*get_type(t)*/ if add_scope && is_binding(t->children[0]) && !ast_bound(t->children[0]) && !multiple_binding_options.contains_key(t->children[0]) { - var first_param_type = get_type(t->children[1]) - if !is_unknown(first_param_type->bound_to) && (!is_obj(first_param_type->bound_to) || ast_bound(first_param_type->bound_to->_obj)) { - if is_obj(first_param_type->bound_to) { - if (!try_to_find_binding_possibilities(t->children[0], t->children[0], get_ast_binding(first_param_type->bound_to->_obj)->parent, false)) + var first_param_type = get_type(t->children[1], binding_epoch::pre_ref()) + if !is_unknown(first_param_type->get_bound_to(binding_epoch::pre_ref())) && (!is_obj(first_param_type->get_bound_to(binding_epoch::pre_ref())) || ast_bound(first_param_type->get_bound_to(binding_epoch::pre_ref())->_obj)) { + if is_obj(first_param_type->get_bound_to(binding_epoch::pre_ref())) { + if (!try_to_find_binding_possibilities(t->children[0], t->children[0], get_ast_binding(first_param_type->get_bound_to(binding_epoch::pre_ref())->_obj, binding_epoch::pre_ref())->parent, false)) return false; } else { if (!try_to_find_binding_possibilities(t->children[0], t->children[0], null>(), false)) @@ -579,7 +579,7 @@ fun main(argc: int, argv: **char): int { work_done = true println("wok done! generic add posibilities (or down to one) for " + to_string(t->children[0]->data)) if ast_bound(t->children[0]) { - unify(binding_types[t->children[0]], get_type(get_ast_binding(t->children[0]))) + unify(binding_types[t->children[0]], get_type(get_ast_binding(t->children[0], binding_epoch::pre_ref()), binding_epoch::pre_ref()), binding_epoch::pre_ref()) } } else { children_start_index = 1 @@ -595,31 +595,32 @@ fun main(argc: int, argv: **char): int { return false } if ast_bound(t) { - unify(binding_types[t], get_type(get_ast_binding(t))) + unify(binding_types[t], get_type(get_ast_binding(t, binding_epoch::pre_ref()), binding_epoch::pre_ref()), binding_epoch::pre_ref()) work_done = true println("wok done! set " + to_string(t->data)) } else { // isn't function, by shadowing we just take the first - if !is_fun(binding_types[t]->bound_to) { + if !is_fun(binding_types[t]->get_bound_to(binding_epoch::pre_ref())) { if (!multiple_binding_options[t].size > 0) error("No possible options for " + to_string(t->data)) var it = multiple_binding_options[t][0] - set_ast_binding(t, it) - unify(binding_types[t], get_type(it)) + set_ast_binding(t, it, binding_epoch::pre_ref()) + unify(binding_types[t], get_type(it, binding_epoch::pre_ref()), binding_epoch::pre_ref()) work_done = true } else { // function type, so we have to get interesting - var filtered_options = multiple_binding_options[t].filter(fun(p: *tree): bool return equality(binding_types[t]->bound_to, get_type(p)->bound_to, true);) + var filtered_options = multiple_binding_options[t].filter(fun(p: *tree): bool return equality(binding_types[t]->get_bound_to(binding_epoch::pre_ref()), + get_type(p, binding_epoch::pre_ref())->get_bound_to(binding_epoch::pre_ref()), true, binding_epoch::pre_ref());) if (filtered_options.size == 0) { - println("Attempting to use our inferenced type " + to_string(binding_types[t]->bound_to) + " 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 " + to_string(get_type(p)->bound_to)); }) + println("Attempting to use our inferenced type " + to_string(binding_types[t]->get_bound_to(binding_epoch::pre_ref())) + " 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 " + to_string(get_type(p, binding_epoch::pre_ref())->get_bound_to(binding_epoch::pre_ref()))); }) error("no options remain after filtering overloads by type for " + to_string(t->data)) } else if (filtered_options.size > 1) { - println("inferenced type " + to_string(binding_types[t]->bound_to) + " HAD MULTIPLE OPTIONS AFTER FILTER for " + to_string(t) + ", that is "+ to_string(t->data)) + println("inferenced type " + to_string(binding_types[t]->get_bound_to(binding_epoch::pre_ref())) + " HAD MULTIPLE OPTIONS AFTER FILTER for " + to_string(t) + ", that is "+ to_string(t->data)) more_to_do = true } else { - set_ast_binding(t, filtered_options[0]) - unify(binding_types[t], get_type(filtered_options[0])) + set_ast_binding(t, filtered_options[0], binding_epoch::pre_ref()) + unify(binding_types[t], get_type(filtered_options[0], binding_epoch::pre_ref()), binding_epoch::pre_ref()) work_done = true println("wok done! set " + to_string(t->data)) } @@ -644,14 +645,14 @@ fun main(argc: int, argv: **char): int { match (t->data) { ast::_binding(b) if (!ast_bound(t)) { println("Trying to error out because we made no progress") - var filtered_options = multiple_binding_options[t].filter(fun(p: *tree): bool return equality(binding_types[t]->bound_to, get_type(p)->bound_to, true);) + var filtered_options = multiple_binding_options[t].filter(fun(p: *tree): bool return equality(binding_types[t]->get_bound_to(binding_epoch::pre_ref()), get_type(p, binding_epoch::pre_ref())->get_bound_to(binding_epoch::pre_ref()), true, binding_epoch::pre_ref());) if (filtered_options.size > 1) { - println("Attempting to use our inferenced type " + to_string(binding_types[t]->bound_to) + " 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 " + to_string(get_type(p)->bound_to)); }) + println("Attempting to use our inferenced type " + to_string(binding_types[t]->get_bound_to(binding_epoch::pre_ref())) + " 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 " + to_string(get_type(p, binding_epoch::pre_ref())->get_bound_to(binding_epoch::pre_ref()))); }) println("current state of this:") print_tree(item, 1) 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 " + to_string(get_type(p)->bound_to)); }) + filtered_options.for_each(fun(p: *tree) { println("\t" + to_string(p->data) + " of type " + to_string(get_type(p, binding_epoch::pre_ref())->get_bound_to(binding_epoch::pre_ref()))); }) error("cannot resolve") } } @@ -666,6 +667,295 @@ fun main(argc: int, argv: **char): int { } + + passes[str("ref_lower")] = fun(item: *tree) { + println("Running ref_lower") + if !pass_poset.done(make_pair(item, str("name_type_resolve"))) { + pass_poset.add_open_dep(make_pair(item, str("ref_lower")), make_pair(item, str("name_type_resolve"))) + return + } + var parameter_update_map = map<*tree, *tree>() + var traverse_for_ref: fun(*tree): void = fun(t: *tree) { + match (t->data) { + ast::_function(name_type_ext) { + var fun_type = get_type(t, binding_epoch::pre_ref()) + for (var i = 0; i < fun_type->get_bound_to(binding_epoch::pre_ref())->_fun.first.first.size; i++;) { + if fun_type->get_bound_to(binding_epoch::pre_ref())->_fun.first.first[i].first == ref_type::_ref() { + var old_param = t->children[i] + println("function definition has refs - " + old_param->data._identifier.first) + var new_param = _identifier(old_param->data._identifier.first, binding_p(type::_ptr(old_param->data._identifier.second), binding_epoch::pre_ref())) + parameter_update_map[old_param] = new_param + t->set_child(i, new_param) + } + } + } + ast::_call(add_scope) { + println("traverse_for_ref call - " + to_string(t->data)) + // we call get type to make sure if it is unknown it is transformed into a function version + var fun_type = get_type(t->children[0], binding_epoch::pre_ref())->get_bound_to(binding_epoch::pre_ref()) + println("\t checking " + to_string(t->children[0]->data) + " for reffed params: " + to_string(fun_type)) + for (var i = 1; i < t->children.size; i++;) { + if fun_type->_fun.first.first[i-1].first == ref_type::_ref() { + println(str("\t\tparam ") + i + " is reffed") + var addr_of_binding = make_ast_binding("op&") + set_single_ast_binding(addr_of_binding, primitive_ops[str("op&")].last(), binding_epoch::pre_ref()) + unify(get_type(addr_of_binding, binding_epoch::pre_ref())->get_bound_to(binding_epoch::pre_ref())->_fun.first.first[0].second, get_type(t->children[i], binding_epoch::pre_ref()), binding_epoch::pre_ref()) + t->set_child(i, _call(false, vec(addr_of_binding, t->children[i]))) + } + } + if fun_type->_fun.first.second.first == ref_type::_ref() { + println("call's return is reffed!") + var addr_of_binding = make_ast_binding("op*") + set_single_ast_binding(addr_of_binding, primitive_ops[str("op*")].last(), binding_epoch::pre_ref()) + unify(get_type(addr_of_binding, binding_epoch::pre_ref())->get_bound_to(binding_epoch::pre_ref())->_fun.first.first[0].second, binding_p(type::_ptr(fun_type->_fun.first.second.second), binding_epoch::pre_ref()), binding_epoch::pre_ref()) + // BUG IN kraken compiler, or weird part of kraken itself - evaluation order isn't guarenteed, so evaling a param could change lhs + /*t->parent->replace_child(t, _call(false, vec(addr_of_binding, t)))*/ + var parent = t->parent + parent->replace_child(t, _call(false, vec(addr_of_binding, t))) + } + } + ast::_binding(b) { + var bound_to = get_ast_binding(t, binding_epoch::pre_ref()) + if parameter_update_map.contains_key(bound_to) { + println("param binding is reffed") + var new_param = parameter_update_map[bound_to] + var addr_of_binding = make_ast_binding("op*") + set_single_ast_binding(addr_of_binding, primitive_ops[str("op*")].last(), binding_epoch::pre_ref()) + unify(get_type(addr_of_binding, binding_epoch::pre_ref())->get_bound_to(binding_epoch::pre_ref())->_fun.first.first[0].second, get_type(new_param, binding_epoch::pre_ref()), binding_epoch::pre_ref()) + t->parent->replace_child(t, _call(false, vec(addr_of_binding, new_param))) + } + } + ast::_return() { + if (t->children.size > 0) { + var ret_is_ref = get_type(get_ancestor_satisfying(t, fun(t: *tree): bool return is_function(t);), binding_epoch::pre_ref())->get_bound_to(binding_epoch::pre_ref())->_fun.first.second.first == ref_type::_ref() + if ret_is_ref { + println("return is reffed") + var addr_of_binding = make_ast_binding("op&") + set_single_ast_binding(addr_of_binding, primitive_ops[str("op&")].last(), binding_epoch::pre_ref()) + unify(get_type(addr_of_binding, binding_epoch::pre_ref())->get_bound_to(binding_epoch::pre_ref())->_fun.first.first[0].second, get_type(t->children[0], binding_epoch::pre_ref()), binding_epoch::pre_ref()) + t->set_child(0, _call(false, vec(addr_of_binding, t->children[0]))) + } + } + } + } + t->children.for_each(traverse_for_ref) + } + traverse_for_ref(item) + + println("post ref_lower") + print_tree(item, 1) + } + + // has to be set instead of map<> as we need to use type's "equality" + // function instead of type's adt's operator== + var instantiated_map = map<*tree, set, *tree>>>() + passes[str("depend_and_template_resolve")] = fun(item: *tree) { + if !pass_poset.done(make_pair(item, str("ref_lower"))) { + pass_poset.add_open_dep(make_pair(item, str("depend_and_template_resolve")), make_pair(item, str("ref_lower"))) + return + } + + println("what we've got at template resolve time") + print_tree(item, 1) + + var resolve: fun(*tree): void = fun(t: *tree) { + var resolve_type: fun(*binding): void = fun(t: *binding) { + match (*t->get_bound_to(binding_epoch::pre_ref())) { + type::_unknown() error("unknown in resolve_type") + type::_template_placeholder() error("template_placeholder in resolve_type") + type::_ptr(p) resolve_type(p) + type::_obj(o) { + resolve(o) + pass_poset.add_close_dep(make_pair(item, str("emit_C")), make_pair(get_ast_binding(o, binding_epoch::pre_ref()), str("emit_C"))) + } + type::_fun(t) { + t.first.first.for_each(fun(p: pair>): void { resolve_type(p.second); }) + resolve_type(t.first.second.second) + } + } + } + match (t->data) { + ast::_binding(b) { + var bound_to = get_ast_binding(t, binding_epoch::pre_ref()) + if (is_top_level_item(bound_to)) { + if (is_template(bound_to)) { + if (!instantiated_map.contains_key(bound_to)) { + instantiated_map[bound_to] = set, *tree>>() + } + + // grab inst types out of binding, or regen again from unify? Cache from first unify? + var inst_map = map<*binding, *binding>() + if (b.second.size > 0) { + for (var i = 0; i < b.second.size; i++;) { + inst_map[bound_to->data._template.second.values[i]] = b.second[i] + } + } else { + // regenning from unify + inst_map = bound_to->data._template.second.associate(fun(k: str, v: *binding): pair<*binding, *binding> + return make_pair(v, binding_p(type::_unknown(), binding_epoch::pre_ref()));) + } + + // but not in the case where this is a templated type instead of a function - that doesn't make any sense + var binding_type = null>() + if is_function(bound_to->children[0]) || is_compiler_intrinsic(bound_to->children[0]) { + // unify in both cases - we need it in the explicit case to make sure our explicit types propegate back + binding_type = get_type(t, binding_epoch::pre_ref()) + unify(binding_type, inst_temp_type(get_type(bound_to->children[0], binding_epoch::pre_ref()), inst_map, binding_epoch::pre_ref()), binding_epoch::pre_ref()) + } else { + binding_type = binding_p(type::_obj(t), binding_epoch::pre_ref()) + } + + // shouldn't cache by binding, but by all insted + println("checking for prior instantiations of " + to_string(bound_to->data)) + var already_inst = instantiated_map[bound_to].filter(fun(p: pair<*binding, *tree>): bool return equality(binding_type->get_bound_to(binding_epoch::pre_ref()), p.first->get_bound_to(binding_epoch::pre_ref()), false, binding_epoch::pre_ref());) + if (already_inst.size() > 1) { + error("already inst > 1, should be impossible") + } else if (already_inst.size() == 1) { + println("alreay instantiated template, using (made from):") + print_tree(bound_to->children[0], 1) + println("cached to:") + print_tree(already_inst.single().second, 1) + 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, binding_epoch::pre_ref()) + } else { + println("Copying tree to instantiate template!" + to_string(bound_to->data)) + println("using inst map:") + inst_map.for_each(fun(k: *binding, v: *binding) { + println("\t" + to_string(k->get_bound_to(binding_epoch::pre_ref())) + " -> " + to_string(v->get_bound_to(binding_epoch::pre_ref()))) + }) + 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, binding_epoch::pre_ref()))) + ast::_binding(b) return ast::_binding(make_triple(b.first, + b.second.map(fun(bd: *binding): *binding return inst_temp_type(bd, inst_map, binding_epoch::pre_ref());), + binding>())) + ast::_function(b) return ast::_function(make_triple(b.first, inst_temp_type(b.second, inst_map, binding_epoch::pre_ref()), b.third)) + ast::_compiler_intrinsic(b) return ast::_compiler_intrinsic(make_triple( + b.first, + inst_temp_type(b.second, inst_map, binding_epoch::pre_ref()), + b.third.map(fun(bd: *binding): *binding return inst_temp_type(bd, inst_map, binding_epoch::pre_ref());))) + ast::_cast(b) return ast::ast::_cast(inst_temp_type(b, inst_map, binding_epoch::pre_ref())) + ast::_value(b) return ast::_value(make_pair(b.first, inst_temp_type(b.second, inst_map, binding_epoch::pre_ref()))) + /*_template: pair>>,*/ + } + return a + }) + // add inst copy as a child of template? + bound_to->add_child(inst_copy) + + 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 + if is_function(bound_to->children[0]) || is_compiler_intrinsic(bound_to->children[0]) { + var binding_type2 = get_type(clone_ast_binding(t), binding_epoch::pre_ref()) + unify(binding_type2, inst_temp_type(get_type(bound_to->children[0], binding_epoch::pre_ref()), inst_map, binding_epoch::pre_ref()), binding_epoch::pre_ref()) + instantiated_map[bound_to].add(make_pair(binding_type2, inst_copy)) + } else { + instantiated_map[bound_to].add(make_pair(binding_p(type::_obj(clone_ast_binding(t)), binding_epoch::pre_ref()), 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, binding_epoch::pre_ref()) + } + } else { + pass_poset.add_close_dep(make_pair(item, str("emit_C")), make_pair(bound_to, str("emit_C"))) + } + // top level var dec + } 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"))) + } + // bound_to might have changed from binding + } + ast::_identifier(p) resolve_type(get_type(t, binding_epoch::pre_ref())) + ast::_function(p) resolve_type(get_type(t, binding_epoch::pre_ref())) + ast::_compiler_intrinsic(p) { + resolve_type(p.second) + p.third.for_each(resolve_type) + } + ast::_cast(p) resolve_type(p) + } + + + t->children.for_each(resolve) + } + resolve(item) + } + + passes[str("defer_lower")] = fun(item: *tree) { + if !pass_poset.done(make_pair(item, str("depend_and_template_resolve"))) { + pass_poset.add_open_dep(make_pair(item, str("defer_lower")), make_pair(item, str("depend_and_template_resolve"))) + return + } + var defer_triple_stack = stack>>>() + var loop_stack = stack(-1) + var traverse_for_defer: fun(*tree): void = fun(t: *tree) { + match (t->data) { + ast::_defer() { + if (is_block(t->parent)) { + t->parent->remove_child(t) + defer_triple_stack.top().top().push(t->children[0]) + } else { + t->parent->replace_child(t, t->children[0]) + } + traverse_for_defer(t->children[0]) + return; + } + ast::_function(name_type_ext) { + defer_triple_stack.push(stack>>()) + t->children.clone().for_each(traverse_for_defer) + defer_triple_stack.pop() + return; + } + ast::_block() { + defer_triple_stack.top().push(stack<*tree>()) + t->children.clone().for_each(traverse_for_defer) + t->children.add_all(defer_triple_stack.top().pop().reverse_vector()) + return; + } + ast::_for() { + loop_stack.push(defer_triple_stack.top().size()) + t->children.clone().for_each(traverse_for_defer) + loop_stack.pop() + return; + } + ast::_while() { + loop_stack.push(defer_triple_stack.top().size()) + t->children.clone().for_each(traverse_for_defer) + loop_stack.pop() + return; + } + ast::_return() { + t->children.clone().for_each(traverse_for_defer) + var our_idx = t->parent->children.find(t) + for (var i = 0; i < defer_triple_stack.top().size(); i++;) { + defer_triple_stack.top().from_top(i).reverse_vector().for_each(fun(c: *tree) { + t->parent->children.add(our_idx, c) + }) + } + return; + } + ast::_break() { + var block = _block() + t->parent->replace_child(t, block) + for (var i = 0; i < defer_triple_stack.top().size() - loop_stack.top(); i++;) + block->add_children(defer_triple_stack.top().from_top(i).reverse_vector()) + block->add_child(t) + return; + } + ast::_continue() { + return; + } + } + t->children.clone().for_each(traverse_for_defer) + } + traverse_for_defer(item) + + println("post defer_lower") + print_tree(item, 1) + } + var taken_names = map<*tree, str>() var id = 0 @@ -754,12 +1044,12 @@ fun main(argc: int, argv: **char): int { } var to_c_type: fun(*binding): str = fun(tb: *binding): str { - match(*tb->bound_to) { + match(*tb->get_bound_to(binding_epoch::post_ref())) { type::_unknown() error("unknown in to_c_type") /*type::_unknown() return str("unknown")*/ type::_ptr(p) return to_c_type(p) + "*" type::_void() return str("void") - type::_obj(b) return get_c_name(get_ast_binding(b)) + type::_obj(b) return get_c_name(get_ast_binding(b, binding_epoch::post_ref())) type::_fun(b) error("fun in to_c_type unimplemented") type::_template_placeholder() error("template_placeholder in to_c_type") type::_bool() return str("bool") @@ -776,295 +1066,6 @@ fun main(argc: int, argv: **char): int { } error("fell through to_c_type") } - - passes[str("ref_lower")] = fun(item: *tree) { - println("Running ref_lower") - if !pass_poset.done(make_pair(item, str("name_type_resolve"))) { - pass_poset.add_open_dep(make_pair(item, str("ref_lower")), make_pair(item, str("name_type_resolve"))) - return - } - var parameter_update_map = map<*tree, *tree>() - var traverse_for_ref: fun(*tree): void = fun(t: *tree) { - match (t->data) { - ast::_function(name_type_ext) { - var fun_type = get_type(t) - for (var i = 0; i < fun_type->bound_to->_fun.first.first.size; i++;) { - if fun_type->bound_to->_fun.first.first[i].first == ref_type::_ref() { - var old_param = t->children[i] - println("function definition has refs - " + old_param->data._identifier.first) - var new_param = _identifier(old_param->data._identifier.first, binding_p(type::_ptr(old_param->data._identifier.second))) - parameter_update_map[old_param] = new_param - t->set_child(i, new_param) - } - } - } - ast::_call(add_scope) { - println("traverse_for_ref call - " + to_string(t->data)) - // we call get type to make sure if it is unknown it is transformed into a function version - var fun_type = get_type(t->children[0])->bound_to - println("\t checking " + to_string(t->children[0]->data) + " for reffed params: " + to_string(fun_type)) - for (var i = 1; i < t->children.size; i++;) { - if fun_type->_fun.first.first[i-1].first == ref_type::_ref() { - println(str("\t\tparam ") + i + " is reffed") - var addr_of_binding = make_ast_binding("op&") - set_single_ast_binding(addr_of_binding, primitive_ops[str("op&")].last()) - unify(get_type(addr_of_binding)->bound_to->_fun.first.first[0].second, get_type(t->children[i])) - t->set_child(i, _call(false, vec(addr_of_binding, t->children[i]))) - } - } - if fun_type->_fun.first.second.first == ref_type::_ref() { - println("call's return is reffed!") - var addr_of_binding = make_ast_binding("op*") - set_single_ast_binding(addr_of_binding, primitive_ops[str("op*")].last()) - unify(get_type(addr_of_binding)->bound_to->_fun.first.first[0].second, binding_p(type::_ptr(fun_type->_fun.first.second.second))) - // BUG IN kraken compiler, or weird part of kraken itself - evaluation order isn't guarenteed, so evaling a param could change lhs - /*t->parent->replace_child(t, _call(false, vec(addr_of_binding, t)))*/ - var parent = t->parent - parent->replace_child(t, _call(false, vec(addr_of_binding, t))) - } - } - ast::_binding(b) { - var bound_to = get_ast_binding(t) - if parameter_update_map.contains_key(bound_to) { - println("param binding is reffed") - var new_param = parameter_update_map[bound_to] - var addr_of_binding = make_ast_binding("op*") - set_single_ast_binding(addr_of_binding, primitive_ops[str("op*")].last()) - unify(get_type(addr_of_binding)->bound_to->_fun.first.first[0].second, get_type(new_param)) - t->parent->replace_child(t, _call(false, vec(addr_of_binding, new_param))) - } - } - ast::_return() { - if (t->children.size > 0) { - var ret_is_ref = get_type(get_ancestor_satisfying(t, fun(t: *tree): bool return is_function(t);))->bound_to->_fun.first.second.first == ref_type::_ref() - if ret_is_ref { - println("return is reffed") - var addr_of_binding = make_ast_binding("op&") - set_single_ast_binding(addr_of_binding, primitive_ops[str("op&")].last()) - unify(get_type(addr_of_binding)->bound_to->_fun.first.first[0].second, get_type(t->children[0])) - t->set_child(0, _call(false, vec(addr_of_binding, t->children[0]))) - } - } - } - } - t->children.for_each(traverse_for_ref) - } - traverse_for_ref(item) - - println("post ref_lower") - print_tree(item, 1) - } - - // has to be set instead of map<> as we need to use type's "equality" - // function instead of type's adt's operator== - var instantiated_map = map<*tree, set, *tree>>>() - passes[str("depend_and_template_resolve")] = fun(item: *tree) { - if !pass_poset.done(make_pair(item, str("ref_lower"))) { - pass_poset.add_open_dep(make_pair(item, str("depend_and_template_resolve")), make_pair(item, str("ref_lower"))) - return - } - - println("what we've got at template resolve time") - print_tree(item, 1) - - var resolve: fun(*tree): void = fun(t: *tree) { - var resolve_type: fun(*binding): void = fun(t: *binding) { - match (*t->bound_to) { - type::_unknown() error("unknown in resolve_type") - type::_template_placeholder() error("template_placeholder in resolve_type") - type::_ptr(p) resolve_type(p) - type::_obj(o) { - resolve(o) - pass_poset.add_close_dep(make_pair(item, str("emit_C")), make_pair(get_ast_binding(o), str("emit_C"))) - } - type::_fun(t) { - t.first.first.for_each(fun(p: pair>): void { resolve_type(p.second); }) - resolve_type(t.first.second.second) - } - } - } - match (t->data) { - ast::_binding(b) { - var bound_to = get_ast_binding(t) - if (is_top_level_item(bound_to)) { - if (is_template(bound_to)) { - if (!instantiated_map.contains_key(bound_to)) { - instantiated_map[bound_to] = set, *tree>>() - } - - // grab inst types out of binding, or regen again from unify? Cache from first unify? - var inst_map = map<*binding, *binding>() - if (b.second.size > 0) { - for (var i = 0; i < b.second.size; i++;) { - inst_map[bound_to->data._template.second.values[i]] = b.second[i] - } - } else { - // regenning from unify - inst_map = bound_to->data._template.second.associate(fun(k: str, v: *binding): pair<*binding, *binding> - return make_pair(v, binding_p(type::_unknown()));) - } - - // but not in the case where this is a templated type instead of a function - that doesn't make any sense - var binding_type = null>() - if is_function(bound_to->children[0]) || is_compiler_intrinsic(bound_to->children[0]) { - // unify in both cases - we need it in the explicit case to make sure our explicit types propegate back - binding_type = get_type(t) - unify(binding_type, inst_temp_type(get_type(bound_to->children[0]), inst_map)) - } else { - binding_type = binding_p(type::_obj(t)) - } - - // shouldn't cache by binding, but by all insted - println("checking for prior instantiations of " + to_string(bound_to->data)) - var already_inst = instantiated_map[bound_to].filter(fun(p: pair<*binding, *tree>): 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) { - println("alreay instantiated template, using (made from):") - print_tree(bound_to->children[0], 1) - println("cached to:") - print_tree(already_inst.single().second, 1) - 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 { - println("Copying tree to instantiate template!" + to_string(bound_to->data)) - println("using inst map:") - inst_map.for_each(fun(k: *binding, v: *binding) { - println("\t" + to_string(k->bound_to) + " -> " + to_string(v->bound_to)) - }) - 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): *binding return inst_temp_type(bd, inst_map);), - binding>())) - 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): *binding 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>>,*/ - } - return a - }) - // add inst copy as a child of template? - bound_to->add_child(inst_copy) - - 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 - if is_function(bound_to->children[0]) || is_compiler_intrinsic(bound_to->children[0]) { - var binding_type2 = get_type(clone_ast_binding(t)) - unify(binding_type2, inst_temp_type(get_type(bound_to->children[0]), inst_map)) - instantiated_map[bound_to].add(make_pair(binding_type2, inst_copy)) - } else { - instantiated_map[bound_to].add(make_pair(binding_p(type::_obj(clone_ast_binding(t))), 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"))) - } - // top level var dec - } 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"))) - } - // bound_to might have changed from binding - } - ast::_identifier(p) resolve_type(get_type(t)) - ast::_function(p) resolve_type(get_type(t)) - ast::_compiler_intrinsic(p) { - resolve_type(p.second) - p.third.for_each(resolve_type) - } - ast::_cast(p) resolve_type(p) - } - - - t->children.for_each(resolve) - } - resolve(item) - } - - passes[str("defer_lower")] = fun(item: *tree) { - if !pass_poset.done(make_pair(item, str("depend_and_template_resolve"))) { - pass_poset.add_open_dep(make_pair(item, str("defer_lower")), make_pair(item, str("depend_and_template_resolve"))) - return - } - var defer_triple_stack = stack>>>() - var loop_stack = stack(-1) - var traverse_for_defer: fun(*tree): void = fun(t: *tree) { - match (t->data) { - ast::_defer() { - if (is_block(t->parent)) { - t->parent->remove_child(t) - defer_triple_stack.top().top().push(t->children[0]) - } else { - t->parent->replace_child(t, t->children[0]) - } - traverse_for_defer(t->children[0]) - return; - } - ast::_function(name_type_ext) { - defer_triple_stack.push(stack>>()) - t->children.clone().for_each(traverse_for_defer) - defer_triple_stack.pop() - return; - } - ast::_block() { - defer_triple_stack.top().push(stack<*tree>()) - t->children.clone().for_each(traverse_for_defer) - t->children.add_all(defer_triple_stack.top().pop().reverse_vector()) - return; - } - ast::_for() { - loop_stack.push(defer_triple_stack.top().size()) - t->children.clone().for_each(traverse_for_defer) - loop_stack.pop() - return; - } - ast::_while() { - loop_stack.push(defer_triple_stack.top().size()) - t->children.clone().for_each(traverse_for_defer) - loop_stack.pop() - return; - } - ast::_return() { - t->children.clone().for_each(traverse_for_defer) - var our_idx = t->parent->children.find(t) - for (var i = 0; i < defer_triple_stack.top().size(); i++;) { - defer_triple_stack.top().from_top(i).reverse_vector().for_each(fun(c: *tree) { - t->parent->children.add(our_idx, c) - }) - } - return; - } - ast::_break() { - var block = _block() - t->parent->replace_child(t, block) - for (var i = 0; i < defer_triple_stack.top().size() - loop_stack.top(); i++;) - block->add_children(defer_triple_stack.top().from_top(i).reverse_vector()) - block->add_child(t) - return; - } - ast::_continue() { - return; - } - } - t->children.clone().for_each(traverse_for_defer) - } - traverse_for_defer(item) - - println("post defer_lower") - print_tree(item, 1) - } - // emit C var C_str = str() var C_type_forward_declaration_str = str() @@ -1092,7 +1093,7 @@ fun main(argc: int, argv: **char): int { ast::_import(b) { } ast::_identifier(b) { C_str += idt + get_c_name(t); } ast::_binding(b) { - C_str += idt + get_c_name(get_ast_binding(t)) + C_str += idt + get_c_name(get_ast_binding(t, binding_epoch::pre_ref())) } ast::_type_def(b) { C_type_forward_declaration_str += "typedef struct " + get_c_name(t) + " " + get_c_name(t) + ";\n" @@ -1100,8 +1101,8 @@ fun main(argc: int, argv: **char): int { C_type_declaration_poset.add_job(t) t->children.for_each(fun(c: *tree) { C_type_declaration_str_map[t] += "\t" + to_c_type(c->children[0]->data._identifier.second) + " " + get_c_name(c->children[0]) + ";\n" - if is_obj(c->children[0]->data._identifier.second->bound_to) { - C_type_declaration_poset.add_open_dep(t, get_ast_binding(c->children[0]->data._identifier.second->bound_to->_obj)) + if is_obj(c->children[0]->data._identifier.second->get_bound_to(binding_epoch::pre_ref())) { + C_type_declaration_poset.add_open_dep(t, get_ast_binding(c->children[0]->data._identifier.second->get_bound_to(binding_epoch::post_ref())->_obj, binding_epoch::post_ref())) } }) C_type_declaration_str_map[t] += "};\n" @@ -1110,7 +1111,7 @@ fun main(argc: int, argv: **char): int { ast::_function(b) { /*var fun_name = b.first*/ var fun_name = get_c_name(t) - var fun_type = b.second->bound_to + var fun_type = b.second->get_bound_to(binding_epoch::post_ref()) var is_ext = b.third var return_type = fun_type->_fun.first.second var parameter_types = fun_type->_fun.first.first @@ -1229,9 +1230,9 @@ fun main(argc: int, argv: **char): int { ast::_continue() { C_str += idt + "continue"; } ast::_defer() { error("no defer should remain at C emit"); } ast::_call(add_scope) { - if (is_compiler_intrinsic(get_ast_binding(t->children[0]))) { + if (is_compiler_intrinsic(get_ast_binding(t->children[0], binding_epoch::post_ref()))) { if (t->children.size == 2) { - var intrinsic_name = get_ast_binding(t->children[0])->data._compiler_intrinsic.first + var intrinsic_name = get_ast_binding(t->children[0], binding_epoch::post_ref())->data._compiler_intrinsic.first if (intrinsic_name == "&" || intrinsic_name == "*") { C_str += idt + "(" + intrinsic_name + "(" emit_C(t->children[1], 0) @@ -1244,7 +1245,7 @@ fun main(argc: int, argv: **char): int { } else if (t->children.size == 3) { C_str += idt + "((" emit_C(t->children[1], 0) - C_str += ")" + get_ast_binding(t->children[0])->data._compiler_intrinsic.first + "(" + C_str += ")" + get_ast_binding(t->children[0], binding_epoch::post_ref())->data._compiler_intrinsic.first + "(" emit_C(t->children[2], 0) C_str += "))" } else error("Calling primitive intrinsic with not 1 or 2 arguments") @@ -1272,7 +1273,7 @@ fun main(argc: int, argv: **char): int { C_str += ")" } ast::_value(b) { - if is_ptr(b.second->bound_to) && is_char(b.second->bound_to->_ptr->bound_to) { + if is_ptr(b.second->get_bound_to(binding_epoch::post_ref())) && is_char(b.second->get_bound_to(binding_epoch::post_ref())->_ptr->get_bound_to(binding_epoch::post_ref())) { C_str += "\"" b.first.for_each(fun(c: char) { if (c == '\n') @@ -1300,20 +1301,20 @@ fun main(argc: int, argv: **char): int { var real_main = _function( str("main"), binding_p(type::_fun(make_triple(make_pair(vec( - make_pair(ref_type::_notref(), binding_p(type::_int())), - make_pair(ref_type::_notref(), binding_p(type::_ptr(binding_p(type::_ptr(binding_p(type::_char())))))) + make_pair(ref_type::_notref(), binding_p(type::_int(), binding_epoch::pre_ref())), + make_pair(ref_type::_notref(), binding_p(type::_ptr(binding_p(type::_ptr(binding_p(type::_char(), binding_epoch::pre_ref())), binding_epoch::pre_ref())), binding_epoch::pre_ref())) ), - make_pair(ref_type::_notref(), binding_p(type::_int())) - ), false, false))), + make_pair(ref_type::_notref(), binding_p(type::_int(), binding_epoch::pre_ref())) + ), false, false)), binding_epoch::pre_ref()), true, vec( - _identifier(str("argc"), binding_p(type::_int())), - _identifier(str("argv"), binding_p(type::_ptr(binding_p(type::_ptr(binding_p(type::_char())))))), + _identifier(str("argc"), binding_p(type::_int(), binding_epoch::pre_ref())), + _identifier(str("argv"), binding_p(type::_ptr(binding_p(type::_ptr(binding_p(type::_char(), binding_epoch::pre_ref())), binding_epoch::pre_ref())), binding_epoch::pre_ref())), _return(vec(_call(false, vec(make_ast_binding("fmain"), make_ast_binding("argc"), make_ast_binding("argv"))))) ) ) var top_unit = _translation_unit(str(), vec( _import(make_ast_binding(kraken_file_name), set(str("*")), vec( - _identifier(kraken_file_name, binding_p(type::_void())) + _identifier(kraken_file_name, binding_p(type::_void(), binding_epoch::pre_ref())) )), real_main )) @@ -1357,7 +1358,7 @@ fun parse_type(syntax: *tree, declared_template_types: ref map, declared_template_types: ref map>): *binding { var next = get_node("pre_reffed", syntax) if (next != null>()) - return binding_p(type::_ptr(parse_type_helper(next, declared_template_types))) + return binding_p(type::_ptr(parse_type_helper(next, declared_template_types)), binding_epoch::pre_ref()) var ident = get_node("scoped_identifier", syntax) var func = get_node("function_type", syntax) @@ -1367,44 +1368,44 @@ fun parse_type_helper(syntax: *tree, declared_template_types: ref map>()) { var inst_with = get_nodes("type", template_inst).map(fun(s: *tree): *binding { return parse_type_helper(s, declared_template_types); }) - return binding_p(type::_obj(make_ast_binding(ident_str, inst_with))) + return binding_p(type::_obj(make_ast_binding(ident_str, inst_with)), binding_epoch::pre_ref()) } else { if (declared_template_types.contains_key(ident_str)) return declared_template_types[ident_str] else - return binding_p(type::_obj(make_ast_binding(ident_str))) + return binding_p(type::_obj(make_ast_binding(ident_str)), binding_epoch::pre_ref()) } } else if (func != null>()) { error("function type parsing not implemented") var param_types = vec>>() - var return_type = make_pair(ref_type::_notref(), binding_p(type::_void())) + var return_type = make_pair(ref_type::_notref(), binding_p(type::_void(), binding_epoch::pre_ref())) var variadic = false var raw = false - return binding_p(type::_fun(make_triple(make_pair(param_types, return_type), variadic, raw))) + return binding_p(type::_fun(make_triple(make_pair(param_types, return_type), variadic, raw)), binding_epoch::pre_ref()) } else if (first_child_name == "\"void\"") { - return binding_p(type::_void()) + return binding_p(type::_void(), binding_epoch::pre_ref()) } else if (first_child_name == "\"bool\"") { - return binding_p(type::_bool()) + return binding_p(type::_bool(), binding_epoch::pre_ref()) } else if (first_child_name == "\"char\"") { - return binding_p(type::_char()) + return binding_p(type::_char(), binding_epoch::pre_ref()) } else if (first_child_name == "\"uchar\"") { - return binding_p(type::_uchar()) + return binding_p(type::_uchar(), binding_epoch::pre_ref()) } else if (first_child_name == "\"short\"") { - return binding_p(type::_short()) + return binding_p(type::_short(), binding_epoch::pre_ref()) } else if (first_child_name == "\"ushort\"") { - return binding_p(type::_ushort()) + return binding_p(type::_ushort(), binding_epoch::pre_ref()) } else if (first_child_name == "\"int\"") { - return binding_p(type::_int()) + return binding_p(type::_int(), binding_epoch::pre_ref()) } else if (first_child_name == "\"uint\"") { - return binding_p(type::_uint()) + return binding_p(type::_uint(), binding_epoch::pre_ref()) } else if (first_child_name == "\"long\"") { - return binding_p(type::_long()) + return binding_p(type::_long(), binding_epoch::pre_ref()) } else if (first_child_name == "\"ulong\"") { - return binding_p(type::_ulong()) + return binding_p(type::_ulong(), binding_epoch::pre_ref()) } else if (first_child_name == "\"float\"") { - return binding_p(type::_float()) + return binding_p(type::_float(), binding_epoch::pre_ref()) } else if (first_child_name == "\"double\"") { - return binding_p(type::_double()) + return binding_p(type::_double(), binding_epoch::pre_ref()) } error(syntax, "could not parse type " + first_child_name) } @@ -1437,7 +1438,7 @@ fun syntax_to_ast(file_name: str, syntax: *tree, import_paths: ref vec>()) { get_nodes("template_param", template).for_each(fun(p: *tree) { var key = concat(p) - var value = binding_p(type::_template_placeholder()) + var value = binding_p(type::_template_placeholder(), binding_epoch::pre_ref()) new_template_type_map[key] = value with_added_declared_template_types[key] = value }) @@ -1459,13 +1460,13 @@ fun syntax_to_ast(file_name: str, syntax: *tree, import_paths: ref vec>): pair> return make_pair(i.first, i.second->data._identifier.second);), return_type), get_node("\"...\"", syntax) != null>(), - false /*get_node("\"run\"", syntax) != null>()*/))) + false /*get_node("\"run\"", syntax) != null>()*/)), binding_epoch::pre_ref()) var body_syntax = get_node("statement", syntax) var body = vec<*tree>() if body_syntax != null>() { @@ -1489,7 +1490,7 @@ fun syntax_to_ast(file_name: str, syntax: *tree, import_paths: ref vec>()) { get_nodes("template_param", template).for_each(fun(p: *tree) { var key = concat(p) - var value = binding_p(type::_template_placeholder()) + var value = binding_p(type::_template_placeholder(), binding_epoch::pre_ref()) new_template_type_map[key] = value with_added_declared_template_types[key] = value }) @@ -1511,7 +1512,7 @@ fun syntax_to_ast(file_name: str, syntax: *tree, import_paths: ref vec>()) { get_nodes("template_param", template).for_each(fun(p: *tree) { var key = concat(p) - var value = binding_p(type::_template_placeholder()) + var value = binding_p(type::_template_placeholder(), binding_epoch::pre_ref()) new_template_type_map[key] = value with_added_declared_template_types[key] = value }) @@ -1523,7 +1524,7 @@ fun syntax_to_ast(file_name: str, syntax: *tree, import_paths: ref vec>()) return _identifier(concat(get_node("identifier", s)), parse_type(option_type, with_added_declared_template_types)) else - return _identifier(concat(get_node("identifier", s)), binding_p(type::_void())) + return _identifier(concat(get_node("identifier", s)), binding_p(type::_void(), binding_epoch::pre_ref())) })) if (new_template_type_map.size() > 0) { return _template(n->data._adt_def, new_template_type_map, vec(n)) @@ -1554,7 +1555,7 @@ fun syntax_to_ast(file_name: str, syntax: *tree, import_paths: ref vecchildren.map(fun(x: *tree): *tree return syntax_to_ast_helper(x, declared_template_types);)) })) } else if (syntax->data.name == "declaration_statement") { - var t = binding_p(type::_unknown()) + var t = binding_p(type::_unknown(), binding_epoch::pre_ref()) var type_syntax = get_node("type", syntax) if type_syntax != null>() t = parse_type(type_syntax, declared_template_types) @@ -1624,13 +1625,13 @@ fun syntax_to_ast(file_name: str, syntax: *tree, import_paths: ref vecdata.name == "number") { var number_string = concat(syntax) if (number_string.contains('.')) - return _value(number_string, binding_p(type::_double())) + return _value(number_string, binding_p(type::_double(), binding_epoch::pre_ref())) else - return _value(number_string, binding_p(type::_int())) + return _value(number_string, binding_p(type::_int(), binding_epoch::pre_ref())) } else if (syntax->data.name == "string") { var value_str = concat(syntax) var start = 1 @@ -1657,9 +1658,9 @@ fun syntax_to_ast(file_name: str, syntax: *tree, import_paths: ref vecdata.name == "bool") - return _value(concat(syntax), binding_p(type::_bool())) + return _value(concat(syntax), binding_p(type::_bool(), binding_epoch::pre_ref())) else if (syntax->data.name == "scoped_identifier" || syntax->data.name == "identifier") return make_ast_binding(concat(syntax)) else { diff --git a/stdlib/ast.krak b/stdlib/ast.krak index 467f983..f880d24 100644 --- a/stdlib/ast.krak +++ b/stdlib/ast.krak @@ -47,11 +47,11 @@ fun to_string(a: ref ast): str { match(a) { ast::_translation_unit(b) return str("_translation_unit(") + b + ")" ast::_import(b) return str("_import(") + to_string(b.first->data) + ")[" + str(",").join(b.second.data) + "]" - ast::_identifier(b) return str("_identifier(") + b.first + ": " + deref_to_string(b.second->bound_to) + ")" - ast::_binding(b) return str("_binding(") + b.first + "[" + str(",").join(b.second.map(fun(x:*binding): str { return deref_to_string(x->bound_to); })) + "]" + "->" + deref_to_string(b.third->bound_to, fun(t: *tree): str return to_string(t->data);) + ")" + ast::_identifier(b) return str("_identifier(") + b.first + ": " + "pre_ref:" + deref_to_string(b.second->get_bound_to(binding_epoch::pre_ref())) + "/post_ref:" + deref_to_string(b.second->get_bound_to(binding_epoch::post_ref())) + ")" + ast::_binding(b) return str("_binding(") + b.first + "[" + str(",").join(b.second.map(fun(x:*binding): str { return "pre_ref:" + deref_to_string(x->get_bound_to(binding_epoch::pre_ref())) + "/post_ref:" + deref_to_string(x->get_bound_to(binding_epoch::post_ref())); })) + "]" + "-> pre_ref:" + deref_to_string(b.third->get_bound_to(binding_epoch::pre_ref()), fun(t: *tree): str return to_string(t->data);) + " /post_ref:" + deref_to_string(b.third->get_bound_to(binding_epoch::post_ref()), fun(t: *tree): str return to_string(t->data);)+ ")" ast::_type_def(b) return str("_type_def(") + b + ")" ast::_adt_def(b) return str("_adt_def(") + b + ")" - ast::_function(b) return str("_function(") + b.first + ": " + deref_to_string(b.second->bound_to) + ", ext?:" + to_string(b.third) + ")" + ast::_function(b) return str("_function(") + b.first + ": " + "pre_ref:" + deref_to_string(b.second->get_bound_to(binding_epoch::pre_ref())) + "/post_ref:" + deref_to_string(b.second->get_bound_to(binding_epoch::post_ref())) + ", ext?:" + to_string(b.third) + ")" ast::_template(b) return str("_template(") + b.first + "[" + str(",").join(b.second.keys) + "])" ast::_declaration() return str("_declaration") ast::_block() return str("_block") @@ -65,9 +65,9 @@ fun to_string(a: ref ast): str { ast::_continue() return str("_continue") ast::_defer() return str("_defer") ast::_call(b) return "_call(add_scope: " + to_string(b) + ")" - ast::_compiler_intrinsic(b) return str("_compiler_intrinsic(") + b.first + ": " + deref_to_string(b.second->bound_to) + ")" + ast::_compiler_intrinsic(b) return str("_compiler_intrinsic(") + b.first + ": " + "pre_ref:" + deref_to_string(b.second->get_bound_to(binding_epoch::pre_ref())) + "/post_ref:" + deref_to_string(b.second->get_bound_to(binding_epoch::post_ref())) + ")" ast::_cast(b) return str("_cast") - ast::_value(b) return str("_value(") + b.first + ": " + deref_to_string(b.second->bound_to) + ")" + ast::_value(b) return str("_value(") + b.first + ": " + "pre_ref:" + deref_to_string(b.second->get_bound_to(binding_epoch::pre_ref())) + "/post_ref:" + deref_to_string(b.second->get_bound_to(binding_epoch::post_ref())) + ")" } } fun _translation_unit(p: str): *tree { @@ -253,7 +253,7 @@ fun make_ast_binding(s: str, v: vec<*binding>): *tree { fun clone_ast_binding(binding: *tree): *tree { match(binding->data) { ast::_binding(b) { - return _binding(b.first, b.second, binding(b.third->bound_to)) + return _binding(b.first, b.second, b.third) } } error("trying to get binding on not a binding") @@ -266,27 +266,27 @@ fun get_ast_binding_inst_types(binding: *tree): ref vec<*binding> { } error("trying to get binding on not a binding") } -fun get_ast_binding(binding: *tree): *tree { +fun get_ast_binding(binding: *tree, epoch: binding_epoch): *tree { match(binding->data) { ast::_binding(b) { - return b.third->bound_to + return b.third->get_bound_to(epoch) } } error("trying to get binding on not a binding") } -fun set_ast_binding(binding: *tree, to: *tree) { +fun set_ast_binding(binding: *tree, to: *tree, epoch: binding_epoch) { match(binding->data) { ast::_binding(b) { - b.third->set(to) + b.third->set(to, epoch) return } } error("trying to set binding on not a binding") } -fun set_single_ast_binding(binding: *tree, to: *tree) { +fun set_single_ast_binding(binding: *tree, to: *tree, epoch: binding_epoch) { match(binding->data) { ast::_binding(b) { - b.third->set_single(to) + b.third->set_single(to, epoch) return } } diff --git a/stdlib/binding.krak b/stdlib/binding.krak index 41dab92..9022f30 100644 --- a/stdlib/binding.krak +++ b/stdlib/binding.krak @@ -5,18 +5,24 @@ import str:* import ast:* import type2:* +adt binding_epoch { + pre_ref, + post_ref, + all +} + var bindings: *vec<*void> fun binding(): *binding { - return binding(null()) + return binding(null(), binding_epoch::all()) } -fun binding_p(it: T): *binding { +fun binding_p(it: T, epoch: binding_epoch): *binding { var p = new() p->copy_construct(&it) - return binding(p) + return binding(p, epoch) } -fun binding(it: *T): *binding { - var to_ret = new>()->construct(it) +fun binding(it: *T, epoch: binding_epoch): *binding { + var to_ret = new>()->construct(it, epoch) if (bindings == null>()) bindings = new>()->construct() bindings->add( (to_ret) cast *void ) @@ -24,46 +30,75 @@ fun binding(it: *T): *binding { } obj binding (Object) { - var bound_to: *T + var bound_to_pre_ref: *T + var bound_to_post_ref: *T fun construct(): *binding { - bound_to = null() + bound_to_pre_ref = null() + bound_to_post_ref = null() return this } - fun construct(it: *T): *binding { - bound_to = it + fun construct(it: *T, epoch: binding_epoch): *binding { + set_single(it, epoch) return this } fun copy_construct(old: *binding): void { - bound_to = old->bound_to + bound_to_pre_ref = old->bound_to_pre_ref + bound_to_post_ref = old->bound_to_post_ref } fun destruct() { - bound_to = null() + bound_to_pre_ref = null() + bound_to_post_ref = null() } - fun bound(): bool { - return bound_to != null() + fun bound(epoch: binding_epoch): bool { + return bound_to_pre_ref != null() || bound_to_post_ref != null() } - fun set(to: T) { + fun set(to: T, epoch: binding_epoch) { var p = new() p->copy_construct(&to) - set(p) + set(p, epoch) } - fun set(to: *T) { - // don't set null, that will set all unbound ones - if (bound_to == null()) { - bound_to = to - return + fun set(to: *T, epoch: binding_epoch) { + var pre_ref_from = bound_to_pre_ref + var post_ref_from = bound_to_post_ref + if epoch == binding_epoch::pre_ref() || epoch == binding_epoch::all() { + bound_to_pre_ref = to + // don't set null, that will set all unbound ones + if pre_ref_from != null() { + for (var i = 0; i < bindings->size; i++;) + if ( ((bindings->get(i)) cast *binding)->bound_to_pre_ref == pre_ref_from) + ((bindings->get(i)) cast *binding)->bound_to_pre_ref = to + } + } + if epoch == binding_epoch::post_ref() || epoch == binding_epoch::all() { + bound_to_post_ref = to + // don't set null, that will set all unbound ones + if post_ref_from != null() { + for (var i = 0; i < bindings->size; i++;) + if ( ((bindings->get(i)) cast *binding)->bound_to_post_ref == post_ref_from) + ((bindings->get(i)) cast *binding)->bound_to_post_ref = to + } } - var from = bound_to - for (var i = 0; i < bindings->size; i++;) - if ( ((bindings->get(i)) cast *binding)->bound_to == from) - ((bindings->get(i)) cast *binding)->bound_to = to } - fun set_single(to: *T) { - bound_to = to + fun set_single(to: *T, epoch: binding_epoch) { + match (epoch) { + binding_epoch::pre_ref() { bound_to_pre_ref = to; } + binding_epoch::post_ref() { bound_to_post_ref = to; } + binding_epoch::all() { bound_to_pre_ref = to; bound_to_post_ref = to; } + } + } + fun bound(): bool { + return bound_to_pre_ref != null() || bound_to_post_ref != null() + } + fun get_bound_to(epoch: binding_epoch): *T { + match (epoch) { + binding_epoch::pre_ref() { return bound_to_pre_ref; } + binding_epoch::post_ref() if bound_to_post_ref != null() { return bound_to_post_ref; } else { return bound_to_pre_ref; } + binding_epoch::all() { error("trying to get_bound_to for all, which doesn't make any sense"); } + } } fun to_string(): str { /*return "binding(" + to_string(bound_to) + ")"*/ - return "binding(" + deref_to_string(bound_to) + ")" + return "binding(pre_ref:" + deref_to_string(bound_to_pre_ref) + "/post_ref:" + deref_to_string(bound_to_post_ref) + ")" } } diff --git a/stdlib/type2.krak b/stdlib/type2.krak index c9763c5..23bb166 100644 --- a/stdlib/type2.krak +++ b/stdlib/type2.krak @@ -40,52 +40,52 @@ adt type { _double } -fun has_unknown(t: *binding): bool { - match (*t->bound_to) { +fun has_unknown(t: *binding, 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): bool return has_unknown(inner_t);) - type::_fun(f) return has_unknown(f.first.second.second) || f.first.first.any_true(fun(p: pair>): 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): 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>): bool return has_unknown(p.second, epoch);) } return false } -fun unify(t1: *binding, t2: *binding) { - 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, t2: *binding, 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, replacements: ref map<*binding, *binding>): *binding { - match (*t->bound_to) { +fun inst_temp_type(t: *binding, replacements: ref map<*binding, *binding>, epoch: binding_epoch): *binding { + 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): *binding return inst_temp_type(b, replacements);) + var binding_types = o->data._binding.second.map(fun(b: *binding): *binding 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, 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>): pair> 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>): pair> 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, replacements: ref map<*binding, *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>): str return to_string(pt.first) + to_string(pt.second->bound_to);)) + to_ret += str(", ").join(b.first.first.map(fun(pt: pair>): 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")