diff --git a/include/ASTTransformation.h b/include/ASTTransformation.h index 41e0c0c..920a53d 100644 --- a/include/ASTTransformation.h +++ b/include/ASTTransformation.h @@ -45,7 +45,8 @@ class ASTTransformation: public NodeTransformation { std::string concatSymbolTree(NodeTree* root); NodeTree* doFunction(NodeTree* scope, std::string lookup, std::vector*> nodes, std::map templateTypeReplacements); - std::set*> findVariablesToClose(NodeTree* func, NodeTree* stat); + NodeTree* generateThis(NodeTree* scope); + std::set*> findVariablesToClose(NodeTree* func, NodeTree* stat, NodeTree* scope); bool inScopeChain(NodeTree* node, NodeTree* scope); NodeTree* functionLookup(NodeTree* scope, std::string lookup, std::vector types); NodeTree* templateFunctionLookup(NodeTree* scope, std::string lookup, std::vector* templateInstantiationTypes, std::vector types, std::map scopeTypeMap); diff --git a/src/ASTTransformation.cpp b/src/ASTTransformation.cpp index 9e6eca4..db5c8fd 100644 --- a/src/ASTTransformation.cpp +++ b/src/ASTTransformation.cpp @@ -487,7 +487,7 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree newNode->getDataRef()->valueType = new Type(mapNodesToTypePointers(parameters), newNode->getDataRef()->valueType); auto statement = transform(getNode("statement", children), scope, types, limitToFunction, templateTypeReplacements); if (name == "lambda") - newNode->getDataRef()->closedVariables = findVariablesToClose(newNode, statement); + newNode->getDataRef()->closedVariables = findVariablesToClose(newNode, statement, scope); for (auto i : newNode->getDataRef()->closedVariables) std::cout << "OK, CLOSED: " << i->getDataRef()->toString() << std::endl; newNode->addChild(statement); @@ -520,7 +520,7 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree std::cerr << "scope lookup error! Could not find " << functionCallString << " in boolean stuff " << std::endl; throw "LOOKUP ERROR: " + functionCallString; } - newNode = function; + return function; } else { // XXX What the heck is this if (children.size() == 0) @@ -928,7 +928,7 @@ bool ASTTransformation::inScopeChain(NodeTree* node, NodeTree* } // We return a set of all identifers used in the children of stat that are not declared somewhere below stat // used to calculate the closedvariables for closures -std::set*> ASTTransformation::findVariablesToClose(NodeTree* func, NodeTree* stat) { +std::set*> ASTTransformation::findVariablesToClose(NodeTree* func, NodeTree* stat, NodeTree* scope) { std::set*> closed; //enum ASTType {undef, translation_unit, interpreter_directive, import, identifier, type_def, //function, code_block, typed_parameter, expression, boolean_expression, statement, @@ -937,18 +937,26 @@ std::set*> ASTTransformation::findVariablesToClose(NodeTreegetDataRef()->type == function || stat->getDataRef()->type == translation_unit || stat->getDataRef()->type == type_def || stat->getDataRef()->type == value - ) + ) { + // if this is a method we know that it is a method of our current enclosing object (as we already know that we're not on the right side of . or ->, see below) + // we should add our enclosing object, this, to our closed over variables + if (stat->getDataRef()->type == function) { + auto statEnclosingScope = stat->getDataRef()->scope["~enclosing_scope"][0]; + if (statEnclosingScope && statEnclosingScope->getDataRef()->valueType && statEnclosingScope->getDataRef()->valueType->typeDefinition) + closed.insert(generateThis(scope)); + } return closed; + } if (stat->getDataRef()->type == function_call && (stat->getDataRef()->symbol.getName() == "." || stat->getDataRef()->symbol.getName() == "->")) { // only search on the left side of access operators like . and -> - auto recClosed = findVariablesToClose(func, stat->getChildren()[1]); + auto recClosed = findVariablesToClose(func, stat->getChildren()[1], scope); closed.insert(recClosed.begin(), recClosed.end()); return closed; } if (stat->getDataRef()->type == identifier && !inScopeChain(stat, func)) closed.insert(stat); for (auto child: stat->getChildren()) { - auto recClosed = findVariablesToClose(func, child); + auto recClosed = findVariablesToClose(func, child, scope); closed.insert(recClosed.begin(), recClosed.end()); } return closed; @@ -1140,7 +1148,18 @@ void ASTTransformation::unifyType(NodeTree *syntaxType, Type type, std:: // to get the type it was instantiated with. auto origionalType = type.typeDefinition->getDataRef()->valueType; auto typeTemplateDefinition = origionalType->templateDefinition; - if (typeTemplateDefinition && concatSymbolTree(getNode("scoped_identifier", children)) == concatSymbolTree(getNode("identifier", typeTemplateDefinition->getChildren()))) { + // we have to get rid of the scope partion of the scoped_identifier so we can compare properly with the typeTemplateDefinition's identifier + auto scoped = getNode("scoped_identifier", children); + NodeTree* ident = nullptr; + while(scoped && !ident) { + ident = getNode("identifier", scoped); + scoped = getNode("scoped_identifier", scoped); + } + //if (typeTemplateDefinition) { + //std::cout << concatSymbolTree(ident) << std::endl; + //std::cout << concatSymbolTree(getNode("identifier", typeTemplateDefinition->getChildren())) << std::endl; + //} + if (typeTemplateDefinition && concatSymbolTree(ident) == concatSymbolTree(getNode("identifier", typeTemplateDefinition->getChildren()))) { std::vector*> uninTypeInstTypes = getNodes("type", getNode("template_inst", children)); std::vector*> typeInstTypes = getNodes("template_param", getNode("template_dec", typeTemplateDefinition->getChildren())); for (int i = 0; i < uninTypeInstTypes.size(); i++) { @@ -1152,6 +1171,7 @@ void ASTTransformation::unifyType(NodeTree *syntaxType, Type type, std:: return; } + throw "the inference just isn't good enough"; } throw "the inference just isn't good enough"; } @@ -1314,6 +1334,18 @@ std::vector*> ASTTransformation::scopeLookup(NodeTree return scopeLookup(scope, lookup, includeModules, std::set*>()); } +NodeTree* ASTTransformation::generateThis(NodeTree* scope) { + NodeTree* identifier = languageLevelReservedWords["this"][0]; + identifier = new NodeTree("identifier", identifier->getData()); + // if we're looking for this, traverse up until we find the declaration of this object and assign it's type to this + NodeTree* trans; + for (trans = scope; trans->getDataRef()->type != type_def; trans = trans->getDataRef()->scope["~enclosing_scope"][0]); + identifier->getDataRef()->valueType = trans->getDataRef()->valueType->clone(); + identifier->getDataRef()->valueType->increaseIndirection(); + identifier->getDataRef()->scope = trans->getDataRef()->scope; + return identifier; +} + std::vector*> ASTTransformation::scopeLookup(NodeTree* scope, std::string lookup, bool includeModules, std::set*> visited) { std::cout << "Scp]|[e looking up " << lookup << std::endl; std::cout << "current: " << scope->getDataRef()->toString() << std::endl; @@ -1330,12 +1362,7 @@ std::vector*> ASTTransformation::scopeLookup(NodeTree std::cout << "found it at language level as reserved word." << std::endl; NodeTree* identifier = LLElementIterator->second[0]; if (lookup == "this") { - identifier = new NodeTree("identifier", identifier->getData()); - // if we're looking for this, traverse up until we find the declaration of this object and assign it's type to this - NodeTree* trans; - for (trans = scope; trans->getDataRef()->type != type_def; trans = trans->getDataRef()->scope["~enclosing_scope"][0]); - identifier->getDataRef()->valueType = trans->getDataRef()->valueType->clone(); - identifier->getDataRef()->valueType->increaseIndirection(); + identifier = generateThis(scope); } std::vector*> thingy; thingy.push_back(identifier); return thingy; diff --git a/src/CGenerator.cpp b/src/CGenerator.cpp index 2dfb0bd..da59402 100644 --- a/src/CGenerator.cpp +++ b/src/CGenerator.cpp @@ -302,7 +302,7 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc if (enclosingFunction->getDataRef()->closedVariables.size()) { std::cout << "WHOH IS A CLOSER" << std::endl; if (enclosingFunction->getDataRef()->closedVariables.find(from) != enclosingFunction->getDataRef()->closedVariables.end()) { - preName += "(*closed_varibles->"; + preName += "(*closed_variables->"; postName += ")"; } } @@ -322,7 +322,7 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc std::string nameDecoration, parameters; if (data.closedVariables.size()) - parameters += closureStructType(data.closedVariables) + " *closed_varibles"; + parameters += closureStructType(data.closedVariables) + " *closed_variables"; for (int j = 0; j < children.size()-1; j++) { if (j > 0 || data.closedVariables.size()) parameters += ", "; @@ -345,7 +345,12 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc if (notFirst) output.preValue += ", "; notFirst = true; - output.preValue += "." + scopePrefix(var) + var->getDataRef()->symbol.getName() + " = &" + scopePrefix(var) + var->getDataRef()->symbol.getName(); + std::string varName = var->getDataRef()->symbol.getName(); + std::string preName; + if (enclosingObject && enclosingObject->getDataRef()->scope.find(varName) != enclosingObject->getDataRef()->scope.end()) + preName += "this->"; + varName = (varName == "this") ? varName : scopePrefix(var) + varName; + output.preValue += "." + varName + " = &" + preName + varName; } output.preValue += "};\n"; output += "("+ ValueTypeToCType(data.valueType, "") +"){(void*)" + funcName + ", &" + tmpStruct + "}"; @@ -636,12 +641,23 @@ CCodeTriple CGenerator::generate(NodeTree* from, NodeTree* enc std::string nameDecoration; for (int i = 0; i < (functionDefChildren.size() > 0 ? functionDefChildren.size()-1 : 0); i++) nameDecoration += "_" + ValueTypeToCTypeDecoration(functionDefChildren[i]->getData().valueType); + // it is possible that this is an object method from inside a closure + // in which case, recover the enclosing object from this + bool addClosedOver = false; + if (enclosingFunction && enclosingFunction->getDataRef()->closedVariables.size()) { + for (auto closedVar : enclosingFunction->getDataRef()->closedVariables) { + if (closedVar->getDataRef()->symbol.getName() == "this") { + enclosingObject = closedVar->getDataRef()->valueType->typeDefinition; + addClosedOver = true; + } + } + } //Check to see if we're inside of an object and this is a method call bool isSelfObjectMethod = enclosingObject && contains(enclosingObject->getChildren(), children[0]); if (isSelfObjectMethod) { output += function_header + scopePrefix(children[0]) + CifyName(enclosingObject->getDataRef()->symbol.getName()) +"__"; output += CifyName(name + nameDecoration) + "("; - output += children.size() > 1 ? "this," : "this"; + output += std::string(addClosedOver ? "(*closed_variables->this)" : "this") + (children.size() > 1 ? "," : ""); } else { output += function_header + scopePrefix(children[0]) + CifyName(name + nameDecoration) + "("; } @@ -745,7 +761,8 @@ std::string CGenerator::generateObjectMethod(NodeTree* enclosingObject, enclosingObjectType.increaseIndirection(); std::vector*> children = from->getChildren(); std::string nameDecoration, parameters; - for (int i = 0; i < children.size()-1; i++) { + // note how we get around children.size() being an unsigned type + for (int i = 0; i+1 < children.size(); i++) { parameters += ", " + ValueTypeToCType(children[i]->getData().valueType, generate(children[i]).oneString()); nameDecoration += "_" + ValueTypeToCTypeDecoration(children[i]->getData().valueType); @@ -821,7 +838,9 @@ std::string CGenerator::closureStructType(std::set*> closedVar // note the increased indirection b/c we're using references to what we closed over for (auto var : closedVariables) { auto tmp = var->getDataRef()->valueType->withIncreasedIndirection(); - typedefString += ValueTypeToCType(&tmp, scopePrefix(var) + var->getDataRef()->symbol.getName()) + ";"; + std::string varName = var->getDataRef()->symbol.getName(); + varName = (varName == "this") ? varName : scopePrefix(var) + varName; + typedefString += ValueTypeToCType(&tmp, varName) + ";"; } std::string structName = "closureStructType" + getID(); typedefString += " } " + structName + ";\n"; diff --git a/stdlib/io.krak b/stdlib/io.krak index b5a0a60..86e471a 100644 --- a/stdlib/io.krak +++ b/stdlib/io.krak @@ -38,6 +38,14 @@ fun print(toPrint: string) : void { print(charArr); } +fun print(toPrint: bool): void { + if (toPrint) + print("true") + else + print("false") + return; +} + fun print(toPrint: int): void { __if_comp__ __C__ { simple_passthrough(toPrint = toPrint::) """ diff --git a/stdlib/map.krak b/stdlib/map.krak index 164b169..c03aa51 100644 --- a/stdlib/map.krak +++ b/stdlib/map.krak @@ -1,4 +1,5 @@ import vector +import io fun map(): map { var toRet.construct(): map @@ -22,18 +23,19 @@ obj map { keys.copy_construct(&old->keys) values.copy_construct(&old->values) } + fun operator=(rhs: map) { + destruct() + copy_construct(&rhs) + } fun destruct() { keys.destruct() values.destruct() } - fun find_index(key: T): int { - return keys.find_index(key) - } fun operator[]=(key: T, value: U) { set(key,value) } fun set(key: T, value: U) { - var keyIdx = find_index(key) + var keyIdx = keys.find(key) if (keyIdx >= 0) { values.set(keyIdx, value) return; @@ -42,7 +44,16 @@ obj map { values.add(value) } fun get(key: T): U { - return values.get(keys.find_index(key)) + return values.get(keys.find(key)) + } + fun remove(key: T) { + var idx = keys.find(key) + if (idx < 0) { + io::println("trying to remove nonexistant key-value!") + return; + } + keys.remove(idx) + values.remove(idx) } fun operator[](key: T): U { return get(key) diff --git a/stdlib/mem.krak b/stdlib/mem.krak index be54a14..136e981 100644 --- a/stdlib/mem.krak +++ b/stdlib/mem.krak @@ -1,4 +1,4 @@ -import io:* +import set __if_comp__ __C__ simple_passthrough """ #include @@ -93,4 +93,15 @@ fun maybe_destruct(it:T*):void { it->destruct() } +// a function that allows the safe deletion of recursive and complicated data structures +fun safe_recursive_delete(first: T*, addingFunc: fun(T*): set::set) { + var toDelete = set::set() + var next = set::set(first) + while (toDelete != next) { + toDelete = next + toDelete.for_each( fun(it: T*) next.add(addingFunc(it)); ) + } + toDelete.for_each( fun(it: T*) delete(it); ) +} + diff --git a/stdlib/regex.krak b/stdlib/regex.krak index 8159ce2..bbed180 100644 --- a/stdlib/regex.krak +++ b/stdlib/regex.krak @@ -2,6 +2,7 @@ import io import vector import string import mem +import set import util import conversions @@ -55,12 +56,14 @@ obj regex(Object) { } fun copy_construct(old:regex*):void { - begin = old->begin - regexString.copy_construct(&old->regexString) + //begin = old->begin + //regexString.copy_construct(&old->regexString) + construct(old->regexString) } fun destruct():void { regexString.destruct() + //mem::safe_recursive_delete(begin, fun(it: regexState*): set::set { return set::set(it); } ) } fun operator=(other: regex):void { diff --git a/stdlib/set.krak b/stdlib/set.krak new file mode 100644 index 0000000..6cc9493 --- /dev/null +++ b/stdlib/set.krak @@ -0,0 +1,60 @@ +import vector +import io + +fun set(): set { + var toRet.construct() : set + return toRet +} + +fun set(item: T): set { + var toRet.construct() : set + toRet.add(item) + return toRet +} + +obj set { + var data: vector::vector + fun construct() { + data.construct() + } + fun copy_construct(old: set*) { + data.copy_construct(&old->data) + } + fun operator=(rhs: set) { + destruct() + copy_construct(&rhs) + } + fun operator==(rhs: set): bool { + if (size() != rhs.size()) + return false + return !data.any_true( fun(item: T): bool return !rhs.contains(item); ) + } + fun destruct() { + data.destruct() + } + fun size():int { + return data.size + } + fun contains(item: T): bool { + return data.find(item) != -1 + } + fun add(item: T) { + if (!contains(item)) + data.add(item) + } + fun add(items: set) { + items.for_each( fun(item: T) add(item); ) + } + fun remove(item: T) { + var idx = data.find(item) + if (idx == -1) { + io::println("CANNOT FIND ITEM TO REMOVE") + return + } + data.remove(idx) + } + fun for_each(func: fun(T):void) { + data.do(func) + } +} + diff --git a/stdlib/string.krak b/stdlib/string.krak index 8902d01..28494b9 100644 --- a/stdlib/string.krak +++ b/stdlib/string.krak @@ -34,6 +34,16 @@ obj string (Object) { construct(*old) } + fun operator=(str: char*): void { + destruct(); + construct(str) + } + + fun operator=(str: string): void { + destruct(); + data.copy_construct(&str.data) + } + fun destruct():void { data.destruct() } @@ -51,11 +61,6 @@ obj string (Object) { } fun length():int { return data.size; } - fun operator=(str: char*): void { - destruct(); - construct(str) - } - fun operator+(str: char*): string { var newStr.construct(str):string var ret.construct(data + newStr.data):string diff --git a/stdlib/vector.krak b/stdlib/vector.krak index 2a50033..da06b4e 100644 --- a/stdlib/vector.krak +++ b/stdlib/vector.krak @@ -133,7 +133,7 @@ obj vector (Object) { // on an object that we want to put in a vector. In this way we avoid the problem // by not generating this function unless it's called - we also get the ability to // do a find index using a different type, which could be fun. - fun find_index(value: U): int { + fun find(value: U): int { for (var i = 0; i < size; i++;) if (data[i] == value) return i; @@ -159,6 +159,16 @@ obj vector (Object) { resize(size*2); maybe_copy_construct(&data[size-1], &dataIn); } + + fun remove(index: int) { + maybe_destruct(&data[index]) + for (var i = index+1; i < size; i++;) { + maybe_copy_construct(&data[i-1], &data[i]) + maybe_destruct(&data[i]) + } + size-- + } + fun do(func: fun(T):void):void { for (var i = 0; i < size; i++;) func(data[i]) diff --git a/tests/test_close_over_members.expected_results b/tests/test_close_over_members.expected_results new file mode 100644 index 0000000..945d41e --- /dev/null +++ b/tests/test_close_over_members.expected_results @@ -0,0 +1,2 @@ +4 +7 diff --git a/tests/test_close_over_members.krak b/tests/test_close_over_members.krak new file mode 100644 index 0000000..ffb6d42 --- /dev/null +++ b/tests/test_close_over_members.krak @@ -0,0 +1,27 @@ +import io:* + +fun runFunc(func: fun():void) { + func() +} + +obj ToClose { + var data: int + fun print4() { + println(4) + } + fun testMethod() { + runFunc(fun() { print4(); } ) + } + fun testVariable() { + data = 7 + runFunc(fun() { println(data); } ) + } +} + +fun main():int { + var it: ToClose + it.testMethod() + it.testVariable() + return 0 +} + diff --git a/tests/test_comparison_overload.expected_results b/tests/test_comparison_overload.expected_results new file mode 100644 index 0000000..c508d53 --- /dev/null +++ b/tests/test_comparison_overload.expected_results @@ -0,0 +1 @@ +false diff --git a/tests/test_comparison_overload.krak b/tests/test_comparison_overload.krak new file mode 100644 index 0000000..885fc8b --- /dev/null +++ b/tests/test_comparison_overload.krak @@ -0,0 +1,25 @@ +import io:* + +fun Comparable(): Comparable { + var toRet : Comparable + return toRet +} + +fun Comparable(item: T): Comparable { + var toRet : Comparable + return toRet +} + +obj Comparable { + fun operator==(other: Comparable):bool { + return false + } +} + +fun main():int { + var first: Comparable + var second: Comparable + println(first == second) + return 0 +} + diff --git a/tests/test_map.expected_results b/tests/test_map.expected_results index d7bb831..e77d4a3 100644 --- a/tests/test_map.expected_results +++ b/tests/test_map.expected_results @@ -9,5 +9,4 @@ Lookie, a map! What I get for not testing different types key: 7, value: Lookie, a map! -key: 20, value: What I get for not testing different types key: 30, value: we'll look for for_each too diff --git a/tests/test_map.krak b/tests/test_map.krak index 1fc482a..9b8a039 100644 --- a/tests/test_map.krak +++ b/tests/test_map.krak @@ -21,6 +21,7 @@ fun main():int { mapEx[30] = "we'll look for for_each too" println(mapEx[7]) println(mapEx[20]) + mapEx.remove(20) mapEx.for_each(fun(key:int, value:char*) { print("key: "); print(key); print(", value: "); println(value); }) return 0 } diff --git a/tests/test_set.expected_results b/tests/test_set.expected_results new file mode 100644 index 0000000..ba67780 --- /dev/null +++ b/tests/test_set.expected_results @@ -0,0 +1,13 @@ +true +false +false +true +true +false +false +false +false +true +true +4 +5 diff --git a/tests/test_set.krak b/tests/test_set.krak new file mode 100644 index 0000000..813bfba --- /dev/null +++ b/tests/test_set.krak @@ -0,0 +1,24 @@ +import io:* +import set:* + +fun main():int { + var s = set(3) + println(s.contains(3)) + println(s.contains(1)) + s.remove(3) + s.add(4) + println(s.contains(3)) + println(s.contains(4)) + + println(s == set(4)) + println(s == set(5)) + s.add(set(5)) + println(s == set(4)) + println(s == set(5)) + println(s.contains(3)) + println(s.contains(4)) + println(s.contains(5)) + + s.for_each( fun(it: int) println(it); ) + return 0 +} diff --git a/tests/test_vectorTest.expected_results b/tests/test_vectorTest.expected_results index d333645..97bc5b0 100644 --- a/tests/test_vectorTest.expected_results +++ b/tests/test_vectorTest.expected_results @@ -25,10 +25,83 @@ find test 0 1 2 -set and []= test +set, []=, and delete test 4 8 9 7 +delete +4 +8 +7 +delete v2 +Constructed: 100 +Constructed: 200 +Constructed: 300 +Copied: 100 to 101 +Copied: 200 to 201 +Copied: 300 to 301 +Copied: 101 to 102 +Copied: 102 to 103 +Copied: 103 to 104 +Destroyed: 103 +Destroyed: 102 +Copied: 201 to 202 +Copied: 202 to 203 +Copied: 203 to 204 +Destroyed: 203 +Destroyed: 202 +Copied: 301 to 302 +Copied: 302 to 303 +Copied: 303 to 304 +Destroyed: 303 +Destroyed: 302 +Copied: 104 to 105 +Copied: 105 to 106 +Copied: 106 to 107 +Destroyed: 106 +Destroyed: 105 +Copied: 204 to 205 +Copied: 205 to 206 +Copied: 206 to 207 +Destroyed: 206 +Destroyed: 205 +Copied: 304 to 305 +Copied: 305 to 306 +Copied: 306 to 307 +Destroyed: 306 +Destroyed: 305 +Destroyed: 204 +Destroyed: 304 +Destroyed: 104 +Destroyed: 301 +Destroyed: 201 +Destroyed: 101 +Copied: 107 to 108 +Copied: 108 to 109 +Copied: 109 to 110 +Destroyed: 109 +Destroyed: 108 +Copied: 207 to 208 +Copied: 208 to 209 +Copied: 209 to 210 +Destroyed: 209 +Destroyed: 208 +Copied: 307 to 308 +Copied: 308 to 309 +Copied: 309 to 310 +Destroyed: 309 +Destroyed: 308 +Destroyed: 207 +Destroyed: 307 +Destroyed: 107 +Destroyed: 210 +Copied: 310 to 311 +Destroyed: 310 done +Destroyed: 311 +Destroyed: 110 +Destroyed: 300 +Destroyed: 200 +Destroyed: 100 Destroyed: 0 diff --git a/tests/test_vectorTest.krak b/tests/test_vectorTest.krak index ccdee5e..9f8e401 100644 --- a/tests/test_vectorTest.krak +++ b/tests/test_vectorTest.krak @@ -107,16 +107,26 @@ fun main(): int { println("find test") var multipleFindTest = vector(1,2,3) - println(multipleFindTest.find_index(1)) - println(multipleFindTest.find_index(2)) - println(multipleFindTest.find_index(3)) + println(multipleFindTest.find(1)) + println(multipleFindTest.find(2)) + println(multipleFindTest.find(3)) - println("set and []= test") + println("set, []=, and delete test") var setTest = vector(4,5,6) setTest.add(7) setTest.set(1,8) setTest[2] = 9 setTest.do(fun(it: int) println(it);) + println("delete") + setTest.remove(2) + setTest.do(fun(it: int) println(it);) + + println("delete v2") + var firstRem.construct(100): AbleToBeDestroyed; + var secondRem.construct(200): AbleToBeDestroyed; + var thirdRem.construct(300): AbleToBeDestroyed; + var remTest = vector(firstRem, secondRem, thirdRem); + remTest.remove(1) println("done")