@@ -139,13 +139,20 @@ struct MatcherPos {
139139 sep : Option < Token > ,
140140 idx : usize ,
141141 up : Option < Box < MatcherPos > > ,
142- matches : Vec < Vec < Rc < NamedMatch > > > ,
142+ matches : Vec < Rc < Vec < NamedMatch > > > ,
143143 match_lo : usize ,
144144 match_cur : usize ,
145145 match_hi : usize ,
146146 sp_lo : BytePos ,
147147}
148148
149+ impl MatcherPos {
150+ fn push_match ( & mut self , idx : usize , m : NamedMatch ) {
151+ let matches = Rc :: make_mut ( & mut self . matches [ idx] ) ;
152+ matches. push ( m) ;
153+ }
154+ }
155+
149156pub type NamedParseResult = ParseResult < HashMap < Ident , Rc < NamedMatch > > > ;
150157
151158pub fn count_names ( ms : & [ TokenTree ] ) -> usize {
@@ -199,14 +206,15 @@ fn initial_matcher_pos(ms: Vec<TokenTree>, lo: BytePos) -> Box<MatcherPos> {
199206/// only on the nesting depth of `ast::TTSeq`s in the originating
200207/// token tree it was derived from.
201208
209+ #[ derive( Debug , Clone ) ]
202210pub enum NamedMatch {
203- MatchedSeq ( Vec < Rc < NamedMatch > > , syntax_pos:: Span ) ,
211+ MatchedSeq ( Rc < Vec < NamedMatch > > , syntax_pos:: Span ) ,
204212 MatchedNonterminal ( Rc < Nonterminal > )
205213}
206214
207- fn nameize < I : Iterator < Item =Rc < NamedMatch > > > ( sess : & ParseSess , ms : & [ TokenTree ] , mut res : I )
215+ fn nameize < I : Iterator < Item =NamedMatch > > ( sess : & ParseSess , ms : & [ TokenTree ] , mut res : I )
208216 -> NamedParseResult {
209- fn n_rec < I : Iterator < Item =Rc < NamedMatch > > > ( sess : & ParseSess , m : & TokenTree , mut res : & mut I ,
217+ fn n_rec < I : Iterator < Item =NamedMatch > > ( sess : & ParseSess , m : & TokenTree , mut res : & mut I ,
210218 ret_val : & mut HashMap < Ident , Rc < NamedMatch > > )
211219 -> Result < ( ) , ( syntax_pos:: Span , String ) > {
212220 match * m {
@@ -228,7 +236,8 @@ fn nameize<I: Iterator<Item=Rc<NamedMatch>>>(sess: &ParseSess, ms: &[TokenTree],
228236 TokenTree :: MetaVarDecl ( sp, bind_name, _) => {
229237 match ret_val. entry ( bind_name) {
230238 Vacant ( spot) => {
231- spot. insert ( res. next ( ) . unwrap ( ) ) ;
239+ // FIXME(simulacrum): Don't construct Rc here
240+ spot. insert ( Rc :: new ( res. next ( ) . unwrap ( ) ) ) ;
232241 }
233242 Occupied ( ..) => {
234243 return Err ( ( sp, format ! ( "duplicated bind name: {}" , bind_name) ) )
@@ -280,8 +289,8 @@ fn token_name_eq(t1 : &Token, t2 : &Token) -> bool {
280289 }
281290}
282291
283- fn create_matches ( len : usize ) -> Vec < Vec < Rc < NamedMatch > > > {
284- ( 0 ..len) . into_iter ( ) . map ( |_| Vec :: new ( ) ) . collect ( )
292+ fn create_matches ( len : usize ) -> Vec < Rc < Vec < NamedMatch > > > {
293+ ( 0 ..len) . into_iter ( ) . map ( |_| Rc :: new ( Vec :: new ( ) ) ) . collect ( )
285294}
286295
287296fn inner_parse_loop ( sess : & ParseSess ,
@@ -320,15 +329,10 @@ fn inner_parse_loop(sess: &ParseSess,
320329 // update matches (the MBE "parse tree") by appending
321330 // each tree as a subtree.
322331
323- // I bet this is a perf problem: we're preemptively
324- // doing a lot of array work that will get thrown away
325- // most of the time.
326-
327332 // Only touch the binders we have actually bound
328333 for idx in ei. match_lo ..ei. match_hi {
329334 let sub = ei. matches [ idx] . clone ( ) ;
330- new_pos. matches [ idx]
331- . push ( Rc :: new ( MatchedSeq ( sub, Span { lo : ei. sp_lo , ..span } ) ) ) ;
335+ new_pos. push_match ( idx, MatchedSeq ( sub, Span { lo : ei. sp_lo , ..span } ) ) ;
332336 }
333337
334338 new_pos. match_cur = ei. match_hi ;
@@ -362,7 +366,7 @@ fn inner_parse_loop(sess: &ParseSess,
362366 new_ei. match_cur += seq. num_captures ;
363367 new_ei. idx += 1 ;
364368 for idx in ei. match_cur ..ei. match_cur + seq. num_captures {
365- new_ei. matches [ idx] . push ( Rc :: new ( MatchedSeq ( vec ! [ ] , sp) ) ) ;
369+ new_ei. push_match ( idx, MatchedSeq ( Rc :: new ( vec ! [ ] ) , sp) ) ;
366370 }
367371 cur_eis. push ( new_ei) ;
368372 }
@@ -446,7 +450,9 @@ pub fn parse(sess: &ParseSess,
446450 /* error messages here could be improved with links to orig. rules */
447451 if token_name_eq ( & parser. token , & token:: Eof ) {
448452 if eof_eis. len ( ) == 1 {
449- let matches = eof_eis[ 0 ] . matches . iter_mut ( ) . map ( |mut dv| dv. pop ( ) . unwrap ( ) ) ;
453+ let matches = eof_eis[ 0 ] . matches . iter_mut ( ) . map ( |mut dv| {
454+ Rc :: make_mut ( dv) . pop ( ) . unwrap ( )
455+ } ) ;
450456 return nameize ( sess, ms, matches) ;
451457 } else if eof_eis. len ( ) > 1 {
452458 return Error ( parser. span , "ambiguity: multiple successful parses" . to_string ( ) ) ;
@@ -479,8 +485,8 @@ pub fn parse(sess: &ParseSess,
479485 let mut ei = bb_eis. pop ( ) . unwrap ( ) ;
480486 if let TokenTree :: MetaVarDecl ( span, _, ident) = ei. top_elts . get_tt ( ei. idx ) {
481487 let match_cur = ei. match_cur ;
482- ei. matches [ match_cur ] . push ( Rc :: new ( MatchedNonterminal (
483- Rc :: new ( parse_nt ( & mut parser, span, & ident. name . as_str ( ) ) ) ) ) ) ;
488+ ei. push_match ( match_cur ,
489+ MatchedNonterminal ( Rc :: new ( parse_nt ( & mut parser, span, & ident. name . as_str ( ) ) ) ) ) ;
484490 ei. idx += 1 ;
485491 ei. match_cur += 1 ;
486492 } else {
0 commit comments