277 lines
8.1 KiB
Plaintext
277 lines
8.1 KiB
Plaintext
import mem
|
|
import io
|
|
import os
|
|
import str
|
|
import set
|
|
import map
|
|
import vec
|
|
import serialize
|
|
|
|
|
|
// maybe my favorite function
|
|
fun do_nothing() {}
|
|
|
|
fun is_object<T>(): bool return false
|
|
fun is_object<T(Object)>(): bool return true
|
|
|
|
fun error(message: *char) error(str::str(message));
|
|
fun error(message: str::str) {
|
|
io::printlnerr("****ERROR****")
|
|
io::printlnerr(message)
|
|
os::exit(-1)
|
|
}
|
|
fun assert(works: bool, message: *char) {
|
|
if (!works)
|
|
error(message)
|
|
}
|
|
fun assert(works: bool, message: str::str) {
|
|
if (!works)
|
|
error(message)
|
|
}
|
|
|
|
fun deref_equality<T>(a: *T, b: *T): bool {
|
|
if ( (a && b && !(*a == *b)) || (a && !b) || (!a && b) )
|
|
return false
|
|
return true
|
|
}
|
|
|
|
fun max<T>(a: T, b: T): T {
|
|
if (a > b)
|
|
return a;
|
|
return b;
|
|
}
|
|
|
|
fun min<T>(a: T, b: T): T {
|
|
if (a > b)
|
|
return b;
|
|
return a;
|
|
}
|
|
|
|
fun hash<T(Hashable)>(item: T): ulong return item.hash()
|
|
fun hash<T>(item: *T): ulong return (item) cast ulong
|
|
fun hash(item: char): ulong return (item) cast ulong
|
|
fun hash(item: uchar): ulong return (item) cast ulong
|
|
fun hash(item: short): ulong return (item) cast ulong
|
|
fun hash(item: ushort): ulong return (item) cast ulong
|
|
fun hash(item: int): ulong return (item) cast ulong
|
|
fun hash(item: uint): ulong return (item) cast ulong
|
|
fun hash(item: long): ulong return (item) cast ulong
|
|
fun hash(item: ulong): ulong return (item) cast ulong
|
|
|
|
// default hash
|
|
fun hash<T>(item: T): ulong {
|
|
io::println("using empty hash - please do not do!")
|
|
return (0) cast ulong
|
|
}
|
|
|
|
fun make_pair<T,U>(first: T, second: U): pair<T,U> {
|
|
var it.construct(first, second): pair<T,U>
|
|
return it
|
|
}
|
|
|
|
// little ugly, but it works
|
|
fun unpack<T,U>(first: ref T, second: ref U): unpack_dummy_pair<T,U> {
|
|
var toRet: unpack_dummy_pair<T,U>
|
|
toRet.first = &first
|
|
toRet.second = &second
|
|
return toRet
|
|
}
|
|
obj unpack_dummy_pair<T,U> {
|
|
var first: *T
|
|
var second: *U
|
|
fun operator=(p: ref pair<T,U>) {
|
|
*first = p.first
|
|
*second = p.second
|
|
}
|
|
}
|
|
|
|
obj pair<T,U> (Object, Serializable, Hashable) {
|
|
var first: T
|
|
var second: U
|
|
|
|
fun construct(firstIn: ref T, secondIn: ref U): *pair<T,U> {
|
|
mem::maybe_copy_construct(&first, &firstIn)
|
|
mem::maybe_copy_construct(&second, &secondIn)
|
|
return this
|
|
}
|
|
|
|
fun construct(): *pair<T,U> {
|
|
mem::maybe_construct(&first)
|
|
mem::maybe_construct(&second)
|
|
return this
|
|
}
|
|
|
|
fun copy_construct(old: *pair<T,U>):void {
|
|
mem::maybe_copy_construct(&first, &old->first)
|
|
mem::maybe_copy_construct(&second, &old->second)
|
|
}
|
|
|
|
fun destruct():void {
|
|
mem::maybe_destruct(&first)
|
|
mem::maybe_destruct(&second)
|
|
}
|
|
fun serialize(): vec::vec<char> {
|
|
return serialize::serialize(first) + serialize::serialize(second)
|
|
}
|
|
fun unserialize(it: ref vec::vec<char>, pos: int): int {
|
|
// can't use unpack :( (b/c we can't make an already constructed empty one)
|
|
var first_pair = serialize::unserialize<T>(it, pos)
|
|
var second_pair = serialize::unserialize<U>(it, first_pair.second)
|
|
mem::maybe_copy_construct(&first, &first_pair.first)
|
|
mem::maybe_copy_construct(&second, &second_pair.first)
|
|
return second_pair.second
|
|
}
|
|
|
|
fun hash():ulong return hash(first) ^ hash(second)
|
|
|
|
// the old unnecessary template to prevent generation
|
|
// if not used trick (in this case, changing out U with V)
|
|
fun operator==<V>(other: ref pair<T,V>): bool {
|
|
return first == other.first && second == other.second
|
|
}
|
|
}
|
|
|
|
fun make_triple<T,U,V>(first: T, second: U, third: V): triple<T,U,V> {
|
|
var it.construct(first, second, third): triple<T,U,V>
|
|
return it
|
|
}
|
|
|
|
// little ugly, but it works
|
|
fun unpack<T,U,V>(first: ref T, second: ref U, third: ref V): unpack_dummy_triple<T,U,V> {
|
|
var toRet: unpack_dummy_triple<T,U>
|
|
toRet.first = &first
|
|
toRet.second = &second
|
|
toRet.third = &third
|
|
return toRet
|
|
}
|
|
obj unpack_dummy_triple<T,U,V> {
|
|
var first: *T
|
|
var second: *U
|
|
var third: *V
|
|
fun operator=(p: ref triple<T,U,V>) {
|
|
*first = p.first
|
|
*second = p.second
|
|
*third = p.third
|
|
}
|
|
}
|
|
|
|
obj triple<T,U,V> (Object, Serializable, Hashable) {
|
|
var first: T
|
|
var second: U
|
|
var third: V
|
|
|
|
fun construct(firstIn: ref T, secondIn: ref U, thirdIn: ref V): *triple<T,U,V> {
|
|
mem::maybe_copy_construct(&first, &firstIn)
|
|
mem::maybe_copy_construct(&second, &secondIn)
|
|
mem::maybe_copy_construct(&third, &thirdIn)
|
|
return this
|
|
}
|
|
|
|
fun construct(): *triple<T,U,V> {
|
|
mem::maybe_construct(&first)
|
|
mem::maybe_construct(&second)
|
|
mem::maybe_construct(&third)
|
|
return this
|
|
}
|
|
|
|
fun copy_construct(old: *triple<T,U,V>):void {
|
|
mem::maybe_copy_construct(&first, &old->first)
|
|
mem::maybe_copy_construct(&second, &old->second)
|
|
mem::maybe_copy_construct(&third, &old->third)
|
|
}
|
|
|
|
fun destruct():void {
|
|
mem::maybe_destruct(&first)
|
|
mem::maybe_destruct(&second)
|
|
mem::maybe_destruct(&third)
|
|
}
|
|
fun serialize(): vec::vec<char> {
|
|
return serialize::serialize(first) + serialize::serialize(second) + serialize::serialize(third)
|
|
}
|
|
fun unserialize(it: ref vec::vec<char>, pos: int): int {
|
|
// can't use unpack :( (b/c we can't make an already constructed empty one)
|
|
var first_pair = serialize::unserialize<T>(it, pos)
|
|
var second_pair = serialize::unserialize<U>(it, first_pair.second)
|
|
var third_pair = serialize::unserialize<V>(it, second_pair.second)
|
|
mem::maybe_copy_construct(&first, &first_pair.first)
|
|
mem::maybe_copy_construct(&second, &second_pair.first)
|
|
mem::maybe_copy_construct(&third, &third_pair.first)
|
|
return third_pair.second
|
|
}
|
|
|
|
fun hash():ulong return hash(first) ^ hash(second) ^ hash(third)
|
|
|
|
// the old unnecessary template to prevent generation
|
|
// if not used trick (in this case, changing out V with X)
|
|
fun operator==<X>(other: ref triple<T,U,X>): bool {
|
|
return first == other.first && second == other.second && third == other.third
|
|
}
|
|
}
|
|
|
|
fun range(end:int): range {
|
|
var toRet.construct(0, end, 1): range
|
|
return toRet
|
|
}
|
|
|
|
fun range(begin: int, end:int): range {
|
|
var toRet.construct(begin, end, 1): range
|
|
return toRet
|
|
}
|
|
fun range(begin: int, end:int, step: int): range {
|
|
var toRet.construct(begin, end, step): range
|
|
return toRet
|
|
}
|
|
|
|
obj range {
|
|
var begin: int
|
|
var end: int
|
|
var step: int
|
|
fun construct(beginIn: int, endIn: int, stepIn: int) : *range {
|
|
begin = beginIn
|
|
end = endIn
|
|
step = stepIn
|
|
}
|
|
fun for_each(func: fun(int):void):void {
|
|
for (var i = begin; i < end; i+= step;)
|
|
func(i)
|
|
}
|
|
fun map<T>(func: fun(int): T): vec::vec<T> {
|
|
var ret.construct( (end-begin)/step + 1 ) : vec::vec<T>
|
|
for (var i = begin; i < end; i+= step;)
|
|
ret.addEnd(func(i))
|
|
return ret
|
|
}
|
|
fun any_true(func: fun(int):bool):bool {
|
|
for (var i = begin; i < end; i+= step;)
|
|
if (func(i))
|
|
return true
|
|
return false
|
|
}
|
|
}
|
|
|
|
// a function that allows the safe deletion of recursive and complicated data structures
|
|
fun safe_recursive_delete<T>(first: *T, addingFunc: fun(*T): set::set<*T>) {
|
|
var toDelete = set::set<*T>()
|
|
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) mem::delete(it); )
|
|
}
|
|
|
|
// a function that allows the safe cloning of recursive and complicated data structures
|
|
// cloneing func is the func that does the cloning, it takes in a recursive clone function and
|
|
// a register clone function
|
|
fun safe_recursive_clone<T>(first: *T, cloningFunc: fun(*T, fun(*T):*T, fun(*T):void): void): *T {
|
|
var rec_map = map::map<*T,*T>()
|
|
// can't do type infrence if you need the type inside the expression...
|
|
var rec_it: fun(*T):*T = fun(it: *T): *T {
|
|
if (!rec_map.contains_key(it))
|
|
cloningFunc(it, rec_it, fun(cloned: *T) { rec_map[it] = cloned; })
|
|
return rec_map[it]
|
|
}
|
|
return rec_it(first)
|
|
}
|
|
|