Ton of work on closures, getting very close. Have the extra types and the promotion and calling all worked out. Now only the actual closure part of the struct needs to be done
This commit is contained in:
1 parent
5d688a5822
commit
542821dd81
8 files changed
+264
-98
No files matched your search
@@ -4,6 +4,7 @@ build-ninja
|
|||||||
*.comp
|
*.comp
|
||||||
stats
|
stats
|
||||||
*.swp
|
*.swp
|
||||||
|
*.swm
|
||||||
*.swo
|
*.swo
|
||||||
*.png
|
*.png
|
||||||
*krakout*
|
*krakout*
|
||||||
|
|||||||
@@ -47,6 +47,8 @@ class ASTTransformation: public NodeTransformation<Symbol,ASTData> {
|
|||||||
std::string concatSymbolTree(NodeTree<Symbol>* root);
|
std::string concatSymbolTree(NodeTree<Symbol>* root);
|
||||||
NodeTree<ASTData>* doFunction(NodeTree<ASTData>* scope, std::string lookup, std::vector<NodeTree<ASTData>*> nodes, std::map<std::string, Type*> templateTypeReplacements);
|
NodeTree<ASTData>* doFunction(NodeTree<ASTData>* scope, std::string lookup, std::vector<NodeTree<ASTData>*> nodes, std::map<std::string, Type*> templateTypeReplacements);
|
||||||
|
|
||||||
|
std::set<NodeTree<ASTData>*> findVariablesToClose(NodeTree<ASTData>* func, NodeTree<ASTData>* stat);
|
||||||
|
bool inScopeChain(NodeTree<ASTData>* node, NodeTree<ASTData>* scope);
|
||||||
NodeTree<ASTData>* functionLookup(NodeTree<ASTData>* scope, std::string lookup, std::vector<Type> types);
|
NodeTree<ASTData>* functionLookup(NodeTree<ASTData>* scope, std::string lookup, std::vector<Type> types);
|
||||||
NodeTree<ASTData>* templateFunctionLookup(NodeTree<ASTData>* scope, std::string lookup, std::vector<Type*>* templateInstantiationTypes, std::vector<Type> types, std::map<std::string, Type*> scopeTypeMap);
|
NodeTree<ASTData>* templateFunctionLookup(NodeTree<ASTData>* scope, std::string lookup, std::vector<Type*>* templateInstantiationTypes, std::vector<Type> types, std::map<std::string, Type*> scopeTypeMap);
|
||||||
std::vector<NodeTree<ASTData>*> scopeLookup(NodeTree<ASTData>* scope, std::string lookup, bool includeModules = false);
|
std::vector<NodeTree<ASTData>*> scopeLookup(NodeTree<ASTData>* scope, std::string lookup, bool includeModules = false);
|
||||||
|
|||||||
@@ -18,6 +18,8 @@
|
|||||||
|
|
||||||
// Note the use of std::pair to hold two strings - the running string for the header file and the running string for the c file.
|
// Note the use of std::pair to hold two strings - the running string for the header file and the running string for the c file.
|
||||||
|
|
||||||
|
enum ClosureTypeSpecialType { ClosureTypeRegularNone, ClosureFunctionPointerTypeWithClosedParam };
|
||||||
|
|
||||||
class CGenerator {
|
class CGenerator {
|
||||||
public:
|
public:
|
||||||
CGenerator();
|
CGenerator();
|
||||||
@@ -27,11 +29,11 @@ class CGenerator {
|
|||||||
bool isUnderTranslationUnit(NodeTree<ASTData>* from, NodeTree<ASTData>* typeDefinition);
|
bool isUnderTranslationUnit(NodeTree<ASTData>* from, NodeTree<ASTData>* typeDefinition);
|
||||||
NodeTree<ASTData>* highestScope(NodeTree<ASTData>* node);
|
NodeTree<ASTData>* highestScope(NodeTree<ASTData>* node);
|
||||||
std::pair<std::string, std::string> generateTranslationUnit(std::string name, std::map<std::string, NodeTree<ASTData>*> ASTs);
|
std::pair<std::string, std::string> generateTranslationUnit(std::string name, std::map<std::string, NodeTree<ASTData>*> ASTs);
|
||||||
CCodeTriple generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enclosingObject = NULL, bool justFuncName = false);
|
CCodeTriple generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enclosingObject = NULL, bool justFuncName = false, NodeTree<ASTData>* enclosingFunction = NULL);
|
||||||
std::string generateAliasChains(std::map<std::string, NodeTree<ASTData>*> ASTs, NodeTree<ASTData>* definition);
|
std::string generateAliasChains(std::map<std::string, NodeTree<ASTData>*> ASTs, NodeTree<ASTData>* definition);
|
||||||
std::string ValueTypeToCType(Type *type, std::string);
|
std::string ValueTypeToCType(Type *type, std::string, ClosureTypeSpecialType closureSpecial = ClosureTypeRegularNone);
|
||||||
std::string ValueTypeToCTypeDecoration(Type *type);
|
std::string ValueTypeToCTypeDecoration(Type *type, ClosureTypeSpecialType closureSpecial = ClosureTypeRegularNone);
|
||||||
std::string ValueTypeToCTypeThingHelper(Type *type, std::string ptrStr);
|
std::string ValueTypeToCTypeThingHelper(Type *type, std::string ptrStr, ClosureTypeSpecialType closureSpecial);
|
||||||
static std::string CifyName(std::string name);
|
static std::string CifyName(std::string name);
|
||||||
static std::string scopePrefix(NodeTree<ASTData>* from);
|
static std::string scopePrefix(NodeTree<ASTData>* from);
|
||||||
std::string generateObjectMethod(NodeTree<ASTData>* enclosingObject, NodeTree<ASTData>* from, std::string *functionPrototype);
|
std::string generateObjectMethod(NodeTree<ASTData>* enclosingObject, NodeTree<ASTData>* from, std::string *functionPrototype);
|
||||||
@@ -49,6 +51,7 @@ class CGenerator {
|
|||||||
std::string generatorString;
|
std::string generatorString;
|
||||||
std::string linkerString;
|
std::string linkerString;
|
||||||
std::string functionTypedefString;
|
std::string functionTypedefString;
|
||||||
|
std::map<Type, std::pair<std::string, std::string>> functionTypedefMap;
|
||||||
std::vector<std::vector<NodeTree<ASTData>*>> distructDoubleStack;
|
std::vector<std::vector<NodeTree<ASTData>*>> distructDoubleStack;
|
||||||
std::stack<int> loopDistructStackDepth;
|
std::stack<int> loopDistructStackDepth;
|
||||||
std::vector<std::vector<NodeTree<ASTData>*>> deferDoubleStack;
|
std::vector<std::vector<NodeTree<ASTData>*>> deferDoubleStack;
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ class Type {
|
|||||||
~Type();
|
~Type();
|
||||||
bool const operator==(const Type &other)const;
|
bool const operator==(const Type &other)const;
|
||||||
bool const operator!=(const Type &other)const;
|
bool const operator!=(const Type &other)const;
|
||||||
|
bool const operator<(const Type &other)const;
|
||||||
Type* clone();
|
Type* clone();
|
||||||
std::string toString(bool showTraits = true);
|
std::string toString(bool showTraits = true);
|
||||||
int getIndirection();
|
int getIndirection();
|
||||||
|
|||||||
@@ -484,7 +484,12 @@ NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree
|
|||||||
newNode->addChildren(parameters);
|
newNode->addChildren(parameters);
|
||||||
// update type with actual type
|
// update type with actual type
|
||||||
newNode->getDataRef()->valueType = new Type(mapNodesToTypePointers(parameters), newNode->getDataRef()->valueType);
|
newNode->getDataRef()->valueType = new Type(mapNodesToTypePointers(parameters), newNode->getDataRef()->valueType);
|
||||||
newNode->addChild(transform(getNode("statement", children), scope, types, limitToFunction, templateTypeReplacements));
|
auto statement = transform(getNode("statement", children), scope, types, limitToFunction, templateTypeReplacements);
|
||||||
|
if (name == "lambda")
|
||||||
|
newNode->getDataRef()->closedVariables = findVariablesToClose(newNode, statement);
|
||||||
|
for (auto i : newNode->getDataRef()->closedVariables)
|
||||||
|
std::cout << "OK, CLOSED: " << i->getDataRef()->toString() << std::endl;
|
||||||
|
newNode->addChild(statement);
|
||||||
std::cout << "finished function" << functionName << std::endl;
|
std::cout << "finished function" << functionName << std::endl;
|
||||||
return newNode;
|
return newNode;
|
||||||
|
|
||||||
@@ -910,6 +915,43 @@ NodeTree<ASTData>* ASTTransformation::doFunction(NodeTree<ASTData>* scope, std::
|
|||||||
}
|
}
|
||||||
return newNode;
|
return newNode;
|
||||||
}
|
}
|
||||||
|
// checks to see if scope is in node's parent scope chain
|
||||||
|
bool ASTTransformation::inScopeChain(NodeTree<ASTData>* node, NodeTree<ASTData>* scope) {
|
||||||
|
auto nodeScope = node->getDataRef()->scope;
|
||||||
|
auto enclosingItr = nodeScope.find("~enclosing_scope");
|
||||||
|
if (enclosingItr == nodeScope.end())
|
||||||
|
return false;
|
||||||
|
if (enclosingItr->second[0] == scope)
|
||||||
|
return true;
|
||||||
|
return inScopeChain(enclosingItr->second[0], scope);
|
||||||
|
}
|
||||||
|
// We return a set of all identifers used in the children of stat that are not declared somewhere below stat
|
||||||
|
// used to calculate the closedvariables for closures
|
||||||
|
std::set<NodeTree<ASTData>*> ASTTransformation::findVariablesToClose(NodeTree<ASTData>* func, NodeTree<ASTData>* stat) {
|
||||||
|
std::set<NodeTree<ASTData>*> closed;
|
||||||
|
for (auto child: stat->getChildren()) {
|
||||||
|
//enum ASTType {undef, translation_unit, interpreter_directive, import, identifier, type_def,
|
||||||
|
//function, code_block, typed_parameter, expression, boolean_expression, statement,
|
||||||
|
//if_statement, while_loop, for_loop, return_statement, break_statement, continue_statement, defer_statement,
|
||||||
|
//assignment_statement, declaration_statement, if_comp, simple_passthrough, passthrough_params,
|
||||||
|
//in_passthrough_params, out_passthrough_params, opt_string, param_assign, function_call, value};
|
||||||
|
if (child->getDataRef()->type == function || child->getDataRef()->type == translation_unit
|
||||||
|
|| child->getDataRef()->type == type_def || child->getDataRef()->type == value
|
||||||
|
)
|
||||||
|
continue;
|
||||||
|
if (child->getDataRef()->type == function_call && (child->getDataRef()->symbol.getName() == "." || child->getDataRef()->symbol.getName() == "->")) {
|
||||||
|
// only search on the left side of access operators like . and ->
|
||||||
|
auto recClosed = findVariablesToClose(func, child->getChildren().front());
|
||||||
|
closed.insert(recClosed.begin(), recClosed.end());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (child->getDataRef()->type == identifier && !inScopeChain(child, func))
|
||||||
|
closed.insert(child);
|
||||||
|
auto recClosed = findVariablesToClose(func, child);
|
||||||
|
closed.insert(recClosed.begin(), recClosed.end());
|
||||||
|
}
|
||||||
|
return closed;
|
||||||
|
}
|
||||||
|
|
||||||
//Lookup a function that takes in parameters matching the types passed in
|
//Lookup a function that takes in parameters matching the types passed in
|
||||||
NodeTree<ASTData>* ASTTransformation::functionLookup(NodeTree<ASTData>* scope, std::string lookup, std::vector<Type> types) {
|
NodeTree<ASTData>* ASTTransformation::functionLookup(NodeTree<ASTData>* scope, std::string lookup, std::vector<Type> types) {
|
||||||
|
|||||||
+154
-76
@@ -187,7 +187,7 @@ std::pair<std::string, std::string> CGenerator::generateTranslationUnit(std::str
|
|||||||
if (parent->getChildren().size() == 1)
|
if (parent->getChildren().size() == 1)
|
||||||
variableDeclarations += ValueTypeToCType(declarationData.valueType, scopePrefix(declaration) + declarationData.symbol.getName()) + "; /*identifier*/\n";
|
variableDeclarations += ValueTypeToCType(declarationData.valueType, scopePrefix(declaration) + declarationData.symbol.getName()) + "; /*identifier*/\n";
|
||||||
else
|
else
|
||||||
variableDeclarations += ValueTypeToCType(declarationData.valueType, generate(parent->getChildren()[0], nullptr, true).oneString()) + " = " + generate(parent->getChildren()[1], nullptr, true).oneString() + ";";
|
variableDeclarations += ValueTypeToCType(declarationData.valueType, generate(parent->getChildren()[0], nullptr, true, nullptr).oneString()) + " = " + generate(parent->getChildren()[1], nullptr, true, nullptr).oneString() + ";";
|
||||||
variableExternDeclarations += "extern " + ValueTypeToCType(declarationData.valueType, declarationData.symbol.getName()) + "; /*extern identifier*/\n";
|
variableExternDeclarations += "extern " + ValueTypeToCType(declarationData.valueType, declarationData.symbol.getName()) + "; /*extern identifier*/\n";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -199,8 +199,10 @@ std::pair<std::string, std::string> CGenerator::generateTranslationUnit(std::str
|
|||||||
functionPrototypes += "/* built in function: " + declarationData.symbol.toString() + " */\n";
|
functionPrototypes += "/* built in function: " + declarationData.symbol.toString() + " */\n";
|
||||||
else {
|
else {
|
||||||
std::string nameDecoration, parameters;
|
std::string nameDecoration, parameters;
|
||||||
|
if (declarationData.closedVariables.size())
|
||||||
|
parameters += "struct closed *closed_varibles";
|
||||||
for (int j = 0; j < decChildren.size()-1; j++) {
|
for (int j = 0; j < decChildren.size()-1; j++) {
|
||||||
if (j > 0)
|
if (j > 0 || declarationData.closedVariables.size() )
|
||||||
parameters += ", ";
|
parameters += ", ";
|
||||||
parameters += ValueTypeToCType(decChildren[j]->getData().valueType, generate(decChildren[j], nullptr).oneString());
|
parameters += ValueTypeToCType(decChildren[j]->getData().valueType, generate(decChildren[j], nullptr).oneString());
|
||||||
nameDecoration += "_" + ValueTypeToCTypeDecoration(decChildren[j]->getData().valueType);
|
nameDecoration += "_" + ValueTypeToCTypeDecoration(decChildren[j]->getData().valueType);
|
||||||
@@ -263,7 +265,7 @@ std::pair<std::string, std::string> CGenerator::generateTranslationUnit(std::str
|
|||||||
}
|
}
|
||||||
|
|
||||||
//The enclosing object is for when we're generating the inside of object methods. They allow us to check scope lookups against the object we're in
|
//The enclosing object is for when we're generating the inside of object methods. They allow us to check scope lookups against the object we're in
|
||||||
CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enclosingObject, bool justFuncName) {
|
CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enclosingObject, bool justFuncName, NodeTree<ASTData>* enclosingFunction) {
|
||||||
ASTData data = from->getData();
|
ASTData data = from->getData();
|
||||||
std::vector<NodeTree<ASTData>*> children = from->getChildren();
|
std::vector<NodeTree<ASTData>*> children = from->getChildren();
|
||||||
//std::string output;
|
//std::string output;
|
||||||
@@ -291,7 +293,17 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
|
|||||||
std::cerr << "Error: this used in non-object scope" << std::endl;
|
std::cerr << "Error: this used in non-object scope" << std::endl;
|
||||||
}
|
}
|
||||||
//If we're in an object method, and our enclosing scope is that object, we're a member of the object and should use the this reference.
|
//If we're in an object method, and our enclosing scope is that object, we're a member of the object and should use the this reference.
|
||||||
std::string preName;
|
std::string preName;
|
||||||
|
//std::string preName = "/*ident*/";
|
||||||
|
// check for this being a closed over variable
|
||||||
|
// first, get declaring function, if it exists
|
||||||
|
if (enclosingFunction) {
|
||||||
|
if (enclosingFunction->getDataRef()->closedVariables.size()) {
|
||||||
|
std::cout << "WHOH IS A CLOSER" << std::endl;
|
||||||
|
if (enclosingFunction->getDataRef()->closedVariables.find(from) != enclosingFunction->getDataRef()->closedVariables.end())
|
||||||
|
preName += "/* SPECIAL CLOSED */ *closed_varibles->";
|
||||||
|
}
|
||||||
|
}
|
||||||
if (enclosingObject && enclosingObject->getDataRef()->scope.find(data.symbol.getName()) != enclosingObject->getDataRef()->scope.end())
|
if (enclosingObject && enclosingObject->getDataRef()->scope.find(data.symbol.getName()) != enclosingObject->getDataRef()->scope.end())
|
||||||
preName += "this->";
|
preName += "this->";
|
||||||
// we're scope prefixing EVERYTHING
|
// we're scope prefixing EVERYTHING
|
||||||
@@ -306,21 +318,33 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
|
|||||||
distructDoubleStack.push_back(std::vector<NodeTree<ASTData>*>());
|
distructDoubleStack.push_back(std::vector<NodeTree<ASTData>*>());
|
||||||
|
|
||||||
std::string nameDecoration, parameters;
|
std::string nameDecoration, parameters;
|
||||||
|
if (data.closedVariables.size())
|
||||||
|
parameters += "struct closed *closed_varibles";
|
||||||
for (int j = 0; j < children.size()-1; j++) {
|
for (int j = 0; j < children.size()-1; j++) {
|
||||||
if (j > 0)
|
if (j > 0 || data.closedVariables.size())
|
||||||
parameters += ", ";
|
parameters += ", ";
|
||||||
parameters += ValueTypeToCType(children[j]->getData().valueType, generate(children[j], enclosingObject, justFuncName).oneString());
|
parameters += ValueTypeToCType(children[j]->getData().valueType, generate(children[j], enclosingObject, justFuncName, enclosingFunction).oneString());
|
||||||
nameDecoration += "_" + ValueTypeToCTypeDecoration(children[j]->getData().valueType);
|
nameDecoration += "_" + ValueTypeToCTypeDecoration(children[j]->getData().valueType);
|
||||||
// add parameters to distructDoubleStack so that their destructors will be called at return (if they exist)
|
// add parameters to distructDoubleStack so that their destructors will be called at return (if they exist)
|
||||||
distructDoubleStack.back().push_back(children[j]);
|
distructDoubleStack.back().push_back(children[j]);
|
||||||
}
|
}
|
||||||
// this is for using functions as values
|
// this is for using functions as values
|
||||||
if (justFuncName) {
|
if (justFuncName) {
|
||||||
output = ((data.symbol.getName() == "main") ? "" : function_header + scopePrefix(from)) + CifyName(data.symbol.getName() + nameDecoration);
|
std::string funcName;
|
||||||
|
if (data.symbol.getName() != "main")
|
||||||
|
funcName += function_header + scopePrefix(from);
|
||||||
|
funcName += CifyName(data.symbol.getName() + nameDecoration);
|
||||||
|
if (from->getDataRef()->closedVariables.size()) {
|
||||||
|
std::string tmpStruct = "closureStruct" + getID();
|
||||||
|
output.preValue += "struct specialClosure " + tmpStruct + ";\n";
|
||||||
|
output += "("+ ValueTypeToCType(data.valueType, "") +"){" + funcName + ", &" + tmpStruct + "}";
|
||||||
|
} else {
|
||||||
|
output += "("+ ValueTypeToCType(data.valueType, "") +"){" + funcName + ", NULL}";
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Note that we always wrap out child in {}, as we now allow one statement functions without a codeblock
|
// Note that we always wrap out child in {}, as we now allow one statement functions without a codeblock
|
||||||
output = "\n" + ValueTypeToCType(data.valueType->returnType, ((data.symbol.getName() == "main") ? "" : function_header + scopePrefix(from)) +
|
output = "\n" + ValueTypeToCType(data.valueType->returnType, ((data.symbol.getName() == "main") ? "" : function_header + scopePrefix(from)) +
|
||||||
CifyName(data.symbol.getName() + nameDecoration)) + "(" + parameters + ") {\n" + generate(children[children.size()-1], enclosingObject, justFuncName).oneString();
|
CifyName(data.symbol.getName() + nameDecoration)) + "(" + parameters + ") {\n" + generate(children[children.size()-1], enclosingObject, justFuncName, from).oneString();
|
||||||
output += emitDestructors(reverse(distructDoubleStack.back()), enclosingObject);
|
output += emitDestructors(reverse(distructDoubleStack.back()), enclosingObject);
|
||||||
output += "}\n";
|
output += "}\n";
|
||||||
}
|
}
|
||||||
@@ -338,10 +362,10 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
|
|||||||
// we push on a new vector to hold deferred statements
|
// we push on a new vector to hold deferred statements
|
||||||
deferDoubleStack.push_back(std::vector<NodeTree<ASTData>*>());
|
deferDoubleStack.push_back(std::vector<NodeTree<ASTData>*>());
|
||||||
for (int i = 0; i < children.size(); i++)
|
for (int i = 0; i < children.size(); i++)
|
||||||
output += generate(children[i], enclosingObject, justFuncName).oneString();
|
output += generate(children[i], enclosingObject, justFuncName, enclosingFunction).oneString();
|
||||||
// we pop off the vector and go through them in reverse emitting them
|
// we pop off the vector and go through them in reverse emitting them
|
||||||
for (auto iter = deferDoubleStack.back().rbegin(); iter != deferDoubleStack.back().rend(); iter++)
|
for (auto iter = deferDoubleStack.back().rbegin(); iter != deferDoubleStack.back().rend(); iter++)
|
||||||
output += generate(*iter, enclosingObject, justFuncName).oneString();
|
output += generate(*iter, enclosingObject, justFuncName, enclosingFunction).oneString();
|
||||||
deferDoubleStack.pop_back();
|
deferDoubleStack.pop_back();
|
||||||
output += emitDestructors(reverse(distructDoubleStack.back()), enclosingObject);
|
output += emitDestructors(reverse(distructDoubleStack.back()), enclosingObject);
|
||||||
distructDoubleStack.pop_back();
|
distructDoubleStack.pop_back();
|
||||||
@@ -357,26 +381,26 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
|
|||||||
output += " " + data.symbol.getName() + " ";
|
output += " " + data.symbol.getName() + " ";
|
||||||
case statement:
|
case statement:
|
||||||
{
|
{
|
||||||
CCodeTriple stat = generate(children[0], enclosingObject, justFuncName);
|
CCodeTriple stat = generate(children[0], enclosingObject, justFuncName, enclosingFunction);
|
||||||
return tabs() + stat.preValue + stat.value + ";\n" + stat.postValue ;
|
return tabs() + stat.preValue + stat.value + ";\n" + stat.postValue ;
|
||||||
}
|
}
|
||||||
case if_statement:
|
case if_statement:
|
||||||
output += "if (" + generate(children[0], enclosingObject, true) + ")\n\t";
|
output += "if (" + generate(children[0], enclosingObject, true, enclosingFunction) + ")\n\t";
|
||||||
// We have to see if the then statement is a regular single statement or a block.
|
// We have to see if the then statement is a regular single statement or a block.
|
||||||
// If it's a block, because it's also a statement a semicolon will be emitted even though
|
// If it's a block, because it's also a statement a semicolon will be emitted even though
|
||||||
// we don't want it to be, as if (a) {b}; else {c}; is not legal C, but if (a) {b} else {c}; is.
|
// we don't want it to be, as if (a) {b}; else {c}; is not legal C, but if (a) {b} else {c}; is.
|
||||||
if (children[1]->getChildren()[0]->getDataRef()->type == code_block) {
|
if (children[1]->getChildren()[0]->getDataRef()->type == code_block) {
|
||||||
std::cout << "Then statement is a block, emitting the block not the statement so no trailing semicolon" << std::endl;
|
std::cout << "Then statement is a block, emitting the block not the statement so no trailing semicolon" << std::endl;
|
||||||
output += generate(children[1]->getChildren()[0], enclosingObject, justFuncName).oneString();
|
output += generate(children[1]->getChildren()[0], enclosingObject, justFuncName, enclosingFunction).oneString();
|
||||||
} else {
|
} else {
|
||||||
// ALSO we always emit blocks now, to handle cases like defer when several statements need to be
|
// ALSO we always emit blocks now, to handle cases like defer when several statements need to be
|
||||||
// run in C even though it is a single Kraken statement
|
// run in C even though it is a single Kraken statement
|
||||||
std::cout << "Then statement is a simple statement, regular emitting the statement so trailing semicolon" << std::endl;
|
std::cout << "Then statement is a simple statement, regular emitting the statement so trailing semicolon" << std::endl;
|
||||||
output += "{ " + generate(children[1], enclosingObject, justFuncName).oneString() + " }";
|
output += "{ " + generate(children[1], enclosingObject, justFuncName, enclosingFunction).oneString() + " }";
|
||||||
}
|
}
|
||||||
// Always emit blocks here too
|
// Always emit blocks here too
|
||||||
if (children.size() > 2)
|
if (children.size() > 2)
|
||||||
output += " else { " + generate(children[2], enclosingObject, justFuncName).oneString() + " }";
|
output += " else { " + generate(children[2], enclosingObject, justFuncName, enclosingFunction).oneString() + " }";
|
||||||
return output;
|
return output;
|
||||||
case while_loop:
|
case while_loop:
|
||||||
// we push on a new vector to hold while stuff that might need a destructor call
|
// we push on a new vector to hold while stuff that might need a destructor call
|
||||||
@@ -386,8 +410,8 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
|
|||||||
// break or continue inside this loop can correctly emit all of the defers through
|
// break or continue inside this loop can correctly emit all of the defers through
|
||||||
// all of the inbetween scopes
|
// all of the inbetween scopes
|
||||||
loopDeferStackDepth.push(deferDoubleStack.size());
|
loopDeferStackDepth.push(deferDoubleStack.size());
|
||||||
output += "while (" + generate(children[0], enclosingObject, true).oneString() + ") {\n\t";
|
output += "while (" + generate(children[0], enclosingObject, true, enclosingFunction).oneString() + ") {\n\t";
|
||||||
output += generate(children[1], enclosingObject, justFuncName).oneString();
|
output += generate(children[1], enclosingObject, justFuncName, enclosingFunction).oneString();
|
||||||
output += emitDestructors(reverse(distructDoubleStack.back()),enclosingObject);
|
output += emitDestructors(reverse(distructDoubleStack.back()),enclosingObject);
|
||||||
output += + "}";
|
output += + "}";
|
||||||
|
|
||||||
@@ -405,8 +429,8 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
|
|||||||
// all of the inbetween scopes
|
// all of the inbetween scopes
|
||||||
loopDeferStackDepth.push(deferDoubleStack.size());
|
loopDeferStackDepth.push(deferDoubleStack.size());
|
||||||
//The strSlice's are there to get ride of an unwanted return and an unwanted semicolon(s)
|
//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).oneString(),0,-3) + generate(children[1], enclosingObject, true).oneString() + ";" + strSlice(generate(children[2], enclosingObject, true).oneString(),0,-3) + ")";
|
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).oneString();
|
output += " {\n\t" + generate(children[3], enclosingObject, justFuncName, enclosingFunction).oneString();
|
||||||
output += emitDestructors(reverse(distructDoubleStack.back()),enclosingObject);
|
output += emitDestructors(reverse(distructDoubleStack.back()),enclosingObject);
|
||||||
output += + "}";
|
output += + "}";
|
||||||
distructDoubleStack.pop_back();
|
distructDoubleStack.pop_back();
|
||||||
@@ -420,11 +444,11 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
|
|||||||
// through all of both arrays, as return will go through all scopes
|
// through all of both arrays, as return will go through all scopes
|
||||||
for (auto topItr = deferDoubleStack.rbegin(); topItr != deferDoubleStack.rend(); topItr++)
|
for (auto topItr = deferDoubleStack.rbegin(); topItr != deferDoubleStack.rend(); topItr++)
|
||||||
for (auto iter = (*topItr).rbegin(); iter != (*topItr).rend(); iter++)
|
for (auto iter = (*topItr).rbegin(); iter != (*topItr).rend(); iter++)
|
||||||
output += generate(*iter, enclosingObject, justFuncName).oneString();
|
output += generate(*iter, enclosingObject, justFuncName, enclosingFunction).oneString();
|
||||||
|
|
||||||
std::string destructors = emitDestructors(reverse(flatten(distructDoubleStack)),enclosingObject);
|
std::string destructors = emitDestructors(reverse(flatten(distructDoubleStack)),enclosingObject);
|
||||||
if (children.size()) {
|
if (children.size()) {
|
||||||
CCodeTriple expr = generate(children[0], enclosingObject, true);
|
CCodeTriple expr = generate(children[0], enclosingObject, true, enclosingFunction);
|
||||||
output.preValue += expr.preValue;
|
output.preValue += expr.preValue;
|
||||||
std::string retTemp = "ret_temp" + getID();
|
std::string retTemp = "ret_temp" + getID();
|
||||||
output.preValue += ValueTypeToCType(children[0]->getDataRef()->valueType, retTemp) + ";\n";
|
output.preValue += ValueTypeToCType(children[0]->getDataRef()->valueType, retTemp) + ";\n";
|
||||||
@@ -446,7 +470,7 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
|
|||||||
// handle everything that's been deferred all the way back to the loop's scope
|
// handle everything that's been deferred all the way back to the loop's scope
|
||||||
for (int i = deferDoubleStack.size()-1; i >= loopDeferStackDepth.top(); i--)
|
for (int i = deferDoubleStack.size()-1; i >= loopDeferStackDepth.top(); i--)
|
||||||
for (auto iter = deferDoubleStack[i].rbegin(); iter != deferDoubleStack[i].rend(); iter++)
|
for (auto iter = deferDoubleStack[i].rbegin(); iter != deferDoubleStack[i].rend(); iter++)
|
||||||
output += generate(*iter, enclosingObject, justFuncName).oneString();
|
output += generate(*iter, enclosingObject, justFuncName, enclosingFunction).oneString();
|
||||||
// ok, emit destructors to where the loop ends
|
// ok, emit destructors to where the loop ends
|
||||||
output += emitDestructors(reverse(flatten(slice(distructDoubleStack,loopDistructStackDepth.top(),-1))),enclosingObject);
|
output += emitDestructors(reverse(flatten(slice(distructDoubleStack,loopDistructStackDepth.top(),-1))),enclosingObject);
|
||||||
return output + "break";
|
return output + "break";
|
||||||
@@ -454,15 +478,15 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
|
|||||||
// handle everything that's been deferred all the way back to the loop's scope
|
// handle everything that's been deferred all the way back to the loop's scope
|
||||||
for (int i = deferDoubleStack.size()-1; i >= loopDeferStackDepth.top(); i--)
|
for (int i = deferDoubleStack.size()-1; i >= loopDeferStackDepth.top(); i--)
|
||||||
for (auto iter = deferDoubleStack[i].rbegin(); iter != deferDoubleStack[i].rend(); iter++)
|
for (auto iter = deferDoubleStack[i].rbegin(); iter != deferDoubleStack[i].rend(); iter++)
|
||||||
output += generate(*iter, enclosingObject, justFuncName).oneString();
|
output += generate(*iter, enclosingObject, justFuncName, enclosingFunction).oneString();
|
||||||
// ok, emit destructors to where the loop ends
|
// ok, emit destructors to where the loop ends
|
||||||
output += emitDestructors(reverse(flatten(slice(distructDoubleStack,loopDistructStackDepth.top(),-1))),enclosingObject);
|
output += emitDestructors(reverse(flatten(slice(distructDoubleStack,loopDistructStackDepth.top(),-1))),enclosingObject);
|
||||||
return output + "continue";
|
return output + "continue";
|
||||||
case defer_statement:
|
case defer_statement:
|
||||||
deferDoubleStack.back().push_back(children[0]);
|
deferDoubleStack.back().push_back(children[0]);
|
||||||
return CCodeTriple("/*defer " + generate(children[0], enclosingObject, justFuncName).oneString() + "*/");
|
return CCodeTriple("/*defer " + generate(children[0], enclosingObject, justFuncName, enclosingFunction).oneString() + "*/");
|
||||||
case assignment_statement:
|
case assignment_statement:
|
||||||
return generate(children[0], enclosingObject, justFuncName).oneString() + " = " + generate(children[1], enclosingObject, true);
|
return generate(children[0], enclosingObject, justFuncName, enclosingFunction).oneString() + " = " + generate(children[1], enclosingObject, true, enclosingFunction);
|
||||||
case declaration_statement:
|
case declaration_statement:
|
||||||
// adding declaration to the distructDoubleStack so that we can call their destructors when leaving scope (}, return, break, continue)
|
// adding declaration to the distructDoubleStack so that we can call their destructors when leaving scope (}, return, break, continue)
|
||||||
// but only if we're inside an actual doublestack
|
// but only if we're inside an actual doublestack
|
||||||
@@ -470,18 +494,18 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
|
|||||||
distructDoubleStack.back().push_back(children[0]);
|
distructDoubleStack.back().push_back(children[0]);
|
||||||
|
|
||||||
if (children.size() == 1)
|
if (children.size() == 1)
|
||||||
return ValueTypeToCType(children[0]->getData().valueType, generate(children[0], enclosingObject, justFuncName).oneString()) + ";";
|
return ValueTypeToCType(children[0]->getData().valueType, generate(children[0], enclosingObject, justFuncName, enclosingFunction).oneString()) + ";";
|
||||||
else if (children[1]->getChildren().size() && children[1]->getChildren()[0]->getChildren().size() > 1
|
else if (children[1]->getChildren().size() && children[1]->getChildren()[0]->getChildren().size() > 1
|
||||||
&& children[1]->getChildren()[0]->getChildren()[1] == children[0]) {
|
&& children[1]->getChildren()[0]->getChildren()[1] == children[0]) {
|
||||||
//That is, if we're a declaration with an init position call (Object a.construct())
|
//That is, if we're a declaration with an init position call (Object a.construct())
|
||||||
//We can tell if our function call (children[1])'s access operation([0])'s lhs ([1]) is the thing we just declared (children[0])
|
//We can tell if our function call (children[1])'s access operation([0])'s lhs ([1]) is the thing we just declared (children[0])
|
||||||
// be sure to end value by passing oneString true
|
// be sure to end value by passing oneString true
|
||||||
return ValueTypeToCType(children[0]->getData().valueType, generate(children[0], enclosingObject, justFuncName).oneString()) + "; " + generate(children[1], enclosingObject, true).oneString(true) + "/*Init Position Call*/";
|
return ValueTypeToCType(children[0]->getData().valueType, generate(children[0], enclosingObject, justFuncName, enclosingFunction).oneString()) + "; " + generate(children[1], enclosingObject, true, enclosingFunction).oneString(true) + "/*Init Position Call*/";
|
||||||
} else {
|
} else {
|
||||||
// copy constructor if exists (even for non same types)
|
// copy constructor if exists (even for non same types)
|
||||||
if (methodExists(children[0]->getDataRef()->valueType, "copy_construct", std::vector<Type>{children[1]->getDataRef()->valueType->withIncreasedIndirection()})) {
|
if (methodExists(children[0]->getDataRef()->valueType, "copy_construct", std::vector<Type>{children[1]->getDataRef()->valueType->withIncreasedIndirection()})) {
|
||||||
CCodeTriple toAssign = generate(children[1], enclosingObject, true);
|
CCodeTriple toAssign = generate(children[1], enclosingObject, true, enclosingFunction);
|
||||||
std::string assignedTo = generate(children[0], enclosingObject, justFuncName).oneString();
|
std::string assignedTo = generate(children[0], enclosingObject, justFuncName, enclosingFunction).oneString();
|
||||||
output.value = toAssign.preValue;
|
output.value = toAssign.preValue;
|
||||||
output.value += ValueTypeToCType(children[0]->getData().valueType, assignedTo) + ";\n";
|
output.value += ValueTypeToCType(children[0]->getData().valueType, assignedTo) + ";\n";
|
||||||
// we put the thing about to be copy constructed in a variable so we can for sure take its address
|
// we put the thing about to be copy constructed in a variable so we can for sure take its address
|
||||||
@@ -492,14 +516,14 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
|
|||||||
output.value += toAssign.postValue;
|
output.value += toAssign.postValue;
|
||||||
return output;
|
return output;
|
||||||
} else {
|
} else {
|
||||||
return ValueTypeToCType(children[0]->getData().valueType, generate(children[0], enclosingObject, justFuncName).oneString()) + " = " + generate(children[1], enclosingObject, true) + ";";
|
return ValueTypeToCType(children[0]->getData().valueType, generate(children[0], enclosingObject, justFuncName, enclosingFunction).oneString()) + " = " + generate(children[1], enclosingObject, true, enclosingFunction) + ";";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case if_comp:
|
case if_comp:
|
||||||
// Lol, this doesn't work because the string gets prefixed now
|
// Lol, this doesn't work because the string gets prefixed now
|
||||||
//if (generate(children[0], enclosingObject) == generatorString)
|
//if (generate(children[0], enclosingObject, enclosingFunction) == generatorString)
|
||||||
if (children[0]->getDataRef()->symbol.getName() == generatorString)
|
if (children[0]->getDataRef()->symbol.getName() == generatorString)
|
||||||
return generate(children[1], enclosingObject, justFuncName);
|
return generate(children[1], enclosingObject, justFuncName, enclosingFunction);
|
||||||
return CCodeTriple("");
|
return CCodeTriple("");
|
||||||
case simple_passthrough:
|
case simple_passthrough:
|
||||||
{
|
{
|
||||||
@@ -513,23 +537,23 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
|
|||||||
auto assignChildren = assign->getChildren();
|
auto assignChildren = assign->getChildren();
|
||||||
if (in_or_out->getDataRef()->type == in_passthrough_params)
|
if (in_or_out->getDataRef()->type == in_passthrough_params)
|
||||||
if (assignChildren.size() == 2)
|
if (assignChildren.size() == 2)
|
||||||
pre_passthrough += ValueTypeToCType(assignChildren[0]->getDataRef()->valueType, assignChildren[1]->getDataRef()->symbol.getName()) + " = " + generate(assignChildren[0], enclosingObject).oneString() + ";\n";
|
pre_passthrough += ValueTypeToCType(assignChildren[0]->getDataRef()->valueType, assignChildren[1]->getDataRef()->symbol.getName()) + " = " + generate(assignChildren[0], enclosingObject, enclosingFunction).oneString() + ";\n";
|
||||||
else
|
else
|
||||||
pre_passthrough += ValueTypeToCType(assignChildren[0]->getDataRef()->valueType, assignChildren[0]->getDataRef()->symbol.getName()) + " = " + generate(assignChildren[0], enclosingObject).oneString() + ";\n";
|
pre_passthrough += ValueTypeToCType(assignChildren[0]->getDataRef()->valueType, assignChildren[0]->getDataRef()->symbol.getName()) + " = " + generate(assignChildren[0], enclosingObject, enclosingFunction).oneString() + ";\n";
|
||||||
else if (in_or_out->getDataRef()->type == out_passthrough_params)
|
else if (in_or_out->getDataRef()->type == out_passthrough_params)
|
||||||
if (assignChildren.size() == 2)
|
if (assignChildren.size() == 2)
|
||||||
post_passthrough += generate(assignChildren[0], enclosingObject, justFuncName).oneString() + " = " + assignChildren[1]->getDataRef()->symbol.getName() + ";\n";
|
post_passthrough += generate(assignChildren[0], enclosingObject, justFuncName, enclosingFunction).oneString() + " = " + assignChildren[1]->getDataRef()->symbol.getName() + ";\n";
|
||||||
else
|
else
|
||||||
post_passthrough += generate(assignChildren[0], enclosingObject, justFuncName).oneString() + " = " + assignChildren[0]->getDataRef()->symbol.getName() + ";\n";
|
post_passthrough += generate(assignChildren[0], enclosingObject, justFuncName, enclosingFunction).oneString() + " = " + assignChildren[0]->getDataRef()->symbol.getName() + ";\n";
|
||||||
else
|
else
|
||||||
linkerString += " " + strSlice(generate(in_or_out, enclosingObject, justFuncName).oneString(), 1, -2) + " ";
|
linkerString += " " + strSlice(generate(in_or_out, enclosingObject, justFuncName, enclosingFunction).oneString(), 1, -2) + " ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// The actual passthrough string is the last child now, as we might
|
// The actual passthrough string is the last child now, as we might
|
||||||
// have passthrough_params be the first child
|
// have passthrough_params be the first child
|
||||||
// we don't generate, as that will escape the returns and we don't want that. We'll just grab the string
|
// we don't generate, as that will escape the returns and we don't want that. We'll just grab the string
|
||||||
//return pre_passthrough + strSlice(generate(children.back(), enclosingObject, justFuncName).oneString(), 3, -4) + post_passthrough;
|
//return pre_passthrough + strSlice(generate(children.back(, enclosingFunction), enclosingObject, justFuncName).oneString(), 3, -4) + post_passthrough;
|
||||||
return pre_passthrough + strSlice(children.back()->getDataRef()->symbol.getName(), 3, -4) + post_passthrough;
|
return pre_passthrough + strSlice(children.back()->getDataRef()->symbol.getName(), 3, -4) + post_passthrough;
|
||||||
}
|
}
|
||||||
case function_call:
|
case function_call:
|
||||||
@@ -542,22 +566,28 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
|
|||||||
// std::cout << name << " == " << children[0]->getData().symbol.getName() << std::endl;
|
// std::cout << name << " == " << children[0]->getData().symbol.getName() << std::endl;
|
||||||
std::string name = children[0]->getDataRef()->symbol.getName();
|
std::string name = children[0]->getDataRef()->symbol.getName();
|
||||||
ASTType funcType = children[0]->getDataRef()->type;
|
ASTType funcType = children[0]->getDataRef()->type;
|
||||||
|
|
||||||
|
// UGLLLLYYYY
|
||||||
|
// But we have these here because some stuff has to be moved out of the giant nested blocks below and this is the way to do it
|
||||||
|
CCodeTriple functionCallSource;
|
||||||
|
bool doClosureInstead = false;
|
||||||
|
|
||||||
//std::cout << "Doing function: " << name << std::endl;
|
//std::cout << "Doing function: " << name << std::endl;
|
||||||
//Test for special functions only if what we're testing is, indeed, the definition, not a function call that returns a callable function pointer
|
//Test for special functions only if what we're testing is, indeed, the definition, not a function call that returns a callable function pointer
|
||||||
if (funcType == function) {
|
if (funcType == function) {
|
||||||
if (name == "++" || name == "--")
|
if (name == "++" || name == "--")
|
||||||
return generate(children[1], enclosingObject, true) + name;
|
return generate(children[1], enclosingObject, true, enclosingFunction) + name;
|
||||||
if ( (name == "*" || name == "&" || name == "!" || name == "-" || name == "+" ) && children.size() == 2) //Is dereference, not multiplication, address-of, or other unary operator
|
if ( (name == "*" || name == "&" || name == "!" || name == "-" || name == "+" ) && children.size() == 2) //Is dereference, not multiplication, address-of, or other unary operator
|
||||||
return name + "(" + generate(children[1], enclosingObject, true) + ")";
|
return name + "(" + generate(children[1], enclosingObject, true, enclosingFunction) + ")";
|
||||||
if (name == "[]")
|
if (name == "[]")
|
||||||
return "(" + generate(children[1], enclosingObject, true) + ")[" + generate(children[2],enclosingObject, true) + "]";
|
return "(" + generate(children[1], enclosingObject, true, enclosingFunction) + ")[" + generate(children[2],enclosingObject, true, enclosingFunction) + "]";
|
||||||
if (name == "+" || name == "-" || name == "*" || name == "/" || name == "==" || name == ">=" || name == "<=" || name == "!="
|
if (name == "+" || name == "-" || name == "*" || name == "/" || name == "==" || name == ">=" || name == "<=" || name == "!="
|
||||||
|| name == "<" || name == ">" || name == "%" || name == "=" || name == "+=" || name == "-=" || name == "*=" || name == "/=" || name == "||"
|
|| name == "<" || name == ">" || name == "%" || name == "=" || name == "+=" || name == "-=" || name == "*=" || name == "/=" || name == "||"
|
||||||
|| name == "&&") {
|
|| name == "&&") {
|
||||||
return "((" + generate(children[1], enclosingObject, true) + ")" + name + "(" + generate(children[2], enclosingObject, true) + "))";
|
return "((" + generate(children[1], enclosingObject, true, enclosingFunction) + ")" + name + "(" + generate(children[2], enclosingObject, true, enclosingFunction) + "))";
|
||||||
} else if (name == "." || name == "->") {
|
} else if (name == "." || name == "->") {
|
||||||
if (children.size() == 1)
|
if (children.size() == 1)
|
||||||
return "/*dot operation with one child*/" + generate(children[0], enclosingObject, true).oneString() + "/*end one child*/";
|
return "/*dot operation with one child*/" + generate(children[0], enclosingObject, true, enclosingFunction).oneString() + "/*end one child*/";
|
||||||
//If this is accessing an actual function, find the function in scope and take the appropriate action. Probabally an object method
|
//If this is accessing an actual function, find the function in scope and take the appropriate action. Probabally an object method
|
||||||
if (children[2]->getDataRef()->type == function) {
|
if (children[2]->getDataRef()->type == function) {
|
||||||
std::string functionName = children[2]->getDataRef()->symbol.getName();
|
std::string functionName = children[2]->getDataRef()->symbol.getName();
|
||||||
@@ -573,20 +603,20 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
|
|||||||
nameDecoration += "_" + ValueTypeToCTypeDecoration(functionDefChildren[i]->getData().valueType);
|
nameDecoration += "_" + ValueTypeToCTypeDecoration(functionDefChildren[i]->getData().valueType);
|
||||||
// Note that we only add scoping to the object, as this specifies our member function too
|
// Note that we only add scoping to the object, as this specifies our member function too
|
||||||
/*HERE*/ return function_header + scopePrefix(unaliasedTypeDef) + CifyName(unaliasedTypeDef->getDataRef()->symbol.getName()) +"__" +
|
/*HERE*/ return function_header + scopePrefix(unaliasedTypeDef) + CifyName(unaliasedTypeDef->getDataRef()->symbol.getName()) +"__" +
|
||||||
CifyName(functionName + nameDecoration) + "(" + (name == "." ? "&" : "") + generate(children[1], enclosingObject, true) + ",";
|
CifyName(functionName + nameDecoration) + "(" + (name == "." ? "&" : "") + generate(children[1], enclosingObject, true, enclosingFunction) + ",";
|
||||||
//The comma lets the upper function call know we already started the param list
|
//The comma lets the upper function call know we already started the param list
|
||||||
//Note that we got here from a function call. We just pass up this special case and let them finish with the perentheses
|
//Note that we got here from a function call. We just pass up this special case and let them finish with the perentheses
|
||||||
} else {
|
} else {
|
||||||
std::cout << "Is not in scope or not type" << std::endl;
|
std::cout << "Is not in scope or not type" << std::endl;
|
||||||
return "((" + generate(children[1], enclosingObject, true) + ")" + name + functionName + ")";
|
return "((" + generate(children[1], enclosingObject, true, enclosingFunction) + ")" + name + functionName + ")";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
std::cout << "Is not in scope or not type" << std::endl;
|
std::cout << "Is not in scope or not type" << std::endl;
|
||||||
return "((" + generate(children[1], enclosingObject, true) + ")" + name + functionName + ")";
|
return "((" + generate(children[1], enclosingObject, true, enclosingFunction) + ")" + name + functionName + ")";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//return "((" + generate(children[1], enclosingObject) + ")" + name + generate(children[2], enclosingObject) + ")";
|
//return "((" + generate(children[1], enclosingObject, enclosingFunction) + ")" + name + generate(children[2], enclosingObject, enclosingFunction) + ")";
|
||||||
return "((" + generate(children[1], enclosingObject, true) + ")" + name + generate(children[2], nullptr, true) + ")";
|
return "((" + generate(children[1], enclosingObject, true, enclosingFunction) + ")" + name + generate(children[2], nullptr, true, enclosingFunction) + ")";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//It's a normal function call, not a special one or a method or anything. Name decorate.
|
//It's a normal function call, not a special one or a method or anything. Name decorate.
|
||||||
@@ -608,29 +638,48 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
|
|||||||
} else {
|
} else {
|
||||||
//This part handles cases where our definition isn't the function definition (that is, it is probabally the return from another function)
|
//This part handles cases where our definition isn't the function definition (that is, it is probabally the return from another function)
|
||||||
//It's probabally the result of an access function call (. or ->) to access an object method.
|
//It's probabally the result of an access function call (. or ->) to access an object method.
|
||||||
CCodeTriple functionCallSource = generate(children[0], enclosingObject, true);
|
//OR a function value!
|
||||||
|
//
|
||||||
|
//THIS IS UUUUUGLLYYY too. We moved the closure part out to after the generation of the params becuase it needs to use them twice
|
||||||
|
functionCallSource = generate(children[0], enclosingObject, true, enclosingFunction);
|
||||||
if (functionCallSource.value[functionCallSource.value.size()-1] == ',') //If it's a member method, it's already started the parameter list.
|
if (functionCallSource.value[functionCallSource.value.size()-1] == ',') //If it's a member method, it's already started the parameter list.
|
||||||
output += children.size() > 1 ? functionCallSource : CCodeTriple(functionCallSource.preValue, functionCallSource.value.substr(0, functionCallSource.value.size()-1), functionCallSource.postValue);
|
output += children.size() > 1 ? functionCallSource : CCodeTriple(functionCallSource.preValue, functionCallSource.value.substr(0, functionCallSource.value.size()-1), functionCallSource.postValue);
|
||||||
else
|
else {
|
||||||
output += functionCallSource + "(";
|
doClosureInstead = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
CCodeTriple parameters;
|
||||||
// see if we should copy_construct all the parameters
|
// see if we should copy_construct all the parameters
|
||||||
for (int i = 1; i < children.size(); i++) { //children[0] is the declaration
|
for (int i = 1; i < children.size(); i++) { //children[0] is the declaration
|
||||||
if (methodExists(children[i]->getDataRef()->valueType, "copy_construct", std::vector<Type>{children[i]->getDataRef()->valueType->withIncreasedIndirection()})) {
|
if (methodExists(children[i]->getDataRef()->valueType, "copy_construct", std::vector<Type>{children[i]->getDataRef()->valueType->withIncreasedIndirection()})) {
|
||||||
std::string tmpParamName = "param" + getID();
|
std::string tmpParamName = "param" + getID();
|
||||||
CCodeTriple paramValue = generate(children[i], enclosingObject, true);
|
CCodeTriple paramValue = generate(children[i], enclosingObject, true, enclosingFunction);
|
||||||
output.preValue += paramValue.preValue;
|
parameters.preValue += paramValue.preValue;
|
||||||
output.preValue += ValueTypeToCType(children[i]->getDataRef()->valueType, tmpParamName) + ";\n";
|
parameters.preValue += ValueTypeToCType(children[i]->getDataRef()->valueType, tmpParamName) + ";\n";
|
||||||
output.preValue += generateMethodIfExists(children[i]->getDataRef()->valueType, "copy_construct", "&"+tmpParamName + ", &" + paramValue.value, std::vector<Type>{children[i]->getDataRef()->valueType->withIncreasedIndirection()});
|
parameters.preValue += generateMethodIfExists(children[i]->getDataRef()->valueType, "copy_construct", "&"+tmpParamName + ", &" + paramValue.value, std::vector<Type>{children[i]->getDataRef()->valueType->withIncreasedIndirection()});
|
||||||
output.value += tmpParamName;
|
parameters.value += tmpParamName;
|
||||||
output.postValue += paramValue.postValue;
|
parameters.postValue += paramValue.postValue;
|
||||||
} else {
|
} else {
|
||||||
output += generate(children[i], enclosingObject, true);
|
parameters += generate(children[i], enclosingObject, true, enclosingFunction);
|
||||||
}
|
}
|
||||||
if (i < children.size()-1)
|
if (i < children.size()-1)
|
||||||
output += ", ";
|
parameters += ", ";
|
||||||
|
}
|
||||||
|
if (doClosureInstead) {
|
||||||
|
Type* funcType = children[0]->getDataRef()->valueType;
|
||||||
|
Type* retType = funcType->returnType;
|
||||||
|
bool doRet = retType->baseType != void_type || retType->getIndirection();
|
||||||
|
std::string tmpName = "functionValueTmp" + getID();
|
||||||
|
std::string retTmpName = "closureRetTemp" + getID();
|
||||||
|
output += CCodeTriple(parameters.preValue + functionCallSource.preValue + ValueTypeToCType(funcType, tmpName) + " = " + functionCallSource.value + ";\n"
|
||||||
|
+ (doRet ? ValueTypeToCType(retType, retTmpName) + ";\n" : "")
|
||||||
|
+ "if (" + tmpName + ".val) { " + (doRet ? (retTmpName + " =") : "") + " (("+ ValueTypeToCTypeDecoration(funcType,ClosureFunctionPointerTypeWithClosedParam) +") (" + tmpName + ".func))(" + tmpName + ".val" + (children.size() > 1 ? ", " : "") + parameters.value + "); }\n"
|
||||||
|
+ "else { " + (doRet ? (retTmpName + " = ") : "") + tmpName + ".func(" + parameters.value + "); }\n",
|
||||||
|
(doRet ? retTmpName : ""),
|
||||||
|
parameters.postValue + functionCallSource.postValue);
|
||||||
|
} else {
|
||||||
|
output += parameters + ") ";
|
||||||
}
|
}
|
||||||
output += ") ";
|
|
||||||
// see if we should add a destructer call to this postValue
|
// see if we should add a destructer call to this postValue
|
||||||
Type* retType = children[0]->getDataRef()->valueType->returnType;
|
Type* retType = children[0]->getDataRef()->valueType->returnType;
|
||||||
if (methodExists(retType, "destruct", std::vector<Type>())) {
|
if (methodExists(retType, "destruct", std::vector<Type>())) {
|
||||||
@@ -665,7 +714,7 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
|
|||||||
std::cout << "Nothing!" << std::endl;
|
std::cout << "Nothing!" << std::endl;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < children.size(); i++)
|
for (int i = 0; i < children.size(); i++)
|
||||||
output += generate(children[i], enclosingObject, justFuncName).oneString();
|
output += generate(children[i], enclosingObject, justFuncName, enclosingFunction).oneString();
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
@@ -754,9 +803,9 @@ std::string CGenerator::emitDestructors(std::vector<NodeTree<ASTData>*> identifi
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string CGenerator::ValueTypeToCType(Type *type, std::string declaration) { return ValueTypeToCTypeThingHelper(type, " " + declaration); }
|
std::string CGenerator::ValueTypeToCType(Type *type, std::string declaration, ClosureTypeSpecialType closureSpecial) { return ValueTypeToCTypeThingHelper(type, " " + declaration, closureSpecial); }
|
||||||
std::string CGenerator::ValueTypeToCTypeDecoration(Type *type) { return CifyName(ValueTypeToCTypeThingHelper(type, "")); }
|
std::string CGenerator::ValueTypeToCTypeDecoration(Type *type, ClosureTypeSpecialType closureSpecial) { return CifyName(ValueTypeToCTypeThingHelper(type, "", closureSpecial)); }
|
||||||
std::string CGenerator::ValueTypeToCTypeThingHelper(Type *type, std::string declaration) {
|
std::string CGenerator::ValueTypeToCTypeThingHelper(Type *type, std::string declaration, ClosureTypeSpecialType closureSpecial) {
|
||||||
std::string return_type;
|
std::string return_type;
|
||||||
bool do_ending = true;
|
bool do_ending = true;
|
||||||
switch (type->baseType) {
|
switch (type->baseType) {
|
||||||
@@ -769,20 +818,49 @@ std::string CGenerator::ValueTypeToCTypeThingHelper(Type *type, std::string decl
|
|||||||
case function_type:
|
case function_type:
|
||||||
{
|
{
|
||||||
std::string indr_str;
|
std::string indr_str;
|
||||||
std::string typedefStr = "typedef ";
|
|
||||||
std::string typedefID = "ID" + CifyName(type->toString(false));
|
|
||||||
for (int i = 0; i < type->getIndirection(); i++)
|
for (int i = 0; i < type->getIndirection(); i++)
|
||||||
indr_str += "*";
|
indr_str += "*";
|
||||||
typedefStr += ValueTypeToCTypeThingHelper(type->returnType, "");
|
|
||||||
typedefStr += " (*" + typedefID + ")(";
|
auto it = functionTypedefMap.find(*type);
|
||||||
if (type->parameterTypes.size() == 0)
|
if (it != functionTypedefMap.end()) {
|
||||||
typedefStr += "void";
|
if (closureSpecial == ClosureFunctionPointerTypeWithClosedParam)
|
||||||
else
|
return_type = it->second.second + declaration;
|
||||||
for (int i = 0; i < type->parameterTypes.size(); i++)
|
else
|
||||||
typedefStr += (i != 0 ? ", " : "") + ValueTypeToCTypeThingHelper(type->parameterTypes[i], "");
|
return_type = it->second.first + declaration;
|
||||||
typedefStr += ");\n";
|
} else {
|
||||||
functionTypedefString += typedefStr;
|
std::string typedefWithoutVoidStr = "typedef ";
|
||||||
return_type = typedefID + indr_str + " " + declaration;
|
std::string typedefWithVoidStr = "typedef ";
|
||||||
|
std::string typedefWithoutVoidID = "ID_novoid_" + CifyName(type->toString(false));
|
||||||
|
std::string typedefWithVoidID = "ID_withvoid_" + CifyName(type->toString(false));
|
||||||
|
std::string typedefStructID = "ID_struct_" + CifyName(type->toString(false));
|
||||||
|
|
||||||
|
std::string typedefStructStr = "typedef struct {" + typedefWithoutVoidID + " func; void* val; } " + typedefStructID + ";\n";
|
||||||
|
|
||||||
|
typedefWithoutVoidStr += ValueTypeToCTypeThingHelper(type->returnType, "", closureSpecial);
|
||||||
|
typedefWithVoidStr += ValueTypeToCTypeThingHelper(type->returnType, "", closureSpecial);
|
||||||
|
typedefWithoutVoidStr += " (*" + typedefWithoutVoidID + ")(";
|
||||||
|
typedefWithVoidStr += " (*" + typedefWithVoidID + ")(";
|
||||||
|
|
||||||
|
typedefWithVoidStr += "void*";
|
||||||
|
if (type->parameterTypes.size() == 0)
|
||||||
|
typedefWithoutVoidStr += "void";
|
||||||
|
else
|
||||||
|
for (int i = 0; i < type->parameterTypes.size(); i++) {
|
||||||
|
typedefWithoutVoidStr += (i != 0 ? ", " : "") + ValueTypeToCTypeThingHelper(type->parameterTypes[i], "", closureSpecial);
|
||||||
|
typedefWithVoidStr += ", " + ValueTypeToCTypeThingHelper(type->parameterTypes[i], "", closureSpecial);
|
||||||
|
}
|
||||||
|
typedefWithoutVoidStr += ");\n";
|
||||||
|
typedefWithVoidStr += ");\n";
|
||||||
|
functionTypedefString += typedefWithoutVoidStr;
|
||||||
|
functionTypedefString += typedefWithVoidStr;
|
||||||
|
functionTypedefString += typedefStructStr;
|
||||||
|
if (closureSpecial == ClosureFunctionPointerTypeWithClosedParam)
|
||||||
|
return_type = typedefWithVoidID + indr_str + declaration;
|
||||||
|
else
|
||||||
|
return_type = typedefStructID + indr_str + declaration;
|
||||||
|
|
||||||
|
functionTypedefMap[*type] = std::make_pair(typedefStructID, typedefWithVoidID);
|
||||||
|
}
|
||||||
do_ending = false;
|
do_ending = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
+37
-1
@@ -83,12 +83,48 @@ Type::~Type() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const bool Type::operator==(const Type &other) const {
|
const bool Type::operator==(const Type &other) const {
|
||||||
return( baseType == other.baseType && indirection == other.indirection && typeDefinition == other.typeDefinition && templateDefinition == other.templateDefinition && other.traits == traits);
|
bool first_part = ( baseType == other.baseType && indirection == other.indirection && typeDefinition == other.typeDefinition && templateDefinition == other.templateDefinition && other.traits == traits);
|
||||||
|
if (!first_part)
|
||||||
|
return false;
|
||||||
|
if ((returnType && !other.returnType) || (!returnType && other.returnType))
|
||||||
|
return false;
|
||||||
|
if (returnType && other.returnType)
|
||||||
|
if (*returnType != *other.returnType)
|
||||||
|
return false;
|
||||||
|
if (parameterTypes.size() != other.parameterTypes.size())
|
||||||
|
return false;
|
||||||
|
for (int i = 0; i < parameterTypes.size(); i++)
|
||||||
|
if (*parameterTypes[i] != *other.parameterTypes[i])
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool Type::operator!=(const Type &other) const {
|
const bool Type::operator!=(const Type &other) const {
|
||||||
return(!this->operator==(other));
|
return(!this->operator==(other));
|
||||||
}
|
}
|
||||||
|
const bool Type::operator<(const Type &other) const {
|
||||||
|
if (baseType != other.baseType)
|
||||||
|
return baseType < other.baseType;
|
||||||
|
if (indirection != other.indirection)
|
||||||
|
return indirection < other.indirection;
|
||||||
|
if (typeDefinition != other.typeDefinition)
|
||||||
|
return typeDefinition < other.typeDefinition;
|
||||||
|
if (templateDefinition != other.templateDefinition)
|
||||||
|
return templateDefinition < other.templateDefinition;
|
||||||
|
if (traits != other.traits)
|
||||||
|
return traits < other.traits;
|
||||||
|
if ((returnType && !other.returnType) || (!returnType && other.returnType))
|
||||||
|
return returnType < other.returnType;
|
||||||
|
if (returnType && other.returnType)
|
||||||
|
if (*returnType != *other.returnType)
|
||||||
|
return *returnType < *other.returnType;
|
||||||
|
if (parameterTypes.size() != other.parameterTypes.size())
|
||||||
|
return parameterTypes.size() < other.parameterTypes.size();
|
||||||
|
for (int i = 0; i < parameterTypes.size(); i++)
|
||||||
|
if (*parameterTypes[i] != *other.parameterTypes[i])
|
||||||
|
return *parameterTypes[i] < *other.parameterTypes[i];
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
std::string Type::toString(bool showTraits) {
|
std::string Type::toString(bool showTraits) {
|
||||||
std::string typeString;
|
std::string typeString;
|
||||||
|
|||||||
+19
-16
@@ -4,26 +4,29 @@ fun runLambda(func: fun():int):void {
|
|||||||
println(func())
|
println(func())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun callLambda(func: fun(int):void):void {
|
fun somethingElse():int { return 4; }
|
||||||
func(10)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun itr<T>(it: T, func: fun(T):T):T {
|
//fun callLambda(func: fun(int):void):void {
|
||||||
println(it)
|
//func(10)
|
||||||
return func(it);
|
//}
|
||||||
}
|
|
||||||
|
//fun itr<T>(it: T, func: fun(T):T):T {
|
||||||
|
//println(it)
|
||||||
|
//return func(it);
|
||||||
|
//}
|
||||||
|
|
||||||
fun main():int {
|
fun main():int {
|
||||||
var func = fun():void { println("8"); }
|
//var func = fun():void { println("8"); }
|
||||||
func()
|
//func()
|
||||||
runLambda(fun():int { return 9;})
|
//runLambda(fun():int { return 9;})
|
||||||
callLambda(fun(a:int):void { println(a);})
|
//callLambda(fun(a:int):void { println(a);})
|
||||||
var j = 0
|
//var j = 0
|
||||||
while (j < 10) j = itr(j, fun(a:int):int { return a+1; })
|
//while (j < 10) j = itr(j, fun(a:int):int { return a+1; })
|
||||||
|
|
||||||
//println("closures now")
|
runLambda(somethingElse)
|
||||||
//var a = 1337
|
println("closures now")
|
||||||
//runLambda(fun():int { return a;})
|
var a = 1337
|
||||||
|
runLambda(fun():int { return a;})
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
Reference in new issue
Block a user