Object traits working now as well. Only specilized templates don't, because I have not yet decided the syntax for them.
This commit is contained in:
@@ -49,9 +49,10 @@ class ASTTransformation: public NodeTransformation<Symbol,ASTData> {
|
|||||||
std::vector<NodeTree<ASTData>*> scopeLookup(NodeTree<ASTData>* scope, std::string lookup);
|
std::vector<NodeTree<ASTData>*> scopeLookup(NodeTree<ASTData>* scope, std::string lookup);
|
||||||
|
|
||||||
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, bool instantiateTemplates);
|
||||||
|
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);
|
||||||
std::vector<std::pair<std::string, std::set<std::string>>> makeTemplateFunctionNameTraitPairs(NodeTree<Symbol>* templateNode);
|
std::vector<std::pair<std::string, std::set<std::string>>> makeTemplateNameTraitPairs(NodeTree<Symbol>* templateNode);
|
||||||
private:
|
private:
|
||||||
Importer * importer;
|
Importer * importer;
|
||||||
std::map<std::string, std::vector<NodeTree<ASTData>*>> languageLevelReservedWords;
|
std::map<std::string, std::vector<NodeTree<ASTData>*>> languageLevelReservedWords;
|
||||||
|
|||||||
+1
-1
@@ -30,7 +30,7 @@ class Type {
|
|||||||
bool const operator==(const Type &other)const;
|
bool const operator==(const Type &other)const;
|
||||||
bool const operator!=(const Type &other)const;
|
bool const operator!=(const Type &other)const;
|
||||||
Type* clone();
|
Type* clone();
|
||||||
std::string toString();
|
std::string toString(bool showTraits = true);
|
||||||
int getIndirection();
|
int getIndirection();
|
||||||
void setIndirection(int indirectionIn);
|
void setIndirection(int indirectionIn);
|
||||||
void increaseIndirection();
|
void increaseIndirection();
|
||||||
|
|||||||
+78
-18
@@ -819,6 +819,59 @@ NodeTree<ASTData>* ASTTransformation::functionLookup(NodeTree<ASTData>* scope, s
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Lookup class templates. It evaluates possible matches on traits
|
||||||
|
NodeTree<ASTData>* ASTTransformation::templateClassLookup(NodeTree<ASTData>* scope, std::string lookup, std::vector<Type*> templateInstantiationTypes) {
|
||||||
|
std::vector<NodeTree<ASTData>*> mostFittingTemplates;
|
||||||
|
int bestNumTraitsSatisfied = -1;
|
||||||
|
auto possibleMatches = scopeLookup(scope, lookup);
|
||||||
|
std::cout << "Template Class instantiation has " << possibleMatches.size() << " possible matches." << std::endl;
|
||||||
|
for (auto i : possibleMatches) {
|
||||||
|
NodeTree<Symbol>* templateSyntaxTree = i->getDataRef()->valueType->templateDefinition;
|
||||||
|
|
||||||
|
auto nameTraitsPairs = makeTemplateNameTraitPairs(templateSyntaxTree->getChildren()[0]);
|
||||||
|
//Check if sizes match between the placeholder and actual template types
|
||||||
|
if (nameTraitsPairs.size() != templateInstantiationTypes.size())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
bool traitsEqual = true;
|
||||||
|
int typeIndex = 0;
|
||||||
|
int currentTraitsSatisfied = 0;
|
||||||
|
for (auto j : nameTraitsPairs) {
|
||||||
|
if (j.second != templateInstantiationTypes[typeIndex]->traits) {
|
||||||
|
traitsEqual = false;
|
||||||
|
std::cout << "Traits unequal 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;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
currentTraitsSatisfied += templateInstantiationTypes[typeIndex]->traits.size();
|
||||||
|
typeIndex++;
|
||||||
|
}
|
||||||
|
if (!traitsEqual)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
//See if this is a better match than the current best
|
||||||
|
if (currentTraitsSatisfied > bestNumTraitsSatisfied) {
|
||||||
|
mostFittingTemplates.clear();
|
||||||
|
std::cout << "Class satisfying " << currentTraitsSatisfied << " beats previous " << bestNumTraitsSatisfied << std::endl;
|
||||||
|
bestNumTraitsSatisfied = currentTraitsSatisfied;
|
||||||
|
} else if (currentTraitsSatisfied < bestNumTraitsSatisfied)
|
||||||
|
continue;
|
||||||
|
mostFittingTemplates.push_back(i);
|
||||||
|
std::cout << "Current class fits, satisfying " << currentTraitsSatisfied << " traits" << std::endl;
|
||||||
|
}
|
||||||
|
if (!mostFittingTemplates.size()) {
|
||||||
|
std::cout << "No template classes fit for " << lookup << "!" << std::endl;
|
||||||
|
throw "No matching template classes";
|
||||||
|
} else if (mostFittingTemplates.size() > 1) {
|
||||||
|
std::cout << "Multiple template classes fit with equal number of traits satisfied for " << lookup << "!" << std::endl;
|
||||||
|
throw "Multiple matching template classes";
|
||||||
|
}
|
||||||
|
return mostFittingTemplates[0];
|
||||||
|
}
|
||||||
|
|
||||||
//Lookup function for template functions. It has some extra concerns compared to function lookup, namely traits
|
//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) {
|
||||||
@@ -826,12 +879,12 @@ NodeTree<ASTData>* ASTTransformation::templateFunctionLookup(NodeTree<ASTData>*
|
|||||||
int bestNumTraitsSatisfied = -1;
|
int bestNumTraitsSatisfied = -1;
|
||||||
auto possibleMatches = scopeLookup(scope, lookup);
|
auto possibleMatches = scopeLookup(scope, lookup);
|
||||||
std::cout << "Template Function instantiation has " << possibleMatches.size() << " possible matches." << std::endl;
|
std::cout << "Template Function instantiation has " << possibleMatches.size() << " possible matches." << std::endl;
|
||||||
|
int index = 1;
|
||||||
for (auto i : possibleMatches) {
|
for (auto i : possibleMatches) {
|
||||||
|
std::cout << "Possibility " << index++ << std::endl;
|
||||||
NodeTree<Symbol>* templateSyntaxTree = i->getDataRef()->valueType->templateDefinition;
|
NodeTree<Symbol>* templateSyntaxTree = i->getDataRef()->valueType->templateDefinition;
|
||||||
|
|
||||||
//When called without a second parameter, makeTemplateFunctionTypeMap returns a map with blank Types filled in that contain the correct Traits
|
auto nameTraitsPairs = makeTemplateNameTraitPairs(templateSyntaxTree->getChildren()[0]);
|
||||||
auto nameTraitsPairs = makeTemplateFunctionNameTraitPairs(templateSyntaxTree->getChildren()[0]);
|
|
||||||
|
|
||||||
//Check if sizes match between the placeholder and actual template types
|
//Check if sizes match between the placeholder and actual template types
|
||||||
if (nameTraitsPairs.size() != templateInstantiationTypes.size())
|
if (nameTraitsPairs.size() != templateInstantiationTypes.size())
|
||||||
continue;
|
continue;
|
||||||
@@ -869,7 +922,7 @@ NodeTree<ASTData>* ASTTransformation::templateFunctionLookup(NodeTree<ASTData>*
|
|||||||
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;
|
||||||
std::cout << "Not equal: " << paramType->toString() << " : Needed Type: " << types[j].toString() << std::endl;
|
std::cout << "Not equal template param: " << paramType->toString() << " : Needed Type actual param: " << types[j].toString() << std::endl;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -896,7 +949,7 @@ NodeTree<ASTData>* ASTTransformation::templateFunctionLookup(NodeTree<ASTData>*
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Extract pairs of type names and traits
|
//Extract pairs of type names and traits
|
||||||
std::vector<std::pair<std::string, std::set<std::string>>> ASTTransformation::makeTemplateFunctionNameTraitPairs(NodeTree<Symbol>* templateNode) {
|
std::vector<std::pair<std::string, std::set<std::string>>> ASTTransformation::makeTemplateNameTraitPairs(NodeTree<Symbol>* templateNode) {
|
||||||
std::vector<NodeTree<Symbol>*> templateParams = slice(templateNode->getChildren(), 1, -2, 2); //Skip <, >, and interveaning commas
|
std::vector<NodeTree<Symbol>*> templateParams = slice(templateNode->getChildren(), 1, -2, 2); //Skip <, >, and interveaning commas
|
||||||
std::vector<std::pair<std::string, std::set<std::string>>> typePairs;
|
std::vector<std::pair<std::string, std::set<std::string>>> typePairs;
|
||||||
for (auto i : templateParams) {
|
for (auto i : templateParams) {
|
||||||
@@ -909,7 +962,7 @@ std::vector<std::pair<std::string, std::set<std::string>>> ASTTransformation::ma
|
|||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
auto typePairs = makeTemplateFunctionNameTraitPairs(templateNode);
|
auto typePairs = makeTemplateNameTraitPairs(templateNode);
|
||||||
std::map<std::string, Type*> typeMap;
|
std::map<std::string, Type*> typeMap;
|
||||||
int typeIndex = 0;
|
int typeIndex = 0;
|
||||||
std::cout << typePairs.size() << " " << types.size() << std::endl;
|
std::cout << typePairs.size() << " " << types.size() << std::endl;
|
||||||
@@ -984,9 +1037,18 @@ Type* ASTTransformation::typeFromTypeNode(NodeTree<Symbol>* typeNode, NodeTree<A
|
|||||||
//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;
|
||||||
|
|
||||||
|
//We pull out the replacement types first so that we can choose the correct possibly overloaded template
|
||||||
|
std::vector<NodeTree<Symbol>*> templateParamInstantiationNodes = slice(typeNode->getChildren()[1]->getChildren(), 1, -2, 2); //same
|
||||||
|
std::vector<Type*> templateParamInstantiationTypes;
|
||||||
|
std::string instTypeString = "";
|
||||||
|
for (int i = 0; i < templateParamInstantiationNodes.size(); i++) {
|
||||||
|
Type* instType = typeFromTypeNode(templateParamInstantiationNodes[i], scope, templateTypeReplacements, instantiateTemplates);
|
||||||
|
templateParamInstantiationTypes.push_back(instType);
|
||||||
|
instTypeString += (instTypeString == "") ? instType->toString(false) : "," + instType->toString(false);
|
||||||
|
}
|
||||||
//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
|
||||||
possibleMatches = scopeLookup(scope,concatSymbolTree(typeNode->getChildren()[0]));
|
NodeTree<ASTData>* templateDefinition = templateClassLookup(scope, concatSymbolTree(typeNode->getChildren()[0]), templateParamInstantiationTypes);
|
||||||
NodeTree<ASTData>* templateDefinition = possibleMatches[0];
|
|
||||||
if (templateDefinition == NULL)
|
if (templateDefinition == NULL)
|
||||||
std::cout << "Template definition is null!" << std::endl;
|
std::cout << "Template definition is null!" << std::endl;
|
||||||
else
|
else
|
||||||
@@ -994,25 +1056,23 @@ Type* ASTTransformation::typeFromTypeNode(NodeTree<Symbol>* typeNode, NodeTree<A
|
|||||||
|
|
||||||
NodeTree<Symbol>* templateSyntaxTree = templateDefinition->getDataRef()->valueType->templateDefinition;
|
NodeTree<Symbol>* templateSyntaxTree = templateDefinition->getDataRef()->valueType->templateDefinition;
|
||||||
//Create a new map of template type names to actual types.
|
//Create a new map of template type names to actual types.
|
||||||
std::map<std::string, Type*> newTemplateTypeReplacement;
|
|
||||||
/*MULTHERE*/
|
|
||||||
std::vector<NodeTree<Symbol>*> templateParamPlaceholderNodes = slice(templateSyntaxTree->getChildren()[0]->getChildren(), 1, -2, 2); //Don't get beginning or end for < or >, skip commas in the middle
|
std::vector<NodeTree<Symbol>*> templateParamPlaceholderNodes = slice(templateSyntaxTree->getChildren()[0]->getChildren(), 1, -2, 2); //Don't get beginning or end for < or >, skip commas in the middle
|
||||||
std::vector<NodeTree<Symbol>*> templateParamInstantiationNodes = slice(typeNode->getChildren()[1]->getChildren(), 1, -2, 2); //same
|
std::map<std::string, Type*> newTemplateTypeReplacement;
|
||||||
std::string instTypeString = "";
|
for (int i = 0; i < templateParamInstantiationTypes.size(); i++)
|
||||||
for (int i = 0; i < templateParamPlaceholderNodes.size(); i++) {
|
newTemplateTypeReplacement[concatSymbolTree(templateParamPlaceholderNodes[i])] = templateParamInstantiationTypes[i];
|
||||||
Type* instType = typeFromTypeNode(templateParamInstantiationNodes[i],scope, templateTypeReplacements, instantiateTemplates);
|
|
||||||
newTemplateTypeReplacement[concatSymbolTree(templateParamPlaceholderNodes[i])] = instType;
|
//Finish creating the new name for this instantiation
|
||||||
instTypeString += (instTypeString == "") ? instType->toString() : "," + instType->toString();
|
|
||||||
}
|
|
||||||
std::string classNameWithoutTemplate = concatSymbolTree(typeNode->getChildren()[0]);
|
std::string classNameWithoutTemplate = concatSymbolTree(typeNode->getChildren()[0]);
|
||||||
std::string fullyInstantiatedName = classNameWithoutTemplate + "<" + instTypeString + ">";
|
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)));
|
||||||
Type* selfType = new Type(typeDefinition); //Type is self-referential since this is the 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.
|
||||||
typeDefinition->getDataRef()->valueType = selfType;
|
typeDefinition->getDataRef()->valueType = selfType;
|
||||||
|
|
||||||
//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;
|
||||||
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
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -65,7 +65,7 @@ const bool Type::operator!=(const Type &other) const {
|
|||||||
return(!this->operator==(other));
|
return(!this->operator==(other));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Type::toString() {
|
std::string Type::toString(bool showTraits) {
|
||||||
std::string typeString;
|
std::string typeString;
|
||||||
switch (baseType) {
|
switch (baseType) {
|
||||||
case none:
|
case none:
|
||||||
@@ -106,7 +106,7 @@ std::string Type::toString() {
|
|||||||
}
|
}
|
||||||
for (int i = 0; i < indirection; i++)
|
for (int i = 0; i < indirection; i++)
|
||||||
typeString += "*";
|
typeString += "*";
|
||||||
if (traits.size()) {
|
if (traits.size() && showTraits) {
|
||||||
typeString += "[ ";
|
typeString += "[ ";
|
||||||
for (auto i : traits)
|
for (auto i : traits)
|
||||||
typeString += i + " ";
|
typeString += i + " ";
|
||||||
|
|||||||
@@ -3,3 +3,7 @@ First Trait
|
|||||||
Second Trait
|
Second Trait
|
||||||
Both Traits
|
Both Traits
|
||||||
|
|
||||||
|
First Trait
|
||||||
|
Second Trait
|
||||||
|
Both Traits
|
||||||
|
No Traits
|
||||||
|
|||||||
+17
-19
@@ -30,11 +30,11 @@ template <AlreadySpecilized> void OneTwoFunc(AlreadySpecilized obj) {
|
|||||||
//This should work for objects too!
|
//This should work for objects too!
|
||||||
//To test, we cycle the mapping of traits
|
//To test, we cycle the mapping of traits
|
||||||
|
|
||||||
|
typedef template<T> OneTwoObj (FirstTrait) {};
|
||||||
|
typedef template<T(FirstTrait)> OneTwoObj (SecondTrait) {};
|
||||||
|
typedef template<T(SecondTrait)> OneTwoObj (FirstTrait, SecondTrait) {};
|
||||||
|
typedef template<T(FirstTrait, SecondTrait)> OneTwoObj {};
|
||||||
/*
|
/*
|
||||||
*typedef template<T> OneTwoObj (FirstTrait) {};
|
|
||||||
*typedef template<T(FirstTrait)> OneTwoObj (SecondTrait) {};
|
|
||||||
*typedef template<T(SecondTrait)> OneTwoObj (FirstTrait, SecondTrait) {};
|
|
||||||
*typedef template<T(FirstTrait, SecondTrait)> OneTwoObj {};
|
|
||||||
*typedef template<AlreadySpecilized> OneTwoObj {
|
*typedef template<AlreadySpecilized> OneTwoObj {
|
||||||
* void proveSpecilized() {
|
* void proveSpecilized() {
|
||||||
* println("I'm specilized!");
|
* println("I'm specilized!");
|
||||||
@@ -57,21 +57,19 @@ int main() {
|
|||||||
|
|
||||||
println();
|
println();
|
||||||
|
|
||||||
/*
|
OneTwoObj<NoTraits> alpha;
|
||||||
* OneTwoObj<NoTraits> alpha;
|
OneTwoObj<Trait1> beta;
|
||||||
* OneTwoObj<Trait1> beta;
|
OneTwoObj<Trait2> gamma;
|
||||||
* OneTwoObj<Trait2> gamma;
|
OneTwoObj<TwoTrait> delta;
|
||||||
* OneTwoObj<TwoTrait> delta;
|
// OneTwoObj<AlreadySpecilized> epsilon;
|
||||||
* OneTwoObj<AlreadySpecilized> epsilon;
|
|
||||||
*
|
OneTwoFunc<OneTwoObj<NoTraits>>(alpha);
|
||||||
* OneTwoFunc<OneTwoObj<NoTraits>>(alpha);
|
OneTwoFunc<OneTwoObj<Trait1>>(beta);
|
||||||
* OneTwoFunc<OneTwoObj<Trait1>>(b);
|
OneTwoFunc<OneTwoObj<Trait2>>(gamma);
|
||||||
* OneTwoFunc<OneTwoObj<Trait2>>(c);
|
OneTwoFunc<OneTwoObj<TwoTrait>>(delta);
|
||||||
* OneTwoFunc<OneTwoObj<TwoTrait>>(d);
|
|
||||||
*
|
//We can't pass along our inner part, so let's just make sure that it is the right object.
|
||||||
* //We can't pass along our inner part, so let's just make sure that it is the right object.
|
//epsilon.proveSpecilized();
|
||||||
* //epsilon.proveSpecilized();
|
|
||||||
*/
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user