Long-standing branch to remove foreign function wrappers altogether. Calls to C functions are done "in place" with no stack manipulation; the scheme relies entirely on the correct use of `#[fixed_stack_segment]` to guarantee adequate stack space. A linter is added to detect when `#[fixed_stack_segment]` annotations are missing. An `externfn!` macro is added to make it easier to declare foreign fns and wrappers in one go: this macro may need some refinement, though, for example it might be good to be able to declare a group of foreign fns. I leave that for future work (hopefully somebody else's work :) ).
Fixes #3678.
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); }
}
}
-impl<'self> String for &'self str {
- fn fmt(s: & &'self str, f: &mut Formatter) {
- f.pad(*s);
+impl<'self, T: str::Str> String for T {
+ fn fmt(s: &T, f: &mut Formatter) {
+ f.pad(s.as_slice());
}
}
}
}
+// 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.
}
}
// Finally the actual format specifier
- spec.ty = self.word();
+ if self.consume('?') {
+ spec.ty = "?";
+ } else {
+ spec.ty = self.word();
+ }
return spec;
}
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",
`%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])
}
}
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}", '☃'), "☃");
t!(ifmt!("{:x}", 10u), "a");
t!(ifmt!("{:X}", 10u), "A");
t!(ifmt!("{:s}", "foo"), "foo");
+ t!(ifmt!("{:s}", ~"foo"), "foo");
+ t!(ifmt!("{:s}", @"foo"), "foo");
t!(ifmt!("{:p}", 0x1234 as *int), "0x1234");
t!(ifmt!("{:p}", 0x1234 as *mut int), "0x1234");
t!(ifmt!("{:d}", A), "aloha");
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");