diff --git a/quasi_macros/src/lib.rs b/quasi_macros/src/lib.rs
index 8aabdef4..bb29d5c1 100644
--- a/quasi_macros/src/lib.rs
+++ b/quasi_macros/src/lib.rs
@@ -451,12 +451,10 @@ fn statements_mk_tt(tt: &ast::TokenTree, matcher: bool) -> Vec
> {
let builder = builder.clone().span(sp);
let e_sp = builder.expr().id("_sp");
- //let e_sp = cx.expr_ident(sp, id_ext("_sp"));
let stmt_let_tt = builder.stmt().let_()
.mut_id("tt")
.expr().vec().build();
- //let stmt_let_tt = cx.stmt_let(sp, true, id_ext("tt"), cx.expr_vec_ng(sp));
let mut tts_stmts = vec![stmt_let_tt];
tts_stmts.extend(statements_mk_tts(&seq.tts[..], matcher).into_iter());
diff --git a/src/lib.rs b/src/lib.rs
index d6195fa2..7fb61919 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(rustc_private)]
+#![feature(collections, rustc_private)]
extern crate syntax;
@@ -17,16 +17,16 @@ use syntax::codemap::Spanned;
use syntax::ext::base::ExtCtxt;
use syntax::parse::token;
use syntax::parse;
-use syntax::print::pprust;
use syntax::ptr::P;
+use std::rc::Rc;
-use syntax::ast::{TokenTree, Generics, Expr};
+use syntax::ast::{TokenTree, Expr};
pub use syntax::parse::new_parser_from_tts;
-pub use syntax::codemap::{BytePos, Span, dummy_spanned};
+pub use syntax::codemap::{BytePos, Span, dummy_spanned, DUMMY_SP};
pub trait ToTokens {
- fn to_tokens(&self, cx: &ExtCtxt) -> Vec;
+ fn to_tokens(&self, _cx: &ExtCtxt) -> Vec;
}
impl ToTokens for TokenTree {
@@ -45,8 +45,7 @@ impl<'a, T: ToTokens> ToTokens for &'a [T] {
impl ToTokens for Vec {
fn to_tokens(&self, cx: &ExtCtxt) -> Vec {
- let slice: &[T] = self;
- slice.to_tokens(cx)
+ self.iter().flat_map(|t| t.to_tokens(cx).into_iter()).collect()
}
}
@@ -66,299 +65,189 @@ impl ToTokens for Option {
}
}
-/* Should be (when bugs in default methods are fixed):
-
-trait ToSource : ToTokens {
- // Takes a thing and generates a string containing rust code for it.
- pub fn to_source() -> String;
-
- // If you can make source, you can definitely make tokens.
- pub fn to_tokens(cx: &ExtCtxt) -> ~[TokenTree] {
- cx.parse_tts(self.to_source())
+impl ToTokens for ast::Ident {
+ fn to_tokens(&self, _cx: &ExtCtxt) -> Vec {
+ vec![ast::TtToken(DUMMY_SP, token::Ident(*self, token::Plain))]
}
}
-*/
-
-// FIXME: Move this trait to pprust and get rid of *_to_str?
-pub trait ToSource {
- // Takes a thing and generates a string containing rust code for it.
- fn to_source(&self) -> String;
-}
-
-// FIXME (Issue #16472): This should go away after ToToken impls
-// are revised to go directly to token-trees.
-trait ToSourceWithHygiene : ToSource {
- // Takes a thing and generates a string containing rust code
- // for it, encoding Idents as special byte sequences to
- // maintain hygiene across serialization and deserialization.
- fn to_source_with_hygiene(&self) -> String;
-}
-
-macro_rules! impl_to_source {
- (P<$t:ty>, $pp:ident) => (
- impl ToSource for P<$t> {
- fn to_source(&self) -> String {
- pprust::$pp(&**self)
- }
- }
- impl ToSourceWithHygiene for P<$t> {
- fn to_source_with_hygiene(&self) -> String {
- pprust::with_hygiene::$pp(&**self)
- }
- }
- );
- ($t:ty, $pp:ident) => (
- impl ToSource for $t {
- fn to_source(&self) -> String {
- pprust::$pp(self)
- }
- }
- impl ToSourceWithHygiene for $t {
- fn to_source_with_hygiene(&self) -> String {
- pprust::with_hygiene::$pp(self)
- }
- }
- );
-}
-
-fn slice_to_source<'a, T: ToSource>(sep: &'static str, xs: &'a [T]) -> String {
- xs.iter()
- .map(|i| i.to_source())
- .collect::>()
- .connect(sep)
- .to_string()
-}
-
-fn slice_to_source_with_hygiene<'a, T: ToSourceWithHygiene>(
- sep: &'static str, xs: &'a [T]) -> String {
- xs.iter()
- .map(|i| i.to_source_with_hygiene())
- .collect::>()
- .connect(sep)
- .to_string()
+impl ToTokens for ast::Path {
+ fn to_tokens(&self, _cx: &ExtCtxt) -> Vec {
+ vec![ast::TtToken(DUMMY_SP, token::Interpolated(token::NtPath(Box::new(self.clone()))))]
+ }
}
-macro_rules! impl_to_source_slice {
- ($t:ty, $sep:expr) => (
- impl ToSource for [$t] {
- fn to_source(&self) -> String {
- slice_to_source($sep, self)
- }
- }
-
- impl ToSourceWithHygiene for [$t] {
- fn to_source_with_hygiene(&self) -> String {
- slice_to_source_with_hygiene($sep, self)
- }
- }
- )
+impl ToTokens for ast::Ty {
+ fn to_tokens(&self, _cx: &ExtCtxt) -> Vec {
+ vec![ast::TtToken(self.span, token::Interpolated(token::NtTy(P(self.clone()))))]
+ }
}
-impl ToSource for ast::Ident {
- fn to_source(&self) -> String {
- token::get_ident(*self).to_string()
+impl ToTokens for ast::Block {
+ fn to_tokens(&self, _cx: &ExtCtxt) -> Vec {
+ vec![ast::TtToken(self.span, token::Interpolated(token::NtBlock(P(self.clone()))))]
}
}
-impl ToSourceWithHygiene for ast::Ident {
- fn to_source_with_hygiene(&self) -> String {
- self.encode_with_hygiene()
+impl ToTokens for P {
+ fn to_tokens(&self, _cx: &ExtCtxt) -> Vec {
+ vec![ast::TtToken(self.span, token::Interpolated(token::NtItem(self.clone())))]
}
}
-impl_to_source! { ast::Path, path_to_string }
-impl_to_source! { ast::Ty, ty_to_string }
-impl_to_source! { ast::Block, block_to_string }
-impl_to_source! { ast::Arg, arg_to_string }
-impl_to_source! { Generics, generics_to_string }
-impl_to_source! { P, item_to_string }
-impl_to_source! { P, stmt_to_string }
-impl_to_source! { P, expr_to_string }
-impl_to_source! { P, pat_to_string }
-impl_to_source! { ast::Arm, arm_to_string }
-impl_to_source_slice! { ast::Ty, ", " }
-impl_to_source_slice! { P, "\n\n" }
-
-impl ToSource for ast::Attribute_ {
- fn to_source(&self) -> String {
- pprust::attribute_to_string(&dummy_spanned(self.clone()))
+impl ToTokens for P {
+ fn to_tokens(&self, _cx: &ExtCtxt) -> Vec {
+ vec![ast::TtToken(self.span, token::Interpolated(token::NtImplItem(self.clone())))]
}
}
-impl ToSourceWithHygiene for ast::Attribute_ {
- fn to_source_with_hygiene(&self) -> String {
- self.to_source()
+
+impl ToTokens for P {
+ fn to_tokens(&self, _cx: &ExtCtxt) -> Vec {
+ vec![ast::TtToken(self.span, token::Interpolated(token::NtTraitItem(self.clone())))]
}
}
-impl ToSource for P {
- fn to_source(&self) -> String {
- pprust::to_string(|s| s.print_impl_item(self))
+impl ToTokens for P {
+ fn to_tokens(&self, _cx: &ExtCtxt) -> Vec {
+ vec![ast::TtToken(self.span, token::Interpolated(token::NtStmt(self.clone())))]
}
}
-impl ToSourceWithHygiene for P {
- fn to_source_with_hygiene(&self) -> String {
- pprust::with_hygiene::to_string_hyg(|s| s.print_impl_item(self))
+impl ToTokens for P {
+ fn to_tokens(&self, _cx: &ExtCtxt) -> Vec {
+ vec![ast::TtToken(self.span, token::Interpolated(token::NtExpr(self.clone())))]
}
}
-impl ToSource for ast::WhereClause {
- fn to_source(&self) -> String {
- pprust::to_string(|s| {
- s.print_where_clause(&self)
- })
+impl ToTokens for P {
+ fn to_tokens(&self, _cx: &ExtCtxt) -> Vec {
+ vec![ast::TtToken(self.span, token::Interpolated(token::NtPat(self.clone())))]
}
}
-impl ToSourceWithHygiene for ast::WhereClause {
- fn to_source_with_hygiene(&self) -> String {
- pprust::with_hygiene::to_string_hyg(|s| {
- s.print_where_clause(&self)
- })
+impl ToTokens for ast::Arm {
+ fn to_tokens(&self, _cx: &ExtCtxt) -> Vec {
+ vec![ast::TtToken(DUMMY_SP, token::Interpolated(token::NtArm(self.clone())))]
}
}
-impl ToSource for str {
- fn to_source(&self) -> String {
- let lit = dummy_spanned(ast::LitStr(
- token::intern_and_get_ident(self), ast::CookedStr));
- pprust::lit_to_string(&lit)
- }
+macro_rules! impl_to_tokens_slice {
+ ($t: ty, $sep: expr) => {
+ impl ToTokens for [$t] {
+ fn to_tokens(&self, cx: &ExtCtxt) -> Vec {
+ let mut v = vec![];
+ for (i, x) in self.iter().enumerate() {
+ if i > 0 {
+ v.push_all(&$sep);
+ }
+ v.extend(x.to_tokens(cx));
+ }
+ v
+ }
+ }
+ };
}
-impl ToSourceWithHygiene for str {
- fn to_source_with_hygiene(&self) -> String {
- self.to_source()
+
+impl_to_tokens_slice! { ast::Ty, [ast::TtToken(DUMMY_SP, token::Comma)] }
+impl_to_tokens_slice! { P, [] }
+
+impl ToTokens for P {
+ fn to_tokens(&self, _cx: &ExtCtxt) -> Vec {
+ vec![ast::TtToken(DUMMY_SP, token::Interpolated(token::NtMeta(self.clone())))]
}
}
-impl ToSource for () {
- fn to_source(&self) -> String {
- "()".to_string()
+impl ToTokens for ast::Attribute {
+ fn to_tokens(&self, cx: &ExtCtxt) -> Vec {
+ let mut r = vec![];
+ // FIXME: The spans could be better
+ r.push(ast::TtToken(self.span, token::Pound));
+ if self.node.style == ast::AttrInner {
+ r.push(ast::TtToken(self.span, token::Not));
+ }
+ r.push(ast::TtDelimited(self.span, Rc::new(ast::Delimited {
+ delim: token::Bracket,
+ open_span: self.span,
+ tts: self.node.value.to_tokens(cx),
+ close_span: self.span,
+ })));
+ r
}
}
-impl ToSourceWithHygiene for () {
- fn to_source_with_hygiene(&self) -> String {
- self.to_source()
+
+impl ToTokens for str {
+ fn to_tokens(&self, cx: &ExtCtxt) -> Vec {
+ let lit = ast::LitStr(
+ token::intern_and_get_ident(self), ast::CookedStr);
+ dummy_spanned(lit).to_tokens(cx)
}
}
-impl ToSource for bool {
- fn to_source(&self) -> String {
- let lit = dummy_spanned(ast::LitBool(*self));
- pprust::lit_to_string(&lit)
+impl ToTokens for () {
+ fn to_tokens(&self, _cx: &ExtCtxt) -> Vec {
+ vec![ast::TtDelimited(DUMMY_SP, Rc::new(ast::Delimited {
+ delim: token::Paren,
+ open_span: DUMMY_SP,
+ tts: vec![],
+ close_span: DUMMY_SP,
+ }))]
}
}
-impl ToSourceWithHygiene for bool {
- fn to_source_with_hygiene(&self) -> String {
- self.to_source()
+
+impl ToTokens for ast::Lit {
+ fn to_tokens(&self, cx: &ExtCtxt) -> Vec {
+ // FIXME: This is wrong
+ P(ast::Expr {
+ id: ast::DUMMY_NODE_ID,
+ node: ast::ExprLit(P(self.clone())),
+ span: DUMMY_SP,
+ }).to_tokens(cx)
}
}
-impl ToSource for char {
- fn to_source(&self) -> String {
- let lit = dummy_spanned(ast::LitChar(*self));
- pprust::lit_to_string(&lit)
+impl ToTokens for bool {
+ fn to_tokens(&self, cx: &ExtCtxt) -> Vec {
+ dummy_spanned(ast::LitBool(*self)).to_tokens(cx)
}
}
-impl ToSourceWithHygiene for char {
- fn to_source_with_hygiene(&self) -> String {
- self.to_source()
+
+impl ToTokens for char {
+ fn to_tokens(&self, cx: &ExtCtxt) -> Vec {
+ dummy_spanned(ast::LitChar(*self)).to_tokens(cx)
}
}
-macro_rules! impl_to_source_isize {
+macro_rules! impl_to_tokens_int {
(signed, $t:ty, $tag:expr) => (
- impl ToSource for $t {
- fn to_source(&self) -> String {
+ impl ToTokens for $t {
+ fn to_tokens(&self, cx: &ExtCtxt) -> Vec {
let lit = ast::LitInt(*self as u64, ast::SignedIntLit($tag,
ast::Sign::new(*self)));
- pprust::lit_to_string(&dummy_spanned(lit))
- }
- }
- impl ToSourceWithHygiene for $t {
- fn to_source_with_hygiene(&self) -> String {
- self.to_source()
+ dummy_spanned(lit).to_tokens(cx)
}
}
);
(unsigned, $t:ty, $tag:expr) => (
- impl ToSource for $t {
- fn to_source(&self) -> String {
- let lit = ast::LitInt(*self as u64, ast::UnsignedIntLit($tag));
- pprust::lit_to_string(&dummy_spanned(lit))
- }
- }
- impl ToSourceWithHygiene for $t {
- fn to_source_with_hygiene(&self) -> String {
- self.to_source()
- }
- }
- );
-}
-
-impl_to_source_isize! { signed, isize, ast::TyIs }
-impl_to_source_isize! { signed, i8, ast::TyI8 }
-impl_to_source_isize! { signed, i16, ast::TyI16 }
-impl_to_source_isize! { signed, i32, ast::TyI32 }
-impl_to_source_isize! { signed, i64, ast::TyI64 }
-
-impl_to_source_isize! { unsigned, usize, ast::TyUs }
-impl_to_source_isize! { unsigned, u8, ast::TyU8 }
-impl_to_source_isize! { unsigned, u16, ast::TyU16 }
-impl_to_source_isize! { unsigned, u32, ast::TyU32 }
-impl_to_source_isize! { unsigned, u64, ast::TyU64 }
-
-// Alas ... we write these out instead. All redundant.
-
-macro_rules! impl_to_tokens {
- ($t:ty) => (
impl ToTokens for $t {
fn to_tokens(&self, cx: &ExtCtxt) -> Vec {
- cx.parse_tts_with_hygiene(self.to_source_with_hygiene())
+ let lit = ast::LitInt(*self as u64, ast::UnsignedIntLit($tag));
+ dummy_spanned(lit).to_tokens(cx)
}
}
- )
+ );
}
-macro_rules! impl_to_tokens_lifetime {
- ($t:ty) => (
- impl<'a> ToTokens for $t {
- fn to_tokens(&self, cx: &ExtCtxt) -> Vec {
- cx.parse_tts_with_hygiene(self.to_source_with_hygiene())
- }
- }
- )
-}
+impl_to_tokens_int! { signed, isize, ast::TyIs }
+impl_to_tokens_int! { signed, i8, ast::TyI8 }
+impl_to_tokens_int! { signed, i16, ast::TyI16 }
+impl_to_tokens_int! { signed, i32, ast::TyI32 }
+impl_to_tokens_int! { signed, i64, ast::TyI64 }
-impl_to_tokens! { ast::Ident }
-impl_to_tokens! { ast::Path }
-impl_to_tokens! { P }
-impl_to_tokens! { P }
-impl_to_tokens! { ast::WhereClause }
-impl_to_tokens! { P }
-impl_to_tokens! { ast::Arm }
-impl_to_tokens! { ast::Ty }
-impl_to_tokens! { Generics }
-impl_to_tokens! { P }
-impl_to_tokens! { P }
-impl_to_tokens! { ast::Block }
-impl_to_tokens! { ast::Arg }
-impl_to_tokens! { ast::Attribute_ }
-impl_to_tokens_lifetime! { &'a str }
-impl_to_tokens! { () }
-impl_to_tokens! { char }
-impl_to_tokens! { bool }
-impl_to_tokens! { isize }
-impl_to_tokens! { i8 }
-impl_to_tokens! { i16 }
-impl_to_tokens! { i32 }
-impl_to_tokens! { i64 }
-impl_to_tokens! { usize }
-impl_to_tokens! { u8 }
-impl_to_tokens! { u16 }
-impl_to_tokens! { u32 }
-impl_to_tokens! { u64 }
+impl_to_tokens_int! { unsigned, usize, ast::TyUs }
+impl_to_tokens_int! { unsigned, u8, ast::TyU8 }
+impl_to_tokens_int! { unsigned, u16, ast::TyU16 }
+impl_to_tokens_int! { unsigned, u32, ast::TyU32 }
+impl_to_tokens_int! { unsigned, u64, ast::TyU64 }
pub trait ExtParseUtils {
fn parse_item(&self, s: String) -> P;
@@ -367,12 +256,6 @@ pub trait ExtParseUtils {
fn parse_tts(&self, s: String) -> Vec;
}
-trait ExtParseUtilsWithHygiene {
- // FIXME (Issue #16472): This should go away after ToToken impls
- // are revised to go directly to token-trees.
- fn parse_tts_with_hygiene(&self, s: String) -> Vec;
-}
-
impl<'a> ExtParseUtils for ExtCtxt<'a> {
fn parse_item(&self, s: String) -> P {
@@ -404,14 +287,3 @@ impl<'a> ExtParseUtils for ExtCtxt<'a> {
self.parse_sess())
}
}
-
-impl<'a> ExtParseUtilsWithHygiene for ExtCtxt<'a> {
-
- fn parse_tts_with_hygiene(&self, s: String) -> Vec {
- use syntax::parse::with_hygiene::parse_tts_from_source_str;
- parse_tts_from_source_str("".to_string(),
- s,
- self.cfg(),
- self.parse_sess())
- }
-}
diff --git a/tests/test.rs b/tests/test.rs
index 745d571a..078ed6cc 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -31,11 +31,7 @@ fn make_ext_ctxt(sess: &parse::ParseSess) -> ExtCtxt {
};
let cfg = vec![];
- let ecfg = expand::ExpansionConfig {
- crate_name: String::new(),
- features: None,
- recursion_limit: 64,
- };
+ let ecfg = expand::ExpansionConfig::default(String::new());
let mut cx = ExtCtxt::new(&sess, cfg, ecfg);
cx.bt_push(info);