forked from RustPython/RustPython
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmacros.rs
More file actions
96 lines (90 loc) · 3.49 KB
/
macros.rs
File metadata and controls
96 lines (90 loc) · 3.49 KB
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
macro_rules! arg_check {
( $vm: ident, $args:ident ) => {
// Zero-arg case
if $args.args.len() != 0 {
return Err($vm.new_type_error(format!(
"Expected no arguments (got: {})", $args.args.len())));
}
};
( $vm: ident, $args:ident, required=[$( ($arg_name:ident, $arg_type:expr) ),*] ) => {
arg_check!($vm, $args, required=[$( ($arg_name, $arg_type) ),*], optional=[]);
};
( $vm: ident, $args:ident, required=[$( ($arg_name:ident, $arg_type:expr) ),*], optional=[$( ($optional_arg_name:ident, $optional_arg_type:expr) ),*] ) => {
let mut expected_args: Vec<(usize, &str, Option<PyObjectRef>)> = vec![];
let mut arg_count = 0;
$(
if arg_count >= $args.args.len() {
// TODO: Report the number of expected arguments
return Err($vm.new_type_error(format!(
"Expected more arguments (got: {})",
$args.args.len()
)));
}
expected_args.push((arg_count, stringify!($arg_name), $arg_type));
let $arg_name = &$args.args[arg_count];
#[allow(unused_assignments)]
{
arg_count += 1;
}
)*
let minimum_arg_count = arg_count;
$(
let $optional_arg_name = if arg_count < $args.args.len() {
expected_args.push((arg_count, stringify!($optional_arg_name), $optional_arg_type));
let ret = Some(&$args.args[arg_count]);
#[allow(unused_assignments)]
{
arg_count += 1;
}
ret
} else {
None
};
)*
if $args.args.len() < minimum_arg_count || $args.args.len() > expected_args.len() {
let expected_str = if minimum_arg_count == arg_count {
format!("{}", arg_count)
} else {
format!("{}-{}", minimum_arg_count, arg_count)
};
return Err($vm.new_type_error(format!(
"Expected {} arguments (got: {})",
expected_str,
$args.args.len()
)));
};
for (arg, (arg_position, arg_name, expected_type)) in
$args.args.iter().zip(expected_args.iter())
{
match expected_type {
Some(expected_type) => {
if !objtype::isinstance(arg, &expected_type) {
let arg_typ = arg.typ();
let expected_type_name = $vm.to_pystr(expected_type)?;
let actual_type = $vm.to_pystr(&arg_typ)?;
return Err($vm.new_type_error(format!(
"argument of type {} is required for parameter {} ({}) (got: {})",
expected_type_name,
arg_position + 1,
arg_name,
actual_type
)));
}
}
// None indicates that we have no type requirement (i.e. we accept any type)
None => {}
}
}
};
}
macro_rules! no_kwargs {
( $vm: ident, $args:ident ) => {
// Zero-arg case
if $args.kwargs.len() != 0 {
return Err($vm.new_type_error(format!(
"Expected no keyword arguments (got: {})",
$args.kwargs.len()
)));
}
};
}