diff --git a/include/ASTTransformation.h b/include/ASTTransformation.h index f65e95f..fccf125 100644 --- a/include/ASTTransformation.h +++ b/include/ASTTransformation.h @@ -20,6 +20,7 @@ class ASTTransformation: public NodeTransformation { std::vector*> transformChildren(std::vector*> children, std::set skipChildren, NodeTree* scope, std::vector types); std::vector mapNodesToTypes(std::vector*> nodes); std::string concatSymbolTree(NodeTree* root); + NodeTree* scopeLookup(NodeTree* scope, std::string lookup, std::vector*> nodes); NodeTree* scopeLookup(NodeTree* scope, std::string lookup, std::vector types = std::vector()); Type* typeFromString(std::string type, NodeTree* scope); private: diff --git a/include/CGenerator.h b/include/CGenerator.h index 9df6248..fe8e8b8 100644 --- a/include/CGenerator.h +++ b/include/CGenerator.h @@ -20,6 +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); std::string generateObjectMethod(NodeTree* enclosingObject, NodeTree* from); std::string generatorString; diff --git a/include/util.h b/include/util.h index 2be7301..7f17f51 100644 --- a/include/util.h +++ b/include/util.h @@ -24,4 +24,16 @@ bool contains(std::vector vec, T item) { return false; } +template +std::vector slice(std::vector vec, int begin, int end) { + std::vector toReturn; + if (begin < 0) + begin += vec.size()+1; + if (end < 0) + end += vec.size()+1; + for (int i = begin; i < end; i++) + toReturn.push_back(vec[i]); + return toReturn; +} + #endif diff --git a/krakenGrammer.kgm b/krakenGrammer.kgm index f396a63..9438a5a 100644 --- a/krakenGrammer.kgm +++ b/krakenGrammer.kgm @@ -29,7 +29,9 @@ triple_quoted_string = "\"\"\"((\"\"(`|1|2|3|4|5|6|7|8|9|0|-|=| |q|w|e|r|t|y|u|i identifier = alpha | alpha alphanumeric ; -function = type WS identifier WS "\(" WS opt_typed_parameter_list WS "\)" WS code_block ; +overloadable_operator = "\+" | "-" | "\*" | "/" | "%" | "^" | "&" | "\|" | "~" | "\!" | "," | "=" | "\+\+" | "--" | "<<" | ">>" | "==" | "!=" | "&&" | "\|\|" | "\+=" | "-=" | "/=" | "%=" | "^=" | "&=" | "\|=" | "\*=" | "<<=" | ">>=" | "->" ; +func_identifier = identifier | identifier overloadable_operator ; +function = type WS func_identifier WS "\(" WS opt_typed_parameter_list WS "\)" WS code_block ; opt_typed_parameter_list = typed_parameter_list | ; typed_parameter_list = typed_parameter_list WS "," WS typed_parameter | typed_parameter ; @@ -89,5 +91,5 @@ string = triple_quoted_string | "\"(`|1|2|3|4|5|6|7|8|9|0|-|=| |q|w|e|r|t|y|u|i| |z|x|c|v|b|n|m|,|.|/|~|!|@|#|$|%|^|&|\*|\(|\)|_|\+|Q|W|E|R|T|Y|U|I|O|P|{|}|\||A|S|D|F|G|H|J|K|L|:|Z|X|C|V|B|N|M|<|>|\?| )*\"" ; comment = "//(`|1|2|3|4|5|6|7|8|9|0|-|=| |q|w|e|r|t|y|u|i|o|p|[|]|\\|a|s|d|f|g|h|j|k|l|;|'|z|x|c|v|b|n|m|,|.|/|~|!|@|#|$|%|^|&|\*|\(|\)|_|\+|Q|W|E|R|T|Y|U|I|O|P|{|}|\||A|S|D|F|G|H|J|K|L|:|\"|Z|X|C|V|B|N|M|<|>|\?| )* -" | "/\*(`|1|2|3|4|5|6|7|8|9|0|-|=| |q|w|e|r|t|y|u|i|o|p|[|]|\\|a|s|d|f|g|h|j|k|l|;|'| -|z|x|c|v|b|n|m|,|.|/|~|!|@|#|$|%|^|&|\*|\(|\)|_|\+|Q|W|E|R|T|Y|U|I|O|P|{|}|\||A|S|D|F|G|H|J|K|L|:|\"|Z|X|C|V|B|N|M|<|>|\?| )*\*/" ; +" | "(/\*+((`|1|2|3|4|5|6|7|8|9|0|-|=| |q|w|e|r|t|y|u|i|o|p|[|]|\\|a|s|d|f|g|h|j|k|l|;|'| +|z|x|c|v|b|n|m|,|.|~|!|@|#|$|%|^|&|\(|\)|_|\+|Q|W|E|R|T|Y|U|I|O|P|{|}|\||A|S|D|F|G|H|J|K|L|:|\"|Z|X|C|V|B|N|M|<|>|\?| )/*\**)+\*/)|(/\*\*/)" ; diff --git a/src/ASTTransformation.cpp b/src/ASTTransformation.cpp index ec74e2a..c91572a 100644 --- a/src/ASTTransformation.cpp +++ b/src/ASTTransformation.cpp @@ -122,7 +122,7 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree skipChildren.insert(1); std::vector*> transformedChildren = transformChildren(children, skipChildren, scope, types); std::string functionCallString = concatSymbolTree(children[1]); - NodeTree* function = scopeLookup(scope, functionCallString, mapNodesToTypes(transformedChildren)); + NodeTree* function = scopeLookup(scope, functionCallString, transformedChildren); if (function == NULL) { std::cout << "scope lookup error! Could not find " << functionCallString << " in boolean stuff " << std::endl; throw "LOOKUP ERROR: " + functionCallString; @@ -150,7 +150,7 @@ 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 = scopeLookup(scope, functionCallName, mapNodesToTypes(transformedChildren)); + NodeTree* function = scopeLookup(scope, functionCallName, transformedChildren); if (function == NULL) { std::cout << "scope lookup error! Could not find " << functionCallName << " in expression " << std::endl; throw "LOOKUP ERROR: " + functionCallName; @@ -189,7 +189,7 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree //std::cout << "scope lookup from factor" << std::endl; std::vector*> transformedChildren; transformedChildren.push_back(param); - NodeTree* function = scopeLookup(scope, funcName, mapNodesToTypes(transformedChildren)); + NodeTree* function = scopeLookup(scope, funcName, transformedChildren); if (function == NULL) { std::cout << "scope lookup error! Could not find " << funcName << " in factor " << std::endl; throw "LOOKUP ERROR: " + funcName; @@ -229,7 +229,7 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree std::vector*> transformedChildren; transformedChildren.push_back(lhs); transformedChildren.push_back(rhs); std::string functionName = assignFuncName.substr(0,1); NodeTree* childCall = new NodeTree(functionName, ASTData(function_call, Symbol(functionName, true))); - NodeTree* functionDef = scopeLookup(scope, functionName, mapNodesToTypes(transformedChildren)); + NodeTree* functionDef = scopeLookup(scope, functionName, transformedChildren); if (functionDef == NULL) { std::cout << "scope lookup error! Could not find " << functionName << " in assignment_statement " << std::endl; throw "LOOKUP ERROR: " + functionName; @@ -362,10 +362,53 @@ std::string ASTTransformation::concatSymbolTree(NodeTree* root) { return concatString; } +//Overloaded with the actual children to allow us to handle operator methods +NodeTree* ASTTransformation::scopeLookup(NodeTree* scope, std::string lookup, std::vector*> nodes) { + // + auto LLElementIterator = languageLevelScope.find(lookup); + if (LLElementIterator != languageLevelScope.end()) { + std::cout << "Checking for early method level operator overload" << std::endl; + std::string lookupOp = "operator" + lookup; + for (auto i : nodes) + std::cout << i->getDataRef()->toString() << " "; + std::cout << std::endl; + NodeTree* operatorMethod = NULL; + if (nodes[0]->getDataRef()->valueType && nodes[0]->getDataRef()->valueType->typeDefinition) + operatorMethod = scopeLookup(nodes[0]->getDataRef()->valueType->typeDefinition, lookupOp, mapNodesToTypes(slice(nodes,1,-1))); + if (operatorMethod) { + //Ok, so we construct + std::cout << "Early method level operator was found" << std::endl; + //return operatorMethod; + 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); + + + //Set the value of this function call + if (function->getDataRef()->valueType) + newNode->getDataRef()->valueType = function->getDataRef()->valueType; + else if (rhs->getDataRef()->valueType) + newNode->getDataRef()->valueType = rhs->getDataRef()->valueType; + else + newNode->getDataRef()->valueType = NULL; + } + std::cout << "Early method level operator was NOT found" << std::endl; + } + return scopeLookup(scope, lookup, mapNodesToTypes(nodes)); +} + NodeTree* ASTTransformation::scopeLookup(NodeTree* scope, std::string lookup, std::vector types) { + //We first search the languageLevelScope to see if it's an operator. If so, we modifiy the lookup with a preceding "operator" + auto LLElementIterator = languageLevelScope.find(lookup); + if (LLElementIterator != languageLevelScope.end()) + lookup = "operator" + lookup; //Search the map auto scopeMap = scope->getDataRef()->scope; auto elementIterator = scopeMap.find(lookup); + for (auto i : scopeMap) + std::cout << i.first << " "; + std::cout << std::endl; // if (elementIterator != scopeMap.end()) { for (auto i = elementIterator->second.begin(); i != elementIterator->second.end(); i++) { @@ -374,7 +417,7 @@ NodeTree* ASTTransformation::scopeLookup(NodeTree* scope, std: return *i; //return *i; std::vector*> children = (*i)->getChildren(); - if (types.size() != (children.size() > 0) ? children.size()-1 : 0) { + if (types.size() != ((children.size() > 0) ? children.size()-1 : 0)) { 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() << " "; @@ -398,16 +441,19 @@ NodeTree* ASTTransformation::scopeLookup(NodeTree* scope, std: auto enclosingIterator = scopeMap.find("~enclosing_scope"); if (enclosingIterator != scopeMap.end()) { // std::cout << "upper scope exists, searching it for " << lookup << std::endl; - return scopeLookup(enclosingIterator->second[0], lookup, types); + NodeTree* upperResult = scopeLookup(enclosingIterator->second[0], lookup, types); + if (upperResult) + return upperResult; } //std::cout << "upper scope does not exist" << std::endl; std::cout << "could not find " << lookup << " in standard scope, checking for operator" << std::endl; //Note that we don't check for types. At some point we should, as we don't know how to add objects/structs without overloaded operators, etc - elementIterator = languageLevelScope.find(lookup); - if (elementIterator != languageLevelScope.end()) { + //Also, we've already searched for the element because this is also how we keep track of operator overloading + if (LLElementIterator != languageLevelScope.end()) { std::cout << "found it at language level as operator." << std::endl; - return elementIterator->second[0]; + return LLElementIterator->second[0]; } + std::cout << "Did not find, returning NULL" << std::endl; return NULL; } diff --git a/src/CGenerator.cpp b/src/CGenerator.cpp index 641ba4d..c6c7723 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 += declarationData.symbol.getName() + nameDecoration + "(" + parameters + "); /*func*/\n"; + output += CifyFunctionName(declarationData.symbol.getName()) + nameDecoration + "(" + parameters + "); /*func*/\n"; break; } case type_def: @@ -104,7 +104,7 @@ 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 + data.symbol.getName(); + return preName + CifyFunctionName(data.symbol.getName()); //Cifying does nothing if not an operator overload } case type_def: if (children.size() == 0) { @@ -132,7 +132,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 += data.symbol.getName() + nameDecoration + "(" + parameters + ")\n" + generate(children[children.size()-1], enclosingObject); + output += CifyFunctionName(data.symbol.getName()) + nameDecoration + "(" + parameters + ")\n" + generate(children[children.size()-1], enclosingObject); return output; } case code_block: @@ -218,7 +218,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() +"__" + functionName + nameDecoration + "(" + (name == "." ? "&" : "") + generate(children[1], enclosingObject) + ","; +/*HERE*/ return possibleObjectType->getDataRef()->symbol.getName() +"__" + CifyFunctionName(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 { @@ -240,7 +240,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 += name + nameDecoration + "("; +/*HERE*/ output += CifyFunctionName(name) + nameDecoration + "("; if (isSelfObjectMethod) output += children.size() > 1 ? "self," : "self"; } @@ -285,8 +285,8 @@ std::string CGenerator::generateObjectMethod(NodeTree* enclosingObject, nameDecoration += "_" + ValueTypeToCTypeDecoration(children[i]->getData().valueType); } output += "\n" + ValueTypeToCType(data.valueType) + " " + enclosingObject->getDataRef()->symbol.getName() +"__" - + data.symbol.getName() + nameDecoration + "(" + ValueTypeToCType(&enclosingObjectType) + " self" + parameters + ")\n" - + generate(children[children.size()-1], enclosingObject); //Pass in the object so we can + + CifyFunctionName(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; } @@ -362,3 +362,47 @@ std::string CGenerator::ValueTypeToCTypeDecoration(Type *type) { return return_type; } +std::string CGenerator::CifyFunctionName(std::string name) { + std::string operatorsToReplace[] = { "+", "plus", + "-", "minus", + "*", "star", + "/", "div", + "%", "mod", + "^", "carat", + "&", "amprsd", + "|", "pipe", + "~", "tilde", + "!", "exclamationpt", + ",", "comma", + "=", "equals", + "++", "doubleplus", + "--", "doubleminus", + "<<", "doubleleft", + ">>", "doubleright", + "==", "doubleequals", + "!=", "notequals", + "&&", "doubleamprsnd", + "||", "doublepipe", + "+=", "plusequals", + "-=", "minusequals", + "/=", "divequals", + "%=", "modequals", + "^=", "caratequals", + "&=", "amprsdequals", + "|=", "pipeequals", + "*=", "starequals", + "<<=", "doublerightequals", + ">>=", "doubleleftequals", + "->", "arrow" }; + int length = sizeof(operatorsToReplace)/sizeof(std::string); + //std::cout << "Length is " << length << std::endl; + for (int i = 0; i < length; i+= 2) { + size_t foundPos = name.find(operatorsToReplace[i]); + while(foundPos != std::string::npos) { + name = strSlice(name, 0, foundPos) + "_" + operatorsToReplace[i+1] + "_" + strSlice(name, foundPos+operatorsToReplace[i].length(), -1); + foundPos = name.find(operatorsToReplace[i]); + } + } + return name; +} +