diff --git a/src/ASTTransformation.cpp b/src/ASTTransformation.cpp index bfa16e6..c1a714c 100644 --- a/src/ASTTransformation.cpp +++ b/src/ASTTransformation.cpp @@ -19,15 +19,15 @@ ASTTransformation::ASTTransformation(Importer *importerIn) { languageLevelOperators["&"].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree("function", ASTData(function, Symbol("&", true), NULL)))); languageLevelOperators["--"].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree("function", ASTData(function, Symbol("--", true), NULL)))); languageLevelOperators["++"].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree("function", ASTData(function, Symbol("++", true), NULL)))); - languageLevelOperators["=="].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree("function", ASTData(function, Symbol("==", true), new Type(boolean))))); - languageLevelOperators["!="].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree("function", ASTData(function, Symbol("!=", true), new Type(boolean))))); - languageLevelOperators["<="].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree("function", ASTData(function, Symbol("<=", true), new Type(boolean))))); - languageLevelOperators[">="].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree("function", ASTData(function, Symbol(">=", true), new Type(boolean))))); - languageLevelOperators["<"].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree("function", ASTData(function, Symbol("<", true), new Type(boolean))))); - languageLevelOperators[">"].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree("function", ASTData(function, Symbol(">", true), new Type(boolean))))); - languageLevelOperators["&&"].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree("function", ASTData(function, Symbol("&&", true), new Type(boolean))))); - languageLevelOperators["||"].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree("function", ASTData(function, Symbol("||", true), new Type(boolean))))); - languageLevelOperators["!"].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree("function", ASTData(function, Symbol("!", true), new Type(boolean))))); + languageLevelOperators["=="].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree("function", ASTData(function, Symbol("==", true), new Type(std::vector(), new Type(boolean)))))); + languageLevelOperators["!="].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree("function", ASTData(function, Symbol("!=", true), new Type(std::vector(), new Type(boolean)))))); + languageLevelOperators["<="].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree("function", ASTData(function, Symbol("<=", true), new Type(std::vector(), new Type(boolean)))))); + languageLevelOperators[">="].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree("function", ASTData(function, Symbol(">=", true), new Type(std::vector(), new Type(boolean)))))); + languageLevelOperators["<"].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree("function", ASTData(function, Symbol("<", true), new Type(std::vector(), new Type(boolean)))))); + languageLevelOperators[">"].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree("function", ASTData(function, Symbol(">", true), new Type(std::vector(), new Type(boolean)))))); + languageLevelOperators["&&"].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree("function", ASTData(function, Symbol("&&", true), new Type(std::vector(), new Type(boolean)))))); + languageLevelOperators["||"].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree("function", ASTData(function, Symbol("||", true), new Type(std::vector(), new Type(boolean)))))); + languageLevelOperators["!"].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree("function", ASTData(function, Symbol("!", true), new Type(std::vector(), new Type(boolean)))))); languageLevelOperators["*="].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree("function", ASTData(function, Symbol("*=", true), NULL)))); languageLevelOperators["="].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree("function", ASTData(function, Symbol("=", true), NULL)))); languageLevelOperators["+="].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree("function", ASTData(function, Symbol("+=", true), NULL)))); @@ -947,10 +947,17 @@ std::set*> ASTTransformation::findVariablesToClose(NodeTree, see below) // we should add our enclosing object, this, to our closed over variables + // also, if this is a lambda, we should close over what it needs to close over too... if (stat->getDataRef()->type == function) { auto statEnclosingScope = stat->getDataRef()->scope["~enclosing_scope"][0]; if (statEnclosingScope && statEnclosingScope->getDataRef()->valueType && statEnclosingScope->getDataRef()->valueType->typeDefinition) closed.insert(generateThis(scope)); + if (stat->getDataRef()->closedVariables.size()) { + for (auto item : stat->getDataRef()->closedVariables) { + auto recClosed = findVariablesToClose(func, item, scope); + closed.insert(recClosed.begin(), recClosed.end()); + } + } } return closed; } diff --git a/src/CGenerator.cpp b/src/CGenerator.cpp index a2a055f..a60356c 100644 --- a/src/CGenerator.cpp +++ b/src/CGenerator.cpp @@ -352,7 +352,9 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc if (enclosingObject && enclosingObject->getDataRef()->scope.find(varName) != enclosingObject->getDataRef()->scope.end()) preName += "this->"; varName = (varName == "this") ? varName : scopePrefix(var) + varName; - output.preValue += "." + varName + " = &" + preName + varName; + // so that we can close over things that have been closed over by an enclosing closure + output.preValue += "." + varName + " = &/*woo*/" + generate(var, enclosingObject, justFuncName, enclosingFunction).oneString() + "/*woo*/"; + //output.preValue += "." + varName + " = &" + preName + varName; } output.preValue += "};\n"; output += "("+ ValueTypeToCType(data.valueType, "") +"){(void*)" + funcName + ", &" + tmpStruct + "}"; @@ -667,31 +669,37 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc return "((" + generate(children[1], enclosingObject, true, enclosingFunction) + ")" + name + generate(children[2], nullptr, true, enclosingFunction) + ")"; } } else { - //It's a normal function call, not a special one or a method or anything. Name decorate. - std::vector*> functionDefChildren = children[0]->getChildren(); - std::cout << "Decorating (none-special)" << name << " " << functionDefChildren.size() << std::endl; - std::string nameDecoration; - for (int i = 0; i < (functionDefChildren.size() > 0 ? functionDefChildren.size()-1 : 0); i++) - nameDecoration += "_" + ValueTypeToCTypeDecoration(functionDefChildren[i]->getData().valueType); - // it is possible that this is an object method from inside a closure - // in which case, recover the enclosing object from this - bool addClosedOver = false; - if (enclosingFunction && enclosingFunction->getDataRef()->closedVariables.size()) { - for (auto closedVar : enclosingFunction->getDataRef()->closedVariables) { - if (closedVar->getDataRef()->symbol.getName() == "this") { - enclosingObject = closedVar->getDataRef()->valueType->typeDefinition; - addClosedOver = true; + // this could a closure literal. sigh, I know. + if (children[0]->getDataRef()->closedVariables.size()) { + functionCallSource = generate(children[0], enclosingObject, true, enclosingFunction); + doClosureInstead = true; + } else { + //It's a normal function call, not a special one or a method or anything. Name decorate. + std::vector*> functionDefChildren = children[0]->getChildren(); + std::cout << "Decorating (none-special)" << name << " " << functionDefChildren.size() << std::endl; + std::string nameDecoration; + for (int i = 0; i < (functionDefChildren.size() > 0 ? functionDefChildren.size()-1 : 0); i++) + nameDecoration += "_" + ValueTypeToCTypeDecoration(functionDefChildren[i]->getData().valueType); + // it is possible that this is an object method from inside a closure + // in which case, recover the enclosing object from this + bool addClosedOver = false; + if (enclosingFunction && enclosingFunction->getDataRef()->closedVariables.size()) { + for (auto closedVar : enclosingFunction->getDataRef()->closedVariables) { + if (closedVar->getDataRef()->symbol.getName() == "this") { + enclosingObject = closedVar->getDataRef()->valueType->typeDefinition; + addClosedOver = true; + } } } - } - //Check to see if we're inside of an object and this is a method call - bool isSelfObjectMethod = enclosingObject && contains(enclosingObject->getChildren(), children[0]); - if (isSelfObjectMethod) { - output += function_header + scopePrefix(children[0]) + CifyName(enclosingObject->getDataRef()->symbol.getName()) +"__"; - output += CifyName(name + nameDecoration) + "("; - output += std::string(addClosedOver ? "(*closed_variables->this)" : "this") + (children.size() > 1 ? "," : ""); - } else { - output += function_header + scopePrefix(children[0]) + CifyName(name + nameDecoration) + "("; + //Check to see if we're inside of an object and this is a method call + bool isSelfObjectMethod = enclosingObject && contains(enclosingObject->getChildren(), children[0]); + if (isSelfObjectMethod) { + output += function_header + scopePrefix(children[0]) + CifyName(enclosingObject->getDataRef()->symbol.getName()) +"__"; + output += CifyName(name + nameDecoration) + "("; + output += std::string(addClosedOver ? "(*closed_variables->this)" : "this") + (children.size() > 1 ? "," : ""); + } else { + output += function_header + scopePrefix(children[0]) + CifyName(name + nameDecoration) + "("; + } } } } else { diff --git a/stdlib/grammer.krak b/stdlib/grammer.krak index 85f6f3e..442f8b6 100644 --- a/stdlib/grammer.krak +++ b/stdlib/grammer.krak @@ -34,17 +34,23 @@ fun load_grammer(path: string::string): grammer { /*io::print("parts: ")*/ /*parts.for_each(fun(i :string::string){ io::print(i); io::print(" "); })*/ /*io::println()*/ - gram.rules.add(rule(symbol::symbol(parts[0], true), - parts.slice(1,-1).map(fun(i: string::string):symbol::symbol { - return symbol::symbol(i, true); - }) - )) + /*gram.rules.add(rule(symbol::symbol(parts[0], true),*/ + /*parts.slice(1,-1).map(fun(i: string::string):symbol::symbol {*/ + /*return symbol::symbol(i, true);*/ + /*})*/ + /*))*/ + var rightSide = vector::vector() + parts.slice(1,-1).for_each( fun(part: string::string) { + if (part == "|") { + gram.rules.add(rule(symbol::symbol(parts[0], false), rightSide)) + rightSide = vector::vector() + } else { + rightSide.add(symbol::symbol(part, part[0] == '"')) + } + }) + gram.rules.add(rule(symbol::symbol(parts[0], false), rightSide)) }) - - /*gram.rules.add(rule(symbol::symbol("test", true), vector::vector(symbol::symbol("rhs", true))))*/ - /*gram.rules.add(rule(symbol::symbol("lhs", true), vector::vector(symbol::symbol("rhs2", true))))*/ - /*gram.regexs.add(regex::regex("reg"))*/ return gram } diff --git a/stdlib/string.krak b/stdlib/string.krak index 7c07d9e..a2a0cdb 100644 --- a/stdlib/string.krak +++ b/stdlib/string.krak @@ -68,6 +68,10 @@ obj string (Object) { 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==(other: *char): bool { + var str.construct(other) : string + return *this == str + } fun operator+(str: *char): string { var newStr.construct(str):string diff --git a/tests/grammer.kgm b/tests/grammer.kgm index aa2876d..15fd58d 100644 --- a/tests/grammer.kgm +++ b/tests/grammer.kgm @@ -1,4 +1,6 @@ # comment a = b ; b = "c" ; -b = "c" "d" ; +b = c "d" ; +c = "a" | d ; +d = "hasreturn" ; diff --git a/tests/test_badMath.expected_results b/tests/test_badMath.expected_results index 7b7e90f..6bf29f7 100644 --- a/tests/test_badMath.expected_results +++ b/tests/test_badMath.expected_results @@ -5,3 +5,5 @@ Spam We'll find out. 34 woo not +true +false diff --git a/tests/test_badMath.krak b/tests/test_badMath.krak index 49461ce..d5dda59 100644 --- a/tests/test_badMath.krak +++ b/tests/test_badMath.krak @@ -1,4 +1,6 @@ -import io; +import io:* +import string:* + fun main(): int { io::println("Spam"); var x: int = 4; @@ -18,4 +20,6 @@ fun main(): int { var boolean = false if ( z > 20 && !boolean) io::println("woo not") + io::println(string("ab")[0] == 'a') + io::println('b' == 'a') } diff --git a/tests/test_close_over_members.expected_results b/tests/test_close_over_members.expected_results index 945d41e..192bcdc 100644 --- a/tests/test_close_over_members.expected_results +++ b/tests/test_close_over_members.expected_results @@ -1,2 +1,5 @@ 4 7 +129 +222 +129 diff --git a/tests/test_close_over_members.krak b/tests/test_close_over_members.krak index c392169..c4e1585 100644 --- a/tests/test_close_over_members.krak +++ b/tests/test_close_over_members.krak @@ -35,8 +35,21 @@ fun main():int { var it: ToClose it.testMethod() it.testVariable() - //var a = 7 - //mem::safe_recursive_delete(&a, fun(it: int*): set::set { return set::set(it); } ) + + var a = 129 + var b = 222 + fun() { + fun() { + println(a) + }() + }() + var c = fun() { + println(b) + fun() { + println(a) + }() + } + c() return 0 } diff --git a/tests/test_grammer.krak b/tests/test_grammer.krak index 4917b62..48d6fb8 100644 --- a/tests/test_grammer.krak +++ b/tests/test_grammer.krak @@ -3,8 +3,8 @@ import grammer:* import string:* fun main():int { - var a = load_grammer(string("../krakenGrammer.kgm")) - /*var a = load_grammer(string("grammer.kgm"))*/ + /*var a = load_grammer(string("../krakenGrammer.kgm"))*/ + var a = load_grammer(string("grammer.kgm")) println(a.to_string()) return 0 } diff --git a/tests/test_lambda_pointer.krak b/tests/test_lambda_pointer.krak deleted file mode 100644 index 6e8c2e3..0000000 --- a/tests/test_lambda_pointer.krak +++ /dev/null @@ -1,8 +0,0 @@ -import io:* - -fun main():int { - var wa: fun():*int - var wb: *fun():int - var wc: *fun():*int - return 0 -} diff --git a/tests/test_string.expected_results b/tests/test_string.expected_results index 8790a13..51c3804 100644 --- a/tests/test_string.expected_results +++ b/tests/test_string.expected_results @@ -9,5 +9,7 @@ a now win! true false +true +false 2 lines diff --git a/tests/test_string.krak b/tests/test_string.krak index a649b4e..861aa84 100644 --- a/tests/test_string.krak +++ b/tests/test_string.krak @@ -22,6 +22,8 @@ fun main(): int { io::println(newWay) io::println( string::string("yes") == string::string("yes") ) io::println( string::string("no") == string::string("yes") ) + io::println( string::string("yes") == "yes") + io::println( string::string("no") == "yes") string::string("2\nlines").lines().for_each(fun(i: string::string) io::println(i);) return 0; }