aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_mbe/src/mbe_expander.rs
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2020-03-14 19:24:18 +0000
committerFlorian Diebold <[email protected]>2020-03-16 17:38:19 +0000
commit0f3a54dd4d439a6598526144c4ecccee9c5f1362 (patch)
treec974dab20b25d0403f23222f4438bb3f9f7d8b0d /crates/ra_mbe/src/mbe_expander.rs
parent6305d094ac61ed6e437537b93f4e587b415678c9 (diff)
wip
Diffstat (limited to 'crates/ra_mbe/src/mbe_expander.rs')
-rw-r--r--crates/ra_mbe/src/mbe_expander.rs49
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;
8use ra_syntax::SmolStr; 8use ra_syntax::SmolStr;
9use rustc_hash::FxHashMap; 9use rustc_hash::FxHashMap;
10 10
11use crate::{ExpandResult, ExpandError}; 11use crate::{ExpandError, ExpandResult};
12 12
13pub(crate) fn expand( 13pub(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
34fn expand_rule(rule: &crate::Rule, input: &tt::Subtree) -> ExpandResult<(tt::Subtree, usize)> { 38fn 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(&macro_invocation.token_tree().unwrap()).unwrap(); 169 ast_to_token_tree(&macro_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}