mech_set/operations/
cartesian_product.rs1
2use crate::*;
3
4use indexmap::set::IndexSet;
5use mech_core::set::MechSet;
6
7#[derive(Debug)]
10struct SetCartesianProductFxn {
11 lhs: Ref<MechSet>,
12 rhs: Ref<MechSet>,
13 out: Ref<MechSet>,
14}
15impl MechFunctionFactory for SetCartesianProductFxn {
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(SetCartesianProductFxn {lhs, rhs, out }))
23 },
24 _ => Err(MechError2::new(IncorrectNumberOfArguments { expected: 2, found: args.len() }, None).with_compiler_loc()),
25 }
26 }
27}
28impl MechFunctionImpl for SetCartesianProductFxn {
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 for elem1 in lhs_ptr.set.clone()
43 {
44 for elem2 in rhs_ptr.set.clone()
45 {
46 out_ptr.set.insert(Value::Tuple(Ref::new(MechTuple{elements: vec![Box::new(elem1.clone()), Box::new(elem2)]})));
47 }
48 }
49
50 out_ptr.num_elements = out_ptr.set.len();
52 out_ptr.kind = if out_ptr.set.len() > 0 {
53 out_ptr.set.iter().next().unwrap().kind()
54 } else {
55 ValueKind::Empty
56 };
57 }
58 }
59 fn out(&self) -> Value { Value::Set(self.out.clone()) }
60 fn to_string(&self) -> String { format!("{:#?}", self) }
61}
62#[cfg(feature = "compiler")]
63impl MechFunctionCompiler for SetCartesianProductFxn {
64 fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
65 let name = format!("SetCartesianProductFxn");
66 compile_binop!(name, self.out, self.lhs, self.rhs, ctx, FeatureFlag::Custom(hash_str("set/cartesian-product")) );
67 }
68}
69register_descriptor! {
70 FunctionDescriptor {
71 name: "SetCartesianProductFxn",
72 ptr: SetCartesianProductFxn::new,
73 }
74}
75
76fn set_cartesian_product_fxn(lhs: Value, rhs: Value) -> MResult<Box<dyn MechFunction>> {
77 match (lhs, rhs) {
78 (Value::Set(lhs), Value::Set(rhs)) => {
79 Ok(Box::new(SetCartesianProductFxn { lhs: lhs.clone(), rhs: rhs.clone(), out: Ref::new(MechSet::new(ValueKind::Tuple(vec![lhs.borrow().kind.clone(), rhs.borrow().kind.clone()]), lhs.borrow().num_elements * rhs.borrow().num_elements)) }))
80 },
81 x => Err(MechError2::new(
82 UnhandledFunctionArgumentKind2 { arg: (x.0.kind(), x.1.kind()), fxn_name: "set/cartesian-product".to_string() },
83 None
84 ).with_compiler_loc()),
85 }
86}
87
88pub struct SetCartesianProduct {}
89impl NativeFunctionCompiler for SetCartesianProduct {
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_cartesian_product_fxn(lhs.clone(),rhs.clone()) {
97 Ok(fxn) => Ok(fxn),
98 Err(x) => {
99 match (lhs,rhs) {
100 (Value::MutableReference(lhs),Value::MutableReference(rhs)) => { set_cartesian_product_fxn(lhs.borrow().clone(),rhs.borrow().clone()) },
101 (lhs,Value::MutableReference(rhs)) => { set_cartesian_product_fxn(lhs.clone(),rhs.borrow().clone()) },
102 (Value::MutableReference(lhs),rhs) => { set_cartesian_product_fxn(lhs.borrow().clone(),rhs.clone()) },
103 x => Err(MechError2::new(
104 UnhandledFunctionArgumentKind2 { arg: (x.0.kind(), x.1.kind()), fxn_name: "set/cartesian-product".to_string() },
105 None
106 ).with_compiler_loc()),
107 }
108 }
109 }
110 }
111}
112
113register_descriptor! {
114 FunctionCompilerDescriptor {
115 name: "set/cartesian-product",
116 ptr: &SetCartesianProduct{},
117 }
118}