Fixed a limitToFunction bug or two, work on ADTs

This commit is contained in:
Nathan Braswell
2015-11-06 03:23:55 -05:00
parent 13c6044193
commit fcc0e770a5
8 changed files with 313 additions and 188 deletions

View File

@@ -17,19 +17,22 @@ void CGenerator::generateCompSet(std::map<std::string, NodeTree<ASTData>*> ASTs,
std::cout << "\n\n =====GENERATE PASS===== \n\n" << std::endl;
std::cout << "\n\nGenerate pass for: " << outputName << std::endl;
buildString += outputName + ".c ";
std::ofstream outputCFile, outputHFile;
//std::ofstream outputCFile, outputHFile;
std::ofstream outputCFile;
outputCFile.open(outputName + "/" + outputName + ".c");
outputHFile.open(outputName + "/" + outputName + ".h");
if (outputCFile.is_open() || outputHFile.is_open()) {
//outputHFile.open(outputName + "/" + outputName + ".h");
//if (outputCFile.is_open() || outputHFile.is_open()) {
if (outputCFile.is_open()) {
// Prequel common to all files
auto chPair = generateTranslationUnit(outputName, ASTs);
outputHFile << "#include <stdbool.h>\n#include <stdlib.h>\n#include <stdio.h>\n" << chPair.first;
outputCFile << "#include \"" + outputName + ".h\"\n\n" << chPair.second;
//outputHFile << "#include <stdbool.h>\n#include <stdlib.h>\n#include <stdio.h>\n" << chPair.first;
//outputCFile << "#include \"" + outputName + ".h\"\n\n" << chPair.second;
outputCFile << "#include <stdbool.h>\n#include <stdlib.h>\n#include <stdio.h>\n" << chPair.first << "\n\n// C FILE BEGIN\n\n" << chPair.second;
} else {
std::cerr << "Cannot open file " << outputName << ".c/h" << std::endl;
}
outputCFile.close();
outputHFile.close();
//outputHFile.close();
buildString += linkerString;
buildString += "-o " + outputName;
@@ -54,150 +57,186 @@ std::string CGenerator::getID() {
std::string CGenerator::generateTypeStruct(NodeTree<ASTData>* from) {
auto data = from->getData();
auto children = from->getChildren();
std::string objectString;
if (data.type == type_def)
objectString = "struct __struct_dummy_";
else if (data.type == adt_def)
objectString = "enum __adt_dummy_";
objectString += scopePrefix(from) + CifyName(data.symbol.getName()) + "__ {\n";
std::string structString, enumString, functionString;
std::string enumName = "__enum_dummy_" + prefixIfNeeded(scopePrefix(from), CifyName(data.symbol.getName())+"__");
enumString = "enum " + enumName + " {\n";
structString = "struct __struct_dummy_";
structString += prefixIfNeeded(scopePrefix(from), CifyName(data.symbol.getName())+"__") + " {\n";
if (data.type == adt_def) {
structString = "typedef " + structString + "enum " + enumName + " flag;\n union { \n";
}
tabLevel++;
for (int i = (data.type == adt_def ? 1 : 0); i < children.size(); i++) {
for (auto child : children) {
//std::cout << children[i]->getName() << std::endl;
if (children[i]->getName() != "function")
objectString += tabs() + generate(children[i], nullptr).oneString() + (data.type == adt_def ? ",\n" : "\n");
if (child->getName() != "function") {
if (data.type == adt_def) {
// if this is not a plain no-data adt member (so if it is a primitive or doesn't have a reference back to)
// wait a sec, this is easier
if ( child->getDataRef()->valueType->typeDefinition != from)
structString += tabs() + ValueTypeToCType(child->getDataRef()->valueType, child->getDataRef()->symbol.getName()) + "; /* adt data member */\n";
} else {
structString += tabs() + generate(child, nullptr).oneString() + "\n";
}
enumString += tabs() + generate(child, nullptr).oneString() + (data.type == adt_def ? ",\n" : "\n");
} else {
if (data.type == adt_def) {
functionString += "\n" + ValueTypeToCType(child->getDataRef()->valueType->returnType, "fun_" + child->getDataRef()->symbol.getName()) + "(" +
(child->getDataRef()->valueType->parameterTypes.size() ? ValueTypeToCType(child->getDataRef()->valueType->parameterTypes[0], "in") : "") + "); /*adt func*/\n";
}
}
}
tabLevel--;
objectString += "};";
return objectString;
if (data.type == adt_def) {
//structString += "} data; /*end union*/ \n";
structString += "}; /*end union*/\n } " + CifyName(data.symbol.getName()) + "; /* end struct */";
} else {
structString += "};";
}
enumString += "};\n";
if (data.type == adt_def)
return enumString + structString + functionString;
return structString;
}
// This method recurseivly generates all aliases of some definition
std::string CGenerator::generateAliasChains(std::map<std::string, NodeTree<ASTData>*> ASTs, NodeTree<ASTData>* definition) {
std::string output;
for (auto trans : ASTs) {
for (auto i = trans.second->getDataRef()->scope.begin(); i != trans.second->getDataRef()->scope.end(); i++) {
for (auto declaration : i->second) {
auto declarationData = declaration->getDataRef();
if (declarationData->type == type_def
&& declarationData->valueType->typeDefinition != declaration
&& declarationData->valueType->typeDefinition == definition) {
output += "typedef " +
scopePrefix(definition) + CifyName(definition->getDataRef()->symbol.getName()) + " " +
scopePrefix(declaration) + CifyName(declarationData->symbol.getName()) + ";\n";
// Recursively add the ones that depend on this one
output += generateAliasChains(ASTs, declaration);
}
std::string output;
for (auto trans : ASTs) {
for (auto i = trans.second->getDataRef()->scope.begin(); i != trans.second->getDataRef()->scope.end(); i++) {
for (auto declaration : i->second) {
auto declarationData = declaration->getDataRef();
if (declarationData->type == type_def
&& declarationData->valueType->typeDefinition != declaration
&& declarationData->valueType->typeDefinition == definition) {
output += "typedef " +
prefixIfNeeded(scopePrefix(definition), CifyName(definition->getDataRef()->symbol.getName())) + " " +
prefixIfNeeded(scopePrefix(declaration), CifyName(declarationData->symbol.getName())) + ";\n";
// Recursively add the ones that depend on this one
output += generateAliasChains(ASTs, declaration);
}
}
}
return output;
}
return output;
}
bool CGenerator::isUnderNodeWithType(NodeTree<ASTData>* from, ASTType type) {
auto scope = from->getDataRef()->scope;
auto upper = scope.find("~enclosing_scope");
if (upper != scope.end()) {
if (upper->second[0]->getDataRef()->type == type)
return true;
return isUnderNodeWithType(upper->second[0], type);
}
return false;
}
bool CGenerator::isUnderTranslationUnit(NodeTree<ASTData>* from, NodeTree<ASTData>* node) {
auto scope = from->getDataRef()->scope;
for (auto i : scope)
for (auto j : i.second)
if (j == node)
return true;
auto scope = from->getDataRef()->scope;
for (auto i : scope)
for (auto j : i.second)
if (j == node)
return true;
auto upper = scope.find("~enclosing_scope");
if (upper != scope.end())
return isUnderTranslationUnit(upper->second[0], node);
return false;
auto upper = scope.find("~enclosing_scope");
if (upper != scope.end())
return isUnderTranslationUnit(upper->second[0], node);
return false;
}
NodeTree<ASTData>* CGenerator::highestScope(NodeTree<ASTData>* node) {
auto it = node->getDataRef()->scope.find("~enclosing_scope");
while (it != node->getDataRef()->scope.end()) {
node = it->second[0];
it = node->getDataRef()->scope.find("~enclosing_scope");
}
return node;
auto it = node->getDataRef()->scope.find("~enclosing_scope");
while (it != node->getDataRef()->scope.end()) {
node = it->second[0];
it = node->getDataRef()->scope.find("~enclosing_scope");
}
return node;
}
// We do translation units in their own function so they can do the pariwise h/c stuff and regualr in function body generation does not
std::pair<std::string, std::string> CGenerator::generateTranslationUnit(std::string name, std::map<std::string, NodeTree<ASTData>*> ASTs) {
// We now pass in the entire map of ASTs and loop through them so that we generate out into a single file
std::string cOutput, hOutput;
// Ok, so we've got to do this in passes to preserve mututally recursive definitions.
//
// First Pass: All classes get "struct dummy_thing; typedef struct dummy_thing thing;".
// Also, other typedefs follow after their naming.
// Second Pass: All top level variable declarations
// Third Pass: Define all actual structs of a class, in correct order (done with posets)
// Fourth Pass: Declare all function prototypes (as functions may be mutually recursive too).
// (this includes object methods)
// Fifth Pass: Define all functions (including object methods).
// We now pass in the entire map of ASTs and loop through them so that we generate out into a single file
std::string cOutput, hOutput;
// Ok, so we've got to do this in passes to preserve mututally recursive definitions.
//
// First Pass: All classes get "struct dummy_thing; typedef struct dummy_thing thing;".
// Also, other typedefs follow after their naming.
// Second Pass: All top level variable declarations
// Third Pass: Define all actual structs of a class, in correct order (done with posets)
// Fourth Pass: Declare all function prototypes (as functions may be mutually recursive too).
// (this includes object methods)
// Fifth Pass: Define all functions (including object methods).
// However, most of these do not actually have to be done as separate passes. First, second, fourth, and fifth
// are done simultanously, but append to different strings that are then concatinated properly, in order.
// However, most of these do not actually have to be done as separate passes. First, second, fourth, and fifth
// are done simultanously, but append to different strings that are then concatinated properly, in order.
std::string importIncludes = "/**\n * Import Includes\n */\n\n";
std::string topLevelCPassthrough = "/**\n * Top Level C Passthrough\n */\n\n";
std::string variableExternDeclarations = "/**\n * Extern Variable Declarations \n */\n\n";
std::string plainTypedefs = "/**\n * Plain Typedefs\n */\n\n";
std::string variableDeclarations = "/**\n * Variable Declarations \n */\n\n";
std::string classStructs = "/**\n * Class Structs\n */\n\n";
std::string functionPrototypes = "/**\n * Function Prototypes\n */\n\n";
std::string functionDefinitions = "/**\n * Function Definitions\n */\n\n";
// There also exists functionTypedefString which is a member variable that keeps
// track of utility typedefs that allow our C type generation to be more sane
// it is emitted in the h file right before functionPrototypes
std::string importIncludes = "/**\n * Import Includes\n */\n\n";
std::string topLevelCPassthrough = "/**\n * Top Level C Passthrough\n */\n\n";
std::string variableExternDeclarations = "/**\n * Extern Variable Declarations \n */\n\n";
std::string plainTypedefs = "/**\n * Plain Typedefs\n */\n\n";
std::string variableDeclarations = "/**\n * Variable Declarations \n */\n\n";
std::string classStructs = "/**\n * Class Structs\n */\n\n";
std::string functionPrototypes = "/**\n * Function Prototypes\n */\n\n";
std::string functionDefinitions = "/**\n * Function Definitions\n */\n\n";
// There also exists functionTypedefString which is a member variable that keeps
// track of utility typedefs that allow our C type generation to be more sane
// it is emitted in the h file right before functionPrototypes
Poset<NodeTree<ASTData>*> typedefPoset;
for (auto trans : ASTs) {
auto children = trans.second->getChildren();
for (int i = 0; i < children.size(); i++) {
if (children[i]->getDataRef()->type == type_def) {
// If we're an alias type, continue. We handle those differently
if (children[i]->getDataRef()->valueType->typeDefinition != children[i])
continue;
Poset<NodeTree<ASTData>*> typedefPoset;
for (auto trans : ASTs) {
auto children = trans.second->getChildren();
for (int i = 0; i < children.size(); i++) {
if (children[i]->getDataRef()->type == type_def) {
// If we're an alias type, continue. We handle those differently
if (children[i]->getDataRef()->valueType->typeDefinition != children[i])
continue;
typedefPoset.addVertex(children[i]); // We add this definition by itself just in case there are no dependencies.
// If it has dependencies, there's no harm in adding it here
// Go through every child in the class looking for declaration statements. For each of these that is not a primitive type
// we will add a dependency from this definition to that definition in the poset.
std::vector<NodeTree<ASTData>*> classChildren = children[i]->getChildren();
for (auto j : classChildren) {
if (j->getDataRef()->type == declaration_statement) {
Type* decType = j->getChildren()[0]->getDataRef()->valueType; // Type of the declaration
if (decType->typeDefinition && decType->getIndirection() == 0) // If this is a custom type and not a pointer
typedefPoset.addRelationship(children[i], decType->typeDefinition); // Add a dependency
}
typedefPoset.addVertex(children[i]); // We add this definition by itself just in case there are no dependencies.
// If it has dependencies, there's no harm in adding it here
// Go through every child in the class looking for declaration statements. For each of these that is not a primitive type
// we will add a dependency from this definition to that definition in the poset.
std::vector<NodeTree<ASTData>*> classChildren = children[i]->getChildren();
for (auto j : classChildren) {
if (j->getDataRef()->type == declaration_statement) {
Type* decType = j->getChildren()[0]->getDataRef()->valueType; // Type of the declaration
if (decType->typeDefinition && decType->getIndirection() == 0) // If this is a custom type and not a pointer
typedefPoset.addRelationship(children[i], decType->typeDefinition); // Add a dependency
}
} else if (children[i]->getDataRef()->type == adt_def) {
//
typedefPoset.addVertex(children[i]); // We add this definition by itself just in case there are no dependencies.
}
} else if (children[i]->getDataRef()->type == adt_def) {
//
typedefPoset.addVertex(children[i]); // We add this definition by itself just in case there are no dependencies.
}
}
//Now generate the typedef's in the correct, topological order
for (NodeTree<ASTData>* i : typedefPoset.getTopoSort())
classStructs += generateTypeStruct(i) + "\n";
}
//Now generate the typedef's in the correct, topological order
for (NodeTree<ASTData>* i : typedefPoset.getTopoSort())
classStructs += generateTypeStruct(i) + "\n";
// Declare everything in translation unit scope here (now for ALL translation units). (allows stuff from other files, automatic forward declarations)
// Also, everything in all of the import's scopes
// Also c passthrough
for (auto trans : ASTs) {
// First go through and emit all the passthroughs, etc
for (auto i : trans.second->getChildren()) {
if (i->getDataRef()->type == if_comp)
topLevelCPassthrough += generate(i, nullptr).oneString();
}
// Declare everything in translation unit scope here (now for ALL translation units). (allows stuff from other files, automatic forward declarations)
// Also, everything in all of the import's scopes
// Also c passthrough
for (auto trans : ASTs) {
// First go through and emit all the passthroughs, etc
for (auto i : trans.second->getChildren()) {
if (i->getDataRef()->type == if_comp)
topLevelCPassthrough += generate(i, nullptr).oneString();
}
for (auto i = trans.second->getDataRef()->scope.begin(); i != trans.second->getDataRef()->scope.end(); i++) {
for (auto declaration : i->second) {
std::vector<NodeTree<ASTData>*> decChildren = declaration->getChildren();
ASTData declarationData = declaration->getData();
switch(declarationData.type) {
case identifier:
{
auto parent = declaration->getDataRef()->scope["~enclosing_scope"][0];
if (parent->getChildren().size() == 1)
variableDeclarations += ValueTypeToCType(declarationData.valueType, scopePrefix(declaration) + declarationData.symbol.getName()) + "; /*identifier*/\n";
else
variableDeclarations += ValueTypeToCType(declarationData.valueType, generate(parent->getChildren()[0], nullptr, true, nullptr).oneString()) + " = " + generate(parent->getChildren()[1], nullptr, true, nullptr).oneString() + ";";
for (auto i = trans.second->getDataRef()->scope.begin(); i != trans.second->getDataRef()->scope.end(); i++) {
for (auto declaration : i->second) {
std::vector<NodeTree<ASTData>*> decChildren = declaration->getChildren();
ASTData declarationData = declaration->getData();
switch(declarationData.type) {
case identifier:
{
auto parent = declaration->getDataRef()->scope["~enclosing_scope"][0];
if (parent->getChildren().size() == 1)
variableDeclarations += ValueTypeToCType(declarationData.valueType, prefixIfNeeded(scopePrefix(declaration), declarationData.symbol.getName())) + "; /*identifier*/\n";
else
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";
break;
}
@@ -217,12 +256,11 @@ std::pair<std::string, std::string> CGenerator::generateTranslationUnit(std::str
parameters += ValueTypeToCType(decChildren[j]->getData().valueType, generate(decChildren[j], nullptr).oneString());
nameDecoration += "_" + ValueTypeToCTypeDecoration(decChildren[j]->getData().valueType);
}
functionPrototypes += "\n" + ValueTypeToCType(declarationData.valueType->returnType, ((declarationData.symbol.getName() == "main") ? "" : function_header + scopePrefix(declaration)) +
CifyName(declarationData.symbol.getName() + nameDecoration)) +
"(" + parameters + "); /*func*/\n";
std::string funName = (declarationData.symbol.getName() == "main") ? "main" :
function_header + prefixIfNeeded(scopePrefix(declaration), CifyName(declarationData.symbol.getName() + nameDecoration));
functionPrototypes += "\n" + ValueTypeToCType(declarationData.valueType->returnType, funName) + "(" + parameters + "); /*func*/\n";
// generate function
std::cout << "Generating " << scopePrefix(declaration) +
CifyName(declarationData.symbol.getName()) << std::endl;
std::cout << "Generating " << prefixIfNeeded(scopePrefix(declaration), CifyName(declarationData.symbol.getName())) << std::endl;
functionDefinitions += generate(declaration, nullptr).oneString();
}
}
@@ -238,13 +276,12 @@ std::pair<std::string, std::string> CGenerator::generateTranslationUnit(std::str
continue; // Aliases of objects are done with the thing it alises
// Otherwise, we're actually a renaming of a primitive, can generate here
plainTypedefs += "typedef " + ValueTypeToCType(declarationData.valueType,
scopePrefix(declaration) +
CifyName(declarationData.symbol.getName())) + ";\n";
prefixIfNeeded(scopePrefix(declaration), CifyName(declarationData.symbol.getName()))) + ";\n";
plainTypedefs += generateAliasChains(ASTs, declaration);
} else {
plainTypedefs += "typedef struct __struct_dummy_" +
scopePrefix(declaration) + CifyName(declarationData.symbol.getName()) + "__ " +
scopePrefix(declaration) + CifyName(declarationData.symbol.getName()) + ";\n";
prefixIfNeeded(scopePrefix(declaration), CifyName(declarationData.symbol.getName()) + "__") + " " +
prefixIfNeeded(scopePrefix(declaration), CifyName(declarationData.symbol.getName())) + ";\n";
functionPrototypes += "/* Method Prototypes for " + declarationData.symbol.getName() + " */\n";
// We use a seperate string for this because we only include it if this is the file we're defined in
std::string objectFunctionDefinitions = "/* Method Definitions for " + declarationData.symbol.getName() + " */\n";
@@ -264,19 +301,15 @@ std::pair<std::string, std::string> CGenerator::generateTranslationUnit(std::str
case adt_def:
{
//type
plainTypedefs += "/* adt " + declarationData.symbol.getName() + " */\n";
//plainTypedefs += "typedef struct __adt_dummy_" +
plainTypedefs += "typedef enum __adt_dummy_" +
scopePrefix(declaration) + CifyName(declarationData.symbol.getName()) + "__ " +
scopePrefix(declaration) + CifyName(declarationData.symbol.getName()) + ";\n";
// We use a seperate string for this because we only include it if this is the file we're defined in
std::string enumString = "/* Enum Definition for " + declarationData.symbol.getName() + " */\n";
// skip the name of the thing
for (int j = 1; j < decChildren.size(); j++) {
std::cout << decChildren[j]->getName() << std::endl;
if (decChildren[j]->getName() == "identifier") //If object method and not template
enumString += "an_option \n";
}
//don't even need to do this anymore, it's all earlier
//plainTypedefs += "/* adt " + declarationData.symbol.getName() + " */\n";
//plainTypedefs += "typedef struct __struct_dummy_" +
//prefixIfNeeded(scopePrefix(declaration), CifyName(declarationData.symbol.getName())+ "__") + " " +
//prefixIfNeeded(scopePrefix(declaration), CifyName(declarationData.symbol.getName())) + ";\n";
//// skip the name of the thing
//for (int j = 1; j < decChildren.size(); j++) {
//std::cout << decChildren[j]->getName() << std::endl;
//}
break;
}
default:
@@ -344,8 +377,8 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
preName += "(*";
postName += ")";
}
// we're scope prefixing EVERYTHING
return preName + scopePrefix(from) + CifyName(data.symbol.getName()) + postName; //Cifying does nothing if not an operator overload
// we're scope prefixing EVERYTHING, but only if needed
return preName + prefixIfNeeded(scopePrefix(from), CifyName(data.symbol.getName())) + postName; //Cifying does nothing if not an operator overload
}
case function:
{
@@ -370,8 +403,9 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
if (justFuncName) {
std::string funcName;
if (data.symbol.getName() != "main")
funcName += function_header + scopePrefix(from);
funcName += CifyName(data.symbol.getName() + nameDecoration);
funcName += function_header + prefixIfNeeded(scopePrefix(from), CifyName(data.symbol.getName() + nameDecoration));
else
funcName += CifyName(data.symbol.getName() + nameDecoration);
if (from->getDataRef()->closedVariables.size()) {
std::string tmpStruct = "closureStruct" + getID();
output.preValue += closureStructType(data.closedVariables) + " " + tmpStruct + " = {";
@@ -384,7 +418,7 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
std::string preName;
if (enclosingObject && enclosingObject->getDataRef()->scope.find(varName) != enclosingObject->getDataRef()->scope.end())
preName += "this->";
varName = (varName == "this") ? varName : scopePrefix(var) + varName;
varName = (varName == "this") ? varName : prefixIfNeeded(scopePrefix(var), 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;
@@ -396,8 +430,9 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
}
} else {
// 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)) +
CifyName(data.symbol.getName() + nameDecoration)) + "(" + parameters + ") {\n" + generate(children[children.size()-1], enclosingObject, justFuncName, from).oneString();
std::string funName = (data.symbol.getName() == "main") ? "main" : function_header + prefixIfNeeded(scopePrefix(from), CifyName(data.symbol.getName() + nameDecoration));
output = "\n" + ValueTypeToCType(data.valueType->returnType, funName) + "(" + parameters + ") {\n" +
generate(children[children.size()-1], enclosingObject, justFuncName, from).oneString();
output += emitDestructors(reverse(distructDoubleStack.back()), enclosingObject);
output += "}\n";
}
@@ -615,6 +650,7 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
return CCodeTriple("");
case simple_passthrough:
{
std::string pre_end_dec, end_assign;
// Stuff is bit more interesting now! XXX
std::string pre_passthrough, post_passthrough;
// Handle input/output parameters
@@ -623,17 +659,27 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
for (auto in_or_out : optParamAssignLists) {
for (auto assign : in_or_out->getChildren()) {
auto assignChildren = assign->getChildren();
if (in_or_out->getDataRef()->type == in_passthrough_params)
if (in_or_out->getDataRef()->type == in_passthrough_params) {
std::string currentName = generate(assignChildren[0], enclosingObject, enclosingFunction).oneString();
std::string toName;
if (assignChildren.size() == 2)
pre_passthrough += ValueTypeToCType(assignChildren[0]->getDataRef()->valueType, assignChildren[1]->getDataRef()->symbol.getName()) + " = " + generate(assignChildren[0], enclosingObject, enclosingFunction).oneString() + ";\n";
toName = assignChildren[1]->getDataRef()->symbol.getName();
else
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)
toName = assignChildren[0]->getDataRef()->symbol.getName();
if (currentName != toName)
pre_passthrough += ValueTypeToCType(assignChildren[0]->getDataRef()->valueType, toName) + " = " + currentName + ";\n";
} else if (in_or_out->getDataRef()->type == out_passthrough_params) {
std::string currentName = generate(assignChildren[0], enclosingObject, justFuncName, enclosingFunction).oneString();
std::string toName;
if (assignChildren.size() == 2)
post_passthrough += generate(assignChildren[0], enclosingObject, justFuncName, enclosingFunction).oneString() + " = " + assignChildren[1]->getDataRef()->symbol.getName() + ";\n";
toName = assignChildren[1]->getDataRef()->symbol.getName();
else
post_passthrough += generate(assignChildren[0], enclosingObject, justFuncName, enclosingFunction).oneString() + " = " + assignChildren[0]->getDataRef()->symbol.getName() + ";\n";
else
toName += assignChildren[0]->getDataRef()->symbol.getName();
std::string trans_dec_name = currentName + "_end_assign";
pre_end_dec += ValueTypeToCType(assignChildren[0]->getDataRef()->valueType, trans_dec_name) + ";\n";
post_passthrough += trans_dec_name + " = " + toName + ";\n";
end_assign += currentName + " = " + trans_dec_name + ";\n";
} else
linkerString += " " + strSlice(generate(in_or_out, enclosingObject, justFuncName, enclosingFunction).oneString(), 1, -2) + " ";
}
}
@@ -641,8 +687,11 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
// The actual passthrough string is the last child now, as we might
// 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
//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;
// we don't want the scope stuff if we're at top level for an include, etc....
if (isUnderNodeWithType(from,function))
return pre_end_dec + "{" + pre_passthrough + strSlice(children.back()->getDataRef()->symbol.getName(), 3, -4) + post_passthrough + "}\n" + end_assign;
else
return strSlice(children.back()->getDataRef()->symbol.getName(), 3, -4);
}
case function_call:
{
@@ -704,7 +753,7 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
for (int i = 0; i < (functionDefChildren.size() > 0 ? functionDefChildren.size()-1 : 0); i++)
nameDecoration += "_" + ValueTypeToCTypeDecoration(functionDefChildren[i]->getData().valueType);
// 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 + prefixIfNeeded(scopePrefix(unaliasedTypeDef), CifyName(unaliasedTypeDef->getDataRef()->symbol.getName())) +"__" +
CifyName(functionName + nameDecoration) + "(" + (name == "." ? "&" : "") + generate(children[1], enclosingObject, true, enclosingFunction) + ",";
//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
@@ -746,11 +795,11 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
//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 += function_header + prefixIfNeeded(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) + "(";
output += function_header + prefixIfNeeded(scopePrefix(children[0]), CifyName(name + nameDecoration)) + "(";
}
}
}
@@ -877,8 +926,9 @@ std::string CGenerator::generateObjectMethod(NodeTree<ASTData>* enclosingObject,
distructDoubleStack.back().push_back(children[i]);
}
std::string functionSignature = "\n" + ValueTypeToCType(data.valueType->returnType, function_header + scopePrefix(from) + CifyName(enclosingObject->getDataRef()->symbol.getName()) +"__"
+ CifyName(data.symbol.getName()) + nameDecoration) + "(" + ValueTypeToCType(&enclosingObjectType, "this") + parameters + ")";
std::string functionSignature = "\n" + ValueTypeToCType(data.valueType->returnType, function_header +
prefixIfNeeded(scopePrefix(from), CifyName(enclosingObject->getDataRef()->symbol.getName())) + "__" +
CifyName(data.symbol.getName()) + nameDecoration) + "(" + ValueTypeToCType(&enclosingObjectType, "this") + parameters + ")";
*functionPrototype += functionSignature + ";\n";
// Note that we always wrap out child in {}, as we now allow one statement functions without a codeblock
//
@@ -928,7 +978,7 @@ std::string CGenerator::generateMethodIfExists(Type* type, std::string method, s
std::string nameDecoration;
for (Type *paramType : methodDef->getDataRef()->valueType->parameterTypes)
nameDecoration += "_" + ValueTypeToCTypeDecoration(paramType);
return function_header + scopePrefix(typeDefinition) + CifyName(typeDefinition->getDataRef()->symbol.getName()) + "__" + method + nameDecoration + "(" + parameter + ");\n";
return function_header + prefixIfNeeded(scopePrefix(typeDefinition), CifyName(typeDefinition->getDataRef()->symbol.getName())) + "__" + method + nameDecoration + "(" + parameter + ");\n";
}
return "";
}
@@ -952,7 +1002,7 @@ std::string CGenerator::closureStructType(std::set<NodeTree<ASTData>*> closedVar
// will actually change the underlying function's type. We cheat and just add a *
//auto tmp = var->getDataRef()->valueType->withIncreasedIndirection();
std::string varName = var->getDataRef()->symbol.getName();
varName = (varName == "this") ? varName : scopePrefix(var) + varName;
varName = (varName == "this") ? varName : prefixIfNeeded(scopePrefix(var), varName);
typedefString += ValueTypeToCType(var->getDataRef()->valueType->withoutReference(), "*"+varName) + ";";
}
std::string structName = "closureStructType" + getID();
@@ -970,7 +1020,7 @@ std::string CGenerator::ValueTypeToCTypeThingHelper(Type *type, std::string decl
switch (type->baseType) {
case none:
if (type->typeDefinition)
return_type = scopePrefix(type->typeDefinition) + CifyName(type->typeDefinition->getDataRef()->symbol.getName());
return_type = prefixIfNeeded(scopePrefix(type->typeDefinition), CifyName(type->typeDefinition->getDataRef()->symbol.getName()));
else
return_type = "none";
break;
@@ -1128,4 +1178,20 @@ std::string CGenerator::scopePrefix(NodeTree<ASTData>* from) {
// that parent object will get scoped. When we add a package system, we'll have to then add their scoping here
return scopePrefix(from->getDataRef()->scope["~enclosing_scope"][0]);
}
std::string CGenerator::prefixIfNeeded(std::string prefix, std::string name) {
return simpleComplexName(name, prefix + name);
}
std::string CGenerator::simpleComplexName(std::string simpleName, std::string complexName) {
auto already = simpleComplexNameMap.find(complexName);
if (already != simpleComplexNameMap.end())
return already->second;
if (usedNameSet.find(simpleName) == usedNameSet.end()) {
usedNameSet.insert(simpleName);
simpleComplexNameMap[complexName] = simpleName;
return simpleName;
}
usedNameSet.insert(complexName);
simpleComplexNameMap[complexName] = complexName;
return complexName;
}