From 2e6e87137dc9fc282404aad2c9377c4a4326de5c Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Tue, 8 Mar 2016 16:04:59 -0500 Subject: [PATCH] Most of stdlib started working 55 tests pass --- stdlib/ast_transformation.krak | 39 ++++++++++++++++++++++++++++------ stdlib/c_generator.krak | 33 +++++++++++++++++----------- stdlib/type.krak | 2 ++ tests/.gitignore | 1 + 4 files changed, 56 insertions(+), 19 deletions(-) diff --git a/stdlib/ast_transformation.krak b/stdlib/ast_transformation.krak index 1767601..5cd34d2 100644 --- a/stdlib/ast_transformation.krak +++ b/stdlib/ast_transformation.krak @@ -390,7 +390,7 @@ obj ast_transformation (Object) { return transform_value(node, scope) } print("FAILED TO TRANSFORM: "); print(name + ": "); println(concat_symbol_tree(node)) - while(1) {} + error("FAILED TO TRANSFORM") return null() } fun transform_all(nodes: vector<*tree>, scope: *ast_node, template_replacements: map): vector<*ast_node> { @@ -511,8 +511,8 @@ obj ast_transformation (Object) { var declaration = ast_declaration_statement_ptr(identifier, expression) // ok, deal with the possible init position method call if (identifiers.size == 2) { - var method = transform(identifiers[1], identifier->identifier.type->type_def, template_replacements) var parameters = get_nodes("parameter", node).map(fun(child: *tree): *ast_node return transform(get_node("boolean_expression", child), scope, template_replacements);) + var method = transform(identifiers[1], identifier->identifier.type->type_def, search_type::function(parameters.map(fun(i:*ast_node):*type return get_ast_type(i);)), template_replacements) declaration->declaration_statement.init_method_call = make_method_call(identifier, method, parameters) } return declaration @@ -542,13 +542,38 @@ obj ast_transformation (Object) { if (get_node("\"=\"", node)) { var possible_assign = find_and_make_any_operator_overload_call(string("="), vector(assign_to, to_assign), scope, template_replacements) if (possible_assign) { - println("Computed and returning operator=!") + println("Computed and returning operator=") return possible_assign } - } else if (get_node("\"\\+=\"", node)) to_assign = make_operator_call("+", vector(assign_to, to_assign)) - else if (get_node("\"-=\"", node)) to_assign = make_operator_call("-", vector(assign_to, to_assign)) - else if (get_node("\"\\*=\"", node)) to_assign = make_operator_call("*", vector(assign_to, to_assign)) - else if (get_node("\"/=\"", node)) to_assign = make_operator_call("/", vector(assign_to, to_assign)) + } else if (get_node("\"\\+=\"", node)) { + var possible_assign = find_and_make_any_operator_overload_call(string("+="), vector(assign_to, to_assign), scope, template_replacements) + if (possible_assign) { + print("Computed and returning operator+=") + return possible_assign + } + to_assign = make_operator_call("+", vector(assign_to, to_assign)) + } else if (get_node("\"-=\"", node)) { + var possible_assign = find_and_make_any_operator_overload_call(string("-="), vector(assign_to, to_assign), scope, template_replacements) + if (possible_assign) { + print("Computed and returning operator-=") + return possible_assign + } + to_assign = make_operator_call("-", vector(assign_to, to_assign)) + } else if (get_node("\"\\*=\"", node)) { + var possible_assign = find_and_make_any_operator_overload_call(string("*="), vector(assign_to, to_assign), scope, template_replacements) + if (possible_assign) { + print("Computed and returning operator*=") + return possible_assign + } + to_assign = make_operator_call("*", vector(assign_to, to_assign)) + } else if (get_node("\"/=\"", node)){ + var possible_assign = find_and_make_any_operator_overload_call(string("/="), vector(assign_to, to_assign), scope, template_replacements) + if (possible_assign) { + print("Computed and returning operator/=") + return possible_assign + } + to_assign = make_operator_call("/", vector(assign_to, to_assign)) + } var assignment = ast_assignment_statement_ptr(assign_to, to_assign) return assignment } diff --git a/stdlib/c_generator.krak b/stdlib/c_generator.krak index 96f716e..30aa35f 100644 --- a/stdlib/c_generator.krak +++ b/stdlib/c_generator.krak @@ -226,7 +226,7 @@ obj c_generator (Object) { top_level_c_passthrough += generate_simple_passthrough(backing.statement->statement.child, true) } ast_node::simple_passthrough(backing) top_level_c_passthrough += generate_simple_passthrough(child, true) - ast_node::declaration_statement(backing) variable_declarations += generate_declaration_statement(child, null(), null(), null>>>(), true).one_string() + ";\n" + ast_node::declaration_statement(backing) variable_declarations += generate_declaration_statement(child, null(), null(), null>>>(), false).one_string() + ";\n" // false - don't do defer ast_node::function(backing) { // check for and add to parameters if a closure generate_function_definition(child, null()) @@ -262,7 +262,7 @@ obj c_generator (Object) { var base_name = get_name(vert) plain_typedefs += string("typedef struct ") + base_name + "_dummy " + base_name + ";\n" structs += string("struct ") + base_name + "_dummy {\n" - vert->type_def.variables.for_each(fun(variable_declaration: *ast_node) structs += generate_declaration_statement(variable_declaration, null(), null(), null>>>(), true).one_string() + ";\n";) + vert->type_def.variables.for_each(fun(variable_declaration: *ast_node) structs += generate_declaration_statement(variable_declaration, null(), null(), null>>>(), false).one_string() + ";\n";) // also no defer stack structs += "};\n" // generate the methods (note some of these may be templates) vert->type_def.methods.for_each(fun(method: *ast_node) { @@ -342,7 +342,7 @@ obj c_generator (Object) { to_ret.pre += ";\n" to_ret += code_triple() + generate(node->declaration_statement.init_method_call, enclosing_object, enclosing_func, null>>>()) } - if (add_to_defer && ident_type->is_object() && has_method(ident_type->type_def, "destruct", vector<*type>())) + if (add_to_defer && ident_type->is_object() && ident_type->indirection == 0 && 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 } @@ -377,14 +377,17 @@ obj c_generator (Object) { return to_ret } fun generate_identifier(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node): code_triple { - var pre = code_triple() - if (get_ast_type(node)->is_ref) - pre += "*" + var pre = string() + var post = string() + if (get_ast_type(node)->is_ref) { + pre += "(*" + post += ")" + } if (enclosing_func && enclosing_func->function.closed_variables.contains(node)) - return pre + code_triple(string("(*(closure_data->") + get_name(node) + "))") + return code_triple(pre + string("(*(closure_data->") + get_name(node) + "))" + post) if (enclosing_object && get_ast_scope(enclosing_object)->contains_key(node->identifier.name) && get_ast_scope(enclosing_object)->get(node->identifier.name).contains(node)) - return pre + code_triple("(this->") + get_name(node) + ")" - return pre + code_triple(get_name(node)) + return code_triple(pre + "(this->" + get_name(node) + ")" + post) + return code_triple(pre + get_name(node) + post) } fun generate_return_statement(node: *ast_node, enclosing_object: *ast_node, enclosing_func: *ast_node, defer_stack: *stack>>): code_triple { var return_value = node->return_statement.return_value @@ -506,6 +509,7 @@ obj c_generator (Object) { if (node->function_call.func->function_call.func->function.name == ".") call_string += "&" // having a null defer stack should be ok, as the only things we should get through here are identifiers and function calls + // XXX should it? wouldn't function calls be a problem? call_string += generate(node->function_call.func->function_call.parameters[0], enclosing_object, enclosing_func, null>>>()) } else if (is_identifier(node->function_call.func) || is_function(node->function_call.func)) { // we handle the case when it's not this later, i.e. it's a lambda returned from another function or something @@ -522,10 +526,11 @@ obj c_generator (Object) { )) return code_triple("(") + generate(parameters[0], enclosing_object, enclosing_func, null>>>()) + func_name + generate(parameters[1], enclosing_object, enclosing_func, null>>>()) + string(")") // 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 == "->") return code_triple("(") + generate(parameters[0], enclosing_object, enclosing_func, null>>>()) + func_name + generate(parameters[1], null(), null(), null>>>()) + string(")") if (func_name == "[]") - return code_triple("(") + generate(parameters[0], enclosing_object, enclosing_func, null>>>()) + "[" + generate(parameters[1], null(), null(), null>>>()) + string("])") + return code_triple("(") + generate(parameters[0], enclosing_object, enclosing_func, null>>>()) + "[" + generate(parameters[1], enclosing_object, enclosing_func, null>>>()) + string("])") // the post ones need to be post-ed specifically, and take the p off if (func_name == "++p" || func_name == "--p") return code_triple("(") + generate(parameters[0], enclosing_object, enclosing_func, null>>>()) + ")" + func_name.slice(0,-2) @@ -560,14 +565,18 @@ obj c_generator (Object) { } } var pre_call = string() - if (func_return_type->is_object() && !func_return_type->is_ref && func_return_type->indirection == 0 && has_method(func_return_type->type_def, "destruct", vector<*type>())) { + // we now have temporary return variables for all objects, even without destruct so we can do chained method calls + // if (func_return_type->is_object() && !func_return_type->is_ref && func_return_type->indirection == 0 && has_method(func_return_type->type_def, "destruct", vector<*type>())) { + if (func_return_type->is_object() && !func_return_type->is_ref && func_return_type->indirection == 0) { // kind of ugly combo here of var temp_ident = ast_identifier_ptr(string("temporary_return")+get_id(), func_return_type, null()) var declaration = ast_declaration_statement_ptr(temp_ident, null()) // have to pass false to the declaration generator, so can't do it through generate_statement call_string.pre += generate_declaration_statement(declaration, enclosing_object, enclosing_func, null>>>(), false).one_string() + ";\n" pre_call = generate_identifier(temp_ident, enclosing_object, enclosing_func).one_string() - call_string.post += generate_statement(ast_statement_ptr(make_method_call(temp_ident, "destruct", vector<*ast_node>())), enclosing_object, enclosing_func, null>>>()).one_string() + // move destruct condition inside + if (has_method(func_return_type->type_def, "destruct", vector<*type>())) + call_string.post += generate_statement(ast_statement_ptr(make_method_call(temp_ident, "destruct", vector<*ast_node>())), enclosing_object, enclosing_func, null>>>()).one_string() } var ref_pre = code_triple() if (func_return_type->is_ref) diff --git a/stdlib/type.krak b/stdlib/type.krak index c0bdcac..2bda26e 100644 --- a/stdlib/type.krak +++ b/stdlib/type.krak @@ -160,6 +160,8 @@ obj type (Object) { return string("impossible type, indirection:") + indirection } fun rank(): int { + if (indirection > 0) + return 5 match (base) { base_type::character() return 1 base_type::integer() return 2 diff --git a/tests/.gitignore b/tests/.gitignore index a6882aa..058d1f3 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -1,2 +1,3 @@ tester test_compiler +*.results