Change AST to struct.
This commit is contained in:
parent
40b6a014ae
commit
dbdb8f43b7
76
src/ast.rs
76
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<Stmt>,
|
||||
statements: Vec<Stmt>,
|
||||
/// Script-defined functions.
|
||||
Shared<Module>,
|
||||
);
|
||||
functions: Shared<Module>,
|
||||
}
|
||||
|
||||
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<Item = Stmt>, lib: impl Into<Shared<Module>>) -> Self {
|
||||
Self(statements.into_iter().collect(), lib.into())
|
||||
pub fn new(
|
||||
statements: impl IntoIterator<Item = Stmt>,
|
||||
functions: impl Into<Shared<Module>>,
|
||||
) -> 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<Stmt> {
|
||||
&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<Module> {
|
||||
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<Item = (FnNamespace, FnAccess, &str, usize, &ScriptFnDef)> + '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![];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,17 +55,17 @@ fn test_optimizer_parse() -> Result<(), Box<EvalAltResult>> {
|
||||
|
||||
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(())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user