1mod builtin;
4mod io;
5mod string;
6mod table;
7
8pub use builtin::load_builtin;
9pub use io::io_lib;
10pub use string::string_lib;
11pub use table::table_lib;
12
13#[macro_export]
14macro_rules! check_args {
15 (@AS_EXPR $e:expr) => {$e};
16
17 (@ARGS_CHECK ($(,)?) -> ($($args:tt)*) ()) => {{
18 $crate::check_args!(@AS_EXPR ($($args)*, Some($($args)*)))
19 }};
20 (@ARGS_CHECK (, *) -> ($($args:tt)*) ()) => {{
21 ($crate::check_args!(@AS_EXPR ($($args)*)), None)
22 }};
23 (@ARGS_CHECK (, $arg:tt $($ty:tt)*) -> ($($args:tt)*) ()) => {{
24 $crate::check_args!(@ARGS_CHECK ($($ty)*) -> ($($args)* + 1) ())
25 }};
26 (@ARGS_CHECK (| $($ty:tt)*) -> ($($args:tt)*) ()) => {{
27 $crate::check_args!(
28 @ARGS_CHECK (, $($ty)*) ->
29 ($crate::check_args!(@AS_EXPR ($($args)*))) ($($args)*)
30 )
31 }};
32 (@ARGS_CHECK ($(,)?) -> ($args:expr) ($($opt_args:tt)+)) => {{
33 ($args, $crate::check_args!(@AS_EXPR Some($($opt_args)*)))
34 }};
35 (@ARGS_CHECK (, *) -> ($args:expr) ($($opt_args:tt)+)) => {{
36 ($args, None)
37 }};
38 (@ARGS_CHECK (, $arg:tt $($ty:tt)*) -> ($args:expr) ($($opt_args:tt)+)) => {{
39 $crate::check_args!(@ARGS_CHECK ($($ty)*) -> ($args) ($($opt_args)+ + 1))
40 }};
41
42 (@BUILD_TUPLE $args_iter:ident, $is_opt:tt ($(,)?) -> ($($body:tt)*)) => {{
43 $crate::check_args!(@AS_EXPR ($($body)*))
44 }};
45 (@BUILD_TUPLE $args_iter:ident, $is_opt:tt (, *) -> ($($body:tt)*)) => {{
46 $crate::check_args!(@AS_EXPR ($($body)* $args_iter.collect::<Vec<_>>()))
47 }};
48 (@BUILD_TUPLE $args_iter:ident, $is_opt:tt (| $($ty:tt)*) -> ($($body:tt)*)) => {{
49 $crate::check_args!(
50 @BUILD_TUPLE $args_iter, PARSE_ARG_OPT (, $($ty)*) -> ($($body)*)
51 )
52 }};
53 (@BUILD_TUPLE $args_iter:ident, $is_opt:tt (, $arg:tt $($ty:tt)*) -> ($($body:tt)*)) => {{
54 $crate::check_args!(
55 @BUILD_TUPLE $args_iter, $is_opt ($($ty)*) ->
56 ($($body)* $crate::check_args!(@$is_opt $args_iter, $arg),)
57 )
58 }};
59
60 (@PARSE_ARG $args_iter:ident, Value) => {{
61 $args_iter.next().unwrap()
62 }};
63 (@PARSE_ARG_OPT $args_iter:ident, Value) => {{
64 $args_iter.next()
65 }};
66 (@PARSE_ARG $args_iter:ident, $ty:tt) => {{
67 let t = $args_iter.next().unwrap();
68 $crate::check_args!(@AS_VALUE_TYPE t, $ty)
69 }};
70 (@PARSE_ARG_OPT $args_iter:ident, $ty:tt) => {{
71 match $args_iter.next() {
72 Some(v) => Some($crate::check_args!(@AS_VALUE_TYPE v, $ty)),
73 None => None,
74 }
75 }};
76
77 (@AS_VALUE_TYPE $value:ident, $ty:tt) => {{
78 if let Value::$ty(v) = $value {
79 v
80 } else {
81 return Err($crate::errors::Error::new(
82 $crate::errors::ErrorKind::UnexpectedType {
83 expected: $crate::objects::ValueType::$ty,
84 found: $value.value_type(),
85 }
86 ));
87 }
88 }};
89
90 ($args:ident $(,)?) => {{
91 let args_len = $args.len();
92 let required = $crate::errors::CallArgumentsErrorKind::from(0);
93 if !required.contains(&args_len) {
94 return Err($crate::errors::Error::new(
95 $crate::errors::ErrorKind::CallArguments {
96 value: None,
97 required,
98 given: args_len,
99 }
100 ));
101 }
102 }};
103 ($args:ident $($cont:tt)*) => {{
104 let args_len = $args.len();
105 let required = $crate::errors::CallArgumentsErrorKind::from(
106 $crate::check_args!(@ARGS_CHECK ($($cont)*) -> (0) ()),
107 );
108 if !required.contains(&args_len) {
109 return Err($crate::errors::Error::new(
110 $crate::errors::ErrorKind::CallArguments {
111 value: None,
112 required,
113 given: args_len,
114 }
115 ));
116 }
117 let mut args_iter = $args.iter().copied();
118 $crate::check_args!(@BUILD_TUPLE args_iter, PARSE_ARG ($($cont)*) -> ())
119 }};
120}