about summary refs log tree commit diff
path: root/src/libsyntax_ext
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <edy.burt@gmail.com>2018-03-16 01:09:22 +0200
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2018-11-30 06:15:19 +0200
commite305994beb1347e2fcadf5c84acec60fb6902551 (patch)
treefa3cc47ac732137a158714c65f2e758667ef7e8f /src/libsyntax_ext
parent3e90a12a8a95933604a8b609197fce61bb24a38c (diff)
downloadrust-e305994beb1347e2fcadf5c84acec60fb6902551.tar.gz
rust-e305994beb1347e2fcadf5c84acec60fb6902551.zip
proc_macro: introduce a "bridge" between clients (proc macros) and servers (compiler front-ends).
Diffstat (limited to 'src/libsyntax_ext')
-rw-r--r--src/libsyntax_ext/deriving/custom.rs65
-rw-r--r--src/libsyntax_ext/lib.rs4
-rw-r--r--src/libsyntax_ext/proc_macro_decls.rs (renamed from src/libsyntax_ext/proc_macro_registrar.rs)142
-rw-r--r--src/libsyntax_ext/proc_macro_impl.rs42
4 files changed, 124 insertions, 129 deletions
diff --git a/src/libsyntax_ext/deriving/custom.rs b/src/libsyntax_ext/deriving/custom.rs
index 55b3928d68e..76826dd93e7 100644
--- a/src/libsyntax_ext/deriving/custom.rs
+++ b/src/libsyntax_ext/deriving/custom.rs
@@ -8,15 +8,18 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::panic;
-
 use errors::FatalError;
-use proc_macro::{TokenStream, __internal};
 use syntax::ast::{self, ItemKind, Attribute, Mac};
 use syntax::attr::{mark_used, mark_known};
 use syntax::source_map::Span;
 use syntax::ext::base::*;
+use syntax::parse;
+use syntax::parse::token::{self, Token};
+use syntax::tokenstream;
 use syntax::visit::Visitor;
+use syntax_pos::DUMMY_SP;
+
+use proc_macro_impl::EXEC_STRATEGY;
 
 struct MarkAttrs<'a>(&'a [ast::Name]);
 
