Skip to content

Commit c46768d

Browse files
committed
Add basic bultin macro infrastructure
1 parent defc7ad commit c46768d

File tree

8 files changed

+148
-29
lines changed

8 files changed

+148
-29
lines changed

crates/ra_hir/src/code_model/src.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ use crate::{
66
adt::VariantDef,
77
db::{AstDatabase, DefDatabase, HirDatabase},
88
ids::AstItemDef,
9-
Const, Either, Enum, EnumVariant, FieldSource, Function, HasBody, HirFileId, MacroDef, Module,
10-
ModuleSource, Static, Struct, StructField, Trait, TypeAlias, Union,
9+
Const, Either, Enum, EnumVariant, FieldSource, Function, HasBody, HirFileId, MacroDef,
10+
MacroDefId, Module, ModuleSource, Static, Struct, StructField, Trait, TypeAlias, Union,
1111
};
1212

1313
pub use hir_expand::Source;
@@ -140,10 +140,15 @@ impl HasSource for TypeAlias {
140140
self.id.source(db)
141141
}
142142
}
143+
143144
impl HasSource for MacroDef {
144145
type Ast = ast::MacroCall;
145146
fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::MacroCall> {
146-
Source { file_id: self.id.ast_id.file_id(), ast: self.id.ast_id.to_node(db) }
147+
let ast_id = match self.id {
148+
MacroDefId::DeclarativeMacro(it) => it.ast_id,
149+
MacroDefId::BuiltinMacro(it) => it.ast_id,
150+
};
151+
Source { file_id: ast_id.file_id(), ast: ast_id.to_node(db) }
147152
}
148153
}
149154

