From d44ce47d1e7280e3be2310ec05cf76d4e3b3ce53 Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Sat, 4 Jul 2015 18:55:15 -0400 Subject: [PATCH] Fix the CGenerator so that function values can be stored in member variables --- include/CGenerator.h | 5 +++-- include/util.h | 15 +++++++++++++++ src/CGenerator.cpp | 22 ++++++++++++++++------ 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/include/CGenerator.h b/include/CGenerator.h index c18b57b..0086690 100644 --- a/include/CGenerator.h +++ b/include/CGenerator.h @@ -20,7 +20,7 @@ // 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 }; +enum ClosureTypeSpecialType { ClosureTypeRegularNone, ClosureFunctionPointerTypeWithoutClosedParam, ClosureFunctionPointerTypeWithClosedParam }; class CGenerator { public: @@ -55,7 +55,8 @@ class CGenerator { std::string generatorString; std::string linkerString; std::string functionTypedefString; - std::map> functionTypedefMap; + std::string functionTypedefStringPre; + std::map> functionTypedefMap; std::map*>, std::string> closureStructMap; std::vector*>> distructDoubleStack; std::stack loopDistructStackDepth; diff --git a/include/util.h b/include/util.h index 1539f9f..372f705 100644 --- a/include/util.h +++ b/include/util.h @@ -22,6 +22,21 @@ std::string join(const std::vector &strVec, std::string joinStr); std::string readFile(std::istream &file); std::string padWithSpaces(std::string str, int padTo); +template +class triple { + public: + T first; + U second; + V third; +}; +template +triple make_triple(T f, U s, V t) { + triple out; + out.first = f; + out.second = s; + out.third = t; + return out; +} template bool contains(std::vector vec, T item) { diff --git a/src/CGenerator.cpp b/src/CGenerator.cpp index 845ee46..a2a055f 100644 --- a/src/CGenerator.cpp +++ b/src/CGenerator.cpp @@ -4,6 +4,8 @@ CGenerator::CGenerator() : generatorString("__C__") { tabLevel = 0; id = 0; function_header = "fun_"; + functionTypedefString = ""; + functionTypedefStringPre = ""; } CGenerator::~CGenerator() { } @@ -259,7 +261,7 @@ std::pair CGenerator::generateTranslationUnit(std::str } } } - hOutput += plainTypedefs + importIncludes + topLevelCPassthrough + variableExternDeclarations + classStructs + functionTypedefString + functionPrototypes; + hOutput += plainTypedefs + importIncludes + topLevelCPassthrough + functionTypedefStringPre + variableExternDeclarations + classStructs + functionTypedefString + functionPrototypes; cOutput += variableDeclarations + functionDefinitions; return std::make_pair(hOutput, cOutput); } @@ -730,8 +732,8 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc 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", + + "if (" + tmpName + ".data) { " + (doRet ? (retTmpName + " =") : "") + " (("+ ValueTypeToCTypeDecoration(funcType,ClosureFunctionPointerTypeWithClosedParam) +") (" + tmpName + ".func))(" + tmpName + ".data" + (children.size() > 1 ? ", " : "") + parameters.value + "); }\n" + + "else { " + (doRet ? (retTmpName + " = ") : "") + " (("+ ValueTypeToCTypeDecoration(funcType,ClosureFunctionPointerTypeWithoutClosedParam) +") (" + tmpName + ".func))(" + parameters.value + "); }\n", (doRet ? retTmpName : ""), parameters.postValue + functionCallSource.postValue); } else { @@ -909,6 +911,8 @@ std::string CGenerator::ValueTypeToCTypeThingHelper(Type *type, std::string decl if (it != functionTypedefMap.end()) { if (closureSpecial == ClosureFunctionPointerTypeWithClosedParam) return_type = it->second.second + declaration; + else if (closureSpecial == ClosureFunctionPointerTypeWithoutClosedParam) + return_type = it->second.third + declaration; else return_type = it->second.first + declaration; } else { @@ -918,7 +922,11 @@ std::string CGenerator::ValueTypeToCTypeThingHelper(Type *type, std::string decl 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"; + // How I wish the world were this kind. Because of C name resolution not looking ahead, this definition needs to be BEFORE + // the object definitions. So to prevent circular dependencies, I'm making this take in a void pointer and we'll simply + // cast in both cases, whether or not there's a data pointer. Sigh. + //std::string typedefStructStr = "typedef struct {" + typedefWithoutVoidID + " func; void* val; } " + typedefStructID + ";\n"; + std::string typedefStructStr = "typedef struct { void* func; void* data; } " + typedefStructID + ";\n"; typedefWithoutVoidStr += ValueTypeToCTypeThingHelper(type->returnType, "", closureSpecial); typedefWithVoidStr += ValueTypeToCTypeThingHelper(type->returnType, "", closureSpecial); @@ -935,15 +943,17 @@ std::string CGenerator::ValueTypeToCTypeThingHelper(Type *type, std::string decl } typedefWithoutVoidStr += ");\n"; typedefWithVoidStr += ");\n"; + // again, sigh functionTypedefString += typedefWithoutVoidStr; functionTypedefString += typedefWithVoidStr; - functionTypedefString += typedefStructStr; + functionTypedefStringPre += typedefStructStr; + //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); + functionTypedefMap[*type] = make_triple(typedefStructID, typedefWithVoidID, typedefWithoutVoidID); } do_ending = false; }