mech_set/operations/
intersection.rs

1
2use crate::*;
3
4use indexmap::set::IndexSet;
5use mech_core::set::MechSet;
6
7// Intersection ------------------------------------------------------------------------
8
9#[derive(Debug)]
10struct SetIntersectionFxn {
11  lhs: Ref<MechSet>,
12  rhs: Ref<MechSet>,
13  out: Ref<MechSet>,
14}
15impl MechFunctionFactory for SetIntersectionFxn {
16  fn new(args: FunctionArgs) -> MResult<Box<dyn MechFunction>> {
17    match args {
18      FunctionArgs::Binary(out, arg1, arg2) => {
19        let lhs: Ref<MechSet> = unsafe { arg1.as_unchecked() }.clone();
20        let rhs: Ref<MechSet> = unsafe { arg2.as_unchecked() }.clone();
21        let out: Ref<MechSet> = unsafe { out.as_unchecked() }.clone();
22        Ok(Box::new(SetIntersectionFxn {lhs, rhs, out }))
23      },
24      _ => Err(MechError2::new(IncorrectNumberOfArguments { expected: 2, found: args.len() }, None).with_compiler_loc()),
25    }
26  }    
27}
28impl MechFunctionImpl for SetIntersectionFxn {
29  fn solve(&self) {
30    unsafe {
31      // Get mutable reference to the output set
32      let out_ptr: &mut MechSet = &mut *(self.out.as_mut_ptr());
33
34      // Get references to lhs and rhs sets
35      let lhs_ptr: &MechSet = &*(self.lhs.as_ptr());
36      let rhs_ptr: &MechSet = &*(self.rhs.as_ptr());
37
38      // Clear the output set first (optional, depending on semantics)
39      out_ptr.set.clear();
40
41      // Intersection lhs and rhs sets into output
42      out_ptr.set = lhs_ptr.set.intersection(&(rhs_ptr.set)).cloned().collect();
43
44      // Update metadata
45      out_ptr.num_elements = out_ptr.set.len();
46      out_ptr.kind = if out_ptr.set.len() > 0 {
47        out_ptr.set.iter().next().unwrap().kind()
48      } else {
49        ValueKind::Empty
50      };
51    }
52  }
53  fn out(&self) -> Value { Value::Set(self.out.clone()) }
54  fn to_string(&self) -> String { format!("{:#?}", self) }
55}
56#[cfg(feature = "compiler")]
57impl MechFunctionCompiler for SetIntersectionFxn {
58  fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
59    let name = format!("SetIntersectionFxn");
60    compile_binop!(name, self.out, self.lhs, self.rhs, ctx, FeatureFlag::Builtin(FeatureKind::Intersection) );
61  }
62}
63register_descriptor! {
64  FunctionDescriptor {
65    name: "SetIntersectionFxn",
66    ptr: SetIntersectionFxn::new,
67  }
68}
69
70fn set_intersection_fxn(lhs: Value, rhs: Value) -> MResult<Box<dyn MechFunction>> {
71  match (lhs, rhs) {
72    (Value::Set(lhs), Value::Set(rhs)) => {
73      Ok(Box::new(SetIntersectionFxn { lhs: lhs.clone(), rhs: rhs.clone(), out: Ref::new(MechSet::new(lhs.borrow().kind.clone(), lhs.borrow().num_elements + rhs.borrow().num_elements)) }))
74    },
75    x => Err(MechError2::new(
76      UnhandledFunctionArgumentKind2 { arg: (x.0.kind(), x.1.kind()), fxn_name: "set/intersection".to_string() },
77      None
78    ).with_compiler_loc()),
79  }
80}
81
82pub struct SetIntersection {}
83impl NativeFunctionCompiler for SetIntersection {
84  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
85    if arguments.len() != 2 {
86      return Err(MechError2::new(IncorrectNumberOfArguments { expected: 2, found: arguments.len() }, None).with_compiler_loc());
87    }
88    let lhs = arguments[0].clone();
89    let rhs = arguments[1].clone();
90    match set_intersection_fxn(lhs.clone(),rhs.clone()) {
91      Ok(fxn) => Ok(fxn),
92      Err(x) => {
93        match (lhs,rhs) {
94          (Value::MutableReference(lhs),Value::MutableReference(rhs)) => { set_intersection_fxn(lhs.borrow().clone(),rhs.borrow().clone()) },
95          (lhs,Value::MutableReference(rhs)) => { set_intersection_fxn(lhs.clone(),rhs.borrow().clone()) },
96          (Value::MutableReference(lhs),rhs) => { set_intersection_fxn(lhs.borrow().clone(),rhs.clone()) },
97          x => Err(MechError2::new(
98            UnhandledFunctionArgumentKind2 { arg: (x.0.kind(), x.1.kind()), fxn_name: "set/intersection".to_string() },
99            None
100          ).with_compiler_loc()),
101        }
102      }
103    }
104  }
105}
106
107register_descriptor! {
108  FunctionCompilerDescriptor {
109    name: "set/intersection",
110    ptr: &SetIntersection{},
111  }
112}