1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
use crate::{types::PackageCallback, Package};

#[derive(Default)]
pub struct ImplPackage {
  pub methods: &'static [(&'static str, PackageCallback)],
  pub name: &'static [u8],
  pub dyn_methods: Vec<(&'static str, PackageCallback)>,
}

impl ImplPackage {
  pub fn new() -> Self {
    Self {
      name: b"ImplPackage [struct]",
      ..Self::default()
    }
  }

  pub fn set_name(mut self, name: &'static str) -> Self {
    self.name = name.as_bytes();
    self
  }

  pub fn add_method(mut self, name: &'static str, callback: PackageCallback) -> Self {
    self.dyn_methods.push((name, callback));
    self
  }
}

impl Package for ImplPackage {
  fn name(&self) -> &'static [u8] {
    self.name
  }

  fn methods(&self) -> crate::types::MethodRes {
    self.methods
  }

  fn dyn_methods(&self) -> crate::types::DynMethodRes {
    self.dyn_methods.clone()
  }
}

#[macro_export]
macro_rules! generate {
  ($y:ident) => {
    ($y.name(), $y.methods(), $y.dyn_methods())
  };

  ($($x:ident),+) => {
    #[no_mangle]
    pub fn modules() -> Vec<(&'static [u8], interpreter::types::MethodRes, interpreter::types::DynMethodRes)> {
      use interpreter::Package;
      vec![$(generate!($x)),+]
    }
  };
}

#[macro_export]
macro_rules! package {
  ($name:expr, $call:expr) => {
    ImplPackage::new()
      .set_name("ImplPackage [macro]")
      .add_method($name, $call)
  };
}