Fix nested closures and related bugs

This commit is contained in:
Nathan Braswell
2015-07-05 02:34:45 -04:00
parent d44ce47d1e
commit cfadf7cebb
13 changed files with 101 additions and 56 deletions

View File

@@ -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;
}

View File

@@ -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 {

View File

@@ -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
}

View File

@@ -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

View File

@@ -1,4 +1,6 @@
# comment
a = b ;
b = "c" ;
b = "c" "d" ;
b = c "d" ;
c = "a" | d ;
d = "hasreturn" ;

View File

@@ -5,3 +5,5 @@ Spam
We'll find out.
34
woo not
true
false

View File

@@ -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')
}

View File

@@ -1,2 +1,5 @@
4
7
129
222
129

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -1,8 +0,0 @@
import io:*
fun main():int {
var wa: fun():*int
var wb: *fun():int
var wc: *fun():*int
return 0
}

View File

@@ -9,5 +9,7 @@ a
now win!
true
false
true
false
2
lines

View File

@@ -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;
}