pub struct VmData<const N: usize = { u8::MAX as usize }> {
pub vars: Arc<VarMap>,
/* private fields */
}Expand description
A flattened math expression, ready for evaluation or further compilation.
Under the hood, VmData stores two different representations:
- A tape in single static assignment form
(
SsaTape), which is suitable for use during tape simplification - A tape in register-allocated form (
RegTape), which can be efficiently evaluated or lowered into machine assembly
§Example
Consider the expression x + y. The SSA tape will look something like
this:
$0 = INPUT 0 // X
$1 = INPUT 1 // Y
$2 = ADD $0 $1 // (X + Y)This will be lowered into a tape using real (or VM) registers:
r0 = INPUT 0 // X
r1 = INPUT 1 // Y
r0 = ADD r0 r1 // (X + Y)Note that in this form, registers are reused (e.g. r0 stores both X and
X + Y).
We can peek at the internals and see this register-allocated tape:
use fidget_core::{
compiler::RegOp,
context::{Context, Tree},
vm::VmData,
var::Var,
};
let tree = Tree::x() + Tree::y();
let mut ctx = Context::new();
let sum = ctx.import(&tree);
let data = VmData::<255>::new(&ctx, &[sum])?;
assert_eq!(data.len(), 4); // X, Y, (X + Y), and output
let mut iter = data.iter_asm();
let vars = &data.vars; // map from var to index
assert_eq!(iter.next().unwrap(), RegOp::Input(0, vars[&Var::X] as u32));
assert_eq!(iter.next().unwrap(), RegOp::Input(1, vars[&Var::Y] as u32));
assert_eq!(iter.next().unwrap(), RegOp::AddRegReg(0, 0, 1));Despite this peek at its internals, users are unlikely to touch VmData
directly; a VmShape wraps the VmData and
implements our common traits.
Fields§
§vars: Arc<VarMap>Mapping from variables to indices during evaluation
This member is stored in a shared pointer because it’s passed down to
children (constructed with VmData::simplify).
Implementations§
Source§impl<const N: usize> VmData<N>
impl<const N: usize> VmData<N>
Sourcepub fn new(context: &Context, nodes: &[Node]) -> Result<Self, Error>
pub fn new(context: &Context, nodes: &[Node]) -> Result<Self, Error>
Builds a new tape for the given node
Sourcepub fn choice_count(&self) -> usize
pub fn choice_count(&self) -> usize
Returns the number of choice (min/max) nodes in the tape.
This is required because some evaluators pre-allocate spaces for the choice array.
Sourcepub fn output_count(&self) -> usize
pub fn output_count(&self) -> usize
Returns the number of output nodes in the tape.
This is required because some evaluators pre-allocate spaces for the output array.
Sourcepub fn slot_count(&self) -> usize
pub fn slot_count(&self) -> usize
Returns the number of slots used by the inner VM tape
Sourcepub fn simplify<const M: usize>(
&self,
choices: &[Choice],
workspace: &mut VmWorkspace<M>,
tape: VmData<M>,
) -> Result<VmData<M>, Error>
pub fn simplify<const M: usize>( &self, choices: &[Choice], workspace: &mut VmWorkspace<M>, tape: VmData<M>, ) -> Result<VmData<M>, Error>
Simplifies both inner tapes, using the provided choice array
To minimize allocations, this function takes a VmWorkspace and
spare VmData; it will reuse those allocations.
Sourcepub fn iter_asm(&self) -> impl Iterator<Item = RegOp> + '_
pub fn iter_asm(&self) -> impl Iterator<Item = RegOp> + '_
Produces an iterator that visits RegOp values in evaluation order
Sourcepub fn pretty_print(&self)
pub fn pretty_print(&self)
Pretty-prints the inner SSA tape
Trait Implementations§
Source§impl<'de, const N: usize> Deserialize<'de> for VmData<N>
impl<'de, const N: usize> Deserialize<'de> for VmData<N>
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Auto Trait Implementations§
impl<const N: usize> Freeze for VmData<N>
impl<const N: usize> RefUnwindSafe for VmData<N>
impl<const N: usize> Send for VmData<N>
impl<const N: usize> Sync for VmData<N>
impl<const N: usize> Unpin for VmData<N>
impl<const N: usize> UnsafeUnpin for VmData<N>
impl<const N: usize> UnwindSafe for VmData<N>
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> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self is actually part of its subset T (and can be converted to it).Source§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset but without any property checks. Always succeeds.Source§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self to the equivalent element of its superset.