From 008cc01c7051e0f61766e531339907f924ef2c2c Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Wed, 1 Jun 2016 23:28:32 -0700 Subject: [PATCH] Lambdas and function values starting to work - using the parameters or return value crashes --- stdlib/ast_transformation.krak | 14 ++++++----- stdlib/interpreter.krak | 46 ++++++++++++++++++++++++++++------ 2 files changed, 47 insertions(+), 13 deletions(-) diff --git a/stdlib/ast_transformation.krak b/stdlib/ast_transformation.krak index a080952..76b96a1 100644 --- a/stdlib/ast_transformation.krak +++ b/stdlib/ast_transformation.krak @@ -971,7 +971,7 @@ obj ast_transformation (Object) { var possible_overload_call = find_and_make_any_operator_overload_call(func_name, parameters, scope, template_replacements) if (possible_overload_call) return possible_overload_call - return ast_function_call_ptr(get_builtin_function(func_name, parameter_types), parameters) + return ast_function_call_ptr(get_builtin_function(func_name, parameter_types, node), parameters) } fun find_and_make_any_operator_overload_call(func_name: string, parameters: vector<*ast_node>, scope: *ast_node, template_replacements: map): *ast_node { var parameter_types = parameters.map(fun(param: *ast_node): *type return get_ast_type(param);) @@ -1131,22 +1131,24 @@ fun make_operator_call(func: *char, params: vector<*ast_node>): *ast_node return 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 { +fun get_builtin_function(name: string, param_types: vector<*type>): *ast_node + return get_builtin_function(name, param_types, null>()) +fun get_builtin_function(name: string, param_types: vector<*type>, syntax: *tree): *ast_node { // none of the builtin functions should take in references param_types = param_types.map(fun(t: *type): *type return t->clone_without_ref();) 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>(), false) if (name == "." || name == "->") { if (name == "->" && param_types[0]->indirection == 0) - error(string("drereferencing not a pointer: ") + name) + error(syntax, string("drereferencing not a pointer: ") + name) else if (name == "." && param_types[0]->indirection != 0) - error(string("dot operator on a pointer: ") + name) + error(syntax, string("dot operator on a pointer: ") + name) else return ast_function_ptr(name, type_ptr(param_types, param_types[1]), vector<*ast_node>(), false) } if (name == "[]") { if (param_types[0]->indirection == 0) - error(string("drereferencing not a pointer: ") + name) + error(syntax, string("drereferencing not a pointer: ") + name) else return ast_function_ptr(name, type_ptr(param_types, param_types[0]->clone_with_decreased_indirection()), vector<*ast_node>(), false) } @@ -1154,7 +1156,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_increased_indirection()), vector<*ast_node>(), false) if (name == "\*" && param_types.size == 1) { if (param_types[0]->indirection == 0) - error(string("drereferencing not a pointer: ") + name) + error(syntax, string("drereferencing not a pointer: ") + name) else return ast_function_ptr(name, type_ptr(param_types, param_types[0]->clone_with_decreased_indirection()), vector<*ast_node>(), false) } diff --git a/stdlib/interpreter.krak b/stdlib/interpreter.krak index 72a02fa..ca8de03 100644 --- a/stdlib/interpreter.krak +++ b/stdlib/interpreter.krak @@ -30,7 +30,8 @@ adt value { void_nothing, pointer: pair<*void,*type>, object_like: pair<*void,*type>, - variable: pair<*void,*type> + variable: pair<*void,*type>, + function: pair<*ast_node,map<*ast_node,value>> } adt control_flow { nor, @@ -132,6 +133,7 @@ fun is_void_nothing(it: value): bool { match(it) { value::void_nothing() return fun is_pointer(it: value): bool { match(it) { value::pointer(var) return true; } return false; } fun is_object_like(it: value): bool { match(it) { value::object_like(var) return true; } return false; } fun is_variable(it: value): bool { match(it) { value::variable(var) return true; } return false; } +fun is_function(it: value): bool { match(it) { value::function(var) return true; } return false; } fun print_value(v: ref value) { match (get_real_value(v)) { @@ -150,6 +152,7 @@ fun print_value(v: ref value) { value::pointer(var) println("pointer") value::object_like(var) println("object_like") value::variable(var) println("variable") + value::function(var) println("function") } } fun truthy(v: ref value):bool { @@ -286,7 +289,7 @@ fun store_into_variable(to: value, from: value) { match (variable.second->base) { base_type::object() { assert(is_object_like(from), "mismatching assignemnt types - from is not object"); memmove(variable.first, from.object_like.first, type_size(from.object_like.second)); } base_type::adt() error(string("trying to store into an adt: ") + variable.second->to_string()) - base_type::function() error(string("trying to store into a function: ") + variable.second->to_string()) + base_type::function() { assert(is_function(from), "mismatching assignemnt types - from is not function"); *(variable.first) cast *pair<*ast_node, map<*ast_node,value>> = from.function; } base_type::boolean() { assert(is_boolean(from), "mismatching assignemnt types - from is not boolean"); *(variable.first) cast *bool = from.boolean; } base_type::character() { assert(is_character(from), "mismatching assignemnt types - from is not character"); *(variable.first) cast *char = from.character; } base_type::ucharacter() { assert(is_ucharacter(from), "mismatching assignemnt types - from is not ucharacter"); *(variable.first) cast *uchar = from.ucharacter; } @@ -298,6 +301,7 @@ fun store_into_variable(to: value, from: value) { base_type::ulong_int() { assert(is_ulong_int(from), "mismatching assignemnt types - from is not ulong_int"); *(variable.first) cast *ulong = from.ulong_int; } base_type::floating() { assert(is_floating(from), "mismatching assignemnt types - from is not floating"); *(variable.first) cast *float = from.floating; } base_type::double_precision() { assert(is_double_precision(from), "mismatching assignemnt types - from is not double"); *(variable.first) cast *double = from.double_precision; } + base_type::function() { assert(is_function(from), "mismatching assignemnt types - from is not function"); *(variable.first) cast *pair<*ast_node,map<*ast_node,value>> = from.function; } } } fun get_real_value(v: value): value { @@ -322,6 +326,7 @@ fun get_real_value(v: value): value { base_type::ulong_int() return value::ulong_int(*(variable.first) cast *ulong) base_type::floating() return value::floating(*(variable.first) cast *float) base_type::double_precision() return value::double_precision(*(variable.first) cast *double) + base_type::function() return value::function(*(variable.first) cast *pair<*ast_node,map<*ast_node,value>>) } error(string("Cannot get real value from variable: ") + variable.second->to_string()) } @@ -332,7 +337,10 @@ fun wrap_into_variable(v: value): value { return value::variable(make_pair(v.object_like.first, v.object_like.second)) var variable_type = get_type_from_primitive_value(v) var to_ret = value::variable(make_pair(malloc(type_size(variable_type)), variable_type)) - store_into_variable(to_ret, v) + if (is_function(v)) + (to_ret.variable.first) cast *pair<*ast_node,map<*ast_node,value>> ->copy_construct(&v.function) + else + store_into_variable(to_ret, v) return to_ret } fun get_type_from_primitive_value(v: value): *type { @@ -350,6 +358,7 @@ fun get_type_from_primitive_value(v: value): *type { value::double_precision(data) return type_ptr(base_type::double_precision()) value::pointer(data) return data.second value::void_nothing() return type_ptr(base_type::void_return()) + value::function(data) return data.first->function.type } println("Bad get_type_from_primitive_value!") print_value(v) @@ -446,7 +455,7 @@ fun type_size(t: *type): ulong { return size } /*base_type::adt() return #sizeof<>*/ - /*base_type::function() return #sizeof<>*/ + base_type::function() return #sizeof>> base_type::boolean() return #sizeof base_type::character() return #sizeof base_type::ucharacter() return #sizeof @@ -474,6 +483,8 @@ fun pop_and_free(var_stack: *stack>) { var_stack->pop().for_each(fun(k: *ast_node, v: value) { match(v) { value::variable(backing) { + /*if (backing.second->is_function())*/ + /*(backing.first) cast *pair<*ast_node,map<*ast_node,value>> ->destruct()*/ free(backing.first) } } @@ -561,8 +572,16 @@ obj interpreter (Object) { var func_call_parameters = func_call->function_call.parameters var func_call_func = func_call->function_call.func var new_enclosing_object = value::void_nothing() + var dot_style_method_call = is_dot_style_method_call(func_call) + // test for function value + if (!dot_style_method_call && !is_function(func_call_func)) { + /*error("func_call_func is not a function")*/ + println(string("func_call_func is not a function: ") + get_ast_name(func_call_func)) + func_call_func = get_real_value(interpret(func_call_func, var_stack, enclosing_object, enclosing_func, defer_stack).first).function.first + println(string("calling func we got from interpreting: ") + get_ast_name(func_call_func)) + } // note here also that this is likely not a foolproof method - if (is_dot_style_method_call(func_call)) { + if (dot_style_method_call) { new_enclosing_object = get_real_value(interpret(func_call_func->function_call.parameters[0], var_stack, enclosing_object, enclosing_func, defer_stack).first) // do a dereference if (is_pointer(new_enclosing_object)) @@ -676,6 +695,8 @@ obj interpreter (Object) { new_var_stack.top()[param_ident] = wrap_into_variable(parameters[i]) } else { new_var_stack.top()[param_ident] = value::variable(make_pair(malloc(type_size(param_type)), param_type)) + //HERE + (new_var_stack.top()[param_ident].variable.first) cast *pair<*ast_node,map<*ast_node,value>> ->construct() store_into_variable(new_var_stack.top()[param_ident], get_real_value(parameters[i])) } } @@ -698,12 +719,16 @@ obj interpreter (Object) { } else if (param_type->indirection == 0 && (param_type->is_adt() || (param_type->is_object() && has_method(param_type->type_def, "copy_construct", vector(param_type->clone_with_increased_indirection()))))) { var temp_ident = ast_identifier_ptr(string("temporary_param") + get_id(), param_type, null()) var_stack->top()[temp_ident] = value::variable(make_pair(malloc(type_size(param_type)), param_type)) + //HERE + (var_stack->top()[temp_ident].variable.first) cast *pair<*ast_node,map<*ast_node,value>> ->construct() interpret(ast_statement_ptr(make_method_call(temp_ident, "copy_construct", vector(make_operator_call("&", vector(parameter_sources[i]))))), var_stack, enclosing_object, enclosing_func, ¶m_defer_stack) new_var_stack.top()[param_ident] = var_stack->top()[temp_ident] // note that we destruct the temp version because that's the one in the var_stack param_defer_stack.push(ast_statement_ptr(make_method_call(temp_ident, "destruct", vector<*ast_node>()))) } else { new_var_stack.top()[param_ident] = value::variable(make_pair(malloc(type_size(param_type)), param_type)) + //HERE + (new_var_stack.top()[param_ident].variable.first) cast *pair<*ast_node,map<*ast_node,value>> ->construct() store_into_variable(new_var_stack.top()[param_ident], get_real_value(interpret(parameter_sources[i], var_stack, enclosing_object, enclosing_func, ¶m_defer_stack).first)) } } @@ -727,7 +752,6 @@ obj interpreter (Object) { return to_ret } fun call_built_in_extern(func_name: string, parameters: vector): value { - /*println(string("calling func: ") + func_name)*/ for (var i = 0; i < parameters.size; i++;) parameters[i] = get_real_value(parameters[i]) if (func_name == "printf") { @@ -793,6 +817,9 @@ obj interpreter (Object) { } return value::void_nothing() } + fun interpret_function(function: *ast_node, var_stack: *stack>, enclosing_object: value, enclosing_func: *ast_node, defer_stack: *stack<*ast_node>): pair { + return make_pair(value::function(make_pair(function, map<*ast_node,value>())), control_flow::nor()) + } fun interpret_statement(stmt: *ast_node, var_stack: *stack>, enclosing_object: value, enclosing_func: *ast_node, defer_stack: *stack<*ast_node>): pair { return interpret(stmt->statement.child, var_stack, enclosing_object, enclosing_func, defer_stack) } @@ -898,7 +925,7 @@ obj interpreter (Object) { return make_pair(value::void_nothing(), control_flow::ret()) var return_expression = stmt->return_statement.return_value var return_type = get_ast_type(return_expression) - var to_ret: value + var to_ret.construct(): value if (get_ast_type(enclosing_func)->return_type->is_ref) { to_ret = interpret(return_expression, var_stack, enclosing_object, enclosing_func, defer_stack).first } else if (return_type->indirection == 0 && (return_type->is_adt() || (return_type->is_object() && has_method(return_type->type_def, "copy_construct", vector(return_type->clone_with_increased_indirection()))))) { @@ -914,6 +941,8 @@ obj interpreter (Object) { /*pop_and_free(var_stack)*/ } else { to_ret = value::variable(make_pair(malloc(type_size(return_type)), return_type)) + //HERE + (to_ret.variable.first) cast *pair<*ast_node,map<*ast_node,value>> ->construct() var ret_val = interpret(return_expression, var_stack, enclosing_object, enclosing_func, defer_stack).first store_into_variable(to_ret, get_real_value(ret_val)) } @@ -923,6 +952,8 @@ obj interpreter (Object) { var ident = stmt->declaration_statement.identifier var ident_type = ident->identifier.type var_stack->top()[ident] = value::variable(make_pair(malloc(type_size(ident_type)),ident_type)) + //HERE + (var_stack->top()[ident].variable.first) cast *pair<*ast_node,map<*ast_node,value>> ->construct() if (stmt->declaration_statement.expression) { if (ident_type->indirection == 0 && (ident_type->is_adt() || (ident_type->is_object() && has_method(ident_type->type_def, "copy_construct", vector(get_ast_type(stmt->declaration_statement.expression)->clone_with_increased_indirection()))))) interpret(ast_statement_ptr(make_method_call(ident, "copy_construct", vector(make_operator_call("&", vector(stmt->declaration_statement.expression))))), var_stack, enclosing_object, enclosing_func, defer_stack) @@ -988,6 +1019,7 @@ obj interpreter (Object) { fun interpret(node: *ast_node, var_stack: *stack>, enclosing_object: value, enclosing_func: *ast_node, defer_stack: *stack<*ast_node>): pair { match (*node) { ast_node::function_call(backing) return interpret_function_call(node, var_stack, enclosing_object, enclosing_func, defer_stack) + ast_node::function(backing) return interpret_function(node, var_stack, enclosing_object, enclosing_func, defer_stack) ast_node::statement(backing) return interpret_statement(node, var_stack, enclosing_object, enclosing_func, defer_stack) ast_node::if_statement(backing) return interpret_if_statement(node, var_stack, enclosing_object, enclosing_func, defer_stack) ast_node::while_loop(backing) return interpret_while_loop(node, var_stack, enclosing_object, enclosing_func, defer_stack)