mech_set/modify/
insert.rs1
2use crate::*;
3
4use indexmap::set::IndexSet;
5use mech_core::set::MechSet;
6
7#[derive(Debug)]
10struct SetInsertFxn {
11 arg1: Ref<MechSet>,
12 arg2: Ref<Value>,
13 out: Ref<MechSet>,
14}
15impl MechFunctionFactory for SetInsertFxn {
16 fn new(args: FunctionArgs) -> MResult<Box<dyn MechFunction>> {
17 match args {
18 FunctionArgs::Binary(out, arg1, arg2) => {
19 let arg1: Ref<MechSet> = unsafe { arg1.as_unchecked() }.clone();
20 let arg2: Ref<Value> = unsafe { arg2.as_unchecked() }.clone();
21 let out: Ref<MechSet> = unsafe { out.as_unchecked() }.clone();
22 Ok(Box::new(SetInsertFxn {arg1, arg2, out }))
23 },
24 _ => Err(MechError2::new(IncorrectNumberOfArguments { expected: 2, found: args.len() }, None).with_compiler_loc()),
25 }
26 }
27}
28
29fn match_types(type1: ValueKind, type2: ValueKind) -> (bool, bool)
30{
31 match (type1, type2)
32 {
33 (ValueKind::Set(k1, s1), ValueKind::Set(k2, s2)) => {
34 let (types_match, _) = match_types(*k1,*k2);
35 (types_match, s1==s2)
36 },
37 (ValueKind::Set(_, _), _) => (false, false),
38 (_, ValueKind::Set(_, _)) => (false, false),
39 (k1, k2) => (k1==k2, k1==k2),
40 }
41}
42
43impl MechFunctionImpl for SetInsertFxn {
44 fn solve(&self) {
45 unsafe {
46 let mut out_ptr: &mut MechSet = &mut *(self.out.as_mut_ptr());
48
49 let set_ptr: &MechSet = &*(self.arg1.as_ptr());
51 let elem_ptr: &Value = &*(self.arg2.as_ptr());
52
53 out_ptr.set.clear();
55
56 let (types_match, sizes_match) = match_types(set_ptr.kind.clone(), elem_ptr.kind().clone());
57 if(types_match)
59 {
60 out_ptr.set = set_ptr.set.clone();
61 out_ptr.set.insert(elem_ptr.clone());
62 if(!sizes_match)
63 {
64 out_ptr.kind = match out_ptr.kind.clone()
65 {
66 ValueKind::Set(k1, _) => ValueKind::Set(k1, None),
67 _ => ValueKind::Empty
68 }
69 }
70 }
71 out_ptr.num_elements = out_ptr.set.len();
73 if(types_match && sizes_match)
74 {
75 out_ptr.kind = set_ptr.kind.clone();
76 }
77 }
78 }
79 fn out(&self) -> Value { Value::Set(self.out.clone()) }
80 fn to_string(&self) -> String { format!("{:#?}", self) }
81}
82#[cfg(feature = "compiler")]
83impl MechFunctionCompiler for SetInsertFxn {
84 fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
85 let name = format!("SetInsertFxn");
86 compile_binop!(name, self.out, self.arg1, self.arg2, ctx, FeatureFlag::Custom(hash_str("set/insert")) );
87 }
88}
89register_descriptor! {
90 FunctionDescriptor {
91 name: "SetInsertFxn",
92 ptr: SetInsertFxn::new,
93 }
94}
95
96fn set_insert_fxn(arg1: Value, arg2: Value) -> MResult<Box<dyn MechFunction>> {
97 match (arg1, arg2) {
98 (Value::Set(arg1), arg2) => {
99 Ok(Box::new(SetInsertFxn { arg1: arg1.clone(), arg2: Ref::new(arg2.clone()), out: Ref::new(MechSet::new(arg1.borrow().kind.clone(), arg1.borrow().num_elements + 1)) }))
100 },
101 x => Err(MechError2::new(
102 UnhandledFunctionArgumentKind2 { arg: (x.0.kind(), x.1.kind()), fxn_name: "set/insert".to_string() },
103 None
104 ).with_compiler_loc()),
105 }
106}
107
108pub struct SetInsert {}
109impl NativeFunctionCompiler for SetInsert {
110 fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
111 if arguments.len() != 2 {
112 return Err(MechError2::new(IncorrectNumberOfArguments { expected: 2, found: arguments.len() }, None).with_compiler_loc());
113 }
114 let arg1 = arguments[0].clone();
115 let arg2 = arguments[1].clone();
116 match set_insert_fxn(arg1.clone(),arg2.clone()) {
117 Ok(fxn) => Ok(fxn),
118 Err(x) => {
119 match (arg1,arg2) {
120 (Value::MutableReference(arg1),Value::MutableReference(arg2)) => { set_insert_fxn(arg1.borrow().clone(),arg2.borrow().clone()) },
121 (arg1,Value::MutableReference(arg2)) => { set_insert_fxn(arg1.clone(),arg2.borrow().clone()) },
122 (Value::MutableReference(arg1),arg2) => { set_insert_fxn(arg1.borrow().clone(),arg2.clone()) },
123 x => Err(MechError2::new(
124 UnhandledFunctionArgumentKind2 { arg: (x.0.kind(), x.1.kind()), fxn_name: "set/insert".to_string() },
125 None
126 ).with_compiler_loc()),
127 }
128 }
129 }
130 }
131}
132
133register_descriptor! {
134 FunctionCompilerDescriptor {
135 name: "set/insert",
136 ptr: &SetInsert{},
137 }
138}