about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-05-02 07:06:50 -0700
committerbors <bors@rust-lang.org>2014-05-02 07:06:50 -0700
commitb5d6b07370b665df6b54fa20e971e61041a233b0 (patch)
tree4a43dbe1601f640ebb8bade6d67898c74bdea0e6
parente97d4e6c190764de1240c2e8a5ac253a60faac6b (diff)
parent1ad0cba5e6a837fdebf5f5543d4b169929972705 (diff)
downloadrust-b5d6b07370b665df6b54fa20e971e61041a233b0.tar.gz
rust-b5d6b07370b665df6b54fa20e971e61041a233b0.zip
auto merge of #13879 : huonw/rust/more-re, r=alexcrichton
Commits for details.

This shouldn't change the generated code at all (except for switching to `LitBinary` from an explicit ExprVec of individual ExprLit bytes for `prefix_bytes`).
-rw-r--r--src/libregex_macros/lib.rs124
-rw-r--r--src/librustdoc/clean.rs3
-rw-r--r--src/libsyntax/ast.rs2
-rw-r--r--src/libsyntax/ext/bytes.rs4
-rw-r--r--src/libsyntax/ext/concat.rs3
-rw-r--r--src/libsyntax/ext/format.rs2
-rw-r--r--src/libsyntax/ext/quote.rs23
-rw-r--r--src/libsyntax/parse/lexer.rs10
-rw-r--r--src/libsyntax/parse/token.rs5
-rw-r--r--src/libsyntax/print/pprust.rs3
-rw-r--r--src/test/run-pass-fulldeps/quote-tokens.rs4
11 files changed, 77 insertions, 106 deletions
diff --git a/src/libregex_macros/lib.rs b/src/libregex_macros/lib.rs
index f88f7fb8115..6706fb16136 100644
--- a/src/libregex_macros/lib.rs
+++ b/src/libregex_macros/lib.rs
@@ -24,8 +24,11 @@
 extern crate regex;
 extern crate syntax;
 
+use std::rc::Rc;
+
 use syntax::ast;
 use syntax::codemap;
