diff --git a/dsl/src/dsl_ast.rs b/dsl/src/dsl_ast.rs index 15c4374..7922d26 100644 --- a/dsl/src/dsl_ast.rs +++ b/dsl/src/dsl_ast.rs @@ -2,40 +2,40 @@ use crate::*; use std::sync::Arc; use std::fmt::{Debug, Display, Formatter}; +/// Emits tokens. +pub trait Ast: Debug { + fn peek (&self) -> Option; + fn next (&mut self) -> Option; + fn rest (self) -> Option>; +} + +/// A [Cst] can be used as an [Ast]. +impl<'source: 'static> Ast for Cst<'source> { + fn peek (&self) -> Option { + Cst::peek(self).map(|token|token.value.into()) + } + fn next (&mut self) -> Option { + Iterator::next(self).map(|token|token.value.into()) + } + fn rest (self) -> Option> { + self.peek().is_some().then(||Box::new(self) as Box) + } +} + #[derive(Clone, Default, Debug)] -pub enum Ast { +pub enum AstValue { #[default] Nil, Err(DslError), Num(usize), Sym(Arc), Key(Arc), Str(Arc), - Exp(Arc>), + Exp(Arc>), } -/// Emits tokens. -pub trait AstIter: Debug { - fn peek (&self) -> Option; - fn next (&mut self) -> Option; - fn rest (self) -> Option>; -} - -/// A [Cst] can be used as an [Ast]. -impl<'source: 'static> AstIter for Cst<'source> { - fn peek (&self) -> Option { - Cst::peek(self).map(|token|token.value.into()) - } - fn next (&mut self) -> Option { - Iterator::next(self).map(|token|token.value.into()) - } - fn rest (self) -> Option> { - self.peek().is_some().then(||Box::new(self) as Box) - } -} - -impl std::fmt::Display for Ast { +impl std::fmt::Display for AstValue { fn fmt (&self, out: &mut Formatter) -> Result<(), std::fmt::Error> { - use Ast::*; + use AstValue::*; write!(out, "{}", match self { Nil => String::new(), Err(e) => format!("[error: {e}]"), @@ -48,7 +48,7 @@ impl std::fmt::Display for Ast { } } -impl<'source: 'static> From> for Ast { +impl<'source: 'static> From> for AstValue { fn from (other: CstValue<'source>) -> Self { use CstValue::*; match other { @@ -63,8 +63,8 @@ impl<'source: 'static> From> for Ast { } } -impl<'source: 'static> Into> for Cst<'source> { - fn into (self) -> Box { +impl<'source: 'static> Into> for Cst<'source> { + fn into (self) -> Box { Box::new(self) } } diff --git a/dsl/src/dsl_domain.rs b/dsl/src/dsl_domain.rs index 88af556..283d79a 100644 --- a/dsl/src/dsl_domain.rs +++ b/dsl/src/dsl_domain.rs @@ -1,37 +1,25 @@ use crate::*; pub trait Eval { - fn try_eval (&self, input: Input) -> Perhaps; - fn eval >, F: Fn()->E> ( - &self, input: Input, error: F - ) -> Usually { - if let Some(value) = self.try_eval(input)? { - Ok(value) - } else { - Result::Err(format!("Eval: {}", error().into()).into()) - } - } + fn eval (&self, input: Input) -> Perhaps; } /// May construct [Self] from token stream. -pub trait Dsl: Sized { - fn try_provide (state: State, source: Ast) -> Perhaps; +pub trait Dsl: Sized { + type State; + fn try_provide (state: Self::State, source: impl Ast) -> Perhaps; fn provide >, F: Fn()->E> ( - state: State, source: Ast, error: F + state: Self::State, source: impl Ast, error: F ) -> Usually { - let next = source.clone(); + let next = source.peek().clone(); if let Some(value) = Self::try_provide(state, source)? { Ok(value) } else { - Result::Err(format!("Dsl: {}: {next:?}", error().into()).into()) + Result::Err(format!("dsl: {}: {next:?}", error().into()).into()) } } } -impl, S> Eval for S { - fn try_eval (&self, input: Ast) -> Perhaps { todo!() } -} - //pub trait Give<'state, 'source, Type> { ///// Implement this to be able to [Give] [Type] from the [Cst]. ///// Advance the stream if returning `Ok>`. diff --git a/input/src/input_dsl.rs b/input/src/input_dsl.rs index c6d26e1..3610f36 100644 --- a/input/src/input_dsl.rs +++ b/input/src/input_dsl.rs @@ -1,53 +1,67 @@ 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, + condition: Option>, + bindings: Box, } 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() }); + pub fn new (layer: Box) -> Self + { Self(vec![]).layer(layer) } + pub fn layer (mut self, layer: Box) -> Self + { self.add_layer(layer); self } + pub fn layer_if (mut self, condition: Box, layer: Box) -> Self + { self.add_layer_if(Some(condition), layer); self } + pub fn add_layer (&mut self, layer: Box) -> &mut Self + { self.add_layer_if(None, layer.into()); self } + pub fn add_layer_if ( + &mut self, + condition: Option>, + bindings: Box + ) -> &mut Self { + self.0.push(InputLayer { condition, bindings, __: 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:?}") +impl, I: Input, O: Command> Eval for InputLayers { + fn eval (&self, input: I) -> Perhaps { + for layer in self.0.iter() { + if let Some(command) = Ok(if let Some(condition) = layer.condition.as_ref() { + if self.matches(condition)? { + self.state().eval(*self)? + } else { + None } + } else { + self.state().eval(*self)? + })? { + return Ok(Some(command)) } } + } +} +/// [Input] state that can be matched against a [CstValue]. +pub trait InputState: Input { + fn state (&self) -> &S; + fn matches (&self, condition: &Box) -> Usually; +} +impl, I: InputState, O: Command> Eval +for InputLayer { + fn eval (&self, input: I) -> Perhaps { + if let Some(AstToken::Exp(exp)) = iter.peek() { + let mut e = exp.clone(); + if let Some(AstToken::Sym(binding)) = e.next() + && input.matches_dsl(binding) + && let Some(command) = Dsl::from_dsl(input.state(), e)? { + return Ok(Some(command)) + } else { + unreachable!("InputLayer: expected symbol, got: {e:?}") + } + } else { + panic!("InputLayer: expected expression, got: {self:?}") + } Ok(None) } } diff --git a/output/src/ops_dsl.rs b/output/src/ops_dsl.rs index e86a634..d34cc34 100644 --- a/output/src/ops_dsl.rs +++ b/output/src/ops_dsl.rs @@ -1,130 +1,150 @@ use crate::*; -impl Dsl for When where S: Eval + Eval { - fn try_provide (state: S, source: Ast) -> Perhaps { - if let Ast::Exp(source) = source { - if let Some(Ast::Key(id)) = source.next() && *id == *"when" { - return Ok(Some(Self( - state.eval(source.next().unwrap(), ||"when: expected condition")?, - state.eval(source.next().unwrap(), ||"when: expected content")?, - ))) - } - } - Ok(None) +impl Eval> for S where + S: Eval + Eval +{ + fn eval (&self, source: I) -> Perhaps { + Ok(match source.peek() { + Some(Value::Key("when")) => Some(Self( + self.provide(source, ||"when: expected condition")?, + self.provide(source, ||"when: expected content")?, + )), + _ => None + }) } } -impl Dsl for Either where S: Eval + Eval + Eval { - fn try_provide (state: S, mut source: Ast) -> Perhaps { - if let Ast::Exp(mut source) = source { - if let Some(Ast::Key(id)) = source.next() && *id == *"either" { - return Ok(Some(Self( - state.eval(source.next().unwrap(), ||"either: expected condition")?, - state.eval(source.next().unwrap(), ||"either: expected content 1")?, - state.eval(source.next().unwrap(), ||"either: expected content 2")?, - ))) - } - } - Ok(None) +impl Eval> for S where + S: Eval + Eval + Eval +{ + fn eval (&self, source: I) -> Perhaps { + Ok(match source.peek() { + Some(Value::Key("either")) => Some(Self( + self.provide(source, ||"either: expected condition")?, + self.provide(source, ||"either: expected content 1")?, + self.provide(source, ||"either: expected content 2")? + )), + _ => None + }) } } -impl Dsl for Bsp -where S: Eval, A> + Eval, B> { - fn try_provide (state: S, source: Ast) -> Perhaps { - Ok(Some(if let Ast::Exp(source) = source { - match source.next() { - Some(Value::Key("bsp/n")) => { - let a: A = state.eval(source.next(), ||"bsp/n: expected content 1")?; - let b: B = state.eval(source.next(), ||"bsp/n: expected content 2")?; +impl Eval> for S where + S: Eval + Eval +{ + fn eval (&self, source: I) -> Perhaps { + Ok(if let Some(Value::Key(key)) = source.peek() { + Some(match key { + "bsp/n" => { + let _ = source.next(); + let a: A = self.provide(source, ||"bsp/n: expected content 1")?; + let b: B = self.provide(source, ||"bsp/n: expected content 2")?; Self::n(a, b) }, - Some(Value::Key("bsp/s")) => { - let a: A = state.eval(source.next(), ||"bsp/s: expected content 1")?; - let b: B = state.eval(source.next(), ||"bsp/s: expected content 2")?; + "bsp/s" => { + let _ = source.next(); + let a: A = self.provide(source, ||"bsp/s: expected content 1")?; + let b: B = self.provide(source, ||"bsp/s: expected content 2")?; Self::s(a, b) }, - Some(Value::Key("bsp/e")) => { - let a: A = state.eval(source.next(), ||"bsp/e: expected content 1")?; - let b: B = state.eval(source.next(), ||"bsp/e: expected content 2")?; + "bsp/e" => { + let _ = source.next(); + let a: A = self.provide(source, ||"bsp/e: expected content 1")?; + let b: B = self.provide(source, ||"bsp/e: expected content 2")?; Self::e(a, b) }, - Some(Value::Key("bsp/w")) => { - let a: A = state.eval(source.next(), ||"bsp/w: expected content 1")?; - let b: B = state.eval(source.next(), ||"bsp/w: expected content 2")?; + "bsp/w" => { + let _ = source.next(); + let a: A = self.provide(source, ||"bsp/w: expected content 1")?; + let b: B = self.provide(source, ||"bsp/w: expected content 2")?; Self::w(a, b) }, - Some(Value::Key("bsp/a")) => { - let a: A = state.eval(source.next(), ||"bsp/a: expected content 1")?; - let b: B = state.eval(source.next(), ||"bsp/a: expected content 2")?; + "bsp/a" => { + let _ = source.next(); + let a: A = self.provide(source, ||"bsp/a: expected content 1")?; + let b: B = self.provide(source, ||"bsp/a: expected content 2")?; Self::a(a, b) }, - Some(Value::Key("bsp/b")) => { - let a: A = state.eval(source.next(), ||"bsp/b: expected content 1")?; - let b: B = state.eval(source.next(), ||"bsp/b: expected content 2")?; + "bsp/b" => { + let _ = source.next(); + let a: A = self.provide(source, ||"bsp/b: expected content 1")?; + let b: B = self.provide(source, ||"bsp/b: expected content 2")?; Self::b(a, b) }, _ => return Ok(None), - } + }) } else { - return Ok(None) - })) + None + }) } } -impl Dsl for Align where S: Eval, A> { - fn try_provide (state: S, source: Ast) -> Perhaps { - Ok(Some(if let Ast::Exp(source) = source { - match source.next() { - Some(Value::Key("align/c")) => { - let content: A = state.eval(source.next(), ||"align/c: expected content")?; +impl Eval> for S where + S: Eval +{ + fn eval (&self, source: I) -> Perhaps { + Ok(if let Some(Value::Key(key)) = source.peek() { + Some(match key { + "align/c" => { + let _ = source.next(); + let content: A = self.provide(source, ||"align/c: expected content")?; Self::c(content) }, - Some(Value::Key("align/x")) => { - let content: A = state.eval(source.next(), ||"align/x: expected content")?; + "align/x" => { + let _ = source.next(); + let content: A = self.provide(source, ||"align/x: expected content")?; Self::x(content) }, - Some(Value::Key("align/y")) => { - let content: A = state.eval(source.next(), ||"align/y: expected content")?; + "align/y" => { + let _ = source.next(); + let content: A = self.provide(source, ||"align/y: expected content")?; Self::y(content) }, - Some(Value::Key("align/n")) => { - let content: A = state.eval(source.next(), ||"align/n: expected content")?; + "align/n" => { + let _ = source.next(); + let content: A = self.provide(source, ||"align/n: expected content")?; Self::n(content) }, - Some(Value::Key("align/s")) => { - let content: A = state.eval(source.next(), ||"align/s: expected content")?; + "align/s" => { + let _ = source.next(); + let content: A = self.provide(source, ||"align/s: expected content")?; Self::s(content) }, - Some(Value::Key("align/e")) => { - let content: A = state.eval(source.next(), ||"align/e: expected content")?; + "align/e" => { + let _ = source.next(); + let content: A = self.provide(source, ||"align/e: expected content")?; Self::e(content) }, - Some(Value::Key("align/w")) => { - let content: A = state.eval(source.next(), ||"align/w: expected content")?; + "align/w" => { + let _ = source.next(); + let content: A = self.provide(source, ||"align/w: expected content")?; Self::w(content) }, - Some(Value::Key("align/nw")) => { - let content: A = state.eval(source.next(), ||"align/nw: expected content")?; + "align/nw" => { + let _ = source.next(); + let content: A = self.provide(source, ||"align/nw: expected content")?; Self::nw(content) }, - Some(Value::Key("align/ne")) => { - let content: A = state.eval(source.next(), ||"align/ne: expected content")?; + "align/ne" => { + let _ = source.next(); + let content: A = self.provide(source, ||"align/ne: expected content")?; Self::ne(content) }, - Some(Value::Key("align/sw")) => { - let content: A = state.eval(source.next(), ||"align/sw: expected content")?; + "align/sw" => { + let _ = source.next(); + let content: A = self.provide(source, ||"align/sw: expected content")?; Self::sw(content) }, - Some(Value::Key("align/se")) => { - let content: A = state.eval(source.next(), ||"align/se: expected content")?; + "align/se" => { + let _ = source.next(); + let content: A = self.provide(source, ||"align/se: expected content")?; Self::se(content) }, _ => return Ok(None), - } + }) } else { - return Ok(None) - })) + None + }) } }