(index<- ) ./libsyntax/ast_map.rs
git branch: * master 5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
modified: Fri May 9 13:02:28 2014
1 // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use abi;
12 use ast::*;
13 use ast_util;
14 use codemap::Span;
15 use fold::Folder;
16 use fold;
17 use parse::token;
18 use print::pprust;
19 use util::small_vector::SmallVector;
20
21 use std::cell::RefCell;
22 use std::fmt;
23 use std::iter;
24 use std::slice;
25 use std::strbuf::StrBuf;
26
27 #[deriving(Clone, Eq)]
28 pub enum PathElem {
29 PathMod(Name),
30 PathName(Name)
31 }
32
33 impl PathElem {
34 pub fn name(&self) -> Name {
35 match *self {
36 PathMod(name) | PathName(name) => name
37 }
38 }
39 }
40
41 impl fmt::Show for PathElem {
42 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
43 let slot = token::get_name(self.name());
44 write!(f.buf, "{}", slot)
45 }
46 }
47
48 #[deriving(Clone)]
49 struct LinkedPathNode<'a> {
50 node: PathElem,
51 next: LinkedPath<'a>,
52 }
53
54 type LinkedPath<'a> = Option<&'a LinkedPathNode<'a>>;
55
56 impl<'a> Iterator<PathElem> for LinkedPath<'a> {
57 fn next(&mut self) -> Option<PathElem> {
58 match *self {
59 Some(node) => {
60 *self = node.next;
61 Some(node.node)
62 }
63 None => None
64 }
65 }
66 }
67
68 // HACK(eddyb) move this into libstd (value wrapper for slice::Items).
69 #[deriving(Clone)]
70 pub struct Values<'a, T>(pub slice::Items<'a, T>);
71
72 impl<'a, T: Copy> Iterator<T> for Values<'a, T> {
73 fn next(&mut self) -> Option<T> {
74 let &Values(ref mut items) = self;
75 items.next().map(|&x| x)
76 }
77 }
78
79 /// The type of the iterator used by with_path.
80 pub type PathElems<'a, 'b> = iter::Chain<Values<'a, PathElem>, LinkedPath<'b>>;
81
82 pub fn path_to_str<PI: Iterator<PathElem>>(mut path: PI) -> StrBuf {
83 let itr = token::get_ident_interner();
84
85 path.fold(StrBuf::new(), |mut s, e| {
86 let e = itr.get(e.name());
87 if !s.is_empty() {
88 s.push_str("::");
89 }
90 s.push_str(e.as_slice());
91 s
92 }).to_strbuf()
93 }
94
95 #[deriving(Clone)]
96 pub enum Node {
97 NodeItem(@Item),
98 NodeForeignItem(@ForeignItem),
99 NodeTraitMethod(@TraitMethod),
100 NodeMethod(@Method),
101 NodeVariant(P<Variant>),
102 NodeExpr(@Expr),
103 NodeStmt(@Stmt),
104 NodeArg(@Pat),
105 NodeLocal(@Pat),
106 NodeBlock(P<Block>),
107
108 /// NodeStructCtor represents a tuple struct.
109 NodeStructCtor(@StructDef),
110
111 NodeLifetime(@Lifetime),
112 }
113
114 // The odd layout is to bring down the total size.
115 #[deriving(Clone)]
116 enum MapEntry {
117 // Placeholder for holes in the map.
118 NotPresent,
119
120 // All the node types, with a parent ID.
121 EntryItem(NodeId, @Item),
122 EntryForeignItem(NodeId, @ForeignItem),
123 EntryTraitMethod(NodeId, @TraitMethod),
124 EntryMethod(NodeId, @Method),
125 EntryVariant(NodeId, P<Variant>),
126 EntryExpr(NodeId, @Expr),
127 EntryStmt(NodeId, @Stmt),
128 EntryArg(NodeId, @Pat),
129 EntryLocal(NodeId, @Pat),
130 EntryBlock(NodeId, P<Block>),
131 EntryStructCtor(NodeId, @StructDef),
132 EntryLifetime(NodeId, @Lifetime),
133
134 // Roots for node trees.
135 RootCrate,
136 RootInlinedParent(P<InlinedParent>)
137 }
138
139 struct InlinedParent {
140 path: Vec<PathElem> ,
141 // Required by NodeTraitMethod and NodeMethod.
142 def_id: DefId
143 }
144
145 impl MapEntry {
146 fn parent(&self) -> Option<NodeId> {
147 Some(match *self {
148 EntryItem(id, _) => id,
149 EntryForeignItem(id, _) => id,
150 EntryTraitMethod(id, _) => id,
151 EntryMethod(id, _) => id,
152 EntryVariant(id, _) => id,
153 EntryExpr(id, _) => id,
154 EntryStmt(id, _) => id,
155 EntryArg(id, _) => id,
156 EntryLocal(id, _) => id,
157 EntryBlock(id, _) => id,
158 EntryStructCtor(id, _) => id,
159 EntryLifetime(id, _) => id,
160 _ => return None
161 })
162 }
163
164 fn to_node(&self) -> Option<Node> {
165 Some(match *self {
166 EntryItem(_, p) => NodeItem(p),
167 EntryForeignItem(_, p) => NodeForeignItem(p),
168 EntryTraitMethod(_, p) => NodeTraitMethod(p),
169 EntryMethod(_, p) => NodeMethod(p),
170 EntryVariant(_, p) => NodeVariant(p),
171 EntryExpr(_, p) => NodeExpr(p),
172 EntryStmt(_, p) => NodeStmt(p),
173 EntryArg(_, p) => NodeArg(p),
174 EntryLocal(_, p) => NodeLocal(p),
175 EntryBlock(_, p) => NodeBlock(p),
176 EntryStructCtor(_, p) => NodeStructCtor(p),
177 EntryLifetime(_, p) => NodeLifetime(p),
178 _ => return None
179 })
180 }
181 }
182
183 pub struct Map {
184 /// NodeIds are sequential integers from 0, so we can be
185 /// super-compact by storing them in a vector. Not everything with
186 /// a NodeId is in the map, but empirically the occupancy is about
187 /// 75-80%, so there's not too much overhead (certainly less than
188 /// a hashmap, since they (at the time of writing) have a maximum
189 /// of 75% occupancy).
190 ///
191 /// Also, indexing is pretty quick when you've got a vector and
192 /// plain old integers.
193 map: RefCell<Vec<MapEntry> >
194 }
195
196 impl Map {
197 fn find_entry(&self, id: NodeId) -> Option<MapEntry> {
198 let map = self.map.borrow();
199 if map.len() > id as uint {
200 Some(*map.get(id as uint))
201 } else {
202 None
203 }
204 }
205
206 /// Retrieve the Node corresponding to `id`, failing if it cannot
207 /// be found.
208 pub fn get(&self, id: NodeId) -> Node {
209 match self.find(id) {
210 Some(node) => node,
211 None => fail!("couldn't find node id {} in the AST map", id)
212 }
213 }
214
215 /// Retrieve the Node corresponding to `id`, returning None if
216 /// cannot be found.
217 pub fn find(&self, id: NodeId) -> Option<Node> {
218 self.find_entry(id).and_then(|x| x.to_node())
219 }
220
221 /// Retrieve the parent NodeId for `id`, or `id` itself if no
222 /// parent is registered in this map.
223 pub fn get_parent(&self, id: NodeId) -> NodeId {
224 self.find_entry(id).and_then(|x| x.parent()).unwrap_or(id)
225 }
226
227 pub fn get_parent_did(&self, id: NodeId) -> DefId {
228 let parent = self.get_parent(id);
229 match self.find_entry(parent) {
230 Some(RootInlinedParent(data)) => data.def_id,
231 _ => ast_util::local_def(parent)
232 }
233 }
234
235 pub fn get_foreign_abi(&self, id: NodeId) -> abi::Abi {
236 let parent = self.get_parent(id);
237 let abi = match self.find_entry(parent) {
238 Some(EntryItem(_, i)) => match i.node {
239 ItemForeignMod(ref nm) => Some(nm.abi),
240 _ => None
241 },
242 // Wrong but OK, because the only inlined foreign items are intrinsics.
243 Some(RootInlinedParent(_)) => Some(abi::RustIntrinsic),
244 _ => None
245 };
246 match abi {
247 Some(abi) => abi,
248 None => fail!("expected foreign mod or inlined parent, found {}",
249 self.node_to_str(parent))
250 }
251 }
252
253 pub fn get_foreign_vis(&self, id: NodeId) -> Visibility {
254 let vis = self.expect_foreign_item(id).vis;
255 match self.find(self.get_parent(id)) {
256 Some(NodeItem(i)) => vis.inherit_from(i.vis),
257 _ => vis
258 }
259 }
260
261 pub fn expect_item(&self, id: NodeId) -> @Item {
262 match self.find(id) {
263 Some(NodeItem(item)) => item,
264 _ => fail!("expected item, found {}", self.node_to_str(id))
265 }
266 }
267
268 pub fn expect_struct(&self, id: NodeId) -> @StructDef {
269 match self.find(id) {
270 Some(NodeItem(i)) => {
271 match i.node {
272 ItemStruct(struct_def, _) => struct_def,
273 _ => fail!("struct ID bound to non-struct")
274 }
275 }
276 Some(NodeVariant(ref variant)) => {
277 match (*variant).node.kind {
278 StructVariantKind(struct_def) => struct_def,
279 _ => fail!("struct ID bound to enum variant that isn't struct-like"),
280 }
281 }
282 _ => fail!(format!("expected struct, found {}", self.node_to_str(id))),
283 }
284 }
285
286 pub fn expect_variant(&self, id: NodeId) -> P<Variant> {
287 match self.find(id) {
288 Some(NodeVariant(variant)) => variant,
289 _ => fail!(format!("expected variant, found {}", self.node_to_str(id))),
290 }
291 }
292
293 pub fn expect_foreign_item(&self, id: NodeId) -> @ForeignItem {
294 match self.find(id) {
295 Some(NodeForeignItem(item)) => item,
296 _ => fail!("expected foreign item, found {}", self.node_to_str(id))
297 }
298 }
299
300 pub fn get_path_elem(&self, id: NodeId) -> PathElem {
301 match self.get(id) {
302 NodeItem(item) => {
303 match item.node {
304 ItemMod(_) | ItemForeignMod(_) => {
305 PathMod(item.ident.name)
306 }
307 _ => PathName(item.ident.name)
308 }
309 }
310 NodeForeignItem(i) => PathName(i.ident.name),
311 NodeMethod(m) => PathName(m.ident.name),
312 NodeTraitMethod(tm) => match *tm {
313 Required(ref m) => PathName(m.ident.name),
314 Provided(ref m) => PathName(m.ident.name)
315 },
316 NodeVariant(v) => PathName(v.node.name.name),
317 node => fail!("no path elem for {:?}", node)
318 }
319 }
320
321 pub fn with_path<T>(&self, id: NodeId, f: |PathElems| -> T) -> T {
322 self.with_path_next(id, None, f)
323 }
324
325 pub fn path_to_str(&self, id: NodeId) -> StrBuf {
326 self.with_path(id, |path| path_to_str(path))
327 }
328
329 fn path_to_str_with_ident(&self, id: NodeId, i: Ident) -> StrBuf {
330 self.with_path(id, |path| {
331 path_to_str(path.chain(Some(PathName(i.name)).move_iter()))
332 })
333 }
334
335 fn with_path_next<T>(&self, id: NodeId, next: LinkedPath, f: |PathElems| -> T) -> T {
336 let parent = self.get_parent(id);
337 let parent = match self.find_entry(id) {
338 Some(EntryForeignItem(..)) | Some(EntryVariant(..)) => {
339 // Anonymous extern items, enum variants and struct ctors
340 // go in the parent scope.
341 self.get_parent(parent)
342 }
343 // But tuple struct ctors don't have names, so use the path of its
344 // parent, the struct item. Similarly with closure expressions.
345 Some(EntryStructCtor(..)) | Some(EntryExpr(..)) => {
346 return self.with_path_next(parent, next, f);
347 }
348 _ => parent
349 };
350 if parent == id {
351 match self.find_entry(id) {
352 Some(RootInlinedParent(data)) => {
353 f(Values(data.path.iter()).chain(next))
354 }
355 _ => f(Values([].iter()).chain(next))
356 }
357 } else {
358 self.with_path_next(parent, Some(&LinkedPathNode {
359 node: self.get_path_elem(id),
360 next: next
361 }), f)
362 }
363 }
364
365 pub fn with_attrs<T>(&self, id: NodeId, f: |Option<&[Attribute]>| -> T) -> T {
366 let node = self.get(id);
367 let attrs = match node {
368 NodeItem(ref i) => Some(i.attrs.as_slice()),
369 NodeForeignItem(ref fi) => Some(fi.attrs.as_slice()),
370 NodeTraitMethod(ref tm) => match **tm {
371 Required(ref type_m) => Some(type_m.attrs.as_slice()),
372 Provided(ref m) => Some(m.attrs.as_slice())
373 },
374 NodeMethod(ref m) => Some(m.attrs.as_slice()),
375 NodeVariant(ref v) => Some(v.node.attrs.as_slice()),
376 // unit/tuple structs take the attributes straight from
377 // the struct definition.
378 // FIXME(eddyb) make this work again (requires access to the map).
379 NodeStructCtor(_) => {
380 return self.with_attrs(self.get_parent(id), f);
381 }
382 _ => None
383 };
384 f(attrs)
385 }
386
387 pub fn span(&self, id: NodeId) -> Span {
388 match self.find(id) {
389 Some(NodeItem(item)) => item.span,
390 Some(NodeForeignItem(foreign_item)) => foreign_item.span,
391 Some(NodeTraitMethod(trait_method)) => {
392 match *trait_method {
393 Required(ref type_method) => type_method.span,
394 Provided(ref method) => method.span,
395 }
396 }
397 Some(NodeMethod(method)) => method.span,
398 Some(NodeVariant(variant)) => variant.span,
399 Some(NodeExpr(expr)) => expr.span,
400 Some(NodeStmt(stmt)) => stmt.span,
401 Some(NodeArg(pat)) | Some(NodeLocal(pat)) => pat.span,
402 Some(NodeBlock(block)) => block.span,
403 Some(NodeStructCtor(_)) => self.expect_item(self.get_parent(id)).span,
404 _ => fail!("node_span: could not find span for id {}", id),
405 }
406 }
407
408 pub fn node_to_str(&self, id: NodeId) -> StrBuf {
409 node_id_to_str(self, id)
410 }
411 }
412
413 pub trait FoldOps {
414 fn new_id(&self, id: NodeId) -> NodeId {
415 id
416 }
417 fn new_span(&self, span: Span) -> Span {
418 span
419 }
420 }
421
422 pub struct Ctx<'a, F> {
423 map: &'a Map,
424 // The node in which we are currently mapping (an item or a method).
425 // When equal to DUMMY_NODE_ID, the next mapped node becomes the parent.
426 parent: NodeId,
427 fold_ops: F
428 }
429
430 impl<'a, F> Ctx<'a, F> {
431 fn insert(&self, id: NodeId, entry: MapEntry) {
432 (*self.map.map.borrow_mut()).grow_set(id as uint, &NotPresent, entry);
433 }
434 }
435
436 impl<'a, F: FoldOps> Folder for Ctx<'a, F> {
437 fn new_id(&mut self, id: NodeId) -> NodeId {
438 let id = self.fold_ops.new_id(id);
439 if self.parent == DUMMY_NODE_ID {
440 self.parent = id;
441 }
442 id
443 }
444
445 fn new_span(&mut self, span: Span) -> Span {
446 self.fold_ops.new_span(span)
447 }
448
449 fn fold_item(&mut self, i: @Item) -> SmallVector<@Item> {
450 let parent = self.parent;
451 self.parent = DUMMY_NODE_ID;
452
453 let i = fold::noop_fold_item(i, self).expect_one("expected one item");
454 assert_eq!(self.parent, i.id);
455
456 match i.node {
457 ItemImpl(_, _, _, ref ms) => {
458 for &m in ms.iter() {
459 self.insert(m.id, EntryMethod(self.parent, m));
460 }
461 }
462 ItemEnum(ref enum_definition, _) => {
463 for &v in enum_definition.variants.iter() {
464 self.insert(v.node.id, EntryVariant(self.parent, v));
465 }
466 }
467 ItemForeignMod(ref nm) => {
468 for &nitem in nm.items.iter() {
469 self.insert(nitem.id, EntryForeignItem(self.parent, nitem));
470 }
471 }
472 ItemStruct(struct_def, _) => {
473 // If this is a tuple-like struct, register the constructor.
474 match struct_def.ctor_id {
475 Some(ctor_id) => {
476 self.insert(ctor_id, EntryStructCtor(self.parent,
477 struct_def));
478 }
479 None => {}
480 }
481 }
482 ItemTrait(_, _, ref traits, ref methods) => {
483 for t in traits.iter() {
484 self.insert(t.ref_id, EntryItem(self.parent, i));
485 }
486
487 for tm in methods.iter() {
488 match *tm {
489 Required(ref m) => {
490 self.insert(m.id, EntryTraitMethod(self.parent,
491 @(*tm).clone()));
492 }
493 Provided(m) => {
494 self.insert(m.id, EntryTraitMethod(self.parent,
495 @Provided(m)));
496 }
497 }
498 }
499 }
500 _ => {}
501 }
502
503 self.parent = parent;
504 self.insert(i.id, EntryItem(self.parent, i));
505
506 SmallVector::one(i)
507 }
508
509 fn fold_pat(&mut self, pat: @Pat) -> @Pat {
510 let pat = fold::noop_fold_pat(pat, self);
511 match pat.node {
512 PatIdent(..) => {
513 // Note: this is at least *potentially* a pattern...
514 self.insert(pat.id, EntryLocal(self.parent, pat));
515 }
516 _ => {}
517 }
518
519 pat
520 }
521
522 fn fold_expr(&mut self, expr: @Expr) -> @Expr {
523 let expr = fold::noop_fold_expr(expr, self);
524
525 self.insert(expr.id, EntryExpr(self.parent, expr));
526
527 expr
528 }
529
530 fn fold_stmt(&mut self, stmt: &Stmt) -> SmallVector<@Stmt> {
531 let stmt = fold::noop_fold_stmt(stmt, self).expect_one("expected one statement");
532 self.insert(ast_util::stmt_id(stmt), EntryStmt(self.parent, stmt));
533 SmallVector::one(stmt)
534 }
535
536 fn fold_type_method(&mut self, m: &TypeMethod) -> TypeMethod {
537 let parent = self.parent;
538 self.parent = DUMMY_NODE_ID;
539 let m = fold::noop_fold_type_method(m, self);
540 assert_eq!(self.parent, m.id);
541 self.parent = parent;
542 m
543 }
544
545 fn fold_method(&mut self, m: @Method) -> @Method {
546 let parent = self.parent;
547 self.parent = DUMMY_NODE_ID;
548 let m = fold::noop_fold_method(m, self);
549 assert_eq!(self.parent, m.id);
550 self.parent = parent;
551 m
552 }
553
554 fn fold_fn_decl(&mut self, decl: &FnDecl) -> P<FnDecl> {
555 let decl = fold::noop_fold_fn_decl(decl, self);
556 for a in decl.inputs.iter() {
557 self.insert(a.id, EntryArg(self.parent, a.pat));
558 }
559 decl
560 }
561
562 fn fold_block(&mut self, block: P<Block>) -> P<Block> {
563 let block = fold::noop_fold_block(block, self);
564 self.insert(block.id, EntryBlock(self.parent, block));
565 block
566 }
567
568 fn fold_lifetime(&mut self, lifetime: &Lifetime) -> Lifetime {
569 let lifetime = fold::noop_fold_lifetime(lifetime, self);
570 self.insert(lifetime.id, EntryLifetime(self.parent, @lifetime));
571 lifetime
572 }
573 }
574
575 pub fn map_crate<F: FoldOps>(krate: Crate, fold_ops: F) -> (Crate, Map) {
576 let map = Map { map: RefCell::new(Vec::new()) };
577 let krate = {
578 let mut cx = Ctx {
579 map: &map,
580 parent: CRATE_NODE_ID,
581 fold_ops: fold_ops
582 };
583 cx.insert(CRATE_NODE_ID, RootCrate);
584 cx.fold_crate(krate)
585 };
586
587 if log_enabled!(::log::DEBUG) {
588 let map = map.map.borrow();
589 // This only makes sense for ordered stores; note the
590 // enumerate to count the number of entries.
591 let (entries_less_1, _) = (*map).iter().filter(|&x| {
592 match *x {
593 NotPresent => false,
594 _ => true
595 }
596 }).enumerate().last().expect("AST map was empty after folding?");
597
598 let entries = entries_less_1 + 1;
599 let vector_length = (*map).len();
600 debug!("The AST map has {} entries with a maximum of {}: occupancy {:.1}%",
601 entries, vector_length, (entries as f64 / vector_length as f64) * 100.);
602 }
603
604 (krate, map)
605 }
606
607 // Used for items loaded from external crate that are being inlined into this
608 // crate. The `path` should be the path to the item but should not include
609 // the item itself.
610 pub fn map_decoded_item<F: FoldOps>(map: &Map,
611 path: Vec<PathElem> ,
612 fold_ops: F,
613 fold: |&mut Ctx<F>| -> InlinedItem)
614 -> InlinedItem {
615 let mut cx = Ctx {
616 map: map,
617 parent: DUMMY_NODE_ID,
618 fold_ops: fold_ops
619 };
620
621 // Generate a NodeId for the RootInlinedParent inserted below.
622 cx.new_id(DUMMY_NODE_ID);
623
624 // Methods get added to the AST map when their impl is visited. Since we
625 // don't decode and instantiate the impl, but just the method, we have to
626 // add it to the table now. Likewise with foreign items.
627 let mut def_id = DefId { krate: LOCAL_CRATE, node: DUMMY_NODE_ID };
628 let ii = fold(&mut cx);
629 match ii {
630 IIItem(_) => {}
631 IIMethod(impl_did, is_provided, m) => {
632 let entry = if is_provided {
633 EntryTraitMethod(cx.parent, @Provided(m))
634 } else {
635 EntryMethod(cx.parent, m)
636 };
637 cx.insert(m.id, entry);
638 def_id = impl_did;
639 }
640 IIForeign(i) => {
641 cx.insert(i.id, EntryForeignItem(cx.parent, i));
642 }
643 }
644
645 cx.insert(cx.parent, RootInlinedParent(P(InlinedParent {
646 path: path,
647 def_id: def_id
648 })));
649
650 ii
651 }
652
653 fn node_id_to_str(map: &Map, id: NodeId) -> StrBuf {
654 match map.find(id) {
655 Some(NodeItem(item)) => {
656 let path_str = map.path_to_str_with_ident(id, item.ident);
657 let item_str = match item.node {
658 ItemStatic(..) => "static",
659 ItemFn(..) => "fn",
660 ItemMod(..) => "mod",
661 ItemForeignMod(..) => "foreign mod",
662 ItemTy(..) => "ty",
663 ItemEnum(..) => "enum",
664 ItemStruct(..) => "struct",
665 ItemTrait(..) => "trait",
666 ItemImpl(..) => "impl",
667 ItemMac(..) => "macro"
668 };
669 (format!("{} {} (id={})", item_str, path_str, id)).to_strbuf()
670 }
671 Some(NodeForeignItem(item)) => {
672 let path_str = map.path_to_str_with_ident(id, item.ident);
673 (format!("foreign item {} (id={})", path_str, id)).to_strbuf()
674 }
675 Some(NodeMethod(m)) => {
676 (format!("method {} in {} (id={})",
677 token::get_ident(m.ident),
678 map.path_to_str(id), id)).to_strbuf()
679 }
680 Some(NodeTraitMethod(ref tm)) => {
681 let m = ast_util::trait_method_to_ty_method(&**tm);
682 (format!("method {} in {} (id={})",
683 token::get_ident(m.ident),
684 map.path_to_str(id), id)).to_strbuf()
685 }
686 Some(NodeVariant(ref variant)) => {
687 (format!("variant {} in {} (id={})",
688 token::get_ident(variant.node.name),
689 map.path_to_str(id), id)).to_strbuf()
690 }
691 Some(NodeExpr(expr)) => {
692 (format!("expr {} (id={})",
693 pprust::expr_to_str(expr), id)).to_strbuf()
694 }
695 Some(NodeStmt(stmt)) => {
696 (format!("stmt {} (id={})",
697 pprust::stmt_to_str(stmt), id)).to_strbuf()
698 }
699 Some(NodeArg(pat)) => {
700 (format!("arg {} (id={})",
701 pprust::pat_to_str(pat), id)).to_strbuf()
702 }
703 Some(NodeLocal(pat)) => {
704 (format!("local {} (id={})",
705 pprust::pat_to_str(pat), id)).to_strbuf()
706 }
707 Some(NodeBlock(block)) => {
708 (format!("block {} (id={})",
709 pprust::block_to_str(block), id)).to_strbuf()
710 }
711 Some(NodeStructCtor(_)) => {
712 (format!("struct_ctor {} (id={})",
713 map.path_to_str(id), id)).to_strbuf()
714 }
715 Some(NodeLifetime(ref l)) => {
716 (format!("lifetime {} (id={})",
717 pprust::lifetime_to_str(*l), id)).to_strbuf()
718 }
719 None => {
720 (format!("unknown node (id={})", id)).to_strbuf()
721 }
722 }
723 }
libsyntax/ast_map.rs:182:1-182:1 -struct- definition:
pub struct Map {
/// NodeIds are sequential integers from 0, so we can be
/// super-compact by storing them in a vector. Not everything with
references:- 6575: pub fn map_crate<F: FoldOps>(krate: Crate, fold_ops: F) -> (Crate, Map) {
576: let map = Map { map: RefCell::new(Vec::new()) };
577: let krate = {
--
653: fn node_id_to_str(map: &Map, id: NodeId) -> StrBuf {
654: match map.find(id) {
libsyntax/ast_map.rs:115:19-115:19 -enum- definition:
enum MapEntry {
// Placeholder for holes in the map.
NotPresent,
references:- 6430: impl<'a, F> Ctx<'a, F> {
431: fn insert(&self, id: NodeId, entry: MapEntry) {
432: (*self.map.map.borrow_mut()).grow_set(id as uint, &NotPresent, entry);
libsyntax/ast_map.rs:95:19-95:19 -enum- definition:
pub enum Node {
NodeItem(@Item),
NodeForeignItem(@ForeignItem),
references:- 5207: /// be found.
208: pub fn get(&self, id: NodeId) -> Node {
209: match self.find(id) {
--
216: /// cannot be found.
217: pub fn find(&self, id: NodeId) -> Option<Node> {
218: self.find_entry(id).and_then(|x| x.to_node())
libsyntax/ast_map.rs:79:48-79:48 -NK_AS_STR_TODO- definition:
/// The type of the iterator used by with_path.
pub type PathElems<'a, 'b> = iter::Chain<Values<'a, PathElem>, LinkedPath<'b>>;
pub fn path_to_str<PI: Iterator<PathElem>>(mut path: PI) -> StrBuf {
references:- 2321: pub fn with_path<T>(&self, id: NodeId, f: |PathElems| -> T) -> T {
322: self.with_path_next(id, None, f)
--
335: fn with_path_next<T>(&self, id: NodeId, next: LinkedPath, f: |PathElems| -> T) -> T {
336: let parent = self.get_parent(id);
libsyntax/ast_map.rs:69:19-69:19 -struct- definition:
pub struct Values<'a, T>(pub slice::Items<'a, T>);
impl<'a, T: Copy> Iterator<T> for Values<'a, T> {
fn next(&mut self) -> Option<T> {
references:- 479: /// The type of the iterator used by with_path.
80: pub type PathElems<'a, 'b> = iter::Chain<Values<'a, PathElem>, LinkedPath<'b>>;
libsyntax/ast_map.rs:27:23-27:23 -enum- definition:
pub enum PathElem {
PathMod(Name),
PathName(Name)
references:- 1528: pub enum PathElem {
--
79: /// The type of the iterator used by with_path.
80: pub type PathElems<'a, 'b> = iter::Chain<Values<'a, PathElem>, LinkedPath<'b>>;
--
139: struct InlinedParent {
140: path: Vec<PathElem> ,
141: // Required by NodeTraitMethod and NodeMethod.
--
300: pub fn get_path_elem(&self, id: NodeId) -> PathElem {
301: match self.get(id) {
--
610: pub fn map_decoded_item<F: FoldOps>(map: &Map,
611: path: Vec<PathElem> ,
612: fold_ops: F,
libsyntax/ast_map.rs:81:1-81:1 -fn- definition:
pub fn path_to_str<PI: Iterator<PathElem>>(mut path: PI) -> StrBuf {
let itr = token::get_ident_interner();
path.fold(StrBuf::new(), |mut s, e| {
references:- 2330: self.with_path(id, |path| {
331: path_to_str(path.chain(Some(PathName(i.name)).move_iter()))
332: })
libsyntax/ast_map.rs:421:1-421:1 -struct- definition:
pub struct Ctx<'a, F> {
map: &'a Map,
// The node in which we are currently mapping (an item or a method).
references:- 5577: let krate = {
578: let mut cx = Ctx {
579: map: &map,
--
614: -> InlinedItem {
615: let mut cx = Ctx {
616: map: map,
libsyntax/ast_map.rs:48:19-48:19 -struct- definition:
struct LinkedPathNode<'a> {
node: PathElem,
next: LinkedPath<'a>,
references:- 649: struct LinkedPathNode<'a> {
--
357: } else {
358: self.with_path_next(parent, Some(&LinkedPathNode {
359: node: self.get_path_elem(id),
libsyntax/ast_map.rs:53:1-53:1 -NK_AS_STR_TODO- definition:
type LinkedPath<'a> = Option<&'a LinkedPathNode<'a>>;
impl<'a> Iterator<PathElem> for LinkedPath<'a> {
fn next(&mut self) -> Option<PathElem> {
references:- 4335: fn with_path_next<T>(&self, id: NodeId, next: LinkedPath, f: |PathElems| -> T) -> T {
336: let parent = self.get_parent(id);
libsyntax/ast_map.rs:138:1-138:1 -struct- definition:
struct InlinedParent {
path: Vec<PathElem> ,
// Required by NodeTraitMethod and NodeMethod.
references:- 2135: RootCrate,
136: RootInlinedParent(P<InlinedParent>)
137: }
--
645: cx.insert(cx.parent, RootInlinedParent(P(InlinedParent {
646: path: path,
libsyntax/ast_map.rs:412:1-412:1 -trait- definition:
pub trait FoldOps {
fn new_id(&self, id: NodeId) -> NodeId {
id
references:- 3609: // the item itself.
610: pub fn map_decoded_item<F: FoldOps>(map: &Map,
611: path: Vec<PathElem> ,