+use syntax::ext::build::AstBuilder;
 use syntax::ext::base::{
     SyntaxExtension, ExtCtxt, MacResult, MacExpr, DummyResult,
     NormalTT, BasicMacroExpander,
@@ -112,13 +115,13 @@ impl<'a> NfaGen<'a> {
         // expression returned.
         let num_cap_locs = 2 * self.prog.num_captures();
         let num_insts = self.prog.insts.len();
-        let cap_names = self.vec_expr(self.names.as_slice(),
-            |cx, name| match name {
-                &Some(ref name) => {
+        let cap_names = self.vec_expr(self.names.as_slice().iter(),
+            |cx, name| match *name {
+                Some(ref name) => {
                     let name = name.as_slice();
                     quote_expr!(cx, Some($name.to_owned()))
                 }
-                &None => quote_expr!(cx, None),
+                None => cx.expr_none(self.sp),
             }
         );
         let prefix_anchor =
@@ -126,10 +129,12 @@ impl<'a> NfaGen<'a> {
                 EmptyBegin(flags) if flags & FLAG_MULTI == 0 => true,
                 _ => false,
             };
-        let init_groups = self.vec_from_fn(num_cap_locs,
-                                           |cx| quote_expr!(cx, None));
-        let prefix_bytes = self.vec_expr(self.prog.prefix.as_slice().as_bytes(),
-                                         |cx, b| quote_expr!(cx, $b));
+        let init_groups = self.vec_expr(range(0, num_cap_locs),
+                                        |cx, _| cx.expr_none(self.sp));
+
+        let prefix_lit = Rc::new(Vec::from_slice(self.prog.prefix.as_slice().as_bytes()));
+        let prefix_bytes = self.cx.expr_lit(self.sp, ast::LitBinary(prefix_lit));
+
         let check_prefix = self.check_prefix();
         let step_insts = self.step_insts();
         let add_insts = self.add_insts();
@@ -320,12 +325,11 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
             let nextpc = pc + 1;
             let body = match *inst {
                 EmptyBegin(flags) => {
-                    let nl = '\n';
                     let cond =
                         if flags & FLAG_MULTI > 0 {
                             quote_expr!(self.cx,
                                 self.chars.is_begin()
-                                || self.chars.prev == Some($nl)
+                                || self.chars.prev == Some('\n')
                             )
                         } else {
                             quote_expr!(self.cx, self.chars.is_begin())
@@ -336,12 +340,11 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
                     })
                 }
                 EmptyEnd(flags) => {
-                    let nl = '\n';
                     let cond =
                         if flags & FLAG_MULTI > 0 {
                             quote_expr!(self.cx,
                                 self.chars.is_end()
-                                || self.chars.cur == Some($nl)
+                                || self.chars.cur == Some('\n')
                             )
                         } else {
                             quote_expr!(self.cx, self.chars.is_end())
@@ -489,16 +492,16 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
                     if flags & FLAG_DOTNL > 0 {
                         quote_expr!(self.cx, self.add(nlist, $nextpc, caps))
                     } else {
-                        let nl = '\n'; // no char lits allowed? wtf?
                         quote_expr!(self.cx, {
-                            if self.chars.prev != Some($nl) {
+                            if self.chars.prev != Some('\n') {
                                 self.add(nlist, $nextpc, caps)
                             }
+                            ()
                         })
                     }
                 }
                 // EmptyBegin, EmptyEnd, EmptyWordBoundary, Save, Jump, Split
-                _ => quote_expr!(self.cx, {}),
+                _ => self.empty_block(),
             };
             self.arm_inst(pc, body)
         }).collect::<Vec<ast::Arm>>();
@@ -510,28 +513,22 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
     // This avoids a binary search (and is hopefully replaced by a jump
     // table).
     fn match_class(&self, casei: bool, ranges: &[(char, char)]) -> @ast::Expr {
+        let expr_true = quote_expr!(self.cx, true);
+
         let mut arms = ranges.iter().map(|&(mut start, mut end)| {
             if casei {
                 start = start.to_uppercase();
                 end = end.to_uppercase();
             }
-            ast::Arm {
-                attrs: vec!(),
-                pats: vec!(@ast::Pat{
-                    id: ast::DUMMY_NODE_ID,
-                    span: self.sp,
-                    node: ast::PatRange(quote_expr!(self.cx, $start),
-                                        quote_expr!(self.cx, $end)),
-                }),
-                guard: None,
-                body: quote_expr!(self.cx, true),
-            }
+            let pat = self.cx.pat(self.sp, ast::PatRange(quote_expr!(self.cx, $start),
+                                                         quote_expr!(self.cx, $end)));
+            self.cx.arm(self.sp, vec!(pat), expr_true)
         }).collect::<Vec<ast::Arm>>();
 
         arms.push(self.wild_arm_expr(quote_expr!(self.cx, false)));
 
         let match_on = quote_expr!(self.cx, c);
-        self.dummy_expr(ast::ExprMatch(match_on, arms))
+        self.cx.expr_match(self.sp, match_on, arms)
     }
 
     // Generates code for checking a literal prefix of the search string.
@@ -539,7 +536,7 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
     // Otherwise, a no-op is returned.
     fn check_prefix(&self) -> @ast::Expr {
         if self.prog.prefix.len() == 0 {
-            quote_expr!(self.cx, {})
+            self.empty_block()
         } else {
             quote_expr!(self.cx,
                 if clist.size == 0 {
@@ -562,24 +559,20 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
     // never be used, but is added to satisfy the compiler complaining about
     // non-exhaustive patterns.
     fn match_insts(&self, mut arms: Vec<ast::Arm>) -> @ast::Expr {
-        let mat_pc = quote_expr!(self.cx, pc);
-        arms.push(self.wild_arm_expr(quote_expr!(self.cx, {})));
-        self.dummy_expr(ast::ExprMatch(mat_pc, arms))
+        arms.push(self.wild_arm_expr(self.empty_block()));
+        self.cx.expr_match(self.sp, quote_expr!(self.cx, pc), arms)
+    }
+
+    fn empty_block(&self) -> @ast::Expr {
+        quote_expr!(self.cx, {})
     }
 
     // Creates a match arm for the instruction at `pc` with the expression
     // `body`.
     fn arm_inst(&self, pc: uint, body: @ast::Expr) -> ast::Arm {
-        ast::Arm {
-            attrs: vec!(),
-            pats: vec!(@ast::Pat{
-                id: ast::DUMMY_NODE_ID,
-                span: self.sp,
-                node: ast::PatLit(quote_expr!(self.cx, $pc)),
-            }),
-            guard: None,
-            body: body,
-        }
+        let pc_pat = self.cx.pat_lit(self.sp, quote_expr!(self.cx, $pc));
+
+        self.cx.arm(self.sp, vec!(pc_pat), body)
     }
 
     // Creates a wild-card match arm with the expression `body`.
@@ -596,56 +589,13 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
         }
     }
 
-    // Builds a `[a, b, .., len]` expression where each element is the result
-    // of executing `to_expr`.
-    fn vec_from_fn(&self, len: uint, to_expr: |&ExtCtxt| -> @ast::Expr)
-                  -> @ast::Expr {
-        self.vec_expr(Vec::from_elem(len, ()).as_slice(),
-                      |cx, _| to_expr(cx))
-    }
 
     // Converts `xs` to a `[x1, x2, .., xN]` expression by calling `to_expr`
     // on each element in `xs`.
-    fn vec_expr<T>(&self, xs: &[T], to_expr: |&ExtCtxt, &T| -> @ast::Expr)
+    fn vec_expr<T, It: Iterator<T>>(&self, xs: It, to_expr: |&ExtCtxt, T| -> @ast::Expr)
                   -> @ast::Expr {
-        let mut exprs = vec!();
-        for x in xs.iter() {
-            exprs.push(to_expr(self.cx, x))
-        }
-        let vec_exprs = self.dummy_expr(ast::ExprVec(exprs));
-        quote_expr!(self.cx, $vec_exprs)
-    }
-
-    // Creates an expression with a dummy node ID given an underlying
-    // `ast::Expr_`.
-    fn dummy_expr(&self, e: ast::Expr_) -> @ast::Expr {
-        @ast::Expr {
-            id: ast::DUMMY_NODE_ID,
-            node: e,
-            span: self.sp,
-        }
-    }
-}
-
-// This trait is defined in the quote module in the syntax crate, but I
-// don't think it's exported.
-// Interestingly, quote_expr! only requires that a 'to_tokens' method be
-// defined rather than satisfying a particular trait.
-#[doc(hidden)]
-trait ToTokens {
-    fn to_tokens(&self, cx: &ExtCtxt) -> Vec<ast::TokenTree>;
-}
-
-impl ToTokens for char {
-    fn to_tokens(&self, _: &ExtCtxt) -> Vec<ast::TokenTree> {
-        vec!(ast::TTTok(codemap::DUMMY_SP, token::LIT_CHAR((*self) as u32)))
-    }
-}
-
-impl ToTokens for bool {
-    fn to_tokens(&self, _: &ExtCtxt) -> Vec<ast::TokenTree> {
-        let ident = token::IDENT(token::str_to_ident(self.to_str()), false);
-        vec!(ast::TTTok(codemap::DUMMY_SP, ident))
+        let exprs = xs.map(|x| to_expr(self.cx, x)).collect();
+        self.cx.expr_vec(self.sp, exprs)
     }
 }
 
diff --git a/src/librustdoc/clean.rs b/src/librustdoc/clean.rs
index cabfe695df7..06d768b4342 100644
--- a/src/librustdoc/clean.rs
+++ b/src/librustdoc/clean.rs
@@ -26,7 +26,6 @@ use rustc::metadata::decoder;
 
 use std::local_data;
 use std::strbuf::StrBuf;
-use std;
 
 use core;
 use doctree;
@@ -1246,7 +1245,7 @@ fn lit_to_str(lit: &ast::Lit) -> ~str {
     match lit.node {
         ast::LitStr(ref st, _) => st.get().to_owned(),
         ast::LitBinary(ref data) => format!("{:?}", data.as_slice()),
-        ast::LitChar(c) => "'".to_owned() + std::char::from_u32(c).unwrap().to_str() + "'",
+        ast::LitChar(c) => format!("'{}'", c),
         ast::LitInt(i, _t) => i.to_str(),
         ast::LitUint(u, _t) => u.to_str(),
         ast::LitIntUnsuffixed(i) => i.to_str(),
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 45f753d0e98..49617a44a86 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -653,7 +653,7 @@ pub type Lit = Spanned<Lit_>;
 pub enum Lit_ {
     LitStr(InternedString, StrStyle),
     LitBinary(Rc<Vec<u8> >),
-    LitChar(u32),
+    LitChar(char),
     LitInt(i64, IntTy),
     LitUint(u64, UintTy),
     LitIntUnsuffixed(i64),
diff --git a/src/libsyntax/ext/bytes.rs b/src/libsyntax/ext/bytes.rs
index f4680b27084..c6349d616ec 100644
--- a/src/libsyntax/ext/bytes.rs
+++ b/src/libsyntax/ext/bytes.rs
@@ -16,8 +16,6 @@ use ext::base::*;
 use ext::base;
 use ext::build::AstBuilder;
 
-use std::char;
-
 pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> ~base::MacResult {
     // Gather all argument expressions
     let exprs = match get_exprs_from_tts(cx, sp, tts) {
@@ -59,7 +57,7 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) ->
 
                 // char literal, push to vector expression
                 ast::LitChar(v) => {
-                    if char::from_u32(v).unwrap().is_ascii() {
+                    if v.is_ascii() {
                         bytes.push(cx.expr_u8(expr.span, v as u8));
                     } else {
                         cx.span_err(expr.span, "non-ascii char literal in bytes!")
diff --git a/src/libsyntax/ext/concat.rs b/src/libsyntax/ext/concat.rs
index 123271c5b5e..fe7fa636e7d 100644
--- a/src/libsyntax/ext/concat.rs
+++ b/src/libsyntax/ext/concat.rs
@@ -14,7 +14,6 @@ use ext::base;
 use ext::build::AstBuilder;
 use parse::token;
 
-use std::char;
 use std::strbuf::StrBuf;
 
 pub fn expand_syntax_ext(cx: &mut base::ExtCtxt,
@@ -35,7 +34,7 @@ pub fn expand_syntax_ext(cx: &mut base::ExtCtxt,
                         accumulator.push_str(s.get());
                     }
                     ast::LitChar(c) => {
-                        accumulator.push_char(char::from_u32(c).unwrap());
+                        accumulator.push_char(c);
                     }
                     ast::LitInt(i, _) | ast::LitIntUnsuffixed(i) => {
                         accumulator.push_str(format!("{}", i));
diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs
index 84021f6362b..df79b105444 100644
--- a/src/libsyntax/ext/format.rs
+++ b/src/libsyntax/ext/format.rs
@@ -561,7 +561,7 @@ impl<'a, 'b> Context<'a, 'b> {
 
                 // Translate the format
                 let fill = match arg.format.fill { Some(c) => c, None => ' ' };
-                let fill = self.ecx.expr_lit(sp, ast::LitChar(fill as u32));
+                let fill = self.ecx.expr_lit(sp, ast::LitChar(fill));
                 let align = match arg.format.align {
                     parse::AlignLeft => {
                         self.ecx.path_global(sp, self.parsepath("AlignLeft"))
diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs
index 68b0ef40b16..fc7f7722354 100644
--- a/src/libsyntax/ext/quote.rs
+++ b/src/libsyntax/ext/quote.rs
@@ -125,6 +125,26 @@ pub mod rt {
         }
     }
 
+    impl ToSource for () {
+        fn to_source(&self) -> ~str {
+            "()".to_owned()
+        }
+    }
+
+    impl ToSource for bool {
+        fn to_source(&self) -> ~str {
+            let lit = dummy_spanned(ast::LitBool(*self));
+            pprust::lit_to_str(&lit)
+        }
+    }
+
+    impl ToSource for char {
+        fn to_source(&self) -> ~str {
+            let lit = dummy_spanned(ast::LitChar(*self));
+            pprust::lit_to_str(&lit)
+        }
+    }
+
     impl ToSource for int {
         fn to_source(&self) -> ~str {
             let lit = dummy_spanned(ast::LitInt(*self as i64, ast::TyI));
@@ -227,6 +247,9 @@ pub mod rt {
     impl_to_tokens!(@ast::Expr)
     impl_to_tokens!(ast::Block)
     impl_to_tokens_self!(&'a str)
+    impl_to_tokens!(())
+    impl_to_tokens!(char)
+    impl_to_tokens!(bool)
     impl_to_tokens!(int)
     impl_to_tokens!(i8)
     impl_to_tokens!(i16)
diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs
index 992d289b4e9..c1f6e21f923 100644
--- a/src/libsyntax/parse/lexer.rs
+++ b/src/libsyntax/parse/lexer.rs
@@ -874,7 +874,7 @@ fn next_token_inner(rdr: &mut StringReader) -> token::Token {
                                "unterminated character constant".to_owned());
         }
         bump(rdr); // advance curr past token
-        return token::LIT_CHAR(c2 as u32);
+        return token::LIT_CHAR(c2);
       }
       '"' => {
         let mut accum_str = StrBuf::new();
@@ -1097,17 +1097,17 @@ mod test {
 
     #[test] fn character_a() {
         assert_eq!(setup(&mk_sh(), "'a'".to_owned()).next_token().tok,
-                   token::LIT_CHAR('a' as u32));
+                   token::LIT_CHAR('a'));
     }
 
     #[test] fn character_space() {
         assert_eq!(setup(&mk_sh(), "' '".to_owned()).next_token().tok,
-                   token::LIT_CHAR(' ' as u32));
+                   token::LIT_CHAR(' '));
     }
 
     #[test] fn character_escaped() {
         assert_eq!(setup(&mk_sh(), "'\\n'".to_owned()).next_token().tok,
-                   token::LIT_CHAR('\n' as u32));
+                   token::LIT_CHAR('\n'));
     }
 
     #[test] fn lifetime_name() {
@@ -1128,7 +1128,7 @@ mod test {
 
     #[test] fn nested_block_comments() {
         assert_eq!(setup(&mk_sh(), "/* /* */ */'a'".to_owned()).next_token().tok,
-                   token::LIT_CHAR('a' as u32));
+                   token::LIT_CHAR('a'));
     }
 
 }
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index 611ce7cc527..519a7d141d3 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -18,7 +18,6 @@ use util::interner;
 
 use serialize::{Decodable, Decoder, Encodable, Encoder};
 use std::cast;
-use std::char;
 use std::fmt;
 use std::local_data;
 use std::path::BytesContainer;
@@ -81,7 +80,7 @@ pub enum Token {
     DOLLAR,
 
     /* Literals */
-    LIT_CHAR(u32),
+    LIT_CHAR(char),
     LIT_INT(i64, ast::IntTy),
     LIT_UINT(u64, ast::UintTy),
     LIT_INT_UNSUFFIXED(i64),
@@ -195,7 +194,7 @@ pub fn to_str(t: &Token) -> ~str {
       /* Literals */
       LIT_CHAR(c) => {
           let mut res = StrBuf::from_str("'");
-          char::from_u32(c).unwrap().escape_default(|c| {
+          c.escape_default(|c| {
               res.push_char(c);
           });
           res.push_char('\'');
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 7ea4dcbf28a..afb66ab8317 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -26,7 +26,6 @@ use print::pp::{Breaks, Consistent, Inconsistent, eof};
 use print::pp;
 
 use std::cast;
-use std::char;
 use std::io::{IoResult, MemWriter};
 use std::io;
 use std::rc::Rc;
@@ -2196,7 +2195,7 @@ impl<'a> State<'a> {
             ast::LitStr(ref st, style) => self.print_string(st.get(), style),
             ast::LitChar(ch) => {
                 let mut res = StrBuf::from_str("'");
-                char::from_u32(ch).unwrap().escape_default(|c| res.push_char(c));
+                ch.escape_default(|c| res.push_char(c));
                 res.push_char('\'');
                 word(&mut self.s, res.into_owned())
             }
diff --git a/src/test/run-pass-fulldeps/quote-tokens.rs b/src/test/run-pass-fulldeps/quote-tokens.rs
index 4243fcb05d5..7c25246807d 100644
--- a/src/test/run-pass-fulldeps/quote-tokens.rs
+++ b/src/test/run-pass-fulldeps/quote-tokens.rs
@@ -26,6 +26,10 @@ fn syntax_extension(cx: &ExtCtxt) {
     let _c: @syntax::ast::Pat = quote_pat!(cx, (x, 1 .. 4, *) );
     let _d: @syntax::ast::Stmt = quote_stmt!(cx, let x = $a; );
     let _e: @syntax::ast::Expr = quote_expr!(cx, match foo { $p_toks => 10 } );
+
+    let _f: @syntax::ast::Expr = quote_expr!(cx, ());
+    let _g: @syntax::ast::Expr = quote_expr!(cx, true);
+    let _h: @syntax::ast::Expr = quote_expr!(cx, 'a');
 }
 
 fn main() {