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() {}`
7 use super::ExpandResult;
9 expander::{Binding, Bindings, Fragment},
10 parser::{Op, RepeatKind, Separator},
11 ExpandError, MetaTemplate,
15 fn contains(&self, name: &str) -> bool {
16 self.inner.contains_key(name)
19 fn get(&self, name: &str, nesting: &mut [NestingState]) -> Result<&Fragment, ExpandError> {
20 let mut b = self.inner.get(name).ok_or_else(|| {
21 ExpandError::BindingError(format!("could not find binding `{}`", name))
23 for nesting_state in nesting.iter_mut() {
24 nesting_state.hit = true;
26 Binding::Fragment(_) => break,
27 Binding::Nested(bs) => bs.get(nesting_state.idx).ok_or_else(|| {
28 nesting_state.at_end = true;
29 ExpandError::BindingError(format!("could not find nested binding `{}`", name))
32 nesting_state.at_end = true;
33 return Err(ExpandError::BindingError(format!(
34 "could not find empty binding `{}`",
41 Binding::Fragment(it) => Ok(it),
42 Binding::Nested(_) => Err(ExpandError::BindingError(format!(
43 "expected simple binding, found nested binding `{}`",
46 Binding::Empty => Err(ExpandError::BindingError(format!(
47 "expected simple binding, found empty binding `{}`",
54 pub(super) fn transcribe(
55 template: &MetaTemplate,
57 ) -> ExpandResult<tt::Subtree> {
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, None, &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 delimiter: Option<Delimiter>,
84 arena: &mut Vec<tt::TokenTree>,
85 ) -> ExpandResult<tt::Subtree> {
86 // 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
87 let start_elements = arena.len();
89 for op in template.iter() {
91 Op::Leaf(tt) => arena.push(tt.clone().into()),
92 Op::Subtree { tokens, delimiter } => {
93 let ExpandResult { value: tt, err: e } =
94 expand_subtree(ctx, &tokens, *delimiter, arena);
96 arena.push(tt.into());
98 Op::Var { name, id, .. } => {
99 let ExpandResult { value: fragment, err: e } = expand_var(ctx, &name, *id);
101 push_fragment(arena, fragment);
103 Op::Repeat { tokens: subtree, kind, separator } => {
104 let ExpandResult { value: fragment, err: e } =
105 expand_repeat(ctx, subtree, *kind, separator, arena);
107 push_fragment(arena, fragment)
111 // drain the elements added in this instance of expand_subtree
112 let tts = arena.drain(start_elements..arena.len()).collect();
113 ExpandResult { value: tt::Subtree { delimiter, token_trees: tts }, err }
116 fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr, id: tt::TokenId) -> ExpandResult<Fragment> {
117 // We already handle $crate case in mbe parser
118 debug_assert!(v != "crate");
120 if !ctx.bindings.contains(v) {
121 // Note that it is possible to have a `$var` inside a macro which is not bound.
124 // macro_rules! foo {
125 // ($a:ident, $b:ident, $c:tt) => {
126 // macro_rules! bar {
128 // fn $bi() -> u8 {$c}
133 // We just treat it a normal tokens
134 let tt = tt::Subtree {
137 tt::Leaf::from(tt::Punct { char: '$', spacing: tt::Spacing::Alone, id }).into(),
138 tt::Leaf::from(tt::Ident { text: v.clone(), id }).into(),
142 ExpandResult::ok(Fragment::Tokens(tt))
144 ctx.bindings.get(&v, &mut ctx.nesting).map_or_else(
145 |e| ExpandResult { value: Fragment::Tokens(tt::TokenTree::empty()), err: Some(e) },
146 |b| ExpandResult::ok(b.clone()),
153 template: &MetaTemplate,
155 separator: &Option<Separator>,
156 arena: &mut Vec<tt::TokenTree>,
157 ) -> ExpandResult<Fragment> {
158 let mut buf: Vec<tt::TokenTree> = Vec::new();
159 ctx.nesting.push(NestingState { idx: 0, at_end: false, hit: false });
160 // Dirty hack to make macro-expansion terminate.
161 // This should be replaced by a proper macro-by-example implementation
163 let mut has_seps = 0;
167 let ExpandResult { value: mut t, err: e } = expand_subtree(ctx, template, None, arena);
168 let nesting_state = ctx.nesting.last_mut().unwrap();
169 if nesting_state.at_end || !nesting_state.hit {
172 nesting_state.idx += 1;
173 nesting_state.hit = false;
176 if counter == limit {
177 log::warn!("expand_tt in repeat pattern exceed limit => {:#?}\n{:#?}", template, ctx);
186 push_subtree(&mut buf, t);
188 if let Some(ref sep) = separator {
190 Separator::Ident(ident) => {
192 buf.push(tt::Leaf::from(ident.clone()).into());
194 Separator::Literal(lit) => {
196 buf.push(tt::Leaf::from(lit.clone()).into());
199 Separator::Puncts(puncts) => {
200 has_seps = puncts.len();
201 for punct in puncts {
202 buf.push(tt::Leaf::from(*punct).into());
208 if RepeatKind::ZeroOrOne == kind {
213 ctx.nesting.pop().unwrap();
214 for _ in 0..has_seps {
218 // Check if it is a single token subtree without any delimiter
219 // e.g {Delimiter:None> ['>'] /Delimiter:None>}
220 let tt = tt::Subtree { delimiter: None, token_trees: buf }.into();
222 if RepeatKind::OneOrMore == kind && counter == 0 {
223 return ExpandResult {
224 value: Fragment::Tokens(tt),
225 err: Some(ExpandError::UnexpectedToken),
228 ExpandResult::ok(Fragment::Tokens(tt))
231 fn push_fragment(buf: &mut Vec<tt::TokenTree>, fragment: Fragment) {
233 Fragment::Tokens(tt::TokenTree::Subtree(tt)) => push_subtree(buf, tt),
234 Fragment::Tokens(tt) | Fragment::Ast(tt) => buf.push(tt),
238 fn push_subtree(buf: &mut Vec<tt::TokenTree>, tt: tt::Subtree) {
240 None => buf.extend(tt.token_trees),
241 _ => buf.push(tt.into()),