import vec:* import queue:* import map:* import set:* import util:* fun poset(): poset { var to_ret.construct(): poset return to_ret } obj poset (Object) { var open_deps: map> var close_deps: map> var opened: set var closed: set fun construct(): *poset { open_deps.construct() close_deps.construct() opened.construct() closed.construct() return this } fun copy_construct(old: *poset) { open_deps.copy_construct(&old->open_deps) close_deps.copy_construct(&old->close_deps) opened.copy_construct(&old->opened) closed.copy_construct(&old->closed) } fun operator=(other: ref poset) { destruct() copy_construct(&other) } fun destruct() { open_deps.destruct() close_deps.destruct() opened.destruct() closed.destruct() } fun size(): int { return open_deps.size() } fun add_open_dep(first: T, second: T) { add_job(first) add_job(second) open_deps[first].add(second) } fun add_close_dep(first: T, second: T) { add_job(first) add_job(second) close_deps[first].add(second) } fun add_job(vertex: T) { if (open_deps.contains_key(vertex)) return; open_deps.set(vertex, set()) close_deps.set(vertex, set()) } fun done(job: T): bool { return closed.contains(job) } fun run(f: fun(T): void) { opened = set() closed = set() while closed.size() != size() { var changed = false // intentionally not refs, as it can change out from under us open_deps.for_each(fun(v: T, ods: set) { if !closed.contains(v) && closed.contains(ods) { if !opened.contains(v) { changed = true f(v) if closed.contains(open_deps[v]) { opened.add(v) } } if closed.contains(open_deps[v]) && closed.contains(close_deps[v]) { changed = true closed.add(v) } } }) if (changed == false) { error("Poset has not changed!") } } } fun get_sorted(): vec { var to_ret = vec() run(fun(i: T) { to_ret.add(i) }) return to_ret } }