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() {
92 err = Some(e.clone());
97 Op::Leaf(tt) => arena.push(tt.clone().into()),
99 let ExpandResult { value: tt, err: e } = expand_subtree(ctx, &tt, arena);
101 arena.push(tt.into());
103 Op::Var { name, id, .. } => {
104 let ExpandResult { value: fragment, err: e } = expand_var(ctx, &name, *id);
106 push_fragment(arena, fragment);
108 Op::Repeat { subtree, kind, separator } => {
109 let ExpandResult { value: fragment, err: e } =
110 expand_repeat(ctx, subtree, *kind, separator, arena);
112 push_fragment(arena, fragment)
116 // drain the elements added in this instance of expand_subtree
117 let tts = arena.drain(start_elements..arena.len()).collect();
118 ExpandResult { value: tt::Subtree { delimiter: template.delimiter, token_trees: tts }, err }
121 fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr, id: tt::TokenId) -> ExpandResult<Fragment> {
122 // We already handle $crate case in mbe parser
123 debug_assert!(v != "crate");
125 if !ctx.bindings.contains(v) {
126 // Note that it is possible to have a `$var` inside a macro which is not bound.
129 // macro_rules! foo {
130 // ($a:ident, $b:ident, $c:tt) => {
131 // macro_rules! bar {
133 // fn $bi() -> u8 {$c}
138 // We just treat it a normal tokens
139 let tt = tt::Subtree {
142 tt::Leaf::from(tt::Punct { char: '$', spacing: tt::Spacing::Alone, id }).into(),
143 tt::Leaf::from(tt::Ident { text: v.clone(), id }).into(),
147 ExpandResult::ok(Fragment::Tokens(tt))
149 ctx.bindings.get(&v, &mut ctx.nesting).map_or_else(
150 |e| ExpandResult { value: Fragment::Tokens(tt::TokenTree::empty()), err: Some(e) },
151 |b| ExpandResult::ok(b.clone()),
158 template: &MetaTemplate,
160 separator: &Option<Separator>,
161 arena: &mut Vec<tt::TokenTree>,
162 ) -> ExpandResult<Fragment> {
163 let mut buf: Vec<tt::TokenTree> = Vec::new();
164 ctx.nesting.push(NestingState { idx: 0, at_end: false, hit: false });
165 // Dirty hack to make macro-expansion terminate.
166 // This should be replaced by a proper macro-by-example implementation
168 let mut has_seps = 0;
172 let ExpandResult { value: mut t, err: e } = expand_subtree(ctx, template, arena);
173 let nesting_state = ctx.nesting.last_mut().unwrap();
174 if nesting_state.at_end || !nesting_state.hit {
177 nesting_state.idx += 1;
178 nesting_state.hit = false;
181 if counter == limit {
182 log::warn!("expand_tt in repeat pattern exceed limit => {:#?}\n{:#?}", template, ctx);
191 push_subtree(&mut buf, t);
193 if let Some(ref sep) = separator {
195 Separator::Ident(ident) => {
197 buf.push(tt::Leaf::from(ident.clone()).into());
199 Separator::Literal(lit) => {
201 buf.push(tt::Leaf::from(lit.clone()).into());
204 Separator::Puncts(puncts) => {
205 has_seps = puncts.len();
206 for punct in puncts {
207 buf.push(tt::Leaf::from(*punct).into());
213 if RepeatKind::ZeroOrOne == kind {
218 ctx.nesting.pop().unwrap();
219 for _ in 0..has_seps {
223 // Check if it is a single token subtree without any delimiter
224 // e.g {Delimiter:None> ['>'] /Delimiter:None>}
225 let tt = tt::Subtree { delimiter: None, token_trees: buf }.into();
227 if RepeatKind::OneOrMore == kind && counter == 0 {
228 return ExpandResult {
229 value: Fragment::Tokens(tt),
230 err: Some(ExpandError::UnexpectedToken),
233 ExpandResult::ok(Fragment::Tokens(tt))
236 fn push_fragment(buf: &mut Vec<tt::TokenTree>, fragment: Fragment) {
238 Fragment::Tokens(tt::TokenTree::Subtree(tt)) => push_subtree(buf, tt),
239 Fragment::Tokens(tt) | Fragment::Ast(tt) => buf.push(tt),
243 fn push_subtree(buf: &mut Vec<tt::TokenTree>, tt: tt::Subtree) {
245 None => buf.extend(tt.token_trees),
246 _ => buf.push(tt.into()),