diff --git a/compiler/ast/src/lib.rs b/compiler/ast/src/lib.rs index b988b348cd..64b97b6bb4 100644 --- a/compiler/ast/src/lib.rs +++ b/compiler/ast/src/lib.rs @@ -43,12 +43,12 @@ pub use self::input::*; pub mod pass; pub use self::pass::*; +pub mod passes; +pub use self::passes::*; + pub mod program; pub use self::program::*; -pub mod reducer; -pub use self::reducer::*; - pub mod statements; pub use self::statements::*; diff --git a/compiler/ast/src/reducer/mod.rs b/compiler/ast/src/passes/mod.rs similarity index 75% rename from compiler/ast/src/reducer/mod.rs rename to compiler/ast/src/passes/mod.rs index 87d296ee02..98f524e338 100644 --- a/compiler/ast/src/reducer/mod.rs +++ b/compiler/ast/src/passes/mod.rs @@ -14,13 +14,19 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -//! This module contains both a Director to reconstruct the AST -//! which maps over every node of the AST and calls a reducer. -//! The Trait for a reducer are methods that can be overridden -//! to make changes to how AST nodes are rebuilt. +//! This module contains both a Reducer and Visitor design pattern. +//! These both iterate over the AST. + +// todo @gluax: Move the files in this module into `leo-passes` in a future PR. pub mod reconstructing_reducer; pub use reconstructing_reducer::*; pub mod reconstructing_director; pub use reconstructing_director::*; + +pub mod visitor; +pub use visitor::*; + +pub mod visitor_director; +pub use visitor_director::*; diff --git a/compiler/ast/src/reducer/reconstructing_director.rs b/compiler/ast/src/passes/reconstructing_director.rs similarity index 100% rename from compiler/ast/src/reducer/reconstructing_director.rs rename to compiler/ast/src/passes/reconstructing_director.rs diff --git a/compiler/ast/src/reducer/reconstructing_reducer.rs b/compiler/ast/src/passes/reconstructing_reducer.rs similarity index 100% rename from compiler/ast/src/reducer/reconstructing_reducer.rs rename to compiler/ast/src/passes/reconstructing_reducer.rs diff --git a/compiler/ast/src/passes/visitor.rs b/compiler/ast/src/passes/visitor.rs new file mode 100644 index 0000000000..c7b64f5bfa --- /dev/null +++ b/compiler/ast/src/passes/visitor.rs @@ -0,0 +1,112 @@ +// Copyright (C) 2019-2022 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . + +//! This module contains Visitor traits for the AST. + +use crate::*; + +pub enum VisitResult { + VisitChildren, + SkipChildren, +} + +impl Default for VisitResult { + fn default() -> Self { + VisitResult::VisitChildren + } +} + +pub trait ExpressionVisitor { + fn visit_expression(&mut self, _input: &Expression) -> VisitResult { + Default::default() + } + + fn visit_identifer(&mut self, _input: &Identifier) -> VisitResult { + Default::default() + } + + fn visit_value(&mut self, _input: &ValueExpression) -> VisitResult { + Default::default() + } + + fn visit_binary(&mut self, _input: &BinaryExpression) -> VisitResult { + Default::default() + } + + fn visit_unary(&mut self, _input: &UnaryExpression) -> VisitResult { + Default::default() + } + + fn visit_ternary(&mut self, _input: &TernaryExpression) -> VisitResult { + Default::default() + } + + fn visit_call(&mut self, _input: &CallExpression) -> VisitResult { + Default::default() + } + + fn visit_err(&mut self, _input: &ErrExpression) -> VisitResult { + Default::default() + } +} + +pub trait StatementVisitor { + fn visit_statement(&mut self, _input: &Statement) -> VisitResult { + Default::default() + } + + fn visit_return(&mut self, _input: &ReturnStatement) -> VisitResult { + Default::default() + } + + fn visit_definition(&mut self, _input: &DefinitionStatement) -> VisitResult { + Default::default() + } + + fn visit_assign(&mut self, _input: &AssignStatement) -> VisitResult { + Default::default() + } + + fn visit_conditional(&mut self, _input: &ConditionalStatement) -> VisitResult { + Default::default() + } + + fn visit_iteration(&mut self, _input: &IterationStatement) -> VisitResult { + Default::default() + } + + fn visit_console(&mut self, _input: &ConsoleStatement) -> VisitResult { + Default::default() + } + + fn visit_expression_statement(&mut self, _input: &ExpressionStatement) -> VisitResult { + Default::default() + } + + fn visit_block(&mut self, _input: &Block) -> VisitResult { + Default::default() + } +} + +pub trait ProgramVisitor { + fn visit_program(&mut self, _input: &Program) -> VisitResult { + Default::default() + } + + fn visit_function(&mut self, _input: &Function) -> VisitResult { + Default::default() + } +} diff --git a/compiler/ast/src/passes/visitor_director.rs b/compiler/ast/src/passes/visitor_director.rs new file mode 100644 index 0000000000..45e7188d22 --- /dev/null +++ b/compiler/ast/src/passes/visitor_director.rs @@ -0,0 +1,170 @@ +// Copyright (C) 2019-2022 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . + +//! This module contains Visitor trait implementations for the AST. +//! It implements default methods for each node to be made +//! given the type of node its visiting. + +// temporary till we use in another pr. +#![allow(dead_code)] + +use crate::*; + +pub struct VisitorDirector { + visitor: V, +} + +impl VisitorDirector { + pub fn new(visitor: V) -> Self { + Self { visitor } + } + + pub fn visitor(self) -> V { + self.visitor + } + + pub fn visit_expression(&mut self, input: &Expression) { + if let VisitResult::VisitChildren = self.visitor.visit_expression(input) { + match input { + Expression::Identifier(_) => {} + Expression::Value(_) => {} + Expression::Binary(expr) => self.visit_binary(expr), + Expression::Unary(expr) => self.visit_unary(expr), + Expression::Ternary(expr) => self.visit_ternary(expr), + Expression::Call(expr) => self.visit_call(expr), + Expression::Err(_) => {} + } + } + } + + pub fn visit_binary(&mut self, input: &BinaryExpression) { + if let VisitResult::VisitChildren = self.visitor.visit_binary(input) { + self.visit_expression(&input.left); + self.visit_expression(&input.right); + } + } + + pub fn visit_unary(&mut self, input: &UnaryExpression) { + if let VisitResult::VisitChildren = self.visitor.visit_unary(input) { + self.visit_expression(&input.inner); + } + } + + pub fn visit_ternary(&mut self, input: &TernaryExpression) { + if let VisitResult::VisitChildren = self.visitor.visit_ternary(input) { + self.visit_expression(&input.condition); + self.visit_expression(&input.if_true); + self.visit_expression(&input.if_false); + } + } + + pub fn visit_call(&mut self, input: &CallExpression) { + if let VisitResult::VisitChildren = self.visitor.visit_call(input) { + self.visit_expression(&input.function); + input.arguments.iter().for_each(|expr| self.visit_expression(expr)); + } + } +} + +impl VisitorDirector { + fn visit_statement(&mut self, input: &Statement) { + if let VisitResult::VisitChildren = self.visitor.visit_statement(input) { + match input { + Statement::Return(stmt) => self.visit_return(stmt), + Statement::Definition(stmt) => self.visit_definition(stmt), + Statement::Assign(stmt) => self.visit_assign(stmt), + Statement::Conditional(stmt) => self.visit_conditional(stmt), + Statement::Iteration(stmt) => self.visit_iteration(stmt), + Statement::Console(stmt) => self.visit_console(stmt), + Statement::Expression(stmt) => self.visit_expression_statement(stmt), + Statement::Block(stmt) => self.visit_block(stmt), + } + } + } + + fn visit_return(&mut self, input: &ReturnStatement) { + if let VisitResult::VisitChildren = self.visitor.visit_return(input) { + self.visit_expression(&input.expression); + } + } + + fn visit_definition(&mut self, input: &DefinitionStatement) { + if let VisitResult::VisitChildren = self.visitor.visit_definition(input) { + self.visit_expression(&input.value); + } + } + + fn visit_assign(&mut self, input: &AssignStatement) { + if let VisitResult::VisitChildren = self.visitor.visit_assign(input) { + self.visit_expression(&input.value); + } + } + + fn visit_conditional(&mut self, input: &ConditionalStatement) { + if let VisitResult::VisitChildren = self.visitor.visit_conditional(input) { + self.visit_expression(&input.condition); + self.visit_block(&input.block); + if let Some(stmt) = input.next.as_ref() { + self.visit_statement(stmt); + } + } + } + + fn visit_iteration(&mut self, input: &IterationStatement) { + if let VisitResult::VisitChildren = self.visitor.visit_iteration(input) { + self.visit_expression(&input.start); + self.visit_expression(&input.stop); + self.visit_block(&input.block); + } + } + + fn visit_console(&mut self, input: &ConsoleStatement) { + if let VisitResult::VisitChildren = self.visitor.visit_console(input) { + if let ConsoleFunction::Assert(expr) = &input.function { + self.visit_expression(expr); + } + } + } + + fn visit_expression_statement(&mut self, input: &ExpressionStatement) { + if let VisitResult::VisitChildren = self.visitor.visit_expression_statement(input) { + self.visit_expression(&input.expression); + } + } + + fn visit_block(&mut self, input: &Block) { + if let VisitResult::VisitChildren = self.visitor.visit_block(input) { + input.statements.iter().for_each(|stmt| self.visit_statement(stmt)); + } + } +} + +impl VisitorDirector { + fn visit_program(&mut self, input: &Program) { + if let VisitResult::VisitChildren = self.visitor.visit_program(input) { + input + .functions + .values() + .for_each(|function| self.visit_function(function)); + } + } + + fn visit_function(&mut self, input: &Function) { + if let VisitResult::VisitChildren = self.visitor.visit_function(input) { + self.visit_block(&input.block); + } + } +} diff --git a/compiler/parser/src/tokenizer/lexer.rs b/compiler/parser/src/tokenizer/lexer.rs index 45ced2d423..8d48cbbd94 100644 --- a/compiler/parser/src/tokenizer/lexer.rs +++ b/compiler/parser/src/tokenizer/lexer.rs @@ -46,7 +46,7 @@ fn eat_identifier(input: &mut Peekable>) -> Option bool { let i = c as u32; - return (0x202A <= i && i <= 0x202E) || (0x2066 <= i && i <= 0x2069); + (0x202A..=0x202E).contains(&i) || (0x2066..=0x2069).contains(&i) } impl Token { diff --git a/docs/grammar/README.md b/docs/grammar/README.md index e4a8a9f6e9..44c9f6b666 100644 Binary files a/docs/grammar/README.md and b/docs/grammar/README.md differ