1pub type SourceLine = usize;
3
4#[derive(Debug, Clone, Copy, Default)]
8pub struct AnnotBool(pub bool);
9
10impl PartialEq for AnnotBool {
11 fn eq(&self, _: &Self) -> bool {
12 true
13 }
14}
15
16impl From<bool> for AnnotBool {
17 fn from(b: bool) -> Self {
18 Self(b)
19 }
20}
21
22#[derive(Debug, Clone)]
25pub struct Spanned<T> {
26 pub node: T,
27 pub line: SourceLine,
28}
29
30impl<T: PartialEq> PartialEq for Spanned<T> {
31 fn eq(&self, other: &Self) -> bool {
32 self.node == other.node
33 }
34}
35
36impl<T> Spanned<T> {
37 pub fn new(node: T, line: SourceLine) -> Self {
38 Self { node, line }
39 }
40
41 pub fn bare(node: T) -> Self {
43 Self { node, line: 0 }
44 }
45}
46
47#[derive(Debug, Clone, PartialEq)]
48pub enum Literal {
49 Int(i64),
50 Float(f64),
51 Str(String),
52 Bool(bool),
53 Unit,
54}
55
56#[derive(Debug, Clone, Copy, PartialEq)]
57pub enum BinOp {
58 Add,
59 Sub,
60 Mul,
61 Div,
62 Eq,
63 Neq,
64 Lt,
65 Gt,
66 Lte,
67 Gte,
68}
69
70#[derive(Debug, Clone, PartialEq)]
71pub struct MatchArm {
72 pub pattern: Pattern,
73 pub body: Box<Spanned<Expr>>,
74}
75
76#[derive(Debug, Clone, PartialEq)]
77pub enum Pattern {
78 Wildcard,
79 Literal(Literal),
80 Ident(String),
81 EmptyList,
83 Cons(String, String),
85 Tuple(Vec<Pattern>),
87 Constructor(String, Vec<String>),
91}
92
93#[derive(Debug, Clone, PartialEq)]
94pub enum StrPart {
95 Literal(String),
96 Parsed(Box<Spanned<Expr>>),
97}
98
99#[derive(Debug, Clone, PartialEq)]
101pub struct TailCallData {
102 pub target: String,
104 pub args: Vec<Spanned<Expr>>,
106}
107
108impl TailCallData {
109 pub fn new(target: String, args: Vec<Spanned<Expr>>) -> Self {
110 Self { target, args }
111 }
112}
113
114#[derive(Debug, Clone, PartialEq)]
115pub enum Expr {
116 Literal(Literal),
117 Ident(String),
118 Attr(Box<Spanned<Expr>>, String),
119 FnCall(Box<Spanned<Expr>>, Vec<Spanned<Expr>>),
120 BinOp(BinOp, Box<Spanned<Expr>>, Box<Spanned<Expr>>),
121 Match {
122 subject: Box<Spanned<Expr>>,
123 arms: Vec<MatchArm>,
124 },
125 Constructor(String, Option<Box<Spanned<Expr>>>),
126 ErrorProp(Box<Spanned<Expr>>),
127 InterpolatedStr(Vec<StrPart>),
128 List(Vec<Spanned<Expr>>),
129 Tuple(Vec<Spanned<Expr>>),
130 MapLiteral(Vec<(Spanned<Expr>, Spanned<Expr>)>),
132 RecordCreate {
134 type_name: String,
135 fields: Vec<(String, Spanned<Expr>)>,
136 },
137 RecordUpdate {
139 type_name: String,
140 base: Box<Spanned<Expr>>,
141 updates: Vec<(String, Spanned<Expr>)>,
142 },
143 TailCall(Box<TailCallData>),
147 IndependentProduct(Vec<Spanned<Expr>>, bool),
153 Resolved {
158 slot: u16,
159 name: String,
160 last_use: AnnotBool,
161 },
162}
163
164#[derive(Debug, Clone, PartialEq)]
165pub enum Stmt {
166 Binding(String, Option<String>, Spanned<Expr>),
167 Expr(Spanned<Expr>),
168}
169
170#[derive(Debug, Clone, PartialEq)]
171pub enum FnBody {
172 Block(Vec<Stmt>),
173}
174
175impl FnBody {
176 pub fn from_expr(expr: Spanned<Expr>) -> Self {
177 Self::Block(vec![Stmt::Expr(expr)])
178 }
179
180 pub fn stmts(&self) -> &[Stmt] {
181 match self {
182 Self::Block(stmts) => stmts,
183 }
184 }
185
186 pub fn stmts_mut(&mut self) -> &mut Vec<Stmt> {
187 match self {
188 Self::Block(stmts) => stmts,
189 }
190 }
191
192 pub fn tail_expr(&self) -> Option<&Spanned<Expr>> {
193 match self.stmts().last() {
194 Some(Stmt::Expr(expr)) => Some(expr),
195 _ => None,
196 }
197 }
198
199 pub fn tail_expr_mut(&mut self) -> Option<&mut Spanned<Expr>> {
200 match self.stmts_mut().last_mut() {
201 Some(Stmt::Expr(expr)) => Some(expr),
202 _ => None,
203 }
204 }
205}
206
207#[derive(Debug, Clone, PartialEq)]
211pub struct FnResolution {
212 pub local_count: u16,
214 pub local_slots: std::sync::Arc<std::collections::HashMap<String, u16>>,
216}
217
218#[derive(Debug, Clone, PartialEq)]
219pub struct FnDef {
220 pub name: String,
221 pub line: usize,
222 pub params: Vec<(String, String)>,
223 pub return_type: String,
224 pub effects: Vec<Spanned<String>>,
225 pub desc: Option<String>,
226 pub body: std::sync::Arc<FnBody>,
227 pub resolution: Option<FnResolution>,
229}
230
231#[derive(Debug, Clone, PartialEq)]
232pub struct Module {
233 pub name: String,
234 pub line: usize,
235 pub depends: Vec<String>,
236 pub exposes: Vec<String>,
237 pub exposes_opaque: Vec<String>,
238 pub exposes_line: Option<usize>,
239 pub intent: String,
240}
241
242#[derive(Debug, Clone, PartialEq)]
243pub enum VerifyGivenDomain {
244 IntRange { start: i64, end: i64 },
246 Explicit(Vec<Spanned<Expr>>),
248}
249
250#[derive(Debug, Clone, PartialEq)]
251pub struct VerifyGiven {
252 pub name: String,
253 pub type_name: String,
254 pub domain: VerifyGivenDomain,
255}
256
257#[derive(Debug, Clone, PartialEq)]
258pub struct VerifyLaw {
259 pub name: String,
260 pub givens: Vec<VerifyGiven>,
261 pub when: Option<Spanned<Expr>>,
263 pub lhs: Spanned<Expr>,
265 pub rhs: Spanned<Expr>,
266 pub sample_guards: Vec<Spanned<Expr>>,
268}
269
270#[derive(Debug, Clone, PartialEq, Default)]
273pub struct SourceSpan {
274 pub line: usize,
275 pub col: usize,
276 pub end_line: usize,
277 pub end_col: usize,
278}
279
280#[derive(Debug, Clone, PartialEq)]
281pub enum VerifyKind {
282 Cases,
283 Law(Box<VerifyLaw>),
284}
285
286#[derive(Debug, Clone, PartialEq)]
287pub struct VerifyBlock {
288 pub fn_name: String,
289 pub line: usize,
290 pub cases: Vec<(Spanned<Expr>, Spanned<Expr>)>,
291 pub case_spans: Vec<SourceSpan>,
292 pub case_givens: Vec<Vec<(String, Spanned<Expr>)>>,
294 pub kind: VerifyKind,
295}
296
297impl VerifyBlock {
298 pub fn new_unspanned(
301 fn_name: String,
302 line: usize,
303 cases: Vec<(Spanned<Expr>, Spanned<Expr>)>,
304 kind: VerifyKind,
305 ) -> Self {
306 let case_spans = vec![SourceSpan::default(); cases.len()];
307 Self {
308 fn_name,
309 line,
310 cases,
311 case_spans,
312 case_givens: vec![],
313 kind,
314 }
315 }
316
317 pub fn iter_cases_with_spans(
318 &self,
319 ) -> impl Iterator<Item = (&(Spanned<Expr>, Spanned<Expr>), &SourceSpan)> {
320 debug_assert_eq!(self.cases.len(), self.case_spans.len());
321 self.cases.iter().zip(&self.case_spans)
322 }
323}
324
325#[derive(Debug, Clone, PartialEq)]
326pub struct DecisionBlock {
327 pub name: String,
328 pub line: usize,
329 pub date: String,
330 pub reason: String,
331 pub chosen: Spanned<DecisionImpact>,
332 pub rejected: Vec<Spanned<DecisionImpact>>,
333 pub impacts: Vec<Spanned<DecisionImpact>>,
334 pub author: Option<String>,
335}
336
337#[derive(Debug, Clone, PartialEq, Eq, Hash)]
338pub enum DecisionImpact {
339 Symbol(String),
340 Semantic(String),
341}
342
343impl DecisionImpact {
344 pub fn text(&self) -> &str {
345 match self {
346 DecisionImpact::Symbol(s) | DecisionImpact::Semantic(s) => s,
347 }
348 }
349
350 pub fn as_context_string(&self) -> String {
351 match self {
352 DecisionImpact::Symbol(s) => s.clone(),
353 DecisionImpact::Semantic(s) => format!("\"{}\"", s),
354 }
355 }
356}
357
358#[derive(Debug, Clone, PartialEq)]
361pub struct TypeVariant {
362 pub name: String,
363 pub fields: Vec<String>, }
365
366#[derive(Debug, Clone, PartialEq)]
368pub enum TypeDef {
369 Sum {
371 name: String,
372 variants: Vec<TypeVariant>,
373 line: usize,
374 },
375 Product {
377 name: String,
378 fields: Vec<(String, String)>,
379 line: usize,
380 },
381}
382
383#[derive(Debug, Clone, PartialEq)]
384pub enum TopLevel {
385 Module(Module),
386 FnDef(FnDef),
387 Verify(VerifyBlock),
388 Decision(DecisionBlock),
389 Stmt(Stmt),
390 TypeDef(TypeDef),
391}