diff --git a/include/Type.h b/include/Type.h index ba5891f..f5aacdc 100644 --- a/include/Type.h +++ b/include/Type.h @@ -5,6 +5,10 @@ #define NULL ((void*)0) #endif +#ifndef SEGFAULT +#define SEGFAULT (*((char*)0)), std::cout << "\t\t\t\tNEGATIVE*************************************************************************" << std::endl; +#endif + #include #include @@ -13,7 +17,7 @@ class ASTData; #include "ASTData.h" #include "util.h" -enum ValueType {none, template_type, void_type, boolean, integer, floating, double_percision, character }; +enum ValueType {none, template_type, template_type_type, void_type, boolean, integer, floating, double_percision, character }; class Type { @@ -30,11 +34,17 @@ class Type { bool const operator!=(const Type &other)const; Type* clone(); std::string toString(); + int getIndirection(); + void setIndirection(int indirectionIn); + void increaseIndirection(); + void decreaseIndirection(); + void modifyIndirection(int mod); + void check(); ValueType baseType; NodeTree* typeDefinition; - int indirection; NodeTree* templateDefinition; private: + int indirection; }; #endif \ No newline at end of file diff --git a/krakenGrammer.kgm b/krakenGrammer.kgm index 4cc0d2a..bc0d40b 100644 --- a/krakenGrammer.kgm +++ b/krakenGrammer.kgm @@ -42,7 +42,7 @@ opt_parameter_list = parameter_list | ; parameter_list = parameter_list WS "," WS parameter | parameter ; parameter = boolean_expression ; -type_def = "typedef" WS identifier WS type | "typedef" WS template_dec WS identifier WS "{" WS class_innerds WS "}" | "typedef" WS identifier WS "{" WS class_innerds WS "}" | "typedef" WS template_dec WS identifier WS "{" WS declaration_block WS "}" ; +type_def = "typedef" WS identifier WS type | "typedef" WS template_dec WS identifier WS "{" WS class_innerds WS "}" | "typedef" WS identifier WS "{" WS class_innerds WS "}" | "typedef" WS template_dec WS identifier WS "{" WS declaration_block WS "}" | "typedef" WS identifier WS "{" WS declaration_block WS "}" ; template_dec = "template" WS "<" WS identifier WS ">" ; class_innerds = visibility_block WS class_innerds | visibility_block ; visibility_block = "public:" WS declaration_block | "protected:" WS declaration_block | "private:" WS declaration_block ; diff --git a/src/ASTTransformation.cpp b/src/ASTTransformation.cpp index 00f4605..eca685e 100644 --- a/src/ASTTransformation.cpp +++ b/src/ASTTransformation.cpp @@ -8,6 +8,8 @@ ASTTransformation::ASTTransformation(Importer *importerIn) { languageLevelScope["+"].push_back( new NodeTree("function", ASTData(function, Symbol("+", true), NULL))); languageLevelScope["-"].push_back(new NodeTree("function", ASTData(function, Symbol("-", true), NULL))); languageLevelScope["*"].push_back(new NodeTree("function", ASTData(function, Symbol("*", true), NULL))); + languageLevelScope["/"].push_back(new NodeTree("function", ASTData(function, Symbol("/", true), NULL))); + languageLevelScope["%"].push_back(new NodeTree("function", ASTData(function, Symbol("%", true), NULL))); languageLevelScope["&"].push_back(new NodeTree("function", ASTData(function, Symbol("&", true), NULL))); languageLevelScope["--"].push_back(new NodeTree("function", ASTData(function, Symbol("--", true), NULL))); languageLevelScope["++"].push_back(new NodeTree("function", ASTData(function, Symbol("++", true), NULL))); @@ -117,6 +119,18 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree newNode = new NodeTree(name, ASTData(function, Symbol(functionName, true), new Type(template_type, from))); scope->getDataRef()->scope[functionName].push_back(newNode); newNode->getDataRef()->scope["~enclosing_scope"].push_back(scope); + std::map yetToBeInstantiatedTemplateTypes; //So that template types (like T) that have not been placed yet are found and given + //a special Type() - baseType = template_type_type + yetToBeInstantiatedTemplateTypes[concatSymbolTree(children[0]->getChildren()[1])] = new Type(template_type_type); //This may have to be combined with templateTypeReplacements if we do templated member functions inside of templated classes + + auto transChildren = transformChildren(slice(children,3,-2), std::set(), newNode, types, yetToBeInstantiatedTemplateTypes); + std::cout << "Template function " << functionName << " has these parameters: "; + for (auto i : transChildren) + std::cout << "||" << i->getDataRef()->toString() << "|| "; + std::cout << "??||" << std::endl; + newNode->addChildren(transChildren); + + std::cout << "Finished Non-Instantiated Template function " << functionName << std::endl; return newNode; } functionName = concatSymbolTree(children[1]); @@ -188,28 +202,18 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree std::string functionCallName = concatSymbolTree(children[1]); //std::cout << "scope lookup from expression or similar" << std::endl; std::vector*> transformedChildren; transformedChildren.push_back(lhs); transformedChildren.push_back(rhs); - NodeTree* function = doFunction(scope, functionCallName, transformedChildren, templateTypeReplacements); - if (function == NULL) { + newNode = doFunction(scope, functionCallName, transformedChildren, templateTypeReplacements); + if (newNode == NULL) { std::cout << "scope lookup error! Could not find " << functionCallName << " in expression " << std::endl; throw "LOOKUP ERROR: " + functionCallName; } - newNode = function; - // newNode = new NodeTree(functionCallName, ASTData(function_call, Symbol(functionCallName, true))); - // newNode->addChild(function); // First child of function call is a link to the function definition - // newNode->addChild(lhs); - // newNode->addChild(rhs); - // if (name == "access_operation") - // std::cout << "Access Operation: " << lhs->getDataRef()->symbol.getName() << " : " << rhs->getDataRef()->symbol.getName() << std::endl; - // std::cout << functionCallName << " - " << function->getName() << " has value type " << function->getDataRef()->valueType << " and rhs " << rhs->getDataRef()->valueType << std::endl; // //Set the value of this function call - if (function->getDataRef()->valueType) - newNode->getDataRef()->valueType = function->getDataRef()->valueType; - else if (rhs->getDataRef()->valueType) + if (newNode->getDataRef()->valueType == NULL && rhs->getDataRef()->valueType) newNode->getDataRef()->valueType = rhs->getDataRef()->valueType; else newNode->getDataRef()->valueType = NULL; - std::cout << "function call to " << functionCallName << " - " << function->getName() << " is now " << newNode->getDataRef()->valueType << std::endl; + std::cout << "function call to " << functionCallName << " - " << newNode->getName() << " is now " << newNode->getDataRef()->valueType << std::endl; return newNode; //skipChildren.insert(1); } else if (children.size() == 2) { @@ -444,9 +448,13 @@ NodeTree* ASTTransformation::doFunction(NodeTree* scope, std:: std::cout< oldTypes = mapNodesToTypes(nodes); - if (lookup == "*" || lookup == "&" || lookup == "[]") { + if ((nodes.size() != 2 && lookup == "*") || lookup == "&" || lookup == "[]") { Type* newType = oldTypes[0].clone(); - lookup == "*" || lookup == "[]" ? newType->indirection-- : newType->indirection++; + if (lookup == "*" || lookup == "[]") + newType->increaseIndirection(); + else + newType->decreaseIndirection(); + newNode->getDataRef()->valueType = newType, std::cout << "Operator " + lookup << " is altering indirection "<< std::endl; } else { newNode->getDataRef()->valueType = function->getDataRef()->valueType, std::cout << "Some other ||" << lookup << "||" << std::endl; @@ -475,7 +483,9 @@ NodeTree* ASTTransformation::scopeLookup(NodeTree* scope, std: return *i; std::vector*> children = (*i)->getChildren(); - if (types.size() != ((children.size() > 0) ? children.size()-1 : 0)) { + //We subtract one from the children to get the type size only if there is at least one child AND this function is not a + //non-instantiated template (which would not have a body node, which is why we subtract one) + if (types.size() != ((children.size() > 0 && (*i)->getDataRef()->valueType->baseType != template_type ) ? children.size()-1 : children.size())) { std::cout << "Type sizes do not match between two " << lookup << "(" << types.size() << "," << ((children.size() > 0) ? children.size()-1 : 0) << "), types are: "; for (auto j : types) std::cout << j.toString() << " "; @@ -484,9 +494,12 @@ NodeTree* ASTTransformation::scopeLookup(NodeTree* scope, std: } bool typesMatch = true; for (int j = 0; j < types.size(); j++) { - if (types[j] != *(children[j]->getDataRef()->valueType)) { + Type* tmpType = children[j]->getDataRef()->valueType; + //Don't worry if types don't match if it's a template type + if (types[j] != *tmpType && tmpType->baseType != template_type_type) { typesMatch = false; - std::cout << "Types do not match between two " << lookup << " " << types[j].toString() << " vs " << children[j]->getDataRef()->valueType->toString() << std::endl; + std::cout << "Types do not match between two " << lookup << " " << types[j].toString(); + std::cout << " vs " << children[j]->getDataRef()->valueType->toString() << std::endl; break; } } @@ -546,7 +559,7 @@ Type* ASTTransformation::typeFromTypeNode(NodeTree* typeNode, NodeTreeclone(); - templateTypeReplacement->indirection += indirection; + templateTypeReplacement->modifyIndirection(indirection); return templateTypeReplacement; } else { std::cout << edited << " was not found in templateTypeReplacements" << std::endl; @@ -592,6 +605,9 @@ Type* ASTTransformation::typeFromTypeNode(NodeTree* typeNode, NodeTreeaddChildren(transformChildren(templateSyntaxTree->getChildren(), skipChildren, typeDefinition, std::vector(), newTemplateTypeReplacement)); std::cout << "Done instantating " << fullyInstantiatedName << " that had template parameter " << templateParameterName << " with " << replacementType->toString() << std::endl; + } else if (typeDefinition == NULL) { + std::cout << "Could not find type " << edited << ", returning NULL" << std::endl; + return NULL; } else { std::cout << "Type: " << edited << " already instantiated with " << typeDefinition << ", will be " << Type(baseType, typeDefinition, indirection).toString() << std::endl; } @@ -605,20 +621,37 @@ NodeTree* ASTTransformation::findOrInstantiateFunctionTemplate(std::vec //First look to see if we can find this already instantiated std::cout << "Finding or instantiating templated function" << std::endl; std::string functionName = concatSymbolTree(children[0]); - std::string fullyInstantiatedName = functionName + concatSymbolTree(children[1]); + Type* templateActualType = typeFromTypeNode(children[1]->getChildren()[1], scope, templateTypeReplacements); + std::string fullyInstantiatedName = functionName + "<" + templateActualType->toString() + ">"; std::cout << "Looking for " << fullyInstantiatedName << std::endl; - NodeTree* instantiatedFunction = scopeLookup(scope, fullyInstantiatedName); + + std::cout << "Types are : "; + for (auto i : types) + std::cout << " " << i.toString(); + std::cout << std::endl; + + NodeTree* instantiatedFunction = scopeLookup(scope, fullyInstantiatedName,types); //If it already exists, return it - if (instantiatedFunction) + if (instantiatedFunction) { + std::cout << fullyInstantiatedName << " already exists! Returning" << std::endl; return instantiatedFunction; + } else { + std::cout << fullyInstantiatedName << " does NOT exist" << std::endl; + } //Otherwise, we're going to instantiate it //Find the template definition - NodeTree* templateDefinition = scopeLookup(scope,functionName); + NodeTree* templateDefinition = scopeLookup(scope,functionName,types); + if (templateDefinition == NULL) { + std::cout << functionName << " search turned up null, returing null" << std::endl; + return NULL; + } + NodeTree* templateSyntaxTree = templateDefinition->getDataRef()->valueType->templateDefinition; std::string templateParameterName = concatSymbolTree(templateSyntaxTree->getChildren()[0]->getChildren()[1]); + std::map newTemplateTypeReplacement; - newTemplateTypeReplacement[templateParameterName] = typeFromTypeNode(children[1]->getChildren()[1], scope, templateTypeReplacements); + newTemplateTypeReplacement[templateParameterName] = templateActualType; std::vector*> templateChildren = templateSyntaxTree->getChildren(); for (int i = 0; i < templateChildren.size(); i++) diff --git a/src/CGenerator.cpp b/src/CGenerator.cpp index e4ec64f..c34fe4e 100644 --- a/src/CGenerator.cpp +++ b/src/CGenerator.cpp @@ -58,21 +58,23 @@ std::string CGenerator::generate(NodeTree* from, NodeTree* enc break; case function: { - if (decChildren.size() == 0) { //Not a real function, must be a built in passthrough { - output += "/* built in function: " + declarationData.toString() + " */\n"; - break; + if (declarationData.valueType->baseType == template_type) + output += "/* template function " + declarationData.symbol.toString() + " */\n"; + else if (decChildren.size() == 0) //Not a real function, must be a built in passthrough + output += "/* built in function: " + declarationData.symbol.toString() + " */\n"; + else { + output += "\n" + ValueTypeToCType(declarationData.valueType) + " "; + std::string nameDecoration, parameters; + for (int j = 0; j < decChildren.size()-1; j++) { + if (j > 0) + parameters += ", "; + parameters += ValueTypeToCType(decChildren[j]->getData().valueType) + " " + generate(decChildren[j], enclosingObject); + nameDecoration += "_" + ValueTypeToCTypeDecoration(decChildren[j]->getData().valueType); + } + output += CifyName(declarationData.symbol.getName()) + nameDecoration + "(" + parameters + "); /*func*/\n"; } - output += "\n" + ValueTypeToCType(declarationData.valueType) + " "; - std::string nameDecoration, parameters; - for (int j = 0; j < decChildren.size()-1; j++) { - if (j > 0) - parameters += ", "; - parameters += ValueTypeToCType(decChildren[j]->getData().valueType) + " " + generate(decChildren[j], enclosingObject); - nameDecoration += "_" + ValueTypeToCTypeDecoration(decChildren[j]->getData().valueType); - } - output += CifyName(declarationData.symbol.getName()) + nameDecoration + "(" + parameters + "); /*func*/\n"; - break; } + break; case type_def: //type output += "/*typedef " + declarationData.symbol.getName() + " */\n"; @@ -114,13 +116,15 @@ std::string CGenerator::generate(NodeTree* from, NodeTree* enc } else { std::string objectString = "typedef struct __struct_dummy_" + CifyName(data.symbol.getName()) + "__ {\n"; std::string postString; //The functions have to be outside the struct definition + tabLevel++; for (int i = 0; i < children.size(); i++) { std::cout << children[i]->getName() << std::endl; if (children[i]->getName() == "function") //If object method postString += generateObjectMethod(from, children[i]) + "\n"; else - objectString += generate(children[i], enclosingObject) + "\n"; + objectString += tabs() + generate(children[i], enclosingObject) + "\n"; } + tabLevel--; objectString += "} " + CifyName(data.symbol.getName()) + ";"; return objectString + postString; //Functions come after the declaration of the struct } @@ -202,7 +206,7 @@ std::string CGenerator::generate(NodeTree* from, NodeTree* enc if (funcType == function) { if (name == "++" || name == "--") return generate(children[1], enclosingObject) + name; - if (name == "*" || name == "&" && children.size() == 2) //Is dereference, not multiplication, or address-of + if ( (name == "*" || name == "&") && children.size() == 2) //Is dereference, not multiplication, or address-of return name + "(" + generate(children[1], enclosingObject) + ")"; if (name == "[]") return "(" + generate(children[1], enclosingObject) + ")[" +generate(children[2],enclosingObject) + "]"; @@ -283,7 +287,7 @@ std::string CGenerator::generateObjectMethod(NodeTree* enclosingObject, std::string output; ASTData data = from->getData(); Type enclosingObjectType = *(enclosingObject->getDataRef()->valueType); //Copy a new type so we can turn it into a pointer if we need to - enclosingObjectType.indirection++; + enclosingObjectType.increaseIndirection(); std::vector*> children = from->getChildren(); std::string nameDecoration, parameters; for (int i = 0; i < children.size()-1; i++) { @@ -327,7 +331,7 @@ std::string CGenerator::ValueTypeToCType(Type *type) { return_type = "unknown_ValueType"; break; } - for (int i = 0; i < type->indirection; i++) + for (int i = 0; i < type->getIndirection(); i++) return_type += "*"; return return_type; } @@ -363,7 +367,7 @@ std::string CGenerator::ValueTypeToCTypeDecoration(Type *type) { return_type = "unknown_ValueType"; break; } - for (int i = 0; i < type->indirection; i++) + for (int i = 0; i < type->getIndirection(); i++) return_type += "_P__"; return return_type; } diff --git a/src/Importer.cpp b/src/Importer.cpp index db04e72..5539516 100644 --- a/src/Importer.cpp +++ b/src/Importer.cpp @@ -40,9 +40,14 @@ Importer::~Importer() { } NodeTree* Importer::import(std::string fileName) { + + std::cout << "\n\nImporting " << fileName << " "; //Check to see if we've already done it - if (imported.find(fileName) != imported.end()) + if (imported.find(fileName) != imported.end()) { + std::cout << "Already Imported!" << std::endl; return imported[fileName]; + } + std::cout << "Not yet imported" << std::endl; std::ifstream programInFile; std::ofstream outFile, outFileTransformed, outFileAST; @@ -126,6 +131,8 @@ NodeTree* Importer::import(std::string fileName) { imported[fileName] = AST; + std::cout << "Done importing " << fileName << "\n\n" << std::endl; + return AST; } diff --git a/src/Type.cpp b/src/Type.cpp index a87aa03..1114777 100644 --- a/src/Type.cpp +++ b/src/Type.cpp @@ -19,6 +19,7 @@ Type::Type(ValueType typeIn, int indirectionIn) { baseType = typeIn; typeDefinition = NULL; templateDefinition = NULL; + if (indirection < 0) SEGFAULT } Type::Type(NodeTree* typeDefinitionIn) { @@ -32,6 +33,7 @@ Type::Type(NodeTree* typeDefinitionIn, int indirectionIn) { baseType = none; typeDefinition = typeDefinitionIn; templateDefinition = NULL; + if (indirection < 0) SEGFAULT } Type::Type(ValueType typeIn, NodeTree* typeDefinitionIn, int indirectionIn) { @@ -39,6 +41,7 @@ Type::Type(ValueType typeIn, NodeTree* typeDefinitionIn, int indirectio indirection = indirectionIn; typeDefinition = typeDefinitionIn; templateDefinition = NULL; + if (indirection < 0) SEGFAULT } Type::Type(ValueType typeIn, NodeTree* templateDefinitionIn) { indirection = 0; @@ -70,6 +73,10 @@ std::string Type::toString() { break; case template_type: typeString = "template: " + templateDefinition->getDataRef()->toString(); + break; + case template_type_type: + typeString = "template_type_type"; + break; case void_type: typeString = "void"; break; @@ -96,9 +103,34 @@ std::string Type::toString() { } for (int i = 0; i < indirection; i++) typeString += "*"; + //std::cout << "Extra components of " << typeString << " are " << indirection << " " << typeDefinition << " " << templateDefinition << std::endl; return typeString; } Type* Type::clone() { return new Type(baseType, typeDefinition, indirection); } + +void Type::check() { + if (indirection < 0) SEGFAULT +} + +int Type::getIndirection() { + return indirection; +} + +void Type::setIndirection(int indirectionIn) { + indirection = indirectionIn; + check(); +} + +void Type::increaseIndirection() { + setIndirection(indirection+1); +} +void Type::decreaseIndirection() { + setIndirection(indirection-1); +} + +void Type::modifyIndirection(int mod) { + setIndirection(indirection + mod); +} diff --git a/stdlib/mem.krak b/stdlib/mem.krak index e4dafa2..0e9bef1 100644 --- a/stdlib/mem.krak +++ b/stdlib/mem.krak @@ -21,3 +21,35 @@ void free(char* memPtr) { """ } } + +template void free(T* memPtr) { + __if_comp__ __C__ { + __simple_passthrough__ """ + free(memPtr); + """ + } +} + +template int sizeof() { + int result = 0; + T testObj; + __if_comp__ __C__ { + __simple_passthrough__ """ + result = sizeof(testObj); + """ + } + return result; +} + + +template T* new(int count) { + return malloc( sizeof() * count ); +} + +template T* new() { + return new(1); +} + +template void delete(T* toDelete) { + free(toDelete); +} diff --git a/stdlib/trivial_container.krak b/stdlib/trivial_container.krak new file mode 100644 index 0000000..341c4d2 --- /dev/null +++ b/stdlib/trivial_container.krak @@ -0,0 +1,9 @@ +import io; + +typedef template trivialContainer { + T data; + void print() { + print(data); + } +}; +