1#[derive(Debug, Clone, PartialEq)]
2pub enum Literal {
3 Int(i64),
4 Float(f64),
5 Str(String),
6 Bool(bool),
7 Unit,
8}
9
10#[derive(Debug, Clone, Copy, PartialEq)]
11pub enum BinOp {
12 Add,
13 Sub,
14 Mul,
15 Div,
16 Eq,
17 Neq,
18 Lt,
19 Gt,
20 Lte,
21 Gte,
22}
23
24#[derive(Debug, Clone, PartialEq)]
25pub struct MatchArm {
26 pub pattern: Pattern,
27 pub body: Box<Expr>,
28}
29
30#[derive(Debug, Clone, PartialEq)]
31pub enum Pattern {
32 Wildcard,
33 Literal(Literal),
34 Ident(String),
35 EmptyList,
37 Cons(String, String),
39 Tuple(Vec<Pattern>),
41 Constructor(String, Vec<String>),
45}
46
47#[derive(Debug, Clone, PartialEq)]
48pub enum StrPart {
49 Literal(String),
50 Parsed(Box<Expr>),
51}
52
53#[derive(Debug, Clone, PartialEq)]
54pub enum Expr {
55 Literal(Literal),
56 Ident(String),
57 Attr(Box<Expr>, String),
58 FnCall(Box<Expr>, Vec<Expr>),
59 BinOp(BinOp, Box<Expr>, Box<Expr>),
60 Match {
61 subject: Box<Expr>,
62 arms: Vec<MatchArm>,
63 line: usize,
64 },
65 Constructor(String, Option<Box<Expr>>),
66 ErrorProp(Box<Expr>),
67 InterpolatedStr(Vec<StrPart>),
68 List(Vec<Expr>),
69 Tuple(Vec<Expr>),
70 MapLiteral(Vec<(Expr, Expr)>),
72 RecordCreate {
74 type_name: String,
75 fields: Vec<(String, Expr)>,
76 },
77 RecordUpdate {
79 type_name: String,
80 base: Box<Expr>,
81 updates: Vec<(String, Expr)>,
82 },
83 TailCall(Box<(String, Vec<Expr>)>),
87 Resolved(u16),
90}
91
92#[derive(Debug, Clone, PartialEq)]
93pub enum Stmt {
94 Binding(String, Option<String>, Expr),
95 Expr(Expr),
96}
97
98#[derive(Debug, Clone, PartialEq)]
99pub enum FnBody {
100 Block(Vec<Stmt>),
101}
102
103impl FnBody {
104 pub fn from_expr(expr: Expr) -> Self {
105 Self::Block(vec![Stmt::Expr(expr)])
106 }
107
108 pub fn stmts(&self) -> &[Stmt] {
109 match self {
110 Self::Block(stmts) => stmts,
111 }
112 }
113
114 pub fn stmts_mut(&mut self) -> &mut Vec<Stmt> {
115 match self {
116 Self::Block(stmts) => stmts,
117 }
118 }
119
120 pub fn tail_expr(&self) -> Option<&Expr> {
121 match self.stmts().last() {
122 Some(Stmt::Expr(expr)) => Some(expr),
123 _ => None,
124 }
125 }
126
127 pub fn tail_expr_mut(&mut self) -> Option<&mut Expr> {
128 match self.stmts_mut().last_mut() {
129 Some(Stmt::Expr(expr)) => Some(expr),
130 _ => None,
131 }
132 }
133}
134
135#[derive(Debug, Clone, PartialEq)]
139pub struct FnResolution {
140 pub local_count: u16,
142 pub local_slots: std::rc::Rc<std::collections::HashMap<String, u16>>,
144}
145
146#[derive(Debug, Clone, PartialEq)]
147pub struct FnDef {
148 pub name: String,
149 pub line: usize,
150 pub params: Vec<(String, String)>,
151 pub return_type: String,
152 pub effects: Vec<String>,
153 pub desc: Option<String>,
154 pub body: std::rc::Rc<FnBody>,
155 pub resolution: Option<FnResolution>,
157}
158
159#[derive(Debug, Clone, PartialEq)]
160pub struct Module {
161 pub name: String,
162 pub line: usize,
163 pub depends: Vec<String>,
164 pub exposes: Vec<String>,
165 pub exposes_opaque: Vec<String>,
166 pub exposes_line: Option<usize>,
167 pub intent: String,
168}
169
170#[derive(Debug, Clone, PartialEq)]
171pub enum VerifyGivenDomain {
172 IntRange { start: i64, end: i64 },
174 Explicit(Vec<Expr>),
176}
177
178#[derive(Debug, Clone, PartialEq)]
179pub struct VerifyGiven {
180 pub name: String,
181 pub type_name: String,
182 pub domain: VerifyGivenDomain,
183}
184
185#[derive(Debug, Clone, PartialEq)]
186pub struct VerifyLaw {
187 pub name: String,
188 pub givens: Vec<VerifyGiven>,
189 pub when: Option<Expr>,
191 pub lhs: Expr,
193 pub rhs: Expr,
194 pub sample_guards: Vec<Expr>,
196}
197
198#[derive(Debug, Clone, PartialEq, Default)]
201pub struct SourceSpan {
202 pub line: usize,
203 pub col: usize,
204 pub end_line: usize,
205 pub end_col: usize,
206}
207
208#[derive(Debug, Clone, PartialEq)]
209pub enum VerifyKind {
210 Cases,
211 Law(Box<VerifyLaw>),
212}
213
214#[derive(Debug, Clone, PartialEq)]
215pub struct VerifyBlock {
216 pub fn_name: String,
217 pub line: usize,
218 pub cases: Vec<(Expr, Expr)>,
219 pub case_spans: Vec<SourceSpan>,
220 pub case_givens: Vec<Vec<(String, Expr)>>,
222 pub kind: VerifyKind,
223}
224
225impl VerifyBlock {
226 pub fn new_unspanned(
229 fn_name: String,
230 line: usize,
231 cases: Vec<(Expr, Expr)>,
232 kind: VerifyKind,
233 ) -> Self {
234 let case_spans = vec![SourceSpan::default(); cases.len()];
235 Self {
236 fn_name,
237 line,
238 cases,
239 case_spans,
240 case_givens: vec![],
241 kind,
242 }
243 }
244
245 pub fn iter_cases_with_spans(&self) -> impl Iterator<Item = (&(Expr, Expr), &SourceSpan)> {
246 debug_assert_eq!(self.cases.len(), self.case_spans.len());
247 self.cases.iter().zip(&self.case_spans)
248 }
249}
250
251#[derive(Debug, Clone, PartialEq)]
252pub struct DecisionBlock {
253 pub name: String,
254 pub line: usize,
255 pub date: String,
256 pub reason: String,
257 pub chosen: DecisionImpact,
258 pub rejected: Vec<DecisionImpact>,
259 pub impacts: Vec<DecisionImpact>,
260 pub author: Option<String>,
261}
262
263#[derive(Debug, Clone, PartialEq, Eq, Hash)]
264pub enum DecisionImpact {
265 Symbol(String),
266 Semantic(String),
267}
268
269impl DecisionImpact {
270 pub fn text(&self) -> &str {
271 match self {
272 DecisionImpact::Symbol(s) | DecisionImpact::Semantic(s) => s,
273 }
274 }
275
276 pub fn as_context_string(&self) -> String {
277 match self {
278 DecisionImpact::Symbol(s) => s.clone(),
279 DecisionImpact::Semantic(s) => format!("\"{}\"", s),
280 }
281 }
282}
283
284#[derive(Debug, Clone, PartialEq)]
287pub struct TypeVariant {
288 pub name: String,
289 pub fields: Vec<String>, }
291
292#[derive(Debug, Clone, PartialEq)]
294pub enum TypeDef {
295 Sum {
297 name: String,
298 variants: Vec<TypeVariant>,
299 line: usize,
300 },
301 Product {
303 name: String,
304 fields: Vec<(String, String)>,
305 line: usize,
306 },
307}
308
309#[derive(Debug, Clone, PartialEq)]
310pub enum TopLevel {
311 Module(Module),
312 FnDef(FnDef),
313 Verify(VerifyBlock),
314 Decision(DecisionBlock),
315 Stmt(Stmt),
316 TypeDef(TypeDef),
317}