import mem:*; import util:*; import io:*; import serialize:*; import util:*; fun vector():vector { var out.construct():vector return out } fun vector(in:T):vector { var out.construct():vector out.add(in) return out } obj vector (Object, Serializable) { var data: *T; var size: int; var available: int; fun construct(): *vector { size = 0; available = 8; data = new(8); return this; } fun construct(ammt: int): *vector { size = 0; available = ammt; data = new(ammt); return this; } fun copy_construct(old: *vector): void { construct(old->size) size = old->size for (var i = 0; i < old->size; i++;) maybe_copy_construct(&data[i], &old->data[i]); //addEnd(old->get(i)) } fun serialize(): vector { var toRet = serialize(size) for (var i = 0; i < size; i++;) toRet += serialize(data[i]) return toRet } fun unserialize(it: ref vector, pos: int): int { unpack(size, pos) = unserialize(it, pos) data = new(size) available = size for (var i = 0; i < size; i++;) { var curr = unserialize(it, pos) pos = curr.second maybe_copy_construct(&data[i], &curr.first); } return pos } fun destruct(): void { if (data) delete(data, size); //data = 1337 data = 0 } fun operator=(other:vector):void { destruct() copy_construct(&other) } fun operator+(other:vector):vector { var newVec.construct():vector for (var i = 0; i < size; i++;) newVec.addEnd(get(i)) for (var i = 0; i < other.size; i++;) newVec.addEnd(other.get(i)) return newVec } fun operator+=(other: T):void { addEnd(other) } fun operator+=(other:vector):void { for (var i = 0; i < other.size; i++;) addEnd(other.get(i)) } fun clone(): vector { var newVec.construct(size): vector for (var i = 0; i < size; i++;) newVec.addEnd(data[i]) return newVec } fun reverse(): vector { var newVec.construct(size): vector for (var i = 0; i < size; i++;) newVec.addEnd(data[(size-i)-1]) return newVec } fun resize(newSize: int): bool { var newData: *T = new(newSize); if (!newData) return false; for (var i: int = 0; i < min(size, newSize); i++;) maybe_copy_construct(&newData[i], &data[i]); delete(data, size); data = newData; available = newSize; size = min(size, newSize) return true; } fun slice(start: int, end: int): vector { var new.construct(): vector if (start < 0) start += size + 1 if (end < 0) end += size + 1 for (var i = start; i < end; i++;) new.add(data[i]) return new } fun at(index: int): ref T { return get(index); } fun operator[](index: int): ref T { return get(index); } fun first(): ref T { return get(0) } fun last(): ref T { return get(size-1) } fun get(index: int): ref T { if (index < 0 || index >= size) { println("Vector access out of bounds! Retuning 0th element as sanest option"); print("Vector tried to access element: "); println(index); print("Max Index of vector: "); println(size-1); /*while(true) {}*/ return data[0]; } return data[index]; } fun getBackingMemory(): *T { return data; } // This is a template for the interesting reason that structs // can not be compared for equality in C, and maybe we haven't defined equality // 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(value: ref U): int { for (var i = 0; i < size; i++;) if (data[i] == value) return i; return -1; } // ditto fun contains(item: ref U): bool { return find(item) != -1 } // yep fun operator==(other: ref vector):bool { if (size != other.size) return false for (var i = 0; i < size; i++;) if (!(data[i] == other.data[i])) // it's !(==) because we want equality if our members are equal, and overloading etc return false return true } fun set(index: int, dataIn: T): void { if (index < 0 || index >= size) return; data[index] = dataIn; } fun add_all(dataIn: ref vector): void { for (var i = 0; i < dataIn.size; i++;) addEnd(dataIn[i]); } // same darn trick fun add_unique(dataIn: U): void { if (!contains(dataIn)) addEnd(dataIn) } fun add(dataIn: ref T): void { addEnd(dataIn); } fun addEnd(dataIn: ref T): void { if (size+1 >= available) resize((size+1)*2); maybe_copy_construct(&data[size], &dataIn); size++; } 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 clear() { for (var i = 0; i < size; i++;) maybe_destruct(&data[i]) size = 0 } fun for_each(func: fun(ref T):void):void { for (var i = 0; i < size; i++;) func(data[i]) } fun for_each(func: fun(T):void):void { for (var i = 0; i < size; i++;) func(data[i]) } fun in_place(func: fun(T):T):void { for (var i = 0; i < size; i++;) data[i] = func(data[i]) } fun map(func: fun(T):U):vector { var newVec.construct(size): vector for (var i = 0; i < size; i++;) newVec.addEnd(func(data[i])) return newVec } fun flatten_map(func: fun(T):vector):vector { var newVec.construct(size): vector for (var i = 0; i < size; i++;) { var to_add = func(data[i]) for (var j = 0; j < to_add.size; j++;) newVec.addEnd(to_add.get(j)) } return newVec } fun filter(func: fun(T):bool):vector { var newVec.construct(): vector for (var i = 0; i < size; i++;) if (func(data[i])) newVec.addEnd(data[i]) return newVec } fun any_true(func: fun(T):bool):bool { for (var i = 0; i < size; i++;) if (func(data[i])) return true return false } fun max(func: fun(T,T):bool): T { var maxIdx = 0 for (var i = 1; i < size; i++;) if (func(data[maxIdx], data[i])) maxIdx = i return data[maxIdx] } };