aboutsummaryrefslogtreecommitdiff
path: root/crates/mbe/src/mbe_expander/transcriber.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/mbe/src/mbe_expander/transcriber.rs')
-rw-r--r--crates/mbe/src/mbe_expander/transcriber.rs47
1 files changed, 21 insertions, 26 deletions
diff --git a/crates/mbe/src/mbe_expander/transcriber.rs b/crates/mbe/src/mbe_expander/transcriber.rs
index 57592dc92..57f3f104d 100644
--- a/crates/mbe/src/mbe_expander/transcriber.rs
+++ b/crates/mbe/src/mbe_expander/transcriber.rs
@@ -6,8 +6,8 @@ use syntax::SmolStr;
6use super::ExpandResult; 6use super::ExpandResult;
7use crate::{ 7use crate::{
8 mbe_expander::{Binding, Bindings, Fragment}, 8 mbe_expander::{Binding, Bindings, Fragment},
9 parser::{parse_template, Op, RepeatKind, Separator}, 9 parser::{Op, RepeatKind, Separator},
10 ExpandError, 10 ExpandError, MetaTemplate,
11}; 11};
12 12
13impl Bindings { 13impl Bindings {
@@ -50,7 +50,10 @@ impl Bindings {
50 } 50 }
51} 51}
52 52
53pub(super) fn transcribe(template: &tt::Subtree, bindings: &Bindings) -> ExpandResult<tt::Subtree> { 53pub(super) fn transcribe(
54 template: &MetaTemplate,
55 bindings: &Bindings,
56) -> ExpandResult<tt::Subtree> {
54 assert!(template.delimiter == None); 57 assert!(template.delimiter == None);
55 let mut ctx = ExpandCtx { bindings: &bindings, nesting: Vec::new() }; 58 let mut ctx = ExpandCtx { bindings: &bindings, nesting: Vec::new() };
56 let mut arena: Vec<tt::TokenTree> = Vec::new(); 59 let mut arena: Vec<tt::TokenTree> = Vec::new();
@@ -76,35 +79,35 @@ struct ExpandCtx<'a> {
76 79
77fn expand_subtree( 80fn expand_subtree(
78 ctx: &mut ExpandCtx, 81 ctx: &mut ExpandCtx,
79 template: &tt::Subtree, 82 template: &MetaTemplate,
80 arena: &mut Vec<tt::TokenTree>, 83 arena: &mut Vec<tt::TokenTree>,
81) -> ExpandResult<tt::Subtree> { 84) -> ExpandResult<tt::Subtree> {
82 // 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 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
83 let start_elements = arena.len(); 86 let start_elements = arena.len();
84 let mut err = None; 87 let mut err = None;
85 for op in parse_template(template) { 88 for op in template.iter() {
86 let op = match op { 89 let op = match op {
87 Ok(op) => op, 90 Ok(op) => op,
88 Err(e) => { 91 Err(e) => {
89 err = Some(e); 92 err = Some(e.clone());
90 break; 93 break;
91 } 94 }
92 }; 95 };
93 match op { 96 match op {
94 Op::TokenTree(tt @ tt::TokenTree::Leaf(..)) => arena.push(tt.clone()), 97 Op::Leaf(tt) => arena.push(tt.clone().into()),
95 Op::TokenTree(tt::TokenTree::Subtree(tt)) => { 98 Op::Subtree(tt) => {
96 let ExpandResult { value: tt, err: e } = expand_subtree(ctx, tt, arena); 99 let ExpandResult { value: tt, err: e } = expand_subtree(ctx, &tt, arena);
97 err = err.or(e); 100 err = err.or(e);
98 arena.push(tt.into()); 101 arena.push(tt.into());
99 } 102 }
100 Op::Var { name, .. } => { 103 Op::Var { name, id, .. } => {
101 let ExpandResult { value: fragment, err: e } = expand_var(ctx, name); 104 let ExpandResult { value: fragment, err: e } = expand_var(ctx, &name, *id);
102 err = err.or(e); 105 err = err.or(e);
103 push_fragment(arena, fragment); 106 push_fragment(arena, fragment);
104 } 107 }
105 Op::Repeat { subtree, kind, separator } => { 108 Op::Repeat { subtree, kind, separator } => {
106 let ExpandResult { value: fragment, err: e } = 109 let ExpandResult { value: fragment, err: e } =
107 expand_repeat(ctx, subtree, kind, separator, arena); 110 expand_repeat(ctx, subtree, *kind, separator, arena);
108 err = err.or(e); 111 err = err.or(e);
109 push_fragment(arena, fragment) 112 push_fragment(arena, fragment)
110 } 113 }
@@ -115,12 +118,10 @@ fn expand_subtree(
115 ExpandResult { value: tt::Subtree { delimiter: template.delimiter, token_trees: tts }, err } 118 ExpandResult { value: tt::Subtree { delimiter: template.delimiter, token_trees: tts }, err }
116} 119}
117 120
118fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> ExpandResult<Fragment> { 121fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr, id: tt::TokenId) -> ExpandResult<Fragment> {
119 if v == "crate" { 122 if v == "crate" {
120 // We simply produce identifier `$crate` here. And it will be resolved when lowering ast to Path. 123 // We simply produce identifier `$crate` here. And it will be resolved when lowering ast to Path.
121 let tt = 124 let tt = tt::Leaf::from(tt::Ident { text: "$crate".into(), id }).into();
122 tt::Leaf::from(tt::Ident { text: "$crate".into(), id: tt::TokenId::unspecified() })
123 .into();
124 ExpandResult::ok(Fragment::Tokens(tt)) 125 ExpandResult::ok(Fragment::Tokens(tt))
125 } else if !ctx.bindings.contains(v) { 126 } else if !ctx.bindings.contains(v) {
126 // Note that it is possible to have a `$var` inside a macro which is not bound. 127 // Note that it is possible to have a `$var` inside a macro which is not bound.
@@ -139,14 +140,8 @@ fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> ExpandResult<Fragment> {
139 let tt = tt::Subtree { 140 let tt = tt::Subtree {
140 delimiter: None, 141 delimiter: None,
141 token_trees: vec![ 142 token_trees: vec![
142 tt::Leaf::from(tt::Punct { 143 tt::Leaf::from(tt::Punct { char: '$', spacing: tt::Spacing::Alone, id }).into(),
143 char: '$', 144 tt::Leaf::from(tt::Ident { text: v.clone(), id }).into(),
144 spacing: tt::Spacing::Alone,
145 id: tt::TokenId::unspecified(),
146 })
147 .into(),
148 tt::Leaf::from(tt::Ident { text: v.clone(), id: tt::TokenId::unspecified() })
149 .into(),
150 ], 145 ],
151 } 146 }
152 .into(); 147 .into();
@@ -161,9 +156,9 @@ fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> ExpandResult<Fragment> {
161 156
162fn expand_repeat( 157fn expand_repeat(
163 ctx: &mut ExpandCtx, 158 ctx: &mut ExpandCtx,
164 template: &tt::Subtree, 159 template: &MetaTemplate,
165 kind: RepeatKind, 160 kind: RepeatKind,
166 separator: Option<Separator>, 161 separator: &Option<Separator>,
167 arena: &mut Vec<tt::TokenTree>, 162 arena: &mut Vec<tt::TokenTree>,
168) -> ExpandResult<Fragment> { 163) -> ExpandResult<Fragment> {
169 let mut buf: Vec<tt::TokenTree> = Vec::new(); 164 let mut buf: Vec<tt::TokenTree> = Vec::new();