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 done: set fun construct(): *poset { open_deps.construct() close_deps.construct() done.construct() return this } fun copy_construct(old: *poset) { open_deps.copy_construct(&old->open_deps) close_deps.copy_construct(&old->close_deps) done.copy_construct(&old->done) } fun operator=(other: ref poset) { destruct() copy_construct(&other) } fun destruct() { open_deps.destruct() close_deps.destruct() done.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) // also add all of the closed deps of what we depend on close_deps[second].for_each(fun(cd: T) { add_open_dep(first, cd) }) } fun add_close_dep(first: T, second: T) { add_job(first) add_job(second) close_deps[first].add(second) // patch this one in to everything that currently depends on first open_deps.for_each(fun(v: T, ods: set) { if ods.contains(first) { add_open_dep(v, 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 done.contains(job) } fun run(f: fun(T): void) { done = set() while done.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 !done.contains(v) && done.contains(ods) { changed = true f(v) if done.contains(open_deps[v]) { done.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 } }