From 7b6e47544a58c60b73110186c509f40a0fabdf57 Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Sun, 14 Jun 2015 18:13:52 -0400 Subject: [PATCH] Some more bugfixes, got regex working as well as the cpp version. (leaks memory like craaazy) --- src/CGenerator.cpp | 16 +++--- stdlib/regex.krak | 67 +++++++++++++++----------- stdlib/string.krak | 4 ++ stdlib/vector.krak | 12 +++++ tests/test_regex.expected_results | 40 +++++++++++++++ tests/test_regex.krak | 52 +++++++++++++++++++- tests/test_templateFuncInfr.krak | 8 +-- tests/test_vectorTest.expected_results | 5 ++ tests/test_vectorTest.krak | 20 ++++++++ 9 files changed, 184 insertions(+), 40 deletions(-) diff --git a/src/CGenerator.cpp b/src/CGenerator.cpp index 393f5b5..f7eb4c6 100644 --- a/src/CGenerator.cpp +++ b/src/CGenerator.cpp @@ -532,9 +532,9 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc //Test for special functions only if what we're testing is, indeed, the definition, not a function call that returns a callable function pointer if (funcType == function) { if (name == "++" || name == "--") - return generate(children[1], enclosingObject, true).oneString() + name; + return generate(children[1], enclosingObject, true) + name; if ( (name == "*" || name == "&" || name == "!" || name == "-" || name == "+" ) && children.size() == 2) //Is dereference, not multiplication, address-of, or other unary operator - return name + "(" + generate(children[1], enclosingObject, true).oneString() + ")"; + return name + "(" + generate(children[1], enclosingObject, true) + ")"; if (name == "[]") return "(" + generate(children[1], enclosingObject, true) + ")[" + generate(children[2],enclosingObject, true) + "]"; if (name == "+" || name == "-" || name == "*" || name == "/" || name == "==" || name == ">=" || name == "<=" || name == "!=" @@ -559,16 +559,16 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc nameDecoration += "_" + ValueTypeToCTypeDecoration(functionDefChildren[i]->getData().valueType); // Note that we only add scoping to the object, as this specifies our member function too /*HERE*/ return function_header + scopePrefix(unaliasedTypeDef) + CifyName(unaliasedTypeDef->getDataRef()->symbol.getName()) +"__" + - CifyName(functionName + nameDecoration) + "(" + (name == "." ? "&" : "") + generate(children[1], enclosingObject, true).oneString() + ","; + CifyName(functionName + nameDecoration) + "(" + (name == "." ? "&" : "") + generate(children[1], enclosingObject, true) + ","; //The comma lets the upper function call know we already started the param list //Note that we got here from a function call. We just pass up this special case and let them finish with the perentheses } else { std::cout << "Is not in scope or not type" << std::endl; - return "((" + generate(children[1], enclosingObject, true).oneString() + ")" + name + functionName + ")"; + return "((" + generate(children[1], enclosingObject, true) + ")" + name + functionName + ")"; } } else { std::cout << "Is not in scope or not type" << std::endl; - return "((" + generate(children[1], enclosingObject, true).oneString() + ")" + name + functionName + ")"; + return "((" + generate(children[1], enclosingObject, true) + ")" + name + functionName + ")"; } } else { //return "((" + generate(children[1], enclosingObject) + ")" + name + generate(children[2], enclosingObject) + ")"; @@ -594,9 +594,9 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc } else { //This part handles cases where our definition isn't the function definition (that is, it is probabally the return from another function) //It's probabally the result of an access function call (. or ->) to access an object method. - std::string functionCallSource = generate(children[0], enclosingObject, true).oneString(); - if (functionCallSource[functionCallSource.size()-1] == ',') //If it's a member method, it's already started the parameter list. - output += children.size() > 1 ? functionCallSource : functionCallSource.substr(0, functionCallSource.size()-1); + CCodeTriple functionCallSource = generate(children[0], enclosingObject, true); + if (functionCallSource.value[functionCallSource.value.size()-1] == ',') //If it's a member method, it's already started the parameter list. + output += children.size() > 1 ? functionCallSource : CCodeTriple(functionCallSource.preValue, functionCallSource.value.substr(0, functionCallSource.value.size()-1), functionCallSource.postValue); else output += functionCallSource + "("; } diff --git a/stdlib/regex.krak b/stdlib/regex.krak index baf8191..992ce1e 100644 --- a/stdlib/regex.krak +++ b/stdlib/regex.krak @@ -52,33 +52,25 @@ obj regexState(Object) { obj regex(Object) { var regexString: string::string - var begin: regexState + var begin: regexState* fun construct(regexStringIn: string::string): regex* { - begin.construct() regexString.copy_construct(®exStringIn) var beginningAndEnd = compile(regexStringIn) - // add each beginning state as a next state of our begin, and the end state as the next state of each end - beginningAndEnd.first.do(fun(it: regexState*, begin: regexState*): void { begin->next_states.add(it); }, &begin) + // init our begin, and the end state as the next state of each end + begin = beginningAndEnd.first beginningAndEnd.second.do(fun(it: regexState*, end: regexState*): void { it->next_states.add(end); }, mem::new()->construct(conversions::to_char(1))) - - io::print("begin: ") - beginningAndEnd.first.do(fun(it: regexState*): void { io::print(it->character); }) - io::print("\nend: ") - beginningAndEnd.second.do(fun(it: regexState*): void { io::print(it->character); }) - io::println() - return this } fun copy_construct(old:regex*):void { - begin.copy_construct(&old->begin) + begin = old->begin regexString.copy_construct(&old->regexString) } fun destruct():void { - begin.destruct() + //begin->destruct() regexString.destruct() } @@ -87,7 +79,7 @@ obj regex(Object) { construct(other.regexString) } - fun compile(regex_string: string::string): util::pair, vector::vector> { + fun compile(regex_string: string::string): util::pair> { var first = mem::new()->construct() var previous_begin = vector::vector() var previous_end = vector::vector() @@ -97,7 +89,7 @@ obj regex(Object) { var escapeing = false for (var i = 0; i < regex_string.length(); i++;) { - //io::print("i: "); io::println(i) + //io::print("i: "); io::print(i); io::print(" : "); io::println(regex_string[i]) if (regex_string[i] == '*' && !escapeing) { for (var j = 0; j < current_end.size; j++;) current_end[j]->next_states.add_all(current_begin) @@ -114,6 +106,31 @@ obj regex(Object) { } else if (regex_string[i] == '|' && !escapeing) { alternating = true } else if (regex_string[i] == '(' && !escapeing) { + // note that we don't have a ')' case, as we skip past it with our indicies + var perenEnd = i + 1 + for (var depth = 1; depth > 0; perenEnd++;) + if (regex_string[perenEnd] == '(') + depth++ + else if (regex_string[perenEnd] == ')') + depth-- + //io::print("unperened: ") + //io::println(regex_string.slice(i+1, perenEnd-1)) + var innerBeginEnd = compile(regex_string.slice(i+1, perenEnd-1)) + // NOTE: perenEnd is one past the close peren + i = perenEnd-1 + + if (alternating) { + previous_end.do(fun(it: regexState*, innerBegin: vector::vector):void { it->next_states.add_all(innerBegin); }, innerBeginEnd.first->next_states) + current_begin.add_all(innerBeginEnd.first->next_states) + current_end.add_all(innerBeginEnd.second) + } else { + current_end.do(fun(it: regexState*, innerBegin: vector::vector):void { it->next_states.add_all(innerBegin); }, innerBeginEnd.first->next_states) + previous_begin = current_begin + previous_end = current_end + current_begin = innerBeginEnd.first->next_states + current_end = innerBeginEnd.second + } + alternating = false } else if (regex_string[i] == '\\' && !escapeing) { escapeing = true } else { @@ -123,8 +140,8 @@ obj regex(Object) { current_begin.add(next) current_end.add(next) } else { - current_end.do(fun(it: regexState*, next: regexState*):void { io::print("adding: "); io::print(next->character); io::print(" to "); io::println(it->character); it->next_states.add(next); }, next) - //current_end.do(fun(it: regexState*, next: regexState*):void { it->next_states.add(next); }, next) + current_end.do(fun(it: regexState*, next: regexState*):void { it->next_states.add(next); }, next) + //current_end.do(fun(it: regexState*, next: regexState*):void { io::print("adding: "); io::print(next->character); io::print(" to "); io::println(it->character); it->next_states.add(next); }, next) //io::print("previous_begin size before current: "); io::println(previous_begin.size) //io::print("current_begin size before current: "); io::println(current_begin.size) previous_begin = current_begin @@ -134,33 +151,27 @@ obj regex(Object) { //io::print("current_begin size after current: "); io::println(current_begin.size) current_end = vector::vector(next) } + escapeing = false + alternating = false } } - var beginAndEnd = util::make_pair(first->next_states, current_end) - mem::delete(first) + var beginAndEnd = util::make_pair(first, current_end) return beginAndEnd } fun long_match(to_match: char*): int { return long_match(string::string(to_match)); } fun long_match(to_match: string::string): int { - var next = vector::vector(&begin) - var longest = 0 + var next = vector::vector(begin) + var longest = -1 for (var i = 0; i < to_match.length(); i++;) { if (next.size == 0) return longest if (next.any_true(fun(state: regexState*):bool { return state->is_end(); })) longest = i //next = next.flatten_map(fun(state: regexState*): vector::vector { return state->match(to_match[i]); }) - //next = next.flatten_map(fun(state: regexState*): vector::vector { return state->match('a'); }) - //next = next.flatten_map(fun(state: regexState*): vector::vector { return state->match('a'); }) next = next.flatten_map(fun(state: regexState*, c:char): vector::vector { return state->match(c); }, to_match[i]) } - /*io::println("ok, ending with")*/ - /*for (var i = 0; i < next.size; i++;) {*/ - /*io::println(next[i]->character)*/ - /*io::println(conversions::to_int(next[i]->next_states[0]->character))*/ - /*}*/ if (next.any_true(fun(state: regexState*):bool { return state->is_end(); })) return to_match.length() return longest diff --git a/stdlib/string.krak b/stdlib/string.krak index 125c653..88fd967 100644 --- a/stdlib/string.krak +++ b/stdlib/string.krak @@ -39,6 +39,10 @@ obj string (Object) { } fun operator[](index: int): char { return data[index]; } + fun slice(first: int, second: int): string { + var new.construct(data.slice(first,second)): string + return new + } fun length():int { return data.size; } fun operator=(str: char*): void { diff --git a/stdlib/vector.krak b/stdlib/vector.krak index b2c14be..44a15e7 100644 --- a/stdlib/vector.krak +++ b/stdlib/vector.krak @@ -42,6 +42,7 @@ obj vector (Object) { fun destruct(): void { if (data) delete(data, size); + //data = 1337 data = 0 } @@ -84,6 +85,17 @@ obj vector (Object) { return true; } + fun slice(start: int, end: int): vector { + var new.construct(): vector + if (start < 0) + start += size + 1 + if (end < 0) + end += size + 1 + for (var i = start; i < end; i++;) + new.add(data[i]) + return new + } + fun at(index: int): T { return get(index); } fun operator[](index: int): T { return get(index); } fun get(index: int): T { diff --git a/tests/test_regex.expected_results b/tests/test_regex.expected_results index 389e262..70dbe32 100644 --- a/tests/test_regex.expected_results +++ b/tests/test_regex.expected_results @@ -1,2 +1,42 @@ +concat 2 +-1 +repitition +2 +18 +26 +-1 +-1 +-1 +alternation +1 +1 +1 +1 +1 +-1 +perens! +1 +1 +2 +2 +2 +12 0 +optional! +-1 +1 +2 +Old Contributed +1 +2 +4 +0 +2 +4 +-1 +1 +5 +0 +6 +9 diff --git a/tests/test_regex.krak b/tests/test_regex.krak index 568cf5a..29e3955 100644 --- a/tests/test_regex.krak +++ b/tests/test_regex.krak @@ -2,11 +2,12 @@ import io:* import regex:* fun main():int { + println("concat") var reg = regex("ab") println(reg.long_match("abab")) println(reg.long_match("aab")) - println("second") + println("repitition") reg = regex("a*b+c") println(reg.long_match("bc")) @@ -15,5 +16,54 @@ fun main():int { println(reg.long_match("aaaaaaaaaaaaaaaa")) println(reg.long_match("aaaaaaaaaaaaaaaac")) println(reg.long_match("aaaaaaaaaaaaaaaab")) + + println("alternation") + + reg = regex("a|b") + println(reg.long_match("a")) + println(reg.long_match("b")) + println(reg.long_match("aa")) + println(reg.long_match("bb")) + println(reg.long_match("ab")) + println(reg.long_match("c")) + + println("perens!") + reg = regex("(a|b)*") + println(reg.long_match("a")) + println(reg.long_match("b")) + println(reg.long_match("aa")) + println(reg.long_match("bb")) + println(reg.long_match("ab")) + println(reg.long_match("abbbaaababab")) + println(reg.long_match("c")) + + println("optional!") + reg = regex("a?b") + println(reg.long_match("a")) + println(reg.long_match("b")) + println(reg.long_match("ab")) + + println("Old Contributed") + var re = regex("a*"); + println(re.long_match("a")); + println(re.long_match("aa")); + println(re.long_match("aaaab")); + println(re.long_match("b")); + + re = regex("a+"); + println(re.long_match("aa")); + println(re.long_match("aaaab")); + println(re.long_match("b")); + + re = regex("a(bc)?"); + println(re.long_match("ab")); + + re = regex("((ab)|c)*"); + println(re.long_match("ababc")); + println(re.long_match("ad")); + println(re.long_match("ababccd")); + + re = regex("bbb((bba+)|(ba+))*a*((a+b)|(a+bb)|(a+))*bbb") ; + println(re.long_match("bbbababbbaaaaaaaaaaaaaaaaaaabbb")); return 0 } diff --git a/tests/test_templateFuncInfr.krak b/tests/test_templateFuncInfr.krak index dbfc0e9..7706831 100644 --- a/tests/test_templateFuncInfr.krak +++ b/tests/test_templateFuncInfr.krak @@ -2,14 +2,16 @@ import io:* import mem:* import vector:* -obj pair { +// pair2 because we actually have a pair now + +obj pair2 { var first: T var second: U } fun id(in: T): T { return in; } fun idVec(in: vector): T { return in.get(0); } -fun pairFun(in: pair, another:double): T { +fun pairFun(in: pair2, another:double): T { println(in.second) println(another) return in.first; @@ -21,7 +23,7 @@ fun main():int { aVec.addEnd(12) println(fromTemplateFun) println(idVec(aVec)) - var testPair: pair + var testPair: pair2 testPair.first = "test string" testPair.second = 9 var someFloat = 13.88 diff --git a/tests/test_vectorTest.expected_results b/tests/test_vectorTest.expected_results index 0de9de3..3e90128 100644 --- a/tests/test_vectorTest.expected_results +++ b/tests/test_vectorTest.expected_results @@ -16,5 +16,10 @@ hayyy first first second +full: 1234 +middle: 23 +all but first: 234 +all but last: 123 +just some: 2 done Destroyed: 0 diff --git a/tests/test_vectorTest.krak b/tests/test_vectorTest.krak index 67652c7..baf85d1 100644 --- a/tests/test_vectorTest.krak +++ b/tests/test_vectorTest.krak @@ -85,6 +85,26 @@ fun main(): int { println(assignTest[0]) println(assignTest[1]) + var sliceTest = vector(1) + sliceTest.add(2) + sliceTest.add(3) + sliceTest.add(4) + print("full: ") + sliceTest.do(fun(it:int):void print(it);) + println() + print("middle: ") + sliceTest.slice(1,-2).do(fun(it:int):void print(it);) + println() + print("all but first: ") + sliceTest.slice(1,-1).do(fun(it:int):void print(it);) + println() + print("all but last: ") + sliceTest.slice(0,-2).do(fun(it:int):void print(it);) + println() + print("just some: ") + sliceTest.slice(1,2).do(fun(it:int):void print(it);) + println() + println("done") return 0;