diff --git a/kraken.krak b/kraken.krak index b818370..cffec54 100644 --- a/kraken.krak +++ b/kraken.krak @@ -9,7 +9,7 @@ import serialize:* import interpreter:* import os:* import ast_transformation:* -/*import adt_lower:**/ +import adt_lower:* import defer_lower:* import c_line_control:* import c_generator:* @@ -100,8 +100,8 @@ fun main(argc: int, argv: **char):int { var importer.construct(parsers, ast_pass, vector(string(), base_dir + "/stdlib/")): importer importer.import(kraken_file_name) // Passes - /*printlnerr("Lowering ADTs")*/ - /*adt_lower(&importer.name_ast_map, &importer.ast_pass.ast_to_syntax)*/ + printlnerr("Lowering ADTs") + adt_lower(&importer.name_ast_map, &importer.ast_pass.ast_to_syntax) printlnerr("Lowering Defer") defer_lower(&importer.name_ast_map, &importer.ast_pass.ast_to_syntax) if (interpret_instead) { diff --git a/stdlib/adt_lower.krak b/stdlib/adt_lower.krak index 386935e..5239365 100644 --- a/stdlib/adt_lower.krak +++ b/stdlib/adt_lower.krak @@ -12,22 +12,199 @@ import ast_transformation:* import pass_common:* fun adt_lower(name_ast_map: *map,*ast_node>>, ast_to_syntax: *map<*ast_node, *tree>) { + var type_def_option_map = map<*ast_node, vector<*ast_node>>() name_ast_map->for_each(fun(name: string, syntax_ast_pair: pair<*tree,*ast_node>) { var helper_before = fun(node: *ast_node, parent_chain: *stack<*ast_node>) { match(*node) { ast_node::adt_def(backing) { - println(backing.name + ": entered!") + /*println(backing.name + ": transforming!")*/ + type_def_option_map[node] = vector<*ast_node>() + var replacement = ast_type_def_ptr(backing.name, false); + // we're going to be replacing adt_def in the same ptr, so this works + replacement->type_def.self_type = node->adt_def.self_type + var replacement_this = make_this_noncached(replacement) + var option_union = ast_type_def_ptr(backing.name + "_union", true); + node->adt_def.options.for_each(fun(opt: *ast_node) { + // want to keep them around + /*if (opt->identifier.type->is_empty_adt_option())*/ + /*opt->identifier.type = type_ptr(base_type::character())*/ + if (!opt->identifier.type->is_empty_adt_option()) + option_union->type_def.variables.add(ast_declaration_statement_ptr(opt, null(), false)) + type_def_option_map[node].add(opt) + }) + var option_union_type = type_ptr(option_union) + option_union->type_def.self_type = option_union_type + var option_union_ident = ast_identifier_ptr(string("data"), option_union_type, replacement) + replacement->type_def.variables.add(ast_declaration_statement_ptr(option_union_ident, null(), false)) + add_to_scope("data", option_union_ident, replacement) + var flag = ast_identifier_ptr(string("flag"), type_ptr(base_type::integer()), replacement) + replacement->type_def.variables.add(ast_declaration_statement_ptr(flag, null(), false)) + add_to_scope("flag", flag, replacement) + add_before_in(option_union, node, parent_chain) + var enclosing_scope = node->adt_def.scope[string("~enclosing_scope")][0] + var idx = 0 + node->adt_def.option_funcs.for_each(fun(func: *ast_node) { + var adt_type = replacement->type_def.self_type + var block = ast_code_block_ptr() + func->function.body_statement = ast_statement_ptr(block) + var to_ret = ast_identifier_ptr(string("to_ret"), adt_type, block) + block->code_block.children.add(ast_statement_ptr(ast_declaration_statement_ptr(to_ret, null(), false))) + + var value = ast_value_ptr(to_string(idx), type_ptr(base_type::integer())) + block->code_block.children.add(ast_statement_ptr(ast_assignment_statement_ptr(make_operator_call(".", vector(to_ret, flag)), value))) + /*var opt = option_union->type_def.variables[idx]->declaration_statement.identifier*/ + var opt = type_def_option_map[node][idx] + var lvalue = make_operator_call(".", vector(make_operator_call(".", vector(to_ret, option_union_ident)), opt)) + if (func->function.parameters.size) { + // do copy_construct if it should + block->code_block.children.add(ast_statement_ptr(assign_or_copy_construct_statement(lvalue, func->function.parameters[0]))) + } + /*} else {*/ + /*// init our placeholders with 0 for equality, etc*/ + /*block->code_block.children.add(ast_statement_ptr(ast_assignment_statement_ptr(lvalue, ast_value_ptr(string("0"), type_ptr(base_type::character())))))*/ + /*}*/ + block->code_block.children.add(ast_statement_ptr(ast_return_statement_ptr(to_ret))) + add_before_in(func, node, parent_chain) + add_to_scope(func->function.name, func, enclosing_scope) + add_to_scope("~enclosing_scope", enclosing_scope, func) + idx++ + }) + node->adt_def.regular_funcs.for_each(fun(func: *ast_node) { + var block = ast_code_block_ptr() + func->function.body_statement = ast_statement_ptr(block) + if (func->function.name == "operator==") { + var other = func->function.parameters[0] + var if_stmt = ast_if_statement_ptr(make_operator_call("!=", vector(make_operator_call("->", vector(replacement_this, flag)), make_operator_call(".", vector(other, flag))))) + if_stmt->if_statement.then_part = ast_statement_ptr(ast_return_statement_ptr(ast_value_ptr(string("false"), type_ptr(base_type::boolean())))) + block->code_block.children.add(if_stmt) + + /*for (var i = 0; i < option_union->type_def.variables.size; i++;) {*/ + for (var i = 0; i < type_def_option_map[node].size; i++;) { + if (get_ast_type(type_def_option_map[node][i])->is_empty_adt_option()) + continue + var if_stmt_inner = ast_if_statement_ptr(make_operator_call("==", vector(make_operator_call("->", vector(replacement_this, flag)), ast_value_ptr(to_string(i), type_ptr(base_type::integer()))))) + /*var option = option_union->type_def.variables[i]->declaration_statement.identifier*/ + var option = type_def_option_map[node][i] + var our_option = make_operator_call(".", vector(make_operator_call("->", vector(replacement_this, option_union_ident)), option)) + var their_option = make_operator_call(".", vector(make_operator_call(".", vector(other, option_union_ident)), option)) + if_stmt_inner->if_statement.then_part = ast_statement_ptr(ast_return_statement_ptr(possible_object_equality(our_option, their_option))) + block->code_block.children.add(if_stmt_inner) + } + block->code_block.children.add(ast_statement_ptr(ast_return_statement_ptr(ast_value_ptr(string("true"), type_ptr(base_type::boolean()))))) + } else if (func->function.name == "operator!=") { + var other = func->function.parameters[0] + block->code_block.children.add(ast_statement_ptr(ast_return_statement_ptr(make_operator_call("!", vector(make_method_call(replacement_this, "operator==", vector(other))))))) + } else if (func->function.name == "construct") { + var value = ast_value_ptr(string("-1"), type_ptr(base_type::integer())) + block->code_block.children.add(ast_statement_ptr(ast_assignment_statement_ptr(make_operator_call("->", vector(replacement_this, flag)), value))) + block->code_block.children.add(ast_statement_ptr(ast_return_statement_ptr(replacement_this))) + } else if (func->function.name == "copy_construct") { + var other = func->function.parameters[0] + block->code_block.children.add(ast_statement_ptr(ast_assignment_statement_ptr(make_operator_call("->", vector(replacement_this, flag)), make_operator_call("->", vector(other, flag))))) + /*for (var i = 0; i < option_union->type_def.variables.size; i++;) {*/ + for (var i = 0; i < type_def_option_map[node].size; i++;) { + if (get_ast_type(type_def_option_map[node][i])->is_empty_adt_option()) + continue + var if_stmt_inner = ast_if_statement_ptr(make_operator_call("==", vector(make_operator_call("->", vector(replacement_this, flag)), ast_value_ptr(to_string(i), type_ptr(base_type::integer()))))) + /*var option = option_union->type_def.variables[i]->declaration_statement.identifier*/ + var option = type_def_option_map[node][i] + var our_option = make_operator_call(".", vector(make_operator_call("->", vector(replacement_this, option_union_ident)), option)) + var their_option = make_operator_call(".", vector(make_operator_call("->", vector(other, option_union_ident)), option)) + if_stmt_inner->if_statement.then_part = ast_statement_ptr(assign_or_copy_construct_statement(our_option, their_option)) + block->code_block.children.add(if_stmt_inner) + } + } else if (func->function.name == "operator=") { + var other = func->function.parameters[0] + block->code_block.children.add(ast_statement_ptr(make_method_call(replacement_this, "destruct", vector<*ast_node>()))) + block->code_block.children.add(ast_statement_ptr(make_method_call(replacement_this, "copy_construct", vector(make_operator_call("&", vector(other)))))) + } else if (func->function.name == "destruct") { + for (var i = 0; i < type_def_option_map[node].size; i++;) { + var option = type_def_option_map[node][i] + var option_type = get_ast_type(option) + if (option_type->is_empty_adt_option()) + continue + if (option_type->indirection == 0 && option_type->is_object() && has_method(option_type->type_def, "destruct", vector<*type>())) { + var if_stmt_inner = ast_if_statement_ptr(make_operator_call("==", vector(make_operator_call("->", vector(replacement_this, flag)), ast_value_ptr(to_string(i), type_ptr(base_type::integer()))))) + var our_option = make_operator_call(".", vector(make_operator_call("->", vector(replacement_this, option_union_ident)), option)) + if_stmt_inner->if_statement.then_part = ast_statement_ptr(make_method_call(our_option, "destruct", vector<*ast_node>())) + block->code_block.children.add(if_stmt_inner) + } + } + } else error("impossible adt method") + replacement->type_def.methods.add(func) + add_to_scope(func->function.name, func, replacement) + add_to_scope("~enclosing_scope", replacement, func) + }) + add_to_scope("~enclosing_scope", enclosing_scope, option_union) + add_to_scope("~enclosing_scope", enclosing_scope, replacement) + *node = *replacement } } } - var helper_after = fun(node: *ast_node, parent_chain: *stack<*ast_node>) { + run_on_tree(helper_before, empty_pass_half, syntax_ast_pair.second) + }) + name_ast_map->for_each(fun(name: string, syntax_ast_pair: pair<*tree,*ast_node>) { + var second_helper = fun(node: *ast_node, parent_chain: *stack<*ast_node>) { match(*node) { - ast_node::adt_def(backing) { - println(backing.name + ": exited!") + ast_node::match_statement(backing) { + /*println("Match statement!")*/ + var block = ast_code_block_ptr() + var value = backing.value + /*var holder = ast_identifier_ptr(string("holder"), get_ast_type(value), block)*/ + var holder = ast_identifier_ptr(string("holder"), get_ast_type(value)->clone_with_increased_indirection(), block) + block->code_block.children.add(ast_statement_ptr(ast_declaration_statement_ptr(holder, null(), false))) + // dirty hack + var if_hack = ast_if_statement_ptr(ast_assignment_statement_ptr(holder, make_operator_call("&", vector(value)))) + block->code_block.children.add(if_hack) + var if_block = ast_code_block_ptr() + if_hack->if_statement.then_part = if_block + /*block->code_block.children.add(ast_statement_ptr(ast_declaration_statement_ptr(holder, make_operator_call("&", vector(value)), false)))*/ + backing.cases.for_each(fun(case_stmt: *ast_node) { + var option = case_stmt->case_statement.option + /*println(string("case: ") + get_ast_name(option))*/ + var flag = get_from_scope(get_ast_type(value)->type_def, "flag") + var data = get_from_scope(get_ast_type(value)->type_def, "data") + var option_num = -7 + if (!type_def_option_map.contains_key(get_ast_type(value)->type_def)) + error("trying to match on non-adt") + for (var i = 0; i < type_def_option_map[get_ast_type(value)->type_def].size; i++;) + if (type_def_option_map[get_ast_type(value)->type_def][i] == option) + option_num = i; + /*var condition = make_operator_call("==", vector(make_operator_call(".", vector(holder, flag)), ast_value_ptr(to_string(option_num), type_ptr(base_type::integer()))))*/ + var condition = make_operator_call("==", vector(make_operator_call("->", vector(holder, flag)), ast_value_ptr(to_string(option_num), type_ptr(base_type::integer())))) + var if_stmt = ast_if_statement_ptr(condition) + var inner_block = ast_code_block_ptr() + var unpack_ident = case_stmt->case_statement.unpack_ident + if (unpack_ident) { + /*var get_option = make_operator_call(".", vector(make_operator_call(".", vector(holder, data)), option))*/ + var get_option = make_operator_call(".", vector(make_operator_call("->", vector(holder, data)), option)) + get_option = make_operator_call("&", vector(get_option)) + unpack_ident->identifier.type = unpack_ident->identifier.type->clone_with_ref() + inner_block->code_block.children.add(ast_statement_ptr(ast_declaration_statement_ptr(unpack_ident, get_option, false))) + } + inner_block->code_block.children.add(case_stmt->case_statement.statement) + if_stmt->if_statement.then_part = inner_block + if_block->code_block.children.add(if_stmt) + }) + *node = *block + } + ast_node::function_call(backing) { + if (is_function(backing.func) && (backing.func->function.name == "." || backing.func->function.name == "->")) { + var left_type = get_ast_type(backing.parameters[0]) + if (left_type->is_object() && is_identifier(backing.parameters[1])) { + for (var i = 0; i < left_type->type_def->type_def.variables.size; i++;) + if (left_type->type_def->type_def.variables[i]->declaration_statement.identifier == backing.parameters[1]) + return; + /*println(backing.parameters[1]->identifier.name + " getting, adt . or -> call!")*/ + var object = node->function_call.parameters[0] + node->function_call.parameters[0] = make_operator_call(backing.func->function.name, vector(object, get_from_scope(left_type->type_def, "data"))) + node->function_call.func = get_builtin_function(".", vector(get_ast_type(get_from_scope(left_type->type_def, "data")), get_ast_type(backing.parameters[1]))) + } + } } } } - run_on_tree(helper_before, helper_after, syntax_ast_pair.second) + run_on_tree(second_helper, empty_pass_half, syntax_ast_pair.second) }) } diff --git a/stdlib/ast_transformation.krak b/stdlib/ast_transformation.krak index 693e786..951d820 100644 --- a/stdlib/ast_transformation.krak +++ b/stdlib/ast_transformation.krak @@ -983,7 +983,7 @@ obj ast_transformation (Object) { 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);) var possible_overload = null() - if ((parameter_types[0]->is_adt() || parameter_types[0]->is_object()) && parameter_types[0]->indirection == 0) { + if (parameter_types[0]->is_object() && parameter_types[0]->indirection == 0) { possible_overload = function_lookup(string("operator")+func_name, parameter_types.first()->type_def, parameter_types.slice(1,-1)) if (!possible_overload) { var inherited_replacements = map() @@ -1112,6 +1112,10 @@ obj ast_transformation (Object) { return fitting_functions.max(fun(a: pair<*ast_node, int>, b: pair<*ast_node, int>): bool return a.second < b.second;).first } } +fun get_from_scope(node: *ast_node, member: *char): *ast_node + return get_from_scope(node, string(member)) +fun get_from_scope(node: *ast_node, member: string): *ast_node + return get_ast_scope(node)->get(member).first() fun has_method(object: *ast_node, name: *char, parameter_types: vector<*type>): bool return has_method(object, string(name), parameter_types); fun has_method(object: *ast_node, name: string, parameter_types: vector<*type>): bool { /*println("HAS METHOD:")*/ @@ -1131,13 +1135,18 @@ fun make_method_call(object_ident: *ast_node, name: string, parameters: vector<* } fun make_method_call(object_ident: *ast_node, method: *ast_node, parameters: vector<*ast_node>): *ast_node { /*println("MAKE METHOD CALL IN:")*/ - var method_access = ast_function_call_ptr(get_builtin_function(string("."), vector(get_ast_type(object_ident), get_ast_type(method))), vector(object_ident, method)) + var access_op = "." + if (get_ast_type(object_ident)->indirection) + access_op = "->" + var method_access = ast_function_call_ptr(get_builtin_function(string(access_op), vector(get_ast_type(object_ident), get_ast_type(method))), vector(object_ident, method)) return ast_function_call_ptr(method_access, parameters) } fun make_operator_call(func: *char, params: vector<*ast_node>): *ast_node return make_operator_call(string(func), params); 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: *char, param_types: vector<*type>): *ast_node + return get_builtin_function(string(name), param_types, null>()) 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 { diff --git a/stdlib/c_generator.krak b/stdlib/c_generator.krak index b769faa..d959f28 100644 --- a/stdlib/c_generator.krak +++ b/stdlib/c_generator.krak @@ -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(), null(), &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(), null()).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(), null()).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(), null(), &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(), null()).one_string() - var param_name = generate_identifier(param, null(), null()).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(), null(), &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(), null()).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(), null()).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(), null(), &defer_stack, false).one_string() - } else { - var option_name = generate_identifier(option, null(), null()).one_string() - var param_name = generate_identifier(param, null(), null()).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(), null(), &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(), null(), &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(), null()).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(), null(), &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(), false), null(), null(), null>>>(), 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(), 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>>>(), 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>>>(), false) + /*var init = generate(node->for_loop.init, enclosing_object, enclosing_func, null>>>(), 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>>>(), false) var update = generate(node->for_loop.update, enclosing_object, enclosing_func, null>>>(), 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>>>(), false) + func_name + in_between + generate(parameters[1], null(), null(), null>>>(), false) + string(")") + return code_triple("(") + generate(parameters[0], enclosing_object, enclosing_func, null>>>(), false) + func_name + generate(parameters[1], null(), null(), null>>>(), false) + string(")") } if (func_name == "[]") return code_triple("(") + generate(parameters[0], enclosing_object, enclosing_func, null>>>(), false) + "[" + generate(parameters[1], enclosing_object, enclosing_func, null>>>(), 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()) var declaration = ast_declaration_statement_ptr(temp_ident, null(), 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()) @@ -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 diff --git a/stdlib/c_line_control.krak b/stdlib/c_line_control.krak index e9210a1..201086f 100644 --- a/stdlib/c_line_control.krak +++ b/stdlib/c_line_control.krak @@ -20,7 +20,6 @@ fun get_line(node: *tree, name: string): *ast_node { fun c_line_control(name_ast_map: *map,*ast_node>>, ast_to_syntax: *map<*ast_node, *tree>) { var first = true name_ast_map->for_each(fun(name: string, syntax_ast_pair: pair<*tree,*ast_node>) { - var helper_after = fun(node: *ast_node, parent_chain: *stack<*ast_node>) {} var helper = fun(node: *ast_node, parent_chain: *stack<*ast_node>) { match(*node) { ast_node::statement(backing) { @@ -32,7 +31,7 @@ fun c_line_control(name_ast_map: *map,*ast_node>>, as } } if (first) - run_on_tree(helper, helper_after, syntax_ast_pair.second) + run_on_tree(helper, empty_pass_half, syntax_ast_pair.second) first = false }) } diff --git a/stdlib/interpreter.krak b/stdlib/interpreter.krak index 8473cbe..1e0922b 100644 --- a/stdlib/interpreter.krak +++ b/stdlib/interpreter.krak @@ -288,7 +288,6 @@ fun store_into_variable(to: value, from: value) { // 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)); } - base_type::adt() error(string("trying to store into an adt: ") + 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; } @@ -493,7 +492,7 @@ fun pop_and_free(var_stack: *stack>) { obj interpreter (Object) { var ast_to_syntax: map<*ast_node, *tree> - var name_ast_map: map,*ast_node>> + var name_ast_map: map,*ast_node>> var globals: map<*ast_node, value> var id_counter: int fun get_id(): string return to_string(id_counter++); @@ -615,7 +614,7 @@ obj interpreter (Object) { var parameters = vector() var parameter_sources = vector<*ast_node>() // if we don't have to copy_construct params (is an operator, or has no object params) - if (func_name == "&" || !func_call_parameters.any_true(fun(p: *ast_node): bool return get_ast_type(p)->is_object_like() && get_ast_type(p)->indirection == 0;)) { + if (func_name == "&" || !func_call_parameters.any_true(fun(p: *ast_node): bool return get_ast_type(p)->is_object() && get_ast_type(p)->indirection == 0;)) { parameters = func_call_parameters.map(fun(p: *ast_node): value return interpret(p, var_stack, enclosing_object, enclosing_func, defer_stack).first;) if ( parameters.size == 2 && (func_name == "+" || func_name == "-" || func_name == "*" || func_name == "/" || func_name == "<" || func_name == ">" || func_name == "<=" || func_name == ">=" @@ -694,7 +693,7 @@ obj interpreter (Object) { else 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)) + 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])) @@ -716,17 +715,17 @@ obj interpreter (Object) { new_var_stack.top()[param_ident] = param else new_var_stack.top()[param_ident] = wrap_into_variable(param) - } 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()))))) { + } else if (param_type->indirection == 0 && (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)) + 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] + 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)) + 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)) @@ -744,7 +743,7 @@ obj interpreter (Object) { pop_and_free(var_stack) } var return_type = func->function.type->return_type - if (!return_type->is_ref && return_type->indirection == 0 && (return_type->is_adt() || (return_type->is_object() && has_method(return_type->type_def, "destruct", vector<*type>())))) { + if (!return_type->is_ref && return_type->indirection == 0 && (return_type->is_object() && has_method(return_type->type_def, "destruct", vector<*type>()))) { var temp_ident = ast_identifier_ptr(string("temporary_return_to_be_destructed") + get_id(), return_type, null()) var_stack->top()[temp_ident] = value::variable(make_pair(to_ret.object_like.first, to_ret.object_like.second)) defer_stack->push(ast_statement_ptr(make_method_call(temp_ident, "destruct", vector<*ast_node>()))) @@ -829,7 +828,7 @@ obj interpreter (Object) { fun interpret_if_statement(if_stmt: *ast_node, var_stack: *stack>, enclosing_object: value, enclosing_func: *ast_node, defer_stack: *stack<*ast_node>): pair { var_stack->push(map<*ast_node,value>()) var inner_defer_stack = stack<*ast_node>() - var value_from_inside = make_pair(value::void_nothing(), control_flow::nor()) + var value_from_inside = make_pair(value::void_nothing(), control_flow::nor()) if (truthy(interpret(if_stmt->if_statement.condition, var_stack, enclosing_object, enclosing_func, &inner_defer_stack).first)) { value_from_inside = interpret(if_stmt->if_statement.then_part, var_stack, enclosing_object, enclosing_func, &inner_defer_stack) } else if (if_stmt->if_statement.else_part) { @@ -842,7 +841,7 @@ obj interpreter (Object) { fun interpret_while_loop(while_loop: *ast_node, var_stack: *stack>, enclosing_object: value, enclosing_func: *ast_node, defer_stack: *stack<*ast_node>): pair { var_stack->push(map<*ast_node,value>()) var inner_defer_stack = stack<*ast_node>() - var value_from_inside = make_pair(value::void_nothing(), control_flow::nor()) + var value_from_inside = make_pair(value::void_nothing(), control_flow::nor()) var going = true while (going && truthy(interpret(while_loop->while_loop.condition, var_stack, enclosing_object, enclosing_func, &inner_defer_stack).first)) { value_from_inside = interpret(while_loop->while_loop.statement, var_stack, enclosing_object, enclosing_func, &inner_defer_stack) @@ -851,7 +850,7 @@ obj interpreter (Object) { if (value_from_inside.second == control_flow::ret() || value_from_inside.second == control_flow::bre()) going = false if (value_from_inside.second == control_flow::bre() || value_from_inside.second == control_flow::con()) - value_from_inside = make_pair(value::void_nothing(), control_flow::nor()) + value_from_inside = make_pair(value::void_nothing(), control_flow::nor()) } interpret_from_defer_stack(&inner_defer_stack, var_stack, value::void_nothing(), enclosing_func) pop_and_free(var_stack) @@ -860,7 +859,7 @@ obj interpreter (Object) { fun interpret_for_loop(for_loop: *ast_node, var_stack: *stack>, enclosing_object: value, enclosing_func: *ast_node): pair { var defer_stack = stack<*ast_node>() var_stack->push(map<*ast_node,value>()) - var value_from_inside = make_pair(value::void_nothing(), control_flow::nor()) + var value_from_inside = make_pair(value::void_nothing(), control_flow::nor()) var going = true interpret(for_loop->for_loop.init, var_stack, enclosing_object, enclosing_func, &defer_stack) while (going && truthy(interpret(for_loop->for_loop.condition, var_stack, enclosing_object, enclosing_func, &defer_stack).first)) { @@ -868,7 +867,7 @@ obj interpreter (Object) { if (value_from_inside.second == control_flow::ret() || value_from_inside.second == control_flow::bre()) going = false if (value_from_inside.second == control_flow::bre() || value_from_inside.second == control_flow::con()) - value_from_inside = make_pair(value::void_nothing(), control_flow::nor()) + value_from_inside = make_pair(value::void_nothing(), control_flow::nor()) // only run update if we're not breaking or continuing if (going) @@ -931,11 +930,11 @@ obj interpreter (Object) { 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()))))) { + } else if (return_type->indirection == 0 && (return_type->is_object() && has_method(return_type->type_def, "copy_construct", vector(return_type->clone_with_increased_indirection())))) { var_stack->push(map<*ast_node,value>()) var inner_defer_stack = stack<*ast_node>() var temp_ident = ast_identifier_ptr(string("temporary_return"), return_type, null()) - var_stack->top()[temp_ident] = value::variable(make_pair(malloc(type_size(return_type)), return_type)) + var_stack->top()[temp_ident] = value::variable(make_pair(malloc(type_size(return_type)), return_type)) interpret(ast_statement_ptr(make_method_call(temp_ident, "copy_construct", vector(make_operator_call("&", vector(return_expression))))), var_stack, enclosing_object, enclosing_func, &inner_defer_stack) to_ret = var_stack->top()[temp_ident] interpret_from_defer_stack(&inner_defer_stack, var_stack, enclosing_object, enclosing_func) @@ -943,7 +942,7 @@ obj interpreter (Object) { var_stack->pop() /*pop_and_free(var_stack)*/ } else { - to_ret = value::variable(make_pair(malloc(type_size(return_type)), return_type)) + 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 @@ -954,11 +953,11 @@ obj interpreter (Object) { fun interpret_declaration_statement(stmt: *ast_node, var_stack: *stack>, enclosing_object: value, enclosing_func: *ast_node, defer_stack: *stack<*ast_node>): pair { 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)) + 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()))))) + if (ident_type->indirection == 0 && (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) else store_into_variable(var_stack->top()[ident], get_real_value(interpret(stmt->declaration_statement.expression, var_stack, enclosing_object, enclosing_func, defer_stack).first)) @@ -966,7 +965,7 @@ obj interpreter (Object) { interpret(stmt->declaration_statement.init_method_call, var_stack, enclosing_object, enclosing_func, defer_stack) } // defering destructs - if (ident_type->indirection == 0 && (ident_type->is_adt() || (ident_type->is_object() && has_method(ident_type->type_def, "destruct", vector<*type>())))) + if (ident_type->indirection == 0 && (ident_type->is_object() && has_method(ident_type->type_def, "destruct", vector<*type>()))) defer_stack->push(ast_statement_ptr(make_method_call(ident, "destruct", vector<*ast_node>()))) return make_pair(value::void_nothing(), control_flow::nor()) } diff --git a/stdlib/pass_common.krak b/stdlib/pass_common.krak index 26a76d6..4de568c 100644 --- a/stdlib/pass_common.krak +++ b/stdlib/pass_common.krak @@ -1,10 +1,33 @@ import ast_nodes:* +import ast_transformation:* import mem:* import util:* import vector:* import stack:* import string:* +fun make_this_noncached(object: *ast_node): *ast_node { + return ast_identifier_ptr("this", object->type_def.self_type->clone_with_indirection(1), object) +} +fun possible_object_equality(lvalue: *ast_node, rvalue: *ast_node): *ast_node { + var ltype = get_ast_type(lvalue) + var rtype = get_ast_type(rvalue) + if (ltype->indirection == 0 && (ltype->is_object() && has_method(ltype->type_def, "operator==", vector(rtype)))) { + return make_method_call(lvalue, "operator==", vector(rvalue)) + } else if (ltype->is_object()) + // return false if object but no operator== (right now don't try for templated) + return ast_value_ptr(string("false"), type_ptr(base_type::boolean())) + return make_operator_call("==", vector(lvalue, rvalue)) +} + +// for now, needs source to already be in a variable for copy_constructing +fun assign_or_copy_construct_statement(lvalue: *ast_node, rvalue: *ast_node): *ast_node { + var ltype = get_ast_type(lvalue) + if (ltype->indirection == 0 && (ltype->is_object() && has_method(ltype->type_def, "copy_construct", vector(ltype->clone_with_increased_indirection())))) + return make_method_call(lvalue, "copy_construct", vector(make_operator_call("&", vector(rvalue)))) + return ast_assignment_statement_ptr(lvalue, rvalue) +} + fun get_children_pointer(node: *ast_node): *vector<*ast_node> { var bc = null>() match(*node) { @@ -54,6 +77,11 @@ fun replace_with_in(orig: *ast_node, new: *ast_node, in: *ast_node) { } } +fun add_before_in(to_add: ref vector<*ast_node>, before: *ast_node, in: *stack<*ast_node>) + to_add.for_each(fun(n: *ast_node) add_before_in(n, before, in);) +fun add_before_in(to_add: vector<*ast_node>, before: *ast_node, in: *ast_node) + to_add.for_each(fun(n: *ast_node) add_before_in(n, before, in);) + fun add_before_in(to_add: *ast_node, before: *ast_node, in: *stack<*ast_node>) add_before_in(to_add, before, in->top()) fun add_before_in(to_add: *ast_node, before: *ast_node, in: *ast_node) { @@ -68,6 +96,7 @@ fun add_before_in(to_add: *ast_node, before: *ast_node, in: *ast_node) { error(string("cannot add_before_in to ") + get_ast_name(in)) } +fun empty_pass_half(node: *ast_node, parent_chain: *stack<*ast_node>) {} fun run_on_tree(func_before: fun(*ast_node,*stack<*ast_node>):void, func_after: fun(*ast_node,*stack<*ast_node>):void, tree: *ast_node) { var parent_stack = stack<*ast_node>() run_on_tree_helper(func_before, func_after, tree, &parent_stack) @@ -79,7 +108,9 @@ fun run_on_tree_helper(func_before: fun(*ast_node,*stack<*ast_node>):void, func_ match(*node) { ast_node::translation_unit(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);) ast_node::type_def(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);) + ast_node::adt_def(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);) ast_node::function(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);) + ast_node::template(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);) ast_node::code_block(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);) ast_node::statement(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);) ast_node::if_statement(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);) @@ -87,6 +118,17 @@ fun run_on_tree_helper(func_before: fun(*ast_node,*stack<*ast_node>):void, func_ ast_node::case_statement(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);) ast_node::while_loop(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);) ast_node::for_loop(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);) + ast_node::return_statement(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);) + ast_node::defer_statement(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);) + ast_node::assignment_statement(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);) + ast_node::declaration_statement(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);) + ast_node::if_comp(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);) + ast_node::function_call(backing) { + if (!is_function(backing.func)) + run_on_tree_helper(func_before, func_after, backing.func, parent_chain) + node->function_call.parameters.for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);) + } + ast_node::cast(backing) get_ast_children(node).for_each(fun(n: *ast_node) run_on_tree_helper(func_before, func_after, n, parent_chain);) } parent_chain->pop() func_after(node, parent_chain) diff --git a/stdlib/type.krak b/stdlib/type.krak index b4aaf79..80d226a 100644 --- a/stdlib/type.krak +++ b/stdlib/type.krak @@ -10,7 +10,6 @@ import io:* adt base_type { none, object, - adt, no_type_adt_option, function, template, @@ -95,10 +94,7 @@ obj type (Object) { return this } fun construct(type_def_in: *ast_node, traits_in: set): *type { - if (is_type_def(type_def_in)) - base.copy_construct(&base_type::object()) - else - base.copy_construct(&base_type::adt()) + base.copy_construct(&base_type::object()) parameter_types.construct() indirection = 0 return_type = null() @@ -160,7 +156,7 @@ obj type (Object) { traits.for_each(fun(t: string) trait_string += t;) trait_string += "] " } - + var indr_string = string("") if (is_ref) indr_string += " ref " @@ -169,8 +165,7 @@ obj type (Object) { for (var i = 0; i < indirection; i++;) indr_string += "*" match (base) { base_type::none() return indr_string + string("none") + trait_string - base_type::object() return indr_string + type_def->type_def.name + trait_string - base_type::adt() return indr_string + type_def->adt_def.name + trait_string + base_type::object() return indr_string + get_ast_name(type_def) + trait_string base_type::no_type_adt_option() return indr_string + "no_type_adt_option" + trait_string base_type::template() return indr_string + string("template") + trait_string base_type::template_type() return indr_string + string("template_type") + trait_string @@ -225,20 +220,12 @@ obj type (Object) { to_ret->is_ref = is_ref_in return to_ret } - fun is_object_like(): bool - return is_object() || is_adt() fun is_object(): bool { match (base) { base_type::object() return true } return false } - fun is_adt(): bool { - match (base) { - base_type::adt() return true - } - return false - } fun is_function(): bool { match (base) { base_type::function() return true diff --git a/tests/test_adt.expected_results b/tests/test_adt.expected_results index bdcae97..64fe7bc 100644 --- a/tests/test_adt.expected_results +++ b/tests/test_adt.expected_results @@ -14,13 +14,15 @@ destructed object 100 : 100 copy constructed object 100 : 300 from 100 : 200 destructed object 100 : 200 copy constructed object 100 : 400 from 100 : 300 -destructed object 100 : 300 copy constructed object 100 : 500 from 100 : 400 destructed object 100 : 400 -done assignment to old variable -matched an_obj correctly 100 : 500 -int assignment to old var +destructed object 100 : 300 +copy constructed object 100 : 600 from 100 : 500 destructed object 100 : 500 +done assignment to old variable +matched an_obj correctly 100 : 600 +int assignment to old var +destructed object 100 : 600 done int assignment to old var matched an_int correctly 1337 test copy_construct for non ref equality @@ -31,6 +33,8 @@ destructed object 110 : 110 copy constructed object 110 : 310 from 110 : 210 destructed object 110 : 210 copy constructed object 110 : 410 from 110 : 310 +copy constructed object 110 : 510 from 110 : 410 +destructed object 110 : 410 destructed object 110 : 310 gonna make object in function 110 constructed object 110 : 110 @@ -39,10 +43,13 @@ destructed object 110 : 110 copy constructed object 110 : 310 from 110 : 210 destructed object 110 : 210 copy constructed object 110 : 410 from 110 : 310 -destructed object 110 : 310 copy constructed object 110 : 510 from 110 : 410 -destructed object 110 : 510 +destructed object 110 : 410 +destructed object 110 : 310 +copy constructed object 110 : 610 from 110 : 510 +destructed object 110 : 610 equality an_obj correctly -destructed object 110 : 410 -destructed object 110 : 410 +destructed object 110 : 510 +destructed object 110 : 510 done test copy_construct for non ref equality +10 diff --git a/tests/test_adt.krak b/tests/test_adt.krak index cb127af..e988075 100644 --- a/tests/test_adt.krak +++ b/tests/test_adt.krak @@ -157,6 +157,7 @@ fun main():int { else println("equality an_obj incorrectly ") println("done test copy_construct for non ref equality"); + println(maybe_object::an_int(10).an_int) return 0 }