about summary refs log tree commit diff
path: root/src/libproc_macro
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2016-10-03 09:49:39 -0700
committerAlex Crichton <alex@alexcrichton.com>2016-10-06 11:07:23 -0700
commit2148bdfcc7ea7b9614d8cbe596cbe7bb75b57cd1 (patch)
tree4a88c4f26d3a898cb9ac26aa6a06fd074253d5a3 /src/libproc_macro
parent7a26aeca77bcf334747eddb630e3b9475149b7f5 (diff)
downloadrust-2148bdfcc7ea7b9614d8cbe596cbe7bb75b57cd1.tar.gz
rust-2148bdfcc7ea7b9614d8cbe596cbe7bb75b57cd1.zip
rustc: Rename rustc_macro to proc_macro
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.
Diffstat (limited to 'src/libproc_macro')
-rw-r--r--src/libproc_macro/Cargo.toml4
-rw-r--r--src/libproc_macro/build.rs89
-rw-r--r--src/libproc_macro/lib.rs250
-rw-r--r--src/libproc_macro/parse.rs26
-rw-r--r--src/libproc_macro/prelude.rs12
-rw-r--r--src/libproc_macro/qquote.rs470
6 files changed, 140 insertions, 711 deletions
diff --git a/src/libproc_macro/Cargo.toml b/src/libproc_macro/Cargo.toml
index 99fb1d65cda..7ce65d0fe4d 100644
--- a/src/libproc_macro/Cargo.toml
+++ b/src/libproc_macro/Cargo.toml
@@ -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" }
diff --git a/src/libproc_macro/build.rs b/src/libproc_macro/build.rs
deleted file mode 100644
index 7b7590b863b..00000000000
--- a/src/libproc_macro/build.rs
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-extern crate syntax;
-extern crate syntax_pos;
-
-use syntax::ast::Ident;
-use syntax::codemap::DUMMY_SP;
-use syntax::parse::token::{self, Token, keywords, str_to_ident};
-use syntax::tokenstream::{self, TokenTree, TokenStream};
-use std::rc::Rc;
-
-/// A wrapper around `TokenStream::concat` to avoid extra namespace specification and
-/// provide TokenStream concatenation as a generic operator.
-pub fn concat(ts1: TokenStream, ts2: TokenStream) -> TokenStream {
-    TokenStream::concat(ts1, ts2)
-}
-
-/// Checks if two identifiers have the same name, disregarding context. This allows us to
-/// fake 'reserved' keywords.
-// FIXME We really want `free-identifier-=?` (a la Dybvig 1993). von Tander 2007 is
-// probably the easiest way to do that.
-pub fn ident_eq(tident: &TokenTree, id: Ident) -> bool {
-    let tid = match *tident {
-        TokenTree::Token(_, Token::Ident(ref id)) => id,
-        _ => {
-            return false;
-        }
-    };
-
-    tid.name == id.name
-}
-
-// ____________________________________________________________________________________________
-// Conversion operators
-
-/// Convert a `&str` into a Token.
-pub fn str_to_token_ident(s: &str) -> Token {
-    Token::Ident(str_to_ident(s))
-}
-
-/// Converts a keyword (from `syntax::parse::token::keywords`) into a Token that
-/// corresponds to it.
-pub fn keyword_to_token_ident(kw: keywords::Keyword) -> Token {
-    Token::Ident(str_to_ident(&kw.name().as_str()[..]))
-}
-
-// ____________________________________________________________________________________________
-// Build Procedures
-
-/// Generically takes a `ts` and delimiter and returns `ts` delimited by the specified
-/// delimiter.
-pub fn build_delimited(ts: TokenStream, delim: token::DelimToken) -> TokenStream {
-    let tts = ts.to_tts();
-    TokenStream::from_tts(vec![TokenTree::Delimited(DUMMY_SP,
-                                                    Rc::new(tokenstream::Delimited {
-                                                        delim: delim,
-                                                        open_span: DUMMY_SP,
-                                                        tts: tts,
-                                                        close_span: DUMMY_SP,
-                                                    }))])
-}
-
-/// Takes `ts` and returns `[ts]`.
-pub fn build_bracket_delimited(ts: TokenStream) -> TokenStream {
-    build_delimited(ts, token::DelimToken::Bracket)
-}
-
-/// Takes `ts` and returns `{ts}`.
-pub fn build_brace_delimited(ts: TokenStream) -> TokenStream {
-    build_delimited(ts, token::DelimToken::Brace)
-}
-
-/// Takes `ts` and returns `(ts)`.
-pub fn build_paren_delimited(ts: TokenStream) -> TokenStream {
-    build_delimited(ts, token::DelimToken::Paren)
-}
-
-/// Constructs `()`.
-pub fn build_empty_args() -> TokenStream {
-    build_paren_delimited(TokenStream::mk_empty())
-}
diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs
index 9e25cb88e01..4b9b92fb3bb 100644
--- a/src/libproc_macro/lib.rs
+++ b/src/libproc_macro/lib.rs
@@ -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(())
+    }
 }
