Struct arithmetic_eval::exec::ExecutableModule
source · pub struct ExecutableModule<T> { /* private fields */ }
Expand description
Executable module together with its imports.
An ExecutableModule
is a result of compiling a Block
of statements. A module can import
Value
s, such as commonly used functions. Importing is performed
when building the module.
After the module is created, it can be associated with an environment via Self::with_env()
and run
.
If the last statement of the block is an expression (that is, not terminated with a ;
),
it is the result of the execution; otherwise, the result is Value::void()
.
In some cases (e.g., when building a REPL) it is useful to get not only the outcome
of the module execution, but the intermediate results as well. Use Self::with_mutable_env()
for such cases.
ExecutableModule
s are generic with respect to the primitive value type, just like Value
.
§Examples
§Basic usage
use arithmetic_parser::grammars::{F32Grammar, Parse, Untyped};
use arithmetic_eval::{env, fns, Environment, ExecutableModule, Value};
let module = Untyped::<F32Grammar>::parse_statements(
"xs.fold(-INFINITY, max)",
)?;
let module = ExecutableModule::new("test", &module)?;
let mut env = Environment::new();
env.insert("INFINITY", Value::Prim(f32::INFINITY))
.insert("xs", Value::void())
.extend(env::Prelude::iter().chain(env::Comparisons::iter()));
// With the original imports, the returned value is `-INFINITY`.
assert_eq!(module.with_env(&env)?.run()?, Value::Prim(f32::NEG_INFINITY));
// Imports can be changed. Let's check that `xs` is indeed an import.
assert!(module.is_import("xs"));
// It's possible to iterate over imports, too.
let imports = module.import_names().collect::<HashSet<_>>();
assert!(imports.is_superset(&HashSet::from_iter(vec!["max", "fold"])));
// Change the `xs` import and run the module again.
let array = [1.0, -3.0, 2.0, 0.5].iter().copied()
.map(Value::Prim)
.collect();
env.insert("xs", Value::Tuple(array));
assert_eq!(module.with_env(&env)?.run()?, Value::Prim(2.0));
§Reusing a module
The same module can be run with multiple imports:
let block = Untyped::<F32Grammar>::parse_statements("x + y")?;
let module = ExecutableModule::new("test", &block)?;
let mut env = Environment::new();
env.insert("x", Value::Prim(3.0)).insert("y", Value::Prim(5.0));
assert_eq!(module.with_env(&env)?.run()?, Value::Prim(8.0));
env.insert("x", Value::Prim(-1.0));
assert_eq!(module.with_env(&env)?.run()?, Value::Prim(4.0));
§Behavior on errors
Self::with_mutable_env()
modifies the environment even if an error occurs during execution:
let module = Untyped::<F32Grammar>::parse_statements("x = 5; assert_eq(x, 4);")?;
let module = ExecutableModule::new("test", &module)?;
let mut env = Environment::new();
env.extend(Assertions::iter());
assert!(module.with_mutable_env(&mut env)?.run().is_err());
assert_eq!(env["x"], Value::Prim(5.0));
Implementations§
source§impl<T: Clone + Debug> ExecutableModule<T>
impl<T: Clone + Debug> ExecutableModule<T>
source§impl<T> ExecutableModule<T>
impl<T> ExecutableModule<T>
sourcepub fn import_names(&self) -> impl Iterator<Item = &str> + '_
pub fn import_names(&self) -> impl Iterator<Item = &str> + '_
Returns a shared reference to imports of this module.
sourcepub fn with_env<'s>(
&'s self,
env: &'s Environment<T>,
) -> Result<WithEnvironment<'s, T>, Error>
pub fn with_env<'s>( &'s self, env: &'s Environment<T>, ) -> Result<WithEnvironment<'s, T>, Error>
Combines this module with the specified Environment
. The environment must contain
all module imports; otherwise, an error will be raised.
§Errors
Returns an error if the environment does not contain all variables imported by this module.
sourcepub fn with_mutable_env<'s>(
&'s self,
env: &'s mut Environment<T>,
) -> Result<WithEnvironment<'s, T>, Error>
pub fn with_mutable_env<'s>( &'s self, env: &'s mut Environment<T>, ) -> Result<WithEnvironment<'s, T>, Error>
Analogue of Self::with_env()
that modifies the provided Environment
when the module is run.
§Errors
Returns an error if the environment does not contain all variables imported by this module.
Trait Implementations§
source§impl<T: Clone> Clone for ExecutableModule<T>
impl<T: Clone> Clone for ExecutableModule<T>
source§fn clone(&self) -> ExecutableModule<T>
fn clone(&self) -> ExecutableModule<T>
1.0.0 · source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source
. Read moreAuto Trait Implementations§
impl<T> Freeze for ExecutableModule<T>
impl<T> !RefUnwindSafe for ExecutableModule<T>
impl<T> Send for ExecutableModule<T>
impl<T> Sync for ExecutableModule<T>
impl<T> Unpin for ExecutableModule<T>where
T: Unpin,
impl<T> !UnwindSafe for ExecutableModule<T>
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
source§default unsafe fn clone_to_uninit(&self, dst: *mut T)
default unsafe fn clone_to_uninit(&self, dst: *mut T)
clone_to_uninit
)