Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
0701571f
R
Rust
项目概览
int
/
Rust
大约 1 年 前同步成功
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
Rust
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
0701571f
编写于
6月 26, 2016
作者:
J
Jeffrey Seyfried
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Implement `macro_rules!` placeholders and the macro scope map
上级
a15dfca5
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
127 addition
and
24 deletion
+127
-24
src/librustc_resolve/assign_ids.rs
src/librustc_resolve/assign_ids.rs
+46
-13
src/librustc_resolve/lib.rs
src/librustc_resolve/lib.rs
+35
-4
src/libsyntax/ext/expand.rs
src/libsyntax/ext/expand.rs
+27
-6
src/libsyntax/ext/mtwt.rs
src/libsyntax/ext/mtwt.rs
+15
-1
src/libsyntax/test.rs
src/libsyntax/test.rs
+4
-0
未找到文件。
src/librustc_resolve/assign_ids.rs
浏览文件 @
0701571f
...
...
@@ -11,20 +11,27 @@
use
Resolver
;
use
rustc
::
session
::
Session
;
use
syntax
::
ast
;
use
syntax
::
fold
::
Folder
;
use
syntax
::
ext
::
mtwt
;
use
syntax
::
fold
::{
self
,
Folder
};
use
syntax
::
ptr
::
P
;
use
syntax
::
util
::
move_map
::
MoveMap
;
use
syntax
::
util
::
small_vector
::
SmallVector
;
use
std
::
collections
::
HashMap
;
use
std
::
mem
;
impl
<
'a
>
Resolver
<
'a
>
{
pub
fn
assign_node_ids
(
&
mut
self
,
krate
:
ast
::
Crate
)
->
ast
::
Crate
{
NodeIdAssigner
{
sess
:
self
.session
,
macros_at_scope
:
&
mut
self
.macros_at_scope
,
}
.fold_crate
(
krate
)
}
}
struct
NodeIdAssigner
<
'a
>
{
sess
:
&
'a
Session
,
macros_at_scope
:
&
'a
mut
HashMap
<
ast
::
NodeId
,
Vec
<
ast
::
Mrk
>>
,
}
impl
<
'a
>
Folder
for
NodeIdAssigner
<
'a
>
{
...
...
@@ -38,22 +45,48 @@ fn fold_block(&mut self, block: P<ast::Block>) -> P<ast::Block> {
block
.id
=
self
.new_id
(
block
.id
);
let
stmt
=
block
.stmts
.pop
();
block
.stmts
=
block
.stmts
.move_flat_map
(|
s
|
self
.fold_stmt
(
s
)
.into_iter
());
if
let
Some
(
ast
::
Stmt
{
node
:
ast
::
StmtKind
::
Expr
(
expr
),
span
,
..
})
=
stmt
{
let
mut
macros
=
Vec
::
new
();
block
.stmts
=
block
.stmts
.move_flat_map
(|
stmt
|
{
if
let
ast
::
StmtKind
::
Item
(
ref
item
)
=
stmt
.node
{
if
let
ast
::
ItemKind
::
Mac
(
..
)
=
item
.node
{
macros
.push
(
mtwt
::
outer_mark
(
item
.ident.ctxt
));
return
None
;
}
}
let
stmt
=
self
.fold_stmt
(
stmt
)
.pop
()
.unwrap
();
if
!
macros
.is_empty
()
{
self
.macros_at_scope
.insert
(
stmt
.id
,
mem
::
replace
(
&
mut
macros
,
Vec
::
new
()));
}
Some
(
stmt
)
});
stmt
.and_then
(|
mut
stmt
|
{
// Avoid wasting a node id on a trailing expression statement,
// which shares a HIR node with the expression itself.
let
expr
=
self
.fold_expr
(
expr
);
block
.stmts
.push
(
ast
::
Stmt
{
id
:
expr
.id
,
node
:
ast
::
StmtKind
::
Expr
(
expr
),
span
:
span
,
});
}
else
if
let
Some
(
stmt
)
=
stmt
{
block
.stmts
.extend
(
self
.fold_stmt
(
stmt
));
}
if
let
ast
::
StmtKind
::
Expr
(
expr
)
=
stmt
.node
{
let
expr
=
self
.fold_expr
(
expr
);
stmt
.id
=
expr
.id
;
stmt
.node
=
ast
::
StmtKind
::
Expr
(
expr
);
Some
(
stmt
)
}
else
{
self
.fold_stmt
(
stmt
)
.pop
()
}
})
.map
(|
stmt
|
{
if
!
macros
.is_empty
()
{
self
.macros_at_scope
.insert
(
stmt
.id
,
mem
::
replace
(
&
mut
macros
,
Vec
::
new
()));
}
block
.stmts
.push
(
stmt
);
});
block
})
}
}
fn
fold_item
(
&
mut
self
,
item
:
P
<
ast
::
Item
>
)
->
SmallVector
<
P
<
ast
::
Item
>>
{
match
item
.node
{
ast
::
ItemKind
::
Mac
(
..
)
=>
SmallVector
::
zero
(),
_
=>
fold
::
noop_fold_item
(
item
,
self
),
}
}
}
src/librustc_resolve/lib.rs
浏览文件 @
0701571f
...
...
@@ -53,6 +53,7 @@
use
rustc
::
hir
::{
Freevar
,
FreevarMap
,
TraitCandidate
,
TraitMap
,
GlobMap
};
use
rustc
::
util
::
nodemap
::{
NodeMap
,
NodeSet
,
FnvHashMap
,
FnvHashSet
};
use
syntax
::
ext
::
mtwt
;
use
syntax
::
ast
::{
self
,
FloatTy
};
use
syntax
::
ast
::{
CRATE_NODE_ID
,
Name
,
NodeId
,
CrateNum
,
IntTy
,
UintTy
};
use
syntax
::
parse
::
token
::{
self
,
keywords
};
...
...
@@ -651,6 +652,9 @@ enum RibKind<'a> {
// We passed through a module.
ModuleRibKind
(
Module
<
'a
>
),
// We passed through a `macro_rules!` statement with the given expansion
MacroDefinition
(
ast
::
Mrk
),
}
#[derive(Copy,
Clone)]
...
...
@@ -927,6 +931,10 @@ pub struct Resolver<'a> {
pub
definitions
:
Definitions
,
// Maps the node id of a statement to the expansions of the `macro_rules!`s
// immediately above the statement (if appropriate).
macros_at_scope
:
HashMap
<
NodeId
,
Vec
<
ast
::
Mrk
>>
,
graph_root
:
Module
<
'a
>
,
prelude
:
Option
<
Module
<
'a
>>
,
...
...
@@ -1113,6 +1121,7 @@ pub fn new(session: &'a Session, make_glob_map: MakeGlobMap, arenas: &'a Resolve
session
:
session
,
definitions
:
Definitions
::
new
(),
macros_at_scope
:
HashMap
::
new
(),
// The outermost module has def ID 0; this is not reflected in the
// AST.
...
...
@@ -1421,6 +1430,16 @@ fn resolve_ident_in_lexical_scope(&mut self,
};
}
}
if
let
MacroDefinition
(
mac
)
=
self
.get_ribs
(
ns
)[
i
]
.kind
{
// If an invocation of this macro created `ident`, give up on `ident`
// and switch to `ident`'s source from the macro definition.
if
let
Some
((
source_ident
,
source_macro
))
=
mtwt
::
source
(
ident
)
{
if
mac
==
source_macro
{
ident
=
source_ident
;
}
}
}
}
None
...
...
@@ -2069,6 +2088,7 @@ fn resolve_block(&mut self, block: &Block) {
let
orig_module
=
self
.current_module
;
let
anonymous_module
=
self
.module_map
.get
(
&
block
.id
)
.cloned
();
// clones a reference
let
mut
num_value_ribs
=
1
;
if
let
Some
(
anonymous_module
)
=
anonymous_module
{
debug!
(
"(resolving block) found anonymous module, moving down"
);
self
.value_ribs
.push
(
Rib
::
new
(
ModuleRibKind
(
anonymous_module
)));
...
...
@@ -2079,11 +2099,22 @@ fn resolve_block(&mut self, block: &Block) {
}
// Descend into the block.
visit
::
walk_block
(
self
,
block
);
for
stmt
in
&
block
.stmts
{
if
let
Some
(
marks
)
=
self
.macros_at_scope
.remove
(
&
stmt
.id
)
{
num_value_ribs
+=
marks
.len
()
as
u32
;
for
mark
in
marks
{
self
.value_ribs
.push
(
Rib
::
new
(
MacroDefinition
(
mark
)));
}
}
self
.visit_stmt
(
stmt
);
}
// Move back up.
self
.current_module
=
orig_module
;
self
.value_ribs
.pop
();
for
_
in
0
..
num_value_ribs
{
self
.value_ribs
.pop
();
}
if
let
Some
(
_
)
=
anonymous_module
{
self
.type_ribs
.pop
();
}
...
...
@@ -2497,7 +2528,7 @@ fn adjust_local_def(&mut self, local_def: LocalDef, span: Span) -> Option<Def> {
Def
::
Local
(
_
,
node_id
)
=>
{
for
rib
in
ribs
{
match
rib
.kind
{
NormalRibKind
|
ModuleRibKind
(
..
)
=>
{
NormalRibKind
|
ModuleRibKind
(
..
)
|
MacroDefinition
(
..
)
=>
{
// Nothing to do. Continue.
}
ClosureRibKind
(
function_id
)
=>
{
...
...
@@ -2546,7 +2577,7 @@ fn adjust_local_def(&mut self, local_def: LocalDef, span: Span) -> Option<Def> {
for
rib
in
ribs
{
match
rib
.kind
{
NormalRibKind
|
MethodRibKind
(
_
)
|
ClosureRibKind
(
..
)
|
ModuleRibKind
(
..
)
=>
{
ModuleRibKind
(
..
)
|
MacroDefinition
(
..
)
=>
{
// Nothing to do. Continue.
}
ItemRibKind
=>
{
...
...
src/libsyntax/ext/expand.rs
浏览文件 @
0701571f
...
...
@@ -15,7 +15,7 @@
use
ext
::
mtwt
;
use
attr
;
use
attr
::
AttrMetaMethods
;
use
codemap
::{
Spanned
,
ExpnInfo
,
NameAndSpan
,
MacroBang
,
MacroAttribute
};
use
codemap
::{
dummy_spanned
,
Spanned
,
ExpnInfo
,
NameAndSpan
,
MacroBang
,
MacroAttribute
};
use
syntax_pos
::{
self
,
Span
,
ExpnId
};
use
config
::
StripUnconfigured
;
use
ext
::
base
::
*
;
...
...
@@ -105,6 +105,23 @@ pub fn expand_expr(expr: ast::Expr, fld: &mut MacroExpander) -> P<ast::Expr> {
}
}
struct
MacroScopePlaceholder
;
impl
MacResult
for
MacroScopePlaceholder
{
fn
make_items
(
self
:
Box
<
Self
>
)
->
Option
<
SmallVector
<
P
<
ast
::
Item
>>>
{
Some
(
SmallVector
::
one
(
P
(
ast
::
Item
{
ident
:
keywords
::
Invalid
.ident
(),
attrs
:
Vec
::
new
(),
id
:
ast
::
DUMMY_NODE_ID
,
node
:
ast
::
ItemKind
::
Mac
(
dummy_spanned
(
ast
::
Mac_
{
path
:
ast
::
Path
{
span
:
syntax_pos
::
DUMMY_SP
,
global
:
false
,
segments
:
Vec
::
new
()
},
tts
:
Vec
::
new
(),
})),
vis
:
ast
::
Visibility
::
Inherited
,
span
:
syntax_pos
::
DUMMY_SP
,
})))
}
}
/// Expand a macro invocation. Returns the result of expansion.
fn
expand_mac_invoc
<
T
>
(
mac
:
ast
::
Mac
,
ident
:
Option
<
Ident
>
,
attrs
:
Vec
<
ast
::
Attribute
>
,
span
:
Span
,
fld
:
&
mut
MacroExpander
)
->
T
...
...
@@ -143,6 +160,7 @@ fn mac_result<'a>(path: &ast::Path, ident: Option<Ident>, tts: Vec<TokenTree>, m
};
let
ident
=
ident
.unwrap_or
(
keywords
::
Invalid
.ident
());
let
marked_tts
=
mark_tts
(
&
tts
,
mark
);
match
*
extension
{
NormalTT
(
ref
expandfun
,
exp_span
,
allow_internal_unstable
)
=>
{
if
ident
.name
!=
keywords
::
Invalid
.name
()
{
...
...
@@ -161,7 +179,6 @@ fn mac_result<'a>(path: &ast::Path, ident: Option<Ident>, tts: Vec<TokenTree>, m
},
});
let
marked_tts
=
mark_tts
(
&
tts
,
mark
);
Some
(
expandfun
.expand
(
fld
.cx
,
call_site
,
&
marked_tts
))
}
...
...
@@ -181,7 +198,6 @@ fn mac_result<'a>(path: &ast::Path, ident: Option<Ident>, tts: Vec<TokenTree>, m
}
});
let
marked_tts
=
mark_tts
(
&
tts
,
mark
);
Some
(
expander
.expand
(
fld
.cx
,
call_site
,
ident
,
marked_tts
))
}
...
...
@@ -210,15 +226,14 @@ fn mac_result<'a>(path: &ast::Path, ident: Option<Ident>, tts: Vec<TokenTree>, m
span
:
call_site
,
imported_from
:
None
,
use_locally
:
true
,
body
:
tts
,
body
:
marked_
tts
,
export
:
attr
::
contains_name
(
&
attrs
,
"macro_export"
),
allow_internal_unstable
:
attr
::
contains_name
(
&
attrs
,
"allow_internal_unstable"
),
attrs
:
attrs
,
});
// macro_rules! has a side effect but expands to nothing.
fld
.cx
.bt_pop
();
None
Some
(
Box
::
new
(
MacroScopePlaceholder
))
}
MultiDecorator
(
..
)
|
MultiModifier
(
..
)
=>
{
...
...
@@ -343,6 +358,12 @@ fn expand_multi_modified(a: Annotatable, fld: &mut MacroExpander) -> SmallVector
match
a
{
Annotatable
::
Item
(
it
)
=>
match
it
.node
{
ast
::
ItemKind
::
Mac
(
..
)
=>
{
if
match
it
.node
{
ItemKind
::
Mac
(
ref
mac
)
=>
mac
.node.path.segments
.is_empty
(),
_
=>
unreachable!
(),
}
{
return
SmallVector
::
one
(
Annotatable
::
Item
(
it
));
}
it
.and_then
(|
it
|
match
it
.node
{
ItemKind
::
Mac
(
mac
)
=>
expand_mac_invoc
(
mac
,
Some
(
it
.ident
),
it
.attrs
,
it
.span
,
fld
),
...
...
src/libsyntax/ext/mtwt.rs
浏览文件 @
0701571f
...
...
@@ -17,7 +17,7 @@
pub
use
self
::
SyntaxContext_
::
*
;
use
ast
::{
Mrk
,
SyntaxContext
};
use
ast
::{
Ident
,
Mrk
,
SyntaxContext
};
use
std
::
cell
::
RefCell
;
use
std
::
collections
::
HashMap
;
...
...
@@ -112,6 +112,20 @@ pub fn outer_mark(ctxt: SyntaxContext) -> Mrk {
})
}
/// If `ident` is macro expanded, return the source ident from the macro definition
/// and the mark of the expansion that created the macro definition.
pub
fn
source
(
ident
:
Ident
)
->
Option
<
(
Ident
/* source ident */
,
Mrk
/* source macro */
)
>
{
with_sctable
(|
sctable
|
{
let
ctxts
=
sctable
.table
.borrow
();
if
let
Mark
(
_
expansion_mark
,
macro_ctxt
)
=
ctxts
[
ident
.ctxt
.0
as
usize
]
{
if
let
Mark
(
definition_mark
,
orig_ctxt
)
=
ctxts
[
macro_ctxt
.0
as
usize
]
{
return
Some
((
Ident
::
new
(
ident
.name
,
orig_ctxt
),
definition_mark
));
}
}
None
})
}
#[cfg(test)]
mod
tests
{
use
ast
::{
EMPTY_CTXT
,
Ident
,
Mrk
,
Name
,
SyntaxContext
};
...
...
src/libsyntax/test.rs
浏览文件 @
0701571f
...
...
@@ -185,6 +185,8 @@ fn fold_mod(&mut self, m: ast::Mod) -> ast::Mod {
mod_folded
}
fn
fold_mac
(
&
mut
self
,
mac
:
ast
::
Mac
)
->
ast
::
Mac
{
mac
}
}
struct
EntryPointCleaner
{
...
...
@@ -234,6 +236,8 @@ fn fold_item(&mut self, i: P<ast::Item>) -> SmallVector<P<ast::Item>> {
SmallVector
::
one
(
folded
)
}
fn
fold_mac
(
&
mut
self
,
mac
:
ast
::
Mac
)
->
ast
::
Mac
{
mac
}
}
fn
mk_reexport_mod
(
cx
:
&
mut
TestCtxt
,
tests
:
Vec
<
ast
::
Ident
>
,
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录