Skip to main content

scan_core/
grammar.rs

1//! The language used by PGs and CSs.
2//!
3//! The type [`Expression<V>`] encodes the used language,
4//! where `V` is the type parameter of variables.
5//! The language features base types and product types,
6//! Boolean logic and basic arithmetic expressions.
7
8mod boolean;
9mod float;
10mod integer;
11mod natural;
12
13use rand::Rng;
14use std::{
15    hash::Hash,
16    ops::{Add, BitAnd, BitOr, Div, Mul, Neg, Not, Rem},
17};
18use thiserror::Error;
19
20use crate::dummy_rng::DummyRng;
21
22pub use boolean::*;
23pub use float::*;
24pub use integer::*;
25pub use natural::*;
26
27/// The error type for operations with [`Type`].
28#[derive(Debug, Clone, Copy, Error)]
29pub enum TypeError {
30    /// Types that should be matching are not,
31    /// or are not compatible with each other.
32    #[error("type mismatch")]
33    TypeMismatch,
34    /// The variable's type is unknown.
35    #[error("the type of variable is unknown")]
36    UnknownVar,
37    /// Bounds violate some constraint.
38    #[error("the bounds violate some constraint")]
39    BadBounds,
40    /// Probability violates some constraint.
41    #[error("the probability violates some constraint")]
42    BadProbability,
43}
44
45/// The types supported by the language internally used by PGs and CSs.
46#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
47pub enum Type {
48    /// Boolean type.
49    Boolean,
50    /// Natural (unsigned) numerical type.
51    Natural,
52    /// Integer numerical type.
53    Integer,
54    /// Floating-point numerical type.
55    Float,
56}
57
58impl Type {
59    /// The default value for a given type.
60    /// Used to initialize variables.
61    pub fn default_value(self) -> Val {
62        match self {
63            Type::Boolean => Val::Boolean(false),
64            Type::Natural => Val::Natural(0),
65            Type::Integer => Val::Integer(0),
66            Type::Float => Val::Float(0.0),
67        }
68    }
69}
70
71/// Possible values for each [`Type`].
72#[derive(Debug, Clone, Copy, PartialEq)]
73pub enum Val {
74    /// Boolean values.
75    Boolean(bool),
76    /// Natural (unsigned) values.
77    Natural(Natural),
78    /// Integer values.
79    Integer(Integer),
80    /// Floating-point values.
81    Float(Float),
82}
83
84impl Val {
85    /// Returns the [`Type`] of the value.
86    pub fn r#type(self) -> Type {
87        match self {
88            Val::Boolean(_) => Type::Boolean,
89            Val::Natural(_) => Type::Natural,
90            Val::Integer(_) => Type::Integer,
91            Val::Float(_) => Type::Float,
92        }
93    }
94}
95
96impl From<bool> for Val {
97    fn from(value: bool) -> Self {
98        Val::Boolean(value)
99    }
100}
101
102impl From<Natural> for Val {
103    fn from(value: Natural) -> Self {
104        Val::Natural(value)
105    }
106}
107
108impl From<Integer> for Val {
109    fn from(value: Integer) -> Self {
110        Val::Integer(value)
111    }
112}
113
114impl From<Float> for Val {
115    fn from(value: Float) -> Self {
116        Val::Float(value)
117    }
118}
119
120/// Expressions for the language internally used by PGs and CSs.
121///
122/// [`Expression<V>`] encodes the language in which `V` is the type of variables.
123///
124/// Note that not all expressions that can be formed are well-typed.
125#[derive(Debug, Clone)]
126pub enum Expression<V>
127where
128    V: Clone,
129{
130    /// Expression of Boolean type.
131    Boolean(BooleanExpr<V>),
132    /// Expression of Natural type (unsigned integers).
133    Natural(NaturalExpr<V>),
134    /// Expression of Integer type.
135    Integer(IntegerExpr<V>),
136    /// Expression of Float type.
137    Float(FloatExpr<V>),
138}
139
140impl<V> From<Val> for Expression<V>
141where
142    V: Clone,
143{
144    fn from(value: Val) -> Self {
145        match value {
146            Val::Boolean(b) => Expression::Boolean(BooleanExpr::Const(b)),
147            Val::Natural(nat) => Expression::Natural(NaturalExpr::Const(nat)),
148            Val::Integer(int) => Expression::Integer(IntegerExpr::Const(int)),
149            Val::Float(float) => Expression::Float(FloatExpr::Const(float)),
150        }
151    }
152}
153
154impl<V> From<bool> for Expression<V>
155where
156    V: Clone,
157{
158    fn from(value: bool) -> Self {
159        Expression::Boolean(BooleanExpr::from(value))
160    }
161}
162
163impl<V> From<Natural> for Expression<V>
164where
165    V: Clone,
166{
167    fn from(value: Natural) -> Self {
168        Expression::Natural(NaturalExpr::from(value))
169    }
170}
171
172impl<V> From<Integer> for Expression<V>
173where
174    V: Clone,
175{
176    fn from(value: Integer) -> Self {
177        Expression::Integer(IntegerExpr::from(value))
178    }
179}
180
181impl<V> From<Float> for Expression<V>
182where
183    V: Clone,
184{
185    fn from(value: Float) -> Self {
186        Expression::Float(FloatExpr::from(value))
187    }
188}
189
190impl<V> Expression<V>
191where
192    V: Clone,
193{
194    /// Computes the type of an expression.
195    ///
196    /// Fails if the expression is badly typed,
197    /// e.g., if variables in it have type incompatible with the expression.
198    pub fn r#type(&self) -> Type {
199        match self {
200            Expression::Boolean(_) => Type::Boolean,
201            Expression::Natural(_) => Type::Natural,
202            Expression::Integer(_) => Type::Integer,
203            Expression::Float(_) => Type::Float,
204        }
205    }
206
207    /// Evaluates the expression with the given variable assignments and provided RNG.
208    ///
209    /// Will assume the expression (with the variable assignment) is well-typed,
210    /// and may panic if producing an unexpected type.
211    pub fn eval<R: Rng>(&self, vars: &dyn Fn(&V) -> Val, rng: &mut R) -> Val {
212        match self {
213            Expression::Boolean(boolean_expr) => Val::Boolean(boolean_expr.eval(vars, rng)),
214            Expression::Natural(natural_expr) => Val::Natural(natural_expr.eval(vars, rng)),
215            Expression::Integer(integer_expr) => Val::Integer(integer_expr.eval(vars, rng)),
216            Expression::Float(float_expr) => Val::Float(float_expr.eval(vars, rng)),
217        }
218    }
219
220    /// Evals a constant expression.
221    /// Returns an error if expression contains variables.
222    pub fn is_constant(&self) -> bool {
223        match self {
224            Expression::Boolean(boolean_expr) => boolean_expr.is_constant(),
225            Expression::Natural(natural_expr) => natural_expr.is_constant(),
226            Expression::Integer(integer_expr) => integer_expr.is_constant(),
227            Expression::Float(float_expr) => float_expr.is_constant(),
228        }
229    }
230
231    /// Evals a constant expression.
232    /// Returns an error if expression contains variables.
233    pub fn eval_constant(&self) -> Result<Val, TypeError> {
234        if self.is_constant() {
235            Ok(self.eval(&|_| panic!("no vars"), &mut DummyRng))
236        } else {
237            Err(TypeError::UnknownVar)
238        }
239    }
240
241    pub(crate) fn map<W: Clone>(self, map: &dyn Fn(V) -> W) -> Expression<W> {
242        match self {
243            Expression::Boolean(boolean_expr) => Expression::Boolean(boolean_expr.map(map)),
244            Expression::Natural(natural_expr) => Expression::Natural(natural_expr.map(map)),
245            Expression::Integer(integer_expr) => Expression::Integer(integer_expr.map(map)),
246            Expression::Float(float_expr) => Expression::Float(float_expr.map(map)),
247        }
248    }
249
250    pub(crate) fn context(&self, vars: &dyn Fn(V) -> Option<Type>) -> Result<(), TypeError> {
251        match self {
252            Expression::Boolean(boolean_expr) => boolean_expr.context(vars),
253            Expression::Natural(natural_expr) => natural_expr.context(vars),
254            Expression::Integer(integer_expr) => integer_expr.context(vars),
255            Expression::Float(float_expr) => float_expr.context(vars),
256        }
257    }
258
259    /// Creates an `[Expression]` out of a variable and the type of such variable.
260    pub fn from_var(var: V, r#type: Type) -> Self {
261        match r#type {
262            Type::Boolean => Expression::Boolean(BooleanExpr::Var(var)),
263            Type::Natural => Expression::Natural(NaturalExpr::Var(var)),
264            Type::Integer => Expression::Integer(IntegerExpr::Var(var)),
265            Type::Float => Expression::Float(FloatExpr::Var(var)),
266        }
267    }
268
269    /// Creates an [`Expression`] that predicates the equality of `self` and `rhs`,
270    /// and returns error if comparison is not possible.
271    ///
272    /// Equality of Boolean is represented as "if and only if".
273    ///
274    /// Equality of numerical types automatically casts the one of most-restrictive type to the less restrictive type of the other one:
275    /// for example, [`NaturalExpr`] can be cast to [`IntegerExpr`] or [`FloatExpr`];
276    /// and `[IntegerExpr]` can be cast to `[FloatExpr]`.
277    pub fn equal_to(self, rhs: Self) -> Result<BooleanExpr<V>, TypeError> {
278        match self {
279            Expression::Boolean(boolean_expr) => match rhs {
280                Expression::Boolean(boolean_expr_rhs) => {
281                    Ok(BooleanExpr::Implies(Box::new((
282                        boolean_expr.clone(),
283                        boolean_expr_rhs.clone(),
284                    ))) & BooleanExpr::Implies(Box::new((boolean_expr_rhs, boolean_expr))))
285                }
286                Expression::Natural(_) | Expression::Integer(_) | Expression::Float(_) => {
287                    Err(TypeError::TypeMismatch)
288                }
289            },
290            Expression::Natural(natural_expr) => match rhs {
291                Expression::Boolean(_) => Err(TypeError::TypeMismatch),
292                Expression::Natural(natural_expr_rhs) => {
293                    Ok(BooleanExpr::NatEqual(natural_expr, natural_expr_rhs))
294                }
295                Expression::Integer(integer_expr_rhs) => Ok(BooleanExpr::IntEqual(
296                    IntegerExpr::from(natural_expr),
297                    integer_expr_rhs,
298                )),
299                Expression::Float(float_expr_rhs) => Ok(BooleanExpr::FloatEqual(
300                    FloatExpr::Nat(natural_expr),
301                    float_expr_rhs,
302                )),
303            },
304            Expression::Integer(integer_expr) => match rhs {
305                Expression::Boolean(_) => Err(TypeError::TypeMismatch),
306                Expression::Natural(natural_expr_rhs) => Ok(BooleanExpr::IntEqual(
307                    integer_expr,
308                    IntegerExpr::from(natural_expr_rhs),
309                )),
310                Expression::Integer(integer_expr_rhs) => {
311                    Ok(BooleanExpr::IntEqual(integer_expr, integer_expr_rhs))
312                }
313                Expression::Float(float_expr_rhs) => Ok(BooleanExpr::FloatEqual(
314                    FloatExpr::Int(integer_expr),
315                    float_expr_rhs,
316                )),
317            },
318            Expression::Float(float_expr) => match rhs {
319                Expression::Boolean(_) => Err(TypeError::TypeMismatch),
320                Expression::Natural(natural_expr_rhs) => Ok(BooleanExpr::FloatEqual(
321                    float_expr,
322                    FloatExpr::Nat(natural_expr_rhs),
323                )),
324                Expression::Integer(integer_expr_rhs) => Ok(BooleanExpr::FloatEqual(
325                    float_expr,
326                    FloatExpr::Int(integer_expr_rhs),
327                )),
328                Expression::Float(float_expr_rhs) => {
329                    Ok(BooleanExpr::FloatEqual(float_expr, float_expr_rhs))
330                }
331            },
332        }
333    }
334
335    /// Creates a [`BooleanExpr`] that compares numerical expressions `self` and `rhs`,
336    /// and returns error if comparison is not possible.
337    ///
338    /// Equality of numerical types automatically casts the one of most-restrictive type to the less restrictive type of the other one;
339    /// see [`Self::equal_to`].
340    pub fn greater_than_or_equal_to(self, rhs: Self) -> Result<BooleanExpr<V>, TypeError> {
341        match self {
342            Expression::Boolean(_) => Err(TypeError::TypeMismatch),
343            Expression::Natural(natural_expr) => match rhs {
344                Expression::Boolean(_) => Err(TypeError::TypeMismatch),
345                Expression::Natural(natural_expr_rhs) => {
346                    Ok(BooleanExpr::NatGreaterEq(natural_expr, natural_expr_rhs))
347                }
348                Expression::Integer(integer_expr_rhs) => Ok(BooleanExpr::IntGreaterEq(
349                    IntegerExpr::from(natural_expr),
350                    integer_expr_rhs,
351                )),
352                Expression::Float(float_expr_rhs) => Ok(BooleanExpr::FloatGreaterEq(
353                    FloatExpr::Nat(natural_expr),
354                    float_expr_rhs,
355                )),
356            },
357            Expression::Integer(integer_expr) => match rhs {
358                Expression::Boolean(_) => Err(TypeError::TypeMismatch),
359                Expression::Natural(natural_expr_rhs) => Ok(BooleanExpr::IntGreaterEq(
360                    integer_expr,
361                    IntegerExpr::from(natural_expr_rhs),
362                )),
363                Expression::Integer(integer_expr_rhs) => {
364                    Ok(BooleanExpr::IntGreaterEq(integer_expr, integer_expr_rhs))
365                }
366                Expression::Float(float_expr_rhs) => Ok(BooleanExpr::FloatGreaterEq(
367                    FloatExpr::Int(integer_expr),
368                    float_expr_rhs,
369                )),
370            },
371            Expression::Float(float_expr) => match rhs {
372                Expression::Boolean(_) => Err(TypeError::TypeMismatch),
373                Expression::Natural(natural_expr_rhs) => Ok(BooleanExpr::FloatGreaterEq(
374                    float_expr,
375                    FloatExpr::Nat(natural_expr_rhs),
376                )),
377                Expression::Integer(integer_expr_rhs) => Ok(BooleanExpr::FloatGreaterEq(
378                    float_expr,
379                    FloatExpr::Int(integer_expr_rhs),
380                )),
381                Expression::Float(float_expr_rhs) => {
382                    Ok(BooleanExpr::FloatGreaterEq(float_expr, float_expr_rhs))
383                }
384            },
385        }
386    }
387
388    /// Creates a [`BooleanExpr`] that compares numerical expressions `self` and `rhs`,
389    /// and returns error if comparison is not possible.
390    ///
391    /// Equality of numerical types automatically casts the one of most-restrictive type to the less restrictive type of the other one;
392    /// see [`Self::equal_to`].
393    pub fn greater_than(self, rhs: Self) -> Result<BooleanExpr<V>, TypeError> {
394        match self {
395            Expression::Boolean(_) => Err(TypeError::TypeMismatch),
396            Expression::Natural(natural_expr) => match rhs {
397                Expression::Boolean(_) => Err(TypeError::TypeMismatch),
398                Expression::Natural(natural_expr_rhs) => {
399                    Ok(BooleanExpr::NatGreater(natural_expr, natural_expr_rhs))
400                }
401                Expression::Integer(integer_expr_rhs) => Ok(BooleanExpr::IntGreater(
402                    IntegerExpr::from(natural_expr),
403                    integer_expr_rhs,
404                )),
405                Expression::Float(float_expr_rhs) => Ok(BooleanExpr::FloatGreater(
406                    FloatExpr::from(natural_expr),
407                    float_expr_rhs,
408                )),
409            },
410            Expression::Integer(integer_expr) => match rhs {
411                Expression::Boolean(_) => Err(TypeError::TypeMismatch),
412                Expression::Natural(natural_expr_rhs) => Ok(BooleanExpr::IntGreater(
413                    integer_expr,
414                    IntegerExpr::from(natural_expr_rhs),
415                )),
416                Expression::Integer(integer_expr_rhs) => {
417                    Ok(BooleanExpr::IntGreater(integer_expr, integer_expr_rhs))
418                }
419                Expression::Float(float_expr_rhs) => Ok(BooleanExpr::FloatGreater(
420                    FloatExpr::from(integer_expr),
421                    float_expr_rhs,
422                )),
423            },
424            Expression::Float(float_expr) => match rhs {
425                Expression::Boolean(_) => Err(TypeError::TypeMismatch),
426                Expression::Natural(natural_expr_rhs) => Ok(BooleanExpr::FloatGreater(
427                    float_expr,
428                    FloatExpr::from(natural_expr_rhs),
429                )),
430                Expression::Integer(integer_expr_rhs) => Ok(BooleanExpr::FloatGreater(
431                    float_expr,
432                    FloatExpr::from(integer_expr_rhs),
433                )),
434                Expression::Float(float_expr_rhs) => {
435                    Ok(BooleanExpr::FloatGreater(float_expr, float_expr_rhs))
436                }
437            },
438        }
439    }
440
441    /// Creates a [`BooleanExpr`] that compares numerical expressions `self` and `rhs`,
442    /// and returns error if comparison is not possible.
443    ///
444    /// Equality of numerical types automatically casts the one of most-restrictive type to the less restrictive type of the other one;
445    /// see [`Self::equal_to`].
446    pub fn less_than(self, rhs: Self) -> Result<BooleanExpr<V>, TypeError> {
447        match self {
448            Expression::Boolean(_) => Err(TypeError::TypeMismatch),
449            Expression::Natural(natural_expr) => match rhs {
450                Expression::Boolean(_) => Err(TypeError::TypeMismatch),
451                Expression::Natural(natural_expr_rhs) => {
452                    Ok(BooleanExpr::NatLess(natural_expr, natural_expr_rhs))
453                }
454                Expression::Integer(integer_expr_rhs) => Ok(BooleanExpr::IntLess(
455                    IntegerExpr::from(natural_expr),
456                    integer_expr_rhs,
457                )),
458                Expression::Float(float_expr_rhs) => Ok(BooleanExpr::FloatLess(
459                    FloatExpr::from(natural_expr),
460                    float_expr_rhs,
461                )),
462            },
463            Expression::Integer(integer_expr) => match rhs {
464                Expression::Boolean(_) => Err(TypeError::TypeMismatch),
465                Expression::Natural(natural_expr_rhs) => Ok(BooleanExpr::IntLess(
466                    integer_expr,
467                    IntegerExpr::from(natural_expr_rhs),
468                )),
469                Expression::Integer(integer_expr_rhs) => {
470                    Ok(BooleanExpr::IntLess(integer_expr, integer_expr_rhs))
471                }
472                Expression::Float(float_expr_rhs) => Ok(BooleanExpr::FloatLess(
473                    FloatExpr::from(integer_expr),
474                    float_expr_rhs,
475                )),
476            },
477            Expression::Float(float_expr) => match rhs {
478                Expression::Boolean(_) => Err(TypeError::TypeMismatch),
479                Expression::Natural(natural_expr_rhs) => Ok(BooleanExpr::FloatLess(
480                    float_expr,
481                    FloatExpr::from(natural_expr_rhs),
482                )),
483                Expression::Integer(integer_expr_rhs) => Ok(BooleanExpr::FloatLess(
484                    float_expr,
485                    FloatExpr::from(integer_expr_rhs),
486                )),
487                Expression::Float(float_expr_rhs) => {
488                    Ok(BooleanExpr::FloatLess(float_expr, float_expr_rhs))
489                }
490            },
491        }
492    }
493
494    /// Creates a [`BooleanExpr`] that compares numerical expressions `self` and `rhs`,
495    /// and returns error if comparison is not possible.
496    ///
497    /// Equality of numerical types automatically casts the one of most-restrictive type to the less restrictive type of the other one;
498    /// see [`Self::equal_to`].
499    pub fn less_than_or_equal_to(self, rhs: Self) -> Result<BooleanExpr<V>, TypeError> {
500        match self {
501            Expression::Boolean(_) => Err(TypeError::TypeMismatch),
502            Expression::Natural(natural_expr) => match rhs {
503                Expression::Boolean(_) => Err(TypeError::TypeMismatch),
504                Expression::Natural(natural_expr_rhs) => {
505                    Ok(BooleanExpr::NatLessEq(natural_expr, natural_expr_rhs))
506                }
507                Expression::Integer(integer_expr_rhs) => Ok(BooleanExpr::IntLessEq(
508                    IntegerExpr::from(natural_expr),
509                    integer_expr_rhs,
510                )),
511                Expression::Float(float_expr_rhs) => Ok(BooleanExpr::FloatLessEq(
512                    FloatExpr::Nat(natural_expr),
513                    float_expr_rhs,
514                )),
515            },
516            Expression::Integer(integer_expr) => match rhs {
517                Expression::Boolean(_) => Err(TypeError::TypeMismatch),
518                Expression::Natural(natural_expr_rhs) => Ok(BooleanExpr::IntLessEq(
519                    integer_expr,
520                    IntegerExpr::from(natural_expr_rhs),
521                )),
522                Expression::Integer(integer_expr_rhs) => {
523                    Ok(BooleanExpr::IntLessEq(integer_expr, integer_expr_rhs))
524                }
525                Expression::Float(float_expr_rhs) => Ok(BooleanExpr::FloatLessEq(
526                    FloatExpr::Int(integer_expr),
527                    float_expr_rhs,
528                )),
529            },
530            Expression::Float(float_expr) => match rhs {
531                Expression::Boolean(_) => Err(TypeError::TypeMismatch),
532                Expression::Natural(natural_expr_rhs) => Ok(BooleanExpr::FloatLessEq(
533                    float_expr,
534                    FloatExpr::Nat(natural_expr_rhs),
535                )),
536                Expression::Integer(integer_expr_rhs) => Ok(BooleanExpr::FloatLessEq(
537                    float_expr,
538                    FloatExpr::Int(integer_expr_rhs),
539                )),
540                Expression::Float(float_expr_rhs) => {
541                    Ok(BooleanExpr::FloatLessEq(float_expr, float_expr_rhs))
542                }
543            },
544        }
545    }
546
547    /// Creates a [`BooleanExpr`] that compares numerical expressions `self` and `rhs`,
548    /// and returns error if comparison is not possible.
549    ///
550    /// Equality of numerical types automatically casts the one of most-restrictive type to the less restrictive type of the other one;
551    /// see [`Self::equal_to`].
552    pub fn ite(self, then: Self, r#else: Self) -> Result<Self, TypeError> {
553        if let Expression::Boolean(r#if) = self {
554            match then {
555                Expression::Boolean(if_boolean_expr) => {
556                    if let Expression::Boolean(else_boolean_expr) = r#else {
557                        Ok(Expression::Boolean(BooleanExpr::Ite(Box::new((
558                            r#if,
559                            if_boolean_expr,
560                            else_boolean_expr,
561                        )))))
562                    } else {
563                        Err(TypeError::TypeMismatch)
564                    }
565                }
566                Expression::Natural(if_natural_expr) => match r#else {
567                    Expression::Boolean(_) => Err(TypeError::TypeMismatch),
568                    Expression::Natural(else_natural_expr) => Ok(Expression::Natural(
569                        NaturalExpr::Ite(Box::new((r#if, if_natural_expr, else_natural_expr))),
570                    )),
571                    Expression::Integer(else_integer_expr) => {
572                        Ok(Expression::Integer(IntegerExpr::Ite(Box::new((
573                            r#if,
574                            IntegerExpr::from(if_natural_expr),
575                            else_integer_expr,
576                        )))))
577                    }
578                    Expression::Float(else_float_expr) => Ok(Expression::Float(FloatExpr::Ite(
579                        Box::new((r#if, FloatExpr::from(if_natural_expr), else_float_expr)),
580                    ))),
581                },
582                Expression::Integer(if_integer_expr) => match r#else {
583                    Expression::Boolean(_) => Err(TypeError::TypeMismatch),
584                    Expression::Natural(else_natural_expr) => {
585                        Ok(Expression::Integer(IntegerExpr::Ite(Box::new((
586                            r#if,
587                            if_integer_expr,
588                            IntegerExpr::from(else_natural_expr),
589                        )))))
590                    }
591                    Expression::Integer(else_integer_expr) => Ok(Expression::Integer(
592                        IntegerExpr::Ite(Box::new((r#if, if_integer_expr, else_integer_expr))),
593                    )),
594                    Expression::Float(else_float_expr) => Ok(Expression::Float(FloatExpr::Ite(
595                        Box::new((r#if, FloatExpr::from(if_integer_expr), else_float_expr)),
596                    ))),
597                },
598                Expression::Float(if_float_expr) => match r#else {
599                    Expression::Boolean(_) => Err(TypeError::TypeMismatch),
600                    Expression::Natural(else_natural_expr) => {
601                        Ok(Expression::Float(FloatExpr::Ite(Box::new((
602                            r#if,
603                            if_float_expr,
604                            FloatExpr::from(else_natural_expr),
605                        )))))
606                    }
607                    Expression::Integer(else_integer_expr) => {
608                        Ok(Expression::Float(FloatExpr::Ite(Box::new((
609                            r#if,
610                            if_float_expr,
611                            FloatExpr::from(else_integer_expr),
612                        )))))
613                    }
614                    Expression::Float(else_float_expr) => Ok(Expression::Float(FloatExpr::Ite(
615                        Box::new((r#if, if_float_expr, else_float_expr)),
616                    ))),
617                },
618            }
619        } else {
620            Err(TypeError::TypeMismatch)
621        }
622    }
623}
624
625impl<V: Clone> Neg for Expression<V> {
626    type Output = Result<Expression<V>, TypeError>;
627
628    fn neg(self) -> Self::Output {
629        match self {
630            Expression::Boolean(_) | Expression::Natural(_) => Err(TypeError::TypeMismatch),
631            Expression::Integer(integer_expr) => Ok(Expression::Integer(-integer_expr)),
632            Expression::Float(float_expr) => Ok(Expression::Float(-float_expr)),
633        }
634    }
635}
636
637impl<V: Clone> Not for Expression<V> {
638    type Output = Result<Expression<V>, TypeError>;
639
640    fn not(self) -> Self::Output {
641        match self {
642            Expression::Boolean(boolean_expr) => Ok(Expression::Boolean(!boolean_expr)),
643            Expression::Natural(_) | Expression::Integer(_) | Expression::Float(_) => {
644                Err(TypeError::TypeMismatch)
645            }
646        }
647    }
648}
649
650impl<V: Clone> Add for Expression<V> {
651    type Output = Result<Self, TypeError>;
652
653    fn add(self, rhs: Self) -> Self::Output {
654        match self {
655            Expression::Boolean(_) => Err(TypeError::TypeMismatch),
656            Expression::Natural(natural_expr) => match rhs {
657                Expression::Boolean(_) => Err(TypeError::TypeMismatch),
658                Expression::Natural(natural_expr_rhs) => {
659                    Ok(Expression::Natural(natural_expr + natural_expr_rhs))
660                }
661                Expression::Integer(integer_expr_rhs) => Ok(Expression::Integer(
662                    IntegerExpr::from(natural_expr) + integer_expr_rhs,
663                )),
664                Expression::Float(float_expr_rhs) => Ok(Expression::Float(
665                    FloatExpr::from(natural_expr) + float_expr_rhs,
666                )),
667            },
668            Expression::Integer(integer_expr) => match rhs {
669                Expression::Boolean(_) => Err(TypeError::TypeMismatch),
670                Expression::Natural(natural_expr_rhs) => Ok(Expression::Integer(
671                    integer_expr + IntegerExpr::from(natural_expr_rhs),
672                )),
673                Expression::Integer(integer_expr_rhs) => {
674                    Ok(Expression::Integer(integer_expr + integer_expr_rhs))
675                }
676                Expression::Float(float_expr_rhs) => Ok(Expression::Float(
677                    FloatExpr::from(integer_expr) + float_expr_rhs,
678                )),
679            },
680            Expression::Float(float_expr) => match rhs {
681                Expression::Boolean(_) => Err(TypeError::TypeMismatch),
682                Expression::Natural(natural_expr_rhs) => Ok(Expression::Float(
683                    float_expr + FloatExpr::from(natural_expr_rhs),
684                )),
685                Expression::Integer(integer_expr_rhs) => Ok(Expression::Float(
686                    float_expr + FloatExpr::from(integer_expr_rhs),
687                )),
688                Expression::Float(float_expr_rhs) => {
689                    Ok(Expression::Float(float_expr + float_expr_rhs))
690                }
691            },
692        }
693    }
694}
695
696impl<V: Clone> Mul for Expression<V> {
697    type Output = Result<Self, TypeError>;
698
699    fn mul(self, rhs: Self) -> Self::Output {
700        match self {
701            Expression::Boolean(_) => Err(TypeError::TypeMismatch),
702            Expression::Natural(natural_expr) => match rhs {
703                Expression::Boolean(_) => Err(TypeError::TypeMismatch),
704                Expression::Natural(natural_expr_rhs) => {
705                    Ok(Expression::Natural(natural_expr * natural_expr_rhs))
706                }
707                Expression::Integer(integer_expr_rhs) => Ok(Expression::Integer(
708                    IntegerExpr::from(natural_expr) * integer_expr_rhs,
709                )),
710                Expression::Float(float_expr_rhs) => Ok(Expression::Float(
711                    FloatExpr::from(natural_expr) * float_expr_rhs,
712                )),
713            },
714            Expression::Integer(integer_expr) => match rhs {
715                Expression::Boolean(_) => Err(TypeError::TypeMismatch),
716                Expression::Natural(natural_expr_rhs) => Ok(Expression::Integer(
717                    integer_expr * IntegerExpr::from(natural_expr_rhs),
718                )),
719                Expression::Integer(integer_expr_rhs) => {
720                    Ok(Expression::Integer(integer_expr * integer_expr_rhs))
721                }
722                Expression::Float(float_expr_rhs) => Ok(Expression::Float(
723                    FloatExpr::from(integer_expr) * float_expr_rhs,
724                )),
725            },
726            Expression::Float(float_expr) => match rhs {
727                Expression::Boolean(_) => Err(TypeError::TypeMismatch),
728                Expression::Natural(natural_expr_rhs) => Ok(Expression::Float(
729                    float_expr * FloatExpr::from(natural_expr_rhs),
730                )),
731                Expression::Integer(integer_expr_rhs) => Ok(Expression::Float(
732                    float_expr * FloatExpr::from(integer_expr_rhs),
733                )),
734                Expression::Float(float_expr_rhs) => {
735                    Ok(Expression::Float(float_expr * float_expr_rhs))
736                }
737            },
738        }
739    }
740}
741
742impl<V: Clone> Div for Expression<V> {
743    type Output = Result<Self, TypeError>;
744
745    fn div(self, rhs: Self) -> Self::Output {
746        match self {
747            Expression::Boolean(_) => Err(TypeError::TypeMismatch),
748            Expression::Natural(natural_expr) => match rhs {
749                Expression::Boolean(_) => Err(TypeError::TypeMismatch),
750                Expression::Natural(natural_expr_rhs) => {
751                    Ok(Expression::Natural(natural_expr / natural_expr_rhs))
752                }
753                Expression::Integer(integer_expr_rhs) => Ok(Expression::Integer(
754                    IntegerExpr::from(natural_expr) / integer_expr_rhs,
755                )),
756                Expression::Float(float_expr_rhs) => Ok(Expression::Float(
757                    FloatExpr::from(natural_expr) / float_expr_rhs,
758                )),
759            },
760            Expression::Integer(integer_expr) => match rhs {
761                Expression::Boolean(_) => Err(TypeError::TypeMismatch),
762                Expression::Natural(natural_expr_rhs) => Ok(Expression::Integer(
763                    integer_expr / IntegerExpr::from(natural_expr_rhs),
764                )),
765                Expression::Integer(integer_expr_rhs) => {
766                    Ok(Expression::Integer(integer_expr / integer_expr_rhs))
767                }
768                Expression::Float(float_expr_rhs) => Ok(Expression::Float(
769                    FloatExpr::from(integer_expr) / float_expr_rhs,
770                )),
771            },
772            Expression::Float(float_expr) => match rhs {
773                Expression::Boolean(_) => Err(TypeError::TypeMismatch),
774                Expression::Natural(natural_expr_rhs) => Ok(Expression::Float(
775                    float_expr / FloatExpr::from(natural_expr_rhs),
776                )),
777                Expression::Integer(integer_expr_rhs) => Ok(Expression::Float(
778                    float_expr / FloatExpr::from(integer_expr_rhs),
779                )),
780                Expression::Float(float_expr_rhs) => {
781                    Ok(Expression::Float(float_expr / float_expr_rhs))
782                }
783            },
784        }
785    }
786}
787
788impl<V: Clone> Rem for Expression<V> {
789    type Output = Result<Self, TypeError>;
790
791    fn rem(self, rhs: Self) -> Self::Output {
792        match self {
793            Expression::Natural(natural_expr) => match rhs {
794                Expression::Natural(natural_expr_rhs) => Ok(Expression::Natural(NaturalExpr::Rem(
795                    Box::new((natural_expr, natural_expr_rhs)),
796                ))),
797                Expression::Integer(integer_expr_rhs) => Ok(Expression::Integer(IntegerExpr::Rem(
798                    Box::new((IntegerExpr::from(natural_expr), integer_expr_rhs)),
799                ))),
800                Expression::Boolean(_) | Expression::Float(_) => Err(TypeError::TypeMismatch),
801            },
802            Expression::Integer(integer_expr) => match rhs {
803                Expression::Natural(natural_expr_rhs) => Ok(Expression::Integer(IntegerExpr::Rem(
804                    Box::new((integer_expr, IntegerExpr::from(natural_expr_rhs))),
805                ))),
806                Expression::Integer(integer_expr_rhs) => Ok(Expression::Integer(IntegerExpr::Rem(
807                    Box::new((integer_expr, integer_expr_rhs)),
808                ))),
809                Expression::Boolean(_) | Expression::Float(_) => Err(TypeError::TypeMismatch),
810            },
811            Expression::Boolean(_) | Expression::Float(_) => Err(TypeError::TypeMismatch),
812        }
813    }
814}
815
816impl<V: Clone> BitAnd for Expression<V> {
817    type Output = Result<Self, TypeError>;
818
819    fn bitand(self, rhs: Self) -> Self::Output {
820        if let Expression::Boolean(lhs) = self {
821            if let Expression::Boolean(rhs) = rhs {
822                Ok(Expression::Boolean(lhs & rhs))
823            } else {
824                Err(TypeError::TypeMismatch)
825            }
826        } else {
827            Err(TypeError::TypeMismatch)
828        }
829    }
830}
831
832impl<V: Clone> BitOr for Expression<V> {
833    type Output = Result<Self, TypeError>;
834
835    fn bitor(self, rhs: Self) -> Self::Output {
836        if let Expression::Boolean(lhs) = self {
837            if let Expression::Boolean(rhs) = rhs {
838                Ok(Expression::Boolean(lhs | rhs))
839            } else {
840                Err(TypeError::TypeMismatch)
841            }
842        } else {
843            Err(TypeError::TypeMismatch)
844        }
845    }
846}