Lambdas and function values starting to work - using the parameters or return value crashes

This commit is contained in:
Nathan Braswell
2016-06-01 23:28:32 -07:00
parent 8cbd2f667f
commit 008cc01c70
2 changed files with 47 additions and 13 deletions

View File

@@ -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<string, *type>): *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<tree<symbol>>())
fun get_builtin_function(name: string, param_types: vector<*type>, syntax: *tree<symbol>): *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)
}

View File

@@ -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<pair<*ast_node,map<*ast_node,value>>>
base_type::boolean() return #sizeof<bool>
base_type::character() return #sizeof<char>
base_type::ucharacter() return #sizeof<uchar>
@@ -474,6 +483,8 @@ fun pop_and_free(var_stack: *stack<map<*ast_node, value>>) {
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<ast_node>())
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, &param_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, &param_defer_stack).first))
}
}
@@ -727,7 +752,6 @@ obj interpreter (Object) {
return to_ret
}
fun call_built_in_extern(func_name: string, parameters: vector<value>): 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<map<*ast_node, value>>, enclosing_object: value, enclosing_func: *ast_node, defer_stack: *stack<*ast_node>): pair<value, control_flow> {
return make_pair(value::function(make_pair(function, map<*ast_node,value>())), control_flow::nor())
}
fun interpret_statement(stmt: *ast_node, var_stack: *stack<map<*ast_node, value>>, enclosing_object: value, enclosing_func: *ast_node, defer_stack: *stack<*ast_node>): pair<value, control_flow> {
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<map<*ast_node, value>>, enclosing_object: value, enclosing_func: *ast_node, defer_stack: *stack<*ast_node>): pair<value, control_flow> {
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)