mech_set/membership/
not_element_of.rs

1use crate::*;
2
3use indexmap::set::IndexSet;
4use mech_core::set::MechSet;
5
6// Not Element Of ----------------------------------------------------------------
7//
8// Returns true iff elem ∉ set. Mirrors element_of with negated result.
9//
10
11#[derive(Debug)]
12struct SetNotElementOfFxn {
13  elem: Ref<Value>,
14  set: Ref<MechSet>,
15  out: Ref<bool>,
16}
17
18impl MechFunctionFactory for SetNotElementOfFxn {
19  fn new(args: FunctionArgs) -> MResult<Box<dyn MechFunction>> {
20    match args {
21      FunctionArgs::Binary(out, arg1, arg2) => {
22        let elem: Ref<Value> = unsafe { arg1.as_unchecked() }.clone();
23        let set: Ref<MechSet> = unsafe { arg2.as_unchecked() }.clone();
24        let out: Ref<bool> = unsafe { out.as_unchecked() }.clone();
25        Ok(Box::new(SetNotElementOfFxn { elem, set, out }))
26      },
27      _ => Err(MechError2::new(IncorrectNumberOfArguments { expected: 2, found: args.len() }, None).with_compiler_loc()),
28    }
29  }
30}
31
32impl MechFunctionImpl for SetNotElementOfFxn {
33  fn solve(&self) {
34    unsafe {
35      let out_ptr: &mut bool = &mut *(self.out.as_mut_ptr());
36      let elem_ptr: &Value = &*(self.elem.as_ptr());
37      let set_ptr: &MechSet = &*(self.set.as_ptr());
38
39      // Only true if kinds are incompatible or the set does not contain elem.
40      if set_ptr.kind == elem_ptr.kind() {
41        *out_ptr = !set_ptr.set.contains(elem_ptr);
42      } else {
43        *out_ptr = true;
44      }
45    }
46  }
47  fn out(&self) -> Value { Value::Bool(self.out.clone()) }
48  fn to_string(&self) -> String { format!("{:#?}", self) }
49}
50
51#[cfg(feature = "compiler")]
52impl MechFunctionCompiler for SetNotElementOfFxn {
53  fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
54    let name = "SetNotElementOfFxn".to_string();
55    // Builtin operator ∉
56    compile_binop!(name, self.out, self.elem, self.set, ctx, FeatureFlag::Builtin(FeatureKind::NotElementOf));
57  }
58}
59
60register_descriptor! {
61  FunctionDescriptor {
62    name: "SetNotElementOfFxn",
63    ptr: SetNotElementOfFxn::new,
64  }
65}
66
67fn set_not_element_of_fxn(elem: Value, set: Value) -> MResult<Box<dyn MechFunction>> {
68  match (elem, set) {
69    (elem, Value::Set(set)) => {
70      Ok(Box::new(SetNotElementOfFxn { elem: Ref::new(elem.clone()), set: set.clone(), out: Ref::new(false) }))
71    },
72    x => Err(MechError2::new(
73      UnhandledFunctionArgumentKind2 {
74        arg: (x.0.kind(), x.1.kind()),
75        fxn_name: "set/not-element-of".to_string(),
76      }, None
77    ).with_compiler_loc()),
78  }
79}
80
81pub struct SetNotElementOf {}
82impl NativeFunctionCompiler for SetNotElementOf {
83  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
84    if arguments.len() != 2 {
85      return Err(MechError2::new(IncorrectNumberOfArguments { expected: 2, found: arguments.len() }, None).with_compiler_loc());
86    }
87    let elem = arguments[0].clone();
88    let set = arguments[1].clone();
89    match set_not_element_of_fxn(elem.clone(), set.clone()) {
90      Ok(fxn) => Ok(fxn),
91      Err(_) => {
92        match (elem, set) {
93          (Value::MutableReference(elem), Value::MutableReference(set)) => set_not_element_of_fxn(elem.borrow().clone(), set.borrow().clone()),
94          (elem, Value::MutableReference(set)) => set_not_element_of_fxn(elem.clone(), set.borrow().clone()),
95          (Value::MutableReference(elem), set) => set_not_element_of_fxn(elem.borrow().clone(), set.clone()),
96          x => Err(MechError2::new(
97            UnhandledFunctionArgumentKind2 { arg: (x.0.kind(), x.1.kind()), fxn_name: "set/not-element-of".to_string() },
98            None
99          ).with_compiler_loc()),
100        }
101      }
102    }
103  }
104}
105
106register_descriptor! {
107  FunctionCompilerDescriptor {
108    name: "set/not-element-of",
109    ptr: &SetNotElementOf{},
110  }
111}