From 495d202af48fd7d8d32d2cbc441646b0eb77a475 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Mon, 6 Jul 2020 10:02:54 +0800 Subject: [PATCH] Add new AST API. --- RELEASES.md | 1 + src/parser.rs | 63 ++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 46 insertions(+), 18 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index 72bbd0be..0e2d8677 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -24,6 +24,7 @@ New features * `Engine::disable_symbol` to surgically disable keywords and/or operators. * `Engine::register_custom_operator` to define a custom operator. * New low-level API `Engine::register_raw_fn`. +* `AST::clone_functions_only`, `AST::clone_functions_only_filtered` and `AST::clone_statements_only` to clone only part of an `AST`. Version 0.16.1 diff --git a/src/parser.rs b/src/parser.rs index 4db75d94..7b919b8d 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -49,7 +49,7 @@ pub use crate::utils::ImmutableString; /// Compiled AST (abstract syntax tree) of a Rhai script. /// -/// Currently, [`AST`] is neither `Send` nor `Sync`. Turn on the `sync` feature to make it `Send + Sync`. +/// Currently, `AST` is neither `Send` nor `Sync`. Turn on the `sync` feature to make it `Send + Sync`. #[derive(Debug, Clone, Default)] pub struct AST( /// Global statements. @@ -59,7 +59,7 @@ pub struct AST( ); impl AST { - /// Create a new [`AST`]. + /// Create a new `AST`. pub fn new(statements: Vec, lib: Module) -> Self { Self(statements, lib) } @@ -95,16 +95,43 @@ impl AST { &self.1 } - /// Merge two [`AST`] into one. Both [`AST`]'s are untouched and a new, merged, version + /// Clone the `AST`'s functions into a new `AST`. + /// No statements are cloned. + /// + /// This operation is cheap because functions are shared. + pub fn clone_functions_only(&self) -> Self { + self.clone_functions_only_filtered(|_, _, _| true) + } + + /// Clone the `AST`'s functions into a new `AST` based on a filter predicate. + /// No statements are cloned. + /// + /// This operation is cheap because functions are shared. + pub fn clone_functions_only_filtered( + &self, + filter: impl Fn(FnAccess, &str, usize) -> bool, + ) -> Self { + let mut functions: Module = Default::default(); + functions.merge_filtered(&self.1, filter); + Self(Default::default(), functions) + } + + /// Clone the `AST`'s script statements into a new `AST`. + /// No functions are cloned. + pub fn clone_statements_only(&self) -> Self { + Self(self.0.clone(), Default::default()) + } + + /// Merge two `AST` into one. Both `AST`'s are untouched and a new, merged, version /// is returned. /// - /// The second [`AST`] is simply appended to the end of the first _without any processing_. - /// Thus, the return value of the first [`AST`] (if using expression-statement syntax) is buried. - /// Of course, if the first [`AST`] uses a `return` statement at the end, then - /// the second [`AST`] will essentially be dead code. + /// The second `AST` is simply appended to the end of the first _without any processing_. + /// Thus, the return value of the first `AST` (if using expression-statement syntax) is buried. + /// Of course, if the first `AST` uses a `return` statement at the end, then + /// the second `AST` will essentially be dead code. /// - /// All script-defined functions in the second [`AST`] overwrite similarly-named functions - /// in the first [`AST`] with the same number of parameters. + /// All script-defined functions in the second `AST` overwrite similarly-named functions + /// in the first `AST` with the same number of parameters. /// /// # Example /// @@ -148,16 +175,16 @@ impl AST { self.merge_filtered(other, |_, _, _| true) } - /// Merge two [`AST`] into one. Both [`AST`]'s are untouched and a new, merged, version + /// Merge two `AST` into one. Both `AST`'s are untouched and a new, merged, version /// is returned. /// - /// The second [`AST`] is simply appended to the end of the first _without any processing_. - /// Thus, the return value of the first [`AST`] (if using expression-statement syntax) is buried. - /// Of course, if the first [`AST`] uses a `return` statement at the end, then - /// the second [`AST`] will essentially be dead code. + /// The second `AST` is simply appended to the end of the first _without any processing_. + /// Thus, the return value of the first `AST` (if using expression-statement syntax) is buried. + /// Of course, if the first `AST` uses a `return` statement at the end, then + /// the second `AST` will essentially be dead code. /// - /// All script-defined functions in the second [`AST`] are first selected based on a filter - /// predicate, then overwrite similarly-named functions in the first [`AST`] with the + /// All script-defined functions in the second `AST` are first selected based on a filter + /// predicate, then overwrite similarly-named functions in the first `AST` with the /// same number of parameters. /// /// # Example @@ -251,13 +278,13 @@ impl AST { self.1.retain_functions(filter); } - /// Clear all function definitions in the [`AST`]. + /// Clear all function definitions in the `AST`. #[cfg(not(feature = "no_function"))] pub fn clear_functions(&mut self) { self.1 = Default::default(); } - /// Clear all statements in the [`AST`], leaving only function definitions. + /// Clear all statements in the `AST`, leaving only function definitions. pub fn clear_statements(&mut self) { self.0 = vec![]; }