From 2a4edf9afd6990f968bb08c016b7b6414e382eb8 Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Sat, 10 May 2014 19:28:36 -0400 Subject: [PATCH] Simple Templates work! Even Templates in other files work. Happy day --- CMakeLists.txt | 8 +++++++- include/ASTTransformation.h | 1 + include/CGenerator.h | 2 +- src/ASTTransformation.cpp | 12 +++++++++--- src/CGenerator.cpp | 28 ++++++++++++++++------------ 5 files changed, 34 insertions(+), 17 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 12ef013..48b80aa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,9 +8,15 @@ set( MY_INCLUDES ${PROJECT_SOURCE_DIR}/include) set( MY_SOURCES main.cpp src/Parser.cpp src/LALRParser.cpp src/GraphStructuredStack.cpp src/RNGLRParser.cpp src/ParseAction.cpp src/ParseRule.cpp src/Symbol.cpp src/StringReader.cpp src/State.cpp src/util.cpp src/Lexer.cpp src/RegEx.cpp src/RegExState.cpp src/Table.cpp src/ASTData.cpp src/ASTTransformation.cpp src/CGenerator.cpp src/Type.cpp src/Importer.cpp ) +add_custom_target(STDLibCopy ALL) +add_custom_command(TARGET STDLibCopy POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${PROJECT_SOURCE_DIR}/stdlib" + "${PROJECT_BINARY_DIR}/stdlib") + include_directories( ${MY_INCLUDES} ) add_executable(kraken ${MY_SOURCES}) -file(COPY stdlib DESTINATION .) + diff --git a/include/ASTTransformation.h b/include/ASTTransformation.h index 0766b94..4ae3e41 100644 --- a/include/ASTTransformation.h +++ b/include/ASTTransformation.h @@ -26,6 +26,7 @@ class ASTTransformation: public NodeTransformation { private: Importer * importer; std::map*>> languageLevelScope; + NodeTree* topScope; //maintained for templates that need to add themselves to the top scope no matter where they are instantiated }; #endif diff --git a/include/CGenerator.h b/include/CGenerator.h index fe8e8b8..d7e4e03 100644 --- a/include/CGenerator.h +++ b/include/CGenerator.h @@ -20,7 +20,7 @@ class CGenerator { std::string generate(NodeTree* from, NodeTree* enclosingObject = NULL); static std::string ValueTypeToCType(Type *type); static std::string ValueTypeToCTypeDecoration(Type *type); - static std::string CifyFunctionName(std::string name); + static std::string CifyName(std::string name); std::string generateObjectMethod(NodeTree* enclosingObject, NodeTree* from); std::string generatorString; diff --git a/src/ASTTransformation.cpp b/src/ASTTransformation.cpp index 2411fbc..84215d0 100644 --- a/src/ASTTransformation.cpp +++ b/src/ASTTransformation.cpp @@ -2,6 +2,7 @@ ASTTransformation::ASTTransformation(Importer *importerIn) { importer = importerIn; + topScope = NULL; //Set up language level special scope. (the final scope checked) //Note the NULL type languageLevelScope["+"].push_back( new NodeTree("function", ASTData(function, Symbol("+", true), NULL))); @@ -45,6 +46,7 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree if (name == "translation_unit") { newNode = new NodeTree(name, ASTData(translation_unit)); scope = newNode; + topScope = newNode; //Top scope is maintained for templates, which need to add themselves to the top scope from where ever they are instantiated } else if (name == "interpreter_directive") { newNode = new NodeTree(name, ASTData(interpreter_directive)); } else if (name == "import" && !current.isTerminal()) { @@ -536,8 +538,7 @@ Type* ASTTransformation::typeFromTypeNode(NodeTree* typeNode, NodeTreeindirection += indirection; return templateTypeReplacement; } - //If not, we better instantiate it and then add it to the scope - //Note that this means the template instantiation is scoped, which is inefficient, though it has a nice correctness about it + //If not, we better instantiate it and then add it to the highest (not current) scope if (typeDefinition == NULL && typeNode->getChildren().size() > 1 && typeNode->getChildren()[1]->getData().getName() == "template_inst") { std::cout << "Template type: " << edited << " not yet instantiated" << std::endl; //Look up this template's plain definition. It's type has the syntax tree that we need to parse @@ -560,7 +561,12 @@ Type* ASTTransformation::typeFromTypeNode(NodeTree* typeNode, NodeTree("type_def", ASTData(type_def, Symbol(fullyInstantiatedName, true, fullyInstantiatedName))); typeDefinition->getDataRef()->valueType = new Type(typeDefinition);; //Type is self-referential since this is the definition - scope->getDataRef()->scope[fullyInstantiatedName].push_back(typeDefinition); + //Note that we're adding to the current top scope. This makes it more efficient by preventing multiple instantiation and should not cause any problems + //It also makes sure it gets generated in the right place + topScope->getDataRef()->scope[fullyInstantiatedName].push_back(typeDefinition); + topScope->addChild(typeDefinition); //Add this object the the highest scope's + + //Note that the instantiated template's scope is the template's definition. typeDefinition->getDataRef()->scope["~enclosing_scope"].push_back(templateDefinition); diff --git a/src/CGenerator.cpp b/src/CGenerator.cpp index 3a856f6..bf146ae 100644 --- a/src/CGenerator.cpp +++ b/src/CGenerator.cpp @@ -70,7 +70,7 @@ std::string CGenerator::generate(NodeTree* from, NodeTree* enc parameters += ValueTypeToCType(decChildren[j]->getData().valueType) + " " + generate(decChildren[j], enclosingObject); nameDecoration += "_" + ValueTypeToCTypeDecoration(decChildren[j]->getData().valueType); } - output += CifyFunctionName(declarationData.symbol.getName()) + nameDecoration + "(" + parameters + "); /*func*/\n"; + output += CifyName(declarationData.symbol.getName()) + nameDecoration + "(" + parameters + "); /*func*/\n"; break; } case type_def: @@ -104,13 +104,15 @@ std::string CGenerator::generate(NodeTree* from, NodeTree* enc if (false) for (int j = 0; j < children.size()-1; j++) preName += ValueTypeToCType(children[j]->getData().valueType) + "_"; - return preName + CifyFunctionName(data.symbol.getName()); //Cifying does nothing if not an operator overload + return preName + CifyName(data.symbol.getName()); //Cifying does nothing if not an operator overload } case type_def: - if (children.size() == 0) { + if (data.valueType->baseType == template_type) { + return "/* non instantiated template " + data.symbol.getName() + " */"; + } else if (children.size() == 0) { return "typedef " + ValueTypeToCType(data.valueType) + " " + data.symbol.getName() + ";"; } else { - std::string objectString = "typedef struct __struct_dummy_" + data.symbol.getName() + "__ {\n"; + std::string objectString = "typedef struct __struct_dummy_" + CifyName(data.symbol.getName()) + "__ {\n"; std::string postString; //The functions have to be outside the struct definition for (int i = 0; i < children.size(); i++) { std::cout << children[i]->getName() << std::endl; @@ -119,7 +121,7 @@ std::string CGenerator::generate(NodeTree* from, NodeTree* enc else objectString += generate(children[i], enclosingObject) + "\n"; } - objectString += "} " + data.symbol.getName() + ";"; + objectString += "} " + CifyName(data.symbol.getName()) + ";"; return objectString + postString; //Functions come after the declaration of the struct } case function: @@ -132,7 +134,7 @@ std::string CGenerator::generate(NodeTree* from, NodeTree* enc parameters += ValueTypeToCType(children[j]->getData().valueType) + " " + generate(children[j], enclosingObject); nameDecoration += "_" + ValueTypeToCTypeDecoration(children[j]->getData().valueType); } - output += CifyFunctionName(data.symbol.getName()) + nameDecoration + "(" + parameters + ")\n" + generate(children[children.size()-1], enclosingObject); + output += CifyName(data.symbol.getName()) + nameDecoration + "(" + parameters + ")\n" + generate(children[children.size()-1], enclosingObject); return output; } case code_block: @@ -220,7 +222,7 @@ std::string CGenerator::generate(NodeTree* from, NodeTree* enc std::cout << "Decorating (in access-should be object) " << name << " " << functionDefChildren.size() << std::endl; for (int i = 0; i < (functionDefChildren.size() > 0 ? functionDefChildren.size()-1 : 0); i++) nameDecoration += "_" + ValueTypeToCTypeDecoration(functionDefChildren[i]->getData().valueType); -/*HERE*/ return possibleObjectType->getDataRef()->symbol.getName() +"__" + CifyFunctionName(functionName) + nameDecoration + "(" + (name == "." ? "&" : "") + generate(children[1], enclosingObject) + ","; +/*HERE*/ return CifyName(possibleObjectType->getDataRef()->symbol.getName()) +"__" + CifyName(functionName) + nameDecoration + "(" + (name == "." ? "&" : "") + generate(children[1], enclosingObject) + ","; //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 } else { @@ -242,7 +244,7 @@ std::string CGenerator::generate(NodeTree* from, NodeTree* enc bool isSelfObjectMethod = enclosingObject && contains(enclosingObject->getChildren(), children[0]); if (isSelfObjectMethod) output += enclosingObject->getDataRef()->symbol.getName() +"__"; -/*HERE*/ output += CifyFunctionName(name) + nameDecoration + "("; +/*HERE*/ output += CifyName(name) + nameDecoration + "("; if (isSelfObjectMethod) output += children.size() > 1 ? "self," : "self"; } @@ -286,8 +288,8 @@ std::string CGenerator::generateObjectMethod(NodeTree* enclosingObject, parameters += ", " + ValueTypeToCType(children[i]->getData().valueType) + " " + generate(children[i]); nameDecoration += "_" + ValueTypeToCTypeDecoration(children[i]->getData().valueType); } - output += "\n" + ValueTypeToCType(data.valueType) + " " + enclosingObject->getDataRef()->symbol.getName() +"__" - + CifyFunctionName(data.symbol.getName()) + nameDecoration + "(" + ValueTypeToCType(&enclosingObjectType) + output += "\n" + ValueTypeToCType(data.valueType) + " " + CifyName(enclosingObject->getDataRef()->symbol.getName()) +"__" + + CifyName(data.symbol.getName()) + nameDecoration + "(" + ValueTypeToCType(&enclosingObjectType) + " self" + parameters + ")\n" + generate(children[children.size()-1], enclosingObject); //Pass in the object so we can properly handle access to member stuff return output; } @@ -297,7 +299,7 @@ std::string CGenerator::ValueTypeToCType(Type *type) { switch (type->baseType) { case none: if (type->typeDefinition) - return_type = type->typeDefinition->getDataRef()->symbol.getName(); + return_type = CifyName(type->typeDefinition->getDataRef()->symbol.getName()); else return_type = "none"; break; @@ -364,7 +366,7 @@ std::string CGenerator::ValueTypeToCTypeDecoration(Type *type) { return return_type; } -std::string CGenerator::CifyFunctionName(std::string name) { +std::string CGenerator::CifyName(std::string name) { std::string operatorsToReplace[] = { "+", "plus", "-", "minus", "*", "star", @@ -394,6 +396,8 @@ std::string CGenerator::CifyFunctionName(std::string name) { "|=", "pipeequals", "*=", "starequals", "<<=", "doublerightequals", + "<", "lessthan", + ">", "greaterthan", ">>=", "doubleleftequals", "->", "arrow" }; int length = sizeof(operatorsToReplace)/sizeof(std::string);