use enum_dispatch::enum_dispatch; use std::fmt; use crate::library; use crate::library::*; use crate::types::{Type, TypeSignature}; #[derive(Debug, Copy, Clone)] pub enum CompileError { MissingArguments, Codegen(fmt::Error), } impl From for CompileError { fn from(v: fmt::Error) -> Self { Self::Codegen(v) } } /// an instantiable Node, parametrized by its connected input types #[enum_dispatch] pub trait ConcreteNode { fn max_inputs(&self) -> usize; fn num_inputs(&self, _connected: &[Option]) -> usize { self.max_inputs() } // set of possible input type combinations given current connections fn signatures_matching(&self, connected: &[Option]) -> Vec; fn signature(&self, connected: &[Option]) -> TypeSignature; fn compile( &self, signature: TypeSignature, inputs: Vec>, outputs: Vec, f: &mut dyn fmt::Write, ) -> Result<(), CompileError>; fn show_body(&mut self, ui: &mut egui::Ui) -> egui::Response { ui.response() } } #[enum_dispatch(ConcreteNode)] #[derive(Clone, PartialEq, serde::Serialize, serde::Deserialize)] pub enum AnyNode { Constant(library::AnyConstant), Conversion(library::Conversion), Input(library::Input), Arithmetic(library::BinArithmetic), Builtin(library::BuiltinFunction), Output(library::Output), } impl NodeIndex for AnyNode { const TITLE: &'static str = ""; fn all() -> impl Iterator { (library::AnyConstant::all().map(AnyNode::from)) .chain(library::Conversion::all().map(AnyNode::from)) .chain(library::Input::all().map(AnyNode::from)) .chain(library::Output::all().map(AnyNode::from)) .chain(library::BuiltinFunction::all().map(AnyNode::from)) } fn pick_node(ui: &mut egui::Ui) -> Option { ui.label("Add node"); None.or(library::AnyConstant::pick_node(ui).map(AnyNode::from)) .or(library::Input::pick_node(ui).map(AnyNode::from)) .or(library::Output::pick_node(ui).map(AnyNode::from)) .or({ ui.separator(); None }) .or(library::BinArithmetic::pick_node(ui).map(AnyNode::from)) .or(library::Conversion::pick_node(ui).map(AnyNode::from)) .or(library::BuiltinFunction::pick_node(ui).map(AnyNode::from)) } } impl fmt::Display for AnyNode { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::Constant(x) => fmt::Display::fmt(x, f), Self::Conversion(x) => fmt::Display::fmt(x, f), Self::Input(x) => fmt::Display::fmt(x, f), Self::Arithmetic(x) => fmt::Display::fmt(x, f), Self::Builtin(x) => fmt::Display::fmt(x, f), Self::Output(x) => fmt::Display::fmt(x, f), } } }