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`.
|
/// 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![];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user