Added union and ref = ptr workaround to interpreter (fixing adt matching), allowing test_union and test_adt to pass.

This commit is contained in:
Nathan Braswell
2016-06-28 01:35:54 -07:00
parent 284d8ac9c7
commit 4195da6492
2 changed files with 43 additions and 23 deletions

View File

@@ -941,6 +941,8 @@ obj ast_transformation (Object) {
var first_param_type = get_ast_type(first_param) var first_param_type = get_ast_type(first_param)
if (!first_param_type) if (!first_param_type)
error(node, "Cannot get type from left side of access operation") 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) second_param = transform(node->children[2], first_param_type->type_def, searching_for, template_replacements)
// template member functions // template member functions
// XXX add in template inst if it exists // XXX add in template inst if it exists

View File

@@ -276,18 +276,22 @@ fun do_floating_op<T,U>(op: string, a: T, b: U, ptr_type: *type): value {
if (op == "!=") return raw_to_value(a != b) if (op == "!=") return raw_to_value(a != b)
error(("Invalid op: ") + op) 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") assert(is_variable(to), "trying to store into not variable")
var variable = to.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 // 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") assert(is_pointer(from), "mismatching assignemnt types - from is not pointer")
*(variable.first) cast **void = from.pointer.first *(variable.first) cast **void = from.pointer.first
return; 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?) // TODO - check to make sure that we don't have to cast pre assign (perhaps alwyas send through the cast?)
match (variable.second->base) { 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::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)) if (!is_variable(v))
return v return v
var variable = v.variable var variable = v.variable
if (variable.second->indirection) var var_ptr = variable.first
return value::pointer(make_pair(*(variable.first) cast **void, variable.second)) var var_type = variable.second
match (variable.second->base) { // 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) // 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::adt() return #sizeof<>*/
/*base_type::function() return #sizeof<>*/ /*base_type::function() return #sizeof<>*/
base_type::boolean() return value::boolean(*(variable.first) cast *bool) base_type::boolean() return value::boolean(*(var_ptr) cast *bool)
base_type::character() return value::character(*(variable.first) cast *char) base_type::character() return value::character(*(var_ptr) cast *char)
base_type::ucharacter() return value::ucharacter(*(variable.first) cast *uchar) base_type::ucharacter() return value::ucharacter(*(var_ptr) cast *uchar)
base_type::short_int() return value::short_int(*(variable.first) cast *short) base_type::short_int() return value::short_int(*(var_ptr) cast *short)
base_type::ushort_int() return value::ushort_int(*(variable.first) cast *ushort) base_type::ushort_int() return value::ushort_int(*(var_ptr) cast *ushort)
base_type::integer() return value::integer(*(variable.first) cast *int) base_type::integer() return value::integer(*(var_ptr) cast *int)
base_type::uinteger() return value::uinteger(*(variable.first) cast *uint) base_type::uinteger() return value::uinteger(*(var_ptr) cast *uint)
base_type::long_int() return value::long_int(*(variable.first) cast *long) base_type::long_int() return value::long_int(*(var_ptr) cast *long)
base_type::ulong_int() return value::ulong_int(*(variable.first) cast *ulong) base_type::ulong_int() return value::ulong_int(*(var_ptr) cast *ulong)
base_type::floating() return value::floating(*(variable.first) cast *float) base_type::floating() return value::floating(*(var_ptr) cast *float)
base_type::double_precision() return value::double_precision(*(variable.first) cast *double) base_type::double_precision() return value::double_precision(*(var_ptr) cast *double)
base_type::function() return value::function(*(variable.first) cast *pair<*ast_node,map<*ast_node,value>>) 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()) 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> return #sizeof<*void>
match (t->base) { match (t->base) {
base_type::object() { base_type::object() {
var size = 0 var size: ulong = 0
t->type_def->type_def.variables.for_each(fun(i: *ast_node) size += type_size(i->declaration_statement.identifier->identifier.type);) 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 return size
} }
/*base_type::adt() return #sizeof<>*/ /*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()) error(string("Invalid type for type_size: ") + t->to_string())
} }
fun offset_into_struct(struct_type: *type, ident: *ast_node): ulong { 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 var size: ulong = 0
for (var i = 0; i < struct_type->type_def->type_def.variables.size; i++;) 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) if (struct_type->type_def->type_def.variables[i]->declaration_statement.identifier == ident)
@@ -903,6 +919,7 @@ obj interpreter (Object) {
//HERE //HERE
if (ident_type->indirection == 0 && ident_type->is_function()) if (ident_type->indirection == 0 && ident_type->is_function())
(var_stack->top()[ident].variable.first) cast *pair<*ast_node,map<*ast_node,value>> ->construct() (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) { 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)) 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) { } 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) // always do cast now to make our best effort at assignment (assign into a double from a float, etc)
// unless it's an object // unless it's an object
var from_real = get_real_value(from) 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)) if (is_object_like(from_real))
store_into_variable(to, from_real) store_into_variable(to, from_real)
else else