use crate::*; /// Namespace. Currently linearly searched. pub struct DslNs<'t, T: 't>(pub &'t [(&'t str, T)]); /// Namespace where keys are symbols. pub trait DslSymNs<'t, T: 't>: 't { const SYMS: DslNs<'t, fn (&'t Self)->T>; fn from_sym (&'t self, dsl: D) -> Usually { if let Some(dsl) = dsl.sym()? { for (sym, get) in Self::SYMS.0 { if dsl == *sym { return Ok(get(self)) } } } return Err(format!("not found: sym: {dsl:?}").into()) } } #[macro_export] macro_rules! dsl_sym ( (|$state:ident:$State:ty| -> $type:ty {$($lit:literal => $exp:expr),* $(,)?})=>{ impl<'t> DslSymNs<'t, $type> for $State { const SYMS: DslNs<'t, fn (&'t $State)->$type> = DslNs(&[$(($lit, |$state: &$State|$exp)),*]); } }); pub trait DslExpNs<'t, T: 't>: 't { const EXPS: DslNs<'t, fn (&'t Self, &str)->T>; } #[macro_export] macro_rules! dsl_exp ( (|$state:ident:$State:ty|->$type:ty { $( [$key:literal $(/ $sub:ident: $Sub:ty)? $(, $arg:ident $(?)? :$argtype:ty)*] => $body:expr ),* $(,)? }) => { impl<'t> DslExpNs<'t, $type> for $State { const EXPS: DslNs<'t, fn (&'t $State, &str)->$type> = DslNs(&[]); } }); pub type DslCb = fn (&App) -> Box>; impl<'t, D: Dsl> std::ops::Index for DslNs<'t, DslCb> { type Output = DslCb; fn index (&self, index: D) -> &Self::Output { if let Ok(Some(symbol)) = index.src() { for (key, value) in self.0.iter() { if symbol == *key { return value } } } &(view_nil as DslCb) } } pub fn view_nil (_: &App) -> Box> { Box::new(Fill::xy("ยท")) }