diff --git a/include/CGenerator.h b/include/CGenerator.h index c0749fe..d5faa65 100644 --- a/include/CGenerator.h +++ b/include/CGenerator.h @@ -26,7 +26,7 @@ class CGenerator { public: CGenerator(); ~CGenerator(); - void generateCompSet(std::map*> ASTs, std::string outputName); + int generateCompSet(std::map*> ASTs, std::string outputName); std::string generateTypeStruct(NodeTree* from); bool isUnderNodeWithType(NodeTree* from, ASTType type); bool isUnderTranslationUnit(NodeTree* from, NodeTree* typeDefinition); diff --git a/main.cpp b/main.cpp index a3b4dff..1504d51 100644 --- a/main.cpp +++ b/main.cpp @@ -184,7 +184,7 @@ int main(int argc, char* argv[]) { //Code generation //For right now, just C - CGenerator().generateCompSet(ASTs, outputName); - return(0); + // return code from calling C compiler + return CGenerator().generateCompSet(ASTs, outputName); } diff --git a/src/CGenerator.cpp b/src/CGenerator.cpp index e9e0084..745f94f 100644 --- a/src/CGenerator.cpp +++ b/src/CGenerator.cpp @@ -15,7 +15,7 @@ CGenerator::~CGenerator() { } // Note the use of std::pair to hold two strings - the running string for the header file and the running string for the c file. -void CGenerator::generateCompSet(std::map*> ASTs, std::string outputName) { +int CGenerator::generateCompSet(std::map*> ASTs, std::string outputName) { //Generate an entire set of files std::string buildString = "#!/bin/sh\ncc -g -O3 -std=c99 "; std::cout << "\n\n =====GENERATE PASS===== \n\n" << std::endl; @@ -47,7 +47,7 @@ void CGenerator::generateCompSet(std::map*> ASTs, outputBuild.close(); std::cout << CLEAR_SCREEN; std::cout << BOLD_GREEN << "KRAKEN COMPILER DONE, CALLING C COMPILER" << RESET_TXT << std::endl; - ssystem("cd " + outputName + "/; sh " + scriptName); + return ssystem("cd " + outputName + "/; sh " + scriptName); } std::string CGenerator::tabs() { diff --git a/stdlib/ast_transformation.krak b/stdlib/ast_transformation.krak index 69df507..28b3a7c 100644 --- a/stdlib/ast_transformation.krak +++ b/stdlib/ast_transformation.krak @@ -358,10 +358,10 @@ fun make_operator_call(func: string, params: vector<*ast_node>): *ast_node { fun transform_assignment_statement(node: *tree, scope: *ast_node): *ast_node { var assign_to = transform(get_node("factor", node), scope) var to_assign = transform(get_node("boolean_expression", node), scope) - if (get_node("\"\\+=\"", node)) to_assign = make_operator_call("+", vector(to_assign, to_assign)) - else if (get_node("\"-=\"", node)) to_assign = make_operator_call("-", vector(to_assign, to_assign)) - else if (get_node("\"\\*=\"", node)) to_assign = make_operator_call("*", vector(to_assign, to_assign)) - else if (get_node("\"/=\"", node)) to_assign = make_operator_call("/", vector(to_assign, to_assign)) + 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)) 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 469a476..19e76b4 100644 --- a/stdlib/c_generator.krak +++ b/stdlib/c_generator.krak @@ -74,10 +74,13 @@ obj code_triple (Object) { } obj c_generator (Object) { + var id_counter: int fun construct(): *c_generator { + id_counter = 0 return this } fun copy_construct(old: *c_generator) { + id_counter = old->id_counter } fun operator=(other: ref c_generator) { destruct() @@ -85,6 +88,7 @@ obj c_generator (Object) { } fun destruct() { } + fun get_id(): string return to_string(id_counter++); fun generate_c(name_ast_map: map,*ast_node>>): pair { var linker_string:string = "" var prequal: string = "#include \n#include \n#include \n" @@ -108,21 +112,27 @@ obj c_generator (Object) { parameter_types = type_to_c(enclosing_object->type_def.self_type) + "*" parameters = type_to_c(enclosing_object->type_def.self_type) + "* this" } + + // stack-stack thing // this could be a stack of strings too, maybe + // start out with one stack on the stack + var defer_stack = stack>>(make_pair(false, stack<*ast_node>())) + var decorated_name = generate_function(child).one_string() // also add in name decoration backing.parameters.for_each(fun(parameter: *ast_node) { if (parameter_types != "") { parameter_types += ", "; parameters += ", ";} parameter_types += type_to_c(parameter->identifier.type) parameters += type_to_c(parameter->identifier.type) + " " + parameter->identifier.name + + // add parameters to destructor thingy (for returns)? Or should that be a different pass? + var parameter_type = parameter->identifier.type + if (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>()))) }) function_prototypes += type_to_c(backing.type->return_type) + " " + decorated_name + "(" + parameter_types + ");\n" - - // add parameters to destructor thingy (for returns)? Or should that be a different pass? - // stack-stack thing // this could be a stack of strings too, maybe - // start out with one stack on the stack - var defer_stack = stack>>(make_pair(false, stack<*ast_node>())) function_definitions += type_to_c(backing.type->return_type) + " " + decorated_name + "(" + parameters + ") {\n" + generate_statement(backing.body_statement, enclosing_object, &defer_stack).one_string() // emit parameter destructors? + function_definitions += generate_from_defer_stack(&defer_stack, -1, enclosing_object).one_string() function_definitions += "}\n" } @@ -178,7 +188,14 @@ obj c_generator (Object) { var identifier = node->declaration_statement.identifier var ident_type = identifier->identifier.type var to_ret = code_triple() + type_to_c(identifier->identifier.type) + " " + identifier->identifier.name - if (node->declaration_statement.expression) to_ret += code_triple(" = ") + generate(node->declaration_statement.expression, enclosing_object, null>>>()) + if (node->declaration_statement.expression) { + if (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 += ";\n"; + to_ret += generate(ast_statement_ptr(make_method_call(identifier, "copy_construct", vector(make_operator_call("&", vector(node->declaration_statement.expression))))), enclosing_object, defer_stack) + } else { + to_ret += code_triple(" = ") + generate(node->declaration_statement.expression, enclosing_object, null>>>()) + } + } if (node->declaration_statement.init_method_call) to_ret += code_triple(";\n") + generate(node->declaration_statement.init_method_call, enclosing_object, null>>>()) if (add_to_defer && 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>()))) @@ -225,7 +242,7 @@ obj c_generator (Object) { var to_ret = code_triple() // if we're returning an object, copy_construct a new one to return if (return_value_type->is_object() && return_value_type->indirection == 0 && has_method(return_value_type->type_def, "copy_construct", vector(return_value_type->clone_with_indirection(1)))) { - var temp_ident = ast_identifier_ptr(string("temporary_return"), return_value_type) + var temp_ident = ast_identifier_ptr(string("temporary_return")+get_id(), return_value_type) 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 to_ret.pre = generate_declaration_statement(declaration, enclosing_object, defer_stack, false).one_string() + ";\n" @@ -285,6 +302,7 @@ obj c_generator (Object) { fun generate_function_call(node: *ast_node, enclosing_object: *ast_node): code_triple { var func_name = string() var call_string = code_triple() + var func_return_type = get_ast_type(node) // handle the obj.method() style of method call var dot_style_method_call = is_function_call(node->function_call.func) && @@ -330,10 +348,10 @@ obj c_generator (Object) { var param_type = get_ast_type(param) if (param_type->is_object() && param_type->indirection == 0 && has_method(param_type->type_def, "copy_construct", vector(param_type->clone_with_indirection(1)))) { - var temp_ident = ast_identifier_ptr(string("temporary_param"), param_type) + var temp_ident = ast_identifier_ptr(string("temporary_param")+get_id(), param_type) 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, null>>>(), false).one_string() + ";\n" + call_string.pre += generate_declaration_statement(declaration, enclosing_object, null>>>(), false).one_string() + ";\n" call_string.pre += generate_statement(ast_statement_ptr(make_method_call(temp_ident, "copy_construct", vector(make_operator_call("&", vector(param))))), enclosing_object, null>>>()).one_string() call_string += generate(temp_ident, enclosing_object, null>>>()) if (has_method(param_type->type_def, "destruct", vector<*type>())) { @@ -343,6 +361,17 @@ obj c_generator (Object) { call_string += generate(param, enclosing_object, null>>>()) } }) + if (func_return_type->is_object() && func_return_type->indirection == 0 && has_method(func_return_type->type_def, "destruct", vector<*type>())) { + // kind of ugly combo here of + var temp_ident = ast_identifier_ptr(string("temporary_return")+get_id(), func_return_type) + 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, null>>>(), false).one_string() + ";\n" + call_string.pre += generate_identifier(temp_ident, enclosing_object).one_string() + " = " + func_name + "(" + call_string.value + ");\n" + call_string.value = generate_identifier(temp_ident, enclosing_object).one_string() + call_string.post += generate_statement(ast_statement_ptr(make_method_call(temp_ident, "destruct", vector<*ast_node>())), enclosing_object, null>>>()).one_string() + return call_string + } return code_triple() + func_name + "(" + call_string + ")" }