mech_set/modify/
remove.rs

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