Skip to content

Commit b5d6b07

Browse files
committed
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`).
2 parents e97d4e6 + 1ad0cba commit b5d6b07

File tree

11 files changed

+77
-106
lines changed

11 files changed

+77
-106
lines changed

src/libregex_macros/lib.rs

+37-87
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,11 @@
2424
extern crate regex;
2525
extern crate syntax;
2626

27+
use std::rc::Rc;
28+
2729
use syntax::ast;
2830
use syntax::codemap;
31+
use syntax::ext::build::AstBuilder;
2932
use syntax::ext::base::{
3033
SyntaxExtension, ExtCtxt, MacResult, MacExpr, DummyResult,
3134
NormalTT, BasicMacroExpander,
@@ -112,24 +115,26 @@ impl<'a> NfaGen<'a> {
112115
// expression returned.
113116
let num_cap_locs = 2 * self.prog.num_captures();
114117
let num_insts = self.prog.insts.len();
115-
let cap_names = self.vec_expr(self.names.as_slice(),
116-
|cx, name| match name {
117-
&Some(ref name) => {
118+
let cap_names = self.vec_expr(self.names.as_slice().iter(),
119+
|cx, name| match *name {
120+
Some(ref name) => {
118121
let name = name.as_slice();
119122
quote_expr!(cx, Some($name.to_owned()))
120123
}
121-
&None => quote_expr!(cx, None),
124+
None => cx.expr_none(self.sp),
122125
}
123126
);
124127
let prefix_anchor =
125128
match self.prog.insts.as_slice()[1] {
126129
EmptyBegin(flags) if flags & FLAG_MULTI == 0 => true,
127130
_ => false,
128131
};
129-
let init_groups = self.vec_from_fn(num_cap_locs,
130-
|cx| quote_expr!(cx, None));
131-
let prefix_bytes = self.vec_expr(self.prog.prefix.as_slice().as_bytes(),
132-
|cx, b| quote_expr!(cx, $b));
132+
let init_groups = self.vec_expr(range(0, num_cap_locs),
133+
|cx, _| cx.expr_none(self.sp));
134+
135+
let prefix_lit = Rc::new(Vec::from_slice(self.prog.prefix.as_slice().as_bytes()));
136+
let prefix_bytes = self.cx.expr_lit(self.sp, ast::LitBinary(prefix_lit));
137+
133138
let check_prefix = self.check_prefix();
134139
let step_insts = self.step_insts();
135140
let add_insts = self.add_insts();
@@ -320,12 +325,11 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
320325
let nextpc = pc + 1;
321326
let body = match *inst {
322327
EmptyBegin(flags) => {
323-
let nl = '\n';
324328
let cond =
325329
if flags & FLAG_MULTI > 0 {
326330
quote_expr!(self.cx,
327331
self.chars.is_begin()
328-
|| self.chars.prev == Some($nl)
332+
|| self.chars.prev == Some('\n')
329333
)
330334
} else {
331335
quote_expr!(self.cx, self.chars.is_begin())
@@ -336,12 +340,11 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
336340
})
337341
}
338342
EmptyEnd(flags) => {
339-
let nl = '\n';
340343
let cond =
341344
if flags & FLAG_MULTI > 0 {
342345
quote_expr!(self.cx,
343346
self.chars.is_end()
344-
|| self.chars.cur == Some($nl)
347+
|| self.chars.cur == Some('\n')
345348
)
346349
} else {
347350
quote_expr!(self.cx, self.chars.is_end())
@@ -489,16 +492,16 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
489492
if flags & FLAG_DOTNL > 0 {
490493
quote_expr!(self.cx, self.add(nlist, $nextpc, caps))
491494
} else {
492-
let nl = '\n'; // no char lits allowed? wtf?
493495
quote_expr!(self.cx, {
494-
if self.chars.prev != Some($nl) {
496+
if self.chars.prev != Some('\n') {
495497
self.add(nlist, $nextpc, caps)
496498
}
499+
()
497500
})
498501
}
499502
}
500503
// EmptyBegin, EmptyEnd, EmptyWordBoundary, Save, Jump, Split
501-
_ => quote_expr!(self.cx, {}),
504+
_ => self.empty_block(),
502505
};
503506
self.arm_inst(pc, body)
504507
}).collect::<Vec<ast::Arm>>();
@@ -510,36 +513,30 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
510513
// This avoids a binary search (and is hopefully replaced by a jump
511514
// table).
512515
fn match_class(&self, casei: bool, ranges: &[(char, char)]) -> @ast::Expr {
516+
let expr_true = quote_expr!(self.cx, true);
517+
513518
let mut arms = ranges.iter().map(|&(mut start, mut end)| {
514519
if casei {
515520
start = start.to_uppercase();
516521
end = end.to_uppercase();
517522
}
518-
ast::Arm {
519-
attrs: vec!(),
520-
pats: vec!(@ast::Pat{
521-
id: ast::DUMMY_NODE_ID,
522-
span: self.sp,
523-
node: ast::PatRange(quote_expr!(self.cx, $start),
524-
quote_expr!(self.cx, $end)),
525-
}),
526-
guard: None,
527-
body: quote_expr!(self.cx, true),
528-
}
523+
let pat = self.cx.pat(self.sp, ast::PatRange(quote_expr!(self.cx, $start),
524+
quote_expr!(self.cx, $end)));
525+
self.cx.arm(self.sp, vec!(pat), expr_true)
529526
}).collect::<Vec<ast::Arm>>();
530527

531528
arms.push(self.wild_arm_expr(quote_expr!(self.cx, false)));
532529

533530
let match_on = quote_expr!(self.cx, c);
534-
self.dummy_expr(ast::ExprMatch(match_on, arms))
531+
self.cx.expr_match(self.sp, match_on, arms)
535532
}
536533

537534
// Generates code for checking a literal prefix of the search string.
538535
// The code is only generated if the regex *has* a literal prefix.
539536
// Otherwise, a no-op is returned.
540537
fn check_prefix(&self) -> @ast::Expr {
541538
if self.prog.prefix.len() == 0 {
542-
quote_expr!(self.cx, {})
539+
self.empty_block()
543540
} else {
544541
quote_expr!(self.cx,
545542
if clist.size == 0 {
@@ -562,24 +559,20 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
562559
// never be used, but is added to satisfy the compiler complaining about
563560
// non-exhaustive patterns.
564561
fn match_insts(&self, mut arms: Vec<ast::Arm>) -> @ast::Expr {
565-
let mat_pc = quote_expr!(self.cx, pc);
566-
arms.push(self.wild_arm_expr(quote_expr!(self.cx, {})));
567-
self.dummy_expr(ast::ExprMatch(mat_pc, arms))
562+
arms.push(self.wild_arm_expr(self.empty_block()));
563+
self.cx.expr_match(self.sp, quote_expr!(self.cx, pc), arms)
564+
}
565+
566+
fn empty_block(&self) -> @ast::Expr {
567+
quote_expr!(self.cx, {})
568568
}
569569

570570
// Creates a match arm for the instruction at `pc` with the expression
571571
// `body`.
572572
fn arm_inst(&self, pc: uint, body: @ast::Expr) -> ast::Arm {
573-
ast::Arm {
574-
attrs: vec!(),
575-
pats: vec!(@ast::Pat{
576-
id: ast::DUMMY_NODE_ID,
577-
span: self.sp,
578-
node: ast::PatLit(quote_expr!(self.cx, $pc)),
579-
}),
580-
guard: None,
581-
body: body,
582-
}
573+
let pc_pat = self.cx.pat_lit(self.sp, quote_expr!(self.cx, $pc));
574+
575+
self.cx.arm(self.sp, vec!(pc_pat), body)
583576
}
584577

585578
// Creates a wild-card match arm with the expression `body`.
@@ -596,56 +589,13 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
596589
}
597590
}
598591

599-
// Builds a `[a, b, .., len]` expression where each element is the result
600-
// of executing `to_expr`.
601-
fn vec_from_fn(&self, len: uint, to_expr: |&ExtCtxt| -> @ast::Expr)
602-
-> @ast::Expr {
603-
self.vec_expr(Vec::from_elem(len, ()).as_slice(),
604-
|cx, _| to_expr(cx))
605-
}
606592

607593
// Converts `xs` to a `[x1, x2, .., xN]` expression by calling `to_expr`
608594
// on each element in `xs`.
609-
fn vec_expr<T>(&self, xs: &[T], to_expr: |&ExtCtxt, &T| -> @ast::Expr)
595+
fn vec_expr<T, It: Iterator<T>>(&self, xs: It, to_expr: |&ExtCtxt, T| -> @ast::Expr)
610596
-> @ast::Expr {
611-
let mut exprs = vec!();
612-
for x in xs.iter() {
613-
exprs.push(to_expr(self.cx, x))
614-
}
615-
let vec_exprs = self.dummy_expr(ast::ExprVec(exprs));
616-
quote_expr!(self.cx, $vec_exprs)
617-
}
618-
619-
// Creates an expression with a dummy node ID given an underlying
620-
// `ast::Expr_`.
621-
fn dummy_expr(&self, e: ast::Expr_) -> @ast::Expr {
622-
@ast::Expr {
623-
id: ast::DUMMY_NODE_ID,
624-
node: e,
625-
span: self.sp,
626-
}
627-
}
628-
}
629-
630-
// This trait is defined in the quote module in the syntax crate, but I
631-
// don't think it's exported.
632-
// Interestingly, quote_expr! only requires that a 'to_tokens' method be
633-
// defined rather than satisfying a particular trait.
634-
#[doc(hidden)]
635-
trait ToTokens {
636-
fn to_tokens(&self, cx: &ExtCtxt) -> Vec<ast::TokenTree>;
637-
}
638-
639-
impl ToTokens for char {
640-
fn to_tokens(&self, _: &ExtCtxt) -> Vec<ast::TokenTree> {
641-
vec!(ast::TTTok(codemap::DUMMY_SP, token::LIT_CHAR((*self) as u32)))
642-
}
643-
}
644-
645-
impl ToTokens for bool {
646-
fn to_tokens(&self, _: &ExtCtxt) -> Vec<ast::TokenTree> {
647-
let ident = token::IDENT(token::str_to_ident(self.to_str()), false);
648-
vec!(ast::TTTok(codemap::DUMMY_SP, ident))
597+
let exprs = xs.map(|x| to_expr(self.cx, x)).collect();
598+
self.cx.expr_vec(self.sp, exprs)
649599
}
650600
}
651601

src/librustdoc/clean.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ use rustc::metadata::decoder;
2626

2727
use std::local_data;
2828
use std::strbuf::StrBuf;
29-
use std;
3029

3130
use core;
3231
use doctree;
@@ -1246,7 +1245,7 @@ fn lit_to_str(lit: &ast::Lit) -> ~str {
12461245
match lit.node {
12471246
ast::LitStr(ref st, _) => st.get().to_owned(),
12481247
ast::LitBinary(ref data) => format!("{:?}", data.as_slice()),
1249-
ast::LitChar(c) => "'".to_owned() + std::char::from_u32(c).unwrap().to_str() + "'",
1248+
ast::LitChar(c) => format!("'{}'", c),
12501249
ast::LitInt(i, _t) => i.to_str(),
12511250
ast::LitUint(u, _t) => u.to_str(),
12521251
ast::LitIntUnsuffixed(i) => i.to_str(),

src/libsyntax/ast.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -653,7 +653,7 @@ pub type Lit = Spanned<Lit_>;
653653
pub enum Lit_ {
654654
LitStr(InternedString, StrStyle),
655655
LitBinary(Rc<Vec<u8> >),
656-
LitChar(u32),
656+
LitChar(char),
657657
LitInt(i64, IntTy),
658658
LitUint(u64, UintTy),
659659
LitIntUnsuffixed(i64),

src/libsyntax/ext/bytes.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ use ext::base::*;
1616
use ext::base;
1717
use ext::build::AstBuilder;
1818

19-
use std::char;
20-
2119
pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> ~base::MacResult {
2220
// Gather all argument expressions
2321
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]) ->
5957

6058
// char literal, push to vector expression
6159
ast::LitChar(v) => {
62-
if char::from_u32(v).unwrap().is_ascii() {
60+
if v.is_ascii() {
6361
bytes.push(cx.expr_u8(expr.span, v as u8));
6462
} else {
6563
cx.span_err(expr.span, "non-ascii char literal in bytes!")

src/libsyntax/ext/concat.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ use ext::base;
1414
use ext::build::AstBuilder;
1515
use parse::token;
1616

17-
use std::char;
1817
use std::strbuf::StrBuf;
1918

2019
pub fn expand_syntax_ext(cx: &mut base::ExtCtxt,
@@ -35,7 +34,7 @@ pub fn expand_syntax_ext(cx: &mut base::ExtCtxt,
3534
accumulator.push_str(s.get());
3635
}
3736
ast::LitChar(c) => {
38-
accumulator.push_char(char::from_u32(c).unwrap());
37+
accumulator.push_char(c);
3938
}
4039
ast::LitInt(i, _) | ast::LitIntUnsuffixed(i) => {
4140
accumulator.push_str(format!("{}", i));

src/libsyntax/ext/format.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -561,7 +561,7 @@ impl<'a, 'b> Context<'a, 'b> {
561561

562562
// Translate the format
563563
let fill = match arg.format.fill { Some(c) => c, None => ' ' };
564-
let fill = self.ecx.expr_lit(sp, ast::LitChar(fill as u32));
564+
let fill = self.ecx.expr_lit(sp, ast::LitChar(fill));
565565
let align = match arg.format.align {
566566
parse::AlignLeft => {
567567
self.ecx.path_global(sp, self.parsepath("AlignLeft"))

src/libsyntax/ext/quote.rs

+23
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,26 @@ pub mod rt {
125125
}
126126
}
127127

128+
impl ToSource for () {
129+
fn to_source(&self) -> ~str {
130+
"()".to_owned()
131+
}
132+
}
133+
134+
impl ToSource for bool {
135+
fn to_source(&self) -> ~str {
136+
let lit = dummy_spanned(ast::LitBool(*self));
137+
pprust::lit_to_str(&lit)
138+
}
139+
}
140+
141+
impl ToSource for char {
142+
fn to_source(&self) -> ~str {
143+
let lit = dummy_spanned(ast::LitChar(*self));
144+
pprust::lit_to_str(&lit)
145+
}
146+
}
147+
128148
impl ToSource for int {
129149
fn to_source(&self) -> ~str {
130150
let lit = dummy_spanned(ast::LitInt(*self as i64, ast::TyI));
@@ -227,6 +247,9 @@ pub mod rt {
227247
impl_to_tokens!(@ast::Expr)
228248
impl_to_tokens!(ast::Block)
229249
impl_to_tokens_self!(&'a str)
250+
impl_to_tokens!(())
251+
impl_to_tokens!(char)
252+
impl_to_tokens!(bool)
230253
impl_to_tokens!(int)
231254
impl_to_tokens!(i8)
232255
impl_to_tokens!(i16)

src/libsyntax/parse/lexer.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -874,7 +874,7 @@ fn next_token_inner(rdr: &mut StringReader) -> token::Token {
874874
"unterminated character constant".to_owned());
875875
}
876876
bump(rdr); // advance curr past token
877-
return token::LIT_CHAR(c2 as u32);
877+
return token::LIT_CHAR(c2);
878878
}
879879
'"' => {
880880
let mut accum_str = StrBuf::new();
@@ -1097,17 +1097,17 @@ mod test {
10971097

10981098
#[test] fn character_a() {
10991099
assert_eq!(setup(&mk_sh(), "'a'".to_owned()).next_token().tok,
1100-
token::LIT_CHAR('a' as u32));
1100+
token::LIT_CHAR('a'));
11011101
}
11021102

11031103
#[test] fn character_space() {
11041104
assert_eq!(setup(&mk_sh(), "' '".to_owned()).next_token().tok,
1105-
token::LIT_CHAR(' ' as u32));
1105+
token::LIT_CHAR(' '));
11061106
}
11071107

11081108
#[test] fn character_escaped() {
11091109
assert_eq!(setup(&mk_sh(), "'\\n'".to_owned()).next_token().tok,
1110-
token::LIT_CHAR('\n' as u32));
1110+
token::LIT_CHAR('\n'));
11111111
}
11121112

11131113
#[test] fn lifetime_name() {
@@ -1128,7 +1128,7 @@ mod test {
11281128

11291129
#[test] fn nested_block_comments() {
11301130
assert_eq!(setup(&mk_sh(), "/* /* */ */'a'".to_owned()).next_token().tok,
1131-
token::LIT_CHAR('a' as u32));
1131+
token::LIT_CHAR('a'));
11321132
}
11331133

11341134
}

0 commit comments

Comments
 (0)