pub trait Shape: Callable {
// Required methods
fn check_value(&self, cx: &mut Cx, value: Value) -> Result<ShapeMatch>;
fn check_expr(&self, cx: &mut Cx, expr: &Expr) -> Result<ShapeMatch>;
fn describe(&self, cx: &mut Cx) -> Result<ShapeDoc>;
// Provided methods
fn id(&self) -> Option<ShapeId> { ... }
fn symbol(&self) -> Option<Symbol> { ... }
fn parents(&self, _cx: &mut Cx) -> Result<Vec<ShapeRef>> { ... }
fn is_effectful(&self) -> bool { ... }
fn is_total(&self) -> bool { ... }
fn is_subshape_of(
&self,
_cx: &mut Cx,
_parent: &dyn Shape,
) -> Result<Option<bool>> { ... }
}Expand description
The one shared engine for matching and binding across the runtime.
Shape is among the kernel’s most important contracts: a single protocol
reused for parsing, checking, binding, dispatch, macro syntax, codec
grammar, lambda locals, and overload selection. It is a first-class kernel
protocol – object-accessible through as_shape,
callable as a matcher (every Shape is a Callable), and subclassable
through open metadata rather than a closed enum.
The kernel defines only this protocol and the match/binding contracts
(ShapeMatch, ShapeBindings, MatchScore, ShapeDoc). Concrete
grammars and matchers are supplied by libraries; SIM is a Rust runtime, not
a Lisp runtime, so no particular surface syntax is baked in here.
A type checks a value with check_value and an
expression with check_expr; both yield a
ShapeMatch. describe provides the human-facing
ShapeDoc. The remaining methods carry optional identity and subshape
metadata and default to neutral answers.
§Examples
use std::sync::Arc;
use sim_kernel::{Cx, DefaultFactory, NoopEvalPolicy, Value};
use sim_kernel::shape::{MatchScore, Shape, ShapeDoc, ShapeMatch};
struct AnyShape;
impl Shape for AnyShape {
fn check_value(&self, _cx: &mut Cx, _v: Value) -> sim_kernel::Result<ShapeMatch> {
Ok(ShapeMatch::accept(MatchScore::exact(1)))
}
fn check_expr(&self, _cx: &mut Cx, _e: &sim_kernel::Expr) -> sim_kernel::Result<ShapeMatch> {
Ok(ShapeMatch::accept(MatchScore::exact(1)))
}
fn describe(&self, _cx: &mut Cx) -> sim_kernel::Result<ShapeDoc> {
Ok(ShapeDoc::new("any"))
}
}
let mut cx = Cx::new(Arc::new(NoopEvalPolicy), Arc::new(DefaultFactory));
let value = cx.factory().string("ok".to_owned()).unwrap();
let matched = AnyShape.check_value(&mut cx, value).unwrap();
assert!(matched.accepted);Required Methods§
Sourcefn check_value(&self, cx: &mut Cx, value: Value) -> Result<ShapeMatch>
fn check_value(&self, cx: &mut Cx, value: Value) -> Result<ShapeMatch>
Check a Value against this shape, yielding a ShapeMatch.
Sourcefn check_expr(&self, cx: &mut Cx, expr: &Expr) -> Result<ShapeMatch>
fn check_expr(&self, cx: &mut Cx, expr: &Expr) -> Result<ShapeMatch>
Check an Expr against this shape, yielding a ShapeMatch.
Provided Methods§
Sourcefn id(&self) -> Option<ShapeId>
fn id(&self) -> Option<ShapeId>
Stable ShapeId when this shape has runtime identity, else None.
Sourcefn parents(&self, _cx: &mut Cx) -> Result<Vec<ShapeRef>>
fn parents(&self, _cx: &mut Cx) -> Result<Vec<ShapeRef>>
Parent shapes for the subshape walk; empty by default.
Sourcefn is_effectful(&self) -> bool
fn is_effectful(&self) -> bool
Whether matching this shape may run effects; false by default.
Sourcefn is_total(&self) -> bool
fn is_total(&self) -> bool
Whether this shape accepts every input in its domain; false by default.
Sourcefn is_subshape_of(
&self,
_cx: &mut Cx,
_parent: &dyn Shape,
) -> Result<Option<bool>>
fn is_subshape_of( &self, _cx: &mut Cx, _parent: &dyn Shape, ) -> Result<Option<bool>>
Return a concrete implication answer when this shape owns the semantics.
None keeps the kernel on the generic id, symbol, Any, and parent walk
path instead of requiring a closed enum of every concrete shape kind.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".