Skip to content

Commit

Permalink
rustc: Rename rustc_macro to proc_macro
Browse files Browse the repository at this point in the history
This commit blanket renames the `rustc_macro` infrastructure to `proc_macro`,
which reflects the general consensus of #35900. A follow up PR to Cargo will be
required to purge the `rustc-macro` name as well.
  • Loading branch information
alexcrichton committed Oct 6, 2016
1 parent 7a26aec commit 2148bdf
Show file tree
Hide file tree
Showing 86 changed files with 612 additions and 614 deletions.
16 changes: 8 additions & 8 deletions mk/crates.mk
Expand Up @@ -59,8 +59,8 @@ RUSTC_CRATES := rustc rustc_typeck rustc_mir rustc_borrowck rustc_resolve rustc_
rustc_trans rustc_back rustc_llvm rustc_privacy rustc_lint \
rustc_data_structures rustc_platform_intrinsics rustc_errors \
rustc_plugin rustc_metadata rustc_passes rustc_save_analysis \
rustc_const_eval rustc_const_math rustc_incremental rustc_macro
HOST_CRATES := syntax syntax_ext proc_macro syntax_pos $(RUSTC_CRATES) rustdoc fmt_macros \
rustc_const_eval rustc_const_math rustc_incremental proc_macro
HOST_CRATES := syntax syntax_ext proc_macro_plugin syntax_pos $(RUSTC_CRATES) rustdoc fmt_macros \
flate arena graphviz log serialize
TOOLS := compiletest rustdoc rustc rustbook error_index_generator

Expand Down Expand Up @@ -101,8 +101,8 @@ DEPS_term := std
DEPS_test := std getopts term native:rust_test_helpers

DEPS_syntax := std term serialize log arena libc rustc_bitflags rustc_unicode rustc_errors syntax_pos
DEPS_syntax_ext := syntax syntax_pos rustc_errors fmt_macros rustc_macro
DEPS_proc_macro := syntax syntax_pos rustc_plugin log
DEPS_syntax_ext := syntax syntax_pos rustc_errors fmt_macros proc_macro
DEPS_proc_macro_plugin := syntax syntax_pos rustc_plugin log
DEPS_syntax_pos := serialize

DEPS_rustc_const_math := std syntax log serialize
Expand All @@ -118,15 +118,15 @@ DEPS_rustc_data_structures := std log serialize libc
DEPS_rustc_driver := arena flate getopts graphviz libc rustc rustc_back rustc_borrowck \
rustc_typeck rustc_mir rustc_resolve log syntax serialize rustc_llvm \
rustc_trans rustc_privacy rustc_lint rustc_plugin \
rustc_metadata syntax_ext proc_macro \
rustc_metadata syntax_ext proc_macro_plugin \
rustc_passes rustc_save_analysis rustc_const_eval \
rustc_incremental syntax_pos rustc_errors rustc_macro
rustc_incremental syntax_pos rustc_errors proc_macro
DEPS_rustc_errors := log libc serialize syntax_pos
DEPS_rustc_lint := rustc log syntax syntax_pos rustc_const_eval
DEPS_rustc_llvm := native:rustllvm libc std rustc_bitflags
DEPS_rustc_macro := std syntax
DEPS_proc_macro := std syntax
DEPS_rustc_metadata := rustc syntax syntax_pos rustc_errors rustc_const_math \
rustc_macro syntax_ext
proc_macro syntax_ext
DEPS_rustc_passes := syntax syntax_pos rustc core rustc_const_eval rustc_errors
DEPS_rustc_mir := rustc syntax syntax_pos rustc_const_math rustc_const_eval rustc_bitflags
DEPS_rustc_resolve := arena rustc log syntax syntax_pos rustc_errors
Expand Down
4 changes: 0 additions & 4 deletions src/libproc_macro/Cargo.toml
Expand Up @@ -4,12 +4,8 @@ name = "proc_macro"
version = "0.0.0"

[lib]
name = "proc_macro"
path = "lib.rs"
crate-type = ["dylib"]

