Fix nested closures and related bugs
This commit is contained in:
@@ -19,15 +19,15 @@ ASTTransformation::ASTTransformation(Importer *importerIn) {
|
||||
languageLevelOperators["&"].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree<ASTData>("function", ASTData(function, Symbol("&", true), NULL))));
|
||||
languageLevelOperators["--"].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree<ASTData>("function", ASTData(function, Symbol("--", true), NULL))));
|
||||
languageLevelOperators["++"].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree<ASTData>("function", ASTData(function, Symbol("++", true), NULL))));
|
||||
languageLevelOperators["=="].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree<ASTData>("function", ASTData(function, Symbol("==", true), new Type(boolean)))));
|
||||
languageLevelOperators["!="].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree<ASTData>("function", ASTData(function, Symbol("!=", true), new Type(boolean)))));
|
||||
languageLevelOperators["<="].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree<ASTData>("function", ASTData(function, Symbol("<=", true), new Type(boolean)))));
|
||||
languageLevelOperators[">="].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree<ASTData>("function", ASTData(function, Symbol(">=", true), new Type(boolean)))));
|
||||
languageLevelOperators["<"].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree<ASTData>("function", ASTData(function, Symbol("<", true), new Type(boolean)))));
|
||||
languageLevelOperators[">"].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree<ASTData>("function", ASTData(function, Symbol(">", true), new Type(boolean)))));
|
||||
languageLevelOperators["&&"].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree<ASTData>("function", ASTData(function, Symbol("&&", true), new Type(boolean)))));
|
||||
languageLevelOperators["||"].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree<ASTData>("function", ASTData(function, Symbol("||", true), new Type(boolean)))));
|
||||
languageLevelOperators["!"].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree<ASTData>("function", ASTData(function, Symbol("!", true), new Type(boolean)))));
|
||||
languageLevelOperators["=="].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree<ASTData>("function", ASTData(function, Symbol("==", true), new Type(std::vector<Type*>(), new Type(boolean))))));
|
||||
languageLevelOperators["!="].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree<ASTData>("function", ASTData(function, Symbol("!=", true), new Type(std::vector<Type*>(), new Type(boolean))))));
|
||||
languageLevelOperators["<="].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree<ASTData>("function", ASTData(function, Symbol("<=", true), new Type(std::vector<Type*>(), new Type(boolean))))));
|
||||
languageLevelOperators[">="].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree<ASTData>("function", ASTData(function, Symbol(">=", true), new Type(std::vector<Type*>(), new Type(boolean))))));
|
||||
languageLevelOperators["<"].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree<ASTData>("function", ASTData(function, Symbol("<", true), new Type(std::vector<Type*>(), new Type(boolean))))));
|
||||
languageLevelOperators[">"].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree<ASTData>("function", ASTData(function, Symbol(">", true), new Type(std::vector<Type*>(), new Type(boolean))))));
|
||||
languageLevelOperators["&&"].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree<ASTData>("function", ASTData(function, Symbol("&&", true), new Type(std::vector<Type*>(), new Type(boolean))))));
|
||||
languageLevelOperators["||"].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree<ASTData>("function", ASTData(function, Symbol("||", true), new Type(std::vector<Type*>(), new Type(boolean))))));
|
||||
languageLevelOperators["!"].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree<ASTData>("function", ASTData(function, Symbol("!", true), new Type(std::vector<Type*>(), new Type(boolean))))));
|
||||
languageLevelOperators["*="].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree<ASTData>("function", ASTData(function, Symbol("*=", true), NULL))));
|
||||
languageLevelOperators["="].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree<ASTData>("function", ASTData(function, Symbol("=", true), NULL))));
|
||||
languageLevelOperators["+="].push_back(addToScope("~enclosing_scope", builtin_trans_unit, new NodeTree<ASTData>("function", ASTData(function, Symbol("+=", true), NULL))));
|
||||
@@ -947,10 +947,17 @@ std::set<NodeTree<ASTData>*> ASTTransformation::findVariablesToClose(NodeTree<AS
|
||||
) {
|
||||
// if this is a method we know that it is a method of our current enclosing object (as we already know that we're not on the right side of . or ->, 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;
|
||||
}
|
||||
|
||||
@@ -352,7 +352,9 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* 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<ASTData>* from, NodeTree<ASTData>* 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<NodeTree<ASTData>*> 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<NodeTree<ASTData>*> 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 {
|
||||
|
||||
@@ -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<symbol::symbol>()
|
||||
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<symbol::symbol>()
|
||||
} 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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
# comment
|
||||
a = b ;
|
||||
b = "c" ;
|
||||
b = "c" "d" ;
|
||||
b = c "d" ;
|
||||
c = "a" | d ;
|
||||
d = "hasreturn" ;
|
||||
|
||||
@@ -5,3 +5,5 @@ Spam
|
||||
We'll find out.
|
||||
34
|
||||
woo not
|
||||
true
|
||||
false
|
||||
|
||||
@@ -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')
|
||||
}
|
||||
|
||||
@@ -1,2 +1,5 @@
|
||||
4
|
||||
7
|
||||
129
|
||||
222
|
||||
129
|
||||
|
||||
@@ -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<int*> { 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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
import io:*
|
||||
|
||||
fun main():int {
|
||||
var wa: fun():*int
|
||||
var wb: *fun():int
|
||||
var wc: *fun():*int
|
||||
return 0
|
||||
}
|
||||
@@ -9,5 +9,7 @@ a
|
||||
now win!
|
||||
true
|
||||
false
|
||||
true
|
||||
false
|
||||
2
|
||||
lines
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user