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: usizeFresh-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: usizeCurrent 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
impl EvalCtx
Sourcepub fn new(io: Box<dyn NarjuIo>) -> Self
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.
Sourcepub fn cell_new(&mut self, v: Val) -> Val
pub fn cell_new(&mut self, v: Val) -> Val
Allocate a fresh cell holding v; returns the Val::Cell handle.
Sourcepub fn reflect(&mut self, e: Exp) -> Exp
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.
Sourcepub fn reflectc(&mut self, e: Exp) -> Val
pub fn reflectc(&mut self, e: Exp) -> Val
EvalCtx::reflect, wrapped as a code value.
Sourcepub fn reifyv<F>(&mut self, f: F) -> Result<Val, NarjuError>
pub fn reifyv<F>(&mut self, f: F) -> 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.