Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 800186b

Browse files
committedMar 13, 2021
Add bindings builder for speed up matching
1 parent f1350dd commit 800186b

File tree

3 files changed

+219
-62
lines changed

3 files changed

+219
-62
lines changed
 

‎crates/mbe/src/expander.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
mod matcher;
66
mod transcriber;
77

8-
use smallvec::SmallVec;
8+
use rustc_hash::FxHashMap;
99
use syntax::SmolStr;
1010

1111
use crate::{ExpandError, ExpandResult};
@@ -96,7 +96,7 @@ pub(crate) fn expand_rules(
9696
/// many is not a plain `usize`, but an `&[usize]`.
9797
#[derive(Debug, Default, Clone, PartialEq, Eq)]
9898
struct Bindings {
99-
inner: SmallVec<[(SmolStr, Binding); 4]>,
99+
inner: FxHashMap<SmolStr, Binding>,
100100
}
101101

102102
#[derive(Debug, Clone, PartialEq, Eq)]

‎crates/mbe/src/expander/matcher.rs

Lines changed: 215 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@
5959
//! eof: [a $( a )* a b ·]
6060
//! ```
6161
62+
use std::rc::Rc;
63+
6264
use crate::{
6365
expander::{Binding, Bindings, Fragment},
6466
parser::{Op, OpDelimited, OpDelimitedIter, RepeatKind, Separator},
@@ -76,43 +78,15 @@ impl Bindings {
7678
// FIXME: Do we have a better way to represent an empty token ?
7779
// Insert an empty subtree for empty token
7880
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)));
8082
}
8183

8284
fn push_empty(&mut self, name: &SmolStr) {
83-
self.inner.push((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 })
85+
self.inner.insert(name.clone(), Binding::Empty);
11286
}
11387

11488
fn bindings(&self) -> impl Iterator<Item = &Binding> {
115-
self.inner.iter().map(|(_, b)| b)
89+
self.inner.values()
11690
}
11791
}
11892

