From 57976beb40d8c8b080fe7a3174c282566705a04d Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Thu, 6 Mar 2014 13:13:40 -0500 Subject: [PATCH] Just got paranoid about saving all this work. Almost finished operator overloading, but everything is slightly broken right now. --- include/ASTData.h | 4 +- include/ASTTransformation.h | 7 +- include/CGenerator.h | 1 + include/NodeTransformation.h | 2 +- include/NodeTree.h | 2 +- include/ParseAction.h | 2 +- include/ParseRule.h | 2 +- include/State.h | 2 +- include/Symbol.h | 2 +- include/Type.h | 4 +- include/util.h | 2 +- src/ASTTransformation.cpp | 245 ++++++++++++++++++++++------------- src/CGenerator.cpp | 136 +++++++++++++------ src/Importer.cpp | 1 + src/Type.cpp | 8 ++ 15 files changed, 273 insertions(+), 147 deletions(-) diff --git a/include/ASTData.h b/include/ASTData.h index cd11e88..48bee63 100644 --- a/include/ASTData.h +++ b/include/ASTData.h @@ -10,7 +10,7 @@ class Type; #include "Type.h" #ifndef NULL -#define NULL 0 +#define NULL ((void*)0) #endif enum ASTType {undef, translation_unit, interpreter_directive, import, identifier, type_def, @@ -29,7 +29,7 @@ class ASTData { ASTType type; Type* valueType; Symbol symbol; - std::map*> scope; + std::map*>> scope; private: }; diff --git a/include/ASTTransformation.h b/include/ASTTransformation.h index a5cf01e..f65e95f 100644 --- a/include/ASTTransformation.h +++ b/include/ASTTransformation.h @@ -16,12 +16,15 @@ class ASTTransformation: public NodeTransformation { ASTTransformation(Importer* importerIn); ~ASTTransformation(); virtual NodeTree* transform(NodeTree* from); - NodeTree* transform(NodeTree* from, NodeTree* scope); + NodeTree* transform(NodeTree* from, NodeTree* scope, std::vector types = std::vector()); + 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); + NodeTree* scopeLookup(NodeTree* scope, std::string lookup, std::vector types = std::vector()); Type* typeFromString(std::string type, NodeTree* scope); private: Importer * importer; + std::map*>> languageLevelScope; }; #endif diff --git a/include/CGenerator.h b/include/CGenerator.h index 09142d6..9df6248 100644 --- a/include/CGenerator.h +++ b/include/CGenerator.h @@ -19,6 +19,7 @@ class CGenerator { void generateCompSet(std::map*> ASTs, std::string outputName); std::string generate(NodeTree* from, NodeTree* enclosingObject = NULL); static std::string ValueTypeToCType(Type *type); + static std::string ValueTypeToCTypeDecoration(Type *type); std::string generateObjectMethod(NodeTree* enclosingObject, NodeTree* from); std::string generatorString; diff --git a/include/NodeTransformation.h b/include/NodeTransformation.h index dc18105..ff51944 100644 --- a/include/NodeTransformation.h +++ b/include/NodeTransformation.h @@ -4,7 +4,7 @@ #include "NodeTree.h" #ifndef NULL -#define NULL 0 +#define NULL ((void*)0) #endif template diff --git a/include/NodeTree.h b/include/NodeTree.h index 0f82dac..b7573f7 100644 --- a/include/NodeTree.h +++ b/include/NodeTree.h @@ -2,7 +2,7 @@ #define NODETREE_H #ifndef NULL -#define NULL 0 +#define NULL ((void*)0) #endif #include diff --git a/include/ParseAction.h b/include/ParseAction.h index 4d62256..175dd61 100644 --- a/include/ParseAction.h +++ b/include/ParseAction.h @@ -2,7 +2,7 @@ #define PARSE_ACTION_H #ifndef NULL -#define NULL 0 +#define NULL ((void*)0) #endif #include "util.h" diff --git a/include/ParseRule.h b/include/ParseRule.h index fc56bea..dd3ac37 100644 --- a/include/ParseRule.h +++ b/include/ParseRule.h @@ -2,7 +2,7 @@ #define PARSERULE_H #ifndef NULL -#define NULL 0 +#define NULL ((void*)0) #endif #include "Symbol.h" diff --git a/include/State.h b/include/State.h index 13bd3e0..bb2d08e 100644 --- a/include/State.h +++ b/include/State.h @@ -2,7 +2,7 @@ #define STATE_H #ifndef NULL -#define NULL 0 +#define NULL ((void*)0) #endif #include "util.h" diff --git a/include/Symbol.h b/include/Symbol.h index 1d306b1..8516555 100644 --- a/include/Symbol.h +++ b/include/Symbol.h @@ -2,7 +2,7 @@ #define SYMBOL_H #ifndef NULL -#define NULL 0 +#define NULL ((void*)0) #endif #include "NodeTree.h" diff --git a/include/Type.h b/include/Type.h index a360d7f..882e143 100644 --- a/include/Type.h +++ b/include/Type.h @@ -2,7 +2,7 @@ #define TYPE_H #ifndef NULL -#define NULL 0 +#define NULL ((void*)0) #endif #include @@ -25,6 +25,8 @@ class Type { Type(NodeTree* typeDefinitionIn, int indirectionIn); Type(ValueType typeIn, NodeTree* typeDefinitionIn, int indirectionIn); ~Type(); + bool const operator==(const Type &other)const; + bool const operator!=(const Type &other)const; std::string toString(); ValueType baseType; NodeTree* typeDefinition; diff --git a/include/util.h b/include/util.h index 7e95b9e..6ca6b1e 100644 --- a/include/util.h +++ b/include/util.h @@ -2,7 +2,7 @@ #define UTIL_H #ifndef NULL -#define NULL 0 +#define NULL ((void*)0) #endif #include diff --git a/src/ASTTransformation.cpp b/src/ASTTransformation.cpp index 241fa05..ec74e2a 100644 --- a/src/ASTTransformation.cpp +++ b/src/ASTTransformation.cpp @@ -1,8 +1,28 @@ #include "ASTTransformation.h" ASTTransformation::ASTTransformation(Importer *importerIn) { - // importer = importerIn; + //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))); + 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))); + 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))); + languageLevelScope["."].push_back(new NodeTree("function", ASTData(function, Symbol(".", true), NULL))); + languageLevelScope["->"].push_back(new NodeTree("function", ASTData(function, Symbol("->", true), NULL))); } ASTTransformation::~ASTTransformation() { @@ -11,10 +31,10 @@ ASTTransformation::~ASTTransformation() { NodeTree* ASTTransformation::transform(NodeTree* from) { //Set up top scope - return transform(from, NULL); + return transform(from, NULL, std::vector()); } -NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree* scope) { +NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree* scope, std::vector types) { Symbol current = from->getData(); std::string name = current.getName(); NodeTree* newNode = NULL; @@ -24,27 +44,6 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree if (name == "translation_unit") { newNode = new NodeTree(name, ASTData(translation_unit)); scope = newNode; - //Temporary scope fix, use placeholder type - scope->getDataRef()->scope["+"] = new NodeTree("function", ASTData(function, Symbol("+", true), NULL)); - scope->getDataRef()->scope["-"] = new NodeTree("function", ASTData(function, Symbol("-", true), NULL)); - scope->getDataRef()->scope["*"] = new NodeTree("function", ASTData(function, Symbol("*", true), NULL)); - scope->getDataRef()->scope["&"] = new NodeTree("function", ASTData(function, Symbol("&", true), NULL)); - scope->getDataRef()->scope["--"] = new NodeTree("function", ASTData(function, Symbol("--", true), NULL)); - scope->getDataRef()->scope["++"] = new NodeTree("function", ASTData(function, Symbol("++", true), NULL)); - scope->getDataRef()->scope["=="] = new NodeTree("function", ASTData(function, Symbol("==", true), NULL)); - scope->getDataRef()->scope["<="] = new NodeTree("function", ASTData(function, Symbol("<=", true), NULL)); - scope->getDataRef()->scope[">="] = new NodeTree("function", ASTData(function, Symbol(">=", true), NULL)); - scope->getDataRef()->scope["<"] = new NodeTree("function", ASTData(function, Symbol("<", true), NULL)); - scope->getDataRef()->scope[">"] = new NodeTree("function", ASTData(function, Symbol(">", true), NULL)); - scope->getDataRef()->scope["&&"] = new NodeTree("function", ASTData(function, Symbol("&&", true), NULL)); - scope->getDataRef()->scope["||"] = new NodeTree("function", ASTData(function, Symbol("||", true), NULL)); - scope->getDataRef()->scope["!"] = new NodeTree("function", ASTData(function, Symbol("!", true), NULL)); - scope->getDataRef()->scope["*="] = new NodeTree("function", ASTData(function, Symbol("*=", true), NULL)); - scope->getDataRef()->scope["+="] = new NodeTree("function", ASTData(function, Symbol("+=", true), NULL)); - scope->getDataRef()->scope["-="] = new NodeTree("function", ASTData(function, Symbol("-=", true), NULL)); - scope->getDataRef()->scope["."] = new NodeTree("function", ASTData(function, Symbol(".", true), NULL)); - scope->getDataRef()->scope["->"] = new NodeTree("function", ASTData(function, Symbol("->", true), NULL)); - } else if (name == "interpreter_directive") { newNode = new NodeTree(name, ASTData(interpreter_directive)); } else if (name == "import" && !current.isTerminal()) { @@ -52,16 +51,17 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree newNode = new NodeTree(name, ASTData(import, Symbol(toImport, true))); //Do the imported file too NodeTree* outsideTranslationUnit = importer->import(toImport + ".krak"); - scope->getDataRef()->scope[toImport] = outsideTranslationUnit; //Put this transation_unit in the scope as it's files name + scope->getDataRef()->scope[toImport].push_back(outsideTranslationUnit); //Put this transation_unit in the scope as it's files name //Now add it to scope for (auto i = outsideTranslationUnit->getDataRef()->scope.begin(); i != outsideTranslationUnit->getDataRef()->scope.end(); i++) - scope->getDataRef()->scope[i->first] = i->second; + for (auto j : i->second) + scope->getDataRef()->scope[i->first].push_back(j); return newNode; // Don't need children of import } else if (name == "identifier") { //Make sure we get the entire name std::string lookupName = concatSymbolTree(from); - //std::cout << "scope lookup from identifier" << std::endl; - newNode = scopeLookup(scope, lookupName); + std::cout << "Looking up: " << lookupName << std::endl; + newNode = scopeLookup(scope, lookupName, types); if (newNode == NULL) { std::cout << "scope lookup error! Could not find " << lookupName << " in identifier " << std::endl; throw "LOOKUP ERROR: " + lookupName; @@ -80,8 +80,8 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree newNode = new NodeTree(name, ASTData(type_def, Symbol(typeAlias, true, typeAlias))); newNode->getDataRef()->valueType = new Type(newNode); //Type is self-referential since this is the definition } - scope->getDataRef()->scope[typeAlias] = newNode; - newNode->getDataRef()->scope["~enclosing_scope"] = scope; + scope->getDataRef()->scope[typeAlias].push_back(newNode); + newNode->getDataRef()->scope["~enclosing_scope"].push_back(scope); scope = newNode; skipChildren.insert(0); //Identifier lookup will be ourselves, as we just added ourselves to the scope //return newNode; @@ -90,66 +90,80 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree newNode = new NodeTree(name, ASTData(function, Symbol(functionName, true), typeFromString(concatSymbolTree(children[0]), scope))); skipChildren.insert(0); skipChildren.insert(1); - scope->getDataRef()->scope[functionName] = newNode; - newNode->getDataRef()->scope["~enclosing_scope"] = scope; + scope->getDataRef()->scope[functionName].push_back(newNode); + newNode->getDataRef()->scope["~enclosing_scope"].push_back(scope); scope = newNode; + + // auto transChildren = transformChildren(children, skipChildren, scope, types); + // std::cout << functionName << " "; + // for (auto i : transChildren) + // std::cout << "||" << i->getDataRef()->toString() << "|| "; + // std::cout << "??||" << std::endl; + // newNode->addChildren(transChildren); + // return newNode; + std::cout << "finished function " << functionName << std::endl; } else if (name == "code_block") { newNode = new NodeTree(name, ASTData(code_block)); - newNode->getDataRef()->scope["~enclosing_scope"] = scope; + newNode->getDataRef()->scope["~enclosing_scope"].push_back(scope); scope = newNode; } else if (name == "typed_parameter") { //newNode = transform(children[1]); //Transform to get the identifier std::string parameterName = concatSymbolTree(children[1]); std::string typeString = concatSymbolTree(children[0]);//Get the type (left child) and set our new identifer to be that type newNode = new NodeTree("identifier", ASTData(identifier, Symbol(parameterName, true), typeFromString(typeString, scope))); - scope->getDataRef()->scope[parameterName] = newNode; - newNode->getDataRef()->scope["~enclosing_scope"] = scope; + scope->getDataRef()->scope[parameterName].push_back(newNode); + newNode->getDataRef()->scope["~enclosing_scope"].push_back(scope); return newNode; } else if (name == "boolean_expression" || name == "and_boolean_expression" || name == "bool_exp") { //If this is an actual part of an expression, not just a premoted term if (children.size() > 1) { + //We do children first so we can do appropriate scope searching with types (yay operator overloading!) + skipChildren.insert(1); + std::vector*> transformedChildren = transformChildren(children, skipChildren, scope, types); std::string functionCallString = concatSymbolTree(children[1]); - NodeTree* function = scopeLookup(scope, functionCallString); + NodeTree* function = scopeLookup(scope, functionCallString, mapNodesToTypes(transformedChildren)); if (function == NULL) { std::cout << "scope lookup error! Could not find " << functionCallString << " in boolean stuff " << std::endl; throw "LOOKUP ERROR: " + functionCallString; } newNode = new NodeTree(functionCallString, ASTData(function_call, function->getDataRef()->valueType)); newNode->addChild(function); // First child of function call is a link to the function - skipChildren.insert(1); + newNode->addChildren(transformedChildren); } else { //std::cout << children.size() << std::endl; if (children.size() == 0) return new NodeTree(); - return transform(children[0], scope); //Just a promoted term, so do child + return transform(children[0], scope, types); //Just a promoted term, so do child } //Here's the order of ops stuff } else if (name == "expression" || name == "shiftand" || name == "term" || name == "unarad" || name == "access_operation") { //unarad can ride through, it should always just be a promoted child //If this is an actual part of an expression, not just a premoted child if (children.size() > 2) { + NodeTree* lhs = transform(children[0], scope); //LHS does not inherit types + NodeTree* rhs; + if (name == "access_operation") + rhs = transform(children[2], lhs->getDataRef()->valueType->typeDefinition, types); //If an access operation, then the right side will be in the lhs's type's scope + else + rhs = transform(children[2], scope, types); + std::string functionCallName = concatSymbolTree(children[1]); //std::cout << "scope lookup from expression or similar" << std::endl; - NodeTree* function = scopeLookup(scope, functionCallName); + std::vector*> transformedChildren; transformedChildren.push_back(lhs); transformedChildren.push_back(rhs); + NodeTree* function = scopeLookup(scope, functionCallName, mapNodesToTypes(transformedChildren)); if (function == NULL) { std::cout << "scope lookup error! Could not find " << functionCallName << " in expression " << std::endl; throw "LOOKUP ERROR: " + functionCallName; } 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 - NodeTree* lhs = transform(children[0], scope); - NodeTree* rhs;// = transform(children[2], scope); - if (name == "access_operation") - rhs = transform(children[2], lhs->getDataRef()->valueType->typeDefinition); //If an access operation, then the right side will be in the lhs's type's scope - else - rhs = transform(children[2], scope); + newNode->addChild(lhs); + newNode->addChild(rhs); if (name == "access_operation") std::cout << "Access Operation: " << lhs->getDataRef()->symbol.getName() << " : " << rhs->getDataRef()->symbol.getName() << std::endl; - - newNode->addChild(lhs); - newNode->addChild(rhs); 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) @@ -160,21 +174,22 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree return newNode; //skipChildren.insert(1); } else { - return transform(children[0], scope); //Just a promoted child, so do it instead + return transform(children[0], scope, types); //Just a promoted child, so do it instead } } else if (name == "factor") { //Do factor here, as it has all the weird unary operators - //If this is an actual part of an expression, not just a premoted child + //If this is an actual part of an expression, not just a premoted child //NO SUPPORT FOR CASTING YET if (children.size() == 2) { std::string funcName = concatSymbolTree(children[0]); NodeTree* param; if (funcName == "*" || funcName == "&" || funcName == "++" || funcName == "--" || funcName == "-" || funcName == "!" || funcName == "~") - param = transform(children[1], scope); + param = transform(children[1], scope, types); else - funcName = concatSymbolTree(children[1]), param = transform(children[0], scope); + funcName = concatSymbolTree(children[1]), param = transform(children[0], scope, types); //std::cout << "scope lookup from factor" << std::endl; - NodeTree* function = scopeLookup(scope, funcName); + std::vector*> transformedChildren; transformedChildren.push_back(param); + NodeTree* function = scopeLookup(scope, funcName, mapNodesToTypes(transformedChildren)); if (function == NULL) { std::cout << "scope lookup error! Could not find " << funcName << " in factor " << std::endl; throw "LOOKUP ERROR: " + funcName; @@ -189,7 +204,7 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree return newNode; } else { - return transform(children[0], scope); //Just a promoted child, so do it instead + return transform(children[0], scope, types); //Just a promoted child, so do it instead } } else if (name == "statement") { newNode = new NodeTree(name, ASTData(statement)); @@ -205,21 +220,23 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree newNode = new NodeTree(name, ASTData(assignment_statement)); std::string assignFuncName = concatSymbolTree(children[1]); if (assignFuncName == "=") { - newNode->addChild(transform(children[0], scope)); - newNode->addChild(transform(children[2], scope)); + newNode->addChild(transform(children[0], scope, types)); + newNode->addChild(transform(children[2], scope, types)); } else { //For assignments like += or *=, expand the syntatic sugar. - NodeTree* lhs = transform(children[0], scope); + NodeTree* lhs = transform(children[0], scope, types); + NodeTree* rhs = transform(children[2], scope, types); + 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); + NodeTree* functionDef = scopeLookup(scope, functionName, mapNodesToTypes(transformedChildren)); if (functionDef == NULL) { std::cout << "scope lookup error! Could not find " << functionName << " in assignment_statement " << std::endl; throw "LOOKUP ERROR: " + functionName; } childCall->addChild(functionDef); //First child of function call is definition of the function childCall->addChild(lhs); - childCall->addChild(transform(children[2], scope)); + childCall->addChild(rhs); newNode->addChild(lhs); newNode->addChild(childCall); } @@ -233,8 +250,8 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree std::string typeString = concatSymbolTree(children[0]);//Get the type (left child) and set our new identifer to be that type Type* identifierType = typeFromString(typeString, scope); NodeTree* newIdentifier = new NodeTree("identifier", ASTData(identifier, Symbol(newIdentifierStr, true), identifierType)); - scope->getDataRef()->scope[newIdentifierStr] = newIdentifier; - newNode->getDataRef()->scope["~enclosing_scope"] = scope; + scope->getDataRef()->scope[newIdentifierStr].push_back(newIdentifier); + newNode->getDataRef()->scope["~enclosing_scope"].push_back(scope); //Now we don't do this thing // if (identifierType->typeDefinition) { // //Is a custom type. Populate this declaration's scope with it's inner declarations @@ -257,29 +274,32 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree } else if (name == "function_call") { std::string functionCallName = concatSymbolTree(children[0]); newNode = new NodeTree(functionCallName, ASTData(function_call, Symbol(functionCallName, true))); - std::cout << "scope lookup from function_call: " << functionCallName << std::endl; - for (auto i : children) - std::cout << i << " : " << i->getName() << " : " << i->getDataRef()->getName() << std::endl; - //NodeTree* function = scopeLookup(scope, functionCallName); - NodeTree* function = transform(children[0], scope);/* scopeLookup(scope, functionCallName);*/ - std::cout << "The thing: " << function << " : " << function->getName() << std::endl; - for (auto i : function->getChildren()) - std::cout << i->getName() << " "; - std::cout << std::endl; // if (function == NULL) { // std::cout << "scope lookup error! Could not find " << functionCallName << " in function_call " << std::endl; // throw "LOOKUP ERROR: " + functionCallName; // } + skipChildren.insert(0); + std::vector*> transformedChildren = transformChildren(children, skipChildren, scope, types); + std::cout << "scope lookup from function_call: " << functionCallName << std::endl; + for (auto i : children) + std::cout << i << " : " << i->getName() << " : " << i->getDataRef()->getName() << std::endl; + + NodeTree* function = transform(children[0], scope, mapNodesToTypes(transformedChildren)); + std::cout << "The thing: " << function << " : " << function->getName() << std::endl; + for (auto i : function->getChildren()) + std::cout << i->getName() << " "; + std::cout << std::endl; newNode->addChild(function); newNode->getDataRef()->valueType = function->getDataRef()->valueType; - skipChildren.insert(0); + newNode->addChildren(transformedChildren); + return newNode; } else if (name == "parameter") { - return transform(children[0], scope); //Don't need a parameter node, just the value + return transform(children[0], scope, types); //Don't need a parameter node, just the value } else if (name == "type") { std::string theConcat = concatSymbolTree(from); //We have no symbol, so this will concat our children newNode = new NodeTree(name, ASTData(value, Symbol(theConcat, true), typeFromString(theConcat, scope))); } else if (name == "number") { - return transform(children[0], scope); + return transform(children[0], scope, types); } else if (name == "integer") { newNode = new NodeTree(name, ASTData(value, Symbol(concatSymbolTree(from), true), new Type(integer))); } else if (name == "float") { @@ -294,20 +314,42 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree return new NodeTree(); } - // In general, iterate through children and do them. Might not do this for all children. + //Do all children but the ones we skip for (int i = 0; i < children.size(); i++) { if (skipChildren.find(i) == skipChildren.end()) { - NodeTree* transChild = transform(children[i], scope); + NodeTree* transChild = transform(children[i], scope, types); if (transChild->getDataRef()->type) //Only add the children that have a real ASTData::ASTType, that is, legit ASTData. newNode->addChild(transChild); else delete transChild; } } - return newNode; } +//We use this functionality a lot at different places +std::vector*> ASTTransformation::transformChildren(std::vector*> children, std::set skipChildren, NodeTree* scope, std::vector types) { + std::vector*> transformedChildren; + // In general, iterate through children and do them. Might not do this for all children. + for (int i = 0; i < children.size(); i++) { + if (skipChildren.find(i) == skipChildren.end()) { + NodeTree* transChild = transform(children[i], scope, types); + if (transChild->getDataRef()->type) //Only add the children that have a real ASTData::ASTType, that is, legit ASTData. + transformedChildren.push_back(transChild); + else + delete transChild; + } + } + return transformedChildren; +} + +std::vector ASTTransformation::mapNodesToTypes(std::vector*> nodes) { + std::vector types; + for (auto i : nodes) + types.push_back(*(i->getDataRef()->valueType)); + return types; +} + std::string ASTTransformation::concatSymbolTree(NodeTree* root) { std::string concatString; std::string ourValue = root->getDataRef()->getValue(); @@ -320,33 +362,52 @@ std::string ASTTransformation::concatSymbolTree(NodeTree* root) { return concatString; } -NodeTree* ASTTransformation::scopeLookup(NodeTree* scope, std::string lookup) { - //First, if it is a struct or object, get it's base. - std::vector splitString = split(lookup, '.'); - if (splitString.size() > 1) { - std::string base = splitString[0]; - // NodeTree* baseDef = scopeLookup(scope, base); - // splitString.erase(splitString.begin()); //Get rid of the base in the split str - // //Now the base is the scope. - // return scopeLookup(baseDef, join(splitString, ".")); //So the joined version doesn't have the base. - return scopeLookup(scope, base); - } +NodeTree* ASTTransformation::scopeLookup(NodeTree* scope, std::string lookup, std::vector types) { //Search the map auto scopeMap = scope->getDataRef()->scope; auto elementIterator = scopeMap.find(lookup); + // if (elementIterator != scopeMap.end()) { - // std::cout << "lookup of " << lookup << " succeded in first scope!" << std::endl; - return elementIterator->second; + for (auto i = elementIterator->second.begin(); i != elementIterator->second.end(); i++) { + //Types and functions cannot have the same name, and types very apparently do not have parameter types, so check and short-circuit + if ((*i)->getDataRef()->type == type_def) + return *i; + //return *i; + std::vector*> children = (*i)->getChildren(); + 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() << " "; + std::cout << std::endl; + continue; + } + bool typesMatch = true; + for (int j = 0; j < types.size(); j++) { + if (types[j] != *(children[j]->getDataRef()->valueType)) { + typesMatch = false; + std::cout << "Types do not match between two " << lookup << std::endl; + break; + } + } + if (typesMatch) + return *i; + } } - //std::cout << "lookup of " << lookup << " failed in first scope, checking for upper scope" << std::endl; + //if it doesn't exist, try the enclosing scope if it exists. 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, lookup); + return scopeLookup(enclosingIterator->second[0], lookup, types); } //std::cout << "upper scope does not exist" << std::endl; - std::cout << "could not find " << lookup << 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()) { + std::cout << "found it at language level as operator." << std::endl; + return elementIterator->second[0]; + } return NULL; } diff --git a/src/CGenerator.cpp b/src/CGenerator.cpp index fd22588..5fda00a 100644 --- a/src/CGenerator.cpp +++ b/src/CGenerator.cpp @@ -48,33 +48,39 @@ std::string CGenerator::generate(NodeTree* from, NodeTree* enc output += generate(children[i], enclosingObject) + "\n"; //Declare everything in translation unit scope here. (allows stuff from other files, automatic forward declarations) for (auto i = data.scope.begin(); i != data.scope.end(); i++) { - NodeTree* declaration = i->second; - std::vector*> decChildren = declaration->getChildren(); - ASTData declarationData = i->second->getData(); - switch(declarationData.type) { - case identifier: - output += ValueTypeToCType(declarationData.valueType) + " " + declarationData.symbol.getName() + "; /*identifier*/\n"; - break; - case function: - if (decChildren.size() == 0) { //Not a real function, must be a built in passthrough { - output += "/* built in function: " + declarationData.toString() + " */\n"; + for (auto overloadedMembers : i->second) { + NodeTree* declaration = overloadedMembers; + std::vector*> decChildren = declaration->getChildren(); + ASTData declarationData = declaration->getData(); + switch(declarationData.type) { + case identifier: + output += ValueTypeToCType(declarationData.valueType) + " " + declarationData.symbol.getName() + "; /*identifier*/\n"; + 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; + } + 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 += nameDecoration + declarationData.symbol.getName() + "(" + parameters + "); /*func*/\n"; break; } - output += "\n" + ValueTypeToCType(declarationData.valueType) + " " + declarationData.symbol.getName() + "("; - for (int j = 0; j < decChildren.size()-1; j++) { - if (j > 0) - output += ", "; - output += ValueTypeToCType(decChildren[j]->getData().valueType) + " " + generate(decChildren[j], enclosingObject); - } - output += "); /*func*/\n"; - break; - case type_def: - //type - output += "/*typedef " + declarationData.symbol.getName() + " */\n"; - break; - default: - //std::cout << "Declaration? named " << declaration->getName() << " of unknown type " << ASTData::ASTTypeToString(declarationData.type) << " in translation unit scope" << std::endl; - output += "/*unknown declaration named " + declaration->getName() + "*/\n"; + case type_def: + //type + output += "/*typedef " + declarationData.symbol.getName() + " */\n"; + break; + default: + //std::cout << "Declaration? named " << declaration->getName() << " of unknown type " << ASTData::ASTTypeToString(declarationData.type) << " in translation unit scope" << std::endl; + output += "/*unknown declaration named " + declaration->getName() + "*/\n"; + } } } //Do here because we need the newlines @@ -92,9 +98,12 @@ std::string CGenerator::generate(NodeTree* from, NodeTree* enc case identifier: { //If we're in an object method, and our enclosing scope is that object, we're a member of the object and should use the self reference. - if (enclosingObject && enclosingObject->getDataRef()->scope.find(data.symbol.getName()) != enclosingObject->getDataRef()->scope.end()) { - return "self->" + data.symbol.getName(); - } + std::string preName; + if (enclosingObject && enclosingObject->getDataRef()->scope.find(data.symbol.getName()) != enclosingObject->getDataRef()->scope.end()) + preName += "self->"; + if (false) + for (int j = 0; j < children.size()-1; j++) + preName += ValueTypeToCType(children[j]->getData().valueType) + "_"; return data.symbol.getName(); } case type_def: @@ -114,21 +123,25 @@ std::string CGenerator::generate(NodeTree* from, NodeTree* enc return objectString + postString; //Functions come after the declaration of the struct } case function: - output += "\n" + ValueTypeToCType(data.valueType) + " " + data.symbol.getName() + "("; - for (int i = 0; i < children.size()-1; i++) { - if (i > 0) - output += ", "; - output += ValueTypeToCType(children[i]->getData().valueType) + " " + generate(children[i], enclosingObject); + { + output += "\n" + ValueTypeToCType(data.valueType) + " "; + std::string nameDecoration, parameters; + for (int j = 0; j < children.size()-1; j++) { + if (j > 0) + parameters += ", "; + parameters += ValueTypeToCType(children[j]->getData().valueType) + " " + generate(children[j], enclosingObject); + nameDecoration += ValueTypeToCTypeDecoration(children[j]->getData().valueType) + "_"; } - output+= ")\n" + generate(children[children.size()-1], enclosingObject); + output += nameDecoration + data.symbol.getName() + "(" + parameters + ")\n" + generate(children[children.size()-1], enclosingObject); return output; + } case code_block: output += "{\n"; tabLevel++; for (int i = 0; i < children.size(); i++) { - std::cout << "Line " << i << std::endl; + //std::cout << "Line " << i << std::endl; std::string line = generate(children[i], enclosingObject); - std::cout << line << std::endl; + //std::cout << line << std::endl; output += line; } tabLevel--; @@ -200,19 +213,19 @@ std::string CGenerator::generate(NodeTree* from, NodeTree* enc NodeTree* possibleObjectType = children[1]->getDataRef()->valueType->typeDefinition; //If is an object method, generate it like one. Needs extension/modification for inheritence if (possibleObjectType && possibleObjectType->getDataRef()->scope.find(functionName) != possibleObjectType->getDataRef()->scope.end()) { - return possibleObjectType->getDataRef()->symbol.getName() +"__" + functionName + "(" + (name == "." ? "&" : "") + generate(children[1], enclosingObject) + ","; +HERE return possibleObjectType->getDataRef()->symbol.getName() +"__" + functionName + "(" + (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 - std::cout << "Is in scope or not type!" << std::endl; + //Note that we got here from a function call. We just pass up this special case and let them finish with the perentheses } else { std::cout << "Is not in scope or not type" << std::endl; - return "((" + generate(children[1], enclosingObject) + ")" + name + functionName + ")"; +WTHISTHIS return "((" + generate(children[1], enclosingObject) + ")" + name + functionName + ")"; } } else { - return "((" + generate(children[1], enclosingObject) + ")" + name + generate(children[2], enclosingObject) + ")"; +ALSOWTH return "((" + generate(children[1], enclosingObject) + ")" + name + generate(children[2], enclosingObject) + ")"; } } else { - output += name + "("; + //It's a normal function call, not a special one or a method or anything +HERE output += name + "("; } } else { std::string functionCallSource = generate(children[0], enclosingObject); @@ -224,7 +237,8 @@ std::string CGenerator::generate(NodeTree* from, NodeTree* enc for (int i = 1; i < children.size(); i++) //children[0] is the declaration if (i < children.size()-1) output += generate(children[i], enclosingObject) + ", "; - else output += generate(children[i], enclosingObject); + else + output += generate(children[i], enclosingObject); output += ") "; return output; } @@ -288,3 +302,39 @@ std::string CGenerator::ValueTypeToCType(Type *type) { return_type += "*"; return return_type; } + +std::string CGenerator::ValueTypeToCTypeDecoration(Type *type) { + std::string return_type; + switch (type->baseType) { + case none: + if (type->typeDefinition) + return_type = type->typeDefinition->getDataRef()->symbol.getName(); + else + return_type = "none"; + break; + case void_type: + return_type = "void"; + break; + case boolean: + return_type = "bool"; + break; + case integer: + return_type = "int"; + break; + case floating: + return_type = "float"; + break; + case double_percision: + return_type = "double"; + break; + case character: + return_type = "char"; + break; + default: + return_type = "unknown_ValueType"; + break; + } + for (int i = 0; i < type->indirection; i++) + return_type += "_P__"; + return return_type; +} diff --git a/src/Importer.cpp b/src/Importer.cpp index d158470..88c367f 100644 --- a/src/Importer.cpp +++ b/src/Importer.cpp @@ -106,6 +106,7 @@ NodeTree* Importer::import(std::string fileName) { } outFileTransformed.close(); + //Call with ourself to allow the transformation to call us to import files that it needs NodeTree* AST = ASTTransformation(this).transform(parseTree); if (AST) { diff --git a/src/Type.cpp b/src/Type.cpp index 613324d..2e40328 100644 --- a/src/Type.cpp +++ b/src/Type.cpp @@ -38,6 +38,14 @@ Type::Type(ValueType typeIn, NodeTree* typeDefinitionIn, int indirectio Type::~Type() { } +const bool Type::operator==(const Type &other) const { + return( baseType == other.baseType && indirection == other.indirection && typeDefinition == other.typeDefinition); +} + +const bool Type::operator!=(const Type &other) const { + return(!this->operator==(other)); +} + std::string Type::toString() { std::string typeString; switch (baseType) {