forked from rust-lang/rust
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvisit.rs
82 lines (72 loc) · 2.15 KB
/
visit.rs
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
use core::ops::ControlFlow;
/// Similar to the `Try` trait, but also implemented for `()`.
pub trait VisitorResult {
type Residual;
fn output() -> Self;
fn from_residual(residual: Self::Residual) -> Self;
fn from_branch(b: ControlFlow<Self::Residual>) -> Self;
fn branch(self) -> ControlFlow<Self::Residual>;
}
impl VisitorResult for () {
#[cfg(feature = "nightly")]
type Residual = !;
#[cfg(not(feature = "nightly"))]
type Residual = core::convert::Infallible;
fn output() -> Self {}
fn from_residual(_: Self::Residual) -> Self {}
fn from_branch(_: ControlFlow<Self::Residual>) -> Self {}
fn branch(self) -> ControlFlow<Self::Residual> {
ControlFlow::Continue(())
}
}
impl<T> VisitorResult for ControlFlow<T> {
type Residual = T;
fn output() -> Self {
ControlFlow::Continue(())
}
fn from_residual(residual: Self::Residual) -> Self {
ControlFlow::Break(residual)
}
fn from_branch(b: Self) -> Self {
b
}
fn branch(self) -> Self {
self
}
}
#[macro_export]
macro_rules! try_visit {
($e:expr) => {
match $crate::visit::VisitorResult::branch($e) {
core::ops::ControlFlow::Continue(()) => (),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return $crate::visit::VisitorResult::from_residual(r);
}
}
};
}
#[macro_export]
macro_rules! visit_opt {
($visitor: expr, $method: ident, $opt: expr $(, $($extra_args: expr),* )?) => {
if let Some(x) = $opt {
$crate::try_visit!($visitor.$method(x $(, $($extra_args,)* )?));
}
}
}
#[macro_export]
macro_rules! walk_list {
($visitor: expr, $method: ident, $list: expr $(, $($extra_args: expr),* )?) => {
for elem in $list {
$crate::try_visit!($visitor.$method(elem $(, $($extra_args,)* )?));
}
}
}
#[macro_export]
macro_rules! walk_visitable_list {
($visitor: expr, $list: expr $(, $($extra_args: expr),* )?) => {
for elem in $list {
$crate::try_visit!(elem.visit_with($visitor $(, $($extra_args,)* )?));
}
}
}