async_gcode/
types.rs

1#[cfg(all(
2    not(feature = "std"),
3    any(feature = "parse-comments", feature = "string-value")
4))]
5use alloc::string::String;
6
7#[derive(Debug)]
8pub(crate) enum ParseResult<G, E> {
9    Input(E),
10    Parsing(crate::Error),
11    Ok(G),
12}
13impl<O, E> From<core::result::Result<O, E>> for ParseResult<O, E> {
14    fn from(f: core::result::Result<O, E>) -> Self {
15        match f {
16            Ok(o) => ParseResult::Ok(o),
17            Err(e) => ParseResult::Input(e),
18        }
19    }
20}
21
22impl<O, E> From<crate::Error> for ParseResult<O, E> {
23    fn from(f: crate::Error) -> Self {
24        ParseResult::Parsing(f)
25    }
26}
27
28#[cfg(not(feature = "parse-comments"))]
29pub type Comment = ();
30#[cfg(feature = "parse-comments")]
31pub type Comment = String;
32
33#[derive(Debug, PartialEq, Clone)]
34pub enum Literal {
35    RealNumber(f64),
36    #[cfg(feature = "string-value")]
37    String(String),
38}
39impl Literal {
40    pub fn as_real_number(&self) -> Option<f64> {
41        match self {
42            Literal::RealNumber(rn) => Some(*rn),
43            #[cfg(feature = "string-value")]
44            _ => None,
45        }
46    }
47    #[cfg(feature = "string-value")]
48    pub fn as_string(&self) -> Option<&str> {
49        match self {
50            Literal::String(string) => Some(string),
51            _ => None,
52        }
53    }
54}
55impl From<i32> for Literal {
56    fn from(from: i32) -> Self {
57        Self::RealNumber(from as f64)
58    }
59}
60impl From<u32> for Literal {
61    fn from(from: u32) -> Self {
62        Self::RealNumber(from as f64)
63    }
64}
65impl From<f64> for Literal {
66    fn from(from: f64) -> Self {
67        Self::RealNumber(from)
68    }
69}
70
71#[cfg(feature = "string-value")]
72impl From<String> for Literal {
73    fn from(from: String) -> Self {
74        Self::String(from)
75    }
76}
77
78#[derive(Debug, PartialEq, Clone)]
79pub enum RealValue {
80    Literal(Literal),
81    #[cfg(any(feature = "parse-parameters", feature = "parse-expressions"))]
82    Expression(expressions::Expression),
83    #[cfg(feature = "optional-value")]
84    None,
85}
86impl Default for RealValue {
87    fn default() -> Self {
88        Self::from(0.)
89    }
90}
91impl<T: Into<Literal>> From<T> for RealValue {
92    fn from(from: T) -> Self {
93        RealValue::Literal(from.into())
94    }
95}
96
97#[cfg(any(feature = "parse-parameters", feature = "parse-expressions"))]
98pub(crate) mod expressions {
99    use super::{Literal, RealValue};
100    use crate::Error;
101    use either::Either;
102
103    #[cfg(not(feature = "std"))]
104    use alloc::vec::Vec;
105
106    pub(crate) type ExprItem = Either<Operator, Literal>;
107    pub(crate) type ExprInner = Vec<ExprItem>;
108
109    #[derive(Debug, PartialEq, Eq, Clone, Copy)]
110    pub enum OpType {
111        Unary,
112        Binary,
113    }
114    #[derive(Debug, PartialEq, Eq, Clone, Copy)]
115    pub enum Associativity {
116        Left,
117        #[cfg(feature = "parse-parameters")]
118        Right,
119    }
120    #[derive(Debug, Clone, Copy, PartialOrd, PartialEq, Eq)]
121    pub enum Precedence {
122        Group1,
123        Group2,
124        Group3,
125        #[cfg(feature = "parse-parameters")]
126        Group4,
127        Group5,
128    }
129
130    #[derive(Debug, PartialEq, Eq, Clone, Copy)]
131    pub enum Operator {
132        // Binary operators
133        Add,
134        Substract,
135        Multiply,
136        Divide,
137        Power,
138
139        And,
140        Or,
141        Xor,
142
143        Modulus,
144
145        // Unary operators
146        Cos,
147        Sin,
148        Tan,
149        ACos,
150        ASin,
151        ATan, // Atan is kind of binary
152
153        Abs,
154        Exp,
155        Fix,
156        Fup,
157        Ln,
158        Round,
159        Sqrt,
160
161        #[cfg(feature = "parse-parameters")]
162        GetParameter,
163    }
164    impl Operator {
165        pub fn op_type(&self) -> OpType {
166            match self {
167                Self::Add
168                | Self::Substract
169                | Self::Multiply
170                | Self::Divide
171                | Self::Modulus
172                | Self::Power
173                | Self::And
174                | Self::Or
175                | Self::Xor
176                | Self::ATan => OpType::Binary,
177                Self::Cos
178                | Self::Sin
179                | Self::Tan
180                | Self::ACos
181                | Self::ASin
182                | Self::Abs
183                | Self::Exp
184                | Self::Fix
185                | Self::Fup
186                | Self::Ln
187                | Self::Round
188                | Self::Sqrt => OpType::Unary,
189                #[cfg(feature = "parse-parameters")]
190                Self::GetParameter => OpType::Unary,
191            }
192        }
193
194        pub fn associativity(&self) -> Associativity {
195            #[allow(clippy::match_single_binding)]
196            match self {
197                #[cfg(feature = "parse-parameters")]
198                Self::GetParameter => Associativity::Right,
199                _ => Associativity::Left,
200            }
201        }
202
203        pub fn precedence(&self) -> Precedence {
204            match *self {
205                Self::Add | Self::Substract | Self::And | Self::Or | Self::Xor => {
206                    Precedence::Group1
207                }
208                Self::Multiply | Self::Divide | Self::Modulus => Precedence::Group2,
209                Self::Power => Precedence::Group3,
210                #[cfg(feature = "parse-parameters")]
211                Self::GetParameter => Precedence::Group4,
212                Self::Cos
213                | Self::Sin
214                | Self::Tan
215                | Self::ACos
216                | Self::ASin
217                | Self::ATan
218                | Self::Abs
219                | Self::Exp
220                | Self::Fix
221                | Self::Fup
222                | Self::Ln
223                | Self::Round
224                | Self::Sqrt => Precedence::Group5,
225            }
226        }
227    }
228
229    #[derive(Debug, PartialEq, Clone)]
230    pub struct Expression(pub(crate) ExprInner);
231    impl Expression {
232        /// Evaluates the expressions to a single literal. Math error may occur during the
233        /// expression's resolution (e.g. division by 0).
234        ///
235        /// When `parse-parameters` is enabled, this method takes a closure as an argument.
236        /// This closure is used to resolve parameters get.
237        pub fn evaluate(
238            &self,
239            #[cfg(feature = "parse-parameters")] _cbk: &mut dyn FnMut(Literal) -> Literal,
240        ) -> Result<Literal, Error> {
241            todo!()
242        }
243    }
244
245    impl From<Operator> for Either<Operator, Literal> {
246        fn from(from: Operator) -> Self {
247            Self::Left(from)
248        }
249    }
250    impl From<Literal> for Either<Operator, Literal> {
251        fn from(from: Literal) -> Self {
252            Self::Right(from)
253        }
254    }
255
256    impl From<Expression> for Either<Literal, Expression> {
257        fn from(from: Expression) -> Self {
258            Self::Right(from)
259        }
260    }
261    impl From<Literal> for Either<Literal, Expression> {
262        fn from(from: Literal) -> Self {
263            Self::Left(from)
264        }
265    }
266
267    impl From<Expression> for RealValue {
268        fn from(from: Expression) -> RealValue {
269            RealValue::Expression(from)
270        }
271    }
272
273    #[cfg(test)]
274    mod test {
275        // test plan for expressions:
276        // TBD
277    }
278}