1use serde::{Deserialize, Serialize};
2
3pub mod visitor;
4pub use visitor::{walk_block, walk_expr, walk_program, walk_stmt, Visitor};
5
6fn is_false(b: &bool) -> bool {
8 !b
9}
10
11fn skip_none<T>(opt: &Option<T>) -> bool {
13 opt.is_none()
14}
15
16fn is_zero_u32(n: &u32) -> bool {
18 *n == 0
19}
20
21#[derive(Debug, Clone, Copy, Default)]
28pub struct Loc {
29 pub line: u32,
30 pub column: u32,
31}
32
33impl Loc {
34 pub fn new(line: u32, column: u32) -> Self {
35 Self { line, column }
36 }
37
38 pub fn position(&self) -> Option<(u32, u32)> {
40 (self.line != 0).then_some((self.line, self.column))
41 }
42
43 pub fn line(&self) -> Option<u32> {
45 (self.line != 0).then_some(self.line)
46 }
47}
48
49impl PartialEq for Loc {
52 fn eq(&self, _other: &Self) -> bool {
53 true
54 }
55}
56
57#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
60pub enum TypeQualifier {
61 Const,
62 Input,
63 Simple,
64 Series,
65}
66
67#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
69pub enum VarKind {
70 #[default]
72 Plain,
73 Var,
75 Varip,
77}
78
79impl VarKind {
80 pub fn is_persistent(self) -> bool {
82 !matches!(self, VarKind::Plain)
83 }
84
85 fn is_plain(&self) -> bool {
87 matches!(self, VarKind::Plain)
88 }
89}
90
91#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
93pub enum Argument {
94 Positional(Expr),
95 Named { name: String, value: Expr },
96}
97
98#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
100pub enum Expr {
101 Literal(Literal),
102 Variable {
103 name: String,
104 #[serde(skip)]
105 loc: Loc,
106 },
107 Binary {
108 left: Box<Expr>,
109 op: BinOp,
110 right: Box<Expr>,
111 #[serde(skip)]
112 loc: Loc,
113 },
114 Unary {
115 op: UnOp,
116 expr: Box<Expr>,
117 },
118 Call {
119 callee: Box<Expr>,
120 #[serde(default, skip_serializing_if = "Vec::is_empty")]
121 type_args: Vec<String>, args: Vec<Argument>,
123 #[serde(default, skip_serializing_if = "is_zero_u32")]
124 id: u32,
125 #[serde(skip)]
126 loc: Loc,
127 },
128 Index {
129 expr: Box<Expr>,
130 index: Box<Expr>,
131 #[serde(default, skip_serializing_if = "is_zero_u32")]
132 id: u32,
133 },
134 MemberAccess {
135 object: Box<Expr>,
136 member: String,
137 #[serde(skip)]
138 member_loc: Loc,
139 },
140 Ternary {
141 condition: Box<Expr>,
142 then_expr: Box<Expr>,
143 else_expr: Box<Expr>,
144 },
145 Function {
146 params: Vec<FunctionParam>,
147 body: Vec<Stmt>,
148 },
149 Array(Vec<Expr>),
150 Switch {
151 value: Box<Expr>,
152 cases: Vec<(Expr, Expr)>, },
154 IfExpr {
155 condition: Box<Expr>,
156 then_expr: Box<Expr>,
157 else_if_branches: Vec<(Expr, Expr)>, else_expr: Option<Box<Expr>>, },
160}
161
162impl Expr {
163 pub fn var(name: impl Into<String>) -> Self {
166 Expr::Variable {
167 name: name.into(),
168 loc: Loc::default(),
169 }
170 }
171}
172
173#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
174pub enum Literal {
175 Int(i64),
176 Number(f64),
177 String(String),
178 Bool(bool),
179 Na, HexColor(String), }
182
183#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
184pub enum BinOp {
185 Add,
186 Sub,
187 Mul,
188 Div,
189 Mod,
190 Eq,
191 NotEq,
192 Less,
193 Greater,
194 LessEq,
195 GreaterEq,
196 And,
197 Or,
198}
199
200#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
201pub enum UnOp {
202 Neg,
203 Not,
204}
205
206#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
207pub enum Stmt {
208 VarDecl {
209 name: String,
210 #[serde(skip_serializing_if = "skip_none")]
211 type_qualifier: Option<TypeQualifier>,
212 type_annotation: Option<String>,
213 initializer: Option<Expr>,
214 #[serde(default, skip_serializing_if = "VarKind::is_plain")]
215 var_kind: VarKind,
216 #[serde(skip)]
217 loc: Loc,
218 },
219 Assignment {
220 target: Expr, value: Expr,
222 },
223 TupleAssignment {
224 names: Vec<String>,
225 value: Expr,
226 #[serde(skip)]
227 loc: Loc,
228 },
229 Expression(Expr),
230 If {
231 condition: Expr,
232 then_branch: Vec<Stmt>,
233 else_if_branches: Vec<(Expr, Vec<Stmt>)>, else_branch: Option<Vec<Stmt>>,
235 },
236 For {
237 var_name: String,
238 from: Expr,
239 to: Expr,
240 #[serde(default, skip_serializing_if = "skip_none")]
241 step: Option<Expr>,
242 body: Vec<Stmt>,
243 #[serde(skip)]
244 loc: Loc,
245 },
246 ForIn {
247 index_var: Option<String>, item_var: String,
251 collection: Expr,
252 body: Vec<Stmt>,
253 #[serde(skip)]
254 loc: Loc,
255 },
256 While {
257 condition: Expr,
258 body: Vec<Stmt>,
259 },
260 Break {
261 #[serde(skip)]
262 loc: Loc,
263 },
264 Continue {
265 #[serde(skip)]
266 loc: Loc,
267 },
268 TypeDecl {
269 name: String,
270 fields: Vec<TypeField>,
271 #[serde(default, skip_serializing_if = "is_false")]
272 export: bool,
273 #[serde(skip)]
274 loc: Loc,
275 },
276 MethodDecl {
277 name: String,
278 params: Vec<MethodParam>,
279 body: Vec<Stmt>,
280 #[serde(default, skip_serializing_if = "is_false")]
281 export: bool,
282 #[serde(skip)]
283 loc: Loc,
284 },
285 EnumDecl {
286 name: String,
287 fields: Vec<EnumField>,
288 #[serde(default, skip_serializing_if = "is_false")]
289 export: bool,
290 #[serde(skip)]
291 loc: Loc,
292 },
293 FunctionDecl {
294 name: String,
295 params: Vec<FunctionParam>,
296 body: Vec<Stmt>,
297 #[serde(default, skip_serializing_if = "is_false")]
298 export: bool,
299 #[serde(skip)]
300 loc: Loc,
301 },
302 Export {
303 item: ExportItem,
304 },
305 Import {
306 path: String, alias: String, #[serde(skip)]
309 loc: Loc,
310 },
311}
312
313#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
315pub enum ExportItem {
316 Type(String), Function(String), }
319
320#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
322pub struct EnumField {
323 pub name: String,
324 pub title: Option<String>, #[serde(skip)]
326 pub loc: Loc,
327}
328
329#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
331pub struct MethodParam {
332 #[serde(skip_serializing_if = "skip_none")]
333 pub type_qualifier: Option<TypeQualifier>,
334 pub type_annotation: Option<String>, pub name: String,
336 pub default_value: Option<Expr>,
337 #[serde(skip)]
338 pub loc: Loc,
339}
340
341#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
343pub struct FunctionParam {
344 #[serde(skip_serializing_if = "skip_none")]
345 pub type_qualifier: Option<TypeQualifier>,
346 #[serde(skip_serializing_if = "skip_none")]
347 pub type_annotation: Option<String>,
348 pub name: String,
349 #[serde(skip_serializing_if = "skip_none")]
350 pub default_value: Option<Expr>,
351 #[serde(skip)]
352 pub loc: Loc,
353}
354
355#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
357pub struct TypeField {
358 pub name: String,
359 #[serde(skip_serializing_if = "skip_none")]
360 pub type_qualifier: Option<TypeQualifier>,
361 pub type_annotation: String,
362 pub default_value: Option<Expr>,
363 #[serde(skip)]
364 pub loc: Loc,
365}
366
367#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
369pub struct Program {
370 pub statements: Vec<Stmt>,
371}
372
373impl Program {
374 pub fn new(statements: Vec<Stmt>) -> Self {
375 Self { statements }
376 }
377}