More all-rounded implementation of the new objecty features, several bugfixes, and updates to the standard library to behave. Vector still needs a bit more work for some operations

This commit is contained in:
Nathan Braswell
2015-06-05 00:34:24 -04:00
parent 6f9ceaa717
commit 7abab02fbf
15 changed files with 185 additions and 87 deletions

1
.gitignore vendored
View File

@@ -4,6 +4,7 @@ build-ninja
*.comp *.comp
stats stats
*.swp *.swp
*.swo
*.png *.png
*krakout* *krakout*
kraklist.txt kraklist.txt

View File

@@ -36,9 +36,9 @@ class CGenerator {
static std::string scopePrefix(NodeTree<ASTData>* from); static std::string scopePrefix(NodeTree<ASTData>* from);
std::string generateObjectMethod(NodeTree<ASTData>* enclosingObject, NodeTree<ASTData>* from, std::string *functionPrototype); std::string generateObjectMethod(NodeTree<ASTData>* enclosingObject, NodeTree<ASTData>* from, std::string *functionPrototype);
NodeTree<ASTData>* getMethodsObjectType(NodeTree<ASTData>* scope, std::string functionName); NodeTree<ASTData>* getMethodsObjectType(NodeTree<ASTData>* scope, std::string functionName);
NodeTree<ASTData>* getMethod(Type* type, std::string method); NodeTree<ASTData>* getMethod(Type* type, std::string method, std::vector<Type> types);
bool methodExists(Type* type, std::string method); bool methodExists(Type* type, std::string method, std::vector<Type> types);
std::string generateMethodIfExists(Type* type, std::string method, std::string parameter); std::string generateMethodIfExists(Type* type, std::string method, std::string parameter, std::vector<Type> methodTypes);
std::string emitDestructors(std::vector<NodeTree<ASTData>*> possibleDeclarations, NodeTree<ASTData>* enclosingObject); std::string emitDestructors(std::vector<NodeTree<ASTData>*> possibleDeclarations, NodeTree<ASTData>* enclosingObject);
std::string tabs(); std::string tabs();
std::string getID(); std::string getID();

View File

@@ -38,6 +38,8 @@ class Type {
void increaseIndirection(); void increaseIndirection();
void decreaseIndirection(); void decreaseIndirection();
void modifyIndirection(int mod); void modifyIndirection(int mod);
Type withIncreasedIndirection();
Type withDecreasedIndirection();
ValueType baseType; ValueType baseType;
NodeTree<ASTData>* typeDefinition; NodeTree<ASTData>* typeDefinition;

View File

@@ -46,6 +46,14 @@ std::vector<T> reverse(std::vector<T> vec) {
return flat; return flat;
} }
template <typename T>
std::vector<T> dereferenced(std::vector<T*> vec) {
std::vector<T> de;
for (T* i:vec)
de.push_back(*i);
return de;
}
template <typename T> template <typename T>
std::vector<T> slice(std::vector<T> vec, int begin, int end, int step = 1) { std::vector<T> slice(std::vector<T> vec, int begin, int end, int step = 1) {
std::vector<T> toReturn; std::vector<T> toReturn;

View File

@@ -1048,7 +1048,7 @@ void ASTTransformation::unifyType(NodeTree<Symbol> *syntaxType, Type type, std::
} }
if (children.size() == 1) { 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 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 // I passed it in... It would contain the typemap from our scope if we are
// doing a template member function of a templated object // doing a template member function of a templated object
@@ -1093,8 +1093,9 @@ void ASTTransformation::unifyTemplateFunction(NodeTree<ASTData>* templateFunctio
std::map<std::string, Type> templateTypeMap; std::map<std::string, Type> templateTypeMap;
for (int i = 0; i < types.size(); i++) for (int i = 0; i < types.size(); i++)
unifyType(getNode("type", templateParameters[i]), types[i], &templateTypeMap, typeMap); unifyType(getNode("type", templateParameters[i]), types[i], &templateTypeMap, typeMap);
for (auto instantiationParam : getNodes("template_param", getNode("template_dec", templateSyntaxTree))) for (auto instantiationParam : getNodes("template_param", getNode("template_dec", templateSyntaxTree))) {
templateInstantiationTypes->push_back(templateTypeMap[concatSymbolTree(instantiationParam)].clone()); 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 //Lookup function for template functions. It has some extra concerns compared to function lookup, namely traits
@@ -1116,10 +1117,17 @@ NodeTree<ASTData>* ASTTransformation::templateFunctionLookup(NodeTree<ASTData>*
// the current scope, which would happen if we're trying to instantiate a template member function // the current scope, which would happen if we're trying to instantiate a template member function
std::map<std::string, Type*> typeMap = scopeTypeMap; std::map<std::string, Type*> typeMap = scopeTypeMap;
// If template instantiation was explicit, use those types. Otherwise, unify to find them // If template instantiation was explicit, use those types. Otherwise, unify to find them
if (templateInstantiationTypes->size()) if (templateInstantiationTypes->size()) {
templateInstantiationTypesPerFunction[i] = *templateInstantiationTypes; templateInstantiationTypesPerFunction[i] = *templateInstantiationTypes;
else std::cout << "passed in types" << std::endl;
}else{
unifyTemplateFunction(i, types, &templateInstantiationTypesPerFunction[i], typeMap); 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]); auto nameTraitsPairs = makeTemplateNameTraitPairs(templateSyntaxTree->getChildren()[1]);
//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() != templateInstantiationTypesPerFunction[i].size()) if (nameTraitsPairs.size() != templateInstantiationTypesPerFunction[i].size())
@@ -1131,11 +1139,11 @@ NodeTree<ASTData>* ASTTransformation::templateFunctionLookup(NodeTree<ASTData>*
for (auto j : nameTraitsPairs) { for (auto j : nameTraitsPairs) {
if (!subset(j.second, templateInstantiationTypesPerFunction[i][typeIndex]->traits)) { if (!subset(j.second, templateInstantiationTypesPerFunction[i][typeIndex]->traits)) {
traitsEqual = false; 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::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(templateInstantiationTypesPerFunction[i][typeIndex]->traits.begin(), templateInstantiationTypesPerFunction[i][typeIndex]->traits.end(), std::ostream_iterator<std::string>(std::cout, " ")); std::copy(templateInstantiationTypesPerFunction[i][typeIndex]->traits.begin(), templateInstantiationTypesPerFunction[i][typeIndex]->traits.end(), std::ostream_iterator<std::string>(std::cout, " "));
std::cout << std::endl; std::cout << "|" << std::endl;
break; break;
} else { } else {
std::cout << "Traits ARE a subset for " << j.first << " and " << templateInstantiationTypesPerFunction[i][typeIndex]->toString() << ": "; std::cout << "Traits ARE a subset for " << j.first << " and " << templateInstantiationTypesPerFunction[i][typeIndex]->toString() << ": ";

View File

@@ -426,8 +426,8 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
output.preValue += expr.preValue; output.preValue += expr.preValue;
std::string retTemp = "ret_temp" + getID(); std::string retTemp = "ret_temp" + getID();
output.preValue += ValueTypeToCType(children[0]->getDataRef()->valueType, retTemp) + ";\n"; output.preValue += ValueTypeToCType(children[0]->getDataRef()->valueType, retTemp) + ";\n";
if (methodExists(children[0]->getDataRef()->valueType, "copy_construct")) if (methodExists(children[0]->getDataRef()->valueType, "copy_construct", std::vector<Type>{children[0]->getDataRef()->valueType->withIncreasedIndirection()}))
output.preValue += generateMethodIfExists(children[0]->getDataRef()->valueType, "copy_construct", "&"+retTemp + ", &" + expr.value); output.preValue += generateMethodIfExists(children[0]->getDataRef()->valueType, "copy_construct", "&"+retTemp + ", &" + expr.value, std::vector<Type>{children[0]->getDataRef()->valueType->withIncreasedIndirection()});
else else
output.preValue += retTemp + " = " + expr.value + ";\n"; output.preValue += retTemp + " = " + expr.value + ";\n";
// move expr post to before return // move expr post to before return
@@ -477,12 +477,12 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
return ValueTypeToCType(children[0]->getData().valueType, generate(children[0], enclosingObject, justFuncName).oneString()) + "; " + generate(children[1], enclosingObject, true).oneString(true) + "/*Init Position Call*/"; return ValueTypeToCType(children[0]->getData().valueType, generate(children[0], enclosingObject, justFuncName).oneString()) + "; " + generate(children[1], enclosingObject, true).oneString(true) + "/*Init Position Call*/";
} else { } else {
// copy constructor if of the same type // 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<Type>{children[1]->getDataRef()->valueType->withIncreasedIndirection()})) {
CCodeTriple toAssign = generate(children[1], enclosingObject, true); CCodeTriple toAssign = generate(children[1], enclosingObject, true);
std::string assignedTo = generate(children[0], enclosingObject, justFuncName).oneString(); std::string assignedTo = generate(children[0], enclosingObject, justFuncName).oneString();
output.value = toAssign.preValue; output.value = toAssign.preValue;
output.value += ValueTypeToCType(children[0]->getData().valueType, assignedTo) + ";\n"; 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<Type>{children[0]->getDataRef()->valueType->withIncreasedIndirection()}) + ";\n" + output.postValue;
output.value += toAssign.postValue; output.value += toAssign.postValue;
return output; return output;
} else { } else {
@@ -540,8 +540,7 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
if (name == "+" || name == "-" || name == "*" || name == "/" || name == "==" || name == ">=" || name == "<=" || name == "!=" if (name == "+" || name == "-" || name == "*" || name == "/" || name == "==" || name == ">=" || name == "<=" || name == "!="
|| name == "<" || name == ">" || 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) + ")" + name + "(" + generate(children[2], enclosingObject, true) + "))";
return "((" + generate(children[1], enclosingObject, true).oneString() + ")" + name + "(" + generate(children[2], enclosingObject, true).oneString() + "))";
} else if (name == "." || name == "->") { } else if (name == "." || name == "->") {
if (children.size() == 1) if (children.size() == 1)
return "/*dot operation with one child*/" + generate(children[0], enclosingObject, true).oneString() + "/*end one child*/"; return "/*dot operation with one child*/" + generate(children[0], enclosingObject, true).oneString() + "/*end one child*/";
@@ -603,12 +602,12 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
} }
// see if we should copy_construct all the parameters // see if we should copy_construct all the parameters
for (int i = 1; i < children.size(); i++) { //children[0] is the declaration 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<Type>{children[i]->getDataRef()->valueType->withIncreasedIndirection()})) {
std::string tmpParamName = "param" + getID(); std::string tmpParamName = "param" + getID();
CCodeTriple paramValue = generate(children[i], enclosingObject, true); CCodeTriple paramValue = generate(children[i], enclosingObject, true);
output.preValue += paramValue.preValue; output.preValue += paramValue.preValue;
output.preValue += ValueTypeToCType(children[i]->getDataRef()->valueType, tmpParamName) + ";\n"; 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<Type>{children[i]->getDataRef()->valueType->withIncreasedIndirection()});
output.value += tmpParamName; output.value += tmpParamName;
output.postValue += paramValue.postValue; output.postValue += paramValue.postValue;
} else { } else {
@@ -620,11 +619,11 @@ CCodeTriple CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
output += ") "; output += ") ";
// see if we should add a destructer call to this postValue // see if we should add a destructer call to this postValue
Type* retType = children[0]->getDataRef()->valueType->returnType; Type* retType = children[0]->getDataRef()->valueType->returnType;
if (methodExists(retType, "destruct")) { if (methodExists(retType, "destruct", std::vector<Type>())) {
std::string retTempName = "return_temp" + getID(); std::string retTempName = "return_temp" + getID();
output.preValue += ValueTypeToCType(retType, retTempName) + " = " + output.value + ";\n"; output.preValue += ValueTypeToCType(retType, retTempName) + " = " + output.value + ";\n";
output.value = retTempName; output.value = retTempName;
output.postValue = generateMethodIfExists(retType, "destruct", "&"+retTempName) + ";\n" + output.postValue; output.postValue = generateMethodIfExists(retType, "destruct", "&"+retTempName, std::vector<Type>()) + ";\n" + output.postValue;
} }
return output; return output;
} }
@@ -674,32 +673,44 @@ std::string CGenerator::generateObjectMethod(NodeTree<ASTData>* enclosingObject,
return output; return output;
} }
NodeTree<ASTData>* CGenerator::getMethod(Type* type, std::string method) { NodeTree<ASTData>* CGenerator::getMethod(Type* type, std::string method, std::vector<Type> types) {
if (type->getIndirection()) if (type->getIndirection())
return nullptr; return nullptr;
NodeTree<ASTData> *typeDefinition = type->typeDefinition; NodeTree<ASTData> *typeDefinition = type->typeDefinition;
if (typeDefinition) { if (typeDefinition) {
auto definitionItr = typeDefinition->getDataRef()->scope.find(method); auto definitionItr = typeDefinition->getDataRef()->scope.find(method);
if (definitionItr != typeDefinition->getDataRef()->scope.end()) if (definitionItr != typeDefinition->getDataRef()->scope.end()) {
return definitionItr->second[0]; for (auto method : definitionItr->second) {
bool methodFits = true;
std::vector<Type> 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; return nullptr;
} }
bool CGenerator::methodExists(Type* type, std::string method) { bool CGenerator::methodExists(Type* type, std::string method, std::vector<Type> types) {
return getMethod(type, method) != nullptr; return getMethod(type, method, types) != nullptr;
} }
std::string CGenerator::generateMethodIfExists(Type* type, std::string method, std::string parameter) { std::string CGenerator::generateMethodIfExists(Type* type, std::string method, std::string parameter, std::vector<Type> methodTypes) {
NodeTree<ASTData> *typeDefinition = type->typeDefinition; NodeTree<ASTData> *methodDef = getMethod(type, method, methodTypes);
NodeTree<ASTData> *methodDef = getMethod(type, method);
if (methodDef) { if (methodDef) {
NodeTree<ASTData> *typeDefinition = type->typeDefinition;
std::string nameDecoration; std::string nameDecoration;
for (Type *paramType : methodDef->getDataRef()->valueType->parameterTypes) for (Type *paramType : methodDef->getDataRef()->valueType->parameterTypes)
nameDecoration += "_" + ValueTypeToCTypeDecoration(paramType); nameDecoration += "_" + ValueTypeToCTypeDecoration(paramType);
return scopePrefix(typeDefinition) + CifyName(typeDefinition->getDataRef()->symbol.getName()) + "__" + method + nameDecoration + "(" + parameter + ");\n"; 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 ""; return "";
} }
@@ -707,7 +718,7 @@ std::string CGenerator::generateMethodIfExists(Type* type, std::string method, s
std::string CGenerator::emitDestructors(std::vector<NodeTree<ASTData>*> identifiers, NodeTree<ASTData>* enclosingObject) { std::string CGenerator::emitDestructors(std::vector<NodeTree<ASTData>*> identifiers, NodeTree<ASTData>* enclosingObject) {
std::string destructorString = ""; std::string destructorString = "";
for (auto identifier : identifiers) 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<Type>());
return destructorString; return destructorString;
} }

View File

@@ -169,3 +169,15 @@ void Type::decreaseIndirection() {
void Type::modifyIndirection(int mod) { void Type::modifyIndirection(int mod) {
setIndirection(indirection + mod); setIndirection(indirection + mod);
} }
Type Type::withIncreasedIndirection() {
Type *newOne = clone();
newOne->increaseIndirection();
return *newOne;
}
Type Type::withDecreasedIndirection() {
Type *newOne = clone();
newOne->decreaseIndirection();
return *newOne;
}

View File

@@ -1,11 +1,11 @@
import vector:*; import vector:*;
import io:*; import io:*;
typedef matrix (Destructable) { typedef matrix (Object) {
var data: vector<double>; var data: vector<double>;
var rows: int; var rows: int;
var cols: int; var cols: int;
///****************************** ///******************************
// Constructors // Constructors
///*****************************/ ///*****************************/
@@ -18,16 +18,16 @@ typedef matrix (Destructable) {
data.construct(); data.construct();
return this; return this;
} }
//Constructor with single argument //Constructor with single argument
//Creates an N x N matrix //Creates an N x N matrix
fun construct(size: int): matrix* { fun construct(size: int): matrix* {
rows = size; rows = size;
cols = size; cols = size;
data.construct(rows*cols); data.construct(rows*cols);
return this; return this;
} }
//Constructor with two arguments //Constructor with two arguments
//Creates an N x M matrix //Creates an N x M matrix
fun construct(r: int, c: int): matrix* { fun construct(r: int, c: int): matrix* {
@@ -36,16 +36,16 @@ typedef matrix (Destructable) {
data.construct(rows*cols); data.construct(rows*cols);
return this; return this;
} }
///**************************** ///****************************
// Utility Functions // Utility Functions
///***************************/ ///***************************/
//Test using indexing at 0 //Test using indexing at 0
fun test0(i: int, j: int): bool { fun test0(i: int, j: int): bool {
var index = i*rows + j; var index = i*rows + j;
if(index > (rows * cols - 1) ) { if(index > (rows * cols - 1) ) {
print("Index ("); print("Index (");
print(i); print(i);
@@ -59,15 +59,15 @@ typedef matrix (Destructable) {
println(")."); println(").");
return false; return false;
} }
return true; return true;
} }
//Test using indexing at 1 //Test using indexing at 1
fun test1(i: int, j: int): bool { fun test1(i: int, j: int): bool {
var index = (i-1)*rows + (j-1); var index = (i-1)*rows + (j-1);
if(index > (rows * cols - 1) ) { if(index > (rows * cols - 1) ) {
print("Index ("); print("Index (");
print(i); print(i);
@@ -81,24 +81,24 @@ typedef matrix (Destructable) {
println(")."); println(").");
return false; return false;
} }
return true; return true;
} }
//Access matrix element //Access matrix element
fun at(i: int, j: int): double { fun at(i: int, j: int): double {
var index = i*rows + j; var index = i*rows + j;
if(test0(i,j)) if(test0(i,j))
return data.at(index); return data.at(index);
return 0; return 0;
} }
//Set matrix element //Set matrix element
fun set(i: int, j: int, num: double): void { fun set(i: int, j: int, num: double): void {
var index = i*rows + j; var index = i*rows + j;
if(test0(i,j)) if(test0(i,j))
@@ -106,11 +106,11 @@ typedef matrix (Destructable) {
return; return;
} }
fun printMatrix(): void { fun printMatrix(): void {
for(var i: int = 0; i < rows; i++;) for(var i: int = 0; i < rows; i++;)
{ {
for(var j: int = 0; j < cols; j++;) for(var j: int = 0; j < cols; j++;)
{ {
print(at(i,j)); print(at(i,j));
@@ -121,11 +121,11 @@ typedef matrix (Destructable) {
return; return;
} }
///************************** ///**************************
// Linear Algebra Functions // Linear Algebra Functions
//**************************/ //**************************/
fun transpose(): void { fun transpose(): void {
var val1: double; var val1: double;
var val2: double; var val2: double;
@@ -138,7 +138,7 @@ typedef matrix (Destructable) {
set(n, m, val2); set(n, m, val2);
set(m, n, val1); set(m, n, val1);
} }
return; return;
} }

View File

@@ -1,3 +1,5 @@
import io:*
__if_comp__ __C__ simple_passthrough """ __if_comp__ __C__ simple_passthrough """
#include <stdlib.h> #include <stdlib.h>
""" """
@@ -41,24 +43,36 @@ fun new<T>(): T* {
return new<T>(1); return new<T>(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<T>(toDelete: T*, itemCount: int): void { fun delete<T>(toDelete: T*, itemCount: int): void {
delete<T>(toDelete); delete<T>(toDelete);
} }
/* Calling this with itemCount = 0 allows you to delete destructable objects without calling their destructors. */ /* Calling this with itemCount = 0 allows you to delete destructable objects without calling their destructors. */
fun delete<T(Destructable)>(toDelete: T*, itemCount: int): void { fun delete<T(Object)>(toDelete: T*, itemCount: int): void {
for (var i: int = 0; i < itemCount; i++;) // 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(); toDelete[i].destruct();
delete<T>(toDelete); delete<T>(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<T>(toDelete: T*): void { fun delete<T>(toDelete: T*): void {
free<T>(toDelete); free<T>(toDelete);
} }
fun delete<T(Destructable)>(toDelete: T*): void { fun delete<T(Object)>(toDelete: T*): void {
toDelete->destruct(); toDelete->destruct();
free<T>(toDelete); free<T>(toDelete);
} }
// a wrapper for copy constructing if it has the Object trait
fun maybe_copy_construct<T>(to:T*, from:T*):void {
*to = *from
}
fun maybe_copy_construct<T(Object)>(to:T*, from:T*):void {
to->copy_construct(from)
}

View File

@@ -1,7 +1,7 @@
import vector; import vector;
import mem; import mem;
obj string (Destructable) { obj string (Object) {
var data: vector::vector<char>; var data: vector::vector<char>;
fun construct(): string* { fun construct(): string* {
data.construct(); data.construct();

View File

@@ -2,7 +2,7 @@ import mem:*;
import util:*; import util:*;
import io:*; import io:*;
obj vector<T> (Destructable) { obj vector<T> (Object) {
var data: T*; var data: T*;
var size: int; var size: int;
var available: int; var available: int;
@@ -23,14 +23,14 @@ obj vector<T> (Destructable) {
} }
fun copy_construct(old: vector<T>*): void { fun copy_construct(old: vector<T>*): void {
construct(old->size) construct()
for (var i = 0; i < size; i++;) for (var i = 0; i < old->size; i++;)
set(i, old->get(i)) addEnd(old->get(i))
} }
fun destruct(): void { fun destruct(): void {
if (data) if (data)
delete<T>(data); delete(data, size);
data = 0 data = 0
} }
@@ -41,11 +41,11 @@ obj vector<T> (Destructable) {
} }
fun operator+(other:vector<T>):vector<T> { fun operator+(other:vector<T>):vector<T> {
var newVec.construct(size + other.size):vector<T> var newVec.construct():vector<T>
for (var i = 0; i < size; i++;) for (var i = 0; i < size; i++;)
newVec.set(i, get(i)) newVec.addEnd(get(i))
for (var i = 0; i < other.size; i++;) for (var i = 0; i < other.size; i++;)
newVec.set(i+size, other.get(i)) newVec.addEnd(other.get(i))
return newVec return newVec
} }
@@ -55,9 +55,9 @@ obj vector<T> (Destructable) {
} }
fun clone(): vector<T> { fun clone(): vector<T> {
var newVec.construct(size): vector<T> var newVec.construct(): vector<T>
for (var i = 0; i < size; i++;) for (var i = 0; i < size; i++;)
newVec.set(i, data[i]) newVec.addEnd(data[i])
return newVec return newVec
} }
@@ -66,8 +66,8 @@ obj vector<T> (Destructable) {
if (!newData) if (!newData)
return false; return false;
for (var i: int = 0; i < lesser<int>(size, newSize); i++;) for (var i: int = 0; i < lesser<int>(size, newSize); i++;)
newData[i] = data[i]; maybe_copy_construct(&newData[i], &data[i]);
delete<T>(data, 0); delete(data, size);
data = newData; data = newData;
available = newSize; available = newSize;
size = lesser(size, newSize) size = lesser(size, newSize)
@@ -101,7 +101,7 @@ obj vector<T> (Destructable) {
size++; size++;
if (size >= available) if (size >= available)
resize(size*2); resize(size*2);
data[size-1] = dataIn; maybe_copy_construct(&data[size-1], &dataIn);
} }
fun do(func: fun(T):void):void { fun do(func: fun(T):void):void {
for (var i = 0; i < size; i++;) for (var i = 0; i < size; i++;)
@@ -112,9 +112,9 @@ obj vector<T> (Destructable) {
data[i] = func(data[i]) data[i] = func(data[i])
} }
fun map<U>(func: fun(T):U):vector<U> { fun map<U>(func: fun(T):U):vector<U> {
var newVec.construct(size): vector<U> var newVec.construct(): vector<U>
for (var i = 0; i < size; i++;) for (var i = 0; i < size; i++;)
newVec.set(i, func(data[i])) newVec.addEnd(func(data[i]))
return newVec return newVec
} }
}; };

View File

@@ -1,3 +1,5 @@
8 8
9 9
10 10
Does have Traits
Does not have Traits

View File

@@ -1,9 +1,10 @@
import io:* import io:*
obj Traited(Traits) {}
fun funcID<T>(genFun: fun():T):T { fun funcID<T>(genFun: fun():T):T {
return genFun() return genFun()
} }
fun retInt():int { fun retInt():int {
return 9 return 9
} }
@@ -21,11 +22,22 @@ fun ptrFn<T>(ptr: T*):void {
println(*ptr) println(*ptr)
} }
fun traitAware<T>(it:T*):void {
println("Does not have Traits")
}
fun traitAware<T(Traits)>(it:T*):void {
println("Does have Traits")
}
fun main():int { fun main():int {
var a = 8 var a = 8
ptrFn(&a) ptrFn(&a)
println(funcID(retInt)) println(funcID(retInt))
doThePrint(printInt) doThePrint(printInt)
var t:Traited
traitAware(&t)
traitAware(&a)
return 0 return 0
} }

View File

@@ -4,6 +4,11 @@
9131321 9131321
15513 15513
3.7000007.7000007.70000015.700000 3.7000007.7000007.70000015.700000
Copied! Constructed: 0
Destroyed! Copied: 0 to 1
Destroyed! Copied: 1 to 2
Destroyed: 1
delete vector
Destroyed: 2
done
Destroyed: 0

View File

@@ -2,13 +2,34 @@ import io:*;
import mem:*; import mem:*;
import vector:*; 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 { 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 { fun destruct(): void {
println("Destroyed!"); print("Destroyed: ")
println(data)
} }
}; };
@@ -42,9 +63,11 @@ fun main(): int {
println(); println();
var desVec: vector<AbleToBeDestroyed>* = new<vector<AbleToBeDestroyed>>()->construct(); var desVec: vector<AbleToBeDestroyed>* = new<vector<AbleToBeDestroyed>>()->construct();
var testDestruct: AbleToBeDestroyed; var testDestruct.construct(0): AbleToBeDestroyed;
desVec->addEnd(testDestruct); desVec->addEnd(testDestruct);
delete<vector<AbleToBeDestroyed>>(desVec); println("delete vector")
delete(desVec);
println("done")
return 0; return 0;
} }