diff --git a/src/libproc_macro/parse.rs b/src/libproc_macro/parse.rs
deleted file mode 100644
index 9af8a68cdcf..00000000000
--- a/src/libproc_macro/parse.rs
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Parsing utilities for writing procedural macros.
-
-extern crate syntax;
-
-use syntax::parse::{ParseSess, filemap_to_tts};
-use syntax::tokenstream::TokenStream;
-
-/// Map a string to tts, using a made-up filename. For example, `lex(15)` will return a
-/// TokenStream containing the literal 15.
-pub fn lex(source_str: &str) -> TokenStream {
-    let ps = ParseSess::new();
-    TokenStream::from_tts(filemap_to_tts(&ps,
-                                         ps.codemap().new_filemap("procmacro_lex".to_string(),
-                                                                  None,
-                                                                  source_str.to_owned())))
-}
diff --git a/src/libproc_macro/prelude.rs b/src/libproc_macro/prelude.rs
deleted file mode 100644
index 4c0c8ba6c66..00000000000
--- a/src/libproc_macro/prelude.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-pub use build::*;
-pub use parse::*;
diff --git a/src/libproc_macro/qquote.rs b/src/libproc_macro/qquote.rs
deleted file mode 100644
index 67d0c77b00d..00000000000
--- a/src/libproc_macro/qquote.rs
+++ /dev/null
@@ -1,470 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! # Quasiquoter
-//! This file contains the implementation internals of the quasiquoter provided by `quote!`.
-//!
-//! ## Ouput
-//! The quasiquoter produces output of the form:
-//! let tmp0 = ...;
-//! let tmp1 = ...;
-//! ...
-//! concat(from_tokens(...), concat(...))
-//!
-//! To the more explicit, the quasiquoter produces a series of bindings that each
-//! construct TokenStreams via constructing Tokens and using `from_tokens`, ultimately
-//! invoking `concat` on these bindings (and inlined expressions) to construct a
-//! TokenStream that resembles the output syntax.
-//!
-
-extern crate rustc_plugin;
-extern crate syntax;
-extern crate syntax_pos;
-
-use build::*;
-use parse::lex;
-use qquote::int_build::*;
-
-use syntax::ast::Ident;
-use syntax::codemap::Span;
-use syntax::ext::base::*;
-use syntax::ext::base;
-use syntax::ext::proc_macro_shim::build_block_emitter;
-use syntax::parse::token::{self, Token, gensym_ident, str_to_ident};
-use syntax::print::pprust;
-use syntax::tokenstream::{TokenTree, TokenStream};
-
-// ____________________________________________________________________________________________
-// Main definition
-/// The user should use the macro, not this procedure.
-pub fn qquote<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[TokenTree])
-                   -> Box<base::MacResult + 'cx> {
-
-    debug!("\nTTs in: {:?}\n", pprust::tts_to_string(&tts[..]));
-    let output = qquoter(cx, TokenStream::from_tts(tts.clone().to_owned()));
-    debug!("\nQQ out: {}\n", pprust::tts_to_string(&output.to_tts()[..]));
-    let imports = concat(lex("use syntax::ext::proc_macro_shim::prelude::*;"),
-                         lex("use proc_macro::prelude::*;"));
-    build_block_emitter(cx, sp, build_brace_delimited(concat(imports, output)))
-}
-
-// ____________________________________________________________________________________________
-// Datatype Definitions
-
-#[derive(Debug)]
-struct QDelimited {
-    delim: token::DelimToken,
-    open_span: Span,
-    tts: Vec<QTT>,
-    close_span: Span,
-}
-
-#[derive(Debug)]
-enum QTT {
-    TT(TokenTree),
-    QDL(QDelimited),
-    QIdent(TokenTree),
-}
-
-type Bindings = Vec<(Ident, TokenStream)>;
-
-// ____________________________________________________________________________________________
-// Quasiquoter Algorithm
-// This algorithm works as follows:
-// Input: TokenStream
-// 1. Walk the TokenStream, gathering up the unquoted expressions and marking them separately.
-// 2. Hoist any unquoted term into its own let-binding via a gensym'd identifier
-// 3. Convert the body from a `complex expression` into a simplified one via `convert_complex_tts
-// 4. Stitch everything together with `concat`.
-fn qquoter<'cx>(cx: &'cx mut ExtCtxt, ts: TokenStream) -> TokenStream {
-    if ts.is_empty() {
-        return lex("TokenStream::mk_empty()");
-    }
-    let qq_res = qquote_iter(cx, 0, ts);
-    let mut bindings = qq_res.0;
-    let body = qq_res.1;
-    let mut cct_res = convert_complex_tts(cx, body);
-
-    bindings.append(&mut cct_res.0);
-
-    if bindings.is_empty() {
-        cct_res.1
-    } else {
-        debug!("BINDINGS");
-        for b in bindings.clone() {
-            debug!("{:?} = {}", b.0, pprust::tts_to_string(&b.1.to_tts()[..]));
-        }
-        TokenStream::concat(unravel(bindings), cct_res.1)
-   }
-}
-
-fn qquote_iter<'cx>(cx: &'cx mut ExtCtxt, depth: i64, ts: TokenStream) -> (Bindings, Vec<QTT>) {
-    let mut depth = depth;
-    let mut bindings: Bindings = Vec::new();
-    let mut output: Vec<QTT> = Vec::new();
-
-    let mut iter = ts.iter();
-
-    loop {
-        let next = iter.next();
-        if next.is_none() {
-            break;
-        }
-        let next = next.unwrap().clone();
-        match next {
-            TokenTree::Token(_, Token::Ident(id)) if is_unquote(id) => {
-                if depth == 0 {
-                    let exp = iter.next();
-                    if exp.is_none() {
-                        break;
-                    } // produce an error or something first
-                    let exp = vec![exp.unwrap().to_owned()];
-                    debug!("RHS: {:?}", exp.clone());
-                    let new_id = gensym_ident("tmp");
-                    debug!("RHS TS: {:?}", TokenStream::from_tts(exp.clone()));
-                    debug!("RHS TS TT: {:?}", TokenStream::from_tts(exp.clone()).to_vec());
-                    bindings.push((new_id, TokenStream::from_tts(exp)));
-                    debug!("BINDINGS");
-                    for b in bindings.clone() {
-                        debug!("{:?} = {}", b.0, pprust::tts_to_string(&b.1.to_tts()[..]));
-                    }
-                    output.push(QTT::QIdent(as_tt(Token::Ident(new_id.clone()))));
-                } else {
-                    depth = depth - 1;
-                    output.push(QTT::TT(next.clone()));
-                }
-            }
-            TokenTree::Token(_, Token::Ident(id)) if is_qquote(id) => {
-                depth = depth + 1;
-            }
-            TokenTree::Delimited(_, ref dl) => {
-                let br = qquote_iter(cx, depth, TokenStream::from_tts(dl.tts.clone().to_owned()));
-                let mut bind_ = br.0;
-                let res_ = br.1;
-                bindings.append(&mut bind_);
-
-                let new_dl = QDelimited {
-                    delim: dl.delim,
-                    open_span: dl.open_span,
-                    tts: res_,
-                    close_span: dl.close_span,
-                };
-
-                output.push(QTT::QDL(new_dl));
-            }
-            t => {
-                output.push(QTT::TT(t));
-            }
-        }
-    }
-
-    (bindings, output)
-}
-
-// ____________________________________________________________________________________________
-// Turns QQTs into a TokenStream and some Bindings.
-/// Construct a chain of concatenations.
-fn unravel_concats(tss: Vec<TokenStream>) -> TokenStream {
-    let mut pushes: Vec<TokenStream> =
-        tss.into_iter().filter(|&ref ts| !ts.is_empty()).collect();
-    let mut output = match pushes.pop() {
-        Some(ts) => ts,
-        None => {
-            return TokenStream::mk_empty();
-        }
-    };
-
-    while let Some(ts) = pushes.pop() {
-        output = build_fn_call(str_to_ident("concat"),
-                               concat(concat(ts,
-                                             from_tokens(vec![Token::Comma])),
-                                      output));
-    }
-    output
-}
-
-/// This converts the vector of QTTs into a seet of Bindings for construction and the main
-/// body as a TokenStream.
-fn convert_complex_tts<'cx>(cx: &'cx mut ExtCtxt, tts: Vec<QTT>) -> (Bindings, TokenStream) {
-    let mut pushes: Vec<TokenStream> = Vec::new();
-    let mut bindings: Bindings = Vec::new();
-
-    let mut iter = tts.into_iter();
-
-    loop {
-        let next = iter.next();
-        if next.is_none() {
-            break;
-        }
-        let next = next.unwrap();
-        match next {
-            QTT::TT(TokenTree::Token(_, t)) => {
-                let token_out = emit_token(t);
-                pushes.push(token_out);
-            }
-            // FIXME handle sequence repetition tokens
-            QTT::QDL(qdl) => {
-                debug!("  QDL: {:?} ", qdl.tts);
-                let new_id = gensym_ident("qdl_tmp");
-                let mut cct_rec = convert_complex_tts(cx, qdl.tts);
-                bindings.append(&mut cct_rec.0);
-                bindings.push((new_id, cct_rec.1));
-
-                let sep = build_delim_tok(qdl.delim);
-
-                pushes.push(build_mod_call(vec![str_to_ident("proc_macro"),
-                                               str_to_ident("build"),
-                                               str_to_ident("build_delimited")],
-                                          concat(from_tokens(vec![Token::Ident(new_id)]),
-                                                 concat(lex(","), sep))));
-            }
-            QTT::QIdent(t) => {
-                pushes.push(TokenStream::from_tts(vec![t]));
-                pushes.push(TokenStream::mk_empty());
-            }
-            _ => panic!("Unhandled case!"),
-        }
-
-    }
-
-    (bindings, unravel_concats(pushes))
-}
-
-// ____________________________________________________________________________________________
-// Utilities
-
-/// Unravels Bindings into a TokenStream of `let` declarations.
-fn unravel(binds: Bindings) -> TokenStream {
-    let mut output = TokenStream::mk_empty();
-
-    for b in binds {
-        output = concat(output, build_let(b.0, b.1));
-    }
-
-    output
-}
-
-/// Checks if the Ident is `unquote`.
-fn is_unquote(id: Ident) -> bool {
-    let qq = str_to_ident("unquote");
-    id.name == qq.name  // We disregard context; unquote is _reserved_
-}
-
-/// Checks if the Ident is `quote`.
-fn is_qquote(id: Ident) -> bool {
-    let qq = str_to_ident("qquote");
-    id.name == qq.name  // We disregard context; qquote is _reserved_
-}
-
-mod int_build {
-    extern crate syntax;
-    extern crate syntax_pos;
-
-    use parse::*;
-    use build::*;
-
-    use syntax::ast::{self, Ident};
-    use syntax::codemap::{DUMMY_SP};
-    use syntax::parse::token::{self, Token, keywords, str_to_ident};
-    use syntax::tokenstream::{TokenTree, TokenStream};
-
-    // ____________________________________________________________________________________________
-    // Emitters
-
-    pub fn emit_token(t: Token) -> TokenStream {
-        concat(lex("TokenStream::from_tokens"),
-               build_paren_delimited(build_vec(build_token_tt(t))))
-    }
-
-    pub fn emit_lit(l: token::Lit, n: Option<ast::Name>) -> TokenStream {
-        let suf = match n {
-            Some(n) => format!("Some(ast::Name({}))", n.0),
-            None => "None".to_string(),
-        };
-
-        let lit = match l {
-            token::Lit::Byte(n) => format!("Lit::Byte(token::intern(\"{}\"))", n.to_string()),
-            token::Lit::Char(n) => format!("Lit::Char(token::intern(\"{}\"))", n.to_string()),
-            token::Lit::Integer(n) => format!("Lit::Integer(token::intern(\"{}\"))", n.to_string()),
-            token::Lit::Float(n) => format!("Lit::Float(token::intern(\"{}\"))", n.to_string()),
-            token::Lit::Str_(n) => format!("Lit::Str_(token::intern(\"{}\"))", n.to_string()),
-            token::Lit::ByteStr(n) => format!("Lit::ByteStr(token::intern(\"{}\"))", n.to_string()),
-            _ => panic!("Unsupported literal"),
-        };
-
-        let res = format!("Token::Literal({},{})", lit, suf);
-        debug!("{}", res);
-        lex(&res)
-    }
-
-    // ____________________________________________________________________________________________
-    // Token Builders
-
-    pub fn build_binop_tok(bot: token::BinOpToken) -> TokenStream {
-        match bot {
-            token::BinOpToken::Plus => lex("Token::BinOp(BinOpToken::Plus)"),
-            token::BinOpToken::Minus => lex("Token::BinOp(BinOpToken::Minus)"),
-            token::BinOpToken::Star => lex("Token::BinOp(BinOpToken::Star)"),
-            token::BinOpToken::Slash => lex("Token::BinOp(BinOpToken::Slash)"),
-            token::BinOpToken::Percent => lex("Token::BinOp(BinOpToken::Percent)"),
-            token::BinOpToken::Caret => lex("Token::BinOp(BinOpToken::Caret)"),
-            token::BinOpToken::And => lex("Token::BinOp(BinOpToken::And)"),
-            token::BinOpToken::Or => lex("Token::BinOp(BinOpToken::Or)"),
-            token::BinOpToken::Shl => lex("Token::BinOp(BinOpToken::Shl)"),
-            token::BinOpToken::Shr => lex("Token::BinOp(BinOpToken::Shr)"),
-        }
-    }
-
-    pub fn build_binopeq_tok(bot: token::BinOpToken) -> TokenStream {
-        match bot {
-            token::BinOpToken::Plus => lex("Token::BinOpEq(BinOpToken::Plus)"),
-            token::BinOpToken::Minus => lex("Token::BinOpEq(BinOpToken::Minus)"),
-            token::BinOpToken::Star => lex("Token::BinOpEq(BinOpToken::Star)"),
-            token::BinOpToken::Slash => lex("Token::BinOpEq(BinOpToken::Slash)"),
-            token::BinOpToken::Percent => lex("Token::BinOpEq(BinOpToken::Percent)"),
-            token::BinOpToken::Caret => lex("Token::BinOpEq(BinOpToken::Caret)"),
-            token::BinOpToken::And => lex("Token::BinOpEq(BinOpToken::And)"),
-            token::BinOpToken::Or => lex("Token::BinOpEq(BinOpToken::Or)"),
-            token::BinOpToken::Shl => lex("Token::BinOpEq(BinOpToken::Shl)"),
-            token::BinOpToken::Shr => lex("Token::BinOpEq(BinOpToken::Shr)"),
-        }
-    }
-
-    pub fn build_delim_tok(dt: token::DelimToken) -> TokenStream {
-        match dt {
-            token::DelimToken::Paren => lex("DelimToken::Paren"),
-            token::DelimToken::Bracket => lex("DelimToken::Bracket"),
-            token::DelimToken::Brace => lex("DelimToken::Brace"),
-            token::DelimToken::NoDelim => lex("DelimToken::NoDelim"),
-        }
-    }
-
-    pub fn build_token_tt(t: Token) -> TokenStream {
-        match t {
-            Token::Eq => lex("Token::Eq"),
-            Token::Lt => lex("Token::Lt"),
-            Token::Le => lex("Token::Le"),
-            Token::EqEq => lex("Token::EqEq"),
-            Token::Ne => lex("Token::Ne"),
-            Token::Ge => lex("Token::Ge"),
-            Token::Gt => lex("Token::Gt"),
-            Token::AndAnd => lex("Token::AndAnd"),
-            Token::OrOr => lex("Token::OrOr"),
-            Token::Not => lex("Token::Not"),
-            Token::Tilde => lex("Token::Tilde"),
-            Token::BinOp(tok) => build_binop_tok(tok),
-            Token::BinOpEq(tok) => build_binopeq_tok(tok),
-            Token::At => lex("Token::At"),
-            Token::Dot => lex("Token::Dot"),
-            Token::DotDot => lex("Token::DotDot"),
-            Token::DotDotDot => lex("Token::DotDotDot"),
-            Token::Comma => lex("Token::Comma"),
-            Token::Semi => lex("Token::Semi"),
-            Token::Colon => lex("Token::Colon"),
-            Token::ModSep => lex("Token::ModSep"),
-            Token::RArrow => lex("Token::RArrow"),
-            Token::LArrow => lex("Token::LArrow"),
-            Token::FatArrow => lex("Token::FatArrow"),
-            Token::Pound => lex("Token::Pound"),
-            Token::Dollar => lex("Token::Dollar"),
-            Token::Question => lex("Token::Question"),
-            Token::OpenDelim(dt) => {
-                match dt {
-                    token::DelimToken::Paren => lex("Token::OpenDelim(DelimToken::Paren)"),
-                    token::DelimToken::Bracket => lex("Token::OpenDelim(DelimToken::Bracket)"),
-                    token::DelimToken::Brace => lex("Token::OpenDelim(DelimToken::Brace)"),
-                    token::DelimToken::NoDelim => lex("DelimToken::NoDelim"),
-                }
-            }
-            Token::CloseDelim(dt) => {
-                match dt {
-                    token::DelimToken::Paren => lex("Token::CloseDelim(DelimToken::Paren)"),
-                    token::DelimToken::Bracket => lex("Token::CloseDelim(DelimToken::Bracket)"),
-                    token::DelimToken::Brace => lex("Token::CloseDelim(DelimToken::Brace)"),
-                    token::DelimToken::NoDelim => lex("DelimToken::NoDelim"),
-                }
-            }
-            Token::Underscore => lex("_"),
-            Token::Literal(lit, sfx) => emit_lit(lit, sfx),
-            // fix ident expansion information... somehow
-            Token::Ident(ident) => lex(&format!("Token::Ident(str_to_ident(\"{}\"))", ident.name)),
-            Token::Lifetime(ident) => lex(&format!("Token::Ident(str_to_ident(\"{}\"))",
-                                                   ident.name)),
-            _ => panic!("Unhandled case!"),
-        }
-    }
-
-    // ____________________________________________________________________________________________
-    // Conversion operators
-
-    pub fn as_tt(t: Token) -> TokenTree {
-        // FIXME do something nicer with the spans
-        TokenTree::Token(DUMMY_SP, t)
-    }
-
-    // ____________________________________________________________________________________________
-    // Build Procedures
-
-    /// Takes `input` and returns `vec![input]`.
-    pub fn build_vec(ts: TokenStream) -> TokenStream {
-        build_mac_call(str_to_ident("vec"), ts)
-        // tts.clone().to_owned()
-    }
-
-    /// Takes `ident` and `rhs` and produces `let ident = rhs;`.
-    pub fn build_let(id: Ident, tts: TokenStream) -> TokenStream {
-        concat(from_tokens(vec![keyword_to_token_ident(keywords::Let),
-                                Token::Ident(id),
-                                Token::Eq]),
-               concat(tts, from_tokens(vec![Token::Semi])))
-    }
-
-    /// Takes `ident ...`, and `args ...` and produces `ident::...(args ...)`.
-    pub fn build_mod_call(ids: Vec<Ident>, args: TokenStream) -> TokenStream {
-        let call = from_tokens(intersperse(ids.into_iter().map(|id| Token::Ident(id)).collect(),
-                                     Token::ModSep));
-        concat(call, build_paren_delimited(args))
-    }
-
-    /// Takes `ident` and `args ...` and produces `ident(args ...)`.
-    pub fn build_fn_call(name: Ident, args: TokenStream) -> TokenStream {
-        concat(from_tokens(vec![Token::Ident(name)]), build_paren_delimited(args))
-    }
-
-    /// Takes `ident` and `args ...` and produces `ident!(args ...)`.
-    pub fn build_mac_call(name: Ident, args: TokenStream) -> TokenStream {
-        concat(from_tokens(vec![Token::Ident(name), Token::Not]),
-               build_paren_delimited(args))
-    }
-
-    // ____________________________________________________________________________________________
-    // Utilities
-
-    /// A wrapper around `TokenStream::from_tokens` to avoid extra namespace specification and
-    /// provide it as a generic operator.
-    pub fn from_tokens(tokens: Vec<Token>) -> TokenStream {
-        TokenStream::from_tokens(tokens)
-    }
-
-    pub fn intersperse<T>(vs: Vec<T>, t: T) -> Vec<T>
-        where T: Clone
-    {
-        if vs.len() < 2 {
-            return vs;
-        }
-        let mut output = vec![vs.get(0).unwrap().to_owned()];
-
-        for v in vs.into_iter().skip(1) {
-            output.push(t.clone());
-            output.push(v);
-        }
-        output
-    }
-}