EvalCtx

Struct EvalCtx 

Source
pub struct EvalCtx {
    pub fresh: usize,
    pub block: Vec<Exp>,
    pub level: usize,
    pub io: Box<dyn NarjuIo>,
    pub cells: Vec<Val>,
    /* private fields */
}
Expand description

Staging and effect state threaded through evaluation.

One EvalCtx is one evaluator instance: it owns the cell heap and the I/O handle, and carries the staging bookkeeping that base.scm keeps in global mutable variables. The staging fields (fresh, block, fun) are saved and restored around each reify scope; cells, level, and io deliberately are not — cell writes and output are effects, and level has its own save/restore in the run-now path.

Fields§

§fresh: usize

Fresh-name counter: the index the next reflected statement’s residual variable will get (the reference’s fresh).

§block: Vec<Exp>

Statements of the innermost open reify scope, in order. Drained into an ANF Let-chain when the scope closes.

§level: usize

Current run nesting depth: incremented for the compile-then-execute phase of a run-now and restored after. The raw REPL displays it in the prompt.

§io: Box<dyn NarjuIo>

Where read, print, and unstaged log perform their I/O.

§cells: Vec<Val>

First-class cell store: Val::Cell(i) indexes here. Cells are per-instance and in-process by design: each evaluator owns its heap, so instances can be snapshotted or run side by side without sharing mutable state. Deliberately NOT part of ScopeSnapshot: cell writes are effects and survive scope save/restore — catch does not roll them back.

Implementations§

Source§

impl EvalCtx

Source

pub fn new(io: Box<dyn NarjuIo>) -> Self

A fresh evaluator over the given I/O implementation. Use crate::io::headless::HeadlessIo for tests and embedding; Default gives a terminal-backed context and panics without a TTY.

Source

pub fn cell_new(&mut self, v: Val) -> Val

Allocate a fresh cell holding v; returns the Val::Cell handle.

Source

pub fn fun_len(&self) -> usize

Number of memoised closures in stFun — used by :ctx command.

Source

pub fn fresh_var(&mut self) -> usize

Allocate the next residual variable index.

Source

pub fn reflect(&mut self, e: Exp) -> Exp

Emit a statement into the current block and return the residual variable that names its result — the paper’s reflect. This is where ANF comes from: every staged operation becomes one Let binding when the enclosing scope drains its block.

Source

pub fn reflectc(&mut self, e: Exp) -> Val

EvalCtx::reflect, wrapped as a code value.

Source

pub fn reifyv<F>(&mut self, f: F) -> Result<Val, NarjuError>
where F: FnOnce(&mut Self) -> Result<Val, NarjuError>,

Wrap a value-producing thunk in a reify-v scope: save the current staging state, run the thunk with an empty block, then either return the thunk’s val (block empty) or wrap it in a Let-chain (block non-empty, val must be Code).

This is the only public reify-style method retained after the CK rewrite. The Machine’s Cont::ReifyVExit implements the same logic iteratively for in-Machine reifyv scopes; this method exists for the top-level entry evalmsg, which wraps one Machine run in a single reifyv scope.

Trait Implementations§

Source§

impl Default for EvalCtx

Source§

fn default() -> Self

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

Auto Trait Implementations§

§

impl Freeze for EvalCtx

§

impl !RefUnwindSafe for EvalCtx

§

impl !Send for EvalCtx

§

impl !Sync for EvalCtx

§

impl Unpin for EvalCtx

§

impl !UnwindSafe for EvalCtx

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> 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, 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.