1use super::objectd::FunctionD;
2use super::{ASTValue, CompileVisitor, Context, Module, RuntimeError};
3use std::path::PathBuf;
4use vek::Vec3;
5
6#[macro_export]
7macro_rules! empty_expr {
8 () => {
9 Box::new(Expr::Value(
10 ASTValue::None,
11 vec![],
12 vec![],
13 Location::default(),
14 ))
15 };
16}
17
18#[macro_export]
19macro_rules! zero_expr_int {
20 () => {
21 Box::new(Expr::Value(
22 ASTValue::Int(0),
23 vec![],
24 vec![],
25 Location::default(),
26 ))
27 };
28}
29
30#[macro_export]
31macro_rules! zero_expr_float {
32 () => {
33 Box::new(Expr::Value(
34 ASTValue::Float(0.0),
35 vec![],
36 vec![],
37 Location::default(),
38 ))
39 };
40}
41
42#[macro_export]
43macro_rules! expr_float {
44 ($val:expr) => {
45 Box::new(Expr::Value(
46 ASTValue::Float($val),
47 vec![],
48 vec![],
49 Location::default(),
50 ))
51 };
52}
53
54#[derive(Clone, Debug)]
56pub enum Stmt {
57 If(Box<Expr>, Box<Stmt>, Option<Box<Stmt>>, Location),
58 While(Box<Expr>, Box<Stmt>, Location),
59 For(
60 Vec<Box<Stmt>>,
61 Vec<Box<Expr>>,
62 Vec<Box<Expr>>,
63 Box<Stmt>,
64 Location,
65 ),
66 Import(Option<Module>, Location),
67 FunctionDeclaration(FunctionD, Location),
68 Print(Box<Expr>, Location),
69 Block(Vec<Box<Stmt>>, Location),
70 Expression(Box<Expr>, Location),
71 VarDeclaration(String, ASTValue, Box<Expr>, Location),
72 StructDeclaration(String, Vec<(String, ASTValue)>, Location),
73 Return(Box<Expr>, Location),
74 Break(Location),
75 Empty,
76}
77
78#[derive(Clone, Debug)]
80pub enum Expr {
81 Value(ASTValue, Vec<u8>, Vec<String>, Location),
82 Logical(Box<Expr>, LogicalOperator, Box<Expr>, Location),
83 Unary(UnaryOperator, Box<Expr>, Location),
84 Equality(Box<Expr>, EqualityOperator, Box<Expr>, Location),
85 Comparison(Box<Expr>, ComparisonOperator, Box<Expr>, Location),
86 Binary(Box<Expr>, BinaryOperator, Box<Expr>, Location),
87 Grouping(Box<Expr>, Location),
88 Variable(String, Vec<u8>, Vec<String>, Location),
89 VariableAssignment(
90 String,
91 AssignmentOperator,
92 Vec<u8>,
93 Vec<String>,
94 Box<Expr>,
95 Location,
96 ),
97 FunctionCall(Box<Expr>, Vec<u8>, Vec<String>, Vec<Box<Expr>>, Location),
98 Ternary(Box<Expr>, Box<Expr>, Box<Expr>, Location),
99}
100
101#[derive(Clone, PartialEq, Debug)]
103pub enum AssignmentOperator {
104 Assign,
105 AddAssign,
106 SubtractAssign,
107 MultiplyAssign,
108 DivideAssign,
109}
110
111impl AssignmentOperator {
112 pub fn describe(&self) -> &str {
113 match self {
114 AssignmentOperator::Assign => "=",
115 AssignmentOperator::AddAssign => "+=",
116 AssignmentOperator::SubtractAssign => "-=",
117 AssignmentOperator::MultiplyAssign => "*=",
118 AssignmentOperator::DivideAssign => "/=",
119 }
120 }
121}
122
123#[derive(Clone, PartialEq, Debug)]
125pub enum LogicalOperator {
126 And,
127 Or,
128}
129
130impl LogicalOperator {
131 pub fn describe(&self) -> &str {
132 match self {
133 LogicalOperator::And => "&&",
134 LogicalOperator::Or => "||",
135 }
136 }
137}
138
139#[derive(Clone, Debug)]
141pub enum UnaryOperator {
142 Negate,
143 Minus,
144}
145
146#[derive(Clone, Debug)]
148pub enum BinaryOperator {
149 Add,
150 Subtract,
151 Multiply,
152 Divide,
153 Mod,
154}
155
156impl BinaryOperator {
157 pub fn describe(&self) -> &str {
158 match self {
159 BinaryOperator::Add => "+",
160 BinaryOperator::Subtract => "-",
161 BinaryOperator::Multiply => "*",
162 BinaryOperator::Divide => "/",
163 BinaryOperator::Mod => "%",
164 }
165 }
166}
167
168#[derive(Clone, Debug)]
170pub enum ComparisonOperator {
171 Greater,
172 GreaterEqual,
173 Less,
174 LessEqual,
175}
176
177impl ComparisonOperator {
178 pub fn describe(&self) -> &str {
179 match self {
180 ComparisonOperator::Greater => ">",
181 ComparisonOperator::GreaterEqual => ">=",
182 ComparisonOperator::Less => "<",
183 ComparisonOperator::LessEqual => "<=",
184 }
185 }
186}
187
188#[derive(Clone, Debug)]
190pub enum EqualityOperator {
191 NotEqual,
192 Equal,
193}
194
195impl EqualityOperator {
196 pub fn describe(&self) -> &str {
197 match self {
198 EqualityOperator::NotEqual => "!=",
199 EqualityOperator::Equal => "==",
200 }
201 }
202}
203
204pub trait Visitor {
206 fn new() -> Self
207 where
208 Self: Sized;
209
210 fn print(
211 &mut self,
212 expression: &Expr,
213 loc: &Location,
214 ctx: &mut Context,
215 ) -> Result<ASTValue, RuntimeError>;
216
217 fn block(
218 &mut self,
219 list: &[Box<Stmt>],
220 loc: &Location,
221 ctx: &mut Context,
222 ) -> Result<ASTValue, RuntimeError>;
223
224 fn expression(
225 &mut self,
226 expression: &Expr,
227 loc: &Location,
228 ctx: &mut Context,
229 ) -> Result<ASTValue, RuntimeError>;
230
231 fn import(
232 &mut self,
233 id: &Option<Module>,
234 loc: &Location,
235 ctx: &mut Context,
236 ) -> Result<ASTValue, RuntimeError>;
237
238 fn function_declaration(
239 &mut self,
240 objectd: &FunctionD,
241 loc: &Location,
242 ctx: &mut Context,
243 ) -> Result<ASTValue, RuntimeError>;
244
245 fn var_declaration(
246 &mut self,
247 name: &str,
248 static_type: &ASTValue,
249 expression: &Expr,
250 loc: &Location,
251 ctx: &mut Context,
252 ) -> Result<ASTValue, RuntimeError>;
253
254 fn value(
255 &mut self,
256 value: ASTValue,
257 swizzle: &[u8],
258 field_path: &[String],
259 loc: &Location,
260 ctx: &mut Context,
261 ) -> Result<ASTValue, RuntimeError>;
262
263 fn unary(
264 &mut self,
265 op: &UnaryOperator,
266 expr: &Expr,
267 loc: &Location,
268 ctx: &mut Context,
269 ) -> Result<ASTValue, RuntimeError>;
270
271 fn equality(
272 &mut self,
273 left: &Expr,
274 op: &EqualityOperator,
275 right: &Expr,
276 loc: &Location,
277 ctx: &mut Context,
278 ) -> Result<ASTValue, RuntimeError>;
279
280 fn comparison(
281 &mut self,
282 left: &Expr,
283 op: &ComparisonOperator,
284 right: &Expr,
285 loc: &Location,
286 ctx: &mut Context,
287 ) -> Result<ASTValue, RuntimeError>;
288
289 fn binary(
290 &mut self,
291 left: &Expr,
292 op: &BinaryOperator,
293 right: &Expr,
294 loc: &Location,
295 ctx: &mut Context,
296 ) -> Result<ASTValue, RuntimeError>;
297
298 fn grouping(
299 &mut self,
300 expression: &Expr,
301 loc: &Location,
302 ctx: &mut Context,
303 ) -> Result<ASTValue, RuntimeError>;
304
305 fn variable(
306 &mut self,
307 name: String,
308 swizzle: &[u8],
309 field_path: &[String],
310 loc: &Location,
311 ctx: &mut Context,
312 ) -> Result<ASTValue, RuntimeError>;
313
314 #[allow(clippy::too_many_arguments)]
315 fn variable_assignment(
316 &mut self,
317 name: String,
318 op: &AssignmentOperator,
319 swizzle: &[u8],
320 field_path: &[String],
321 expression: &Expr,
322 loc: &Location,
323 ctx: &mut Context,
324 ) -> Result<ASTValue, RuntimeError>;
325
326 fn func_call(
327 &mut self,
328 callee: &Expr,
329 swizzle: &[u8],
330 field_path: &[String],
331 args: &[Box<Expr>],
332 loc: &Location,
333 ctx: &mut Context,
334 ) -> Result<ASTValue, RuntimeError>;
335
336 fn struct_declaration(
337 &mut self,
338 name: &str,
339 field: &[(String, ASTValue)],
340 loc: &Location,
341 ctx: &mut Context,
342 ) -> Result<ASTValue, RuntimeError>;
343
344 fn return_stmt(
345 &mut self,
346 expr: &Expr,
347 loc: &Location,
348 ctx: &mut Context,
349 ) -> Result<ASTValue, RuntimeError>;
350
351 fn break_stmt(&mut self, loc: &Location, ctx: &mut Context) -> Result<ASTValue, RuntimeError>;
352 fn empty_stmt(&mut self, ctx: &mut Context) -> Result<ASTValue, RuntimeError>;
353
354 fn if_stmt(
355 &mut self,
356 cond: &Expr,
357 then_stmt: &Stmt,
358 else_stmt: &Option<Box<Stmt>>,
359 loc: &Location,
360 ctx: &mut Context,
361 ) -> Result<ASTValue, RuntimeError>;
362
363 fn while_stmt(
364 &mut self,
365 cond: &Expr,
366 body_stmt: &Stmt,
367 loc: &Location,
368 ctx: &mut Context,
369 ) -> Result<ASTValue, RuntimeError>;
370
371 fn for_stmt(
372 &mut self,
373 init: &[Box<Stmt>],
374 cond: &[Box<Expr>],
375 incr: &[Box<Expr>],
376 body_stmt: &Stmt,
377 loc: &Location,
378 ctx: &mut Context,
379 ) -> Result<ASTValue, RuntimeError>;
380
381 fn logical_expr(
382 &mut self,
383 left: &Expr,
384 op: &LogicalOperator,
385 right: &Expr,
386 loc: &Location,
387 ctx: &mut Context,
388 ) -> Result<ASTValue, RuntimeError>;
389
390 fn ternary(
391 &mut self,
392 condition: &Expr,
393 then_expr: &Expr,
394 else_expr: &Expr,
395 loc: &Location,
396 ctx: &mut Context,
397 ) -> Result<ASTValue, RuntimeError>;
398}
399
400impl Stmt {
401 pub fn accept(
402 &self,
403 visitor: &mut dyn Visitor,
404 ctx: &mut Context,
405 ) -> Result<ASTValue, RuntimeError> {
406 match self {
407 Stmt::If(cond, then_stmt, else_stmt, loc) => {
408 visitor.if_stmt(cond, then_stmt, else_stmt, loc, ctx)
409 }
410 Stmt::While(cond, body, loc) => visitor.while_stmt(cond, body, loc, ctx),
411 Stmt::For(init, cond, incr, body, loc) => {
412 visitor.for_stmt(init, cond, incr, body, loc, ctx)
413 }
414 Stmt::Print(expression, loc) => visitor.print(expression, loc, ctx),
415 Stmt::Block(list, loc) => visitor.block(list, loc, ctx),
416 Stmt::Expression(expression, loc) => visitor.expression(expression, loc, ctx),
417 Stmt::Import(module, loc) => visitor.import(module, loc, ctx),
418 Stmt::FunctionDeclaration(objectd, loc) => {
419 visitor.function_declaration(objectd, loc, ctx)
420 }
421 Stmt::VarDeclaration(name, static_type, initializer, loc) => {
422 visitor.var_declaration(name, static_type, initializer, loc, ctx)
423 }
424 Stmt::StructDeclaration(name, fields, loc) => {
425 visitor.struct_declaration(name, fields, loc, ctx)
426 }
427 Stmt::Break(loc) => visitor.break_stmt(loc, ctx),
428 Stmt::Empty => visitor.empty_stmt(ctx),
429 Stmt::Return(expr, loc) => visitor.return_stmt(expr, loc, ctx),
430 }
431 }
432}
433
434impl Expr {
435 pub fn accept(
436 &self,
437 visitor: &mut dyn Visitor,
438 ctx: &mut Context,
439 ) -> Result<ASTValue, RuntimeError> {
440 match self {
441 Expr::Value(value, swizzle, field_path, loc) => {
442 visitor.value(value.clone(), swizzle, field_path, loc, ctx)
443 }
444 Expr::Logical(left, op, right, loc) => visitor.logical_expr(left, op, right, loc, ctx),
445 Expr::Unary(op, expr, loc) => visitor.unary(op, expr, loc, ctx),
446 Expr::Equality(left, op, right, loc) => visitor.equality(left, op, right, loc, ctx),
447 Expr::Comparison(left, op, right, loc) => visitor.comparison(left, op, right, loc, ctx),
448 Expr::Binary(left, op, right, loc) => visitor.binary(left, op, right, loc, ctx),
449 Expr::Grouping(expr, loc) => visitor.grouping(expr, loc, ctx),
450 Expr::Variable(name, swizzle, field_path, loc) => {
451 visitor.variable(name.clone(), swizzle, field_path, loc, ctx)
452 }
453 Expr::VariableAssignment(name, op, swizzle, field_path, expr, loc) => {
454 visitor.variable_assignment(name.clone(), op, swizzle, field_path, expr, loc, ctx)
455 }
456 Expr::FunctionCall(callee, args, swizzle, field_path, loc) => {
457 visitor.func_call(callee, args, swizzle, field_path, loc, ctx)
458 }
459 Expr::Ternary(cond, then_expr, else_expr, loc) => {
460 visitor.ternary(cond, then_expr, else_expr, loc, ctx)
461 }
462 }
463 }
464
465 pub fn to_vec3(&self, visitor: &mut CompileVisitor, ctx: &mut Context) -> Option<Vec3<f32>> {
467 if let Expr::Value(ASTValue::Float3(x, y, z), _, _, _) = self {
468 let x_val = x.accept(visitor, ctx).ok()?;
469 let y_val = y.accept(visitor, ctx).ok()?;
470 let z_val = z.accept(visitor, ctx).ok()?;
471
472 if let (ASTValue::Float(x_f), ASTValue::Float(y_f), ASTValue::Float(z_f)) =
473 (x_val, y_val, z_val)
474 {
475 return Some(Vec3::new(x_f, y_f, z_f));
476 }
477 }
478 None
479 }
480}
481
482#[derive(Clone, Debug)]
484pub struct Location {
485 pub line: usize,
486 pub path: PathBuf,
487}
488
489impl Default for Location {
490 fn default() -> Self {
491 Self::new(0, PathBuf::default())
492 }
493}
494
495impl Location {
496 pub fn new(line: usize, path: PathBuf) -> Self {
497 Location { line, path }
498 }
499
500 pub fn describe(&self) -> String {
501 format!("at line {}.", self.line)
503 }
504}