datex_core/visitor/
mod.rs

1use crate::values::core_values::r#type::Type;
2
3pub mod expression;
4pub mod type_expression;
5
6#[derive(Debug, Clone)]
7/// Actions that can be taken when visiting an expression
8pub enum VisitAction<T: Sized> {
9    /// Continue visiting child nodes
10    VisitChildren,
11    /// Skip visiting child nodes
12    SkipChildren,
13    /// Replace the current node with a new one, skipping child nodes
14    Replace(T),
15    /// Recurse into child nodes, then replace the current node with a new one
16    ReplaceRecurseChildNodes(T),
17    /// Replace the current node with a new one, and recurse into it
18    ReplaceRecurse(T),
19    /// Set the type annotation of the current node, and recurse into child nodes
20    SetTypeRecurseChildNodes(Type),
21    /// Set the type annotation of the current node, skipping child nodes
22    SetTypeSkipChildren(Type),
23    /// Convert the current node to a no-op
24    ToNoop,
25}
26
27#[cfg(test)]
28mod tests {
29    use crate::ast::expressions::CreateRef;
30    use crate::ast::expressions::{
31        BinaryOperation, DatexExpression, DatexExpressionData, Statements,
32        VariableAccess,
33    };
34    use crate::ast::type_expressions::{TypeExpression, TypeExpressionData};
35    use crate::global::operators::BinaryOperator;
36    use crate::global::operators::binary::ArithmeticOperator;
37    use crate::parser::Parser;
38    use crate::visitor::{
39        VisitAction, expression::visitable::ExpressionVisitResult,
40    };
41    use crate::visitor::{
42        expression::ExpressionVisitor,
43        type_expression::{
44            TypeExpressionVisitor, visitable::TypeExpressionVisitResult,
45        },
46    };
47    use core::ops::Range;
48
49    pub struct MyAstTypeExpressionError {
50        message: String,
51    }
52
53    #[derive(Debug)]
54    pub struct MyAstExpressionError {
55        message: String,
56    }
57    impl MyAstExpressionError {
58        pub fn new(msg: &str) -> MyAstExpressionError {
59            Self {
60                message: msg.to_string(),
61            }
62        }
63    }
64
65    struct MyAst;
66    impl TypeExpressionVisitor<MyAstExpressionError> for MyAst {
67        fn visit_literal_type(
68            &mut self,
69            literal: &mut String,
70            span: &Range<usize>,
71        ) -> TypeExpressionVisitResult<MyAstExpressionError> {
72            Ok(VisitAction::Replace(TypeExpression::new(
73                TypeExpressionData::VariableAccess(VariableAccess {
74                    id: 0,
75                    name: "MYTYPE".to_string(),
76                }),
77                span.clone(),
78            )))
79        }
80    }
81    impl ExpressionVisitor<MyAstExpressionError> for MyAst {
82        fn handle_expression_error(
83            &mut self,
84            error: MyAstExpressionError,
85            expression: &DatexExpression,
86        ) -> Result<VisitAction<DatexExpression>, MyAstExpressionError>
87        {
88            println!(
89                "Expression error: {:?} at {:?}. Aborting...",
90                error, expression.span
91            );
92            Err(error)
93        }
94        fn visit_create_ref(
95            &mut self,
96            create_ref: &mut CreateRef,
97            span: &Range<usize>,
98        ) -> ExpressionVisitResult<MyAstExpressionError> {
99            Ok(VisitAction::VisitChildren)
100        }
101
102        fn visit_identifier(
103            &mut self,
104            identifier: &mut String,
105            span: &Range<usize>,
106        ) -> ExpressionVisitResult<MyAstExpressionError> {
107            Ok(VisitAction::Replace(DatexExpression {
108                data: DatexExpressionData::VariableAccess(VariableAccess {
109                    id: 0,
110                    name: identifier.clone(),
111                }),
112                span: span.clone(),
113                ty: None,
114            }))
115        }
116
117        fn visit_boolean(
118            &mut self,
119            boolean: &mut bool,
120            span: &Range<usize>,
121        ) -> ExpressionVisitResult<MyAstExpressionError> {
122            Err(MyAstExpressionError::new("Booleans are not allowed"))
123        }
124    }
125
126    #[test]
127    fn simple_test() {
128        let mut ast = Parser::parse_with_default_options(
129            "var x: integer/u8 = 42; x; ((42 + x))",
130        )
131        .unwrap();
132        MyAst.visit_datex_expression(&mut ast).unwrap();
133        println!("{:#?}", ast);
134    }
135
136    #[test]
137    fn error() {
138        let mut ast =
139            Parser::parse_with_default_options("true + false").unwrap();
140        let mut transformer = MyAst;
141        let res = transformer.visit_datex_expression(&mut ast);
142        assert!(res.is_err());
143    }
144
145    #[test]
146    fn test() {
147        let mut ast = DatexExpression {
148            data: DatexExpressionData::Statements(Statements {
149                statements: vec![DatexExpression {
150                    data: DatexExpressionData::BinaryOperation(
151                        BinaryOperation {
152                            operator: BinaryOperator::Arithmetic(
153                                ArithmeticOperator::Add,
154                            ),
155                            left: Box::new(DatexExpression {
156                                data: DatexExpressionData::Identifier(
157                                    "x".to_string(),
158                                ),
159                                span: 0..1,
160                                ty: None,
161                            }),
162                            right: Box::new(DatexExpression {
163                                data: DatexExpressionData::Identifier(
164                                    "y".to_string(),
165                                ),
166                                span: 2..3,
167                                ty: None,
168                            }),
169                            ty: None,
170                        },
171                    ),
172                    span: 0..3,
173                    ty: None,
174                }],
175                is_terminated: true,
176                unbounded: None,
177            }),
178            span: 1..2,
179            ty: None,
180        };
181        let transformer = &mut MyAst;
182        transformer.visit_datex_expression(&mut ast).unwrap();
183        println!("{:?}", ast);
184    }
185}