Change AST to struct.

This commit is contained in:
Stephen Chung 2020-12-12 15:57:55 +08:00
parent 40b6a014ae
commit dbdb8f43b7
2 changed files with 50 additions and 32 deletions

View File

@ -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`. /// Currently, [`AST`] is neither `Send` nor `Sync`. Turn on the `sync` feature to make it `Send + Sync`.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct AST( pub struct AST {
/// Global statements. /// Global statements.
Vec<Stmt>, statements: Vec<Stmt>,
/// Script-defined functions. /// Script-defined functions.
Shared<Module>, functions: Shared<Module>,
); }
impl Default for AST { impl Default for AST {
fn default() -> Self { fn default() -> Self {
Self(Vec::with_capacity(16), Default::default()) Self {
statements: Vec::with_capacity(16),
functions: Default::default(),
}
} }
} }
impl AST { impl AST {
/// Create a new [`AST`]. /// Create a new [`AST`].
#[inline(always)] #[inline(always)]
pub fn new(statements: impl IntoIterator<Item = Stmt>, lib: impl Into<Shared<Module>>) -> Self { pub fn new(
Self(statements.into_iter().collect(), lib.into()) statements: impl IntoIterator<Item = Stmt>,
functions: impl Into<Shared<Module>>,
) -> Self {
Self {
statements: statements.into_iter().collect(),
functions: functions.into(),
}
} }
/// Get the statements. /// Get the statements.
#[cfg(not(feature = "internals"))] #[cfg(not(feature = "internals"))]
#[inline(always)] #[inline(always)]
pub(crate) fn statements(&self) -> &[Stmt] { pub(crate) fn statements(&self) -> &[Stmt] {
&self.0 &self.statements
} }
/// _(INTERNALS)_ Get the statements. /// _(INTERNALS)_ Get the statements.
/// Exported under the `internals` feature only. /// Exported under the `internals` feature only.
@ -142,26 +151,26 @@ impl AST {
#[deprecated(note = "this method is volatile and may change")] #[deprecated(note = "this method is volatile and may change")]
#[inline(always)] #[inline(always)]
pub fn statements(&self) -> &[Stmt] { pub fn statements(&self) -> &[Stmt] {
&self.0 &self.statements
} }
/// Get a mutable reference to the statements. /// Get a mutable reference to the statements.
#[cfg(not(feature = "no_optimize"))] #[cfg(not(feature = "no_optimize"))]
#[inline(always)] #[inline(always)]
pub(crate) fn statements_mut(&mut self) -> &mut Vec<Stmt> { pub(crate) fn statements_mut(&mut self) -> &mut Vec<Stmt> {
&mut self.0 &mut self.statements
} }
/// Get the internal shared [`Module`] containing all script-defined functions. /// Get the internal shared [`Module`] containing all script-defined functions.
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
#[inline(always)] #[inline(always)]
pub(crate) fn shared_lib(&self) -> Shared<Module> { pub(crate) fn shared_lib(&self) -> Shared<Module> {
self.1.clone() self.functions.clone()
} }
/// Get the internal [`Module`] containing all script-defined functions. /// Get the internal [`Module`] containing all script-defined functions.
#[cfg(not(feature = "internals"))] #[cfg(not(feature = "internals"))]
#[inline(always)] #[inline(always)]
pub(crate) fn lib(&self) -> &Module { pub(crate) fn lib(&self) -> &Module {
&self.1 &self.functions
} }
/// _(INTERNALS)_ Get the internal [`Module`] containing all script-defined functions. /// _(INTERNALS)_ Get the internal [`Module`] containing all script-defined functions.
/// Exported under the `internals` feature only. /// Exported under the `internals` feature only.
@ -169,7 +178,7 @@ impl AST {
#[deprecated(note = "this method is volatile and may change")] #[deprecated(note = "this method is volatile and may change")]
#[inline(always)] #[inline(always)]
pub fn lib(&self) -> &Module { pub fn lib(&self) -> &Module {
&self.1 &self.functions
} }
/// Clone the [`AST`]'s functions into a new [`AST`]. /// Clone the [`AST`]'s functions into a new [`AST`].
/// No statements are cloned. /// No statements are cloned.
@ -191,14 +200,20 @@ impl AST {
mut filter: impl FnMut(FnNamespace, FnAccess, bool, &str, usize) -> bool, mut filter: impl FnMut(FnNamespace, FnAccess, bool, &str, usize) -> bool,
) -> Self { ) -> Self {
let mut functions: Module = Default::default(); let mut functions: Module = Default::default();
functions.merge_filtered(&self.1, &mut filter); functions.merge_filtered(&self.functions, &mut filter);
Self(Default::default(), functions.into()) Self {
statements: Default::default(),
functions: functions.into(),
}
} }
/// Clone the [`AST`]'s script statements into a new [`AST`]. /// Clone the [`AST`]'s script statements into a new [`AST`].
/// No functions are cloned. /// No functions are cloned.
#[inline(always)] #[inline(always)]
pub fn clone_statements_only(&self) -> Self { 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 /// Merge two [`AST`] into one. Both [`AST`]'s are untouched and a new, merged, version
/// is returned. /// is returned.
@ -363,21 +378,24 @@ impl AST {
other: &Self, other: &Self,
mut filter: impl FnMut(FnNamespace, FnAccess, bool, &str, usize) -> bool, mut filter: impl FnMut(FnNamespace, FnAccess, bool, &str, usize) -> bool,
) -> Self { ) -> 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) => { (false, false) => {
let mut statements = statements.clone(); let mut statements = statements.clone();
statements.extend(other.0.iter().cloned()); statements.extend(other.statements.iter().cloned());
statements statements
} }
(false, true) => statements.clone(), (false, true) => statements.clone(),
(true, false) => other.0.clone(), (true, false) => other.statements.clone(),
(true, true) => vec![], (true, true) => vec![],
}; };
let mut functions = functions.as_ref().clone(); 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) Self::new(ast, functions)
} }
@ -438,9 +456,9 @@ impl AST {
other: Self, other: Self,
mut filter: impl FnMut(FnNamespace, FnAccess, bool, &str, usize) -> bool, mut filter: impl FnMut(FnNamespace, FnAccess, bool, &str, usize) -> bool,
) -> &mut Self { ) -> &mut Self {
self.0.extend(other.0.into_iter()); self.statements.extend(other.statements.into_iter());
if !other.1.is_empty() { if !other.functions.is_empty() {
shared_make_mut(&mut self.1).merge_filtered(&other.1, &mut filter); shared_make_mut(&mut self.functions).merge_filtered(&other.functions, &mut filter);
} }
self self
} }
@ -473,8 +491,8 @@ impl AST {
&mut self, &mut self,
filter: impl FnMut(FnNamespace, FnAccess, &str, usize) -> bool, filter: impl FnMut(FnNamespace, FnAccess, &str, usize) -> bool,
) -> &mut Self { ) -> &mut Self {
if !self.1.is_empty() { if !self.functions.is_empty() {
shared_make_mut(&mut self.1).retain_script_functions(filter); shared_make_mut(&mut self.functions).retain_script_functions(filter);
} }
self self
} }
@ -484,18 +502,18 @@ impl AST {
pub fn iter_functions<'a>( pub fn iter_functions<'a>(
&'a self, &'a self,
) -> impl Iterator<Item = (FnNamespace, FnAccess, &str, usize, &ScriptFnDef)> + 'a { ) -> impl Iterator<Item = (FnNamespace, FnAccess, &str, usize, &ScriptFnDef)> + 'a {
self.1.iter_script_fn() self.functions.iter_script_fn()
} }
/// Clear all function definitions in the [`AST`]. /// Clear all function definitions in the [`AST`].
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
#[inline(always)] #[inline(always)]
pub fn clear_functions(&mut self) { pub fn clear_functions(&mut self) {
self.1 = Default::default(); self.functions = Default::default();
} }
/// Clear all statements in the [`AST`], leaving only function definitions. /// Clear all statements in the [`AST`], leaving only function definitions.
#[inline(always)] #[inline(always)]
pub fn clear_statements(&mut self) { pub fn clear_statements(&mut self) {
self.0 = vec![]; self.statements = vec![];
} }
} }

View File

@ -55,17 +55,17 @@ fn test_optimizer_parse() -> Result<(), Box<EvalAltResult>> {
let ast = engine.compile("{ const DECISION = false; if DECISION { 42 } else { 123 } }")?; 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 }")?; 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); engine.set_optimization_level(OptimizationLevel::Full);
let ast = engine.compile("abs(-42)")?; 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(()) Ok(())
} }