]> git.lizzy.rs Git - rust.git/commitdiff
libsyntax: Add more quasiquoting macros
authorKyle Mayes <kyle@mayeses.com>
Wed, 11 Nov 2015 20:19:01 +0000 (15:19 -0500)
committerKyle Mayes <kyle@mayeses.com>
Wed, 11 Nov 2015 20:19:01 +0000 (15:19 -0500)
src/libsyntax/ext/base.rs
src/libsyntax/ext/quote.rs
src/libsyntax/fold.rs
src/libsyntax/parse/parser.rs
src/libsyntax/parse/token.rs
src/libsyntax/print/pprust.rs
src/test/compile-fail-fulldeps/gated-quote.rs
src/test/run-pass-fulldeps/qquote.rs

index 3f925c9d7bae699af3076a72f63d11f528565f9f..3e854cd72bac4db63450249dd52830febda63c80 100644 (file)
@@ -512,6 +512,18 @@ fn builtin_normal_expander(f: MacroExpanderFn) -> SyntaxExtension {
         syntax_expanders.insert(intern("quote_attr"),
                            builtin_normal_expander(
                                 ext::quote::expand_quote_attr));
+        syntax_expanders.insert(intern("quote_arg"),
+                           builtin_normal_expander(
+                                ext::quote::expand_quote_arg));
+        syntax_expanders.insert(intern("quote_block"),
+                           builtin_normal_expander(
+                                ext::quote::expand_quote_block));
+        syntax_expanders.insert(intern("quote_meta_item"),
+                           builtin_normal_expander(
+                                ext::quote::expand_quote_meta_item));
+        syntax_expanders.insert(intern("quote_path"),
+                           builtin_normal_expander(
+                                ext::quote::expand_quote_path));
     }
 
     syntax_expanders.insert(intern("line"),
index 5e1d233916419d7d9eb3812c1471ab21777654f1..dc4a061ce782ebbe22d4fc7d8fdafe34bb289de3 100644 (file)
@@ -158,6 +158,18 @@ fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
         }
     }
 
+    impl ToTokens for ast::Arg {
+        fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
+            vec![TokenTree::Token(DUMMY_SP, token::Interpolated(token::NtArg(self.clone())))]
+        }
+    }
+
+    impl ToTokens for P<ast::Block> {
+        fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
+            vec![TokenTree::Token(DUMMY_SP, token::Interpolated(token::NtBlock(self.clone())))]
+        }
+    }
+
     macro_rules! impl_to_tokens_slice {
         ($t: ty, $sep: expr) => {
             impl ToTokens for [$t] {
@@ -177,6 +189,7 @@ fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
 
     impl_to_tokens_slice! { ast::Ty, [TokenTree::Token(DUMMY_SP, token::Comma)] }
     impl_to_tokens_slice! { P<ast::Item>, [] }
+    impl_to_tokens_slice! { ast::Arg, [TokenTree::Token(DUMMY_SP, token::Comma)] }
 
     impl ToTokens for P<ast::MetaItem> {
         fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
@@ -383,6 +396,39 @@ pub fn expand_quote_attr(cx: &mut ExtCtxt,
     base::MacEager::expr(expanded)
 }
 
+pub fn expand_quote_arg(cx: &mut ExtCtxt,
+                        sp: Span,
+                        tts: &[TokenTree])
+                        -> Box<base::MacResult+'static> {
+    let expanded = expand_parse_call(cx, sp, "parse_arg_panic", vec!(), tts);
+    base::MacEager::expr(expanded)
+}
+
+pub fn expand_quote_block(cx: &mut ExtCtxt,
+                        sp: Span,
+                        tts: &[TokenTree])
+                        -> Box<base::MacResult+'static> {
+    let expanded = expand_parse_call(cx, sp, "parse_block_panic", vec!(), tts);
+    base::MacEager::expr(expanded)
+}
+
+pub fn expand_quote_meta_item(cx: &mut ExtCtxt,
+                        sp: Span,
+                        tts: &[TokenTree])
+                        -> Box<base::MacResult+'static> {
+    let expanded = expand_parse_call(cx, sp, "parse_meta_item_panic", vec!(), tts);
+    base::MacEager::expr(expanded)
+}
+
+pub fn expand_quote_path(cx: &mut ExtCtxt,
+                        sp: Span,
+                        tts: &[TokenTree])
+                        -> Box<base::MacResult+'static> {
+    let mode = mk_parser_path(cx, sp, "LifetimeAndTypesWithoutColons");
+    let expanded = expand_parse_call(cx, sp, "parse_path_panic", vec!(mode), tts);
+    base::MacEager::expr(expanded)
+}
+
 pub fn expand_quote_matcher(cx: &mut ExtCtxt,
                             sp: Span,
                             tts: &[TokenTree])
