1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
//! The callable contract: objects that can be invoked with checked arguments.
//!
//! This is protocol the libraries implement; the kernel defines [`Callable`]
//! and the invocation surface, not concrete callable behavior.
use crate::{
env::Cx,
error::Result,
object::{Args, Object, RawArgs, ShapeRef},
value::Value,
};
/// Runtime protocol for values that can be called.
///
/// Functions, constructors, macros that accept raw expressions, and host or
/// guest function stubs all share this protocol. A callable is always a
/// runtime object, so it also has a class, display form, reflection table, and
/// optional protocol views through `Object`.
pub trait Callable: Object {
/// Invoke the callable with already-evaluated, checked [`Args`].
fn call(&self, cx: &mut Cx, args: Args) -> Result<Value>;
/// Optional shape describing the accepted argument list, for browsing.
fn browse_args_shape(&self, _cx: &mut Cx) -> Result<Option<ShapeRef>> {
Ok(None)
}
/// Optional shape describing the call result, for browsing.
fn browse_result_shape(&self, _cx: &mut Cx) -> Result<Option<ShapeRef>> {
Ok(None)
}
/// Invoke the callable on raw, unevaluated argument expressions.
///
/// The default evaluates each expression in `cx` and forwards to
/// [`Callable::call`]; macro-like callables override to inspect raw forms.
fn call_exprs(&self, cx: &mut Cx, args: RawArgs) -> Result<Value> {
let values = args
.into_exprs()
.into_iter()
.map(|expr| cx.eval_expr(expr))
.collect::<Result<Vec<_>>>()?;
self.call(cx, Args::new(values))
}
}