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:
Nathan Braswell
2015-05-27 00:58:33 -04:00
parent 88bab7f0d7
commit 85834789e4
9 changed files with 120 additions and 32 deletions

View File

@@ -27,6 +27,7 @@ class ASTData {
~ASTData();
std::string toString();
static std::string ASTTypeToString(ASTType type);
ASTType type;
Type* valueType;
Symbol symbol;

View File

@@ -48,7 +48,7 @@ class ASTTransformation: public NodeTransformation<Symbol,ASTData> {
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>* 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::map<std::string, Type*> scopeTypeMap);
std::vector<NodeTree<ASTData>*> scopeLookup(NodeTree<ASTData>* scope, std::string lookup, bool includeModules = false);
std::vector<NodeTree<ASTData>*> scopeLookup(NodeTree<ASTData>* scope, std::string lookup, bool includeModules, std::vector<NodeTree<ASTData>*> visited);
@@ -56,10 +56,10 @@ class ASTTransformation: public NodeTransformation<Symbol,ASTData> {
NodeTree<ASTData>* addToScope(std::string name, NodeTree<ASTData>* toAdd, NodeTree<ASTData>* addTo);
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);
void unifyType(NodeTree<Symbol> *syntaxType, Type type, std::map<std::string, Type>* templateTypeMap);
void unifyTemplateFunction(NodeTree<ASTData>* templateFunction, std::vector<Type> types, std::vector<Type*>* templateInstantiationTypes);
void unifyType(NodeTree<Symbol> *syntaxType, Type type, std::map<std::string, Type>* templateTypeMap, std::map<std::string, Type*> typeMap);
void unifyTemplateFunction(NodeTree<ASTData>* templateFunction, std::vector<Type> types, std::vector<Type*>* templateInstantiationTypes, std::map<std::string, Type*> typeMap);
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::map<std::string, Type*> scopeTypeMap);
std::vector<std::pair<std::string, std::set<std::string>>> makeTemplateNameTraitPairs(NodeTree<Symbol>* templateNode);
private:

View File

@@ -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

View File

@@ -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:

View File

@@ -26,6 +26,13 @@ obj vector<T> (Destructable) {
delete<T>(data);
}
fun clone(): vector<T> {
var newVec.construct(size): vector<T>
for (var i = 0; i < size; i++;)
newVec.set(i, data[i])
return newVec
}
fun resize(newSize: int): bool {
var newData: T* = new<T>(newSize);
if (!newData)
@@ -67,5 +74,15 @@ obj vector<T> (Destructable) {
resize(size*2);
data[size-1] = dataIn;
}
fun in_place(func: fun(T):T):void {
for (var i = 0; i < size; i++;)
data[i] = func(data[i])
}
fun map<U>(func: fun(T):U):vector<U> {
var newVec.construct(size): vector<U>
for (var i = 0; i < size; i++;)
newVec.set(i, func(data[i]))
return newVec
}
};

View File

@@ -0,0 +1,3 @@
3.141592
7
hi

View File

@@ -0,0 +1,30 @@
import io:*
obj templd<T> {
var data: T
fun construct(dataIn:T):void {
data = dataIn
}
fun conv<U>(func: fun(T):U): U {
return func(data)
}
}
obj onlyMember {
var data: int
fun printAThing<T>(otherDat: T):void {
println(data)
println(otherDat)
}
}
fun main():int {
var hmm.construct(3): templd<int>
println(hmm.conv(fun(it:int):double { return it + 0.141592; }))
var onlyM: onlyMember
onlyM.data = 7
onlyM.printAThing("hi")
return 0
}

View File

@@ -1,3 +1,6 @@
4
1337
26614
15513
3.7000007.7000007.70000015.700000
Destroyed!

View File

@@ -17,7 +17,22 @@ fun main(): int {
println(intVec.size);
for (var i: int = 0; i < intVec.size; i++;)
print(intVec.at(i));
println();
// in place lambda map
intVec.in_place(fun(it:int):int { return it*2; })
for (var i: int = 0; i < intVec.size; i++;)
print(intVec.at(i));
println();
var subd = intVec.map(fun(it:int):int { return it-1; })
for (var i: int = 0; i < subd.size; i++;)
print(subd.at(i));
println();
var newType = intVec.map(fun(it:int):double { return it+1.7; })
for (var i: int = 0; i < newType.size; i++;)
print(newType.at(i));
println();
var desVec: vector<AbleToBeDestroyed>* = new<vector<AbleToBeDestroyed>>()->construct();