Implement quote! and other proc_macro API.
This commit is contained in:
parent
7d41674b17
commit
e42836b208
34 changed files with 1084 additions and 576 deletions
|
|
@ -8,50 +8,37 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![allow(unused_parens)]
|
||||
#![feature(plugin)]
|
||||
#![feature(plugin_registrar)]
|
||||
#![feature(rustc_private)]
|
||||
#![plugin(proc_macro_plugin)]
|
||||
// no-prefer-dynamic
|
||||
|
||||
extern crate rustc_plugin;
|
||||
extern crate syntax;
|
||||
#![crate_type = "proc-macro"]
|
||||
#![feature(proc_macro, proc_macro_lib)]
|
||||
|
||||
use rustc_plugin::Registry;
|
||||
extern crate proc_macro;
|
||||
|
||||
use syntax::ext::base::SyntaxExtension;
|
||||
use syntax::parse::token::Token;
|
||||
use syntax::symbol::Symbol;
|
||||
use syntax::tokenstream::{TokenTree, TokenStream};
|
||||
use proc_macro::{TokenStream, TokenKind, quote};
|
||||
|
||||
#[plugin_registrar]
|
||||
pub fn plugin_registrar(reg: &mut Registry) {
|
||||
reg.register_syntax_extension(Symbol::intern("cond"),
|
||||
SyntaxExtension::ProcMacro(Box::new(cond)));
|
||||
}
|
||||
|
||||
fn cond(input: TokenStream) -> TokenStream {
|
||||
#[proc_macro]
|
||||
pub fn cond(input: TokenStream) -> TokenStream {
|
||||
let mut conds = Vec::new();
|
||||
let mut input = input.trees().peekable();
|
||||
let mut input = input.into_iter().peekable();
|
||||
while let Some(tree) = input.next() {
|
||||
let mut cond = match tree {
|
||||
TokenTree::Delimited(_, ref delimited) => delimited.stream(),
|
||||
let cond = match tree.kind {
|
||||
TokenKind::Sequence(_, cond) => cond,
|
||||
_ => panic!("Invalid input"),
|
||||
};
|
||||
let mut trees = cond.trees();
|
||||
let test = trees.next();
|
||||
let rhs = trees.collect::<TokenStream>();
|
||||
let mut cond_trees = cond.clone().into_iter();
|
||||
let test = cond_trees.next().expect("Unexpected empty condition in `cond!`");
|
||||
let rhs = cond_trees.collect::<TokenStream>();
|
||||
if rhs.is_empty() {
|
||||
panic!("Invalid macro usage in cond: {}", cond);
|
||||
}
|
||||
let is_else = match test {
|
||||
Some(TokenTree::Token(_, Token::Ident(ident))) if ident.name == "else" => true,
|
||||
let is_else = match test.kind {
|
||||
TokenKind::Word(word) => *word == *"else",
|
||||
_ => false,
|
||||
};
|
||||
conds.push(if is_else || input.peek().is_none() {
|
||||
quote!({ $rhs })
|
||||
} else {
|
||||
let test = test.unwrap();
|
||||
quote!(if $test { $rhs } else)
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,29 +8,20 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(plugin)]
|
||||
#![feature(plugin_registrar)]
|
||||
#![feature(rustc_private)]
|
||||
#![plugin(proc_macro_plugin)]
|
||||
// no-prefer-dynamic
|
||||
|
||||
extern crate rustc_plugin;
|
||||
extern crate syntax;
|
||||
#![crate_type = "proc-macro"]
|
||||
#![feature(proc_macro, proc_macro_lib)]
|
||||
|
||||
use rustc_plugin::Registry;
|
||||
use syntax::ext::base::SyntaxExtension;
|
||||
use syntax::symbol::Symbol;
|
||||
use syntax::tokenstream::TokenStream;
|
||||
extern crate proc_macro;
|
||||
|
||||
#[plugin_registrar]
|
||||
pub fn plugin_registrar(reg: &mut Registry) {
|
||||
reg.register_syntax_extension(Symbol::intern("hello"),
|
||||
SyntaxExtension::ProcMacro(Box::new(hello)));
|
||||
}
|
||||
use proc_macro::{TokenStream, quote};
|
||||
|
||||
// This macro is not very interesting, but it does contain delimited tokens with
|
||||
// no content - `()` and `{}` - which has caused problems in the past.
|
||||
// Also, it tests that we can escape `$` via `$$`.
|
||||
fn hello(_: TokenStream) -> TokenStream {
|
||||
#[proc_macro]
|
||||
pub fn hello(_: TokenStream) -> TokenStream {
|
||||
quote!({
|
||||
fn hello() {}
|
||||
macro_rules! m { ($$($$t:tt)*) => { $$($$t)* } }
|
||||
|
|
|
|||
|
|
@ -8,47 +8,37 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(plugin, plugin_registrar, rustc_private)]
|
||||
#![plugin(proc_macro_plugin)]
|
||||
// no-prefer-dynamic
|
||||
|
||||
extern crate rustc_plugin;
|
||||
extern crate syntax;
|
||||
#![crate_type = "proc-macro"]
|
||||
#![feature(proc_macro, proc_macro_lib)]
|
||||
|
||||
use rustc_plugin::Registry;
|
||||
use syntax::ext::base::SyntaxExtension;
|
||||
use syntax::tokenstream::TokenStream;
|
||||
use syntax::symbol::Symbol;
|
||||
extern crate proc_macro;
|
||||
|
||||
#[plugin_registrar]
|
||||
pub fn plugin_registrar(reg: &mut Registry) {
|
||||
reg.register_syntax_extension(Symbol::intern("attr_tru"),
|
||||
SyntaxExtension::AttrProcMacro(Box::new(attr_tru)));
|
||||
reg.register_syntax_extension(Symbol::intern("attr_identity"),
|
||||
SyntaxExtension::AttrProcMacro(Box::new(attr_identity)));
|
||||
reg.register_syntax_extension(Symbol::intern("tru"),
|
||||
SyntaxExtension::ProcMacro(Box::new(tru)));
|
||||
reg.register_syntax_extension(Symbol::intern("ret_tru"),
|
||||
SyntaxExtension::ProcMacro(Box::new(ret_tru)));
|
||||
reg.register_syntax_extension(Symbol::intern("identity"),
|
||||
SyntaxExtension::ProcMacro(Box::new(identity)));
|
||||
use proc_macro::{TokenStream, quote};
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn attr_tru(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
let name = item.into_iter().skip(1).next().unwrap();
|
||||
quote!(fn $name() -> bool { true })
|
||||
}
|
||||
|
||||
fn attr_tru(_attr: TokenStream, _item: TokenStream) -> TokenStream {
|
||||
quote!(fn f1() -> bool { true })
|
||||
}
|
||||
|
||||
fn attr_identity(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
#[proc_macro_attribute]
|
||||
pub fn attr_identity(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
quote!($item)
|
||||
}
|
||||
|
||||
fn tru(_ts: TokenStream) -> TokenStream {
|
||||
#[proc_macro]
|
||||
pub fn tru(_ts: TokenStream) -> TokenStream {
|
||||
quote!(true)
|
||||
}
|
||||
|
||||
fn ret_tru(_ts: TokenStream) -> TokenStream {
|
||||
#[proc_macro]
|
||||
pub fn ret_tru(_ts: TokenStream) -> TokenStream {
|
||||
quote!(return true;)
|
||||
}
|
||||
|
||||
fn identity(ts: TokenStream) -> TokenStream {
|
||||
#[proc_macro]
|
||||
pub fn identity(ts: TokenStream) -> TokenStream {
|
||||
quote!($ts)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,40 +0,0 @@
|
|||
// Copyright 2012-2014 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.
|
||||
|
||||
// ignore-stage1
|
||||
|
||||
#![feature(plugin)]
|
||||
#![feature(rustc_private)]
|
||||
#![plugin(proc_macro_plugin)]
|
||||
|
||||
extern crate syntax;
|
||||
extern crate syntax_pos;
|
||||
|
||||
use syntax::ast::{Ident, Name};
|
||||
use syntax::parse::token::{self, Token, Lit};
|
||||
use syntax::tokenstream::TokenTree;
|
||||
|
||||
fn main() {
|
||||
let true_tok = token::Ident(Ident::from_str("true"));
|
||||
assert!(quote!(true).eq_unspanned(&true_tok.into()));
|
||||
|
||||
// issue #35829, extended check to proc_macro.
|
||||
let triple_dot_tok = Token::DotDotDot;
|
||||
assert!(quote!(...).eq_unspanned(&triple_dot_tok.into()));
|
||||
|
||||
let byte_str_tok = Token::Literal(Lit::ByteStr(Name::intern("one")), None);
|
||||
assert!(quote!(b"one").eq_unspanned(&byte_str_tok.into()));
|
||||
|
||||
let byte_str_raw_tok = Token::Literal(Lit::ByteStrRaw(Name::intern("#\"two\"#"), 3), None);
|
||||
assert!(quote!(br###"#"two"#"###).eq_unspanned(&byte_str_raw_tok.into()));
|
||||
|
||||
let str_raw_tok = Token::Literal(Lit::StrRaw(Name::intern("#\"three\"#"), 2), None);
|
||||
assert!(quote!(r##"#"three"#"##).eq_unspanned(&str_raw_tok.into()));
|
||||
}
|
||||
|
|
@ -11,9 +11,11 @@
|
|||
// aux-build:cond_plugin.rs
|
||||
// ignore-stage1
|
||||
|
||||
#![feature(plugin)]
|
||||
#![feature(rustc_private)]
|
||||
#![plugin(cond_plugin)]
|
||||
#![feature(proc_macro)]
|
||||
|
||||
extern crate cond_plugin;
|
||||
|
||||
use cond_plugin::cond;
|
||||
|
||||
fn fact(n : i64) -> i64 {
|
||||
if n == 0 {
|
||||
|
|
|
|||
|
|
@ -13,10 +13,10 @@
|
|||
// aux-build:hello_macro.rs
|
||||
// ignore-stage1
|
||||
|
||||
#![feature(plugin)]
|
||||
#![feature(rustc_private)]
|
||||
#![plugin(hello_macro)]
|
||||
#![feature(proc_macro)]
|
||||
|
||||
extern crate hello_macro;
|
||||
|
||||
fn main() {
|
||||
hello!();
|
||||
hello_macro::hello!();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,10 +12,11 @@
|
|||
// ignore-stage1
|
||||
// ignore-cross-compile
|
||||
|
||||
#![feature(plugin, custom_attribute)]
|
||||
#![feature(type_macros)]
|
||||
#![feature(proc_macro)]
|
||||
|
||||
#![plugin(proc_macro_def)]
|
||||
extern crate proc_macro_def;
|
||||
|
||||
use proc_macro_def::{attr_tru, attr_identity, identity, ret_tru, tru};
|
||||
|
||||
#[attr_tru]
|
||||
fn f1() -> bool {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue