|
|
|
|
@@ -19,12 +19,15 @@ adt search_type {
|
|
|
|
|
|
|
|
|
|
obj ast_transformation (Object) {
|
|
|
|
|
var ast_to_syntax: map<*ast_node, *tree<symbol>>
|
|
|
|
|
var fourth_pass_worklist: queue<*ast_node>
|
|
|
|
|
fun construct(): *ast_transformation {
|
|
|
|
|
ast_to_syntax.construct()
|
|
|
|
|
fourth_pass_worklist.construct()
|
|
|
|
|
return this
|
|
|
|
|
}
|
|
|
|
|
fun copy_construct(old: *ast_transformation) {
|
|
|
|
|
ast_to_syntax.copy_construct(&old->ast_to_syntax)
|
|
|
|
|
fourth_pass_worklist.copy_construct(&old->fourth_pass_worklist)
|
|
|
|
|
}
|
|
|
|
|
fun operator=(old: ref ast_transformation) {
|
|
|
|
|
destruct()
|
|
|
|
|
@@ -32,6 +35,7 @@ obj ast_transformation (Object) {
|
|
|
|
|
}
|
|
|
|
|
fun destruct() {
|
|
|
|
|
ast_to_syntax.destruct()
|
|
|
|
|
fourth_pass_worklist.destruct()
|
|
|
|
|
}
|
|
|
|
|
// first pass defines all type_defs (objects and aliases), ADTs, and top-level if-comps/passthroughs
|
|
|
|
|
fun first_pass(file_name: string, parse_tree: *tree<symbol>, importer: *importer): *ast_node {
|
|
|
|
|
@@ -39,14 +43,7 @@ obj ast_transformation (Object) {
|
|
|
|
|
importer->register(file_name, parse_tree, translation_unit)
|
|
|
|
|
parse_tree->children.for_each(fun(child: *tree<symbol>) {
|
|
|
|
|
if (child->data.name == "type_def") {
|
|
|
|
|
var name = concat_symbol_tree(get_node("identifier", child))
|
|
|
|
|
var type_def_node = ast_type_def_ptr(name)
|
|
|
|
|
type_def_node->type_def.self_type = type_ptr(type_def_node)
|
|
|
|
|
translation_unit->translation_unit.children.add(type_def_node)
|
|
|
|
|
ast_to_syntax.set(type_def_node, child)
|
|
|
|
|
add_to_scope("~enclosing_scope", translation_unit, type_def_node)
|
|
|
|
|
add_to_scope(name, type_def_node, translation_unit)
|
|
|
|
|
// set up type - self-referential, traits, template, etc
|
|
|
|
|
translation_unit->translation_unit.children.add(first_pass_type_def(child, translation_unit, false))
|
|
|
|
|
} else if (child->data.name == "adt_def") {
|
|
|
|
|
var name = concat_symbol_tree(get_node("identifier", child))
|
|
|
|
|
var adt_def_node = ast_adt_def_ptr(name)
|
|
|
|
|
@@ -80,6 +77,30 @@ obj ast_transformation (Object) {
|
|
|
|
|
})
|
|
|
|
|
return translation_unit
|
|
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
|
if (template_dec && !instantiate_template) {
|
|
|
|
|
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>()))
|
|
|
|
|
})
|
|
|
|
|
var template = ast_template_ptr(name, child, template_types, template_type_replacements, false)
|
|
|
|
|
add_to_scope("~enclosing_scope", scope, template)
|
|
|
|
|
add_to_scope(name, template, scope)
|
|
|
|
|
return template
|
|
|
|
|
} else {
|
|
|
|
|
var type_def_node = ast_type_def_ptr(name)
|
|
|
|
|
type_def_node->type_def.self_type = type_ptr(type_def_node)
|
|
|
|
|
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)
|
|
|
|
|
return type_def_node
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// defines inside of objects + ADTs, outside declaration statements, and function prototypes
|
|
|
|
|
fun second_pass(parse_tree: *tree<symbol>, translation_unit: *ast_node) {
|
|
|
|
|
println(string("Second Pass for ") + translation_unit->translation_unit.name)
|
|
|
|
|
@@ -98,67 +119,42 @@ obj ast_transformation (Object) {
|
|
|
|
|
// work on the ones already started
|
|
|
|
|
translation_unit->translation_unit.children.for_each(fun(node: *ast_node) {
|
|
|
|
|
match(*node) {
|
|
|
|
|
ast_node::type_def(backing) {
|
|
|
|
|
var type_def_syntax = ast_to_syntax[node]
|
|
|
|
|
type_def_syntax->children.for_each(fun(child: *tree<symbol>) {
|
|
|
|
|
if (child->data.name == "declaration_statement") {
|
|
|
|
|
var declaration_node = transform_declaration_statement(child, node, map<string, *type>())
|
|
|
|
|
node->type_def.variables.add(declaration_node)
|
|
|
|
|
ast_to_syntax.set(declaration_node, child)
|
|
|
|
|
} else if (child->data.name == "function") {
|
|
|
|
|
// again, also handles templates
|
|
|
|
|
var function_node = second_pass_function(child, node, map<string, *type>(), true)
|
|
|
|
|
node->type_def.methods.add(function_node)
|
|
|
|
|
ast_to_syntax.set(function_node, child)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
ast_node::type_def(backing) second_pass_type_def(ast_to_syntax[node], node, translation_unit, map<string, *type>())
|
|
|
|
|
ast_node::adt_def(backing) do_nothing() // actually go through and do methods inside
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
// The third pass finishes up by doing all function bodies (top level and methods in objects)
|
|
|
|
|
fun third_pass(parse_tree: *tree<symbol>, translation_unit: *ast_node) {
|
|
|
|
|
println(string("Third Pass for ") + translation_unit->translation_unit.name)
|
|
|
|
|
translation_unit->translation_unit.children.for_each(fun(node: *ast_node) {
|
|
|
|
|
match(*node) {
|
|
|
|
|
ast_node::type_def(backing) {
|
|
|
|
|
// make sure not a template? or the method not a template?
|
|
|
|
|
// also same body problem as below
|
|
|
|
|
node->type_def.methods.for_each(fun(method: *ast_node) {
|
|
|
|
|
method->function.body_statement = transform_statement(get_node("statement", ast_to_syntax[method]), method, map<string, *type>())
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
ast_node::function(backing) {
|
|
|
|
|
// make sure not a template
|
|
|
|
|
// huh, I guess I can't actually assign to the backing.
|
|
|
|
|
// This is actually a little bit of a problem, maybe these should be pointers also. All the pointers!
|
|
|
|
|
node->function.body_statement = transform_statement(get_node("statement", ast_to_syntax[node]), node, map<string, *type>())
|
|
|
|
|
}
|
|
|
|
|
fun second_pass_type_def(type_def_syntax: *tree<symbol>, node: *ast_node, scope: *ast_node, template_replacements: map<string, *type>) {
|
|
|
|
|
type_def_syntax->children.for_each(fun(child: *tree<symbol>) {
|
|
|
|
|
if (child->data.name == "declaration_statement") {
|
|
|
|
|
var declaration_node = transform_declaration_statement(child, node, template_replacements)
|
|
|
|
|
node->type_def.variables.add(declaration_node)
|
|
|
|
|
ast_to_syntax.set(declaration_node, child)
|
|
|
|
|
} else if (child->data.name == "function") {
|
|
|
|
|
// again, also handles templates
|
|
|
|
|
var function_node = second_pass_function(child, node, template_replacements, true)
|
|
|
|
|
node->type_def.methods.add(function_node)
|
|
|
|
|
ast_to_syntax.set(function_node, child)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
// The fourth pass generates the class templates that have not yet been generated in a "chaotic iteration" loop
|
|
|
|
|
fun fourth_pass(parse_tree: *tree<symbol>, translation_unit: *ast_node) {
|
|
|
|
|
println(string("Fourth Pass for ") + translation_unit->translation_unit.name)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fun second_pass_function(node: *tree<symbol>, scope: *ast_node, template_replacements: map<string, *type>, do_raw_template: bool): *ast_node {
|
|
|
|
|
var function_name = concat_symbol_tree(get_node("func_identifier", node))
|
|
|
|
|
var template_dec = get_node("template_dec", node)
|
|
|
|
|
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.for_each(fun(key: string, value: *type) println(string("MAP: ") + key + " : " + value->to_string());)
|
|
|
|
|
println("MAP DONE")
|
|
|
|
|
var function_template = ast_function_template_ptr(function_name, node, template_types, template_type_replacements)
|
|
|
|
|
add_to_scope(function_name, function_template, scope)
|
|
|
|
|
add_to_scope("~enclosing_scope", scope, function_template)
|
|
|
|
|
return function_template
|
|
|
|
|
var template = ast_template_ptr(function_name, node, template_types, template_type_replacements, true)
|
|
|
|
|
add_to_scope(function_name, template, scope)
|
|
|
|
|
add_to_scope("~enclosing_scope", scope, template)
|
|
|
|
|
return template
|
|
|
|
|
}
|
|
|
|
|
// check to see if it is a template
|
|
|
|
|
// figure out return type
|
|
|
|
|
@@ -181,7 +177,38 @@ fun second_pass_function(node: *tree<symbol>, scope: *ast_node, template_replace
|
|
|
|
|
parameters.for_each(fun(parameter: *ast_node) add_to_scope(parameter->identifier.name, parameter, function_node);)
|
|
|
|
|
return function_node
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The third pass finishes up by doing all function bodies (top level and methods in objects)
|
|
|
|
|
fun third_pass(parse_tree: *tree<symbol>, translation_unit: *ast_node) {
|
|
|
|
|
println(string("Third Pass for ") + translation_unit->translation_unit.name)
|
|
|
|
|
translation_unit->translation_unit.children.for_each(fun(node: *ast_node) {
|
|
|
|
|
match(*node) {
|
|
|
|
|
ast_node::type_def(backing) {
|
|
|
|
|
// make sure not a template? or the method not a template?
|
|
|
|
|
// also same body problem as below
|
|
|
|
|
node->type_def.methods.for_each(fun(method: *ast_node) {
|
|
|
|
|
method->function.body_statement = transform_statement(get_node("statement", ast_to_syntax[method]), method, map<string, *type>())
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
ast_node::function(backing) {
|
|
|
|
|
// make sure not a template
|
|
|
|
|
// huh, I guess I can't actually assign to the backing.
|
|
|
|
|
// This is actually a little bit of a problem, maybe these should be pointers also. All the pointers!
|
|
|
|
|
node->function.body_statement = transform_statement(get_node("statement", ast_to_syntax[node]), node, map<string, *type>())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
// The fourth pass generates the class templates that have not yet been generated in a worklist loop
|
|
|
|
|
fun fourth_pass(parse_tree: *tree<symbol>, translation_unit: *ast_node) {
|
|
|
|
|
println(string("Fourth Pass for ") + translation_unit->translation_unit.name)
|
|
|
|
|
while (!fourth_pass_worklist.empty()) {
|
|
|
|
|
var partially_inst_type_def = fourth_pass_worklist.pop()
|
|
|
|
|
partially_inst_type_def->type_def.methods.for_each(fun(method: *ast_node) {
|
|
|
|
|
// this is the wrong map
|
|
|
|
|
method->function.body_statement = transform_statement(get_node("statement", ast_to_syntax[method]), method, map<string, *type>())
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fun transform_type(node: *tree<symbol>, scope: *ast_node, template_replacements: map<string, *type>): *type {
|
|
|
|
|
// check for references and step down
|
|
|
|
|
// always get to pre-reffed level
|
|
|
|
|
@@ -192,6 +219,52 @@ fun transform_type(node: *tree<symbol>, scope: *ast_node, template_replacements:
|
|
|
|
|
real_node = get_node("pre_reffed", real_node)
|
|
|
|
|
indirection++
|
|
|
|
|
}
|
|
|
|
|
var template_inst = get_node("template_inst", real_node)
|
|
|
|
|
if (template_inst) {
|
|
|
|
|
var name = concat_symbol_tree(get_node("scoped_identifier", real_node))
|
|
|
|
|
println(string("trying to instantiate a template object: ") + name)
|
|
|
|
|
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)
|
|
|
|
|
for (var i = 0; i < results.size; i++;) {
|
|
|
|
|
if (!is_template(results[i]) || results[i]->template.is_function)
|
|
|
|
|
continue
|
|
|
|
|
println(to_string(i) + " is an object template!")
|
|
|
|
|
var template_types = results[i]->template.template_types
|
|
|
|
|
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 {
|
|
|
|
|
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
|
|
|
|
|
results[i]->template.instantiated_map.set(real_types_deref, inst_type)
|
|
|
|
|
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)
|
|
|
|
|
}
|
|
|
|
|
error("FREAK OUT AUTOMATON")
|
|
|
|
|
}
|
|
|
|
|
var type_syntax_str = concat_symbol_tree(real_node)
|
|
|
|
|
println(type_syntax_str + " *************************")
|
|
|
|
|
if (template_replacements.contains_key(type_syntax_str)) {
|
|
|
|
|
@@ -365,25 +438,6 @@ fun transform_declaration_statement(node: *tree<symbol>, scope: *ast_node, templ
|
|
|
|
|
add_to_scope(name, identifier, scope)
|
|
|
|
|
return declaration
|
|
|
|
|
}
|
|
|
|
|
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 {
|
|
|
|
|
return function_lookup(name, object, parameter_types) || false
|
|
|
|
|
}
|
|
|
|
|
fun make_method_call(object_ident: *ast_node, name: *char, parameters: vector<*ast_node>): *ast_node return make_method_call(object_ident, string(name), parameters);
|
|
|
|
|
fun make_method_call(object_ident: *ast_node, name: string, parameters: vector<*ast_node>): *ast_node {
|
|
|
|
|
var method = function_lookup(name, get_ast_type(object_ident)->type_def, parameters.map(fun(param: *ast_node): *type return get_ast_type(param);))
|
|
|
|
|
print("Here is the Method: ")
|
|
|
|
|
println(method)
|
|
|
|
|
return make_method_call(object_ident, method, parameters)
|
|
|
|
|
}
|
|
|
|
|
fun make_method_call(object_ident: *ast_node, method: *ast_node, parameters: vector<*ast_node>): *ast_node {
|
|
|
|
|
var method_access = ast_function_call_ptr(get_builtin_function(string("."), vector(get_ast_type(object_ident), get_ast_type(method))), vector(object_ident, method))
|
|
|
|
|
return ast_function_call_ptr(method_access, parameters)
|
|
|
|
|
}
|
|
|
|
|
fun make_operator_call(func: *char, params: vector<*ast_node>): *ast_node return make_operator_call(string(func), params);
|
|
|
|
|
fun make_operator_call(func: string, params: vector<*ast_node>): *ast_node {
|
|
|
|
|
return ast_function_call_ptr(get_builtin_function(func, params.map(fun(p:*ast_node): *type return get_ast_type(p);)), params)
|
|
|
|
|
}
|
|
|
|
|
fun transform_assignment_statement(node: *tree<symbol>, scope: *ast_node, template_replacements: map<string, *type>): *ast_node {
|
|
|
|
|
var assign_to = transform(get_node("factor", node), scope, template_replacements)
|
|
|
|
|
var to_assign = transform(get_node("boolean_expression", node), scope, template_replacements)
|
|
|
|
|
@@ -455,7 +509,7 @@ fun transform_expression(node: *tree<symbol>, scope: *ast_node, searching_for: s
|
|
|
|
|
if (node->children.size == 1) {
|
|
|
|
|
var possible_func = transform(node->children[0], scope, searching_for, template_replacements)
|
|
|
|
|
if (!possible_func) match (searching_for) {
|
|
|
|
|
search_type::function(type_vec) possible_func = find_or_instantiate_function_template(node->children[0], null<tree<symbol>>(), scope, type_vec, template_replacements);
|
|
|
|
|
search_type::function(type_vec) possible_func = find_or_instantiate_template_function(node->children[0], null<tree<symbol>>(), scope, type_vec, template_replacements);
|
|
|
|
|
}
|
|
|
|
|
if (!possible_func)
|
|
|
|
|
println(concat_symbol_tree(node) + ": HAS NO POSSIBLE FUNCTION OR FUNCTION TEMPLATE SOLUTIONS")
|
|
|
|
|
@@ -470,7 +524,7 @@ fun transform_expression(node: *tree<symbol>, scope: *ast_node, searching_for: s
|
|
|
|
|
println("TE<PLATE LOOKUO MAKES NO SENSE")
|
|
|
|
|
return null<ast_node>()
|
|
|
|
|
}
|
|
|
|
|
search_type::function(type_vec) return find_or_instantiate_function_template(identifier, template_inst, scope, type_vec, template_replacements)
|
|
|
|
|
search_type::function(type_vec) return find_or_instantiate_template_function(identifier, template_inst, scope, type_vec, template_replacements)
|
|
|
|
|
}
|
|
|
|
|
println("NEVER EVER HAPPEN")
|
|
|
|
|
}
|
|
|
|
|
@@ -497,6 +551,104 @@ fun transform_expression(node: *tree<symbol>, scope: *ast_node, searching_for: s
|
|
|
|
|
var parameter_types = parameters.map(fun(param: *ast_node): *type return get_ast_type(param);)
|
|
|
|
|
return ast_function_call_ptr(get_builtin_function(func_name, parameter_types), parameters)
|
|
|
|
|
}
|
|
|
|
|
fun find_or_instantiate_template_function(identifier: *tree<symbol>, template_inst: *tree<symbol>, scope: *ast_node, param_types: vector<*type>, template_replacements: map<string, *type>): *ast_node {
|
|
|
|
|
var name = concat_symbol_tree(identifier)
|
|
|
|
|
println(string("trying to instantiate a template function: ") + name)
|
|
|
|
|
var results = scope_lookup(name, scope)
|
|
|
|
|
var real_types = vector<*type>()
|
|
|
|
|
var real_types_deref = vector<type>()
|
|
|
|
|
var had_real_types = false
|
|
|
|
|
if (template_inst) {
|
|
|
|
|
real_types = get_nodes("type", template_inst).map(fun(t: *tree<symbol>): *type return transform_type(t, scope, template_replacements);)
|
|
|
|
|
real_types_deref = real_types.map(fun(t:*type):type return *t;)
|
|
|
|
|
had_real_types = true
|
|
|
|
|
}
|
|
|
|
|
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) {
|
|
|
|
|
// reset the vars, cuz we might be iterating through multiple of them
|
|
|
|
|
real_types = vector<*type>()
|
|
|
|
|
real_types_deref = vector<type>()
|
|
|
|
|
// Template Function Instance Inference time
|
|
|
|
|
var typed_params = get_nodes("typed_parameter", results[i]->template.syntax_node).map(fun(t: *tree<symbol>): *tree<symbol> return get_node("type",t);)
|
|
|
|
|
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)
|
|
|
|
|
for (var j = 0; j < typed_params.size; j++;) {
|
|
|
|
|
var t = template_type_replacements[template_types[j]];
|
|
|
|
|
real_types.add(t)
|
|
|
|
|
real_types_deref.add(*t)
|
|
|
|
|
}
|
|
|
|
|
} else if (template_types.size != real_types.size)
|
|
|
|
|
continue
|
|
|
|
|
// 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("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_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
|
|
|
|
|
results[i]->template.instantiated_map.set(real_types_deref, inst_func)
|
|
|
|
|
// 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
|
|
|
|
|
else
|
|
|
|
|
println(string("this paticular ") + name + " did not satisfy params")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
println("FREAK OUT MACHINE")
|
|
|
|
|
return null<ast_node>()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
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 {
|
|
|
|
|
println("HAS METHOD:")
|
|
|
|
|
var to_ret = function_lookup(name, object, parameter_types) || false
|
|
|
|
|
println("HAS METHOD result:")
|
|
|
|
|
println(to_ret)
|
|
|
|
|
return to_ret
|
|
|
|
|
}
|
|
|
|
|
fun make_method_call(object_ident: *ast_node, name: *char, parameters: vector<*ast_node>): *ast_node return make_method_call(object_ident, string(name), parameters);
|
|
|
|
|
fun make_method_call(object_ident: *ast_node, name: string, parameters: vector<*ast_node>): *ast_node {
|
|
|
|
|
println("MAKE METHOD CALL OUT:")
|
|
|
|
|
var method = function_lookup(name, get_ast_type(object_ident)->type_def, parameters.map(fun(param: *ast_node): *type return get_ast_type(param);))
|
|
|
|
|
print("Here is the Method: ")
|
|
|
|
|
println(method)
|
|
|
|
|
return make_method_call(object_ident, method, parameters)
|
|
|
|
|
}
|
|
|
|
|
fun make_method_call(object_ident: *ast_node, method: *ast_node, parameters: vector<*ast_node>): *ast_node {
|
|
|
|
|
println("MAKE METHOD CALL IN:")
|
|
|
|
|
var method_access = ast_function_call_ptr(get_builtin_function(string("."), vector(get_ast_type(object_ident), get_ast_type(method))), vector(object_ident, method))
|
|
|
|
|
return ast_function_call_ptr(method_access, parameters)
|
|
|
|
|
}
|
|
|
|
|
fun make_operator_call(func: *char, params: vector<*ast_node>): *ast_node return make_operator_call(string(func), params);
|
|
|
|
|
fun make_operator_call(func: string, params: vector<*ast_node>): *ast_node {
|
|
|
|
|
return ast_function_call_ptr(get_builtin_function(func, params.map(fun(p:*ast_node): *type return get_ast_type(p);)), params)
|
|
|
|
|
}
|
|
|
|
|
fun get_builtin_function(name: string, param_types: vector<*type>): *ast_node {
|
|
|
|
|
if (name == "==" || name == "!=" || name == ">" || name == "<" || name == "<=" || name == ">" || name == ">=" || name == "&&" || name == "||" || name == "!")
|
|
|
|
|
return ast_function_ptr(name, type_ptr(param_types, type_ptr(base_type::boolean())), vector<*ast_node>())
|
|
|
|
|
@@ -533,78 +685,6 @@ fun unify_type(template_type: *tree<symbol>, param_type: *type, new_map: *map<st
|
|
|
|
|
error("TYPE INFERENCE NOT GOOD ENOUGH")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fun find_or_instantiate_function_template(identifier: *tree<symbol>, template_inst: *tree<symbol>, scope: *ast_node, param_types: vector<*type>, template_replacements: map<string, *type>): *ast_node {
|
|
|
|
|
var name = concat_symbol_tree(identifier)
|
|
|
|
|
println(string("trying to instantiate a template function: ") + name)
|
|
|
|
|
var results = scope_lookup(name, scope)
|
|
|
|
|
var real_types = vector<*type>()
|
|
|
|
|
var real_types_deref = vector<type>()
|
|
|
|
|
var had_real_types = false
|
|
|
|
|
if (template_inst) {
|
|
|
|
|
real_types = get_nodes("type", template_inst).map(fun(t: *tree<symbol>): *type return transform_type(t, scope, template_replacements);)
|
|
|
|
|
real_types_deref = real_types.map(fun(t:*type):type return *t;)
|
|
|
|
|
had_real_types = true
|
|
|
|
|
}
|
|
|
|
|
for (var i = 0; i < results.size; i++;) {
|
|
|
|
|
if (is_function_template(results[i])) {
|
|
|
|
|
println(string() + i + " is a template!")
|
|
|
|
|
var template_types = results[i]->function_template.template_types
|
|
|
|
|
var template_type_replacements = results[i]->function_template.template_type_replacements
|
|
|
|
|
if (!had_real_types) {
|
|
|
|
|
// reset the vars, cuz we might be iterating through multiple of them
|
|
|
|
|
real_types = vector<*type>()
|
|
|
|
|
real_types_deref = vector<type>()
|
|
|
|
|
// Template Function Instance Inference time
|
|
|
|
|
var typed_params = get_nodes("typed_parameter", results[i]->function_template.syntax_node).map(fun(t: *tree<symbol>): *tree<symbol> return get_node("type",t);)
|
|
|
|
|
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)
|
|
|
|
|
for (var j = 0; j < typed_params.size; j++;) {
|
|
|
|
|
var t = template_type_replacements[template_types[j]];
|
|
|
|
|
real_types.add(t)
|
|
|
|
|
real_types_deref.add(*t)
|
|
|
|
|
}
|
|
|
|
|
} else if (template_types.size != real_types.size)
|
|
|
|
|
continue
|
|
|
|
|
// check if already instantiated
|
|
|
|
|
var inst_func = null<ast_node>()
|
|
|
|
|
if (results[i]->function_template.instantiated_map.contains_key(real_types_deref)) {
|
|
|
|
|
println("USING CACHED TEMPLATE FUNCITON")
|
|
|
|
|
inst_func = results[i]->function_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_func = second_pass_function(results[i]->function_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
|
|
|
|
|
results[i]->function_template.instantiated_map.set(real_types_deref, inst_func)
|
|
|
|
|
// and fully instantiate it
|
|
|
|
|
inst_func->function.body_statement = transform_statement(get_node("statement", results[i]->function_template.syntax_node), inst_func, template_type_replacements)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (function_satisfies_params(inst_func, param_types))
|
|
|
|
|
return inst_func
|
|
|
|
|
else
|
|
|
|
|
println(string("this paticular ") + name + " did not satisfy params")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
println("FREAK OUT MACHINE")
|
|
|
|
|
return null<ast_node>()
|
|
|
|
|
}
|
|
|
|
|
fun function_satisfies_params(node: *ast_node, param_types: vector<*type>): bool {
|
|
|
|
|
var func_param_types = get_ast_type(node)->parameter_types
|
|
|
|
|
var param_string = string()
|
|
|
|
|
|