Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
79fa9eb6
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,发现更多精彩内容 >>
提交
79fa9eb6
编写于
9月 01, 2016
作者:
J
Jeffrey Seyfried
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Refactor `SyntaxEnv`.
上级
4ed2c0ea
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
119 addition
and
126 deletion
+119
-126
src/libsyntax/ext/base.rs
src/libsyntax/ext/base.rs
+94
-75
src/libsyntax/ext/expand.rs
src/libsyntax/ext/expand.rs
+20
-44
src/libsyntax/ext/source_util.rs
src/libsyntax/ext/source_util.rs
+3
-5
src/libsyntax/ext/tt/macro_rules.rs
src/libsyntax/ext/tt/macro_rules.rs
+2
-2
未找到文件。
src/libsyntax/ext/base.rs
浏览文件 @
79fa9eb6
...
...
@@ -24,6 +24,7 @@
use
parse
::
token
;
use
parse
::
token
::{
InternedString
,
intern
,
str_to_ident
};
use
ptr
::
P
;
use
std_inject
;
use
util
::
small_vector
::
SmallVector
;
use
util
::
lev_distance
::
find_best_match_for_name
;
use
fold
::
Folder
;
...
...
@@ -463,19 +464,6 @@ pub enum SyntaxExtension {
pub
type
NamedSyntaxExtension
=
(
Name
,
SyntaxExtension
);
pub
struct
BlockInfo
{
/// Should macros escape from this scope?
pub
macros_escape
:
bool
,
}
impl
BlockInfo
{
pub
fn
new
()
->
BlockInfo
{
BlockInfo
{
macros_escape
:
false
,
}
}
}
/// The base map of methods for expanding syntax extension
/// AST nodes into full ASTs
fn
initial_syntax_expander_table
<
'feat
>
(
ecfg
:
&
expand
::
ExpansionConfig
<
'feat
>
)
...
...
@@ -586,15 +574,11 @@ pub struct ExtCtxt<'a> {
pub
crate_root
:
Option
<&
'static
str
>
,
pub
loader
:
&
'a
mut
MacroLoader
,
pub
mod_path
:
Vec
<
ast
::
Ident
>
,
pub
exported_macros
:
Vec
<
ast
::
MacroDef
>
,
pub
syntax_env
:
SyntaxEnv
,
pub
derive_modes
:
HashMap
<
InternedString
,
Box
<
MultiItemModifier
>>
,
pub
recursion_count
:
usize
,
pub
directory
:
PathBuf
,
pub
in_block
:
bool
,
}
impl
<
'a
>
ExtCtxt
<
'a
>
{
...
...
@@ -602,22 +586,17 @@ pub fn new(parse_sess: &'a parse::ParseSess, cfg: ast::CrateConfig,
ecfg
:
expand
::
ExpansionConfig
<
'a
>
,
loader
:
&
'a
mut
MacroLoader
)
->
ExtCtxt
<
'a
>
{
let
env
=
initial_syntax_expander_table
(
&
ecfg
);
ExtCtxt
{
syntax_env
:
initial_syntax_expander_table
(
&
ecfg
),
parse_sess
:
parse_sess
,
cfg
:
cfg
,
backtrace
:
NO_EXPANSION
,
mod_path
:
Vec
::
new
(),
ecfg
:
ecfg
,
crate_root
:
None
,
exported_macros
:
Vec
::
new
(),
loader
:
loader
,
syntax_env
:
env
,
derive_modes
:
HashMap
::
new
(),
recursion_count
:
0
,
directory
:
PathBuf
::
new
(),
in_block
:
false
,
}
}
...
...
@@ -666,14 +645,6 @@ pub fn expansion_cause(&self) -> Span {
last_macro
.expect
(
"missing expansion backtrace"
)
}
pub
fn
mod_push
(
&
mut
self
,
i
:
ast
::
Ident
)
{
self
.mod_path
.push
(
i
);
}
pub
fn
mod_pop
(
&
mut
self
)
{
self
.mod_path
.pop
()
.unwrap
();
}
pub
fn
mod_path
(
&
self
)
->
Vec
<
ast
::
Ident
>
{
let
mut
v
=
Vec
::
new
();
v
.push
(
token
::
str_to_ident
(
&
self
.ecfg.crate_name
));
v
.extend
(
self
.mod_path
.iter
()
.cloned
());
return
v
;
}
pub
fn
bt_push
(
&
mut
self
,
ei
:
ExpnInfo
)
{
self
.recursion_count
+=
1
;
if
self
.recursion_count
>
self
.ecfg.recursion_limit
{
...
...
@@ -818,6 +789,30 @@ pub fn suggest_macro_name(&mut self,
}
}
}
pub
fn
initialize
(
&
mut
self
,
user_exts
:
Vec
<
NamedSyntaxExtension
>
,
krate
:
&
ast
::
Crate
)
{
if
std_inject
::
no_core
(
&
krate
)
{
self
.crate_root
=
None
;
}
else
if
std_inject
::
no_std
(
&
krate
)
{
self
.crate_root
=
Some
(
"core"
);
}
else
{
self
.crate_root
=
Some
(
"std"
);
}
// User extensions must be added before expander.load_macros is called,
// so that macros from external crates shadow user defined extensions.
for
(
name
,
extension
)
in
user_exts
{
self
.syntax_env
.insert
(
name
,
extension
);
}
self
.syntax_env.current_module
=
Module
(
0
);
let
mut
paths
=
ModulePaths
{
mod_path
:
vec!
[
token
::
str_to_ident
(
&
self
.ecfg.crate_name
)],
directory
:
PathBuf
::
from
(
self
.parse_sess
.codemap
()
.span_to_filename
(
krate
.span
)),
};
paths
.directory
.pop
();
self
.syntax_env.module_data
[
0
]
.paths
=
Rc
::
new
(
paths
);
}
}
/// Extract a string literal from the macro expanded version of `expr`,
...
...
@@ -904,79 +899,103 @@ pub fn get_exprs_from_tts(cx: &mut ExtCtxt,
///
/// This environment maps Names to SyntaxExtensions.
pub
struct
SyntaxEnv
{
chain
:
Vec
<
MapChainFrame
>
,
module_data
:
Vec
<
ModuleData
>
,
current_module
:
Module
,
/// All bang-style macro/extension names
/// encountered so far; to be used for diagnostics in resolve
pub
names
:
HashSet
<
Name
>
,
}
// impl question: how to implement it? Initially, the
// env will contain only macros, so it might be painful
// to add an empty frame for every context. Let's just
// get it working, first....
#[derive(Copy,
Clone,
PartialEq,
Eq)]
pub
struct
Module
(
u32
);
// NB! the mutability of the underlying maps means that
// if expansion is out-of-order, a deeper scope may be
// able to refer to a macro that was added to an enclosing
// scope lexically later than the deeper scope.
struct
ModuleData
{
parent
:
Module
,
paths
:
Rc
<
ModulePaths
>
,
macros
:
HashMap
<
Name
,
Rc
<
SyntaxExtension
>>
,
macros_escape
:
bool
,
in_block
:
bool
,
}
struct
MapChainFrame
{
info
:
BlockInfo
,
map
:
HashMap
<
Name
,
Rc
<
SyntaxExtension
>>
,
#[derive(Clone)]
pub
struct
ModulePaths
{
pub
mod_path
:
Vec
<
ast
::
Ident
>
,
pub
directory
:
PathBuf
,
}
impl
SyntaxEnv
{
fn
new
()
->
SyntaxEnv
{
let
mut
map
=
SyntaxEnv
{
chain
:
Vec
::
new
()
,
names
:
HashSet
::
new
()};
map
.push_frame
();
map
let
mut
env
=
SyntaxEnv
{
current_module
:
Module
(
0
),
module_data
:
Vec
::
new
(),
names
:
HashSet
::
new
(),
};
let
paths
=
Rc
::
new
(
ModulePaths
{
mod_path
:
Vec
::
new
(),
directory
:
PathBuf
::
new
()
});
env
.add_module
(
false
,
false
,
paths
);
env
}
pub
fn
push_frame
(
&
mut
self
)
{
self
.chain
.push
(
MapChainFrame
{
info
:
BlockInfo
::
new
(),
map
:
HashMap
::
new
(),
});
fn
data
(
&
self
,
module
:
Module
)
->
&
ModuleData
{
&
self
.module_data
[
module
.0
as
usize
]
}
pub
fn
pop_frame
(
&
mut
self
)
{
assert
!
(
self
.chain
.len
()
>
1
,
"too many pops on MapChain!"
);
self
.chain
.pop
();
pub
fn
set_current_module
(
&
mut
self
,
module
:
Module
)
->
Module
{
::
std
::
mem
::
replace
(
&
mut
self
.current_module
,
module
)
}
fn
find_escape_frame
(
&
mut
self
)
->
&
mut
MapChainFrame
{
for
(
i
,
frame
)
in
self
.chain
.iter_mut
()
.enumerate
()
.rev
()
{
if
!
frame
.info.macros_escape
||
i
==
0
{
return
frame
}
}
unreachable!
()
pub
fn
paths
(
&
self
)
->
Rc
<
ModulePaths
>
{
self
.data
(
self
.current_module
)
.paths
.clone
()
}
pub
fn
in_block
(
&
self
)
->
bool
{
self
.data
(
self
.current_module
)
.in_block
}
pub
fn
find
(
&
self
,
k
:
Name
)
->
Option
<
Rc
<
SyntaxExtension
>>
{
for
frame
in
self
.chain
.iter
()
.rev
()
{
if
let
Some
(
v
)
=
frame
.map
.get
(
&
k
)
{
return
Some
(
v
.clone
());
pub
fn
add_module
(
&
mut
self
,
macros_escape
:
bool
,
in_block
:
bool
,
paths
:
Rc
<
ModulePaths
>
)
->
Module
{
let
data
=
ModuleData
{
parent
:
self
.current_module
,
paths
:
paths
,
macros
:
HashMap
::
new
(),
macros_escape
:
macros_escape
,
in_block
:
in_block
,
};
self
.module_data
.push
(
data
);
Module
(
self
.module_data
.len
()
as
u32
-
1
)
}
pub
fn
find
(
&
self
,
name
:
Name
)
->
Option
<
Rc
<
SyntaxExtension
>>
{
let
mut
module
=
self
.current_module
;
let
mut
module_data
;
loop
{
module_data
=
self
.data
(
module
);
if
let
Some
(
ext
)
=
module_data
.macros
.get
(
&
name
)
{
return
Some
(
ext
.clone
());
}
if
module
==
module_data
.parent
{
return
None
;
}
module
=
module_data
.parent
;
}
None
}
pub
fn
insert
(
&
mut
self
,
k
:
Name
,
v
:
SyntaxExtension
)
{
if
let
NormalTT
(
..
)
=
v
{
self
.names
.insert
(
k
);
pub
fn
insert
(
&
mut
self
,
name
:
Name
,
ext
:
SyntaxExtension
)
{
if
let
NormalTT
(
..
)
=
ext
{
self
.names
.insert
(
name
);
}
self
.find_escape_frame
()
.map
.insert
(
k
,
Rc
::
new
(
v
));
}
pub
fn
info
(
&
mut
self
)
->
&
mut
BlockInfo
{
let
last_chain_index
=
self
.chain
.len
()
-
1
;
&
mut
self
.chain
[
last_chain_index
]
.info
let
mut
module
=
self
.current_module
;
while
self
.data
(
module
)
.macros_escape
{
module
=
self
.data
(
module
)
.parent
;
}
self
.module_data
[
module
.0
as
usize
]
.macros
.insert
(
name
,
Rc
::
new
(
ext
));
}
pub
fn
is_crate_root
(
&
mut
self
)
->
bool
{
// The first frame is pushed in `SyntaxEnv::new()` and the second frame is
// pushed when folding the crate root pseudo-module (c.f. noop_fold_crate).
self
.c
hain
.len
()
<=
2
self
.c
urrent_module
.0
<=
1
}
}
src/libsyntax/ext/expand.rs
浏览文件 @
79fa9eb6
...
...
@@ -26,9 +26,9 @@
use
util
::
small_vector
::
SmallVector
;
use
visit
;
use
visit
::
Visitor
;
use
std_inject
;
use
std
::
path
::
PathBuf
;
use
std
::
rc
::
Rc
;
macro_rules!
expansions
{
(
$
(
$kind:ident
:
$ty:ty
,
$kind_name:expr
,
.
$make:ident
,
...
...
@@ -467,24 +467,9 @@ fn contains_macro_use(&mut self, attrs: &[ast::Attribute]) -> bool {
}
false
}
fn
with_exts_frame
<
T
,
F
:
FnOnce
(
&
mut
Self
)
->
T
>
(
&
mut
self
,
macros_escape
:
bool
,
f
:
F
)
->
T
{
self
.cx.syntax_env
.push_frame
();
self
.cx.syntax_env
.info
()
.macros_escape
=
macros_escape
;
let
result
=
f
(
self
);
self
.cx.syntax_env
.pop_frame
();
result
}
}
impl
<
'a
,
'b
>
Folder
for
MacroExpander
<
'a
,
'b
>
{
fn
fold_crate
(
&
mut
self
,
c
:
Crate
)
->
Crate
{
let
mut
directory
=
PathBuf
::
from
(
self
.cx.parse_sess
.codemap
()
.span_to_filename
(
c
.span
));
directory
.pop
();
self
.cx.directory
=
directory
;
noop_fold_crate
(
c
,
self
)
}
fn
fold_expr
(
&
mut
self
,
expr
:
P
<
ast
::
Expr
>
)
->
P
<
ast
::
Expr
>
{
let
expr
=
expr
.unwrap
();
if
let
ast
::
ExprKind
::
Mac
(
mac
)
=
expr
.node
{
...
...
@@ -542,9 +527,12 @@ fn fold_stmt(&mut self, stmt: ast::Stmt) -> SmallVector<ast::Stmt> {
}
fn
fold_block
(
&
mut
self
,
block
:
P
<
Block
>
)
->
P
<
Block
>
{
let
was_in_block
=
::
std
::
mem
::
replace
(
&
mut
self
.cx.in_block
,
true
);
let
result
=
self
.with_exts_frame
(
false
,
|
this
|
noop_fold_block
(
block
,
this
));
self
.cx.in_block
=
was_in_block
;
let
paths
=
self
.cx.syntax_env
.paths
();
let
module
=
self
.cx.syntax_env
.add_module
(
false
,
true
,
paths
);
let
orig_module
=
self
.cx.syntax_env
.set_current_module
(
module
);
let
result
=
noop_fold_block
(
block
,
self
);
self
.cx.syntax_env
.set_current_module
(
orig_module
);
result
}
...
...
@@ -578,26 +566,27 @@ fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
})
}
ast
::
ItemKind
::
Mod
(
ast
::
Mod
{
inner
,
..
})
=>
{
self
.cx
.mod_push
(
item
.ident
);
let
macro_use
=
self
.contains_macro_use
(
&
item
.attrs
);
let
directory
=
self
.cx.directory
.clone
();
let
mut
paths
=
(
*
self
.cx.syntax_env
.paths
())
.clone
();
paths
.mod_path
.push
(
item
.ident
);
if
item
.span
.contains
(
inner
)
{
self
.cx
.directory
.push
(
&*
{
paths
.directory
.push
(
&*
{
::
attr
::
first_attr_value_str_by_name
(
&
item
.attrs
,
"path"
)
.unwrap_or
(
item
.ident.name
.as_str
())
});
}
else
{
self
.cx
.directory
=
match
inner
{
paths
.directory
=
match
inner
{
syntax_pos
::
DUMMY_SP
=>
PathBuf
::
new
(),
_
=>
PathBuf
::
from
(
self
.cx.parse_sess
.codemap
()
.span_to_filename
(
inner
)),
};
self
.cx
.directory
.pop
();
paths
.directory
.pop
();
}
let
result
=
self
.with_exts_frame
(
macro_use
,
|
this
|
noop_fold_item
(
item
,
this
));
self
.cx.directory
=
directory
;
self
.cx
.mod_pop
();
let
macro_use
=
self
.contains_macro_use
(
&
item
.attrs
);
let
in_block
=
self
.cx.syntax_env
.in_block
();
let
module
=
self
.cx.syntax_env
.add_module
(
macro_use
,
in_block
,
Rc
::
new
(
paths
));
let
module
=
self
.cx.syntax_env
.set_current_module
(
module
);
let
result
=
noop_fold_item
(
item
,
self
);
self
.cx.syntax_env
.set_current_module
(
module
);
result
},
_
=>
noop_fold_item
(
item
,
self
),
...
...
@@ -744,19 +733,7 @@ pub fn expand_crate(cx: &mut ExtCtxt,
pub
fn
expand_crate_with_expander
(
expander
:
&
mut
MacroExpander
,
user_exts
:
Vec
<
NamedSyntaxExtension
>
,
mut
c
:
Crate
)
->
Crate
{
if
std_inject
::
no_core
(
&
c
)
{
expander
.cx.crate_root
=
None
;
}
else
if
std_inject
::
no_std
(
&
c
)
{
expander
.cx.crate_root
=
Some
(
"core"
);
}
else
{
expander
.cx.crate_root
=
Some
(
"std"
);
}
// User extensions must be added before expander.load_macros is called,
// so that macros from external crates shadow user defined extensions.
for
(
name
,
extension
)
in
user_exts
{
expander
.cx.syntax_env
.insert
(
name
,
extension
);
}
expander
.cx
.initialize
(
user_exts
,
&
c
);
let
items
=
Expansion
::
Items
(
SmallVector
::
many
(
c
.module.items
));
let
configured
=
items
.fold_with
(
&
mut
expander
.strip_unconfigured
());
...
...
@@ -765,12 +742,11 @@ pub fn expand_crate_with_expander(expander: &mut MacroExpander,
let
err_count
=
expander
.cx.parse_sess.span_diagnostic
.err_count
();
let
mut
ret
=
expander
.fold_crate
(
c
);
ret
.exported_macros
=
expander
.cx.exported_macros
.clone
();
if
expander
.cx.parse_sess.span_diagnostic
.err_count
()
>
err_count
{
expander
.cx.parse_sess.span_diagnostic
.abort_if_errors
();
}
ret
.exported_macros
=
expander
.cx.exported_macros
.clone
();
ret
}
...
...
src/libsyntax/ext/source_util.rs
浏览文件 @
79fa9eb6
...
...
@@ -74,11 +74,9 @@ pub fn expand_stringify(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTre
pub
fn
expand_mod
(
cx
:
&
mut
ExtCtxt
,
sp
:
Span
,
tts
:
&
[
tokenstream
::
TokenTree
])
->
Box
<
base
::
MacResult
+
'static
>
{
base
::
check_zero_tts
(
cx
,
sp
,
tts
,
"module_path!"
);
let
string
=
cx
.mod_path
()
.iter
()
.map
(|
x
|
x
.to_string
())
.collect
::
<
Vec
<
String
>>
()
.join
(
"::"
);
let
paths
=
cx
.syntax_env
.paths
();
let
string
=
paths
.mod_path
.iter
()
.map
(|
x
|
x
.to_string
())
.collect
::
<
Vec
<
String
>>
()
.join
(
"::"
);
base
::
MacEager
::
expr
(
cx
.expr_str
(
sp
,
token
::
intern_and_get_ident
(
&
string
[
..
])))
...
...
src/libsyntax/ext/tt/macro_rules.rs
浏览文件 @
79fa9eb6
...
...
@@ -211,8 +211,8 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt,
imported_from
,
rhs
);
let
mut
p
=
Parser
::
new
(
cx
.parse_sess
(),
cx
.cfg
(),
Box
::
new
(
trncbr
));
p
.directory
=
cx
.directory
.clone
();
p
.restrictions
=
match
cx
.
in_block
{
p
.directory
=
cx
.
syntax_env
.paths
()
.
directory
.clone
();
p
.restrictions
=
match
cx
.
syntax_env
.in_block
()
{
true
=>
Restrictions
::
NO_NONINLINE_MOD
,
false
=>
Restrictions
::
empty
(),
};
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录