From 37cffac9cdad8412b3a97d9ce14e9a2a3298b4bc Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Tue, 18 Feb 2014 21:55:00 -0500 Subject: [PATCH] Objects work now! We have methods! --- include/ASTTransformation.h | 1 + main.cpp | 2 +- src/ASTData.cpp | 4 ++- src/ASTTransformation.cpp | 68 ++++++++++++++++++++++--------------- src/CGenerator.cpp | 40 ++++++++++++++-------- 5 files changed, 70 insertions(+), 45 deletions(-) diff --git a/include/ASTTransformation.h b/include/ASTTransformation.h index 31aaa3e..a5cf01e 100644 --- a/include/ASTTransformation.h +++ b/include/ASTTransformation.h @@ -23,4 +23,5 @@ class ASTTransformation: public NodeTransformation { private: Importer * importer; }; + #endif diff --git a/main.cpp b/main.cpp index c0f6036..90028d0 100644 --- a/main.cpp +++ b/main.cpp @@ -138,7 +138,7 @@ int main(int argc, char* argv[]) { /*NodeTree* AST =*/ importer.import(programName); - std::map*> ASTs =importer.getASTMap(); + std::map*> ASTs = importer.getASTMap(); //Do optomization, etc. here. //None at this time, instead going straight to C in this first (more naive) version diff --git a/src/ASTData.cpp b/src/ASTData.cpp index f8fd0c2..22fc30d 100644 --- a/src/ASTData.cpp +++ b/src/ASTData.cpp @@ -21,7 +21,9 @@ ASTData::~ASTData() { } std::string ASTData::toString() { - return ASTTypeToString(type) + (symbol.isTerminal() ? " " + symbol.toString() : "") + " " + (valueType ? valueType->toString() : "no_type"); + return ASTTypeToString(type) + " " + + (symbol.isTerminal() ? " " + symbol.toString() : "") + " " + + (valueType ? valueType->toString() : "no_type"); } std::string ASTData::ASTTypeToString(ASTType type) { diff --git a/src/ASTTransformation.cpp b/src/ASTTransformation.cpp index 58d829e..241fa05 100644 --- a/src/ASTTransformation.cpp +++ b/src/ASTTransformation.cpp @@ -24,27 +24,26 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree if (name == "translation_unit") { newNode = new NodeTree(name, ASTData(translation_unit)); scope = newNode; - //Temporary scope fix - Type placeholderType; - scope->getDataRef()->scope["+"] = new NodeTree("function", ASTData(function, Symbol("+", true), &placeholderType)); - scope->getDataRef()->scope["-"] = new NodeTree("function", ASTData(function, Symbol("-", true), &placeholderType)); - scope->getDataRef()->scope["*"] = new NodeTree("function", ASTData(function, Symbol("*", true), &placeholderType)); - scope->getDataRef()->scope["&"] = new NodeTree("function", ASTData(function, Symbol("&", true), &placeholderType)); - scope->getDataRef()->scope["--"] = new NodeTree("function", ASTData(function, Symbol("--", true), &placeholderType)); - scope->getDataRef()->scope["++"] = new NodeTree("function", ASTData(function, Symbol("++", true), &placeholderType)); - scope->getDataRef()->scope["=="] = new NodeTree("function", ASTData(function, Symbol("==", true), &placeholderType)); - scope->getDataRef()->scope["<="] = new NodeTree("function", ASTData(function, Symbol("<=", true), &placeholderType)); - scope->getDataRef()->scope[">="] = new NodeTree("function", ASTData(function, Symbol(">=", true), &placeholderType)); - scope->getDataRef()->scope["<"] = new NodeTree("function", ASTData(function, Symbol("<", true), &placeholderType)); - scope->getDataRef()->scope[">"] = new NodeTree("function", ASTData(function, Symbol(">", true), &placeholderType)); - scope->getDataRef()->scope["&&"] = new NodeTree("function", ASTData(function, Symbol("&&", true), &placeholderType)); - scope->getDataRef()->scope["||"] = new NodeTree("function", ASTData(function, Symbol("||", true), &placeholderType)); - scope->getDataRef()->scope["!"] = new NodeTree("function", ASTData(function, Symbol("!", true), &placeholderType)); - scope->getDataRef()->scope["*="] = new NodeTree("function", ASTData(function, Symbol("*=", true), &placeholderType)); - scope->getDataRef()->scope["+="] = new NodeTree("function", ASTData(function, Symbol("+=", true), &placeholderType)); - scope->getDataRef()->scope["-="] = new NodeTree("function", ASTData(function, Symbol("-=", true), &placeholderType)); - scope->getDataRef()->scope["."] = new NodeTree("function", ASTData(function, Symbol(".", true), &placeholderType)); - scope->getDataRef()->scope["->"] = new NodeTree("function", ASTData(function, Symbol("->", true), &placeholderType)); + //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)); @@ -116,7 +115,7 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree 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)); + 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); } else { @@ -150,6 +149,14 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree newNode->addChild(lhs); newNode->addChild(rhs); + std::cout << functionCallName << " - " << function->getName() << " has value type " << function->getDataRef()->valueType << " and rhs " << rhs->getDataRef()->valueType << std::endl; + 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 << "function call to " << functionCallName << " - " << function->getName() << " is now " << newNode->getDataRef()->valueType << std::endl; return newNode; //skipChildren.insert(1); } else { @@ -160,11 +167,11 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree //NO SUPPORT FOR CASTING YET if (children.size() == 2) { std::string funcName = concatSymbolTree(children[0]); - int funcNum; + NodeTree* param; if (funcName == "*" || funcName == "&" || funcName == "++" || funcName == "--" || funcName == "-" || funcName == "!" || funcName == "~") - funcNum = 0; + param = transform(children[1], scope); else - funcName = concatSymbolTree(children[1]), funcNum = 1; + funcName = concatSymbolTree(children[1]), param = transform(children[0], scope); //std::cout << "scope lookup from factor" << std::endl; NodeTree* function = scopeLookup(scope, funcName); @@ -174,7 +181,13 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree } newNode = new NodeTree(funcName, ASTData(function_call, Symbol(funcName, true))); newNode->addChild(function); - skipChildren.insert(funcNum); + newNode->addChild(param); + if (function->getDataRef()->valueType) + newNode->getDataRef()->valueType = function->getDataRef()->valueType; + else + newNode->getDataRef()->valueType = param->getDataRef()->valueType; + + return newNode; } else { return transform(children[0], scope); //Just a promoted child, so do it instead } @@ -258,11 +271,10 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree // throw "LOOKUP ERROR: " + functionCallName; // } newNode->addChild(function); + newNode->getDataRef()->valueType = function->getDataRef()->valueType; skipChildren.insert(0); } else if (name == "parameter") { return transform(children[0], scope); //Don't need a parameter node, just the value - } else if (name == "parameter") { - return transform(children[0], scope); //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))); diff --git a/src/CGenerator.cpp b/src/CGenerator.cpp index 1fa959b..fd22588 100644 --- a/src/CGenerator.cpp +++ b/src/CGenerator.cpp @@ -194,22 +194,32 @@ std::string CGenerator::generate(NodeTree* from, NodeTree* enc else if (name == "." || name == "->") { if (children.size() == 1) return "/*dot operation with one child*/" + generate(children[0], enclosingObject) + "/*end one child*/"; - //If this is accessing an actual function, just output the name. No actual function definition should be in an access operation - if (children[2]->getDataRef()->type == function) - return "((" + generate(children[1], enclosingObject) + ")" + name + children[2]->getDataRef()->symbol.getName() + ")"; - return "((" + generate(children[1], enclosingObject) + ")" + name + generate(children[2], enclosingObject) + ")"; - } - } - //output += data.symbol.getName() + "("; - if (funcType == function) { - output += name + "("; - std::cout << "Is a function, outputting name!" << std::cout; - if (enclosingObject && enclosingObject->getDataRef()->scope.find(name) != enclosingObject->getDataRef()->scope.end()) { - //So, it is part of the enclosing object's namespace, so it's (for now) a member function and we need to pass in an implicit self reference - output += ValueTypeToCType(enclosingObject->getDataRef()->valueType) + "* self, "; + //If this is accessing an actual function, find the function in scope and take the appropriate action. Probabally an object method + if (children[2]->getDataRef()->type == function) { + std::string functionName = children[2]->getDataRef()->symbol.getName(); + 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) + ","; + //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; + } else { + std::cout << "Is not in scope or not type" << std::endl; + return "((" + generate(children[1], enclosingObject) + ")" + name + functionName + ")"; + } + } else { + return "((" + generate(children[1], enclosingObject) + ")" + name + generate(children[2], enclosingObject) + ")"; + } + } else { + output += name + "("; } } else { - output += generate(children[0], enclosingObject) + "("; + std::string functionCallSource = generate(children[0], enclosingObject); + if (functionCallSource[functionCallSource.size()-1] == ',') //If it's a member method, it's already started the parameter list. + output += children.size() > 1 ? functionCallSource : functionCallSource.substr(0, functionCallSource.size()-1); + else + output += functionCallSource + "("; } for (int i = 1; i < children.size(); i++) //children[0] is the declaration if (i < children.size()-1) @@ -233,7 +243,7 @@ std::string CGenerator::generate(NodeTree* from, NodeTree* enc std::string CGenerator::generateObjectMethod(NodeTree* enclosingObject, NodeTree* from) { std::string output; ASTData data = from->getData(); - Type enclosingObjectType = *(enclosingObject->getDataRef()->valueType); //Copy a new type so we can turn it into a pointer + Type enclosingObjectType = *(enclosingObject->getDataRef()->valueType); //Copy a new type so we can turn it into a pointer if we need to enclosingObjectType.indirection++; std::vector*> children = from->getChildren(); output += "\n" + ValueTypeToCType(data.valueType) + " " + enclosingObject->getDataRef()->symbol.getName() +"__" + data.symbol.getName() + "(" + ValueTypeToCType(&enclosingObjectType) + " self";