@@ -162,6 +136,187 @@ pub(super) fn match_(pattern: &MetaTemplate, input: &tt::Subtree) -> Match {
162136
}
163137
}
164138

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::with_capacity(8));
166+
let nidx = self.nested.len();
167+
self.nested.push(Vec::with_capacity(8));
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+
let mut item = Vec::with_capacity(8);
186+
item.push(LinkNode::Parent { idx, len });
187+
target.push(item);
188+
}
189+
190+
new_idx
191+
}
192+
}
193+
194+
fn push_empty(&mut self, idx: &mut BindingsIdx, var: &SmolStr) {
195+
self.nodes[idx.0].push(LinkNode::Node(Rc::new(BindingKind::Empty(var.clone()))));
196+
}
197+
198+
fn push_optional(&mut self, idx: &mut BindingsIdx, var: &SmolStr) {
199+
self.nodes[idx.0].push(LinkNode::Node(Rc::new(BindingKind::Optional(var.clone()))));
200+
}
201+
202+
fn push_fragment(&mut self, idx: &mut BindingsIdx, var: &SmolStr, fragment: Fragment) {
203+
self.nodes[idx.0]
204+
.push(LinkNode::Node(Rc::new(BindingKind::Fragment(var.clone(), fragment))));
205+
}
206+
207+
fn push_nested(&mut self, parent: &mut BindingsIdx, child: &BindingsIdx) {
208+
let BindingsIdx(idx, nidx) = self.copy(&child);
209+
self.nodes[parent.0].push(LinkNode::Node(Rc::new(BindingKind::Nested(idx, nidx))));
210+
}
211+
212+
fn push_default(&mut self, idx: &mut BindingsIdx) {
213+
self.nested[idx.1].push(LinkNode::Node(idx.0));
214+
let new_idx = self.nodes.len();
215+
self.nodes.push(Vec::with_capacity(8));
216+
idx.0 = new_idx;
217+
}
218+
219+
fn build(self, idx: &BindingsIdx) -> Bindings {
220+
let mut bindings = Bindings::default();
221+
self.build_recur(&mut bindings, self.nodes[idx.0].clone());
222+
bindings
223+
}
224+
225+
fn build_recur(&self, bindings: &mut Bindings, nodes: Vec<LinkNode<Rc<BindingKind>>>) {
226+
for cmd in self.flatten_nodes(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, list) => {
238+
let list = self.flatten_nested(*idx, *list);
239+
240+
for (idx, iter) in list.enumerate() {
241+
for (key, value) in &iter.inner {
242+
let bindings = bindings
243+
.inner
244+
.entry(key.clone())
245+
.or_insert_with(|| Binding::Nested(Vec::new()));
246+
247+
if let Binding::Nested(it) = bindings {
248+
// insert empty nested bindings before this one
249+
while it.len() < idx {
250+
it.push(Binding::Nested(Vec::new()));
251+
}
252+
it.push(value.clone());
253+
}
254+
}
255+
}
256+
}
257+
}
258+
}
259+
}
260+
261+
fn flatten_nested_ref(&self, id: usize, len: usize) -> Vec<Vec<LinkNode<Rc<BindingKind>>>> {
262+
self.nested[id]
263+
.iter()
264+
.take(len)
265+
.map(|it| match it {
266+
LinkNode::Node(id) => vec![self.nodes[*id].clone()],
267+
LinkNode::Parent { idx, len } => self.flatten_nested_ref(*idx, *len),
268+
})
269+
.flatten()
270+
.collect()
271+
}
272+
273+
fn flatten_nested<'a>(
274+
&'a self,
275+
idx: usize,
276+
list: usize,
277+
) -> impl Iterator<Item = Bindings> + 'a {
278+
let last = self.nodes[idx].clone();
279+
self.nested[list]
280+
.iter()
281+
.map(move |it| match *it {
282+
LinkNode::Node(idx) => vec![self.nodes[idx].clone()],
283+
LinkNode::Parent { idx, len } => self.flatten_nested_ref(idx, len),
284+
})
285+
.flatten()
286+
.chain(std::iter::once(last))
287+
.map(move |iter| {
288+
let mut child_bindings = Bindings::default();
289+
self.build_recur(&mut child_bindings, iter);
290+
child_bindings
291+
})
292+
}
293+
294+
fn flatten_nodes_ref(&self, id: usize, len: usize) -> Vec<Rc<BindingKind>> {
295+
self.nodes[id]
296+
.iter()
297+
.take(len)
298+
.map(|it| match it {
299+
LinkNode::Node(it) => vec![it.clone()],
300+
LinkNode::Parent { idx, len } => self.flatten_nodes_ref(*idx, *len),
301+
})
302+
.flatten()
303+
.collect()
304+
}
305+
306+
fn flatten_nodes<'a>(
307+
&'a self,
308+
nodes: Vec<LinkNode<Rc<BindingKind>>>,
309+
) -> impl Iterator<Item = Rc<BindingKind>> + 'a {
310+
nodes
311+
.into_iter()
312+
.map(move |it| match it {
313+
LinkNode::Node(it) => vec![it],
314+
LinkNode::Parent { idx, len } => self.flatten_nodes_ref(idx, len),
315+
})
316+
.flatten()
317+
}
318+
}
319+
165320
#[derive(Debug, Clone)]
166321
struct MatchState<'t> {
167322
/// The position of the "dot" in this matcher
@@ -187,7 +342,7 @@ struct MatchState<'t> {
187342
sep_parsed: Option<usize>,
188343

189344
/// Matched meta variables bindings
190-
bindings: SmallVec<[Bindings; 4]>,
345+
bindings: BindingsIdx,
191346

