rush_parser/
ast.rs

1use std::fmt::{self, Debug, Display, Formatter};
2
3use crate::Span;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub enum Type {
7    Int(usize),
8    Float(usize),
9    Bool(usize),
10    Char(usize),
11    Unit,
12    /// Internal use only, used for diverging expressions
13    Never,
14    /// Internal use only, used if typecheck could not determine a type
15    Unknown,
16}
17
18impl Display for Type {
19    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
20        match self {
21            Self::Int(indirections) => write!(f, "{}int", "*".repeat(*indirections)),
22            Self::Float(indirections) => write!(f, "{}float", "*".repeat(*indirections)),
23            Self::Bool(indirections) => write!(f, "{}bool", "*".repeat(*indirections)),
24            Self::Char(indirections) => write!(f, "{}char", "*".repeat(*indirections)),
25            Self::Unit => write!(f, "()"),
26            Self::Never => write!(f, "!"),
27            Self::Unknown => write!(f, "{{unknown}}"),
28        }
29    }
30}
31
32impl Type {
33    pub fn add_ref(self) -> Option<Self> {
34        Some(match self {
35            Type::Int(ptr) => Type::Int(ptr + 1),
36            Type::Float(ptr) => Type::Float(ptr + 1),
37            Type::Bool(ptr) => Type::Bool(ptr + 1),
38            Type::Char(ptr) => Type::Char(ptr + 1),
39            _ => return None,
40        })
41    }
42
43    pub fn sub_deref(self) -> Option<Self> {
44        Some(match self {
45            Type::Int(ptr) | Type::Float(ptr) | Type::Bool(ptr) | Type::Char(ptr) if ptr == 0 => {
46                return None
47            }
48            Type::Int(ptr) => Type::Int(ptr - 1),
49            Type::Float(ptr) => Type::Float(ptr - 1),
50            Type::Bool(ptr) => Type::Bool(ptr - 1),
51            Type::Char(ptr) => Type::Char(ptr - 1),
52            _ => return None,
53        })
54    }
55
56    pub fn ptr_count(&self) -> Option<usize> {
57        match self {
58            Type::Int(ptr) => Some(*ptr),
59            Type::Float(ptr) => Some(*ptr),
60            Type::Bool(ptr) => Some(*ptr),
61            Type::Char(ptr) => Some(*ptr),
62            Type::Unit => None,
63            Type::Never => None,
64            Type::Unknown => None,
65        }
66    }
67}
68
69#[derive(Debug, Clone, PartialEq, Eq)]
70pub struct Spanned<'src, T> {
71    pub span: Span<'src>,
72    pub inner: T,
73}
74
75#[derive(Debug, Clone, PartialEq)]
76pub struct Program<'src> {
77    pub span: Span<'src>,
78    pub functions: Vec<FunctionDefinition<'src>>,
79    pub globals: Vec<LetStmt<'src>>,
80}
81
82#[derive(Debug, Clone, PartialEq)]
83pub struct FunctionDefinition<'src> {
84    pub span: Span<'src>,
85    pub name: Spanned<'src, &'src str>,
86    pub params: Spanned<'src, Vec<Parameter<'src>>>,
87    pub return_type: Spanned<'src, Option<Type>>,
88    pub block: Block<'src>,
89}
90
91#[derive(Debug, Clone, PartialEq, Eq)]
92pub struct Parameter<'src> {
93    pub mutable: bool,
94    pub name: Spanned<'src, &'src str>,
95    pub type_: Spanned<'src, Type>,
96}
97
98#[derive(Debug, Clone, PartialEq)]
99pub struct Block<'src> {
100    pub span: Span<'src>,
101    pub stmts: Vec<Statement<'src>>,
102    pub expr: Option<Expression<'src>>,
103}
104
105impl<'src> Block<'src> {
106    /// Returns the span responsible for the block's result type
107    pub fn result_span(&self) -> Span<'src> {
108        self.expr.as_ref().map_or_else(
109            || self.stmts.last().map_or(self.span, |stmt| stmt.span()),
110            |expr| expr.span(),
111        )
112    }
113}
114
115#[derive(Debug, Clone, PartialEq)]
116pub enum Statement<'src> {
117    Let(LetStmt<'src>),
118    Return(ReturnStmt<'src>),
119    Loop(LoopStmt<'src>),
120    While(WhileStmt<'src>),
121    For(ForStmt<'src>),
122    Break(BreakStmt<'src>),
123    Continue(ContinueStmt<'src>),
124    Expr(ExprStmt<'src>),
125}
126
127impl<'src> Statement<'src> {
128    pub fn span(&self) -> Span<'src> {
129        match self {
130            Self::Let(stmt) => stmt.span,
131            Self::Return(stmt) => stmt.span,
132            Self::Loop(stmt) => stmt.span,
133            Self::While(stmt) => stmt.span,
134            Self::For(stmt) => stmt.span,
135            Self::Break(stmt) => stmt.span,
136            Self::Continue(stmt) => stmt.span,
137            Self::Expr(stmt) => stmt.span,
138        }
139    }
140}
141
142#[derive(Debug, Clone, PartialEq)]
143pub struct LetStmt<'src> {
144    pub span: Span<'src>,
145    pub mutable: bool,
146    pub name: Spanned<'src, &'src str>,
147    pub type_: Option<Spanned<'src, Type>>,
148    pub expr: Expression<'src>,
149}
150
151#[derive(Debug, Clone, PartialEq)]
152pub struct ReturnStmt<'src> {
153    pub span: Span<'src>,
154    pub expr: Option<Expression<'src>>,
155}
156
157#[derive(Debug, Clone, PartialEq)]
158pub struct LoopStmt<'src> {
159    pub span: Span<'src>,
160    pub block: Block<'src>,
161}
162
163#[derive(Debug, Clone, PartialEq)]
164pub struct WhileStmt<'src> {
165    pub span: Span<'src>,
166    pub cond: Expression<'src>,
167    pub block: Block<'src>,
168}
169
170#[derive(Debug, Clone, PartialEq)]
171pub struct ForStmt<'src> {
172    pub span: Span<'src>,
173    pub ident: Spanned<'src, &'src str>,
174    pub initializer: Expression<'src>,
175    pub cond: Expression<'src>,
176    pub update: Expression<'src>,
177    pub block: Block<'src>,
178}
179
180#[derive(Debug, Clone, PartialEq, Eq)]
181pub struct BreakStmt<'src> {
182    pub span: Span<'src>,
183}
184
185#[derive(Debug, Clone, PartialEq, Eq)]
186pub struct ContinueStmt<'src> {
187    pub span: Span<'src>,
188}
189
190#[derive(Debug, Clone, PartialEq)]
191pub struct ExprStmt<'src> {
192    pub span: Span<'src>,
193    pub expr: Expression<'src>,
194}
195
196#[derive(Debug, Clone, PartialEq)]
197pub enum Expression<'src> {
198    Block(Box<Block<'src>>),
199    If(Box<IfExpr<'src>>),
200    Int(Spanned<'src, i64>),
201    Float(Spanned<'src, f64>),
202    Bool(Spanned<'src, bool>),
203    Char(Spanned<'src, u8>),
204    Ident(Spanned<'src, &'src str>),
205    Prefix(Box<PrefixExpr<'src>>),
206    Infix(Box<InfixExpr<'src>>),
207    Assign(Box<AssignExpr<'src>>),
208    Call(Box<CallExpr<'src>>),
209    Cast(Box<CastExpr<'src>>),
210    Grouped(Spanned<'src, Box<Expression<'src>>>),
211}
212
213impl<'src> Expression<'src> {
214    pub fn span(&self) -> Span<'src> {
215        match self {
216            Self::Block(expr) => expr.span,
217            Self::If(expr) => expr.span,
218            Self::Int(expr) => expr.span,
219            Self::Float(expr) => expr.span,
220            Self::Bool(expr) => expr.span,
221            Self::Char(expr) => expr.span,
222            Self::Ident(expr) => expr.span,
223            Self::Prefix(expr) => expr.span,
224            Self::Infix(expr) => expr.span,
225            Self::Assign(expr) => expr.span,
226            Self::Call(expr) => expr.span,
227            Self::Cast(expr) => expr.span,
228            Self::Grouped(expr) => expr.span,
229        }
230    }
231}
232
233#[derive(Debug, Clone, PartialEq)]
234pub struct IfExpr<'src> {
235    pub span: Span<'src>,
236    pub cond: Expression<'src>,
237    pub then_block: Block<'src>,
238    pub else_block: Option<Block<'src>>,
239}
240
241#[derive(Debug, Clone, PartialEq)]
242pub struct PrefixExpr<'src> {
243    pub span: Span<'src>,
244    pub op: PrefixOp,
245    pub expr: Expression<'src>,
246}
247
248#[derive(Debug, Clone, Copy, PartialEq, Eq)]
249pub enum PrefixOp {
250    /// !
251    Not,
252    /// -
253    Neg,
254    /// &
255    Ref,
256    /// *
257    Deref,
258}
259
260impl Display for PrefixOp {
261    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
262        write!(
263            f,
264            "{}",
265            match self {
266                PrefixOp::Not => "!",
267                PrefixOp::Neg => "-",
268                PrefixOp::Ref => "&",
269                PrefixOp::Deref => "*",
270            }
271        )
272    }
273}
274
275#[derive(Debug, Clone, PartialEq)]
276pub struct InfixExpr<'src> {
277    pub span: Span<'src>,
278    pub lhs: Expression<'src>,
279    pub op: InfixOp,
280    pub rhs: Expression<'src>,
281}
282
283#[derive(Debug, Clone, Copy, PartialEq, Eq)]
284pub enum InfixOp {
285    /// +
286    Plus,
287    /// -
288    Minus,
289    /// *
290    Mul,
291    /// /
292    Div,
293    /// %
294    Rem,
295    /// *
296    Pow,
297
298    /// ==
299    Eq,
300    /// !=
301    Neq,
302    /// <
303    Lt,
304    /// >
305    Gt,
306    /// <=
307    Lte,
308    /// >=
309    Gte,
310
311    /// <<
312    Shl,
313    /// >>
314    Shr,
315    /// |
316    BitOr,
317    /// &
318    BitAnd,
319    /// ^
320    BitXor,
321
322    /// &&
323    And,
324    /// ||
325    Or,
326}
327
328impl From<AssignOp> for InfixOp {
329    fn from(src: AssignOp) -> Self {
330        match src {
331            AssignOp::Plus => InfixOp::Plus,
332            AssignOp::Minus => InfixOp::Minus,
333            AssignOp::Mul => InfixOp::Mul,
334            AssignOp::Div => InfixOp::Div,
335            AssignOp::Shl => InfixOp::Shl,
336            AssignOp::Shr => InfixOp::Shr,
337            AssignOp::Rem => InfixOp::Rem,
338            AssignOp::Pow => InfixOp::Pow,
339            AssignOp::BitOr => InfixOp::BitOr,
340            AssignOp::BitAnd => InfixOp::BitAnd,
341            AssignOp::BitXor => Self::BitXor,
342            AssignOp::Basic => panic!("cannot convert assign op basic to infix op"),
343        }
344    }
345}
346
347impl Display for InfixOp {
348    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
349        write!(
350            f,
351            "{}",
352            match self {
353                Self::Plus => "+",
354                Self::Minus => "-",
355                Self::Mul => "*",
356                Self::Div => "/",
357                Self::Rem => "%",
358                Self::Pow => "**",
359                Self::Eq => "==",
360                Self::Neq => "!=",
361                Self::Lt => "<",
362                Self::Gt => ">",
363                Self::Lte => "<=",
364                Self::Gte => ">=",
365                Self::Shl => "<<",
366                Self::Shr => ">>",
367                Self::BitOr => "|",
368                Self::BitAnd => "&",
369                Self::BitXor => "^",
370                Self::And => "&&",
371                Self::Or => "||",
372            }
373        )
374    }
375}
376
377#[derive(Debug, Clone, PartialEq)]
378pub struct AssignExpr<'src> {
379    pub span: Span<'src>,
380    pub assignee: Spanned<'src, &'src str>,
381    pub assignee_ptr_count: usize,
382    pub op: AssignOp,
383    pub expr: Expression<'src>,
384}
385
386#[derive(Debug, Clone, Copy, PartialEq, Eq)]
387pub enum AssignOp {
388    /// =
389    Basic,
390    /// +=
391    Plus,
392    /// -=
393    Minus,
394    /// *=
395    Mul,
396    /// /=
397    Div,
398    /// %=
399    Rem,
400    /// **=
401    Pow,
402    /// <<=
403    Shl,
404    /// >>=
405    Shr,
406    /// |=
407    BitOr,
408    /// &=
409    BitAnd,
410    /// ^=
411    BitXor,
412}
413
414impl Display for AssignOp {
415    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
416        write!(
417            f,
418            "{}=",
419            match self {
420                Self::Basic => "",
421                Self::Plus => "+",
422                Self::Minus => "-",
423                Self::Mul => "*",
424                Self::Div => "/",
425                Self::Rem => "%",
426                Self::Pow => "**",
427                Self::Shl => "<<",
428                Self::Shr => ">>",
429                Self::BitOr => "|",
430                Self::BitAnd => "&",
431                Self::BitXor => "^",
432            }
433        )
434    }
435}
436
437#[derive(Debug, Clone, PartialEq)]
438pub struct CallExpr<'src> {
439    pub span: Span<'src>,
440    pub func: Spanned<'src, &'src str>,
441    pub args: Vec<Expression<'src>>,
442}
443
444#[derive(Debug, Clone, PartialEq)]
445pub struct CastExpr<'src> {
446    pub span: Span<'src>,
447    pub expr: Expression<'src>,
448    pub type_: Spanned<'src, Type>,
449}