mech_set/setdata/
size.rs

1use crate::*;
2
3use indexmap::set::IndexSet;
4use mech_core::set::MechSet;
5
6// Size --------------------------------------------------------------------------
7//
8// Returns the cardinality |A| as a u64.
9//
10
11#[derive(Debug)]
12struct SetSizeFxn {
13  input: Ref<MechSet>,
14  out: Ref<u64>,
15}
16
17impl MechFunctionFactory for SetSizeFxn {
18  fn new(args: FunctionArgs) -> MResult<Box<dyn MechFunction>> {
19    match args {
20      FunctionArgs::Unary(out, arg1) => {
21        let input: Ref<MechSet> = unsafe { arg1.as_unchecked() }.clone();
22        let out: Ref<u64> = unsafe { out.as_unchecked() }.clone();
23        Ok(Box::new(SetSizeFxn { input, out }))
24      },
25      _ => Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: args.len() }, None).with_compiler_loc()),
26    }
27  }
28}
29
30impl MechFunctionImpl for SetSizeFxn {
31  fn solve(&self) {
32    unsafe {
33      let out_ptr: &mut u64 = &mut *(self.out.as_mut_ptr());
34      let input_ptr: &MechSet = &*(self.input.as_ptr());
35      // Uses the internal IndexSet length
36      *out_ptr = input_ptr.set.len() as u64;
37    }
38  }
39  fn out(&self) -> Value { Value::U64(self.out.clone()) }
40  fn to_string(&self) -> String { format!("{:#?}", self) }
41}
42
43#[cfg(feature = "compiler")]
44impl MechFunctionCompiler for SetSizeFxn {
45  fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
46    let name = "SetSizeFxn".to_string();
47    // Custom feature route: set/size
48    compile_unop!(name, self.out, self.input, ctx, FeatureFlag::Custom(hash_str("set/size")));
49  }
50}
51
52register_descriptor! {
53  FunctionDescriptor {
54    name: "SetSizeFxn",
55    ptr: SetSizeFxn::new,
56  }
57}
58
59fn set_size_fxn(input: Value) -> MResult<Box<dyn MechFunction>> {
60  match input {
61    Value::Set(s) => Ok(Box::new(SetSizeFxn { input: s.clone(), out: Ref::new(0u64) })),
62    x => Err(MechError2::new(UnhandledFunctionArgumentKind1 {
63      arg: x.kind(),
64      fxn_name: "set/size".to_string(),
65    }, None).with_compiler_loc()),
66  }
67}
68
69pub struct SetSize {}
70impl NativeFunctionCompiler for SetSize {
71  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
72    if arguments.len() != 1 {
73      return Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: arguments.len() },None).with_compiler_loc());
74    }
75    let input = arguments[0].clone();
76    match set_size_fxn(input.clone()) {
77      Ok(fxn) => Ok(fxn),
78      Err(_) => {
79        match input {
80          Value::MutableReference(r) => set_size_fxn(r.borrow().clone()),
81          x => Err(MechError2::new(
82            UnhandledFunctionArgumentKind1 { arg: arguments[0].kind(), fxn_name: "set/size".to_string() },
83            None
84          ).with_compiler_loc()),
85        }
86      }
87    }
88  }
89}
90
91register_descriptor! {
92  FunctionCompilerDescriptor {
93    name: "set/size",
94    ptr: &SetSize{},
95  }
96}