1 //! Transcriber takes a template, like `fn $ident() {}`, a set of bindings like
2 //! `$ident => foo`, interpolates variables in the template, to get `fn foo() {}`
6 use super::ExpandResult;
8 expander::{Binding, Bindings, Fragment},
9 parser::{Op, RepeatKind, Separator},
10 ExpandError, MetaTemplate,
14 fn contains(&self, name: &str) -> bool {
15 self.inner.contains_key(name)
18 fn get(&self, name: &str, nesting: &mut [NestingState]) -> Result<&Fragment, ExpandError> {
19 let mut b = self.inner.get(name).ok_or_else(|| {
20 ExpandError::BindingError(format!("could not find binding `{}`", name))
22 for nesting_state in nesting.iter_mut() {
23 nesting_state.hit = true;
25 Binding::Fragment(_) => break,
26 Binding::Nested(bs) => bs.get(nesting_state.idx).ok_or_else(|| {
27 nesting_state.at_end = true;
28 ExpandError::BindingError(format!("could not find nested binding `{}`", name))
31 nesting_state.at_end = true;
32 return Err(ExpandError::BindingError(format!(
33 "could not find empty binding `{}`",
40 Binding::Fragment(it) => Ok(it),
41 Binding::Nested(_) => Err(ExpandError::BindingError(format!(
42 "expected simple binding, found nested binding `{}`",
45 Binding::Empty => Err(ExpandError::BindingError(format!(
46 "expected simple binding, found empty binding `{}`",
53 pub(super) fn transcribe(
54 template: &MetaTemplate,
56 ) -> ExpandResult<tt::Subtree> {
57 assert!(template.delimiter == None);
58 let mut ctx = ExpandCtx { bindings: &bindings, nesting: Vec::new() };
59 let mut arena: Vec<tt::TokenTree> = Vec::new();
60 expand_subtree(&mut ctx, template, &mut arena)
66 /// `hit` is currently necessary to tell `expand_repeat` if it should stop
67 /// because there is no variable in use by the current repetition
69 /// `at_end` is currently necessary to tell `expand_repeat` if it should stop
70 /// because there is no more value available for the current repetition
75 struct ExpandCtx<'a> {
76 bindings: &'a Bindings,
77 nesting: Vec<NestingState>,
82 template: &MetaTemplate,
83 arena: &mut Vec<tt::TokenTree>,
84 ) -> ExpandResult<tt::Subtree> {
85 // remember how many elements are in the arena now - when returning, we want to drain exactly how many elements we added. This way, the recursive uses of the arena get their own "view" of the arena, but will reuse the allocation
86 let start_elements = arena.len();
88 for op in template.iter() {
90 Op::Leaf(tt) => arena.push(tt.clone().into()),
92 let ExpandResult { value: tt, err: e } = expand_subtree(ctx, &tt, arena);
94 arena.push(tt.into());
96 Op::Var { name, id, .. } => {
97 let ExpandResult { value: fragment, err: e } = expand_var(ctx, &name, *id);
99 push_fragment(arena, fragment);
101 Op::Repeat { subtree, kind, separator } => {
102 let ExpandResult { value: fragment, err: e } =
103 expand_repeat(ctx, subtree, *kind, separator, arena);
105 push_fragment(arena, fragment)
109 // drain the elements added in this instance of expand_subtree
110 let tts = arena.drain(start_elements..arena.len()).collect();
111 ExpandResult { value: tt::Subtree { delimiter: template.delimiter, token_trees: tts }, err }
114 fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr, id: tt::TokenId) -> ExpandResult<Fragment> {
115 // We already handle $crate case in mbe parser
116 debug_assert!(v != "crate");
118 if !ctx.bindings.contains(v) {
119 // Note that it is possible to have a `$var` inside a macro which is not bound.
122 // macro_rules! foo {
123 // ($a:ident, $b:ident, $c:tt) => {
124 // macro_rules! bar {
126 // fn $bi() -> u8 {$c}
131 // We just treat it a normal tokens
132 let tt = tt::Subtree {
135 tt::Leaf::from(tt::Punct { char: '$', spacing: tt::Spacing::Alone, id }).into(),
136 tt::Leaf::from(tt::Ident { text: v.clone(), id }).into(),
140 ExpandResult::ok(Fragment::Tokens(tt))
142 ctx.bindings.get(&v, &mut ctx.nesting).map_or_else(
143 |e| ExpandResult { value: Fragment::Tokens(tt::TokenTree::empty()), err: Some(e) },
144 |b| ExpandResult::ok(b.clone()),
151 template: &MetaTemplate,
153 separator: &Option<Separator>,
154 arena: &mut Vec<tt::TokenTree>,
155 ) -> ExpandResult<Fragment> {
156 let mut buf: Vec<tt::TokenTree> = Vec::new();
157 ctx.nesting.push(NestingState { idx: 0, at_end: false, hit: false });
158 // Dirty hack to make macro-expansion terminate.
159 // This should be replaced by a proper macro-by-example implementation
161 let mut has_seps = 0;
165 let ExpandResult { value: mut t, err: e } = expand_subtree(ctx, template, arena);
166 let nesting_state = ctx.nesting.last_mut().unwrap();
167 if nesting_state.at_end || !nesting_state.hit {
170 nesting_state.idx += 1;
171 nesting_state.hit = false;
174 if counter == limit {
175 log::warn!("expand_tt in repeat pattern exceed limit => {:#?}\n{:#?}", template, ctx);
184 push_subtree(&mut buf, t);
186 if let Some(ref sep) = separator {
188 Separator::Ident(ident) => {
190 buf.push(tt::Leaf::from(ident.clone()).into());
192 Separator::Literal(lit) => {
194 buf.push(tt::Leaf::from(lit.clone()).into());
197 Separator::Puncts(puncts) => {
198 has_seps = puncts.len();
199 for punct in puncts {
200 buf.push(tt::Leaf::from(*punct).into());
206 if RepeatKind::ZeroOrOne == kind {
211 ctx.nesting.pop().unwrap();
212 for _ in 0..has_seps {
216 // Check if it is a single token subtree without any delimiter
217 // e.g {Delimiter:None> ['>'] /Delimiter:None>}
218 let tt = tt::Subtree { delimiter: None, token_trees: buf }.into();
220 if RepeatKind::OneOrMore == kind && counter == 0 {
221 return ExpandResult {
222 value: Fragment::Tokens(tt),
223 err: Some(ExpandError::UnexpectedToken),
226 ExpandResult::ok(Fragment::Tokens(tt))
229 fn push_fragment(buf: &mut Vec<tt::TokenTree>, fragment: Fragment) {
231 Fragment::Tokens(tt::TokenTree::Subtree(tt)) => push_subtree(buf, tt),
232 Fragment::Tokens(tt) | Fragment::Ast(tt) => buf.push(tt),
236 fn push_subtree(buf: &mut Vec<tt::TokenTree>, tt: tt::Subtree) {
238 None => buf.extend(tt.token_trees),
239 _ => buf.push(tt.into()),