syntax: format: put static arrays in their own blocks to avoid needing a wrapper block.

This commit is contained in:
Eduard Burtescu 2014-12-19 16:16:16 +02:00
parent 22376be754
commit 17b3c1107a
1 changed files with 38 additions and 39 deletions

View File

@ -473,22 +473,27 @@ impl<'a, 'b> Context<'a, 'b> {
} }
} }
fn item_static_array(ecx: &mut ExtCtxt, fn static_array(ecx: &mut ExtCtxt,
name: ast::Ident, name: &str,
piece_ty: P<ast::Ty>, piece_ty: P<ast::Ty>,
pieces: Vec<P<ast::Expr>>) pieces: Vec<P<ast::Expr>>)
-> P<ast::Stmt> { -> P<ast::Expr> {
let fmtsp = piece_ty.span; let fmtsp = piece_ty.span;
let fmt = ecx.expr_vec(fmtsp, pieces); let ty = ecx.ty_rptr(fmtsp,
let fmt = ecx.expr_addr_of(fmtsp, fmt); ecx.ty(fmtsp, ast::TyVec(piece_ty)),
let ty = ast::TyVec(piece_ty); Some(ecx.lifetime(fmtsp, special_idents::static_lifetime.name)),
let ty = ast::TyRptr(Some(ecx.lifetime(fmtsp, special_idents::static_lifetime.name)), ast::MutImmutable);
ast::MutTy{ mutbl: ast::MutImmutable, ty: ecx.ty(fmtsp, ty) }); let slice = ecx.expr_vec_slice(fmtsp, pieces);
let ty = ecx.ty(fmtsp, ty); let st = ast::ItemStatic(ty, ast::MutImmutable, slice);
let st = ast::ItemStatic(ty, ast::MutImmutable, fmt);
let name = ecx.ident_of(name);
let item = ecx.item(fmtsp, name, Context::static_attrs(ecx, fmtsp), st); let item = ecx.item(fmtsp, name, Context::static_attrs(ecx, fmtsp), st);
let decl = respan(fmtsp, ast::DeclItem(item)); let decl = respan(fmtsp, ast::DeclItem(item));
P(respan(fmtsp, ast::StmtDecl(P(decl), ast::DUMMY_NODE_ID)))
// Wrap the declaration in a block so that it forms a single expression.
ecx.expr_block(ecx.block(fmtsp,
vec![P(respan(fmtsp, ast::StmtDecl(P(decl), ast::DUMMY_NODE_ID)))],
Some(ecx.expr_ident(fmtsp, name))))
} }
/// Actually builds the expression which the iformat! block will be expanded /// Actually builds the expression which the iformat! block will be expanded
@ -501,33 +506,17 @@ impl<'a, 'b> Context<'a, 'b> {
// First, build up the static array which will become our precompiled // First, build up the static array which will become our precompiled
// format "string" // format "string"
let static_str_name = self.ecx.ident_of("__STATIC_FMTSTR"); let static_lifetime = self.ecx.lifetime(self.fmtsp, special_idents::static_lifetime.name);
let static_lifetime = self.ecx.lifetime(self.fmtsp, self.ecx.ident_of("'static").name);
let piece_ty = self.ecx.ty_rptr( let piece_ty = self.ecx.ty_rptr(
self.fmtsp, self.fmtsp,
self.ecx.ty_ident(self.fmtsp, self.ecx.ident_of("str")), self.ecx.ty_ident(self.fmtsp, self.ecx.ident_of("str")),
Some(static_lifetime), Some(static_lifetime),
ast::MutImmutable); ast::MutImmutable);
let mut lets = vec![ let pieces = Context::static_array(self.ecx,
Context::item_static_array(self.ecx, static_str_name, piece_ty, self.str_pieces) "__STATIC_FMTSTR",
];
// Then, build up the static array which will store our precompiled
// nonstandard placeholders, if there are any.
let static_args_name = self.ecx.ident_of("__STATIC_FMTARGS");
if !self.all_pieces_simple {
let piece_ty = self.ecx.ty_path(self.ecx.path_all(
self.fmtsp,
true, Context::rtpath(self.ecx, "Argument"),
vec![static_lifetime],
vec![],
vec![]
));
lets.push(Context::item_static_array(self.ecx,
static_args_name,
piece_ty, piece_ty,
self.pieces)); self.str_pieces);
}
// Right now there is a bug such that for the expression: // Right now there is a bug such that for the expression:
// foo(bar(&1)) // foo(bar(&1))
@ -571,13 +560,25 @@ impl<'a, 'b> Context<'a, 'b> {
let args = locals.into_iter().chain(names.into_iter().map(|a| a.unwrap())); let args = locals.into_iter().chain(names.into_iter().map(|a| a.unwrap()));
// Now create the fmt::Arguments struct with all our locals we created. // Now create the fmt::Arguments struct with all our locals we created.
let pieces = self.ecx.expr_ident(self.fmtsp, static_str_name);
let args_slice = self.ecx.expr_vec_slice(self.fmtsp, args.collect()); let args_slice = self.ecx.expr_vec_slice(self.fmtsp, args.collect());
let (fn_name, fn_args) = if self.all_pieces_simple { let (fn_name, fn_args) = if self.all_pieces_simple {
("new", vec![pieces, args_slice]) ("new", vec![pieces, args_slice])
} else { } else {
let fmt = self.ecx.expr_ident(self.fmtsp, static_args_name); // Build up the static array which will store our precompiled
// nonstandard placeholders, if there are any.
let piece_ty = self.ecx.ty_path(self.ecx.path_all(
self.fmtsp,
true, Context::rtpath(self.ecx, "Argument"),
vec![static_lifetime],
vec![],
vec![]
));
let fmt = Context::static_array(self.ecx,
"__STATIC_FMTARGS",
piece_ty,
self.pieces);
("with_placeholders", vec![pieces, fmt, args_slice]) ("with_placeholders", vec![pieces, fmt, args_slice])
}; };
@ -587,7 +588,7 @@ impl<'a, 'b> Context<'a, 'b> {
self.ecx.ident_of("Arguments"), self.ecx.ident_of("Arguments"),
self.ecx.ident_of(fn_name)), fn_args); self.ecx.ident_of(fn_name)), fn_args);
let result = match invocation { let body = match invocation {
Call(e) => { Call(e) => {
let span = e.span; let span = e.span;
self.ecx.expr_call(span, e, vec![ self.ecx.expr_call(span, e, vec![
@ -601,8 +602,6 @@ impl<'a, 'b> Context<'a, 'b> {
]) ])
} }
}; };
let body = self.ecx.expr_block(self.ecx.block(self.fmtsp, lets,
Some(result)));
// Constructs an AST equivalent to: // Constructs an AST equivalent to:
// //