arithmetic_parser/ast/
mod.rs

1//! ASTs for arithmetic expressions and statements.
2
3use core::fmt;
4
5pub use self::{
6    expr::{Expr, ExprType, SpannedExpr},
7    lvalue::{
8        Destructure, DestructureRest, Lvalue, LvalueLen, LvalueType, ObjectDestructure,
9        ObjectDestructureField, SpannedLvalue,
10    },
11};
12use crate::{
13    alloc::{vec, Box, Vec},
14    grammars::Grammar,
15    spans::Spanned,
16};
17
18mod expr;
19mod lvalue;
20
21/// Object expression, such as `#{ x, y: x + 2 }`.
22#[derive(Debug)]
23#[non_exhaustive]
24pub struct ObjectExpr<'a, T: Grammar> {
25    /// Fields. Each field is the field name and an optional expression (that is, parts
26    /// before and after the colon char `:`, respectively).
27    pub fields: Vec<(Spanned<'a>, Option<SpannedExpr<'a, T>>)>,
28}
29
30impl<T: Grammar> Clone for ObjectExpr<'_, T> {
31    fn clone(&self) -> Self {
32        Self {
33            fields: self.fields.clone(),
34        }
35    }
36}
37
38impl<T: Grammar> PartialEq for ObjectExpr<'_, T> {
39    fn eq(&self, other: &Self) -> bool {
40        self.fields == other.fields
41    }
42}
43
44/// Statement: an expression or a variable assignment.
45#[derive(Debug)]
46#[non_exhaustive]
47pub enum Statement<'a, T: Grammar> {
48    /// Expression, e.g., `x + (1, 2)`.
49    Expr(SpannedExpr<'a, T>),
50    /// Assigment, e.g., `(x, y) = (5, 8)`.
51    Assignment {
52        /// LHS of the assignment.
53        lhs: SpannedLvalue<'a, T::Type<'a>>,
54        /// RHS of the assignment.
55        rhs: Box<SpannedExpr<'a, T>>,
56    },
57}
58
59impl<T: Grammar> Statement<'_, T> {
60    /// Returns the type of this statement.
61    pub fn ty(&self) -> StatementType {
62        match self {
63            Self::Expr(_) => StatementType::Expr,
64            Self::Assignment { .. } => StatementType::Assignment,
65        }
66    }
67}
68
69impl<T: Grammar> Clone for Statement<'_, T> {
70    fn clone(&self) -> Self {
71        match self {
72            Self::Expr(expr) => Self::Expr(expr.clone()),
73            Self::Assignment { lhs, rhs } => Self::Assignment {
74                lhs: lhs.clone(),
75                rhs: rhs.clone(),
76            },
77        }
78    }
79}
80
81impl<'a, T> PartialEq for Statement<'a, T>
82where
83    T: Grammar,
84    T::Lit: PartialEq,
85    T::Type<'a>: PartialEq,
86{
87    fn eq(&self, other: &Self) -> bool {
88        match (self, other) {
89            (Self::Expr(this), Self::Expr(that)) => this == that,
90
91            (
92                Self::Assignment { lhs, rhs },
93                Self::Assignment {
94                    lhs: that_lhs,
95                    rhs: that_rhs,
96                },
97            ) => lhs == that_lhs && rhs == that_rhs,
98
99            _ => false,
100        }
101    }
102}
103
104/// Statement with the associated code span.
105pub type SpannedStatement<'a, T> = Spanned<'a, Statement<'a, T>>;
106
107/// Type of a [`Statement`].
108#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
109#[non_exhaustive]
110pub enum StatementType {
111    /// Expression, e.g., `x + (1, 2)`.
112    Expr,
113    /// Assigment, e.g., `(x, y) = (5, 8)`.
114    Assignment,
115}
116
117impl fmt::Display for StatementType {
118    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
119        formatter.write_str(match self {
120            Self::Expr => "expression",
121            Self::Assignment => "variable assignment",
122        })
123    }
124}
125
126/// Block of statements.
127///
128/// A block may end with a return expression, e.g., `{ x = 1; x }`.
129#[derive(Debug)]
130#[non_exhaustive]
131pub struct Block<'a, T: Grammar> {
132    /// Statements in the block.
133    pub statements: Vec<SpannedStatement<'a, T>>,
134    /// The last statement in the block which is returned from the block.
135    pub return_value: Option<Box<SpannedExpr<'a, T>>>,
136}
137
138impl<T: Grammar> Clone for Block<'_, T> {
139    fn clone(&self) -> Self {
140        Self {
141            statements: self.statements.clone(),
142            return_value: self.return_value.clone(),
143        }
144    }
145}
146
147impl<'a, T> PartialEq for Block<'a, T>
148where
149    T: Grammar,
150    T::Lit: PartialEq,
151    T::Type<'a>: PartialEq,
152{
153    fn eq(&self, other: &Self) -> bool {
154        self.return_value == other.return_value && self.statements == other.statements
155    }
156}
157
158impl<T: Grammar> Block<'_, T> {
159    /// Creates an empty block.
160    pub fn empty() -> Self {
161        Self {
162            statements: vec![],
163            return_value: None,
164        }
165    }
166}
167
168/// Function definition, e.g., `|x, y| x + y`.
169///
170/// A function definition consists of a list of arguments and the function body.
171#[derive(Debug)]
172#[non_exhaustive]
173pub struct FnDefinition<'a, T: Grammar> {
174    /// Function arguments, e.g., `x, y`.
175    pub args: Spanned<'a, Destructure<'a, T::Type<'a>>>,
176    /// Function body, e.g., `x + y`.
177    pub body: Block<'a, T>,
178}
179
180impl<T: Grammar> Clone for FnDefinition<'_, T> {
181    fn clone(&self) -> Self {
182        Self {
183            args: self.args.clone(),
184            body: self.body.clone(),
185        }
186    }
187}
188
189impl<'a, T> PartialEq for FnDefinition<'a, T>
190where
191    T: Grammar,
192    T::Lit: PartialEq,
193    T::Type<'a>: PartialEq,
194{
195    fn eq(&self, other: &Self) -> bool {
196        self.args == other.args && self.body == other.body
197    }
198}