Skip to main content

Shape

Trait Shape 

Source
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§

Source

fn check_value(&self, cx: &mut Cx, value: Value) -> Result<ShapeMatch>

Check a Value against this shape, yielding a ShapeMatch.

Source

fn check_expr(&self, cx: &mut Cx, expr: &Expr) -> Result<ShapeMatch>

Check an Expr against this shape, yielding a ShapeMatch.

Source

fn describe(&self, cx: &mut Cx) -> Result<ShapeDoc>

Produce the human-facing ShapeDoc for this shape.

Provided Methods§

Source

fn id(&self) -> Option<ShapeId>

Stable ShapeId when this shape has runtime identity, else None.

Source

fn symbol(&self) -> Option<Symbol>

Symbol naming this shape when it has one, else None.

Source

fn parents(&self, _cx: &mut Cx) -> Result<Vec<ShapeRef>>

Parent shapes for the subshape walk; empty by default.

Source

fn is_effectful(&self) -> bool

Whether matching this shape may run effects; false by default.

Source

fn is_total(&self) -> bool

Whether this shape accepts every input in its domain; false by default.

Source

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

Implementors§