Skip to content

Commit a78142c

Browse files
bors[bot]matklad
andcommitted
Merge #791
791: docs r=matklad a=matklad Co-authored-by: Aleksey Kladov <[email protected]>
2 parents b356ab4 + ae31268 commit a78142c

File tree

5 files changed

+65
-13
lines changed

5 files changed

+65
-13
lines changed

crates/ra_mbe/src/lib.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,8 @@ impl_froms!(TokenTree: Leaf, Subtree);
144144
let macro_invocation =
145145
source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap();
146146

147-
let definition_tt = ast_to_token_tree(macro_definition.token_tree().unwrap()).unwrap();
148-
let invocation_tt = ast_to_token_tree(macro_invocation.token_tree().unwrap()).unwrap();
147+
let (definition_tt, _) = ast_to_token_tree(macro_definition.token_tree().unwrap()).unwrap();
148+
let (invocation_tt, _) = ast_to_token_tree(macro_invocation.token_tree().unwrap()).unwrap();
149149
let rules = crate::MacroRules::parse(&definition_tt).unwrap();
150150
let expansion = rules.expand(&invocation_tt).unwrap();
151151
assert_eq!(
@@ -160,7 +160,7 @@ impl_froms!(TokenTree: Leaf, Subtree);
160160
let macro_definition =
161161
source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap();
162162

163-
let definition_tt = ast_to_token_tree(macro_definition.token_tree().unwrap()).unwrap();
163+
let (definition_tt, _) = ast_to_token_tree(macro_definition.token_tree().unwrap()).unwrap();
164164
crate::MacroRules::parse(&definition_tt).unwrap()
165165
}
166166

@@ -169,7 +169,7 @@ impl_froms!(TokenTree: Leaf, Subtree);
169169
let macro_invocation =
170170
source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap();
171171

172-
let invocation_tt = ast_to_token_tree(macro_invocation.token_tree().unwrap()).unwrap();
172+
let (invocation_tt, _) = ast_to_token_tree(macro_invocation.token_tree().unwrap()).unwrap();
173173

174174
let expaned = rules.expand(&invocation_tt).unwrap();
175175
assert_eq!(expaned.to_string(), expansion);

crates/ra_mbe/src/mbe_expander.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
/// `tt::TokenTree` for the result of the expansion.
44
use rustc_hash::FxHashMap;
55
use ra_syntax::SmolStr;
6+
use tt::TokenId;
67

78
use crate::tt_cursor::TtCursor;
89

