about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGarming Sam <garming_sam@outlook.com>2015-05-14 23:40:16 +1200
committerGarming Sam <garming_sam@outlook.com>2015-08-09 20:53:57 +1200
commitf4ea3928aca448788e0d3abc05d7ece832278f80 (patch)
treef0940c917820b4acdcaa73ca431de91cf5129636
parentea5cc76aac7094abfe01657db8312c8450b15200 (diff)
downloadrust-f4ea3928aca448788e0d3abc05d7ece832278f80.tar.gz
rust-f4ea3928aca448788e0d3abc05d7ece832278f80.zip
Introduce callback to resolver
Sets a flag to pass through the rest of the walker.
-rw-r--r--src/librustc_resolve/lib.rs108
1 files changed, 92 insertions, 16 deletions
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index fa9c7a2038c..b6e9619129b 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -397,7 +397,7 @@ enum PatternBindingMode {
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
-enum Namespace {
+pub enum Namespace {
     TypeNS,
     ValueNS
 }
@@ -445,18 +445,38 @@ enum NameDefinition {
 
 impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
     fn visit_item(&mut self, item: &Item) {
+        if let Some(ref callback) = self.callback {
+            if callback(ast_map::Node::NodeItem(item), &mut self.resolved) {
+                return;
+            }
+        }
         self.resolve_item(item);
     }
     fn visit_arm(&mut self, arm: &Arm) {
         self.resolve_arm(arm);
     }
     fn visit_block(&mut self, block: &Block) {
+        if let Some(ref callback) = self.callback {
+            if callback(ast_map::Node::NodeBlock(block), &mut self.resolved) {
+                return;
+            }
+        }
         self.resolve_block(block);
     }
     fn visit_expr(&mut self, expr: &Expr) {
+        if let Some(ref callback) = self.callback {
+            if callback(ast_map::Node::NodeExpr(expr), &mut self.resolved) {
+                return;
+            }
+        }
         self.resolve_expr(expr);
     }
     fn visit_local(&mut self, local: &Local) {
+        if let Some(ref callback) = self.callback {
+            if callback(ast_map::Node::NodeLocal(&*local.pat), &mut self.resolved) {
+                return;
+            }
+        }
         self.resolve_local(local);
     }
     fn visit_ty(&mut self, ty: &Ty) {
@@ -475,6 +495,11 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
         visit::walk_poly_trait_ref(self, tref, m);
     }
     fn visit_variant(&mut self, variant: &ast::Variant, generics: &Generics) {
+        if let Some(ref callback) = self.callback {
+            if callback(ast_map::Node::NodeVariant(variant), &mut self.resolved) {
+                return;
+            }
+        }
         if let Some(ref dis_expr) = variant.node.disr_expr {
             // resolve the discriminator expr as a constant
             self.with_constant_rib(|this| {
@@ -498,6 +523,11 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
         }
     }
     fn visit_foreign_item(&mut self, foreign_item: &ast::ForeignItem) {
+        if let Some(ref callback) = self.callback {
+            if callback(ast_map::Node::NodeForeignItem(foreign_item), &mut self.resolved) {
+                return;
+            }
+        }
         let type_parameters = match foreign_item.node {
             ForeignItemFn(_, ref generics) => {
                 HasTypeParameters(generics, FnSpace, ItemRibKind)
@@ -1110,6 +1140,13 @@ pub struct Resolver<'a, 'tcx:'a> {
 
     used_imports: HashSet<(NodeId, Namespace)>,
     used_crates: HashSet<CrateNum>,
+
+    // Callback function for intercepting walks
+    callback: Option<Box<Fn(ast_map::Node, &mut bool) -> bool>>,
+    // The intention is that the callback modifies this flag.
+    // Once set, the resolver falls out of the walk, preserving the ribs.
+    resolved: bool,
+
 }
 
 #[derive(PartialEq)]
@@ -1171,6 +1208,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             emit_errors: true,
             make_glob_map: make_glob_map == MakeGlobMap::Yes,
             glob_map: HashMap::new(),
+
+            callback: None,
+            resolved: false,
+
         }
     }
 
@@ -2207,7 +2248,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         f(self);
 
         match type_parameters {
-            HasTypeParameters(..) => { self.type_ribs.pop(); }
+            HasTypeParameters(..) => { if !self.resolved { self.type_ribs.pop(); } }
             NoTypeParameters => { }
         }
     }
@@ -2217,7 +2258,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
     {
         self.label_ribs.push(Rib::new(NormalRibKind));
         f(self);
-        self.label_ribs.pop();
+        if !self.resolved {
+            self.label_ribs.pop();
+        }
     }
 
     fn with_constant_rib<F>(&mut self, f: F) where
@@ -2226,8 +2269,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         self.value_ribs.push(Rib::new(ConstantItemRibKind));
         self.type_ribs.push(Rib::new(ConstantItemRibKind));
         f(self);
-        self.type_ribs.pop();
-        self.value_ribs.pop();
+        if !self.resolved {
+            self.type_ribs.pop();
+            self.value_ribs.pop();
+        }
     }
 
     fn resolve_function(&mut self,
@@ -2258,8 +2303,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
         debug!("(resolving function) leaving function");
 
-        self.label_ribs.pop();
-        self.value_ribs.pop();
+        if !self.resolved {
+            self.label_ribs.pop();
+            self.value_ribs.pop();
+        }
     }
 
     fn resolve_trait_reference(&mut self,
@@ -2362,7 +2409,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         self_type_rib.bindings.insert(name, DlDef(self_def));
         self.type_ribs.push(self_type_rib);
         f(self);
-        self.type_ribs.pop();
+        if !self.resolved {
+            self.type_ribs.pop();
+        }
     }
 
     fn resolve_implementation(&mut self,
@@ -2531,7 +2580,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         visit::walk_expr_opt(self, &arm.guard);
         self.visit_expr(&*arm.body);
 
-        self.value_ribs.pop();
+        if !self.resolved {
+            self.value_ribs.pop();
+        }
     }
 
     fn resolve_block(&mut self, block: &Block) {
@@ -2575,7 +2626,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         // Move back up.
         self.current_module = orig_module;
 
-        self.value_ribs.pop();
+        if !self.resolved {
+            self.value_ribs.pop();
+        }
         debug!("(resolving block) leaving block");
     }
 
@@ -3017,12 +3070,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
     /// doesn't skip straight to the containing module.
     /// Skips `path_depth` trailing segments, which is also reflected in the
     /// returned value. See `middle::def::PathResolution` for more info.
-    fn resolve_path(&mut self,
-                    id: NodeId,
-                    path: &Path,
-                    path_depth: usize,
-                    namespace: Namespace,
-                    check_ribs: bool) -> Option<PathResolution> {
+    pub fn resolve_path(&mut self,
+                        id: NodeId,
+                        path: &Path,
+                        path_depth: usize,
+                        namespace: Namespace,
+                        check_ribs: bool) -> Option<PathResolution> {
         let span = path.span;
         let segments = &path.segments[..path.segments.len()-path_depth];
 
@@ -3991,4 +4044,27 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session,
     }
 }
 
+pub fn create_resolver<'a, 'tcx>(session: &'a Session,
+                                 ast_map: &'a ast_map::Map<'tcx>,
+                                 _: &LanguageItems,
+                                 krate: &'a Crate,
+                                 make_glob_map: MakeGlobMap,
+                                 callback: Option<Box<Fn(ast_map::Node, &mut bool) -> bool>>)
+                                 -> Resolver<'a, 'tcx> {
+    let mut resolver = Resolver::new(session, ast_map, krate.span, make_glob_map);
+
+    resolver.callback = callback;
+
+    build_reduced_graph::build_reduced_graph(&mut resolver, krate);
+    session.abort_if_errors();
+
+    resolve_imports::resolve_imports(&mut resolver);
+    session.abort_if_errors();
+
+    record_exports::record(&mut resolver);
+    session.abort_if_errors();
+
+    resolver
+}
+
 __build_diagnostic_array! { librustc_resolve, DIAGNOSTICS }