Build up the result of fmt! in a buffer instead of a vector
This commit is contained in:
parent
d700500d0c
commit
1a0d212dd9
2 changed files with 44 additions and 30 deletions
|
@ -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 {
|
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));
|
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,
|
pub fn mk_call_(cx: @ext_ctxt, sp: span, fn_expr: @ast::expr,
|
||||||
+args: ~[@ast::expr]) -> @ast::expr {
|
+args: ~[@ast::expr]) -> @ast::expr {
|
||||||
mk_expr(cx, sp, ast::expr_call(fn_expr, args, ast::NoSugar))
|
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) {
|
fn log_conv(c: &Conv) {
|
||||||
|
debug!("Building conversion:");
|
||||||
match c.param {
|
match c.param {
|
||||||
Some(p) => { debug!("param: %s", p.to_str()); }
|
Some(p) => { debug!("param: %s", p.to_str()); }
|
||||||
_ => debug!("param: none")
|
_ => debug!("param: none")
|
||||||
|
@ -268,15 +269,15 @@ fn pieces_to_expr(cx: @ext_ctxt, sp: span,
|
||||||
TyPoly => debug!("type: poly")
|
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 fmt_sp = args[0].span;
|
||||||
let mut n = 0u;
|
let mut n = 0u;
|
||||||
let mut piece_exprs = ~[];
|
|
||||||
let nargs = args.len();
|
let nargs = args.len();
|
||||||
for pieces.each |pc| {
|
let pieces = do vec::map_consume(pieces) |pc| {
|
||||||
match *pc {
|
match pc {
|
||||||
PieceString(ref s) => {
|
PieceString(s) => mk_uniq_str(cx, fmt_sp, s),
|
||||||
piece_exprs.push(mk_uniq_str(cx, fmt_sp, copy *s))
|
|
||||||
}
|
|
||||||
PieceConv(ref conv) => {
|
PieceConv(ref conv) => {
|
||||||
n += 1u;
|
n += 1u;
|
||||||
if n >= nargs {
|
if n >= nargs {
|
||||||
|
@ -284,33 +285,43 @@ fn pieces_to_expr(cx: @ext_ctxt, sp: span,
|
||||||
~"not enough arguments to fmt! " +
|
~"not enough arguments to fmt! " +
|
||||||
~"for the given format string");
|
~"for the given format string");
|
||||||
}
|
}
|
||||||
debug!("Building conversion:");
|
|
||||||
log_conv(conv);
|
log_conv(conv);
|
||||||
let arg_expr = args[n];
|
make_new_conv(cx, fmt_sp, conv, args[n])
|
||||||
let c_expr = make_new_conv(
|
|
||||||
cx,
|
|
||||||
fmt_sp,
|
|
||||||
conv,
|
|
||||||
arg_expr
|
|
||||||
);
|
|
||||||
piece_exprs.push(c_expr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
let expected_nargs = n + 1u; // n conversions + the fmt string
|
let expected_nargs = n + 1u; // n conversions + the fmt string
|
||||||
|
|
||||||
if expected_nargs < nargs {
|
if expected_nargs < nargs {
|
||||||
cx.span_fatal
|
cx.span_fatal
|
||||||
(sp, fmt!("too many arguments to fmt!. found %u, expected %u",
|
(sp, fmt!("too many arguments to fmt!. found %u, expected %u",
|
||||||
nargs, expected_nargs));
|
nargs, expected_nargs));
|
||||||
}
|
}
|
||||||
|
|
||||||
let arg_vec = mk_fixed_vec_e(cx, fmt_sp, piece_exprs);
|
/* Concatenate all of the strings together with str::push_str. This
|
||||||
return mk_call_global(cx,
|
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,
|
fmt_sp,
|
||||||
~[cx.parse_sess().interner.intern(@~"str"),
|
~[str_ident, push_ident],
|
||||||
cx.parse_sess().interner.intern(@~"concat")],
|
~[mk_mut_addr_of(cx, fmt_sp, buf()),
|
||||||
~[arg_vec]);
|
pc]);
|
||||||
|
mk_stmt(cx, fmt_sp, call)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return mk_block(cx, fmt_sp, ~[], stms, Some(buf()));
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// Local Variables:
|
// Local Variables:
|
||||||
|
|
Loading…
Reference in a new issue