Build up the result of fmt! in a buffer instead of a vector

This commit is contained in:
Alex Crichton 2013-03-20 13:01:58 -04:00
parent d700500d0c
commit 1a0d212dd9
2 changed files with 44 additions and 30 deletions

View file

@ -108,6 +108,9 @@ pub fn mk_access(cx: @ext_ctxt, sp: span, +p: ~[ast::ident], m: ast::ident)
pub fn mk_addr_of(cx: @ext_ctxt, sp: span, e: @ast::expr) -> @ast::expr {
return mk_expr(cx, sp, ast::expr_addr_of(ast::m_imm, e));
}
pub fn mk_mut_addr_of(cx: @ext_ctxt, sp: span, e: @ast::expr) -> @ast::expr {
return mk_expr(cx, sp, ast::expr_addr_of(ast::m_mutbl, e));
}
pub fn mk_call_(cx: @ext_ctxt, sp: span, fn_expr: @ast::expr,
+args: ~[@ast::expr]) -> @ast::expr {
mk_expr(cx, sp, ast::expr_call(fn_expr, args, ast::NoSugar))

View file

@ -221,6 +221,7 @@ fn pieces_to_expr(cx: @ext_ctxt, sp: span,
}
}
fn log_conv(c: &Conv) {
debug!("Building conversion:");
match c.param {
Some(p) => { debug!("param: %s", p.to_str()); }
_ => debug!("param: none")
@ -268,15 +269,15 @@ fn pieces_to_expr(cx: @ext_ctxt, sp: span,
TyPoly => debug!("type: poly")
}
}
/* Translate each piece (portion of the fmt expression) into a ~str
expression to be concatenated below */
let fmt_sp = args[0].span;
let mut n = 0u;
let mut piece_exprs = ~[];
let nargs = args.len();
for pieces.each |pc| {
match *pc {
PieceString(ref s) => {
piece_exprs.push(mk_uniq_str(cx, fmt_sp, copy *s))
}
let pieces = do vec::map_consume(pieces) |pc| {
match pc {
PieceString(s) => mk_uniq_str(cx, fmt_sp, s),
PieceConv(ref conv) => {
n += 1u;
if n >= nargs {
@ -284,33 +285,43 @@ fn pieces_to_expr(cx: @ext_ctxt, sp: span,
~"not enough arguments to fmt! " +
~"for the given format string");
}
debug!("Building conversion:");
log_conv(conv);
let arg_expr = args[n];
let c_expr = make_new_conv(
cx,
fmt_sp,
conv,
arg_expr
);
piece_exprs.push(c_expr);
}
make_new_conv(cx, fmt_sp, conv, args[n])
}
}
};
let expected_nargs = n + 1u; // n conversions + the fmt string
if expected_nargs < nargs {
cx.span_fatal
(sp, fmt!("too many arguments to fmt!. found %u, expected %u",
nargs, expected_nargs));
}
let arg_vec = mk_fixed_vec_e(cx, fmt_sp, piece_exprs);
return mk_call_global(cx,
/* Concatenate all of the strings together with str::push_str. This
involves storing the first piece into a local variable, and then
pushing each other piece onto the local. The local is contained in its
own block to not conflict with other names as much as possible */
let ident = cx.parse_sess().interner.intern(@~"__fmtbuf");
let buf = || mk_path(cx, fmt_sp, ~[ident]);
let str_ident = cx.parse_sess().interner.intern(@~"str");
let push_ident = cx.parse_sess().interner.intern(@~"push_str");
let mut first = true;
let stms = do vec::map_consume(pieces) |pc| {
if first {
first = false;
mk_local(cx, fmt_sp, true, ident, pc)
} else {
let call = mk_call_global(cx,
fmt_sp,
~[cx.parse_sess().interner.intern(@~"str"),
cx.parse_sess().interner.intern(@~"concat")],
~[arg_vec]);
~[str_ident, push_ident],
~[mk_mut_addr_of(cx, fmt_sp, buf()),
pc]);
mk_stmt(cx, fmt_sp, call)
}
};
return mk_block(cx, fmt_sp, ~[], stms, Some(buf()));
}
//
// Local Variables: