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