1use crate::token::Span;
4
5#[derive(Debug, Clone)]
7pub struct Module {
8 pub name: Ident,
10 pub decls: Vec<Decl>,
12 pub span: Span,
14}
15
16#[derive(Debug, Clone)]
18pub struct Ident {
19 pub name: String,
21 pub span: Span,
23}
24
25impl Ident {
26 pub fn new(name: impl Into<String>, span: Span) -> Self {
27 Self {
28 name: name.into(),
29 span,
30 }
31 }
32}
33
34#[derive(Debug, Clone)]
36pub enum Decl {
37 Use(UseDecl),
39 Const(ConstDecl),
41 Var(VarDecl),
43 Type(TypeDecl),
45 Func(FuncDecl),
47 Init(InitDecl),
49 Action(ActionDecl),
51 Invariant(InvariantDecl),
53 Property(PropertyDecl),
55 Fairness(FairnessDecl),
57}
58
59impl Decl {
60 pub fn span(&self) -> Span {
61 match self {
62 Decl::Use(d) => d.span,
63 Decl::Const(d) => d.span,
64 Decl::Var(d) => d.span,
65 Decl::Type(d) => d.span,
66 Decl::Func(d) => d.span,
67 Decl::Init(d) => d.span,
68 Decl::Action(d) => d.span,
69 Decl::Invariant(d) => d.span,
70 Decl::Property(d) => d.span,
71 Decl::Fairness(d) => d.span,
72 }
73 }
74}
75
76#[derive(Debug, Clone)]
78pub struct UseDecl {
79 pub module: Ident,
80 pub span: Span,
81}
82
83#[derive(Debug, Clone)]
85pub enum ConstValue {
86 Type(TypeExpr),
88 Scalar(i64),
90}
91
92#[derive(Debug, Clone)]
94pub struct ConstDecl {
95 pub name: Ident,
96 pub value: ConstValue,
97 pub span: Span,
98}
99
100#[derive(Debug, Clone)]
102pub struct VarDecl {
103 pub name: Ident,
104 pub ty: TypeExpr,
105 pub span: Span,
106}
107
108#[derive(Debug, Clone)]
110pub struct TypeDecl {
111 pub name: Ident,
112 pub ty: TypeExpr,
113 pub span: Span,
114}
115
116#[derive(Debug, Clone)]
120pub struct FuncDecl {
121 pub name: Ident,
122 pub params: Vec<FuncParam>,
123 pub body: Expr,
124 pub span: Span,
125}
126
127#[derive(Debug, Clone)]
129pub struct FuncParam {
130 pub name: Ident,
131 pub span: Span,
132}
133
134#[derive(Debug, Clone)]
136pub struct InitDecl {
137 pub body: Expr,
138 pub span: Span,
139}
140
141#[derive(Debug, Clone)]
143pub struct ActionDecl {
144 pub name: Ident,
145 pub params: Vec<Param>,
146 pub body: ActionBody,
147 pub span: Span,
148}
149
150#[derive(Debug, Clone)]
152pub struct ActionBody {
153 pub requires: Vec<Expr>,
155 pub effect: Option<Expr>,
157 pub span: Span,
158}
159
160#[derive(Debug, Clone)]
162pub struct Param {
163 pub name: Ident,
164 pub ty: TypeExpr,
165 pub span: Span,
166}
167
168#[derive(Debug, Clone)]
170pub struct InvariantDecl {
171 pub name: Ident,
172 pub body: Expr,
173 pub span: Span,
174}
175
176#[derive(Debug, Clone)]
178pub struct PropertyDecl {
179 pub name: Ident,
180 pub body: Expr,
181 pub span: Span,
182}
183
184#[derive(Debug, Clone)]
186pub struct FairnessDecl {
187 pub constraints: Vec<FairnessConstraint>,
188 pub span: Span,
189}
190
191#[derive(Debug, Clone)]
193pub struct FairnessConstraint {
194 pub kind: FairnessKind,
195 pub action: Ident,
196 pub span: Span,
197}
198
199#[derive(Debug, Clone, Copy, PartialEq, Eq)]
201pub enum FairnessKind {
202 Weak,
203 Strong,
204}
205
206#[derive(Debug, Clone)]
208pub enum TypeExpr {
209 Named(Ident),
211 Set(Box<TypeExpr>, Span),
213 Seq(Box<TypeExpr>, Span),
215 Dict(Box<TypeExpr>, Box<TypeExpr>, Span),
217 Option(Box<TypeExpr>, Span),
219 Range(Box<Expr>, Box<Expr>, Span),
221 Tuple(Vec<TypeExpr>, Span),
223}
224
225impl TypeExpr {
226 pub fn span(&self) -> Span {
227 match self {
228 TypeExpr::Named(id) => id.span,
229 TypeExpr::Set(_, span) => *span,
230 TypeExpr::Seq(_, span) => *span,
231 TypeExpr::Dict(_, _, span) => *span,
232 TypeExpr::Option(_, span) => *span,
233 TypeExpr::Range(_, _, span) => *span,
234 TypeExpr::Tuple(_, span) => *span,
235 }
236 }
237}
238
239#[derive(Debug, Clone)]
241pub struct Expr {
242 pub kind: ExprKind,
243 pub span: Span,
244}
245
246impl Expr {
247 pub fn new(kind: ExprKind, span: Span) -> Self {
248 Self { kind, span }
249 }
250}
251
252#[derive(Debug, Clone)]
254pub enum ExprKind {
255 Bool(bool),
257 Int(i64),
259 String(String),
261 Ident(String),
263 Primed(String),
265
266 Binary {
268 op: BinOp,
269 left: Box<Expr>,
270 right: Box<Expr>,
271 },
272 Unary { op: UnaryOp, operand: Box<Expr> },
274
275 Index { base: Box<Expr>, index: Box<Expr> },
277 Slice {
279 base: Box<Expr>,
280 lo: Box<Expr>,
281 hi: Box<Expr>,
282 },
283 Field { base: Box<Expr>, field: Ident },
285 Call { func: Box<Expr>, args: Vec<Expr> },
287
288 SetLit(Vec<Expr>),
290 SeqLit(Vec<Expr>),
292 TupleLit(Vec<Expr>),
294 DictLit(Vec<(Expr, Expr)>),
296 FnLit {
298 var: Ident,
299 domain: Box<Expr>,
300 body: Box<Expr>,
301 },
302
303 SetComprehension {
305 element: Box<Expr>,
306 var: Ident,
307 domain: Box<Expr>,
308 filter: Option<Box<Expr>>,
309 },
310
311 RecordUpdate {
313 base: Box<Expr>,
314 updates: Vec<RecordFieldUpdate>,
315 },
316
317 Quantifier {
319 kind: QuantifierKind,
320 bindings: Vec<Binding>,
321 body: Box<Expr>,
322 },
323 Choose {
325 var: Ident,
326 domain: Box<Expr>,
327 predicate: Box<Expr>,
328 },
329 Fix { var: Ident, predicate: Box<Expr> },
331
332 Let {
334 var: Ident,
335 value: Box<Expr>,
336 body: Box<Expr>,
337 },
338 If {
340 cond: Box<Expr>,
341 then_branch: Box<Expr>,
342 else_branch: Box<Expr>,
343 },
344
345 Require(Box<Expr>),
347 Changes(Ident),
349 Enabled(Ident),
351
352 SeqHead(Box<Expr>),
354 SeqTail(Box<Expr>),
356 Len(Box<Expr>),
358 Keys(Box<Expr>),
360 Values(Box<Expr>),
362 BigUnion(Box<Expr>),
364 Powerset(Box<Expr>),
366
367 Always(Box<Expr>),
369 Eventually(Box<Expr>),
371 LeadsTo { left: Box<Expr>, right: Box<Expr> },
373
374 Range { lo: Box<Expr>, hi: Box<Expr> },
376
377 Paren(Box<Expr>),
379}
380
381#[derive(Debug, Clone)]
383pub enum RecordFieldUpdate {
384 Field { name: Ident, value: Expr },
386 Dynamic { key: Expr, value: Expr },
388}
389
390#[derive(Debug, Clone, Copy, PartialEq, Eq)]
392pub enum BinOp {
393 And,
395 Or,
396 Implies,
397 Iff,
398
399 Eq,
401 Ne,
402 Lt,
403 Le,
404 Gt,
405 Ge,
406
407 Add,
409 Sub,
410 Mul,
411 Div,
412 Mod,
413
414 In,
416 NotIn,
417 Union,
418 Intersect,
419 Diff,
420 SubsetOf,
421
422 Concat,
424}
425
426impl BinOp {
427 pub fn precedence(self) -> u8 {
429 match self {
430 BinOp::Iff => 1,
431 BinOp::Implies => 2,
432 BinOp::Or => 3,
433 BinOp::And => 4,
434 BinOp::Eq | BinOp::Ne | BinOp::Lt | BinOp::Le | BinOp::Gt | BinOp::Ge => 5,
435 BinOp::In | BinOp::NotIn | BinOp::SubsetOf => 5,
436 BinOp::Union | BinOp::Diff | BinOp::Concat => 6,
437 BinOp::Add | BinOp::Sub => 6,
438 BinOp::Intersect => 7,
439 BinOp::Mul | BinOp::Div | BinOp::Mod => 7,
440 }
441 }
442
443 pub fn is_right_assoc(self) -> bool {
445 matches!(self, BinOp::Implies | BinOp::Iff)
446 }
447}
448
449#[derive(Debug, Clone, Copy, PartialEq, Eq)]
451pub enum UnaryOp {
452 Not,
453 Neg,
454}
455
456#[derive(Debug, Clone, Copy, PartialEq, Eq)]
458pub enum QuantifierKind {
459 Forall,
460 Exists,
461}
462
463#[derive(Debug, Clone)]
465pub struct Binding {
466 pub var: Ident,
467 pub domain: Expr,
468 pub span: Span,
469}
470
471#[cfg(test)]
472mod tests {
473 use super::*;
474
475 #[test]
476 fn test_binop_precedence() {
477 assert!(BinOp::Mul.precedence() > BinOp::Add.precedence());
479 assert!(BinOp::Add.precedence() > BinOp::Eq.precedence());
481 assert!(BinOp::Eq.precedence() > BinOp::And.precedence());
483 assert!(BinOp::And.precedence() > BinOp::Or.precedence());
485 assert!(BinOp::Or.precedence() > BinOp::Implies.precedence());
487 }
488}