aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_mbe/src/mbe_expander.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_mbe/src/mbe_expander.rs')
-rw-r--r--crates/ra_mbe/src/mbe_expander.rs29
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;
8use ra_syntax::SmolStr; 8use ra_syntax::SmolStr;
9use rustc_hash::FxHashMap; 9use rustc_hash::FxHashMap;
10 10
11use crate::ExpandError; 11use crate::{ExpandResult, ExpandError};
12 12
13pub(crate) fn expand( 13pub(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
20fn expand_rule(rule: &crate::Rule, input: &tt::Subtree) -> Result<tt::Subtree, ExpandError> { 31fn 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();