|
|
|
|
@@ -81,7 +81,15 @@ std::string CGenerator::generateTypeStruct(NodeTree<ASTData>* from) {
|
|
|
|
|
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()) + "(" +
|
|
|
|
|
std::string fun_name = child->getDataRef()->symbol.getName();
|
|
|
|
|
std::string first_param;
|
|
|
|
|
if (fun_name == "operator==") {
|
|
|
|
|
fun_name = "fun_" + data.symbol.getName() + "__" + CifyName(fun_name);
|
|
|
|
|
first_param = ValueTypeToCType(child->getDataRef()->valueType->parameterTypes[0]->withIncreasedIndirectionPtr(), "this") + ", ";
|
|
|
|
|
} else {
|
|
|
|
|
fun_name = "fun_" + fun_name;
|
|
|
|
|
}
|
|
|
|
|
functionString += "\n" + ValueTypeToCType(child->getDataRef()->valueType->returnType, fun_name) + "(" + first_param +
|
|
|
|
|
(child->getDataRef()->valueType->parameterTypes.size() ? ValueTypeToCType(child->getDataRef()->valueType->parameterTypes[0], "in") : "") + "); /*adt func*/\n";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -101,8 +109,8 @@ std::string CGenerator::generateTypeStruct(NodeTree<ASTData>* from) {
|
|
|
|
|
|
|
|
|
|
// 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) {
|
|
|
|
|
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();
|
|
|
|
|
@@ -117,75 +125,75 @@ for (auto trans : ASTs) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
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()) {
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool CGenerator::isUnderTranslationUnit(NodeTree<ASTData>* from, NodeTree<ASTData>* node) {
|
|
|
|
|
auto scope = from->getDataRef()->scope;
|
|
|
|
|
for (auto i : scope)
|
|
|
|
|
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())
|
|
|
|
|
auto upper = scope.find("~enclosing_scope");
|
|
|
|
|
if (upper != scope.end())
|
|
|
|
|
return isUnderTranslationUnit(upper->second[0], node);
|
|
|
|
|
return false;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NodeTree<ASTData>* CGenerator::highestScope(NodeTree<ASTData>* node) {
|
|
|
|
|
auto it = node->getDataRef()->scope.find("~enclosing_scope");
|
|
|
|
|
while (it != node->getDataRef()->scope.end()) {
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
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) {
|
|
|
|
|
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) {
|
|
|
|
|
@@ -210,15 +218,15 @@ for (auto trans : ASTs) {
|
|
|
|
|
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())
|
|
|
|
|
}
|
|
|
|
|
//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) {
|
|
|
|
|
// 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)
|
|
|
|
|
@@ -753,7 +761,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 + prefixIfNeeded(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
|
|
|
|
|
|