|
1 | | -// count number of tokens given as arguments. |
2 | | -// see: https://danielkeep.github.io/tlborm/book/blk-counting.html |
3 | | -#[macro_export] |
4 | | -macro_rules! replace_expr { |
5 | | - ($_t:tt $sub:expr) => { |
6 | | - $sub |
7 | | - }; |
8 | | -} |
9 | | - |
10 | | -#[macro_export] |
11 | | -macro_rules! count_tts { |
12 | | - ($($tts:tt)*) => {0usize $(+ $crate::replace_expr!($tts 1usize))*}; |
13 | | -} |
14 | | - |
15 | | -#[macro_export] |
16 | | -macro_rules! type_check { |
17 | | - ($vm:ident, $args:ident, $arg_count:ident, $arg_name:ident, $arg_type:expr) => { |
18 | | - // None indicates that we have no type requirement (i.e. we accept any type) |
19 | | - if let Some(expected_type) = $arg_type { |
20 | | - let arg = &$args.args[$arg_count]; |
21 | | - |
22 | | - if !$crate::obj::objtype::isinstance(arg, &expected_type) { |
23 | | - use $crate::pyobject::TypeProtocol; |
24 | | - |
25 | | - let arg_typ = arg.class(); |
26 | | - let expected_type_name = $vm.to_pystr(&expected_type)?; |
27 | | - let actual_type = $vm.to_pystr(&arg_typ)?; |
28 | | - return Err($vm.new_type_error(format!( |
29 | | - "argument of type {} is required for parameter {} ({}) (got: {})", |
30 | | - expected_type_name, |
31 | | - $arg_count + 1, |
32 | | - stringify!($arg_name), |
33 | | - actual_type |
34 | | - ))); |
35 | | - } |
36 | | - } |
37 | | - }; |
38 | | -} |
39 | | - |
40 | | -#[macro_export] |
41 | | -macro_rules! arg_check { |
42 | | - ( $vm: ident, $args:ident ) => { |
43 | | - // Zero-arg case |
44 | | - if $args.args.len() != 0 { |
45 | | - return Err($vm.new_type_error(format!( |
46 | | - "Expected no arguments (got: {})", $args.args.len()))); |
47 | | - } |
48 | | - }; |
49 | | - ( $vm: ident, $args:ident, required=[$( ($arg_name:ident, $arg_type:expr) ),*] ) => { |
50 | | - $crate::arg_check!($vm, $args, required=[$( ($arg_name, $arg_type) ),*], optional=[]); |
51 | | - }; |
52 | | - ( $vm: ident, $args:ident, required=[$( ($arg_name:ident, $arg_type:expr) ),*], optional=[$( ($optional_arg_name:ident, $optional_arg_type:expr) ),*] ) => { |
53 | | - let mut arg_count = 0; |
54 | | - |
55 | | - // use macro magic to compile-time count number of required and optional arguments |
56 | | - let minimum_arg_count = $crate::count_tts!($($arg_name)*); |
57 | | - let maximum_arg_count = minimum_arg_count + $crate::count_tts!($($optional_arg_name)*); |
58 | | - |
59 | | - // verify that the number of given arguments is right |
60 | | - if $args.args.len() < minimum_arg_count || $args.args.len() > maximum_arg_count { |
61 | | - let expected_str = if minimum_arg_count == maximum_arg_count { |
62 | | - format!("{}", minimum_arg_count) |
63 | | - } else { |
64 | | - format!("{}-{}", minimum_arg_count, maximum_arg_count) |
65 | | - }; |
66 | | - return Err($vm.new_type_error(format!( |
67 | | - "Expected {} arguments (got: {})", |
68 | | - expected_str, |
69 | | - $args.args.len() |
70 | | - ))); |
71 | | - }; |
72 | | - |
73 | | - // for each required parameter: |
74 | | - // check if the type matches. If not, return with error |
75 | | - // assign the arg to a variable |
76 | | - $( |
77 | | - $crate::type_check!($vm, $args, arg_count, $arg_name, $arg_type); |
78 | | - let $arg_name = &$args.args[arg_count]; |
79 | | - #[allow(unused_assignments)] |
80 | | - { |
81 | | - arg_count += 1; |
82 | | - } |
83 | | - )* |
84 | | - |
85 | | - // for each optional parameter, if there are enough positional arguments: |
86 | | - // check if the type matches. If not, return with error |
87 | | - // assign the arg to a variable |
88 | | - $( |
89 | | - let $optional_arg_name = if arg_count < $args.args.len() { |
90 | | - $crate::type_check!($vm, $args, arg_count, $optional_arg_name, $optional_arg_type); |
91 | | - let ret = Some(&$args.args[arg_count]); |
92 | | - #[allow(unused_assignments)] |
93 | | - { |
94 | | - arg_count += 1; |
95 | | - } |
96 | | - ret |
97 | | - } else { |
98 | | - None |
99 | | - }; |
100 | | - )* |
101 | | - }; |
102 | | -} |
103 | | - |
104 | 1 | #[macro_export] |
105 | 2 | macro_rules! no_kwargs { |
106 | 3 | ( $vm: ident, $args:ident ) => { |
|
0 commit comments