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.rs91
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,
}
}