diff --git a/src/libregex_macros/lib.rs b/src/libregex_macros/lib.rs index f88f7fb8115df0e830ab6a47da6d2bf7aedf324f..6706fb16136dc4dc8e18e1f7547f4747de67c582 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 @@ fn code(&mut self) -> @ast::Expr { // 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 @@ fn code(&mut self) -> @ast::Expr { 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 add_insts(&self) -> @ast::Expr { 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 add_insts(&self) -> @ast::Expr { }) } 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 step_insts(&self) -> @ast::Expr { 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::>(); @@ -510,28 +513,22 @@ fn step_insts(&self) -> @ast::Expr { // 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::>(); 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 match_class(&self, casei: bool, ranges: &[(char, char)]) -> @ast::Expr { // 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 check_prefix(&self) -> @ast::Expr { // never be used, but is added to satisfy the compiler complaining about // non-exhaustive patterns. fn match_insts(&self, mut arms: Vec) -> @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 wild_arm_expr(&self, body: @ast::Expr) -> ast::Arm { } } - // 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(&self, xs: &[T], to_expr: |&ExtCtxt, &T| -> @ast::Expr) + fn vec_expr>(&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; -} - -impl ToTokens for char { - fn to_tokens(&self, _: &ExtCtxt) -> Vec { - vec!(ast::TTTok(codemap::DUMMY_SP, token::LIT_CHAR((*self) as u32))) - } -} - -impl ToTokens for bool { - fn to_tokens(&self, _: &ExtCtxt) -> Vec { - 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 cabfe695df714ab255cd198acfe2e2e031b741b2..06d768b4342503f6746601d0c84f5ed6de149bac 100644 --- a/src/librustdoc/clean.rs +++ b/src/librustdoc/clean.rs @@ -26,7 +26,6 @@ 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 45f753d0e98327f6dd38f5f6a776d71df627c443..49617a44a863fbd2cf00a7e62294e7c425d2b0c7 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -653,7 +653,7 @@ pub enum StrStyle { pub enum Lit_ { LitStr(InternedString, StrStyle), LitBinary(Rc >), - 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 f4680b27084f881781a6f2c04fb7e7246718bbc6..c6349d616eca3d478fe84a6a74b6833e485aecb9 100644 --- a/src/libsyntax/ext/bytes.rs +++ b/src/libsyntax/ext/bytes.rs @@ -16,8 +16,6 @@ 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 123271c5b5e608e18a1c50b1d8ea71296467703d..fe7fa636e7d59c6b87b7e85c9f1e1bc11bc8c692 100644 --- a/src/libsyntax/ext/concat.rs +++ b/src/libsyntax/ext/concat.rs @@ -14,7 +14,6 @@ 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 84021f6362b7c9c1a916ec98a1ff0a3d837a08d2..df79b1054443247f67f351a9bb3c20df64afc081 100644 --- a/src/libsyntax/ext/format.rs +++ b/src/libsyntax/ext/format.rs @@ -561,7 +561,7 @@ fn trans_piece(&mut self, piece: &parse::Piece) -> @ast::Expr { // 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 68b0ef40b16bb4949da56fa6a0559a16beb7dcaf..fc7f772235474af10ab0d3a1db58057b17045bbf 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -125,6 +125,26 @@ fn to_source(&self) -> ~str { } } + 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 @@ fn to_tokens(&self, cx: &ExtCtxt) -> Vec { 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 992d289b4e9753110d2d4da8317c0bb6f604a150..c1f6e21f923c311093c84f0682952e72fbd680b8 100644 --- a/src/libsyntax/parse/lexer.rs +++ b/src/libsyntax/parse/lexer.rs @@ -874,7 +874,7 @@ fn binop(rdr: &mut StringReader, op: token::BinOp) -> 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 @@ fn mk_ident (id: &str, is_mod_name: bool) -> token::Token { #[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 @@ fn mk_ident (id: &str, is_mod_name: bool) -> token::Token { #[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 611ce7cc52798081beecffa6305322a9c2e4574c..519a7d141d33f411b93a4b83f3b5578165f8d41a 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -18,7 +18,6 @@ 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 7ea4dcbf28a2e20b9e1837420b6b97fa42abfd70..afb66ab831750864775903a7ea43613d3ee800b8 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -26,7 +26,6 @@ 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 @@ pub fn print_literal(&mut self, lit: &ast::Lit) -> IoResult<()> { 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 4243fcb05d5cd5fc23f4e88cf5ca80d78aca0249..7c25246807d57a514036611f33e61955adf2c4b1 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() {