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 pub effects: Option<Vec<String>>,
246 pub effects_line: Option<usize>,
247}
248
249#[derive(Debug, Clone, PartialEq)]
250pub enum VerifyGivenDomain {
251 IntRange { start: i64, end: i64 },
253 Explicit(Vec<Spanned<Expr>>),
255}
256
257#[derive(Debug, Clone, PartialEq)]
258pub struct VerifyGiven {
259 pub name: String,
260 pub type_name: String,
261 pub domain: VerifyGivenDomain,
262}
263
264#[derive(Debug, Clone, PartialEq)]
265pub struct VerifyLaw {
266 pub name: String,
267 pub givens: Vec<VerifyGiven>,
268 pub when: Option<Spanned<Expr>>,
270 pub lhs: Spanned<Expr>,
272 pub rhs: Spanned<Expr>,
273 pub sample_guards: Vec<Spanned<Expr>>,
275}
276
277#[derive(Debug, Clone, PartialEq, Default)]
280pub struct SourceSpan {
281 pub line: usize,
282 pub col: usize,
283 pub end_line: usize,
284 pub end_col: usize,
285}
286
287#[derive(Debug, Clone, PartialEq)]
288pub enum VerifyKind {
289 Cases,
290 Law(Box<VerifyLaw>),
291}
292
293#[derive(Debug, Clone, PartialEq)]
294pub struct VerifyBlock {
295 pub fn_name: String,
296 pub line: usize,
297 pub cases: Vec<(Spanned<Expr>, Spanned<Expr>)>,
298 pub case_spans: Vec<SourceSpan>,
299 pub case_givens: Vec<Vec<(String, Spanned<Expr>)>>,
301 pub case_hostile_origins: Vec<bool>,
308 pub case_hostile_profiles: Vec<Vec<(String, String)>>,
316 pub kind: VerifyKind,
317 pub trace: bool,
323 pub cases_givens: Vec<VerifyGiven>,
329}
330
331impl VerifyBlock {
332 pub fn new_unspanned(
335 fn_name: String,
336 line: usize,
337 cases: Vec<(Spanned<Expr>, Spanned<Expr>)>,
338 kind: VerifyKind,
339 ) -> Self {
340 let case_spans = vec![SourceSpan::default(); cases.len()];
341 let case_hostile_origins = vec![false; cases.len()];
342 let case_hostile_profiles = vec![Vec::new(); cases.len()];
343 Self {
344 fn_name,
345 line,
346 cases,
347 case_spans,
348 case_givens: vec![],
349 case_hostile_origins,
350 case_hostile_profiles,
351 kind,
352 trace: false,
353 cases_givens: vec![],
354 }
355 }
356
357 pub fn iter_cases_with_spans(
358 &self,
359 ) -> impl Iterator<Item = (&(Spanned<Expr>, Spanned<Expr>), &SourceSpan)> {
360 debug_assert_eq!(self.cases.len(), self.case_spans.len());
361 self.cases.iter().zip(&self.case_spans)
362 }
363}
364
365#[derive(Debug, Clone, PartialEq)]
366pub struct DecisionBlock {
367 pub name: String,
368 pub line: usize,
369 pub date: String,
370 pub reason: String,
371 pub chosen: Spanned<DecisionImpact>,
372 pub rejected: Vec<Spanned<DecisionImpact>>,
373 pub impacts: Vec<Spanned<DecisionImpact>>,
374 pub author: Option<String>,
375}
376
377#[derive(Debug, Clone, PartialEq, Eq, Hash)]
378pub enum DecisionImpact {
379 Symbol(String),
380 Semantic(String),
381}
382
383impl DecisionImpact {
384 pub fn text(&self) -> &str {
385 match self {
386 DecisionImpact::Symbol(s) | DecisionImpact::Semantic(s) => s,
387 }
388 }
389
390 pub fn as_context_string(&self) -> String {
391 match self {
392 DecisionImpact::Symbol(s) => s.clone(),
393 DecisionImpact::Semantic(s) => format!("\"{}\"", s),
394 }
395 }
396}
397
398#[derive(Debug, Clone, PartialEq)]
401pub struct TypeVariant {
402 pub name: String,
403 pub fields: Vec<String>, }
405
406#[derive(Debug, Clone, PartialEq)]
408pub enum TypeDef {
409 Sum {
411 name: String,
412 variants: Vec<TypeVariant>,
413 line: usize,
414 },
415 Product {
417 name: String,
418 fields: Vec<(String, String)>,
419 line: usize,
420 },
421}
422
423#[derive(Debug, Clone, PartialEq)]
424pub enum TopLevel {
425 Module(Module),
426 FnDef(FnDef),
427 Verify(VerifyBlock),
428 Decision(DecisionBlock),
429 Stmt(Stmt),
430 TypeDef(TypeDef),
431}