[dependencies]
log = { path = "../liblog" }
rustc_plugin = { path = "../librustc_plugin" }
syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" }
250 changes: 140 additions & 110 deletions src/libproc_macro/lib.rs
Expand Up @@ -8,130 +8,160 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! # Proc_Macro
//! A support library for macro authors when defining new macros.
//!
//! A library for procedural macro writers.
//! This library, provided by the standard distribution, provides the types
//! consumed in the interfaces of procedurally defined macro definitions.
//! Currently the primary use of this crate is to provide the ability to define
//! new custom derive modes through `#[proc_macro_derive]`.
//!
//! ## Usage
//! This package provides the `qquote!` macro for syntax creation, and the prelude
//! (at libproc_macro::prelude) provides a number of operations:
//! - `concat`, for concatenating two TokenStreams.
//! - `ident_eq`, for checking if two identifiers are equal regardless of syntax context.
//! - `str_to_token_ident`, for converting an `&str` into a Token.
//! - `keyword_to_token_delim`, for converting a `parse::token::keywords::Keyword` into a
//! Token.
//! - `build_delimited`, for creating a new TokenStream from an existing one and a delimiter
//! by wrapping the TokenStream in the delimiter.
//! - `build_bracket_delimited`, `build_brace_delimited`, and `build_paren_delimited`, for
//! easing the above.
//! - `build_empty_args`, which returns a TokenStream containing `()`.
//! - `lex`, which takes an `&str` and returns the TokenStream it represents.
//! Added recently as part of [RFC 1681] this crate is currently *unstable* and
//! requires the `#![feature(proc_macro_lib)]` directive to use.
//!
//! The `qquote!` macro also imports `syntax::ext::proc_macro_shim::prelude::*`, so you
//! will need to `extern crate syntax` for usage. (This is a temporary solution until more
//! of the external API in libproc_macro is stabilized to support the token construction
//! operations that the qausiquoter relies on.) The shim file also provides additional
//! operations, such as `build_block_emitter` (as used in the `cond` example below).
//!
//! ## TokenStreams
//!
//! TokenStreams serve as the basis of the macro system. They are, in essence, vectors of
//! TokenTrees, where indexing treats delimited values as a single term. That is, the term
//! `even(a+c) && even(b)` will be indexibly encoded as `even | (a+c) | even | (b)` where,
//! in reality, `(a+c)` is actually a decorated pointer to `a | + | c`.
//!
//! If a user has a TokenStream that is a single, delimited value, they can use
//! `maybe_delimited` to destruct it and receive the internal vector as a new TokenStream
//! as:
//! ```
//! `(a+c)`.maybe_delimited() ~> Some(a | + | c)`
//! ```
//!
//! Check the TokenStream documentation for more information; the structure also provides
//! cheap concatenation and slicing.
//!
//! ## Quasiquotation
//!
//! The quasiquoter creates output that, when run, constructs the tokenstream specified as
//! input. For example, `qquote!(5 + 5)` will produce a program, that, when run, will
//! construct the TokenStream `5 | + | 5`.
//!
//! ### Unquoting
//!
//! Unquoting is currently done as `unquote`, and works by taking the single next
//! TokenTree in the TokenStream as the unquoted term. Ergonomically, `unquote(foo)` works
//! fine, but `unquote foo` is also supported.
//!
//! A simple example might be:
//!
//!```
//!fn double(tmp: TokenStream) -> TokenStream {
//! qquote!(unquote(tmp) * 2)
//!}
//!```
//!
//! ### Large Example: Implementing Scheme's `cond`
//!
//! Below is the full implementation of Scheme's `cond` operator.
//!
//! ```
//! fn cond_rec(input: TokenStream) -> TokenStream {
//! if input.is_empty() { return quote!(); }
//!
//! let next = input.slice(0..1);
//! let rest = input.slice_from(1..);
//!
//! let clause : TokenStream = match next.maybe_delimited() {
//! Some(ts) => ts,
//! _ => panic!("Invalid input"),
//! };
//!
//! // clause is ([test]) [rhs]
//! if clause.len() < 2 { panic!("Invalid macro usage in cond: {:?}", clause) }
//!
//! let test: TokenStream = clause.slice(0..1);
//! let rhs: TokenStream = clause.slice_from(1..);
//!
//! if ident_eq(&test[0], str_to_ident("else")) || rest.is_empty() {
//! quote!({unquote(rhs)})
//! } else {
//! quote!({if unquote(test) { unquote(rhs) } else { cond!(unquote(rest)) } })
//! }
//! }
//! ```
//! [RFC 1681]: https://github.com/rust-lang/rfcs/blob/master/text/1681-macros-1.1.md
//!
//! Note that this crate is intentionally very bare-bones currently. The main
//! type, `TokenStream`, only supports `fmt::Display` and `FromStr`
//! implementations, indicating that it can only go to and come from a string.
//! This functionality is intended to be expanded over time as more surface
//! area for macro authors is stabilized.

#![crate_name = "proc_macro"]
#![unstable(feature = "rustc_private", issue = "27812")]
#![feature(plugin_registrar)]
#![crate_type = "dylib"]
#![unstable(feature = "proc_macro_lib", issue = "27812")]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/")]
#![crate_type = "dylib"]
#![cfg_attr(not(stage0), deny(warnings))]
#![deny(missing_docs)]

