Implemented traits, so test_traitsTest passes now and fixed small bug that allowed test_functionsValues to pass as well. 42 now

This commit is contained in:
Nathan Braswell
2016-02-29 04:53:03 -05:00
parent 939cf83da1
commit d6bb0cf45b
5 changed files with 105 additions and 75 deletions

View File

@@ -77,6 +77,11 @@ obj ast_transformation (Object) {
})
return translation_unit
}
fun transform_traits(traits_node: *tree<symbol>): set<string> {
if (!traits_node)
return set<string>()
return from_vector(get_nodes("scoped_identifier", traits_node).map(fun(s: *tree<symbol>): string return concat_symbol_tree(s);))
}
fun first_pass_type_def(child: *tree<symbol>, 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<symbol>) {
template_types.add(concat_symbol_tree(get_node("identifier", template_param)))
template_type_replacements.set(template_types.last(), type_ptr(vector<string>()))
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<string>()
var template_type_replacements = map<string, *type>()
// XXX add traits
get_nodes("template_param", template_dec).for_each(fun(template_param: *tree<symbol>) {
template_types.add(concat_symbol_tree(get_node("identifier", template_param)))
template_type_replacements.set(template_types.last(), type_ptr(vector<string>()))
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<symbol>): *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<pair<*ast_node, int>>()
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 inst_type = null<ast_node>()
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 {
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<ast_node>()
// 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 {
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))
}
if (fitting_types.size == 0) {
println("no working templated object found")
error("FREAK OUT AUTOMATON")
return null<type>()
}
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<pair<*ast_node, int>>()
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<type>()
@@ -737,24 +760,32 @@ 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<ast_node>()
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(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])
@@ -772,6 +803,15 @@ obj ast_transformation (Object) {
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 {
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,16 +820,18 @@ 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")
}
}
if (fitting_functions.size == 0) {
println("no working templated method found")
return null<ast_node>()
}
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);
fun has_method(object: *ast_node, name: string, parameter_types: vector<*type>): bool {
@@ -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
}
}

View File

@@ -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)

View File

@@ -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<type>()->construct()
}
fun type_ptr(definition: *ast_node): *type {
return new<type>()->construct(definition)
fun type_ptr(definition: *ast_node): *type return type_ptr(definition, set<string>());
fun type_ptr(definition: *ast_node, traits: set<string>): *type {
return new<type>()->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<type>()->construct(parameters, return_type, indirection)
}
fun type_ptr(traits: vector<string>): *type {
fun type_ptr(traits: set<string>): *type {
return new<type>()->construct(traits)
}
@@ -44,7 +47,7 @@ obj type (Object) {
var return_type: *type
var indirection: int
var type_def: *ast_node
var traits: vector<string>
var traits: set<string>
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<string>): *type {
fun construct(traits_in: set<string>): *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<string>): *type {
base.copy_construct(&base_type::object())
parameter_types.construct()
indirection = 0
return_type = null<type>()
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) {

View File

@@ -1,4 +1,4 @@
import io:*
import simple_print:*
fun test(): void {
println(9)

View File

@@ -22,11 +22,6 @@ fun OneTwoFunc<T(SecondTrait)>(obj: T): void {
fun OneTwoFunc<T(FirstTrait, SecondTrait)>(obj: T): void {
println("Both Traits");
}
/*
template <AlreadySpecilized> |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<T> (FirstTrait) {};
obj OneTwoObj<T(FirstTrait)> (SecondTrait) {};
obj OneTwoObj<T(SecondTrait)> (FirstTrait, SecondTrait) {};
obj OneTwoObj<T(FirstTrait, SecondTrait)> {};
/*
*obj template<AlreadySpecilized> OneTwoObj {
* void proveSpecilized() {
* println("I'm specilized!");
* }
*};
*/
fun main(): int {
var a: NoTraits;
@@ -54,7 +42,6 @@ fun main(): int {
OneTwoFunc<Trait1>(b);
OneTwoFunc<Trait2>(c);
OneTwoFunc<TwoTrait>(d);
// OneTwoFunc<AlreadySpecilized>(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<Trait1>;
var gamma: OneTwoObj<Trait2>;
var delta: OneTwoObj<TwoTrait>;
// |OneTwoObj<AlreadySpecilized>| epsilon;
var zeta: OneTwoObj<*TwoTrait>;
OneTwoFunc<OneTwoObj<NoTraits>>(alpha);