about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJohn Clements <clements@racket-lang.org>2014-07-09 16:41:13 -0700
committerJohn Clements <clements@racket-lang.org>2014-07-11 10:32:42 -0700
commitc253b3675ab03b6c64021e8acee3988cea81f3f9 (patch)
tree670d9923537f7dde804e639f56a4478620b8a727
parent53642eed801d157613de0998cdcf0a3da8c36cb3 (diff)
downloadrust-c253b3675ab03b6c64021e8acee3988cea81f3f9.tar.gz
rust-c253b3675ab03b6c64021e8acee3988cea81f3f9.zip
add Macro Exterminator
the Macro Exterminator ensures that there are no macro invocations in
an AST. This should help make later passes confident that there aren't
hidden items, methods, expressions, etc.
-rw-r--r--src/librustc/driver/driver.rs7
-rw-r--r--src/libsyntax/ext/expand.rs19
2 files changed, 25 insertions, 1 deletions
diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs
index 6a016edcd28..ad83e2cfe17 100644
--- a/src/librustc/driver/driver.rs
+++ b/src/librustc/driver/driver.rs
@@ -259,6 +259,8 @@ pub fn phase_2_configure_and_expand(sess: &Session,
         }
     );
 
+    // JBC: make CFG processing part of expansion to avoid this problem:
+
     // strip again, in case expansion added anything with a #[cfg].
     krate = time(time_passes, "configuration 2", krate, |krate|
                  front::config::strip_unconfigured_items(krate));
@@ -279,6 +281,9 @@ pub fn phase_2_configure_and_expand(sess: &Session,
         krate.encode(&mut json).unwrap();
     }
 
+    time(time_passes, "checking that all macro invocations are gone", &krate, |krate|
+         syntax::ext::expand::check_for_macros(&sess.parse_sess, krate));
+
     Some((krate, map))
 }
 
@@ -291,6 +296,7 @@ pub struct CrateAnalysis {
     pub name: String,
 }
 
+
 /// Run the resolution, typechecking, region checking and other
 /// miscellaneous analysis passes on the crate. Return various
 /// structures carrying the results of the analysis.
@@ -298,7 +304,6 @@ pub fn phase_3_run_analysis_passes(sess: Session,
                                    krate: &ast::Crate,
                                    ast_map: syntax::ast_map::Map,
                                    name: String) -> CrateAnalysis {
-
     let time_passes = sess.time_passes();
 
     time(time_passes, "external crate/lib resolution", (), |_|
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 084faca02c5..c82364fb17e 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -1151,6 +1151,25 @@ fn original_span(cx: &ExtCtxt) -> Gc<codemap::ExpnInfo> {
     return einfo;
 }
 
+/// Check that there are no macro invocations left in the AST:
+pub fn check_for_macros(sess: &parse::ParseSess, krate: &ast::Crate) {
+    visit::walk_crate(&mut MacroExterminator{sess:sess}, krate, ());
+}
+
+/// A visitor that ensures that no macro invocations remain in an AST.
+struct MacroExterminator<'a>{
+    sess: &'a parse::ParseSess
+}
+
+impl<'a> visit::Visitor<()> for MacroExterminator<'a> {
+    fn visit_mac(&mut self, macro: &ast::Mac, _:()) {
+        self.sess.span_diagnostic.span_bug(macro.span,
+                                           "macro exterminator: expected AST \
+                                           with no macro invocations");
+    }
+}
+
+
 #[cfg(test)]
 mod test {
     use super::{pattern_bindings, expand_crate, contains_macro_escape};