Files
kraken/stdlib/poset.krak

97 lines
2.5 KiB
Plaintext

import vec:*
import queue:*
import map:*
import set:*
import util:*
fun poset<T>(): poset<T> {
var to_ret.construct(): poset<T>
return to_ret
}
obj poset<T> (Object) {
var open_deps: map<T, set<T>>
var close_deps: map<T, set<T>>
var done: set<T>
fun construct(): *poset<T> {
open_deps.construct()
close_deps.construct()
done.construct()
return this
}
fun copy_construct(old: *poset<T>) {
open_deps.copy_construct(&old->open_deps)
close_deps.copy_construct(&old->close_deps)
done.copy_construct(&old->done)
}
fun operator=(other: ref poset<T>) {
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<T>) {
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<T>())
close_deps.set(vertex, set<T>())
}
fun done(job: T): bool {
return done.contains(job)
}
fun run(f: fun(T): void) {
done = set<T>()
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<T>) {
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<T> {
var to_ret = vec<T>()
run(fun(i: T) {
to_ret.add(i)
})
return to_ret
}
}