@@ -440,6 +486,11 @@ fn mk_token_path(cx: &ExtCtxt, sp: Span, name: &str) -> P<ast::Expr> {
     cx.expr_path(cx.path_global(sp, idents))
 }
 
+fn mk_parser_path(cx: &ExtCtxt, sp: Span, name: &str) -> P<ast::Expr> {
+    let idents = vec!(id_ext("syntax"), id_ext("parse"), id_ext("parser"), id_ext(name));
+    cx.expr_path(cx.path_global(sp, idents))
+}
+
 fn mk_binop(cx: &ExtCtxt, sp: Span, bop: token::BinOpToken) -> P<ast::Expr> {
     let name = match bop {
         token::Plus     => "Plus",
index 284bf46cc3fcd37e37d522fb692e82d254b1b6e2..66ee5aa12ca885fb16e5ee61bf47170e46b04395 100644 (file)
@@ -684,6 +684,7 @@ pub fn noop_fold_interpolated<T: Folder>(nt: token::Nonterminal, fld: &mut T)
         token::NtGenerics(generics) => token::NtGenerics(fld.fold_generics(generics)),
         token::NtWhereClause(where_clause) =>
             token::NtWhereClause(fld.fold_where_clause(where_clause)),
+        token::NtArg(arg) => token::NtArg(fld.fold_arg(arg)),
     }
 }
 
index fde1058a785c0466147941e0a91eaba39729a675..f5e4114464fbc26af083c14c7657a9a22cd29591 100644 (file)
@@ -393,6 +393,22 @@ pub fn parse_attribute_panic(&mut self, permit_inner: bool) -> ast::Attribute {
         panictry!(self.parse_attribute(permit_inner))
     }
 
+    pub fn parse_arg_panic(&mut self) -> Arg {
+        panictry!(self.parse_arg())
+    }
+
+    pub fn parse_block_panic(&mut self) -> P<Block> {
+        panictry!(self.parse_block())
+    }
+
+    pub fn parse_meta_item_panic(&mut self) -> P<ast::MetaItem> {
+        panictry!(self.parse_meta_item())
+    }
+
+    pub fn parse_path_panic(&mut self, mode: PathParsingMode) -> ast::Path {
+        panictry!(self.parse_path(mode))
+    }
+
     /// Convert a token to a string using self's reader
     pub fn token_to_string(token: &token::Token) -> String {
         pprust::token_to_string(token)
@@ -1455,6 +1471,8 @@ pub fn is_named_argument(&mut self) -> bool {
     /// This version of parse arg doesn't necessarily require
     /// identifier names.
     pub fn parse_arg_general(&mut self, require_name: bool) -> PResult<Arg> {
+        maybe_whole!(no_clone self, NtArg);
+
         let pat = if require_name || self.is_named_argument() {
             debug!("parse_arg_general parse_pat (require_name:{})",
                    require_name);
index ba24dc3c0a74ec155fbc4d870741374560da667d..5e4449af60405876b19c54ef4c86b14b5096d5d1 100644 (file)
@@ -381,12 +381,13 @@ pub enum Nonterminal {
     NtMeta(P<ast::MetaItem>),
     NtPath(Box<ast::Path>),
     NtTT(P<ast::TokenTree>), // needs P'ed to break a circularity
-    // These is not exposed to macros, but is used by quasiquote.
+    // These are not exposed to macros, but are used by quasiquote.
     NtArm(ast::Arm),
     NtImplItem(P<ast::ImplItem>),
     NtTraitItem(P<ast::TraitItem>),
     NtGenerics(ast::Generics),
     NtWhereClause(ast::WhereClause),
+    NtArg(ast::Arg),
 }
 
 impl fmt::Debug for Nonterminal {
@@ -407,6 +408,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             NtTraitItem(..) => f.pad("NtTraitItem(..)"),
             NtGenerics(..) => f.pad("NtGenerics(..)"),
             NtWhereClause(..) => f.pad("NtWhereClause(..)"),
+            NtArg(..) => f.pad("NtArg(..)"),
         }
     }
 }
index fad0b7869f02d5e56c0455fef0254e97dcc68436..5b8f5c0aef6f78857ade02f6b5e3c7683b72bf7e 100644 (file)
@@ -305,6 +305,7 @@ pub fn token_to_string(tok: &Token) -> String {
             token::NtTraitItem(ref e)   => trait_item_to_string(&**e),
             token::NtGenerics(ref e)    => generics_to_string(&*e),
             token::NtWhereClause(ref e) => where_clause_to_string(&*e),
+            token::NtArg(ref e)         => arg_to_string(&*e),
         }
     }
 }
