lucia_lang/libs/
mod.rs

1//! The Lucia Standard Library.
2
3mod 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}