Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/mbe/src/expander/transcriber.rs')
| -rw-r--r-- | crates/mbe/src/expander/transcriber.rs | 91 |
1 files changed, 23 insertions, 68 deletions
diff --git a/crates/mbe/src/expander/transcriber.rs b/crates/mbe/src/expander/transcriber.rs index 4de7cccd96..286bd748cb 100644 --- a/crates/mbe/src/expander/transcriber.rs +++ b/crates/mbe/src/expander/transcriber.rs @@ -8,14 +8,17 @@ use tt::Delimiter; use crate::{ expander::{Binding, Bindings, Fragment}, parser::{MetaVarKind, Op, RepeatKind, Separator}, - CountError, ExpandError, ExpandResult, MetaTemplate, + ExpandError, ExpandErrorKind, ExpandResult, MetaTemplate, }; impl Bindings { - fn get(&self, name: &Symbol) -> Result<&Binding, ExpandError> { + fn get(&self, name: &Symbol, span: Span) -> Result<&Binding, ExpandError> { match self.inner.get(name) { Some(binding) => Ok(binding), - None => Err(ExpandError::UnresolvedBinding(Box::new(Box::from(name.as_str())))), + None => Err(ExpandError::new( + span, + ExpandErrorKind::UnresolvedBinding(Box::new(Box::from(name.as_str()))), + )), } } @@ -27,10 +30,10 @@ impl Bindings { marker: impl Fn(&mut Span), ) -> Result<Fragment, ExpandError> { macro_rules! binding_err { - ($($arg:tt)*) => { ExpandError::binding_error(format!($($arg)*)) }; + ($($arg:tt)*) => { ExpandError::binding_error(span, format!($($arg)*)) }; } - let mut b = self.get(name)?; + let mut b = self.get(name, span)?; for nesting_state in nesting.iter_mut() { nesting_state.hit = true; b = match b { @@ -142,10 +145,9 @@ pub(super) fn transcribe( template: &MetaTemplate, bindings: &Bindings, marker: impl Fn(&mut Span) + Copy, - new_meta_vars: bool, call_site: Span, ) -> ExpandResult<tt::Subtree<Span>> { - let mut ctx = ExpandCtx { bindings, nesting: Vec::new(), new_meta_vars, call_site }; + let mut ctx = ExpandCtx { bindings, nesting: Vec::new(), call_site }; let mut arena: Vec<tt::TokenTree<Span>> = Vec::new(); expand_subtree(&mut ctx, template, None, &mut arena, marker) } @@ -165,7 +167,6 @@ struct NestingState { struct ExpandCtx<'a> { bindings: &'a Bindings, nesting: Vec<NestingState>, - new_meta_vars: bool, call_site: Span, } @@ -263,7 +264,7 @@ fn expand_subtree( ); } Op::Count { name, depth } => { - let mut binding = match ctx.bindings.get(name) { + let mut binding = match ctx.bindings.get(name, ctx.call_site) { Ok(b) => b, Err(e) => { if err.is_none() { @@ -299,29 +300,11 @@ fn expand_subtree( } } - let res = if ctx.new_meta_vars { - count(binding, 0, depth.unwrap_or(0)) - } else { - count_old(binding, 0, *depth) - }; + let res = count(binding, 0, depth.unwrap_or(0)); - let c = match res { - Ok(c) => c, - Err(e) => { - // XXX: It *might* make sense to emit a dummy integer value like `0` here. - // That would type inference a bit more robust in cases like - // `v[${count(t)}]` where index doesn't matter, but also could lead to - // wrong infefrence for cases like `tup.${count(t)}` where index itself - // does matter. - if err.is_none() { - err = Some(e.into()); - } - continue; - } - }; arena.push( tt::Leaf::Literal(tt::Literal { - symbol: Symbol::integer(c), + symbol: Symbol::integer(res), span: ctx.call_site, suffix: None, kind: tt::LitKind::Integer, @@ -353,7 +336,7 @@ fn expand_var( match ctx.bindings.get_fragment(v, id, &mut ctx.nesting, marker) { Ok(it) => ExpandResult::ok(it), - Err(ExpandError::UnresolvedBinding(_)) => { + Err(e) if matches!(e.inner.1, ExpandErrorKind::UnresolvedBinding(_)) => { // Note that it is possible to have a `$var` inside a macro which is not bound. // For example: // ``` @@ -435,7 +418,7 @@ fn expand_repeat( } .into(), ), - err: Some(ExpandError::LimitExceeded), + err: Some(ExpandError::new(ctx.call_site, ExpandErrorKind::LimitExceeded)), }; } @@ -481,16 +464,16 @@ fn expand_repeat( let tt = tt::Subtree { delimiter: tt::Delimiter::invisible_spanned(ctx.call_site), token_trees: buf.into_boxed_slice(), - } - .into(); + }; if RepeatKind::OneOrMore == kind && counter == 0 { + let span = tt.delimiter.open; return ExpandResult { - value: Fragment::Tokens(tt), - err: Some(ExpandError::UnexpectedToken), + value: Fragment::Tokens(tt.into()), + err: Some(ExpandError::new(span, ExpandErrorKind::UnexpectedToken)), }; } - ExpandResult { value: Fragment::Tokens(tt), err } + ExpandResult { value: Fragment::Tokens(tt.into()), err } } fn push_fragment(ctx: &ExpandCtx<'_>, buf: &mut Vec<tt::TokenTree<Span>>, fragment: Fragment) { @@ -557,44 +540,16 @@ fn fix_up_and_push_path_tt( /// Handles `${count(t, depth)}`. `our_depth` is the recursion depth and `count_depth` is the depth /// defined by the metavar expression. -fn count(binding: &Binding, depth_curr: usize, depth_max: usize) -> Result<usize, CountError> { +fn count(binding: &Binding, depth_curr: usize, depth_max: usize) -> usize { match binding { Binding::Nested(bs) => { if depth_curr == depth_max { - Ok(bs.len()) + bs.len() } else { bs.iter().map(|b| count(b, depth_curr + 1, depth_max)).sum() } } - Binding::Empty => Ok(0), - Binding::Fragment(_) | Binding::Missing(_) => Ok(1), - } -} - -fn count_old( - binding: &Binding, - our_depth: usize, - count_depth: Option<usize>, -) -> Result<usize, CountError> { - match binding { - Binding::Nested(bs) => match count_depth { - None => bs.iter().map(|b| count_old(b, our_depth + 1, None)).sum(), - Some(0) => Ok(bs.len()), - Some(d) => bs.iter().map(|b| count_old(b, our_depth + 1, Some(d - 1))).sum(), - }, - Binding::Empty => Ok(0), - Binding::Fragment(_) | Binding::Missing(_) => { - if our_depth == 0 { - // `${count(t)}` is placed inside the innermost repetition. This includes cases - // where `t` is not a repeated fragment. - Err(CountError::Misplaced) - } else if count_depth.is_none() { - Ok(1) - } else { - // We've reached at the innermost repeated fragment, but the user wants us to go - // further! - Err(CountError::OutOfBounds) - } - } + Binding::Empty => 0, + Binding::Fragment(_) | Binding::Missing(_) => 1, } } |