From 815c213270ee816730aea39d2b756523501ec99a Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Mon, 15 Feb 2016 16:31:01 -0500 Subject: [PATCH] Make --parse-only not highlight and redo format of parse errors so that kraken.vim syntax checking works, fix naming to allow multiple instantiations of object templates, fix so that template type replacements go through to bodies of methods of object templates in the fourth_pass --- include/Parser.h | 2 +- include/RNGLRParser.h | 2 +- src/Importer.cpp | 4 +- src/RNGLRParser.cpp | 45 +++++++++++--------- stdlib/ast_transformation.krak | 9 +++- stdlib/c_generator.krak | 35 ++++++++++++--- stdlib/map.krak | 14 ++++++ stdlib/type.krak | 1 + tests/test_obj_create_scope.expected_results | 1 + tests/test_obj_create_scope.krak | 23 ++++++++++ tests/to_parse.krak | 10 +++++ 11 files changed, 115 insertions(+), 31 deletions(-) create mode 100644 tests/test_obj_create_scope.expected_results create mode 100644 tests/test_obj_create_scope.krak diff --git a/include/Parser.h b/include/Parser.h index 2a4eba5..a0d9543 100644 --- a/include/Parser.h +++ b/include/Parser.h @@ -28,7 +28,7 @@ class Parser { virtual void loadGrammer(std::string grammerInputString); virtual void createStateSet(); virtual std::string stateSetToString(); - virtual NodeTree* parseInput(std::string inputString, std::string filename) = 0; // filename for error reporting + virtual NodeTree* parseInput(std::string inputString, std::string filename, bool highlight_errors) = 0; // filename for error reporting virtual std::string grammerToString(); virtual std::string grammerToDOT(); diff --git a/include/RNGLRParser.h b/include/RNGLRParser.h index 1dad38e..5c8c756 100644 --- a/include/RNGLRParser.h +++ b/include/RNGLRParser.h @@ -17,7 +17,7 @@ class RNGLRParser: public Parser { public: RNGLRParser(); ~RNGLRParser(); - NodeTree* parseInput(std::string inputString, std::string filename); // filename for error reporting + NodeTree* parseInput(std::string inputString, std::string filename, bool highlight_errors); // filename for error reporting void printReconstructedFrontier(int frontier); private: diff --git a/src/Importer.cpp b/src/Importer.cpp index 13ccda4..ecfd3b5 100644 --- a/src/Importer.cpp +++ b/src/Importer.cpp @@ -197,7 +197,7 @@ NodeTree* Importer::parseAndTrim(std::string fileName) { programInFile.close(); //std::cout << programInputFileString << std::endl; - NodeTree* parseTree = parser->parseInput(programInputFileString, inputFileName); + NodeTree* parseTree = parser->parseInput(programInputFileString, inputFileName, !only_parse); if (parseTree) { //std::cout << parseTree->DOTGraphString() << std::endl; @@ -208,6 +208,8 @@ NodeTree* Importer::parseAndTrim(std::string fileName) { throw "unexceptablblllll"; return NULL; } + if (only_parse) + return parseTree; //outFile.close(); //Remove Transformations diff --git a/src/RNGLRParser.cpp b/src/RNGLRParser.cpp index 51a7f3d..006856a 100644 --- a/src/RNGLRParser.cpp +++ b/src/RNGLRParser.cpp @@ -33,7 +33,7 @@ void RNGLRParser::printReconstructedFrontier(int frontier) { } } -NodeTree* RNGLRParser::parseInput(std::string inputString, std::string filename) { +NodeTree* RNGLRParser::parseInput(std::string inputString, std::string filename, bool highlight_errors) { input.clear(); gss.clear(); while(!toReduce.empty()) toReduce.pop(); @@ -114,29 +114,36 @@ NodeTree* RNGLRParser::parseInput(std::string inputString, std::string f for (int i = 0; i < input.size(); i++) { // std::cout << "Checking if frontier " << i << " is empty" << std::endl; - if (gss.frontierIsEmpty(i)) { - //std::cout << "Frontier " << i << " is empty." << std::endl; - //std::cerr << "Parsing failed on " << input[i].toString() << std::endl; - //std::cerr << "Problem is on line: " << findLine(i) << std::endl; -// std::cerr << filename << ":" << findLine(i) << std::endl; + if (gss.frontierIsEmpty(i)) { + //std::cout << "Frontier " << i << " is empty." << std::endl; + //std::cerr << "Parsing failed on " << input[i].toString() << std::endl; + //std::cerr << "Problem is on line: " << findLine(i) << std::endl; + // std::cerr << filename << ":" << findLine(i) << std::endl; errord = true; - std::cout << BOLDMAGENTA << "parse error" << std::endl; - - std::cout << BOLDWHITE << "Error at: " << BOLDBLUE << filename << ":" << findLine(i) << std::endl; - - std::ifstream infile(filename); - std::string line; - int linecount = 0; - while(std::getline(infile,line)) - { - if(linecount == findLine(i) - 1) - std::cout << BOLDRED << line << std::endl; - linecount++; + if (highlight_errors) + std::cout << BOLDBLUE; + std::cout << filename << ":" << findLine(i) << std::endl; + if (highlight_errors) + std::cout << BOLDMAGENTA; + std::cout << ": parse error" << std::endl; + + std::ifstream infile(filename); + std::string line; + int linecount = 0; + while(std::getline(infile,line)) + { + if(linecount == findLine(i) - 1) { + if (highlight_errors) + std::cout << BOLDRED; + std::cout << line << std::endl; } + linecount++; + } + if (highlight_errors) std::cout << RESET << std::endl; break; - } + } //Clear the vector of SPPF nodes created every step SPPFStepNodes.clear(); diff --git a/stdlib/ast_transformation.krak b/stdlib/ast_transformation.krak index ff519e3..5f13c4c 100644 --- a/stdlib/ast_transformation.krak +++ b/stdlib/ast_transformation.krak @@ -204,8 +204,13 @@ obj ast_transformation (Object) { while (!fourth_pass_worklist.empty()) { var partially_inst_type_def = fourth_pass_worklist.pop() partially_inst_type_def->type_def.methods.for_each(fun(method: *ast_node) { - // this is the wrong map - method->function.body_statement = transform_statement(get_node("statement", ast_to_syntax[method]), method, map()) + var template = partially_inst_type_def->type_def.scope[string("~enclosing_scope")][0] + var template_types = template->template.template_types + var real_types = template->template.instantiated_map.reverse_get(partially_inst_type_def) + var replacements = map() + for (var i = 0; i < template_types.size; i++;) + replacements.set(template_types[i], real_types[i].clone()) + method->function.body_statement = transform_statement(get_node("statement", ast_to_syntax[method]), method, replacements) }) } } diff --git a/stdlib/c_generator.krak b/stdlib/c_generator.krak index 878f3ca..7dae2b4 100644 --- a/stdlib/c_generator.krak +++ b/stdlib/c_generator.krak @@ -118,7 +118,6 @@ obj c_generator (Object) { 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) @@ -183,8 +182,10 @@ obj c_generator (Object) { }) }) type_poset.get_sorted().for_each(fun(vert: *ast_node) { - plain_typedefs += string("typedef struct ") + vert->type_def.name + "_dummy " + vert->type_def.name + ";\n" - structs += string("struct ") + vert->type_def.name + "_dummy {\n" + /*var base_name = vert->type_def.name*/ + 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>>>(), true).one_string() + ";\n";) structs += "};\n" // generate the methods @@ -317,9 +318,7 @@ obj c_generator (Object) { } // this generates the function as a value, not the actual function fun generate_function(node: *ast_node): code_triple { - var str = code_triple(node->function.name) - node->function.parameters.for_each(fun(param: *ast_node) str += string("_") + type_decoration(param->identifier.type);) - return str + return code_triple(get_name(node)) } fun generate_function_call(node: *ast_node, enclosing_object: *ast_node): code_triple { var func_name = string() @@ -461,7 +460,7 @@ obj c_generator (Object) { base_type::floating() return string("float") + indirection base_type::double_precision() return string("double") + indirection base_type::object() { - return type->type_def->type_def.name + indirection + return get_name(type->type_def) + indirection } base_type::function() { var temp = indirection + string("function: (") @@ -471,6 +470,28 @@ obj c_generator (Object) { } return string("impossible type") + indirection } + fun get_name(node: *ast_node): string { + match (*node) { + ast_node::type_def(backing) { + var upper = backing.scope[string("~enclosing_scope")][0] + var result = backing.name + if (is_template(upper)) + upper->template.instantiated_map.reverse_get(node).for_each(fun(t: ref type) result += string("_") + type_decoration(&t);) + return result + } + ast_node::function(backing) { + // be careful, operators like . come through this + var upper = backing.scope.get_with_default(string("~enclosing_scope"), vector(null()))[0] + var str = string() + if (upper && is_type_def(upper)) + str += get_name(upper) + str += node->function.name + node->function.parameters.for_each(fun(param: *ast_node) str += string("_") + type_decoration(param->identifier.type);) + return str + } + } + return string("impossible name") + } } diff --git a/stdlib/map.krak b/stdlib/map.krak index 1d6e1b4..798b76d 100644 --- a/stdlib/map.krak +++ b/stdlib/map.krak @@ -74,6 +74,20 @@ obj map (Object, Serializable) { } return values.get(key_loc) } + fun get_with_default(key: T, default_val: ref U): ref U { + if (contains_key(key)) + return get(key) + return default_val + } + fun reverse_get(value: U): ref T { + /*return values.get(keys.find(key))*/ + var value_loc = values.find(value) + if (value_loc == -1) { + io::println("trying to access nonexistant value-key!") + while (true) {} + } + return keys.get(value_loc) + } fun remove(key: T) { var idx = keys.find(key) if (idx < 0) { diff --git a/stdlib/type.krak b/stdlib/type.krak index 5931c48..a424b2f 100644 --- a/stdlib/type.krak +++ b/stdlib/type.krak @@ -150,6 +150,7 @@ obj type (Object) { } return 0 } + fun clone(): *type return clone_with_indirection(indirection); fun clone_with_increased_indirection(): *type return clone_with_indirection(indirection+1); fun clone_with_increased_indirection(more: int): *type return clone_with_indirection(indirection+more); fun clone_with_decreased_indirection(): *type return clone_with_indirection(indirection-1); diff --git a/tests/test_obj_create_scope.expected_results b/tests/test_obj_create_scope.expected_results new file mode 100644 index 0000000..7f8f011 --- /dev/null +++ b/tests/test_obj_create_scope.expected_results @@ -0,0 +1 @@ +7 diff --git a/tests/test_obj_create_scope.krak b/tests/test_obj_create_scope.krak new file mode 100644 index 0000000..b20b3b8 --- /dev/null +++ b/tests/test_obj_create_scope.krak @@ -0,0 +1,23 @@ +import simple_print:* + +obj ConTest { + var a: int + fun construct(a: int): *ConTest { + ConTest::a = a + return this + } +} + +fun main(): int { + var b.construct(7): ConTest + println(b.a) + return 0 +} + + + + + + + + diff --git a/tests/to_parse.krak b/tests/to_parse.krak index b0bccd5..5d649df 100644 --- a/tests/to_parse.krak +++ b/tests/to_parse.krak @@ -56,11 +56,21 @@ fun some_other_function(in: bool): float { */ obj SimpleContainer { var data: T + fun print_data() { + var indirection: T + indirection = data + println(indirection) + } + fun construct(dataIn: T) data = dataIn } fun main(): int { var it: SimpleContainer<*char> it.data = "Wooo object template" println(it.data) + it.data = "Wooo object template methods" + it.print_data() + var it2.construct(3): SimpleContainer + it2.print_data() /*println(other_id("Wooo function template inference"))*/ /*var a = id(7)*/ /*println(a)*/