From f3cdea068e2686d9a95442b5b500b274812e8747 Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Tue, 7 Jul 2015 00:46:00 -0400 Subject: [PATCH] Added mem::safe_recursive_clone, and while it works for regex, it's actually slower then remaking it. Hmmmm, maybe because some of the stdlib is inefficent --- src/ASTTransformation.cpp | 24 +++++++++++++----------- src/CGenerator.cpp | 6 +++++- stdlib/map.krak | 3 +++ stdlib/mem.krak | 15 +++++++++++++++ stdlib/regex.krak | 17 ++++++++++++----- stdlib/vector.krak | 7 ------- tests/test_grammer.krak | 5 +++-- tests/test_rec_closure.expected_results | 5 +++++ tests/test_rec_closure.krak | 12 ++++++++++++ 9 files changed, 68 insertions(+), 26 deletions(-) create mode 100644 tests/test_rec_closure.expected_results create mode 100644 tests/test_rec_closure.krak diff --git a/src/ASTTransformation.cpp b/src/ASTTransformation.cpp index c1a714c..6702db4 100644 --- a/src/ASTTransformation.cpp +++ b/src/ASTTransformation.cpp @@ -692,21 +692,23 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree return newNode; } - auto boolExp = getNode("boolean_expression", children); - NodeTree* toAssign = boolExp ? transform(boolExp, scope, types, limitToFunction, templateTypeReplacements) : nullptr; - // for type inferencing - if (!identifierType) { - if (toAssign) - identifierType = toAssign->getDataRef()->valueType; - else - throw "have to inference but no expression"; - } - NodeTree* newIdentifier = new NodeTree("identifier", ASTData(identifier, Symbol(newIdentifierStr, true), identifierType)); addToScope(newIdentifierStr, newIdentifier, scope); addToScope("~enclosing_scope", scope, newNode); addToScope("~enclosing_scope", newNode, newIdentifier); + auto boolExp = getNode("boolean_expression", children); + NodeTree* toAssign = boolExp ? transform(boolExp, scope, types, limitToFunction, templateTypeReplacements) : nullptr; + // for type inferencing + if (!identifierType) { + if (toAssign) { + identifierType = toAssign->getDataRef()->valueType; + newIdentifier->getDataRef()->valueType = identifierType; + } else + throw "have to inference but no expression"; + } + + newNode->addChild(newIdentifier); if (toAssign) newNode->addChild(toAssign); @@ -791,7 +793,7 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree throw "Ambigious parse!"; } else { // Should get rid of this eventually. Right now it handles cases like sign, alpha, a comma, etc - std::cout << "Unhandled syntax node: " << name << std::endl; + //std::cout << "Unhandled syntax node: " << name << std::endl; return new NodeTree(); } diff --git a/src/CGenerator.cpp b/src/CGenerator.cpp index a60356c..76782a0 100644 --- a/src/CGenerator.cpp +++ b/src/CGenerator.cpp @@ -566,7 +566,11 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc output.value += toAssign.postValue; return output; } else { - return ValueTypeToCType(children[0]->getData().valueType, generate(children[0], enclosingObject, justFuncName, enclosingFunction).oneString()) + " = " + generate(children[1], enclosingObject, true, enclosingFunction) + ";"; + // we might use this address in the right hand side (recursive closures), so split it up + std::string assignTo = generate(children[0], enclosingObject, justFuncName, enclosingFunction).oneString(); + output.preValue = ValueTypeToCType(children[0]->getData().valueType, assignTo) + ";\n"; + output += assignTo + " = " + generate(children[1], enclosingObject, true, enclosingFunction) + ";"; + return output; } } case if_comp: diff --git a/stdlib/map.krak b/stdlib/map.krak index f44dc5c..bc84c48 100644 --- a/stdlib/map.krak +++ b/stdlib/map.krak @@ -43,6 +43,9 @@ obj map (Object) { keys.add(key) values.add(value) } + fun contains_key(key: T): bool { + return keys.contains(key) + } fun get(key: T): U { return values.get(keys.find(key)) } diff --git a/stdlib/mem.krak b/stdlib/mem.krak index 1076e4a..5299652 100644 --- a/stdlib/mem.krak +++ b/stdlib/mem.krak @@ -1,4 +1,5 @@ import set +import map __if_comp__ __C__ simple_passthrough """ #include @@ -105,4 +106,18 @@ fun safe_recursive_delete(first: *T, addingFunc: fun(*T): set::set<*T>) { toDelete.for_each( fun(it: *T) delete(it); ) } +// a function that allows the safe cloning of recursive and complicated data structures +// cloneing func is the func that does the cloning, it takes in a recursive clone function and +// a register clone function +fun safe_recursive_clone(first: *T, cloningFunc: fun(*T, fun(*T):*T, fun(*T):void): void): *T { + var rec_map = map::map<*T,*T>() + // can't do type infrence if you need the type inside the expression... + var rec_it: fun(*T):*T = fun(it: *T): *T { + if (!rec_map.contains_key(it)) + cloningFunc(it, rec_it, fun(cloned: *T) { rec_map[it] = cloned; }) + return rec_map[it] + } + return rec_it(first) +} + diff --git a/stdlib/regex.krak b/stdlib/regex.krak index b4de205..e06247b 100644 --- a/stdlib/regex.krak +++ b/stdlib/regex.krak @@ -56,14 +56,21 @@ obj regex (Object) { } fun copy_construct(old:*regex):void { - begin = old->begin - regexString.copy_construct(&old->regexString) - /*construct(old->regexString)*/ + construct(old->regexString) + /*begin = old->begin*/ + /*regexString.copy_construct(&old->regexString)*/ + /*begin = mem::safe_recursive_clone(old->begin, fun(it: *regexState, cloner: fun(*regexState):*regexState, register: fun(*regexState):void): void {*/ + /*var newOne = mem::new()->construct(it->character)*/ + /*register(newOne)*/ + /*it->next_states.for_each(fun(next_state: *regexState) {*/ + /*newOne->next_states.add(cloner(next_state))*/ + /*})*/ + /*})*/ } fun destruct():void { regexString.destruct() - /*mem::safe_recursive_delete(begin, fun(it: *regexState): set::set<*regexState> { return set::from_vector(it->next_states); } )*/ + mem::safe_recursive_delete(begin, fun(it: *regexState): set::set<*regexState> { return set::from_vector(it->next_states); } ) } fun operator==(other: regex):bool { @@ -72,7 +79,7 @@ obj regex (Object) { fun operator=(other: regex):void { destruct() - construct(other.regexString) + copy_construct(&other) } fun compile(regex_string: string::string): util::pair<*regexState, vector::vector<*regexState>> { diff --git a/stdlib/vector.krak b/stdlib/vector.krak index 6feffdb..4c7f664 100644 --- a/stdlib/vector.krak +++ b/stdlib/vector.krak @@ -25,13 +25,6 @@ obj vector (Object) { return this; } - fun construct(newSize: int): *vector{ - size = newSize; - available = newSize; - - data = new(newSize); - return this; - } fun copy_construct(old: *vector): void { construct() diff --git a/tests/test_grammer.krak b/tests/test_grammer.krak index f477920..d46016a 100644 --- a/tests/test_grammer.krak +++ b/tests/test_grammer.krak @@ -6,14 +6,15 @@ import util:* fun main():int { var a = load_grammer(read_file(string("../krakenGrammer.kgm"))) - /*var a = load_grammer(string("grammer.kgm"))*/ + /*var a = load_grammer(read_file(string("grammer.kgm")))*/ println(a.to_string()) var lex = lexer(a.regexs) lex.set_input(read_file(string("test_grammer.krak"))) /*lex.set_input(string("ccdahas spacedhas*/ /*returndaaaaaaaaaaaaaa"))*/ println("woo lexing:") - range(80).for_each(fun(i: int) { println(lex.next().to_string()); } ) + range(8).for_each(fun(i: int) { println(lex.next().to_string()); } ) + /*range(80).for_each(fun(i: int) { println(lex.next().to_string()); } )*/ return 0 } diff --git a/tests/test_rec_closure.expected_results b/tests/test_rec_closure.expected_results new file mode 100644 index 0000000..cb48cd2 --- /dev/null +++ b/tests/test_rec_closure.expected_results @@ -0,0 +1,5 @@ +thingy: 4 +thingy: 3 +thingy: 2 +thingy: 1 +thingy: 0 diff --git a/tests/test_rec_closure.krak b/tests/test_rec_closure.krak new file mode 100644 index 0000000..b33ad1c --- /dev/null +++ b/tests/test_rec_closure.krak @@ -0,0 +1,12 @@ +import io:* + +fun main():int { + var message = "thingy: " + var func: fun(int):void = fun(it: int) { + print(message); println(it) + if (it > 0) + func(it-1) + } + func(4) +} +