sim-shape 0.1.3

Shape algebra, comparison, and match-hook helpers.
Documentation
use std::sync::Arc;

use sim_kernel::{ClassId, Expr, Symbol};

use crate::{ClassShape, ExprKind, ExprKindShape, FieldShape, FieldSpec, ObjectExpr, Shape};

use super::cx;

#[test]
fn class_shape_checks_runtime_class() {
    let mut cx = cx();
    let value = cx
        .factory()
        .class_stub(ClassId(77), Symbol::new("Point"))
        .unwrap();
    let shape = ClassShape::new(Symbol::new("Point"));
    assert!(shape.check_value(&mut cx, value).unwrap().accepted);
    assert!(
        !shape
            .check_expr(&mut cx, &Expr::Map(Vec::new()))
            .unwrap()
            .accepted
    );
}

#[test]
fn object_expr_roundtrips() {
    let expr = ObjectExpr {
        class: Symbol::new("Point"),
        fields: vec![(Symbol::new("x"), Expr::Bool(true))],
    }
    .to_expr();
    let parsed = ObjectExpr::parse(&expr).unwrap();
    assert_eq!(parsed.class, Symbol::new("Point"));
    assert_eq!(parsed.field(&Symbol::new("x")), Some(&Expr::Bool(true)));
}

#[test]
fn field_shape_checks_required_fields() {
    let mut cx = cx();
    let shape = FieldShape::new(
        Symbol::new("Point"),
        vec![FieldSpec::required(
            Symbol::new("x"),
            Arc::new(ExprKindShape::new(ExprKind::Number)),
        )],
    );
    let expr = ObjectExpr {
        class: Symbol::new("Point"),
        fields: vec![(Symbol::new("y"), Expr::Bool(true))],
    }
    .to_expr();
    let matched = shape.check_expr(&mut cx, &expr).unwrap();
    assert!(!matched.accepted);
}