Build up the result of fmt! in a buffer instead of a vector
This commit is contained in:
parent
d700500d0c
commit
1a0d212dd9
@ -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))
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user