From d6bb0cf45b3f2fb63a2f87e78a42cab39aa2bef8 Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Mon, 29 Feb 2016 04:53:03 -0500 Subject: [PATCH] Implemented traits, so test_traitsTest passes now and fixed small bug that allowed test_functionsValues to pass as well. 42 now --- stdlib/ast_transformation.krak | 142 +++++++++++++++++++++----------- stdlib/importer.krak | 2 +- stdlib/type.krak | 19 +++-- tests/test_functionsValues.krak | 2 +- tests/test_traitsTest.krak | 15 ---- 5 files changed, 105 insertions(+), 75 deletions(-) diff --git a/stdlib/ast_transformation.krak b/stdlib/ast_transformation.krak index 9971cd8..2ffc511 100644 --- a/stdlib/ast_transformation.krak +++ b/stdlib/ast_transformation.krak @@ -77,6 +77,11 @@ obj ast_transformation (Object) { }) return translation_unit } + fun transform_traits(traits_node: *tree): set { + if (!traits_node) + return set() + return from_vector(get_nodes("scoped_identifier", traits_node).map(fun(s: *tree): string return concat_symbol_tree(s);)) + } fun first_pass_type_def(child: *tree, scope: *ast_node, instantiate_template: bool): *ast_node { var name = concat_symbol_tree(get_node("identifier", child)) var template_dec = get_node("template_dec", child) @@ -86,7 +91,7 @@ obj ast_transformation (Object) { // XXX add traits get_nodes("template_param", template_dec).for_each(fun(template_param: *tree) { template_types.add(concat_symbol_tree(get_node("identifier", template_param))) - template_type_replacements.set(template_types.last(), type_ptr(vector())) + template_type_replacements.set(template_types.last(), type_ptr(transform_traits(get_node("traits", template_param)))) }) var template = ast_template_ptr(name, child, template_types, template_type_replacements, false) add_to_scope("~enclosing_scope", scope, template) @@ -94,7 +99,7 @@ obj ast_transformation (Object) { return template } else { var type_def_node = ast_type_def_ptr(name) - type_def_node->type_def.self_type = type_ptr(type_def_node) + type_def_node->type_def.self_type = type_ptr(type_def_node, transform_traits(get_node("traits", child))) ast_to_syntax.set(type_def_node, child) add_to_scope("~enclosing_scope", scope, type_def_node) add_to_scope(name, type_def_node, scope) @@ -147,10 +152,9 @@ obj ast_transformation (Object) { if (do_raw_template && template_dec) { var template_types = vector() var template_type_replacements = map() - // XXX add traits get_nodes("template_param", template_dec).for_each(fun(template_param: *tree) { template_types.add(concat_symbol_tree(get_node("identifier", template_param))) - template_type_replacements.set(template_types.last(), type_ptr(vector())) + template_type_replacements.set(template_types.last(), type_ptr(transform_traits(get_node("traits", template_param)))) }) template_type_replacements.for_each(fun(key: string, value: *type) println(string("MAP: ") + key + " : " + value->to_string());) println("MAP DONE") @@ -243,6 +247,8 @@ obj ast_transformation (Object) { var real_types = get_nodes("type", template_inst).map(fun(t: *tree): *type return transform_type(t, scope, template_replacements);) var real_types_deref = real_types.map(fun(t:*type):type return *t;) var results = scope_lookup(name, scope) + + var fitting_types = vector>() for (var i = 0; i < results.size; i++;) { if (!is_template(results[i]) || results[i]->template.is_function) continue @@ -251,26 +257,36 @@ obj ast_transformation (Object) { var template_type_replacements = results[i]->template.template_type_replacements if (template_types.size != real_types.size) continue - // check if already instantiated + + var num_satisfied_traits = 0 + var satisfied_traits = true + template_type_replacements.for_each(fun(key: string, value: *type) num_satisfied_traits += value->traits.size();) + println("FOR FIND OR INSTATINTATE PREEEE") + template_type_replacements.for_each(fun(key: string, value: *type) println(string("MAP: ") + key + " : " + value->to_string());) + println("MAP DONE") + for (var j = 0; j < template_types.size; j++;) { + satisfied_traits = satisfied_traits && real_types[j]->traits.contains(template_type_replacements[template_types[j]]->traits) && + (real_types[j]->indirection == 0 || template_type_replacements[template_types[j]]->traits.size() == 0) + template_type_replacements[template_types[j]] = real_types[j] + println("Just made") + println(template_types[j]) + println("equal to") + println(real_types[j]->to_string()) + } + if (!satisfied_traits) { + println(name + " did not satisfy traits!") + continue + } + println("FOR FIND OR INSTATINTATE") + template_type_replacements.for_each(fun(key: string, value: *type) println(string("MAP: ") + key + " : " + value->to_string());) + println("MAP DONE") + var inst_type = null() + // check if already instantiated if (results[i]->template.instantiated_map.contains_key(real_types_deref)) { println("USING CACHED TEMPLATE OBJECT") inst_type = results[i]->template.instantiated_map[real_types_deref] } else { - println("FOR FIND OR INSTATINTATE PREEEE") - template_type_replacements.for_each(fun(key: string, value: *type) println(string("MAP: ") + key + " : " + value->to_string());) - println("MAP DONE") - for (var j = 0; j < template_types.size; j++;) { - template_type_replacements[template_types[j]] = real_types[j] - println("Just made") - println(template_types[j]) - println("equal to") - println(real_types[j]->to_string()) - } - println("FOR FIND OR INSTATINTATE") - template_type_replacements.for_each(fun(key: string, value: *type) println(string("MAP: ") + key + " : " + value->to_string());) - println("MAP DONE") - inst_type = first_pass_type_def(results[i]->template.syntax_node, results[i], true) // add to instantiated_map so we only instantiate with a paticular set of types once // put in map first for recursive purposes @@ -279,9 +295,14 @@ obj ast_transformation (Object) { second_pass_type_def(results[i]->template.syntax_node, inst_type, results[i], template_type_replacements) fourth_pass_worklist.push(inst_type) } - return inst_type->type_def.self_type->clone_with_indirection(indirection) + fitting_types.add(make_pair(inst_type, num_satisfied_traits)) } - error("FREAK OUT AUTOMATON") + if (fitting_types.size == 0) { + println("no working templated object found") + error("FREAK OUT AUTOMATON") + return null() + } + return fitting_types.max(fun(a: pair<*ast_node, int>, b: pair<*ast_node, int>): bool return a.second < b.second;).first->type_def.self_type->clone_with_indirection(indirection) } var type_syntax_str = concat_symbol_tree(real_node) println(type_syntax_str + " *************************") @@ -723,12 +744,14 @@ obj ast_transformation (Object) { real_types_deref = real_types.map(fun(t:*type):type return *t;) had_real_types = true } + var fitting_functions = vector>() for (var i = 0; i < results.size; i++;) { if (is_template(results[i]) && results[i]->template.is_function) { println(string() + i + " is a template!") var template_types = results[i]->template.template_types var template_type_replacements = results[i]->template.template_type_replacements if (!had_real_types) { + var unify_template_type_replacements = template_type_replacements // reset the vars, cuz we might be iterating through multiple of them real_types = vector<*type>() real_types_deref = vector() @@ -737,41 +760,58 @@ obj ast_transformation (Object) { if (param_types.size != typed_params.size) continue for (var j = 0; j < typed_params.size; j++;) - unify_type(typed_params[j], param_types[j], &template_type_replacements, template_replacements) + unify_type(typed_params[j], param_types[j], &unify_template_type_replacements, template_replacements) for (var j = 0; j < typed_params.size; j++;) { - var t = template_type_replacements[template_types[j]]; + var t = unify_template_type_replacements[template_types[j]]; real_types.add(t) real_types_deref.add(*t) } } else if (template_types.size != real_types.size) continue + var num_satisfied_traits = 0 + var satisfied_traits = true + template_type_replacements.for_each(fun(key: string, value: *type) num_satisfied_traits += value->traits.size();) // check if already instantiated var inst_func = null() + println(string("FOR TEMPLATE FUNCTION ") + name) + println("FOR FIND OR INSTATINTATE PREEEE") + template_type_replacements.for_each(fun(key: string, value: *type) println(string("MAP: ") + key + " : " + value->to_string());) + println("MAP DONE") + for (var j = 0; j < template_types.size; j++;) { + print("NEW TRAITS IN ALREADY: ") + template_type_replacements[template_types[j]]->traits.for_each(fun (t: string) print(t + " ");) + println() + print("NEW TRAITS PASSED IN: ") + real_types[j]->traits.for_each(fun (t: string) print(t + " ");) + println() + satisfied_traits = satisfied_traits && real_types[j]->traits.contains(template_type_replacements[template_types[j]]->traits) && + (real_types[j]->indirection == 0 || template_type_replacements[template_types[j]]->traits.size() == 0) + template_type_replacements[template_types[j]] = real_types[j] + println("Just made") + println(template_types[j]) + println("equal to") + println(real_types[j]->to_string()) + } + replacements_base.for_each(fun(key: string, value: *type) { + template_type_replacements[key] = value + println("Just Inherited") + println(key) + println("equal to") + println(value->to_string()) + }) + println("FOR FIND OR INSTATINTATE") + template_type_replacements.for_each(fun(key: string, value: *type) println(string("MAP: ") + key + " : " + value->to_string());) + println("MAP DONE") + + if (!satisfied_traits) { + println("Did not satisfy traits!") + continue + } + if (results[i]->template.instantiated_map.contains_key(real_types_deref)) { println("USING CACHED TEMPLATE FUNCITON") inst_func = results[i]->template.instantiated_map[real_types_deref] } else { - println("FOR FIND OR INSTATINTATE PREEEE") - template_type_replacements.for_each(fun(key: string, value: *type) println(string("MAP: ") + key + " : " + value->to_string());) - println("MAP DONE") - for (var j = 0; j < template_types.size; j++;) { - template_type_replacements[template_types[j]] = real_types[j] - println("Just made") - println(template_types[j]) - println("equal to") - println(real_types[j]->to_string()) - } - replacements_base.for_each(fun(key: string, value: *type) { - template_type_replacements[key] = value - println("Just Inherited") - println(key) - println("equal to") - println(value->to_string()) - }) - println("FOR FIND OR INSTATINTATE") - template_type_replacements.for_each(fun(key: string, value: *type) println(string("MAP: ") + key + " : " + value->to_string());) - println("MAP DONE") - inst_func = second_pass_function(results[i]->template.syntax_node, results[i], template_type_replacements, false) // add to instantiated_map so we only instantiate with a paticular set of types once // put in map first for recursive purposes @@ -780,15 +820,17 @@ obj ast_transformation (Object) { // and fully instantiate it inst_func->function.body_statement = transform_statement(get_node("statement", results[i]->template.syntax_node), inst_func, template_type_replacements) } - if (function_satisfies_params(inst_func, param_types)) - return inst_func + fitting_functions.add(make_pair(inst_func, num_satisfied_traits)) else println(string("this paticular ") + name + " did not satisfy params") } } - println("no working templated method found") - return null() + if (fitting_functions.size == 0) { + println("no working templated method found") + return null() + } + return fitting_functions.max(fun(a: pair<*ast_node, int>, b: pair<*ast_node, int>): bool return a.second < b.second;).first } } fun has_method(object: *ast_node, name: *char, parameter_types: vector<*type>): bool return has_method(object, string(name), parameter_types); @@ -825,7 +867,7 @@ fun get_builtin_function(name: string, param_types: vector<*type>): *ast_node { return ast_function_ptr(name, type_ptr(param_types, param_types[0]->clone_with_decreased_indirection()), vector<*ast_node>()) if (name == "&") return ast_function_ptr(name, type_ptr(param_types, param_types[0]->clone_with_increased_indirection()), vector<*ast_node>()) - if (name == "\*") + if (name == "\*" && param_types.size == 1) return ast_function_ptr(name, type_ptr(param_types, param_types[0]->clone_with_decreased_indirection()), vector<*ast_node>()) if (param_types.size > 1 && param_types[1]->rank() > param_types[0]->rank()) return ast_function_ptr(name, type_ptr(param_types, param_types[1]), vector<*ast_node>()) @@ -880,7 +922,7 @@ fun function_satisfies_params(node: *ast_node, param_types: vector<*type>): bool } for (var j = 0; j < param_types.size; j++;) { if (*func_param_types[j] != *param_types[j]) { - println(string("types don't match") + func_param_types[j]->to_string() + " with needed " + param_types[j]->to_string()) + println(string("types don't match ") + func_param_types[j]->to_string() + " with needed " + param_types[j]->to_string()) return false } } diff --git a/stdlib/importer.krak b/stdlib/importer.krak index 8aee79b..951f3b2 100644 --- a/stdlib/importer.krak +++ b/stdlib/importer.krak @@ -98,7 +98,7 @@ obj importer (Object) { remove_node(symbol("\"\\(\"", true), parse_tree) remove_node(symbol("\"\\)\"", true), parse_tree) remove_node(symbol("\"var\"", true), parse_tree) - remove_node(symbol("\"fun\"", true), parse_tree) + // remove_node(symbol("\"fun\"", true), parse_tree) remove_node(symbol("\"template\"", true), parse_tree) remove_node(symbol("\"return\"", true), parse_tree) remove_node(symbol("\"defer\"", true), parse_tree) diff --git a/stdlib/type.krak b/stdlib/type.krak index 76cbb67..e92d368 100644 --- a/stdlib/type.krak +++ b/stdlib/type.krak @@ -1,7 +1,9 @@ import mem:* import string:* import vector:* +import set:* import ast_nodes:* +import io:* // hmm, like the ast_node, this is another candadate for being fully an ADT // one issue is that there are properties shared between most of the options (indirection, say) @@ -22,8 +24,9 @@ adt base_type { fun type_ptr(): *type { return new()->construct() } -fun type_ptr(definition: *ast_node): *type { - return new()->construct(definition) +fun type_ptr(definition: *ast_node): *type return type_ptr(definition, set()); +fun type_ptr(definition: *ast_node, traits: set): *type { + return new()->construct(definition, traits) } fun type_ptr(base: base_type): *type return type_ptr(base, 0); fun type_ptr(base: base_type, indirection: int): *type { @@ -34,7 +37,7 @@ fun type_ptr(parameters: vector<*type>, return_type: *type, indirection: int): * return new()->construct(parameters, return_type, indirection) } -fun type_ptr(traits: vector): *type { +fun type_ptr(traits: set): *type { return new()->construct(traits) } @@ -44,7 +47,7 @@ obj type (Object) { var return_type: *type var indirection: int var type_def: *ast_node - var traits: vector + var traits: set fun construct(): *type { base.copy_construct(&base_type::none()) parameter_types.construct() @@ -54,7 +57,7 @@ obj type (Object) { traits.construct() return this } - fun construct(traits_in: vector): *type { + fun construct(traits_in: set): *type { base.copy_construct(&base_type::template_type()) parameter_types.construct() indirection = 0 @@ -72,13 +75,13 @@ obj type (Object) { traits.construct() return this } - fun construct(type_def_in: *ast_node): *type { + fun construct(type_def_in: *ast_node, traits_in: set): *type { base.copy_construct(&base_type::object()) parameter_types.construct() indirection = 0 return_type = null() type_def = type_def_in - traits.construct() + traits.copy_construct(&traits_in) return this } fun construct(parameter_types_in: vector<*type>, return_type_in: *type, indirection_in: int): *type { @@ -119,7 +122,7 @@ obj type (Object) { } fun to_string(): string { var all_string = string("traits:[") - for (var i = 0; i < traits.size; i++;) all_string += traits[i] + traits.for_each(fun(t: string) all_string += t;) all_string += "] " for (var i = 0; i < indirection; i++;) all_string += "*" match (base) { diff --git a/tests/test_functionsValues.krak b/tests/test_functionsValues.krak index 6690273..5551bfc 100644 --- a/tests/test_functionsValues.krak +++ b/tests/test_functionsValues.krak @@ -1,4 +1,4 @@ -import io:* +import simple_print:* fun test(): void { println(9) diff --git a/tests/test_traitsTest.krak b/tests/test_traitsTest.krak index 9916381..8495dcd 100644 --- a/tests/test_traitsTest.krak +++ b/tests/test_traitsTest.krak @@ -22,11 +22,6 @@ fun OneTwoFunc(obj: T): void { fun OneTwoFunc(obj: T): void { println("Both Traits"); } -/* -template |void| OneTwoFunc(|AlreadySpecilized| obj) { - println("Already Specilized"); -} -*/ //This should work for objects too! //To test, we cycle the mapping of traits @@ -34,13 +29,6 @@ obj OneTwoObj (FirstTrait) {}; obj OneTwoObj (SecondTrait) {}; obj OneTwoObj (FirstTrait, SecondTrait) {}; obj OneTwoObj {}; -/* - *obj template OneTwoObj { - * void proveSpecilized() { - * println("I'm specilized!"); - * } - *}; - */ fun main(): int { var a: NoTraits; @@ -54,7 +42,6 @@ fun main(): int { OneTwoFunc(b); OneTwoFunc(c); OneTwoFunc(d); -// OneTwoFunc(e); OneTwoFunc<*TwoTrait>(f); println(); @@ -62,7 +49,6 @@ fun main(): int { OneTwoFunc(b); OneTwoFunc(c); OneTwoFunc(d); -// OneTwoFunc(e); OneTwoFunc(f); println(); @@ -70,7 +56,6 @@ fun main(): int { var beta: OneTwoObj; var gamma: OneTwoObj; var delta: OneTwoObj; -// |OneTwoObj| epsilon; var zeta: OneTwoObj<*TwoTrait>; OneTwoFunc>(alpha);