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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use std::collections::HashMap;
use syntax::ast::*;
use syntax::visit::{self, Visitor};
use crate::ast_manip::Visit;
#[derive(Clone, Debug)]
pub struct NodeTable<'s, T: ?Sized + 's> {
nodes: HashMap<NodeId, &'s T>,
}
impl<'s, T> Default for NodeTable<'s, T> {
fn default() -> NodeTable<'s, T> {
NodeTable {
nodes: HashMap::new(),
}
}
}
impl<'s, T: ?Sized> NodeTable<'s, T> {
pub fn new() -> NodeTable<'s, T> {
NodeTable {
nodes: HashMap::new(),
}
}
pub fn insert(&mut self, id: NodeId, node: &'s T) {
if id == DUMMY_NODE_ID {
return;
}
assert!(!self.nodes.contains_key(&id));
self.nodes.insert(id, node);
}
pub fn get(&self, id: NodeId) -> Option<&'s T> {
self.nodes.get(&id).map(|&x| x)
}
pub fn len(&self) -> usize {
self.nodes.len()
}
}
#[derive(Clone, Default)]
pub struct AstMap<'s> {
pub exprs: NodeTable<'s, Expr>,
pub pats: NodeTable<'s, Pat>,
pub tys: NodeTable<'s, Ty>,
pub stmts: NodeTable<'s, Stmt>,
pub items: NodeTable<'s, Item>,
pub foreign_items: NodeTable<'s, ForeignItem>,
pub blocks: NodeTable<'s, Block>,
}
impl<'s> AstMap<'s> {
pub fn new() -> AstMap<'s> {
AstMap {
exprs: NodeTable::new(),
pats: NodeTable::new(),
tys: NodeTable::new(),
stmts: NodeTable::new(),
items: NodeTable::new(),
foreign_items: NodeTable::new(),
blocks: NodeTable::new(),
}
}
}
struct MapAstInto<'a, 's: 'a> {
map: &'a mut AstMap<'s>,
}
impl<'a, 's> Visitor<'s> for MapAstInto<'a, 's> {
fn visit_expr(&mut self, x: &'s Expr) {
if let ExprKind::Paren(_) = x.node {
} else {
self.map.exprs.insert(x.id, x);
}
visit::walk_expr(self, x);
}
fn visit_pat(&mut self, x: &'s Pat) {
self.map.pats.insert(x.id, x);
visit::walk_pat(self, x);
}
fn visit_ty(&mut self, x: &'s Ty) {
self.map.tys.insert(x.id, x);
visit::walk_ty(self, x);
}
fn visit_stmt(&mut self, x: &'s Stmt) {
self.map.stmts.insert(x.id, x);
visit::walk_stmt(self, x);
}
fn visit_item(&mut self, x: &'s Item) {
self.map.items.insert(x.id, x);
visit::walk_item(self, x);
}
fn visit_foreign_item(&mut self, x: &'s ForeignItem) {
self.map.foreign_items.insert(x.id, x);
visit::walk_foreign_item(self, x);
}
fn visit_block(&mut self, x: &'s Block) {
self.map.blocks.insert(x.id, x);
visit::walk_block(self, x);
}
fn visit_mac(&mut self, mac: &'s Mac) {
visit::walk_mac(self, mac);
}
}
pub fn map_ast_into<'s, T: Visit>(x: &'s T, map: &mut AstMap<'s>) {
x.visit(&mut MapAstInto { map })
}
pub fn map_ast<'s, T: Visit>(x: &'s T) -> AstMap<'s> {
let mut m = AstMap::new();
map_ast_into(x, &mut m);
m
}