#![feature(staged_api)]
#![feature(rustc_diagnostic_macros)]
#![feature(rustc_private)]
#![feature(staged_api)]
#![feature(lang_items)]

extern crate rustc_plugin;
extern crate syntax;
extern crate syntax_pos;
#[macro_use] extern crate log;

mod qquote;
pub mod build;
pub mod parse;
pub mod prelude;
use qquote::qquote;
use std::fmt;
use std::str::FromStr;

use syntax::ast;
use syntax::parse;
use syntax::ptr::P;

/// The main type provided by this crate, representing an abstract stream of
/// tokens.
///
/// This is both the input and output of `#[proc_macro_derive]` definitions.
/// Currently it's required to be a list of valid Rust items, but this
/// restriction may be lifted in the future.
///
/// The API of this type is intentionally bare-bones, but it'll be expanded over
/// time!
pub struct TokenStream {
inner: Vec<P<ast::Item>>,
}

/// Error returned from `TokenStream::from_str`.
#[derive(Debug)]
pub struct LexError {
_inner: (),
}

/// Permanently unstable internal implementation details of this crate. This
/// should not be used.
///
/// These methods are used by the rest of the compiler to generate instances of
/// `TokenStream` to hand to macro definitions, as well as consume the output.
///
/// Note that this module is also intentionally separate from the rest of the
/// crate. This allows the `#[unstable]` directive below to naturally apply to
/// all of the contents.
#[unstable(feature = "proc_macro_internals", issue = "27812")]
#[doc(hidden)]
pub mod __internal {
use std::cell::Cell;

use syntax::ast;
use syntax::ptr::P;
use syntax::parse::ParseSess;
use super::TokenStream;

pub fn new_token_stream(item: P<ast::Item>) -> TokenStream {
TokenStream { inner: vec![item] }
}

use rustc_plugin::Registry;
pub fn token_stream_items(stream: TokenStream) -> Vec<P<ast::Item>> {
stream.inner
}

// ____________________________________________________________________________________________
// Main macro definition
pub trait Registry {
fn register_custom_derive(&mut self,
trait_name: &str,
expand: fn(TokenStream) -> TokenStream);
}

// Emulate scoped_thread_local!() here essentially
thread_local! {
static CURRENT_SESS: Cell<*const ParseSess> = Cell::new(0 as *const _);
}

pub fn set_parse_sess<F, R>(sess: &ParseSess, f: F) -> R
where F: FnOnce() -> R
{
struct Reset { prev: *const ParseSess }

impl Drop for Reset {
fn drop(&mut self) {
CURRENT_SESS.with(|p| p.set(self.prev));
}
}

CURRENT_SESS.with(|p| {
let _reset = Reset { prev: p.get() };
p.set(sess);
f()
})
}

pub fn with_parse_sess<F, R>(f: F) -> R
where F: FnOnce(&ParseSess) -> R
{
let p = CURRENT_SESS.with(|p| p.get());
assert!(!p.is_null());
f(unsafe { &*p })
}
}

impl FromStr for TokenStream {
type Err = LexError;

fn from_str(src: &str) -> Result<TokenStream, LexError> {
__internal::with_parse_sess(|sess| {
let src = src.to_string();
let cfg = Vec::new();
let name = "<proc-macro source code>".to_string();
let mut parser = parse::new_parser_from_source_str(sess, cfg, name,
src);
let mut ret = TokenStream { inner: Vec::new() };
loop {
match parser.parse_item() {
Ok(Some(item)) => ret.inner.push(item),
Ok(None) => return Ok(ret),
Err(mut err) => {
err.cancel();
return Err(LexError { _inner: () })
}
}
}
})
}
}

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
reg.register_macro("qquote", qquote);
impl fmt::Display for TokenStream {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for item in self.inner.iter() {
let item = syntax::print::pprust::item_to_string(item);
try!(f.write_str(&item));
try!(f.write_str("\n"));
}
Ok(())
}
}
@@ -1,12 +1,14 @@
[package]
authors = ["The Rust Project Developers"]
name = "rustc_macro"
name = "proc_macro_plugin"
version = "0.0.0"

[lib]
name = "rustc_macro"
path = "lib.rs"
crate-type = ["dylib"]

[dependencies]
log = { path = "../liblog" }
rustc_plugin = { path = "../librustc_plugin" }
syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" }
File renamed without changes.

0 comments on commit 2148bdf

Please sign in to comment.