diff options
Diffstat (limited to 'crates/mbe')
-rw-r--r-- | crates/mbe/src/expander.rs | 4 | ||||
-rw-r--r-- | crates/mbe/src/expander/matcher.rs | 266 | ||||
-rw-r--r-- | crates/mbe/src/expander/transcriber.rs | 19 |
3 files changed, 220 insertions, 69 deletions
diff --git a/crates/mbe/src/expander.rs b/crates/mbe/src/expander.rs index 2efff8f52..3197c834c 100644 --- a/crates/mbe/src/expander.rs +++ b/crates/mbe/src/expander.rs | |||
@@ -5,7 +5,7 @@ | |||
5 | mod matcher; | 5 | mod matcher; |
6 | mod transcriber; | 6 | mod transcriber; |
7 | 7 | ||
8 | use smallvec::SmallVec; | 8 | use rustc_hash::FxHashMap; |
9 | use syntax::SmolStr; | 9 | use syntax::SmolStr; |
10 | 10 | ||
11 | use crate::{ExpandError, ExpandResult}; | 11 | use crate::{ExpandError, ExpandResult}; |
@@ -96,7 +96,7 @@ pub(crate) fn expand_rules( | |||
96 | /// many is not a plain `usize`, but an `&[usize]`. | 96 | /// many is not a plain `usize`, but an `&[usize]`. |
97 | #[derive(Debug, Default, Clone, PartialEq, Eq)] | 97 | #[derive(Debug, Default, Clone, PartialEq, Eq)] |
98 | struct Bindings { | 98 | struct Bindings { |
99 | inner: SmallVec<[(SmolStr, Binding); 4]>, | 99 | inner: FxHashMap<SmolStr, Binding>, |
100 | } | 100 | } |
101 | 101 | ||
102 | #[derive(Debug, Clone, PartialEq, Eq)] | 102 | #[derive(Debug, Clone, PartialEq, Eq)] |
diff --git a/crates/mbe/src/expander/matcher.rs b/crates/mbe/src/expander/matcher.rs index 9d3d28055..2c69e8968 100644 --- a/crates/mbe/src/expander/matcher.rs +++ b/crates/mbe/src/expander/matcher.rs | |||
@@ -59,6 +59,8 @@ | |||
59 | //! eof: [a $( a )* a b ·] | 59 | //! eof: [a $( a )* a b ·] |
60 | //! ``` | 60 | //! ``` |
61 | 61 | ||
62 | use std::rc::Rc; | ||
63 | |||
62 | use crate::{ | 64 | use crate::{ |
63 | expander::{Binding, Bindings, Fragment}, | 65 | expander::{Binding, Bindings, Fragment}, |
64 | parser::{Op, OpDelimited, OpDelimitedIter, RepeatKind, Separator}, | 66 | parser::{Op, OpDelimited, OpDelimitedIter, RepeatKind, Separator}, |
@@ -76,43 +78,15 @@ impl Bindings { | |||
76 | // FIXME: Do we have a better way to represent an empty token ? | 78 | // FIXME: Do we have a better way to represent an empty token ? |
77 | // Insert an empty subtree for empty token | 79 | // Insert an empty subtree for empty token |
78 | let tt = tt::Subtree::default().into(); | 80 | let tt = tt::Subtree::default().into(); |
79 | self.inner.push((name.clone(), Binding::Fragment(Fragment::Tokens(tt)))); | 81 | self.inner.insert(name.clone(), Binding::Fragment(Fragment::Tokens(tt))); |
80 | } | 82 | } |
81 | 83 | ||
82 | fn push_empty(&mut self, name: &SmolStr) { | 84 | fn push_empty(&mut self, name: &SmolStr) { |
83 | self.inner.push((name.clone(), Binding::Empty)); | 85 | self.inner.insert(name.clone(), Binding::Empty); |
84 | } | ||
85 | |||
86 | fn push_nested(&mut self, idx: usize, nested: Bindings) -> Result<(), ExpandError> { | ||
87 | for (key, value) in nested.inner { | ||
88 | if self.get_mut(&key).is_none() { | ||
89 | self.inner.push((key.clone(), Binding::Nested(Vec::new()))); | ||
90 | } | ||
91 | match self.get_mut(&key) { | ||
92 | Some(Binding::Nested(it)) => { | ||
93 | // insert empty nested bindings before this one | ||
94 | while it.len() < idx { | ||
95 | it.push(Binding::Nested(vec![])); | ||
96 | } | ||
97 | it.push(value); | ||
98 | } | ||
99 | _ => { | ||
100 | return Err(ExpandError::BindingError(format!( | ||
101 | "could not find binding `{}`", | ||
102 | key | ||
103 | ))); | ||
104 | } | ||
105 | } | ||
106 | } | ||
107 | Ok(()) | ||
108 | } | ||
109 | |||
110 | fn get_mut(&mut self, name: &str) -> Option<&mut Binding> { | ||
111 | self.inner.iter_mut().find_map(|(n, b)| if n == name { Some(b) } else { None }) | ||
112 | } | 86 | } |
113 | 87 | ||
114 | fn bindings(&self) -> impl Iterator<Item = &Binding> { | 88 | fn bindings(&self) -> impl Iterator<Item = &Binding> { |
115 | self.inner.iter().map(|(_, b)| b) | 89 | self.inner.values() |
116 | } | 90 | } |
117 | } | 91 | } |
118 | 92 | ||
@@ -163,6 +137,181 @@ pub(super) fn match_(pattern: &MetaTemplate, input: &tt::Subtree) -> Match { | |||
163 | } | 137 | } |
164 | 138 | ||
165 | #[derive(Debug, Clone)] | 139 | #[derive(Debug, Clone)] |
140 | enum BindingKind { | ||
141 | Empty(SmolStr), | ||
142 | Optional(SmolStr), | ||
143 | Fragment(SmolStr, Fragment), | ||
144 | Nested(usize, usize), | ||
145 | } | ||
146 | |||
147 | #[derive(Debug, Clone)] | ||
148 | struct BindingsIdx(usize, usize); | ||
149 | |||
150 | #[derive(Debug, Clone)] | ||
151 | enum LinkNode<T> { | ||
152 | Node(T), | ||
153 | Parent { idx: usize, len: usize }, | ||
154 | } | ||
155 | |||
156 | #[derive(Default)] | ||
157 | struct BindingsBuilder { | ||
158 | nodes: Vec<Vec<LinkNode<Rc<BindingKind>>>>, | ||
159 | nested: Vec<Vec<LinkNode<usize>>>, | ||
160 | } | ||
161 | |||
162 | impl BindingsBuilder { | ||
163 | fn alloc(&mut self) -> BindingsIdx { | ||
164 | let idx = self.nodes.len(); | ||
165 | self.nodes.push(Vec::new()); | ||
166 | let nidx = self.nested.len(); | ||
167 | self.nested.push(Vec::new()); | ||
168 | BindingsIdx(idx, nidx) | ||
169 | } | ||
170 | |||
171 | fn copy(&mut self, bindings: &BindingsIdx) -> BindingsIdx { | ||
172 | let idx = copy_parent(bindings.0, &mut self.nodes); | ||
173 | let nidx = copy_parent(bindings.1, &mut self.nested); | ||
174 | return BindingsIdx(idx, nidx); | ||
175 | |||
176 | fn copy_parent<T>(idx: usize, target: &mut Vec<Vec<LinkNode<T>>>) -> usize | ||
177 | where | ||
178 | T: Clone, | ||
179 | { | ||
180 | let new_idx = target.len(); | ||
181 | let len = target[idx].len(); | ||
182 | if len < 4 { | ||
183 | target.push(target[idx].clone()) | ||
184 | } else { | ||
185 | target.push(vec![LinkNode::Parent { idx, len }]); | ||
186 | } | ||
187 | new_idx | ||
188 | } | ||
189 | } | ||
190 | |||
191 | fn push_empty(&mut self, idx: &mut BindingsIdx, var: &SmolStr) { | ||
192 | self.nodes[idx.0].push(LinkNode::Node(Rc::new(BindingKind::Empty(var.clone())))); | ||
193 | } | ||
194 | |||
195 | fn push_optional(&mut self, idx: &mut BindingsIdx, var: &SmolStr) { | ||
196 | self.nodes[idx.0].push(LinkNode::Node(Rc::new(BindingKind::Optional(var.clone())))); | ||
197 | } | ||
198 | |||
199 | fn push_fragment(&mut self, idx: &mut BindingsIdx, var: &SmolStr, fragment: Fragment) { | ||
200 | self.nodes[idx.0] | ||
201 | .push(LinkNode::Node(Rc::new(BindingKind::Fragment(var.clone(), fragment)))); | ||
202 | } | ||
203 | |||
204 | fn push_nested(&mut self, parent: &mut BindingsIdx, child: &BindingsIdx) { | ||
205 | let BindingsIdx(idx, nidx) = self.copy(&child); | ||
206 | self.nodes[parent.0].push(LinkNode::Node(Rc::new(BindingKind::Nested(idx, nidx)))); | ||
207 | } | ||
208 | |||
209 | fn push_default(&mut self, idx: &mut BindingsIdx) { | ||
210 | self.nested[idx.1].push(LinkNode::Node(idx.0)); | ||
211 | let new_idx = self.nodes.len(); | ||
212 | self.nodes.push(Vec::new()); | ||
213 | idx.0 = new_idx; | ||
214 | } | ||
215 | |||
216 | fn build(self, idx: &BindingsIdx) -> Bindings { | ||
217 | let mut bindings = Bindings::default(); | ||
218 | self.build_inner(&mut bindings, &self.nodes[idx.0]); | ||
219 | bindings | ||
220 | } | ||
221 | |||
222 | fn build_inner(&self, bindings: &mut Bindings, link_nodes: &Vec<LinkNode<Rc<BindingKind>>>) { | ||
223 | let mut nodes = Vec::new(); | ||
224 | self.collect_nodes(&link_nodes, &mut nodes); | ||
225 | |||
226 | for cmd in nodes { | ||
227 | match &**cmd { | ||
228 | BindingKind::Empty(name) => { | ||
229 | bindings.push_empty(name); | ||
230 | } | ||
231 | BindingKind::Optional(name) => { | ||
232 | bindings.push_optional(name); | ||
233 | } | ||
234 | BindingKind::Fragment(name, fragment) => { | ||
235 | bindings.inner.insert(name.clone(), Binding::Fragment(fragment.clone())); | ||
236 | } | ||
237 | BindingKind::Nested(idx, nested_idx) => { | ||
238 | let mut nested_nodes = Vec::new(); | ||
239 | self.collect_nested(*idx, *nested_idx, &mut nested_nodes); | ||
240 | |||
241 | for (idx, iter) in nested_nodes.into_iter().enumerate() { | ||
242 | for (key, value) in &iter.inner { | ||
243 | let bindings = bindings | ||
244 | .inner | ||
245 | .entry(key.clone()) | ||
246 | .or_insert_with(|| Binding::Nested(Vec::new())); | ||
247 | |||
248 | if let Binding::Nested(it) = bindings { | ||
249 | // insert empty nested bindings before this one | ||
250 | while it.len() < idx { | ||
251 | it.push(Binding::Nested(Vec::new())); | ||
252 | } | ||
253 | it.push(value.clone()); | ||
254 | } | ||
255 | } | ||
256 | } | ||
257 | } | ||
258 | } | ||
259 | } | ||
260 | } | ||
261 | |||
262 | fn collect_nested_ref<'a>( | ||
263 | &'a self, | ||
264 | id: usize, | ||
265 | len: usize, | ||
266 | nested_refs: &mut Vec<&'a Vec<LinkNode<Rc<BindingKind>>>>, | ||
267 | ) { | ||
268 | self.nested[id].iter().take(len).for_each(|it| match it { | ||
269 | LinkNode::Node(id) => nested_refs.push(&self.nodes[*id]), | ||
270 | LinkNode::Parent { idx, len } => self.collect_nested_ref(*idx, *len, nested_refs), | ||
271 | }); | ||
272 | } | ||
273 | |||
274 | fn collect_nested(&self, idx: usize, nested_idx: usize, nested: &mut Vec<Bindings>) { | ||
275 | let last = &self.nodes[idx]; | ||
276 | let mut nested_refs = Vec::new(); | ||
277 | self.nested[nested_idx].iter().for_each(|it| match *it { | ||
278 | LinkNode::Node(idx) => nested_refs.push(&self.nodes[idx]), | ||
279 | LinkNode::Parent { idx, len } => self.collect_nested_ref(idx, len, &mut nested_refs), | ||
280 | }); | ||
281 | nested_refs.push(last); | ||
282 | |||
283 | nested_refs.into_iter().for_each(|iter| { | ||
284 | let mut child_bindings = Bindings::default(); | ||
285 | self.build_inner(&mut child_bindings, &iter); | ||
286 | nested.push(child_bindings) | ||
287 | }) | ||
288 | } | ||
289 | |||
290 | fn collect_nodes_ref<'a>( | ||
291 | &'a self, | ||
292 | id: usize, | ||
293 | len: usize, | ||
294 | nodes: &mut Vec<&'a Rc<BindingKind>>, | ||
295 | ) { | ||
296 | self.nodes[id].iter().take(len).for_each(|it| match it { | ||
297 | LinkNode::Node(it) => nodes.push(it), | ||
298 | LinkNode::Parent { idx, len } => self.collect_nodes_ref(*idx, *len, nodes), | ||
299 | }); | ||
300 | } | ||
301 | |||
302 | fn collect_nodes<'a>( | ||
303 | &'a self, | ||
304 | link_nodes: &'a Vec<LinkNode<Rc<BindingKind>>>, | ||
305 | nodes: &mut Vec<&'a Rc<BindingKind>>, | ||
306 | ) { | ||
307 | link_nodes.into_iter().for_each(|it| match it { | ||
308 | LinkNode::Node(it) => nodes.push(it), | ||
309 | LinkNode::Parent { idx, len } => self.collect_nodes_ref(*idx, *len, nodes), | ||
310 | }); | ||
311 | } | ||
312 | } | ||
313 | |||
314 | #[derive(Debug, Clone)] | ||
166 | struct MatchState<'t> { | 315 | struct MatchState<'t> { |
167 | /// The position of the "dot" in this matcher | 316 | /// The position of the "dot" in this matcher |
168 | dot: OpDelimitedIter<'t>, | 317 | dot: OpDelimitedIter<'t>, |
@@ -187,7 +336,7 @@ struct MatchState<'t> { | |||
187 | sep_parsed: Option<usize>, | 336 | sep_parsed: Option<usize>, |
188 | 337 | ||
189 | /// Matched meta variables bindings | 338 | /// Matched meta variables bindings |
190 | bindings: SmallVec<[Bindings; 4]>, | 339 | bindings: BindingsIdx, |
191 | 340 | ||
192 | /// Cached result of meta variable parsing | 341 | /// Cached result of meta variable parsing |
193 | meta_result: Option<(TtIter<'t>, ExpandResult<Option<Fragment>>)>, | 342 | meta_result: Option<(TtIter<'t>, ExpandResult<Option<Fragment>>)>, |
@@ -218,6 +367,7 @@ fn match_loop_inner<'t>( | |||
218 | src: TtIter<'t>, | 367 | src: TtIter<'t>, |
219 | stack: &[TtIter<'t>], | 368 | stack: &[TtIter<'t>], |
220 | res: &mut Match, | 369 | res: &mut Match, |
370 | bindings_builder: &mut BindingsBuilder, | ||
221 | cur_items: &mut SmallVec<[MatchState<'t>; 1]>, | 371 | cur_items: &mut SmallVec<[MatchState<'t>; 1]>, |
222 | bb_items: &mut SmallVec<[MatchState<'t>; 1]>, | 372 | bb_items: &mut SmallVec<[MatchState<'t>; 1]>, |
223 | next_items: &mut Vec<MatchState<'t>>, | 373 | next_items: &mut Vec<MatchState<'t>>, |
@@ -251,12 +401,10 @@ fn match_loop_inner<'t>( | |||
251 | if item.sep_parsed.is_none() { | 401 | if item.sep_parsed.is_none() { |
252 | // Get the `up` matcher | 402 | // Get the `up` matcher |
253 | let mut new_pos = *item.up.clone().unwrap(); | 403 | let mut new_pos = *item.up.clone().unwrap(); |
404 | new_pos.bindings = bindings_builder.copy(&new_pos.bindings); | ||
254 | // Add matches from this repetition to the `matches` of `up` | 405 | // Add matches from this repetition to the `matches` of `up` |
255 | if let Some(bindings) = new_pos.bindings.last_mut() { | 406 | bindings_builder.push_nested(&mut new_pos.bindings, &item.bindings); |
256 | for (i, b) in item.bindings.iter_mut().enumerate() { | 407 | |
257 | bindings.push_nested(i, b.clone()).unwrap(); | ||
258 | } | ||
259 | } | ||
260 | // Move the "dot" past the repetition in `up` | 408 | // Move the "dot" past the repetition in `up` |
261 | new_pos.dot.next(); | 409 | new_pos.dot.next(); |
262 | new_pos.is_error = new_pos.is_error || item.is_error; | 410 | new_pos.is_error = new_pos.is_error || item.is_error; |
@@ -280,7 +428,7 @@ fn match_loop_inner<'t>( | |||
280 | else if item.sep_kind != Some(RepeatKind::ZeroOrOne) { | 428 | else if item.sep_kind != Some(RepeatKind::ZeroOrOne) { |
281 | item.dot = item.dot.reset(); | 429 | item.dot = item.dot.reset(); |
282 | item.sep_parsed = None; | 430 | item.sep_parsed = None; |
283 | item.bindings.push(Bindings::default()); | 431 | bindings_builder.push_default(&mut item.bindings); |
284 | cur_items.push(item); | 432 | cur_items.push(item); |
285 | } | 433 | } |
286 | } else { | 434 | } else { |
@@ -298,12 +446,12 @@ fn match_loop_inner<'t>( | |||
298 | OpDelimited::Op(Op::Repeat { tokens, kind, separator }) => { | 446 | OpDelimited::Op(Op::Repeat { tokens, kind, separator }) => { |
299 | if matches!(kind, RepeatKind::ZeroOrMore | RepeatKind::ZeroOrOne) { | 447 | if matches!(kind, RepeatKind::ZeroOrMore | RepeatKind::ZeroOrOne) { |
300 | let mut new_item = item.clone(); | 448 | let mut new_item = item.clone(); |
449 | new_item.bindings = bindings_builder.copy(&new_item.bindings); | ||
301 | new_item.dot.next(); | 450 | new_item.dot.next(); |
302 | let mut vars = Vec::new(); | 451 | let mut vars = Vec::new(); |
303 | let bindings = new_item.bindings.last_mut().unwrap(); | ||
304 | collect_vars(&mut vars, tokens); | 452 | collect_vars(&mut vars, tokens); |
305 | for var in vars { | 453 | for var in vars { |
306 | bindings.push_empty(&var); | 454 | bindings_builder.push_empty(&mut new_item.bindings, &var); |
307 | } | 455 | } |
308 | cur_items.push(new_item); | 456 | cur_items.push(new_item); |
309 | } | 457 | } |
@@ -314,7 +462,7 @@ fn match_loop_inner<'t>( | |||
314 | sep: separator.clone(), | 462 | sep: separator.clone(), |
315 | sep_kind: Some(*kind), | 463 | sep_kind: Some(*kind), |
316 | sep_parsed: None, | 464 | sep_parsed: None, |
317 | bindings: smallvec![Bindings::default()], | 465 | bindings: bindings_builder.alloc(), |
318 | meta_result: None, | 466 | meta_result: None, |
319 | is_error: false, | 467 | is_error: false, |
320 | }) | 468 | }) |
@@ -339,7 +487,7 @@ fn match_loop_inner<'t>( | |||
339 | item.meta_result = Some((fork, match_res)); | 487 | item.meta_result = Some((fork, match_res)); |
340 | try_push!(bb_items, item); | 488 | try_push!(bb_items, item); |
341 | } else { | 489 | } else { |
342 | item.bindings.last_mut().unwrap().push_optional(name); | 490 | bindings_builder.push_optional(&mut item.bindings, &name); |
343 | item.dot.next(); | 491 | item.dot.next(); |
344 | cur_items.push(item); | 492 | cur_items.push(item); |
345 | } | 493 | } |
@@ -348,11 +496,11 @@ fn match_loop_inner<'t>( | |||
348 | res.add_err(err); | 496 | res.add_err(err); |
349 | match match_res.value { | 497 | match match_res.value { |
350 | Some(fragment) => { | 498 | Some(fragment) => { |
351 | item.bindings | 499 | bindings_builder.push_fragment( |
352 | .last_mut() | 500 | &mut item.bindings, |
353 | .unwrap() | 501 | &name, |
354 | .inner | 502 | fragment, |
355 | .push((name.clone(), Binding::Fragment(fragment))); | 503 | ); |
356 | } | 504 | } |
357 | _ => {} | 505 | _ => {} |
358 | } | 506 | } |
@@ -394,6 +542,8 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree) -> Match { | |||
394 | let mut res = Match::default(); | 542 | let mut res = Match::default(); |
395 | let mut error_reover_item = None; | 543 | let mut error_reover_item = None; |
396 | 544 | ||
545 | let mut bindings_builder = BindingsBuilder::default(); | ||
546 | |||
397 | let mut cur_items = smallvec![MatchState { | 547 | let mut cur_items = smallvec![MatchState { |
398 | dot: pattern.iter_delimited(None), | 548 | dot: pattern.iter_delimited(None), |
399 | stack: Default::default(), | 549 | stack: Default::default(), |
@@ -401,7 +551,7 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree) -> Match { | |||
401 | sep: None, | 551 | sep: None, |
402 | sep_kind: None, | 552 | sep_kind: None, |
403 | sep_parsed: None, | 553 | sep_parsed: None, |
404 | bindings: smallvec![Bindings::default()], | 554 | bindings: bindings_builder.alloc(), |
405 | is_error: false, | 555 | is_error: false, |
406 | meta_result: None, | 556 | meta_result: None, |
407 | }]; | 557 | }]; |
@@ -419,6 +569,7 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree) -> Match { | |||
419 | src.clone(), | 569 | src.clone(), |
420 | &stack, | 570 | &stack, |
421 | &mut res, | 571 | &mut res, |
572 | &mut bindings_builder, | ||
422 | &mut cur_items, | 573 | &mut cur_items, |
423 | &mut bb_items, | 574 | &mut bb_items, |
424 | &mut next_items, | 575 | &mut next_items, |
@@ -428,9 +579,9 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree) -> Match { | |||
428 | stdx::always!(cur_items.is_empty()); | 579 | stdx::always!(cur_items.is_empty()); |
429 | 580 | ||
430 | if error_items.len() > 0 { | 581 | if error_items.len() > 0 { |
431 | error_reover_item = error_items.pop(); | 582 | error_reover_item = error_items.pop().map(|it| it.bindings); |
432 | } else if eof_items.len() > 0 { | 583 | } else if eof_items.len() > 0 { |
433 | error_reover_item = Some(eof_items[0].clone()); | 584 | error_reover_item = Some(eof_items[0].bindings.clone()); |
434 | } | 585 | } |
435 | 586 | ||
436 | // We need to do some post processing after the `match_loop_inner`. | 587 | // We need to do some post processing after the `match_loop_inner`. |
@@ -440,11 +591,11 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree) -> Match { | |||
440 | if eof_items.len() == 1 { | 591 | if eof_items.len() == 1 { |
441 | // remove all errors, because it is the correct answer ! | 592 | // remove all errors, because it is the correct answer ! |
442 | res = Match::default(); | 593 | res = Match::default(); |
443 | res.bindings = eof_items[0].bindings[0].clone(); | 594 | res.bindings = bindings_builder.build(&eof_items[0].bindings); |
444 | } else { | 595 | } else { |
445 | // Error recovery | 596 | // Error recovery |
446 | if error_reover_item.is_some() { | 597 | if error_reover_item.is_some() { |
447 | res.bindings = error_reover_item.unwrap().bindings[0].clone(); | 598 | res.bindings = bindings_builder.build(&error_reover_item.unwrap()); |
448 | } | 599 | } |
449 | res.add_err(ExpandError::UnexpectedToken); | 600 | res.add_err(ExpandError::UnexpectedToken); |
450 | } | 601 | } |
@@ -467,8 +618,8 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree) -> Match { | |||
467 | } | 618 | } |
468 | res.add_err(err!("leftover tokens")); | 619 | res.add_err(err!("leftover tokens")); |
469 | 620 | ||
470 | if let Some(mut error_reover_item) = error_reover_item { | 621 | if let Some(error_reover_item) = error_reover_item { |
471 | res.bindings = error_reover_item.bindings.remove(0); | 622 | res.bindings = bindings_builder.build(&error_reover_item); |
472 | } | 623 | } |
473 | return res; | 624 | return res; |
474 | } | 625 | } |
@@ -494,12 +645,13 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree) -> Match { | |||
494 | 645 | ||
495 | if let Some(OpDelimited::Op(Op::Var { name, .. })) = item.dot.peek() { | 646 | if let Some(OpDelimited::Op(Op::Var { name, .. })) = item.dot.peek() { |
496 | let (iter, match_res) = item.meta_result.take().unwrap(); | 647 | let (iter, match_res) = item.meta_result.take().unwrap(); |
497 | let bindings = item.bindings.last_mut().unwrap(); | ||
498 | match match_res.value { | 648 | match match_res.value { |
499 | Some(fragment) => { | 649 | Some(fragment) => { |
500 | bindings.inner.push((name.clone(), Binding::Fragment(fragment))); | 650 | bindings_builder.push_fragment(&mut item.bindings, &name, fragment); |
651 | } | ||
652 | None if match_res.err.is_none() => { | ||
653 | bindings_builder.push_optional(&mut item.bindings, &name); | ||
501 | } | 654 | } |
502 | None if match_res.err.is_none() => bindings.push_optional(name), | ||
503 | _ => {} | 655 | _ => {} |
504 | } | 656 | } |
505 | if let Some(err) = match_res.err { | 657 | if let Some(err) = match_res.err { |
diff --git a/crates/mbe/src/expander/transcriber.rs b/crates/mbe/src/expander/transcriber.rs index ad9953a7d..dd7fa97d7 100644 --- a/crates/mbe/src/expander/transcriber.rs +++ b/crates/mbe/src/expander/transcriber.rs | |||
@@ -2,7 +2,7 @@ | |||
2 | //! `$ident => foo`, interpolates variables in the template, to get `fn foo() {}` | 2 | //! `$ident => foo`, interpolates variables in the template, to get `fn foo() {}` |
3 | 3 | ||
4 | use syntax::SmolStr; | 4 | use syntax::SmolStr; |
5 | use tt::Delimiter; | 5 | use tt::{Delimiter, Subtree}; |
6 | 6 | ||
7 | use super::ExpandResult; | 7 | use super::ExpandResult; |
8 | use crate::{ | 8 | use crate::{ |
@@ -13,17 +13,13 @@ use crate::{ | |||
13 | 13 | ||
14 | impl Bindings { | 14 | impl Bindings { |
15 | fn contains(&self, name: &str) -> bool { | 15 | fn contains(&self, name: &str) -> bool { |
16 | self.inner.iter().any(|(n, _)| n == name) | 16 | self.inner.contains_key(name) |
17 | } | 17 | } |
18 | 18 | ||
19 | fn get(&self, name: &str, nesting: &mut [NestingState]) -> Result<&Fragment, ExpandError> { | 19 | fn get(&self, name: &str, nesting: &mut [NestingState]) -> Result<&Fragment, ExpandError> { |
20 | let mut b: &Binding = self | 20 | let mut b: &Binding = self.inner.get(name).ok_or_else(|| { |
21 | .inner | 21 | ExpandError::BindingError(format!("could not find binding `{}`", name)) |
22 | .iter() | 22 | })?; |
23 | .find_map(|(n, b)| if n == name { Some(b) } else { None }) | ||
24 | .ok_or_else(|| { | ||
25 | ExpandError::BindingError(format!("could not find binding `{}`", name)) | ||
26 | })?; | ||
27 | for nesting_state in nesting.iter_mut() { | 23 | for nesting_state in nesting.iter_mut() { |
28 | nesting_state.hit = true; | 24 | nesting_state.hit = true; |
29 | b = match b { | 25 | b = match b { |
@@ -179,7 +175,10 @@ fn expand_repeat( | |||
179 | counter += 1; | 175 | counter += 1; |
180 | if counter == limit { | 176 | if counter == limit { |
181 | log::warn!("expand_tt in repeat pattern exceed limit => {:#?}\n{:#?}", template, ctx); | 177 | log::warn!("expand_tt in repeat pattern exceed limit => {:#?}\n{:#?}", template, ctx); |
182 | break; | 178 | return ExpandResult { |
179 | value: Fragment::Tokens(Subtree::default().into()), | ||
180 | err: Some(ExpandError::Other("Expand exceed limit".to_string())), | ||
181 | }; | ||
183 | } | 182 | } |
184 | 183 | ||
185 | if e.is_some() { | 184 | if e.is_some() { |