mech_set/relations/
proper_subset.rs

1use crate::*;
2
3use indexmap::set::IndexSet;
4use mech_core::set::MechSet;
5
6// Proper Subset ------------------------------------------------------------------
7//
8// Returns true iff lhs ⊂ rhs, i.e. lhs is a subset of rhs and strictly smaller.
9//
10
11#[derive(Debug)]
12struct SetProperSubsetFxn {
13  lhs: Ref<MechSet>,
14  rhs: Ref<MechSet>,
15  out: Ref<bool>,
16}
17
18impl MechFunctionFactory for SetProperSubsetFxn {
19  fn new(args: FunctionArgs) -> MResult<Box<dyn MechFunction>> {
20    match args {
21      FunctionArgs::Binary(out, arg1, arg2) => {
22        let lhs: Ref<MechSet> = unsafe { arg1.as_unchecked() }.clone();
23        let rhs: Ref<MechSet> = unsafe { arg2.as_unchecked() }.clone();
24        let out: Ref<bool> = unsafe { out.as_unchecked() }.clone();
25        Ok(Box::new(SetProperSubsetFxn { lhs, rhs, out }))
26      },
27      _ => Err(MechError2::new(IncorrectNumberOfArguments { expected: 2, found: args.len() }, None).with_compiler_loc()),
28    }
29  }
30}
31
32impl MechFunctionImpl for SetProperSubsetFxn {
33  fn solve(&self) {
34    unsafe {
35      let out_ptr: &mut bool = &mut *(self.out.as_mut_ptr());
36      let lhs_ptr: &MechSet = &*(self.lhs.as_ptr());
37      let rhs_ptr: &MechSet = &*(self.rhs.as_ptr());
38      // Proper subset: lhs ⊂ rhs  <=>  lhs ⊆ rhs and |lhs| < |rhs|
39      *out_ptr = lhs_ptr.set.is_subset(&rhs_ptr.set) && (lhs_ptr.set.len() < rhs_ptr.set.len());
40    }
41  }
42  fn out(&self) -> Value { Value::Bool(self.out.clone()) }
43  fn to_string(&self) -> String { format!("{:#?}", self) }
44}
45
46#[cfg(feature = "compiler")]
47impl MechFunctionCompiler for SetProperSubsetFxn {
48  fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
49    let name = "SetProperSubsetFxn".to_string();
50    // Builtin operator ⊊
51    compile_binop!(name, self.out, self.lhs, self.rhs, ctx, FeatureFlag::Builtin(FeatureKind::ProperSubset));
52  }
53}
54
55register_descriptor! {
56  FunctionDescriptor {
57    name: "SetProperSubsetFxn",
58    ptr: SetProperSubsetFxn::new,
59  }
60}
61
62fn set_proper_subset_fxn(lhs: Value, rhs: Value) -> MResult<Box<dyn MechFunction>> {
63  match (lhs, rhs) {
64    (Value::Set(lhs), Value::Set(rhs)) => {
65      Ok(Box::new(SetProperSubsetFxn { lhs: lhs.clone(), rhs: rhs.clone(), out: Ref::new(false) }))
66    },
67    x => Err(MechError2::new(
68      UnhandledFunctionArgumentKind2 {
69        arg: (x.0.kind(), x.1.kind()),
70        fxn_name: "set/proper-subset".to_string(),
71      }, None
72    ).with_compiler_loc()),
73  }
74}
75
76pub struct SetProperSubset {}
77impl NativeFunctionCompiler for SetProperSubset {
78  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
79    if arguments.len() != 2 {
80      return Err(MechError2::new(IncorrectNumberOfArguments { expected: 2, found: arguments.len() }, None).with_compiler_loc());
81    }
82    let lhs = arguments[0].clone();
83    let rhs = arguments[1].clone();
84    match set_proper_subset_fxn(lhs.clone(), rhs.clone()) {
85      Ok(fxn) => Ok(fxn),
86      Err(_) => {
87        match (lhs, rhs) {
88          (Value::MutableReference(lhs), Value::MutableReference(rhs)) => set_proper_subset_fxn(lhs.borrow().clone(), rhs.borrow().clone()),
89          (lhs, Value::MutableReference(rhs)) => set_proper_subset_fxn(lhs.clone(), rhs.borrow().clone()),
90          (Value::MutableReference(lhs), rhs) => set_proper_subset_fxn(lhs.borrow().clone(), rhs.clone()),
91          x => Err(MechError2::new(
92            UnhandledFunctionArgumentKind2 { arg: (x.0.kind(), x.1.kind()), fxn_name: "set/proper-subset".to_string() },
93            None
94          ).with_compiler_loc()),
95        }
96      }
97    }
98  }
99}
100
101register_descriptor! {
102  FunctionCompilerDescriptor {
103    name: "set/proper_subset",
104    ptr: &SetProperSubset{},
105  }
106}