Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
7714cb29
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,发现更多精彩内容 >>
提交
7714cb29
编写于
7月 05, 2011
作者:
P
Patrick Walton
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
rustc: Make AST paths use interior vectors
上级
368f1f4b
变更
12
隐藏空白更改
内联
并排
Showing
12 changed file
with
71 addition
and
43 deletion
+71
-43
src/comp/metadata/tydecode.rs
src/comp/metadata/tydecode.rs
+4
-4
src/comp/middle/resolve.rs
src/comp/middle/resolve.rs
+3
-2
src/comp/middle/tstate/auxiliary.rs
src/comp/middle/tstate/auxiliary.rs
+1
-1
src/comp/middle/tstate/bitvectors.rs
src/comp/middle/tstate/bitvectors.rs
+1
-1
src/comp/middle/typeck.rs
src/comp/middle/typeck.rs
+5
-6
src/comp/syntax/ast.rs
src/comp/syntax/ast.rs
+7
-5
src/comp/syntax/ext/base.rs
src/comp/syntax/ext/base.rs
+3
-2
src/comp/syntax/ext/fmt.rs
src/comp/syntax/ext/fmt.rs
+5
-6
src/comp/syntax/ext/simplext.rs
src/comp/syntax/ext/simplext.rs
+4
-2
src/comp/syntax/fold.rs
src/comp/syntax/fold.rs
+3
-2
src/comp/syntax/parse/parser.rs
src/comp/syntax/parse/parser.rs
+18
-7
src/comp/syntax/print/pprust.rs
src/comp/syntax/print/pprust.rs
+17
-5
未找到文件。
src/comp/metadata/tydecode.rs
浏览文件 @
7714cb29
...
...
@@ -80,21 +80,21 @@ fn parse_constrs(@pstate st, str_def sd) -> (@ty::constr_def)[] {
}
fn
parse_path
(
@
pstate
st
,
str_def
sd
)
->
ast
::
path
{
let
vec
[
ast
::
ident
]
idents
=
[];
let
ast
::
ident
[]
idents
=
~
[];
fn
is_last
(
char
c
)
->
bool
{
ret
(
c
==
'('
||
c
==
':'
);
}
idents
+=
[
parse_ident_
(
st
,
sd
,
is_last
)];
idents
+=
~
[
parse_ident_
(
st
,
sd
,
is_last
)];
while
(
true
)
{
alt
(
peek
(
st
)
as
char
)
{
case
(
':'
)
{
next
(
st
);
next
(
st
);
}
case
(
?
c
)
{
if
(
c
==
'('
)
{
ret
respan
(
rec
(
lo
=
0u
,
hi
=
0u
),
rec
(
idents
=
idents
,
types
=
[]));
rec
(
idents
=
idents
,
types
=
~
[]));
}
else
{
idents
+=
[
parse_ident_
(
st
,
sd
,
is_last
)];
idents
+=
~
[
parse_ident_
(
st
,
sd
,
is_last
)];
}
}
}
...
...
src/comp/middle/resolve.rs
浏览文件 @
7714cb29
...
...
@@ -18,6 +18,7 @@
import
middle
::
ty
::
constr_table
;
import
syntax
::
visit
;
import
visit
::
vt
;
import
std
::
ivec
;
import
std
::
map
::
hashmap
;
import
std
::
list
;
import
std
::
list
::
list
;
...
...
@@ -554,9 +555,9 @@ fn mk_unresolved_msg(&ident id, &str kind) -> str {
}
// Lookup helpers
fn
lookup_path_strict
(
&
env
e
,
&
scopes
sc
,
&
span
sp
,
vec
[
ident
]
idents
,
fn
lookup_path_strict
(
&
env
e
,
&
scopes
sc
,
&
span
sp
,
&
ident
[
]
idents
,
namespace
ns
)
->
option
::
t
[
def
]
{
auto
n_idents
=
vec
::
len
(
idents
);
auto
n_idents
=
i
vec
::
len
(
idents
);
auto
headns
=
if
(
n_idents
==
1u
)
{
ns
}
else
{
ns_module
};
auto
dcur
=
lookup_in_scope_strict
(
e
,
sc
,
sp
,
idents
.
(
0
),
headns
);
auto
i
=
1u
;
...
...
src/comp/middle/tstate/auxiliary.rs
浏览文件 @
7714cb29
...
...
@@ -641,7 +641,7 @@ fn substitute_arg(&ty::ctxt cx, &(@expr)[] actuals, @constr_arg a) ->
}
fn
path_to_ident
(
&
ty
::
ctxt
cx
,
&
path
p
)
->
ident
{
alt
(
std
::
vec
::
last
(
p
.node.idents
))
{
alt
(
i
vec
::
last
(
p
.node.idents
))
{
case
(
none
)
{
cx
.sess
.span_fatal
(
p
.span
,
"Malformed path"
);
}
case
(
some
(
?
i
))
{
ret
i
;
}
}
...
...
src/comp/middle/tstate/bitvectors.rs
浏览文件 @
7714cb29
...
...
@@ -230,7 +230,7 @@ fn kill_poststate(&fn_ctxt fcx, node_id id, &constr_ c) -> bool {
fn
clear_in_poststate_expr
(
&
fn_ctxt
fcx
,
&@
expr
e
,
&
poststate
t
)
{
alt
(
e
.node
)
{
case
(
expr_path
(
?
p
))
{
alt
(
std
::
vec
::
last
(
p
.node.idents
))
{
alt
(
i
vec
::
last
(
p
.node.idents
))
{
case
(
some
(
?
i
))
{
alt
(
local_node_id_to_def
(
fcx
,
e
.id
))
{
case
(
some
(
def_local
(
?
d_id
)))
{
...
...
src/comp/middle/typeck.rs
浏览文件 @
7714cb29
...
...
@@ -157,7 +157,7 @@ fn instantiate_path(&@fn_ctxt fcx, &ast::path pth, &ty_param_count_and_ty tpt,
ty_param_count
);
auto
ty_param_vars
=
bind_result
._0
;
auto
ty_substs_opt
;
auto
ty_substs_len
=
vec
::
len
[
@
ast
::
ty
](
pth
.node.types
);
auto
ty_substs_len
=
i
vec
::
len
[
@
ast
::
ty
](
pth
.node.types
);
if
(
ty_substs_len
>
0u
)
{
let
ty
::
t
[]
ty_substs
=
~
[];
auto
i
=
0u
;
...
...
@@ -258,7 +258,7 @@ fn ast_mt_to_mt(&ty::ctxt tcx, &ty_getter getter, &ast::mt mt) -> ty::mt {
ret
rec
(
ty
=
ast_ty_to_ty
(
tcx
,
getter
,
mt
.ty
),
mut
=
mt
.mut
);
}
fn
instantiate
(
&
ty
::
ctxt
tcx
,
&
span
sp
,
&
ty_getter
getter
,
&
ast
::
def_id
id
,
&
vec
[
@
ast
::
ty
]
args
)
->
ty
::
t
{
&
ast
::
def_id
id
,
&
(
@
ast
::
ty
)[
]
args
)
->
ty
::
t
{
// TODO: maybe record cname chains so we can do
// "foo = int" like OCaml?
...
...
@@ -346,9 +346,8 @@ fn instantiate(&ty::ctxt tcx, &span sp, &ty_getter getter,
case
(
ast
::
ty_path
(
?
path
,
?
id
))
{
alt
(
tcx
.def_map
.find
(
id
))
{
case
(
some
(
ast
::
def_ty
(
?
id
)))
{
typ
=
instantiate
(
tcx
,
ast_ty
.span
,
getter
,
id
,
path
.node.types
);
typ
=
instantiate
(
tcx
,
ast_ty
.span
,
getter
,
id
,
path
.node.types
);
}
case
(
some
(
ast
::
def_native_ty
(
?
id
)))
{
typ
=
getter
(
id
)
._1
;
}
case
(
some
(
ast
::
def_ty_arg
(
?
id
)))
{
...
...
@@ -1696,7 +1695,7 @@ fn check_binop_type_compat(&@fn_ctxt fcx, span span,
// The definition doesn't take type parameters. If the programmer
// supplied some, that's an error.
if
(
vec
::
len
[
@
ast
::
ty
](
pth
.node.types
)
>
0u
)
{
if
(
i
vec
::
len
[
@
ast
::
ty
](
pth
.node.types
)
>
0u
)
{
fcx
.ccx.tcx.sess
.span_fatal
(
expr
.span
,
"this kind of value does not
\
take type parameters"
);
...
...
src/comp/syntax/ast.rs
浏览文件 @
7714cb29
// The Rust abstract syntax tree.
import
std
::
ivec
;
import
std
::
option
;
import
std
::
str
;
import
std
::
vec
;
...
...
@@ -15,11 +17,11 @@
// FIXME: with typestate constraint, could say
// idents and types are the same length, and are
// non-empty
type
path_
=
rec
(
vec
[
ident
]
idents
,
vec
[
@
ty
]
types
);
type
path_
=
rec
(
ident
[]
idents
,
(
@
ty
)[
]
types
);
type
path
=
spanned
[
path_
];
fn
path_name
(
&
path
p
)
->
str
{
ret
str
::
connect
(
p
.node.idents
,
"::"
);
}
fn
path_name
(
&
path
p
)
->
str
{
ret
str
::
connect
_ivec
(
p
.node.idents
,
"::"
);
}
type
crate_num
=
int
;
type
node_id
=
int
;
...
...
@@ -632,11 +634,11 @@ fn ternary_to_if(&@expr e) -> @ast::expr {
// Path stringification
fn
path_to_str
(
&
ast
::
path
pth
)
->
str
{
auto
result
=
str
::
connect
(
pth
.node.idents
,
"::"
);
if
(
vec
::
len
[
@
ast
::
ty
](
pth
.node.types
)
>
0u
)
{
auto
result
=
str
::
connect
_ivec
(
pth
.node.idents
,
"::"
);
if
(
i
vec
::
len
[
@
ast
::
ty
](
pth
.node.types
)
>
0u
)
{
fn
f
(
&@
ast
::
ty
t
)
->
str
{
ret
print
::
pprust
::
ty_to_str
(
*
t
);
}
result
+=
"["
;
result
+=
str
::
connect
(
vec
::
map
(
f
,
pth
.node.types
),
","
);
result
+=
str
::
connect
_ivec
(
i
vec
::
map
(
f
,
pth
.node.types
),
","
);
result
+=
"]"
;
}
ret
result
;
...
...
src/comp/syntax/ext/base.rs
浏览文件 @
7714cb29
import
std
::
ivec
;
import
std
::
vec
;
import
std
::
option
;
import
std
::
map
::
hashmap
;
...
...
@@ -71,8 +72,8 @@ fn expr_to_str(&ext_ctxt cx, @ast::expr expr, str error) -> str {
fn
expr_to_ident
(
&
ext_ctxt
cx
,
@
ast
::
expr
expr
,
str
error
)
->
ast
::
ident
{
alt
(
expr
.node
)
{
case
(
ast
::
expr_path
(
?
p
))
{
if
(
vec
::
len
(
p
.node.types
)
>
0u
||
vec
::
len
(
p
.node.idents
)
!=
1u
)
{
if
(
i
vec
::
len
(
p
.node.types
)
>
0u
||
i
vec
::
len
(
p
.node.idents
)
!=
1u
)
{
cx
.span_fatal
(
expr
.span
,
error
);
}
else
{
ret
p
.node.idents
.
(
0
);
...
...
src/comp/syntax/ext/fmt.rs
浏览文件 @
7714cb29
...
...
@@ -60,10 +60,9 @@ fn make_add_expr(&ext_ctxt cx, span sp, @ast::expr lhs,
auto
binexpr
=
ast
::
expr_binary
(
ast
::
add
,
lhs
,
rhs
);
ret
@
rec
(
id
=
cx
.next_id
(),
node
=
binexpr
,
span
=
sp
);
}
fn
make_path_expr
(
&
ext_ctxt
cx
,
span
sp
,
vec
[
ast
::
ident
]
idents
)
fn
make_path_expr
(
&
ext_ctxt
cx
,
span
sp
,
&
ast
::
ident
[
]
idents
)
->
@
ast
::
expr
{
let
vec
[
@
ast
::
ty
]
types
=
[];
auto
path
=
rec
(
idents
=
idents
,
types
=
types
);
auto
path
=
rec
(
idents
=
idents
,
types
=~
[]);
auto
sp_path
=
rec
(
node
=
path
,
span
=
sp
);
auto
pathexpr
=
ast
::
expr_path
(
sp_path
);
ret
@
rec
(
id
=
cx
.next_id
(),
node
=
pathexpr
,
span
=
sp
);
...
...
@@ -73,7 +72,7 @@ fn make_vec_expr(&ext_ctxt cx, span sp, vec[@ast::expr] exprs) ->
auto
vecexpr
=
ast
::
expr_vec
(
exprs
,
ast
::
imm
,
ast
::
sk_rc
);
ret
@
rec
(
id
=
cx
.next_id
(),
node
=
vecexpr
,
span
=
sp
);
}
fn
make_call
(
&
ext_ctxt
cx
,
span
sp
,
vec
[
ast
::
ident
]
fn_path
,
fn
make_call
(
&
ext_ctxt
cx
,
span
sp
,
&
ast
::
ident
[
]
fn_path
,
vec
[
@
ast
::
expr
]
args
)
->
@
ast
::
expr
{
auto
pathexpr
=
make_path_expr
(
cx
,
sp
,
fn_path
);
auto
callexpr
=
ast
::
expr_call
(
pathexpr
,
args
);
...
...
@@ -92,11 +91,11 @@ fn make_rec_expr(&ext_ctxt cx, span sp,
auto
recexpr
=
ast
::
expr_rec
(
astfields
,
option
::
none
[
@
ast
::
expr
]);
ret
@
rec
(
id
=
cx
.next_id
(),
node
=
recexpr
,
span
=
sp
);
}
fn
make_path_vec
(
str
ident
)
->
vec
[
str
]
{
fn
make_path_vec
(
str
ident
)
->
str
[
]
{
// FIXME: #fmt can't currently be used from within std
// because we're explicitly referencing the 'std' crate here
ret
[
"std"
,
"extfmt"
,
"rt"
,
ident
];
ret
~
[
"std"
,
"extfmt"
,
"rt"
,
ident
];
}
fn
make_rt_path_expr
(
&
ext_ctxt
cx
,
span
sp
,
str
ident
)
->
@
ast
::
expr
{
...
...
src/comp/syntax/ext/simplext.rs
浏览文件 @
7714cb29
use
std
;
import
codemap
::
span
;
import
std
::
ivec
;
import
std
::
vec
;
import
std
::
option
;
import
vec
::
map
;
...
...
@@ -50,7 +51,7 @@ fn subst_ident(&ext_ctxt cx, &vec[@ast::expr] args,
fn
subst_path
(
&
ext_ctxt
cx
,
&
vec
[
@
ast
::
expr
]
args
,
@
vec
[
ident
]
param_names
,
&
path_
p
,
ast_fold
fld
)
->
path_
{
// Don't substitute into qualified names.
if
(
len
(
p
.types
)
>
0u
||
len
(
p
.idents
)
!=
1u
)
{
ret
p
;
}
if
(
ivec
::
len
(
p
.types
)
>
0u
||
ivec
::
len
(
p
.idents
)
!=
1u
)
{
ret
p
;
}
alt
(
position
(
p
.idents
.
(
0
),
*
param_names
))
{
case
(
some
[
uint
](
?
idx
))
{
alt
(
args
.
(
idx
)
.node
)
{
...
...
@@ -75,7 +76,8 @@ fn subst_expr(&ext_ctxt cx, &vec[@ast::expr] args, @vec[ident] param_names,
ret
alt
(
e
)
{
case
(
expr_path
(
?
p
)){
// Don't substitute into qualified names.
if
(
len
(
p
.node.types
)
>
0u
||
len
(
p
.node.idents
)
!=
1u
)
{
e
}
if
(
ivec
::
len
(
p
.node.types
)
>
0u
||
ivec
::
len
(
p
.node.idents
)
!=
1u
)
{
e
}
alt
(
position
(
p
.node.idents
.
(
0
),
*
param_names
))
{
case
(
some
[
uint
](
?
idx
))
{
args
.
(
idx
)
.node
...
...
src/comp/syntax/fold.rs
浏览文件 @
7714cb29
import
syntax
::
codemap
::
span
;
import
ast
::
*
;
import
std
::
ivec
;
import
std
::
vec
;
import
std
::
option
;
import
vec
::
map
;
...
...
@@ -486,8 +487,8 @@ fn noop_fold_ident(&ident i, ast_fold fld) -> ident {
}
fn
noop_fold_path
(
&
path_
p
,
ast_fold
fld
)
->
path_
{
ret
rec
(
idents
=
map
(
fld
.fold_ident
,
p
.idents
),
types
=
map
(
fld
.fold_ty
,
p
.types
));
ret
rec
(
idents
=
ivec
::
map
(
fld
.fold_ident
,
p
.idents
),
types
=
ivec
::
map
(
fld
.fold_ty
,
p
.types
));
}
fn
noop_fold_local
(
&
local_
l
,
ast_fold
fld
)
->
local_
{
...
...
src/comp/syntax/parse/parser.rs
浏览文件 @
7714cb29
import
std
::
io
;
import
std
::
ivec
;
import
std
::
vec
;
import
std
::
str
;
import
std
::
option
;
...
...
@@ -409,13 +410,18 @@ fn parse_ty_postfix(@ast::ty orig_t, &parser p) -> @ast::ty {
// This is explicit type parameter instantiation.
auto
seq
=
parse_seq_to_end
(
token
::
RBRACKET
,
some
(
token
::
COMMA
),
parse_ty
,
p
);
// FIXME: Remove this vec->ivec conversion.
auto
seq_ivec
=
~
[];
for
(
@
ast
::
ty
typ
in
seq
)
{
seq_ivec
+=
~
[
typ
];
}
alt
(
orig_t
.node
)
{
case
(
ast
::
ty_path
(
?
pth
,
?
ann
))
{
auto
hi
=
p
.get_hi_pos
();
ret
@
spanned
(
lo
,
hi
,
ast
::
ty_path
(
spanned
(
lo
,
hi
,
rec
(
idents
=
pth
.node.idents
,
types
=
seq
)),
types
=
seq
_ivec
)),
ann
));
}
case
(
_
)
{
...
...
@@ -637,12 +643,12 @@ fn is_ident(token::token t) -> bool {
fn
parse_path
(
&
parser
p
)
->
ast
::
path
{
auto
lo
=
p
.get_lo_pos
();
auto
hi
=
lo
;
let
vec
[
ast
::
ident
]
ids
=
[];
let
ast
::
ident
[]
ids
=
~
[];
while
(
true
)
{
alt
(
p
.peek
())
{
case
(
token
::
IDENT
(
?
i
,
_
))
{
hi
=
p
.get_hi_pos
();
ids
+=
[
p
.get_str
(
i
)];
ids
+=
~
[
p
.get_str
(
i
)];
p
.bump
();
if
(
p
.peek
()
==
token
::
MOD_SEP
)
{
p
.bump
();
}
else
{
break
;
}
}
...
...
@@ -650,7 +656,7 @@ fn parse_path(&parser p) -> ast::path {
}
}
hi
=
p
.get_hi_pos
();
ret
spanned
(
lo
,
hi
,
rec
(
idents
=
ids
,
types
=
[]));
ret
spanned
(
lo
,
hi
,
rec
(
idents
=
ids
,
types
=
~
[]));
}
fn
parse_path_and_ty_param_substs
(
&
parser
p
)
->
ast
::
path
{
...
...
@@ -659,8 +665,13 @@ fn parse_path_and_ty_param_substs(&parser p) -> ast::path {
if
(
p
.peek
()
==
token
::
LBRACKET
)
{
auto
seq
=
parse_seq
(
token
::
LBRACKET
,
token
::
RBRACKET
,
some
(
token
::
COMMA
),
parse_ty
,
p
);
// FIXME: Remove this vec->ivec conversion.
auto
seq_ivec
=
~
[];
for
(
@
ast
::
ty
typ
in
seq
.node
)
{
seq_ivec
+=
~
[
typ
];
}
auto
hi
=
p
.get_hi_pos
();
path
=
spanned
(
lo
,
hi
,
rec
(
idents
=
path
.node.idents
,
types
=
seq
.node
));
path
=
spanned
(
lo
,
hi
,
rec
(
idents
=
path
.node.idents
,
types
=
seq
_ivec
));
}
ret
path
;
}
...
...
@@ -954,7 +965,7 @@ fn parse_syntax_ext(&parser p) -> @ast::expr {
fn
parse_syntax_ext_naked
(
&
parser
p
,
uint
lo
)
->
@
ast
::
expr
{
auto
pth
=
parse_path
(
p
);
if
(
vec
::
len
(
pth
.node.idents
)
==
0u
)
{
if
(
i
vec
::
len
(
pth
.node.idents
)
==
0u
)
{
p
.fatal
(
"expected a syntax expander name"
);
}
auto
es
=
parse_seq
(
token
::
LPAREN
,
token
::
RPAREN
,
...
...
@@ -974,7 +985,7 @@ fn parse_syntax_ext_naked(&parser p, uint lo) -> @ast::expr {
fn
expand_syntax_ext
(
&
parser
p
,
span
sp
,
&
ast
::
path
path
,
vec
[
@
ast
::
expr
]
args
,
option
::
t
[
str
]
body
)
->
ast
::
expr_
{
assert
(
vec
::
len
(
path
.node.idents
)
>
0u
);
assert
(
i
vec
::
len
(
path
.node.idents
)
>
0u
);
auto
extname
=
path
.node.idents
.
(
0
);
alt
(
p
.get_syntax_expanders
()
.find
(
extname
))
{
case
(
none
)
{
p
.fatal
(
"unknown syntax expander: '"
+
extname
+
"'"
);
}
...
...
src/comp/syntax/print/pprust.rs
浏览文件 @
7714cb29
import
std
::
uint
;
import
std
::
ivec
;
import
std
::
int
;
import
std
::
vec
;
import
std
::
str
;
import
std
::
io
;
import
std
::
str
;
import
std
::
uint
;
import
std
::
vec
;
import
std
::
option
;
import
parse
::
lexer
;
import
syntax
::
codemap
::
codemap
;
...
...
@@ -206,6 +207,17 @@ fn commasep[IN](&ps s, breaks b, vec[IN] elts, fn(&ps, &IN) op) {
end
(
s
);
}
fn
commasep_ivec
[
IN
](
&
ps
s
,
breaks
b
,
&
IN
[]
elts
,
fn
(
&
ps
,
&
IN
)
op
)
{
box
(
s
,
0u
,
b
);
auto
first
=
true
;
for
(
IN
elt
in
elts
)
{
if
(
first
)
{
first
=
false
;
}
else
{
word_space
(
s
,
","
);
}
op
(
s
,
elt
);
}
end
(
s
);
}
fn
commasep_cmnt
[
IN
](
&
ps
s
,
breaks
b
,
vec
[
IN
]
elts
,
fn
(
&
ps
,
&
IN
)
op
,
fn
(
&
IN
)
->
codemap
::
span
get_span
)
{
box
(
s
,
0u
,
b
);
...
...
@@ -1013,9 +1025,9 @@ fn print_path(&ps s, &ast::path path) {
if
(
first
)
{
first
=
false
;
}
else
{
word
(
s
.s
,
"::"
);
}
word
(
s
.s
,
id
);
}
if
(
vec
::
len
(
path
.node.types
)
>
0u
)
{
if
(
i
vec
::
len
(
path
.node.types
)
>
0u
)
{
word
(
s
.s
,
"["
);
commasep
(
s
,
inconsistent
,
path
.node.types
,
print_boxed_type
);
commasep
_ivec
(
s
,
inconsistent
,
path
.node.types
,
print_boxed_type
);
word
(
s
.s
,
"]"
);
}
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录