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
.
The lifetime of a module depends on the lifetime of the code, but this dependency
can be eliminated via [StripCode
] implementation.
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 more