diff --git a/krakenGrammer.kgm b/krakenGrammer.kgm index 82a4d57..a71a65a 100644 --- a/krakenGrammer.kgm +++ b/krakenGrammer.kgm @@ -113,7 +113,7 @@ term = term WS "/" WS factor | term WS "\*" WS factor | term WS "%" WS factor | factor = "\+\+" WS unarad | unarad WS "\+\+" | "--" WS unarad | unarad WS "--" | "\+" WS unarad | "-" WS unarad | "!" WS unarad | "~" WS unarad | "\(" WS type WS "\)" WS unarad | "\*" WS unarad | "&" WS unarad | unarad ; unarad = number | scoped_identifier | scoped_identifier WS template_inst | access_operation | function_call | bool | string | character | "\(" WS boolean_expression WS "\)" | unarad WS "[" WS expression WS "]" | lambda ; number = integer | floating_literal ; -access_operation = unarad "." identifier | unarad "->" identifier | unarad "." identifier WS template_inst | unarad "->" identifier WS template_inst ; +access_operation = unarad WS "." WS identifier | unarad WS "->" WS identifier | unarad WS "." WS identifier WS template_inst | unarad WS "->" WS identifier WS template_inst ; assignment_statement = factor WS "=" WS boolean_expression | factor WS "\+=" WS boolean_expression | factor WS "-=" WS boolean_expression | factor WS "\*=" WS boolean_expression | factor WS "/=" WS boolean_expression ; # if it's being assigned to, we allow type inferencing diff --git a/src/CGenerator.cpp b/src/CGenerator.cpp index 8b0344b..845ee46 100644 --- a/src/CGenerator.cpp +++ b/src/CGenerator.cpp @@ -444,6 +444,7 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc return output; } case for_loop: + { // we push on a new vector to hold for stuff that might need a destructor call loopDistructStackDepth.push(distructDoubleStack.size()); distructDoubleStack.push_back(std::vector*>()); @@ -452,15 +453,37 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc // all of the inbetween scopes loopDeferStackDepth.push(deferDoubleStack.size()); //The strSlice's are there to get ride of an unwanted return and an unwanted semicolon(s) - output += "for (" + strSlice(generate(children[0], enclosingObject, true, enclosingFunction).oneString(),0,-3) + generate(children[1], enclosingObject, true, enclosingFunction).oneString() + ";" + strSlice(generate(children[2], enclosingObject, true, enclosingFunction).oneString(),0,-3) + ")"; - output += " {\n\t" + generate(children[3], enclosingObject, justFuncName, enclosingFunction).oneString(); + + std::string doUpdateName = "do_update" + getID(); + // INITIALIZER + output += "{"; + output += generate(children[0], enclosingObject, true, enclosingFunction).oneString(); + output += "bool " + doUpdateName + " = false;\n"; + output += "for (;;) {"; + // UPDATE + output += "if (" + doUpdateName + ") {"; + output += generate(children[2], enclosingObject, true, enclosingFunction).oneString(); + output += "}\n"; + output += doUpdateName + " = true;\n"; + // CONDITION + // note that the postValue happens whether or not we break + CCodeTriple condition = generate(children[1], enclosingObject, true, enclosingFunction); + output += condition.preValue; + output += "if (!(" + condition.value + ")) {\n"; + output += condition.postValue; + output += "break;\n}"; + output += condition.postValue; + // BODY + output += generate(children[3], enclosingObject, justFuncName, enclosingFunction).oneString(); output += emitDestructors(reverse(distructDoubleStack.back()),enclosingObject); - output += + "}"; + output += "}"; + output += "}"; distructDoubleStack.pop_back(); loopDistructStackDepth.pop(); // and pop it off again loopDeferStackDepth.pop(); return output; + } case return_statement: { // we pop off the vector and go through them in reverse emitting them, going @@ -716,11 +739,14 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc } // see if we should add a destructer call to this postValue Type* retType = children[0]->getDataRef()->valueType->returnType; - if (methodExists(retType, "destruct", std::vector())) { + if (retType->baseType != void_type) { + // we always use return temps now :( (for psudo-pod objects that still have methods called on them, like range(1,3).for_each(...) std::string retTempName = "return_temp" + getID(); output.preValue += ValueTypeToCType(retType, retTempName) + " = " + output.value + ";\n"; output.value = retTempName; - output.postValue = generateMethodIfExists(retType, "destruct", "&"+retTempName, std::vector()) + ";\n" + output.postValue; + if (methodExists(retType, "destruct", std::vector())) { + output.postValue = generateMethodIfExists(retType, "destruct", "&"+retTempName, std::vector()) + ";\n" + output.postValue; + } } return output; } diff --git a/stdlib/lexer.krak b/stdlib/lexer.krak new file mode 100644 index 0000000..bde32ff --- /dev/null +++ b/stdlib/lexer.krak @@ -0,0 +1,45 @@ +import regex +import symbol +import string +import vector +import util + +obj lexer { + var regs: vector::vector + var input: string::string + var position: int + fun construct(): lexer* { + regs.construct() + input.construct() + position = 0 + return this + } + fun destruct() { + regs.destruct() + input.destruct() + } + fun copy_construct(old: lexer*) { + regs.copy_construct(&old->regs) + input.copy_construct(&old->input) + position = old->position + } + fun operator=(old: lexer) { + destruct() + copy_construct(&old) + } + fun add_regex(newOne: regex::regex) { + regs.add(newOne) + } + fun set_input(in: string::string) { + input = in + } + fun next(): symbol::symbol { + var max = regs.map(fun(reg: regex::regex): util::pair { + return util::make_pair(reg.long_match(input.slice(position, -1)), reg.regexString); }) + .max(fun(first: util::pair, second: util::pair): bool + { return first.first < second.first; }) + position += max.first + return symbol::symbol(input.slice(position-max.first, position), max.second, true) + } +} + diff --git a/stdlib/mem.krak b/stdlib/mem.krak index 136e981..0d8c2a0 100644 --- a/stdlib/mem.krak +++ b/stdlib/mem.krak @@ -52,9 +52,10 @@ fun delete(toDelete: T*, itemCount: int): void { fun delete(toDelete: T*, itemCount: int): void { // start at one because the actual delete will call the destructor of the first one as it // finishes the pointer - for (var i: int = 1; i < itemCount; i++;) + for (var i: int = 0; i < itemCount; i++;) toDelete[i].destruct(); - delete(toDelete); + free(toDelete); + //delete(toDelete); } /* We specilize on the trait Object to decide on whether or not the destructor should be called */ diff --git a/stdlib/regex.krak b/stdlib/regex.krak index 6f57cda..b92f267 100644 --- a/stdlib/regex.krak +++ b/stdlib/regex.krak @@ -51,7 +51,7 @@ obj regex(Object) { // init our begin, and the end state as the next state of each end begin = beginningAndEnd.first var end = mem::new()->construct(conversions::to_char(1)) - beginningAndEnd.second.do(fun(it: regexState*): void { it->next_states.add(end); }) + beginningAndEnd.second.for_each(fun(it: regexState*): void { it->next_states.add(end); }) return this } @@ -111,11 +111,11 @@ obj regex(Object) { i = perenEnd-1 if (alternating) { - previous_end.do(fun(it: regexState*):void { it->next_states.add_all(innerBeginEnd.first->next_states); } ) + previous_end.for_each(fun(it: regexState*):void { it->next_states.add_all(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*):void { it->next_states.add_all(innerBeginEnd.first->next_states); } ) + current_end.for_each(fun(it: regexState*):void { it->next_states.add_all(innerBeginEnd.first->next_states); } ) previous_begin = current_begin previous_end = current_end current_begin = innerBeginEnd.first->next_states @@ -129,11 +129,11 @@ obj regex(Object) { } else { var next = mem::new()->construct(regex_string[i]) if (alternating) { - previous_end.do(fun(it: regexState*):void { it->next_states.add(next); }) + previous_end.for_each(fun(it: regexState*):void { it->next_states.add(next); }) current_begin.add(next) current_end.add(next) } else { - current_end.do(fun(it: regexState*):void { it->next_states.add(next); }) + current_end.for_each(fun(it: regexState*):void { it->next_states.add(next); }) previous_begin = current_begin previous_end = current_end current_begin = vector::vector(next) diff --git a/stdlib/set.krak b/stdlib/set.krak index f9b889e..c9ba9b9 100644 --- a/stdlib/set.krak +++ b/stdlib/set.krak @@ -14,7 +14,7 @@ fun set(item: T): set { fun from_vector(items: vector::vector): set { var toRet.construct() : set - items.do( fun(item: T) toRet.add(item); ) + items.for_each( fun(item: T) toRet.add(item); ) return toRet } @@ -63,7 +63,7 @@ obj set { data.remove(idx) } fun for_each(func: fun(T):void) { - data.do(func) + data.for_each(func) } } diff --git a/stdlib/string.krak b/stdlib/string.krak index 28494b9..eb99a91 100644 --- a/stdlib/string.krak +++ b/stdlib/string.krak @@ -1,4 +1,5 @@ import vector +import util import mem fun string(in:char*):string { @@ -25,6 +26,9 @@ obj string (Object) { data.copy_construct(&vec); return this; } + fun construct(str: string): string* { + return construct(str.data); + } fun copy_construct(old: string*): void { data.copy_construct(&old->data) @@ -61,17 +65,32 @@ obj string (Object) { } fun length():int { return data.size; } + fun operator==(other: string): bool { + return length() == other.length() && !util::range(length()).any_true(fun(i: int):bool { return data[i] != other[i]; } ) + } + fun operator+(str: char*): string { var newStr.construct(str):string var ret.construct(data + newStr.data):string return ret } + fun operator+(str: string): string { + var newStr.construct(str):string + var ret.construct(data + newStr.data):string + return ret + } + fun operator+=(str: char*): void { var newStr.construct(str):string data += newStr.data } + fun operator+=(str: string): void { + var newStr.construct(str):string + data += newStr.data + } + fun toCharArray(): char* { var out: char* = mem::new(data.size+1); for (var i: int = 0; i < data.size; i++;) diff --git a/stdlib/symbol.krak b/stdlib/symbol.krak new file mode 100644 index 0000000..a7c318b --- /dev/null +++ b/stdlib/symbol.krak @@ -0,0 +1,54 @@ +import string + +fun symbol(dataIn: char*, nameIn: char*, terminalIn: bool): symbol { + var toRet.construct(string::string(dataIn), string::string(nameIn), terminalIn): symbol + return toRet +} + +fun symbol(dataIn: string::string, nameIn: string::string, terminalIn: bool): symbol { + var toRet.construct(dataIn, nameIn, terminalIn): symbol + return toRet +} + +obj symbol { + var data: string::string + var name: string::string + var terminal: bool + + fun construct(): symbol* { + data.construct() + name.construct() + return this + } + fun construct(dataIn: string::string, nameIn: string::string, terminalIn: bool): symbol* { + data.construct(dataIn) + name.construct(nameIn) + terminal = terminalIn + return this + } + fun destruct() { + data.destruct() + name.destruct() + } + fun copy_construct(old: symbol*) { + data.copy_construct(&old->data) + name.copy_construct(&old->name) + terminal = old->terminal + } + fun operator=(old: symbol) { + destruct() + copy_construct(&old) + } + fun operator==(other: symbol): bool { + return data == other.data && name == other.name && terminal == other.terminal; + } + fun to_string(): string::string { + var terminalString: char* + if (terminal) + terminalString = "true" + else + terminalString = "false" + return name + ": " + data + " " + terminalString + } +} + diff --git a/stdlib/util.krak b/stdlib/util.krak index d563286..e5e7c03 100644 --- a/stdlib/util.krak +++ b/stdlib/util.krak @@ -44,3 +44,38 @@ obj pair(Object) { } } +fun range(end:int): range { + var toRet.construct(0, end, 1): range + return toRet +} + +fun range(begin: int, end:int): range { + var toRet.construct(begin, end, 1): range + return toRet +} +fun range(begin: int, end:int, step: int): range { + var toRet.construct(begin, end, step): range + return toRet +} + +obj range { + var begin: int + var end: int + var step: int + fun construct(beginIn: int, endIn: int, stepIn: int) : range* { + begin = beginIn + end = endIn + step = stepIn + } + fun for_each(func: fun(int):void):void { + for (var i = begin; i < end; i+= step;) + func(i) + } + fun any_true(func: fun(int):bool):bool { + for (var i = begin; i < end; i+= step;) + if (func(i)) + return true + return false + } +} + diff --git a/stdlib/vector.krak b/stdlib/vector.krak index da06b4e..d4a4745 100644 --- a/stdlib/vector.krak +++ b/stdlib/vector.krak @@ -169,14 +169,10 @@ obj vector (Object) { size-- } - fun do(func: fun(T):void):void { + fun for_each(func: fun(T):void):void { for (var i = 0; i < size; i++;) func(data[i]) } - fun do(func: fun(T,U):void, extraParam: U):void { - for (var i = 0; i < size; i++;) - func(data[i], extraParam) - } fun in_place(func: fun(T):T):void { for (var i = 0; i < size; i++;) data[i] = func(data[i]) @@ -196,15 +192,6 @@ obj vector (Object) { } return newVec } - fun flatten_map(func: fun(T,V):vector, extraParam:V):vector { - var newVec.construct(): vector - for (var i = 0; i < size; i++;) { - var to_add = func(data[i], extraParam) - for (var j = 0; j < to_add.size; j++;) - newVec.addEnd(to_add.get(j)) - } - return newVec - } fun filter(func: fun(T):bool):vector { var newVec.construct(): vector for (var i = 0; i < size; i++;) @@ -212,18 +199,18 @@ obj vector (Object) { newVec.addEnd(data[i]) return newVec } - fun filter(func: fun(T,U):bool, extraParam: U):vector { - var newVec.construct(): vector - for (var i = 0; i < size; i++;) - if (func(data[i], extraParam)) - newVec.addEnd(data[i]) - return newVec - } fun any_true(func: fun(T):bool):bool { for (var i = 0; i < size; i++;) if (func(data[i])) return true return false } + fun max(func: fun(T,T):bool): T { + var maxIdx = 0 + for (var i = 1; i < size; i++;) + if (func(data[maxIdx], data[i])) + maxIdx = i + return data[maxIdx] + } }; diff --git a/tests/test_cgen_bug.krak b/tests/test_cgen_bug.krak index cddfd25..e8ad0d2 100644 --- a/tests/test_cgen_bug.krak +++ b/tests/test_cgen_bug.krak @@ -2,7 +2,7 @@ import io:* import vector:* fun onlyMatch(vec: vector, matchWith: int): vector { - return vec.filter(fun(it:int, other:int):bool { return it == other; }, matchWith) + return vec.filter(fun(it:int):bool { return it == matchWith; }) } fun main():int { diff --git a/tests/test_lexer.expected_results b/tests/test_lexer.expected_results new file mode 100644 index 0000000..40e88f8 --- /dev/null +++ b/tests/test_lexer.expected_results @@ -0,0 +1,2 @@ +a+: aaaa true +test: test true diff --git a/tests/test_lexer.krak b/tests/test_lexer.krak new file mode 100644 index 0000000..0c3fac8 --- /dev/null +++ b/tests/test_lexer.krak @@ -0,0 +1,16 @@ +import lexer:* +import regex:* +import string:* +import symbol:* +import io:* + +fun main(): int { + var lex.construct(): lexer + lex.set_input(string("aaaatesta")) + lex.add_regex(regex("a+")) + lex.add_regex(regex("test")) + println(lex.next().to_string()) + println(lex.next().to_string()) + return 0 +} + diff --git a/tests/test_string.expected_results b/tests/test_string.expected_results index ccc760d..1496117 100644 --- a/tests/test_string.expected_results +++ b/tests/test_string.expected_results @@ -7,3 +7,5 @@ hope3 new way! a now win! +true +false diff --git a/tests/test_string.krak b/tests/test_string.krak index 41e2572..9a9fdd5 100644 --- a/tests/test_string.krak +++ b/tests/test_string.krak @@ -20,6 +20,8 @@ fun main(): int { newWay[5] = 'i' newWay[6] = 'n' io::println(newWay) + io::println( string::string("yes") == string::string("yes") ) + io::println( string::string("no") == string::string("yes") ) return 0; } diff --git a/tests/test_util.expected_results b/tests/test_util.expected_results index b83449b..731aaa6 100644 --- a/tests/test_util.expected_results +++ b/tests/test_util.expected_results @@ -2,6 +2,10 @@ 7.000000 2 8.000000 +36912 +234567 +false +true 3 hi construct diff --git a/tests/test_util.krak b/tests/test_util.krak index b37c2a1..a770e59 100644 --- a/tests/test_util.krak +++ b/tests/test_util.krak @@ -31,6 +31,13 @@ fun main():int { println(greater(1,2)) println(greater(7.0,8.0)) + range(3,13, 3).for_each(fun(i: int) { print(i); }) + println() + range(2,8).for_each(fun(i: int) { print(i); }) + println() + println(range(2,8,2).any_true(fun(i: int): bool { return i%2 == 1; } )) + println(range(3).any_true(fun(i: int): bool { return i%2 == 1; } )) + var oddPair = make_pair(3, "hi") println(oddPair.first) println(oddPair.second) diff --git a/tests/test_vectorTest.expected_results b/tests/test_vectorTest.expected_results index 97bc5b0..94b1324 100644 --- a/tests/test_vectorTest.expected_results +++ b/tests/test_vectorTest.expected_results @@ -71,9 +71,9 @@ Copied: 305 to 306 Copied: 306 to 307 Destroyed: 306 Destroyed: 305 +Destroyed: 104 Destroyed: 204 Destroyed: 304 -Destroyed: 104 Destroyed: 301 Destroyed: 201 Destroyed: 101 @@ -92,15 +92,15 @@ Copied: 308 to 309 Copied: 309 to 310 Destroyed: 309 Destroyed: 308 +Destroyed: 107 Destroyed: 207 Destroyed: 307 -Destroyed: 107 Destroyed: 210 Copied: 310 to 311 Destroyed: 310 done -Destroyed: 311 Destroyed: 110 +Destroyed: 311 Destroyed: 300 Destroyed: 200 Destroyed: 100 diff --git a/tests/test_vectorTest.krak b/tests/test_vectorTest.krak index 9f8e401..d9a2b24 100644 --- a/tests/test_vectorTest.krak +++ b/tests/test_vectorTest.krak @@ -52,7 +52,7 @@ fun main(): int { for (var i: int = 0; i < intVec.size; i++;) print(intVec.at(i)); println(); - intVec.do(fun(it:int):void print(it+7);) + intVec.for_each(fun(it:int):void print(it+7);) println(); var subd = intVec.map(fun(it:int):int { return it-1; }) @@ -90,19 +90,19 @@ fun main(): int { sliceTest.add(3) sliceTest.add(4) print("full: ") - sliceTest.do(fun(it:int):void print(it);) + sliceTest.for_each(fun(it:int):void print(it);) println() print("middle: ") - sliceTest.slice(1,-2).do(fun(it:int):void print(it);) + sliceTest.slice(1,-2).for_each(fun(it:int):void print(it);) println() print("all but first: ") - sliceTest.slice(1,-1).do(fun(it:int):void print(it);) + sliceTest.slice(1,-1).for_each(fun(it:int):void print(it);) println() print("all but last: ") - sliceTest.slice(0,-2).do(fun(it:int):void print(it);) + sliceTest.slice(0,-2).for_each(fun(it:int):void print(it);) println() print("just some: ") - sliceTest.slice(1,2).do(fun(it:int):void print(it);) + sliceTest.slice(1,2).for_each(fun(it:int):void print(it);) println() println("find test") @@ -116,10 +116,10 @@ fun main(): int { setTest.add(7) setTest.set(1,8) setTest[2] = 9 - setTest.do(fun(it: int) println(it);) + setTest.for_each(fun(it: int) println(it);) println("delete") setTest.remove(2) - setTest.do(fun(it: int) println(it);) + setTest.for_each(fun(it: int) println(it);) println("delete v2") var firstRem.construct(100): AbleToBeDestroyed;