diff options
Diffstat (limited to 'crates/ra_mbe/src/mbe_expander.rs')
-rw-r--r-- | crates/ra_mbe/src/mbe_expander.rs | 49 |
1 files changed, 29 insertions, 20 deletions
diff --git a/crates/ra_mbe/src/mbe_expander.rs b/crates/ra_mbe/src/mbe_expander.rs index 5083d5410..b2faa86d2 100644 --- a/crates/ra_mbe/src/mbe_expander.rs +++ b/crates/ra_mbe/src/mbe_expander.rs | |||
@@ -8,33 +8,44 @@ mod transcriber; | |||
8 | use ra_syntax::SmolStr; | 8 | use ra_syntax::SmolStr; |
9 | use rustc_hash::FxHashMap; | 9 | use rustc_hash::FxHashMap; |
10 | 10 | ||
11 | use crate::{ExpandResult, ExpandError}; | 11 | use crate::{ExpandError, ExpandResult}; |
12 | 12 | ||
13 | pub(crate) fn expand( | 13 | pub(crate) fn expand(rules: &crate::MacroRules, input: &tt::Subtree) -> ExpandResult<tt::Subtree> { |
14 | rules: &crate::MacroRules, | 14 | let (mut result, mut unmatched_tokens, mut unmatched_patterns, mut err) = ( |
15 | input: &tt::Subtree, | 15 | tt::Subtree::default(), |
16 | ) -> ExpandResult<tt::Subtree> { | 16 | usize::max_value(), |
17 | let (mut result, mut left_over, mut err) = (tt::Subtree::default(), usize::max_value(), Some(ExpandError::NoMatchingRule)); | 17 | usize::max_value(), |
18 | Some(ExpandError::NoMatchingRule), | ||
19 | ); | ||
18 | for rule in &rules.rules { | 20 | for rule in &rules.rules { |
19 | let ((res, left), e) = expand_rule(rule, input); | 21 | let ((res, tokens, patterns), e) = expand_rule(rule, input); |
20 | if e.is_none() { | 22 | if e.is_none() { |
21 | // if we find a rule that applies without errors, we're done | 23 | // if we find a rule that applies without errors, we're done |
22 | return (res, None); | 24 | return (res, None); |
23 | } | 25 | } |
24 | // use the rule if we matched more tokens | 26 | // use the rule if we matched more tokens, or had fewer patterns left |
25 | if left < left_over { | 27 | if tokens < unmatched_tokens || tokens == unmatched_tokens && patterns < unmatched_patterns |
28 | { | ||
26 | result = res; | 29 | result = res; |
27 | err = e; | 30 | err = e; |
28 | left_over = left; | 31 | unmatched_tokens = tokens; |
32 | unmatched_patterns = patterns; | ||
29 | } | 33 | } |
30 | } | 34 | } |
31 | (result, err) | 35 | (result, err) |
32 | } | 36 | } |
33 | 37 | ||
34 | fn expand_rule(rule: &crate::Rule, input: &tt::Subtree) -> ExpandResult<(tt::Subtree, usize)> { | 38 | fn expand_rule( |
35 | let ((bindings, left_over), bindings_err) = dbg!(matcher::match_(&rule.lhs, input)); | 39 | rule: &crate::Rule, |
36 | let (res, transcribe_err) = dbg!(transcriber::transcribe(&rule.rhs, &bindings)); | 40 | input: &tt::Subtree, |
37 | ((res, left_over), bindings_err.or(transcribe_err)) | 41 | ) -> ExpandResult<(tt::Subtree, usize, usize)> { |
42 | dbg!(&rule.lhs); | ||
43 | let (match_result, bindings_err) = dbg!(matcher::match_(&rule.lhs, input)); | ||
44 | let (res, transcribe_err) = dbg!(transcriber::transcribe(&rule.rhs, &match_result.bindings)); | ||
45 | ( | ||
46 | (res, match_result.unmatched_tokens, match_result.unmatched_patterns), | ||
47 | bindings_err.or(transcribe_err), | ||
48 | ) | ||
38 | } | 49 | } |
39 | 50 | ||
40 | /// The actual algorithm for expansion is not too hard, but is pretty tricky. | 51 | /// The actual algorithm for expansion is not too hard, but is pretty tricky. |
@@ -149,10 +160,7 @@ mod tests { | |||
149 | crate::MacroRules::parse(&definition_tt).unwrap() | 160 | crate::MacroRules::parse(&definition_tt).unwrap() |
150 | } | 161 | } |
151 | 162 | ||
152 | fn expand_first( | 163 | fn expand_first(rules: &crate::MacroRules, invocation: &str) -> ExpandResult<tt::Subtree> { |
153 | rules: &crate::MacroRules, | ||
154 | invocation: &str, | ||
155 | ) -> ExpandResult<tt::Subtree> { | ||
156 | let source_file = ast::SourceFile::parse(invocation).ok().unwrap(); | 164 | let source_file = ast::SourceFile::parse(invocation).ok().unwrap(); |
157 | let macro_invocation = | 165 | let macro_invocation = |
158 | source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); | 166 | source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); |
@@ -160,6 +168,7 @@ mod tests { | |||
160 | let (invocation_tt, _) = | 168 | let (invocation_tt, _) = |
161 | ast_to_token_tree(¯o_invocation.token_tree().unwrap()).unwrap(); | 169 | ast_to_token_tree(¯o_invocation.token_tree().unwrap()).unwrap(); |
162 | 170 | ||
163 | expand_rule(&rules.rules[0], &invocation_tt) | 171 | let expanded = expand_rule(&rules.rules[0], &invocation_tt); |
172 | ((expanded.0).0, expanded.1) | ||
164 | } | 173 | } |
165 | } | 174 | } |