Env

Struct Env 

Source
pub struct Env { /* private fields */ }
Expand description

A lexical environment: a persistent chain of frames, so a closure can capture cheaply.

Implementations§

Source§

impl Env

Source

pub fn new() -> Env

Source

pub fn extend(&self, bindings: Vec<(VarId, Value)>) -> Env

Source

pub fn call_frame( parent: &Arc<Env>, params: &[VarId], args: impl Iterator<Item = Value>, locals: u32, ) -> Env

The frame a call runs in: the parameters, then locals reserved slots for the bindings the body is going to make.

One allocation. Map<Range, _> has a length the compiler can trust, so collecting it into an Arc<[_]> sizes the allocation once — which is why the parameters and the reserved tail are produced by one iterator rather than a vector that is then converted.

Source

pub fn put(&mut self, bindings: &mut Vec<(VarId, Value)>) -> bool

Bind bindings into this frame’s reserved tail, if there is room for all of them and nobody else is holding the frame.

Answers whether it did. false means the caller must fall back to Env::extend and chain a scope — which happens when a closure has captured this environment (its clone holds the frame, so Arc::get_mut refuses), when the reservation was too small, or when the program was built by something that never ran the reservation pass at all.

The safety argument is the refusal: a closure that captured this environment can see the slots this would write, and Arc::get_mut is what proves that has not happened. Every binding gets a slot of its own, so nothing a closure captured is ever overwritten.

Source

pub fn put_one(&mut self, var: VarId, value: Value) -> Result<(), Value>

Env::put for a single binding, which is what a let is — and a let is much the most common of the two, so it does not build a vector to hand over. Answers the value back when there is no room for it.

Source

pub fn extend_shared(parent: &Arc<Env>, frame: Arc<[(VarId, Value)]>) -> Env

Extend a parent that is already behind an Arc — which a closure’s captured environment is, so that a call clones a pointer instead of boxing a copy of the environment.

This is the per-call path. extend above is the per-let path, where the parent is owned by the evaluator’s loop and has to be boxed; there are far fewer of those.

Source

pub fn empty_shared() -> Arc<Env>

An environment with nothing in it, behind an Arc, shared by every top-level definition.

Source

pub fn get(&self, v: VarId) -> Option<&Value>

Source

pub fn read(&mut self, v: VarId, may_move: bool) -> Option<Value>

Read v, and move it out of the frame when three things hold: the caller says no later evaluation reads it, this environment is the only holder of the frame it lives in, and the value is one whose copy costs something.

The third condition is not an optimisation of an optimisation — it is what keeps the other two from costing more than they save. Moving is strictly more work than cloning at the point of the read: a clone of an Int is a copy of eight bytes and a clone of a container is one atomic increment, where a move has to find the slot, prove the frame is unshared and empty it. It pays only when somebody downstream can then use the sole ownership — which today is list_append pushing in place and with rebuilding a record’s fields — and measuring it without this condition showed every benchmark in the tree 6–13% slower, because the reads that dominate a real program are of Ints and nothing was gained by moving one (69 §69.7).

The caller must have established that no later evaluation reads vcrate::liveness is what establishes it, and last_use is the flag. What this adds is the second half of the safety argument: a frame is emptied only when nothing else holds it, so an environment captured by a closure or shared with an inner scope is read from rather than emptied, and a caller that is wrong about liveness gets an unbound-variable error rather than somebody else’s missing binding.

Trait Implementations§

Source§

impl Clone for Env

Source§

fn clone(&self) -> Env

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Env

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Env

Source§

fn default() -> Env

Returns the “default value” for a type. Read more
Source§

impl PartialEq for Env

Source§

fn eq(&self, other: &Env) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Eq for Env

Source§

impl StructuralPartialEq for Env

Auto Trait Implementations§

§

impl Freeze for Env

§

impl RefUnwindSafe for Env

§

impl Send for Env

§

impl Sync for Env

§

impl Unpin for Env

§

impl UnwindSafe for Env

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.