47 lines
1.0 KiB
Rust
47 lines
1.0 KiB
Rust
use preserves::value::Set;
|
|
|
|
use crate::gen::schema::ModulePath;
|
|
use crate::gen::schema::Ref;
|
|
|
|
pub struct WalkState<T> {
|
|
pub context: T,
|
|
pub module_path: ModulePath,
|
|
seen: Set<Ref>,
|
|
}
|
|
|
|
impl<T> WalkState<T> {
|
|
pub fn new(context: T, module_path: ModulePath) -> Self {
|
|
WalkState {
|
|
context,
|
|
module_path,
|
|
seen: Set::new(),
|
|
}
|
|
}
|
|
|
|
pub fn cycle_check<
|
|
E,
|
|
F: Fn(&T, &Ref) -> Option<E>,
|
|
R,
|
|
Ks: FnOnce(&mut Self, Option<E>) -> R,
|
|
Kf: FnOnce() -> R,
|
|
>(
|
|
&mut self,
|
|
r: &Ref,
|
|
step: F,
|
|
ks: Ks,
|
|
kf: Kf,
|
|
) -> R {
|
|
let r = r.qualify(&self.module_path);
|
|
if self.seen.contains(&r) {
|
|
kf()
|
|
} else {
|
|
self.seen.insert(r.clone());
|
|
let maybe_e = step(&self.context, &r);
|
|
let saved = std::mem::replace(&mut self.module_path, r.module);
|
|
let result = ks(self, maybe_e);
|
|
self.module_path = saved;
|
|
result
|
|
}
|
|
}
|
|
}
|