Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/comp/syntax/ext/fmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ fn pieces_to_expr(cx: ext_ctxt, sp: span, pieces: [piece], args: [@ast::expr])
ty_int(s) {
alt s { signed. { ret true; } unsigned. { ret false; } }
}
ty_float. { ret true; }
_ { ret false; }
}
}
Expand Down Expand Up @@ -250,6 +251,7 @@ fn pieces_to_expr(cx: ext_ctxt, sp: span, pieces: [piece], args: [@ast::expr])
ty_hex(_) { ret make_conv_call(cx, arg.span, "uint", cnv, arg); }
ty_bits. { ret make_conv_call(cx, arg.span, "uint", cnv, arg); }
ty_octal. { ret make_conv_call(cx, arg.span, "uint", cnv, arg); }
ty_float. { ret make_conv_call(cx, arg.span, "float", cnv, arg); }
_ { cx.span_unimpl(sp, unsupported); }
}
}
Expand Down Expand Up @@ -301,6 +303,7 @@ fn pieces_to_expr(cx: ext_ctxt, sp: span, pieces: [piece], args: [@ast::expr])
}
}
ty_octal. { log "type: octal"; }
ty_float. { log "type: float"; }
}
}
let fmt_sp = args[0].span;
Expand Down
2 changes: 0 additions & 2 deletions src/comp/util/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,8 +275,6 @@ fn is_main_name(path: [ast::ident]) -> bool {
str::eq(option::get(std::vec::last(path)), "main")
}



//
// Local Variables:
// mode: rust
Expand Down
18 changes: 18 additions & 0 deletions src/lib/extfmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ mod ct {
ty_bits;
ty_hex(caseness);
ty_octal;
ty_float;
// FIXME: More types
}
tag flag {
Expand Down Expand Up @@ -246,6 +247,8 @@ mod ct {
ty_bits
} else if str::eq(tstr, "o") {
ty_octal
} else if str::eq(tstr, "f") {
ty_float
} else { error("unknown type in conversion: " + tstr) };
ret {ty: t, next: i + 1u};
}
Expand Down Expand Up @@ -328,6 +331,21 @@ mod rt {
};
ret pad(cv, unpadded, pad_nozero);
}
fn conv_float(cv: conv, f: float) -> str {
let (to_str, digits) = alt cv.precision {
count_is(c) { (float::to_str_exact, c as uint) }
count_implied. { (float::to_str, 6u) }
};
let s = to_str(f, digits);
if 0.0 <= f {
if have_flag(cv.flags, flag_sign_always) {
s = "+" + s;
} else if have_flag(cv.flags, flag_space_for_sign) {
s = " " + s;
}
}
ret pad(cv, s, pad_signed);
}

// Convert an int to string with minimum number of digits. If precision is
// 0 and num is 0 then the result is the empty string.
Expand Down
41 changes: 37 additions & 4 deletions src/lib/float.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,64 @@ Module: float
*/

