#[doc(inline)]
pub use crate::visit::{self, Visitor};
pub use apply::Apply;
pub use branch::{Branch, BranchNewError};
#[doc(inline)]
pub use conns::Conns;
pub use delay::Delay;
pub use expr::{Expr, ExprNewError};
pub use fn_::{Fn, FnNodeTag};
use gantz_ca::CaHash;
pub use id::{IDENTITY_NAME, Identity};
pub use pull::{Pull, WithPullEval};
pub use push::{Push, WithPushEval};
pub use ref_::{AsRefNode, Ref};
use serde::{Deserialize, Serialize};
pub use state::{NodeState, State, WithStateType};
use steel::{parser::ast::ExprKind, steel_vm::engine::Engine};
pub mod apply;
pub mod branch;
mod conns;
pub mod delay;
pub mod expr;
pub mod fn_;
pub mod graph;
pub mod id;
pub mod pull;
pub mod push;
pub mod ref_;
pub mod rust;
pub mod state;
pub trait Node: std::any::Any {
fn n_inputs(&self, _ctx: MetaCtx) -> usize {
0
}
fn n_outputs(&self, _ctx: MetaCtx) -> usize {
0
}
fn branches(&self, _ctx: MetaCtx) -> Vec<EvalConf> {
vec![]
}
fn expr(&self, ctx: ExprCtx<'_, '_>) -> ExprResult;
fn push_eval(&self, _ctx: MetaCtx) -> Vec<EvalConf> {
vec![]
}
fn pull_eval(&self, _ctx: MetaCtx) -> Vec<EvalConf> {
vec![]
}
fn inlet(&self, _ctx: MetaCtx) -> bool {
false
}
fn outlet(&self, _ctx: MetaCtx) -> bool {
false
}
fn delay(&self, _ctx: MetaCtx) -> bool {
false
}
fn stateful(&self, _ctx: MetaCtx) -> bool {
false
}
fn register(&self, _ctx: RegCtx<'_, '_>) {}
fn required_addrs(&self) -> Vec<gantz_ca::ContentAddr> {
vec![]
}
fn visit(&self, _ctx: visit::Ctx<'_, '_>, _visitor: &mut dyn Visitor) {}
}
#[derive(
Clone, Debug, Default, Deserialize, Serialize, CaHash, Eq, Hash, Ord, PartialEq, PartialOrd,
)]
#[cahash("gantz.eval-conf")]
pub enum EvalConf {
#[default]
All,
Set(Conns),
}
pub type Id = usize;
pub type GetNode<'a> = &'a dyn std::ops::Fn(&gantz_ca::ContentAddr) -> Option<&'a dyn Node>;
#[derive(Clone, Copy)]
pub struct MetaCtx<'a> {
get_node: GetNode<'a>,
}
pub struct RegCtx<'env, 'data> {
get_node: GetNode<'env>,
path: &'data [Id],
vm: &'data mut Engine,
}
pub struct ExprCtx<'env, 'data> {
get_node: GetNode<'env>,
path: &'data [Id],
inputs: &'data [Option<String>],
outputs: &'data Conns,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct EvalFn;
#[derive(
Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Deserialize, Serialize, CaHash,
)]
pub struct Input(pub u16);
#[derive(
Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Deserialize, Serialize, CaHash,
)]
pub struct Output(pub u16);
#[derive(Clone, Debug, thiserror::Error)]
#[error("{0}")]
pub struct ExprError(Box<str>);
pub type ExprResult = Result<ExprKind, ExprError>;
impl<'a> MetaCtx<'a> {
pub fn new(get_node: GetNode<'a>) -> Self {
Self { get_node }
}
pub fn node(&self, ca: &gantz_ca::ContentAddr) -> Option<&'a dyn Node> {
(self.get_node)(ca)
}
pub fn get_node(&self) -> GetNode<'a> {
self.get_node
}
}
impl<'env, 'data> RegCtx<'env, 'data> {
pub fn new(get_node: GetNode<'env>, path: &'data [Id], vm: &'data mut Engine) -> Self {
Self { get_node, path, vm }
}
pub fn node(&self, ca: &gantz_ca::ContentAddr) -> Option<&'env dyn Node> {
(self.get_node)(ca)
}
pub fn path(&self) -> &'data [Id] {
self.path
}
pub fn get_node(&self) -> GetNode<'env> {
self.get_node
}
pub fn vm(&mut self) -> &mut Engine {
self.vm
}
pub fn into_parts(self) -> (GetNode<'env>, &'data [Id], &'data mut Engine) {
(self.get_node, self.path, self.vm)
}
}
impl<'env, 'data> ExprCtx<'env, 'data> {
pub fn new(
get_node: GetNode<'env>,
path: &'data [Id],
inputs: &'data [Option<String>],
outputs: &'data Conns,
) -> Self {
Self {
get_node,
path,
inputs,
outputs,
}
}
pub fn node(&self, ca: &gantz_ca::ContentAddr) -> Option<&'env dyn Node> {
(self.get_node)(ca)
}
pub fn path(&self) -> &'data [Id] {
self.path
}
pub fn inputs(&self) -> &'data [Option<String>] {
self.inputs
}
pub fn outputs(&self) -> &'data Conns {
self.outputs
}
pub fn get_node(&self) -> GetNode<'env> {
self.get_node
}
pub fn args(&self) -> &str {
crate::ARGS
}
}
macro_rules! impl_node_for_ptr {
($($Ty:ident)::*) => {
impl<T> Node for $($Ty)::*<T>
where
T: ?Sized + Node,
{
fn n_inputs(&self, ctx: MetaCtx) -> usize {
(**self).n_inputs(ctx)
}
fn n_outputs(&self, ctx: MetaCtx) -> usize {
(**self).n_outputs(ctx)
}
fn branches(&self, ctx: MetaCtx) -> Vec<EvalConf> {
(**self).branches(ctx)
}
fn expr(&self, ctx: ExprCtx<'_, '_>) -> ExprResult {
(**self).expr(ctx)
}
fn push_eval(&self, ctx: MetaCtx) -> Vec<EvalConf> {
(**self).push_eval(ctx)
}
fn pull_eval(&self, ctx: MetaCtx) -> Vec<EvalConf> {
(**self).pull_eval(ctx)
}
fn inlet(&self, ctx: MetaCtx) -> bool {
(**self).inlet(ctx)
}
fn outlet(&self, ctx: MetaCtx) -> bool {
(**self).outlet(ctx)
}
fn delay(&self, ctx: MetaCtx) -> bool {
(**self).delay(ctx)
}
fn stateful(&self, ctx: MetaCtx) -> bool {
(**self).stateful(ctx)
}
fn register(&self, ctx: RegCtx<'_, '_>) {
(**self).register(ctx)
}
fn required_addrs(&self) -> Vec<gantz_ca::ContentAddr> {
(**self).required_addrs()
}
fn visit(&self, ctx: visit::Ctx<'_, '_>, visitor: &mut dyn Visitor) {
(**self).visit(ctx, visitor)
}
}
};
}
impl_node_for_ptr!(Box);
impl_node_for_ptr!(std::rc::Rc);
impl_node_for_ptr!(std::sync::Arc);
impl<'env, 'data> Clone for ExprCtx<'env, 'data> {
fn clone(&self) -> Self {
Self {
get_node: self.get_node,
path: self.path,
inputs: self.inputs,
outputs: self.outputs,
}
}
}
impl From<u16> for Input {
fn from(u: u16) -> Self {
Input(u)
}
}
impl From<u16> for Output {
fn from(u: u16) -> Self {
Output(u)
}
}
impl ExprError {
pub fn custom(msg: impl std::fmt::Display) -> Self {
Self(msg.to_string().into_boxed_str())
}
}
pub fn expr(expr: impl Into<String>) -> Result<Expr, ExprNewError> {
Expr::new(expr)
}
pub fn branch(src: impl Into<String>, branches: Vec<Conns>) -> Result<Branch, BranchNewError> {
Branch::new(src, branches)
}
pub fn parse_expr(src: &str) -> ExprResult {
let exprs = Engine::emit_ast(src).map_err(|e| ExprError::custom(e))?;
exprs
.into_iter()
.next()
.ok_or_else(|| ExprError::custom("empty expression"))
}
pub fn visit(ctx: visit::Ctx<'_, '_>, node: &dyn Node, visitor: &mut dyn Visitor) {
visitor.visit_pre(ctx, node);
node.visit(ctx, visitor);
visitor.visit_post(ctx, node);
}
pub fn visit_typed<V: visit::TypedVisitor<N>, N: Node>(
ctx: visit::Ctx<'_, '_>,
node: &N,
visitor: &mut V,
) {
visit(ctx, node, &mut visit::Typed::<&mut V, N>::new(visitor));
}
pub fn register(ctx: visit::Ctx<'_, '_>, node: &dyn Node, vm: &mut Engine) {
visit(ctx, node, &mut visit::Register(vm));
}
pub fn builtins<N>() -> Vec<crate::builtin::Builtin<N>>
where
N: crate::builtin::FromNode<Apply>
+ crate::builtin::FromNode<Branch>
+ crate::builtin::FromNode<Delay>
+ crate::builtin::FromNode<Expr>
+ crate::builtin::FromNode<Identity>
+ crate::builtin::FromNode<graph::Inlet>
+ crate::builtin::FromNode<graph::Outlet>,
{
use crate::builtin::Builtin;
vec![
Builtin::new("apply", || N::from_node(Apply::default())),
Builtin::new("branch", || N::from_node(Branch::default())),
Builtin::new("delay", || N::from_node(Delay::default())),
Builtin::new("expr", || N::from_node(Expr::new("()").unwrap())),
Builtin::new(IDENTITY_NAME, || N::from_node(Identity)),
Builtin::new("inlet", || N::from_node(graph::Inlet::default())),
Builtin::new("outlet", || N::from_node(graph::Outlet::default())),
]
}