Skip to main content

sim_shape/primitives/combinators/
effectful.rs

1//! Effectful wrapper combinator.
2
3use std::sync::Arc;
4
5use sim_kernel::{Cx, Expr, Result, ShapeId, Value, shape_is_subshape_of};
6
7use crate::base::{Shape, ShapeDoc, ShapeMatch};
8
9/// A shape that marks its inner shape's matching as effectful.
10///
11/// Delegates checks to the inner shape but reports `is_effectful() == true` and
12/// carries no shape id, signalling that parse-time validation through this
13/// shape needs a trusted parser position.
14pub struct EffectfulShape {
15    inner: Arc<dyn Shape>,
16}
17
18impl EffectfulShape {
19    /// Wrap an inner shape, marking its matching as effectful.
20    pub fn new(inner: Arc<dyn Shape>) -> Self {
21        Self { inner }
22    }
23
24    /// The wrapped inner shape.
25    pub fn inner(&self) -> &Arc<dyn Shape> {
26        &self.inner
27    }
28}
29
30impl Shape for EffectfulShape {
31    fn id(&self) -> Option<ShapeId> {
32        None
33    }
34
35    fn is_effectful(&self) -> bool {
36        true
37    }
38
39    fn is_total(&self) -> bool {
40        self.inner.is_total()
41    }
42
43    fn is_subshape_of(&self, cx: &mut Cx, parent: &dyn Shape) -> Result<Option<bool>> {
44        let Some(parent) = parent.as_any().downcast_ref::<Self>() else {
45            return Ok(Some(false));
46        };
47        shape_is_subshape_of(cx, self.inner.as_ref(), parent.inner.as_ref()).map(Some)
48    }
49
50    fn check_value(&self, cx: &mut Cx, value: Value) -> Result<ShapeMatch> {
51        self.inner.check_value(cx, value)
52    }
53
54    fn check_expr(&self, cx: &mut Cx, expr: &Expr) -> Result<ShapeMatch> {
55        self.inner.check_expr(cx, expr)
56    }
57
58    fn describe(&self, cx: &mut Cx) -> Result<ShapeDoc> {
59        let inner = self.inner.describe(cx)?;
60        Ok(
61            ShapeDoc::new(format!("effectful {}", inner.name)).with_detail(
62                "effectful parse-time validation requires a trusted parser position".to_owned(),
63            ),
64        )
65    }
66}