192347
/// Cached result of meta variable parsing
193348
meta_result: Option<(TtIter<'t>, ExpandResult<Option<Fragment>>)>,
@@ -218,6 +373,7 @@ fn match_loop_inner<'t>(
218373
src: TtIter<'t>,
219374
stack: &[TtIter<'t>],
220375
res: &mut Match,
376+
bindings_builder: &mut BindingsBuilder,
221377
cur_items: &mut SmallVec<[MatchState<'t>; 1]>,
222378
bb_items: &mut SmallVec<[MatchState<'t>; 1]>,
223379
next_items: &mut Vec<MatchState<'t>>,
@@ -251,12 +407,10 @@ fn match_loop_inner<'t>(
251407
if item.sep_parsed.is_none() {
252408
// Get the `up` matcher
253409
let mut new_pos = *item.up.clone().unwrap();
410+
new_pos.bindings = bindings_builder.copy(&new_pos.bindings);
254411
// Add matches from this repetition to the `matches` of `up`
255-
if let Some(bindings) = new_pos.bindings.last_mut() {
256-
for (i, b) in item.bindings.iter_mut().enumerate() {
257-
bindings.push_nested(i, b.clone()).unwrap();
258-
}
259-
}
412+
bindings_builder.push_nested(&mut new_pos.bindings, &item.bindings);
413+
260414
// Move the "dot" past the repetition in `up`
261415
new_pos.dot.next();
262416
new_pos.is_error = new_pos.is_error || item.is_error;
@@ -280,7 +434,7 @@ fn match_loop_inner<'t>(
280434
else if item.sep_kind != Some(RepeatKind::ZeroOrOne) {
281435
item.dot = item.dot.reset();
282436
item.sep_parsed = None;
283-
item.bindings.push(Bindings::default());
437+
bindings_builder.push_default(&mut item.bindings);
284438
cur_items.push(item);
285439
}
286440
} else {
@@ -298,12 +452,12 @@ fn match_loop_inner<'t>(
298452
OpDelimited::Op(Op::Repeat { tokens, kind, separator }) => {
299453
if matches!(kind, RepeatKind::ZeroOrMore | RepeatKind::ZeroOrOne) {
300454
let mut new_item = item.clone();
455+
new_item.bindings = bindings_builder.copy(&new_item.bindings);
301456
new_item.dot.next();
302457
let mut vars = Vec::new();
303-
let bindings = new_item.bindings.last_mut().unwrap();
304458
collect_vars(&mut vars, tokens);
305459
for var in vars {
306-
bindings.push_empty(&var);
460+
bindings_builder.push_empty(&mut new_item.bindings, &var);
307461
}
308462
cur_items.push(new_item);
309463
}
@@ -314,7 +468,7 @@ fn match_loop_inner<'t>(
314468
sep: separator.clone(),
315469
sep_kind: Some(*kind),
316470
sep_parsed: None,
317-
bindings: smallvec![Bindings::default()],
471+
bindings: bindings_builder.alloc(),
318472
meta_result: None,
319473
is_error: false,
320474
})
@@ -339,7 +493,7 @@ fn match_loop_inner<'t>(
339493
item.meta_result = Some((fork, match_res));
340494
try_push!(bb_items, item);
341495
} else {
342-
item.bindings.last_mut().unwrap().push_optional(name);
496+
bindings_builder.push_optional(&mut item.bindings, &name);
343497
item.dot.next();
344498
cur_items.push(item);
345499
}
@@ -348,11 +502,11 @@ fn match_loop_inner<'t>(
348502
res.add_err(err);
349503
match match_res.value {
350504
Some(fragment) => {
351-
item.bindings
352-
.last_mut()
353-
.unwrap()
354-
.inner
355-
.push((name.clone(), Binding::Fragment(fragment)));
505+
bindings_builder.push_fragment(
506+
&mut item.bindings,
507+
&name,
508+
fragment,
509+
);
356510
}
357511
_ => {}
358512
}
@@ -394,14 +548,16 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree) -> Match {
394548
let mut res = Match::default();
395549
let mut error_reover_item = None;
396550

551+
let mut bindings_builder = BindingsBuilder::default();
552+
397553
let mut cur_items = smallvec![MatchState {
398554
dot: pattern.iter_delimited(None),
399555
stack: Default::default(),
400556
up: None,
401557
sep: None,
402558
sep_kind: None,
403559
sep_parsed: None,
404-
bindings: smallvec![Bindings::default()],
560+
bindings: bindings_builder.alloc(),
405561
is_error: false,
406562
meta_result: None,
407563
}];
@@ -419,6 +575,7 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree) -> Match {
419575
src.clone(),
420576
&stack,
421577
&mut res,
578+
&mut bindings_builder,
422579
&mut cur_items,
423580
&mut bb_items,
424581
&mut next_items,
@@ -428,9 +585,9 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree) -> Match {
428585
stdx::always!(cur_items.is_empty());
429586

430587
if error_items.len() > 0 {
431-
error_reover_item = error_items.pop();
588+
error_reover_item = error_items.pop().map(|it| it.bindings);
432589
} else if eof_items.len() > 0 {
433-
error_reover_item = Some(eof_items[0].clone());
590+
error_reover_item = Some(eof_items[0].bindings.clone());
434591
}
435592

436593
// We need to do some post processing after the `match_loop_inner`.
@@ -440,11 +597,11 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree) -> Match {
440597
if eof_items.len() == 1 {
441598
// remove all errors, because it is the correct answer !
442599
res = Match::default();
443-
res.bindings = eof_items[0].bindings[0].clone();
600+
res.bindings = bindings_builder.build(&eof_items[0].bindings);
444601
} else {
445602
// Error recovery
446603
if error_reover_item.is_some() {
447-
res.bindings = error_reover_item.unwrap().bindings[0].clone();
604+
res.bindings = bindings_builder.build(&error_reover_item.unwrap());
448605
}
449606
res.add_err(ExpandError::UnexpectedToken);
450607
}
@@ -467,8 +624,8 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree) -> Match {
467624
}
468625
res.add_err(err!("leftover tokens"));
469626

470-
if let Some(mut error_reover_item) = error_reover_item {
471-
res.bindings = error_reover_item.bindings.remove(0);
627+
if let Some(error_reover_item) = error_reover_item {
628+
res.bindings = bindings_builder.build(&error_reover_item);
472629
}
473630
return res;
474631
}
@@ -494,12 +651,13 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree) -> Match {
494651

495652
if let Some(OpDelimited::Op(Op::Var { name, .. })) = item.dot.peek() {
496653
let (iter, match_res) = item.meta_result.take().unwrap();
497-
let bindings = item.bindings.last_mut().unwrap();
498654
match match_res.value {
499655
Some(fragment) => {
500-
bindings.inner.push((name.clone(), Binding::Fragment(fragment)));
656+
bindings_builder.push_fragment(&mut item.bindings, &name, fragment);
657+
}
658+
None if match_res.err.is_none() => {
659+
bindings_builder.push_optional(&mut item.bindings, &name);
501660
}
502-
None if match_res.err.is_none() => bindings.push_optional(name),
503661
_ => {}
504662
}
505663
if let Some(err) = match_res.err {

‎crates/mbe/src/expander/transcriber.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,13 @@ use crate::{
1313

1414
impl Bindings {
1515
fn contains(&self, name: &str) -> bool {
16-
self.inner.iter().any(|(n, _)| n == name)
16+
self.inner.contains_key(name)
1717
}
1818

1919
fn get(&self, name: &str, nesting: &mut [NestingState]) -> Result<&Fragment, ExpandError> {
2020
let mut b: &Binding = self
2121
.inner
22-
.iter()
23-
.find_map(|(n, b)| if n == name { Some(b) } else { None })
22+
.get(name)
2423
.ok_or_else(|| {
2524
ExpandError::BindingError(format!("could not find binding `{}`", name))
2625
})?;

0 commit comments

Comments
 (0)
Please sign in to comment.