Remove Option from source and use empty string as no source.

This commit is contained in:
Stephen Chung 2022-01-01 17:20:00 +08:00
parent 8329baea29
commit 135b1f54c2
10 changed files with 118 additions and 98 deletions

View File

@ -209,9 +209,8 @@ impl Engine {
level: usize, level: usize,
) -> RhaiResult { ) -> RhaiResult {
let mut state = EvalState::new(); let mut state = EvalState::new();
if ast.source_raw().is_some() { global.source = ast.source_raw().clone();
global.source = ast.source_raw().cloned();
}
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
{ {
global.embedded_module_resolver = ast.resolver().cloned(); global.embedded_module_resolver = ast.resolver().cloned();

View File

@ -46,9 +46,8 @@ impl Engine {
pub fn run_ast_with_scope(&self, scope: &mut Scope, ast: &AST) -> RhaiResultOf<()> { pub fn run_ast_with_scope(&self, scope: &mut Scope, ast: &AST) -> RhaiResultOf<()> {
let global = &mut GlobalRuntimeState::new(); let global = &mut GlobalRuntimeState::new();
let mut state = EvalState::new(); let mut state = EvalState::new();
if ast.source_raw().is_some() { global.source = ast.source_raw().clone();
global.source = ast.source_raw().cloned();
}
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
{ {
global.embedded_module_resolver = ast.resolver().cloned(); global.embedded_module_resolver = ast.resolver().cloned();

View File

@ -17,7 +17,8 @@ use std::{
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct AST { pub struct AST {
/// Source of the [`AST`]. /// Source of the [`AST`].
source: Option<Identifier>, /// No source if string is empty.
source: Identifier,
/// Global statements. /// Global statements.
body: StmtBlock, body: StmtBlock,
/// Script-defined functions. /// Script-defined functions.
@ -45,7 +46,7 @@ impl AST {
#[cfg(not(feature = "no_function"))] functions: impl Into<crate::Shared<crate::Module>>, #[cfg(not(feature = "no_function"))] functions: impl Into<crate::Shared<crate::Module>>,
) -> Self { ) -> Self {
Self { Self {
source: None, source: Identifier::new_const(),
body: StmtBlock::new(statements, Position::NONE), body: StmtBlock::new(statements, Position::NONE),
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
functions: functions.into(), functions: functions.into(),
@ -63,7 +64,7 @@ impl AST {
#[cfg(not(feature = "no_function"))] functions: impl Into<crate::Shared<crate::Module>>, #[cfg(not(feature = "no_function"))] functions: impl Into<crate::Shared<crate::Module>>,
) -> Self { ) -> Self {
Self { Self {
source: None, source: Identifier::new_const(),
body: StmtBlock::new(statements, Position::NONE), body: StmtBlock::new(statements, Position::NONE),
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
functions: functions.into(), functions: functions.into(),
@ -111,7 +112,7 @@ impl AST {
#[must_use] #[must_use]
pub fn empty() -> Self { pub fn empty() -> Self {
Self { Self {
source: None, source: Identifier::new_const(),
body: StmtBlock::NONE, body: StmtBlock::NONE,
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
functions: crate::Module::new().into(), functions: crate::Module::new().into(),
@ -123,13 +124,17 @@ impl AST {
#[inline(always)] #[inline(always)]
#[must_use] #[must_use]
pub fn source(&self) -> Option<&str> { pub fn source(&self) -> Option<&str> {
self.source.as_ref().map(|s| s.as_str()) if self.source.is_empty() {
None
} else {
Some(&self.source)
}
} }
/// Get a reference to the source. /// Get a reference to the source.
#[inline(always)] #[inline(always)]
#[must_use] #[must_use]
pub(crate) fn source_raw(&self) -> Option<&Identifier> { pub(crate) fn source_raw(&self) -> &Identifier {
self.source.as_ref() &self.source
} }
/// Set the source. /// Set the source.
#[inline] #[inline]
@ -139,13 +144,13 @@ impl AST {
crate::Shared::get_mut(&mut self.functions) crate::Shared::get_mut(&mut self.functions)
.as_mut() .as_mut()
.map(|m| m.set_id(source.clone())); .map(|m| m.set_id(source.clone()));
self.source = Some(source); self.source = source;
self self
} }
/// Clear the source. /// Clear the source.
#[inline(always)] #[inline(always)]
pub fn clear_source(&mut self) -> &mut Self { pub fn clear_source(&mut self) -> &mut Self {
self.source = None; self.source.clear();
self self
} }
/// Get the statements. /// Get the statements.
@ -467,8 +472,6 @@ impl AST {
(true, true) => StmtBlock::NONE, (true, true) => StmtBlock::NONE,
}; };
let source = other.source.clone().or_else(|| self.source.clone());
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
let functions = { let functions = {
let mut functions = self.functions.as_ref().clone(); let mut functions = self.functions.as_ref().clone();
@ -476,12 +479,12 @@ impl AST {
functions functions
}; };
if let Some(source) = source { if !other.source.is_empty() {
Self::new_with_source( Self::new_with_source(
merged, merged,
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
functions, functions,
source, other.source.clone(),
) )
} else { } else {
Self::new( Self::new(

View File

@ -2,6 +2,7 @@
use crate::api::custom_syntax::CustomSyntax; use crate::api::custom_syntax::CustomSyntax;
use crate::ast::{Expr, FnCallExpr, Ident, OpAssignment, Stmt, AST_OPTION_FLAGS::*}; use crate::ast::{Expr, FnCallExpr, Ident, OpAssignment, Stmt, AST_OPTION_FLAGS::*};
use crate::func::call::FnResolutionCache;
use crate::func::native::{OnDebugCallback, OnParseTokenCallback, OnPrintCallback, OnVarCallback}; use crate::func::native::{OnDebugCallback, OnParseTokenCallback, OnPrintCallback, OnVarCallback};
use crate::func::{get_hasher, CallableFunction, IteratorFn}; use crate::func::{get_hasher, CallableFunction, IteratorFn};
use crate::module::Namespace; use crate::module::Namespace;
@ -507,7 +508,8 @@ pub struct GlobalRuntimeState {
/// Stack of imported [modules][Module]. /// Stack of imported [modules][Module].
modules: StaticVec<Shared<Module>>, modules: StaticVec<Shared<Module>>,
/// Source of the current context. /// Source of the current context.
pub source: Option<Identifier>, /// No source if the string is empty.
pub source: Identifier,
/// Number of operations performed. /// Number of operations performed.
pub num_operations: u64, pub num_operations: u64,
/// Number of modules loaded. /// Number of modules loaded.
@ -539,7 +541,7 @@ impl GlobalRuntimeState {
Self { Self {
keys: StaticVec::new_const(), keys: StaticVec::new_const(),
modules: StaticVec::new_const(), modules: StaticVec::new_const(),
source: None, source: Identifier::new_const(),
num_operations: 0, num_operations: 0,
num_modules_loaded: 0, num_modules_loaded: 0,
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
@ -629,11 +631,11 @@ impl GlobalRuntimeState {
/// Get the specified function via its hash key from the stack of globally-imported [modules][Module]. /// Get the specified function via its hash key from the stack of globally-imported [modules][Module].
#[inline] #[inline]
#[must_use] #[must_use]
pub fn get_fn(&self, hash: u64) -> Option<(&CallableFunction, Option<&Identifier>)> { pub fn get_fn(&self, hash: u64) -> Option<(&CallableFunction, Option<&str>)> {
self.modules self.modules
.iter() .iter()
.rev() .rev()
.find_map(|m| m.get_qualified_fn(hash).map(|f| (f, m.id_raw()))) .find_map(|m| m.get_qualified_fn(hash).map(|f| (f, m.id())))
} }
/// Does the specified [`TypeId`][std::any::TypeId] iterator exist in the stack of /// Does the specified [`TypeId`][std::any::TypeId] iterator exist in the stack of
/// globally-imported [modules][Module]? /// globally-imported [modules][Module]?
@ -746,20 +748,6 @@ impl fmt::Debug for GlobalRuntimeState {
} }
} }
/// _(internals)_ An entry in a function resolution cache.
/// Exported under the `internals` feature only.
#[derive(Debug, Clone)]
pub struct FnResolutionCacheEntry {
/// Function.
pub func: CallableFunction,
/// Optional source.
pub source: Option<Box<str>>,
}
/// _(internals)_ A function resolution cache.
/// Exported under the `internals` feature only.
pub type FnResolutionCache = BTreeMap<u64, Option<Box<FnResolutionCacheEntry>>>;
/// _(internals)_ A type that holds all the current states of the [`Engine`]. /// _(internals)_ A type that holds all the current states of the [`Engine`].
/// Exported under the `internals` feature only. /// Exported under the `internals` feature only.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -844,7 +832,11 @@ impl<'x, 'px, 'pt> EvalContext<'_, 'x, 'px, '_, '_, '_, '_, 'pt> {
#[inline(always)] #[inline(always)]
#[must_use] #[must_use]
pub fn source(&self) -> Option<&str> { pub fn source(&self) -> Option<&str> {
self.global.source.as_ref().map(|s| s.as_str()) if self.global.source.is_empty() {
None
} else {
Some(&self.global.source)
}
} }
/// The current [`Scope`]. /// The current [`Scope`].
#[inline(always)] #[inline(always)]
@ -3041,8 +3033,8 @@ impl Engine {
err_map.insert("message".into(), err.to_string().into()); err_map.insert("message".into(), err.to_string().into());
if let Some(ref source) = global.source { if !global.source.is_empty() {
err_map.insert("source".into(), source.as_str().into()); err_map.insert("source".into(), global.source.clone().into());
} }
if err_pos.is_none() { if err_pos.is_none() {
@ -3174,7 +3166,11 @@ impl Engine {
{ {
use crate::ModuleResolver; use crate::ModuleResolver;
let source = global.source.as_ref().map(|s| s.as_str()); let source = if global.source.is_empty() {
None
} else {
Some(global.source.as_str())
};
let path_pos = expr.position(); let path_pos = expr.position();
let module = global let module = global

View File

@ -6,9 +6,8 @@ use super::{get_builtin_binary_op_fn, get_builtin_op_assignment_fn};
use crate::api::default_limits::MAX_DYNAMIC_PARAMETERS; use crate::api::default_limits::MAX_DYNAMIC_PARAMETERS;
use crate::ast::{Expr, FnCallHashes, Stmt}; use crate::ast::{Expr, FnCallHashes, Stmt};
use crate::engine::{ use crate::engine::{
EvalState, FnResolutionCacheEntry, GlobalRuntimeState, KEYWORD_DEBUG, KEYWORD_EVAL, EvalState, GlobalRuntimeState, KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_FN_PTR,
KEYWORD_FN_PTR, KEYWORD_FN_PTR_CALL, KEYWORD_FN_PTR_CURRY, KEYWORD_IS_DEF_VAR, KEYWORD_PRINT, KEYWORD_FN_PTR_CALL, KEYWORD_FN_PTR_CURRY, KEYWORD_IS_DEF_VAR, KEYWORD_PRINT, KEYWORD_TYPE_OF,
KEYWORD_TYPE_OF,
}; };
use crate::module::Namespace; use crate::module::Namespace;
use crate::tokenizer::Token; use crate::tokenizer::Token;
@ -20,6 +19,7 @@ use crate::{
use std::prelude::v1::*; use std::prelude::v1::*;
use std::{ use std::{
any::{type_name, TypeId}, any::{type_name, TypeId},
collections::BTreeMap,
convert::TryFrom, convert::TryFrom,
mem, mem,
}; };
@ -125,6 +125,24 @@ pub fn ensure_no_data_race(
Ok(()) Ok(())
} }
/// _(internals)_ An entry in a function resolution cache.
/// Exported under the `internals` feature only.
#[derive(Debug, Clone)]
pub struct FnResolutionCacheEntry {
/// Function.
pub func: CallableFunction,
/// Optional source.
/// No source if the string is empty.
pub source: Identifier,
}
/// _(internals)_ A function resolution cache.
/// Exported under the `internals` feature only.
///
/// [`FnResolutionCacheEntry`] is [`Box`]ed in order to pack as many entries inside a single B-Tree
/// level as possible.
pub type FnResolutionCache = BTreeMap<u64, Option<Box<FnResolutionCacheEntry>>>;
impl Engine { impl Engine {
/// Generate the signature for a function call. /// Generate the signature for a function call.
#[inline] #[inline]
@ -206,14 +224,14 @@ impl Engine {
.find_map(|m| { .find_map(|m| {
m.get_fn(hash).cloned().map(|func| FnResolutionCacheEntry { m.get_fn(hash).cloned().map(|func| FnResolutionCacheEntry {
func, func,
source: m.id_raw().map(|s| s.to_string().into_boxed_str()), source: m.id_raw().clone(),
}) })
}) })
.or_else(|| { .or_else(|| {
self.global_modules.iter().find_map(|m| { self.global_modules.iter().find_map(|m| {
m.get_fn(hash).cloned().map(|func| FnResolutionCacheEntry { m.get_fn(hash).cloned().map(|func| FnResolutionCacheEntry {
func, func,
source: m.id_raw().map(|s| s.to_string().into_boxed_str()), source: m.id_raw().clone(),
}) })
}) })
}) })
@ -222,7 +240,8 @@ impl Engine {
.get_fn(hash) .get_fn(hash)
.map(|(func, source)| FnResolutionCacheEntry { .map(|(func, source)| FnResolutionCacheEntry {
func: func.clone(), func: func.clone(),
source: source.map(|s| s.to_string().into_boxed_str()), source: source
.map_or_else(|| Identifier::new_const(), Into::into),
}) })
}) })
.or_else(|| { .or_else(|| {
@ -230,7 +249,7 @@ impl Engine {
m.get_qualified_fn(hash).cloned().map(|func| { m.get_qualified_fn(hash).cloned().map(|func| {
FnResolutionCacheEntry { FnResolutionCacheEntry {
func, func,
source: m.id_raw().map(|s| s.to_string().into_boxed_str()), source: m.id_raw().clone(),
} }
}) })
}) })
@ -253,7 +272,7 @@ impl Engine {
func: CallableFunction::from_method( func: CallableFunction::from_method(
Box::new(f) as Box<FnAny> Box::new(f) as Box<FnAny>
), ),
source: None, source: Identifier::new_const(),
} }
}) })
} else { } else {
@ -265,7 +284,7 @@ impl Engine {
func: CallableFunction::from_method( func: CallableFunction::from_method(
Box::new(f) as Box<FnAny> Box::new(f) as Box<FnAny>
), ),
source: None, source: Identifier::new_const(),
}) })
} }
.map(Box::new) .map(Box::new)
@ -353,10 +372,15 @@ impl Engine {
} }
// Run external function // Run external function
let source = source let source = if source.is_empty() {
.as_ref() if parent_source.is_empty() {
.map(|s| &**s) None
.or_else(|| parent_source.as_ref().map(|s| s.as_str())); } else {
Some(parent_source.as_str())
}
} else {
Some(source.as_str())
};
let context = (self, name, source, &*global, lib, pos).into(); let context = (self, name, source, &*global, lib, pos).into();
@ -400,7 +424,11 @@ impl Engine {
pos, pos,
) )
})?; })?;
let source = global.source.as_ref().map(|s| s.as_str()); let source = if global.source.is_empty() {
None
} else {
Some(global.source.as_str())
};
(debug(&text, source, pos).into(), false) (debug(&text, source, pos).into(), false)
} else { } else {
(Dynamic::UNIT, false) (Dynamic::UNIT, false)
@ -572,7 +600,7 @@ impl Engine {
// Script-defined function call? // Script-defined function call?
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
if let Some(FnResolutionCacheEntry { func, source }) = self if let Some(FnResolutionCacheEntry { func, mut source }) = self
.resolve_fn( .resolve_fn(
global, global,
state, state,
@ -603,13 +631,12 @@ impl Engine {
} }
}; };
mem::swap(&mut global.source, &mut source);
let result = if _is_method_call { let result = if _is_method_call {
// Method call of script function - map first argument to `this` // Method call of script function - map first argument to `this`
let (first_arg, rest_args) = args.split_first_mut().expect("not empty"); let (first_arg, rest_args) = args.split_first_mut().expect("not empty");
let orig_source = global.source.take();
global.source = source.map(Into::into);
let level = _level + 1; let level = _level + 1;
let result = self.call_script_fn( let result = self.call_script_fn(
@ -625,9 +652,6 @@ impl Engine {
level, level,
); );
// Restore the original source
global.source = orig_source;
result? result?
} else { } else {
// Normal call of script function // Normal call of script function
@ -641,18 +665,12 @@ impl Engine {
.change_first_arg_to_copy(args); .change_first_arg_to_copy(args);
} }
let orig_source = global.source.take();
global.source = source.map(Into::into);
let level = _level + 1; let level = _level + 1;
let result = self.call_script_fn( let result = self.call_script_fn(
scope, global, state, lib, &mut None, func, args, pos, true, level, scope, global, state, lib, &mut None, func, args, pos, true, level,
); );
// Restore the original source
global.source = orig_source;
// Restore the original reference // Restore the original reference
if let Some(bk) = backup { if let Some(bk) = backup {
bk.restore_first_arg(args) bk.restore_first_arg(args)
@ -661,6 +679,9 @@ impl Engine {
result? result?
}; };
// Restore the original source
mem::swap(&mut global.source, &mut source);
return Ok((result, false)); return Ok((result, false));
} }
@ -1058,11 +1079,7 @@ impl Engine {
return result.map_err(|err| { return result.map_err(|err| {
ERR::ErrorInFunctionCall( ERR::ErrorInFunctionCall(
KEYWORD_EVAL.to_string(), KEYWORD_EVAL.to_string(),
global global.source.to_string(),
.source
.as_ref()
.map(Identifier::to_string)
.unwrap_or_default(),
err, err,
pos, pos,
) )
@ -1265,7 +1282,7 @@ impl Engine {
} else { } else {
let new_scope = &mut Scope::new(); let new_scope = &mut Scope::new();
let mut source = module.id_raw().cloned(); let mut source = module.id_raw().clone();
mem::swap(&mut global.source, &mut source); mem::swap(&mut global.source, &mut source);
let level = level + 1; let level = level + 1;

View File

@ -90,7 +90,7 @@ impl<'a, M: AsRef<[&'a Module]> + ?Sized, S: AsRef<str> + 'a + ?Sized>
Self { Self {
engine: value.0, engine: value.0,
fn_name: value.1.as_ref(), fn_name: value.1.as_ref(),
source: value.2.map(|v| v.as_ref()), source: value.2.map(S::as_ref),
global: Some(value.3), global: Some(value.3),
lib: value.4.as_ref(), lib: value.4.as_ref(),
pos: value.5, pos: value.5,
@ -156,7 +156,7 @@ impl<'a> NativeCallContext<'a> {
Self { Self {
engine, engine,
fn_name: fn_name.as_ref(), fn_name: fn_name.as_ref(),
source: source.map(|v| v.as_ref()), source: source.map(S::as_ref),
global: Some(global), global: Some(global),
lib, lib,
pos, pos,

View File

@ -47,9 +47,8 @@ impl Engine {
fn_def fn_def
.lib .lib
.as_ref() .as_ref()
.and_then(|m| m.id().map(|id| id.to_string())) .and_then(|m| m.id().map(str::to_string))
.or_else(|| global.source.as_ref().map(|s| s.to_string())) .unwrap_or_else(|| global.source.to_string()),
.unwrap_or_default(),
err, err,
pos, pos,
) )

View File

@ -247,7 +247,10 @@ pub use ast::{
pub use ast::FloatWrapper; pub use ast::FloatWrapper;
#[cfg(feature = "internals")] #[cfg(feature = "internals")]
pub use engine::{EvalState, FnResolutionCache, FnResolutionCacheEntry, GlobalRuntimeState}; pub use engine::{EvalState, GlobalRuntimeState};
#[cfg(feature = "internals")]
pub use func::call::{FnResolutionCache, FnResolutionCacheEntry};
#[cfg(feature = "internals")] #[cfg(feature = "internals")]
pub use module::Namespace; pub use module::Namespace;

View File

@ -131,7 +131,8 @@ pub fn calc_native_fn_hash(
#[derive(Clone)] #[derive(Clone)]
pub struct Module { pub struct Module {
/// ID identifying the module. /// ID identifying the module.
id: Option<Identifier>, /// No ID if string is empty.
id: Identifier,
/// Is this module internal? /// Is this module internal?
pub(crate) internal: bool, pub(crate) internal: bool,
/// Is this module part of a standard library? /// Is this module part of a standard library?
@ -170,8 +171,9 @@ impl fmt::Debug for Module {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut d = f.debug_struct("Module"); let mut d = f.debug_struct("Module");
self.id.as_ref().map(|id| d.field("id", id)); if !self.id.is_empty() {
d.field("id", &self.id);
}
if !self.modules.is_empty() { if !self.modules.is_empty() {
d.field( d.field(
"modules", "modules",
@ -241,7 +243,7 @@ impl Module {
#[must_use] #[must_use]
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
id: None, id: Identifier::new_const(),
internal: false, internal: false,
standard: false, standard: false,
modules: BTreeMap::new(), modules: BTreeMap::new(),
@ -270,18 +272,24 @@ impl Module {
#[inline] #[inline]
#[must_use] #[must_use]
pub fn id(&self) -> Option<&str> { pub fn id(&self) -> Option<&str> {
self.id_raw().map(|s| s.as_str()) if self.id_raw().is_empty() {
None
} else {
Some(self.id_raw())
}
} }
/// Get the ID of the [`Module`] as an [`Identifier`], if any. /// Get the ID of the [`Module`] as an [`Identifier`], if any.
#[inline(always)] #[inline(always)]
#[must_use] #[must_use]
pub(crate) const fn id_raw(&self) -> Option<&Identifier> { pub(crate) const fn id_raw(&self) -> &Identifier {
self.id.as_ref() &self.id
} }
/// Set the ID of the [`Module`]. /// Set the ID of the [`Module`].
/// ///
/// If the string is empty, it is equivalent to clearing the ID.
///
/// # Example /// # Example
/// ///
/// ``` /// ```
@ -292,7 +300,7 @@ impl Module {
/// ``` /// ```
#[inline(always)] #[inline(always)]
pub fn set_id(&mut self, id: impl Into<Identifier>) -> &mut Self { pub fn set_id(&mut self, id: impl Into<Identifier>) -> &mut Self {
self.id = Some(id.into()); self.id = id.into();
self self
} }
/// Clear the ID of the [`Module`]. /// Clear the ID of the [`Module`].
@ -309,7 +317,7 @@ impl Module {
/// ``` /// ```
#[inline(always)] #[inline(always)]
pub fn clear_id(&mut self) -> &mut Self { pub fn clear_id(&mut self) -> &mut Self {
self.id = None; self.id.clear();
self self
} }
@ -1616,11 +1624,7 @@ impl Module {
}); });
} }
if let Some(s) = ast.source_raw() { module.set_id(ast.source_raw().clone());
module.set_id(s.clone());
} else {
module.clear_id();
}
module.build_index(); module.build_index();

View File

@ -80,21 +80,21 @@ fn test_optimizer_parse() -> Result<(), Box<EvalAltResult>> {
assert_eq!( assert_eq!(
format!("{:?}", ast), format!("{:?}", ast),
"AST { source: None, body: Block[Expr(123 @ 1:53)], functions: Module, resolver: None }" "AST { source: \"\", body: Block[Expr(123 @ 1:53)], functions: Module, resolver: None }"
); );
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_eq!( assert_eq!(
format!("{:?}", ast), format!("{:?}", ast),
r#"AST { source: None, body: Block[Var(false @ 1:18, "DECISION" @ 1:7, (Constant), 1:1), Expr(123 @ 1:51)], functions: Module, resolver: None }"# r#"AST { source: "", body: Block[Var(false @ 1:18, "DECISION" @ 1:7, (Constant), 1:1), Expr(123 @ 1:51)], functions: Module, resolver: None }"#
); );
let ast = engine.compile("if 1 == 2 { 42 }")?; let ast = engine.compile("if 1 == 2 { 42 }")?;
assert_eq!( assert_eq!(
format!("{:?}", ast), format!("{:?}", ast),
"AST { source: None, body: Block[], functions: Module, resolver: None }" "AST { source: \"\", body: Block[], functions: Module, resolver: None }"
); );
engine.set_optimization_level(OptimizationLevel::Full); engine.set_optimization_level(OptimizationLevel::Full);
@ -103,7 +103,7 @@ fn test_optimizer_parse() -> Result<(), Box<EvalAltResult>> {
assert_eq!( assert_eq!(
format!("{:?}", ast), format!("{:?}", ast),
"AST { source: None, body: Block[Expr(42 @ 1:1)], functions: Module, resolver: None }" "AST { source: \"\", body: Block[Expr(42 @ 1:1)], functions: Module, resolver: None }"
); );
Ok(()) Ok(())