Skip to main content

rusterix/vm/
ast.rs

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/// Statements in the AST
55#[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/// Expressions in the AST
79#[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/// Assignment operators in the AST
102#[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/// Logical operators in the AST
124#[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/// Unary operators in the AST
140#[derive(Clone, Debug)]
141pub enum UnaryOperator {
142    Negate,
143    Minus,
144}
145
146/// Binary operators in the AST
147#[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/// Comparison operators in the AST
169#[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/// Equality operators in the AST
189#[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
204/// Visitor trait
205pub 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    /// Converts a Float3 expression to a Vec3<f32>
466    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/// Location in the source code
483#[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!("in '{}' at line {}.", self.file, self.line)
502        format!("at line {}.", self.line)
503    }
504}