Now using adt_lower, which also makes the backing deconstruct a reference, which makes sense
This commit is contained in:
@@ -223,7 +223,7 @@ obj c_generator (Object) {
|
||||
|
||||
// add parameters to destructor thingy (for returns)? Or should that be a different pass?
|
||||
var parameter_type = parameter->identifier.type
|
||||
if (!parameter_type->is_ref && parameter_type->indirection == 0 && (parameter_type->is_adt() || (parameter_type->is_object() && has_method(parameter_type->type_def, "destruct", vector<*type>()))))
|
||||
if (!parameter_type->is_ref && parameter_type->indirection == 0 && (parameter_type->is_object() && has_method(parameter_type->type_def, "destruct", vector<*type>())))
|
||||
defer_stack->top().second.push(ast_statement_ptr(make_method_call(parameter, "destruct", vector<*ast_node>())))
|
||||
})
|
||||
if (backing.is_variadic) {
|
||||
@@ -261,119 +261,7 @@ obj c_generator (Object) {
|
||||
function_definitions += generate_from_defer_stack(&defer_stack, -1, enclosing_object, child).one_string()
|
||||
function_definitions += "}\n"
|
||||
} else if (!backing.is_extern) {
|
||||
// adt constructor if no body and not extern
|
||||
// wow. no pass in for no this
|
||||
enclosing_object = get_ast_scope(child)->get(string("~enclosing_scope"))[0]
|
||||
// if this is an option constructor
|
||||
if (enclosing_object->adt_def.options.any_true(fun(opt: *ast_node): bool return opt->identifier.name == backing.name;)) {
|
||||
var option_ident = enclosing_object->adt_def.options.find_first_satisfying(fun(opt: *ast_node): bool return opt->identifier.name == backing.name;)
|
||||
var option_type = option_ident->identifier.type
|
||||
function_definitions += " { \n"
|
||||
var to_ret_ident = ast_identifier_ptr("to_ret", enclosing_object->type_def.self_type, enclosing_object)
|
||||
function_definitions += type_to_c(enclosing_object->adt_def.self_type) + " "+ get_name(to_ret_ident) + ";\n"
|
||||
function_definitions += get_name(to_ret_ident) + ".flag = " + string("enum_opt_") + get_name(option_ident) + ";\n"
|
||||
if (option_type->is_empty_adt_option())
|
||||
function_definitions += "/*no inner data*/\n"
|
||||
else {
|
||||
var param = backing.parameters[0]
|
||||
if (option_type->indirection == 0 && (option_type->is_adt() || (option_type->is_object() && has_method(option_type->type_def, "copy_construct", vector(option_type->clone_with_increased_indirection()))))) {
|
||||
function_definitions += generate(ast_statement_ptr(make_method_call(make_operator_call(".", vector(to_ret_ident, option_ident)), "copy_construct", vector(make_operator_call("&", vector(param))))), null<ast_node>(), null<ast_node>(), &defer_stack, false).one_string()
|
||||
function_definitions += generate_from_defer_stack(&defer_stack, -1, enclosing_object, child).one_string()
|
||||
} else {
|
||||
function_definitions += get_name(to_ret_ident) +".data." + get_name(option_ident) + " = " + get_name(param) + ";\n"
|
||||
}
|
||||
}
|
||||
function_definitions += "return " + get_name(to_ret_ident) + ";\n"
|
||||
function_definitions += "}\n"
|
||||
} else {
|
||||
// this is one of the other functions instead
|
||||
var adt_this = ast_identifier_ptr("this", enclosing_object->type_def.self_type->clone_with_indirection(1), enclosing_object)
|
||||
function_definitions += "{\n"
|
||||
if (backing.name == "operator==") {
|
||||
var param = backing.parameters[0]
|
||||
function_definitions += "/*operator==*/"
|
||||
function_definitions += string("if (this->flag != ") + generate_identifier(param, null<ast_node>(), null<ast_node>()).one_string() + ".flag) return false;\n"
|
||||
enclosing_object->adt_def.options.for_each(fun(option: *ast_node) {
|
||||
var option_type = option->identifier.type
|
||||
function_definitions += string("if (this->flag == ") + string("enum_opt_") + generate_identifier(option, null<ast_node>(), null<ast_node>()).one_string() + ") {\n"
|
||||
if (option_type->is_empty_adt_option()) {
|
||||
function_definitions += "return true;"
|
||||
} else {
|
||||
if (option_type->indirection == 0 && (option_type->is_adt() || (option_type->is_object() && has_method(option_type->type_def, "operator==", vector(option_type))))) {
|
||||
defer_stack.push(make_pair(false, stack<*ast_node>()))
|
||||
var equals_res = generate(ast_statement_ptr(make_method_call(make_operator_call("->", vector(adt_this, option)), "operator==", vector(make_operator_call(".", vector(param, option))))), null<ast_node>(), null<ast_node>(), &defer_stack, false)
|
||||
equals_res.value = string("bool result = ") + equals_res.value + ";\n"
|
||||
equals_res.post += generate_from_defer_stack(&defer_stack, -1, enclosing_object, child).one_string()
|
||||
defer_stack.pop()
|
||||
function_definitions += equals_res.one_string() + "return result;\n"
|
||||
} else if (option_type->is_object()) {
|
||||
// if we are an object but don't define an operator== function (or it is templated)
|
||||
// always return false.
|
||||
function_definitions += "return false;\n"
|
||||
} else {
|
||||
var option_name = generate_identifier(option, null<ast_node>(), null<ast_node>()).one_string()
|
||||
var param_name = generate_identifier(param, null<ast_node>(), null<ast_node>()).one_string()
|
||||
function_definitions += string("return this->data.") + option_name + " == " + param_name + ".data." + option_name + ";\n"
|
||||
}
|
||||
}
|
||||
function_definitions += "}\n"
|
||||
})
|
||||
} else if (backing.name == "operator!=") {
|
||||
var param = backing.parameters[0]
|
||||
function_definitions += "/*operator!=*/"
|
||||
defer_stack.push(make_pair(false, stack<*ast_node>()))
|
||||
var equals_res = generate(ast_statement_ptr(make_method_call(make_operator_call("*", vector(adt_this)), "operator==", vector(param))), null<ast_node>(), null<ast_node>(), &defer_stack, false)
|
||||
equals_res.value = string("bool result = !") + equals_res.value + ";\n"
|
||||
equals_res.post += generate_from_defer_stack(&defer_stack, -1, enclosing_object, child).one_string()
|
||||
defer_stack.pop()
|
||||
function_definitions += equals_res.one_string() + "return result;\n"
|
||||
} else if (backing.name == "construct") {
|
||||
function_definitions += "/*construct*/"
|
||||
function_definitions += "this->flag = -1;\n"
|
||||
function_definitions += "return this;\n"
|
||||
} else if (backing.name == "copy_construct") {
|
||||
var param = backing.parameters[0]
|
||||
function_definitions += "/*copy_construct*/"
|
||||
function_definitions += string("this->flag = ") + generate_identifier(param, null<ast_node>(), null<ast_node>()).one_string() + "->flag;\n"
|
||||
enclosing_object->adt_def.options.for_each(fun(option: *ast_node) {
|
||||
var option_type = option->identifier.type
|
||||
function_definitions += string("if (this->flag == ") + string("enum_opt_") + generate_identifier(option, null<ast_node>(), null<ast_node>()).one_string() + ") {\n"
|
||||
if (option_type->is_empty_adt_option()) {
|
||||
function_definitions += "/*no data to copy*/;"
|
||||
} else {
|
||||
if (option_type->indirection == 0 && (option_type->is_adt() || (option_type->is_object() && has_method(option_type->type_def, "copy_construct", vector(option_type->clone_with_increased_indirection()))))) {
|
||||
// don't really need the defer_stack
|
||||
function_definitions += generate(ast_statement_ptr(make_method_call(make_operator_call("->", vector(adt_this, option)), "copy_construct", vector(make_operator_call("&", vector(make_operator_call("->", vector(param, option))))))), null<ast_node>(), null<ast_node>(), &defer_stack, false).one_string()
|
||||
} else {
|
||||
var option_name = generate_identifier(option, null<ast_node>(), null<ast_node>()).one_string()
|
||||
var param_name = generate_identifier(param, null<ast_node>(), null<ast_node>()).one_string()
|
||||
function_definitions += string("this->data.") + option_name + " = " + param_name + "->data." + option_name + ";\n"
|
||||
}
|
||||
}
|
||||
function_definitions += "}\n"
|
||||
})
|
||||
} else if (backing.name == "operator=") {
|
||||
var param = backing.parameters[0]
|
||||
function_definitions += "/*operator=*/"
|
||||
defer_stack.push(make_pair(false, stack<*ast_node>()))
|
||||
function_definitions += generate(ast_statement_ptr(make_method_call(make_operator_call("*", vector(adt_this)), "destruct", vector<*ast_node>())), null<ast_node>(), null<ast_node>(), &defer_stack, false).one_string()
|
||||
function_definitions += generate(ast_statement_ptr(make_method_call(make_operator_call("*", vector(adt_this)), "copy_construct", vector(make_operator_call("&", vector(param))))), null<ast_node>(), null<ast_node>(), &defer_stack, false).one_string()
|
||||
function_definitions += generate_from_defer_stack(&defer_stack, -1, enclosing_object, child).one_string()
|
||||
defer_stack.pop()
|
||||
} else if (backing.name == "destruct") {
|
||||
function_definitions += "/*destruct*/"
|
||||
enclosing_object->adt_def.options.for_each(fun(option: *ast_node) {
|
||||
var option_type = option->identifier.type
|
||||
function_definitions += string("if (this->flag == ") + string("enum_opt_") + generate_identifier(option, null<ast_node>(), null<ast_node>()).one_string() + ") {\n"
|
||||
if (option_type->indirection == 0 && (option_type->is_adt() || (option_type->is_object() && has_method(option_type->type_def, "destruct", vector<*type>())))) {
|
||||
// don't really need the defer_stack
|
||||
function_definitions += generate(ast_statement_ptr(make_method_call(make_operator_call("->", vector(adt_this, option)), "destruct", vector<*ast_node>())), null<ast_node>(), null<ast_node>(), &defer_stack, false).one_string()
|
||||
}
|
||||
function_definitions += "}\n"
|
||||
})
|
||||
}
|
||||
function_definitions += "}\n"
|
||||
}
|
||||
error("Empty function statement and not extern - no ADTs anymore!")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -432,12 +320,7 @@ obj c_generator (Object) {
|
||||
})
|
||||
}
|
||||
ast_node::adt_def(backing) {
|
||||
type_poset.add_vertex(child)
|
||||
backing.options.for_each(fun(i: *ast_node) {
|
||||
var var_type = get_ast_type(i)
|
||||
if (!var_type->indirection && var_type->type_def)
|
||||
type_poset.add_relationship(child, var_type->type_def)
|
||||
})
|
||||
error("ADT remaining!")
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -464,25 +347,7 @@ obj c_generator (Object) {
|
||||
generate_function_definition(method, vert, false);
|
||||
})
|
||||
} else {
|
||||
// adt
|
||||
var add_to_structs = string()
|
||||
var add_to_enum = string()
|
||||
vert->adt_def.options.for_each(fun(option: *ast_node) {
|
||||
add_to_enum += string("enum_opt_") + get_name(option) + ","
|
||||
if (!option->identifier.type->is_empty_adt_option())
|
||||
add_to_structs += generate_declaration_statement(ast_declaration_statement_ptr(option, null<ast_node>(), false), null<ast_node>(), null<ast_node>(), null<stack<pair<bool,stack<*ast_node>>>>(), false).one_string() + ";\n"
|
||||
})
|
||||
structs += string("enum { ") + add_to_enum + " } flag;\n"
|
||||
structs += string("union { ") + add_to_structs + " } data;\n"
|
||||
// now do methods and generation functions
|
||||
vert->adt_def.option_funcs.for_each(fun(option_func: *ast_node) {
|
||||
// no vert so no this
|
||||
generate_function_definition(option_func, null<ast_node>(), false);
|
||||
})
|
||||
vert->adt_def.regular_funcs.for_each(fun(regular_func: *ast_node) {
|
||||
// want the this this time
|
||||
generate_function_definition(regular_func, vert, false);
|
||||
})
|
||||
error("no adt, but how did we get this far?")
|
||||
}
|
||||
structs += "};\n"
|
||||
})
|
||||
@@ -545,7 +410,7 @@ obj c_generator (Object) {
|
||||
pre_stuff = string("extern ") + pre_stuff
|
||||
var to_ret = code_triple(pre_stuff, string(), string())
|
||||
if (node->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(node->declaration_statement.expression)->clone_with_increased_indirection()))))) {
|
||||
if (ident_type->indirection == 0 && (ident_type->is_object() && has_method(ident_type->type_def, "copy_construct", vector(get_ast_type(node->declaration_statement.expression)->clone_with_increased_indirection())))) {
|
||||
to_ret.pre += ";\n"
|
||||
to_ret += generate(ast_statement_ptr(make_method_call(identifier, "copy_construct", vector(make_operator_call("&", vector(node->declaration_statement.expression))))), enclosing_object, enclosing_func, defer_stack, false)
|
||||
} else {
|
||||
@@ -565,7 +430,8 @@ obj c_generator (Object) {
|
||||
to_ret.pre += ";\n"
|
||||
to_ret += code_triple() + generate(node->declaration_statement.init_method_call, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false)
|
||||
}
|
||||
if (add_to_defer && ident_type->indirection == 0 && (ident_type->is_adt() || (ident_type->is_object() && has_method(ident_type->type_def, "destruct", vector<*type>()))))
|
||||
// reference can happen because some passes generate them (adt_lower right now)
|
||||
if (add_to_defer && !ident_type->is_ref && ident_type->indirection == 0 && (ident_type->is_object() && has_method(ident_type->type_def, "destruct", vector<*type>())))
|
||||
defer_stack->top().second.push(ast_statement_ptr(make_method_call(identifier, "destruct", vector<*ast_node>())))
|
||||
return to_ret
|
||||
}
|
||||
@@ -593,7 +459,8 @@ obj c_generator (Object) {
|
||||
// stick another stack on
|
||||
defer_stack->push(make_pair(true, stack<*ast_node>()))
|
||||
// gotta take off last semicolon
|
||||
var init = generate(node->for_loop.init, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false)
|
||||
/*var init = generate(node->for_loop.init, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false)*/
|
||||
var init = generate(node->for_loop.init, enclosing_object, enclosing_func, defer_stack, false)
|
||||
var cond = generate(node->for_loop.condition, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false)
|
||||
var update = generate(node->for_loop.update, enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false)
|
||||
var do_update_name = string("do_update") + get_id()
|
||||
@@ -645,7 +512,7 @@ obj c_generator (Object) {
|
||||
if ((function_return_type->is_object() || return_value_type->is_object()) && !function_return_type->equality(return_value_type, false))
|
||||
// note the clone with decreased indirection because of the clone with increased indirection above
|
||||
error(ast_to_syntax[node], string("return type does not match: ") + function_return_type->to_string() + ", " + return_value_type->to_string());
|
||||
if (!function_return_type->is_ref && return_value_type->indirection == 0 && (return_value_type->is_adt() || (return_value_type->is_object() && has_method(return_value_type->type_def, "copy_construct", vector(return_value_type->clone_with_indirection(1)))))) {
|
||||
if (!function_return_type->is_ref && return_value_type->indirection == 0 && (return_value_type->is_object() && has_method(return_value_type->type_def, "copy_construct", vector(return_value_type->clone_with_indirection(1))))) {
|
||||
to_ret.pre += generate_statement(ast_statement_ptr(make_method_call(temp_ident, "copy_construct", vector(make_operator_call("&", vector(return_value))))), enclosing_object, enclosing_func, defer_stack).one_string()
|
||||
} else {
|
||||
var refamp = string()
|
||||
@@ -850,11 +717,7 @@ obj c_generator (Object) {
|
||||
// don't propegate enclosing function down right of access
|
||||
// XXX what about enclosing object? should it be the thing on the left?
|
||||
if (func_name == "." || func_name == "->") {
|
||||
// special case right hand side is an adt to access inside of adt
|
||||
var in_between = string()
|
||||
if (get_ast_type(parameters[0])->is_adt())
|
||||
in_between = "data."
|
||||
return code_triple("(") + generate(parameters[0], enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false) + func_name + in_between + generate(parameters[1], null<ast_node>(), null<ast_node>(), null<stack<pair<bool,stack<*ast_node>>>>(), false) + string(")")
|
||||
return code_triple("(") + generate(parameters[0], enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false) + func_name + generate(parameters[1], null<ast_node>(), null<ast_node>(), null<stack<pair<bool,stack<*ast_node>>>>(), false) + string(")")
|
||||
}
|
||||
if (func_name == "[]")
|
||||
return code_triple("(") + generate(parameters[0], enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false) + "[" + generate(parameters[1], enclosing_object, enclosing_func, null<stack<pair<bool,stack<*ast_node>>>>(), false) + string("])")
|
||||
@@ -886,7 +749,7 @@ obj c_generator (Object) {
|
||||
call_string += "&"
|
||||
|
||||
var param_type = get_ast_type(param)
|
||||
if (!in_function_param_type->is_ref && 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_indirection(1)))))) {
|
||||
if (!in_function_param_type->is_ref && param_type->indirection == 0 && (param_type->is_object() && has_method(param_type->type_def, "copy_construct", vector(param_type->clone_with_indirection(1))))) {
|
||||
var temp_ident = ast_identifier_ptr(string("temporary_param")+get_id(), param_type->clone_without_ref(), null<ast_node>())
|
||||
var declaration = ast_declaration_statement_ptr(temp_ident, null<ast_node>(), false)
|
||||
// have to pass false to the declaration generator, so can't do it through generate_statement
|
||||
@@ -899,7 +762,7 @@ obj c_generator (Object) {
|
||||
}
|
||||
var pre_call = string()
|
||||
// temporary returns if we're asked for them or we need them for destruct
|
||||
var needs_temp_for_destruct = func_return_type->indirection == 0 && (func_return_type->is_adt() || (func_return_type->is_object() && has_method(func_return_type->type_def, "destruct", vector<*type>())))
|
||||
var needs_temp_for_destruct = func_return_type->indirection == 0 && (func_return_type->is_object() && has_method(func_return_type->type_def, "destruct", vector<*type>()))
|
||||
if (!func_return_type->is_ref && (needs_temp_for_destruct || (!func_return_type->is_void() && need_variable)) ) {
|
||||
// kind of ugly combo here of
|
||||
var temp_ident = ast_identifier_ptr(string("temporary_return")+get_id(), func_return_type, null<ast_node>())
|
||||
@@ -971,7 +834,7 @@ obj c_generator (Object) {
|
||||
return code_triple("sizeof(") + type_to_c(node->compiler_intrinsic.type_parameters[0]) + ")"
|
||||
} else if (node->compiler_intrinsic.intrinsic == "link") {
|
||||
node->compiler_intrinsic.parameters.for_each(fun(str: string) {
|
||||
linker_string += string("-l") + str + " "
|
||||
linker_string += string("-l") + str + " "
|
||||
})
|
||||
return code_triple()
|
||||
}
|
||||
@@ -1028,7 +891,6 @@ obj c_generator (Object) {
|
||||
base_type::floating() return indirection + string("float")
|
||||
base_type::double_precision() return indirection + string("double")
|
||||
base_type::object() return cify_name(type->type_def->type_def.name)
|
||||
base_type::adt() return type->type_def->adt_def.name
|
||||
base_type::function() {
|
||||
var temp = indirection + string("function_")
|
||||
type->parameter_types.for_each(fun(parameter_type: *type) temp += type_decoration(parameter_type) + "_";)
|
||||
@@ -1058,7 +920,6 @@ obj c_generator (Object) {
|
||||
base_type::floating() return string("float") + indirection
|
||||
base_type::double_precision() return string("double") + indirection
|
||||
base_type::object() return get_name(type->type_def) + indirection
|
||||
base_type::adt() return get_name(type->type_def) + indirection
|
||||
base_type::function() {
|
||||
// maybe disregard indirection in the future?
|
||||
type = type->clone_with_indirection(0,false)
|
||||
@@ -1094,7 +955,7 @@ obj c_generator (Object) {
|
||||
upper->template.instantiated_map.reverse_get(node).for_each(fun(t: ref type) result += string("_") + type_decoration(&t);)
|
||||
}
|
||||
ast_node::adt_def(backing) {
|
||||
result = backing.name
|
||||
error("shouldn't have adt")
|
||||
}
|
||||
ast_node::function(backing) {
|
||||
// be careful, operators like . come through this, but so do adt constructor funcs
|
||||
|
||||
Reference in New Issue
Block a user