From 8a676a1b5ba471503e6c43f82481a1a3bf704cf3 Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Thu, 23 Feb 2017 01:24:22 -0500 Subject: [PATCH] More work. Doesn't compile at this point --- stdlib/ast_transformation.krak | 2 ++ stdlib/function_value_lower.krak | 27 +++++++++++++++++++++++++-- stdlib/pass_common.krak | 17 +++++++++++++++-- 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/stdlib/ast_transformation.krak b/stdlib/ast_transformation.krak index f8c0706..1e37b88 100644 --- a/stdlib/ast_transformation.krak +++ b/stdlib/ast_transformation.krak @@ -797,6 +797,8 @@ obj ast_transformation (Object) { // don't bother with a full transform for parameters with their own function, just get the boolean expression and transform it var parameters = get_nodes("parameter", node).map(fun(child: *tree): *ast_node return transform(get_node("boolean_expression", child), scope, template_replacements);) var parameter_types = parameters.map(fun(param: *ast_node): *type return get_ast_type(param);) + if (parameter_types.any_true(fun(ptype: *type): bool return !ptype;)) + error(node, "One of the parameter types is null!") var func = transform(get_node("unarad", node), scope, search_type::function(parameter_types), template_replacements) // may return an identifier of type object if doing operator() - but the () have been stripped out by importer var func_type = get_ast_type(func) diff --git a/stdlib/function_value_lower.krak b/stdlib/function_value_lower.krak index 6d72676..2e9a1a7 100644 --- a/stdlib/function_value_lower.krak +++ b/stdlib/function_value_lower.krak @@ -3,6 +3,7 @@ import tree:* import vector:* import map:* import util:* +import type:* import string:* import mem:* import io:* @@ -79,19 +80,26 @@ fun function_value_lower(name_ast_map: *map,*ast_node var void_ptr = type_ptr(base_type::void_return(), 1); // this most vexing parse actually causes a compiler segfault as it tries to call the result of type_ptr as a function.... // AND IT STILL DOES EVEN WITH ALL MY CHEKCS + var lambda_type_to_struct_type = map(); //freaking vexing parse moved (function_types_needed_wo_lambdas + function_types_needed_for_lambdas).for_each(fun(t: type) { var cleaned = t.clone() cleaned->is_raw = true var new_type_def_name = t.to_string() + "_function_value_struct" var new_type_def = ast_type_def_ptr(new_type_def_name) - new_type_def->type_def.variables.add(ast_declaration_statement_ptr(ast_identifier_ptr("func", cleaned, new_type_def), null())) - new_type_def->type_def.variables.add(ast_declaration_statement_ptr(ast_identifier_ptr("data", void_ptr, new_type_def), null())) + var func_ident = ast_identifier_ptr("func", cleaned, new_type_def) + add_to_scope("func", func_ident, new_type_def) + var data_ident = ast_identifier_ptr("data", void_ptr, new_type_def) + add_to_scope("data", data_ident, new_type_def) + new_type_def->type_def.variables.add(ast_declaration_statement_ptr(func_ident, null())) + new_type_def->type_def.variables.add(ast_declaration_statement_ptr(data_ident, null())) add_to_scope("~enclosing_scope", name_ast_map->values.first().second, new_type_def) add_to_scope(new_type_def_name, new_type_def, name_ast_map->values.first().second) name_ast_map->values.first().second->translation_unit.children.add(new_type_def) + lambda_type_to_struct_type[t] = type_ptr(new_type_def) }) + var lambda_creation_funcs = map<*ast_node, *ast_node>() // create the closure type for each lambda var closure_id = 0 lambdas.for_each(fun(l: *ast_node) { @@ -106,8 +114,23 @@ fun function_value_lower(name_ast_map: *map,*ast_node add_to_scope(new_type_def_name, new_type_def, name_ast_map->values.first().second) name_ast_map->values.first().second->translation_unit.children.add(new_type_def) } + + var return_type = lambda_type_to_struct_type[*l->function.type] + var creation_type = type_ptr(vector<*type>(), return_type, 0, false, false, true) + lambda_creation_funcs[l] = ast_function_ptr(l->function.name + "_creation", creation_type, vector<*ast_node>(), false); + var body = ast_code_block_ptr() + var ident = ast_identifier_ptr("to_ret", return_type, body) + body->code_block.children.add(ast_declaration_statement_ptr(ident, null())) + body->code_block.children.add(ast_assignment_statement_ptr(access_expression(ident, "func"), l)) + body->code_block.children.add(ast_assignment_statement_ptr(access_expression(ident, "data"), ast_value_ptr(string("0"), type_ptr(base_type::void_return(), 1)))) + lambda_creation_funcs[l]->function.body_statement = body + name_ast_map->values.first().second->translation_unit.children.add(lambda_creation_funcs[l]) + // after we use it's type to look up the new one... + l->function.type->is_raw = true; }) function_value_creation_points.for_each(fun(p: function_parent_block) { + var func_call = ast_function_call_ptr(lambda_creation_funcs[p.function], vector<*ast_node>()) + replace_with_in(p.function, func_call, p.parent) }) } diff --git a/stdlib/pass_common.krak b/stdlib/pass_common.krak index 666ebfa..5a88d7a 100644 --- a/stdlib/pass_common.krak +++ b/stdlib/pass_common.krak @@ -49,9 +49,9 @@ fun is_dot_style_method_call(node: *ast_node): bool { fun function_satisfies_params(node: *ast_node, param_types: vector<*type>): bool { var func_type = get_ast_type(node) var func_param_types = func_type->parameter_types - var param_string = string() - param_types.for_each(fun(t: *type) param_string += t->to_string() + ", ";) if (!func_type->is_variadic && func_param_types.size != param_types.size) { + var param_string = string() + param_types.for_each(fun(t: *type) param_string += t->to_string() + ", ";) /*println(string("type sizes don't match ") + param_types.size + " with needed " + param_string)*/ return false } else if (param_types.size < func_param_types.size) { @@ -70,6 +70,19 @@ fun function_satisfies_params(node: *ast_node, param_types: vector<*type>): bool } return true } +fun access_expression(left: *ast_node, right: *char): *ast_node return access_expression(left, string(right)) +fun access_expression(left: *ast_node, right: ref string): *ast_node { + var ltype = get_ast_type(left) + if (!ltype->is_object()) + error("Trying to generate an access expression and the left side is not an object") + var ident = identifier_lookup(right, ltype->type_def) + if (!ident) + error("Trying to generate an access expression, can't find right: " + right) + + if (ltype->indirection) + return make_operator_call("->", vector(left, ident)) + return make_operator_call(".", vector(left, ident)) +} fun function_lookup(name: string, scope: *ast_node, param_types: vector<*type>): *ast_node { var results = scope_lookup(name, scope) for (var i = 0; i < results.size; i++;) {