/*
Function: to_str
Function: to_str_common

Converts a float to a string

Parameters:

num - The float value
digits: The number of significant digits
digits - The number of significant digits
exact - Whether to enforce the exact number of significant digits
*/
fn to_str(num: float, digits: uint) -> str {
fn to_str_common(num: float, digits: uint, exact: bool) -> str {
let (num, accum) = num < 0.0 ? (-num, "-") : (num, "");
let trunc = num as uint;
let frac = num - (trunc as float);
accum += uint::str(trunc);
if frac == 0.0 || digits == 0u { ret accum; }
accum += ".";
let i = digits;
while i > 0u && frac > 0.0 {
let epsilon = 1. / pow_uint_to_uint_as_float(10u, i);
while i > 0u && (frac >= epsilon || exact) {
frac *= 10.0;
epsilon *= 10.0;
let digit = frac as uint;
accum += uint::str(digit);
frac -= digit as float;
i -= 1u;
}
ret accum;

}

/*
Function: to_str

Converts a float to a string with exactly the number of provided significant
digits

Parameters:

num - The float value
digits - The number of significant digits
*/
fn to_str_exact(num: float, digits: uint) -> str {
to_str_common(num, digits, true)
}

/*
Function: to_str

Converts a float to a string with a maximum number of significant digits

Parameters:

num - The float value
digits - The number of significant digits
*/
fn to_str(num: float, digits: uint) -> str {
to_str_common(num, digits, false)
}

/*
Expand Down
14 changes: 14 additions & 0 deletions src/test/run-pass/syntax-extension-fmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ fn part1() {
test(#fmt["%X", 0x12ab_u], "12AB");
test(#fmt["%o", 10u], "12");
test(#fmt["%t", 0b11010101_u], "11010101");
test(#fmt["%f", 5.82], "5.82");
// 32-bit limits

test(#fmt["%i", -2147483648], "-2147483648");
Expand All @@ -61,6 +62,7 @@ fn part2() {
test(#fmt["%10o", 10u], " 12");
test(#fmt["%10t", 0xff_u], " 11111111");
test(#fmt["%10c", 'A'], " A");
test(#fmt["%10f", 5.82], " 5.82");
// Left justify

test(#fmt["%-10d", 500], "500 ");
Expand All @@ -73,6 +75,7 @@ fn part2() {
test(#fmt["%-10o", 10u], "12 ");
test(#fmt["%-10t", 0xff_u], "11111111 ");
test(#fmt["%-10c", 'A'], "A ");
test(#fmt["%-10f", 5.82], "5.82 ");
}

fn part3() {
Expand All @@ -90,6 +93,7 @@ fn part3() {
test(#fmt["%.o", 10u], "12");
test(#fmt["%.t", 3u], "11");
test(#fmt["%.c", 'A'], "A");
test(#fmt["%.f", 5.82], "5");
test(#fmt["%.0d", 0], "");
test(#fmt["%.0u", 0u], "");
test(#fmt["%.0x", 0u], "");
Expand All @@ -102,6 +106,7 @@ fn part3() {
test(#fmt["%.0o", 10u], "12");
test(#fmt["%.0t", 3u], "11");
test(#fmt["%.0c", 'A'], "A");
test(#fmt["%.0f", 5.892], "5");
test(#fmt["%.1d", 0], "0");
test(#fmt["%.1u", 0u], "0");
test(#fmt["%.1x", 0u], "0");
Expand All @@ -114,6 +119,7 @@ fn part3() {
test(#fmt["%.1o", 10u], "12");
test(#fmt["%.1t", 3u], "11");
test(#fmt["%.1c", 'A'], "A");
test(#fmt["%.1f", 5.82], "5.8");
}
fn part4() {
test(#fmt["%.5d", 0], "00000");
Expand All @@ -128,6 +134,7 @@ fn part4() {
test(#fmt["%.5o", 10u], "00012");
test(#fmt["%.5t", 3u], "00011");
test(#fmt["%.5c", 'A'], "A");
test(#fmt["%.5f", 5.82], "5.82000");
// Bool precision. I'm not sure if it's good or bad to have bool
// conversions support precision - it's not standard printf so we
// can do whatever. For now I'm making it behave the same as string
Expand All @@ -144,15 +151,19 @@ fn part5() {
test(#fmt["%+d", 0], "+0");
test(#fmt["%+d", 1], "+1");
test(#fmt["%+d", -1], "-1");
test(#fmt["%+f", 0.0], "+0");
// Leave space for sign

test(#fmt["% d", 0], " 0");
test(#fmt["% d", 1], " 1");
test(#fmt["% d", -1], "-1");
test(#fmt["% f", 0.0], " 0");
// Plus overrides space

test(#fmt["% +d", 0], "+0");
test(#fmt["%+ d", 0], "+0");
test(#fmt["% +f", 0.0], "+0");
test(#fmt["%+ f", 0.0], "+0");
// 0-padding

test(#fmt["%05d", 0], "00000");
Expand All @@ -163,6 +174,7 @@ fn part5() {
test(#fmt["%05X", 127u], "0007F");
test(#fmt["%05o", 10u], "00012");
test(#fmt["%05t", 3u], "00011");
test(#fmt["%05f", 5.82], "05.82");
// 0-padding a string is undefined but glibc does this:

test(#fmt["%05s", "test"], " test");
Expand All @@ -181,6 +193,7 @@ fn part5() {
test(#fmt["%-05s", "test"], "test ");
test(#fmt["%-05c", 'A'], "A ");
test(#fmt["%-05b", true], "true ");
test(#fmt["%-05f", 5.82], "5.82 ");
}
fn part6() {
// Precision overrides 0-padding
Expand All @@ -196,6 +209,7 @@ fn part6() {
test(#fmt["%06.5x", 127u], " 0007f");
test(#fmt["%06.5X", 127u], " 0007F");
test(#fmt["%06.5o", 10u], " 00012");
test(#fmt["%08.5f", 5.82], " 5.82000");
// Signed combinations

test(#fmt["% 5d", 1], " 1");
Expand Down