use crate::*; use std::marker::PhantomData; use std::fmt::Debug; /// List of input layers with optional conditional filters. #[derive(Default, Debug)] pub struct InputLayers(Vec>); #[derive(Default, Debug)] pub struct InputLayer{ __: PhantomData, condition: Option, binding: Ast, } impl InputLayers { pub fn new (layer: Ast) -> Self { Self(vec![]).layer(layer) } pub fn layer (mut self, layer: Ast) -> Self { self.add_layer(layer); self } pub fn layer_if (mut self, condition: Ast, layer: Ast) -> Self { self.add_layer_if(Some(condition), layer); self } pub fn add_layer (&mut self, layer: Ast) -> &mut Self { self.add_layer_if(None, layer.into()); self } pub fn add_layer_if (&mut self, condition: Option, binding: Ast) -> &mut Self { self.0.push(InputLayer { condition, binding, __: Default::default() }); self } } impl + Eval, C: Command, I: Debug + Eval> Eval<(S, I), C> for InputLayers { fn try_eval (&self, (state, input): (S, I)) -> Perhaps { for InputLayer { condition, binding, .. } in self.0.iter() { let mut matches = true; if let Some(condition) = condition { matches = state.eval(condition.clone(), ||"input: no condition")?; } if matches { if let Ast::Exp(e) = binding { if let Some(ast) = e.peek() { if input.eval(ast.clone(), ||"InputLayers: input.eval(binding) failed")? && let Some(command) = state.try_eval(ast)? { return Ok(Some(command)) } } else { unreachable!("InputLayer") } } else { panic!("InputLayer: expected expression, got: {input:?}") } } } Ok(None) } }