crates/ra_hir_def/src/nameres/collector.rs

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
//! FIXME: write short doc here
22
33
use hir_expand::{
4+
builtin_macro::find_builtin_macro,
45
name::{self, AsName, Name},
5-
HirFileId, MacroCallId, MacroCallLoc, MacroDefId, MacroFileKind,
6+
DeclarativeMacro, HirFileId, MacroCallId, MacroCallLoc, MacroDefId, MacroFileKind,
67
};
78
use ra_cfg::CfgOptions;
89
use ra_db::{CrateId, FileId};
@@ -688,11 +689,32 @@ where
688689
fn collect_macro(&mut self, mac: &raw::MacroData) {
689690
let ast_id = AstId::new(self.file_id, mac.ast_id);
690691

692+
// Case 0: builtin macros
693+
if mac.builtin {
694+
if let Some(name) = &mac.name {
695+
let krate = self.def_collector.def_map.krate;
696+
if let Some(macro_id) = find_builtin_macro(name, krate, ast_id) {
697+
self.def_collector.define_macro(
698+
self.module_id,
699+
name.clone(),
700+
macro_id,
701+
mac.export,
702+
);
703+
return;
704+
}
705+
}
706+
}
707+
691708
// Case 1: macro rules, define a macro in crate-global mutable scope
692709
if is_macro_rules(&mac.path) {
693710
if let Some(name) = &mac.name {
694-
let macro_id = MacroDefId { ast_id, krate: self.def_collector.def_map.krate };
695-
self.def_collector.define_macro(self.module_id, name.clone(), macro_id, mac.export);
711+
let macro_id = DeclarativeMacro { ast_id, krate: self.def_collector.def_map.krate };
712+
self.def_collector.define_macro(
713+
self.module_id,
714+
name.clone(),
715+
MacroDefId::DeclarativeMacro(macro_id),
716+
mac.export,
717+
);
696718
}
697719
return;
698720
}

crates/ra_hir_def/src/nameres/raw.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ pub(super) struct MacroData {
200200
pub(super) path: Path,
201201
pub(super) name: Option<Name>,
202202
pub(super) export: bool,
203+
pub(super) builtin: bool,
203204
}
204205

205206
struct RawItemsCollector {
@@ -367,7 +368,11 @@ impl RawItemsCollector {
367368
// FIXME: cfg_attr
368369
let export = m.attrs().filter_map(|x| x.simple_name()).any(|name| name == "macro_export");
369370

370-
let m = self.raw_items.macros.alloc(MacroData { ast_id, path, name, export });
371+
// FIXME: cfg_attr
372+
let builtin =
373+
m.attrs().filter_map(|x| x.simple_name()).any(|name| name == "rustc_builtin_macro");
374+
375+
let m = self.raw_items.macros.alloc(MacroData { ast_id, path, name, export, builtin });
371376
self.push_item(current_module, attrs, RawItemKind::Macro(m));
372377
}
373378

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//! Builtin macro
2+
use crate::{ast, name, AstId, BuiltinMacro, CrateId, MacroDefId};
3+
4+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
5+
pub enum BuiltinExpander {
6+
Line
7+
}
8+
9+
impl BuiltinExpander {
10+
pub fn expand(&self, _tt: &tt::Subtree) -> Result<tt::Subtree, mbe::ExpandError> {
11+
Err(mbe::ExpandError::UnexpectedToken)
12+
}
13+
}
14+
15+
pub fn find_builtin_macro(
16+
ident: &name::Name,
17+
krate: CrateId,
18+
ast_id: AstId<ast::MacroCall>,
19+
) -> Option<MacroDefId> {
20+
// FIXME: Better registering method
21+
if ident == &name::LINE {
22+
Some(MacroDefId::BuiltinMacro(BuiltinMacro { expander: BuiltinExpander::Line, krate, ast_id }))
23+
} else {
24+
None
25+
}
26+
}

crates/ra_hir_expand/src/db.rs

Lines changed: 50 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,37 @@ use ra_prof::profile;
99
use ra_syntax::{AstNode, Parse, SyntaxNode};
1010

1111
use crate::{
12-
ast_id_map::AstIdMap, HirFileId, HirFileIdRepr, MacroCallId, MacroCallLoc, MacroDefId,
13-
MacroFile, MacroFileKind,
12+
ast_id_map::AstIdMap, BuiltinExpander, HirFileId, HirFileIdRepr, MacroCallId, MacroCallLoc,
13+
MacroDefId, MacroFile, MacroFileKind,
1414
};
1515

16+
#[derive(Debug, Clone, Eq, PartialEq)]
17+
pub enum TokenExpander {
18+
MacroRules(mbe::MacroRules),
19+
Builtin(BuiltinExpander),
20+
}
21+
22+
impl TokenExpander {
23+
pub fn expand(
24+
&self,
25+
db: &dyn AstDatabase,
26+
id: MacroCallId,
27+
tt: &tt::Subtree,
28+
) -> Result<tt::Subtree, mbe::ExpandError> {
29+
match self {
30+
TokenExpander::MacroRules(it) => it.expand(tt),
31+
TokenExpander::Builtin(it) => it.expand(tt),
32+
}
33+
}
34+
35+
pub fn shift(&self) -> u32 {
36+
match self {
37+
TokenExpander::MacroRules(it) => it.shift(),
38+
TokenExpander::Builtin(_) => 0,
39+
}
40+
}
41+
}
42+
1643
// FIXME: rename to ExpandDatabase
1744
#[salsa::query_group(AstDatabaseStorage)]
1845
pub trait AstDatabase: SourceDatabase {
@@ -24,7 +51,7 @@ pub trait AstDatabase: SourceDatabase {
2451
#[salsa::interned]
2552
fn intern_macro(&self, macro_call: MacroCallLoc) -> MacroCallId;
2653
fn macro_arg(&self, id: MacroCallId) -> Option<Arc<(tt::Subtree, mbe::TokenMap)>>;
27-
fn macro_def(&self, id: MacroDefId) -> Option<Arc<(mbe::MacroRules, mbe::TokenMap)>>;
54+
fn macro_def(&self, id: MacroDefId) -> Option<Arc<(TokenExpander, mbe::TokenMap)>>;
2855
fn parse_macro(
2956
&self,
3057
macro_file: MacroFile,
@@ -41,18 +68,25 @@ pub(crate) fn ast_id_map(db: &dyn AstDatabase, file_id: HirFileId) -> Arc<AstIdM
4168
pub(crate) fn macro_def(
4269
db: &dyn AstDatabase,
4370
id: MacroDefId,
44-
) -> Option<Arc<(mbe::MacroRules, mbe::TokenMap)>> {
45-
let macro_call = id.ast_id.to_node(db);
46-
let arg = macro_call.token_tree()?;
47-
let (tt, tmap) = mbe::ast_to_token_tree(&arg).or_else(|| {
48-
log::warn!("fail on macro_def to token tree: {:#?}", arg);
49-
None
50-
})?;
51-
let rules = MacroRules::parse(&tt).ok().or_else(|| {
52-
log::warn!("fail on macro_def parse: {:#?}", tt);
53-
None
54-
})?;
55-
Some(Arc::new((rules, tmap)))
71+
) -> Option<Arc<(TokenExpander, mbe::TokenMap)>> {
72+
match id {
73+
MacroDefId::DeclarativeMacro(it) => {
74+
let macro_call = it.ast_id.to_node(db);
75+
let arg = macro_call.token_tree()?;
76+
let (tt, tmap) = mbe::ast_to_token_tree(&arg).or_else(|| {
77+
log::warn!("fail on macro_def to token tree: {:#?}", arg);
78+
None
79+
})?;
80+
let rules = MacroRules::parse(&tt).ok().or_else(|| {
81+
log::warn!("fail on macro_def parse: {:#?}", tt);
82+
None
83+
})?;
84+
Some(Arc::new((TokenExpander::MacroRules(rules), tmap)))
85+
}
86+
MacroDefId::BuiltinMacro(it) => {
87+
Some(Arc::new((TokenExpander::Builtin(it.expander.clone()), mbe::TokenMap::default())))
88+
}
89+
}
5690
}
5791

5892
pub(crate) fn macro_arg(
@@ -74,7 +108,7 @@ pub(crate) fn macro_expand(
74108
let macro_arg = db.macro_arg(id).ok_or("Fail to args in to tt::TokenTree")?;
75109

76110
let macro_rules = db.macro_def(loc.def).ok_or("Fail to find macro definition")?;
77-
let tt = macro_rules.0.expand(&macro_arg.0).map_err(|err| format!("{:?}", err))?;
111+
let tt = macro_rules.0.expand(db, id, &macro_arg.0).map_err(|err| format!("{:?}", err))?;
78112
// Set a hard limit for the expanded tt
79113
let count = tt.count();
80114
if count > 65536 {

crates/ra_hir_expand/src/hygiene.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::{
99
db::AstDatabase,
1010
either::Either,
1111
name::{AsName, Name},
12-
HirFileId, HirFileIdRepr,
12+
HirFileId, HirFileIdRepr, MacroDefId,
1313
};
1414

1515
#[derive(Debug)]
@@ -24,7 +24,10 @@ impl Hygiene {
2424
HirFileIdRepr::FileId(_) => None,
2525
HirFileIdRepr::MacroFile(macro_file) => {
2626
let loc = db.lookup_intern_macro(macro_file.macro_call_id);
27-
Some(loc.def.krate)
27+
match loc.def {
28+
MacroDefId::DeclarativeMacro(it) => Some(it.krate),
29+
MacroDefId::BuiltinMacro(_) => None,
30+
}
2831
}
2932
};
3033
Hygiene { def_crate }

crates/ra_hir_expand/src/lib.rs

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ pub mod either;
1010
pub mod name;
1111
pub mod hygiene;
1212
pub mod diagnostics;
13+
pub mod builtin_macro;
1314

1415
use std::hash::{Hash, Hasher};
1516
use std::sync::Arc;
@@ -21,6 +22,7 @@ use ra_syntax::{
2122
};
2223

2324
use crate::ast_id_map::FileAstId;
25+
use crate::builtin_macro::BuiltinExpander;
2426

2527
/// Input to the analyzer is a set of files, where each file is identified by
2628
/// `FileId` and contains source code. However, another source of source code in
@@ -75,17 +77,23 @@ impl HirFileId {
7577
HirFileIdRepr::MacroFile(macro_file) => {
7678
let loc: MacroCallLoc = db.lookup_intern_macro(macro_file.macro_call_id);
7779

80+
// FIXME: Do we support expansion information in builtin macro?
81+
let macro_decl = match loc.def {
82+
MacroDefId::DeclarativeMacro(it) => (it),
83+
MacroDefId::BuiltinMacro(_) => return None,
84+
};
85+
7886
let arg_start = loc.ast_id.to_node(db).token_tree()?.syntax().text_range().start();
7987
let def_start =
80-
loc.def.ast_id.to_node(db).token_tree()?.syntax().text_range().start();
88+
macro_decl.ast_id.to_node(db).token_tree()?.syntax().text_range().start();
8189

8290
let macro_def = db.macro_def(loc.def)?;
8391
let shift = macro_def.0.shift();
8492
let exp_map = db.parse_macro(macro_file)?.1;
8593
let macro_arg = db.macro_arg(macro_file.macro_call_id)?;
8694

8795
let arg_start = (loc.ast_id.file_id, arg_start);
88-
let def_start = (loc.def.ast_id.file_id, def_start);
96+
let def_start = (macro_decl.ast_id.file_id, def_start);
8997

9098
Some(ExpansionInfo { arg_start, def_start, macro_arg, macro_def, exp_map, shift })
9199
}
@@ -119,9 +127,22 @@ impl salsa::InternKey for MacroCallId {
119127
}
120128

121129
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
122-
pub struct MacroDefId {
130+
pub enum MacroDefId {
131+
DeclarativeMacro(DeclarativeMacro),
132+
BuiltinMacro(BuiltinMacro),
133+
}
134+
135+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
136+
pub struct DeclarativeMacro {
137+
pub krate: CrateId,
138+
pub ast_id: AstId<ast::MacroCall>,
139+
}
140+
141+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
142+
pub struct BuiltinMacro {
123143
pub krate: CrateId,
124144
pub ast_id: AstId<ast::MacroCall>,
145+
pub expander: BuiltinExpander,
125146
}
126147

127148
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -144,7 +165,7 @@ pub struct ExpansionInfo {
144165
pub(crate) def_start: (HirFileId, TextUnit),
145166
pub(crate) shift: u32,
146167

147-
pub(crate) macro_def: Arc<(mbe::MacroRules, mbe::TokenMap)>,
168+
pub(crate) macro_def: Arc<(db::TokenExpander, mbe::TokenMap)>,
148169
pub(crate) macro_arg: Arc<(tt::Subtree, mbe::TokenMap)>,
149170
pub(crate) exp_map: Arc<mbe::RevTokenMap>,
150171
}

crates/ra_hir_expand/src/name.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,3 +140,6 @@ pub const RESULT_TYPE: Name = Name::new_inline_ascii(6, b"Result");
140140
pub const OUTPUT_TYPE: Name = Name::new_inline_ascii(6, b"Output");
141141
pub const TARGET_TYPE: Name = Name::new_inline_ascii(6, b"Target");
142142
pub const BOX_TYPE: Name = Name::new_inline_ascii(3, b"Box");
143+
144+
// Builtin Macros
145+
pub const LINE_MACRO: Name = Name::new_inline_ascii(4, b"line");

0 commit comments

Comments
 (0)