@@ -185,7 +186,8 @@ fn expand_tt(
185186
}
186187
crate::TokenTree::Leaf(leaf) => match leaf {
187188
crate::Leaf::Ident(ident) => {
188-
tt::Leaf::from(tt::Ident { text: ident.text.clone() }).into()
189+
tt::Leaf::from(tt::Ident { text: ident.text.clone(), id: TokenId::unspecified() })
190+
.into()
189191
}
190192
crate::Leaf::Punct(punct) => tt::Leaf::from(punct.clone()).into(),
191193
crate::Leaf::Var(v) => bindings.get(&v.text, nesting)?.clone(),

crates/ra_mbe/src/mbe_parser.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ fn parse_subtree(tt: &tt::Subtree) -> Option<crate::Subtree> {
4141
}
4242
}
4343
tt::Leaf::Punct(punct) => crate::Leaf::from(*punct).into(),
44-
tt::Leaf::Ident(tt::Ident { text }) => {
44+
tt::Leaf::Ident(tt::Ident { text, id: _ }) => {
4545
crate::Leaf::from(crate::Ident { text: text.clone() }).into()
4646
}
4747
tt::Leaf::Literal(tt::Literal { text }) => {

crates/ra_mbe/src/syntax_bridge.rs

+40-6
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,42 @@
1-
use ra_syntax::{ast, AstNode, SyntaxNode, SyntaxKind::*};
1+
use ra_syntax::{
2+
AstNode, SyntaxNode, TextRange,
3+
ast, SyntaxKind::*, TextUnit
4+
};
25

3-
pub fn ast_to_token_tree(ast: &ast::TokenTree) -> Option<tt::Subtree> {
4-
convert_tt(ast.syntax())
6+
/// Maps `tt::TokenId` to the relative range of the original token.
7+
#[derive(Default)]
8+
pub struct TokenMap {
9+
/// Maps `tt::TokenId` to the *relative* source range.
10+
toknes: Vec<TextRange>,
511
}
612

7-
fn convert_tt(tt: &SyntaxNode) -> Option<tt::Subtree> {
13+
/// Convert the syntax tree (what user has written) to a `TokenTree` (what macro
14+
/// will consume).
15+
pub fn ast_to_token_tree(ast: &ast::TokenTree) -> Option<(tt::Subtree, TokenMap)> {
16+
let mut token_map = TokenMap::default();
17+
let node = ast.syntax();
18+
let tt = convert_tt(&mut token_map, node.range().start(), node)?;
19+
Some((tt, token_map))
20+
}
21+
22+
impl TokenMap {
23+
pub fn relative_range_of(&self, tt: tt::TokenId) -> Option<TextRange> {
24+
let idx = tt.0 as usize;
25+
self.toknes.get(idx).map(|&it| it)
26+
}
27+
28+
fn alloc(&mut self, relative_range: TextRange) -> tt::TokenId {
29+
let id = self.toknes.len();
30+
self.toknes.push(relative_range);
31+
tt::TokenId(id as u32)
32+
}
33+
}
34+
35+
fn convert_tt(
36+
token_map: &mut TokenMap,
37+
global_offset: TextUnit,
38+
tt: &SyntaxNode,
39+
) -> Option<tt::Subtree> {
840
let first_child = tt.first_child()?;
941
let last_child = tt.last_child()?;
1042
let delimiter = match (first_child.kind(), last_child.kind()) {
@@ -34,10 +66,12 @@ fn convert_tt(tt: &SyntaxNode) -> Option<tt::Subtree> {
3466
}
3567
} else {
3668
let child: tt::TokenTree = if child.kind() == TOKEN_TREE {
37-
convert_tt(child)?.into()
69+
convert_tt(token_map, global_offset, child)?.into()
3870
} else if child.kind().is_keyword() || child.kind() == IDENT {
71+
let relative_range = child.range() - global_offset;
72+
let id = token_map.alloc(relative_range);
3973
let text = child.leaf_text().unwrap().clone();
40-
tt::Leaf::from(tt::Ident { text }).into()
74+
tt::Leaf::from(tt::Ident { text, id }).into()
4175
} else if child.kind().is_literal() {
4276
tt::Leaf::from(tt::Literal { text: child.leaf_text().unwrap().clone() }).into()
4377
} else {

crates/ra_tt/src/lib.rs

+17-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/// `tt` crate defines a `TokenTree` datastructure: this is the interface (both
1+
/// `tt` crate defines a `TokenTree` data structure: this is the interface (both
22
/// input and output) of macros. It closely mirrors `proc_macro` crate's
33
/// `TokenTree`.
44
@@ -18,6 +18,21 @@ use std::fmt;
1818

1919
use smol_str::SmolStr;
2020

21+
/// Represents identity of the token.
22+
///
23+
/// For hygiene purposes, we need to track which expanded tokens originated from
24+
/// which source tokens. We do it by assigning an distinct identity to each
25+
/// source token and making sure that identities are preserved during macro
26+
/// expansion.
27+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
28+
pub struct TokenId(pub u32);
29+
30+
impl TokenId {
31+
pub const fn unspecified() -> TokenId {
32+
TokenId(!0)
33+
}
34+
}
35+
2136
#[derive(Debug, Clone)]
2237
pub enum TokenTree {
2338
Leaf(Leaf),
@@ -67,6 +82,7 @@ pub enum Spacing {
6782
#[derive(Debug, Clone)]
6883
pub struct Ident {
6984
pub text: SmolStr,
85+
pub id: TokenId,
7086
}
7187

7288
impl fmt::Display for TokenTree {

0 commit comments

Comments
 (0)