Some bugfixes and added templated member functions\! (even for templated objs\!) In this vein, added in_place and map functions to vector\!
This commit is contained in:
@@ -241,14 +241,6 @@ NodeTree<ASTData>* ASTTransformation::secondPassFunction(NodeTree<Symbol>* from,
|
||||
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
|
||||
}
|
||||
// Just to see, I don't think templated functions actually need parameters at this point, and we might not have enough info anyway...
|
||||
auto transChildren = transformChildren(slice(children,2,-3), std::set<int>(), functionDef, std::vector<Type>(), yetToBeInstantiatedTemplateTypes);
|
||||
std::cout << "Template function " << functionName << " has these parameters: ";
|
||||
for (auto i : transChildren)
|
||||
std::cout << "||" << i->getDataRef()->toString() << "|| ";
|
||||
std::cout << "DoneList" << std::endl;
|
||||
functionDef->addChildren(transChildren);
|
||||
|
||||
std::cout << "Finished Non-Instantiated Template function " << functionName << std::endl;
|
||||
return functionDef;
|
||||
}
|
||||
@@ -286,7 +278,8 @@ void ASTTransformation::thirdPass(NodeTree<ASTData>* ast, NodeTree<Symbol>* pars
|
||||
|
||||
//Do the inside of classes here
|
||||
for (NodeTree<Symbol>* j : typedefChildren) {
|
||||
if (j->getDataRef()->getName() == "function") {
|
||||
// skip templated member functions
|
||||
if (j->getDataRef()->getName() == "function" && j->getChildren()[1]->getDataRef()->getName() != "template_dec") {
|
||||
thirdPassFunction(j, searchScopeForFunctionDef(typeDef, j, std::map<std::string, Type*>()), std::map<std::string, Type*>()); //do member method
|
||||
}
|
||||
}
|
||||
@@ -316,7 +309,7 @@ void ASTTransformation::thirdPass(NodeTree<ASTData>* ast, NodeTree<Symbol>* pars
|
||||
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")
|
||||
if (j->getDataRef()->getName() == "function" && j->getChildren()[1]->getDataRef()->getName() != "template_dec")
|
||||
thirdPassFunction(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
|
||||
}
|
||||
@@ -527,6 +520,9 @@ NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree
|
||||
if (name == "access_operation") {
|
||||
std::cout << "lhs is: " << lhs->getDataRef()->toString() << std::endl;
|
||||
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
|
||||
// this might be a template member function, so do like below would do, but make it our rhs
|
||||
if (rhs == nullptr)
|
||||
rhs = findOrInstantiateFunctionTemplate(slice(children,2,-1), lhs->getDataRef()->valueType->typeDefinition, types, templateTypeReplacements);
|
||||
} else
|
||||
rhs = transform(children[2], scope, types, templateTypeReplacements);
|
||||
|
||||
@@ -1013,11 +1009,14 @@ NodeTree<ASTData>* ASTTransformation::templateClassLookup(NodeTree<ASTData>* sco
|
||||
return *mostFittingTemplates.begin();
|
||||
}
|
||||
|
||||
void ASTTransformation::unifyType(NodeTree<Symbol> *syntaxType, Type type, std::map<std::string, Type>* templateTypeMap) {
|
||||
void ASTTransformation::unifyType(NodeTree<Symbol> *syntaxType, Type type, std::map<std::string, Type>* templateTypeMap, std::map<std::string, Type*> typeMap) {
|
||||
// Ok, 3 options for syntaxType here.
|
||||
// 1) This a basic type. (int, or object, etc)
|
||||
// THIS ONE will fall through and get put in the map, but it
|
||||
// doesn't matter b/c it'll get filterd out in unifyTemplateFunction
|
||||
// I also kina feel like maybe I need to worry about typeMap, which is why
|
||||
// I passed it in... It would contain the typemap from our scope if we are
|
||||
// doing a template member function of a templated object
|
||||
// 2) This is a template type type (i.e. T)
|
||||
// match! set up templateTypeMap[T] -> type
|
||||
// 3) This some sort of instantiated template
|
||||
@@ -1037,20 +1036,23 @@ void ASTTransformation::unifyType(NodeTree<Symbol> *syntaxType, Type type, std::
|
||||
auto childrenTypes = getNodes("type", children.back()->getChildren());
|
||||
// unify params
|
||||
for (int i = 0; i < childrenTypes.size()-1; i++)
|
||||
unifyType(childrenTypes[i], *type.parameterTypes[i], templateTypeMap);
|
||||
unifyType(childrenTypes.back(), *type.returnType, templateTypeMap);
|
||||
unifyType(childrenTypes[i], *type.parameterTypes[i], templateTypeMap, typeMap);
|
||||
unifyType(childrenTypes.back(), *type.returnType, templateTypeMap, typeMap);
|
||||
return;
|
||||
}
|
||||
|
||||
if (children.size() == 1) {
|
||||
(*templateTypeMap)[concatSymbolTree(children.back())] = type;
|
||||
// I also kina feel like maybe I need to worry about typeMap, which is why
|
||||
// I passed it in... It would contain the typemap from our scope if we are
|
||||
// doing a template member function of a templated object
|
||||
} else {
|
||||
// go down one in our pointer
|
||||
if (children.back()->getDataRef()->getValue() == "*") {
|
||||
// gotta be a better way to do this
|
||||
Type* clonedType = type.clone();
|
||||
clonedType->decreaseIndirection();
|
||||
unifyType(children.front(), *clonedType, templateTypeMap);
|
||||
unifyType(children.front(), *clonedType, templateTypeMap, typeMap);
|
||||
delete clonedType;
|
||||
return;
|
||||
}
|
||||
@@ -1068,7 +1070,7 @@ void ASTTransformation::unifyType(NodeTree<Symbol> *syntaxType, Type type, std::
|
||||
std::vector<NodeTree<Symbol>*> uninTypeInstTypes = getNodes("type", getNode("template_inst", children));
|
||||
std::vector<NodeTree<Symbol>*> typeInstTypes = getNodes("template_param", getNode("template_dec", typeTemplateDefinition->getChildren()));
|
||||
for (int i = 0; i < uninTypeInstTypes.size(); i++)
|
||||
unifyType(uninTypeInstTypes[i], *origionalType->templateTypeReplacement[concatSymbolTree(typeInstTypes[i])], templateTypeMap);
|
||||
unifyType(uninTypeInstTypes[i], *origionalType->templateTypeReplacement[concatSymbolTree(typeInstTypes[i])], templateTypeMap, typeMap);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1077,20 +1079,20 @@ void ASTTransformation::unifyType(NodeTree<Symbol> *syntaxType, Type type, std::
|
||||
}
|
||||
}
|
||||
|
||||
void ASTTransformation::unifyTemplateFunction(NodeTree<ASTData>* templateFunction, std::vector<Type> types, std::vector<Type*>* templateInstantiationTypes) {
|
||||
void ASTTransformation::unifyTemplateFunction(NodeTree<ASTData>* templateFunction, std::vector<Type> types, std::vector<Type*>* templateInstantiationTypes, std::map<std::string, Type*> typeMap) {
|
||||
NodeTree<Symbol>* templateSyntaxTree = templateFunction->getDataRef()->valueType->templateDefinition;
|
||||
std::vector<NodeTree<Symbol>*> templateParameters = getNodes("typed_parameter", templateSyntaxTree);
|
||||
if (templateParameters.size() != types.size())
|
||||
return;
|
||||
std::map<std::string, Type> templateTypeMap;
|
||||
for (int i = 0; i < types.size(); i++)
|
||||
unifyType(getNode("type", templateParameters[i]), types[i], &templateTypeMap);
|
||||
unifyType(getNode("type", templateParameters[i]), types[i], &templateTypeMap, typeMap);
|
||||
for (auto instantiationParam : getNodes("template_param", getNode("template_dec", templateSyntaxTree)))
|
||||
templateInstantiationTypes->push_back(templateTypeMap[concatSymbolTree(instantiationParam)].clone());
|
||||
}
|
||||
|
||||
//Lookup function for template functions. It has some extra concerns compared to function lookup, namely traits
|
||||
NodeTree<ASTData>* ASTTransformation::templateFunctionLookup(NodeTree<ASTData>* scope, std::string lookup, std::vector<Type*>* templateInstantiationTypes, std::vector<Type> types) {
|
||||
NodeTree<ASTData>* ASTTransformation::templateFunctionLookup(NodeTree<ASTData>* scope, std::string lookup, std::vector<Type*>* templateInstantiationTypes, std::vector<Type> types, std::map<std::string, Type*> scopeTypeMap) {
|
||||
std::map<NodeTree<ASTData>*, std::vector<Type*>> templateInstantiationTypesPerFunction;
|
||||
std::set<NodeTree<ASTData>*> mostFittingTemplates;
|
||||
int bestNumTraitsSatisfied = -1;
|
||||
@@ -1104,17 +1106,19 @@ NodeTree<ASTData>* ASTTransformation::templateFunctionLookup(NodeTree<ASTData>*
|
||||
std::cout << "Not a template, skipping" << std::endl;
|
||||
continue;
|
||||
}
|
||||
// We have the type map here because we might want to augment it with the typeMap from
|
||||
// the current scope, which would happen if we're trying to instantiate a template member function
|
||||
std::map<std::string, Type*> typeMap = scopeTypeMap;
|
||||
// If template instantiation was explicit, use those types. Otherwise, unify to find them
|
||||
if (templateInstantiationTypes->size())
|
||||
templateInstantiationTypesPerFunction[i] = *templateInstantiationTypes;
|
||||
else
|
||||
unifyTemplateFunction(i, types, &templateInstantiationTypesPerFunction[i]);
|
||||
unifyTemplateFunction(i, types, &templateInstantiationTypesPerFunction[i], typeMap);
|
||||
auto nameTraitsPairs = makeTemplateNameTraitPairs(templateSyntaxTree->getChildren()[1]);
|
||||
//Check if sizes match between the placeholder and actual template types
|
||||
if (nameTraitsPairs.size() != templateInstantiationTypesPerFunction[i].size())
|
||||
continue;
|
||||
|
||||
std::map<std::string, Type*> typeMap;
|
||||
bool traitsEqual = true;
|
||||
int typeIndex = 0;
|
||||
int currentTraitsSatisfied = 0;
|
||||
@@ -1197,9 +1201,11 @@ std::vector<std::pair<std::string, std::set<std::string>>> ASTTransformation::ma
|
||||
return typePairs;
|
||||
}
|
||||
|
||||
std::map<std::string, Type*> ASTTransformation::makeTemplateFunctionTypeMap(NodeTree<Symbol>* templateNode, std::vector<Type*> types) {
|
||||
std::map<std::string, Type*> ASTTransformation::makeTemplateFunctionTypeMap(NodeTree<Symbol>* templateNode, std::vector<Type*> types, std::map<std::string, Type*> scopeTypeMap) {
|
||||
auto typePairs = makeTemplateNameTraitPairs(templateNode);
|
||||
std::map<std::string, Type*> typeMap;
|
||||
// we start with the scopeTypeMap because we want to combine
|
||||
// them (this is for templated member functions of templated objects)
|
||||
std::map<std::string, Type*> typeMap = scopeTypeMap;
|
||||
int typeIndex = 0;
|
||||
std::cout << typePairs.size() << " " << types.size() << std::endl;
|
||||
for (auto i : typePairs) {
|
||||
@@ -1450,6 +1456,17 @@ NodeTree<ASTData>* ASTTransformation::findOrInstantiateFunctionTemplate(std::vec
|
||||
std::vector<Type*> templateActualTypes;
|
||||
NodeTree<ASTData>* templateDefinition = NULL;
|
||||
|
||||
// If this is a templated member function, we should also add this function to the object
|
||||
NodeTree<ASTData>* objectForTemplateMethod = NULL;
|
||||
// Ok, our scope might have a typeMap if we are inside a templated object and are looking
|
||||
// for a templated member function
|
||||
std::map<std::string, Type*> scopeTypeMap;
|
||||
if (scope->getDataRef()->valueType && scope->getDataRef()->valueType->typeDefinition
|
||||
&& scope->getDataRef()->valueType->typeDefinition->getDataRef()->valueType) {
|
||||
objectForTemplateMethod = scope->getDataRef()->valueType->typeDefinition;
|
||||
scopeTypeMap = objectForTemplateMethod->getDataRef()->valueType->templateTypeReplacement;
|
||||
}
|
||||
|
||||
// Are we supposed to infer our instantiation, or not? If we have only one child we're inferring as we don't
|
||||
// have the actual instantiation part. If do have the instantiation part, then we'll use that.
|
||||
// Note that as a part o finferring the instantiation we already find the template, so we make that
|
||||
@@ -1457,7 +1474,7 @@ NodeTree<ASTData>* ASTTransformation::findOrInstantiateFunctionTemplate(std::vec
|
||||
std::string instTypeString = "";
|
||||
if (children.size() == 1) {
|
||||
// templateFunctionLookup adds the actual types to templateActualTypes if it's currently empty
|
||||
templateDefinition = templateFunctionLookup(scope, functionName, &templateActualTypes, types);
|
||||
templateDefinition = templateFunctionLookup(scope, functionName, &templateActualTypes, types, scopeTypeMap);
|
||||
for (auto instType : templateActualTypes)
|
||||
instTypeString += (instTypeString == "" ? instType->toString() : "," + instType->toString());
|
||||
} else {
|
||||
@@ -1497,7 +1514,7 @@ NodeTree<ASTData>* ASTTransformation::findOrInstantiateFunctionTemplate(std::vec
|
||||
// by here, it's not as either we had the instantiation already or we figured out out before
|
||||
// and are not actually doing this call
|
||||
if (!templateDefinition)
|
||||
templateDefinition = templateFunctionLookup(scope, functionName, &templateActualTypes, types);
|
||||
templateDefinition = templateFunctionLookup(scope, functionName, &templateActualTypes, types, scopeTypeMap);
|
||||
if (templateDefinition == NULL) {
|
||||
std::cout << functionName << " search turned up null, returing null" << std::endl;
|
||||
return NULL;
|
||||
@@ -1505,7 +1522,7 @@ NodeTree<ASTData>* ASTTransformation::findOrInstantiateFunctionTemplate(std::vec
|
||||
|
||||
NodeTree<Symbol>* templateSyntaxTree = templateDefinition->getDataRef()->valueType->templateDefinition;
|
||||
// Makes a map between the names of the template placeholder parameters and the provided types
|
||||
std::map<std::string, Type*> newTemplateTypeReplacement = makeTemplateFunctionTypeMap(templateSyntaxTree->getChildren()[1], templateActualTypes);
|
||||
std::map<std::string, Type*> newTemplateTypeReplacement = makeTemplateFunctionTypeMap(templateSyntaxTree->getChildren()[1], templateActualTypes, scopeTypeMap);
|
||||
|
||||
std::vector<NodeTree<Symbol>*> templateChildren = templateSyntaxTree->getChildren();
|
||||
for (int i = 0; i < templateChildren.size(); i++)
|
||||
@@ -1516,7 +1533,8 @@ NodeTree<ASTData>* ASTTransformation::findOrInstantiateFunctionTemplate(std::vec
|
||||
addToScope("~enclosing_scope", templateDefinition->getDataRef()->scope["~enclosing_scope"][0], instantiatedFunction);
|
||||
// Arrrrrgh this has a hard time working because the functions will need to see their parameter once they are emitted as C.
|
||||
// HAHAHAHAHA DOESN'T MATTER ALL ONE C FILE NOW, swap back to old way
|
||||
auto templateTopScope = getUpperTranslationUnit(templateDefinition);
|
||||
// OR, THIS IS A TEMPLATE METHOD AND ADD TO THE OBJECT
|
||||
auto templateTopScope = objectForTemplateMethod ? objectForTemplateMethod : getUpperTranslationUnit(templateDefinition);
|
||||
addToScope(fullyInstantiatedName, instantiatedFunction, templateTopScope);
|
||||
templateTopScope->addChild(instantiatedFunction); // Add this object the the highest scope's
|
||||
|
||||
|
||||
@@ -227,7 +227,8 @@ std::pair<std::string, std::string> CGenerator::generateTranslationUnit(std::str
|
||||
std::string objectFunctionDefinitions = "/* Method Definitions for " + declarationData.symbol.getName() + " */\n";
|
||||
for (int j = 0; j < decChildren.size(); j++) {
|
||||
std::cout << decChildren[j]->getName() << std::endl;
|
||||
if (decChildren[j]->getName() == "function") //If object method
|
||||
if (decChildren[j]->getName() == "function"
|
||||
&& decChildren[j]->getDataRef()->valueType->baseType != template_type) //If object method and not template
|
||||
objectFunctionDefinitions += generateObjectMethod(declaration, decChildren[j], &functionPrototypes) + "\n";
|
||||
}
|
||||
// Add all aliases to the plain typedefs. This will add any alias that aliases to this object, and any alias that aliases to that, and so on
|
||||
@@ -397,7 +398,7 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
|
||||
&& children[1]->getChildren()[0]->getChildren()[1] == children[0]) {
|
||||
//That is, if we're a declaration with an init position call (Object a.construct())
|
||||
//We can tell if our function call (children[1])'s access operation([0])'s lhs ([1]) is the thing we just declared (children[0])
|
||||
return ValueTypeToCType(children[0]->getData().valueType, generate(children[0], enclosingObject, justFuncName)) + "; " + generate(children[1]) + "/*Init Position Call*/";
|
||||
return ValueTypeToCType(children[0]->getData().valueType, generate(children[0], enclosingObject, justFuncName)) + "; " + generate(children[1], enclosingObject, true) + "/*Init Position Call*/";
|
||||
} else
|
||||
return ValueTypeToCType(children[0]->getData().valueType, generate(children[0], enclosingObject, justFuncName)) + " = " + generate(children[1], enclosingObject, true) + ";";
|
||||
case if_comp:
|
||||
|
||||
Reference in New Issue
Block a user