aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_mbe
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2020-03-16 11:22:10 +0000
committerFlorian Diebold <[email protected]>2020-03-16 17:38:19 +0000
commitd655749aaeb31461f9af923bbf0b36d219cff343 (patch)
treed7f8e8a11bd4794567fb24ac29b2b85ebd247881 /crates/ra_mbe
parentf3c6a2e3dbe477a7e0ac714a5bdbda6e8838fcfa (diff)
Turn ExpandResult into struct
Diffstat (limited to 'crates/ra_mbe')
-rw-r--r--crates/ra_mbe/src/lib.rs32
-rw-r--r--crates/ra_mbe/src/mbe_expander.rs16
-rw-r--r--crates/ra_mbe/src/mbe_expander/matcher.rs21
-rw-r--r--crates/ra_mbe/src/mbe_expander/transcriber.rs22
-rw-r--r--crates/ra_mbe/src/tests.rs3
5 files changed, 59 insertions, 35 deletions
diff --git a/crates/ra_mbe/src/lib.rs b/crates/ra_mbe/src/lib.rs
index 3adec4978..6a9037bfc 100644
--- a/crates/ra_mbe/src/lib.rs
+++ b/crates/ra_mbe/src/lib.rs
@@ -30,8 +30,6 @@ pub enum ExpandError {
30 InvalidRepeat, 30 InvalidRepeat,
31} 31}
32 32
33pub type ExpandResult<T> = (T, Option<ExpandError>);
34
35pub use crate::syntax_bridge::{ 33pub use crate::syntax_bridge::{
36 ast_to_token_tree, parse_to_token_tree, syntax_node_to_token_tree, token_tree_to_syntax_node, 34 ast_to_token_tree, parse_to_token_tree, syntax_node_to_token_tree, token_tree_to_syntax_node,
37 TokenMap, 35 TokenMap,
@@ -211,5 +209,35 @@ fn validate(pattern: &tt::Subtree) -> Result<(), ParseError> {
211 Ok(()) 209 Ok(())
212} 210}
213 211
212pub struct ExpandResult<T>(pub T, pub Option<ExpandError>);
213
214impl<T> ExpandResult<T> {
215 pub fn ok(t: T) -> ExpandResult<T> {
216 ExpandResult(t, None)
217 }
218
219 pub fn only_err(err: ExpandError) -> ExpandResult<T>
220 where
221 T: Default,
222 {
223 ExpandResult(Default::default(), Some(err))
224 }
225
226 pub fn map<U>(self, f: impl FnOnce(T) -> U) -> ExpandResult<U> {
227 ExpandResult(f(self.0), self.1)
228 }
229
230 pub fn result(self) -> Result<T, ExpandError> {
231 self.1.map(Err).unwrap_or(Ok(self.0))
232 }
233}
234
235impl<T: Default> From<Result<T, ExpandError>> for ExpandResult<T> {
236 fn from(result: Result<T, ExpandError>) -> ExpandResult<T> {
237 result
238 .map_or_else(|e| ExpandResult(Default::default(), Some(e)), |it| ExpandResult(it, None))
239 }
240}
241
214#[cfg(test)] 242#[cfg(test)]
215mod tests; 243mod tests;
diff --git a/crates/ra_mbe/src/mbe_expander.rs b/crates/ra_mbe/src/mbe_expander.rs
index 204c30e3d..0a4d73dda 100644
--- a/crates/ra_mbe/src/mbe_expander.rs
+++ b/crates/ra_mbe/src/mbe_expander.rs
@@ -18,12 +18,13 @@ fn expand_rules(rules: &[crate::Rule], input: &tt::Subtree) -> ExpandResult<tt::
18 let mut match_: Option<(matcher::Match, &crate::Rule)> = None; 18 let mut match_: Option<(matcher::Match, &crate::Rule)> = None;
19 let mut err = Some(ExpandError::NoMatchingRule); 19 let mut err = Some(ExpandError::NoMatchingRule);
20 for rule in rules { 20 for rule in rules {
21 let (new_match, bindings_err) = matcher::match_(&rule.lhs, input); 21 let ExpandResult(new_match, bindings_err) = matcher::match_(&rule.lhs, input);
22 if bindings_err.is_none() { 22 if bindings_err.is_none() {
23 // 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
24 let (res, transcribe_err) = transcriber::transcribe(&rule.rhs, &new_match.bindings); 24 let ExpandResult(res, transcribe_err) =
25 transcriber::transcribe(&rule.rhs, &new_match.bindings);
25 if transcribe_err.is_none() { 26 if transcribe_err.is_none() {
26 return (res, None); 27 return ExpandResult::ok(res);
27 } 28 }
28 } 29 }
29 // use the rule if we matched more tokens, or had fewer patterns left 30 // use the rule if we matched more tokens, or had fewer patterns left
@@ -43,10 +44,11 @@ fn expand_rules(rules: &[crate::Rule], input: &tt::Subtree) -> ExpandResult<tt::
43 } 44 }
44 if let Some((match_, rule)) = match_ { 45 if let Some((match_, rule)) = match_ {
45 // if we got here, there was no match without errors 46 // if we got here, there was no match without errors
46 let (result, transcribe_err) = transcriber::transcribe(&rule.rhs, &match_.bindings); 47 let ExpandResult(result, transcribe_err) =
47 (result, err.or(transcribe_err)) 48 transcriber::transcribe(&rule.rhs, &match_.bindings);
49 ExpandResult(result, err.or(transcribe_err))
48 } else { 50 } else {
49 (tt::Subtree::default(), err) 51 ExpandResult(tt::Subtree::default(), err)
50 } 52 }
51} 53}
52 54
@@ -171,6 +173,6 @@ mod tests {
171 ast_to_token_tree(&macro_invocation.token_tree().unwrap()).unwrap(); 173 ast_to_token_tree(&macro_invocation.token_tree().unwrap()).unwrap();
172 174
173 let expanded = expand_rules(&rules.rules, &invocation_tt); 175 let expanded = expand_rules(&rules.rules, &invocation_tt);
174 (expanded.0, expanded.1) 176 expanded
175 } 177 }
176} 178}
diff --git a/crates/ra_mbe/src/mbe_expander/matcher.rs b/crates/ra_mbe/src/mbe_expander/matcher.rs
index f40d55d4e..22fb5d74c 100644
--- a/crates/ra_mbe/src/mbe_expander/matcher.rs
+++ b/crates/ra_mbe/src/mbe_expander/matcher.rs
@@ -79,7 +79,7 @@ pub(super) fn match_(pattern: &tt::Subtree, src: &tt::Subtree) -> ExpandResult<M
79 err = Some(err!("leftover tokens")); 79 err = Some(err!("leftover tokens"));
80 } 80 }
81 81
82 (res, err) 82 ExpandResult(res, err)
83} 83}
84 84
85fn match_subtree( 85fn match_subtree(
@@ -148,7 +148,7 @@ fn match_subtree(
148 continue; 148 continue;
149 } 149 }
150 }; 150 };
151 let (matched, match_err) = match_meta_var(kind.as_str(), src); 151 let ExpandResult(matched, match_err) = match_meta_var(kind.as_str(), src);
152 match matched { 152 match matched {
153 Some(fragment) => { 153 Some(fragment) => {
154 res.bindings.inner.insert(name.clone(), Binding::Fragment(fragment)); 154 res.bindings.inner.insert(name.clone(), Binding::Fragment(fragment));
@@ -308,17 +308,17 @@ impl<'a> TtIter<'a> {
308 token_trees: res.into_iter().cloned().collect(), 308 token_trees: res.into_iter().cloned().collect(),
309 })), 309 })),
310 }; 310 };
311 (res, err) 311 ExpandResult(res, err)
312 } 312 }
313 313
314 pub(crate) fn eat_vis(&mut self) -> Option<tt::TokenTree> { 314 pub(crate) fn eat_vis(&mut self) -> Option<tt::TokenTree> {
315 let mut fork = self.clone(); 315 let mut fork = self.clone();
316 match fork.expect_fragment(Visibility) { 316 match fork.expect_fragment(Visibility) {
317 (tt, None) => { 317 ExpandResult(tt, None) => {
318 *self = fork; 318 *self = fork;
319 tt 319 tt
320 } 320 }
321 (_, Some(_)) => None, 321 ExpandResult(_, Some(_)) => None,
322 } 322 }
323 } 323 }
324} 324}
@@ -419,12 +419,11 @@ fn match_meta_var(kind: &str, input: &mut TtIter) -> ExpandResult<Option<Fragmen
419 }, 419 },
420 _ => Err(ExpandError::UnexpectedToken), 420 _ => Err(ExpandError::UnexpectedToken),
421 }; 421 };
422 return to_expand_result(tt_result.map(|it| it.map(Fragment::Tokens))); 422 return tt_result.map(|it| it.map(Fragment::Tokens)).into();
423 } 423 }
424 }; 424 };
425 let (tt, err) = input.expect_fragment(fragment); 425 let result = input.expect_fragment(fragment);
426 let fragment = if kind == "expr" { tt.map(Fragment::Ast) } else { tt.map(Fragment::Tokens) }; 426 result.map(|tt| if kind == "expr" { tt.map(Fragment::Ast) } else { tt.map(Fragment::Tokens) })
427 (fragment, err)
428} 427}
429 428
430fn collect_vars(buf: &mut Vec<SmolStr>, pattern: &tt::Subtree) -> Result<(), ExpandError> { 429fn collect_vars(buf: &mut Vec<SmolStr>, pattern: &tt::Subtree) -> Result<(), ExpandError> {
@@ -438,7 +437,3 @@ fn collect_vars(buf: &mut Vec<SmolStr>, pattern: &tt::Subtree) -> Result<(), Exp
438 } 437 }
439 Ok(()) 438 Ok(())
440} 439}
441
442fn to_expand_result<T: Default>(result: Result<T, ExpandError>) -> ExpandResult<T> {
443 result.map_or_else(|e| (Default::default(), Some(e)), |it| (it, None))
444}
diff --git a/crates/ra_mbe/src/mbe_expander/transcriber.rs b/crates/ra_mbe/src/mbe_expander/transcriber.rs
index c53c2d35e..4b173edd3 100644
--- a/crates/ra_mbe/src/mbe_expander/transcriber.rs
+++ b/crates/ra_mbe/src/mbe_expander/transcriber.rs
@@ -87,23 +87,23 @@ fn expand_subtree(ctx: &mut ExpandCtx, template: &tt::Subtree) -> ExpandResult<t
87 match op { 87 match op {
88 Op::TokenTree(tt @ tt::TokenTree::Leaf(..)) => buf.push(tt.clone()), 88 Op::TokenTree(tt @ tt::TokenTree::Leaf(..)) => buf.push(tt.clone()),
89 Op::TokenTree(tt::TokenTree::Subtree(tt)) => { 89 Op::TokenTree(tt::TokenTree::Subtree(tt)) => {
90 let (tt, e) = expand_subtree(ctx, tt); 90 let ExpandResult(tt, e) = expand_subtree(ctx, tt);
91 err = err.or(e); 91 err = err.or(e);
92 buf.push(tt.into()); 92 buf.push(tt.into());
93 } 93 }
94 Op::Var { name, kind: _ } => { 94 Op::Var { name, kind: _ } => {
95 let (fragment, e) = expand_var(ctx, name); 95 let ExpandResult(fragment, e) = expand_var(ctx, name);
96 err = err.or(e); 96 err = err.or(e);
97 push_fragment(&mut buf, fragment); 97 push_fragment(&mut buf, fragment);
98 } 98 }
99 Op::Repeat { subtree, kind, separator } => { 99 Op::Repeat { subtree, kind, separator } => {
100 let (fragment, e) = expand_repeat(ctx, subtree, kind, separator); 100 let ExpandResult(fragment, e) = expand_repeat(ctx, subtree, kind, separator);
101 err = err.or(e); 101 err = err.or(e);
102 push_fragment(&mut buf, fragment) 102 push_fragment(&mut buf, fragment)
103 } 103 }
104 } 104 }
105 } 105 }
106 (tt::Subtree { delimiter: template.delimiter, token_trees: buf }, err) 106 ExpandResult(tt::Subtree { delimiter: template.delimiter, token_trees: buf }, err)
107} 107}
108 108
109fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> ExpandResult<Fragment> { 109fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> ExpandResult<Fragment> {
@@ -112,7 +112,7 @@ fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> ExpandResult<Fragment> {
112 let tt = 112 let tt =
113 tt::Leaf::from(tt::Ident { text: "$crate".into(), id: tt::TokenId::unspecified() }) 113 tt::Leaf::from(tt::Ident { text: "$crate".into(), id: tt::TokenId::unspecified() })
114 .into(); 114 .into();
115 (Fragment::Tokens(tt), None) 115 ExpandResult::ok(Fragment::Tokens(tt))
116 } else if !ctx.bindings.contains(v) { 116 } else if !ctx.bindings.contains(v) {
117 // Note that it is possible to have a `$var` inside a macro which is not bound. 117 // Note that it is possible to have a `$var` inside a macro which is not bound.
118 // For example: 118 // For example:
@@ -141,11 +141,11 @@ fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> ExpandResult<Fragment> {
141 ], 141 ],
142 } 142 }
143 .into(); 143 .into();
144 (Fragment::Tokens(tt), None) 144 ExpandResult::ok(Fragment::Tokens(tt))
145 } else { 145 } else {
146 ctx.bindings.get(&v, &mut ctx.nesting).map_or_else( 146 ctx.bindings.get(&v, &mut ctx.nesting).map_or_else(
147 |e| (Fragment::Tokens(tt::TokenTree::empty()), Some(e)), 147 |e| ExpandResult(Fragment::Tokens(tt::TokenTree::empty()), Some(e)),
148 |b| (b.clone(), None), 148 |b| ExpandResult::ok(b.clone()),
149 ) 149 )
150 } 150 }
151} 151}
@@ -165,7 +165,7 @@ fn expand_repeat(
165 let mut counter = 0; 165 let mut counter = 0;
166 166
167 loop { 167 loop {
168 let (mut t, e) = expand_subtree(ctx, template); 168 let ExpandResult(mut t, e) = expand_subtree(ctx, template);
169 let nesting_state = ctx.nesting.last_mut().unwrap(); 169 let nesting_state = ctx.nesting.last_mut().unwrap();
170 if nesting_state.at_end || !nesting_state.hit { 170 if nesting_state.at_end || !nesting_state.hit {
171 break; 171 break;
@@ -225,9 +225,9 @@ fn expand_repeat(
225 let tt = tt::Subtree { delimiter: None, token_trees: buf }.into(); 225 let tt = tt::Subtree { delimiter: None, token_trees: buf }.into();
226 226
227 if RepeatKind::OneOrMore == kind && counter == 0 { 227 if RepeatKind::OneOrMore == kind && counter == 0 {
228 return (Fragment::Tokens(tt), Some(ExpandError::UnexpectedToken)); 228 return ExpandResult(Fragment::Tokens(tt), Some(ExpandError::UnexpectedToken));
229 } 229 }
230 (Fragment::Tokens(tt), None) 230 ExpandResult::ok(Fragment::Tokens(tt))
231} 231}
232 232
233fn push_fragment(buf: &mut Vec<tt::TokenTree>, fragment: Fragment) { 233fn push_fragment(buf: &mut Vec<tt::TokenTree>, fragment: Fragment) {
diff --git a/crates/ra_mbe/src/tests.rs b/crates/ra_mbe/src/tests.rs
index faf88c1b1..44f381938 100644
--- a/crates/ra_mbe/src/tests.rs
+++ b/crates/ra_mbe/src/tests.rs
@@ -1430,8 +1430,7 @@ impl MacroFixture {
1430 let (invocation_tt, _) = 1430 let (invocation_tt, _) =
1431 ast_to_token_tree(&macro_invocation.token_tree().unwrap()).unwrap(); 1431 ast_to_token_tree(&macro_invocation.token_tree().unwrap()).unwrap();
1432 1432
1433 let (tt, err) = self.rules.expand(&invocation_tt); 1433 self.rules.expand(&invocation_tt).result()
1434 err.map(Err).unwrap_or(Ok(tt))
1435 } 1434 }
1436 1435
1437 fn assert_expand_err(&self, invocation: &str, err: &ExpandError) { 1436 fn assert_expand_err(&self, invocation: &str, err: &ExpandError) {