Skip to main content

dada_ir_ast/ast/
expr.rs

1use dada_util::{FromImpls, SalsaSerialize};
2use salsa::Update;
3use serde::Serialize;
4
5use crate::span::{Span, Spanned};
6
7use super::{AstGenericTerm, AstPath, AstTy, DeferredParse, SpanVec, SpannedIdentifier};
8
9#[derive(SalsaSerialize)]
10#[salsa::tracked(debug)]
11pub struct AstBlock<'db> {
12    #[return_ref]
13    pub statements: SpanVec<'db, AstStatement<'db>>,
14}
15
16#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Update, Debug, FromImpls, Serialize)]
17pub enum AstStatement<'db> {
18    Let(AstLetStatement<'db>),
19    Expr(AstExpr<'db>),
20}
21
22impl<'db> Spanned<'db> for AstStatement<'db> {
23    fn span(&self, db: &'db dyn crate::Db) -> Span<'db> {
24        match self {
25            AstStatement::Let(s) => s.span(db),
26            AstStatement::Expr(e) => e.span,
27        }
28    }
29}
30
31/// `let x = v`, `let x: t = v`, etc
32#[derive(SalsaSerialize)]
33#[salsa::tracked(debug)]
34pub struct AstLetStatement<'db> {
35    pub span: Span<'db>,
36    pub mutable: Option<Span<'db>>,
37    pub name: SpannedIdentifier<'db>,
38    pub ty: Option<AstTy<'db>>,
39    pub initializer: Option<AstExpr<'db>>,
40}
41
42#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Update, Debug, Serialize)]
43pub struct AstExpr<'db> {
44    pub span: Span<'db>,
45    pub kind: Box<AstExprKind<'db>>,
46}
47
48impl<'db> AstExpr<'db> {
49    pub fn new(span: Span<'db>, kind: AstExprKind<'db>) -> Self {
50        Self {
51            span,
52            kind: Box::new(kind),
53        }
54    }
55}
56
57#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Update, Debug, Serialize)]
58pub enum AstExprKind<'db> {
59    /// `{ ... }`
60    Block(AstBlock<'db>),
61
62    /// `22`
63    Literal(Literal<'db>),
64
65    /// `x`
66    Id(SpannedIdentifier<'db>),
67
68    /// `E.f`
69    ///
70    /// Note that this is not necessarily a field.
71    /// Interpretation is needed.
72    DotId(AstExpr<'db>, SpannedIdentifier<'db>),
73
74    /// `E[..]`
75    ///
76    /// Note that we cannot parse the contents of the `[..]`
77    /// until we have resolved the expression `E`.
78    SquareBracketOp(AstExpr<'db>, SquareBracketArgs<'db>),
79
80    /// `E(expr0, expr1, ..., exprN)`
81    ///
82    /// Note that the callee expression could also be
83    /// a `DotId` in which case this is a method call
84    /// as well as a `SquareBracketsOp`.
85    ParenthesisOp(AstExpr<'db>, SpanVec<'db, AstExpr<'db>>),
86
87    /// `(a, b, c)`
88    ///
89    /// Could also be `(a)`.
90    Tuple(SpanVec<'db, AstExpr<'db>>),
91
92    /// `a { field: value }`
93    Constructor(AstPath<'db>, SpanVec<'db, AstConstructorField<'db>>),
94
95    /// `return x`
96    Return(Option<AstExpr<'db>>),
97
98    /// `x.await`
99    Await {
100        future: AstExpr<'db>,
101        await_keyword: Span<'db>,
102    },
103
104    /// `x.lease`, `x.ref`, or `x.give`
105    PermissionOp {
106        value: AstExpr<'db>,
107        op: PermissionOp,
108    },
109
110    /// `a + b` etc
111    BinaryOp(SpannedBinaryOp<'db>, AstExpr<'db>, AstExpr<'db>),
112
113    /// `!foo` etc
114    UnaryOp(SpannedUnaryOp<'db>, AstExpr<'db>),
115
116    /// If/else-if chain
117    If(Vec<IfArm<'db>>),
118}
119
120#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Update, Debug, Serialize)]
121pub enum PermissionOp {
122    Mutate,
123    Reference,
124    Give,
125    Share,
126}
127
128#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Update, Debug, Serialize)]
129pub struct IfArm<'db> {
130    /// if None, this is an `else` (and should come last)
131    pub condition: Option<AstExpr<'db>>,
132
133    /// the value
134    pub result: AstBlock<'db>,
135}
136
137#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Update, Debug, Serialize)]
138pub struct SpannedBinaryOp<'db> {
139    pub span: Span<'db>,
140    pub op: AstBinaryOp,
141}
142
143#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Update, Debug, Serialize)]
144pub enum AstBinaryOp {
145    Add,
146    Sub,
147    Mul,
148    Div,
149    AndAnd,
150    OrOr,
151    GreaterThan,
152    LessThan,
153    GreaterEqual,
154    LessEqual,
155    EqualEqual,
156    Assign,
157}
158
159impl std::fmt::Display for AstBinaryOp {
160    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
161        match self {
162            AstBinaryOp::Add => write!(f, "+"),
163            AstBinaryOp::Sub => write!(f, "-"),
164            AstBinaryOp::Mul => write!(f, "*"),
165            AstBinaryOp::Div => write!(f, "/"),
166            AstBinaryOp::AndAnd => write!(f, "&&"),
167            AstBinaryOp::OrOr => write!(f, "||"),
168            AstBinaryOp::GreaterThan => write!(f, ">"),
169            AstBinaryOp::LessThan => write!(f, "<"),
170            AstBinaryOp::GreaterEqual => write!(f, ">="),
171            AstBinaryOp::LessEqual => write!(f, "<="),
172            AstBinaryOp::EqualEqual => write!(f, "=="),
173            AstBinaryOp::Assign => write!(f, "="),
174        }
175    }
176}
177
178#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Update, Debug, Serialize)]
179pub struct SpannedUnaryOp<'db> {
180    pub span: Span<'db>,
181    pub op: UnaryOp,
182}
183
184#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Update, Debug, Serialize)]
185pub enum UnaryOp {
186    Not,
187    Negate,
188}
189
190/// Created when we parse `x[..]` expressions or paths to store the `..` contents.
191/// We can't eagerly parse it because we don't yet know whether to parse it
192/// as types or expressions.
193#[derive(SalsaSerialize)]
194#[salsa::tracked(debug)]
195pub struct SquareBracketArgs<'db> {
196    #[return_ref]
197    pub deferred: DeferredParse<'db>,
198}
199
200#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Update, Debug, Serialize)]
201pub struct AstConstructorField<'db> {
202    pub name: SpannedIdentifier<'db>,
203    pub value: AstExpr<'db>,
204}
205
206#[derive(SalsaSerialize)]
207#[salsa::interned(debug)]
208pub struct Literal<'db> {
209    pub kind: LiteralKind,
210    #[return_ref]
211    pub text: String,
212}
213
214#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Update, Debug, Serialize)]
215pub enum LiteralKind {
216    Boolean,
217    Integer,
218    String,
219}
220
221#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Update, Debug, Serialize)]
222pub struct AstParenExpr<'db> {
223    pub callee: AstExpr<'db>,
224    pub generic_args: Option<SpanVec<'db, AstGenericTerm<'db>>>,
225    pub args: SpanVec<'db, AstExpr<'db>>,
226}