From 4195da649228dde1f047a7d1571ec6f4421fc65f Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Tue, 28 Jun 2016 01:35:54 -0700 Subject: [PATCH] Added union and ref = ptr workaround to interpreter (fixing adt matching), allowing test_union and test_adt to pass. --- stdlib/ast_transformation.krak | 2 ++ stdlib/interpreter.krak | 64 ++++++++++++++++++++++------------ 2 files changed, 43 insertions(+), 23 deletions(-) diff --git a/stdlib/ast_transformation.krak b/stdlib/ast_transformation.krak index e46a41f..ce1f65b 100644 --- a/stdlib/ast_transformation.krak +++ b/stdlib/ast_transformation.krak @@ -941,6 +941,8 @@ obj ast_transformation (Object) { var first_param_type = get_ast_type(first_param) if (!first_param_type) error(node, "Cannot get type from left side of access operation") + if (!first_param_type->is_object()) + error(node, "Type from left side of access operation isn't object") second_param = transform(node->children[2], first_param_type->type_def, searching_for, template_replacements) // template member functions // XXX add in template inst if it exists diff --git a/stdlib/interpreter.krak b/stdlib/interpreter.krak index 844f88d..c49f6fd 100644 --- a/stdlib/interpreter.krak +++ b/stdlib/interpreter.krak @@ -276,18 +276,22 @@ fun do_floating_op(op: string, a: T, b: U, ptr_type: *type): value { if (op == "!=") return raw_to_value(a != b) error(("Invalid op: ") + op) } -fun store_into_variable(to: value, from: value) { +// the ref special case is interesting because it also means we have to take in the value by ref +fun store_into_variable(to: ref value, from: value) { assert(is_variable(to), "trying to store into not variable") var variable = to.variable - // check for indirection + // NOTE // we have a special case here - we allow assigning to a ref from a pointer, as this is used in adt_lower - if (variable.second->indirection || (variable.second->is_ref && is_pointer(from))) { + if (variable.second->is_ref && is_pointer(from) && variable.second->clone_with_increased_indirection()->equality(from.pointer.second, false)) { + to.variable.first = from.pointer.first + return; + } + // check for indirection + if (variable.second->indirection) { assert(is_pointer(from), "mismatching assignemnt types - from is not pointer") *(variable.first) cast **void = from.pointer.first return; } - if (variable.second->is_ref && is_pointer(from)) { - } // TODO - check to make sure that we don't have to cast pre assign (perhaps alwyas send through the cast?) 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)); } @@ -310,25 +314,28 @@ fun get_real_value(v: value): value { if (!is_variable(v)) return v var variable = v.variable - if (variable.second->indirection) - return value::pointer(make_pair(*(variable.first) cast **void, variable.second)) - match (variable.second->base) { + var var_ptr = variable.first + var var_type = variable.second + // step through indirection first + if (var_type->indirection) + return value::pointer(make_pair(*(var_ptr) cast **void, var_type)) + match (var_type->base) { // really this could just be make_pair(variable) - base_type::object() return value::object_like(make_pair(variable.first, variable.second)) + base_type::object() return value::object_like(make_pair(var_ptr, var_type)) /*base_type::adt() return #sizeof<>*/ /*base_type::function() return #sizeof<>*/ - base_type::boolean() return value::boolean(*(variable.first) cast *bool) - base_type::character() return value::character(*(variable.first) cast *char) - base_type::ucharacter() return value::ucharacter(*(variable.first) cast *uchar) - base_type::short_int() return value::short_int(*(variable.first) cast *short) - base_type::ushort_int() return value::ushort_int(*(variable.first) cast *ushort) - base_type::integer() return value::integer(*(variable.first) cast *int) - base_type::uinteger() return value::uinteger(*(variable.first) cast *uint) - base_type::long_int() return value::long_int(*(variable.first) cast *long) - 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>>) + base_type::boolean() return value::boolean(*(var_ptr) cast *bool) + base_type::character() return value::character(*(var_ptr) cast *char) + base_type::ucharacter() return value::ucharacter(*(var_ptr) cast *uchar) + base_type::short_int() return value::short_int(*(var_ptr) cast *short) + base_type::ushort_int() return value::ushort_int(*(var_ptr) cast *ushort) + base_type::integer() return value::integer(*(var_ptr) cast *int) + base_type::uinteger() return value::uinteger(*(var_ptr) cast *uint) + base_type::long_int() return value::long_int(*(var_ptr) cast *long) + base_type::ulong_int() return value::ulong_int(*(var_ptr) cast *ulong) + base_type::floating() return value::floating(*(var_ptr) cast *float) + base_type::double_precision() return value::double_precision(*(var_ptr) cast *double) + base_type::function() return value::function(*(var_ptr) cast *pair<*ast_node,map<*ast_node,value>>) } error(string("Cannot get real value from variable: ") + variable.second->to_string()) } @@ -452,8 +459,15 @@ fun type_size(t: *type): ulong { return #sizeof<*void> match (t->base) { base_type::object() { - var size = 0 - t->type_def->type_def.variables.for_each(fun(i: *ast_node) size += type_size(i->declaration_statement.identifier->identifier.type);) + var size: ulong = 0 + t->type_def->type_def.variables.for_each(fun(i: *ast_node) { + var individual_size = type_size(i->declaration_statement.identifier->identifier.type) + if (t->type_def->type_def.is_union) { + size = max(size, individual_size) + } else { + size += individual_size + } + }) return size } /*base_type::adt() return #sizeof<>*/ @@ -473,6 +487,8 @@ fun type_size(t: *type): ulong { error(string("Invalid type for type_size: ") + t->to_string()) } fun offset_into_struct(struct_type: *type, ident: *ast_node): ulong { + if (struct_type->type_def->type_def.is_union) + return 0 var size: ulong = 0 for (var i = 0; i < struct_type->type_def->type_def.variables.size; i++;) if (struct_type->type_def->type_def.variables[i]->declaration_statement.identifier == ident) @@ -903,6 +919,7 @@ obj interpreter (Object) { //HERE if (ident_type->indirection == 0 && ident_type->is_function()) (var_stack->top()[ident].variable.first) cast *pair<*ast_node,map<*ast_node,value>> ->construct() + // NOTE: store_into_variable takes to in as a ref because it might change it in the special case ref = ptr if (stmt->declaration_statement.expression) { store_into_variable(var_stack->top()[ident], get_real_value(interpret(stmt->declaration_statement.expression, var_stack, enclosing_object, enclosing_func).first)) } else if (stmt->declaration_statement.init_method_call) { @@ -917,6 +934,7 @@ obj interpreter (Object) { // always do cast now to make our best effort at assignment (assign into a double from a float, etc) // unless it's an object var from_real = get_real_value(from) + // NOTE: store_into_variable takes to in as a ref because it might change it in the special case ref = ptr if (is_object_like(from_real)) store_into_variable(to, from_real) else