pub trait Callable {
// Required methods
fn allocate_vector(&mut self, elements: Vec<Value>) -> Value;
fn call_value(
&mut self,
callee: &Value,
args: &mut Vec<Value>,
span: Span,
) -> Result<Value, RuntimeError>;
fn arity(&self, callee: &Value) -> Option<usize>;
fn snapshot(
&mut self,
value: &Value,
span: Span,
) -> Result<Value, RuntimeError>;
}Expand description
How the builtins call back into the evaluator.
Higher-order builtins such as Result.mapError invoke a Cove callback, so
they need the interpreter that owns the call stack.
Required Methods§
Sourcefn allocate_vector(&mut self, elements: Vec<Value>) -> Value
fn allocate_vector(&mut self, elements: Vec<Value>) -> Value
Allocates growable vector storage in the running task’s heap.
Every Vector a program can reach is created through this, so the
collector’s table of objects is the complete set of values that can
form a cycle. A builtin that makes one asks its caller rather than
calling VectorStorage::new directly.
Sourcefn call_value(
&mut self,
callee: &Value,
args: &mut Vec<Value>,
span: Span,
) -> Result<Value, RuntimeError>
fn call_value( &mut self, callee: &Value, args: &mut Vec<Value>, span: Span, ) -> Result<Value, RuntimeError>
Calls a closure value with already evaluated arguments.
The arguments are taken out of args, which is left empty. The
vector belongs to the caller and comes back to it, capacity and all,
which is what lets a per-element callback be invoked without
allocating a vector per element: walk_with hands the same one
down for the whole walk. Issue #193 is the cost that made that worth
arranging — map, filter, fold and sorted built and dropped a
Vec<Value> for every element they visited, which is the same shape
the predecessor’s own argument vectors had before #184 and on the
one path that scheme could not reach.
A caller that fails partway is still handed back a vector it may
reuse: an implementation drains what it was given before it runs
anything, so args is empty whether the call answered or raised.
Sourcefn arity(&self, callee: &Value) -> Option<usize>
fn arity(&self, callee: &Value) -> Option<usize>
The number of parameters callee declares, when it is a closure.
Sourcefn snapshot(&mut self, value: &Value, span: Span) -> Result<Value, RuntimeError>
fn snapshot(&mut self, value: &Value, span: Span) -> Result<Value, RuntimeError>
The independent copy Snapshot makes of one value.
A hook on this trait, whose one implementor is Interpreter, because
a struct and an enum answer their own impl Snapshot for Type
through a declaration that only the interpreter reaches this way. The
linear-memory backend puts the same recursion in the lowering
instead, exactly because a builtin never calls back into Cove —
docs/LINEAR_VM.md says why. snapshot recurses through here so
that a Vector of structs reaches the interpreter’s own answer for
each one.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".