Fixed quite a few bugs, including makeing find template functions check for trait subset, not trait equality, and add the number required to the satisfied count. Based on what is now breaking, it looks like it's time to give the builtin functions types.

This commit is contained in:
Nathan Braswell
2014-07-23 02:23:21 -07:00
parent eae538907d
commit 87ad0c187e
7 changed files with 182 additions and 131 deletions

View File

@@ -34,21 +34,21 @@ class ASTTransformation: public NodeTransformation<Symbol,ASTData> {
//The fourth pass finishes up by doing all function bodies //The fourth pass finishes up by doing all function bodies
void fourthPass(NodeTree<ASTData>* ast, NodeTree<Symbol>* parseTree); void fourthPass(NodeTree<ASTData>* ast, NodeTree<Symbol>* parseTree);
NodeTree<ASTData>* seachScopeForFunctionDef(NodeTree<ASTData>* scope, NodeTree<Symbol>* parseTree, std::map<std::string, Type*> templateTypeReplacements); NodeTree<ASTData>* searchScopeForFunctionDef(NodeTree<ASTData>* scope, NodeTree<Symbol>* parseTree, std::map<std::string, Type*> templateTypeReplacements);
void fourthPassFunction(NodeTree<Symbol>* from, NodeTree<ASTData>* functionDef, std::map<std::string, Type*> templateTypeReplacements); void fourthPassFunction(NodeTree<Symbol>* from, NodeTree<ASTData>* functionDef, std::map<std::string, Type*> templateTypeReplacements);
virtual NodeTree<ASTData>* transform(NodeTree<Symbol>* from); virtual NodeTree<ASTData>* transform(NodeTree<Symbol>* from);
NodeTree<ASTData>* transform(NodeTree<Symbol>* from, NodeTree<ASTData>* scope, std::vector<Type> types, std::map<std::string, Type*> templateTypeReplacements, bool instantiateTemplates); NodeTree<ASTData>* transform(NodeTree<Symbol>* from, NodeTree<ASTData>* scope, std::vector<Type> types, std::map<std::string, Type*> templateTypeReplacements);
std::vector<NodeTree<ASTData>*> transformChildren(std::vector<NodeTree<Symbol>*> children, std::set<int> skipChildren, NodeTree<ASTData>* scope, std::vector<Type> types, std::map<std::string, Type*> templateTypeReplacements, bool instantiateTemplates); std::vector<NodeTree<ASTData>*> transformChildren(std::vector<NodeTree<Symbol>*> children, std::set<int> skipChildren, NodeTree<ASTData>* scope, std::vector<Type> types, std::map<std::string, Type*> templateTypeReplacements);
std::vector<Type> mapNodesToTypes(std::vector<NodeTree<ASTData>*> nodes); std::vector<Type> mapNodesToTypes(std::vector<NodeTree<ASTData>*> nodes);
std::string concatSymbolTree(NodeTree<Symbol>* root); std::string concatSymbolTree(NodeTree<Symbol>* root);
NodeTree<ASTData>* doFunction(NodeTree<ASTData>* scope, std::string lookup, std::vector<NodeTree<ASTData>*> nodes, std::map<std::string, Type*> templateTypeReplacements); NodeTree<ASTData>* doFunction(NodeTree<ASTData>* scope, std::string lookup, std::vector<NodeTree<ASTData>*> nodes, std::map<std::string, Type*> templateTypeReplacements);
NodeTree<ASTData>* functionLookup(NodeTree<ASTData>* scope, std::string lookup, std::vector<Type> types); NodeTree<ASTData>* functionLookup(NodeTree<ASTData>* scope, std::string lookup, std::vector<Type> types);
NodeTree<ASTData>* templateFunctionLookup(NodeTree<ASTData>* scope, std::string lookup, std::vector<Type*> templateInstantiationTypes, std::vector<Type> types); NodeTree<ASTData>* templateFunctionLookup(NodeTree<ASTData>* scope, std::string lookup, std::vector<Type*> templateInstantiationTypes, std::vector<Type> types);
std::vector<NodeTree<ASTData>*> scopeLookup(NodeTree<ASTData>* scope, std::string lookup); std::vector<NodeTree<ASTData>*> scopeLookup(NodeTree<ASTData>* scope, std::string lookup, bool includeModules = false);
Type* typeFromTypeNode(NodeTree<Symbol>* typeNode, NodeTree<ASTData>* scope, std::map<std::string, Type*> templateTypeReplacements, bool instantiateTemplates); Type* typeFromTypeNode(NodeTree<Symbol>* typeNode, NodeTree<ASTData>* scope, std::map<std::string, Type*> templateTypeReplacements);
NodeTree<ASTData>* templateClassLookup(NodeTree<ASTData>* scope, std::string name, std::vector<Type*> templateInstantiationTypes); NodeTree<ASTData>* templateClassLookup(NodeTree<ASTData>* scope, std::string name, std::vector<Type*> templateInstantiationTypes);
NodeTree<ASTData>* findOrInstantiateFunctionTemplate(std::vector<NodeTree<Symbol>*> children, NodeTree<ASTData>* scope, std::vector<Type> types, std::map<std::string, Type*> templateTypeReplacements); NodeTree<ASTData>* findOrInstantiateFunctionTemplate(std::vector<NodeTree<Symbol>*> children, NodeTree<ASTData>* scope, std::vector<Type> types, std::map<std::string, Type*> templateTypeReplacements);
std::map<std::string, Type*> makeTemplateFunctionTypeMap(NodeTree<Symbol>* templateNode, std::vector<Type*> types); std::map<std::string, Type*> makeTemplateFunctionTypeMap(NodeTree<Symbol>* templateNode, std::vector<Type*> types);

View File

@@ -9,6 +9,7 @@
#include <string> #include <string>
#include <sstream> #include <sstream>
#include <vector> #include <vector>
#include <set>
#include <fstream> #include <fstream>
#include <cstring> #include <cstring>
@@ -40,6 +41,14 @@ std::vector<T> slice(std::vector<T> vec, int begin, int end, int step = 1) {
toReturn.push_back(vec[i]); toReturn.push_back(vec[i]);
return toReturn; return toReturn;
} }
template <typename T>
bool subset(std::set<T> a, std::set<T> b) {
for (auto i : a)
if (b.find(i) == b.end())
return false;
return true;
}
/* /*
std::vector<std::string> split(std::string str, char delim) { std::vector<std::string> split(std::string str, char delim) {
std::stringstream stream(str); std::stringstream stream(str);

View File

@@ -79,7 +79,7 @@ function_call = unarad "\(" WS opt_parameter_list WS "\)" ;
boolean_expression = boolean_expression WS "\|\|" WS and_boolean_expression | and_boolean_expression ; boolean_expression = boolean_expression WS "\|\|" WS and_boolean_expression | and_boolean_expression ;
and_boolean_expression = and_boolean_expression "&&" bool_exp | bool_exp ; and_boolean_expression = and_boolean_expression "&&" bool_exp | bool_exp ;
bool_exp = expression WS comparator WS expression | bool | expression ; bool_exp = expression WS comparator WS expression | expression ;
comparator = "==" | "<=" | ">=" | "!=" | "<" | ">" ; comparator = "==" | "<=" | ">=" | "!=" | "<" | ">" ;
expression = expression WS "<<" WS term | expression WS right_shift WS shiftand | shiftand ; expression = expression WS "<<" WS term | expression WS right_shift WS shiftand | shiftand ;

View File

@@ -118,7 +118,7 @@ void ASTTransformation::secondPass(NodeTree<ASTData>* ast, NodeTree<Symbol>* par
//It's an alias. Note that if typedefChildren.size() == 1 it's because its a regular class with no body, i.e. {} //It's an alias. Note that if typedefChildren.size() == 1 it's because its a regular class with no body, i.e. {}
if (typedefChildren.size() > 1 && typedefChildren[1]->getData().getName() == "type") { if (typedefChildren.size() > 1 && typedefChildren[1]->getData().getName() == "type") {
Type* aliasedType = typeFromTypeNode(typedefChildren[1], ast, std::map<std::string, Type*>(), false); //false - don't fully instantiate templates Type* aliasedType = typeFromTypeNode(typedefChildren[1], ast, std::map<std::string, Type*>());
typeDef->getDataRef()->valueType = aliasedType; typeDef->getDataRef()->valueType = aliasedType;
typeDef->getDataRef()->scope["~enclosing_scope"][0] = aliasedType->typeDefinition; //So that object lookups find the right member. Note that this overrides translation_unit as a parent scope typeDef->getDataRef()->scope["~enclosing_scope"][0] = aliasedType->typeDefinition; //So that object lookups find the right member. Note that this overrides translation_unit as a parent scope
// std::cout << name << " alias's to " << aliasedType->typeDefinition << std::endl; // std::cout << name << " alias's to " << aliasedType->typeDefinition << std::endl;
@@ -155,7 +155,7 @@ NodeTree<ASTData>* ASTTransformation::secondPassDeclaration(NodeTree<Symbol>* fr
//Check here for method call (an error here) //Check here for method call (an error here)
NodeTree<ASTData>* decStmt = new NodeTree<ASTData>("declaration_statement", ASTData(declaration_statement)); NodeTree<ASTData>* decStmt = new NodeTree<ASTData>("declaration_statement", ASTData(declaration_statement));
std::string newIdentifierStr = concatSymbolTree(from->getChildren()[1]); std::string newIdentifierStr = concatSymbolTree(from->getChildren()[1]);
Type* identifierType = typeFromTypeNode(from->getChildren()[0], scope, templateTypeReplacements, false); Type* identifierType = typeFromTypeNode(from->getChildren()[0], scope, templateTypeReplacements);
std::cout << "Declaring an identifier " << newIdentifierStr << " to be of type " << identifierType->toString() << std::endl; std::cout << "Declaring an identifier " << newIdentifierStr << " to be of type " << identifierType->toString() << std::endl;
NodeTree<ASTData>* newIdentifier = new NodeTree<ASTData>("identifier", ASTData(identifier, Symbol(newIdentifierStr, true), identifierType)); NodeTree<ASTData>* newIdentifier = new NodeTree<ASTData>("identifier", ASTData(identifier, Symbol(newIdentifierStr, true), identifierType));
scope->getDataRef()->scope[newIdentifierStr].push_back(newIdentifier); scope->getDataRef()->scope[newIdentifierStr].push_back(newIdentifier);
@@ -184,7 +184,7 @@ NodeTree<ASTData>* ASTTransformation::secondPassFunction(NodeTree<Symbol>* from,
else //has traits else //has traits
yetToBeInstantiatedTemplateTypes[concatSymbolTree(i->getChildren()[0])] = new Type(template_type_type, parseTraits(i->getChildren()[1])); //This may have to be combined with templateTypeReplacements if we do templated member functions inside of templated classes yetToBeInstantiatedTemplateTypes[concatSymbolTree(i->getChildren()[0])] = new Type(template_type_type, parseTraits(i->getChildren()[1])); //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<int>(), functionDef, std::vector<Type>(), yetToBeInstantiatedTemplateTypes, false); auto transChildren = transformChildren(slice(children,3,-2), std::set<int>(), functionDef, std::vector<Type>(), yetToBeInstantiatedTemplateTypes);
std::cout << "Template function " << functionName << " has these parameters: "; std::cout << "Template function " << functionName << " has these parameters: ";
for (auto i : transChildren) for (auto i : transChildren)
std::cout << "||" << i->getDataRef()->toString() << "|| "; std::cout << "||" << i->getDataRef()->toString() << "|| ";
@@ -195,11 +195,11 @@ NodeTree<ASTData>* ASTTransformation::secondPassFunction(NodeTree<Symbol>* from,
return functionDef; return functionDef;
} }
functionName = concatSymbolTree(children[1]); functionName = concatSymbolTree(children[1]);
functionDef = new NodeTree<ASTData>("function", ASTData(function, Symbol(functionName, true), typeFromTypeNode(children[0], scope, templateTypeReplacements, false))); functionDef = new NodeTree<ASTData>("function", ASTData(function, Symbol(functionName, true), typeFromTypeNode(children[0], scope, templateTypeReplacements)));
scope->getDataRef()->scope[functionName].push_back(functionDef); scope->getDataRef()->scope[functionName].push_back(functionDef);
functionDef->getDataRef()->scope["~enclosing_scope"].push_back(scope); functionDef->getDataRef()->scope["~enclosing_scope"].push_back(scope);
//We only do the parameter nodes. We don't do the body yet, as this is the secondPass //We only do the parameter nodes. We don't do the body yet, as this is the secondPass
auto transChildren = transformChildren(slice(children,2,-2), std::set<int>(), functionDef, std::vector<Type>(), templateTypeReplacements, false); auto transChildren = transformChildren(slice(children,2,-2), std::set<int>(), functionDef, std::vector<Type>(), templateTypeReplacements);
// std::cout << "REGULAR function " << functionName << " has " << transChildren.size() << " parameters: "; // std::cout << "REGULAR function " << functionName << " has " << transChildren.size() << " parameters: ";
// for (auto i : transChildren) // for (auto i : transChildren)
@@ -240,22 +240,6 @@ void ASTTransformation::fourthPass(NodeTree<ASTData>* ast, NodeTree<Symbol>* par
topScope = ast; //Top scope is maintained for templates, which need to add themselves to the top scope from where ever they are instantiated topScope = ast; //Top scope is maintained for templates, which need to add themselves to the top scope from where ever they are instantiated
std::vector<NodeTree<Symbol>*> children = parseTree->getChildren(); std::vector<NodeTree<Symbol>*> children = parseTree->getChildren();
//First copy unfinished class templates into a new list and do them before anything else, so we know exactly which ones we need to do.
std::vector<NodeTree<ASTData>*> classTemplates;
for (auto i : ast->getDataRef()->scope) {
if (i.second[0]->getDataRef()->type == type_def && i.second[0]->getDataRef()->valueType->templateTypeReplacement.size()) {
classTemplates.push_back(i.second[0]);
std::cout << "Saving " << i.second[0]->getDataRef()->toString() << " to instantiate." << std::endl;
}
}
for (auto i : classTemplates) {
Type* classTemplateType = i->getDataRef()->valueType;
std::cout << "Instantiating template " << i->getDataRef()->toString() << std::endl;
for (NodeTree<Symbol>* j : classTemplateType->templateDefinition->getChildren())
if (j->getDataRef()->getName() == "function")
fourthPassFunction(j, seachScopeForFunctionDef(i, j, classTemplateType->templateTypeReplacement), classTemplateType->templateTypeReplacement); //do member method
}
//Go through and finish both regular functions and class methods //Go through and finish both regular functions and class methods
//Note that this pass can instantiate class AND function templates //Note that this pass can instantiate class AND function templates
for (NodeTree<Symbol>* i : children) { for (NodeTree<Symbol>* i : children) {
@@ -273,20 +257,44 @@ void ASTTransformation::fourthPass(NodeTree<ASTData>* ast, NodeTree<Symbol>* par
//Do the inside of classes here //Do the inside of classes here
for (NodeTree<Symbol>* j : typedefChildren) { for (NodeTree<Symbol>* j : typedefChildren) {
if (j->getDataRef()->getName() == "function") { if (j->getDataRef()->getName() == "function") {
fourthPassFunction(j, seachScopeForFunctionDef(typeDef, j, std::map<std::string, Type*>()), std::map<std::string, Type*>()); //do member method fourthPassFunction(j, searchScopeForFunctionDef(typeDef, j, std::map<std::string, Type*>()), std::map<std::string, Type*>()); //do member method
} }
} }
} else if (i->getDataRef()->getName() == "function") { } else if (i->getDataRef()->getName() == "function") {
//Do prototypes of functions //Do prototypes of functions
if (i->getChildren()[0]->getData().getName() == "template_dec") if (i->getChildren()[0]->getData().getName() == "template_dec")
continue; //We've already set up function templates continue; //We've already set up function templates
fourthPassFunction(i, seachScopeForFunctionDef(ast, i, std::map<std::string, Type*>()), std::map<std::string, Type*>()); fourthPassFunction(i, searchScopeForFunctionDef(ast, i, std::map<std::string, Type*>()), std::map<std::string, Type*>());
}
}
// We do these here, in a loop, so that we can do mututally recursive definitions
// even inside of class templates. As its methods may cause partial instantiation of
// other class templates, we need to do this until the size no longer changes.
std::vector<NodeTree<ASTData>*> classTemplates;
int lastSize = 0;
while (lastSize != ast->getDataRef()->scope.size()) {
lastSize = ast->getDataRef()->scope.size();
classTemplates.clear();
for (auto i : ast->getDataRef()->scope) {
if (i.second[0]->getDataRef()->type == type_def && i.second[0]->getDataRef()->valueType->templateTypeReplacement.size()) {
classTemplates.push_back(i.second[0]);
std::cout << "Saving " << i.second[0]->getDataRef()->toString() << " to instantiate." << std::endl;
}
}
for (auto i : classTemplates) {
Type* classTemplateType = i->getDataRef()->valueType;
std::cout << "Instantiating template " << i->getDataRef()->toString() << std::endl;
for (NodeTree<Symbol>* j : classTemplateType->templateDefinition->getChildren())
if (j->getDataRef()->getName() == "function")
fourthPassFunction(j, searchScopeForFunctionDef(i, j, classTemplateType->templateTypeReplacement), classTemplateType->templateTypeReplacement); //do member method
classTemplateType->templateTypeReplacement.clear(); // This template has been fully instantiated, clear it's map so it won't be instantiated again
} }
} }
} }
//This function finds the right AST definition in a scope given its parseTree //This function finds the right AST definition in a scope given its parseTree
NodeTree<ASTData>* ASTTransformation::seachScopeForFunctionDef(NodeTree<ASTData>* scope, NodeTree<Symbol>* parseTree, std::map<std::string, Type*> templateTypeReplacements) { NodeTree<ASTData>* ASTTransformation::searchScopeForFunctionDef(NodeTree<ASTData>* scope, NodeTree<Symbol>* parseTree, std::map<std::string, Type*> templateTypeReplacements) {
std::string functionName = concatSymbolTree(parseTree->getChildren()[1]); std::string functionName = concatSymbolTree(parseTree->getChildren()[1]);
std::vector<Type> types; std::vector<Type> types;
std::vector<NodeTree<Symbol>*> children = parseTree->getChildren(); std::vector<NodeTree<Symbol>*> children = parseTree->getChildren();
@@ -294,11 +302,11 @@ NodeTree<ASTData>* ASTTransformation::seachScopeForFunctionDef(NodeTree<ASTData>
std::cout << "\n Searching scope for function def, function is :" << concatSymbolTree(children[1]) << ", children size is " << children.size() << std::endl; std::cout << "\n Searching scope for function def, function is :" << concatSymbolTree(children[1]) << ", children size is " << children.size() << std::endl;
for (int i = 2; i < children.size()-1; i+=2) { //Skip over commas for (int i = 2; i < children.size()-1; i+=2) { //Skip over commas
std::cout << "Making type for lookup ||" << concatSymbolTree(children[i]) << "||" << std::endl; std::cout << "Making type for lookup ||" << concatSymbolTree(children[i]) << "||" << std::endl;
Type type = *typeFromTypeNode(children[i]->getChildren()[0], scope, templateTypeReplacements, true); Type type = *typeFromTypeNode(children[i]->getChildren()[0], scope, templateTypeReplacements);
std::cout << "Type made: " << type.toString() << std::endl; std::cout << "Type made: " << type.toString() << std::endl;
types.push_back(type); types.push_back(type);
} }
std::cout << "About to seach scope about " << concatSymbolTree(children[1]) << std::endl; std::cout << "About to search scope about " << concatSymbolTree(children[1]) << std::endl;
NodeTree<ASTData>* result = functionLookup(scope, functionName, types); NodeTree<ASTData>* result = functionLookup(scope, functionName, types);
std::cout << "Done searching scope about " << concatSymbolTree(children[1]) << std::endl; std::cout << "Done searching scope about " << concatSymbolTree(children[1]) << std::endl;
return result; return result;
@@ -309,15 +317,15 @@ NodeTree<ASTData>* ASTTransformation::seachScopeForFunctionDef(NodeTree<ASTData>
//Note that it may instantiate class OR function templates, which need to be fully instantiated //Note that it may instantiate class OR function templates, which need to be fully instantiated
void ASTTransformation::fourthPassFunction(NodeTree<Symbol>* from, NodeTree<ASTData>* functionDef, std::map<std::string, Type*> templateTypeReplacements) { void ASTTransformation::fourthPassFunction(NodeTree<Symbol>* from, NodeTree<ASTData>* functionDef, std::map<std::string, Type*> templateTypeReplacements) {
NodeTree<Symbol>* codeBlock = from->getChildren()[from->getChildren().size()-1]; NodeTree<Symbol>* codeBlock = from->getChildren()[from->getChildren().size()-1];
functionDef->addChild(transform(codeBlock, functionDef, std::vector<Type>(), templateTypeReplacements, true)); functionDef->addChild(transform(codeBlock, functionDef, std::vector<Type>(), templateTypeReplacements));
} }
NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from) { NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from) {
//Set up top scope //Set up top scope
return transform(from, NULL, std::vector<Type>(), std::map<std::string, Type*>(), false); return transform(from, NULL, std::vector<Type>(), std::map<std::string, Type*>());
} }
NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree<ASTData>* scope, std::vector<Type> types, std::map<std::string, Type*> templateTypeReplacements, bool instantiateTemplates) { NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree<ASTData>* scope, std::vector<Type> types, std::map<std::string, Type*> templateTypeReplacements) {
Symbol current = from->getData(); Symbol current = from->getData();
std::string name = current.getName(); std::string name = current.getName();
NodeTree<ASTData>* newNode = NULL; NodeTree<ASTData>* newNode = NULL;
@@ -351,8 +359,7 @@ NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree
newNode = scope->getDataRef()->scope[typeAlias][0]; //The node for this type_def has already been made by translation_unit. newNode = scope->getDataRef()->scope[typeAlias][0]; //The node for this type_def has already been made by translation_unit.
//This is done so that types that reference each other can be declared in any order //This is done so that types that reference each other can be declared in any order
//newNode = new NodeTree<ASTData>(name, ASTData(type_def, Symbol(typeAlias, true, typeAlias), typeFromTypeNode(children[1], scope, templateTypeReplacements))); newNode->getDataRef()->valueType = typeFromTypeNode(children[1], scope, templateTypeReplacements);
newNode->getDataRef()->valueType = typeFromTypeNode(children[1], scope, templateTypeReplacements, instantiateTemplates);
skipChildren.insert(0); //Don't want any children, it's unnecessary for ailising skipChildren.insert(0); //Don't want any children, it's unnecessary for ailising
skipChildren.insert(1); skipChildren.insert(1);
} else { //Is a struct or class } else { //Is a struct or class
@@ -364,7 +371,6 @@ NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree
//This is done so that types that reference each other can be declared in any order //This is done so that types that reference each other can be declared in any order
// std::cout << "typeAlias is " << typeAlias << " and newNode is " << newNode << std::endl; // std::cout << "typeAlias is " << typeAlias << " and newNode is " << newNode << std::endl;
//newNode = new NodeTree<ASTData>(name, ASTData(type_def, Symbol(typeAlias, true, typeAlias)));
//So we give this typedef its name without any template types and make its type template_type, and point to this from node. //So we give this typedef its name without any template types and make its type template_type, and point to this from node.
//Then, when this template is instantiated, it will run transform on from with the types filled in. //Then, when this template is instantiated, it will run transform on from with the types filled in.
objectType = new Type(template_type, from); objectType = new Type(template_type, from);
@@ -374,7 +380,6 @@ NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree
newNode = scope->getDataRef()->scope[typeAlias][0]; //The node for this type_def has already been made by translation_unit. newNode = scope->getDataRef()->scope[typeAlias][0]; //The node for this type_def has already been made by translation_unit.
//This is done so that types that reference each other can be declared in any order //This is done so that types that reference each other can be declared in any order
//newNode = new NodeTree<ASTData>(name, ASTData(type_def, Symbol(typeAlias, true, typeAlias)));
objectType = new Type(newNode); objectType = new Type(newNode);
skipChildren.insert(0); //Identifier lookup will be ourselves, as we just added ourselves to the scope skipChildren.insert(0); //Identifier lookup will be ourselves, as we just added ourselves to the scope
} }
@@ -400,7 +405,7 @@ NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree
for (auto i : slice(children[0]->getChildren(), 1, -1, 2)) //skip commas for (auto i : slice(children[0]->getChildren(), 1, -1, 2)) //skip commas
yetToBeInstantiatedTemplateTypes[concatSymbolTree(i)] = new Type(template_type_type); //This may have to be combined with templateTypeReplacements if we do templated member functions inside of templated classes yetToBeInstantiatedTemplateTypes[concatSymbolTree(i)] = 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<int>(), newNode, types, yetToBeInstantiatedTemplateTypes, instantiateTemplates); auto transChildren = transformChildren(slice(children,3,-2), std::set<int>(), newNode, types, yetToBeInstantiatedTemplateTypes);
std::cout << "Template function " << functionName << " has these parameters: "; std::cout << "Template function " << functionName << " has these parameters: ";
for (auto i : transChildren) for (auto i : transChildren)
std::cout << "||" << i->getDataRef()->toString() << "|| "; std::cout << "||" << i->getDataRef()->toString() << "|| ";
@@ -411,7 +416,7 @@ NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree
return newNode; return newNode;
} }
functionName = concatSymbolTree(children[1]); functionName = concatSymbolTree(children[1]);
newNode = new NodeTree<ASTData>(name, ASTData(function, Symbol(functionName, true), typeFromTypeNode(children[0], scope, templateTypeReplacements, instantiateTemplates))); newNode = new NodeTree<ASTData>(name, ASTData(function, Symbol(functionName, true), typeFromTypeNode(children[0], scope, templateTypeReplacements)));
skipChildren.insert(0); skipChildren.insert(0);
skipChildren.insert(1); skipChildren.insert(1);
scope->getDataRef()->scope[functionName].push_back(newNode); scope->getDataRef()->scope[functionName].push_back(newNode);
@@ -436,7 +441,7 @@ NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree
std::string parameterName = concatSymbolTree(children[1]); std::string parameterName = concatSymbolTree(children[1]);
std::cout << "Doing typed parameter " << parameterName << std::endl; std::cout << "Doing typed parameter " << parameterName << std::endl;
//std::string typeString = concatSymbolTree(children[0]);//Get the type (left child) and set our new identifer to be that type //std::string typeString = concatSymbolTree(children[0]);//Get the type (left child) and set our new identifer to be that type
newNode = new NodeTree<ASTData>("identifier", ASTData(identifier, Symbol(parameterName, true), typeFromTypeNode(children[0], scope, templateTypeReplacements, instantiateTemplates))); newNode = new NodeTree<ASTData>("identifier", ASTData(identifier, Symbol(parameterName, true), typeFromTypeNode(children[0], scope, templateTypeReplacements)));
scope->getDataRef()->scope[parameterName].push_back(newNode); scope->getDataRef()->scope[parameterName].push_back(newNode);
newNode->getDataRef()->scope["~enclosing_scope"].push_back(scope); newNode->getDataRef()->scope["~enclosing_scope"].push_back(scope);
std::cout << "Done doing typed_parameter " << parameterName << std::endl; std::cout << "Done doing typed_parameter " << parameterName << std::endl;
@@ -446,7 +451,7 @@ NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree
if (children.size() > 1) { if (children.size() > 1) {
//We do children first so we can do appropriate scope searching with types (yay operator overloading!) //We do children first so we can do appropriate scope searching with types (yay operator overloading!)
skipChildren.insert(1); skipChildren.insert(1);
std::vector<NodeTree<ASTData>*> transformedChildren = transformChildren(children, skipChildren, scope, types, templateTypeReplacements, instantiateTemplates); std::vector<NodeTree<ASTData>*> transformedChildren = transformChildren(children, skipChildren, scope, types, templateTypeReplacements);
std::string functionCallString = concatSymbolTree(children[1]); std::string functionCallString = concatSymbolTree(children[1]);
NodeTree<ASTData>* function = doFunction(scope, functionCallString, transformedChildren, templateTypeReplacements); NodeTree<ASTData>* function = doFunction(scope, functionCallString, transformedChildren, templateTypeReplacements);
if (function == NULL) { if (function == NULL) {
@@ -461,20 +466,20 @@ NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree
//std::cout << children.size() << std::endl; //std::cout << children.size() << std::endl;
if (children.size() == 0) if (children.size() == 0)
return new NodeTree<ASTData>(); return new NodeTree<ASTData>();
return transform(children[0], scope, types, templateTypeReplacements, instantiateTemplates); //Just a promoted term, so do child return transform(children[0], scope, types, templateTypeReplacements); //Just a promoted term, so do child
} }
//Here's the order of ops stuff //Here's the order of ops stuff
} else if (name == "expression" || name == "shiftand" || name == "term" || name == "unarad" || name == "access_operation") { } else if (name == "expression" || name == "shiftand" || name == "term" || name == "unarad" || name == "access_operation") {
//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
if (children.size() > 2) { if (children.size() > 2) {
NodeTree<ASTData>* lhs = transform(children[0], scope, std::vector<Type>(), templateTypeReplacements, instantiateTemplates); //LHS does not inherit types NodeTree<ASTData>* lhs = transform(children[0], scope, std::vector<Type>(), templateTypeReplacements); //LHS does not inherit types
NodeTree<ASTData>* rhs; NodeTree<ASTData>* rhs;
if (name == "access_operation") { if (name == "access_operation") {
std::cout << "lhs is: " << lhs->getDataRef()->toString() << std::endl; std::cout << "lhs is: " << lhs->getDataRef()->toString() << std::endl;
rhs = transform(children[2], lhs->getDataRef()->valueType->typeDefinition, types, templateTypeReplacements, instantiateTemplates); //If an access operation, then the right side will be in the lhs's type's scope rhs = transform(children[2], lhs->getDataRef()->valueType->typeDefinition, types, templateTypeReplacements); //If an access operation, then the right side will be in the lhs's type's scope
} }
else else
rhs = transform(children[2], scope, types, templateTypeReplacements, instantiateTemplates); rhs = transform(children[2], scope, types, templateTypeReplacements);
std::string functionCallName = concatSymbolTree(children[1]); std::string functionCallName = concatSymbolTree(children[1]);
if (functionCallName == "[") if (functionCallName == "[")
@@ -501,7 +506,7 @@ NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree
//Is template instantiation //Is template instantiation
return findOrInstantiateFunctionTemplate(children, scope, types, templateTypeReplacements); return findOrInstantiateFunctionTemplate(children, scope, types, templateTypeReplacements);
} else { } else {
return transform(children[0], scope, types, templateTypeReplacements, instantiateTemplates); //Just a promoted child, so do it instead return transform(children[0], scope, types, templateTypeReplacements); //Just a promoted child, so do it instead
} }
} else if (name == "factor") { //Do factor here, as it has all the weird unary operators } 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
@@ -511,9 +516,9 @@ NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree
funcName = concatSymbolTree(children[0]); funcName = concatSymbolTree(children[0]);
NodeTree<ASTData>* param; NodeTree<ASTData>* param;
if (funcName == "*" || funcName == "&" || funcName == "++" || funcName == "--" || funcName == "-" || funcName == "!" || funcName == "~") if (funcName == "*" || funcName == "&" || funcName == "++" || funcName == "--" || funcName == "-" || funcName == "!" || funcName == "~")
param = transform(children[1], scope, types, templateTypeReplacements, instantiateTemplates); param = transform(children[1], scope, types, templateTypeReplacements);
else else
funcName = concatSymbolTree(children[1]), param = transform(children[0], scope, types, templateTypeReplacements, instantiateTemplates); funcName = concatSymbolTree(children[1]), param = transform(children[0], scope, types, templateTypeReplacements);
//std::cout << "scope lookup from factor" << std::endl; //std::cout << "scope lookup from factor" << std::endl;
std::vector<NodeTree<ASTData>*> transformedChildren; transformedChildren.push_back(param); std::vector<NodeTree<ASTData>*> transformedChildren; transformedChildren.push_back(param);
@@ -525,7 +530,7 @@ NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree
return function; return function;
} else { } else {
return transform(children[0], scope, types, templateTypeReplacements, instantiateTemplates); //Just a promoted child, so do it instead return transform(children[0], scope, types, templateTypeReplacements); //Just a promoted child, so do it instead
} }
} else if (name == "statement") { } else if (name == "statement") {
newNode = new NodeTree<ASTData>(name, ASTData(statement)); newNode = new NodeTree<ASTData>(name, ASTData(statement));
@@ -541,12 +546,12 @@ NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree
newNode = new NodeTree<ASTData>(name, ASTData(assignment_statement)); newNode = new NodeTree<ASTData>(name, ASTData(assignment_statement));
std::string assignFuncName = concatSymbolTree(children[1]); std::string assignFuncName = concatSymbolTree(children[1]);
if (assignFuncName == "=") { if (assignFuncName == "=") {
newNode->addChild(transform(children[0], scope, types, templateTypeReplacements, instantiateTemplates)); newNode->addChild(transform(children[0], scope, types, templateTypeReplacements));
newNode->addChild(transform(children[2], scope, types, templateTypeReplacements, instantiateTemplates)); newNode->addChild(transform(children[2], scope, types, templateTypeReplacements));
} else { } else {
//For assignments like += or *=, expand the syntatic sugar. //For assignments like += or *=, expand the syntatic sugar.
NodeTree<ASTData>* lhs = transform(children[0], scope, types, templateTypeReplacements, instantiateTemplates); NodeTree<ASTData>* lhs = transform(children[0], scope, types, templateTypeReplacements);
NodeTree<ASTData>* rhs = transform(children[2], scope, types, templateTypeReplacements, instantiateTemplates); NodeTree<ASTData>* rhs = transform(children[2], scope, types, templateTypeReplacements);
std::vector<NodeTree<ASTData>*> transformedChildren; transformedChildren.push_back(lhs); transformedChildren.push_back(rhs); std::vector<NodeTree<ASTData>*> transformedChildren; transformedChildren.push_back(lhs); transformedChildren.push_back(rhs);
std::string functionName = assignFuncName.substr(0,1); std::string functionName = assignFuncName.substr(0,1);
NodeTree<ASTData>* operatorCall = doFunction(scope, functionName, transformedChildren, templateTypeReplacements); NodeTree<ASTData>* operatorCall = doFunction(scope, functionName, transformedChildren, templateTypeReplacements);
@@ -564,7 +569,7 @@ NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree
// NodeTree<ASTData>* newIdentifier = transform(children[1], scope); //Transform the identifier // NodeTree<ASTData>* newIdentifier = transform(children[1], scope); //Transform the identifier
// newIdentifier->getDataRef()->valueType = Type(concatSymbolTree(children[0]));//set the type of the identifier // newIdentifier->getDataRef()->valueType = Type(concatSymbolTree(children[0]));//set the type of the identifier
std::string newIdentifierStr = concatSymbolTree(children[1]); std::string newIdentifierStr = concatSymbolTree(children[1]);
Type* identifierType = typeFromTypeNode(children[0], scope, templateTypeReplacements, instantiateTemplates); Type* identifierType = typeFromTypeNode(children[0], scope, templateTypeReplacements);
std::cout << "Declaring an identifier " << newIdentifierStr << " to be of type " << identifierType->toString() << std::endl; std::cout << "Declaring an identifier " << newIdentifierStr << " to be of type " << identifierType->toString() << std::endl;
NodeTree<ASTData>* newIdentifier = new NodeTree<ASTData>("identifier", ASTData(identifier, Symbol(newIdentifierStr, true), identifierType)); NodeTree<ASTData>* newIdentifier = new NodeTree<ASTData>("identifier", ASTData(identifier, Symbol(newIdentifierStr, true), identifierType));
scope->getDataRef()->scope[newIdentifierStr].push_back(newIdentifier); scope->getDataRef()->scope[newIdentifierStr].push_back(newIdentifier);
@@ -577,8 +582,8 @@ NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree
//This code is a simplified version of the code in function_call with respect to access_operation. //This code is a simplified version of the code in function_call with respect to access_operation.
//Note that in this case, what is lhs there is our newIdentifier here (the declaration of the left side of the access operation) //Note that in this case, what is lhs there is our newIdentifier here (the declaration of the left side of the access operation)
auto sliced = slice(children, 4, -1); auto sliced = slice(children, 4, -1);
std::vector<NodeTree<ASTData>*> initPositionFuncParams = transformChildren(sliced, std::set<int>(), scope, types, templateTypeReplacements, instantiateTemplates); std::vector<NodeTree<ASTData>*> initPositionFuncParams = transformChildren(sliced, std::set<int>(), scope, types, templateTypeReplacements);
NodeTree<ASTData>* rhs = transform(children[3], identifierType->typeDefinition, mapNodesToTypes(initPositionFuncParams), templateTypeReplacements, instantiateTemplates); //If an access operation, then the right side will be in the lhs's type's scope NodeTree<ASTData>* rhs = transform(children[3], identifierType->typeDefinition, mapNodesToTypes(initPositionFuncParams), templateTypeReplacements); //If an access operation, then the right side will be in the lhs's type's scope
std::vector<NodeTree<ASTData>*> transformedChildren; transformedChildren.push_back(newIdentifier); transformedChildren.push_back(rhs); std::vector<NodeTree<ASTData>*> transformedChildren; transformedChildren.push_back(newIdentifier); transformedChildren.push_back(rhs);
NodeTree<ASTData>* accessFuncCall = doFunction(scope, ".", transformedChildren, templateTypeReplacements); NodeTree<ASTData>* accessFuncCall = doFunction(scope, ".", transformedChildren, templateTypeReplacements);
accessFuncCall->getDataRef()->valueType = rhs->getDataRef()->valueType; accessFuncCall->getDataRef()->valueType = rhs->getDataRef()->valueType;
@@ -595,7 +600,7 @@ NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree
skipChildren.insert(0); //These, the type and the identifier, have been taken care of. skipChildren.insert(0); //These, the type and the identifier, have been taken care of.
skipChildren.insert(1); skipChildren.insert(1);
newNode->addChildren(transformChildren(children, skipChildren, scope, types, templateTypeReplacements, instantiateTemplates)); newNode->addChildren(transformChildren(children, skipChildren, scope, types, templateTypeReplacements));
return newNode; return newNode;
} else if (name == "if_comp") { } else if (name == "if_comp") {
newNode = new NodeTree<ASTData>(name, ASTData(if_comp)); newNode = new NodeTree<ASTData>(name, ASTData(if_comp));
@@ -608,12 +613,12 @@ NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree
newNode = new NodeTree<ASTData>(functionCallName, ASTData(function_call, Symbol(functionCallName, true))); newNode = new NodeTree<ASTData>(functionCallName, ASTData(function_call, Symbol(functionCallName, true)));
skipChildren.insert(0); skipChildren.insert(0);
std::vector<NodeTree<ASTData>*> transformedChildren = transformChildren(children, skipChildren, scope, types, templateTypeReplacements, instantiateTemplates); std::vector<NodeTree<ASTData>*> transformedChildren = transformChildren(children, skipChildren, scope, types, templateTypeReplacements);
std::cout << "scope lookup from function_call: " << functionCallName << std::endl; std::cout << "scope lookup from function_call: " << functionCallName << std::endl;
for (auto i : children) for (auto i : children)
std::cout << i << " : " << i->getName() << " : " << i->getDataRef()->getName() << std::endl; std::cout << i << " : " << i->getName() << " : " << i->getDataRef()->getName() << std::endl;
NodeTree<ASTData>* function = transform(children[0], scope, mapNodesToTypes(transformedChildren), templateTypeReplacements, instantiateTemplates); NodeTree<ASTData>* function = transform(children[0], scope, mapNodesToTypes(transformedChildren), templateTypeReplacements);
std::cout << "The thing: " << function << " : " << function->getName() << std::endl; std::cout << "The thing: " << function << " : " << function->getName() << std::endl;
for (auto i : function->getChildren()) for (auto i : function->getChildren())
std::cout << i->getName() << " "; std::cout << i->getName() << " ";
@@ -623,12 +628,12 @@ NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree
newNode->addChildren(transformedChildren); newNode->addChildren(transformedChildren);
return newNode; return newNode;
} else if (name == "parameter") { } else if (name == "parameter") {
return transform(children[0], scope, types, templateTypeReplacements, instantiateTemplates); //Don't need a parameter node, just the value return transform(children[0], scope, types, templateTypeReplacements); //Don't need a parameter node, just the value
} else if (name == "type") { } else if (name == "type") {
std::string theConcat = concatSymbolTree(from); //We have no symbol, so this will concat our children std::string theConcat = concatSymbolTree(from); //We have no symbol, so this will concat our children
newNode = new NodeTree<ASTData>(name, ASTData(value, Symbol(theConcat, true), typeFromTypeNode(from, scope, templateTypeReplacements, instantiateTemplates))); newNode = new NodeTree<ASTData>(name, ASTData(value, Symbol(theConcat, true), typeFromTypeNode(from, scope, templateTypeReplacements)));
} else if (name == "number") { } else if (name == "number") {
return transform(children[0], scope, types, templateTypeReplacements, instantiateTemplates); return transform(children[0], scope, types, templateTypeReplacements);
} else if (name == "integer") { } else if (name == "integer") {
newNode = new NodeTree<ASTData>(name, ASTData(value, Symbol(concatSymbolTree(from), true), new Type(integer))); newNode = new NodeTree<ASTData>(name, ASTData(value, Symbol(concatSymbolTree(from), true), new Type(integer)));
} else if (name == "floating_literal") { } else if (name == "floating_literal") {
@@ -648,22 +653,27 @@ NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree
newNode = new NodeTree<ASTData>(name, ASTData(value, Symbol(concatSymbolTree(children[0]), true), new Type(character, 1))); //Indirection of 1 for array newNode = new NodeTree<ASTData>(name, ASTData(value, Symbol(concatSymbolTree(children[0]), true), new Type(character, 1))); //Indirection of 1 for array
}else if (name == "character") { }else if (name == "character") {
newNode = new NodeTree<ASTData>(name, ASTData(value, Symbol(concatSymbolTree(children[0]), true), new Type(character, 0))); //Indirection of 0 for character newNode = new NodeTree<ASTData>(name, ASTData(value, Symbol(concatSymbolTree(children[0]), true), new Type(character, 0))); //Indirection of 0 for character
} else if (name == "AmbiguityPackOuter" || name == "AmbiguityPackInner") {
std::cout << "Ambigious program when parsed by this grammer! This is a bug, please report it." << std::endl;
throw "Ambigious parse!";
} else { } else {
// Should get rid of this eventually. Right now it handles cases like sign, alpha, a comma, etc
std::cout << "Unhandled syntax node: " << name << std::endl;
return new NodeTree<ASTData>(); return new NodeTree<ASTData>();
} }
//Do all children but the ones we skip //Do all children but the ones we skip
newNode->addChildren(transformChildren(children, skipChildren, scope, types, templateTypeReplacements, instantiateTemplates)); newNode->addChildren(transformChildren(children, skipChildren, scope, types, templateTypeReplacements));
return newNode; return newNode;
} }
//We use this functionality a lot at different places //We use this functionality a lot at different places
std::vector<NodeTree<ASTData>*> ASTTransformation::transformChildren(std::vector<NodeTree<Symbol>*> children, std::set<int> skipChildren, NodeTree<ASTData>* scope, std::vector<Type> types, std::map<std::string, Type*> templateTypeReplacements, bool instantiateTemplates) { std::vector<NodeTree<ASTData>*> ASTTransformation::transformChildren(std::vector<NodeTree<Symbol>*> children, std::set<int> skipChildren, NodeTree<ASTData>* scope, std::vector<Type> types, std::map<std::string, Type*> templateTypeReplacements) {
std::vector<NodeTree<ASTData>*> transformedChildren; std::vector<NodeTree<ASTData>*> transformedChildren;
// In general, iterate through children and do them. Might not do this for all children. // In general, iterate through children and do them. Might not do this for all children.
for (int i = 0; i < children.size(); i++) { for (int i = 0; i < children.size(); i++) {
if (skipChildren.find(i) == skipChildren.end()) { if (skipChildren.find(i) == skipChildren.end()) {
NodeTree<ASTData>* transChild = transform(children[i], scope, types, templateTypeReplacements, instantiateTemplates); NodeTree<ASTData>* transChild = transform(children[i], scope, types, templateTypeReplacements);
if (transChild->getDataRef()->type) //Only add the children that have a real ASTData::ASTType, that is, legit ASTData. if (transChild->getDataRef()->type) //Only add the children that have a real ASTData::ASTType, that is, legit ASTData.
transformedChildren.push_back(transChild); transformedChildren.push_back(transChild);
else else
@@ -837,17 +847,24 @@ NodeTree<ASTData>* ASTTransformation::templateClassLookup(NodeTree<ASTData>* sco
int typeIndex = 0; int typeIndex = 0;
int currentTraitsSatisfied = 0; int currentTraitsSatisfied = 0;
for (auto j : nameTraitsPairs) { for (auto j : nameTraitsPairs) {
if (j.second != templateInstantiationTypes[typeIndex]->traits) { if (!subset(j.second, templateInstantiationTypes[typeIndex]->traits)) {
traitsEqual = false; traitsEqual = false;
std::cout << "Traits unequal for " << j.first << " and " << templateInstantiationTypes[typeIndex]->toString() << ": "; std::cout << "Traits not subset for " << j.first << " and " << templateInstantiationTypes[typeIndex]->toString() << ": ";
//std::cout << baseType << " " << indirection << " " << typeDefinition << " " << templateDefinition << " " << traits << ; //std::cout << baseType << " " << indirection << " " << typeDefinition << " " << templateDefinition << " " << traits << ;
std::copy(j.second.begin(), j.second.end(), std::ostream_iterator<std::string>(std::cout, " ")); std::copy(j.second.begin(), j.second.end(), std::ostream_iterator<std::string>(std::cout, " "));
std::cout << " vs "; std::cout << " vs ";
std::copy(templateInstantiationTypes[typeIndex]->traits.begin(), templateInstantiationTypes[typeIndex]->traits.end(), std::ostream_iterator<std::string>(std::cout, " ")); std::copy(templateInstantiationTypes[typeIndex]->traits.begin(), templateInstantiationTypes[typeIndex]->traits.end(), std::ostream_iterator<std::string>(std::cout, " "));
std::cout << std::endl; std::cout << std::endl;
break; break;
} else {
std::cout << "Traits ARE subset for " << j.first << " and " << templateInstantiationTypes[typeIndex]->toString() << ": ";
//std::cout << baseType << " " << indirection << " " << typeDefinition << " " << templateDefinition << " " << traits << ;
std::copy(j.second.begin(), j.second.end(), std::ostream_iterator<std::string>(std::cout, " "));
std::cout << " vs ";
std::copy(templateInstantiationTypes[typeIndex]->traits.begin(), templateInstantiationTypes[typeIndex]->traits.end(), std::ostream_iterator<std::string>(std::cout, " "));
std::cout << std::endl;
} }
currentTraitsSatisfied += templateInstantiationTypes[typeIndex]->traits.size(); currentTraitsSatisfied += j.second.size();
typeIndex++; typeIndex++;
} }
if (!traitsEqual) if (!traitsEqual)
@@ -898,18 +915,24 @@ NodeTree<ASTData>* ASTTransformation::templateFunctionLookup(NodeTree<ASTData>*
int typeIndex = 0; int typeIndex = 0;
int currentTraitsSatisfied = 0; int currentTraitsSatisfied = 0;
for (auto j : nameTraitsPairs) { for (auto j : nameTraitsPairs) {
if (j.second != templateInstantiationTypes[typeIndex]->traits) { if (!subset(j.second, templateInstantiationTypes[typeIndex]->traits)) {
traitsEqual = false; traitsEqual = false;
std::cout << "Traits unequal for " << j.first << " and " << templateInstantiationTypes[typeIndex]->toString() << ": "; std::cout << "Traits not a subset for " << j.first << " and " << templateInstantiationTypes[typeIndex]->toString() << ": ";
std::copy(j.second.begin(), j.second.end(), std::ostream_iterator<std::string>(std::cout, " ")); std::copy(j.second.begin(), j.second.end(), std::ostream_iterator<std::string>(std::cout, " "));
std::cout << " vs "; std::cout << " vs ";
std::copy(templateInstantiationTypes[typeIndex]->traits.begin(), templateInstantiationTypes[typeIndex]->traits.end(), std::ostream_iterator<std::string>(std::cout, " ")); std::copy(templateInstantiationTypes[typeIndex]->traits.begin(), templateInstantiationTypes[typeIndex]->traits.end(), std::ostream_iterator<std::string>(std::cout, " "));
std::cout << std::endl; std::cout << std::endl;
break; break;
} else {
std::cout << "Traits ARE a subset for " << j.first << " and " << templateInstantiationTypes[typeIndex]->toString() << ": ";
std::copy(j.second.begin(), j.second.end(), std::ostream_iterator<std::string>(std::cout, " "));
std::cout << " vs ";
std::copy(templateInstantiationTypes[typeIndex]->traits.begin(), templateInstantiationTypes[typeIndex]->traits.end(), std::ostream_iterator<std::string>(std::cout, " "));
std::cout << std::endl;
} }
//As we go, build up the typeMap for when we transform the parameters for parameter checking //As we go, build up the typeMap for when we transform the parameters for parameter checking
typeMap[j.first] = templateInstantiationTypes[typeIndex]; typeMap[j.first] = templateInstantiationTypes[typeIndex];
currentTraitsSatisfied += templateInstantiationTypes[typeIndex]->traits.size(); currentTraitsSatisfied += j.second.size();
typeIndex++; typeIndex++;
} }
if (!traitsEqual) if (!traitsEqual)
@@ -922,7 +945,7 @@ NodeTree<ASTData>* ASTTransformation::templateFunctionLookup(NodeTree<ASTData>*
bool parameterTypesMatch = true; bool parameterTypesMatch = true;
for (int j = 0; j < functionParameters.size(); j++) { for (int j = 0; j < functionParameters.size(); j++) {
auto paramType = typeFromTypeNode(functionParameters[j]->getChildren()[0], scope, typeMap, false); auto paramType = typeFromTypeNode(functionParameters[j]->getChildren()[0], scope, typeMap);
std::cout << "Template param type: " << paramType->toString() << " : Needed Type: " << types[j].toString() << std::endl; std::cout << "Template param type: " << paramType->toString() << " : Needed Type: " << types[j].toString() << std::endl;
if (*paramType != types[j]) { if (*paramType != types[j]) {
parameterTypesMatch = false; parameterTypesMatch = false;
@@ -978,7 +1001,7 @@ std::map<std::string, Type*> ASTTransformation::makeTemplateFunctionTypeMap(Node
return typeMap; return typeMap;
} }
std::vector<NodeTree<ASTData>*> ASTTransformation::scopeLookup(NodeTree<ASTData>* scope, std::string lookup) { std::vector<NodeTree<ASTData>*> ASTTransformation::scopeLookup(NodeTree<ASTData>* scope, std::string lookup, bool includeModules) {
//We first check to see if it's one of the special reserved identifiers (only this, for now) and return early if it is. //We first check to see if it's one of the special reserved identifiers (only this, for now) and return early if it is.
auto LLElementIterator = languageLevelReservedWords.find(lookup); auto LLElementIterator = languageLevelReservedWords.find(lookup);
if (LLElementIterator != languageLevelReservedWords.end()) { if (LLElementIterator != languageLevelReservedWords.end()) {
@@ -988,9 +1011,12 @@ std::vector<NodeTree<ASTData>*> ASTTransformation::scopeLookup(NodeTree<ASTData>
std::vector<NodeTree<ASTData>*> matches; std::vector<NodeTree<ASTData>*> matches;
std::map<std::string, std::vector<NodeTree<ASTData>*>> scopeMap = scope->getDataRef()->scope; std::map<std::string, std::vector<NodeTree<ASTData>*>> scopeMap = scope->getDataRef()->scope;
auto possibleMatches = scopeMap.find(lookup); auto possibleMatches = scopeMap.find(lookup);
if (possibleMatches != scopeMap.end()) if (possibleMatches != scopeMap.end()) {
matches.insert(matches.end(), possibleMatches->second.begin(), possibleMatches->second.end()); for (auto i : possibleMatches->second)
if (includeModules || i->getName() != "translation_unit")
matches.push_back(i);
std::cout << "Found " << possibleMatches->second.size() << " match(s) at " << scope->getDataRef()->toString() << std::endl;
}
// Add results from our enclosing scope, if it exists // Add results from our enclosing scope, if it exists
auto enclosingIterator = scopeMap.find("~enclosing_scope"); auto enclosingIterator = scopeMap.find("~enclosing_scope");
if (enclosingIterator != scopeMap.end()) { if (enclosingIterator != scopeMap.end()) {
@@ -1001,7 +1027,7 @@ std::vector<NodeTree<ASTData>*> ASTTransformation::scopeLookup(NodeTree<ASTData>
} }
//Create a type from a syntax tree. This can get complicated with templates //Create a type from a syntax tree. This can get complicated with templates
Type* ASTTransformation::typeFromTypeNode(NodeTree<Symbol>* typeNode, NodeTree<ASTData>* scope, std::map<std::string, Type*> templateTypeReplacements, bool instantiateTemplates) { Type* ASTTransformation::typeFromTypeNode(NodeTree<Symbol>* typeNode, NodeTree<ASTData>* scope, std::map<std::string, Type*> templateTypeReplacements) {
std::string typeIn = concatSymbolTree(typeNode); std::string typeIn = concatSymbolTree(typeNode);
int indirection = 0; int indirection = 0;
@@ -1044,6 +1070,14 @@ Type* ASTTransformation::typeFromTypeNode(NodeTree<Symbol>* typeNode, NodeTree<A
std::cout << i.first << " "; std::cout << i.first << " ";
std::cout << std::endl; std::cout << std::endl;
// getChildren()[1] is \* because of pointer instead of template_inst
// To counter this, for every indirection we step down a level
for (int i = 0; i < indirection; i++)
typeNode = typeNode->getChildren()[0];
std::cout << possibleMatches.size() << " " << typeNode->getChildren().size() << std::endl;
if (typeNode->getChildren().size() > 1)
std::cout << typeNode->getChildren()[1]->getDataRef()->getName() << std::endl;
//If not, we better instantiate it and then add it to the highest (not current) scope //If not, we better instantiate it and then add it to the highest (not current) scope
if (possibleMatches.size() == 0 && typeNode->getChildren().size() > 1 && typeNode->getChildren()[1]->getData().getName() == "template_inst") { if (possibleMatches.size() == 0 && typeNode->getChildren().size() > 1 && typeNode->getChildren()[1]->getData().getName() == "template_inst") {
std::cout << "Template type: " << edited << " not yet instantiated" << std::endl; std::cout << "Template type: " << edited << " not yet instantiated" << std::endl;
@@ -1053,10 +1087,23 @@ Type* ASTTransformation::typeFromTypeNode(NodeTree<Symbol>* typeNode, NodeTree<A
std::vector<Type*> templateParamInstantiationTypes; std::vector<Type*> templateParamInstantiationTypes;
std::string instTypeString = ""; std::string instTypeString = "";
for (int i = 0; i < templateParamInstantiationNodes.size(); i++) { for (int i = 0; i < templateParamInstantiationNodes.size(); i++) {
Type* instType = typeFromTypeNode(templateParamInstantiationNodes[i], scope, templateTypeReplacements, instantiateTemplates); Type* instType = typeFromTypeNode(templateParamInstantiationNodes[i], scope, templateTypeReplacements);
templateParamInstantiationTypes.push_back(instType); templateParamInstantiationTypes.push_back(instType);
instTypeString += (instTypeString == "") ? instType->toString(false) : "," + instType->toString(false); instTypeString += (instTypeString == "") ? instType->toString(false) : "," + instType->toString(false);
} }
//Finish creating the new name for this instantiation
std::string classNameWithoutTemplate = concatSymbolTree(typeNode->getChildren()[0]);
std::string fullyInstantiatedName = classNameWithoutTemplate + "<" + instTypeString + ">";
// Recheck for prior definition here, now that we have the true name.
possibleMatches = scopeLookup(scope, fullyInstantiatedName);
if (possibleMatches.size()) {
typeDefinition = possibleMatches[0];
traits = typeDefinition->getDataRef()->valueType->traits;
std::cout << "Found already instantiated template of " << fullyInstantiatedName << " at second check" << std::endl;
} else {
std::cout << "Did not find already instantiated template of " << fullyInstantiatedName << " at second check" << std::endl;
//Look up this template's plain definition. It's type has the syntax tree that we need to parse //Look up this template's plain definition. It's type has the syntax tree that we need to parse
NodeTree<ASTData>* templateDefinition = templateClassLookup(scope, concatSymbolTree(typeNode->getChildren()[0]), templateParamInstantiationTypes); NodeTree<ASTData>* templateDefinition = templateClassLookup(scope, concatSymbolTree(typeNode->getChildren()[0]), templateParamInstantiationTypes);
if (templateDefinition == NULL) if (templateDefinition == NULL)
@@ -1071,10 +1118,6 @@ Type* ASTTransformation::typeFromTypeNode(NodeTree<Symbol>* typeNode, NodeTree<A
for (int i = 0; i < templateParamInstantiationTypes.size(); i++) for (int i = 0; i < templateParamInstantiationTypes.size(); i++)
newTemplateTypeReplacement[concatSymbolTree(templateParamPlaceholderNodes[i])] = templateParamInstantiationTypes[i]; newTemplateTypeReplacement[concatSymbolTree(templateParamPlaceholderNodes[i])] = templateParamInstantiationTypes[i];
//Finish creating the new name for this instantiation
std::string classNameWithoutTemplate = concatSymbolTree(typeNode->getChildren()[0]);
std::string fullyInstantiatedName = classNameWithoutTemplate + "<" + instTypeString + ">";
typeDefinition = new NodeTree<ASTData>("type_def", ASTData(type_def, Symbol(fullyInstantiatedName, true, fullyInstantiatedName))); typeDefinition = new NodeTree<ASTData>("type_def", ASTData(type_def, Symbol(fullyInstantiatedName, true, fullyInstantiatedName)));
traits = templateDefinition->getDataRef()->valueType->traits; // We have the same traits as the template definition traits = templateDefinition->getDataRef()->valueType->traits; // We have the same traits as the template definition
Type* selfType = new Type(typeDefinition, traits); // Type is self-referential since this is the definition. Type* selfType = new Type(typeDefinition, traits); // Type is self-referential since this is the definition.
@@ -1082,25 +1125,24 @@ Type* ASTTransformation::typeFromTypeNode(NodeTree<Symbol>* typeNode, NodeTree<A
//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 //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 //It also makes sure it gets generated in the right place
std::cout << "Adding to top scope with fullyInstantiatedName " << fullyInstantiatedName << std::endl; std::cout << "Adding to top scope and template's origional scope with fullyInstantiatedName " << fullyInstantiatedName << std::endl;
topScope->getDataRef()->scope[fullyInstantiatedName].push_back(typeDefinition); topScope->getDataRef()->scope[fullyInstantiatedName].push_back(typeDefinition);
topScope->addChild(typeDefinition); //Add this object the the highest scope's topScope->addChild(typeDefinition); //Add this object the the highest scope's
NodeTree<ASTData>* templateHighScope = templateDefinition->getDataRef()->scope["~enclosing_scope"][0];
if (topScope != templateHighScope)
templateHighScope->getDataRef()->scope[fullyInstantiatedName].push_back(typeDefinition);
//Note that the instantiated template's scope is the template's definition. //Note that the instantiated template's scope is the template's definition.
typeDefinition->getDataRef()->scope["~enclosing_scope"].push_back(templateDefinition); typeDefinition->getDataRef()->scope["~enclosing_scope"].push_back(templateDefinition);
if (!instantiateTemplates) { // We only partially instantiate templates no matter what now
std::cout << "!instantiateTemplates, so only partially instantiating " << fullyInstantiatedName << std::endl; // They are all fully instantiated in the loop at the end of the 4th pass
// This is done for code simplicity and so that that loop can do template class methods
// that instantiate other templates that instantiate other templates while still retaining the
// deferred method allowing us to correctly instantiate multiple levels of mututally recursive definitions.
selfType->templateDefinition = templateSyntaxTree; //We're going to still need this when we finish instantiating selfType->templateDefinition = templateSyntaxTree; //We're going to still need this when we finish instantiating
selfType->templateTypeReplacement = newTemplateTypeReplacement; //Save the types for use when this is fully instantiated in pass 4 selfType->templateTypeReplacement = newTemplateTypeReplacement; //Save the types for use when this is fully instantiated in pass 4
secondPassDoClassInsides(typeDefinition, templateSyntaxTree->getChildren(), newTemplateTypeReplacement); //Use these types when instantiating data members secondPassDoClassInsides(typeDefinition, templateSyntaxTree->getChildren(), newTemplateTypeReplacement); //Use these types when instantiating data members
} else {
//We're fully instantiating types. (we must be in pass 4)
std::set<int> skipChildren;
skipChildren.insert(0); //Don't do the template part
skipChildren.insert(1); //Identifier lookup will be ourselves, as we just added ourselves to the scope
typeDefinition->addChildren(transformChildren(templateSyntaxTree->getChildren(), skipChildren, typeDefinition, std::vector<Type>(), newTemplateTypeReplacement, instantiateTemplates));
} }
} else if (possibleMatches.size() == 0) { } else if (possibleMatches.size() == 0) {
std::cout << "Could not find type " << edited << ", returning NULL" << std::endl; std::cout << "Could not find type " << edited << ", returning NULL" << std::endl;
@@ -1124,7 +1166,7 @@ NodeTree<ASTData>* ASTTransformation::findOrInstantiateFunctionTemplate(std::vec
std::string instTypeString = ""; std::string instTypeString = "";
std::vector<Type*> templateActualTypes; std::vector<Type*> templateActualTypes;
for (int i = 0; i < templateParamInstantiationNodes.size(); i++) { for (int i = 0; i < templateParamInstantiationNodes.size(); i++) {
Type* instType = typeFromTypeNode(templateParamInstantiationNodes[i],scope, templateTypeReplacements, true); Type* instType = typeFromTypeNode(templateParamInstantiationNodes[i],scope, templateTypeReplacements);
instTypeString += (instTypeString == "" ? instType->toString() : "," + instType->toString()); instTypeString += (instTypeString == "" ? instType->toString() : "," + instType->toString());
templateActualTypes.push_back(instType); templateActualTypes.push_back(instType);
} }
@@ -1163,7 +1205,7 @@ NodeTree<ASTData>* ASTTransformation::findOrInstantiateFunctionTemplate(std::vec
std::cout << ", " << i << " : " << templateChildren[i]->getDataRef()->getName(); std::cout << ", " << i << " : " << templateChildren[i]->getDataRef()->getName();
std::cout << std::endl; std::cout << std::endl;
instantiatedFunction = new NodeTree<ASTData>("function", ASTData(function, Symbol(fullyInstantiatedName, true), typeFromTypeNode(templateChildren[1], scope, newTemplateTypeReplacement, true))); instantiatedFunction = new NodeTree<ASTData>("function", ASTData(function, Symbol(fullyInstantiatedName, true), typeFromTypeNode(templateChildren[1], scope, newTemplateTypeReplacement)));
std::set<int> skipChildren; std::set<int> skipChildren;
skipChildren.insert(0); skipChildren.insert(0);
skipChildren.insert(1); skipChildren.insert(1);
@@ -1171,7 +1213,7 @@ NodeTree<ASTData>* ASTTransformation::findOrInstantiateFunctionTemplate(std::vec
scope->getDataRef()->scope[fullyInstantiatedName].push_back(instantiatedFunction); scope->getDataRef()->scope[fullyInstantiatedName].push_back(instantiatedFunction);
instantiatedFunction->getDataRef()->scope["~enclosing_scope"].push_back(templateDefinition->getDataRef()->scope["~enclosing_scope"][0]); //Instantiated Template Function's scope is it's template's definition's scope instantiatedFunction->getDataRef()->scope["~enclosing_scope"].push_back(templateDefinition->getDataRef()->scope["~enclosing_scope"][0]); //Instantiated Template Function's scope is it's template's definition's scope
std::cout << "About to do children of " << functionName << " to " << fullyInstantiatedName << std::endl; std::cout << "About to do children of " << functionName << " to " << fullyInstantiatedName << std::endl;
instantiatedFunction->addChildren(transformChildren(templateSyntaxTree->getChildren(), skipChildren, instantiatedFunction, std::vector<Type>(), newTemplateTypeReplacement, true)); instantiatedFunction->addChildren(transformChildren(templateSyntaxTree->getChildren(), skipChildren, instantiatedFunction, std::vector<Type>(), newTemplateTypeReplacement));
topScope->getDataRef()->scope[fullyInstantiatedName].push_back(instantiatedFunction); topScope->getDataRef()->scope[fullyInstantiatedName].push_back(instantiatedFunction);
topScope->addChild(instantiatedFunction); //Add this object the the highest scope's topScope->addChild(instantiatedFunction); //Add this object the the highest scope's

View File

@@ -56,7 +56,7 @@ template <T> void delete(T* toDelete, int itemCount) {
} }
template <T(Destructable)> void delete(T* toDelete, int itemCount) { template <T(Destructable)> void delete(T* toDelete, int itemCount) {
for (int i = 0; i < itemDestructCount; i++;) for (int i = 0; i < itemCount; i++;)
toDelete[i].destruct(); toDelete[i].destruct();
delete<T>(toDelete); delete<T>(toDelete);
} }
@@ -67,7 +67,6 @@ template <T> void delete(T* toDelete) {
} }
template <T(Destructable)> void delete(T* toDelete) { template <T(Destructable)> void delete(T* toDelete) {
if (destruct)
toDelete->destruct(); toDelete->destruct();
free(toDelete); free(toDelete);
} }

View File

@@ -1,13 +1,13 @@
import mem; import mem;
import util; import util;
typedef template<T> vector { typedef template<T> vector (Destructable) {
T *data; T *data;
int size; int size;
int available; int available;
bool destroyItems; bool destroyItems;
vector<T> *construct(bool destroyItemsIn) { vector<T>* construct(bool destroyItemsIn) {
destroyItems = destroyItemsIn; destroyItems = destroyItemsIn;
return construct(); return construct();
size = 0; size = 0;

View File

@@ -1,7 +1,8 @@
import io; import io;
import mem;
import vector; import vector;
typedef Destructable { typedef AbleToBeDestroyed (Destructable) {
void destruct() { void destruct() {
println("Destroyed!"); println("Destroyed!");
} }
@@ -9,19 +10,19 @@ typedef Destructable {
int main() { int main() {
vector<int> intVec.construct(false); vector<int> intVec.construct(false);
intVec.addBack(1); intVec.addEnd(1);
intVec.addBack(3); intVec.addEnd(3);
intVec.addBack(3); intVec.addEnd(3);
intVec.addBack(7); intVec.addEnd(7);
for (int i = 0; i < intVec.size(); i++;) for (int i = 0; i < intVec.size(); i++;)
print(intVec.at(i)); print(intVec.at(i));
println(); println();
vector<Destructable>* desVec = new<vector<Destructable>>()->construct(true); vector<AbleToBeDestroyed>* desVec = new<vector<AbleToBeDestroyed>>()->construct(true);
Destructable testDestruct; AbleToBeDestroyed testDestruct;
desVec->addBack(testDestruct); desVec->addEnd(testDestruct);
delete<vector<Destructable>>(desVec); delete<vector<AbleToBeDestroyed>>(desVec);
return 0; return 0;
} }