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 },
132 MemberAccess {
133 object: Box<Expr>,
134 member: String,
135 #[serde(skip)]
136 member_loc: Loc,
137 },
138 Ternary {
139 condition: Box<Expr>,
140 then_expr: Box<Expr>,
141 else_expr: Box<Expr>,
142 },
143 Function {
144 params: Vec<FunctionParam>,
145 body: Vec<Stmt>,
146 },
147 Array(Vec<Expr>),
148 Switch {
149 value: Box<Expr>,
150 cases: Vec<(Expr, Expr)>, },
152 IfExpr {
153 condition: Box<Expr>,
154 then_expr: Box<Expr>,
155 else_if_branches: Vec<(Expr, Expr)>, else_expr: Option<Box<Expr>>, },
158}
159
160impl Expr {
161 pub fn var(name: impl Into<String>) -> Self {
164 Expr::Variable {
165 name: name.into(),
166 loc: Loc::default(),
167 }
168 }
169}
170
171#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
172pub enum Literal {
173 Int(i64),
174 Number(f64),
175 String(String),
176 Bool(bool),
177 Na, HexColor(String), }
180
181#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
182pub enum BinOp {
183 Add,
184 Sub,
185 Mul,
186 Div,
187 Mod,
188 Eq,
189 NotEq,
190 Less,
191 Greater,
192 LessEq,
193 GreaterEq,
194 And,
195 Or,
196}
197
198#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
199pub enum UnOp {
200 Neg,
201 Not,
202}
203
204#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
205pub enum Stmt {
206 VarDecl {
207 name: String,
208 #[serde(skip_serializing_if = "skip_none")]
209 type_qualifier: Option<TypeQualifier>,
210 type_annotation: Option<String>,
211 initializer: Option<Expr>,
212 #[serde(default, skip_serializing_if = "VarKind::is_plain")]
213 var_kind: VarKind,
214 #[serde(skip)]
215 loc: Loc,
216 },
217 Assignment {
218 target: Expr, value: Expr,
220 },
221 TupleAssignment {
222 names: Vec<String>,
223 value: Expr,
224 #[serde(skip)]
225 loc: Loc,
226 },
227 Expression(Expr),
228 If {
229 condition: Expr,
230 then_branch: Vec<Stmt>,
231 else_if_branches: Vec<(Expr, Vec<Stmt>)>, else_branch: Option<Vec<Stmt>>,
233 },
234 For {
235 var_name: String,
236 from: Expr,
237 to: Expr,
238 #[serde(default, skip_serializing_if = "skip_none")]
239 step: Option<Expr>,
240 body: Vec<Stmt>,
241 #[serde(skip)]
242 loc: Loc,
243 },
244 ForIn {
245 index_var: Option<String>, item_var: String,
249 collection: Expr,
250 body: Vec<Stmt>,
251 #[serde(skip)]
252 loc: Loc,
253 },
254 While {
255 condition: Expr,
256 body: Vec<Stmt>,
257 },
258 Break {
259 #[serde(skip)]
260 loc: Loc,
261 },
262 Continue {
263 #[serde(skip)]
264 loc: Loc,
265 },
266 TypeDecl {
267 name: String,
268 fields: Vec<TypeField>,
269 #[serde(default, skip_serializing_if = "is_false")]
270 export: bool,
271 #[serde(skip)]
272 loc: Loc,
273 },
274 MethodDecl {
275 name: String,
276 params: Vec<MethodParam>,
277 body: Vec<Stmt>,
278 #[serde(default, skip_serializing_if = "is_false")]
279 export: bool,
280 #[serde(skip)]
281 loc: Loc,
282 },
283 EnumDecl {
284 name: String,
285 fields: Vec<EnumField>,
286 #[serde(default, skip_serializing_if = "is_false")]
287 export: bool,
288 #[serde(skip)]
289 loc: Loc,
290 },
291 FunctionDecl {
292 name: String,
293 params: Vec<FunctionParam>,
294 body: Vec<Stmt>,
295 #[serde(default, skip_serializing_if = "is_false")]
296 export: bool,
297 #[serde(skip)]
298 loc: Loc,
299 },
300 Export {
301 item: ExportItem,
302 },
303 Import {
304 path: String, alias: String, #[serde(skip)]
307 loc: Loc,
308 },
309}
310
311#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
313pub enum ExportItem {
314 Type(String), Function(String), }
317
318#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
320pub struct EnumField {
321 pub name: String,
322 pub title: Option<String>, #[serde(skip)]
324 pub loc: Loc,
325}
326
327#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
329pub struct MethodParam {
330 #[serde(skip_serializing_if = "skip_none")]
331 pub type_qualifier: Option<TypeQualifier>,
332 pub type_annotation: Option<String>, pub name: String,
334 pub default_value: Option<Expr>,
335 #[serde(skip)]
336 pub loc: Loc,
337}
338
339#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
341pub struct FunctionParam {
342 #[serde(skip_serializing_if = "skip_none")]
343 pub type_qualifier: Option<TypeQualifier>,
344 #[serde(skip_serializing_if = "skip_none")]
345 pub type_annotation: Option<String>,
346 pub name: String,
347 #[serde(skip_serializing_if = "skip_none")]
348 pub default_value: Option<Expr>,
349 #[serde(skip)]
350 pub loc: Loc,
351}
352
353#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
355pub struct TypeField {
356 pub name: String,
357 #[serde(skip_serializing_if = "skip_none")]
358 pub type_qualifier: Option<TypeQualifier>,
359 pub type_annotation: String,
360 pub default_value: Option<Expr>,
361 #[serde(skip)]
362 pub loc: Loc,
363}
364
365#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
367pub struct Program {
368 pub statements: Vec<Stmt>,
369}
370
371impl Program {
372 pub fn new(statements: Vec<Stmt>) -> Self {
373 Self { statements }
374 }
375}