diff --git a/.gitignore b/.gitignore index 07bf24d..5f5441e 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ build-ninja *.comp stats *.swp +*.swo *.png *krakout* kraklist.txt diff --git a/include/CGenerator.h b/include/CGenerator.h index 6fbfbc6..6a615bf 100644 --- a/include/CGenerator.h +++ b/include/CGenerator.h @@ -36,9 +36,9 @@ class CGenerator { static std::string scopePrefix(NodeTree* from); std::string generateObjectMethod(NodeTree* enclosingObject, NodeTree* from, std::string *functionPrototype); NodeTree* getMethodsObjectType(NodeTree* scope, std::string functionName); - NodeTree* getMethod(Type* type, std::string method); - bool methodExists(Type* type, std::string method); - std::string generateMethodIfExists(Type* type, std::string method, std::string parameter); + NodeTree* getMethod(Type* type, std::string method, std::vector types); + bool methodExists(Type* type, std::string method, std::vector types); + std::string generateMethodIfExists(Type* type, std::string method, std::string parameter, std::vector methodTypes); std::string emitDestructors(std::vector*> possibleDeclarations, NodeTree* enclosingObject); std::string tabs(); std::string getID(); diff --git a/include/Type.h b/include/Type.h index 82aeb1a..c568160 100644 --- a/include/Type.h +++ b/include/Type.h @@ -38,6 +38,8 @@ class Type { void increaseIndirection(); void decreaseIndirection(); void modifyIndirection(int mod); + Type withIncreasedIndirection(); + Type withDecreasedIndirection(); ValueType baseType; NodeTree* typeDefinition; diff --git a/include/util.h b/include/util.h index ef84e60..1539f9f 100644 --- a/include/util.h +++ b/include/util.h @@ -46,6 +46,14 @@ std::vector reverse(std::vector vec) { return flat; } +template +std::vector dereferenced(std::vector vec) { + std::vector de; + for (T* i:vec) + de.push_back(*i); + return de; +} + template std::vector slice(std::vector vec, int begin, int end, int step = 1) { std::vector toReturn; diff --git a/src/ASTTransformation.cpp b/src/ASTTransformation.cpp index 3e8c9e3..920f4e8 100644 --- a/src/ASTTransformation.cpp +++ b/src/ASTTransformation.cpp @@ -1048,7 +1048,7 @@ void ASTTransformation::unifyType(NodeTree *syntaxType, Type type, std:: } if (children.size() == 1) { - (*templateTypeMap)[concatSymbolTree(children.back())] = type; + (*templateTypeMap)[concatSymbolTree(children.front())] = 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 @@ -1093,8 +1093,9 @@ void ASTTransformation::unifyTemplateFunction(NodeTree* templateFunctio std::map templateTypeMap; for (int i = 0; i < types.size(); i++) 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()); + for (auto instantiationParam : getNodes("template_param", getNode("template_dec", templateSyntaxTree))) { + templateInstantiationTypes->push_back(templateTypeMap[concatSymbolTree(getNode("identifier", instantiationParam))].clone()); // gotta be careful of catching the traits in the concat + } } //Lookup function for template functions. It has some extra concerns compared to function lookup, namely traits @@ -1116,10 +1117,17 @@ NodeTree* ASTTransformation::templateFunctionLookup(NodeTree* // the current scope, which would happen if we're trying to instantiate a template member function std::map typeMap = scopeTypeMap; // If template instantiation was explicit, use those types. Otherwise, unify to find them - if (templateInstantiationTypes->size()) + if (templateInstantiationTypes->size()) { templateInstantiationTypesPerFunction[i] = *templateInstantiationTypes; - else + std::cout << "passed in types" << std::endl; + }else{ unifyTemplateFunction(i, types, &templateInstantiationTypesPerFunction[i], typeMap); + std::cout << "unified types" << std::endl; + } + std::cout << "TYPES ARE: "; + for (Type *a : templateInstantiationTypesPerFunction[i]) + std::cout << a->toString() << " : "; + std::cout << std::endl; auto nameTraitsPairs = makeTemplateNameTraitPairs(templateSyntaxTree->getChildren()[1]); //Check if sizes match between the placeholder and actual template types if (nameTraitsPairs.size() != templateInstantiationTypesPerFunction[i].size()) @@ -1131,11 +1139,11 @@ NodeTree* ASTTransformation::templateFunctionLookup(NodeTree* for (auto j : nameTraitsPairs) { if (!subset(j.second, templateInstantiationTypesPerFunction[i][typeIndex]->traits)) { traitsEqual = false; - std::cout << "Traits not a subset for " << j.first << " and " << templateInstantiationTypesPerFunction[i][typeIndex]->toString() << ": "; + std::cout << "Traits not a subset for " << j.first << " and " << templateInstantiationTypesPerFunction[i][typeIndex]->toString() << ": |"; std::copy(j.second.begin(), j.second.end(), std::ostream_iterator(std::cout, " ")); - std::cout << " vs "; + std::cout << "| vs |"; std::copy(templateInstantiationTypesPerFunction[i][typeIndex]->traits.begin(), templateInstantiationTypesPerFunction[i][typeIndex]->traits.end(), std::ostream_iterator(std::cout, " ")); - std::cout << std::endl; + std::cout << "|" << std::endl; break; } else { std::cout << "Traits ARE a subset for " << j.first << " and " << templateInstantiationTypesPerFunction[i][typeIndex]->toString() << ": "; diff --git a/src/CGenerator.cpp b/src/CGenerator.cpp index a36f5dd..dbbd88a 100644 --- a/src/CGenerator.cpp +++ b/src/CGenerator.cpp @@ -426,8 +426,8 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc output.preValue += expr.preValue; std::string retTemp = "ret_temp" + getID(); output.preValue += ValueTypeToCType(children[0]->getDataRef()->valueType, retTemp) + ";\n"; - if (methodExists(children[0]->getDataRef()->valueType, "copy_construct")) - output.preValue += generateMethodIfExists(children[0]->getDataRef()->valueType, "copy_construct", "&"+retTemp + ", &" + expr.value); + if (methodExists(children[0]->getDataRef()->valueType, "copy_construct", std::vector{children[0]->getDataRef()->valueType->withIncreasedIndirection()})) + output.preValue += generateMethodIfExists(children[0]->getDataRef()->valueType, "copy_construct", "&"+retTemp + ", &" + expr.value, std::vector{children[0]->getDataRef()->valueType->withIncreasedIndirection()}); else output.preValue += retTemp + " = " + expr.value + ";\n"; // move expr post to before return @@ -477,12 +477,12 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc return ValueTypeToCType(children[0]->getData().valueType, generate(children[0], enclosingObject, justFuncName).oneString()) + "; " + generate(children[1], enclosingObject, true).oneString(true) + "/*Init Position Call*/"; } else { // copy constructor if of the same type - if (*children[0]->getDataRef()->valueType == *children[1]->getDataRef()->valueType && methodExists(children[1]->getDataRef()->valueType, "copy_construct")) { + if (*children[0]->getDataRef()->valueType == *children[1]->getDataRef()->valueType && methodExists(children[1]->getDataRef()->valueType, "copy_construct", std::vector{children[1]->getDataRef()->valueType->withIncreasedIndirection()})) { CCodeTriple toAssign = generate(children[1], enclosingObject, true); std::string assignedTo = generate(children[0], enclosingObject, justFuncName).oneString(); output.value = toAssign.preValue; output.value += ValueTypeToCType(children[0]->getData().valueType, assignedTo) + ";\n"; - output.value += generateMethodIfExists(children[0]->getDataRef()->valueType, "copy_construct", "&" + assignedTo + ", &" + toAssign.value) + ";\n" + output.postValue; + output.value += generateMethodIfExists(children[0]->getDataRef()->valueType, "copy_construct", "&" + assignedTo + ", &" + toAssign.value, std::vector{children[0]->getDataRef()->valueType->withIncreasedIndirection()}) + ";\n" + output.postValue; output.value += toAssign.postValue; return output; } else { @@ -540,8 +540,7 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc if (name == "+" || name == "-" || name == "*" || name == "/" || name == "==" || name == ">=" || name == "<=" || name == "!=" || name == "<" || name == ">" || name == "%" || name == "=" || name == "+=" || name == "-=" || name == "*=" || name == "/=" || name == "||" || name == "&&") { - std::cout << "THIS IS IT NAME: " << name << std::endl; - return "((" + generate(children[1], enclosingObject, true).oneString() + ")" + name + "(" + generate(children[2], enclosingObject, true).oneString() + "))"; + return "((" + generate(children[1], enclosingObject, true) + ")" + name + "(" + generate(children[2], enclosingObject, true) + "))"; } else if (name == "." || name == "->") { if (children.size() == 1) return "/*dot operation with one child*/" + generate(children[0], enclosingObject, true).oneString() + "/*end one child*/"; @@ -603,12 +602,12 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc } // see if we should copy_construct all the parameters for (int i = 1; i < children.size(); i++) { //children[0] is the declaration - if (methodExists(children[i]->getDataRef()->valueType, "copy_construct")) { + if (methodExists(children[i]->getDataRef()->valueType, "copy_construct", std::vector{children[i]->getDataRef()->valueType->withIncreasedIndirection()})) { std::string tmpParamName = "param" + getID(); CCodeTriple paramValue = generate(children[i], enclosingObject, true); output.preValue += paramValue.preValue; output.preValue += ValueTypeToCType(children[i]->getDataRef()->valueType, tmpParamName) + ";\n"; - output.preValue += generateMethodIfExists(children[i]->getDataRef()->valueType, "copy_construct", "&"+tmpParamName + ", &" + paramValue.value); + output.preValue += generateMethodIfExists(children[i]->getDataRef()->valueType, "copy_construct", "&"+tmpParamName + ", &" + paramValue.value, std::vector{children[i]->getDataRef()->valueType->withIncreasedIndirection()}); output.value += tmpParamName; output.postValue += paramValue.postValue; } else { @@ -620,11 +619,11 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc output += ") "; // see if we should add a destructer call to this postValue Type* retType = children[0]->getDataRef()->valueType->returnType; - if (methodExists(retType, "destruct")) { + if (methodExists(retType, "destruct", std::vector())) { std::string retTempName = "return_temp" + getID(); output.preValue += ValueTypeToCType(retType, retTempName) + " = " + output.value + ";\n"; output.value = retTempName; - output.postValue = generateMethodIfExists(retType, "destruct", "&"+retTempName) + ";\n" + output.postValue; + output.postValue = generateMethodIfExists(retType, "destruct", "&"+retTempName, std::vector()) + ";\n" + output.postValue; } return output; } @@ -674,32 +673,44 @@ std::string CGenerator::generateObjectMethod(NodeTree* enclosingObject, return output; } -NodeTree* CGenerator::getMethod(Type* type, std::string method) { +NodeTree* CGenerator::getMethod(Type* type, std::string method, std::vector types) { if (type->getIndirection()) return nullptr; NodeTree *typeDefinition = type->typeDefinition; if (typeDefinition) { auto definitionItr = typeDefinition->getDataRef()->scope.find(method); - if (definitionItr != typeDefinition->getDataRef()->scope.end()) - return definitionItr->second[0]; + if (definitionItr != typeDefinition->getDataRef()->scope.end()) { + for (auto method : definitionItr->second) { + bool methodFits = true; + std::vector methodTypes = dereferenced(method->getDataRef()->valueType->parameterTypes); + if (types.size() != methodTypes.size()) + continue; + for (int i = 0; i < types.size(); i++) { + if (types[i] != methodTypes[i]) { + methodFits = false; + break; + } + } + if (methodFits) + return method; + } + } } return nullptr; } -bool CGenerator::methodExists(Type* type, std::string method) { - return getMethod(type, method) != nullptr; +bool CGenerator::methodExists(Type* type, std::string method, std::vector types) { + return getMethod(type, method, types) != nullptr; } -std::string CGenerator::generateMethodIfExists(Type* type, std::string method, std::string parameter) { - NodeTree *typeDefinition = type->typeDefinition; - NodeTree *methodDef = getMethod(type, method); +std::string CGenerator::generateMethodIfExists(Type* type, std::string method, std::string parameter, std::vector methodTypes) { + NodeTree *methodDef = getMethod(type, method, methodTypes); if (methodDef) { + NodeTree *typeDefinition = type->typeDefinition; std::string nameDecoration; for (Type *paramType : methodDef->getDataRef()->valueType->parameterTypes) nameDecoration += "_" + ValueTypeToCTypeDecoration(paramType); return scopePrefix(typeDefinition) + CifyName(typeDefinition->getDataRef()->symbol.getName()) + "__" + method + nameDecoration + "(" + parameter + ");\n"; - } else { - std::cout << method << " DOESN'T EXIST FOR TYPE " << type->toString() << std::endl; } return ""; } @@ -707,7 +718,7 @@ std::string CGenerator::generateMethodIfExists(Type* type, std::string method, s std::string CGenerator::emitDestructors(std::vector*> identifiers, NodeTree* enclosingObject) { std::string destructorString = ""; for (auto identifier : identifiers) - destructorString += tabs() + generateMethodIfExists(identifier->getDataRef()->valueType, "destruct", "&" + generate(identifier, enclosingObject).oneString()); + destructorString += tabs() + generateMethodIfExists(identifier->getDataRef()->valueType, "destruct", "&" + generate(identifier, enclosingObject).oneString(), std::vector()); return destructorString; } diff --git a/src/Type.cpp b/src/Type.cpp index 9975181..f40ea53 100644 --- a/src/Type.cpp +++ b/src/Type.cpp @@ -169,3 +169,15 @@ void Type::decreaseIndirection() { void Type::modifyIndirection(int mod) { setIndirection(indirection + mod); } + +Type Type::withIncreasedIndirection() { + Type *newOne = clone(); + newOne->increaseIndirection(); + return *newOne; +} +Type Type::withDecreasedIndirection() { + Type *newOne = clone(); + newOne->decreaseIndirection(); + return *newOne; +} + diff --git a/stdlib/matrix.krak b/stdlib/matrix.krak index 7edc235..a2f8895 100644 --- a/stdlib/matrix.krak +++ b/stdlib/matrix.krak @@ -1,11 +1,11 @@ import vector:*; import io:*; -typedef matrix (Destructable) { +typedef matrix (Object) { var data: vector; var rows: int; var cols: int; - + ///****************************** // Constructors ///*****************************/ @@ -18,16 +18,16 @@ typedef matrix (Destructable) { data.construct(); return this; } - + //Constructor with single argument //Creates an N x N matrix fun construct(size: int): matrix* { rows = size; cols = size; data.construct(rows*cols); - return this; + return this; } - + //Constructor with two arguments //Creates an N x M matrix fun construct(r: int, c: int): matrix* { @@ -36,16 +36,16 @@ typedef matrix (Destructable) { data.construct(rows*cols); return this; } - + ///**************************** // Utility Functions ///***************************/ - + //Test using indexing at 0 fun test0(i: int, j: int): bool { - + var index = i*rows + j; - + if(index > (rows * cols - 1) ) { print("Index ("); print(i); @@ -59,15 +59,15 @@ typedef matrix (Destructable) { println(")."); return false; } - + return true; } - + //Test using indexing at 1 fun test1(i: int, j: int): bool { - + var index = (i-1)*rows + (j-1); - + if(index > (rows * cols - 1) ) { print("Index ("); print(i); @@ -81,24 +81,24 @@ typedef matrix (Destructable) { println(")."); return false; } - + return true; } - + //Access matrix element fun at(i: int, j: int): double { - + var index = i*rows + j; if(test0(i,j)) return data.at(index); - + return 0; } - + //Set matrix element fun set(i: int, j: int, num: double): void { - + var index = i*rows + j; if(test0(i,j)) @@ -106,11 +106,11 @@ typedef matrix (Destructable) { return; } - + fun printMatrix(): void { - + for(var i: int = 0; i < rows; i++;) - { + { for(var j: int = 0; j < cols; j++;) { print(at(i,j)); @@ -121,11 +121,11 @@ typedef matrix (Destructable) { return; } - + ///************************** // Linear Algebra Functions //**************************/ - + fun transpose(): void { var val1: double; var val2: double; @@ -138,7 +138,7 @@ typedef matrix (Destructable) { set(n, m, val2); set(m, n, val1); } - + return; } diff --git a/stdlib/mem.krak b/stdlib/mem.krak index 156711c..5eb5573 100644 --- a/stdlib/mem.krak +++ b/stdlib/mem.krak @@ -1,3 +1,5 @@ +import io:* + __if_comp__ __C__ simple_passthrough """ #include """ @@ -41,24 +43,36 @@ fun new(): T* { return new(1); } -/* We specilize on the trait Destructable to decide on whether or not the destructor should be called */ +/* We specilize on the trait Object to decide on whether or not the destructor should be called */ fun delete(toDelete: T*, itemCount: int): void { delete(toDelete); } /* Calling this with itemCount = 0 allows you to delete destructable objects without calling their destructors. */ -fun delete(toDelete: T*, itemCount: int): void { - for (var i: int = 0; i < itemCount; i++;) +fun delete(toDelete: T*, itemCount: int): void { + // start at one because the actual delete will call the destructor of the first one as it + // finishes the pointer + for (var i: int = 1; i < itemCount; i++;) toDelete[i].destruct(); delete(toDelete); } -/* We specilize on the trait Destructable to decide on whether or not the destructor should be called */ +/* We specilize on the trait Object to decide on whether or not the destructor should be called */ fun delete(toDelete: T*): void { free(toDelete); } -fun delete(toDelete: T*): void { +fun delete(toDelete: T*): void { toDelete->destruct(); free(toDelete); } + +// a wrapper for copy constructing if it has the Object trait +fun maybe_copy_construct(to:T*, from:T*):void { + *to = *from +} + +fun maybe_copy_construct(to:T*, from:T*):void { + to->copy_construct(from) +} + diff --git a/stdlib/string.krak b/stdlib/string.krak index 8f2e9f0..77657c4 100644 --- a/stdlib/string.krak +++ b/stdlib/string.krak @@ -1,7 +1,7 @@ import vector; import mem; -obj string (Destructable) { +obj string (Object) { var data: vector::vector; fun construct(): string* { data.construct(); diff --git a/stdlib/vector.krak b/stdlib/vector.krak index 832d956..8b36dc6 100644 --- a/stdlib/vector.krak +++ b/stdlib/vector.krak @@ -2,7 +2,7 @@ import mem:*; import util:*; import io:*; -obj vector (Destructable) { +obj vector (Object) { var data: T*; var size: int; var available: int; @@ -23,14 +23,14 @@ obj vector (Destructable) { } fun copy_construct(old: vector*): void { - construct(old->size) - for (var i = 0; i < size; i++;) - set(i, old->get(i)) + construct() + for (var i = 0; i < old->size; i++;) + addEnd(old->get(i)) } fun destruct(): void { if (data) - delete(data); + delete(data, size); data = 0 } @@ -41,11 +41,11 @@ obj vector (Destructable) { } fun operator+(other:vector):vector { - var newVec.construct(size + other.size):vector + var newVec.construct():vector for (var i = 0; i < size; i++;) - newVec.set(i, get(i)) + newVec.addEnd(get(i)) for (var i = 0; i < other.size; i++;) - newVec.set(i+size, other.get(i)) + newVec.addEnd(other.get(i)) return newVec } @@ -55,9 +55,9 @@ obj vector (Destructable) { } fun clone(): vector { - var newVec.construct(size): vector + var newVec.construct(): vector for (var i = 0; i < size; i++;) - newVec.set(i, data[i]) + newVec.addEnd(data[i]) return newVec } @@ -66,8 +66,8 @@ obj vector (Destructable) { if (!newData) return false; for (var i: int = 0; i < lesser(size, newSize); i++;) - newData[i] = data[i]; - delete(data, 0); + maybe_copy_construct(&newData[i], &data[i]); + delete(data, size); data = newData; available = newSize; size = lesser(size, newSize) @@ -101,7 +101,7 @@ obj vector (Destructable) { size++; if (size >= available) resize(size*2); - data[size-1] = dataIn; + maybe_copy_construct(&data[size-1], &dataIn); } fun do(func: fun(T):void):void { for (var i = 0; i < size; i++;) @@ -112,9 +112,9 @@ obj vector (Destructable) { data[i] = func(data[i]) } fun map(func: fun(T):U):vector { - var newVec.construct(size): vector + var newVec.construct(): vector for (var i = 0; i < size; i++;) - newVec.set(i, func(data[i])) + newVec.addEnd(func(data[i])) return newVec } }; diff --git a/tests/test_functionTemplateInference.expected_results b/tests/test_functionTemplateInference.expected_results index 236483f..8092ecf 100644 --- a/tests/test_functionTemplateInference.expected_results +++ b/tests/test_functionTemplateInference.expected_results @@ -1,3 +1,5 @@ 8 9 10 +Does have Traits +Does not have Traits diff --git a/tests/test_functionTemplateInference.krak b/tests/test_functionTemplateInference.krak index a7ad5be..171a751 100644 --- a/tests/test_functionTemplateInference.krak +++ b/tests/test_functionTemplateInference.krak @@ -1,9 +1,10 @@ import io:* +obj Traited(Traits) {} + fun funcID(genFun: fun():T):T { return genFun() } - fun retInt():int { return 9 } @@ -21,11 +22,22 @@ fun ptrFn(ptr: T*):void { println(*ptr) } +fun traitAware(it:T*):void { + println("Does not have Traits") +} + +fun traitAware(it:T*):void { + println("Does have Traits") +} + fun main():int { var a = 8 ptrFn(&a) println(funcID(retInt)) doThePrint(printInt) + var t:Traited + traitAware(&t) + traitAware(&a) return 0 } diff --git a/tests/test_vectorTest.expected_results b/tests/test_vectorTest.expected_results index 9e443c1..9422df1 100644 --- a/tests/test_vectorTest.expected_results +++ b/tests/test_vectorTest.expected_results @@ -4,6 +4,11 @@ 9131321 15513 3.7000007.7000007.70000015.700000 -Copied! -Destroyed! -Destroyed! +Constructed: 0 +Copied: 0 to 1 +Copied: 1 to 2 +Destroyed: 1 +delete vector +Destroyed: 2 +done +Destroyed: 0 diff --git a/tests/test_vectorTest.krak b/tests/test_vectorTest.krak index f9213ee..ffbb5bb 100644 --- a/tests/test_vectorTest.krak +++ b/tests/test_vectorTest.krak @@ -2,13 +2,34 @@ import io:*; import mem:*; import vector:*; -obj AbleToBeDestroyed (Destructable) { +obj AbleToBeDestroyed (Object) { + var data:int + fun construct(dat:int):void { + data = dat + print("Constructed: ") + println(data) + } fun copy_construct(other:AbleToBeDestroyed*):void { - println("Copied!"); + data = other->data+1 + print("Copied: ") + print(other->data) + print(" to ") + println(data) + } + + fun operator=(other:AbleToBeDestroyed):void { + print("Assigned: ") + print(other.data) + print(" to ") + print(data) + print(" is now ") + data = other.data+1 + println(data) } fun destruct(): void { - println("Destroyed!"); + print("Destroyed: ") + println(data) } }; @@ -42,9 +63,11 @@ fun main(): int { println(); var desVec: vector* = new>()->construct(); - var testDestruct: AbleToBeDestroyed; + var testDestruct.construct(0): AbleToBeDestroyed; desVec->addEnd(testDestruct); - delete>(desVec); + println("delete vector") + delete(desVec); + println("done") return 0; }