diff options
Diffstat (limited to 'crates/ra_mbe/src/mbe_expander.rs')
-rw-r--r-- | crates/ra_mbe/src/mbe_expander.rs | 29 |
1 files changed, 20 insertions, 9 deletions
diff --git a/crates/ra_mbe/src/mbe_expander.rs b/crates/ra_mbe/src/mbe_expander.rs index b455b7321..da3952428 100644 --- a/crates/ra_mbe/src/mbe_expander.rs +++ b/crates/ra_mbe/src/mbe_expander.rs | |||
@@ -8,19 +8,30 @@ 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::ExpandError; | 11 | use crate::{ExpandResult, ExpandError}; |
12 | 12 | ||
13 | pub(crate) fn expand( | 13 | pub(crate) fn expand( |
14 | rules: &crate::MacroRules, | 14 | rules: &crate::MacroRules, |
15 | input: &tt::Subtree, | 15 | input: &tt::Subtree, |
16 | ) -> Result<tt::Subtree, ExpandError> { | 16 | ) -> ExpandResult<tt::Subtree> { |
17 | rules.rules.iter().find_map(|it| expand_rule(it, input).ok()).ok_or(ExpandError::NoMatchingRule) | 17 | let (mut result, mut err) = (tt::Subtree::default(), Some(ExpandError::NoMatchingRule)); |
18 | for rule in &rules.rules { | ||
19 | let (res, e) = expand_rule(rule, input); | ||
20 | if e.is_none() { | ||
21 | // if we find a rule that applies without errors, we're done | ||
22 | return (res, None); | ||
23 | } | ||
24 | // TODO decide which result is better | ||
25 | result = res; | ||
26 | err = e; | ||
27 | } | ||
28 | (result, err) | ||
18 | } | 29 | } |
19 | 30 | ||
20 | fn expand_rule(rule: &crate::Rule, input: &tt::Subtree) -> Result<tt::Subtree, ExpandError> { | 31 | fn expand_rule(rule: &crate::Rule, input: &tt::Subtree) -> ExpandResult<tt::Subtree> { |
21 | let bindings = matcher::match_(&rule.lhs, input)?; | 32 | let (bindings, bindings_err) = dbg!(matcher::match_(&rule.lhs, input)); |
22 | let res = transcriber::transcribe(&rule.rhs, &bindings)?; | 33 | let (res, transcribe_err) = dbg!(transcriber::transcribe(&rule.rhs, &bindings)); |
23 | Ok(res) | 34 | (res, bindings_err.or(transcribe_err)) |
24 | } | 35 | } |
25 | 36 | ||
26 | /// The actual algorithm for expansion is not too hard, but is pretty tricky. | 37 | /// The actual algorithm for expansion is not too hard, but is pretty tricky. |
@@ -111,7 +122,7 @@ mod tests { | |||
111 | } | 122 | } |
112 | 123 | ||
113 | fn assert_err(macro_body: &str, invocation: &str, err: ExpandError) { | 124 | fn assert_err(macro_body: &str, invocation: &str, err: ExpandError) { |
114 | assert_eq!(expand_first(&create_rules(&format_macro(macro_body)), invocation), Err(err)); | 125 | assert_eq!(expand_first(&create_rules(&format_macro(macro_body)), invocation).1, Some(err)); |
115 | } | 126 | } |
116 | 127 | ||
117 | fn format_macro(macro_body: &str) -> String { | 128 | fn format_macro(macro_body: &str) -> String { |
@@ -138,7 +149,7 @@ mod tests { | |||
138 | fn expand_first( | 149 | fn expand_first( |
139 | rules: &crate::MacroRules, | 150 | rules: &crate::MacroRules, |
140 | invocation: &str, | 151 | invocation: &str, |
141 | ) -> Result<tt::Subtree, ExpandError> { | 152 | ) -> ExpandResult<tt::Subtree> { |
142 | let source_file = ast::SourceFile::parse(invocation).ok().unwrap(); | 153 | let source_file = ast::SourceFile::parse(invocation).ok().unwrap(); |
143 | let macro_invocation = | 154 | let macro_invocation = |
144 | source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); | 155 | source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); |