mech_set/operations/
union.rs1
2use crate::*;
3
4use indexmap::set::IndexSet;
5use mech_core::set::MechSet;
6
7#[derive(Debug)]
10struct SetUnionFxn {
11 lhs: Ref<MechSet>,
12 rhs: Ref<MechSet>,
13 out: Ref<MechSet>,
14}
15impl MechFunctionFactory for SetUnionFxn {
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(SetUnionFxn {lhs, rhs, out }))
23 },
24 _ => Err(MechError2::new(IncorrectNumberOfArguments { expected: 2, found: args.len() }, None).with_compiler_loc()),
25 }
26 }
27}
28impl MechFunctionImpl for SetUnionFxn {
29 fn solve(&self) {
30 unsafe {
31 let out_ptr: &mut MechSet = &mut *(self.out.as_mut_ptr());
33
34 let lhs_ptr: &MechSet = &*(self.lhs.as_ptr());
36 let rhs_ptr: &MechSet = &*(self.rhs.as_ptr());
37
38 out_ptr.set.clear();
40
41 out_ptr.set = lhs_ptr.set.union(&(rhs_ptr.set)).cloned().collect();
43
44 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 SetUnionFxn {
58 fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
59 let name = format!("SetUnionFxn");
60 compile_binop!(name, self.out, self.lhs, self.rhs, ctx, FeatureFlag::Builtin(FeatureKind::Union) );
61 }
62}
63register_descriptor! {
64 FunctionDescriptor {
65 name: "SetUnionFxn",
66 ptr: SetUnionFxn::new,
67 }
68}
69
70fn set_union_fxn(lhs: Value, rhs: Value) -> MResult<Box<dyn MechFunction>> {
71 match (lhs, rhs) {
72 (Value::Set(lhs), Value::Set(rhs)) => {
73 Ok(Box::new(SetUnionFxn { 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 {
77 arg: (x.0.kind(), x.1.kind()),
78 fxn_name: "set/union".to_string(),
79 }, None
80 ).with_compiler_loc()),
81 }
82}
83
84pub struct SetUnion {}
85impl NativeFunctionCompiler for SetUnion {
86 fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
87 if arguments.len() != 2 {
88 return Err(MechError2::new(IncorrectNumberOfArguments { expected: 2, found: arguments.len() }, None).with_compiler_loc());
89 }
90 let lhs = arguments[0].clone();
91 let rhs = arguments[1].clone();
92 match set_union_fxn(lhs.clone(),rhs.clone()) {
93 Ok(fxn) => Ok(fxn),
94 Err(x) => {
95 match (lhs,rhs) {
96 (Value::MutableReference(lhs),Value::MutableReference(rhs)) => { set_union_fxn(lhs.borrow().clone(),rhs.borrow().clone()) },
97 (lhs,Value::MutableReference(rhs)) => { set_union_fxn(lhs.clone(),rhs.borrow().clone()) },
98 (Value::MutableReference(lhs),rhs) => { set_union_fxn(lhs.borrow().clone(),rhs.clone()) },
99 x => Err(MechError2::new(
100 UnhandledFunctionArgumentKind2 { arg: (x.0.kind(), x.1.kind()), fxn_name: "set/union".to_string() },
101 None
102 ).with_compiler_loc()),
103 }
104 }
105 }
106 }
107}
108
109register_descriptor! {
110 FunctionCompilerDescriptor {
111 name: "set/union",
112 ptr: &SetUnion{},
113 }
114}