import mem:*; import util:*; import io:*; import serialize:*; import util:*; import map:*; fun vec():vec { var out.construct():vec return out } fun vec(in:T):vec { var out.construct():vec out.add(in) return out } obj vec (Object, Serializable) { var data: *T; var size: int; var available: int; fun construct(): *vec { size = 0; available = 8; data = new(8); return this; } fun construct(ammt: int): *vec { size = 0; available = ammt; data = new(ammt); return this; } fun copy_construct(old: *vec): void { construct(old->available) size = old->size if (is_object()) { for (var i = 0; i < old->size; i++;) maybe_copy_construct(&data[i], &old->data[i]); } else { memmove((data) cast *void, (old->data) cast *void, size * #sizeof) } } fun swap(other: ref vec) { var temp_data = data var temp_size = size var temp_available = available data = other.data size = other.size available = other.available other.data = temp_data other.size = temp_size other.available = temp_available } fun serialize(): vec { var toRet = serialize(size) for (var i = 0; i < size; i++;) toRet += serialize(data[i]) return toRet } fun unserialize(it: ref vec, 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 set_size(s: int) { size = s } fun operator=(other:ref vec):void { if (size < other.size) { destruct() copy_construct(&other) } else { clear() if (is_object()) { for (var i = 0; i < other.size; i++;) addEnd(other.get(i)) } else { size = other.size memmove((data) cast *void, (other.data) cast *void, size * #sizeof) } } } fun operator+(other: ref vec):vec { var newVec.construct(size+other.size):vec 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: ref T):vec { var newVec.copy_construct(this):vec newVec.addEnd(other) return newVec } fun operator+=(other: ref T):void { addEnd(other) } fun operator+=(other: ref vec):void { for (var i = 0; i < other.size; i++;) addEnd(other.get(i)) } fun clone(): vec { var newVec.construct(size): vec for (var i = 0; i < size; i++;) newVec.addEnd(data[i]) return newVec } fun reverse(): vec { var newVec.construct(size): vec 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): vec { if (start < 0) start += size + 1 if (end < 0) end += size + 1 var new.construct(end-start): vec 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) { print("Vector tried to access element: "); println(index); print("Max Index of vec: "); 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 vec. 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 vec):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 operator< (other: ref vec):bool { if (size < other.size) return true 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 true return false } fun set(index: int, dataIn: ref T): void { if (index < 0 || index >= size) return; data[index] = dataIn; } fun add_all(dataIn: ref vec): void { for (var i = 0; i < dataIn.size; i++;) addEnd(dataIn[i]); } fun add_all_unique(dataIn: ref vec): void { for (var i = 0; i < dataIn.size; i++;) add_unique(dataIn[i]); } // same darn trick fun add_unique(dataIn: ref U): void { if (!contains(dataIn)) addEnd(dataIn) } fun add(dataIn: ref T): void { addEnd(dataIn); } fun addEnd(dataIn: ref T): void { // if we resize, we need to be careful as the dataIn reference // may come from this itself if (size+1 > available) { var temp = dataIn resize((size+1)*2); maybe_copy_construct(&data[size], &temp); } else { maybe_copy_construct(&data[size], &dataIn); } size++; } fun add(index: int, dataIn: ref T) { if (size == 0) { add(dataIn) return } add(last()) for (var i = size-2; i > index; i--;) { data[i] = data[i-1] } data[index] = 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 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 for_each_reverse(func: fun(ref T):void):void { for (var i = size-1; i >= 0; i--;) func(data[i]) } fun for_each_reverse(func: fun(T):void):void { for (var i = size-1; i >= 0; 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(ref T):U):vec { var newVec.construct(size): vec for (var i = 0; i < size; i++;) newVec.addEnd(func(data[i])) return newVec } fun map(func: run(ref T):U):vec { var newVec.construct(size): vec for (var i = 0; i < size; i++;) newVec.addEnd(func(data[i])) return newVec } fun map(func: fun(T):U):vec { var newVec.construct(size): vec for (var i = 0; i < size; i++;) newVec.addEnd(func(data[i])) return newVec } fun map(func: run(T):U):vec { var newVec.construct(size): vec for (var i = 0; i < size; i++;) newVec.addEnd(func(data[i])) return newVec } fun flatten_map(func: fun(T):vec):vec { var newVec.construct(size): vec 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 associate(func: fun(T):pair): map { var to_ret = map() for (var i = 0; i < size; i++;) { var kv = func(data[i]) to_ret[kv.first] = kv.second } return to_ret } fun find_first_satisfying(func: fun(T):bool): T return filter(func)[0] fun filter(func: fun(T):bool):vec { var newVec.construct(): vec 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(ref T, ref T):bool): T { var maxIdx = 0 for (var i = 1; i < size; i++;) if (func(data[maxIdx], data[i])) maxIdx = i return data[maxIdx] } 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] } fun reduce(func: fun(T,U): U, initial: U): U { for (var i = 0; i < size; i++;) initial = func(data[i], initial) return initial } fun sorted(less_than: run(ref U, ref U): bool): vec { if size < 2 { return *this } else { var left = slice(0, size/2).sorted(less_than) var right = slice(size/2, -1).sorted(less_than) var to_ret.construct(size): vec var l = 0 var r = 0 while (l < left.size || r < right.size) { if l == left.size { to_ret.add(right[r++]) } else if r == right.size { to_ret.add(left[l++]) } else if less_than(left[l], right[r]) { to_ret.add(left[l++]) } else { to_ret.add(right[r++]) } } return to_ret } } fun pop(): T { var to_ret = data[size-1] remove(size-1) return to_ret } };