mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-07 05:15:02 +00:00
Delegate {}
to Default instead of Poly
By using a separate trait this is overridable on a per-type basis and makes room for the possibility of even more arguments passed in for the future.
This commit is contained in:
parent
109274426a
commit
22c7bbfd0c
@ -356,28 +356,46 @@ pub struct Argument<'self> {
|
||||
priv value: &'self util::Void,
|
||||
}
|
||||
|
||||
/// When a format is not otherwise specified, types are formatted by ascribing
|
||||
/// to this trait. There is not an explicit way of selecting this trait to be
|
||||
/// used for formatting, it is only if no other format is specified.
|
||||
#[allow(missing_doc)]
|
||||
pub trait Default { fn fmt(&Self, &mut Formatter); }
|
||||
|
||||
/// Format trait for the `b` character
|
||||
#[allow(missing_doc)]
|
||||
pub trait Bool { fn fmt(&Self, &mut Formatter); }
|
||||
/// Format trait for the `c` character
|
||||
#[allow(missing_doc)]
|
||||
pub trait Char { fn fmt(&Self, &mut Formatter); }
|
||||
/// Format trait for the `i` and `d` characters
|
||||
#[allow(missing_doc)]
|
||||
pub trait Signed { fn fmt(&Self, &mut Formatter); }
|
||||
/// Format trait for the `u` character
|
||||
#[allow(missing_doc)]
|
||||
pub trait Unsigned { fn fmt(&Self, &mut Formatter); }
|
||||
/// Format trait for the `o` character
|
||||
#[allow(missing_doc)]
|
||||
pub trait Octal { fn fmt(&Self, &mut Formatter); }
|
||||
/// Format trait for the `b` character
|
||||
#[allow(missing_doc)]
|
||||
pub trait Binary { fn fmt(&Self, &mut Formatter); }
|
||||
/// Format trait for the `x` character
|
||||
#[allow(missing_doc)]
|
||||
pub trait LowerHex { fn fmt(&Self, &mut Formatter); }
|
||||
/// Format trait for the `X` character
|
||||
#[allow(missing_doc)]
|
||||
pub trait UpperHex { fn fmt(&Self, &mut Formatter); }
|
||||
/// Format trait for the `s` character
|
||||
#[allow(missing_doc)]
|
||||
pub trait String { fn fmt(&Self, &mut Formatter); }
|
||||
/// Format trait for the `?` character
|
||||
#[allow(missing_doc)]
|
||||
pub trait Poly { fn fmt(&Self, &mut Formatter); }
|
||||
/// Format trait for the `p` character
|
||||
#[allow(missing_doc)]
|
||||
pub trait Pointer { fn fmt(&Self, &mut Formatter); }
|
||||
/// Format trait for the `f` character
|
||||
#[allow(missing_doc)]
|
||||
pub trait Float { fn fmt(&Self, &mut Formatter); }
|
||||
|
||||
@ -855,5 +873,37 @@ impl<T> Pointer for *const T {
|
||||
}
|
||||
}
|
||||
|
||||
// Implementation of Default for various core types
|
||||
|
||||
macro_rules! delegate(($ty:ty to $other:ident) => {
|
||||
impl<'self> Default for $ty {
|
||||
fn fmt(me: &$ty, f: &mut Formatter) {
|
||||
$other::fmt(me, f)
|
||||
}
|
||||
}
|
||||
})
|
||||
delegate!(int to Signed)
|
||||
delegate!( i8 to Signed)
|
||||
delegate!(i16 to Signed)
|
||||
delegate!(i32 to Signed)
|
||||
delegate!(i64 to Signed)
|
||||
delegate!(uint to Unsigned)
|
||||
delegate!( u8 to Unsigned)
|
||||
delegate!( u16 to Unsigned)
|
||||
delegate!( u32 to Unsigned)
|
||||
delegate!( u64 to Unsigned)
|
||||
delegate!(@str to String)
|
||||
delegate!(~str to String)
|
||||
delegate!(&'self str to String)
|
||||
delegate!(bool to Bool)
|
||||
delegate!(char to Char)
|
||||
delegate!(float to Float)
|
||||
delegate!(f32 to Float)
|
||||
delegate!(f64 to Float)
|
||||
|
||||
impl<T> Default for *const T {
|
||||
fn fmt(me: &*const T, f: &mut Formatter) { Pointer::fmt(me, f) }
|
||||
}
|
||||
|
||||
// If you expected tests to be here, look instead at the run-pass/ifmt.rs test,
|
||||
// it's a lot easier than creating all of the rt::Piece structures here.
|
||||
|
@ -339,7 +339,11 @@ impl<'self> Parser<'self> {
|
||||
}
|
||||
}
|
||||
// Finally the actual format specifier
|
||||
spec.ty = self.word();
|
||||
if self.consume('?') {
|
||||
spec.ty = "?";
|
||||
} else {
|
||||
spec.ty = self.word();
|
||||
}
|
||||
return spec;
|
||||
}
|
||||
|
||||
|
@ -623,19 +623,16 @@ impl Context {
|
||||
|
||||
fn format_arg(&self, sp: span, arg: Either<uint, @str>,
|
||||
ident: ast::ident) -> @ast::expr {
|
||||
let mut ty = match arg {
|
||||
let ty = match arg {
|
||||
Left(i) => self.arg_types[i].unwrap(),
|
||||
Right(s) => *self.name_types.get(&s)
|
||||
};
|
||||
// Default types to '?' if nothing else is specified.
|
||||
if ty == Unknown {
|
||||
ty = Known(@"?");
|
||||
}
|
||||
|
||||
let argptr = self.ecx.expr_addr_of(sp, self.ecx.expr_ident(sp, ident));
|
||||
match ty {
|
||||
let fmt_trait = match ty {
|
||||
Unknown => "Default",
|
||||
Known(tyname) => {
|
||||
let fmt_trait = match tyname.as_slice() {
|
||||
match tyname.as_slice() {
|
||||
"?" => "Poly",
|
||||
"b" => "Bool",
|
||||
"c" => "Char",
|
||||
@ -653,35 +650,35 @@ impl Context {
|
||||
`%s`", tyname));
|
||||
"Dummy"
|
||||
}
|
||||
};
|
||||
let format_fn = self.ecx.path_global(sp, ~[
|
||||
self.ecx.ident_of("std"),
|
||||
self.ecx.ident_of("fmt"),
|
||||
self.ecx.ident_of(fmt_trait),
|
||||
self.ecx.ident_of("fmt"),
|
||||
]);
|
||||
self.ecx.expr_call_global(sp, ~[
|
||||
self.ecx.ident_of("std"),
|
||||
self.ecx.ident_of("fmt"),
|
||||
self.ecx.ident_of("argument"),
|
||||
], ~[self.ecx.expr_path(format_fn), argptr])
|
||||
}
|
||||
}
|
||||
String => {
|
||||
self.ecx.expr_call_global(sp, ~[
|
||||
return self.ecx.expr_call_global(sp, ~[
|
||||
self.ecx.ident_of("std"),
|
||||
self.ecx.ident_of("fmt"),
|
||||
self.ecx.ident_of("argumentstr"),
|
||||
], ~[argptr])
|
||||
}
|
||||
Unsigned => {
|
||||
self.ecx.expr_call_global(sp, ~[
|
||||
return self.ecx.expr_call_global(sp, ~[
|
||||
self.ecx.ident_of("std"),
|
||||
self.ecx.ident_of("fmt"),
|
||||
self.ecx.ident_of("argumentuint"),
|
||||
], ~[argptr])
|
||||
}
|
||||
Unknown => { fail!() }
|
||||
}
|
||||
};
|
||||
|
||||
let format_fn = self.ecx.path_global(sp, ~[
|
||||
self.ecx.ident_of("std"),
|
||||
self.ecx.ident_of("fmt"),
|
||||
self.ecx.ident_of(fmt_trait),
|
||||
self.ecx.ident_of("fmt"),
|
||||
]);
|
||||
self.ecx.expr_call_global(sp, ~[
|
||||
self.ecx.ident_of("std"),
|
||||
self.ecx.ident_of("fmt"),
|
||||
self.ecx.ident_of("argument"),
|
||||
], ~[self.ecx.expr_path(format_fn), argptr])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,16 +25,36 @@ pub fn main() {
|
||||
macro_rules! t(($a:expr, $b:expr) => { assert_eq!($a, $b.to_owned()) })
|
||||
|
||||
// Make sure there's a poly formatter that takes anything
|
||||
t!(ifmt!("{}", 1), "1");
|
||||
t!(ifmt!("{}", A), "{}");
|
||||
t!(ifmt!("{}", ()), "()");
|
||||
t!(ifmt!("{}", @(~1, "foo")), "@(~1, \"foo\")");
|
||||
t!(ifmt!("{:?}", 1), "1");
|
||||
t!(ifmt!("{:?}", A), "{}");
|
||||
t!(ifmt!("{:?}", ()), "()");
|
||||
t!(ifmt!("{:?}", @(~1, "foo")), "@(~1, \"foo\")");
|
||||
|
||||
// Various edge cases without formats
|
||||
t!(ifmt!(""), "");
|
||||
t!(ifmt!("hello"), "hello");
|
||||
t!(ifmt!("hello \\{"), "hello {");
|
||||
|
||||
// default formatters should work
|
||||
t!(ifmt!("{}", 1i), "1");
|
||||
t!(ifmt!("{}", 1i8), "1");
|
||||
t!(ifmt!("{}", 1i16), "1");
|
||||
t!(ifmt!("{}", 1i32), "1");
|
||||
t!(ifmt!("{}", 1i64), "1");
|
||||
t!(ifmt!("{}", 1u), "1");
|
||||
t!(ifmt!("{}", 1u8), "1");
|
||||
t!(ifmt!("{}", 1u16), "1");
|
||||
t!(ifmt!("{}", 1u32), "1");
|
||||
t!(ifmt!("{}", 1u64), "1");
|
||||
t!(ifmt!("{}", 1.0f), "1");
|
||||
t!(ifmt!("{}", 1.0f32), "1");
|
||||
t!(ifmt!("{}", 1.0f64), "1");
|
||||
t!(ifmt!("{}", "a"), "a");
|
||||
t!(ifmt!("{}", ~"a"), "a");
|
||||
t!(ifmt!("{}", @"a"), "a");
|
||||
t!(ifmt!("{}", false), "false");
|
||||
t!(ifmt!("{}", 'a'), "a");
|
||||
|
||||
// At least exercise all the formats
|
||||
t!(ifmt!("{:b}", true), "true");
|
||||
t!(ifmt!("{:c}", '☃'), "☃");
|
||||
@ -56,7 +76,7 @@ pub fn main() {
|
||||
t!(ifmt!("{foo} {bar}", foo=0, bar=1), "0 1");
|
||||
t!(ifmt!("{foo} {1} {bar} {0}", 0, 1, foo=2, bar=3), "2 1 3 0");
|
||||
t!(ifmt!("{} {0:s}", "a"), "a a");
|
||||
t!(ifmt!("{} {0}", "a"), "\"a\" \"a\"");
|
||||
t!(ifmt!("{} {0}", "a"), "a a");
|
||||
|
||||
// Methods should probably work
|
||||
t!(ifmt!("{0, plural, =1{a#} =2{b#} zero{c#} other{d#}}", 0u), "c0");
|
||||
|
Loading…
Reference in New Issue
Block a user