diff --git a/src/libcore/io.rs b/src/libcore/io.rs index 77b486ca44619..7d76d8d30cd36 100644 --- a/src/libcore/io.rs +++ b/src/libcore/io.rs @@ -10,7 +10,37 @@ /*! -Basic input/output +The `io` module contains basic input and output routines. + +A quick summary: + +## `Reader` and `Writer` traits + +These traits define the minimal set of methods that anything that can do +input and output should implement. + +## `ReaderUtil` and `WriterUtil` traits + +Richer methods that allow you to do more. `Reader` only lets you read a certain +number of bytes into a buffer, while `ReaderUtil` allows you to read a whole +line, for example. + +Generally, these richer methods are probably the ones you want to actually +use in day-to-day Rust. + +Furthermore, because there is an implementation of `ReaderUtil` for +``, when your input or output code implements `Reader`, you get +all of these methods for free. + +## `print` and `println` + +These very useful functions are defined here. You generally don't need to +import them, though, as the prelude already does. + +## `stdin`, `stdout`, and `stderr` + +These functions return references to the classic three file descriptors. They +implement `Reader` and `Writer`, where appropriate. */ @@ -1010,6 +1040,16 @@ pub fn FILE_reader(f: *libc::FILE, cleanup: bool) -> @Reader { // top-level functions that take a reader, or a set of default methods on // reader (which can then be called reader) +/** +* Gives a `Reader` that allows you to read values from standard input. +* +* # Examples +* ~~~ +* let stdin = core::io::stdin(); +* let line = stdin.read_line(); +* core::io::print(line); +* ~~~ +*/ pub fn stdin() -> @Reader { unsafe { @rustrt::rust_get_stdin() as @Reader @@ -1561,13 +1601,57 @@ pub fn buffered_file_writer(path: &Path) -> Result<@Writer, ~str> { // FIXME (#2004) it would be great if this could be a const // FIXME (#2004) why are these different from the way stdin() is // implemented? + + +/** +* Gives a `Writer` which allows you to write to the standard output. +* +* # Examples +* ~~~ +* let stdout = core::io::stdout(); +* stdout.write_str("hello\n"); +* ~~~ +*/ pub fn stdout() -> @Writer { fd_writer(libc::STDOUT_FILENO as c_int, false) } + +/** +* Gives a `Writer` which allows you to write to standard error. +* +* # Examples +* ~~~ +* let stderr = core::io::stderr(); +* stderr.write_str("hello\n"); +* ~~~ +*/ pub fn stderr() -> @Writer { fd_writer(libc::STDERR_FILENO as c_int, false) } +/** +* Prints a string to standard output. +* +* This string will not have an implicit newline at the end. If you want +* an implicit newline, please see `println`. +* +* # Examples +* ~~~ +* // print is imported into the prelude, and so is always available. +* print("hello"); +* ~~~ +*/ pub fn print(s: &str) { stdout().write_str(s); } +/** +* Prints a string to standard output, followed by a newline. +* +* If you do not want an implicit newline, please see `print`. +* +* # Examples +* ~~~ +* // println is imported into the prelude, and so is always available. +* println("hello"); +* ~~~ +*/ pub fn println(s: &str) { stdout().write_line(s); } diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index d06bf1480c989..9198991e5360e 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -9,7 +9,7 @@ // except according to those terms. use core::hashmap::HashMap; -use core::libc::c_uint; +use core::libc::{c_uint, c_ushort}; pub type Opcode = u32; pub type Bool = c_uint; @@ -221,7 +221,7 @@ pub mod llvm { use super::{SectionIteratorRef, TargetDataRef, TypeKind, TypeRef, UseRef}; use super::{ValueRef}; - use core::libc::{c_char, c_int, c_longlong, c_uint, c_ulonglong}; + use core::libc::{c_char, c_int, c_longlong, c_ushort, c_uint, c_ulonglong}; #[link_args = "-Lrustllvm -lrustllvm"] #[link_name = "rustllvm"] @@ -451,6 +451,10 @@ pub mod llvm { /* all zeroes */ #[fast_ffi] pub unsafe fn LLVMConstAllOnes(Ty: TypeRef) -> ValueRef; + #[fast_ffi] + pub unsafe fn LLVMConstICmp(Pred: c_ushort, V1: ValueRef, V2: ValueRef) -> ValueRef; + #[fast_ffi] + pub unsafe fn LLVMConstFCmp(Pred: c_ushort, V1: ValueRef, V2: ValueRef) -> ValueRef; /* only for int/vector */ #[fast_ffi] pub unsafe fn LLVMGetUndef(Ty: TypeRef) -> ValueRef; @@ -1914,6 +1918,16 @@ pub fn SetLinkage(Global: ValueRef, Link: Linkage) { } } +pub fn ConstICmp(Pred: IntPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef { + unsafe { + llvm::LLVMConstICmp(Pred as c_ushort, V1, V2) + } +} +pub fn ConstFCmp(Pred: RealPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef { + unsafe { + llvm::LLVMConstFCmp(Pred as c_ushort, V1, V2) + } +} /* Memory-managed object interface to type handles. */ pub struct TypeNames { diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 8c21998768e95..460da5d60b33f 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -386,8 +386,20 @@ fn encode_reexported_static_methods(ecx: @EncodeContext, match ecx.tcx.trait_methods_cache.find(&exp.def_id) { Some(methods) => { match ecx.tcx.items.find(&exp.def_id.node) { - Some(&ast_map::node_item(_, path)) => { - if mod_path != *path { + Some(&ast_map::node_item(item, path)) => { + let original_name = ecx.tcx.sess.str_of(item.ident); + + // + // We don't need to reexport static methods on traits + // declared in the same module as our `pub use ...` since + // that's done when we encode the trait item. + // + // The only exception is when the reexport *changes* the + // name e.g. `pub use Foo = self::Bar` -- we have + // encoded metadata for static methods relative to Bar, + // but not yet for Foo. + // + if mod_path != *path || *exp.name != *original_name { for methods.each |&m| { if m.explicit_self == ast::sty_static { encode_reexported_static_method(ecx, diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs index e08cc536a701f..22014fa330414 100644 --- a/src/librustc/middle/trans/consts.rs +++ b/src/librustc/middle/trans/consts.rs @@ -9,8 +9,11 @@ // except according to those terms. use back::abi; -use lib::llvm::{llvm, SetLinkage, PrivateLinkage, - ValueRef, TypeRef, Bool, True, False}; +use lib::llvm::{llvm, ConstFCmp, ConstICmp, SetLinkage, PrivateLinkage, ValueRef, TypeRef, Bool, + True, False}; +use lib::llvm::{IntEQ, IntNE, IntUGT, IntUGE, IntULT, IntULE, IntSGT, IntSGE, IntSLT, IntSLE, + RealOEQ, RealOGT, RealOGE, RealOLT, RealOLE, RealONE}; + use metadata::csearch; use middle::const_eval; use middle::trans::adt; @@ -280,8 +283,8 @@ fn const_expr_unadjusted(cx: @CrateContext, e: @ast::expr) -> ValueRef { else if signed { llvm::LLVMConstSRem(te1, te2) } else { llvm::LLVMConstURem(te1, te2) } } - ast::and | - ast::or => cx.sess.span_unimpl(e.span, "binop logic"), + ast::and => llvm::LLVMConstAnd(te1, te2), + ast::or => llvm::LLVMConstOr(te1, te2), ast::bitxor => llvm::LLVMConstXor(te1, te2), ast::bitand => llvm::LLVMConstAnd(te1, te2), ast::bitor => llvm::LLVMConstOr(te1, te2), @@ -290,14 +293,44 @@ fn const_expr_unadjusted(cx: @CrateContext, e: @ast::expr) -> ValueRef { if signed { llvm::LLVMConstAShr(te1, te2) } else { llvm::LLVMConstLShr(te1, te2) } } - ast::eq | - ast::lt | - ast::le | - ast::ne | - ast::ge | - ast::gt => cx.sess.span_unimpl(e.span, "binop comparator") - } - } + ast::eq => { + if is_float { ConstFCmp(RealOEQ, te1, te2) } + else { ConstICmp(IntEQ, te1, te2) } + }, + ast::lt => { + if is_float { ConstFCmp(RealOLT, te1, te2) } + else { + if signed { ConstICmp(IntSLT, te1, te2) } + else { ConstICmp(IntULT, te1, te2) } + } + }, + ast::le => { + if is_float { ConstFCmp(RealOLE, te1, te2) } + else { + if signed { ConstICmp(IntSLE, te1, te2) } + else { ConstICmp(IntULE, te1, te2) } + } + }, + ast::ne => { + if is_float { ConstFCmp(RealONE, te1, te2) } + else { ConstICmp(IntNE, te1, te2) } + }, + ast::ge => { + if is_float { ConstFCmp(RealOGE, te1, te2) } + else { + if signed { ConstICmp(IntSGE, te1, te2) } + else { ConstICmp(IntUGE, te1, te2) } + } + }, + ast::gt => { + if is_float { ConstFCmp(RealOGT, te1, te2) } + else { + if signed { ConstICmp(IntSGT, te1, te2) } + else { ConstICmp(IntUGT, te1, te2) } + } + }, + }; + }, ast::expr_unary(u, e) => { let te = const_expr(cx, e); let ty = ty::expr_ty(cx.tcx, e); diff --git a/src/libstd/arc.rs b/src/libstd/arc.rs index f0158acfa79fa..130deb38f3336 100644 --- a/src/libstd/arc.rs +++ b/src/libstd/arc.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,9 +8,33 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/** +/*! * Concurrency-enabled mechanisms for sharing mutable and/or immutable state * between tasks. + * + * # Example + * + * In this example, a large vector of floats is shared between several tasks. + * With simple pipes, without ARC, a copy would have to be made for each task. + * + * ~~~ + * extern mod std; + * use std::arc; + * let numbers=vec::from_fn(100, |ind| (ind as float)*rand::random()); + * let shared_numbers=arc::ARC(numbers); + * + * for 10.times { + * let (port, chan) = stream(); + * chan.send(shared_numbers.clone()); + * + * do spawn { + * let shared_numbers=port.recv(); + * let local_numbers=shared_numbers.get(); + * + * // Work with the local numbers + * } + * } + * ~~~ */ use sync; @@ -21,7 +45,7 @@ use core::unstable::sync::UnsafeAtomicRcBox; use core::ptr; use core::task; -/// As sync::condvar, a mechanism for unlock-and-descheduling and signalling. +/// As sync::condvar, a mechanism for unlock-and-descheduling and signaling. pub struct Condvar<'self> { is_mutex: bool, failed: &'self mut bool, @@ -93,9 +117,14 @@ pub fn ARC(data: T) -> ARC { * wrapper. */ pub fn get<'a, T:Const + Owned>(rc: &'a ARC) -> &'a T { - unsafe { &*rc.x.get_immut() } + rc.get() } +impl ARC { + pub fn get<'a>(&'a self) -> &'a T { + unsafe { &*self.x.get_immut() } + } +} /** * Duplicate an atomically reference counted wrapper. * @@ -501,13 +530,14 @@ mod tests { let arc_v = p.recv(); let v = copy *arc::get::<~[int]>(&arc_v); - assert_eq!(v[3], 4); + assert_eq!(v[3],4); }; let c = p.recv(); c.send(arc::clone(&arc_v)); assert_eq!((*arc::get(&arc_v))[2], 3); + assert_eq!(arc_v.get()[4], 5); info!(arc_v); } diff --git a/src/test/auxiliary/mod_trait_with_static_methods_lib.rs b/src/test/auxiliary/mod_trait_with_static_methods_lib.rs index 2099c6a2f2f2f..3591ff7931855 100644 --- a/src/test/auxiliary/mod_trait_with_static_methods_lib.rs +++ b/src/test/auxiliary/mod_trait_with_static_methods_lib.rs @@ -9,6 +9,15 @@ // except according to those terms. pub use sub_foo::Foo; +pub use Baz = self::Bar; + +pub trait Bar { + pub fn bar() -> Self; +} + +impl Bar for int { + pub fn bar() -> int { 84 } +} pub mod sub_foo { pub trait Foo { @@ -18,4 +27,5 @@ pub mod sub_foo { impl Foo for int { pub fn foo() -> int { 42 } } + } diff --git a/src/test/run-pass/const-binops.rs b/src/test/run-pass/const-binops.rs new file mode 100644 index 0000000000000..cd87ca3ab537e --- /dev/null +++ b/src/test/run-pass/const-binops.rs @@ -0,0 +1,116 @@ +static a: int = -4 + 3; +static a2: uint = 3 + 3; +static b: float = 3.0 + 2.7; + +static c: int = 3 - 4; +static d: uint = 3 - 3; +static e: float = 3.0 - 2.7; + +static e2: int = -3 * 3; +static f: uint = 3 * 3; +static g: float = 3.3 * 3.3; + +static h: int = 3 / -1; +static i: uint = 3 / 3; +static j: float = 3.3 / 3.3; + +static n: bool = true && false; + +static o: bool = true || false; + +static p: int = 3 & 1; +static q: uint = 1 & 3; + +static r: int = 3 | 1; +static s: uint = 1 | 3; + +static t: int = 3 ^ 1; +static u: uint = 1 ^ 3; + +static v: int = 1 << 3; + +// NOTE: better shr coverage +static w: int = 1024 >> 4; +static x: uint = 1024 >> 4; + +static y: bool = 1 == 1; +static z: bool = 1.0 == 1.0; + +static aa: bool = 1 <= 2; +static ab: bool = -1 <= 2; +static ac: bool = 1.0 <= 2.0; + +static ad: bool = 1 < 2; +static ae: bool = -1 < 2; +static af: bool = 1.0 < 2.0; + +static ag: bool = 1 != 2; +static ah: bool = -1 != 2; +static ai: bool = 1.0 != 2.0; + +static aj: bool = 2 >= 1; +static ak: bool = 2 >= -2; +static al: bool = 1.0 >= -2.0; + +static am: bool = 2 > 1; +static an: bool = 2 > -2; +static ao: bool = 1.0 > -2.0; + +fn main() { + assert_eq!(a, -1); + assert_eq!(a2, 6); + assert_approx_eq!(b, 5.7); + + assert_eq!(c, -1); + assert_eq!(d, 0); + assert_approx_eq!(e, 0.3); + + assert_eq!(e2, -9); + assert_eq!(f, 9); + assert_approx_eq!(g, 10.89); + + assert_eq!(h, -3); + assert_eq!(i, 1); + assert_approx_eq!(j, 1.0); + + assert_eq!(n, false); + + assert_eq!(o, true); + + assert_eq!(p, 1); + assert_eq!(q, 1); + + assert_eq!(r, 3); + assert_eq!(s, 3); + + assert_eq!(t, 2); + assert_eq!(u, 2); + + assert_eq!(v, 8); + + assert_eq!(w, 64); + assert_eq!(x, 64); + + assert_eq!(y, true); + assert_eq!(z, true); + + assert_eq!(aa, true); + assert_eq!(ab, true); + assert_eq!(ac, true); + + assert_eq!(ad, true); + assert_eq!(ae, true); + assert_eq!(af, true); + + assert_eq!(ag, true); + assert_eq!(ah, true); + assert_eq!(ai, true); + + assert_eq!(aj, true); + assert_eq!(ak, true); + assert_eq!(al, true); + + assert_eq!(am, true); + assert_eq!(an, true); + assert_eq!(ao, true); +} diff --git a/src/test/run-pass/trait_with_static_methods_cross_crate.rs b/src/test/run-pass/trait_with_static_methods_cross_crate.rs index 20dcbf3267b70..4402881c43ddd 100644 --- a/src/test/run-pass/trait_with_static_methods_cross_crate.rs +++ b/src/test/run-pass/trait_with_static_methods_cross_crate.rs @@ -13,7 +13,9 @@ extern mod mod_trait_with_static_methods_lib; use mod_trait_with_static_methods_lib::Foo; +use mod_trait_with_static_methods_lib::Baz; pub fn main() { assert_eq!(42, Foo::foo()); + assert_eq!(84, Baz::bar()); }