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 body: Vec<Stmt>,
239 #[serde(skip)]
240 loc: Loc,
241 },
242 ForIn {
243 index_var: Option<String>, item_var: String,
247 collection: Expr,
248 body: Vec<Stmt>,
249 #[serde(skip)]
250 loc: Loc,
251 },
252 While {
253 condition: Expr,
254 body: Vec<Stmt>,
255 },
256 Break,
257 Continue,
258 TypeDecl {
259 name: String,
260 fields: Vec<TypeField>,
261 #[serde(default, skip_serializing_if = "is_false")]
262 export: bool,
263 #[serde(skip)]
264 loc: Loc,
265 },
266 MethodDecl {
267 name: String,
268 params: Vec<MethodParam>,
269 body: Vec<Stmt>,
270 #[serde(default, skip_serializing_if = "is_false")]
271 export: bool,
272 #[serde(skip)]
273 loc: Loc,
274 },
275 EnumDecl {
276 name: String,
277 fields: Vec<EnumField>,
278 #[serde(default, skip_serializing_if = "is_false")]
279 export: bool,
280 #[serde(skip)]
281 loc: Loc,
282 },
283 FunctionDecl {
284 name: String,
285 params: Vec<FunctionParam>,
286 body: Vec<Stmt>,
287 #[serde(default, skip_serializing_if = "is_false")]
288 export: bool,
289 #[serde(skip)]
290 loc: Loc,
291 },
292 Export {
293 item: ExportItem,
294 },
295 Import {
296 path: String, alias: String, #[serde(skip)]
299 loc: Loc,
300 },
301}
302
303#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
305pub enum ExportItem {
306 Type(String), Function(String), }
309
310#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
312pub struct EnumField {
313 pub name: String,
314 pub title: Option<String>, #[serde(skip)]
316 pub loc: Loc,
317}
318
319#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
321pub struct MethodParam {
322 #[serde(skip_serializing_if = "skip_none")]
323 pub type_qualifier: Option<TypeQualifier>,
324 pub type_annotation: Option<String>, pub name: String,
326 pub default_value: Option<Expr>,
327 #[serde(skip)]
328 pub loc: Loc,
329}
330
331#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
333pub struct FunctionParam {
334 #[serde(skip_serializing_if = "skip_none")]
335 pub type_qualifier: Option<TypeQualifier>,
336 #[serde(skip_serializing_if = "skip_none")]
337 pub type_annotation: Option<String>,
338 pub name: String,
339 #[serde(skip_serializing_if = "skip_none")]
340 pub default_value: Option<Expr>,
341 #[serde(skip)]
342 pub loc: Loc,
343}
344
345#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
347pub struct TypeField {
348 pub name: String,
349 #[serde(skip_serializing_if = "skip_none")]
350 pub type_qualifier: Option<TypeQualifier>,
351 pub type_annotation: String,
352 pub default_value: Option<Expr>,
353 #[serde(skip)]
354 pub loc: Loc,
355}
356
357#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
359pub struct Program {
360 pub statements: Vec<Stmt>,
361}
362
363impl Program {
364 pub fn new(statements: Vec<Stmt>) -> Self {
365 Self { statements }
366 }
367}