1use serde::{Deserialize, Serialize};
7
8#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
9pub struct Program {
10 pub items: Vec<Item>,
11}
12
13#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
14pub enum Item {
15 Import(Import),
16 TypeDecl(TypeDecl),
17 FnDecl(FnDecl),
18}
19
20#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
21pub struct Import {
22 pub reference: String,
23 pub alias: String,
24}
25
26#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
27pub struct TypeDecl {
28 pub name: String,
29 pub params: Vec<String>,
30 pub definition: TypeExpr,
31}
32
33#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
34pub struct FnDecl {
35 pub name: String,
36 pub type_params: Vec<String>,
37 pub params: Vec<Param>,
38 pub effects: Vec<Effect>,
39 pub return_type: TypeExpr,
40 pub body: Block,
41 #[serde(default, skip_serializing_if = "Vec::is_empty")]
48 pub examples: Vec<Example>,
49}
50
51#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
52pub struct Example {
53 pub args: Vec<Expr>,
55 pub expected: Expr,
57}
58
59#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
60pub struct Param {
61 pub name: String,
62 pub ty: TypeExpr,
63}
64
65#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
66pub struct Effect {
67 pub name: String,
68 pub arg: Option<EffectArg>,
69}
70
71#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
72pub enum EffectArg {
73 Str(String),
74 Int(i64),
75 Ident(String),
76}
77
78#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
79pub enum TypeExpr {
80 Named { name: String, args: Vec<TypeExpr> },
83 Record(Vec<TypeField>),
84 Tuple(Vec<TypeExpr>),
85 Function {
86 params: Vec<TypeExpr>,
87 effects: Vec<Effect>,
88 ret: Box<TypeExpr>,
89 },
90 Union(Vec<UnionVariant>),
91 RecordWithSpreads {
94 spreads: Vec<String>,
95 fields: Vec<TypeField>,
96 },
97 Refined {
106 base: Box<TypeExpr>,
107 binding: String,
108 predicate: Box<Expr>,
109 },
110}
111
112#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
113pub struct TypeField {
114 pub name: String,
115 pub ty: TypeExpr,
116}
117
118#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
119pub struct UnionVariant {
120 pub name: String,
121 pub payload: Option<TypeExpr>,
123}
124
125#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
126pub struct Block {
127 pub statements: Vec<Statement>,
128 pub result: Box<Expr>,
129}
130
131#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
132pub enum Statement {
133 Let { name: String, ty: Option<TypeExpr>, value: Expr },
134 Expr(Expr),
135}
136
137#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
138pub enum Expr {
139 Lit(Literal),
140 Var(String),
141 Block(Block),
142 Call { callee: Box<Expr>, args: Vec<Expr> },
143 Pipe { left: Box<Expr>, right: Box<Expr> },
144 Try(Box<Expr>),
146 Field { value: Box<Expr>, field: String },
148 BinOp { op: BinOp, lhs: Box<Expr>, rhs: Box<Expr> },
149 UnaryOp { op: UnaryOp, expr: Box<Expr> },
150 If { cond: Box<Expr>, then_block: Block, else_block: Block },
151 Match { scrutinee: Box<Expr>, arms: Vec<Arm> },
152 RecordLit(Vec<RecordLitField>),
153 TupleLit(Vec<Expr>),
154 ListLit(Vec<Expr>),
155 Constructor { name: String, args: Vec<Expr> },
161 Lambda(Box<Lambda>),
162 Ascription { value: Box<Expr>, ty: TypeExpr },
167}
168
169#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
170pub struct Lambda {
171 pub params: Vec<Param>,
172 pub return_type: TypeExpr,
173 pub effects: Vec<Effect>,
174 pub body: Block,
175}
176
177#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
178pub struct RecordLitField {
179 pub name: String,
180 pub value: Expr,
181}
182
183#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)]
184pub enum BinOp {
185 Add, Sub, Mul, Div, Mod,
186 Eq, Neq, Lt, Lte, Gt, Gte,
187 And, Or,
188}
189
190impl BinOp {
191 pub fn precedence(self) -> u8 {
192 use BinOp::*;
193 match self {
194 Or => 1,
195 And => 2,
196 Eq | Neq | Lt | Lte | Gt | Gte => 3,
197 Add | Sub => 4,
198 Mul | Div | Mod => 5,
199 }
200 }
201
202 pub fn as_str(self) -> &'static str {
203 use BinOp::*;
204 match self {
205 Add => "+", Sub => "-", Mul => "*", Div => "/", Mod => "%",
206 Eq => "==", Neq => "!=", Lt => "<", Lte => "<=", Gt => ">", Gte => ">=",
207 And => "and", Or => "or",
208 }
209 }
210}
211
212#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)]
213pub enum UnaryOp { Neg, Not }
214
215#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
216pub struct Arm {
217 pub pattern: Pattern,
218 pub body: Expr,
219}
220
221#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
222pub enum Pattern {
223 Lit(Literal),
224 Var(String),
226 Wild,
227 Constructor { name: String, args: Vec<Pattern> },
228 Record { fields: Vec<RecordPatField>, rest: bool },
229 Tuple(Vec<Pattern>),
230}
231
232#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
233pub struct RecordPatField {
234 pub name: String,
235 pub pattern: Option<Pattern>,
237}
238
239#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
240pub enum Literal {
241 Int(i64),
242 Float(f64),
243 Str(String),
244 Bytes(Vec<u8>),
245 Bool(bool),
246 Unit,
247}