mech_set/relations/
not_equals.rs

1use crate::*;
2
3use indexmap::set::IndexSet;
4use mech_core::set::MechSet;
5
6// Not Equals --------------------------------------------------------------------
7//
8// Returns true if lhs and rhs do NOT contain exactly the same elements.
9//
10
11#[derive(Debug)]
12struct SetNotEqualsFxn {
13  lhs: Ref<MechSet>,
14  rhs: Ref<MechSet>,
15  out: Ref<bool>,
16}
17
18impl MechFunctionFactory for SetNotEqualsFxn {
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(SetNotEqualsFxn { 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 SetNotEqualsFxn {
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
39      // Uses the implementation of PartialEq for IndexSet (!= operator)
40      *out_ptr = lhs_ptr.set != rhs_ptr.set;
41    }
42  }
43  fn out(&self) -> Value { Value::Bool(self.out.clone()) }
44  fn to_string(&self) -> String { format!("{:#?}", self) }
45}
46
47#[cfg(feature = "compiler")]
48impl MechFunctionCompiler for SetNotEqualsFxn {
49  fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
50    let name = "SetNotEqualsFxn".to_string();
51    // Custom feature route: set/not_equals
52    compile_binop!(name, self.out, self.lhs, self.rhs, ctx, FeatureFlag::Custom(hash_str("set/not_equals")));
53  }
54}
55
56register_descriptor! {
57  FunctionDescriptor {
58    name: "SetNotEqualsFxn",
59    ptr: SetNotEqualsFxn::new,
60  }
61}
62
63fn set_not_equals_fxn(lhs: Value, rhs: Value) -> MResult<Box<dyn MechFunction>> {
64  match (lhs, rhs) {
65    (Value::Set(lhs), Value::Set(rhs)) => {
66      Ok(Box::new(SetNotEqualsFxn { lhs: lhs.clone(), rhs: rhs.clone(), out: Ref::new(false) }))
67    },
68    x => Err(MechError2::new(
69      UnhandledFunctionArgumentKind2 {
70        arg: (x.0.kind(), x.1.kind()),
71        fxn_name: "set/not-equals".to_string(),
72      }, None
73    ).with_compiler_loc()),
74  }
75}
76
77pub struct SetNotEquals {}
78impl NativeFunctionCompiler for SetNotEquals {
79  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
80    if arguments.len() != 2 {
81      return Err(MechError2::new(IncorrectNumberOfArguments { expected: 2, found: arguments.len() }, None).with_compiler_loc());
82    }
83    let lhs = arguments[0].clone();
84    let rhs = arguments[1].clone();
85    match set_not_equals_fxn(lhs.clone(), rhs.clone()) {
86      Ok(fxn) => Ok(fxn),
87      Err(_) => {
88        match (lhs, rhs) {
89          (Value::MutableReference(lhs), Value::MutableReference(rhs)) => set_not_equals_fxn(lhs.borrow().clone(), rhs.borrow().clone()),
90          (lhs, Value::MutableReference(rhs)) => set_not_equals_fxn(lhs.clone(), rhs.borrow().clone()),
91          (Value::MutableReference(lhs), rhs) => set_not_equals_fxn(lhs.borrow().clone(), rhs.clone()),
92          x => Err(MechError2::new(
93            UnhandledFunctionArgumentKind2 { arg: (x.0.kind(), x.1.kind()), fxn_name: "set/not-equals".to_string() },
94            None
95          ).with_compiler_loc()),
96        }
97      }
98    }
99  }
100}
101
102register_descriptor! {
103  FunctionCompilerDescriptor {
104    name: "set/not_equals",
105    ptr: &SetNotEquals{},
106  }
107}