@@ -32,14 +35,10 @@ impl<'a> Visitor<'a> for MarkAttrs<'a> {
 }
 
 pub struct ProcMacroDerive {
-    inner: fn(TokenStream) -> TokenStream,
-    attrs: Vec<ast::Name>,
-}
-
-impl ProcMacroDerive {
-    pub fn new(inner: fn(TokenStream) -> TokenStream, attrs: Vec<ast::Name>) -> ProcMacroDerive {
-        ProcMacroDerive { inner: inner, attrs: attrs }
-    }
+    pub client: ::proc_macro::bridge::client::Client<
+        fn(::proc_macro::TokenStream) -> ::proc_macro::TokenStream,
+    >,
+    pub attrs: Vec<ast::Name>,
 }
 
 impl MultiItemModifier for ProcMacroDerive {
@@ -75,10 +74,12 @@ impl MultiItemModifier for ProcMacroDerive {
         // Mark attributes as known, and used.
         MarkAttrs(&self.attrs).visit_item(&item);
 
-        let input = __internal::new_token_stream(ecx.resolver.eliminate_crate_var(item));
-        let res = __internal::set_sess(ecx, || {
-            let inner = self.inner;
-            panic::catch_unwind(panic::AssertUnwindSafe(|| inner(input)))
+        let item = ecx.resolver.eliminate_crate_var(item);
+        let token = Token::interpolated(token::NtItem(item));
+        let input = tokenstream::TokenTree::Token(DUMMY_SP, token).into();
+        let server = ::proc_macro::rustc::Rustc;
+        let res = ::proc_macro::__internal::set_sess(ecx, || {
+            self.client.run(&EXEC_STRATEGY, server, input)
         });
 
         let stream = match res {
@@ -86,10 +87,7 @@ impl MultiItemModifier for ProcMacroDerive {
             Err(e) => {
                 let msg = "proc-macro derive panicked";
                 let mut err = ecx.struct_span_fatal(span, msg);
-                if let Some(s) = e.downcast_ref::<String>() {
-                    err.help(&format!("message: {}", s));
-                }
-                if let Some(s) = e.downcast_ref::<&'static str>() {
+                if let Some(s) = e.as_str() {
                     err.help(&format!("message: {}", s));
                 }
 
@@ -99,21 +97,32 @@ impl MultiItemModifier for ProcMacroDerive {
         };
 
         let error_count_before = ecx.parse_sess.span_diagnostic.err_count();
-        __internal::set_sess(ecx, || {
-            let msg = "proc-macro derive produced unparseable tokens";
-            match __internal::token_stream_parse_items(stream) {
-                // fail if there have been errors emitted
-                Ok(_) if ecx.parse_sess.span_diagnostic.err_count() > error_count_before => {
-                    ecx.struct_span_fatal(span, msg).emit();
-                    FatalError.raise();
+        let msg = "proc-macro derive produced unparseable tokens";
+
+        let mut parser = parse::stream_to_parser(ecx.parse_sess, stream);
+        let mut items = vec![];
+
+        loop {
+            match parser.parse_item().map_err(::proc_macro::__internal::parse_to_lex_err) {
+                Ok(None) => break,
+                Ok(Some(item)) => {
+                    items.push(Annotatable::Item(item))
                 }
-                Ok(new_items) => new_items.into_iter().map(Annotatable::Item).collect(),
                 Err(_) => {
                     // FIXME: handle this better
                     ecx.struct_span_fatal(span, msg).emit();
                     FatalError.raise();
                 }
             }
-        })
+        }
+
+
+        // fail if there have been errors emitted
+        if ecx.parse_sess.span_diagnostic.err_count() > error_count_before {
+            ecx.struct_span_fatal(span, msg).emit();
+            FatalError.raise();
+        }
+
+        items
     }
 }
diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs
index 7c023fc5c9c..c5bceff4733 100644
--- a/src/libsyntax_ext/lib.rs
+++ b/src/libsyntax_ext/lib.rs
@@ -55,9 +55,7 @@ mod trace_macros;
 mod test;
 mod test_case;
 
-pub mod proc_macro_registrar;
-
-
+pub mod proc_macro_decls;
 pub mod proc_macro_impl;
 
 use rustc_data_structures::sync::Lrc;
diff --git a/src/libsyntax_ext/proc_macro_registrar.rs b/src/libsyntax_ext/proc_macro_decls.rs
index 65e175f95df..c859275ed02 100644
--- a/src/libsyntax_ext/proc_macro_registrar.rs
+++ b/src/libsyntax_ext/proc_macro_decls.rs
@@ -91,7 +91,7 @@ pub fn modify(sess: &ParseSess,
         return krate;
     }
 
-    krate.module.items.push(mk_registrar(&mut cx, &derives, &attr_macros, &bang_macros));
+    krate.module.items.push(mk_decls(&mut cx, &derives, &attr_macros, &bang_macros));
 
     krate
 }
@@ -339,19 +339,21 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> {
 //      mod $gensym {
 //          extern crate proc_macro;
 //
-//          use proc_macro::__internal::Registry;
+//          use proc_macro::bridge::client::ProcMacro;
 //
-//          #[plugin_registrar]
-//          fn registrar(registrar: &mut Registry) {
-//              registrar.register_custom_derive($name_trait1, ::$name1, &[]);
-//              registrar.register_custom_derive($name_trait2, ::$name2, &["attribute_name"]);
+//          #[rustc_proc_macro_decls]
+//          static DECLS: &[ProcMacro] = &[
+//              ProcMacro::custom_derive($name_trait1, &[], ::$name1);
+//              ProcMacro::custom_derive($name_trait2, &["attribute_name"], ::$name2);
 //              // ...
-//          }
+//          ];
 //      }
-fn mk_registrar(cx: &mut ExtCtxt,
-                custom_derives: &[ProcMacroDerive],
-                custom_attrs: &[ProcMacroDef],
-                custom_macros: &[ProcMacroDef]) -> P<ast::Item> {
+fn mk_decls(
+    cx: &mut ExtCtxt,
+    custom_derives: &[ProcMacroDerive],
+    custom_attrs: &[ProcMacroDef],
+    custom_macros: &[ProcMacroDef],
+) -> P<ast::Item> {
     let mark = Mark::fresh(Mark::root());
     mark.set_expn_info(ExpnInfo {
         call_site: DUMMY_SP,
@@ -370,75 +372,67 @@ fn mk_registrar(cx: &mut ExtCtxt,
                         Vec::new(),
                         ast::ItemKind::ExternCrate(None));
 
-    let __internal = Ident::from_str("__internal");
-    let registry = Ident::from_str("Registry");
-    let registrar = Ident::from_str("_registrar");
-    let register_custom_derive = Ident::from_str("register_custom_derive");
-    let register_attr_proc_macro = Ident::from_str("register_attr_proc_macro");
-    let register_bang_proc_macro = Ident::from_str("register_bang_proc_macro");
+    let bridge = Ident::from_str("bridge");
+    let client = Ident::from_str("client");
+    let proc_macro_ty = Ident::from_str("ProcMacro");
+    let custom_derive = Ident::from_str("custom_derive");
+    let attr = Ident::from_str("attr");
+    let bang = Ident::from_str("bang");
     let crate_kw = Ident::with_empty_ctxt(keywords::Crate.name());
-    let local_path = |cx: &mut ExtCtxt, sp: Span, name: Ident| {
-        cx.path(sp.with_ctxt(span.ctxt()), vec![crate_kw, name])
+
+    let decls = {
+        let local_path = |sp: Span, name| {
+            cx.expr_path(cx.path(sp.with_ctxt(span.ctxt()), vec![crate_kw, name]))
+        };
+        let proc_macro_ty_method_path = |method| cx.expr_path(cx.path(span, vec![
+            proc_macro, bridge, client, proc_macro_ty, method,
+        ]));
+        custom_derives.iter().map(|cd| {
+            cx.expr_call(span, proc_macro_ty_method_path(custom_derive), vec![
+                cx.expr_str(cd.span, cd.trait_name),
+                cx.expr_vec_slice(
+                    span,
+                    cd.attrs.iter().map(|&s| cx.expr_str(cd.span, s)).collect::<Vec<_>>()
+                ),
+                local_path(cd.span, cd.function_name),
+            ])
+        }).chain(custom_attrs.iter().map(|ca| {
+            cx.expr_call(span, proc_macro_ty_method_path(attr), vec![
+                cx.expr_str(ca.span, ca.function_name.name),
+                local_path(ca.span, ca.function_name),
+            ])
+        })).chain(custom_macros.iter().map(|cm| {
+            cx.expr_call(span, proc_macro_ty_method_path(bang), vec![
+                cx.expr_str(cm.span, cm.function_name.name),
+                local_path(cm.span, cm.function_name),
+            ])
+        })).collect()
     };
 
-    let mut stmts = custom_derives.iter().map(|cd| {
-        let path = local_path(cx, cd.span, cd.function_name);
-        let trait_name = cx.expr_str(cd.span, cd.trait_name);
-        let attrs = cx.expr_vec_slice(
-            span,
-            cd.attrs.iter().map(|&s| cx.expr_str(cd.span, s)).collect::<Vec<_>>()
-        );
-        let registrar = cx.expr_ident(span, registrar);
-        let ufcs_path = cx.path(span, vec![proc_macro, __internal, registry,
-                                           register_custom_derive]);
-
-        cx.stmt_expr(cx.expr_call(span, cx.expr_path(ufcs_path),
-                                  vec![registrar, trait_name, cx.expr_path(path), attrs]))
-
-    }).collect::<Vec<_>>();
-
-    stmts.extend(custom_attrs.iter().map(|ca| {
-        let name = cx.expr_str(ca.span, ca.function_name.name);
-        let path = local_path(cx, ca.span, ca.function_name);
-        let registrar = cx.expr_ident(ca.span, registrar);
-
-        let ufcs_path = cx.path(span,
-                                vec![proc_macro, __internal, registry, register_attr_proc_macro]);
-
-        cx.stmt_expr(cx.expr_call(span, cx.expr_path(ufcs_path),
-                                  vec![registrar, name, cx.expr_path(path)]))
-    }));
-
-    stmts.extend(custom_macros.iter().map(|cm| {
-        let name = cx.expr_str(cm.span, cm.function_name.name);
-        let path = local_path(cx, cm.span, cm.function_name);
-        let registrar = cx.expr_ident(cm.span, registrar);
-
-        let ufcs_path = cx.path(span,
-                                vec![proc_macro, __internal, registry, register_bang_proc_macro]);
-
-        cx.stmt_expr(cx.expr_call(span, cx.expr_path(ufcs_path),
-                                  vec![registrar, name, cx.expr_path(path)]))
-    }));
-
-    let path = cx.path(span, vec![proc_macro, __internal, registry]);
-    let registrar_path = cx.ty_path(path);
-    let arg_ty = cx.ty_rptr(span, registrar_path, None, ast::Mutability::Mutable);
-    let func = cx.item_fn(span,
-                          registrar,
-                          vec![cx.arg(span, registrar, arg_ty)],
-                          cx.ty(span, ast::TyKind::Tup(Vec::new())),
-                          cx.block(span, stmts));
-
-    let derive_registrar = cx.meta_word(span, Symbol::intern("rustc_derive_registrar"));
-    let derive_registrar = cx.attribute(span, derive_registrar);
-    let func = func.map(|mut i| {
-        i.attrs.push(derive_registrar);
+    let decls_static = cx.item_static(
+        span,
+        Ident::from_str("_DECLS"),
+        cx.ty_rptr(span,
+            cx.ty(span, ast::TyKind::Slice(
+                cx.ty_path(cx.path(span,
+                    vec![proc_macro, bridge, client, proc_macro_ty])))),
+            None, ast::Mutability::Immutable),
+        ast::Mutability::Immutable,
+        cx.expr_vec_slice(span, decls),
+    ).map(|mut i| {
+        let attr = cx.meta_word(span, Symbol::intern("rustc_proc_macro_decls"));
+        i.attrs.push(cx.attribute(span, attr));
         i.vis = respan(span, ast::VisibilityKind::Public);
         i
     });
-    let ident = ast::Ident::with_empty_ctxt(Symbol::gensym("registrar"));
-    let module = cx.item_mod(span, span, ident, Vec::new(), vec![krate, func]).map(|mut i| {
+
+    let module = cx.item_mod(
+        span,
+        span,
+        ast::Ident::with_empty_ctxt(Symbol::gensym("decls")),
+        vec![],
+        vec![krate, decls_static],
+    ).map(|mut i| {
         i.vis = respan(span, ast::VisibilityKind::Public);
         i
     });
diff --git a/src/libsyntax_ext/proc_macro_impl.rs b/src/libsyntax_ext/proc_macro_impl.rs
index ff60262055b..1f111dfcaf9 100644
--- a/src/libsyntax_ext/proc_macro_impl.rs
+++ b/src/libsyntax_ext/proc_macro_impl.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::panic;
 
 use errors::FatalError;
 
@@ -17,11 +16,13 @@ use syntax::ext::base::*;
 use syntax::tokenstream::TokenStream;
 use syntax::ext::base;
 
-use proc_macro::TokenStream as TsShim;
-use proc_macro::__internal;
+pub const EXEC_STRATEGY: ::proc_macro::bridge::server::SameThread =
+    ::proc_macro::bridge::server::SameThread;
 
 pub struct AttrProcMacro {
-    pub inner: fn(TsShim, TsShim) -> TsShim,
+    pub client: ::proc_macro::bridge::client::Client<
+        fn(::proc_macro::TokenStream, ::proc_macro::TokenStream) -> ::proc_macro::TokenStream,
+    >,
 }
 
 impl base::AttrProcMacro for AttrProcMacro {
@@ -31,22 +32,17 @@ impl base::AttrProcMacro for AttrProcMacro {
                    annotation: TokenStream,
                    annotated: TokenStream)
                    -> TokenStream {
-        let annotation = __internal::token_stream_wrap(annotation);
-        let annotated = __internal::token_stream_wrap(annotated);
-
-        let res = __internal::set_sess(ecx, || {
-            panic::catch_unwind(panic::AssertUnwindSafe(|| (self.inner)(annotation, annotated)))
+        let server = ::proc_macro::rustc::Rustc;
+        let res = ::proc_macro::__internal::set_sess(ecx, || {
+            self.client.run(&EXEC_STRATEGY, server, annotation, annotated)
         });
 
         match res {
-            Ok(stream) => __internal::token_stream_inner(stream),
+            Ok(stream) => stream,
             Err(e) => {
                 let msg = "custom attribute panicked";
                 let mut err = ecx.struct_span_fatal(span, msg);
-                if let Some(s) = e.downcast_ref::<String>() {
-                    err.help(&format!("message: {}", s));
-                }
-                if let Some(s) = e.downcast_ref::<&'static str>() {
+                if let Some(s) = e.as_str() {
                     err.help(&format!("message: {}", s));
                 }
 
@@ -58,7 +54,9 @@ impl base::AttrProcMacro for AttrProcMacro {
 }
 
 pub struct BangProcMacro {
-    pub inner: fn(TsShim) -> TsShim,
+    pub client: ::proc_macro::bridge::client::Client<
+        fn(::proc_macro::TokenStream) -> ::proc_macro::TokenStream,
+    >,
 }
 
 impl base::ProcMacro for BangProcMacro {
@@ -67,21 +65,17 @@ impl base::ProcMacro for BangProcMacro {
                    span: Span,
                    input: TokenStream)
                    -> TokenStream {
-        let input = __internal::token_stream_wrap(input);
-
-        let res = __internal::set_sess(ecx, || {
-            panic::catch_unwind(panic::AssertUnwindSafe(|| (self.inner)(input)))
+        let server = ::proc_macro::rustc::Rustc;
+        let res = ::proc_macro::__internal::set_sess(ecx, || {
+            self.client.run(&EXEC_STRATEGY, server, input)
         });
 
         match res {
-            Ok(stream) => __internal::token_stream_inner(stream),
+            Ok(stream) => stream,
             Err(e) => {
                 let msg = "proc macro panicked";
                 let mut err = ecx.struct_span_fatal(span, msg);
-                if let Some(s) = e.downcast_ref::<String>() {
-                    err.help(&format!("message: {}", s));
-                }
-                if let Some(s) = e.downcast_ref::<&'static str>() {
+                if let Some(s) = e.as_str() {
                     err.help(&format!("message: {}", s));
                 }