1use crate::source::{FileId, Span};
6
7#[derive(Clone, Debug)]
8pub struct Program {
9 pub file: FileId,
10 pub decls: Vec<Decl>,
11}
12
13#[derive(Clone, Debug)]
14pub struct Ident {
15 pub name: String,
16 pub span: Span,
17}
18
19#[derive(Clone, Debug)]
21pub struct Path {
22 pub segs: Vec<Ident>,
23 pub span: Span,
24}
25
26impl Path {
27 pub fn single(id: Ident) -> Self {
28 Path { span: id.span, segs: vec![id] }
29 }
30
31 pub fn is_single(&self, name: &str) -> bool {
32 self.segs.len() == 1 && self.segs[0].name == name
33 }
34
35 pub fn dotted(&self) -> String {
36 self.segs.iter().map(|s| s.name.as_str()).collect::<Vec<_>>().join(".")
37 }
38}
39
40#[derive(Clone, Debug)]
41pub enum Decl {
42 Import { path: String, alias: Ident, span: Span },
44 Const { name: Ident, ty: Option<Ty>, value: Expr, span: Span },
46 StaticAssert { cond: Expr, span: Span },
48 Dim { name: Ident, bound: Option<Expr>, span: Span },
50 TypeAlias { name: Ident, ty: Ty, span: Span },
52 Module(ModuleDecl),
53 Fn(FnDecl),
54 Optimizer { name: Ident, items: Vec<ConfigItem>, span: Span },
56 Training { items: Vec<ConfigItem>, span: Span },
58 Inference { items: Vec<ConfigItem>, span: Span },
60 Effect { name: Ident, span: Span },
62 Model { name: Ident, body: ModExpr, span: Span },
64}
65
66impl Decl {
67 pub fn span(&self) -> Span {
68 match self {
69 Decl::Import { span, .. }
70 | Decl::Const { span, .. }
71 | Decl::StaticAssert { span, .. }
72 | Decl::Dim { span, .. }
73 | Decl::TypeAlias { span, .. }
74 | Decl::Optimizer { span, .. }
75 | Decl::Training { span, .. }
76 | Decl::Inference { span, .. }
77 | Decl::Effect { span, .. }
78 | Decl::Model { span, .. } => *span,
79 Decl::Module(m) => m.span,
80 Decl::Fn(f) => f.span,
81 }
82 }
83
84 pub fn name(&self) -> Option<&Ident> {
85 match self {
86 Decl::Import { alias, .. } => Some(alias),
87 Decl::Const { name, .. }
88 | Decl::Dim { name, .. }
89 | Decl::TypeAlias { name, .. }
90 | Decl::Optimizer { name, .. }
91 | Decl::Effect { name, .. }
92 | Decl::Model { name, .. } => Some(name),
93 Decl::Module(m) => Some(&m.name),
94 Decl::Fn(f) => Some(&f.name),
95 Decl::StaticAssert { .. } | Decl::Training { .. } | Decl::Inference { .. } => None,
96 }
97 }
98}
99
100#[derive(Clone, Debug)]
101pub struct ModuleDecl {
102 pub name: Ident,
103 pub typarams: Vec<TyParam>,
104 pub members: Vec<Member>,
105 pub span: Span,
106}
107
108#[derive(Clone, Debug)]
110pub struct TyParam {
111 pub name: Ident,
112 pub kind: Ident,
114}
115
116#[derive(Clone, Debug)]
117pub enum Member {
118 Param { names: Vec<Ident>, ty: Ty, init: Option<Expr>, span: Span },
120 Use { names: Vec<Ident>, module: ModExpr, span: Span },
122 Fn(FnDecl),
123}
124
125#[derive(Clone, Debug)]
128pub enum ModExpr {
129 App { path: Path, dim_args: Vec<Expr>, mod_args: Vec<ModExpr>, span: Span },
130 Compose { parts: Vec<ModExpr>, span: Span },
131}
132
133impl ModExpr {
134 pub fn span(&self) -> Span {
135 match self {
136 ModExpr::App { span, .. } | ModExpr::Compose { span, .. } => *span,
137 }
138 }
139}
140
141#[derive(Clone, Debug)]
142pub struct FnDecl {
143 pub name: Ident,
144 pub typarams: Vec<TyParam>,
145 pub params: Vec<Param>,
146 pub ret: Option<Ty>,
147 pub effects: Vec<Ident>,
149 pub body: Expr,
150 pub span: Span,
151}
152
153#[derive(Clone, Debug)]
154pub struct Param {
155 pub name: Ident,
156 pub ty: Option<Ty>,
157 pub default: Option<Expr>,
158 pub axis: bool,
160 pub span: Span,
161}
162
163#[derive(Clone, Debug)]
164pub enum ConfigItem {
165 Field { name: Ident, ty: Option<Ty>, value: Expr, span: Span },
167 Checkpoint { every: Expr, to: String, span: Span },
169}
170
171#[derive(Clone, Debug)]
172pub enum Ty {
173 Real { axes: Vec<AxisSpec>, span: Span },
175 Idx { bound: Box<Expr>, axes: Vec<AxisSpec>, span: Span },
177 Bool { axes: Vec<AxisSpec>, span: Span },
181 Param { inner: Box<Ty>, span: Span },
183 Params { module: Path, span: Span },
185 Named { path: Path, args: Vec<Expr>, span: Span },
187 Tuple { elems: Vec<Ty>, span: Span },
188}
189
190impl Ty {
191 pub fn span(&self) -> Span {
192 match self {
193 Ty::Real { span, .. }
194 | Ty::Idx { span, .. }
195 | Ty::Bool { span, .. }
196 | Ty::Param { span, .. }
197 | Ty::Params { span, .. }
198 | Ty::Named { span, .. }
199 | Ty::Tuple { span, .. } => *span,
200 }
201 }
202}
203
204#[derive(Clone, Debug)]
205pub enum AxisSpec {
206 Axis { name: Option<Ident>, dim: Expr },
208 Ellipsis { span: Span },
210}
211
212#[derive(Clone, Debug)]
213pub enum Expr {
214 Lit { lit: Lit, span: Span },
215 Var { path: Path },
216 Let { pat: Pat, init: Box<Expr>, body: Box<Expr>, span: Span },
218 Lambda { pat: Pat, body: Box<Expr>, span: Span },
220 Call { callee: Box<Expr>, args: Vec<Arg>, span: Span },
221 Field { base: Box<Expr>, field: Ident, span: Span },
223 Index { base: Box<Expr>, sels: Vec<IndexSel>, span: Span },
225 Inst { base: Box<Expr>, args: Vec<Expr>, span: Span },
227 Ein { axes: Vec<Ident>, body: Box<Expr>, span: Span },
229 Binary { op: BinOp, lhs: Box<Expr>, rhs: Box<Expr>, span: Span },
230 Unary { op: UnOp, expr: Box<Expr>, span: Span },
231 Ascribe { expr: Box<Expr>, ty: Ty, span: Span },
233 Tuple { elems: Vec<Expr>, span: Span },
234}
235
236impl Expr {
237 pub fn span(&self) -> Span {
238 match self {
239 Expr::Lit { span, .. }
240 | Expr::Let { span, .. }
241 | Expr::Lambda { span, .. }
242 | Expr::Call { span, .. }
243 | Expr::Field { span, .. }
244 | Expr::Index { span, .. }
245 | Expr::Inst { span, .. }
246 | Expr::Ein { span, .. }
247 | Expr::Binary { span, .. }
248 | Expr::Unary { span, .. }
249 | Expr::Ascribe { span, .. }
250 | Expr::Tuple { span, .. } => *span,
251 Expr::Var { path } => path.span,
252 }
253 }
254}
255
256#[derive(Clone, Debug)]
257pub enum Pat {
258 Ident(Ident),
259 Tuple { elems: Vec<Pat>, span: Span },
260}
261
262impl Pat {
263 pub fn span(&self) -> Span {
264 match self {
265 Pat::Ident(i) => i.span,
266 Pat::Tuple { span, .. } => *span,
267 }
268 }
269}
270
271#[derive(Clone, Debug)]
272pub enum Arg {
273 Pos(Expr),
274 Named { name: Ident, value: Expr },
276 Axis(Ident),
278 NamedAxis { name: Ident, value: Expr },
280}
281
282#[derive(Clone, Debug)]
283pub enum IndexSel {
284 Pos(Expr),
285 Named { axis: Ident, value: Expr },
287 Slice { axis: Option<Ident>, lo: Expr, hi: Expr },
290}
291
292#[derive(Clone, Debug)]
293pub enum Lit {
294 Nat(String),
295 Float(String),
296 Quantity { num: String, unit: String },
297 Str(String),
298}
299
300#[derive(Clone, Copy, Debug, PartialEq, Eq)]
301pub enum BinOp {
302 Pipe,
304 Alt,
306 Tensor,
308 Compose,
310 Eq,
311 Le,
312 Ge,
313 Lt,
314 Gt,
315 Add,
316 Sub,
317 Mul,
318 Div,
319 Rem,
320 Dot,
322 Pow,
323}
324
325impl BinOp {
326 pub fn text(self) -> &'static str {
327 match self {
328 BinOp::Pipe => "|>",
329 BinOp::Alt => "|",
330 BinOp::Tensor => "⊗",
331 BinOp::Compose => "∘",
332 BinOp::Eq => "==",
333 BinOp::Le => "<=",
334 BinOp::Ge => ">=",
335 BinOp::Lt => "<",
336 BinOp::Gt => ">",
337 BinOp::Add => "+",
338 BinOp::Sub => "-",
339 BinOp::Mul => "*",
340 BinOp::Div => "/",
341 BinOp::Rem => "%",
342 BinOp::Dot => "·",
343 BinOp::Pow => "^",
344 }
345 }
346}
347
348#[derive(Clone, Copy, Debug, PartialEq, Eq)]
349pub enum UnOp {
350 Neg,
351}