diff options
| author | Piotr Czarnecki <pioczarn@gmail.com> | 2014-08-21 14:34:00 +0100 |
|---|---|---|
| committer | Piotr Czarnecki <pioczarn@gmail.com> | 2014-09-09 20:34:41 +0100 |
| commit | 696367fb8de63a3ff264c65981457b9fbd0e7b06 (patch) | |
| tree | 4b5d33c711873f1fd881300a13f91b7a90d12be7 /src/libsyntax | |
| parent | 6f34760e4173dda94162502153fe4c5a2a96fc9d (diff) | |
| download | rust-696367fb8de63a3ff264c65981457b9fbd0e7b06.tar.gz rust-696367fb8de63a3ff264c65981457b9fbd0e7b06.zip | |
Decouple string and argument pieces
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ext/format.rs | 84 |
1 files changed, 54 insertions, 30 deletions
diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs index b3bb01e1d04..fc4d8c83c51 100644 --- a/src/libsyntax/ext/format.rs +++ b/src/libsyntax/ext/format.rs @@ -49,11 +49,13 @@ struct Context<'a, 'b:'a> { name_types: HashMap<String, ArgumentType>, name_ordering: Vec<String>, - /// The latest consecutive literal strings - literal: Option<String>, + /// The latest consecutive literal strings, or empty if there weren't any. + literal: String, - /// Collection of the compiled `rt::Piece` structures + /// Collection of the compiled `rt::Argument` structures pieces: Vec<Gc<ast::Expr>>, + /// Collection of string literals + str_pieces: Vec<Gc<ast::Expr>>, name_positions: HashMap<String, uint>, method_statics: Vec<Gc<ast::Item>>, @@ -370,28 +372,22 @@ impl<'a, 'b> Context<'a, 'b> { } } - /// Translate the accumulated string literals to a static `rt::Piece` - fn trans_literal_string(&mut self) -> Option<Gc<ast::Expr>> { + /// Translate the accumulated string literals to a literal expression + fn trans_literal_string(&mut self) -> Gc<ast::Expr> { let sp = self.fmtsp; - self.literal.take().map(|s| { - let s = token::intern_and_get_ident(s.as_slice()); - self.ecx.expr_call_global(sp, - self.rtpath("String"), - vec!( - self.ecx.expr_str(sp, s) - )) - }) + let s = token::intern_and_get_ident(self.literal.as_slice()); + self.literal.clear(); + self.ecx.expr_str(sp, s) } - /// Translate a `parse::Piece` to a static `rt::Piece` + /// Translate a `parse::Piece` to a static `rt::Argument` or append + /// to the `literal` string. fn trans_piece(&mut self, piece: &parse::Piece) -> Option<Gc<ast::Expr>> { + // let mut is_not_default = true; let sp = self.fmtsp; match *piece { parse::String(s) => { - match self.literal { - Some(ref mut sb) => sb.push_str(s), - ref mut empty => *empty = Some(String::from_str(s)), - } + self.literal.push_str(s); None } parse::Argument(ref arg) => { @@ -450,10 +446,9 @@ impl<'a, 'b> Context<'a, 'b> { self.ecx.field_imm(sp, self.ecx.ident_of("width"), width))); let path = self.ecx.path_global(sp, self.rtpath("Argument")); - let s = self.ecx.expr_struct(sp, path, vec!( + Some(self.ecx.expr_struct(sp, path, vec!( self.ecx.field_imm(sp, self.ecx.ident_of("position"), pos), - self.ecx.field_imm(sp, self.ecx.ident_of("format"), fmt))); - Some(self.ecx.expr_call_global(sp, self.rtpath("Argument"), vec!(s))) + self.ecx.field_imm(sp, self.ecx.ident_of("format"), fmt)))) } } } @@ -476,6 +471,30 @@ impl<'a, 'b> Context<'a, 'b> { // Next, build up the static array which will become our precompiled // format "string" + let fmt = self.ecx.expr_vec(self.fmtsp, self.str_pieces.clone()); + let piece_ty = self.ecx.ty_rptr(self.fmtsp, + self.ecx.ty_ident(self.fmtsp, + self.ecx.ident_of("str")), + Some(self.ecx.lifetime(self.fmtsp, + self.ecx.ident_of( + "'static").name)), + ast::MutImmutable); + + let ty = ast::TyFixedLengthVec( + piece_ty, + self.ecx.expr_uint(self.fmtsp, self.str_pieces.len()) + ); + let ty = self.ecx.ty(self.fmtsp, ty); + let st = ast::ItemStatic(ty, ast::MutImmutable, fmt); + let static_str_name = self.ecx.ident_of("__STATIC_FMTSTR"); + let item = self.ecx.item(self.fmtsp, static_str_name, + self.static_attrs(), st); + let decl = respan(self.fmtsp, ast::DeclItem(item)); + lets.push(box(GC) respan(self.fmtsp, + ast::StmtDecl(box(GC) decl, ast::DUMMY_NODE_ID))); + + // Then, build up the static array which will become our precompiled + // format "string" let fmt = self.ecx.expr_vec(self.fmtsp, self.pieces.clone()); let piece_ty = self.ecx.ty_path(self.ecx.path_all( self.fmtsp, @@ -483,7 +502,7 @@ impl<'a, 'b> Context<'a, 'b> { self.ecx.ident_of("std"), self.ecx.ident_of("fmt"), self.ecx.ident_of("rt"), - self.ecx.ident_of("Piece")), + self.ecx.ident_of("Argument")), vec!(self.ecx.lifetime(self.fmtsp, self.ecx.ident_of("'static").name)), Vec::new() @@ -494,8 +513,8 @@ impl<'a, 'b> Context<'a, 'b> { ); let ty = self.ecx.ty(self.fmtsp, ty); let st = ast::ItemStatic(ty, ast::MutImmutable, fmt); - let static_name = self.ecx.ident_of("__STATIC_FMTSTR"); - let item = self.ecx.item(self.fmtsp, static_name, + let static_args_name = self.ecx.ident_of("__STATIC_FMTARGS"); + let item = self.ecx.item(self.fmtsp, static_args_name, self.static_attrs(), st); let decl = respan(self.fmtsp, ast::DeclItem(item)); lets.push(box(GC) respan(self.fmtsp, @@ -545,13 +564,14 @@ impl<'a, 'b> Context<'a, 'b> { } // Now create the fmt::Arguments struct with all our locals we created. - let fmt = self.ecx.expr_ident(self.fmtsp, static_name); + let pieces = self.ecx.expr_ident(self.fmtsp, static_str_name); + let fmt = self.ecx.expr_ident(self.fmtsp, static_args_name); let args_slice = self.ecx.expr_ident(self.fmtsp, slicename); let result = self.ecx.expr_call_global(self.fmtsp, vec!( self.ecx.ident_of("std"), self.ecx.ident_of("fmt"), self.ecx.ident_of("Arguments"), - self.ecx.ident_of("new")), vec!(fmt, args_slice)); + self.ecx.ident_of("new")), vec!(pieces, fmt, args_slice)); // We did all the work of making sure that the arguments // structure is safe, so we can safely have an unsafe block. @@ -718,8 +738,9 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span, name_ordering: name_ordering, nest_level: 0, next_arg: 0, - literal: None, + literal: String::new(), pieces: Vec::new(), + str_pieces: Vec::new(), method_statics: Vec::new(), fmtsp: sp, }; @@ -739,8 +760,8 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span, cx.verify_piece(&piece); match cx.trans_piece(&piece) { Some(piece) => { - cx.trans_literal_string().map(|piece| - cx.pieces.push(piece)); + let s = cx.trans_literal_string(); + cx.str_pieces.push(s); cx.pieces.push(piece); } None => {} @@ -758,7 +779,10 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span, } None => {} } - cx.trans_literal_string().map(|piece| cx.pieces.push(piece)); + if !cx.literal.is_empty() { + let s = cx.trans_literal_string(); + cx.str_pieces.push(s); + } // Make sure that all arguments were used and all arguments have types. for (i, ty) in cx.arg_types.iter().enumerate() { |