index 6a5cd88a591563676d71a7b5cffbb519765f85d7..cd801fbcd889be760e192fef18b71cf809029299 100644 (file)
@@ -37,14 +37,18 @@ fn name_of(&self, st: &str) -> ast::Name { loop { } }
 
 pub fn main() {
     let ecx = &ParseSess;
-    let x = quote_tokens!(ecx, 3);   //~ ERROR macro undefined: 'quote_tokens!'
-    let x = quote_expr!(ecx, 3);     //~ ERROR macro undefined: 'quote_expr!'
-    let x = quote_ty!(ecx, 3);       //~ ERROR macro undefined: 'quote_ty!'
-    let x = quote_method!(ecx, 3);   //~ ERROR macro undefined: 'quote_method!'
-    let x = quote_item!(ecx, 3);     //~ ERROR macro undefined: 'quote_item!'
-    let x = quote_pat!(ecx, 3);      //~ ERROR macro undefined: 'quote_pat!'
-    let x = quote_arm!(ecx, 3);      //~ ERROR macro undefined: 'quote_arm!'
-    let x = quote_stmt!(ecx, 3);     //~ ERROR macro undefined: 'quote_stmt!'
-    let x = quote_matcher!(ecx, 3);  //~ ERROR macro undefined: 'quote_matcher!'
-    let x = quote_attr!(ecx, 3);     //~ ERROR macro undefined: 'quote_attr!'
+    let x = quote_tokens!(ecx, 3);    //~ ERROR macro undefined: 'quote_tokens!'
+    let x = quote_expr!(ecx, 3);      //~ ERROR macro undefined: 'quote_expr!'
+    let x = quote_ty!(ecx, 3);        //~ ERROR macro undefined: 'quote_ty!'
+    let x = quote_method!(ecx, 3);    //~ ERROR macro undefined: 'quote_method!'
+    let x = quote_item!(ecx, 3);      //~ ERROR macro undefined: 'quote_item!'
+    let x = quote_pat!(ecx, 3);       //~ ERROR macro undefined: 'quote_pat!'
+    let x = quote_arm!(ecx, 3);       //~ ERROR macro undefined: 'quote_arm!'
+    let x = quote_stmt!(ecx, 3);      //~ ERROR macro undefined: 'quote_stmt!'
+    let x = quote_matcher!(ecx, 3);   //~ ERROR macro undefined: 'quote_matcher!'
+    let x = quote_attr!(ecx, 3);      //~ ERROR macro undefined: 'quote_attr!'
+    let x = quote_arg!(ecx, 3);       //~ ERROR macro undefined: 'quote_arg!'
+    let x = quote_block!(ecx, 3);     //~ ERROR macro undefined: 'quote_block!'
+    let x = quote_meta_item!(ecx, 3); //~ ERROR macro undefined: 'quote_meta_item!'
+    let x = quote_path!(ecx, 3);      //~ ERROR macro undefined: 'quote_path!'
 }
index ba713bb98f8547a71e8728b08fe14f78ccc9a8e0..edaa88452c4854ecc53bd57671907b4200ccc9eb 100644 (file)
@@ -63,4 +63,41 @@ macro_rules! check {
 
     let attr = quote_attr!(cx, #![cfg(foo = "bar")]);
     check!(attribute_to_string, attr, quote_attr!(cx, $attr); r#"#![cfg(foo = "bar")]"#);
+
+    // quote_arg!
+
+    let arg = quote_arg!(cx, foo: i32);
+    check!(arg_to_string, arg, quote_arg!(cx, $arg); "foo: i32");
+
+    let function = quote_item!(cx, fn f($arg) { }).unwrap();
+    check!(item_to_string, function; "fn f(foo: i32) { }");
+
+    let args = vec![arg, quote_arg!(cx, bar: u32)];
+    let args = &args[..];
+    let function = quote_item!(cx, fn f($args) { }).unwrap();
+    check!(item_to_string, function; "fn f(foo: i32, bar: u32) { }");
+
+    // quote_block!
+
+    let block = quote_block!(cx, { $stmt let y = 40u32; });
+    check!(block_to_string, block, *quote_block!(cx, $block); "{ let x = 20u16; let y = 40u32; }");
+
+    let function = quote_item!(cx, fn f() $block).unwrap();
+    check!(item_to_string, function; "fn f() { let x = 20u16; let y = 40u32; }");
+
+    // quote_path!
+
+    let path = quote_path!(cx, ::syntax::ptr::P<MetaItem>);
+    check!(path_to_string, path, quote_path!(cx, $path); "::syntax::ptr::P<MetaItem>");
+
+    let ty = quote_ty!(cx, $path);
+    check!(ty_to_string, ty; "::syntax::ptr::P<MetaItem>");
+
+    // quote_meta_item!
+
+    let meta = quote_meta_item!(cx, cfg(foo = "bar"));
+    check!(meta_item_to_string, meta, *quote_meta_item!(cx, $meta); r#"cfg(foo = "bar")"#);
+
+    let attr = quote_attr!(cx, #![$meta]);
+    check!(attribute_to_string, attr; r#"#![cfg(foo = "bar")]"#);
 }