From dbdb8f43b750f1f6d34f064f92b4344d3cae4053 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Sat, 12 Dec 2020 15:57:55 +0800 Subject: [PATCH] Change AST to struct. --- src/ast.rs | 76 ++++++++++++++++++++++++++++------------------ tests/optimizer.rs | 6 ++-- 2 files changed, 50 insertions(+), 32 deletions(-) diff --git a/src/ast.rs b/src/ast.rs index ecac8042..2867b48f 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -111,30 +111,39 @@ impl fmt::Display for ScriptFnDef { /// /// Currently, [`AST`] is neither `Send` nor `Sync`. Turn on the `sync` feature to make it `Send + Sync`. #[derive(Debug, Clone)] -pub struct AST( +pub struct AST { /// Global statements. - Vec, + statements: Vec, /// Script-defined functions. - Shared, -); + functions: Shared, +} impl Default for AST { fn default() -> Self { - Self(Vec::with_capacity(16), Default::default()) + Self { + statements: Vec::with_capacity(16), + functions: Default::default(), + } } } impl AST { /// Create a new [`AST`]. #[inline(always)] - pub fn new(statements: impl IntoIterator, lib: impl Into>) -> Self { - Self(statements.into_iter().collect(), lib.into()) + pub fn new( + statements: impl IntoIterator, + functions: impl Into>, + ) -> Self { + Self { + statements: statements.into_iter().collect(), + functions: functions.into(), + } } /// Get the statements. #[cfg(not(feature = "internals"))] #[inline(always)] pub(crate) fn statements(&self) -> &[Stmt] { - &self.0 + &self.statements } /// _(INTERNALS)_ Get the statements. /// Exported under the `internals` feature only. @@ -142,26 +151,26 @@ impl AST { #[deprecated(note = "this method is volatile and may change")] #[inline(always)] pub fn statements(&self) -> &[Stmt] { - &self.0 + &self.statements } /// Get a mutable reference to the statements. #[cfg(not(feature = "no_optimize"))] #[inline(always)] pub(crate) fn statements_mut(&mut self) -> &mut Vec { - &mut self.0 + &mut self.statements } /// Get the internal shared [`Module`] containing all script-defined functions. #[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_function"))] #[inline(always)] pub(crate) fn shared_lib(&self) -> Shared { - self.1.clone() + self.functions.clone() } /// Get the internal [`Module`] containing all script-defined functions. #[cfg(not(feature = "internals"))] #[inline(always)] pub(crate) fn lib(&self) -> &Module { - &self.1 + &self.functions } /// _(INTERNALS)_ Get the internal [`Module`] containing all script-defined functions. /// Exported under the `internals` feature only. @@ -169,7 +178,7 @@ impl AST { #[deprecated(note = "this method is volatile and may change")] #[inline(always)] pub fn lib(&self) -> &Module { - &self.1 + &self.functions } /// Clone the [`AST`]'s functions into a new [`AST`]. /// No statements are cloned. @@ -191,14 +200,20 @@ impl AST { mut filter: impl FnMut(FnNamespace, FnAccess, bool, &str, usize) -> bool, ) -> Self { let mut functions: Module = Default::default(); - functions.merge_filtered(&self.1, &mut filter); - Self(Default::default(), functions.into()) + functions.merge_filtered(&self.functions, &mut filter); + Self { + statements: Default::default(), + functions: functions.into(), + } } /// Clone the [`AST`]'s script statements into a new [`AST`]. /// No functions are cloned. #[inline(always)] pub fn clone_statements_only(&self) -> Self { - Self(self.0.clone(), Default::default()) + Self { + statements: self.statements.clone(), + functions: Default::default(), + } } /// Merge two [`AST`] into one. Both [`AST`]'s are untouched and a new, merged, version /// is returned. @@ -363,21 +378,24 @@ impl AST { other: &Self, mut filter: impl FnMut(FnNamespace, FnAccess, bool, &str, usize) -> bool, ) -> Self { - let Self(statements, functions) = self; + let Self { + statements, + functions, + } = self; - let ast = match (statements.is_empty(), other.0.is_empty()) { + let ast = match (statements.is_empty(), other.statements.is_empty()) { (false, false) => { let mut statements = statements.clone(); - statements.extend(other.0.iter().cloned()); + statements.extend(other.statements.iter().cloned()); statements } (false, true) => statements.clone(), - (true, false) => other.0.clone(), + (true, false) => other.statements.clone(), (true, true) => vec![], }; let mut functions = functions.as_ref().clone(); - functions.merge_filtered(&other.1, &mut filter); + functions.merge_filtered(&other.functions, &mut filter); Self::new(ast, functions) } @@ -438,9 +456,9 @@ impl AST { other: Self, mut filter: impl FnMut(FnNamespace, FnAccess, bool, &str, usize) -> bool, ) -> &mut Self { - self.0.extend(other.0.into_iter()); - if !other.1.is_empty() { - shared_make_mut(&mut self.1).merge_filtered(&other.1, &mut filter); + self.statements.extend(other.statements.into_iter()); + if !other.functions.is_empty() { + shared_make_mut(&mut self.functions).merge_filtered(&other.functions, &mut filter); } self } @@ -473,8 +491,8 @@ impl AST { &mut self, filter: impl FnMut(FnNamespace, FnAccess, &str, usize) -> bool, ) -> &mut Self { - if !self.1.is_empty() { - shared_make_mut(&mut self.1).retain_script_functions(filter); + if !self.functions.is_empty() { + shared_make_mut(&mut self.functions).retain_script_functions(filter); } self } @@ -484,18 +502,18 @@ impl AST { pub fn iter_functions<'a>( &'a self, ) -> impl Iterator + 'a { - self.1.iter_script_fn() + self.functions.iter_script_fn() } /// Clear all function definitions in the [`AST`]. #[cfg(not(feature = "no_function"))] #[inline(always)] pub fn clear_functions(&mut self) { - self.1 = Default::default(); + self.functions = Default::default(); } /// Clear all statements in the [`AST`], leaving only function definitions. #[inline(always)] pub fn clear_statements(&mut self) { - self.0 = vec![]; + self.statements = vec![]; } } diff --git a/tests/optimizer.rs b/tests/optimizer.rs index fa817bf1..bffc2633 100644 --- a/tests/optimizer.rs +++ b/tests/optimizer.rs @@ -55,17 +55,17 @@ fn test_optimizer_parse() -> Result<(), Box> { let ast = engine.compile("{ const DECISION = false; if DECISION { 42 } else { 123 } }")?; - assert!(format!("{:?}", ast).starts_with(r#"AST([Block([Const(IdentX { name: "DECISION", pos: 1:9 }, Some(Unit(0:0)), false, 1:3), Expr(IntegerConstant(123, 1:53))], 1:1)]"#)); + assert!(format!("{:?}", ast).starts_with(r#"AST { statements: [Block([Const(IdentX { name: "DECISION", pos: 1:9 }, Some(Unit(0:0)), false, 1:3), Expr(IntegerConstant(123, 1:53))], 1:1)]"#)); let ast = engine.compile("if 1 == 2 { 42 }")?; - assert!(format!("{:?}", ast).starts_with("AST([], Module(")); + assert!(format!("{:?}", ast).starts_with("AST { statements: [], functions: Module(")); engine.set_optimization_level(OptimizationLevel::Full); let ast = engine.compile("abs(-42)")?; - assert!(format!("{:?}", ast).starts_with(r"AST([Expr(IntegerConstant(42, 1:1))]")); + assert!(format!("{:?}", ast).starts_with(r"AST { statements: [Expr(IntegerConstant(42, 1:1))]")); Ok(()) }