use crate::{
Edge,
node::{self, Node},
};
use std::collections::HashSet;
use steel::steel_vm::engine::Engine;
pub use typed::{Typed, TypedVisitor};
mod typed;
pub trait Visitor {
fn visit_pre(&mut self, _ctx: Ctx<'_, '_>, _node: &dyn Node) {}
fn visit_post(&mut self, _ctx: Ctx<'_, '_>, _node: &dyn Node) {}
}
#[derive(Clone, Copy)]
pub struct Ctx<'env, 'data> {
get_node: node::GetNode<'env>,
path: &'data [node::Id],
inputs: &'data [(node::Id, Edge)],
}
pub(crate) struct Register<'vm>(pub(crate) &'vm mut Engine);
pub(crate) struct RequiredAddrs<'a> {
pub addrs: &'a mut HashSet<gantz_ca::ContentAddr>,
}
impl<'env, 'data> Ctx<'env, 'data> {
pub fn new(
get_node: node::GetNode<'env>,
path: &'data [node::Id],
inputs: &'data [(node::Id, Edge)],
) -> Self {
Self {
get_node,
path,
inputs,
}
}
pub fn node(&self, ca: &gantz_ca::ContentAddr) -> Option<&'env dyn Node> {
(self.get_node)(ca)
}
pub fn path(&self) -> &'data [node::Id] {
self.path
}
pub fn id(&self) -> node::Id {
*self.path.last().expect("path cannot be empty")
}
pub fn inputs(&self) -> &'data [(node::Id, Edge)] {
self.inputs
}
pub fn get_node(&self) -> node::GetNode<'env> {
self.get_node
}
}
impl Visitor for Register<'_> {
fn visit_pre(&mut self, ctx: Ctx<'_, '_>, node: &dyn Node) {
let reg_ctx = node::RegCtx::new(ctx.get_node(), ctx.path(), self.0);
node.register(reg_ctx);
}
}
impl Visitor for RequiredAddrs<'_> {
fn visit_pre(&mut self, _ctx: Ctx<'_, '_>, node: &dyn Node) {
self.addrs.extend(node.required_addrs());
}
}