1pub type SourceLine = usize;
3
4#[derive(Debug, Clone)]
7pub struct Spanned<T> {
8 pub node: T,
9 pub line: SourceLine,
10}
11
12impl<T: PartialEq> PartialEq for Spanned<T> {
13 fn eq(&self, other: &Self) -> bool {
14 self.node == other.node
15 }
16}
17
18impl<T> Spanned<T> {
19 pub fn new(node: T, line: SourceLine) -> Self {
20 Self { node, line }
21 }
22
23 pub fn bare(node: T) -> Self {
25 Self { node, line: 0 }
26 }
27}
28
29#[derive(Debug, Clone, PartialEq)]
30pub enum Literal {
31 Int(i64),
32 Float(f64),
33 Str(String),
34 Bool(bool),
35 Unit,
36}
37
38#[derive(Debug, Clone, Copy, PartialEq)]
39pub enum BinOp {
40 Add,
41 Sub,
42 Mul,
43 Div,
44 Eq,
45 Neq,
46 Lt,
47 Gt,
48 Lte,
49 Gte,
50}
51
52#[derive(Debug, Clone, PartialEq)]
53pub struct MatchArm {
54 pub pattern: Pattern,
55 pub body: Box<Spanned<Expr>>,
56}
57
58#[derive(Debug, Clone, PartialEq)]
59pub enum Pattern {
60 Wildcard,
61 Literal(Literal),
62 Ident(String),
63 EmptyList,
65 Cons(String, String),
67 Tuple(Vec<Pattern>),
69 Constructor(String, Vec<String>),
73}
74
75#[derive(Debug, Clone, PartialEq)]
76pub enum StrPart {
77 Literal(String),
78 Parsed(Box<Spanned<Expr>>),
79}
80
81#[derive(Debug, Clone, PartialEq)]
82pub enum Expr {
83 Literal(Literal),
84 Ident(String),
85 Attr(Box<Spanned<Expr>>, String),
86 FnCall(Box<Spanned<Expr>>, Vec<Spanned<Expr>>),
87 BinOp(BinOp, Box<Spanned<Expr>>, Box<Spanned<Expr>>),
88 Match {
89 subject: Box<Spanned<Expr>>,
90 arms: Vec<MatchArm>,
91 },
92 Constructor(String, Option<Box<Spanned<Expr>>>),
93 ErrorProp(Box<Spanned<Expr>>),
94 InterpolatedStr(Vec<StrPart>),
95 List(Vec<Spanned<Expr>>),
96 Tuple(Vec<Spanned<Expr>>),
97 MapLiteral(Vec<(Spanned<Expr>, Spanned<Expr>)>),
99 RecordCreate {
101 type_name: String,
102 fields: Vec<(String, Spanned<Expr>)>,
103 },
104 RecordUpdate {
106 type_name: String,
107 base: Box<Spanned<Expr>>,
108 updates: Vec<(String, Spanned<Expr>)>,
109 },
110 TailCall(Box<(String, Vec<Spanned<Expr>>)>),
113 IndependentProduct(Vec<Spanned<Expr>>, bool),
119 Resolved(u16),
122}
123
124#[derive(Debug, Clone, PartialEq)]
125pub enum Stmt {
126 Binding(String, Option<String>, Spanned<Expr>),
127 Expr(Spanned<Expr>),
128}
129
130#[derive(Debug, Clone, PartialEq)]
131pub enum FnBody {
132 Block(Vec<Stmt>),
133}
134
135impl FnBody {
136 pub fn from_expr(expr: Spanned<Expr>) -> Self {
137 Self::Block(vec![Stmt::Expr(expr)])
138 }
139
140 pub fn stmts(&self) -> &[Stmt] {
141 match self {
142 Self::Block(stmts) => stmts,
143 }
144 }
145
146 pub fn stmts_mut(&mut self) -> &mut Vec<Stmt> {
147 match self {
148 Self::Block(stmts) => stmts,
149 }
150 }
151
152 pub fn tail_expr(&self) -> Option<&Spanned<Expr>> {
153 match self.stmts().last() {
154 Some(Stmt::Expr(expr)) => Some(expr),
155 _ => None,
156 }
157 }
158
159 pub fn tail_expr_mut(&mut self) -> Option<&mut Spanned<Expr>> {
160 match self.stmts_mut().last_mut() {
161 Some(Stmt::Expr(expr)) => Some(expr),
162 _ => None,
163 }
164 }
165}
166
167#[derive(Debug, Clone, PartialEq)]
171pub struct FnResolution {
172 pub local_count: u16,
174 pub local_slots: std::sync::Arc<std::collections::HashMap<String, u16>>,
176}
177
178#[derive(Debug, Clone, PartialEq)]
179pub struct FnDef {
180 pub name: String,
181 pub line: usize,
182 pub params: Vec<(String, String)>,
183 pub return_type: String,
184 pub effects: Vec<Spanned<String>>,
185 pub desc: Option<String>,
186 pub body: std::sync::Arc<FnBody>,
187 pub resolution: Option<FnResolution>,
189}
190
191#[derive(Debug, Clone, PartialEq)]
192pub struct Module {
193 pub name: String,
194 pub line: usize,
195 pub depends: Vec<String>,
196 pub exposes: Vec<String>,
197 pub exposes_opaque: Vec<String>,
198 pub exposes_line: Option<usize>,
199 pub intent: String,
200}
201
202#[derive(Debug, Clone, PartialEq)]
203pub enum VerifyGivenDomain {
204 IntRange { start: i64, end: i64 },
206 Explicit(Vec<Spanned<Expr>>),
208}
209
210#[derive(Debug, Clone, PartialEq)]
211pub struct VerifyGiven {
212 pub name: String,
213 pub type_name: String,
214 pub domain: VerifyGivenDomain,
215}
216
217#[derive(Debug, Clone, PartialEq)]
218pub struct VerifyLaw {
219 pub name: String,
220 pub givens: Vec<VerifyGiven>,
221 pub when: Option<Spanned<Expr>>,
223 pub lhs: Spanned<Expr>,
225 pub rhs: Spanned<Expr>,
226 pub sample_guards: Vec<Spanned<Expr>>,
228}
229
230#[derive(Debug, Clone, PartialEq, Default)]
233pub struct SourceSpan {
234 pub line: usize,
235 pub col: usize,
236 pub end_line: usize,
237 pub end_col: usize,
238}
239
240#[derive(Debug, Clone, PartialEq)]
241pub enum VerifyKind {
242 Cases,
243 Law(Box<VerifyLaw>),
244}
245
246#[derive(Debug, Clone, PartialEq)]
247pub struct VerifyBlock {
248 pub fn_name: String,
249 pub line: usize,
250 pub cases: Vec<(Spanned<Expr>, Spanned<Expr>)>,
251 pub case_spans: Vec<SourceSpan>,
252 pub case_givens: Vec<Vec<(String, Spanned<Expr>)>>,
254 pub kind: VerifyKind,
255}
256
257impl VerifyBlock {
258 pub fn new_unspanned(
261 fn_name: String,
262 line: usize,
263 cases: Vec<(Spanned<Expr>, Spanned<Expr>)>,
264 kind: VerifyKind,
265 ) -> Self {
266 let case_spans = vec![SourceSpan::default(); cases.len()];
267 Self {
268 fn_name,
269 line,
270 cases,
271 case_spans,
272 case_givens: vec![],
273 kind,
274 }
275 }
276
277 pub fn iter_cases_with_spans(
278 &self,
279 ) -> impl Iterator<Item = (&(Spanned<Expr>, Spanned<Expr>), &SourceSpan)> {
280 debug_assert_eq!(self.cases.len(), self.case_spans.len());
281 self.cases.iter().zip(&self.case_spans)
282 }
283}
284
285#[derive(Debug, Clone, PartialEq)]
286pub struct DecisionBlock {
287 pub name: String,
288 pub line: usize,
289 pub date: String,
290 pub reason: String,
291 pub chosen: Spanned<DecisionImpact>,
292 pub rejected: Vec<Spanned<DecisionImpact>>,
293 pub impacts: Vec<Spanned<DecisionImpact>>,
294 pub author: Option<String>,
295}
296
297#[derive(Debug, Clone, PartialEq, Eq, Hash)]
298pub enum DecisionImpact {
299 Symbol(String),
300 Semantic(String),
301}
302
303impl DecisionImpact {
304 pub fn text(&self) -> &str {
305 match self {
306 DecisionImpact::Symbol(s) | DecisionImpact::Semantic(s) => s,
307 }
308 }
309
310 pub fn as_context_string(&self) -> String {
311 match self {
312 DecisionImpact::Symbol(s) => s.clone(),
313 DecisionImpact::Semantic(s) => format!("\"{}\"", s),
314 }
315 }
316}
317
318#[derive(Debug, Clone, PartialEq)]
321pub struct TypeVariant {
322 pub name: String,
323 pub fields: Vec<String>, }
325
326#[derive(Debug, Clone, PartialEq)]
328pub enum TypeDef {
329 Sum {
331 name: String,
332 variants: Vec<TypeVariant>,
333 line: usize,
334 },
335 Product {
337 name: String,
338 fields: Vec<(String, String)>,
339 line: usize,
340 },
341}
342
343#[derive(Debug, Clone, PartialEq)]
344pub enum TopLevel {
345 Module(Module),
346 FnDef(FnDef),
347 Verify(VerifyBlock),
348 Decision(DecisionBlock),
349 Stmt(Stmt),
350 TypeDef(TypeDef),
351}