see [Continue expressions](#continue-expressions) for continue expressions.
~~~~~~~~{.ebnf .gram}
-loop_expr : "loop" [ ident ':' ] '{' block '}';
+loop_expr : [ lifetime ':' ] "loop" '{' block '}';
~~~~~~~~
A `loop` expression may optionally have a _label_.
### Break expressions
~~~~~~~~{.ebnf .gram}
-break_expr : "break" [ ident ];
+break_expr : "break" [ lifetime ];
~~~~~~~~
A `break` expression has an optional `label`.
### Continue expressions
~~~~~~~~{.ebnf .gram}
-continue_expr : "loop" [ ident ];
+continue_expr : "loop" [ lifetime ];
~~~~~~~~
A continue expression, written `loop`, also has an optional `label`.
An example of an `match` expression:
-~~~~
+~~~~ {.xfail-test}
# fn process_pair(a: int, b: int) { }
# fn process_ten() { }
For reference, the examples used here are also available as an [library on
GitHub](https://github.com/thestinger/rust-snappy).
+# Destructors
+
+Foreign libraries often hand off ownership of resources to the calling code,
+which should be wrapped in a destructor to provide safety and guarantee their
+release.
+
+A type with the same functionality as owned boxes can be implemented by
+wrapping `malloc` and `free`:
+
+~~~~
+use core::libc::{c_void, size_t, malloc, free};
+
+#[abi = "rust-intrinsic"]
+extern "rust-intrinsic" mod rusti {
+ fn init<T>() -> T;
+}
+
+// a wrapper around the handle returned by the foreign code
+pub struct Unique<T> {
+ priv ptr: *mut T
+}
+
+pub impl<'self, T: Owned> Unique<T> {
+ fn new(value: T) -> Unique<T> {
+ unsafe {
+ let ptr = malloc(core::sys::size_of::<T>() as size_t) as *mut T;
+ assert!(!ptr::is_null(ptr));
+ *ptr = value;
+ Unique{ptr: ptr}
+ }
+ }
+
+ // the 'self lifetime results in the same semantics as `&*x` with ~T
+ fn borrow(&self) -> &'self T {
+ unsafe { cast::transmute(self.ptr) }
+ }
+
+ // the 'self lifetime results in the same semantics as `&mut *x` with ~T
+ fn borrow_mut(&mut self) -> &'self mut T {
+ unsafe { cast::transmute(self.ptr) }
+ }
+}
+
+#[unsafe_destructor]
+impl<T: Owned> Drop for Unique<T> {
+ fn finalize(&self) {
+ unsafe {
+ let mut x = rusti::init(); // dummy value to swap in
+ x <-> *self.ptr; // moving the object out is needed to call the destructor
+ free(self.ptr as *c_void)
+ }
+ }
+}
+
+// A comparison between the built-in ~ and this reimplementation
+fn main() {
+ {
+ let mut x = ~5;
+ *x = 10;
+ } // `x` is freed here
+
+ {
+ let mut y = Unique::new(5);
+ *y.borrow_mut() = 10;
+ } // `y` is freed here
+}
+~~~~
+
# Linking
In addition to the `#[link_args]` attribute for explicitly passing arguments to the linker, an
# Destructors
-C-style resource management requires the programmer to match every allocation
-with a free, which means manually tracking the responsibility for cleaning up
-(the owner). Correctness is left to the programmer, and it's easy to get wrong.
+A *destructor* is a function responsible for cleaning up the resources used by
+an object when it is no longer accessible. Destructors can be defined to handle
+the release of resources like files, sockets and heap memory.
-The following code demonstrates manual memory management, in order to contrast
-it with Rust's resource management. Rust enforces safety, so the `unsafe`
-keyword is used to explicitly wrap the unsafe code. The keyword is a promise to
-the compiler that unsafety does not leak outside of the unsafe block, and is
-used to create safe concepts on top of low-level code.
+Objects are never accessible after their destructor has been called, so there
+are no dynamic failures from accessing freed resources. When a task fails, the
+destructors of all objects in the task are called.
-~~~~
-use core::libc::{calloc, free, size_t};
-
-fn main() {
- unsafe {
- let a = calloc(1, int::bytes as size_t);
-
- let d;
+The `~` sigil represents a unique handle for a memory allocation on the heap:
- {
- let b = calloc(1, int::bytes as size_t);
-
- let c = calloc(1, int::bytes as size_t);
- d = c; // move ownership to d
-
- free(b);
- }
-
- free(d);
- free(a);
- }
-}
~~~~
-
-Rust uses destructors to handle the release of resources like memory
-allocations, files and sockets. An object will only be destroyed when there is
-no longer any way to access it, which prevents dynamic failures from an attempt
-to use a freed resource. When a task fails, the stack unwinds and the
-destructors of all objects owned by that task are called.
-
-The unsafe code from above can be contained behind a safe API that prevents
-memory leaks or use-after-free:
-
-~~~~
-use core::libc::{calloc, free, c_void, size_t};
-
-struct Blob { priv ptr: *c_void }
-
-impl Blob {
- fn new() -> Blob {
- unsafe { Blob{ptr: calloc(1, int::bytes as size_t)} }
- }
-}
-
-impl Drop for Blob {
- fn finalize(&self) {
- unsafe { free(self.ptr); }
- }
-}
-
-fn main() {
- let a = Blob::new();
-
- let d;
-
- {
- let b = Blob::new();
-
- let c = Blob::new();
- d = c; // move ownership to d
-
- // b is destroyed here
- }
-
- // d is destroyed here
- // a is destroyed here
+{
+ // an integer allocated on the heap
+ let y = ~10;
}
+// the destructor frees the heap memory as soon as `y` goes out of scope
~~~~
-This pattern is common enough that Rust includes dynamically allocated memory
-as first-class types (`~` and `@`). Non-memory resources like files are cleaned
-up with custom destructors.
-
-~~~~
-fn main() {
- let a = ~0;
-
- let d;
-
- {
- let b = ~0;
-
- let c = ~0;
- d = c; // move ownership to d
-
- // b is destroyed here
- }
-
- // d is destroyed here
- // a is destroyed here
-}
-~~~~
+Rust includes syntax for heap memory allocation in the language since it's
+commonly used, but the same semantics can be implemented by a type with a
+custom destructor.
# Ownership
the garbage collector starts a new ownership tree, and the destructor is called
when it is collected.
+~~~~
+// the struct owns the objects contained in the `x` and `y` fields
+struct Foo { x: int, y: ~int }
+
+{
+ // `a` is the owner of the struct, and thus the owner of the struct's fields
+ let a = Foo { x: 5, y: ~10 };
+}
+// when `a` goes out of scope, the destructor for the `~int` in the struct's
+// field is called
+
+// `b` is mutable, and the mutability is inherited by the objects it owns
+let mut b = Foo { x: 5, y: ~10 };
+b.x = 10;
+~~~~
+
If an object doesn't contain garbage-collected boxes, it consists of a single
ownership tree and is given the `Owned` trait which allows it to be sent
between tasks. Custom destructors can only be implemented directly on types
## Owned boxes
An owned box (`~`) is a uniquely owned allocation on the heap. It inherits the
-mutability and lifetime of the owner as it would if there was no box.
+mutability and lifetime of the owner as it would if there was no box:
~~~~
let x = 5; // immutable
The purpose of an owned box is to add a layer of indirection in order to create
recursive data structures or cheaply pass around an object larger than a
-pointer. Since an owned box has a unique owner, it can be used to represent any
-tree data structure.
+pointer. Since an owned box has a unique owner, it can only be used to
+represent a tree data structure.
The following struct won't compile, because the lack of indirection would mean
it has an infinite size:
c = b; // error
~~~~
-
# Move semantics
Rust uses a shallow copy for parameter passing, assignment and returning values
impl Drop for TimeBomb {
fn finalize(&self) {
- for iter::repeat(self.explosivity) {
+ for old_iter::repeat(self.explosivity) {
io::println("blam!");
}
}
`T` as an explicit type parameter for `len`, in either the trait or
the impl, would be a compile-time error.
-Within a trait definition, `self` is a special type that you can think
+Within a trait definition, `Self` is a special type that you can think
of as a type parameter. An implementation of the trait for any given
-type `T` replaces the `self` type parameter with `T`. Simply, in a
-trait, `self` is a type, and in an impl, `self` is a value. The
-following trait describes types that support an equality operation:
+type `T` replaces the `Self` type parameter with `T`. The following
+trait describes types that support an equality operation:
~~~~
// In a trait, `self` refers to the self argument.
~~~~
Notice that in the trait definition, `equals` takes a
-second parameter of type `self`.
+second parameter of type `Self`.
In contrast, in the `impl`, `equals` takes a second parameter of
type `int`, only using `self` as the name of the receiver.
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
#[deriving(Eq)]
pub enum mode {
mode_compile_fail,
#[crate_type = "bin"];
-#[no_core];
-
#[allow(vecs_implicitly_copyable)];
#[allow(non_camel_case_types)];
#[allow(deprecated_mode)];
#[allow(deprecated_pattern)];
-extern mod core(vers = "0.7-pre");
extern mod std(vers = "0.7-pre");
use core::*;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
-use core::io;
-use core::io::ReaderUtil;
-use core::str;
-
pub struct ExpectedError { line: uint, kind: ~str, msg: ~str }
// Load any test directives embedded in the file
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use common;
use common::config;
-use core::io::ReaderUtil;
-use core::io;
-use core::os;
-use core::str;
-
pub struct TestProps {
// Lines that should be expected, in order, on standard out
error_patterns: ~[~str],
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-use core::io::{ReaderUtil, WriterUtil};
-use core::io;
use core::libc::c_int;
-use core::os;
use core::run::spawn_process;
use core::run;
-use core::str;
-use core::task;
#[cfg(target_os = "win32")]
fn target_env(lib_path: ~str, prog: ~str) -> ~[(~str,~str)] {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use common::mode_run_pass;
use common::mode_run_fail;
use common::mode_compile_fail;
use util;
use util::logv;
-use core::io::WriterUtil;
-use core::io;
-use core::os;
-use core::str;
-use core::uint;
-use core::vec;
-
pub fn run(config: config, testfile: ~str) {
if config.verbose {
// We're going to be dumping a lot of info. Start on a new line.
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use common::config;
-use core::io;
use core::os::getenv;
pub fn make_new_path(path: ~str) -> ~str {
:require 'rust-mode
:group 'rust-mode)
-(defvar rust-indent-unit 4)
+(defcustom rust-indent-unit 4
+ "Amount of offset per level of indentation"
+ :type 'integer
+ :require 'rust-mode
+ :group 'rust-mode)
+
(defvar rust-syntax-table (let ((table (make-syntax-table)))
(c-populate-syntax-table table)
table))
...
}
-{
- enum-instruction-scheduling-1
- Memcheck:Cond
- fun:*fold_mod*
- ...
-}
-
-{
- enum-instruction-scheduling-2
- Memcheck:Cond
- fun:*fold_nmod*
- ...
-}
-
-{
- enum-instruction-scheduling-3
- Memcheck:Cond
- fun:*fold_crate*
- ...
-}
-
-{
- enum-instruction-scheduling-4
- Memcheck:Cond
- fun:*fold_enum*
- ...
-}
-
-{
- enum-instruction-scheduling-5
- Memcheck:Cond
- fun:*write_variant*
- ...
-}
-
-{
- enum-instruction-scheduling-6
- Memcheck:Cond
- fun:*merge_method_attrs*
- ...
-}
-
-{
- enum-instruction-scheduling-7
- Memcheck:Cond
- fun:*parse_config_*
- ...
-}
-
-{
- enum-instruction-scheduling-8
- Memcheck:Cond
- fun:*should_set_output_format_to_markdown_if_requested*
- ...
-}
-
-{
- enum-instruction-scheduling-9
- Memcheck:Cond
- fun:*get_authority*
- ...
-}
-
-{
- enum-instruction-scheduling-10
- Memcheck:Cond
- fun:*config_from_opts*
- ...
-}
-
{
llvm-user-new-leak
Memcheck:Leak
}
{
- llvm-optimization-reads-uninitialized-memory-1
- Memcheck:Cond
- fun:_ZN4test17run_tests_console4anon13expr_fn*
- ...
-}
-
-{
- llvm-optimization-reads-uninitialized-memory-2
- Memcheck:Cond
- fun:_ZN4test17run_tests_console*
- ...
-}
-
-{
- llvm-optimization-reads-uninitialized-memory-3
- Memcheck:Cond
- fun:_ZN4test9run_tests*
- ...
-}
-
-{
- llvm-optimization-reads-uninitialized-memory-4
- Memcheck:Cond
- fun:_ZN5parse6parser14__extensions__10meth_*parse_item_fn*
- ...
-}
-
-{
- llvm-optimization-reads-uninitialized-memory-5
- Memcheck:Cond
- fun:_ZN4fold25noop_fold_item_underscore*
- ...
-}
-
-{
- llvm-optimization-reads-uninitialized-memory-6
- Memcheck:Cond
- fun:_ZN5parse6parser14__extensions__10meth_*parse_item_fn17*
- ...
-}
-
-{
- llvm-optimization-reads-uninitialized-memory-9
- Memcheck:Cond
- fun:_ZN5parse6parser14__extensions__10meth_*parse_item_foreign_fn*
- ...
-}
-
-{
- llvm-optimization-reads-uninitialized-memory-11
- Memcheck:Cond
- fun:_ZN4fold22noop_fold_foreign_item17_*
- ...
-}
-
-
-{
- llvm-optimization-reads-uninitialized-memory-12
- Memcheck:Cond
- fun:_ZN5parse6parser14__extensions__10meth_*parse_item_struct*
- ...
-}
-
-{
- llvm-optimization-reads-uninitialized-memory-13
- Memcheck:Cond
- fun:_ZN5parse6parser14__extensions__10meth_*parse_item_type*
- ...
-}
-
-{
- llvm-optimization-reads-uninitialized-memory-14
- Memcheck:Cond
- fun:_ZN7ast_map6map_fn16_*
- fun:_ZN5visit30visit_struct_dtor_helper_*
- obj:*
- fun:_ZN8unstable6extfmt2rt14__extensions__10meth_*
- ...
-}
-
-{
- llvm-optimization-reads-uninitialized-memory-15
- Memcheck:Cond
- fun:_ZN7ast_map6map_fn16_*
- fun:_ZN5visit30visit_struct_dtor_helper_*
- ...
-}
-
-{
- llvm-optimization-reads-uninitialized-memory-16
+ goddammit-llvm-why-u-no-valgrind
Memcheck:Cond
- fun:_ZN7ast_map6map_fn*
- fun:_ZN5visit30visit_struct_dtor_helper*
+ fun:*
...
}
use cast::transmute;
use kinds::Copy;
-use iter;
+use old_iter;
use option::Option;
-use ptr::addr_of;
use sys;
use uint;
use vec;
#[inline(always)]
pub fn capacity<T>(v: @[T]) -> uint {
unsafe {
- let repr: **raw::VecRepr =
- ::cast::transmute(addr_of(&v));
+ let repr: **raw::VecRepr = transmute(&v);
(**repr).unboxed.alloc / sys::size_of::<T>()
}
}
* Creates an immutable vector of size `n_elts` and initializes the elements
* to the value returned by the function `op`.
*/
-pub fn from_fn<T>(n_elts: uint, op: iter::InitOp<T>) -> @[T] {
+pub fn from_fn<T>(n_elts: uint, op: old_iter::InitOp<T>) -> @[T] {
do build_sized(n_elts) |push| {
let mut i: uint = 0u;
while i < n_elts { push(op(i)); i += 1u; }
pub mod raw {
use at_vec::{capacity, rustrt};
- use cast::transmute;
+ use cast::{transmute, transmute_copy};
use libc;
- use unstable::intrinsics::{move_val_init};
- use ptr::addr_of;
use ptr;
use sys;
use uint;
+ use unstable::intrinsics::{move_val_init};
use vec;
pub type VecRepr = vec::raw::VecRepr;
*/
#[inline(always)]
pub unsafe fn set_len<T>(v: @[T], new_len: uint) {
- let repr: **mut VecRepr = ::cast::transmute(addr_of(&v));
+ let repr: **mut VecRepr = transmute(&v);
(**repr).unboxed.fill = new_len * sys::size_of::<T>();
}
#[inline(always)]
pub unsafe fn push<T>(v: &mut @[T], initval: T) {
- let repr: **VecRepr = ::cast::reinterpret_cast(&v);
+ let repr: **VecRepr = transmute_copy(&v);
let fill = (**repr).unboxed.fill;
if (**repr).unboxed.alloc > fill {
push_fast(v, initval);
- }
- else {
+ } else {
push_slow(v, initval);
}
}
let repr: **mut VecRepr = ::cast::transmute(v);
let fill = (**repr).unboxed.fill;
(**repr).unboxed.fill += sys::size_of::<T>();
- let p = addr_of(&((**repr).unboxed.data));
+ let p = &((**repr).unboxed.data);
let p = ptr::offset(p, fill) as *mut T;
move_val_init(&mut(*p), initval);
}
//! Unsafe casting functions
+use sys;
+use unstable;
+
pub mod rusti {
#[abi = "rust-intrinsic"]
#[link_name = "rusti"]
pub extern "rust-intrinsic" {
fn forget<T>(+x: T);
+
+ #[cfg(stage0)]
fn reinterpret_cast<T, U>(&&e: T) -> U;
+
+ #[cfg(stage1)]
+ #[cfg(stage2)]
+ #[cfg(stage3)]
+ fn transmute<T,U>(e: T) -> U;
}
}
/// Casts the value at `src` to U. The two types must have the same length.
#[inline(always)]
+#[cfg(stage0)]
pub unsafe fn reinterpret_cast<T, U>(src: &T) -> U {
rusti::reinterpret_cast(*src)
}
+/// Unsafely copies and casts the value at `src` to U, even if the value is
+/// noncopyable. The two types must have the same length.
+#[inline(always)]
+#[cfg(stage0)]
+pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
+ rusti::reinterpret_cast(*src)
+}
+
+#[inline(always)]
+#[cfg(stage1)]
+#[cfg(stage2)]
+#[cfg(stage3)]
+pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
+ let mut dest: U = unstable::intrinsics::init();
+ {
+ let dest_ptr: *mut u8 = rusti::transmute(&mut dest);
+ let src_ptr: *u8 = rusti::transmute(src);
+ unstable::intrinsics::memmove64(dest_ptr,
+ src_ptr,
+ sys::size_of::<U>() as u64);
+ }
+ dest
+}
+
/**
* Move a thing into the void
*
* assert!(transmute("L") == ~[76u8, 0u8]);
*/
#[inline(always)]
+#[cfg(stage0)]
pub unsafe fn transmute<L, G>(thing: L) -> G {
let newthing: G = reinterpret_cast(&thing);
forget(thing);
newthing
}
+#[inline(always)]
+#[cfg(stage1)]
+#[cfg(stage2)]
+#[cfg(stage3)]
+pub unsafe fn transmute<L, G>(thing: L) -> G {
+ rusti::transmute(thing)
+}
+
/// Coerce an immutable reference to be mutable.
#[inline(always)]
pub unsafe fn transmute_mut<'a,T>(ptr: &'a T) -> &'a mut T { transmute(ptr) }
#[cfg(test)]
mod tests {
- use cast::{bump_box_refcount, reinterpret_cast, transmute};
+ use cast::{bump_box_refcount, transmute};
#[test]
+ #[cfg(stage0)]
fn test_reinterpret_cast() {
- assert!(1u == unsafe { reinterpret_cast(&1) });
+ assert!(1u == unsafe { ::cast::reinterpret_cast(&1) });
+ }
+
+ #[test]
+ #[cfg(stage1)]
+ #[cfg(stage2)]
+ #[cfg(stage3)]
+ fn test_transmute_copy() {
+ assert!(1u == unsafe { ::cast::transmute_copy(&1) });
}
#[test]
let box = @~"box box box"; // refcount 1
bump_box_refcount(box); // refcount 2
let ptr: *int = transmute(box); // refcount 2
- let _box1: @~str = reinterpret_cast(&ptr);
- let _box2: @~str = reinterpret_cast(&ptr);
+ let _box1: @~str = ::cast::transmute_copy(&ptr);
+ let _box2: @~str = ::cast::transmute_copy(&ptr);
assert!(*_box1 == ~"box box box");
assert!(*_box2 == ~"box box box");
// Will destroy _box1 and _box2. Without the bump, this would
//! Utilities for manipulating the char type
+use cmp::Ord;
use option::{None, Option, Some};
use str;
use u32;
else { fail!(~"invalid character!") }
}
-/**
- * Compare two chars
- *
- * # Return value
- *
- * -1 if a < b, 0 if a == b, +1 if a > b
- */
-#[inline(always)]
-pub fn cmp(a: char, b: char) -> int {
- return if b > a { -1 }
- else if b < a { 1 }
- else { 0 }
-}
-
#[cfg(notest)]
impl Eq for char {
+ #[inline(always)]
fn eq(&self, other: &char) -> bool { (*self) == (*other) }
+ #[inline(always)]
fn ne(&self, other: &char) -> bool { (*self) != (*other) }
}
+#[cfg(notest)]
+impl Ord for char {
+ #[inline(always)]
+ fn lt(&self, other: &char) -> bool { *self < *other }
+ #[inline(always)]
+ fn le(&self, other: &char) -> bool { *self <= *other }
+ #[inline(always)]
+ fn gt(&self, other: &char) -> bool { *self > *other }
+ #[inline(always)]
+ fn ge(&self, other: &char) -> bool { *self >= *other }
+}
+
#[test]
fn test_is_lowercase() {
assert!(is_lowercase('a'));
totaleq_impl!(int)
totaleq_impl!(uint)
+totaleq_impl!(char)
+
#[deriving(Clone, Eq)]
pub enum Ordering { Less = -1, Equal = 0, Greater = 1 }
totalord_impl!(int)
totalord_impl!(uint)
+totalord_impl!(char)
+
pub fn cmp2<A:TotalOrd,B:TotalOrd>(
a1: &A, b1: &B,
a2: &A, b2: &B) -> Ordering
#[allow(non_camel_case_types)]
pub mod oneshot {
priv use core::kinds::Owned;
+ use ptr::to_unsafe_ptr;
pub fn init<T: Owned>() -> (client::Oneshot<T>, server::Oneshot<T>) {
pub use core::pipes::HasBuffer;
do ::core::pipes::entangle_buffer(buffer) |buffer, data| {
{
data.Oneshot.set_buffer(buffer);
- ::ptr::addr_of(&(data.Oneshot))
+ to_unsafe_ptr(&data.Oneshot)
}
}
}
}
/// The send end of a oneshot pipe.
-pub type ChanOne<T> = oneshot::client::Oneshot<T>;
+pub struct ChanOne<T> {
+ contents: oneshot::client::Oneshot<T>
+}
+
+impl<T> ChanOne<T> {
+ pub fn new(contents: oneshot::client::Oneshot<T>) -> ChanOne<T> {
+ ChanOne {
+ contents: contents
+ }
+ }
+}
+
/// The receive end of a oneshot pipe.
-pub type PortOne<T> = oneshot::server::Oneshot<T>;
+pub struct PortOne<T> {
+ contents: oneshot::server::Oneshot<T>
+}
+
+impl<T> PortOne<T> {
+ pub fn new(contents: oneshot::server::Oneshot<T>) -> PortOne<T> {
+ PortOne {
+ contents: contents
+ }
+ }
+}
/// Initialiase a (send-endpoint, recv-endpoint) oneshot pipe pair.
pub fn oneshot<T: Owned>() -> (PortOne<T>, ChanOne<T>) {
let (chan, port) = oneshot::init();
- (port, chan)
+ (PortOne::new(port), ChanOne::new(chan))
}
pub impl<T: Owned> PortOne<T> {
fn recv(self) -> T { recv_one(self) }
fn try_recv(self) -> Option<T> { try_recv_one(self) }
+ fn unwrap(self) -> oneshot::server::Oneshot<T> {
+ match self {
+ PortOne { contents: s } => s
+ }
+ }
}
pub impl<T: Owned> ChanOne<T> {
fn send(self, data: T) { send_one(self, data) }
fn try_send(self, data: T) -> bool { try_send_one(self, data) }
+ fn unwrap(self) -> oneshot::client::Oneshot<T> {
+ match self {
+ ChanOne { contents: s } => s
+ }
+ }
}
/**
* closed.
*/
pub fn recv_one<T: Owned>(port: PortOne<T>) -> T {
- let oneshot::send(message) = recv(port);
- message
+ match port {
+ PortOne { contents: port } => {
+ let oneshot::send(message) = recv(port);
+ message
+ }
+ }
}
/// Receive a message from a oneshot pipe unless the connection was closed.
pub fn try_recv_one<T: Owned> (port: PortOne<T>) -> Option<T> {
- let message = try_recv(port);
-
- if message.is_none() { None }
- else {
- let oneshot::send(message) = message.unwrap();
- Some(message)
+ match port {
+ PortOne { contents: port } => {
+ let message = try_recv(port);
+
+ if message.is_none() {
+ None
+ } else {
+ let oneshot::send(message) = message.unwrap();
+ Some(message)
+ }
+ }
}
}
/// Send a message on a oneshot pipe, failing if the connection was closed.
pub fn send_one<T: Owned>(chan: ChanOne<T>, data: T) {
- oneshot::client::send(chan, data);
+ match chan {
+ ChanOne { contents: chan } => oneshot::client::send(chan, data),
+ }
}
/**
* Send a message on a oneshot pipe, or return false if the connection was
* closed.
*/
-pub fn try_send_one<T: Owned>(chan: ChanOne<T>, data: T)
- -> bool {
- oneshot::client::try_send(chan, data).is_some()
+pub fn try_send_one<T: Owned>(chan: ChanOne<T>, data: T) -> bool {
+ match chan {
+ ChanOne { contents: chan } => {
+ oneshot::client::try_send(chan, data).is_some()
+ }
+ }
}
#[test]
fn test_oneshot() {
- let (c, p) = oneshot::init();
+ let (p, c) = oneshot();
- oneshot::client::send(c, ());
+ c.send(());
- recv_one(p)
+ p.recv()
}
#[test]
pub use ops::{Drop};
#[cfg(stage0)]
pub use ops::{Add, Sub, Mul, Div, Modulo, Neg, Not};
-#[cfg(stage1)]
-#[cfg(stage2)]
-#[cfg(stage3)]
+#[cfg(not(stage0))]
pub use ops::{Add, Sub, Mul, Quot, Rem, Neg, Not};
pub use ops::{BitAnd, BitOr, BitXor};
pub use ops::{Shl, Shr, Index};
pub use vec::{CopyableVector, ImmutableVector};
pub use vec::{ImmutableEqVector, ImmutableCopyableVector};
pub use vec::{OwnedVector, OwnedCopyableVector, MutableVector};
-pub use iter::{BaseIter, ExtendedIter, EqIter, CopyableIter};
-pub use iter::{CopyableOrderedIter, CopyableNonstrictIter, Times};
-pub use iter::{ExtendedMutableIter};
+pub use old_iter::{BaseIter, ExtendedIter, EqIter, CopyableIter};
+pub use old_iter::{CopyableOrderedIter, CopyableNonstrictIter};
+pub use old_iter::{ExtendedMutableIter};
+pub use iter::Times;
+
+pub use num::{Num, NumCast};
+pub use num::{Orderable, Signed, Unsigned, Round};
+pub use num::{Algebraic, Trigonometric, Exponential, Hyperbolic};
+pub use num::{Integer, Fractional, Real, RealExt};
+pub use num::{Bitwise, BitCount, Bounded};
+pub use num::{Primitive, Int, Float};
-pub use num::{Num, Signed, Unsigned, Natural, NumCast};
pub use ptr::Ptr;
pub use to_str::ToStr;
pub use clone::Clone;
#[path = "num/num.rs"]
pub mod num;
pub mod iter;
+pub mod old_iter;
pub mod iterator;
pub mod to_str;
pub mod to_bytes;
let res =
rustrt::tdefl_compress_mem_to_heap(b as *c_void,
len as size_t,
- ptr::addr_of(&outsz),
+ &outsz,
lz_norm);
assert!(res as int != 0);
let out = vec::raw::from_buf_raw(res as *u8,
let res =
rustrt::tinfl_decompress_mem_to_heap(b as *c_void,
len as size_t,
- ptr::addr_of(&outsz),
+ &outsz,
0);
assert!(res as int != 0);
let out = vec::raw::from_buf_raw(res as *u8,
// own stack roots on the stack anyway.
let sentinel_box = ~0;
let sentinel: **Word = if expect_sentinel() {
- cast::transmute(ptr::addr_of(&sentinel_box))
+ cast::transmute(&sentinel_box)
} else {
ptr::null()
};
use container::{Container, Mutable, Map, Set};
use cmp::{Eq, Equiv};
use hash::Hash;
-use iter::BaseIter;
+use old_iter::BaseIter;
use hash::Hash;
-use iter;
+use old_iter;
use option::{None, Option, Some};
use rand::RngUtil;
use rand;
/// Return true if the set has no elements in common with `other`.
/// This is equivalent to checking for an empty intersection.
fn is_disjoint(&self, other: &HashSet<T>) -> bool {
- iter::all(self, |v| !other.contains(v))
+ old_iter::all(self, |v| !other.contains(v))
}
/// Return true if the set is a subset of another
fn is_subset(&self, other: &HashSet<T>) -> bool {
- iter::all(self, |v| other.contains(v))
+ old_iter::all(self, |v| other.contains(v))
}
/// Return true if the set is a superset of another
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-/*!
+/*! Composable internal iterators
-The iteration traits and common implementation
+Internal iterators are functions implementing the protocol used by the `for` loop.
-*/
-
-use cmp::{Eq, Ord};
-use kinds::Copy;
-use option::{None, Option, Some};
-use vec;
+An internal iterator takes `fn(...) -> bool` as a parameter, with returning `false` used to signal
+breaking out of iteration. The adaptors in the module work with any such iterator, not just ones
+tied to specific traits. For example:
-/// A function used to initialize the elements of a sequence
-pub type InitOp<'self,T> = &'self fn(uint) -> T;
-
-pub trait BaseIter<A> {
- fn each(&self, blk: &fn(v: &A) -> bool);
- fn size_hint(&self) -> Option<uint>;
-}
+~~~~
+use core::iter::iter_to_vec;
+println(iter_to_vec(|f| uint::range(0, 20, f)).to_str());
+~~~~
-pub trait ReverseIter<A>: BaseIter<A> {
- fn each_reverse(&self, blk: &fn(&A) -> bool);
-}
+An external iterator object implementing the interface in the `iterator` module can be used as an
+internal iterator by calling the `advance` method. For example:
-pub trait MutableIter<A>: BaseIter<A> {
- fn each_mut(&mut self, blk: &fn(&mut A) -> bool);
-}
+~~~~
+use core::iterator::*;
-pub trait ExtendedIter<A> {
- fn eachi(&self, blk: &fn(uint, v: &A) -> bool);
- fn all(&self, blk: &fn(&A) -> bool) -> bool;
- fn any(&self, blk: &fn(&A) -> bool) -> bool;
- fn foldl<B>(&self, b0: B, blk: &fn(&B, &A) -> B) -> B;
- fn position(&self, f: &fn(&A) -> bool) -> Option<uint>;
- fn map_to_vec<B>(&self, op: &fn(&A) -> B) -> ~[B];
- fn flat_map_to_vec<B,IB: BaseIter<B>>(&self, op: &fn(&A) -> IB) -> ~[B];
+let xs = [0u, 1, 2, 3, 4, 5];
+let ys = [30, 40, 50, 60];
+let mut it = xs.iter().chain(ys.iter());
+for it.advance |&x: &uint| {
+ println(x.to_str());
}
+~~~~
-pub trait ExtendedMutableIter<A> {
- fn eachi_mut(&mut self, blk: &fn(uint, &mut A) -> bool);
-}
+Internal iterators provide a subset of the functionality of an external iterator. It's not possible
+to interleave them to implement algorithms like `zip`, `union` and `merge`. However, they're often
+much easier to implement.
-pub trait EqIter<A:Eq> {
- fn contains(&self, x: &A) -> bool;
- fn count(&self, x: &A) -> uint;
-}
+*/
pub trait Times {
fn times(&self, it: &fn() -> bool);
}
-pub trait CopyableIter<A:Copy> {
- fn filter_to_vec(&self, pred: &fn(&A) -> bool) -> ~[A];
- fn to_vec(&self) -> ~[A];
- fn find(&self, p: &fn(&A) -> bool) -> Option<A>;
-}
-
-pub trait CopyableOrderedIter<A:Copy + Ord> {
- fn min(&self) -> A;
- fn max(&self) -> A;
-}
-
-pub trait CopyableNonstrictIter<A:Copy> {
- // Like "each", but copies out the value. If the receiver is mutated while
- // iterating over it, the semantics must not be memory-unsafe but are
- // otherwise undefined.
- fn each_val(&const self, f: &fn(A) -> bool);
-}
-
-// A trait for sequences that can be built by imperatively pushing elements
-// onto them.
-pub trait Buildable<A> {
- /**
- * Builds a buildable sequence by calling a provided function with
- * an argument function that pushes an element onto the back of
- * the sequence.
- * This version takes an initial size for the sequence.
- *
- * # Arguments
- *
- * * size - A hint for an initial size of the sequence
- * * builder - A function that will construct the sequence. It receives
- * as an argument a function that will push an element
- * onto the sequence being constructed.
- */
- fn build_sized(size: uint, builder: &fn(push: &fn(A))) -> Self;
-}
-
-#[inline(always)]
-pub fn eachi<A,IA:BaseIter<A>>(self: &IA, blk: &fn(uint, &A) -> bool) {
- let mut i = 0;
- for self.each |a| {
- if !blk(i, a) { break; }
- i += 1;
- }
-}
-
-#[inline(always)]
-pub fn all<A,IA:BaseIter<A>>(self: &IA, blk: &fn(&A) -> bool) -> bool {
- for self.each |a| {
- if !blk(a) { return false; }
- }
- return true;
-}
-
-#[inline(always)]
-pub fn any<A,IA:BaseIter<A>>(self: &IA, blk: &fn(&A) -> bool) -> bool {
- for self.each |a| {
- if blk(a) { return true; }
- }
- return false;
-}
-
-#[inline(always)]
-pub fn filter_to_vec<A:Copy,IA:BaseIter<A>>(self: &IA,
- prd: &fn(&A) -> bool)
- -> ~[A] {
- do vec::build_sized_opt(self.size_hint()) |push| {
- for self.each |a| {
- if prd(a) { push(*a); }
- }
- }
-}
-
-#[inline(always)]
-pub fn map_to_vec<A,B,IA:BaseIter<A>>(self: &IA, op: &fn(&A) -> B) -> ~[B] {
- do vec::build_sized_opt(self.size_hint()) |push| {
- for self.each |a| {
- push(op(a));
- }
- }
-}
-
-#[inline(always)]
-pub fn flat_map_to_vec<A,B,IA:BaseIter<A>,IB:BaseIter<B>>(self: &IA,
- op: &fn(&A) -> IB)
- -> ~[B] {
- do vec::build |push| {
- for self.each |a| {
- for op(a).each |&b| {
- push(b);
- }
- }
- }
-}
-
-#[inline(always)]
-pub fn foldl<A,B,IA:BaseIter<A>>(self: &IA, b0: B, blk: &fn(&B, &A) -> B)
- -> B {
- let mut b = b0;
- for self.each |a| {
- b = blk(&b, a);
- }
- b
-}
-
-#[inline(always)]
-pub fn to_vec<A:Copy,IA:BaseIter<A>>(self: &IA) -> ~[A] {
- map_to_vec(self, |&x| x)
-}
-
-#[inline(always)]
-pub fn contains<A:Eq,IA:BaseIter<A>>(self: &IA, x: &A) -> bool {
- for self.each |a| {
- if *a == *x { return true; }
- }
- return false;
-}
-
-#[inline(always)]
-pub fn count<A:Eq,IA:BaseIter<A>>(self: &IA, x: &A) -> uint {
- do foldl(self, 0) |count, value| {
- if *value == *x {
- *count + 1
- } else {
- *count
- }
- }
-}
-
-#[inline(always)]
-pub fn position<A,IA:BaseIter<A>>(self: &IA, f: &fn(&A) -> bool)
- -> Option<uint> {
- let mut i = 0;
- for self.each |a| {
- if f(a) { return Some(i); }
- i += 1;
- }
- return None;
-}
-
-// note: 'rposition' would only make sense to provide with a bidirectional
-// iter interface, such as would provide "reach" in addition to "each". As is,
-// it would have to be implemented with foldr, which is too inefficient.
-
-#[inline(always)]
-pub fn repeat(times: uint, blk: &fn() -> bool) {
- let mut i = 0;
- while i < times {
- if !blk() { break }
- i += 1;
- }
-}
-
-#[inline(always)]
-pub fn min<A:Copy + Ord,IA:BaseIter<A>>(self: &IA) -> A {
- match do foldl::<A,Option<A>,IA>(self, None) |a, b| {
- match a {
- &Some(ref a_) if *a_ < *b => {
- *(a)
- }
- _ => Some(*b)
- }
- } {
- Some(val) => val,
- None => fail!(~"min called on empty iterator")
- }
-}
-
-#[inline(always)]
-pub fn max<A:Copy + Ord,IA:BaseIter<A>>(self: &IA) -> A {
- match do foldl::<A,Option<A>,IA>(self, None) |a, b| {
- match a {
- &Some(ref a_) if *a_ > *b => {
- *(a)
- }
- _ => Some(*b)
- }
- } {
- Some(val) => val,
- None => fail!(~"max called on empty iterator")
- }
-}
-
-#[inline(always)]
-pub fn find<A:Copy,IA:BaseIter<A>>(self: &IA, f: &fn(&A) -> bool)
- -> Option<A> {
- for self.each |i| {
- if f(i) { return Some(*i) }
- }
- return None;
-}
-
-// Some functions for just building
-
/**
- * Builds a sequence by calling a provided function with an argument
- * function that pushes an element to the back of a sequence.
+ * Transform an internal iterator into an owned vector.
*
- * # Arguments
+ * # Example:
*
- * * builder - A function that will construct the sequence. It receives
- * as an argument a function that will push an element
- * onto the sequence being constructed.
+ * ~~~
+ * let xs = ~[1, 2, 3];
+ * let ys = do iter_to_vec |f| { xs.each(|x| f(*x)) };
+ * assert_eq!(xs, ys);
+ * ~~~
*/
#[inline(always)]
-pub fn build<A,B: Buildable<A>>(builder: &fn(push: &fn(A))) -> B {
- Buildable::build_sized(4, builder)
+pub fn iter_to_vec<T>(iter: &fn(f: &fn(T) -> bool)) -> ~[T] {
+ let mut v = ~[];
+ for iter |x| { v.push(x) }
+ v
}
/**
- * Builds a sequence by calling a provided function with an argument
- * function that pushes an element to the back of the sequence.
- * This version takes an initial size for the sequence.
+ * Return true if `predicate` is true for any values yielded by an internal iterator.
*
- * # Arguments
+ * Example:
*
- * * size - An option, maybe containing initial size of the sequence
- * to reserve.
- * * builder - A function that will construct the sequence. It receives
- * as an argument a function that will push an element
- * onto the sequence being constructed.
+ * ~~~~
+ * let xs = ~[1u, 2, 3, 4, 5];
+ * assert!(any(|&x: &uint| x > 2, |f| xs.each(f)));
+ * assert!(!any(|&x: &uint| x > 5, |f| xs.each(f)));
+ * ~~~~
*/
#[inline(always)]
-pub fn build_sized_opt<A,B: Buildable<A>>(size: Option<uint>,
- builder: &fn(push: &fn(A))) -> B {
- Buildable::build_sized(size.get_or_default(4), builder)
-}
-
-// Functions that combine iteration and building
-
-/// Applies a function to each element of an iterable and returns the results
-/// in a sequence built via `BU`. See also `map_to_vec`.
-#[inline(always)]
-pub fn map<T,IT: BaseIter<T>,U,BU: Buildable<U>>(v: &IT, f: &fn(&T) -> U)
- -> BU {
- do build_sized_opt(v.size_hint()) |push| {
- for v.each() |elem| {
- push(f(elem));
+pub fn any<T>(predicate: &fn(T) -> bool, iter: &fn(f: &fn(T) -> bool)) -> bool {
+ for iter |x| {
+ if predicate(x) {
+ return true
}
}
+ false
}
/**
- * Creates and initializes a generic sequence from a function.
+ * Return true if `predicate` is true for all values yielded by an internal iterator.
*
- * Creates a generic sequence of size `n_elts` and initializes the elements
- * to the value returned by the function `op`.
- */
-#[inline(always)]
-pub fn from_fn<T,BT: Buildable<T>>(n_elts: uint, op: InitOp<T>) -> BT {
- do Buildable::build_sized(n_elts) |push| {
- let mut i: uint = 0u;
- while i < n_elts { push(op(i)); i += 1u; }
- }
-}
-
-/**
- * Creates and initializes a generic sequence with some elements.
+ * # Example:
*
- * Creates an immutable vector of size `n_elts` and initializes the elements
- * to the value `t`.
+ * ~~~~
+ * assert!(all(|&x: &uint| x < 6, |f| uint::range(1, 6, f)));
+ * assert!(!all(|&x: &uint| x < 5, |f| uint::range(1, 6, f)));
+ * ~~~~
*/
#[inline(always)]
-pub fn from_elem<T:Copy,BT:Buildable<T>>(n_elts: uint, t: T) -> BT {
- do Buildable::build_sized(n_elts) |push| {
- let mut i: uint = 0;
- while i < n_elts { push(t); i += 1; }
+pub fn all<T>(predicate: &fn(T) -> bool, iter: &fn(f: &fn(T) -> bool)) -> bool {
+ for iter |x| {
+ if !predicate(x) {
+ return false
+ }
}
+ true
}
-/// Appends two generic sequences.
-#[inline(always)]
-pub fn append<T:Copy,IT:BaseIter<T>,BT:Buildable<T>>(lhs: &IT, rhs: &IT)
- -> BT {
- let size_opt = lhs.size_hint().chain_ref(
- |sz1| rhs.size_hint().map(|sz2| *sz1+*sz2));
- do build_sized_opt(size_opt) |push| {
- for lhs.each |x| { push(*x); }
- for rhs.each |x| { push(*x); }
- }
-}
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use prelude::*;
-/// Copies a generic sequence, possibly converting it to a different
-/// type of sequence.
-#[inline(always)]
-pub fn copy_seq<T:Copy,IT:BaseIter<T>,BT:Buildable<T>>(v: &IT) -> BT {
- do build_sized_opt(v.size_hint()) |push| {
- for v.each |x| { push(*x); }
+ #[test]
+ fn test_iter_to_vec() {
+ let xs = ~[1, 2, 3];
+ let ys = do iter_to_vec |f| { xs.each(|x| f(*x)) };
+ assert_eq!(xs, ys);
}
-}
-/**
- * Helper function to transform an internal iterator into an owned vector.
- *
- * # Example:
- *
- * ~~~
- * let v = ~[1, 2, 3];
- * let v2 = do iter_to_vec |f| { v.each(|e| f(*e)) };
- * if v != v2 { fail!() }
- * ~~~
- */
-#[inline(always)]
-pub fn iter_to_vec<T>(pusher: &fn(it: &fn(T) -> bool)) -> ~[T] {
- let mut v = ~[];
- let pushf = |e| {v.push(e); true};
- pusher(pushf);
- v
-}
+ #[test]
+ fn test_any() {
+ let xs = ~[1u, 2, 3, 4, 5];
+ assert!(any(|&x: &uint| x > 2, |f| xs.each(f)));
+ assert!(!any(|&x: &uint| x > 5, |f| xs.each(f)));
+ }
-#[test]
-fn test_iter_to_vec() {
- let v = ~[1, 2, 3];
- let v2 = do iter_to_vec |f| { v.each(|e| f(*e)) };
- if v != v2 { fail!() }
+ #[test]
+ fn test_all() {
+ assert!(all(|x: uint| x < 6, |f| uint::range(1, 6, f)));
+ assert!(!all(|x: uint| x < 5, |f| uint::range(1, 6, f)));
+ }
}
}
}
+pub struct ScanIterator<'self, A, B, T, St> {
+ priv iter: T,
+ priv f: &'self fn(&mut St, A) -> Option<B>,
+ state: St
+}
+
+impl<'self, A, B, T: Iterator<A>, St> Iterator<B> for ScanIterator<'self, A, B, T, St> {
+ #[inline]
+ fn next(&mut self) -> Option<B> {
+ self.iter.next().chain(|a| (self.f)(&mut self.state, a))
+ }
+}
+
pub struct UnfoldrIterator<'self, A, St> {
priv f: &'self fn(&mut St) -> Option<A>,
state: St
}
}
-pub struct ScanIterator<'self, A, B, T, St> {
- priv iter: T,
- priv f: &'self fn(&mut St, A) -> Option<B>,
- state: St
+/// An infinite iterator starting at `start` and advancing by `step` with each iteration
+pub struct Counter<A> {
+ state: A,
+ step: A
}
-impl<'self, A, B, T: Iterator<A>, St> Iterator<B> for ScanIterator<'self, A, B, T, St> {
- #[inline]
- fn next(&mut self) -> Option<B> {
- self.iter.next().chain(|a| (self.f)(&mut self.state, a))
+pub impl<A> Counter<A> {
+ #[inline(always)]
+ fn new(start: A, step: A) -> Counter<A> {
+ Counter{state: start, step: step}
+ }
+}
+
+impl<A: Add<A, A> + Clone> Iterator<A> for Counter<A> {
+ #[inline(always)]
+ fn next(&mut self) -> Option<A> {
+ let result = self.state.clone();
+ self.state = self.state.add(&self.step); // FIXME: #6050
+ Some(result)
}
}
use super::*;
use prelude::*;
+ #[test]
+ fn test_counter_to_vec() {
+ let mut it = Counter::new(0, 5).take(10);
+ let xs = iter::iter_to_vec(|f| it.advance(f));
+ assert_eq!(xs, ~[0, 5, 10, 15, 20, 25, 30, 35, 40, 45]);
+ }
+
#[test]
fn test_iterator_chain() {
let xs = [0u, 1, 2, 3, 4, 5];
//! Operations on managed box types
-use ptr;
+use ptr::to_unsafe_ptr;
#[cfg(notest)] use cmp::{Eq, Ord};
#[inline(always)]
pub fn ptr_eq<T>(a: @T, b: @T) -> bool {
//! Determine if two shared boxes point to the same object
- ptr::addr_of(&(*a)) == ptr::addr_of(&(*b))
+ let a_ptr: *T = to_unsafe_ptr(&*a), b_ptr: *T = to_unsafe_ptr(&*b);
+ a_ptr == b_ptr
}
#[inline(always)]
pub fn mut_ptr_eq<T>(a: @mut T, b: @mut T) -> bool {
//! Determine if two mutable shared boxes point to the same object
- ptr::addr_of(&(*a)) == ptr::addr_of(&(*b))
+ let a_ptr: *T = to_unsafe_ptr(&*a), b_ptr: *T = to_unsafe_ptr(&*b);
+ a_ptr == b_ptr
}
#[cfg(notest)]
unsafe fn fmax(a: c_double, b: c_double) -> c_double;
#[link_name="fmin"]
unsafe fn fmin(a: c_double, b: c_double) -> c_double;
- unsafe fn nextafter(x: c_double, y: c_double) -> c_double;
+ #[link_name="nextafter"]
+ unsafe fn next_after(x: c_double, y: c_double) -> c_double;
unsafe fn frexp(n: c_double, value: &mut c_int) -> c_double;
unsafe fn hypot(x: c_double, y: c_double) -> c_double;
unsafe fn ldexp(x: c_double, n: c_int) -> c_double;
#[link_name="fminf"]
unsafe fn fmin(a: c_float, b: c_float) -> c_float;
#[link_name="nextafterf"]
- unsafe fn nextafter(x: c_float, y: c_float) -> c_float;
+ unsafe fn next_after(x: c_float, y: c_float) -> c_float;
#[link_name="hypotf"]
unsafe fn hypot(x: c_float, y: c_float) -> c_float;
#[link_name="ldexpf"]
//! Operations and constants for `f32`
-use num::strconv;
-use num::Signed;
-use num;
-use option::Option;
use from_str;
-use to_str;
-
-#[cfg(notest)] use cmp::{Eq, Ord};
-#[cfg(stage0,notest)]
-use ops::{Add, Sub, Mul, Div, Modulo, Neg};
-#[cfg(stage1,notest)]
-#[cfg(stage2,notest)]
-#[cfg(stage3,notest)]
-use ops::{Add, Sub, Mul, Quot, Rem, Neg};
+use num::{Zero, One, strconv};
+use prelude::*;
pub use cmath::c_float_targ_consts::*;
fn abs_sub(a: c_float, b: c_float) -> c_float = c_float_utils::abs_sub,
fn fmax(a: c_float, b: c_float) -> c_float = c_float_utils::fmax,
fn fmin(a: c_float, b: c_float) -> c_float = c_float_utils::fmin,
- fn nextafter(x: c_float, y: c_float) -> c_float = c_float_utils::nextafter,
+ fn next_after(x: c_float, y: c_float) -> c_float = c_float_utils::next_after,
fn frexp(n: c_float, value: &mut c_int) -> c_float = c_float_utils::frexp,
fn hypot(x: c_float, y: c_float) -> c_float = c_float_utils::hypot,
fn ldexp(x: c_float, n: c_int) -> c_float = c_float_utils::ldexp,
fn sinh(n: c_float) -> c_float = c_float_utils::sinh,
fn tan(n: c_float) -> c_float = c_float_utils::tan,
fn tanh(n: c_float) -> c_float = c_float_utils::tanh,
- fn tgamma(n: c_float) -> c_float = c_float_utils::tgamma)
-
+ fn tgamma(n: c_float) -> c_float = c_float_utils::tgamma
+)
// These are not defined inside consts:: for consistency with
// the integer types
pub static neg_infinity: f32 = -1.0_f32/0.0_f32;
-#[inline(always)]
-pub fn is_NaN(f: f32) -> bool { f != f }
-
#[inline(always)]
pub fn add(x: f32, y: f32) -> f32 { return x + y; }
// FIXME (#1999): replace the predicates below with llvm intrinsics or
// calls to the libmath macros in the rust runtime for performance.
-/// Returns true if `x` is a zero number (positive or negative zero)
-#[inline(always)]
-pub fn is_zero(x: f32) -> bool {
- return x == 0.0f32 || x == -0.0f32;
-}
-
-/// Returns true if `x`is an infinite number
-#[inline(always)]
-pub fn is_infinite(x: f32) -> bool {
- return x == infinity || x == neg_infinity;
-}
-
-/// Returns true if `x`is a finite number
-#[inline(always)]
-pub fn is_finite(x: f32) -> bool {
- return !(is_NaN(x) || is_infinite(x));
-}
-
// FIXME (#1999): add is_normal, is_subnormal, and fpclassify.
/* Module: consts */
return log2(n) / log2(b);
}
+impl Num for f32 {}
+
#[cfg(notest)]
impl Eq for f32 {
#[inline(always)]
fn gt(&self, other: &f32) -> bool { (*self) > (*other) }
}
-impl num::Zero for f32 {
+impl Orderable for f32 {
+ /// Returns `NaN` if either of the numbers are `NaN`.
+ #[inline(always)]
+ fn min(&self, other: &f32) -> f32 {
+ if self.is_NaN() || other.is_NaN() { Float::NaN() } else { fmin(*self, *other) }
+ }
+
+ /// Returns `NaN` if either of the numbers are `NaN`.
+ #[inline(always)]
+ fn max(&self, other: &f32) -> f32 {
+ if self.is_NaN() || other.is_NaN() { Float::NaN() } else { fmax(*self, *other) }
+ }
+
+ /// Returns the number constrained within the range `mn <= self <= mx`.
+ /// If any of the numbers are `NaN` then `NaN` is returned.
+ #[inline(always)]
+ fn clamp(&self, mn: &f32, mx: &f32) -> f32 {
+ if self.is_NaN() { *self }
+ else if !(*self <= *mx) { *mx }
+ else if !(*self >= *mn) { *mn }
+ else { *self }
+ }
+}
+
+impl Zero for f32 {
#[inline(always)]
fn zero() -> f32 { 0.0 }
+
+ /// Returns true if the number is equal to either `0.0` or `-0.0`
+ #[inline(always)]
+ fn is_zero(&self) -> bool { *self == 0.0 || *self == -0.0 }
}
-impl num::One for f32 {
+impl One for f32 {
#[inline(always)]
fn one() -> f32 { 1.0 }
}
#[inline(always)]
fn div(&self, other: &f32) -> f32 { *self / *other }
}
-
-#[cfg(stage1,notest)]
-#[cfg(stage2,notest)]
-#[cfg(stage3,notest)]
+#[cfg(not(stage0),notest)]
impl Quot<f32,f32> for f32 {
#[inline(always)]
fn quot(&self, other: &f32) -> f32 { *self / *other }
#[inline(always)]
fn modulo(&self, other: &f32) -> f32 { *self % *other }
}
-
-#[cfg(stage1,notest)]
-#[cfg(stage2,notest)]
-#[cfg(stage3,notest)]
+#[cfg(not(stage0),notest)]
impl Rem<f32,f32> for f32 {
#[inline(always)]
fn rem(&self, other: &f32) -> f32 { *self % *other }
#[inline(always)]
fn abs(&self) -> f32 { abs(*self) }
- /**
- * # Returns
- *
- * - `1.0` if the number is positive, `+0.0` or `infinity`
- * - `-1.0` if the number is negative, `-0.0` or `neg_infinity`
- * - `NaN` if the number is `NaN`
- */
+ ///
+ /// # Returns
+ ///
+ /// - `1.0` if the number is positive, `+0.0` or `infinity`
+ /// - `-1.0` if the number is negative, `-0.0` or `neg_infinity`
+ /// - `NaN` if the number is NaN
+ ///
#[inline(always)]
fn signum(&self) -> f32 {
- if is_NaN(*self) { NaN } else { copysign(1.0, *self) }
+ if self.is_NaN() { NaN } else { copysign(1.0, *self) }
}
/// Returns `true` if the number is positive, including `+0.0` and `infinity`
fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == neg_infinity }
}
-impl num::Round for f32 {
+impl Round for f32 {
+ /// Round half-way cases toward `neg_infinity`
#[inline(always)]
- fn round(&self, mode: num::RoundMode) -> f32 {
- match mode {
- num::RoundDown => floor(*self),
- num::RoundUp => ceil(*self),
- num::RoundToZero if self.is_negative() => ceil(*self),
- num::RoundToZero => floor(*self),
- num::RoundFromZero if self.is_negative() => floor(*self),
- num::RoundFromZero => ceil(*self)
- }
+ fn floor(&self) -> f32 { floor(*self) }
+
+ /// Round half-way cases toward `infinity`
+ #[inline(always)]
+ fn ceil(&self) -> f32 { ceil(*self) }
+
+ /// Round half-way cases away from `0.0`
+ #[inline(always)]
+ fn round(&self) -> f32 { round(*self) }
+
+ /// The integer part of the number (rounds towards `0.0`)
+ #[inline(always)]
+ fn trunc(&self) -> f32 { trunc(*self) }
+
+ ///
+ /// The fractional part of the number, satisfying:
+ ///
+ /// ~~~
+ /// assert!(x == trunc(x) + fract(x))
+ /// ~~~
+ ///
+ #[inline(always)]
+ fn fract(&self) -> f32 { *self - self.trunc() }
+}
+
+impl Fractional for f32 {
+ /// The reciprocal (multiplicative inverse) of the number
+ #[inline(always)]
+ fn recip(&self) -> f32 { 1.0 / *self }
+}
+
+impl Algebraic for f32 {
+ #[inline(always)]
+ fn pow(&self, n: f32) -> f32 { pow(*self, n) }
+
+ #[inline(always)]
+ fn sqrt(&self) -> f32 { sqrt(*self) }
+
+ #[inline(always)]
+ fn rsqrt(&self) -> f32 { self.sqrt().recip() }
+
+ #[inline(always)]
+ fn cbrt(&self) -> f32 { cbrt(*self) }
+
+ #[inline(always)]
+ fn hypot(&self, other: f32) -> f32 { hypot(*self, other) }
+}
+
+impl Trigonometric for f32 {
+ #[inline(always)]
+ fn sin(&self) -> f32 { sin(*self) }
+
+ #[inline(always)]
+ fn cos(&self) -> f32 { cos(*self) }
+
+ #[inline(always)]
+ fn tan(&self) -> f32 { tan(*self) }
+
+ #[inline(always)]
+ fn asin(&self) -> f32 { asin(*self) }
+
+ #[inline(always)]
+ fn acos(&self) -> f32 { acos(*self) }
+
+ #[inline(always)]
+ fn atan(&self) -> f32 { atan(*self) }
+
+ #[inline(always)]
+ fn atan2(&self, other: f32) -> f32 { atan2(*self, other) }
+}
+
+impl Exponential for f32 {
+ #[inline(always)]
+ fn exp(&self) -> f32 { exp(*self) }
+
+ #[inline(always)]
+ fn exp2(&self) -> f32 { exp2(*self) }
+
+ #[inline(always)]
+ fn expm1(&self) -> f32 { expm1(*self) }
+
+ #[inline(always)]
+ fn log(&self) -> f32 { ln(*self) }
+
+ #[inline(always)]
+ fn log2(&self) -> f32 { log2(*self) }
+
+ #[inline(always)]
+ fn log10(&self) -> f32 { log10(*self) }
+}
+
+impl Hyperbolic for f32 {
+ #[inline(always)]
+ fn sinh(&self) -> f32 { sinh(*self) }
+
+ #[inline(always)]
+ fn cosh(&self) -> f32 { cosh(*self) }
+
+ #[inline(always)]
+ fn tanh(&self) -> f32 { tanh(*self) }
+}
+
+impl Real for f32 {
+ /// Archimedes' constant
+ #[inline(always)]
+ fn pi() -> f32 { 3.14159265358979323846264338327950288 }
+
+ /// 2.0 * pi
+ #[inline(always)]
+ fn two_pi() -> f32 { 6.28318530717958647692528676655900576 }
+
+ /// pi / 2.0
+ #[inline(always)]
+ fn frac_pi_2() -> f32 { 1.57079632679489661923132169163975144 }
+
+ /// pi / 3.0
+ #[inline(always)]
+ fn frac_pi_3() -> f32 { 1.04719755119659774615421446109316763 }
+
+ /// pi / 4.0
+ #[inline(always)]
+ fn frac_pi_4() -> f32 { 0.785398163397448309615660845819875721 }
+
+ /// pi / 6.0
+ #[inline(always)]
+ fn frac_pi_6() -> f32 { 0.52359877559829887307710723054658381 }
+
+ /// pi / 8.0
+ #[inline(always)]
+ fn frac_pi_8() -> f32 { 0.39269908169872415480783042290993786 }
+
+ /// 1 .0/ pi
+ #[inline(always)]
+ fn frac_1_pi() -> f32 { 0.318309886183790671537767526745028724 }
+
+ /// 2.0 / pi
+ #[inline(always)]
+ fn frac_2_pi() -> f32 { 0.636619772367581343075535053490057448 }
+
+ /// 2.0 / sqrt(pi)
+ #[inline(always)]
+ fn frac_2_sqrtpi() -> f32 { 1.12837916709551257389615890312154517 }
+
+ /// sqrt(2.0)
+ #[inline(always)]
+ fn sqrt2() -> f32 { 1.41421356237309504880168872420969808 }
+
+ /// 1.0 / sqrt(2.0)
+ #[inline(always)]
+ fn frac_1_sqrt2() -> f32 { 0.707106781186547524400844362104849039 }
+
+ /// Euler's number
+ #[inline(always)]
+ fn e() -> f32 { 2.71828182845904523536028747135266250 }
+
+ /// log2(e)
+ #[inline(always)]
+ fn log2_e() -> f32 { 1.44269504088896340735992468100189214 }
+
+ /// log10(e)
+ #[inline(always)]
+ fn log10_e() -> f32 { 0.434294481903251827651128918916605082 }
+
+ /// log(2.0)
+ #[inline(always)]
+ fn log_2() -> f32 { 0.693147180559945309417232121458176568 }
+
+ /// log(10.0)
+ #[inline(always)]
+ fn log_10() -> f32 { 2.30258509299404568401799145468436421 }
+
+ /// Converts to degrees, assuming the number is in radians
+ #[inline(always)]
+ fn to_degrees(&self) -> f32 { *self * (180.0 / Real::pi::<f32>()) }
+
+ /// Converts to radians, assuming the number is in degrees
+ #[inline(always)]
+ fn to_radians(&self) -> f32 { *self * (Real::pi::<f32>() / 180.0) }
+}
+
+impl Bounded for f32 {
+ #[inline(always)]
+ fn min_value() -> f32 { 1.17549435e-38 }
+
+ #[inline(always)]
+ fn max_value() -> f32 { 3.40282347e+38 }
+}
+
+impl Primitive for f32 {
+ #[inline(always)]
+ fn bits() -> uint { 32 }
+
+ #[inline(always)]
+ fn bytes() -> uint { Primitive::bits::<f32>() / 8 }
+}
+
+impl Float for f32 {
+ #[inline(always)]
+ fn NaN() -> f32 { 0.0 / 0.0 }
+
+ #[inline(always)]
+ fn infinity() -> f32 { 1.0 / 0.0 }
+
+ #[inline(always)]
+ fn neg_infinity() -> f32 { -1.0 / 0.0 }
+
+ #[inline(always)]
+ fn neg_zero() -> f32 { -0.0 }
+
+ #[inline(always)]
+ fn is_NaN(&self) -> bool { *self != *self }
+
+ #[inline(always)]
+ fn mantissa_digits() -> uint { 24 }
+
+ #[inline(always)]
+ fn digits() -> uint { 6 }
+
+ #[inline(always)]
+ fn epsilon() -> f32 { 1.19209290e-07 }
+
+ #[inline(always)]
+ fn min_exp() -> int { -125 }
+
+ #[inline(always)]
+ fn max_exp() -> int { 128 }
+
+ #[inline(always)]
+ fn min_10_exp() -> int { -37 }
+
+ #[inline(always)]
+ fn max_10_exp() -> int { 38 }
+
+ /// Returns `true` if the number is infinite
+ #[inline(always)]
+ fn is_infinite(&self) -> bool {
+ *self == Float::infinity() || *self == Float::neg_infinity()
}
+ /// Returns `true` if the number is finite
#[inline(always)]
- fn floor(&self) -> f32 { floor(*self) }
+ fn is_finite(&self) -> bool {
+ !(self.is_NaN() || self.is_infinite())
+ }
+
+ ///
+ /// Fused multiply-add. Computes `(self * a) + b` with only one rounding error. This
+ /// produces a more accurate result with better performance than a separate multiplication
+ /// operation followed by an add.
+ ///
#[inline(always)]
- fn ceil(&self) -> f32 { ceil(*self) }
+ fn mul_add(&self, a: f32, b: f32) -> f32 {
+ mul_add(*self, a, b)
+ }
+
+ /// Returns the next representable floating-point value in the direction of `other`
#[inline(always)]
- fn fract(&self) -> f32 {
- if self.is_negative() {
- (*self) - ceil(*self)
- } else {
- (*self) - floor(*self)
- }
+ fn next_after(&self, other: f32) -> f32 {
+ next_after(*self, other)
}
}
-/**
- * Section: String Conversions
- */
+//
+// Section: String Conversions
+//
-/**
- * Converts a float to a string
- *
- * # Arguments
- *
- * * num - The float value
- */
+///
+/// Converts a float to a string
+///
+/// # Arguments
+///
+/// * num - The float value
+///
#[inline(always)]
pub fn to_str(num: f32) -> ~str {
let (r, _) = strconv::to_str_common(
r
}
-/**
- * Converts a float to a string in hexadecimal format
- *
- * # Arguments
- *
- * * num - The float value
- */
+///
+/// Converts a float to a string in hexadecimal format
+///
+/// # Arguments
+///
+/// * num - The float value
+///
#[inline(always)]
pub fn to_str_hex(num: f32) -> ~str {
let (r, _) = strconv::to_str_common(
r
}
-/**
- * Converts a float to a string in a given radix
- *
- * # Arguments
- *
- * * num - The float value
- * * radix - The base to use
- *
- * # Failure
- *
- * Fails if called on a special value like `inf`, `-inf` or `NaN` due to
- * possible misinterpretation of the result at higher bases. If those values
- * are expected, use `to_str_radix_special()` instead.
- */
+///
+/// Converts a float to a string in a given radix
+///
+/// # Arguments
+///
+/// * num - The float value
+/// * radix - The base to use
+///
+/// # Failure
+///
+/// Fails if called on a special value like `inf`, `-inf` or `NaN` due to
+/// possible misinterpretation of the result at higher bases. If those values
+/// are expected, use `to_str_radix_special()` instead.
+///
#[inline(always)]
pub fn to_str_radix(num: f32, rdx: uint) -> ~str {
let (r, special) = strconv::to_str_common(
r
}
-/**
- * Converts a float to a string in a given radix, and a flag indicating
- * whether it's a special value
- *
- * # Arguments
- *
- * * num - The float value
- * * radix - The base to use
- */
+///
+/// Converts a float to a string in a given radix, and a flag indicating
+/// whether it's a special value
+///
+/// # Arguments
+///
+/// * num - The float value
+/// * radix - The base to use
+///
#[inline(always)]
pub fn to_str_radix_special(num: f32, rdx: uint) -> (~str, bool) {
strconv::to_str_common(&num, rdx, true,
strconv::SignNeg, strconv::DigAll)
}
-/**
- * Converts a float to a string with exactly the number of
- * provided significant digits
- *
- * # Arguments
- *
- * * num - The float value
- * * digits - The number of significant digits
- */
+///
+/// Converts a float to a string with exactly the number of
+/// provided significant digits
+///
+/// # Arguments
+///
+/// * num - The float value
+/// * digits - The number of significant digits
+///
#[inline(always)]
pub fn to_str_exact(num: f32, dig: uint) -> ~str {
let (r, _) = strconv::to_str_common(
r
}
-/**
- * Converts a float to a string with a maximum number of
- * significant digits
- *
- * # Arguments
- *
- * * num - The float value
- * * digits - The number of significant digits
- */
+///
+/// Converts a float to a string with a maximum number of
+/// significant digits
+///
+/// # Arguments
+///
+/// * num - The float value
+/// * digits - The number of significant digits
+///
#[inline(always)]
pub fn to_str_digits(num: f32, dig: uint) -> ~str {
let (r, _) = strconv::to_str_common(
}
}
-/**
- * Convert a string in base 10 to a float.
- * Accepts a optional decimal exponent.
- *
- * This function accepts strings such as
- *
- * * '3.14'
- * * '+3.14', equivalent to '3.14'
- * * '-3.14'
- * * '2.5E10', or equivalently, '2.5e10'
- * * '2.5E-10'
- * * '.' (understood as 0)
- * * '5.'
- * * '.5', or, equivalently, '0.5'
- * * '+inf', 'inf', '-inf', 'NaN'
- *
- * Leading and trailing whitespace represent an error.
- *
- * # Arguments
- *
- * * num - A string
- *
- * # Return value
- *
- * `none` if the string did not represent a valid number. Otherwise,
- * `Some(n)` where `n` is the floating-point number represented by `num`.
- */
+///
+/// Convert a string in base 10 to a float.
+/// Accepts a optional decimal exponent.
+///
+/// This function accepts strings such as
+///
+/// * '3.14'
+/// * '+3.14', equivalent to '3.14'
+/// * '-3.14'
+/// * '2.5E10', or equivalently, '2.5e10'
+/// * '2.5E-10'
+/// * '.' (understood as 0)
+/// * '5.'
+/// * '.5', or, equivalently, '0.5'
+/// * '+inf', 'inf', '-inf', 'NaN'
+///
+/// Leading and trailing whitespace represent an error.
+///
+/// # Arguments
+///
+/// * num - A string
+///
+/// # Return value
+///
+/// `none` if the string did not represent a valid number. Otherwise,
+/// `Some(n)` where `n` is the floating-point number represented by `num`.
+///
#[inline(always)]
pub fn from_str(num: &str) -> Option<f32> {
strconv::from_str_common(num, 10u, true, true, true,
strconv::ExpDec, false, false)
}
-/**
- * Convert a string in base 16 to a float.
- * Accepts a optional binary exponent.
- *
- * This function accepts strings such as
- *
- * * 'a4.fe'
- * * '+a4.fe', equivalent to 'a4.fe'
- * * '-a4.fe'
- * * '2b.aP128', or equivalently, '2b.ap128'
- * * '2b.aP-128'
- * * '.' (understood as 0)
- * * 'c.'
- * * '.c', or, equivalently, '0.c'
- * * '+inf', 'inf', '-inf', 'NaN'
- *
- * Leading and trailing whitespace represent an error.
- *
- * # Arguments
- *
- * * num - A string
- *
- * # Return value
- *
- * `none` if the string did not represent a valid number. Otherwise,
- * `Some(n)` where `n` is the floating-point number represented by `[num]`.
- */
+///
+/// Convert a string in base 16 to a float.
+/// Accepts a optional binary exponent.
+///
+/// This function accepts strings such as
+///
+/// * 'a4.fe'
+/// * '+a4.fe', equivalent to 'a4.fe'
+/// * '-a4.fe'
+/// * '2b.aP128', or equivalently, '2b.ap128'
+/// * '2b.aP-128'
+/// * '.' (understood as 0)
+/// * 'c.'
+/// * '.c', or, equivalently, '0.c'
+/// * '+inf', 'inf', '-inf', 'NaN'
+///
+/// Leading and trailing whitespace represent an error.
+///
+/// # Arguments
+///
+/// * num - A string
+///
+/// # Return value
+///
+/// `none` if the string did not represent a valid number. Otherwise,
+/// `Some(n)` where `n` is the floating-point number represented by `[num]`.
+///
#[inline(always)]
pub fn from_str_hex(num: &str) -> Option<f32> {
strconv::from_str_common(num, 16u, true, true, true,
strconv::ExpBin, false, false)
}
-/**
- * Convert a string in an given base to a float.
- *
- * Due to possible conflicts, this function does **not** accept
- * the special values `inf`, `-inf`, `+inf` and `NaN`, **nor**
- * does it recognize exponents of any kind.
- *
- * Leading and trailing whitespace represent an error.
- *
- * # Arguments
- *
- * * num - A string
- * * radix - The base to use. Must lie in the range [2 .. 36]
- *
- * # Return value
- *
- * `none` if the string did not represent a valid number. Otherwise,
- * `Some(n)` where `n` is the floating-point number represented by `num`.
- */
+///
+/// Convert a string in an given base to a float.
+///
+/// Due to possible conflicts, this function does **not** accept
+/// the special values `inf`, `-inf`, `+inf` and `NaN`, **nor**
+/// does it recognize exponents of any kind.
+///
+/// Leading and trailing whitespace represent an error.
+///
+/// # Arguments
+///
+/// * num - A string
+/// * radix - The base to use. Must lie in the range [2 .. 36]
+///
+/// # Return value
+///
+/// `none` if the string did not represent a valid number. Otherwise,
+/// `Some(n)` where `n` is the floating-point number represented by `num`.
+///
#[inline(always)]
pub fn from_str_radix(num: &str, rdx: uint) -> Option<f32> {
strconv::from_str_common(num, rdx, true, true, false,
#[cfg(test)]
mod tests {
use f32::*;
+ use super::*;
+ use prelude::*;
+
+ macro_rules! assert_fuzzy_eq(
+ ($a:expr, $b:expr) => ({
+ let a = $a, b = $b;
+ if !((a - b).abs() < 1.0e-6) {
+ fail!(fmt!("The values were not approximately equal. Found: %? and %?", a, b));
+ }
+ })
+ )
+
+ #[test]
+ fn test_num() {
+ num::test_num(10f32, 2f32);
+ }
+
+ #[test]
+ fn test_min() {
+ assert_eq!(1f32.min(&2f32), 1f32);
+ assert_eq!(2f32.min(&1f32), 1f32);
+ }
+
+ #[test]
+ fn test_max() {
+ assert_eq!(1f32.max(&2f32), 2f32);
+ assert_eq!(2f32.max(&1f32), 2f32);
+ }
+
+ #[test]
+ fn test_clamp() {
+ assert_eq!(1f32.clamp(&2f32, &4f32), 2f32);
+ assert_eq!(8f32.clamp(&2f32, &4f32), 4f32);
+ assert_eq!(3f32.clamp(&2f32, &4f32), 3f32);
+ assert!(3f32.clamp(&Float::NaN::<f32>(), &4f32).is_NaN());
+ assert!(3f32.clamp(&2f32, &Float::NaN::<f32>()).is_NaN());
+ assert!(Float::NaN::<f32>().clamp(&2f32, &4f32).is_NaN());
+ }
+
+ #[test]
+ fn test_floor() {
+ assert_fuzzy_eq!(1.0f32.floor(), 1.0f32);
+ assert_fuzzy_eq!(1.3f32.floor(), 1.0f32);
+ assert_fuzzy_eq!(1.5f32.floor(), 1.0f32);
+ assert_fuzzy_eq!(1.7f32.floor(), 1.0f32);
+ assert_fuzzy_eq!(0.0f32.floor(), 0.0f32);
+ assert_fuzzy_eq!((-0.0f32).floor(), -0.0f32);
+ assert_fuzzy_eq!((-1.0f32).floor(), -1.0f32);
+ assert_fuzzy_eq!((-1.3f32).floor(), -2.0f32);
+ assert_fuzzy_eq!((-1.5f32).floor(), -2.0f32);
+ assert_fuzzy_eq!((-1.7f32).floor(), -2.0f32);
+ }
+
+ #[test]
+ fn test_ceil() {
+ assert_fuzzy_eq!(1.0f32.ceil(), 1.0f32);
+ assert_fuzzy_eq!(1.3f32.ceil(), 2.0f32);
+ assert_fuzzy_eq!(1.5f32.ceil(), 2.0f32);
+ assert_fuzzy_eq!(1.7f32.ceil(), 2.0f32);
+ assert_fuzzy_eq!(0.0f32.ceil(), 0.0f32);
+ assert_fuzzy_eq!((-0.0f32).ceil(), -0.0f32);
+ assert_fuzzy_eq!((-1.0f32).ceil(), -1.0f32);
+ assert_fuzzy_eq!((-1.3f32).ceil(), -1.0f32);
+ assert_fuzzy_eq!((-1.5f32).ceil(), -1.0f32);
+ assert_fuzzy_eq!((-1.7f32).ceil(), -1.0f32);
+ }
+
+ #[test]
+ fn test_round() {
+ assert_fuzzy_eq!(1.0f32.round(), 1.0f32);
+ assert_fuzzy_eq!(1.3f32.round(), 1.0f32);
+ assert_fuzzy_eq!(1.5f32.round(), 2.0f32);
+ assert_fuzzy_eq!(1.7f32.round(), 2.0f32);
+ assert_fuzzy_eq!(0.0f32.round(), 0.0f32);
+ assert_fuzzy_eq!((-0.0f32).round(), -0.0f32);
+ assert_fuzzy_eq!((-1.0f32).round(), -1.0f32);
+ assert_fuzzy_eq!((-1.3f32).round(), -1.0f32);
+ assert_fuzzy_eq!((-1.5f32).round(), -2.0f32);
+ assert_fuzzy_eq!((-1.7f32).round(), -2.0f32);
+ }
+
+ #[test]
+ fn test_trunc() {
+ assert_fuzzy_eq!(1.0f32.trunc(), 1.0f32);
+ assert_fuzzy_eq!(1.3f32.trunc(), 1.0f32);
+ assert_fuzzy_eq!(1.5f32.trunc(), 1.0f32);
+ assert_fuzzy_eq!(1.7f32.trunc(), 1.0f32);
+ assert_fuzzy_eq!(0.0f32.trunc(), 0.0f32);
+ assert_fuzzy_eq!((-0.0f32).trunc(), -0.0f32);
+ assert_fuzzy_eq!((-1.0f32).trunc(), -1.0f32);
+ assert_fuzzy_eq!((-1.3f32).trunc(), -1.0f32);
+ assert_fuzzy_eq!((-1.5f32).trunc(), -1.0f32);
+ assert_fuzzy_eq!((-1.7f32).trunc(), -1.0f32);
+ }
+
+ #[test]
+ fn test_fract() {
+ assert_fuzzy_eq!(1.0f32.fract(), 0.0f32);
+ assert_fuzzy_eq!(1.3f32.fract(), 0.3f32);
+ assert_fuzzy_eq!(1.5f32.fract(), 0.5f32);
+ assert_fuzzy_eq!(1.7f32.fract(), 0.7f32);
+ assert_fuzzy_eq!(0.0f32.fract(), 0.0f32);
+ assert_fuzzy_eq!((-0.0f32).fract(), -0.0f32);
+ assert_fuzzy_eq!((-1.0f32).fract(), -0.0f32);
+ assert_fuzzy_eq!((-1.3f32).fract(), -0.3f32);
+ assert_fuzzy_eq!((-1.5f32).fract(), -0.5f32);
+ assert_fuzzy_eq!((-1.7f32).fract(), -0.7f32);
+ }
+
+ #[test]
+ fn test_real_consts() {
+ assert_fuzzy_eq!(Real::two_pi::<f32>(), 2f32 * Real::pi::<f32>());
+ assert_fuzzy_eq!(Real::frac_pi_2::<f32>(), Real::pi::<f32>() / 2f32);
+ assert_fuzzy_eq!(Real::frac_pi_3::<f32>(), Real::pi::<f32>() / 3f32);
+ assert_fuzzy_eq!(Real::frac_pi_4::<f32>(), Real::pi::<f32>() / 4f32);
+ assert_fuzzy_eq!(Real::frac_pi_6::<f32>(), Real::pi::<f32>() / 6f32);
+ assert_fuzzy_eq!(Real::frac_pi_8::<f32>(), Real::pi::<f32>() / 8f32);
+ assert_fuzzy_eq!(Real::frac_1_pi::<f32>(), 1f32 / Real::pi::<f32>());
+ assert_fuzzy_eq!(Real::frac_2_pi::<f32>(), 2f32 / Real::pi::<f32>());
+ assert_fuzzy_eq!(Real::frac_2_sqrtpi::<f32>(), 2f32 / Real::pi::<f32>().sqrt());
+ assert_fuzzy_eq!(Real::sqrt2::<f32>(), 2f32.sqrt());
+ assert_fuzzy_eq!(Real::frac_1_sqrt2::<f32>(), 1f32 / 2f32.sqrt());
+ assert_fuzzy_eq!(Real::log2_e::<f32>(), Real::e::<f32>().log2());
+ assert_fuzzy_eq!(Real::log10_e::<f32>(), Real::e::<f32>().log10());
+ assert_fuzzy_eq!(Real::log_2::<f32>(), 2f32.log());
+ assert_fuzzy_eq!(Real::log_10::<f32>(), 10f32.log());
+ }
#[test]
pub fn test_signed() {
assert_eq!((-1f32).abs(), 1f32);
assert_eq!(neg_infinity.abs(), infinity);
assert_eq!((1f32/neg_infinity).abs(), 0f32);
- assert!(is_NaN(NaN.abs()));
+ assert!(NaN.abs().is_NaN());
assert_eq!(infinity.signum(), 1f32);
assert_eq!(1f32.signum(), 1f32);
assert_eq!((-1f32).signum(), -1f32);
assert_eq!(neg_infinity.signum(), -1f32);
assert_eq!((1f32/neg_infinity).signum(), -1f32);
- assert!(is_NaN(NaN.signum()));
+ assert!(NaN.signum().is_NaN());
assert!(infinity.is_positive());
assert!(1f32.is_positive());
assert!((1f32/neg_infinity).is_negative());
assert!(!NaN.is_negative());
}
+
+ #[test]
+ fn test_primitive() {
+ assert_eq!(Primitive::bits::<f32>(), sys::size_of::<f32>() * 8);
+ assert_eq!(Primitive::bytes::<f32>(), sys::size_of::<f32>());
+ }
}
//
//! Operations and constants for `f64`
-use num::strconv;
-use num::Signed;
-use num;
-use option::Option;
-use to_str;
use from_str;
-
-#[cfg(notest)] use cmp::{Eq, Ord};
-#[cfg(stage0,notest)]
-use ops::{Add, Sub, Mul, Div, Modulo, Neg};
-#[cfg(stage1,notest)]
-#[cfg(stage2,notest)]
-#[cfg(stage3,notest)]
-use ops::{Add, Sub, Mul, Quot, Rem, Neg};
+use libc::c_int;
+use num::{Zero, One, strconv};
+use prelude::*;
pub use cmath::c_double_targ_consts::*;
pub use cmp::{min, max};
fn abs_sub(a: c_double, b: c_double) -> c_double = c_double_utils::abs_sub,
fn fmax(a: c_double, b: c_double) -> c_double = c_double_utils::fmax,
fn fmin(a: c_double, b: c_double) -> c_double = c_double_utils::fmin,
- fn nextafter(x: c_double, y: c_double) -> c_double = c_double_utils::nextafter,
+ fn next_after(x: c_double, y: c_double) -> c_double = c_double_utils::next_after,
fn frexp(n: c_double, value: &mut c_int) -> c_double = c_double_utils::frexp,
fn hypot(x: c_double, y: c_double) -> c_double = c_double_utils::hypot,
fn ldexp(x: c_double, n: c_int) -> c_double = c_double_utils::ldexp,
fn jn(i: c_int, n: c_double) -> c_double = c_double_utils::jn,
fn y0(n: c_double) -> c_double = c_double_utils::y0,
fn y1(n: c_double) -> c_double = c_double_utils::y1,
- fn yn(i: c_int, n: c_double) -> c_double = c_double_utils::yn)
+ fn yn(i: c_int, n: c_double) -> c_double = c_double_utils::yn
+)
// FIXME (#1433): obtain these in a different way
pub static neg_infinity: f64 = -1.0_f64/0.0_f64;
-#[inline(always)]
-pub fn is_NaN(f: f64) -> bool { f != f }
-
#[inline(always)]
pub fn add(x: f64, y: f64) -> f64 { return x + y; }
#[inline(always)]
pub fn gt(x: f64, y: f64) -> bool { return x > y; }
-/// Returns true if `x` is a zero number (positive or negative zero)
-#[inline(always)]
-pub fn is_zero(x: f64) -> bool {
- return x == 0.0f64 || x == -0.0f64;
-}
-
-/// Returns true if `x`is an infinite number
-#[inline(always)]
-pub fn is_infinite(x: f64) -> bool {
- return x == infinity || x == neg_infinity;
-}
-
-/// Returns true if `x` is a finite number
-#[inline(always)]
-pub fn is_finite(x: f64) -> bool {
- return !(is_NaN(x) || is_infinite(x));
-}
-
// FIXME (#1999): add is_normal, is_subnormal, and fpclassify
return log2(n) / log2(b);
}
+impl Num for f64 {}
+
#[cfg(notest)]
impl Eq for f64 {
#[inline(always)]
fn gt(&self, other: &f64) -> bool { (*self) > (*other) }
}
-impl num::Zero for f64 {
+impl Orderable for f64 {
+ /// Returns `NaN` if either of the numbers are `NaN`.
+ #[inline(always)]
+ fn min(&self, other: &f64) -> f64 {
+ if self.is_NaN() || other.is_NaN() { Float::NaN() } else { fmin(*self, *other) }
+ }
+
+ /// Returns `NaN` if either of the numbers are `NaN`.
+ #[inline(always)]
+ fn max(&self, other: &f64) -> f64 {
+ if self.is_NaN() || other.is_NaN() { Float::NaN() } else { fmax(*self, *other) }
+ }
+
+ /// Returns the number constrained within the range `mn <= self <= mx`.
+ /// If any of the numbers are `NaN` then `NaN` is returned.
+ #[inline(always)]
+ fn clamp(&self, mn: &f64, mx: &f64) -> f64 {
+ if self.is_NaN() { *self }
+ else if !(*self <= *mx) { *mx }
+ else if !(*self >= *mn) { *mn }
+ else { *self }
+ }
+}
+
+impl Zero for f64 {
#[inline(always)]
fn zero() -> f64 { 0.0 }
+
+ /// Returns true if the number is equal to either `0.0` or `-0.0`
+ #[inline(always)]
+ fn is_zero(&self) -> bool { *self == 0.0 || *self == -0.0 }
}
-impl num::One for f64 {
+impl One for f64 {
#[inline(always)]
fn one() -> f64 { 1.0 }
}
impl Div<f64,f64> for f64 {
fn div(&self, other: &f64) -> f64 { *self / *other }
}
-#[cfg(stage1,notest)]
-#[cfg(stage2,notest)]
-#[cfg(stage3,notest)]
+#[cfg(not(stage0),notest)]
impl Quot<f64,f64> for f64 {
#[inline(always)]
fn quot(&self, other: &f64) -> f64 { *self / *other }
impl Modulo<f64,f64> for f64 {
fn modulo(&self, other: &f64) -> f64 { *self % *other }
}
-#[cfg(stage1,notest)]
-#[cfg(stage2,notest)]
-#[cfg(stage3,notest)]
+#[cfg(not(stage0),notest)]
impl Rem<f64,f64> for f64 {
#[inline(always)]
fn rem(&self, other: &f64) -> f64 { *self % *other }
#[inline(always)]
fn abs(&self) -> f64 { abs(*self) }
- /**
- * # Returns
- *
- * - `1.0` if the number is positive, `+0.0` or `infinity`
- * - `-1.0` if the number is negative, `-0.0` or `neg_infinity`
- * - `NaN` if the number is `NaN`
- */
+ ///
+ /// # Returns
+ ///
+ /// - `1.0` if the number is positive, `+0.0` or `infinity`
+ /// - `-1.0` if the number is negative, `-0.0` or `neg_infinity`
+ /// - `NaN` if the number is NaN
+ ///
#[inline(always)]
fn signum(&self) -> f64 {
- if is_NaN(*self) { NaN } else { copysign(1.0, *self) }
+ if self.is_NaN() { NaN } else { copysign(1.0, *self) }
}
/// Returns `true` if the number is positive, including `+0.0` and `infinity`
fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == neg_infinity }
}
-impl num::Round for f64 {
+impl Round for f64 {
+ /// Round half-way cases toward `neg_infinity`
#[inline(always)]
- fn round(&self, mode: num::RoundMode) -> f64 {
- match mode {
- num::RoundDown => floor(*self),
- num::RoundUp => ceil(*self),
- num::RoundToZero if self.is_negative() => ceil(*self),
- num::RoundToZero => floor(*self),
- num::RoundFromZero if self.is_negative() => floor(*self),
- num::RoundFromZero => ceil(*self)
- }
+ fn floor(&self) -> f64 { floor(*self) }
+
+ /// Round half-way cases toward `infinity`
+ #[inline(always)]
+ fn ceil(&self) -> f64 { ceil(*self) }
+
+ /// Round half-way cases away from `0.0`
+ #[inline(always)]
+ fn round(&self) -> f64 { round(*self) }
+
+ /// The integer part of the number (rounds towards `0.0`)
+ #[inline(always)]
+ fn trunc(&self) -> f64 { trunc(*self) }
+
+ ///
+ /// The fractional part of the number, satisfying:
+ ///
+ /// ~~~
+ /// assert!(x == trunc(x) + fract(x))
+ /// ~~~
+ ///
+ #[inline(always)]
+ fn fract(&self) -> f64 { *self - self.trunc() }
+}
+
+impl Fractional for f64 {
+ /// The reciprocal (multiplicative inverse) of the number
+ #[inline(always)]
+ fn recip(&self) -> f64 { 1.0 / *self }
+}
+
+impl Algebraic for f64 {
+ #[inline(always)]
+ fn pow(&self, n: f64) -> f64 { pow(*self, n) }
+
+ #[inline(always)]
+ fn sqrt(&self) -> f64 { sqrt(*self) }
+
+ #[inline(always)]
+ fn rsqrt(&self) -> f64 { self.sqrt().recip() }
+
+ #[inline(always)]
+ fn cbrt(&self) -> f64 { cbrt(*self) }
+
+ #[inline(always)]
+ fn hypot(&self, other: f64) -> f64 { hypot(*self, other) }
+}
+
+impl Trigonometric for f64 {
+ #[inline(always)]
+ fn sin(&self) -> f64 { sin(*self) }
+
+ #[inline(always)]
+ fn cos(&self) -> f64 { cos(*self) }
+
+ #[inline(always)]
+ fn tan(&self) -> f64 { tan(*self) }
+
+ #[inline(always)]
+ fn asin(&self) -> f64 { asin(*self) }
+
+ #[inline(always)]
+ fn acos(&self) -> f64 { acos(*self) }
+
+ #[inline(always)]
+ fn atan(&self) -> f64 { atan(*self) }
+
+ #[inline(always)]
+ fn atan2(&self, other: f64) -> f64 { atan2(*self, other) }
+}
+
+impl Exponential for f64 {
+ #[inline(always)]
+ fn exp(&self) -> f64 { exp(*self) }
+
+ #[inline(always)]
+ fn exp2(&self) -> f64 { exp2(*self) }
+
+ #[inline(always)]
+ fn expm1(&self) -> f64 { expm1(*self) }
+
+ #[inline(always)]
+ fn log(&self) -> f64 { ln(*self) }
+
+ #[inline(always)]
+ fn log2(&self) -> f64 { log2(*self) }
+
+ #[inline(always)]
+ fn log10(&self) -> f64 { log10(*self) }
+}
+
+impl Hyperbolic for f64 {
+ #[inline(always)]
+ fn sinh(&self) -> f64 { sinh(*self) }
+
+ #[inline(always)]
+ fn cosh(&self) -> f64 { cosh(*self) }
+
+ #[inline(always)]
+ fn tanh(&self) -> f64 { tanh(*self) }
+}
+
+impl Real for f64 {
+ /// Archimedes' constant
+ #[inline(always)]
+ fn pi() -> f64 { 3.14159265358979323846264338327950288 }
+
+ /// 2.0 * pi
+ #[inline(always)]
+ fn two_pi() -> f64 { 6.28318530717958647692528676655900576 }
+
+ /// pi / 2.0
+ #[inline(always)]
+ fn frac_pi_2() -> f64 { 1.57079632679489661923132169163975144 }
+
+ /// pi / 3.0
+ #[inline(always)]
+ fn frac_pi_3() -> f64 { 1.04719755119659774615421446109316763 }
+
+ /// pi / 4.0
+ #[inline(always)]
+ fn frac_pi_4() -> f64 { 0.785398163397448309615660845819875721 }
+
+ /// pi / 6.0
+ #[inline(always)]
+ fn frac_pi_6() -> f64 { 0.52359877559829887307710723054658381 }
+
+ /// pi / 8.0
+ #[inline(always)]
+ fn frac_pi_8() -> f64 { 0.39269908169872415480783042290993786 }
+
+ /// 1.0 / pi
+ #[inline(always)]
+ fn frac_1_pi() -> f64 { 0.318309886183790671537767526745028724 }
+
+ /// 2.0 / pi
+ #[inline(always)]
+ fn frac_2_pi() -> f64 { 0.636619772367581343075535053490057448 }
+
+ /// 2.0 / sqrt(pi)
+ #[inline(always)]
+ fn frac_2_sqrtpi() -> f64 { 1.12837916709551257389615890312154517 }
+
+ /// sqrt(2.0)
+ #[inline(always)]
+ fn sqrt2() -> f64 { 1.41421356237309504880168872420969808 }
+
+ /// 1.0 / sqrt(2.0)
+ #[inline(always)]
+ fn frac_1_sqrt2() -> f64 { 0.707106781186547524400844362104849039 }
+
+ /// Euler's number
+ #[inline(always)]
+ fn e() -> f64 { 2.71828182845904523536028747135266250 }
+
+ /// log2(e)
+ #[inline(always)]
+ fn log2_e() -> f64 { 1.44269504088896340735992468100189214 }
+
+ /// log10(e)
+ #[inline(always)]
+ fn log10_e() -> f64 { 0.434294481903251827651128918916605082 }
+
+ /// log(2.0)
+ #[inline(always)]
+ fn log_2() -> f64 { 0.693147180559945309417232121458176568 }
+
+ /// log(10.0)
+ #[inline(always)]
+ fn log_10() -> f64 { 2.30258509299404568401799145468436421 }
+
+ /// Converts to degrees, assuming the number is in radians
+ #[inline(always)]
+ fn to_degrees(&self) -> f64 { *self * (180.0 / Real::pi::<f64>()) }
+
+ /// Converts to radians, assuming the number is in degrees
+ #[inline(always)]
+ fn to_radians(&self) -> f64 { *self * (Real::pi::<f64>() / 180.0) }
+}
+
+impl RealExt for f64 {
+ #[inline(always)]
+ fn lgamma(&self) -> (int, f64) {
+ let mut sign = 0;
+ let result = lgamma(*self, &mut sign);
+ (sign as int, result)
}
#[inline(always)]
- fn floor(&self) -> f64 { floor(*self) }
+ fn tgamma(&self) -> f64 { tgamma(*self) }
+
#[inline(always)]
- fn ceil(&self) -> f64 { ceil(*self) }
+ fn j0(&self) -> f64 { j0(*self) }
+
#[inline(always)]
- fn fract(&self) -> f64 {
- if self.is_negative() {
- (*self) - ceil(*self)
- } else {
- (*self) - floor(*self)
- }
+ fn j1(&self) -> f64 { j1(*self) }
+
+ #[inline(always)]
+ fn jn(&self, n: int) -> f64 { jn(n as c_int, *self) }
+
+ #[inline(always)]
+ fn y0(&self) -> f64 { y0(*self) }
+
+ #[inline(always)]
+ fn y1(&self) -> f64 { y1(*self) }
+
+ #[inline(always)]
+ fn yn(&self, n: int) -> f64 { yn(n as c_int, *self) }
+}
+
+impl Bounded for f64 {
+ #[inline(always)]
+ fn min_value() -> f64 { 2.2250738585072014e-308 }
+
+ #[inline(always)]
+ fn max_value() -> f64 { 1.7976931348623157e+308 }
+}
+
+impl Primitive for f64 {
+ #[inline(always)]
+ fn bits() -> uint { 64 }
+
+ #[inline(always)]
+ fn bytes() -> uint { Primitive::bits::<f64>() / 8 }
+}
+
+impl Float for f64 {
+ #[inline(always)]
+ fn NaN() -> f64 { 0.0 / 0.0 }
+
+ #[inline(always)]
+ fn infinity() -> f64 { 1.0 / 0.0 }
+
+ #[inline(always)]
+ fn neg_infinity() -> f64 { -1.0 / 0.0 }
+
+ #[inline(always)]
+ fn neg_zero() -> f64 { -0.0 }
+
+ #[inline(always)]
+ fn is_NaN(&self) -> bool { *self != *self }
+
+ /// Returns `true` if the number is infinite
+ #[inline(always)]
+ fn is_infinite(&self) -> bool {
+ *self == Float::infinity() || *self == Float::neg_infinity()
+ }
+
+ /// Returns `true` if the number is finite
+ #[inline(always)]
+ fn is_finite(&self) -> bool {
+ !(self.is_NaN() || self.is_infinite())
+ }
+
+ #[inline(always)]
+ fn mantissa_digits() -> uint { 53 }
+
+ #[inline(always)]
+ fn digits() -> uint { 15 }
+
+ #[inline(always)]
+ fn epsilon() -> f64 { 2.2204460492503131e-16 }
+
+ #[inline(always)]
+ fn min_exp() -> int { -1021 }
+
+ #[inline(always)]
+ fn max_exp() -> int { 1024 }
+
+ #[inline(always)]
+ fn min_10_exp() -> int { -307 }
+
+ #[inline(always)]
+ fn max_10_exp() -> int { 308 }
+
+ ///
+ /// Fused multiply-add. Computes `(self * a) + b` with only one rounding error. This
+ /// produces a more accurate result with better performance than a separate multiplication
+ /// operation followed by an add.
+ ///
+ #[inline(always)]
+ fn mul_add(&self, a: f64, b: f64) -> f64 {
+ mul_add(*self, a, b)
+ }
+
+ /// Returns the next representable floating-point value in the direction of `other`
+ #[inline(always)]
+ fn next_after(&self, other: f64) -> f64 {
+ next_after(*self, other)
}
}
-/**
- * Section: String Conversions
- */
+//
+// Section: String Conversions
+//
-/**
- * Converts a float to a string
- *
- * # Arguments
- *
- * * num - The float value
- */
+///
+/// Converts a float to a string
+///
+/// # Arguments
+///
+/// * num - The float value
+///
#[inline(always)]
pub fn to_str(num: f64) -> ~str {
let (r, _) = strconv::to_str_common(
r
}
-/**
- * Converts a float to a string in hexadecimal format
- *
- * # Arguments
- *
- * * num - The float value
- */
+///
+/// Converts a float to a string in hexadecimal format
+///
+/// # Arguments
+///
+/// * num - The float value
+///
#[inline(always)]
pub fn to_str_hex(num: f64) -> ~str {
let (r, _) = strconv::to_str_common(
r
}
-/**
- * Converts a float to a string in a given radix
- *
- * # Arguments
- *
- * * num - The float value
- * * radix - The base to use
- *
- * # Failure
- *
- * Fails if called on a special value like `inf`, `-inf` or `NaN` due to
- * possible misinterpretation of the result at higher bases. If those values
- * are expected, use `to_str_radix_special()` instead.
- */
+///
+/// Converts a float to a string in a given radix
+///
+/// # Arguments
+///
+/// * num - The float value
+/// * radix - The base to use
+///
+/// # Failure
+///
+/// Fails if called on a special value like `inf`, `-inf` or `NaN` due to
+/// possible misinterpretation of the result at higher bases. If those values
+/// are expected, use `to_str_radix_special()` instead.
+///
#[inline(always)]
pub fn to_str_radix(num: f64, rdx: uint) -> ~str {
let (r, special) = strconv::to_str_common(
r
}
-/**
- * Converts a float to a string in a given radix, and a flag indicating
- * whether it's a special value
- *
- * # Arguments
- *
- * * num - The float value
- * * radix - The base to use
- */
+///
+/// Converts a float to a string in a given radix, and a flag indicating
+/// whether it's a special value
+///
+/// # Arguments
+///
+/// * num - The float value
+/// * radix - The base to use
+///
#[inline(always)]
pub fn to_str_radix_special(num: f64, rdx: uint) -> (~str, bool) {
strconv::to_str_common(&num, rdx, true,
strconv::SignNeg, strconv::DigAll)
}
-/**
- * Converts a float to a string with exactly the number of
- * provided significant digits
- *
- * # Arguments
- *
- * * num - The float value
- * * digits - The number of significant digits
- */
+///
+/// Converts a float to a string with exactly the number of
+/// provided significant digits
+///
+/// # Arguments
+///
+/// * num - The float value
+/// * digits - The number of significant digits
+///
#[inline(always)]
pub fn to_str_exact(num: f64, dig: uint) -> ~str {
let (r, _) = strconv::to_str_common(
r
}
-/**
- * Converts a float to a string with a maximum number of
- * significant digits
- *
- * # Arguments
- *
- * * num - The float value
- * * digits - The number of significant digits
- */
+///
+/// Converts a float to a string with a maximum number of
+/// significant digits
+///
+/// # Arguments
+///
+/// * num - The float value
+/// * digits - The number of significant digits
+///
#[inline(always)]
pub fn to_str_digits(num: f64, dig: uint) -> ~str {
let (r, _) = strconv::to_str_common(
}
}
-/**
- * Convert a string in base 10 to a float.
- * Accepts a optional decimal exponent.
- *
- * This function accepts strings such as
- *
- * * '3.14'
- * * '+3.14', equivalent to '3.14'
- * * '-3.14'
- * * '2.5E10', or equivalently, '2.5e10'
- * * '2.5E-10'
- * * '.' (understood as 0)
- * * '5.'
- * * '.5', or, equivalently, '0.5'
- * * '+inf', 'inf', '-inf', 'NaN'
- *
- * Leading and trailing whitespace represent an error.
- *
- * # Arguments
- *
- * * num - A string
- *
- * # Return value
- *
- * `none` if the string did not represent a valid number. Otherwise,
- * `Some(n)` where `n` is the floating-point number represented by `num`.
- */
+///
+/// Convert a string in base 10 to a float.
+/// Accepts a optional decimal exponent.
+///
+/// This function accepts strings such as
+///
+/// * '3.14'
+/// * '+3.14', equivalent to '3.14'
+/// * '-3.14'
+/// * '2.5E10', or equivalently, '2.5e10'
+/// * '2.5E-10'
+/// * '.' (understood as 0)
+/// * '5.'
+/// * '.5', or, equivalently, '0.5'
+/// * '+inf', 'inf', '-inf', 'NaN'
+///
+/// Leading and trailing whitespace represent an error.
+///
+/// # Arguments
+///
+/// * num - A string
+///
+/// # Return value
+///
+/// `none` if the string did not represent a valid number. Otherwise,
+/// `Some(n)` where `n` is the floating-point number represented by `num`.
+///
#[inline(always)]
pub fn from_str(num: &str) -> Option<f64> {
strconv::from_str_common(num, 10u, true, true, true,
strconv::ExpDec, false, false)
}
-/**
- * Convert a string in base 16 to a float.
- * Accepts a optional binary exponent.
- *
- * This function accepts strings such as
- *
- * * 'a4.fe'
- * * '+a4.fe', equivalent to 'a4.fe'
- * * '-a4.fe'
- * * '2b.aP128', or equivalently, '2b.ap128'
- * * '2b.aP-128'
- * * '.' (understood as 0)
- * * 'c.'
- * * '.c', or, equivalently, '0.c'
- * * '+inf', 'inf', '-inf', 'NaN'
- *
- * Leading and trailing whitespace represent an error.
- *
- * # Arguments
- *
- * * num - A string
- *
- * # Return value
- *
- * `none` if the string did not represent a valid number. Otherwise,
- * `Some(n)` where `n` is the floating-point number represented by `[num]`.
- */
+///
+/// Convert a string in base 16 to a float.
+/// Accepts a optional binary exponent.
+///
+/// This function accepts strings such as
+///
+/// * 'a4.fe'
+/// * '+a4.fe', equivalent to 'a4.fe'
+/// * '-a4.fe'
+/// * '2b.aP128', or equivalently, '2b.ap128'
+/// * '2b.aP-128'
+/// * '.' (understood as 0)
+/// * 'c.'
+/// * '.c', or, equivalently, '0.c'
+/// * '+inf', 'inf', '-inf', 'NaN'
+///
+/// Leading and trailing whitespace represent an error.
+///
+/// # Arguments
+///
+/// * num - A string
+///
+/// # Return value
+///
+/// `none` if the string did not represent a valid number. Otherwise,
+/// `Some(n)` where `n` is the floating-point number represented by `[num]`.
+///
#[inline(always)]
pub fn from_str_hex(num: &str) -> Option<f64> {
strconv::from_str_common(num, 16u, true, true, true,
strconv::ExpBin, false, false)
}
-/**
- * Convert a string in an given base to a float.
- *
- * Due to possible conflicts, this function does **not** accept
- * the special values `inf`, `-inf`, `+inf` and `NaN`, **nor**
- * does it recognize exponents of any kind.
- *
- * Leading and trailing whitespace represent an error.
- *
- * # Arguments
- *
- * * num - A string
- * * radix - The base to use. Must lie in the range [2 .. 36]
- *
- * # Return value
- *
- * `none` if the string did not represent a valid number. Otherwise,
- * `Some(n)` where `n` is the floating-point number represented by `num`.
- */
+///
+/// Convert a string in an given base to a float.
+///
+/// Due to possible conflicts, this function does **not** accept
+/// the special values `inf`, `-inf`, `+inf` and `NaN`, **nor**
+/// does it recognize exponents of any kind.
+///
+/// Leading and trailing whitespace represent an error.
+///
+/// # Arguments
+///
+/// * num - A string
+/// * radix - The base to use. Must lie in the range [2 .. 36]
+///
+/// # Return value
+///
+/// `none` if the string did not represent a valid number. Otherwise,
+/// `Some(n)` where `n` is the floating-point number represented by `num`.
+///
#[inline(always)]
pub fn from_str_radix(num: &str, rdx: uint) -> Option<f64> {
strconv::from_str_common(num, rdx, true, true, false,
#[cfg(test)]
mod tests {
use f64::*;
+ use super::*;
+ use prelude::*;
+
+ macro_rules! assert_fuzzy_eq(
+ ($a:expr, $b:expr) => ({
+ let a = $a, b = $b;
+ if !((a - b).abs() < 1.0e-6) {
+ fail!(fmt!("The values were not approximately equal. \
+ Found: %? and expected %?", a, b));
+ }
+ })
+ )
+
+ #[test]
+ fn test_num() {
+ num::test_num(10f64, 2f64);
+ }
+
+ #[test]
+ fn test_min() {
+ assert_eq!(1f64.min(&2f64), 1f64);
+ assert_eq!(2f64.min(&1f64), 1f64);
+ assert!(1f64.min(&Float::NaN::<f64>()).is_NaN());
+ assert!(Float::NaN::<f64>().min(&1f64).is_NaN());
+ }
+
+ #[test]
+ fn test_max() {
+ assert_eq!(1f64.max(&2f64), 2f64);
+ assert_eq!(2f64.max(&1f64), 2f64);
+ assert!(1f64.max(&Float::NaN::<f64>()).is_NaN());
+ assert!(Float::NaN::<f64>().max(&1f64).is_NaN());
+ }
+
+ #[test]
+ fn test_clamp() {
+ assert_eq!(1f64.clamp(&2f64, &4f64), 2f64);
+ assert_eq!(8f64.clamp(&2f64, &4f64), 4f64);
+ assert_eq!(3f64.clamp(&2f64, &4f64), 3f64);
+ assert!(3f64.clamp(&Float::NaN::<f64>(), &4f64).is_NaN());
+ assert!(3f64.clamp(&2f64, &Float::NaN::<f64>()).is_NaN());
+ assert!(Float::NaN::<f64>().clamp(&2f64, &4f64).is_NaN());
+ }
+
+ #[test]
+ fn test_floor() {
+ assert_fuzzy_eq!(1.0f64.floor(), 1.0f64);
+ assert_fuzzy_eq!(1.3f64.floor(), 1.0f64);
+ assert_fuzzy_eq!(1.5f64.floor(), 1.0f64);
+ assert_fuzzy_eq!(1.7f64.floor(), 1.0f64);
+ assert_fuzzy_eq!(0.0f64.floor(), 0.0f64);
+ assert_fuzzy_eq!((-0.0f64).floor(), -0.0f64);
+ assert_fuzzy_eq!((-1.0f64).floor(), -1.0f64);
+ assert_fuzzy_eq!((-1.3f64).floor(), -2.0f64);
+ assert_fuzzy_eq!((-1.5f64).floor(), -2.0f64);
+ assert_fuzzy_eq!((-1.7f64).floor(), -2.0f64);
+ }
+
+ #[test]
+ fn test_ceil() {
+ assert_fuzzy_eq!(1.0f64.ceil(), 1.0f64);
+ assert_fuzzy_eq!(1.3f64.ceil(), 2.0f64);
+ assert_fuzzy_eq!(1.5f64.ceil(), 2.0f64);
+ assert_fuzzy_eq!(1.7f64.ceil(), 2.0f64);
+ assert_fuzzy_eq!(0.0f64.ceil(), 0.0f64);
+ assert_fuzzy_eq!((-0.0f64).ceil(), -0.0f64);
+ assert_fuzzy_eq!((-1.0f64).ceil(), -1.0f64);
+ assert_fuzzy_eq!((-1.3f64).ceil(), -1.0f64);
+ assert_fuzzy_eq!((-1.5f64).ceil(), -1.0f64);
+ assert_fuzzy_eq!((-1.7f64).ceil(), -1.0f64);
+ }
+
+ #[test]
+ fn test_round() {
+ assert_fuzzy_eq!(1.0f64.round(), 1.0f64);
+ assert_fuzzy_eq!(1.3f64.round(), 1.0f64);
+ assert_fuzzy_eq!(1.5f64.round(), 2.0f64);
+ assert_fuzzy_eq!(1.7f64.round(), 2.0f64);
+ assert_fuzzy_eq!(0.0f64.round(), 0.0f64);
+ assert_fuzzy_eq!((-0.0f64).round(), -0.0f64);
+ assert_fuzzy_eq!((-1.0f64).round(), -1.0f64);
+ assert_fuzzy_eq!((-1.3f64).round(), -1.0f64);
+ assert_fuzzy_eq!((-1.5f64).round(), -2.0f64);
+ assert_fuzzy_eq!((-1.7f64).round(), -2.0f64);
+ }
+
+ #[test]
+ fn test_trunc() {
+ assert_fuzzy_eq!(1.0f64.trunc(), 1.0f64);
+ assert_fuzzy_eq!(1.3f64.trunc(), 1.0f64);
+ assert_fuzzy_eq!(1.5f64.trunc(), 1.0f64);
+ assert_fuzzy_eq!(1.7f64.trunc(), 1.0f64);
+ assert_fuzzy_eq!(0.0f64.trunc(), 0.0f64);
+ assert_fuzzy_eq!((-0.0f64).trunc(), -0.0f64);
+ assert_fuzzy_eq!((-1.0f64).trunc(), -1.0f64);
+ assert_fuzzy_eq!((-1.3f64).trunc(), -1.0f64);
+ assert_fuzzy_eq!((-1.5f64).trunc(), -1.0f64);
+ assert_fuzzy_eq!((-1.7f64).trunc(), -1.0f64);
+ }
+
+ #[test]
+ fn test_fract() {
+ assert_fuzzy_eq!(1.0f64.fract(), 0.0f64);
+ assert_fuzzy_eq!(1.3f64.fract(), 0.3f64);
+ assert_fuzzy_eq!(1.5f64.fract(), 0.5f64);
+ assert_fuzzy_eq!(1.7f64.fract(), 0.7f64);
+ assert_fuzzy_eq!(0.0f64.fract(), 0.0f64);
+ assert_fuzzy_eq!((-0.0f64).fract(), -0.0f64);
+ assert_fuzzy_eq!((-1.0f64).fract(), -0.0f64);
+ assert_fuzzy_eq!((-1.3f64).fract(), -0.3f64);
+ assert_fuzzy_eq!((-1.5f64).fract(), -0.5f64);
+ assert_fuzzy_eq!((-1.7f64).fract(), -0.7f64);
+ }
+
+ #[test]
+ fn test_real_consts() {
+ assert_fuzzy_eq!(Real::two_pi::<f64>(), 2.0 * Real::pi::<f64>());
+ assert_fuzzy_eq!(Real::frac_pi_2::<f64>(), Real::pi::<f64>() / 2f64);
+ assert_fuzzy_eq!(Real::frac_pi_3::<f64>(), Real::pi::<f64>() / 3f64);
+ assert_fuzzy_eq!(Real::frac_pi_4::<f64>(), Real::pi::<f64>() / 4f64);
+ assert_fuzzy_eq!(Real::frac_pi_6::<f64>(), Real::pi::<f64>() / 6f64);
+ assert_fuzzy_eq!(Real::frac_pi_8::<f64>(), Real::pi::<f64>() / 8f64);
+ assert_fuzzy_eq!(Real::frac_1_pi::<f64>(), 1f64 / Real::pi::<f64>());
+ assert_fuzzy_eq!(Real::frac_2_pi::<f64>(), 2f64 / Real::pi::<f64>());
+ assert_fuzzy_eq!(Real::frac_2_sqrtpi::<f64>(), 2f64 / Real::pi::<f64>().sqrt());
+ assert_fuzzy_eq!(Real::sqrt2::<f64>(), 2f64.sqrt());
+ assert_fuzzy_eq!(Real::frac_1_sqrt2::<f64>(), 1f64 / 2f64.sqrt());
+ assert_fuzzy_eq!(Real::log2_e::<f64>(), Real::e::<f64>().log2());
+ assert_fuzzy_eq!(Real::log10_e::<f64>(), Real::e::<f64>().log10());
+ assert_fuzzy_eq!(Real::log_2::<f64>(), 2f64.log());
+ assert_fuzzy_eq!(Real::log_10::<f64>(), 10f64.log());
+ }
#[test]
pub fn test_signed() {
assert_eq!((-1f64).abs(), 1f64);
assert_eq!(neg_infinity.abs(), infinity);
assert_eq!((1f64/neg_infinity).abs(), 0f64);
- assert!(is_NaN(NaN.abs()));
+ assert!(NaN.abs().is_NaN());
assert_eq!(infinity.signum(), 1f64);
assert_eq!(1f64.signum(), 1f64);
assert_eq!((-1f64).signum(), -1f64);
assert_eq!(neg_infinity.signum(), -1f64);
assert_eq!((1f64/neg_infinity).signum(), -1f64);
- assert!(is_NaN(NaN.signum()));
+ assert!(NaN.signum().is_NaN());
assert!(infinity.is_positive());
assert!(1f64.is_positive());
assert!((1f64/neg_infinity).is_negative());
assert!(!NaN.is_negative());
}
+
+ #[test]
+ fn test_primitive() {
+ assert_eq!(Primitive::bits::<f64>(), sys::size_of::<f64>() * 8);
+ assert_eq!(Primitive::bytes::<f64>(), sys::size_of::<f64>());
+ }
}
//
// PORT this must match in width according to architecture
-use f64;
-use num::strconv;
-use num::Signed;
-use num;
-use option::Option;
-use to_str;
use from_str;
-
-#[cfg(notest)] use cmp::{Eq, Ord};
-#[cfg(stage0,notest)]
-use ops::{Add, Sub, Mul, Div, Modulo, Neg};
-#[cfg(stage1,notest)]
-#[cfg(stage2,notest)]
-#[cfg(stage3,notest)]
-use ops::{Add, Sub, Mul, Quot, Rem, Neg};
+use libc::c_int;
+use num::{Zero, One, strconv};
+use prelude::*;
pub use f64::{add, sub, mul, quot, rem, lt, le, eq, ne, ge, gt};
pub use f64::logarithm;
pub use f64::{acos, asin, atan2, cbrt, ceil, copysign, cosh, floor};
pub use f64::{erf, erfc, exp, expm1, exp2, abs_sub};
-pub use f64::{mul_add, fmax, fmin, nextafter, frexp, hypot, ldexp};
+pub use f64::{mul_add, fmax, fmin, next_after, frexp, hypot, ldexp};
pub use f64::{lgamma, ln, log_radix, ln1p, log10, log2, ilog_radix};
pub use f64::{modf, pow, powi, round, sinh, tanh, tgamma, trunc};
pub use f64::{j0, j1, jn, y0, y1, yn};
pub static ln_10: float = 2.30258509299404568401799145468436421;
}
-/*
- * Section: String Conversions
- */
+//
+// Section: String Conversions
+//
-/**
- * Converts a float to a string
- *
- * # Arguments
- *
- * * num - The float value
- */
+///
+/// Converts a float to a string
+///
+/// # Arguments
+///
+/// * num - The float value
+///
#[inline(always)]
pub fn to_str(num: float) -> ~str {
let (r, _) = strconv::to_str_common(
r
}
-/**
- * Converts a float to a string in hexadecimal format
- *
- * # Arguments
- *
- * * num - The float value
- */
+///
+/// Converts a float to a string in hexadecimal format
+///
+/// # Arguments
+///
+/// * num - The float value
+///
#[inline(always)]
pub fn to_str_hex(num: float) -> ~str {
let (r, _) = strconv::to_str_common(
r
}
-/**
- * Converts a float to a string in a given radix
- *
- * # Arguments
- *
- * * num - The float value
- * * radix - The base to use
- *
- * # Failure
- *
- * Fails if called on a special value like `inf`, `-inf` or `NaN` due to
- * possible misinterpretation of the result at higher bases. If those values
- * are expected, use `to_str_radix_special()` instead.
- */
+///
+/// Converts a float to a string in a given radix
+///
+/// # Arguments
+///
+/// * num - The float value
+/// * radix - The base to use
+///
+/// # Failure
+///
+/// Fails if called on a special value like `inf`, `-inf` or `NaN` due to
+/// possible misinterpretation of the result at higher bases. If those values
+/// are expected, use `to_str_radix_special()` instead.
+///
#[inline(always)]
pub fn to_str_radix(num: float, radix: uint) -> ~str {
let (r, special) = strconv::to_str_common(
r
}
-/**
- * Converts a float to a string in a given radix, and a flag indicating
- * whether it's a special value
- *
- * # Arguments
- *
- * * num - The float value
- * * radix - The base to use
- */
+///
+/// Converts a float to a string in a given radix, and a flag indicating
+/// whether it's a special value
+///
+/// # Arguments
+///
+/// * num - The float value
+/// * radix - The base to use
+///
#[inline(always)]
pub fn to_str_radix_special(num: float, radix: uint) -> (~str, bool) {
strconv::to_str_common(&num, radix, true,
strconv::SignNeg, strconv::DigAll)
}
-/**
- * Converts a float to a string with exactly the number of
- * provided significant digits
- *
- * # Arguments
- *
- * * num - The float value
- * * digits - The number of significant digits
- */
+///
+/// Converts a float to a string with exactly the number of
+/// provided significant digits
+///
+/// # Arguments
+///
+/// * num - The float value
+/// * digits - The number of significant digits
+///
#[inline(always)]
pub fn to_str_exact(num: float, digits: uint) -> ~str {
let (r, _) = strconv::to_str_common(
r
}
-/**
- * Converts a float to a string with a maximum number of
- * significant digits
- *
- * # Arguments
- *
- * * num - The float value
- * * digits - The number of significant digits
- */
+///
+/// Converts a float to a string with a maximum number of
+/// significant digits
+///
+/// # Arguments
+///
+/// * num - The float value
+/// * digits - The number of significant digits
+///
#[inline(always)]
pub fn to_str_digits(num: float, digits: uint) -> ~str {
let (r, _) = strconv::to_str_common(
}
}
-/**
- * Convert a string in base 10 to a float.
- * Accepts a optional decimal exponent.
- *
- * This function accepts strings such as
- *
- * * '3.14'
- * * '+3.14', equivalent to '3.14'
- * * '-3.14'
- * * '2.5E10', or equivalently, '2.5e10'
- * * '2.5E-10'
- * * '.' (understood as 0)
- * * '5.'
- * * '.5', or, equivalently, '0.5'
- * * '+inf', 'inf', '-inf', 'NaN'
- *
- * Leading and trailing whitespace represent an error.
- *
- * # Arguments
- *
- * * num - A string
- *
- * # Return value
- *
- * `none` if the string did not represent a valid number. Otherwise,
- * `Some(n)` where `n` is the floating-point number represented by `num`.
- */
+///
+/// Convert a string in base 10 to a float.
+/// Accepts a optional decimal exponent.
+///
+/// This function accepts strings such as
+///
+/// * '3.14'
+/// * '+3.14', equivalent to '3.14'
+/// * '-3.14'
+/// * '2.5E10', or equivalently, '2.5e10'
+/// * '2.5E-10'
+/// * '.' (understood as 0)
+/// * '5.'
+/// * '.5', or, equivalently, '0.5'
+/// * '+inf', 'inf', '-inf', 'NaN'
+///
+/// Leading and trailing whitespace represent an error.
+///
+/// # Arguments
+///
+/// * num - A string
+///
+/// # Return value
+///
+/// `none` if the string did not represent a valid number. Otherwise,
+/// `Some(n)` where `n` is the floating-point number represented by `num`.
+///
#[inline(always)]
pub fn from_str(num: &str) -> Option<float> {
strconv::from_str_common(num, 10u, true, true, true,
strconv::ExpDec, false, false)
}
-/**
- * Convert a string in base 16 to a float.
- * Accepts a optional binary exponent.
- *
- * This function accepts strings such as
- *
- * * 'a4.fe'
- * * '+a4.fe', equivalent to 'a4.fe'
- * * '-a4.fe'
- * * '2b.aP128', or equivalently, '2b.ap128'
- * * '2b.aP-128'
- * * '.' (understood as 0)
- * * 'c.'
- * * '.c', or, equivalently, '0.c'
- * * '+inf', 'inf', '-inf', 'NaN'
- *
- * Leading and trailing whitespace represent an error.
- *
- * # Arguments
- *
- * * num - A string
- *
- * # Return value
- *
- * `none` if the string did not represent a valid number. Otherwise,
- * `Some(n)` where `n` is the floating-point number represented by `[num]`.
- */
+///
+/// Convert a string in base 16 to a float.
+/// Accepts a optional binary exponent.
+///
+/// This function accepts strings such as
+///
+/// * 'a4.fe'
+/// * '+a4.fe', equivalent to 'a4.fe'
+/// * '-a4.fe'
+/// * '2b.aP128', or equivalently, '2b.ap128'
+/// * '2b.aP-128'
+/// * '.' (understood as 0)
+/// * 'c.'
+/// * '.c', or, equivalently, '0.c'
+/// * '+inf', 'inf', '-inf', 'NaN'
+///
+/// Leading and trailing whitespace represent an error.
+///
+/// # Arguments
+///
+/// * num - A string
+///
+/// # Return value
+///
+/// `none` if the string did not represent a valid number. Otherwise,
+/// `Some(n)` where `n` is the floating-point number represented by `[num]`.
+///
#[inline(always)]
pub fn from_str_hex(num: &str) -> Option<float> {
strconv::from_str_common(num, 16u, true, true, true,
strconv::ExpBin, false, false)
}
-/**
- * Convert a string in an given base to a float.
- *
- * Due to possible conflicts, this function does **not** accept
- * the special values `inf`, `-inf`, `+inf` and `NaN`, **nor**
- * does it recognize exponents of any kind.
- *
- * Leading and trailing whitespace represent an error.
- *
- * # Arguments
- *
- * * num - A string
- * * radix - The base to use. Must lie in the range [2 .. 36]
- *
- * # Return value
- *
- * `none` if the string did not represent a valid number. Otherwise,
- * `Some(n)` where `n` is the floating-point number represented by `num`.
- */
+///
+/// Convert a string in an given base to a float.
+///
+/// Due to possible conflicts, this function does **not** accept
+/// the special values `inf`, `-inf`, `+inf` and `NaN`, **nor**
+/// does it recognize exponents of any kind.
+///
+/// Leading and trailing whitespace represent an error.
+///
+/// # Arguments
+///
+/// * num - A string
+/// * radix - The base to use. Must lie in the range [2 .. 36]
+///
+/// # Return value
+///
+/// `none` if the string did not represent a valid number. Otherwise,
+/// `Some(n)` where `n` is the floating-point number represented by `num`.
+///
#[inline(always)]
pub fn from_str_radix(num: &str, radix: uint) -> Option<float> {
strconv::from_str_common(num, radix, true, true, false,
}
}
-/**
- * Section: Arithmetics
- */
+//
+// Section: Arithmetics
+//
-/**
- * Compute the exponentiation of an integer by another integer as a float
- *
- * # Arguments
- *
- * * x - The base
- * * pow - The exponent
- *
- * # Return value
- *
- * `NaN` if both `x` and `pow` are `0u`, otherwise `x^pow`
- */
+///
+/// Compute the exponentiation of an integer by another integer as a float
+///
+/// # Arguments
+///
+/// * x - The base
+/// * pow - The exponent
+///
+/// # Return value
+///
+/// `NaN` if both `x` and `pow` are `0u`, otherwise `x^pow`
+///
pub fn pow_with_uint(base: uint, pow: uint) -> float {
if base == 0u {
if pow == 0u {
return total;
}
-#[inline(always)]
-pub fn is_zero(x: float) -> bool { f64::is_zero(x as f64) }
-#[inline(always)]
-pub fn is_infinite(x: float) -> bool { f64::is_infinite(x as f64) }
-#[inline(always)]
-pub fn is_finite(x: float) -> bool { f64::is_finite(x as f64) }
-#[inline(always)]
-pub fn is_NaN(x: float) -> bool { f64::is_NaN(x as f64) }
-
#[inline(always)]
pub fn abs(x: float) -> float {
f64::abs(x as f64) as float
f64::tan(x as f64) as float
}
+impl Num for float {}
+
#[cfg(notest)]
impl Eq for float {
#[inline(always)]
fn gt(&self, other: &float) -> bool { (*self) > (*other) }
}
-impl num::Zero for float {
+impl Orderable for float {
+ /// Returns `NaN` if either of the numbers are `NaN`.
+ #[inline(always)]
+ fn min(&self, other: &float) -> float {
+ (*self as f64).min(&(*other as f64)) as float
+ }
+
+ /// Returns `NaN` if either of the numbers are `NaN`.
+ #[inline(always)]
+ fn max(&self, other: &float) -> float {
+ (*self as f64).max(&(*other as f64)) as float
+ }
+
+ /// Returns the number constrained within the range `mn <= self <= mx`.
+ /// If any of the numbers are `NaN` then `NaN` is returned.
+ #[inline(always)]
+ fn clamp(&self, mn: &float, mx: &float) -> float {
+ (*self as f64).clamp(&(*mn as f64), &(*mx as f64)) as float
+ }
+}
+
+impl Zero for float {
#[inline(always)]
fn zero() -> float { 0.0 }
+
+ /// Returns true if the number is equal to either `0.0` or `-0.0`
+ #[inline(always)]
+ fn is_zero(&self) -> bool { *self == 0.0 || *self == -0.0 }
}
-impl num::One for float {
+impl One for float {
#[inline(always)]
fn one() -> float { 1.0 }
}
-impl num::Round for float {
- #[inline(always)]
- fn round(&self, mode: num::RoundMode) -> float {
- match mode {
- num::RoundDown
- => f64::floor(*self as f64) as float,
- num::RoundUp
- => f64::ceil(*self as f64) as float,
- num::RoundToZero if self.is_negative()
- => f64::ceil(*self as f64) as float,
- num::RoundToZero
- => f64::floor(*self as f64) as float,
- num::RoundFromZero if self.is_negative()
- => f64::floor(*self as f64) as float,
- num::RoundFromZero
- => f64::ceil(*self as f64) as float
- }
+impl Round for float {
+ /// Round half-way cases toward `neg_infinity`
+ #[inline(always)]
+ fn floor(&self) -> float { floor(*self as f64) as float }
+
+ /// Round half-way cases toward `infinity`
+ #[inline(always)]
+ fn ceil(&self) -> float { ceil(*self as f64) as float }
+
+ /// Round half-way cases away from `0.0`
+ #[inline(always)]
+ fn round(&self) -> float { round(*self as f64) as float }
+
+ /// The integer part of the number (rounds towards `0.0`)
+ #[inline(always)]
+ fn trunc(&self) -> float { trunc(*self as f64) as float }
+
+ ///
+ /// The fractional part of the number, satisfying:
+ ///
+ /// ~~~
+ /// assert!(x == trunc(x) + fract(x))
+ /// ~~~
+ ///
+ #[inline(always)]
+ fn fract(&self) -> float { *self - self.trunc() }
+}
+
+impl Fractional for float {
+ /// The reciprocal (multiplicative inverse) of the number
+ #[inline(always)]
+ fn recip(&self) -> float { 1.0 / *self }
+}
+
+impl Algebraic for float {
+ #[inline(always)]
+ fn pow(&self, n: float) -> float {
+ (*self as f64).pow(n as f64) as float
}
#[inline(always)]
- fn floor(&self) -> float { f64::floor(*self as f64) as float}
+ fn sqrt(&self) -> float {
+ (*self as f64).sqrt() as float
+ }
+
#[inline(always)]
- fn ceil(&self) -> float { f64::ceil(*self as f64) as float}
+ fn rsqrt(&self) -> float {
+ (*self as f64).rsqrt() as float
+ }
+
#[inline(always)]
- fn fract(&self) -> float {
- if self.is_negative() {
- (*self) - (f64::ceil(*self as f64) as float)
- } else {
- (*self) - (f64::floor(*self as f64) as float)
- }
+ fn cbrt(&self) -> float {
+ (*self as f64).cbrt() as float
+ }
+
+ #[inline(always)]
+ fn hypot(&self, other: float) -> float {
+ (*self as f64).hypot(other as f64) as float
+ }
+}
+
+impl Trigonometric for float {
+ #[inline(always)]
+ fn sin(&self) -> float {
+ (*self as f64).sin() as float
+ }
+
+ #[inline(always)]
+ fn cos(&self) -> float {
+ (*self as f64).cos() as float
+ }
+
+ #[inline(always)]
+ fn tan(&self) -> float {
+ (*self as f64).tan() as float
+ }
+
+ #[inline(always)]
+ fn asin(&self) -> float {
+ (*self as f64).asin() as float
+ }
+
+ #[inline(always)]
+ fn acos(&self) -> float {
+ (*self as f64).acos() as float
+ }
+
+ #[inline(always)]
+ fn atan(&self) -> float {
+ (*self as f64).atan() as float
+ }
+
+ #[inline(always)]
+ fn atan2(&self, other: float) -> float {
+ (*self as f64).atan2(other as f64) as float
}
}
+impl Exponential for float {
+ #[inline(always)]
+ fn exp(&self) -> float {
+ (*self as f64).exp() as float
+ }
+
+ #[inline(always)]
+ fn exp2(&self) -> float {
+ (*self as f64).exp2() as float
+ }
+
+ #[inline(always)]
+ fn expm1(&self) -> float {
+ (*self as f64).expm1() as float
+ }
+
+ #[inline(always)]
+ fn log(&self) -> float {
+ (*self as f64).log() as float
+ }
+
+ #[inline(always)]
+ fn log2(&self) -> float {
+ (*self as f64).log2() as float
+ }
+
+ #[inline(always)]
+ fn log10(&self) -> float {
+ (*self as f64).log10() as float
+ }
+}
+
+impl Hyperbolic for float {
+ #[inline(always)]
+ fn sinh(&self) -> float {
+ (*self as f64).sinh() as float
+ }
+
+ #[inline(always)]
+ fn cosh(&self) -> float {
+ (*self as f64).cosh() as float
+ }
+
+ #[inline(always)]
+ fn tanh(&self) -> float {
+ (*self as f64).tanh() as float
+ }
+}
+
+impl Real for float {
+ /// Archimedes' constant
+ #[inline(always)]
+ fn pi() -> float { 3.14159265358979323846264338327950288 }
+
+ /// 2.0 * pi
+ #[inline(always)]
+ fn two_pi() -> float { 6.28318530717958647692528676655900576 }
+
+ /// pi / 2.0
+ #[inline(always)]
+ fn frac_pi_2() -> float { 1.57079632679489661923132169163975144 }
+
+ /// pi / 3.0
+ #[inline(always)]
+ fn frac_pi_3() -> float { 1.04719755119659774615421446109316763 }
+
+ /// pi / 4.0
+ #[inline(always)]
+ fn frac_pi_4() -> float { 0.785398163397448309615660845819875721 }
+
+ /// pi / 6.0
+ #[inline(always)]
+ fn frac_pi_6() -> float { 0.52359877559829887307710723054658381 }
+
+ /// pi / 8.0
+ #[inline(always)]
+ fn frac_pi_8() -> float { 0.39269908169872415480783042290993786 }
+
+ /// 1.0 / pi
+ #[inline(always)]
+ fn frac_1_pi() -> float { 0.318309886183790671537767526745028724 }
+
+ /// 2.0 / pi
+ #[inline(always)]
+ fn frac_2_pi() -> float { 0.636619772367581343075535053490057448 }
+
+ /// 2 .0/ sqrt(pi)
+ #[inline(always)]
+ fn frac_2_sqrtpi() -> float { 1.12837916709551257389615890312154517 }
+
+ /// sqrt(2.0)
+ #[inline(always)]
+ fn sqrt2() -> float { 1.41421356237309504880168872420969808 }
+
+ /// 1.0 / sqrt(2.0)
+ #[inline(always)]
+ fn frac_1_sqrt2() -> float { 0.707106781186547524400844362104849039 }
+
+ /// Euler's number
+ #[inline(always)]
+ fn e() -> float { 2.71828182845904523536028747135266250 }
+
+ /// log2(e)
+ #[inline(always)]
+ fn log2_e() -> float { 1.44269504088896340735992468100189214 }
+
+ /// log10(e)
+ #[inline(always)]
+ fn log10_e() -> float { 0.434294481903251827651128918916605082 }
+
+ /// log(2.0)
+ #[inline(always)]
+ fn log_2() -> float { 0.693147180559945309417232121458176568 }
+
+ /// log(10.0)
+ #[inline(always)]
+ fn log_10() -> float { 2.30258509299404568401799145468436421 }
+
+ /// Converts to degrees, assuming the number is in radians
+ #[inline(always)]
+ fn to_degrees(&self) -> float { (*self as f64).to_degrees() as float }
+
+ /// Converts to radians, assuming the number is in degrees
+ #[inline(always)]
+ fn to_radians(&self) -> float { (*self as f64).to_radians() as float }
+}
+
+impl RealExt for float {
+ #[inline(always)]
+ fn lgamma(&self) -> (int, float) {
+ let mut sign = 0;
+ let result = lgamma(*self as f64, &mut sign);
+ (sign as int, result as float)
+ }
+
+ #[inline(always)]
+ fn tgamma(&self) -> float { tgamma(*self as f64) as float }
+
+ #[inline(always)]
+ fn j0(&self) -> float { j0(*self as f64) as float }
+
+ #[inline(always)]
+ fn j1(&self) -> float { j1(*self as f64) as float }
+
+ #[inline(always)]
+ fn jn(&self, n: int) -> float { jn(n as c_int, *self as f64) as float }
+
+ #[inline(always)]
+ fn y0(&self) -> float { y0(*self as f64) as float }
+
+ #[inline(always)]
+ fn y1(&self) -> float { y1(*self as f64) as float }
+
+ #[inline(always)]
+ fn yn(&self, n: int) -> float { yn(n as c_int, *self as f64) as float }
+}
+
#[cfg(notest)]
impl Add<float,float> for float {
#[inline(always)]
#[inline(always)]
fn div(&self, other: &float) -> float { *self / *other }
}
-#[cfg(stage1,notest)]
-#[cfg(stage2,notest)]
-#[cfg(stage3,notest)]
+#[cfg(not(stage0),notest)]
impl Quot<float,float> for float {
#[inline(always)]
fn quot(&self, other: &float) -> float { *self / *other }
#[inline(always)]
fn modulo(&self, other: &float) -> float { *self % *other }
}
-#[cfg(stage1,notest)]
-#[cfg(stage2,notest)]
-#[cfg(stage3,notest)]
+#[cfg(not(stage0),notest)]
impl Rem<float,float> for float {
#[inline(always)]
fn rem(&self, other: &float) -> float { *self % *other }
#[inline(always)]
fn abs(&self) -> float { abs(*self) }
- /**
- * # Returns
- *
- * - `1.0` if the number is positive, `+0.0` or `infinity`
- * - `-1.0` if the number is negative, `-0.0` or `neg_infinity`
- * - `NaN` if the number is NaN
- */
+ ///
+ /// # Returns
+ ///
+ /// - `1.0` if the number is positive, `+0.0` or `infinity`
+ /// - `-1.0` if the number is negative, `-0.0` or `neg_infinity`
+ /// - `NaN` if the number is NaN
+ ///
#[inline(always)]
fn signum(&self) -> float {
- if is_NaN(*self) { NaN } else { f64::copysign(1.0, *self as f64) as float }
+ if self.is_NaN() { NaN } else { f64::copysign(1.0, *self as f64) as float }
}
/// Returns `true` if the number is positive, including `+0.0` and `infinity`
fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == neg_infinity }
}
+impl Bounded for float {
+ #[inline(always)]
+ fn min_value() -> float { Bounded::min_value::<f64>() as float }
+
+ #[inline(always)]
+ fn max_value() -> float { Bounded::max_value::<f64>() as float }
+}
+
+impl Primitive for float {
+ #[inline(always)]
+ fn bits() -> uint { Primitive::bits::<f64>() }
+
+ #[inline(always)]
+ fn bytes() -> uint { Primitive::bytes::<f64>() }
+}
+
+impl Float for float {
+ #[inline(always)]
+ fn NaN() -> float { 0.0 / 0.0 }
+
+ #[inline(always)]
+ fn infinity() -> float { 1.0 / 0.0 }
+
+ #[inline(always)]
+ fn neg_infinity() -> float { -1.0 / 0.0 }
+
+ #[inline(always)]
+ fn neg_zero() -> float { -0.0 }
+
+ #[inline(always)]
+ fn is_NaN(&self) -> bool { *self != *self }
+
+ #[inline(always)]
+ fn mantissa_digits() -> uint { Float::mantissa_digits::<f64>() }
+
+ #[inline(always)]
+ fn digits() -> uint { Float::digits::<f64>() }
+
+ #[inline(always)]
+ fn epsilon() -> float { Float::epsilon::<f64>() as float }
+
+ #[inline(always)]
+ fn min_exp() -> int { Float::min_exp::<f64>() }
+
+ #[inline(always)]
+ fn max_exp() -> int { Float::max_exp::<f64>() }
+
+ #[inline(always)]
+ fn min_10_exp() -> int { Float::min_10_exp::<f64>() }
+
+ #[inline(always)]
+ fn max_10_exp() -> int { Float::max_10_exp::<f64>() }
+
+ /// Returns `true` if the number is infinite
+ #[inline(always)]
+ fn is_infinite(&self) -> bool {
+ *self == Float::infinity() || *self == Float::neg_infinity()
+ }
+
+ /// Returns `true` if the number is finite
+ #[inline(always)]
+ fn is_finite(&self) -> bool {
+ !(self.is_NaN() || self.is_infinite())
+ }
+
+ ///
+ /// Fused multiply-add. Computes `(self * a) + b` with only one rounding error. This
+ /// produces a more accurate result with better performance than a separate multiplication
+ /// operation followed by an add.
+ ///
+ #[inline(always)]
+ fn mul_add(&self, a: float, b: float) -> float {
+ mul_add(*self as f64, a as f64, b as f64) as float
+ }
+
+ /// Returns the next representable floating-point value in the direction of `other`
+ #[inline(always)]
+ fn next_after(&self, other: float) -> float {
+ next_after(*self as f64, other as f64) as float
+ }
+}
+
#[cfg(test)]
mod tests {
use super::*;
use prelude::*;
+ macro_rules! assert_fuzzy_eq(
+ ($a:expr, $b:expr) => ({
+ let a = $a, b = $b;
+ if !((a - b).abs() < 1.0e-6) {
+ fail!(fmt!("The values were not approximately equal. Found: %? and %?", a, b));
+ }
+ })
+ )
+
+ #[test]
+ fn test_num() {
+ num::test_num(10f, 2f);
+ }
+
+ #[test]
+ fn test_min() {
+ assert_eq!(1f.min(&2f), 1f);
+ assert_eq!(2f.min(&1f), 1f);
+ }
+
#[test]
- pub fn test_signed() {
+ fn test_max() {
+ assert_eq!(1f.max(&2f), 2f);
+ assert_eq!(2f.max(&1f), 2f);
+ }
+
+ #[test]
+ fn test_clamp() {
+ assert_eq!(1f.clamp(&2f, &4f), 2f);
+ assert_eq!(8f.clamp(&2f, &4f), 4f);
+ assert_eq!(3f.clamp(&2f, &4f), 3f);
+ assert!(3f.clamp(&Float::NaN::<float>(), &4f).is_NaN());
+ assert!(3f.clamp(&2f, &Float::NaN::<float>()).is_NaN());
+ assert!(Float::NaN::<float>().clamp(&2f, &4f).is_NaN());
+ }
+
+ #[test]
+ fn test_floor() {
+ assert_fuzzy_eq!(1.0f.floor(), 1.0f);
+ assert_fuzzy_eq!(1.3f.floor(), 1.0f);
+ assert_fuzzy_eq!(1.5f.floor(), 1.0f);
+ assert_fuzzy_eq!(1.7f.floor(), 1.0f);
+ assert_fuzzy_eq!(0.0f.floor(), 0.0f);
+ assert_fuzzy_eq!((-0.0f).floor(), -0.0f);
+ assert_fuzzy_eq!((-1.0f).floor(), -1.0f);
+ assert_fuzzy_eq!((-1.3f).floor(), -2.0f);
+ assert_fuzzy_eq!((-1.5f).floor(), -2.0f);
+ assert_fuzzy_eq!((-1.7f).floor(), -2.0f);
+ }
+
+ #[test]
+ fn test_ceil() {
+ assert_fuzzy_eq!(1.0f.ceil(), 1.0f);
+ assert_fuzzy_eq!(1.3f.ceil(), 2.0f);
+ assert_fuzzy_eq!(1.5f.ceil(), 2.0f);
+ assert_fuzzy_eq!(1.7f.ceil(), 2.0f);
+ assert_fuzzy_eq!(0.0f.ceil(), 0.0f);
+ assert_fuzzy_eq!((-0.0f).ceil(), -0.0f);
+ assert_fuzzy_eq!((-1.0f).ceil(), -1.0f);
+ assert_fuzzy_eq!((-1.3f).ceil(), -1.0f);
+ assert_fuzzy_eq!((-1.5f).ceil(), -1.0f);
+ assert_fuzzy_eq!((-1.7f).ceil(), -1.0f);
+ }
+
+ #[test]
+ fn test_round() {
+ assert_fuzzy_eq!(1.0f.round(), 1.0f);
+ assert_fuzzy_eq!(1.3f.round(), 1.0f);
+ assert_fuzzy_eq!(1.5f.round(), 2.0f);
+ assert_fuzzy_eq!(1.7f.round(), 2.0f);
+ assert_fuzzy_eq!(0.0f.round(), 0.0f);
+ assert_fuzzy_eq!((-0.0f).round(), -0.0f);
+ assert_fuzzy_eq!((-1.0f).round(), -1.0f);
+ assert_fuzzy_eq!((-1.3f).round(), -1.0f);
+ assert_fuzzy_eq!((-1.5f).round(), -2.0f);
+ assert_fuzzy_eq!((-1.7f).round(), -2.0f);
+ }
+
+ #[test]
+ fn test_trunc() {
+ assert_fuzzy_eq!(1.0f.trunc(), 1.0f);
+ assert_fuzzy_eq!(1.3f.trunc(), 1.0f);
+ assert_fuzzy_eq!(1.5f.trunc(), 1.0f);
+ assert_fuzzy_eq!(1.7f.trunc(), 1.0f);
+ assert_fuzzy_eq!(0.0f.trunc(), 0.0f);
+ assert_fuzzy_eq!((-0.0f).trunc(), -0.0f);
+ assert_fuzzy_eq!((-1.0f).trunc(), -1.0f);
+ assert_fuzzy_eq!((-1.3f).trunc(), -1.0f);
+ assert_fuzzy_eq!((-1.5f).trunc(), -1.0f);
+ assert_fuzzy_eq!((-1.7f).trunc(), -1.0f);
+ }
+
+ #[test]
+ fn test_fract() {
+ assert_fuzzy_eq!(1.0f.fract(), 0.0f);
+ assert_fuzzy_eq!(1.3f.fract(), 0.3f);
+ assert_fuzzy_eq!(1.5f.fract(), 0.5f);
+ assert_fuzzy_eq!(1.7f.fract(), 0.7f);
+ assert_fuzzy_eq!(0.0f.fract(), 0.0f);
+ assert_fuzzy_eq!((-0.0f).fract(), -0.0f);
+ assert_fuzzy_eq!((-1.0f).fract(), -0.0f);
+ assert_fuzzy_eq!((-1.3f).fract(), -0.3f);
+ assert_fuzzy_eq!((-1.5f).fract(), -0.5f);
+ assert_fuzzy_eq!((-1.7f).fract(), -0.7f);
+ }
+
+ #[test]
+ fn test_real_consts() {
+ assert_fuzzy_eq!(Real::two_pi::<float>(), 2f * Real::pi::<float>());
+ assert_fuzzy_eq!(Real::frac_pi_2::<float>(), Real::pi::<float>() / 2f);
+ assert_fuzzy_eq!(Real::frac_pi_3::<float>(), Real::pi::<float>() / 3f);
+ assert_fuzzy_eq!(Real::frac_pi_4::<float>(), Real::pi::<float>() / 4f);
+ assert_fuzzy_eq!(Real::frac_pi_6::<float>(), Real::pi::<float>() / 6f);
+ assert_fuzzy_eq!(Real::frac_pi_8::<float>(), Real::pi::<float>() / 8f);
+ assert_fuzzy_eq!(Real::frac_1_pi::<float>(), 1f / Real::pi::<float>());
+ assert_fuzzy_eq!(Real::frac_2_pi::<float>(), 2f / Real::pi::<float>());
+ assert_fuzzy_eq!(Real::frac_2_sqrtpi::<float>(), 2f / Real::pi::<float>().sqrt());
+ assert_fuzzy_eq!(Real::sqrt2::<float>(), 2f.sqrt());
+ assert_fuzzy_eq!(Real::frac_1_sqrt2::<float>(), 1f / 2f.sqrt());
+ assert_fuzzy_eq!(Real::log2_e::<float>(), Real::e::<float>().log2());
+ assert_fuzzy_eq!(Real::log10_e::<float>(), Real::e::<float>().log10());
+ assert_fuzzy_eq!(Real::log_2::<float>(), 2f.log());
+ assert_fuzzy_eq!(Real::log_10::<float>(), 10f.log());
+ }
+
+ #[test]
+ fn test_signed() {
assert_eq!(infinity.abs(), infinity);
assert_eq!(1f.abs(), 1f);
assert_eq!(0f.abs(), 0f);
assert_eq!((-1f).abs(), 1f);
assert_eq!(neg_infinity.abs(), infinity);
assert_eq!((1f/neg_infinity).abs(), 0f);
- assert!(is_NaN(NaN.abs()));
+ assert!(NaN.abs().is_NaN());
assert_eq!(infinity.signum(), 1f);
assert_eq!(1f.signum(), 1f);
assert_eq!((-1f).signum(), -1f);
assert_eq!(neg_infinity.signum(), -1f);
assert_eq!((1f/neg_infinity).signum(), -1f);
- assert!(is_NaN(NaN.signum()));
+ assert!(NaN.signum().is_NaN());
assert!(infinity.is_positive());
assert!(1f.is_positive());
assert!(!NaN.is_negative());
}
+ #[test]
+ fn test_primitive() {
+ assert_eq!(Primitive::bits::<float>(), sys::size_of::<float>() * 8);
+ assert_eq!(Primitive::bytes::<float>(), sys::size_of::<float>());
+ }
+
#[test]
pub fn test_to_str_exact_do_decimal() {
let s = to_str_exact(5.0, 4u);
assert_eq!(from_str(~"-inf"), Some(neg_infinity));
// note: NaN != NaN, hence this slightly complex test
match from_str(~"NaN") {
- Some(f) => assert!(is_NaN(f)),
+ Some(f) => assert!(f.is_NaN()),
None => fail!()
}
// note: -0 == 0, hence these slightly more complex tests
match from_str(~"-0") {
- Some(v) if is_zero(v) => assert!(v.is_negative()),
+ Some(v) if v.is_zero() => assert!(v.is_negative()),
_ => fail!()
}
match from_str(~"0") {
- Some(v) if is_zero(v) => assert!(v.is_positive()),
+ Some(v) if v.is_zero() => assert!(v.is_positive()),
_ => fail!()
}
assert_eq!(from_str_hex(~"-inf"), Some(neg_infinity));
// note: NaN != NaN, hence this slightly complex test
match from_str_hex(~"NaN") {
- Some(f) => assert!(is_NaN(f)),
+ Some(f) => assert!(f.is_NaN()),
None => fail!()
}
// note: -0 == 0, hence these slightly more complex tests
match from_str_hex(~"-0") {
- Some(v) if is_zero(v) => assert!(v.is_negative()),
+ Some(v) if v.is_zero() => assert!(v.is_negative()),
_ => fail!()
}
match from_str_hex(~"0") {
- Some(v) if is_zero(v) => assert!(v.is_positive()),
+ Some(v) if v.is_zero() => assert!(v.is_positive()),
_ => fail!()
}
assert_eq!(from_str_hex(~"e"), Some(14.));
assert_eq!(to_str_digits(infinity, 10u), ~"inf");
assert_eq!(to_str_digits(-infinity, 10u), ~"-inf");
}
-
- #[test]
- pub fn test_round() {
- assert_eq!(round(5.8), 6.0);
- assert_eq!(round(5.2), 5.0);
- assert_eq!(round(3.0), 3.0);
- assert_eq!(round(2.5), 3.0);
- assert_eq!(round(-3.5), -4.0);
- }
}
//
use T = self::inst::T;
-use to_str::ToStr;
use from_str::FromStr;
use num::{ToStrRadix, FromStrRadix};
-use num::strconv;
-use num::Signed;
-use num;
+use num::{Zero, One, strconv};
use prelude::*;
pub use cmp::{min, max};
#[inline(always)]
pub fn quot(x: T, y: T) -> T { x / y }
-/**
- * Returns the remainder of y / x.
- *
- * # Examples
- * ~~~
- * assert!(int::rem(5 / 2) == 1);
- * ~~~
- *
- * When faced with negative numbers, the result copies the sign of the
- * dividend.
- *
- * ~~~
- * assert!(int::rem(2 / -3) == 2);
- * ~~~
- *
- * ~~~
- * assert!(int::rem(-2 / 3) == -2);
- * ~~~
- *
- */
+///
+/// Returns the remainder of y / x.
+///
+/// # Examples
+/// ~~~
+/// assert!(int::rem(5 / 2) == 1);
+/// ~~~
+///
+/// When faced with negative numbers, the result copies the sign of the
+/// dividend.
+///
+/// ~~~
+/// assert!(int::rem(2 / -3) == 2);
+/// ~~~
+///
+/// ~~~
+/// assert!(int::rem(-2 / 3) == -2);
+/// ~~~
+///
+///
#[inline(always)]
pub fn rem(x: T, y: T) -> T { x % y }
#[inline(always)]
pub fn gt(x: T, y: T) -> bool { x > y }
-/**
- * Iterate over the range [`lo`..`hi`)
- *
- * # Arguments
- *
- * * `lo` - lower bound, inclusive
- * * `hi` - higher bound, exclusive
- *
- * # Examples
- * ~~~
- * let mut sum = 0;
- * for int::range(1, 5) |i| {
- * sum += i;
- * }
- * assert!(sum == 10);
- * ~~~
- */
+///
+/// Iterate over the range [`lo`..`hi`)
+///
+/// # Arguments
+///
+/// * `lo` - lower bound, inclusive
+/// * `hi` - higher bound, exclusive
+///
+/// # Examples
+/// ~~~
+/// let mut sum = 0;
+/// for int::range(1, 5) |i| {
+/// sum += i;
+/// }
+/// assert!(sum == 10);
+/// ~~~
+///
#[inline(always)]
/// Iterate over the range [`start`,`start`+`step`..`stop`)
pub fn range_step(start: T, stop: T, step: T, it: &fn(T) -> bool) {
#[inline(always)]
pub fn abs(i: T) -> T { i.abs() }
+impl Num for T {}
+
#[cfg(notest)]
impl Ord for T {
#[inline(always)]
fn ne(&self, other: &T) -> bool { return (*self) != (*other); }
}
-impl num::Zero for T {
+impl Orderable for T {
+ #[inline(always)]
+ fn min(&self, other: &T) -> T {
+ if *self < *other { *self } else { *other }
+ }
+
+ #[inline(always)]
+ fn max(&self, other: &T) -> T {
+ if *self > *other { *self } else { *other }
+ }
+
+ #[inline(always)]
+ fn clamp(&self, mn: &T, mx: &T) -> T {
+ if *self > *mx { *mx } else
+ if *self < *mn { *mn } else { *self }
+ }
+}
+
+impl Zero for T {
#[inline(always)]
fn zero() -> T { 0 }
+
+ #[inline(always)]
+ fn is_zero(&self) -> bool { *self == 0 }
}
-impl num::One for T {
+impl One for T {
#[inline(always)]
fn one() -> T { 1 }
}
#[inline(always)]
fn div(&self, other: &T) -> T { *self / *other }
}
-
-#[cfg(stage1,notest)]
-#[cfg(stage2,notest)]
-#[cfg(stage3,notest)]
+#[cfg(not(stage0),notest)]
impl Quot<T,T> for T {
- /**
- * Returns the integer quotient, truncated towards 0. As this behaviour reflects
- * the underlying machine implementation it is more efficient than `Natural::div`.
- *
- * # Examples
- *
- * ~~~
- * assert!( 8 / 3 == 2);
- * assert!( 8 / -3 == -2);
- * assert!(-8 / 3 == -2);
- * assert!(-8 / -3 == 2);
-
- * assert!( 1 / 2 == 0);
- * assert!( 1 / -2 == 0);
- * assert!(-1 / 2 == 0);
- * assert!(-1 / -2 == 0);
- * ~~~
- */
+ ///
+ /// Returns the integer quotient, truncated towards 0. As this behaviour reflects
+ /// the underlying machine implementation it is more efficient than `Natural::div`.
+ ///
+ /// # Examples
+ ///
+ /// ~~~
+ /// assert!( 8 / 3 == 2);
+ /// assert!( 8 / -3 == -2);
+ /// assert!(-8 / 3 == -2);
+ /// assert!(-8 / -3 == 2);
+
+ /// assert!( 1 / 2 == 0);
+ /// assert!( 1 / -2 == 0);
+ /// assert!(-1 / 2 == 0);
+ /// assert!(-1 / -2 == 0);
+ /// ~~~
+ ///
#[inline(always)]
fn quot(&self, other: &T) -> T { *self / *other }
}
#[inline(always)]
fn modulo(&self, other: &T) -> T { *self % *other }
}
-
-#[cfg(stage1,notest)]
-#[cfg(stage2,notest)]
-#[cfg(stage3,notest)]
+#[cfg(not(stage0),notest)]
impl Rem<T,T> for T {
- /**
- * Returns the integer remainder after division, satisfying:
- *
- * ~~~
- * assert!((n / d) * d + (n % d) == n)
- * ~~~
- *
- * # Examples
- *
- * ~~~
- * assert!( 8 % 3 == 2);
- * assert!( 8 % -3 == 2);
- * assert!(-8 % 3 == -2);
- * assert!(-8 % -3 == -2);
-
- * assert!( 1 % 2 == 1);
- * assert!( 1 % -2 == 1);
- * assert!(-1 % 2 == -1);
- * assert!(-1 % -2 == -1);
- * ~~~
- */
+ ///
+ /// Returns the integer remainder after division, satisfying:
+ ///
+ /// ~~~
+ /// assert!((n / d) * d + (n % d) == n)
+ /// ~~~
+ ///
+ /// # Examples
+ ///
+ /// ~~~
+ /// assert!( 8 % 3 == 2);
+ /// assert!( 8 % -3 == 2);
+ /// assert!(-8 % 3 == -2);
+ /// assert!(-8 % -3 == -2);
+
+ /// assert!( 1 % 2 == 1);
+ /// assert!( 1 % -2 == 1);
+ /// assert!(-1 % 2 == -1);
+ /// assert!(-1 % -2 == -1);
+ /// ~~~
+ ///
#[inline(always)]
fn rem(&self, other: &T) -> T { *self % *other }
}
if self.is_negative() { -*self } else { *self }
}
- /**
- * # Returns
- *
- * - `0` if the number is zero
- * - `1` if the number is positive
- * - `-1` if the number is negative
- */
+ ///
+ /// # Returns
+ ///
+ /// - `0` if the number is zero
+ /// - `1` if the number is positive
+ /// - `-1` if the number is negative
+ ///
#[inline(always)]
fn signum(&self) -> T {
match *self {
fn is_negative(&self) -> bool { *self < 0 }
}
-impl Natural for T {
- /**
- * Floored integer division
- *
- * # Examples
- *
- * ~~~
- * assert!(( 8).div( 3) == 2);
- * assert!(( 8).div(-3) == -3);
- * assert!((-8).div( 3) == -3);
- * assert!((-8).div(-3) == 2);
- *
- * assert!(( 1).div( 2) == 0);
- * assert!(( 1).div(-2) == -1);
- * assert!((-1).div( 2) == -1);
- * assert!((-1).div(-2) == 0);
- * ~~~
- */
- #[inline(always)]
- fn div(&self, other: T) -> T {
+impl Integer for T {
+ ///
+ /// Floored integer division
+ ///
+ /// # Examples
+ ///
+ /// ~~~
+ /// assert!(( 8).div( 3) == 2);
+ /// assert!(( 8).div(-3) == -3);
+ /// assert!((-8).div( 3) == -3);
+ /// assert!((-8).div(-3) == 2);
+ ///
+ /// assert!(( 1).div( 2) == 0);
+ /// assert!(( 1).div(-2) == -1);
+ /// assert!((-1).div( 2) == -1);
+ /// assert!((-1).div(-2) == 0);
+ /// ~~~
+ ///
+ #[inline(always)]
+ fn div(&self, other: &T) -> T {
// Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
// December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
match self.quot_rem(other) {
- (q, r) if (r > 0 && other < 0)
- || (r < 0 && other > 0) => q - 1,
- (q, _) => q,
+ (q, r) if (r > 0 && *other < 0)
+ || (r < 0 && *other > 0) => q - 1,
+ (q, _) => q,
}
}
- /**
- * Integer modulo, satisfying:
- *
- * ~~~
- * assert!(n.div(d) * d + n.modulo(d) == n)
- * ~~~
- *
- * # Examples
- *
- * ~~~
- * assert!(( 8).modulo( 3) == 2);
- * assert!(( 8).modulo(-3) == -1);
- * assert!((-8).modulo( 3) == 1);
- * assert!((-8).modulo(-3) == -2);
- *
- * assert!(( 1).modulo( 2) == 1);
- * assert!(( 1).modulo(-2) == -1);
- * assert!((-1).modulo( 2) == 1);
- * assert!((-1).modulo(-2) == -1);
- * ~~~
- */
- #[inline(always)]
- fn modulo(&self, other: T) -> T {
+ ///
+ /// Integer modulo, satisfying:
+ ///
+ /// ~~~
+ /// assert!(n.div(d) * d + n.modulo(d) == n)
+ /// ~~~
+ ///
+ /// # Examples
+ ///
+ /// ~~~
+ /// assert!(( 8).modulo( 3) == 2);
+ /// assert!(( 8).modulo(-3) == -1);
+ /// assert!((-8).modulo( 3) == 1);
+ /// assert!((-8).modulo(-3) == -2);
+ ///
+ /// assert!(( 1).modulo( 2) == 1);
+ /// assert!(( 1).modulo(-2) == -1);
+ /// assert!((-1).modulo( 2) == 1);
+ /// assert!((-1).modulo(-2) == -1);
+ /// ~~~
+ ///
+ #[inline(always)]
+ fn modulo(&self, other: &T) -> T {
// Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
// December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
- match *self % other {
- r if (r > 0 && other < 0)
- || (r < 0 && other > 0) => r + other,
- r => r,
+ match *self % *other {
+ r if (r > 0 && *other < 0)
+ || (r < 0 && *other > 0) => r + *other,
+ r => r,
}
}
/// Calculates `div` and `modulo` simultaneously
#[inline(always)]
- fn div_mod(&self, other: T) -> (T,T) {
+ fn div_mod(&self, other: &T) -> (T,T) {
// Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
// December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
match self.quot_rem(other) {
- (q, r) if (r > 0 && other < 0)
- || (r < 0 && other > 0) => (q - 1, r + other),
- (q, r) => (q, r),
+ (q, r) if (r > 0 && *other < 0)
+ || (r < 0 && *other > 0) => (q - 1, r + *other),
+ (q, r) => (q, r),
}
}
/// Calculates `quot` (`\`) and `rem` (`%`) simultaneously
#[inline(always)]
- fn quot_rem(&self, other: T) -> (T,T) {
- (*self / other, *self % other)
+ fn quot_rem(&self, other: &T) -> (T,T) {
+ (*self / *other, *self % *other)
}
- /**
- * Calculates the Greatest Common Divisor (GCD) of the number and `other`
- *
- * The result is always positive
- */
+ ///
+ /// Calculates the Greatest Common Divisor (GCD) of the number and `other`
+ ///
+ /// The result is always positive
+ ///
#[inline(always)]
- fn gcd(&self, other: T) -> T {
+ fn gcd(&self, other: &T) -> T {
// Use Euclid's algorithm
- let mut m = *self, n = other;
+ let mut m = *self, n = *other;
while m != 0 {
let temp = m;
m = n % temp;
n.abs()
}
- /**
- * Calculates the Lowest Common Multiple (LCM) of the number and `other`
- */
+ ///
+ /// Calculates the Lowest Common Multiple (LCM) of the number and `other`
+ ///
#[inline(always)]
- fn lcm(&self, other: T) -> T {
- ((*self * other) / self.gcd(other)).abs() // should not have to recaluculate abs
+ fn lcm(&self, other: &T) -> T {
+ ((*self * *other) / self.gcd(other)).abs() // should not have to recaluculate abs
}
/// Returns `true` if the number can be divided by `other` without leaving a remainder
#[inline(always)]
- fn divisible_by(&self, other: T) -> bool { *self % other == 0 }
+ fn is_multiple_of(&self, other: &T) -> bool { *self % *other == 0 }
/// Returns `true` if the number is divisible by `2`
#[inline(always)]
- fn is_even(&self) -> bool { self.divisible_by(2) }
+ fn is_even(&self) -> bool { self.is_multiple_of(&2) }
/// Returns `true` if the number is not divisible by `2`
#[inline(always)]
fn is_odd(&self) -> bool { !self.is_even() }
}
+impl Bitwise for T {}
+
#[cfg(notest)]
impl BitOr<T,T> for T {
#[inline(always)]
fn not(&self) -> T { !*self }
}
+impl Bounded for T {
+ #[inline(always)]
+ fn min_value() -> T { min_value }
+
+ #[inline(always)]
+ fn max_value() -> T { max_value }
+}
+
+impl Int for T {}
+
// String conversion functions and impl str -> num
/// Parse a string as a number in base 10.
use super::inst::T;
use prelude::*;
+ #[test]
+ fn test_num() {
+ num::test_num(10 as T, 2 as T);
+ }
+
+ #[test]
+ fn test_orderable() {
+ assert_eq!((1 as T).min(&(2 as T)), 1 as T);
+ assert_eq!((2 as T).min(&(1 as T)), 1 as T);
+ assert_eq!((1 as T).max(&(2 as T)), 2 as T);
+ assert_eq!((2 as T).max(&(1 as T)), 2 as T);
+ assert_eq!((1 as T).clamp(&(2 as T), &(4 as T)), 2 as T);
+ assert_eq!((8 as T).clamp(&(2 as T), &(4 as T)), 4 as T);
+ assert_eq!((3 as T).clamp(&(2 as T), &(4 as T)), 3 as T);
+ }
+
#[test]
pub fn test_signed() {
assert_eq!((1 as T).abs(), 1 as T);
assert!((-1 as T).is_negative());
}
- /**
- * Checks that the division rule holds for:
- *
- * - `n`: numerator (dividend)
- * - `d`: denominator (divisor)
- * - `qr`: quotient and remainder
- */
+ ///
+ /// Checks that the division rule holds for:
+ ///
+ /// - `n`: numerator (dividend)
+ /// - `d`: denominator (divisor)
+ /// - `qr`: quotient and remainder
+ ///
#[cfg(test)]
- fn test_division_rule(nd: (T,T), qr: (T,T)) {
- let (n,d) = nd,
- (q,r) = qr;
-
+ fn test_division_rule((n,d): (T,T), (q,r): (T,T)) {
assert_eq!(d * q + r, n);
}
fn test_nd_qr(nd: (T,T), qr: (T,T)) {
let (n,d) = nd;
let separate_quot_rem = (n / d, n % d);
- let combined_quot_rem = n.quot_rem(d);
+ let combined_quot_rem = n.quot_rem(&d);
assert_eq!(separate_quot_rem, qr);
assert_eq!(combined_quot_rem, qr);
fn test_div_mod() {
fn test_nd_dm(nd: (T,T), dm: (T,T)) {
let (n,d) = nd;
- let separate_div_mod = (n.div(d), n.modulo(d));
- let combined_div_mod = n.div_mod(d);
+ let separate_div_mod = (n.div(&d), n.modulo(&d));
+ let combined_div_mod = n.div_mod(&d);
assert_eq!(separate_div_mod, dm);
assert_eq!(combined_div_mod, dm);
#[test]
fn test_gcd() {
- assert_eq!((10 as T).gcd(2), 2 as T);
- assert_eq!((10 as T).gcd(3), 1 as T);
- assert_eq!((0 as T).gcd(3), 3 as T);
- assert_eq!((3 as T).gcd(3), 3 as T);
- assert_eq!((56 as T).gcd(42), 14 as T);
- assert_eq!((3 as T).gcd(-3), 3 as T);
- assert_eq!((-6 as T).gcd(3), 3 as T);
- assert_eq!((-4 as T).gcd(-2), 2 as T);
+ assert_eq!((10 as T).gcd(&2), 2 as T);
+ assert_eq!((10 as T).gcd(&3), 1 as T);
+ assert_eq!((0 as T).gcd(&3), 3 as T);
+ assert_eq!((3 as T).gcd(&3), 3 as T);
+ assert_eq!((56 as T).gcd(&42), 14 as T);
+ assert_eq!((3 as T).gcd(&-3), 3 as T);
+ assert_eq!((-6 as T).gcd(&3), 3 as T);
+ assert_eq!((-4 as T).gcd(&-2), 2 as T);
}
#[test]
fn test_lcm() {
- assert_eq!((1 as T).lcm(0), 0 as T);
- assert_eq!((0 as T).lcm(1), 0 as T);
- assert_eq!((1 as T).lcm(1), 1 as T);
- assert_eq!((-1 as T).lcm(1), 1 as T);
- assert_eq!((1 as T).lcm(-1), 1 as T);
- assert_eq!((-1 as T).lcm(-1), 1 as T);
- assert_eq!((8 as T).lcm(9), 72 as T);
- assert_eq!((11 as T).lcm(5), 55 as T);
+ assert_eq!((1 as T).lcm(&0), 0 as T);
+ assert_eq!((0 as T).lcm(&1), 0 as T);
+ assert_eq!((1 as T).lcm(&1), 1 as T);
+ assert_eq!((-1 as T).lcm(&1), 1 as T);
+ assert_eq!((1 as T).lcm(&-1), 1 as T);
+ assert_eq!((-1 as T).lcm(&-1), 1 as T);
+ assert_eq!((8 as T).lcm(&9), 72 as T);
+ assert_eq!((11 as T).lcm(&5), 55 as T);
}
#[test]
- fn test_bitwise_ops() {
+ fn test_bitwise() {
assert_eq!(0b1110 as T, (0b1100 as T).bitor(&(0b1010 as T)));
assert_eq!(0b1000 as T, (0b1100 as T).bitand(&(0b1010 as T)));
assert_eq!(0b0110 as T, (0b1100 as T).bitxor(&(0b1010 as T)));
assert_eq!(-(0b11 as T) - (1 as T), (0b11 as T).not());
}
+ #[test]
+ fn test_multiple_of() {
+ assert!((6 as T).is_multiple_of(&(6 as T)));
+ assert!((6 as T).is_multiple_of(&(3 as T)));
+ assert!((6 as T).is_multiple_of(&(1 as T)));
+ assert!((-8 as T).is_multiple_of(&(4 as T)));
+ assert!((8 as T).is_multiple_of(&(-1 as T)));
+ assert!((-8 as T).is_multiple_of(&(-2 as T)));
+ }
+
+ #[test]
+ fn test_even() {
+ assert_eq!((-4 as T).is_even(), true);
+ assert_eq!((-3 as T).is_even(), false);
+ assert_eq!((-2 as T).is_even(), true);
+ assert_eq!((-1 as T).is_even(), false);
+ assert_eq!((0 as T).is_even(), true);
+ assert_eq!((1 as T).is_even(), false);
+ assert_eq!((2 as T).is_even(), true);
+ assert_eq!((3 as T).is_even(), false);
+ assert_eq!((4 as T).is_even(), true);
+ }
+
+ #[test]
+ fn test_odd() {
+ assert_eq!((-4 as T).is_odd(), false);
+ assert_eq!((-3 as T).is_odd(), true);
+ assert_eq!((-2 as T).is_odd(), false);
+ assert_eq!((-1 as T).is_odd(), true);
+ assert_eq!((0 as T).is_odd(), false);
+ assert_eq!((1 as T).is_odd(), true);
+ assert_eq!((2 as T).is_odd(), false);
+ assert_eq!((3 as T).is_odd(), true);
+ assert_eq!((4 as T).is_odd(), false);
+ }
+
+ #[test]
+ fn test_bitcount() {
+ assert_eq!((0b010101 as T).population_count(), 3);
+ }
+
+ #[test]
+ fn test_primitive() {
+ assert_eq!(Primitive::bits::<T>(), sys::size_of::<T>() * 8);
+ assert_eq!(Primitive::bytes::<T>(), sys::size_of::<T>());
+ }
+
#[test]
fn test_from_str() {
assert_eq!(from_str(~"0"), Some(0 as T));
//! Operations and constants for `i16`
mod inst {
+ use num::{Primitive, BitCount};
+ use unstable::intrinsics;
+
pub type T = i16;
pub static bits: uint = ::u16::bits;
+
+ impl Primitive for i16 {
+ #[inline(always)]
+ fn bits() -> uint { 16 }
+
+ #[inline(always)]
+ fn bytes() -> uint { Primitive::bits::<i16>() / 8 }
+ }
+
+ impl BitCount for i16 {
+ /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
+ #[inline(always)]
+ fn population_count(&self) -> i16 { unsafe { intrinsics::ctpop16(*self) } }
+
+ /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
+ #[inline(always)]
+ fn leading_zeros(&self) -> i16 { unsafe { intrinsics::ctlz16(*self) } }
+
+ /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
+ #[inline(always)]
+ fn trailing_zeros(&self) -> i16 { unsafe { intrinsics::cttz16(*self) } }
+ }
}
//! Operations and constants for `i32`
mod inst {
+ use num::{Primitive, BitCount};
+ use unstable::intrinsics;
+
pub type T = i32;
pub static bits: uint = ::u32::bits;
+
+ impl Primitive for i32 {
+ #[inline(always)]
+ fn bits() -> uint { 32 }
+
+ #[inline(always)]
+ fn bytes() -> uint { Primitive::bits::<i32>() / 8 }
+ }
+
+ impl BitCount for i32 {
+ /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
+ #[inline(always)]
+ fn population_count(&self) -> i32 { unsafe { intrinsics::ctpop32(*self) } }
+
+ /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
+ #[inline(always)]
+ fn leading_zeros(&self) -> i32 { unsafe { intrinsics::ctlz32(*self) } }
+
+ /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
+ #[inline(always)]
+ fn trailing_zeros(&self) -> i32 { unsafe { intrinsics::cttz32(*self) } }
+ }
}
//! Operations and constants for `i64`
mod inst {
+ use num::{Primitive, BitCount};
+ use unstable::intrinsics;
+
pub type T = i64;
pub static bits: uint = ::u64::bits;
+
+ impl Primitive for i64 {
+ #[inline(always)]
+ fn bits() -> uint { 64 }
+
+ #[inline(always)]
+ fn bytes() -> uint { Primitive::bits::<i64>() / 8 }
+ }
+
+ impl BitCount for i64 {
+ /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
+ #[inline(always)]
+ fn population_count(&self) -> i64 { unsafe { intrinsics::ctpop64(*self) } }
+
+ /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
+ #[inline(always)]
+ fn leading_zeros(&self) -> i64 { unsafe { intrinsics::ctlz64(*self) } }
+
+ /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
+ #[inline(always)]
+ fn trailing_zeros(&self) -> i64 { unsafe { intrinsics::cttz64(*self) } }
+ }
}
//! Operations and constants for `i8`
mod inst {
+ use num::{Primitive, BitCount};
+ use unstable::intrinsics;
+
pub type T = i8;
pub static bits: uint = ::u8::bits;
+
+ impl Primitive for i8 {
+ #[inline(always)]
+ fn bits() -> uint { 8 }
+
+ #[inline(always)]
+ fn bytes() -> uint { Primitive::bits::<i8>() / 8 }
+ }
+
+ impl BitCount for i8 {
+ /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
+ #[inline(always)]
+ fn population_count(&self) -> i8 { unsafe { intrinsics::ctpop8(*self) } }
+
+ /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
+ #[inline(always)]
+ fn leading_zeros(&self) -> i8 { unsafe { intrinsics::ctlz8(*self) } }
+
+ /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
+ #[inline(always)]
+ fn trailing_zeros(&self) -> i8 { unsafe { intrinsics::cttz8(*self) } }
+ }
}
pub use self::inst::pow;
mod inst {
+ use num::{Primitive, BitCount};
+
pub type T = int;
pub static bits: uint = ::uint::bits;
+ impl Primitive for int {
+ #[cfg(target_word_size = "32")]
+ #[inline(always)]
+ fn bits() -> uint { 32 }
+
+ #[cfg(target_word_size = "64")]
+ #[inline(always)]
+ fn bits() -> uint { 64 }
+
+ #[inline(always)]
+ fn bytes() -> uint { Primitive::bits::<int>() / 8 }
+ }
+
+ #[cfg(target_word_size = "32")]
+ #[inline(always)]
+ impl BitCount for int {
+ /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
+ #[inline(always)]
+ fn population_count(&self) -> int { (*self as i32).population_count() as int }
+
+ /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
+ #[inline(always)]
+ fn leading_zeros(&self) -> int { (*self as i32).leading_zeros() as int }
+
+ /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
+ #[inline(always)]
+ fn trailing_zeros(&self) -> int { (*self as i32).trailing_zeros() as int }
+ }
+
+ #[cfg(target_word_size = "64")]
+ #[inline(always)]
+ impl BitCount for int {
+ /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
+ #[inline(always)]
+ fn population_count(&self) -> int { (*self as i64).population_count() as int }
+
+ /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
+ #[inline(always)]
+ fn leading_zeros(&self) -> int { (*self as i64).leading_zeros() as int }
+
+ /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
+ #[inline(always)]
+ fn trailing_zeros(&self) -> int { (*self as i64).trailing_zeros() as int }
+ }
+
/// Returns `base` raised to the power of `exponent`
pub fn pow(base: int, exponent: uint) -> int {
if exponent == 0u {
use Quot = ops::Div;
#[cfg(stage0)]
use Rem = ops::Modulo;
-#[cfg(stage1)]
-#[cfg(stage2)]
-#[cfg(stage3)]
+#[cfg(not(stage0))]
use ops::{Add, Sub, Mul, Quot, Rem, Neg};
+use ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr};
use option::Option;
use kinds::Copy;
pub mod strconv;
+///
+/// The base trait for numeric types
+///
pub trait Num: Eq + Zero + One
+ Neg<Self>
+ Add<Self,Self>
+ Quot<Self,Self>
+ Rem<Self,Self> {}
-impl Num for u8 {}
-impl Num for u16 {}
-impl Num for u32 {}
-impl Num for u64 {}
-impl Num for uint {}
-impl Num for i8 {}
-impl Num for i16 {}
-impl Num for i32 {}
-impl Num for i64 {}
-impl Num for int {}
-impl Num for f32 {}
-impl Num for f64 {}
-impl Num for float {}
-
pub trait IntConvertible {
fn to_int(&self) -> int;
fn from_int(n: int) -> Self;
}
+pub trait Orderable: Ord {
+ // These should be methods on `Ord`, with overridable default implementations. We don't want
+ // to encumber all implementors of Ord by requiring them to implement these functions, but at
+ // the same time we want to be able to take advantage of the speed of the specific numeric
+ // functions (like the `fmin` and `fmax` intrinsics).
+ fn min(&self, other: &Self) -> Self;
+ fn max(&self, other: &Self) -> Self;
+ fn clamp(&self, mn: &Self, mx: &Self) -> Self;
+}
+
pub trait Zero {
- fn zero() -> Self;
+ fn zero() -> Self; // FIXME (#5527): This should be an associated constant
+ fn is_zero(&self) -> bool;
}
pub trait One {
- fn one() -> Self;
+ fn one() -> Self; // FIXME (#5527): This should be an associated constant
}
pub trait Signed: Num
if v < Zero::zero() { v.neg() } else { v }
}
-pub trait Natural: Num
- + Ord
+pub trait Integer: Num
+ + Orderable
+ Quot<Self,Self>
+ Rem<Self,Self> {
- fn div(&self, other: Self) -> Self;
- fn modulo(&self, other: Self) -> Self;
- fn div_mod(&self, other: Self) -> (Self,Self);
- fn quot_rem(&self, other: Self) -> (Self,Self);
-
- fn gcd(&self, other: Self) -> Self;
- fn lcm(&self, other: Self) -> Self;
- fn divisible_by(&self, other: Self) -> bool;
+ fn div(&self, other: &Self) -> Self;
+ fn modulo(&self, other: &Self) -> Self;
+ fn div_mod(&self, other: &Self) -> (Self,Self);
+ fn quot_rem(&self, other: &Self) -> (Self,Self);
+
+ fn gcd(&self, other: &Self) -> Self;
+ fn lcm(&self, other: &Self) -> Self;
+
+ fn is_multiple_of(&self, other: &Self) -> bool;
fn is_even(&self) -> bool;
fn is_odd(&self) -> bool;
}
pub trait Round {
- fn round(&self, mode: RoundMode) -> Self;
-
fn floor(&self) -> Self;
- fn ceil(&self) -> Self;
+ fn ceil(&self) -> Self;
+ fn round(&self) -> Self;
+ fn trunc(&self) -> Self;
fn fract(&self) -> Self;
}
-pub enum RoundMode {
- RoundDown,
- RoundUp,
- RoundToZero,
- RoundFromZero
+pub trait Fractional: Num
+ + Orderable
+ + Round
+ + Quot<Self,Self> {
+ fn recip(&self) -> Self;
+}
+
+pub trait Algebraic {
+ fn pow(&self, n: Self) -> Self;
+ fn sqrt(&self) -> Self;
+ fn rsqrt(&self) -> Self;
+ fn cbrt(&self) -> Self;
+ fn hypot(&self, other: Self) -> Self;
+}
+
+pub trait Trigonometric {
+ fn sin(&self) -> Self;
+ fn cos(&self) -> Self;
+ fn tan(&self) -> Self;
+ fn asin(&self) -> Self;
+ fn acos(&self) -> Self;
+ fn atan(&self) -> Self;
+ fn atan2(&self, other: Self) -> Self;
+}
+
+pub trait Exponential {
+ fn exp(&self) -> Self;
+ fn exp2(&self) -> Self;
+ fn expm1(&self) -> Self;
+ fn log(&self) -> Self;
+ fn log2(&self) -> Self;
+ fn log10(&self) -> Self;
+}
+
+pub trait Hyperbolic: Exponential {
+ fn sinh(&self) -> Self;
+ fn cosh(&self) -> Self;
+ fn tanh(&self) -> Self;
}
-/**
- * Cast from one machine scalar to another
- *
- * # Example
- *
- * ~~~
- * let twenty: f32 = num::cast(0x14);
- * assert_eq!(twenty, 20f32);
- * ~~~
- */
+///
+/// Defines constants and methods common to real numbers
+///
+pub trait Real: Signed
+ + Fractional
+ + Algebraic
+ + Trigonometric
+ + Hyperbolic {
+ // Common Constants
+ // FIXME (#5527): These should be associated constants
+ fn pi() -> Self;
+ fn two_pi() -> Self;
+ fn frac_pi_2() -> Self;
+ fn frac_pi_3() -> Self;
+ fn frac_pi_4() -> Self;
+ fn frac_pi_6() -> Self;
+ fn frac_pi_8() -> Self;
+ fn frac_1_pi() -> Self;
+ fn frac_2_pi() -> Self;
+ fn frac_2_sqrtpi() -> Self;
+ fn sqrt2() -> Self;
+ fn frac_1_sqrt2() -> Self;
+ fn e() -> Self;
+ fn log2_e() -> Self;
+ fn log10_e() -> Self;
+ fn log_2() -> Self;
+ fn log_10() -> Self;
+
+ // Angular conversions
+ fn to_degrees(&self) -> Self;
+ fn to_radians(&self) -> Self;
+}
+
+///
+/// Methods that are harder to implement and not commonly used.
+///
+pub trait RealExt: Real {
+ // FIXME (#5527): usages of `int` should be replaced with an associated
+ // integer type once these are implemented
+
+ // Gamma functions
+ fn lgamma(&self) -> (int, Self);
+ fn tgamma(&self) -> Self;
+
+ // Bessel functions
+ fn j0(&self) -> Self;
+ fn j1(&self) -> Self;
+ fn jn(&self, n: int) -> Self;
+ fn y0(&self) -> Self;
+ fn y1(&self) -> Self;
+ fn yn(&self, n: int) -> Self;
+}
+
+///
+/// Collects the bitwise operators under one trait.
+///
+pub trait Bitwise: Not<Self>
+ + BitAnd<Self,Self>
+ + BitOr<Self,Self>
+ + BitXor<Self,Self>
+ + Shl<Self,Self>
+ + Shr<Self,Self> {}
+
+pub trait BitCount {
+ fn population_count(&self) -> Self;
+ fn leading_zeros(&self) -> Self;
+ fn trailing_zeros(&self) -> Self;
+}
+
+pub trait Bounded {
+ // FIXME (#5527): These should be associated constants
+ fn min_value() -> Self;
+ fn max_value() -> Self;
+}
+
+///
+/// Specifies the available operations common to all of Rust's core numeric primitives.
+/// These may not always make sense from a purely mathematical point of view, but
+/// may be useful for systems programming.
+///
+pub trait Primitive: Num
+ + NumCast
+ + Bounded
+ + Neg<Self>
+ + Add<Self,Self>
+ + Sub<Self,Self>
+ + Mul<Self,Self>
+ + Quot<Self,Self>
+ + Rem<Self,Self> {
+ // FIXME (#5527): These should be associated constants
+ fn bits() -> uint;
+ fn bytes() -> uint;
+}
+
+///
+/// A collection of traits relevant to primitive signed and unsigned integers
+///
+pub trait Int: Integer
+ + Primitive
+ + Bitwise
+ + BitCount {}
+
+///
+/// Primitive floating point numbers
+///
+pub trait Float: Real
+ + Signed
+ + Primitive {
+ // FIXME (#5527): These should be associated constants
+ fn NaN() -> Self;
+ fn infinity() -> Self;
+ fn neg_infinity() -> Self;
+ fn neg_zero() -> Self;
+
+ fn is_NaN(&self) -> bool;
+ fn is_infinite(&self) -> bool;
+ fn is_finite(&self) -> bool;
+
+ fn mantissa_digits() -> uint;
+ fn digits() -> uint;
+ fn epsilon() -> Self;
+ fn min_exp() -> int;
+ fn max_exp() -> int;
+ fn min_10_exp() -> int;
+ fn max_10_exp() -> int;
+
+ fn mul_add(&self, a: Self, b: Self) -> Self;
+ fn next_after(&self, other: Self) -> Self;
+}
+
+///
+/// Cast from one machine scalar to another
+///
+/// # Example
+///
+/// ~~~
+/// let twenty: f32 = num::cast(0x14);
+/// assert_eq!(twenty, 20f32);
+/// ~~~
+///
#[inline(always)]
pub fn cast<T:NumCast,U:NumCast>(n: T) -> U {
NumCast::from(n)
}
-/**
- * An interface for casting between machine scalars
- */
+///
+/// An interface for casting between machine scalars
+///
pub trait NumCast {
fn from<T:NumCast>(n: T) -> Self;
pub fn from_str_radix(str: &str, radix: uint) -> Option<Self>;
}
-// Generic math functions:
-
-/**
- * Calculates a power to a given radix, optimized for uint `pow` and `radix`.
- *
- * Returns `radix^pow` as `T`.
- *
- * Note:
- * Also returns `1` for `0^0`, despite that technically being an
- * undefined number. The reason for this is twofold:
- * - If code written to use this function cares about that special case, it's
- * probably going to catch it before making the call.
- * - If code written to use this function doesn't care about it, it's
- * probably assuming that `x^0` always equals `1`.
- */
+///
+/// Calculates a power to a given radix, optimized for uint `pow` and `radix`.
+///
+/// Returns `radix^pow` as `T`.
+///
+/// Note:
+/// Also returns `1` for `0^0`, despite that technically being an
+/// undefined number. The reason for this is twofold:
+/// - If code written to use this function cares about that special case, it's
+/// probably going to catch it before making the call.
+/// - If code written to use this function doesn't care about it, it's
+/// probably assuming that `x^0` always equals `1`.
+///
pub fn pow_with_uint<T:NumCast+One+Zero+Copy+Quot<T,T>+Mul<T,T>>(
radix: uint, pow: uint) -> T {
let _0: T = Zero::zero();
total
}
+/// Helper function for testing numeric operations
#[cfg(stage0,test)]
-fn test_num<T:Num + NumCast>(ten: T, two: T) {
+pub fn test_num<T:Num + NumCast>(ten: T, two: T) {
assert_eq!(ten.add(&two), cast(12));
assert_eq!(ten.sub(&two), cast(8));
assert_eq!(ten.mul(&two), cast(20));
#[cfg(stage1,test)]
#[cfg(stage2,test)]
#[cfg(stage3,test)]
-fn test_num<T:Num + NumCast>(ten: T, two: T) {
+pub fn test_num<T:Num + NumCast>(ten: T, two: T) {
assert_eq!(ten.add(&two), cast(12));
assert_eq!(ten.sub(&two), cast(8));
assert_eq!(ten.mul(&two), cast(20));
assert_eq!(ten.rem(&two), ten % two);
}
-#[test] fn test_u8_num() { test_num(10u8, 2u8) }
-#[test] fn test_u16_num() { test_num(10u16, 2u16) }
-#[test] fn test_u32_num() { test_num(10u32, 2u32) }
-#[test] fn test_u64_num() { test_num(10u64, 2u64) }
-#[test] fn test_uint_num() { test_num(10u, 2u) }
-#[test] fn test_i8_num() { test_num(10i8, 2i8) }
-#[test] fn test_i16_num() { test_num(10i16, 2i16) }
-#[test] fn test_i32_num() { test_num(10i32, 2i32) }
-#[test] fn test_i64_num() { test_num(10i64, 2i64) }
-#[test] fn test_int_num() { test_num(10i, 2i) }
-#[test] fn test_f32_num() { test_num(10f32, 2f32) }
-#[test] fn test_f64_num() { test_num(10f64, 2f64) }
-#[test] fn test_float_num() { test_num(10f, 2f) }
-
macro_rules! test_cast_20(
($_20:expr) => ({
let _20 = $_20;
use T = self::inst::T;
use T_SIGNED = self::inst::T_SIGNED;
-use to_str::ToStr;
use from_str::FromStr;
use num::{ToStrRadix, FromStrRadix};
-use num::strconv;
-use num::Unsigned;
-use num;
-use option::Option;
+use num::{Zero, One, strconv};
use prelude::*;
pub use cmp::{min, max};
pub fn gt(x: T, y: T) -> bool { x > y }
#[inline(always)]
-/**
- * Iterate over the range [`start`,`start`+`step`..`stop`)
- *
- */
+///
+/// Iterate over the range [`start`,`start`+`step`..`stop`)
+///
pub fn range_step(start: T,
stop: T,
step: T_SIGNED,
max_value ^ i
}
+impl Num for T {}
+
#[cfg(notest)]
impl Ord for T {
#[inline(always)]
fn ne(&self, other: &T) -> bool { return (*self) != (*other); }
}
-impl num::Zero for T {
+impl Orderable for T {
+ #[inline(always)]
+ fn min(&self, other: &T) -> T {
+ if *self < *other { *self } else { *other }
+ }
+
+ #[inline(always)]
+ fn max(&self, other: &T) -> T {
+ if *self > *other { *self } else { *other }
+ }
+
+ #[inline(always)]
+ fn clamp(&self, mn: &T, mx: &T) -> T {
+ if *self > *mx { *mx } else
+ if *self < *mn { *mn } else { *self }
+ }
+}
+
+impl Zero for T {
#[inline(always)]
fn zero() -> T { 0 }
+
+ #[inline(always)]
+ fn is_zero(&self) -> bool { *self == 0 }
}
-impl num::One for T {
+impl One for T {
#[inline(always)]
fn one() -> T { 1 }
}
#[inline(always)]
fn div(&self, other: &T) -> T { *self / *other }
}
-
-#[cfg(stage1,notest)]
-#[cfg(stage2,notest)]
-#[cfg(stage3,notest)]
+#[cfg(not(stage0),notest)]
impl Quot<T,T> for T {
#[inline(always)]
fn quot(&self, other: &T) -> T { *self / *other }
#[inline(always)]
fn modulo(&self, other: &T) -> T { *self % *other }
}
-
-#[cfg(stage1,notest)]
-#[cfg(stage2,notest)]
-#[cfg(stage3,notest)]
+#[cfg(not(stage0),notest)]
impl Rem<T,T> for T {
#[inline(always)]
fn rem(&self, other: &T) -> T { *self % *other }
impl Unsigned for T {}
-impl Natural for T {
+impl Integer for T {
/// Unsigned integer division. Returns the same result as `quot` (`/`).
#[inline(always)]
- fn div(&self, other: T) -> T { *self / other }
+ fn div(&self, other: &T) -> T { *self / *other }
/// Unsigned integer modulo operation. Returns the same result as `rem` (`%`).
#[inline(always)]
- fn modulo(&self, other: T) -> T { *self / other }
+ fn modulo(&self, other: &T) -> T { *self / *other }
/// Calculates `div` and `modulo` simultaneously
#[inline(always)]
- fn div_mod(&self, other: T) -> (T,T) {
- (*self / other, *self % other)
+ fn div_mod(&self, other: &T) -> (T,T) {
+ (*self / *other, *self % *other)
}
/// Calculates `quot` (`\`) and `rem` (`%`) simultaneously
#[inline(always)]
- fn quot_rem(&self, other: T) -> (T,T) {
- (*self / other, *self % other)
+ fn quot_rem(&self, other: &T) -> (T,T) {
+ (*self / *other, *self % *other)
}
/// Calculates the Greatest Common Divisor (GCD) of the number and `other`
#[inline(always)]
- fn gcd(&self, other: T) -> T {
+ fn gcd(&self, other: &T) -> T {
// Use Euclid's algorithm
- let mut m = *self, n = other;
+ let mut m = *self, n = *other;
while m != 0 {
let temp = m;
m = n % temp;
/// Calculates the Lowest Common Multiple (LCM) of the number and `other`
#[inline(always)]
- fn lcm(&self, other: T) -> T {
- (*self * other) / self.gcd(other)
+ fn lcm(&self, other: &T) -> T {
+ (*self * *other) / self.gcd(other)
}
/// Returns `true` if the number can be divided by `other` without leaving a remainder
#[inline(always)]
- fn divisible_by(&self, other: T) -> bool { *self % other == 0 }
+ fn is_multiple_of(&self, other: &T) -> bool { *self % *other == 0 }
/// Returns `true` if the number is divisible by `2`
#[inline(always)]
- fn is_even(&self) -> bool { self.divisible_by(2) }
+ fn is_even(&self) -> bool { self.is_multiple_of(&2) }
/// Returns `true` if the number is not divisible by `2`
#[inline(always)]
fn is_odd(&self) -> bool { !self.is_even() }
}
+impl Bitwise for T {}
+
#[cfg(notest)]
impl BitOr<T,T> for T {
#[inline(always)]
fn not(&self) -> T { !*self }
}
+impl Bounded for T {
+ #[inline(always)]
+ fn min_value() -> T { min_value }
+
+ #[inline(always)]
+ fn max_value() -> T { max_value }
+}
+
+impl Int for T {}
+
// String conversion functions and impl str -> num
/// Parse a string as a number in base 10.
use super::inst::T;
use prelude::*;
+ #[test]
+ fn test_num() {
+ num::test_num(10 as T, 2 as T);
+ }
+
+ #[test]
+ fn test_orderable() {
+ assert_eq!((1 as T).min(&(2 as T)), 1 as T);
+ assert_eq!((2 as T).min(&(1 as T)), 1 as T);
+ assert_eq!((1 as T).max(&(2 as T)), 2 as T);
+ assert_eq!((2 as T).max(&(1 as T)), 2 as T);
+ assert_eq!((1 as T).clamp(&(2 as T), &(4 as T)), 2 as T);
+ assert_eq!((8 as T).clamp(&(2 as T), &(4 as T)), 4 as T);
+ assert_eq!((3 as T).clamp(&(2 as T), &(4 as T)), 3 as T);
+ }
+
#[test]
fn test_gcd() {
- assert_eq!((10 as T).gcd(2), 2 as T);
- assert_eq!((10 as T).gcd(3), 1 as T);
- assert_eq!((0 as T).gcd(3), 3 as T);
- assert_eq!((3 as T).gcd(3), 3 as T);
- assert_eq!((56 as T).gcd(42), 14 as T);
+ assert_eq!((10 as T).gcd(&2), 2 as T);
+ assert_eq!((10 as T).gcd(&3), 1 as T);
+ assert_eq!((0 as T).gcd(&3), 3 as T);
+ assert_eq!((3 as T).gcd(&3), 3 as T);
+ assert_eq!((56 as T).gcd(&42), 14 as T);
}
#[test]
fn test_lcm() {
- assert_eq!((1 as T).lcm(0), 0 as T);
- assert_eq!((0 as T).lcm(1), 0 as T);
- assert_eq!((1 as T).lcm(1), 1 as T);
- assert_eq!((8 as T).lcm(9), 72 as T);
- assert_eq!((11 as T).lcm(5), 55 as T);
- assert_eq!((99 as T).lcm(17), 1683 as T);
+ assert_eq!((1 as T).lcm(&0), 0 as T);
+ assert_eq!((0 as T).lcm(&1), 0 as T);
+ assert_eq!((1 as T).lcm(&1), 1 as T);
+ assert_eq!((8 as T).lcm(&9), 72 as T);
+ assert_eq!((11 as T).lcm(&5), 55 as T);
+ assert_eq!((99 as T).lcm(&17), 1683 as T);
+ }
+
+ #[test]
+ fn test_multiple_of() {
+ assert!((6 as T).is_multiple_of(&(6 as T)));
+ assert!((6 as T).is_multiple_of(&(3 as T)));
+ assert!((6 as T).is_multiple_of(&(1 as T)));
+ }
+
+ #[test]
+ fn test_even() {
+ assert_eq!((0 as T).is_even(), true);
+ assert_eq!((1 as T).is_even(), false);
+ assert_eq!((2 as T).is_even(), true);
+ assert_eq!((3 as T).is_even(), false);
+ assert_eq!((4 as T).is_even(), true);
+ }
+
+ #[test]
+ fn test_odd() {
+ assert_eq!((0 as T).is_odd(), false);
+ assert_eq!((1 as T).is_odd(), true);
+ assert_eq!((2 as T).is_odd(), false);
+ assert_eq!((3 as T).is_odd(), true);
+ assert_eq!((4 as T).is_odd(), false);
}
#[test]
- fn test_bitwise_ops() {
+ fn test_bitwise() {
assert_eq!(0b1110 as T, (0b1100 as T).bitor(&(0b1010 as T)));
assert_eq!(0b1000 as T, (0b1100 as T).bitand(&(0b1010 as T)));
assert_eq!(0b0110 as T, (0b1100 as T).bitxor(&(0b1010 as T)));
assert_eq!(max_value - (0b1011 as T), (0b1011 as T).not());
}
+ #[test]
+ fn test_bitcount() {
+ assert_eq!((0b010101 as T).population_count(), 3);
+ }
+
+ #[test]
+ fn test_primitive() {
+ assert_eq!(Primitive::bits::<T>(), sys::size_of::<T>() * 8);
+ assert_eq!(Primitive::bytes::<T>(), sys::size_of::<T>());
+ }
+
#[test]
pub fn test_to_str() {
assert_eq!(to_str_radix(0 as T, 10u), ~"0");
//! Operations and constants for `u16`
mod inst {
+ use num::{Primitive, BitCount};
+ use unstable::intrinsics;
+
pub type T = u16;
#[allow(non_camel_case_types)]
pub type T_SIGNED = i16;
pub static bits: uint = 16;
+
+ impl Primitive for u16 {
+ #[inline(always)]
+ fn bits() -> uint { 16 }
+
+ #[inline(always)]
+ fn bytes() -> uint { Primitive::bits::<u16>() / 8 }
+ }
+
+ impl BitCount for u16 {
+ /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
+ #[inline(always)]
+ fn population_count(&self) -> u16 { unsafe { intrinsics::ctpop16(*self as i16) as u16 } }
+
+ /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
+ #[inline(always)]
+ fn leading_zeros(&self) -> u16 { unsafe { intrinsics::ctlz16(*self as i16) as u16 } }
+
+ /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
+ #[inline(always)]
+ fn trailing_zeros(&self) -> u16 { unsafe { intrinsics::cttz16(*self as i16) as u16 } }
+ }
}
//! Operations and constants for `u32`
mod inst {
+ use num::{Primitive, BitCount};
+ use unstable::intrinsics;
+
pub type T = u32;
#[allow(non_camel_case_types)]
pub type T_SIGNED = i32;
pub static bits: uint = 32;
+
+ impl Primitive for u32 {
+ #[inline(always)]
+ fn bits() -> uint { 32 }
+
+ #[inline(always)]
+ fn bytes() -> uint { Primitive::bits::<u32>() / 8 }
+ }
+
+ impl BitCount for u32 {
+ /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
+ #[inline(always)]
+ fn population_count(&self) -> u32 { unsafe { intrinsics::ctpop32(*self as i32) as u32 } }
+
+ /// Counts the number of leading zeros. Wraps LLVM's `ctlp` intrinsic.
+ #[inline(always)]
+ fn leading_zeros(&self) -> u32 { unsafe { intrinsics::ctlz32(*self as i32) as u32 } }
+
+ /// Counts the number of trailing zeros. Wraps LLVM's `cttp` intrinsic.
+ #[inline(always)]
+ fn trailing_zeros(&self) -> u32 { unsafe { intrinsics::cttz32(*self as i32) as u32 } }
+ }
}
//! Operations and constants for `u64`
mod inst {
+ use num::{Primitive, BitCount};
+ use unstable::intrinsics;
+
pub type T = u64;
#[allow(non_camel_case_types)]
pub type T_SIGNED = i64;
pub static bits: uint = 64;
+
+ impl Primitive for u64 {
+ #[inline(always)]
+ fn bits() -> uint { 64 }
+
+ #[inline(always)]
+ fn bytes() -> uint { Primitive::bits::<u64>() / 8 }
+ }
+
+ impl BitCount for u64 {
+ /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
+ #[inline(always)]
+ fn population_count(&self) -> u64 { unsafe { intrinsics::ctpop64(*self as i64) as u64 } }
+
+ /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
+ #[inline(always)]
+ fn leading_zeros(&self) -> u64 { unsafe { intrinsics::ctlz64(*self as i64) as u64 } }
+
+ /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
+ #[inline(always)]
+ fn trailing_zeros(&self) -> u64 { unsafe { intrinsics::cttz64(*self as i64) as u64 } }
+ }
}
//! Operations and constants for `u8`
mod inst {
+ use num::{Primitive, BitCount};
+ use unstable::intrinsics;
+
pub type T = u8;
#[allow(non_camel_case_types)]
pub type T_SIGNED = i8;
pub static bits: uint = 8;
+
+ impl Primitive for u8 {
+ #[inline(always)]
+ fn bits() -> uint { 8 }
+
+ #[inline(always)]
+ fn bytes() -> uint { Primitive::bits::<u8>() / 8 }
+ }
+
+ impl BitCount for u8 {
+ /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
+ #[inline(always)]
+ fn population_count(&self) -> u8 { unsafe { intrinsics::ctpop8(*self as i8) as u8 } }
+
+ /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
+ #[inline(always)]
+ fn leading_zeros(&self) -> u8 { unsafe { intrinsics::ctlz8(*self as i8) as u8 } }
+
+ /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
+ #[inline(always)]
+ fn trailing_zeros(&self) -> u8 { unsafe { intrinsics::cttz8(*self as i8) as u8 } }
+ }
}
};
pub mod inst {
- use sys;
use iter;
+ use num::{Primitive, BitCount};
+ use sys;
pub type T = uint;
#[allow(non_camel_case_types)]
#[cfg(target_arch = "x86_64")]
pub static bits: uint = 64;
- /**
- * Divide two numbers, return the result, rounded up.
- *
- * # Arguments
- *
- * * x - an integer
- * * y - an integer distinct from 0u
- *
- * # Return value
- *
- * The smallest integer `q` such that `x/y <= q`.
- */
+ impl Primitive for uint {
+ #[cfg(target_word_size = "32")]
+ #[inline(always)]
+ fn bits() -> uint { 32 }
+
+ #[cfg(target_word_size = "64")]
+ #[inline(always)]
+ fn bits() -> uint { 64 }
+
+ #[inline(always)]
+ fn bytes() -> uint { Primitive::bits::<uint>() / 8 }
+ }
+
+ #[cfg(target_word_size = "32")]
+ #[inline(always)]
+ impl BitCount for uint {
+ /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
+ #[inline(always)]
+ fn population_count(&self) -> uint { (*self as i32).population_count() as uint }
+
+ /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
+ #[inline(always)]
+ fn leading_zeros(&self) -> uint { (*self as i32).leading_zeros() as uint }
+
+ /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
+ #[inline(always)]
+ fn trailing_zeros(&self) -> uint { (*self as i32).trailing_zeros() as uint }
+ }
+
+ #[cfg(target_word_size = "64")]
+ #[inline(always)]
+ impl BitCount for uint {
+ /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
+ #[inline(always)]
+ fn population_count(&self) -> uint { (*self as i64).population_count() as uint }
+
+ /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
+ #[inline(always)]
+ fn leading_zeros(&self) -> uint { (*self as i64).leading_zeros() as uint }
+
+ /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
+ #[inline(always)]
+ fn trailing_zeros(&self) -> uint { (*self as i64).trailing_zeros() as uint }
+ }
+
+ ///
+ /// Divide two numbers, return the result, rounded up.
+ ///
+ /// # Arguments
+ ///
+ /// * x - an integer
+ /// * y - an integer distinct from 0u
+ ///
+ /// # Return value
+ ///
+ /// The smallest integer `q` such that `x/y <= q`.
+ ///
pub fn div_ceil(x: uint, y: uint) -> uint {
let div = x / y;
if x % y == 0u { div }
else { div + 1u }
}
- /**
- * Divide two numbers, return the result, rounded to the closest integer.
- *
- * # Arguments
- *
- * * x - an integer
- * * y - an integer distinct from 0u
- *
- * # Return value
- *
- * The integer `q` closest to `x/y`.
- */
+ ///
+ /// Divide two numbers, return the result, rounded to the closest integer.
+ ///
+ /// # Arguments
+ ///
+ /// * x - an integer
+ /// * y - an integer distinct from 0u
+ ///
+ /// # Return value
+ ///
+ /// The integer `q` closest to `x/y`.
+ ///
pub fn div_round(x: uint, y: uint) -> uint {
let div = x / y;
if x % y * 2u < y { div }
else { div + 1u }
}
- /**
- * Divide two numbers, return the result, rounded down.
- *
- * Note: This is the same function as `div`.
- *
- * # Arguments
- *
- * * x - an integer
- * * y - an integer distinct from 0u
- *
- * # Return value
- *
- * The smallest integer `q` such that `x/y <= q`. This
- * is either `x/y` or `x/y + 1`.
- */
+ ///
+ /// Divide two numbers, return the result, rounded down.
+ ///
+ /// Note: This is the same function as `div`.
+ ///
+ /// # Arguments
+ ///
+ /// * x - an integer
+ /// * y - an integer distinct from 0u
+ ///
+ /// # Return value
+ ///
+ /// The smallest integer `q` such that `x/y <= q`. This
+ /// is either `x/y` or `x/y + 1`.
+ ///
pub fn div_floor(x: uint, y: uint) -> uint { return x / y; }
- /**
- * Iterate over the range [`lo`..`hi`), or stop when requested
- *
- * # Arguments
- *
- * * lo - The integer at which to start the loop (included)
- * * hi - The integer at which to stop the loop (excluded)
- * * it - A block to execute with each consecutive integer of the range.
- * Return `true` to continue, `false` to stop.
- *
- * # Return value
- *
- * `true` If execution proceeded correctly, `false` if it was interrupted,
- * that is if `it` returned `false` at any point.
- */
+ ///
+ /// Iterate over the range [`lo`..`hi`), or stop when requested
+ ///
+ /// # Arguments
+ ///
+ /// * lo - The integer at which to start the loop (included)
+ /// * hi - The integer at which to stop the loop (excluded)
+ /// * it - A block to execute with each consecutive integer of the range.
+ /// Return `true` to continue, `false` to stop.
+ ///
+ /// # Return value
+ ///
+ /// `true` If execution proceeded correctly, `false` if it was interrupted,
+ /// that is if `it` returned `false` at any point.
+ ///
pub fn iterate(lo: uint, hi: uint, it: &fn(uint) -> bool) -> bool {
let mut i = lo;
while i < hi {
impl iter::Times for uint {
#[inline(always)]
- /**
- * A convenience form for basic iteration. Given a uint `x`,
- * `for x.times { ... }` executes the given block x times.
- *
- * Equivalent to `for uint::range(0, x) |_| { ... }`.
- *
- * Not defined on all integer types to permit unambiguous
- * use with integer literals of inferred integer-type as
- * the self-value (eg. `for 100.times { ... }`).
- */
+ ///
+ /// A convenience form for basic iteration. Given a uint `x`,
+ /// `for x.times { ... }` executes the given block x times.
+ ///
+ /// Equivalent to `for uint::range(0, x) |_| { ... }`.
+ ///
+ /// Not defined on all integer types to permit unambiguous
+ /// use with integer literals of inferred integer-type as
+ /// the self-value (eg. `for 100.times { ... }`).
+ ///
fn times(&self, it: &fn() -> bool) {
let mut i = *self;
while i > 0 {
--- /dev/null
+// 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.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+
+**Deprecated** iteration traits and common implementations.
+
+*/
+
+use cmp::{Eq, Ord};
+use kinds::Copy;
+use option::{None, Option, Some};
+use vec;
+
+/// A function used to initialize the elements of a sequence
+pub type InitOp<'self,T> = &'self fn(uint) -> T;
+
+pub trait BaseIter<A> {
+ fn each(&self, blk: &fn(v: &A) -> bool);
+ fn size_hint(&self) -> Option<uint>;
+}
+
+pub trait ReverseIter<A>: BaseIter<A> {
+ fn each_reverse(&self, blk: &fn(&A) -> bool);
+}
+
+pub trait MutableIter<A>: BaseIter<A> {
+ fn each_mut(&mut self, blk: &fn(&mut A) -> bool);
+}
+
+pub trait ExtendedIter<A> {
+ fn eachi(&self, blk: &fn(uint, v: &A) -> bool);
+ fn all(&self, blk: &fn(&A) -> bool) -> bool;
+ fn any(&self, blk: &fn(&A) -> bool) -> bool;
+ fn foldl<B>(&self, b0: B, blk: &fn(&B, &A) -> B) -> B;
+ fn position(&self, f: &fn(&A) -> bool) -> Option<uint>;
+ fn map_to_vec<B>(&self, op: &fn(&A) -> B) -> ~[B];
+ fn flat_map_to_vec<B,IB: BaseIter<B>>(&self, op: &fn(&A) -> IB) -> ~[B];
+}
+
+pub trait ExtendedMutableIter<A> {
+ fn eachi_mut(&mut self, blk: &fn(uint, &mut A) -> bool);
+}
+
+pub trait EqIter<A:Eq> {
+ fn contains(&self, x: &A) -> bool;
+ fn count(&self, x: &A) -> uint;
+}
+
+pub trait CopyableIter<A:Copy> {
+ fn filter_to_vec(&self, pred: &fn(&A) -> bool) -> ~[A];
+ fn to_vec(&self) -> ~[A];
+ fn find(&self, p: &fn(&A) -> bool) -> Option<A>;
+}
+
+pub trait CopyableOrderedIter<A:Copy + Ord> {
+ fn min(&self) -> A;
+ fn max(&self) -> A;
+}
+
+pub trait CopyableNonstrictIter<A:Copy> {
+ // Like "each", but copies out the value. If the receiver is mutated while
+ // iterating over it, the semantics must not be memory-unsafe but are
+ // otherwise undefined.
+ fn each_val(&const self, f: &fn(A) -> bool);
+}
+
+// A trait for sequences that can be built by imperatively pushing elements
+// onto them.
+pub trait Buildable<A> {
+ /**
+ * Builds a buildable sequence by calling a provided function with
+ * an argument function that pushes an element onto the back of
+ * the sequence.
+ * This version takes an initial size for the sequence.
+ *
+ * # Arguments
+ *
+ * * size - A hint for an initial size of the sequence
+ * * builder - A function that will construct the sequence. It receives
+ * as an argument a function that will push an element
+ * onto the sequence being constructed.
+ */
+ fn build_sized(size: uint, builder: &fn(push: &fn(A))) -> Self;
+}
+
+#[inline(always)]
+pub fn eachi<A,IA:BaseIter<A>>(self: &IA, blk: &fn(uint, &A) -> bool) {
+ let mut i = 0;
+ for self.each |a| {
+ if !blk(i, a) { break; }
+ i += 1;
+ }
+}
+
+#[inline(always)]
+pub fn all<A,IA:BaseIter<A>>(self: &IA, blk: &fn(&A) -> bool) -> bool {
+ for self.each |a| {
+ if !blk(a) { return false; }
+ }
+ return true;
+}
+
+#[inline(always)]
+pub fn any<A,IA:BaseIter<A>>(self: &IA, blk: &fn(&A) -> bool) -> bool {
+ for self.each |a| {
+ if blk(a) { return true; }
+ }
+ return false;
+}
+
+#[inline(always)]
+pub fn filter_to_vec<A:Copy,IA:BaseIter<A>>(self: &IA,
+ prd: &fn(&A) -> bool)
+ -> ~[A] {
+ do vec::build_sized_opt(self.size_hint()) |push| {
+ for self.each |a| {
+ if prd(a) { push(*a); }
+ }
+ }
+}
+
+#[inline(always)]
+pub fn map_to_vec<A,B,IA:BaseIter<A>>(self: &IA, op: &fn(&A) -> B) -> ~[B] {
+ do vec::build_sized_opt(self.size_hint()) |push| {
+ for self.each |a| {
+ push(op(a));
+ }
+ }
+}
+
+#[inline(always)]
+pub fn flat_map_to_vec<A,B,IA:BaseIter<A>,IB:BaseIter<B>>(self: &IA,
+ op: &fn(&A) -> IB)
+ -> ~[B] {
+ do vec::build |push| {
+ for self.each |a| {
+ for op(a).each |&b| {
+ push(b);
+ }
+ }
+ }
+}
+
+#[inline(always)]
+pub fn foldl<A,B,IA:BaseIter<A>>(self: &IA, b0: B, blk: &fn(&B, &A) -> B)
+ -> B {
+ let mut b = b0;
+ for self.each |a| {
+ b = blk(&b, a);
+ }
+ b
+}
+
+#[inline(always)]
+pub fn to_vec<A:Copy,IA:BaseIter<A>>(self: &IA) -> ~[A] {
+ map_to_vec(self, |&x| x)
+}
+
+#[inline(always)]
+pub fn contains<A:Eq,IA:BaseIter<A>>(self: &IA, x: &A) -> bool {
+ for self.each |a| {
+ if *a == *x { return true; }
+ }
+ return false;
+}
+
+#[inline(always)]
+pub fn count<A:Eq,IA:BaseIter<A>>(self: &IA, x: &A) -> uint {
+ do foldl(self, 0) |count, value| {
+ if *value == *x {
+ *count + 1
+ } else {
+ *count
+ }
+ }
+}
+
+#[inline(always)]
+pub fn position<A,IA:BaseIter<A>>(self: &IA, f: &fn(&A) -> bool)
+ -> Option<uint> {
+ let mut i = 0;
+ for self.each |a| {
+ if f(a) { return Some(i); }
+ i += 1;
+ }
+ return None;
+}
+
+// note: 'rposition' would only make sense to provide with a bidirectional
+// iter interface, such as would provide "reach" in addition to "each". As is,
+// it would have to be implemented with foldr, which is too inefficient.
+
+#[inline(always)]
+pub fn repeat(times: uint, blk: &fn() -> bool) {
+ let mut i = 0;
+ while i < times {
+ if !blk() { break }
+ i += 1;
+ }
+}
+
+#[inline(always)]
+pub fn min<A:Copy + Ord,IA:BaseIter<A>>(self: &IA) -> A {
+ match do foldl::<A,Option<A>,IA>(self, None) |a, b| {
+ match a {
+ &Some(ref a_) if *a_ < *b => {
+ *(a)
+ }
+ _ => Some(*b)
+ }
+ } {
+ Some(val) => val,
+ None => fail!(~"min called on empty iterator")
+ }
+}
+
+#[inline(always)]
+pub fn max<A:Copy + Ord,IA:BaseIter<A>>(self: &IA) -> A {
+ match do foldl::<A,Option<A>,IA>(self, None) |a, b| {
+ match a {
+ &Some(ref a_) if *a_ > *b => {
+ *(a)
+ }
+ _ => Some(*b)
+ }
+ } {
+ Some(val) => val,
+ None => fail!(~"max called on empty iterator")
+ }
+}
+
+#[inline(always)]
+pub fn find<A:Copy,IA:BaseIter<A>>(self: &IA, f: &fn(&A) -> bool)
+ -> Option<A> {
+ for self.each |i| {
+ if f(i) { return Some(*i) }
+ }
+ return None;
+}
+
+// Some functions for just building
+
+/**
+ * Builds a sequence by calling a provided function with an argument
+ * function that pushes an element to the back of a sequence.
+ *
+ * # Arguments
+ *
+ * * builder - A function that will construct the sequence. It receives
+ * as an argument a function that will push an element
+ * onto the sequence being constructed.
+ */
+#[inline(always)]
+pub fn build<A,B: Buildable<A>>(builder: &fn(push: &fn(A))) -> B {
+ Buildable::build_sized(4, builder)
+}
+
+/**
+ * Builds a sequence by calling a provided function with an argument
+ * function that pushes an element to the back of the sequence.
+ * This version takes an initial size for the sequence.
+ *
+ * # Arguments
+ *
+ * * size - An option, maybe containing initial size of the sequence
+ * to reserve.
+ * * builder - A function that will construct the sequence. It receives
+ * as an argument a function that will push an element
+ * onto the sequence being constructed.
+ */
+#[inline(always)]
+pub fn build_sized_opt<A,B: Buildable<A>>(size: Option<uint>,
+ builder: &fn(push: &fn(A))) -> B {
+ Buildable::build_sized(size.get_or_default(4), builder)
+}
+
+// Functions that combine iteration and building
+
+/// Applies a function to each element of an iterable and returns the results
+/// in a sequence built via `BU`. See also `map_to_vec`.
+#[inline(always)]
+pub fn map<T,IT: BaseIter<T>,U,BU: Buildable<U>>(v: &IT, f: &fn(&T) -> U)
+ -> BU {
+ do build_sized_opt(v.size_hint()) |push| {
+ for v.each() |elem| {
+ push(f(elem));
+ }
+ }
+}
+
+/**
+ * Creates and initializes a generic sequence from a function.
+ *
+ * Creates a generic sequence of size `n_elts` and initializes the elements
+ * to the value returned by the function `op`.
+ */
+#[inline(always)]
+pub fn from_fn<T,BT: Buildable<T>>(n_elts: uint, op: InitOp<T>) -> BT {
+ do Buildable::build_sized(n_elts) |push| {
+ let mut i: uint = 0u;
+ while i < n_elts { push(op(i)); i += 1u; }
+ }
+}
+
+/**
+ * Creates and initializes a generic sequence with some elements.
+ *
+ * Creates an immutable vector of size `n_elts` and initializes the elements
+ * to the value `t`.
+ */
+#[inline(always)]
+pub fn from_elem<T:Copy,BT:Buildable<T>>(n_elts: uint, t: T) -> BT {
+ do Buildable::build_sized(n_elts) |push| {
+ let mut i: uint = 0;
+ while i < n_elts { push(t); i += 1; }
+ }
+}
+
+/// Appends two generic sequences.
+#[inline(always)]
+pub fn append<T:Copy,IT:BaseIter<T>,BT:Buildable<T>>(lhs: &IT, rhs: &IT)
+ -> BT {
+ let size_opt = lhs.size_hint().chain_ref(
+ |sz1| rhs.size_hint().map(|sz2| *sz1+*sz2));
+ do build_sized_opt(size_opt) |push| {
+ for lhs.each |x| { push(*x); }
+ for rhs.each |x| { push(*x); }
+ }
+}
+
+/// Copies a generic sequence, possibly converting it to a different
+/// type of sequence.
+#[inline(always)]
+pub fn copy_seq<T:Copy,IT:BaseIter<T>,BT:Buildable<T>>(v: &IT) -> BT {
+ do build_sized_opt(v.size_hint()) |push| {
+ for v.each |x| { push(*x); }
+ }
+}
fn div(&self, rhs: &RHS) -> Result;
}
#[lang="quot"]
-#[cfg(stage1)]
-#[cfg(stage2)]
-#[cfg(stage3)]
+#[cfg(not(stage0))]
pub trait Quot<RHS,Result> {
fn quot(&self, rhs: &RHS) -> Result;
}
fn modulo(&self, rhs: &RHS) -> Result;
}
#[lang="rem"]
-#[cfg(stage1)]
-#[cfg(stage2)]
-#[cfg(stage3)]
+#[cfg(not(stage0))]
pub trait Rem<RHS,Result> {
fn rem(&self, rhs: &RHS) -> Result;
}
use kinds::Copy;
use util;
use num::Zero;
-use iter::{BaseIter, MutableIter, ExtendedIter};
-use iter;
+use old_iter::{BaseIter, MutableIter, ExtendedIter};
+use old_iter;
-#[cfg(test)] use ptr;
#[cfg(test)] use str;
/// The option type
impl<A> ExtendedIter<A> for Option<A> {
pub fn eachi(&self, blk: &fn(uint, v: &A) -> bool) {
- iter::eachi(self, blk)
+ old_iter::eachi(self, blk)
}
pub fn all(&self, blk: &fn(&A) -> bool) -> bool {
- iter::all(self, blk)
+ old_iter::all(self, blk)
}
pub fn any(&self, blk: &fn(&A) -> bool) -> bool {
- iter::any(self, blk)
+ old_iter::any(self, blk)
}
pub fn foldl<B>(&self, b0: B, blk: &fn(&B, &A) -> B) -> B {
- iter::foldl(self, b0, blk)
+ old_iter::foldl(self, b0, blk)
}
pub fn position(&self, f: &fn(&A) -> bool) -> Option<uint> {
- iter::position(self, f)
+ old_iter::position(self, f)
}
fn map_to_vec<B>(&self, op: &fn(&A) -> B) -> ~[B] {
- iter::map_to_vec(self, op)
+ old_iter::map_to_vec(self, op)
}
fn flat_map_to_vec<B,IB:BaseIter<B>>(&self, op: &fn(&A) -> IB)
-> ~[B] {
- iter::flat_map_to_vec(self, op)
+ old_iter::flat_map_to_vec(self, op)
}
}
#[test]
fn test_unwrap_ptr() {
- let x = ~0;
- let addr_x = ptr::addr_of(&(*x));
- let opt = Some(x);
- let y = opt.unwrap();
- let addr_y = ptr::addr_of(&(*y));
- assert!(addr_x == addr_y);
+ unsafe {
+ let x = ~0;
+ let addr_x: *int = ::cast::transmute(&*x);
+ let opt = Some(x);
+ let y = opt.unwrap();
+ let addr_y: *int = ::cast::transmute(&*y);
+ assert!(addr_x == addr_y);
+ }
}
#[test]
pub use libc::fclose;
pub use os::consts::*;
-// FIXME: move these to str perhaps? #2620
-
pub fn close(fd: c_int) -> c_int {
unsafe {
libc::close(fd)
}
}
+// FIXME: move these to str perhaps? #2620
+
pub fn as_c_charp<T>(s: &str, f: &fn(*c_char) -> T) -> T {
str::as_c_str(s, |b| f(b as *c_char))
}
}
}
+/// Creates a directory with a given mode.
+/// Returns true iff creation
+/// succeeded. Also creates all intermediate subdirectories
+/// if they don't already exist, giving all of them the same mode.
+pub fn mkdir_recursive(p: &Path, mode: c_int) -> bool {
+ if path_is_dir(p) {
+ return true;
+ }
+ let parent = p.dir_path();
+ debug!("mkdir_recursive: parent = %s",
+ parent.to_str());
+ if parent.to_str() == ~"."
+ || parent.to_str() == ~"/" { // !!!
+ // No parent directories to create
+ path_is_dir(&parent) && make_dir(p, mode)
+ }
+ else {
+ mkdir_recursive(&parent, mode) && make_dir(p, mode)
+ }
+}
+
/// Lists the contents of a directory
#[allow(non_implicitly_copyable_typarams)]
pub fn list_dir(p: &Path) -> ~[~str] {
assert!((remove_file(&out)));
}
}
+
+ #[test]
+ fn recursive_mkdir_ok() {
+ use libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
+
+ let root = os::tmpdir();
+ let path = "xy/z/zy";
+ let nested = root.push(path);
+ assert!(os::mkdir_recursive(&nested, (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
+ assert!(os::path_is_dir(&root.push("xy")));
+ assert!(os::path_is_dir(&root.push("xy/z")));
+ assert!(os::path_is_dir(&nested));
+ }
+
}
use to_str::ToStr;
use ascii::{AsciiCast, AsciiStr};
+#[cfg(windows)]
+pub use Path = self::WindowsPath;
+#[cfg(unix)]
+pub use Path = self::PosixPath;
+
#[deriving(Clone, Eq)]
pub struct WindowsPath {
host: Option<~str>,
fn is_absolute(&self) -> bool;
}
-#[cfg(windows)]
-pub type Path = WindowsPath;
-
-#[cfg(windows)]
-pub fn Path(s: &str) -> Path {
- WindowsPath(s)
-}
-
-#[cfg(unix)]
-pub type Path = PosixPath;
-
-#[cfg(unix)]
-pub fn Path(s: &str) -> Path {
- PosixPath(s)
-}
-
#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
mod stat {
*/
-use cast::{forget, reinterpret_cast, transmute};
+use cast::{forget, transmute, transmute_copy};
use either::{Either, Left, Right};
use kinds::Owned;
use libc;
static SPIN_COUNT: uint = 0;
macro_rules! move_it (
- { $x:expr } => ( unsafe { let y = *ptr::addr_of(&($x)); y } )
+ { $x:expr } => ( unsafe { let y = *ptr::to_unsafe_ptr(&($x)); y } )
)
#[deriving(Eq)]
mut state: State,
mut blocked_task: *rust_task,
- // This is a reinterpret_cast of a ~buffer, that can also be cast
+ // This is a transmute_copy of a ~buffer, that can also be cast
// to a buffer_header if need be.
mut buffer: *libc::c_void,
}
// thing. You'll proobably want to forget them when you're done.
unsafe fn buf_header(&self) -> ~BufferHeader {
assert!(self.buffer.is_not_null());
- reinterpret_cast(&self.buffer)
+ transmute_copy(&self.buffer)
}
fn set_buffer<T:Owned>(&self, b: ~Buffer<T>) {
unsafe {
- self.buffer = reinterpret_cast(&b);
+ self.buffer = transmute_copy(&b);
}
}
}
};
unsafe {
- b.data.header.buffer = reinterpret_cast(&b);
+ b.data.header.buffer = transmute_copy(&b);
}
b
}
pub fn packet<T>() -> *Packet<T> {
let b = unibuffer();
- let p = ptr::addr_of(&(b.data));
+ let p = ptr::to_unsafe_ptr(&(b.data));
// We'll take over memory management from here.
unsafe { forget(b) }
p
init: &fn(*libc::c_void, x: &T) -> *Packet<Tstart>)
-> (SendPacketBuffered<Tstart, T>, RecvPacketBuffered<Tstart, T>)
{
- let p = init(unsafe { reinterpret_cast(&buffer) }, &buffer.data);
+ let p = init(unsafe { transmute_copy(&buffer) }, &buffer.data);
unsafe { forget(buffer) }
(SendPacketBuffered(p), RecvPacketBuffered(p))
}
fn finalize(&self) {
unsafe {
let b = move_it!(self.buffer);
- //let p = ptr::addr_of(*b);
+ //let p = ptr::to_unsafe_ptr(*b);
//error!("drop %?", p);
let old_count = intrinsics::atomic_xsub_rel(&mut b.header.ref_count, 1);
//let old_count = atomic_xchng_rel(b.header.ref_count, 0);
}
fn BufferResource<T>(b: ~Buffer<T>) -> BufferResource<T> {
- //let p = ptr::addr_of(*b);
+ //let p = ptr::to_unsafe_ptr(*b);
//error!("take %?", p);
unsafe { intrinsics::atomic_xadd_acq(&mut b.header.ref_count, 1) };
let header = p.header();
let p_ = p.unwrap();
let p = unsafe { &*p_ };
- assert!(ptr::addr_of(&(p.header)) == header);
+ assert!(ptr::to_unsafe_ptr(&(p.header)) == header);
assert!(p.payload.is_none());
p.payload = Some(payload);
let old_state = swap_state_rel(&mut p.header.state, Full);
unsafe {
rustrt::task_signal_event(
old_task,
- ptr::addr_of(&(p.header)) as *libc::c_void);
+ ptr::to_unsafe_ptr(&(p.header)) as *libc::c_void);
rustrt::rust_task_deref(old_task);
}
}
unsafe {
rustrt::task_signal_event(
old_task,
- ptr::addr_of(&(p.header)) as *libc::c_void);
+ ptr::to_unsafe_ptr(&(p.header)) as *libc::c_void);
rustrt::rust_task_deref(old_task);
}
}
p: Some(p),
buffer: unsafe {
Some(BufferResource(
- get_buffer(ptr::addr_of(&((*p).header)))))
+ get_buffer(ptr::to_unsafe_ptr(&((*p).header)))))
}
}
}
match self.p {
Some(packet) => unsafe {
let packet = &*packet;
- let header = ptr::addr_of(&(packet.header));
+ let header = ptr::to_unsafe_ptr(&(packet.header));
//forget(packet);
header
},
match self.p {
Some(packet) => unsafe {
let packet = &*packet;
- let header = ptr::addr_of(&(packet.header));
+ let header = ptr::to_unsafe_ptr(&(packet.header));
//forget(packet);
header
},
p: Some(p),
buffer: unsafe {
Some(BufferResource(
- get_buffer(ptr::addr_of(&((*p).header)))))
+ get_buffer(ptr::to_unsafe_ptr(&((*p).header)))))
}
}
}
#[test]
fn test_oneshot() {
- let (c, p) = oneshot::init();
+ let (p, c) = oneshot();
- oneshot::client::send(c, ());
+ c.send(());
recv_one(p)
}
pub use kinds::{Const, Copy, Owned, Durable};
#[cfg(stage0)]
pub use ops::{Add, Sub, Mul, Div, Modulo, Neg, Not};
-#[cfg(stage1)]
-#[cfg(stage2)]
-#[cfg(stage3)]
+#[cfg(not(stage0))]
pub use ops::{Add, Sub, Mul, Quot, Rem, Neg, Not};
pub use ops::{BitAnd, BitOr, BitXor};
pub use ops::{Drop};
pub use cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater};
pub use container::{Container, Mutable, Map, Set};
pub use hash::Hash;
-pub use iter::{BaseIter, ReverseIter, MutableIter, ExtendedIter, EqIter};
-pub use iter::{CopyableIter, CopyableOrderedIter, CopyableNonstrictIter};
-pub use iter::{Times, ExtendedMutableIter};
-pub use num::{Num, Signed, Unsigned, Natural, NumCast};
+pub use old_iter::{BaseIter, ReverseIter, MutableIter, ExtendedIter, EqIter};
+pub use old_iter::{CopyableIter, CopyableOrderedIter, CopyableNonstrictIter};
+pub use old_iter::{ExtendedMutableIter};
+pub use iter::Times;
+pub use num::{Num, NumCast};
+pub use num::{Orderable, Signed, Unsigned, Round};
+pub use num::{Algebraic, Trigonometric, Exponential, Hyperbolic};
+pub use num::{Integer, Fractional, Real, RealExt};
+pub use num::{Bitwise, BitCount, Bounded};
+pub use num::{Primitive, Int, Float};
pub use path::GenericPath;
pub use path::Path;
pub use path::PosixPath;
pub use int;
pub use io;
pub use iter;
+pub use old_iter;
pub use libc;
pub use num;
pub use ops;
}
}
-pub mod rusti {
- #[abi = "rust-intrinsic"]
- pub extern "rust-intrinsic" {
- fn addr_of<T>(&&val: T) -> *T;
- }
-}
-
-/// Get an unsafe pointer to a value
-#[inline(always)]
-pub fn addr_of<T>(val: &T) -> *T { unsafe { rusti::addr_of(*val) } }
-
/// Calculate the offset from a pointer
#[inline(always)]
pub fn offset<T>(ptr: *T, count: uint) -> *T {
/**
Transform a region pointer - &T - to an unsafe pointer - *T.
This is safe, but is implemented with an unsafe block due to
- reinterpret_cast.
+ transmute.
*/
#[inline(always)]
pub fn to_unsafe_ptr<T>(thing: &T) -> *T {
/**
Transform a const region pointer - &const T - to a const unsafe pointer -
*const T. This is safe, but is implemented with an unsafe block due to
- reinterpret_cast.
+ transmute.
*/
#[inline(always)]
pub fn to_const_unsafe_ptr<T>(thing: &const T) -> *const T {
/**
Transform a mutable region pointer - &mut T - to a mutable unsafe pointer -
*mut T. This is safe, but is implemented with an unsafe block due to
- reinterpret_cast.
+ transmute.
*/
#[inline(always)]
pub fn to_mut_unsafe_ptr<T>(thing: &mut T) -> *mut T {
/**
Cast a region pointer - &T - to a uint.
This is safe, but is implemented with an unsafe block due to
- reinterpret_cast.
+ transmute.
(I couldn't think of a cutesy name for this one.)
*/
// Allow direct chaining with `task_rng`
impl<R: Rng> Rng for @R {
- fn next(&self) -> u32 { (*self).next() }
+ fn next(&self) -> u32 { (**self).next() }
}
/**
* generator.
*/
pub fn random<T: Rand>() -> T {
- task_rng().gen()
+ (*task_rng()).gen()
}
#[cfg(test)]
/**
* Applies op to the pairwise elements from `ss` and `ts`, aborting on
- * error. This could be implemented using `map2()` but it is more efficient
+ * error. This could be implemented using `map_zip()` but it is more efficient
* on its own as no result vector is built.
*/
#[inline(always)]
let sched = local_sched::unsafe_borrow();
let task = sched.current_task.get_mut_ref();
- task.local_services.run(start);
+ // FIXME #6141: shouldn't neet to put `start()` in another closure
+ task.local_services.run(||start());
}
let sched = local_sched::take();
pub impl Thread {
fn start(main: ~fn()) -> Thread {
- fn substart(main: &fn()) -> *raw_thread {
- unsafe { rust_raw_thread_start(&main) }
+ fn substart(main: &~fn()) -> *raw_thread {
+ unsafe { rust_raw_thread_start(main) }
}
- let raw = substart(main);
+ let raw = substart(&main);
Thread {
main: main,
raw_thread: raw
}
extern {
- pub unsafe fn rust_raw_thread_start(f: &(&fn())) -> *raw_thread;
+ pub unsafe fn rust_raw_thread_start(f: &(~fn())) -> *raw_thread;
pub unsafe fn rust_raw_thread_join_delete(thread: *raw_thread);
}
/// Transmute an owned vector to a Buf
pub fn vec_to_uv_buf(v: ~[u8]) -> Buf {
- let data = unsafe { malloc(v.len() as size_t) } as *u8;
- assert!(data.is_not_null());
- do vec::as_imm_buf(v) |b, l| {
- let data = data as *mut u8;
- unsafe { ptr::copy_memory(data, b, l) }
+ unsafe {
+ let data = malloc(v.len() as size_t) as *u8;
+ assert!(data.is_not_null());
+ do vec::as_imm_buf(v) |b, l| {
+ let data = data as *mut u8;
+ ptr::copy_memory(data, b, l)
+ }
+ uvll::buf_init(data, v.len())
}
- let buf = unsafe { uvll::buf_init(data, v.len()) };
- return buf;
}
/// Transmute a Buf that was once a ~[u8] back to ~[u8]
return Some(v);
} else {
// No buffer
+ rtdebug!("No buffer!");
return None;
}
}
}
pub unsafe fn buf_init(input: *u8, len: uint) -> uv_buf_t {
let out_buf = uv_buf_t { base: ptr::null(), len: 0 as size_t };
- let out_buf_ptr = ptr::addr_of(&out_buf);
+ let out_buf_ptr = ptr::to_unsafe_ptr(&out_buf);
rust_uv_buf_init(out_buf_ptr, input, len as size_t);
return out_buf;
}
pub unsafe fn get_last_err_info(uv_loop: *c_void) -> ~str {
let err = last_error(uv_loop);
- let err_ptr = ptr::addr_of(&err);
+ let err_ptr = ptr::to_unsafe_ptr(&err);
let err_name = str::raw::from_c_str(err_name(err_ptr));
let err_msg = str::raw::from_c_str(strerror(err_ptr));
return fmt!("LIBUV ERROR: name: %s msg: %s",
pub unsafe fn get_last_err_data(uv_loop: *c_void) -> uv_err_data {
let err = last_error(uv_loop);
- let err_ptr = ptr::addr_of(&err);
+ let err_ptr = ptr::to_unsafe_ptr(&err);
let err_name = str::raw::from_c_str(err_name(err_ptr));
let err_msg = str::raw::from_c_str(strerror(err_ptr));
uv_err_data { err_name: err_name, err_msg: err_msg }
pub mod rusti {
#[abi = "rust-intrinsic"]
pub extern "rust-intrinsic" {
+ #[cfg(stage0)]
pub fn frame_address(f: &once fn(x: *u8));
+ #[cfg(not(stage0))]
+ pub fn frame_address(+f: &once fn(x: *u8));
}
}
*/
use at_vec;
+use cast::transmute;
use cast;
use char;
use clone::Clone;
#[inline(always)]
pub fn as_buf<T>(s: &str, f: &fn(*u8, uint) -> T) -> T {
unsafe {
- let v : *(*u8,uint) = ::cast::transmute(ptr::addr_of(&s));
+ let v : *(*u8,uint) = transmute(&s);
let (buf,len) = *v;
f(buf, len)
}
#[inline(always)]
pub fn refcount<T>(t: @T) -> uint {
unsafe {
- let ref_ptr: *uint = cast::reinterpret_cast(&t);
+ let ref_ptr: *uint = cast::transmute_copy(&t);
*ref_ptr - 1
}
}
}
}
-/** Initiate task failure */
+/// Trait for initiating task failure.
+pub trait FailWithCause {
+ /// Fail the current task, taking ownership of `cause`
+ fn fail_with(cause: Self, file: &'static str, line: uint) -> !;
+}
+
+impl FailWithCause for ~str {
+ fn fail_with(cause: ~str, file: &'static str, line: uint) -> ! {
+ do str::as_buf(cause) |msg_buf, _msg_len| {
+ do str::as_buf(file) |file_buf, _file_len| {
+ unsafe {
+ let msg_buf = cast::transmute(msg_buf);
+ let file_buf = cast::transmute(file_buf);
+ begin_unwind_(msg_buf, file_buf, line as libc::size_t)
+ }
+ }
+ }
+ }
+}
+
+impl FailWithCause for &'static str {
+ fn fail_with(cause: &'static str, file: &'static str, line: uint) -> ! {
+ do str::as_buf(cause) |msg_buf, _msg_len| {
+ do str::as_buf(file) |file_buf, _file_len| {
+ unsafe {
+ let msg_buf = cast::transmute(msg_buf);
+ let file_buf = cast::transmute(file_buf);
+ begin_unwind_(msg_buf, file_buf, line as libc::size_t)
+ }
+ }
+ }
+ }
+}
+
+// NOTE: remove function after snapshot
+#[cfg(stage0)]
pub fn begin_unwind(msg: ~str, file: ~str, line: uint) -> ! {
use rt::{context, OldTaskContext};
}
}
+// NOTE: remove function after snapshot
+#[cfg(stage0)]
pub fn fail_assert(msg: &str, file: &str, line: uint) -> ! {
let (msg, file) = (msg.to_owned(), file.to_owned());
begin_unwind(~"assertion failed: " + msg, file, line)
assert!(new_f(20) == 30);
}
}
+
+ #[test]
+ #[should_fail]
+ fn fail_static() { FailWithCause::fail_with("cause", file!(), line!()) }
+
+ #[test]
+ #[should_fail]
+ fn fail_owned() { FailWithCause::fail_with(~"cause", file!(), line!()) }
}
// Local Variables:
let map_ptr = rt::rust_get_task_local_data(task);
if map_ptr.is_null() {
let map: TaskLocalMap = @mut ~[];
- // Use reinterpret_cast -- transmute would take map away from us also.
- rt::rust_set_task_local_data(
- task, cast::transmute(map));
+ rt::rust_set_task_local_data(task, cast::transmute(map));
rt::rust_task_local_data_atexit(task, cleanup_task_local_map_extern_cb);
// Also need to reference it an extra time to keep it for now.
let nonmut = cast::transmute::<TaskLocalMap,
}
}
-unsafe fn key_to_key_value<T:Durable>(
- key: LocalDataKey<T>) -> *libc::c_void {
-
+unsafe fn key_to_key_value<T:Durable>(key: LocalDataKey<T>) -> *libc::c_void {
// Keys are closures, which are (fnptr,envptr) pairs. Use fnptr.
// Use reintepret_cast -- transmute would leak (forget) the closure.
- let pair: (*libc::c_void, *libc::c_void) = cast::transmute(key);
+ let pair: (*libc::c_void, *libc::c_void) = cast::transmute_copy(&key);
pair.first()
}
let ch = ch.clone();
do spawn_unlinked {
// Give middle task a chance to fail-but-not-kill-us.
- for iter::repeat(16) { task::yield(); }
+ for old_iter::repeat(16) { task::yield(); }
ch.send(()); // If killed first, grandparent hangs.
}
fail!(); // Shouldn't kill either (grand)parent or (grand)child.
fn test_spawn_unlinked_sup_no_fail_up() { // child unlinked fails
do spawn_supervised { fail!(); }
// Give child a chance to fail-but-not-kill-us.
- for iter::repeat(16) { task::yield(); }
+ for old_iter::repeat(16) { task::yield(); }
}
#[test] #[should_fail] #[ignore(cfg(windows))]
fn test_spawn_unlinked_sup_fail_down() {
loop { task::yield(); }
}
}
- for iter::repeat(16) { task::yield(); }
+ for old_iter::repeat(16) { task::yield(); }
fail!();
}
loop { task::yield(); }
}
}
- for iter::repeat(16) { task::yield(); }
+ for old_iter::repeat(16) { task::yield(); }
fail!();
}
loop { task::yield(); }
}
}
- for iter::repeat(16) { task::yield(); }
+ for old_iter::repeat(16) { task::yield(); }
fail!();
}
loop { task::yield(); }
}
}
- for iter::repeat(16) { task::yield(); }
+ for old_iter::repeat(16) { task::yield(); }
fail!();
}
// Testing that a task in one scheduler can block in foreign code
// without affecting other schedulers
- for iter::repeat(20u) {
+ for old_iter::repeat(20u) {
let (start_po, start_ch) = stream();
let (fin_po, fin_ch) = stream();
let (p, ch) = stream::<uint>();
let x = ~1;
- let x_in_parent = ptr::addr_of(&(*x)) as uint;
+ let x_in_parent = ptr::to_unsafe_ptr(&*x) as uint;
do spawnfn || {
- let x_in_child = ptr::addr_of(&(*x)) as uint;
+ let x_in_child = ptr::to_unsafe_ptr(&*x) as uint;
ch.send(x_in_child);
}
// We want to do this after failing
do spawn_unlinked {
- for iter::repeat(10) { yield() }
+ for old_iter::repeat(10) { yield() }
ch.send(());
}
// We want to do this after failing
do spawn_unlinked || {
- for iter::repeat(10) { yield() }
+ for old_iter::repeat(10) { yield() }
ch.send(());
}
#[cfg(test)] use task::default_task_opts;
macro_rules! move_it (
- { $x:expr } => ( unsafe { let y = *ptr::addr_of(&($x)); y } )
+ { $x:expr } => ( unsafe { let y = *ptr::to_unsafe_ptr(&($x)); y } )
)
type TaskSet = HashSet<*rust_task>;
fn map<C>(&self, f: &fn(a: &A, b: &B) -> C) -> ~[C] {
match *self {
(ref a, ref b) => {
- vec::map2(*a, *b, f)
+ vec::map_zip(*a, *b, f)
}
}
}
fn map<C>(&self, f: &fn(a: &A, b: &B) -> C) -> ~[C] {
match *self {
(ref a, ref b) => {
- vec::map2(*a, *b, f)
+ vec::map_zip(*a, *b, f)
}
}
}
pub fn forget<T>(_: T) -> ();
// XXX: intrinsic uses legacy modes
+ #[cfg(stage0)]
fn reinterpret_cast<T,U>(&&src: T) -> U;
- // XXX: intrinsic uses legacy modes
- fn addr_of<T>(&&scr: T) -> *T;
pub fn needs_drop<T>() -> bool;
#[lang="malloc"]
#[inline(always)]
#[cfg(stage0)] // For some reason this isn't working on windows in stage0
-pub unsafe fn local_malloc(td: *c_char, size: uintptr_t) -> *c_char {
+pub unsafe fn local_malloc(td: *c_char, size: uintptr_t) -> *c_char {
return rustrt::rust_upcall_malloc_noswitch(td, size);
}
use container::{Container, Mutable};
use cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater};
use clone::Clone;
-use iter::BaseIter;
-use iter;
+use old_iter::BaseIter;
+use old_iter;
#[cfg(stage1)]
#[cfg(stage2)]
#[cfg(stage3)]
use kinds::Copy;
use libc;
use option::{None, Option, Some};
-use unstable::intrinsics;
+use ptr::to_unsafe_ptr;
use ptr;
-use ptr::addr_of;
use sys;
use uint;
+use unstable::intrinsics;
use vec;
#[cfg(notest)] use cmp::Equiv;
#[inline(always)]
pub fn capacity<T>(v: &const ~[T]) -> uint {
unsafe {
- let repr: **raw::VecRepr = ::cast::transmute(v);
+ let repr: **raw::VecRepr = transmute(v);
(**repr).unboxed.alloc / sys::nonzero_size_of::<T>()
}
}
// A botch to tide us over until core and std are fully demuted.
pub fn uniq_len<T>(v: &const ~[T]) -> uint {
unsafe {
- let v: &~[T] = ::cast::transmute(v);
+ let v: &~[T] = transmute(v);
as_const_buf(*v, |_p, len| len)
}
}
* Creates an immutable vector of size `n_elts` and initializes the elements
* to the value returned by the function `op`.
*/
-pub fn from_fn<T>(n_elts: uint, op: iter::InitOp<T>) -> ~[T] {
+pub fn from_fn<T>(n_elts: uint, op: old_iter::InitOp<T>) -> ~[T] {
unsafe {
let mut v = with_capacity(n_elts);
do as_mut_buf(v) |p, _len| {
from_fn(t.len(), |i| t[i])
}
+/// Creates a new vector with a capacity of `capacity`
pub fn with_capacity<T>(capacity: uint) -> ~[T] {
let mut vec = ~[];
reserve(&mut vec, capacity);
assert!(end <= len(v));
do as_imm_buf(v) |p, _len| {
unsafe {
- ::cast::transmute(
- (ptr::offset(p, start),
- (end - start) * sys::nonzero_size_of::<T>()))
+ transmute((ptr::offset(p, start),
+ (end - start) * sys::nonzero_size_of::<T>()))
}
}
}
assert!(end <= v.len());
do as_mut_buf(v) |p, _len| {
unsafe {
- ::cast::transmute(
- (ptr::mut_offset(p, start),
- (end - start) * sys::nonzero_size_of::<T>()))
+ transmute((ptr::mut_offset(p, start),
+ (end - start) * sys::nonzero_size_of::<T>()))
}
}
}
assert!(end <= len(v));
do as_const_buf(v) |p, _len| {
unsafe {
- ::cast::transmute(
- (ptr::const_offset(p, start),
- (end - start) * sys::nonzero_size_of::<T>()))
+ transmute((ptr::const_offset(p, start),
+ (end - start) * sys::nonzero_size_of::<T>()))
}
}
}
{
let first_slice = slice(*v, 0, 1);
let last_slice = slice(*v, next_ln, ln);
- raw::copy_memory(::cast::transmute(last_slice), first_slice, 1);
+ raw::copy_memory(transmute(last_slice), first_slice, 1);
}
// Memcopy everything to the left one element
{
let init_slice = slice(*v, 0, next_ln);
let tail_slice = slice(*v, 1, ln);
- raw::copy_memory(::cast::transmute(init_slice),
+ raw::copy_memory(transmute(init_slice),
tail_slice,
next_ln);
}
#[inline(always)]
pub fn push<T>(v: &mut ~[T], initval: T) {
unsafe {
- let repr: **raw::VecRepr = ::cast::transmute(&mut *v);
+ let repr: **raw::VecRepr = transmute(&mut *v);
let fill = (**repr).unboxed.fill;
if (**repr).unboxed.alloc > fill {
push_fast(v, initval);
// This doesn't bother to make sure we have space.
#[inline(always)] // really pretty please
unsafe fn push_fast<T>(v: &mut ~[T], initval: T) {
- let repr: **mut raw::VecRepr = ::cast::transmute(v);
+ let repr: **mut raw::VecRepr = transmute(v);
let fill = (**repr).unboxed.fill;
(**repr).unboxed.fill += sys::nonzero_size_of::<T>();
- let p = addr_of(&((**repr).unboxed.data));
+ let p = to_unsafe_ptr(&((**repr).unboxed.data));
let p = ptr::offset(p, fill) as *mut T;
intrinsics::move_val_init(&mut(*p), initval);
}
* * init_op - A function to call to retreive each appended element's
* value
*/
-pub fn grow_fn<T>(v: &mut ~[T], n: uint, op: iter::InitOp<T>) {
+pub fn grow_fn<T>(v: &mut ~[T], n: uint, op: old_iter::InitOp<T>) {
let new_len = v.len() + n;
reserve_at_least(&mut *v, new_len);
let mut i: uint = 0u;
result
}
-/// Apply a function to each pair of elements and return the results
-pub fn map2<T:Copy,U:Copy,V>(v0: &[T], v1: &[U],
+/**
+ * Apply a function to each pair of elements and return the results.
+ * Equivalent to `map(zip(v0, v1), f)`.
+ */
+pub fn map_zip<T:Copy,U:Copy,V>(v0: &[T], v1: &[U],
f: &fn(t: &T, v: &U) -> V) -> ~[V] {
let v0_len = len(v0);
if v0_len != len(v1) { fail!(); }
}
}
+// see doc below
+#[cfg(stage0)] // XXX: lifetimes!
+pub fn windowed<T>(n: uint, v: &[T], it: &fn(&[T]) -> bool) {
+ assert!(1u <= n);
+ if n > v.len() { return; }
+ for uint::range(0, v.len() - n + 1) |i| {
+ if !it(v.slice(i, i+n)) { return }
+ }
+}
+
/**
* Iterate over all contiguous windows of length `n` of the vector `v`.
*
* ~~~
*
*/
-#[cfg(stage0)] // XXX: lifetimes!
-pub fn windowed<T>(n: uint, v: &[T], it: &fn(&[T]) -> bool) {
- assert!(1u <= n);
- if n > v.len() { return; }
- for uint::range(0, v.len() - n + 1) |i| {
- if !it(v.slice(i, i+n)) { return }
- }
-}
#[cfg(stage1)]
#[cfg(stage2)]
#[cfg(stage3)]
// instead!
unsafe {
- let v : *(*T,uint) =
- ::cast::transmute(addr_of(&s));
+ let v : *(*T,uint) = transmute(&s);
let (buf,len) = *v;
f(buf, len / sys::nonzero_size_of::<T>())
}
#[inline(always)]
pub fn as_const_buf<T,U>(s: &const [T], f: &fn(*const T, uint) -> U) -> U {
unsafe {
- let v : *(*const T,uint) =
- ::cast::transmute(addr_of(&s));
+ let v : *(*const T,uint) = transmute(&s);
let (buf,len) = *v;
f(buf, len / sys::nonzero_size_of::<T>())
}
#[inline(always)]
pub fn as_mut_buf<T,U>(s: &mut [T], f: &fn(*mut T, uint) -> U) -> U {
unsafe {
- let v : *(*mut T,uint) =
- ::cast::transmute(addr_of(&s));
+ let v : *(*mut T,uint) = transmute(&s);
let (buf,len) = *v;
f(buf, len / sys::nonzero_size_of::<T>())
}
fn consume_reverse(self, f: &fn(uint, v: T));
fn filter(self, f: &fn(t: &T) -> bool) -> ~[T];
fn partition(self, f: &fn(&T) -> bool) -> (~[T], ~[T]);
- fn grow_fn(&mut self, n: uint, op: iter::InitOp<T>);
+ fn grow_fn(&mut self, n: uint, op: old_iter::InitOp<T>);
}
impl<T> OwnedVector<T> for ~[T] {
}
#[inline]
- fn grow_fn(&mut self, n: uint, op: iter::InitOp<T>) {
+ fn grow_fn(&mut self, n: uint, op: old_iter::InitOp<T>) {
grow_fn(self, n, op);
}
}
/// Unsafe operations
pub mod raw {
+ use cast::transmute;
use kinds::Copy;
use managed;
use option::{None, Some};
- use unstable::intrinsics;
- use ptr::addr_of;
use ptr;
use sys;
+ use unstable::intrinsics;
use vec::{UnboxedVecRepr, as_const_buf, as_mut_buf, len, with_capacity};
/// The internal representation of a (boxed) vector
*/
#[inline(always)]
pub unsafe fn set_len<T>(v: &mut ~[T], new_len: uint) {
- let repr: **mut VecRepr = ::cast::transmute(v);
+ let repr: **mut VecRepr = transmute(v);
(**repr).unboxed.fill = new_len * sys::nonzero_size_of::<T>();
}
*/
#[inline(always)]
pub unsafe fn to_ptr<T>(v: &[T]) -> *T {
- let repr: **SliceRepr = ::cast::transmute(&v);
- ::cast::transmute(addr_of(&((**repr).data)))
+ let repr: **SliceRepr = transmute(&v);
+ transmute(&((**repr).data))
}
/** see `to_ptr()` */
#[inline(always)]
pub unsafe fn to_const_ptr<T>(v: &const [T]) -> *const T {
- let repr: **SliceRepr = ::cast::transmute(&v);
- ::cast::transmute(addr_of(&((**repr).data)))
+ let repr: **SliceRepr = transmute(&v);
+ transmute(&((**repr).data))
}
/** see `to_ptr()` */
#[inline(always)]
pub unsafe fn to_mut_ptr<T>(v: &mut [T]) -> *mut T {
- let repr: **SliceRepr = ::cast::transmute(&v);
- ::cast::transmute(addr_of(&((**repr).data)))
+ let repr: **SliceRepr = transmute(&v);
+ transmute(&((**repr).data))
}
/**
len: uint,
f: &fn(v: &[T]) -> U) -> U {
let pair = (p, len * sys::nonzero_size_of::<T>());
- let v : *(&'blk [T]) =
- ::cast::transmute(addr_of(&pair));
+ let v : *(&'blk [T]) = transmute(&pair);
f(*v)
}
len: uint,
f: &fn(v: &mut [T]) -> U) -> U {
let pair = (p, len * sys::nonzero_size_of::<T>());
- let v : *(&'blk mut [T]) =
- ::cast::transmute(addr_of(&pair));
+ let v : *(&'blk mut [T]) = transmute(&pair);
f(*v)
}
// ITERATION TRAIT METHODS
#[cfg(stage0)]
-impl<'self,A> iter::BaseIter<A> for &'self [A] {
+impl<'self,A> old_iter::BaseIter<A> for &'self [A] {
#[inline(always)]
fn each(&self, blk: &fn(v: &'self A) -> bool) { each(*self, blk) }
#[inline(always)]
#[cfg(stage1)]
#[cfg(stage2)]
#[cfg(stage3)]
-impl<'self,A> iter::BaseIter<A> for &'self [A] {
+impl<'self,A> old_iter::BaseIter<A> for &'self [A] {
#[inline(always)]
fn each<'a>(&'a self, blk: &fn(v: &'a A) -> bool) { each(*self, blk) }
#[inline(always)]
// FIXME(#4148): This should be redundant
#[cfg(stage0)]
-impl<A> iter::BaseIter<A> for ~[A] {
+impl<A> old_iter::BaseIter<A> for ~[A] {
#[inline(always)]
fn each(&self, blk: &fn(v: &'self A) -> bool) { each(*self, blk) }
#[inline(always)]
#[cfg(stage1)]
#[cfg(stage2)]
#[cfg(stage3)]
-impl<A> iter::BaseIter<A> for ~[A] {
+impl<A> old_iter::BaseIter<A> for ~[A] {
#[inline(always)]
fn each<'a>(&'a self, blk: &fn(v: &'a A) -> bool) { each(*self, blk) }
#[inline(always)]
// FIXME(#4148): This should be redundant
#[cfg(stage0)]
-impl<A> iter::BaseIter<A> for @[A] {
+impl<A> old_iter::BaseIter<A> for @[A] {
#[inline(always)]
fn each(&self, blk: &fn(v: &'self A) -> bool) { each(*self, blk) }
#[inline(always)]
#[cfg(stage1)]
#[cfg(stage2)]
#[cfg(stage3)]
-impl<A> iter::BaseIter<A> for @[A] {
+impl<A> old_iter::BaseIter<A> for @[A] {
#[inline(always)]
fn each<'a>(&'a self, blk: &fn(v: &'a A) -> bool) { each(*self, blk) }
#[inline(always)]
}
#[cfg(stage0)]
-impl<'self,A> iter::MutableIter<A> for &'self mut [A] {
+impl<'self,A> old_iter::MutableIter<A> for &'self mut [A] {
#[inline(always)]
fn each_mut(&mut self, blk: &fn(v: &'self mut A) -> bool) {
each_mut(*self, blk)
#[cfg(stage1)]
#[cfg(stage2)]
#[cfg(stage3)]
-impl<'self,A> iter::MutableIter<A> for &'self mut [A] {
+impl<'self,A> old_iter::MutableIter<A> for &'self mut [A] {
#[inline(always)]
fn each_mut<'a>(&'a mut self, blk: &fn(v: &'a mut A) -> bool) {
each_mut(*self, blk)
// FIXME(#4148): This should be redundant
#[cfg(stage0)]
-impl<A> iter::MutableIter<A> for ~[A] {
+impl<A> old_iter::MutableIter<A> for ~[A] {
#[inline(always)]
fn each_mut(&mut self, blk: &fn(v: &'self mut A) -> bool) {
each_mut(*self, blk)
#[cfg(stage1)]
#[cfg(stage2)]
#[cfg(stage3)]
-impl<A> iter::MutableIter<A> for ~[A] {
+impl<A> old_iter::MutableIter<A> for ~[A] {
#[inline(always)]
fn each_mut<'a>(&'a mut self, blk: &fn(v: &'a mut A) -> bool) {
each_mut(*self, blk)
}
// FIXME(#4148): This should be redundant
-impl<A> iter::MutableIter<A> for @mut [A] {
+impl<A> old_iter::MutableIter<A> for @mut [A] {
#[inline(always)]
fn each_mut(&mut self, blk: &fn(v: &mut A) -> bool) {
each_mut(*self, blk)
}
}
-impl<'self,A> iter::ExtendedIter<A> for &'self [A] {
+impl<'self,A> old_iter::ExtendedIter<A> for &'self [A] {
pub fn eachi(&self, blk: &fn(uint, v: &A) -> bool) {
- iter::eachi(self, blk)
+ old_iter::eachi(self, blk)
}
pub fn all(&self, blk: &fn(&A) -> bool) -> bool {
- iter::all(self, blk)
+ old_iter::all(self, blk)
}
pub fn any(&self, blk: &fn(&A) -> bool) -> bool {
- iter::any(self, blk)
+ old_iter::any(self, blk)
}
pub fn foldl<B>(&self, b0: B, blk: &fn(&B, &A) -> B) -> B {
- iter::foldl(self, b0, blk)
+ old_iter::foldl(self, b0, blk)
}
pub fn position(&self, f: &fn(&A) -> bool) -> Option<uint> {
- iter::position(self, f)
+ old_iter::position(self, f)
}
fn map_to_vec<B>(&self, op: &fn(&A) -> B) -> ~[B] {
- iter::map_to_vec(self, op)
+ old_iter::map_to_vec(self, op)
}
fn flat_map_to_vec<B,IB:BaseIter<B>>(&self, op: &fn(&A) -> IB)
-> ~[B] {
- iter::flat_map_to_vec(self, op)
+ old_iter::flat_map_to_vec(self, op)
}
}
-impl<'self,A> iter::ExtendedMutableIter<A> for &'self mut [A] {
+impl<'self,A> old_iter::ExtendedMutableIter<A> for &'self mut [A] {
#[inline(always)]
pub fn eachi_mut(&mut self, blk: &fn(uint, v: &mut A) -> bool) {
eachi_mut(*self, blk)
}
// FIXME(#4148): This should be redundant
-impl<A> iter::ExtendedIter<A> for ~[A] {
+impl<A> old_iter::ExtendedIter<A> for ~[A] {
pub fn eachi(&self, blk: &fn(uint, v: &A) -> bool) {
- iter::eachi(self, blk)
+ old_iter::eachi(self, blk)
}
pub fn all(&self, blk: &fn(&A) -> bool) -> bool {
- iter::all(self, blk)
+ old_iter::all(self, blk)
}
pub fn any(&self, blk: &fn(&A) -> bool) -> bool {
- iter::any(self, blk)
+ old_iter::any(self, blk)
}
pub fn foldl<B>(&self, b0: B, blk: &fn(&B, &A) -> B) -> B {
- iter::foldl(self, b0, blk)
+ old_iter::foldl(self, b0, blk)
}
pub fn position(&self, f: &fn(&A) -> bool) -> Option<uint> {
- iter::position(self, f)
+ old_iter::position(self, f)
}
fn map_to_vec<B>(&self, op: &fn(&A) -> B) -> ~[B] {
- iter::map_to_vec(self, op)
+ old_iter::map_to_vec(self, op)
}
fn flat_map_to_vec<B,IB:BaseIter<B>>(&self, op: &fn(&A) -> IB)
-> ~[B] {
- iter::flat_map_to_vec(self, op)
+ old_iter::flat_map_to_vec(self, op)
}
}
// FIXME(#4148): This should be redundant
-impl<A> iter::ExtendedIter<A> for @[A] {
+impl<A> old_iter::ExtendedIter<A> for @[A] {
pub fn eachi(&self, blk: &fn(uint, v: &A) -> bool) {
- iter::eachi(self, blk)
+ old_iter::eachi(self, blk)
}
pub fn all(&self, blk: &fn(&A) -> bool) -> bool {
- iter::all(self, blk)
+ old_iter::all(self, blk)
}
pub fn any(&self, blk: &fn(&A) -> bool) -> bool {
- iter::any(self, blk)
+ old_iter::any(self, blk)
}
pub fn foldl<B>(&self, b0: B, blk: &fn(&B, &A) -> B) -> B {
- iter::foldl(self, b0, blk)
+ old_iter::foldl(self, b0, blk)
}
pub fn position(&self, f: &fn(&A) -> bool) -> Option<uint> {
- iter::position(self, f)
+ old_iter::position(self, f)
}
fn map_to_vec<B>(&self, op: &fn(&A) -> B) -> ~[B] {
- iter::map_to_vec(self, op)
+ old_iter::map_to_vec(self, op)
}
fn flat_map_to_vec<B,IB:BaseIter<B>>(&self, op: &fn(&A) -> IB)
-> ~[B] {
- iter::flat_map_to_vec(self, op)
+ old_iter::flat_map_to_vec(self, op)
}
}
-impl<'self,A:Eq> iter::EqIter<A> for &'self [A] {
- pub fn contains(&self, x: &A) -> bool { iter::contains(self, x) }
- pub fn count(&self, x: &A) -> uint { iter::count(self, x) }
+impl<'self,A:Eq> old_iter::EqIter<A> for &'self [A] {
+ pub fn contains(&self, x: &A) -> bool { old_iter::contains(self, x) }
+ pub fn count(&self, x: &A) -> uint { old_iter::count(self, x) }
}
// FIXME(#4148): This should be redundant
-impl<A:Eq> iter::EqIter<A> for ~[A] {
- pub fn contains(&self, x: &A) -> bool { iter::contains(self, x) }
- pub fn count(&self, x: &A) -> uint { iter::count(self, x) }
+impl<A:Eq> old_iter::EqIter<A> for ~[A] {
+ pub fn contains(&self, x: &A) -> bool { old_iter::contains(self, x) }
+ pub fn count(&self, x: &A) -> uint { old_iter::count(self, x) }
}
// FIXME(#4148): This should be redundant
-impl<A:Eq> iter::EqIter<A> for @[A] {
- pub fn contains(&self, x: &A) -> bool { iter::contains(self, x) }
- pub fn count(&self, x: &A) -> uint { iter::count(self, x) }
+impl<A:Eq> old_iter::EqIter<A> for @[A] {
+ pub fn contains(&self, x: &A) -> bool { old_iter::contains(self, x) }
+ pub fn count(&self, x: &A) -> uint { old_iter::count(self, x) }
}
-impl<'self,A:Copy> iter::CopyableIter<A> for &'self [A] {
+impl<'self,A:Copy> old_iter::CopyableIter<A> for &'self [A] {
fn filter_to_vec(&self, pred: &fn(&A) -> bool) -> ~[A] {
- iter::filter_to_vec(self, pred)
+ old_iter::filter_to_vec(self, pred)
}
- fn to_vec(&self) -> ~[A] { iter::to_vec(self) }
+ fn to_vec(&self) -> ~[A] { old_iter::to_vec(self) }
pub fn find(&self, f: &fn(&A) -> bool) -> Option<A> {
- iter::find(self, f)
+ old_iter::find(self, f)
}
}
// FIXME(#4148): This should be redundant
-impl<A:Copy> iter::CopyableIter<A> for ~[A] {
+impl<A:Copy> old_iter::CopyableIter<A> for ~[A] {
fn filter_to_vec(&self, pred: &fn(&A) -> bool) -> ~[A] {
- iter::filter_to_vec(self, pred)
+ old_iter::filter_to_vec(self, pred)
}
- fn to_vec(&self) -> ~[A] { iter::to_vec(self) }
+ fn to_vec(&self) -> ~[A] { old_iter::to_vec(self) }
pub fn find(&self, f: &fn(&A) -> bool) -> Option<A> {
- iter::find(self, f)
+ old_iter::find(self, f)
}
}
// FIXME(#4148): This should be redundant
-impl<A:Copy> iter::CopyableIter<A> for @[A] {
+impl<A:Copy> old_iter::CopyableIter<A> for @[A] {
fn filter_to_vec(&self, pred: &fn(&A) -> bool) -> ~[A] {
- iter::filter_to_vec(self, pred)
+ old_iter::filter_to_vec(self, pred)
}
- fn to_vec(&self) -> ~[A] { iter::to_vec(self) }
+ fn to_vec(&self) -> ~[A] { old_iter::to_vec(self) }
pub fn find(&self, f: &fn(&A) -> bool) -> Option<A> {
- iter::find(self, f)
+ old_iter::find(self, f)
}
}
-impl<'self,A:Copy + Ord> iter::CopyableOrderedIter<A> for &'self [A] {
- fn min(&self) -> A { iter::min(self) }
- fn max(&self) -> A { iter::max(self) }
+impl<'self,A:Copy + Ord> old_iter::CopyableOrderedIter<A> for &'self [A] {
+ fn min(&self) -> A { old_iter::min(self) }
+ fn max(&self) -> A { old_iter::max(self) }
}
// FIXME(#4148): This should be redundant
-impl<A:Copy + Ord> iter::CopyableOrderedIter<A> for ~[A] {
- fn min(&self) -> A { iter::min(self) }
- fn max(&self) -> A { iter::max(self) }
+impl<A:Copy + Ord> old_iter::CopyableOrderedIter<A> for ~[A] {
+ fn min(&self) -> A { old_iter::min(self) }
+ fn max(&self) -> A { old_iter::max(self) }
}
// FIXME(#4148): This should be redundant
-impl<A:Copy + Ord> iter::CopyableOrderedIter<A> for @[A] {
- fn min(&self) -> A { iter::min(self) }
- fn max(&self) -> A { iter::max(self) }
+impl<A:Copy + Ord> old_iter::CopyableOrderedIter<A> for @[A] {
+ fn min(&self) -> A { old_iter::min(self) }
+ fn max(&self) -> A { old_iter::max(self) }
}
-impl<'self,A:Copy> iter::CopyableNonstrictIter<A> for &'self [A] {
+impl<'self,A:Copy> old_iter::CopyableNonstrictIter<A> for &'self [A] {
fn each_val(&const self, f: &fn(A) -> bool) {
let mut i = 0;
while i < self.len() {
}
// FIXME(#4148): This should be redundant
-impl<A:Copy> iter::CopyableNonstrictIter<A> for ~[A] {
+impl<A:Copy> old_iter::CopyableNonstrictIter<A> for ~[A] {
fn each_val(&const self, f: &fn(A) -> bool) {
let mut i = 0;
while i < uniq_len(self) {
}
// FIXME(#4148): This should be redundant
-impl<A:Copy> iter::CopyableNonstrictIter<A> for @[A] {
+impl<A:Copy> old_iter::CopyableNonstrictIter<A> for @[A] {
fn each_val(&const self, f: &fn(A) -> bool) {
let mut i = 0;
while i < self.len() {
}
#[test]
- fn test_map2() {
+ fn test_map_zip() {
fn times(x: &int, y: &int) -> int { *x * *y }
let f = times;
let v0 = ~[1, 2, 3, 4, 5];
let v1 = ~[5, 4, 3, 2, 1];
- let u = map2::<int, int, int>(v0, v1, f);
+ let u = map_zip::<int, int, int>(v0, v1, f);
let mut i = 0;
while i < 5 { assert!(v0[i] * v1[i] == u[i]); i += 1; }
}
#[ignore(windows)]
#[should_fail]
#[allow(non_implicitly_copyable_typarams)]
- fn test_map2_fail() {
+ fn test_map_zip_fail() {
let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
let mut i = 0;
- do map2(v, v) |_elt1, _elt2| {
+ do map_zip(v, v) |_elt1, _elt2| {
if i == 2 {
fail!()
}
#[comment = "The Rust fuzzer library"];
#[license = "MIT/ASL2"];
#[crate_type = "lib"];
-#[no_core];
-#[legacy_modes];
-
-#[allow(vecs_implicitly_copyable)];
#[allow(non_camel_case_types)];
-#[allow(deprecated_mode)];
-#[allow(deprecated_pattern)];
-extern mod core(vers = "0.7-pre");
extern mod std(vers = "0.7-pre");
extern mod syntax(vers = "0.7-pre");
-use core::*;
-use core::io::WriterUtil;
+use core::run;
-use syntax::{ast, fold, visit, codemap};
+use syntax::diagnostic;
+use syntax::parse::token::ident_interner;
+use syntax::parse::token;
use syntax::parse;
use syntax::print::pprust;
-use syntax::diagnostic;
+use syntax::{ast, fold, visit, codemap};
#[deriving(Eq)]
pub enum test_mode { tm_converge, tm_run, }
pub struct Context { mode: test_mode } // + rng
-pub fn write_file(filename: &Path, content: ~str) {
- result::get(
- &io::file_writer(filename, ~[io::Create, io::Truncate]))
- .write_str(content);
+pub fn write_file(filename: &Path, content: &str) {
+ result::get(&io::file_writer(filename, ~[io::Create, io::Truncate]))
+ .write_str(content);
}
-pub fn contains(haystack: ~str, needle: ~str) -> bool {
+pub fn contains(haystack: &str, needle: &str) -> bool {
str::contains(haystack, needle)
}
pub fn find_rust_files(files: &mut ~[Path], path: &Path) {
if path.filetype() == Some(~".rs") && !contains(path.to_str(), ~"utf8") {
// ignoring "utf8" tests because something is broken
- files.push(*path);
+ files.push(path.clone());
} else if os::path_is_dir(path)
&& !contains(path.to_str(), ~"compile-fail")
&& !contains(path.to_str(), ~"build") {
}
-pub fn common_exprs() -> ~[ast::expr] {
- fn dse(e: ast::expr_) -> ast::expr {
- ast::expr {
+pub fn common_exprs() -> ~[@ast::expr] {
+ fn dse(e: ast::expr_) -> @ast::expr {
+ @ast::expr {
id: 0,
callee_id: -1,
node: e,
dse(ast::expr_lit(@dsl(ast::lit_bool(false)))),
dse(ast::expr_lit(@dsl(ast::lit_bool(true)))),
dse(ast::expr_unary(ast::box(ast::m_imm),
- @dse(ast::expr_lit(@dsl(ast::lit_bool(true)))))),
+ dse(ast::expr_lit(@dsl(ast::lit_bool(true)))))),
dse(ast::expr_unary(ast::uniq(ast::m_imm),
- @dse(ast::expr_lit(@dsl(ast::lit_bool(true))))))
+ dse(ast::expr_lit(@dsl(ast::lit_bool(true))))))
]
}
pub fn safe_to_steal_expr(e: @ast::expr, tm: test_mode) -> bool {
- safe_to_use_expr(*e, tm)
+ safe_to_use_expr(e, tm)
}
-pub fn safe_to_use_expr(e: ast::expr, tm: test_mode) -> bool {
+pub fn safe_to_use_expr(e: @ast::expr, tm: test_mode) -> bool {
match tm {
tm_converge => {
match e.node {
// Not type-parameterized: https://github.com/mozilla/rust/issues/898 (FIXED)
pub fn stash_expr_if(c: @fn(@ast::expr, test_mode)->bool,
- es: @mut ~[ast::expr],
+ es: @mut ~[@ast::expr],
e: @ast::expr,
tm: test_mode) {
if c(e, tm) {
- *es += ~[*e];
+ *es += ~[e];
} else {
/* now my indices are wrong :( */
}
}
-pub fn stash_ty_if(c: @fn(@ast::Ty, test_mode)->bool,
- es: @mut ~[ast::Ty],
+pub fn stash_ty_if(c: @fn(@ast::Ty, test_mode) -> bool,
+ es: @mut ~[@ast::Ty],
e: @ast::Ty,
tm: test_mode) {
if c(e, tm) {
- es.push(*e);
+ es.push(e);
} else {
/* now my indices are wrong :( */
}
}
-pub struct StolenStuff {exprs: ~[ast::expr], tys: ~[ast::Ty]}
+pub struct StolenStuff {
+ exprs: ~[@ast::expr],
+ tys: ~[@ast::Ty]
+}
pub fn steal(crate: @ast::crate, tm: test_mode) -> StolenStuff {
let exprs = @mut ~[];
.. *visit::default_simple_visitor()
});
visit::visit_crate(crate, (), v);
- StolenStuff {exprs: *exprs, tys: *tys}
+ StolenStuff {
+ exprs: (*exprs).clone(),
+ tys: (*tys).clone(),
+ }
}
pub fn safe_to_replace_expr(e: &ast::expr_, _tm: test_mode) -> bool {
match *e {
- // https://github.com/mozilla/rust/issues/652
- ast::expr_if(*) => { false }
- ast::expr_block(_) => { false }
+ // https://github.com/mozilla/rust/issues/652
+ ast::expr_if(*) => false,
+ ast::expr_block(_) => false,
- // expr_call is also missing a constraint
- ast::expr_fn_block(*) => { false }
+ // expr_call is also missing a constraint
+ ast::expr_fn_block(*) => false,
- _ => { true }
+ _ => true,
}
}
}
// Replace the |i|th expr (in fold order) of |crate| with |newexpr|.
-pub fn replace_expr_in_crate(crate: @ast::crate, i: uint,
- newexpr: ast::expr, tm: test_mode) ->
- ast::crate {
+pub fn replace_expr_in_crate(crate: @ast::crate,
+ i: uint,
+ newexpr: @ast::expr,
+ tm: test_mode)
+ -> @ast::crate {
let j: @mut uint = @mut 0u;
fn fold_expr_rep(j_: @mut uint,
i_: uint,
- newexpr_: ast::expr_,
+ newexpr_: &ast::expr_,
original: &ast::expr_,
fld: @fold::ast_fold,
tm_: test_mode)
- -> ast::expr_ {
- *j_ += 1u;
- if i_ + 1u == *j_ && safe_to_replace_expr(original, tm_) {
- newexpr_
+ -> ast::expr_ {
+ *j_ += 1;
+ if i_ + 1 == *j_ && safe_to_replace_expr(original, tm_) {
+ copy *newexpr_
} else {
fold::noop_fold_expr(original, fld)
}
}
let afp = @fold::AstFoldFns {
fold_expr: fold::wrap(|a,b| {
- fold_expr_rep(j, i, newexpr.node, a, b, tm)
+ fold_expr_rep(j, i, &newexpr.node, a, b, tm)
}),
.. *fold::default_ast_fold()
};
let af = fold::make_fold(afp);
let crate2: @ast::crate = @af.fold_crate(crate);
- *crate2
+ crate2
}
// Replace the |i|th ty (in fold order) of |crate| with |newty|.
-pub fn replace_ty_in_crate(crate: @ast::crate, i: uint, newty: ast::Ty,
- tm: test_mode) -> ast::crate {
+pub fn replace_ty_in_crate(crate: @ast::crate,
+ i: uint,
+ newty: @ast::Ty,
+ tm: test_mode)
+ -> @ast::crate {
let j: @mut uint = @mut 0u;
fn fold_ty_rep(j_: @mut uint,
i_: uint,
- newty_: ast::ty_,
+ newty_: &ast::ty_,
original: &ast::ty_,
fld: @fold::ast_fold,
tm_: test_mode)
- -> ast::ty_ {
- *j_ += 1u;
- if i_ + 1u == *j_ && safe_to_replace_ty(original, tm_) {
- newty_
- } else { fold::noop_fold_ty(original, fld) }
+ -> ast::ty_ {
+ *j_ += 1;
+ if i_ + 1 == *j_ && safe_to_replace_ty(original, tm_) {
+ copy *newty_
+ } else {
+ fold::noop_fold_ty(original, fld)
+ }
}
let afp = @fold::AstFoldFns {
- fold_ty: fold::wrap(|a,b| fold_ty_rep(j, i, newty.node, a, b, tm) ),
+ fold_ty: fold::wrap(|a,b| fold_ty_rep(j, i, &newty.node, a, b, tm)),
.. *fold::default_ast_fold()
};
let af = fold::make_fold(afp);
let crate2: @ast::crate = @af.fold_crate(crate);
- *crate2
+ crate2
}
pub fn under(n: uint, it: &fn(uint)) {
io::with_str_writer(f)
}
-pub fn check_variants_of_ast(crate: @ast::crate, codemap: @codemap::CodeMap,
- filename: &Path, cx: Context) {
+pub fn check_variants_of_ast(crate: @ast::crate,
+ codemap: @codemap::CodeMap,
+ filename: &Path,
+ cx: Context) {
let stolen = steal(crate, cx.mode);
- let extra_exprs = do common_exprs().filtered |a| {
- safe_to_use_expr(*a, cx.mode)
+ let extra_exprs = do common_exprs().filtered |&a| {
+ safe_to_use_expr(a, cx.mode)
};
- check_variants_T(crate, codemap, filename, ~"expr",
- extra_exprs + stolen.exprs, pprust::expr_to_str,
- replace_expr_in_crate, cx);
- check_variants_T(crate, codemap, filename, ~"ty", stolen.tys,
- pprust::ty_to_str, replace_ty_in_crate, cx);
-}
-
-pub fn check_variants_T<T: Copy>(
- crate: @ast::crate,
- codemap: @codemap::CodeMap,
- filename: &Path,
- thing_label: ~str,
- things: ~[T],
- stringifier: @fn(@T, @syntax::parse::token::ident_interner) -> ~str,
- replacer: @fn(@ast::crate, uint, T, test_mode) -> ast::crate,
- cx: Context
- ) {
+ check_variants_T(crate,
+ codemap,
+ filename,
+ ~"expr",
+ extra_exprs + stolen.exprs,
+ pprust::expr_to_str,
+ replace_expr_in_crate,
+ cx);
+ check_variants_T(crate,
+ codemap,
+ filename,
+ ~"ty",
+ stolen.tys,
+ pprust::ty_to_str,
+ replace_ty_in_crate,
+ cx);
+}
+
+pub fn check_variants_T<T:Copy>(crate: @ast::crate,
+ codemap: @codemap::CodeMap,
+ filename: &Path,
+ thing_label: ~str,
+ things: &[T],
+ stringifier: @fn(T, @ident_interner) -> ~str,
+ replacer: @fn(@ast::crate,
+ uint,
+ T,
+ test_mode)
+ -> @ast::crate,
+ cx: Context) {
error!("%s contains %u %s objects", filename.to_str(),
things.len(), thing_label);
error!("Replacing... #%?", uint::to_str(i));
let fname = str::from_slice(filename.to_str());
do under(uint::min(L, 30)) |j| {
- error!("With... %?", stringifier(@things[j], intr));
- let crate2 = @replacer(crate, i, things[j], cx.mode);
+ let fname = fname.to_str();
+ error!("With... %?", stringifier(things[j], intr));
+ let crate2 = replacer(crate, i, things[j], cx.mode);
// It would be best to test the *crate* for stability, but
// testing the string for stability is easier and ok for now.
let handler = diagnostic::mk_handler(None);
let str3 = do io::with_str_reader("") |rdr| {
- @as_str(|a|pprust::print_crate(
- codemap,
- intr,
- diagnostic::mk_span_handler(handler, codemap),
- crate2,
- fname,
- rdr,
- a,
- pprust::no_ann(),
- false))
+ let fname = fname.to_str();
+ let string = do as_str |a| {
+ let span_handler =
+ diagnostic::mk_span_handler(handler, codemap);
+ pprust::print_crate(codemap,
+ intr,
+ span_handler,
+ crate2,
+ fname.to_str(),
+ rdr,
+ a,
+ pprust::no_ann(),
+ false)
+ };
+ @string
};
match cx.mode {
- tm_converge => {
- check_roundtrip_convergence(str3, 1u);
- }
- tm_run => {
- let file_label = fmt!("rusttmp/%s_%s_%u_%u",
- last_part(filename.to_str()),
- thing_label, i, j);
- let safe_to_run = !(content_is_dangerous_to_run(*str3)
- || has_raw_pointers(crate2));
- check_whole_compiler(*str3, &Path(file_label),
- safe_to_run);
- }
+ tm_converge => check_roundtrip_convergence(str3, 1),
+ tm_run => {
+ let file_label = fmt!("rusttmp/%s_%s_%u_%u",
+ last_part(filename.to_str()),
+ thing_label,
+ i,
+ j);
+ let safe_to_run = !(content_is_dangerous_to_run(*str3)
+ || has_raw_pointers(crate2));
+ check_whole_compiler(*str3,
+ &Path(file_label),
+ safe_to_run);
+ }
}
}
}
// - that would be tricky, requiring use of tasks or serialization
// or randomness.
// This seems to find plenty of bugs as it is :)
-pub fn check_whole_compiler(code: ~str, suggested_filename_prefix: &Path,
+pub fn check_whole_compiler(code: &str,
+ suggested_filename_prefix: &Path,
allow_running: bool) {
let filename = &suggested_filename_prefix.with_filetype("rs");
write_file(filename, code);
let filename = Path("tmp.rs");
let sess = parse::new_parse_sess(option::None);
write_file(&filename, *code);
- let crate = parse::parse_crate_from_source_str(
- filename.to_str(), code, ~[], sess);
+ let crate = parse::parse_crate_from_source_str(filename.to_str(),
+ code,
+ ~[],
+ sess);
do io::with_str_reader(*code) |rdr| {
- as_str(|a|
- pprust::print_crate(
- sess.cm,
- // Assuming there are no token_trees
- syntax::parse::token::mk_fake_ident_interner(),
- copy sess.span_diagnostic,
- crate,
- filename.to_str(),
- rdr, a,
- pprust::no_ann(),
- false) )
+ let filename = filename.to_str();
+ do as_str |a| {
+ pprust::print_crate(sess.cm,
+ // Assuming there are no token_trees
+ token::mk_fake_ident_interner(),
+ copy sess.span_diagnostic,
+ crate,
+ filename.to_str(),
+ rdr,
+ a,
+ pprust::no_ann(),
+ false)
+ }
}
}
return *has_rp;
}
-pub fn content_is_dangerous_to_run(code: ~str) -> bool {
+pub fn content_is_dangerous_to_run(code: &str) -> bool {
let dangerous_patterns =
~[~"xfail-test",
~"import", // espeically fs, run
return false;
}
-pub fn content_is_dangerous_to_compile(code: ~str) -> bool {
+pub fn content_is_dangerous_to_compile(code: &str) -> bool {
let dangerous_patterns =
~[~"xfail-test"];
return false;
}
-pub fn content_might_not_converge(code: ~str) -> bool {
+pub fn content_might_not_converge(code: &str) -> bool {
let confusing_patterns =
~[~"xfail-test",
~"xfail-pretty",
}
pub fn check_roundtrip_convergence(code: @~str, maxIters: uint) {
-
let mut i = 0u;
let mut newv = code;
let mut oldv = code;
let file_str = file.to_str();
error!("check_variants: %?", file_str);
- let sess = parse::new_parse_sess(option::None);
- let crate =
- parse::parse_crate_from_source_str(
- file_str,
- s, ~[], sess);
+ let sess = parse::new_parse_sess(None);
+ let crate = parse::parse_crate_from_source_str(file_str.to_str(),
+ s,
+ ~[],
+ sess);
io::with_str_reader(*s, |rdr| {
+ let file_str = file_str.to_str();
error!("%s",
- as_str(|a| pprust::print_crate(
- sess.cm,
- // Assuming no token_trees
- syntax::parse::token::mk_fake_ident_interner(),
- copy sess.span_diagnostic,
- crate,
- file_str,
- rdr, a,
- pprust::no_ann(),
- false)))
+ as_str(|a| {
+ pprust::print_crate(
+ sess.cm,
+ // Assuming no token_trees
+ token::mk_fake_ident_interner(),
+ copy sess.span_diagnostic,
+ crate,
+ file_str.to_str(),
+ rdr,
+ a,
+ pprust::no_ann(),
+ false)
+ }))
});
check_variants_of_ast(crate, sess.cm, file, cx);
}
#[license = "MIT/ASL2"];
#[crate_type = "lib"];
-extern mod core(vers = "0.7-pre");
-
use core::run;
enum ValidUsage {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use back::rpath;
use driver::session::Session;
use driver::session;
use middle::ty;
use util::ppaux;
-use core::char;
use core::hash::Streaming;
use core::hash;
use core::io::WriterUtil;
use core::libc::{c_int, c_uint};
use core::os::consts::{macos, freebsd, linux, android, win32};
-use core::os;
-use core::ptr;
use core::run;
-use core::str;
-use core::vec;
use syntax::ast;
use syntax::ast_map::{path, path_mod, path_name};
use syntax::attr;
use lib::llvm::{ModuleRef, PassManagerRef};
use metadata::cstore;
- use core::cast;
use core::libc::c_int;
- use core::ptr;
- use core::str;
pub mod rusti {
#[nolink]
use lib::llvm::{False, ModuleRef, mk_pass_manager, mk_target_data};
use lib;
- use core::prelude::*;
use core::libc::{c_int, c_uint};
use core::path::Path;
- use core::str;
use core::run;
pub fn is_object_or_assembly_or_exe(ot: output_type) -> bool {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use driver::session;
use metadata::cstore;
use metadata::filesearch;
-use core::os;
-use core::uint;
use core::util;
-use core::vec;
use core::hashmap::HashSet;
fn not_win32(os: session::os) -> bool {
// FIXME(#2119): the outer attribute should be #[cfg(unix, test)], then
// these redundant #[cfg(test)] blocks can be removed
#[cfg(test)]
- use core::prelude::*;
#[cfg(test)]
use back::rpath::{get_absolute_rpath, get_install_prefix_rpath};
#[cfg(test)]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use back::link;
use back::{arm, x86, x86_64, mips};
use driver::session::{Aggressive};
-> @ast::crate {
match *input {
file_input(ref file) => {
- parse::parse_crate_from_file_using_tts(&(*file), cfg, sess.parse_sess)
+ parse::parse_crate_from_file(&(*file), cfg, sess.parse_sess)
}
str_input(ref src) => {
// FIXME (#2319): Don't really want to box the source string
#[cfg(test)]
mod test {
- use core::prelude::*;
-
use driver::driver::{build_configuration, build_session};
use driver::driver::{build_session_options, optgroups, str_input};
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use back::link;
use back::target_strs;
use back;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use syntax::{ast, fold, attr};
-use core::option;
-use core::vec;
-
type in_cfg_pred = @fn(attrs: ~[ast::attribute]) -> bool;
struct Context {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use driver::session::Session;
-use core::vec;
use syntax::ast;
use syntax::attr;
use syntax::codemap;
#[abi = "rust-intrinsic"]
pub extern "rust-intrinsic" {
pub fn get_tydesc<T>() -> *();
- pub fn visit_tydesc(++td: *TyDesc, &&tv: @TyVisitor);
+ pub fn visit_tydesc(++td: *TyDesc, ++tv: @TyVisitor);
}
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use driver::session::Session;
use syntax::parse;
use syntax::ast;
use syntax::codemap::spanned;
-use core::vec;
-
pub fn inject_intrinsic(sess: Session, crate: @ast::crate) -> @ast::crate {
let intrinsic_module = @(include_str!("intrinsic.rs").to_owned());
// Code that generates a test runner to run all the tests in a crate
-use core::prelude::*;
-
use driver::session;
use front::config;
-use core::vec;
use syntax::ast_util::*;
use syntax::attr;
use syntax::codemap::{dummy_sp, span, ExpandedFrom, CallInfo, NameAndSpan};
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use core::hashmap::HashMap;
use core::libc::c_uint;
-use core::option;
-use core::ptr;
-use core::str;
-use core::vec;
pub type Opcode = u32;
pub type Bool = c_uint;
tag_table_freevars = 0x59,
tag_table_tcache = 0x5a,
tag_table_param_defs = 0x5b,
- tag_table_inferred_modes = 0x5c,
tag_table_mutbl = 0x5d,
tag_table_last_use = 0x5e,
tag_table_spill = 0x5f,
//! Validates all used crates and extern libraries and loads their metadata
-use core::prelude::*;
-
use metadata::cstore;
use metadata::decoder;
use metadata::filesearch::FileSearch;
use metadata::loader;
use core::hashmap::HashMap;
-use core::vec;
use syntax::attr;
use syntax::codemap::{span, dummy_sp};
use syntax::diagnostic::span_handler;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
// Searching for information from the cstore
-use core::prelude::*;
-
use metadata::common::*;
use metadata::cstore;
use metadata::decoder;
use metadata;
use middle::{ty, resolve};
-use core::vec;
use reader = std::ebml::reader;
use syntax::ast;
use syntax::ast_map;
// The crate store - a central repo for information collected about external
// crates and libraries
-use core::prelude::*;
-
use metadata::cstore;
use metadata::decoder;
use core::hashmap::HashMap;
-use core::vec;
use std;
use syntax::ast;
use syntax::parse::token::ident_interner;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
// Decoding metadata from a single crate's metadata
-use core::prelude::*;
-
use metadata::cstore::crate_metadata;
use metadata::common::*;
use metadata::csearch::{ProvidedTraitMethodInfo, StaticMethodInfo};
}
}
-pub fn item_type(_item_id: ast::def_id, item: ebml::Doc,
- tcx: ty::ctxt, cdata: cmd) -> ty::t {
+pub fn item_type(_: ast::def_id, item: ebml::Doc, tcx: ty::ctxt, cdata: cmd)
+ -> ty::t {
doc_type(item, tcx, cdata)
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
// Metadata encoding
-use core::prelude::*;
-
use metadata::common::*;
use metadata::cstore;
use metadata::decoder;
use core::flate;
use core::hash::HashUtil;
use core::hashmap::HashMap;
-use core::int;
-use core::io::{Writer, WriterUtil};
-use core::io;
-use core::str;
-use core::to_bytes::IterBytes;
-use core::uint;
-use core::vec;
use std::serialize::Encodable;
use std;
use syntax::abi::AbiSet;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
// A module for searching for libraries
// FIXME (#2658): I'm not happy how this module turned out. Should
// probably just be folded into cstore.
-use core::prelude::*;
-
-use core::option;
-use core::os;
-use core::result::Result;
-use core::result;
-use core::str;
-
pub type pick<'self, T> = &'self fn(path: &Path) -> Option<T>;
pub fn pick_file(file: Path, path: &Path) -> Option<Path> {
//! Finds crate binaries and loads their metadata
-use core::prelude::*;
-
use lib::llvm::{False, llvm, mk_object_file, mk_section_iter};
use metadata::decoder;
use metadata::encoder;
use syntax::print::pprust;
use syntax::{ast, attr};
-use core::cast;
use core::flate;
-use core::io::WriterUtil;
-use core::io;
use core::os::consts::{macos, freebsd, linux, android, win32};
-use core::option;
-use core::ptr;
-use core::str;
-use core::uint;
-use core::vec;
pub enum os {
os_macos,
// tjc note: Would be great to have a `match check` macro equivalent
// for some of these
-use core::prelude::*;
-
use middle::ty;
-use core::str;
-use core::uint;
-use core::vec;
use syntax::abi::AbiSet;
use syntax::abi;
use syntax::ast;
}
fn parse_arg(st: @mut PState, conv: conv_did) -> ty::arg {
- ty::arg { mode: parse_mode(st), ty: parse_ty(st, conv) }
-}
-
-fn parse_mode(st: @mut PState) -> ast::mode {
- let m = ast::expl(match next(st) {
- '+' => ast::by_copy,
- '=' => ast::by_ref,
- _ => fail!(~"bad mode")
- });
- return m;
+ ty::arg {
+ ty: parse_ty(st, conv)
+ }
}
fn parse_closure_ty(st: @mut PState, conv: conv_did) -> ty::ClosureTy {
assert!((next(st) == '['));
let mut inputs: ~[ty::arg] = ~[];
while peek(st) != ']' {
- let mode = parse_mode(st);
- inputs.push(ty::arg { mode: mode, ty: parse_ty(st, conv) });
+ inputs.push(ty::arg { ty: parse_ty(st, conv) });
}
st.pos += 1u; // eat the ']'
let ret_ty = parse_ty(st, conv);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
// Type encoding
-use core::prelude::*;
-
use middle::ty::param_ty;
use middle::ty;
}
pub fn enc_arg(w: @io::Writer, cx: @ctxt, arg: ty::arg) {
- enc_mode(w, cx, arg.mode);
enc_ty(w, cx, arg.ty);
}
-pub fn enc_mode(w: @io::Writer, cx: @ctxt, m: mode) {
- match ty::resolved_mode(cx.tcx, m) {
- by_copy => w.write_char('+'),
- by_ref => w.write_char('='),
- }
-}
-
fn enc_purity(w: @io::Writer, p: purity) {
match p {
pure_fn => w.write_char('p'),
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use c = metadata::common;
use cstore = metadata::cstore;
use driver::session::Session;
ast::def_mod(did) => { ast::def_mod(did.tr(xcx)) }
ast::def_foreign_mod(did) => { ast::def_foreign_mod(did.tr(xcx)) }
ast::def_const(did) => { ast::def_const(did.tr(xcx)) }
- ast::def_arg(nid, m, b) => { ast::def_arg(xcx.tr_id(nid), m, b) }
+ ast::def_arg(nid, b) => { ast::def_arg(xcx.tr_id(nid), b) }
ast::def_local(nid, b) => { ast::def_local(xcx.tr_id(nid), b) }
ast::def_variant(e_did, v_did) => {
ast::def_variant(e_did.tr(xcx), v_did.tr(xcx))
do ebml_w.emit_field(~"origin", 1u) {
mme.origin.encode(ebml_w);
}
+ do ebml_w.emit_field(~"self_mode", 3) {
+ mme.self_mode.encode(ebml_w);
+ }
}
}
do ebml_w.emit_struct_field("origin", 1u) {
mme.origin.encode(ebml_w);
}
+ do ebml_w.emit_struct_field("self_mode", 3) {
+ mme.self_mode.encode(ebml_w);
+ }
}
}
Decodable::decode(self);
method_origin.tr(xcx)
}),
+ self_mode: self.read_field(~"self_mode", 3, || {
+ let self_mode: ty::SelfMode = Decodable::decode(self);
+ self_mode
+ }),
}
}
}
self_arg: self.read_struct_field("self_arg", 0u, || {
self.read_arg(xcx)
}),
- explicit_self: self.read_struct_field("explicit_self", 2u, || {
+ explicit_self: self.read_struct_field("explicit_self", 2, || {
let self_type: ast::self_ty_ = Decodable::decode(self);
self_type
}),
Decodable::decode(self);
method_origin.tr(xcx)
}),
+ self_mode: self.read_struct_field("self_mode", 3, || {
+ let self_mode: ty::SelfMode = Decodable::decode(self);
+ self_mode
+ }),
}
}
}
}
}
- // I believe it is not necessary to encode this information. The
- // ids will appear in the AST but in the *type* information, which
- // is what we actually use in trans, all modes will have been
- // resolved.
- //
- //for tcx.inferred_modes.find(&id).each |m| {
- // ebml_w.tag(c::tag_table_inferred_modes) {||
- // ebml_w.id(id);
- // ebml_w.tag(c::tag_table_val) {||
- // tyencode::enc_mode(ebml_w.writer, ty_str_ctxt(), m);
- // }
- // }
- //}
-
if maps.mutbl_map.contains(&id) {
do ebml_w.tag(c::tag_table_mutbl) {
ebml_w.id(id);
// 3. assignments do not affect things loaned out as immutable
// 4. moves do not affect things loaned out in any way
-use core::prelude::*;
-
use middle::moves;
use middle::typeck::check::PurityState;
use middle::borrowck::{Loan, bckerr, BorrowckCtxt, inherent_mutability};
use util::ppaux::ty_to_str;
use core::hashmap::HashSet;
-use core::uint;
use core::util::with;
use syntax::ast::m_mutbl;
use syntax::ast;
// their associated scopes. In phase two, checking loans, we will then make
// sure that all of these loans are honored.
-use core::prelude::*;
-
use middle::borrowck::preserve::{PreserveCondition, PcOk, PcIfPure};
use middle::borrowck::{Loan, bckerr, bckres, BorrowckCtxt, err_mutbl};
use middle::borrowck::{LoanKind, TotalFreeze, PartialFreeze,
use util::ppaux::{Repr, region_to_str};
use core::hashmap::{HashSet, HashMap};
-use core::vec;
use syntax::ast::{m_const, m_imm, m_mutbl};
use syntax::ast;
use syntax::codemap::span;
visit::visit_expr(ex, self, vt);
}
- ast::expr_call(f, ref args, _) => {
- let arg_tys = ty::ty_fn_args(ty::expr_ty(self.tcx(), f));
- let scope_r = ty::re_scope(ex.id);
- for vec::each2(*args, arg_tys) |arg, arg_ty| {
- match ty::resolved_mode(self.tcx(), arg_ty.mode) {
- ast::by_ref => {
- let arg_cmt = self.bccx.cat_expr(*arg);
- self.guarantee_valid(arg_cmt, m_imm, scope_r);
- }
- ast::by_copy => {}
- }
- }
- visit::visit_expr(ex, self, vt);
- }
-
- ast::expr_method_call(_, _, _, ref args, _) => {
- let arg_tys = ty::ty_fn_args(ty::node_id_to_type(self.tcx(),
- ex.callee_id));
- let scope_r = ty::re_scope(ex.id);
- for vec::each2(*args, arg_tys) |arg, arg_ty| {
- match ty::resolved_mode(self.tcx(), arg_ty.mode) {
- ast::by_ref => {
- let arg_cmt = self.bccx.cat_expr(*arg);
- self.guarantee_valid(arg_cmt, m_imm, scope_r);
- }
- ast::by_copy => {}
- }
- }
-
- visit::visit_expr(ex, self, vt);
- }
-
ast::expr_match(ex_v, ref arms) => {
let cmt = self.bccx.cat_expr(ex_v);
for (*arms).each |arm| {
// Loan(Ex, M, S) = Ls holds if ToAddr(Ex) will remain valid for the entirety
// of the scope S, presuming that the returned set of loans `Ls` are honored.
-use core::prelude::*;
-
use middle::borrowck::{Loan, bckerr, bckres, BorrowckCtxt, err_mutbl};
use middle::borrowck::{LoanKind, TotalFreeze, PartialFreeze,
TotalTake, PartialTake, Immobile};
use middle::ty;
use util::common::indenter;
-use core::result::{Err, Ok};
use syntax::ast::m_imm;
use syntax::ast;
given a memory location and not used as immediates.
*/
-use core::prelude::*;
-
use middle::mem_categorization::*;
use middle::ty;
use middle::typeck;
use util::ppaux::note_and_explain_region;
use core::hashmap::{HashSet, HashMap};
-use core::io;
-use core::result::{Result, Ok, Err};
use core::to_bytes;
use syntax::ast::{mutability, m_imm};
use syntax::ast;
// the scope S.
//
-use core::prelude::*;
-
use middle::borrowck::{RootInfo, bckerr, bckerr_code, bckres, BorrowckCtxt};
use middle::borrowck::{err_mut_uniq, err_mut_variant};
use middle::borrowck::{err_out_of_root_scope, err_out_of_scope};
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use driver::session::Session;
use middle::resolve;
use middle::ty;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use middle::const_eval::{compare_const_vals, lookup_const_by_id};
use middle::const_eval::{eval_const_expr, const_val, const_bool};
use middle::pat_util::*;
use middle::moves;
use util::ppaux::ty_to_str;
-use core::uint;
-use core::vec;
use std::sort;
use syntax::ast::*;
use syntax::ast_util::{unguarded_pat, walk_pat};
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use metadata::csearch;
use middle::astencode;
use middle::ty;
use middle;
-use core::float;
-use core::vec;
use syntax::{ast, ast_map, ast_util, visit};
use syntax::ast::*;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
// A pass that annotates for each loops and functions with the free
// variables that they contain.
-use core::prelude::*;
-
use middle::resolve;
use middle::ty;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use middle::freevars::freevar_entry;
use middle::freevars;
use middle::liveness;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
// Detecting language items.
//
// Language items are items that represent concepts intrinsic to the language
//
// * Functions called by the compiler itself.
-use core::prelude::*;
-
use driver::session::Session;
use metadata::csearch::each_lang_item;
use metadata::cstore::iter_crate_data;
use syntax::visit::{default_simple_visitor, mk_simple_visitor, SimpleVisitor};
use syntax::visit::visit_crate;
+use core::cast::transmute;
use core::hashmap::HashMap;
-use core::ptr;
pub enum LangItem {
ConstTraitLangItem, // 0
}
fn collect_local_language_items(&self) {
- let this = ptr::addr_of(&self);
- visit_crate(self.crate, (), mk_simple_visitor(@SimpleVisitor {
- visit_item: |item| {
- for item.attrs.each |attribute| {
- unsafe {
- (*this).match_and_collect_meta_item(
- local_def(item.id),
- attribute.node.value
- );
+ unsafe {
+ let this: *LanguageItemCollector<'self> = transmute(self);
+ visit_crate(self.crate, (), mk_simple_visitor(@SimpleVisitor {
+ visit_item: |item| {
+ for item.attrs.each |attribute| {
+ unsafe {
+ (*this).match_and_collect_meta_item(
+ local_def(item.id),
+ attribute.node.value
+ );
+ }
}
- }
- },
- .. *default_simple_visitor()
- }));
+ },
+ .. *default_simple_visitor()
+ }));
+ }
}
fn collect_external_language_items(&self) {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use driver::session::Session;
use driver::session;
use middle::ty;
use util::ppaux::{ty_to_str};
use core::hashmap::HashMap;
-use core::char;
-use core::cmp;
-use core::i8;
-use core::i16;
-use core::i32;
-use core::i64;
-use core::int;
-use core::str;
-use core::u8;
-use core::u16;
-use core::u32;
-use core::u64;
-use core::uint;
-use core::vec;
use std::smallintmap::SmallIntMap;
use syntax::attr;
use syntax::codemap::span;
use syntax::codemap;
-use syntax::print::pprust::mode_to_str;
use syntax::{ast, visit};
/**
unrecognized_lint,
non_implicitly_copyable_typarams,
vecs_implicitly_copyable,
- deprecated_mode,
deprecated_pattern,
non_camel_case_types,
type_limits,
deprecated_mutable_fields,
deprecated_drop,
unused_unsafe,
- foreign_mode,
managed_heap_memory,
owned_heap_memory,
heap_memory,
- legacy_modes,
-
unused_variable,
dead_assignment,
unused_mut,
default: warn
}),
- (~"deprecated_mode",
- LintSpec {
- lint: deprecated_mode,
- desc: "warn about deprecated uses of modes",
- default: warn
- }),
-
- (~"foreign_mode",
- LintSpec {
- lint: foreign_mode,
- desc: "warn about deprecated uses of modes in foreign fns",
- default: warn
- }),
-
(~"deprecated_pattern",
LintSpec {
lint: deprecated_pattern,
default: allow
}),
- (~"legacy modes",
- LintSpec {
- lint: legacy_modes,
- desc: "allow legacy modes",
- default: forbid
- }),
-
(~"type_limits",
LintSpec {
lint: type_limits,
check_item_path_statement(cx, i);
check_item_non_camel_case_types(cx, i);
check_item_heap(cx, i);
- check_item_deprecated_modes(cx, i);
check_item_type_limits(cx, i);
check_item_default_methods(cx, i);
check_item_deprecated_mutable_fields(cx, i);
fn check_foreign_fn(cx: ty::ctxt, fn_id: ast::node_id,
decl: &ast::fn_decl) {
- // warn about `&&` mode on foreign functions, both because it is
- // deprecated and because its semantics have changed recently:
- for decl.inputs.eachi |i, arg| {
- match ty::resolved_mode(cx, arg.mode) {
- ast::by_copy => {}
- ast::by_ref => {
- cx.sess.span_lint(
- foreign_mode, fn_id, fn_id, arg.ty.span,
- fmt!("foreign function uses `&&` mode \
- on argument %u", i));
- }
- }
- }
-
let tys = vec::map(decl.inputs, |a| a.ty );
for vec::each(vec::append_one(tys, decl.output)) |ty| {
match ty.node {
visit::visit_item(it, (), visit);
}
-fn check_fn(tcx: ty::ctxt, fk: &visit::fn_kind, decl: &ast::fn_decl,
- _body: &ast::blk, span: span, id: ast::node_id) {
+fn check_fn(_: ty::ctxt,
+ fk: &visit::fn_kind,
+ _: &ast::fn_decl,
+ _: &ast::blk,
+ _: span,
+ id: ast::node_id) {
debug!("lint check_fn fk=%? id=%?", fk, id);
-
- // Check for deprecated modes
- match *fk {
- // don't complain about blocks, since they tend to get their modes
- // specified from the outside
- visit::fk_fn_block(*) => {}
-
- _ => {
- let fn_ty = ty::node_id_to_type(tcx, id);
- check_fn_deprecated_modes(tcx, fn_ty, decl, span, id);
- }
- }
-
-}
-
-fn check_fn_deprecated_modes(tcx: ty::ctxt, fn_ty: ty::t, decl: &ast::fn_decl,
- span: span, id: ast::node_id) {
- match ty::get(fn_ty).sty {
- ty::ty_closure(ty::ClosureTy {sig: ref sig, _}) |
- ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, _}) => {
- let mut counter = 0;
- for vec::each2(sig.inputs, decl.inputs) |arg_ty, arg_ast| {
- counter += 1;
- debug!("arg %d, ty=%s, mode=%s",
- counter,
- ty_to_str(tcx, arg_ty.ty),
- mode_to_str(arg_ast.mode));
- match arg_ast.mode {
- ast::expl(ast::by_copy) => {
- if !tcx.legacy_modes {
- tcx.sess.span_lint(
- deprecated_mode, id, id, span,
- fmt!("argument %d uses by-copy mode",
- counter));
- }
- }
-
- ast::expl(_) => {
- tcx.sess.span_lint(
- deprecated_mode, id, id,
- span,
- fmt!("argument %d uses an explicit mode", counter));
- }
-
- ast::infer(_) => {
- if tcx.legacy_modes {
- let kind = ty::type_contents(tcx, arg_ty.ty);
- if !kind.is_safe_for_default_mode(tcx) {
- tcx.sess.span_lint(
- deprecated_mode, id, id,
- span,
- fmt!("argument %d uses the default mode \
- but shouldn't",
- counter));
- }
- }
- }
- }
-
- match ty::get(arg_ty.ty).sty {
- ty::ty_closure(*) | ty::ty_bare_fn(*) => {
- let span = arg_ast.ty.span;
- // Recurse to check fn-type argument
- match arg_ast.ty.node {
- ast::ty_closure(@ast::TyClosure{decl: ref d, _}) |
- ast::ty_bare_fn(@ast::TyBareFn{decl: ref d, _})=>{
- check_fn_deprecated_modes(tcx, arg_ty.ty,
- d, span, id);
- }
- ast::ty_path(*) => {
- // This is probably a typedef, so we can't
- // see the actual fn decl
- // e.g. fn foo(f: InitOp<T>)
- }
- _ => {
- tcx.sess.span_warn(span, ~"what");
- error!("arg %d, ty=%s, mode=%s",
- counter,
- ty_to_str(tcx, arg_ty.ty),
- mode_to_str(arg_ast.mode));
- error!("%?",arg_ast.ty.node);
- fail!()
- }
- };
- }
- _ => ()
- }
- }
- }
-
- _ => tcx.sess.impossible_case(span, ~"check_fn: function has \
- non-fn type")
- }
-}
-
-fn check_item_deprecated_modes(tcx: ty::ctxt, it: @ast::item) {
- match it.node {
- ast::item_ty(ty, _) => {
- match ty.node {
- ast::ty_closure(@ast::TyClosure {decl: ref decl, _}) |
- ast::ty_bare_fn(@ast::TyBareFn {decl: ref decl, _}) => {
- let fn_ty = ty::node_id_to_type(tcx, it.id);
- check_fn_deprecated_modes(
- tcx, fn_ty, decl, ty.span, it.id)
- }
- _ => ()
- }
- }
- _ => ()
- }
}
pub fn check_crate(tcx: ty::ctxt, crate: @ast::crate) {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
/*!
* A classic liveness analysis based on dataflow over the AST. Computes,
* for each local variable in a function, whether that variable is live
* to return explicitly.
*/
-use core::prelude::*;
use middle::lint::{unused_variable, dead_assignment};
use middle::pat_util;
use middle::moves;
use util::ppaux::ty_to_str;
+use core::cast::transmute;
use core::hashmap::HashMap;
-use core::io::WriterUtil;
-use core::io;
-use core::ptr;
-use core::to_str;
-use core::uint;
-use core::vec;
use core::util::with;
use syntax::ast::*;
use syntax::codemap::span;
}
enum VarKind {
- Arg(node_id, ident, rmode),
+ Arg(node_id, ident),
Local(LocalInfo),
ImplicitRet
}
fn relevant_def(def: def) -> Option<node_id> {
match def {
- def_binding(nid, _) |
- def_arg(nid, _, _) |
- def_local(nid, _) |
- def_self(nid, _) => Some(nid),
+ def_binding(nid, _) |
+ def_arg(nid, _) |
+ def_local(nid, _) |
+ def_self(nid, _) => Some(nid),
- _ => None
+ _ => None
}
}
self.num_vars += 1;
match vk {
- Local(LocalInfo {id:node_id, _}) |
- Arg(node_id, _, _) => {
+ Local(LocalInfo { id: node_id, _ }) | Arg(node_id, _) => {
self.variable_map.insert(node_id, v);
- }
+ },
ImplicitRet => {}
}
fn variable_name(&mut self, var: Variable) -> @~str {
match self.var_kinds[*var] {
- Local(LocalInfo {ident: nm, _}) |
- Arg(_, nm, _) => self.tcx.sess.str_of(nm),
+ Local(LocalInfo { ident: nm, _ }) | Arg(_, nm) => {
+ self.tcx.sess.str_of(nm)
+ },
ImplicitRet => @~"<implicit-ret>"
}
}
let vk = self.var_kinds[*var];
debug!("Node %d is a last use of variable %?", expr_id, vk);
match vk {
- Arg(id, _, by_copy) |
- Local(LocalInfo {id: id, kind: FromLetNoInitializer, _}) |
- Local(LocalInfo {id: id, kind: FromLetWithInitializer, _}) |
- Local(LocalInfo {id: id, kind: FromMatch(_), _}) => {
- let v = match self.last_use_map.find(&expr_id) {
- Some(&v) => v,
- None => {
- let v = @mut ~[];
- self.last_use_map.insert(expr_id, v);
- v
- }
- };
+ Arg(id, _) |
+ Local(LocalInfo { id: id, kind: FromLetNoInitializer, _ }) |
+ Local(LocalInfo { id: id, kind: FromLetWithInitializer, _ }) |
+ Local(LocalInfo { id: id, kind: FromMatch(_), _ }) => {
+ let v = match self.last_use_map.find(&expr_id) {
+ Some(&v) => v,
+ None => {
+ let v = @mut ~[];
+ self.last_use_map.insert(expr_id, v);
+ v
+ }
+ };
- v.push(id);
- }
- Arg(_, _, by_ref) |
- ImplicitRet => {
- debug!("--but it is not owned");
- }
+ v.push(id);
+ }
+ ImplicitRet => debug!("--but it is not owned"),
}
}
}
self.last_use_map,
self.cur_item);
- debug!("creating fn_maps: %x", ptr::addr_of(&(*fn_maps)) as uint);
+ unsafe {
+ debug!("creating fn_maps: %x", transmute(&*fn_maps));
+ }
for decl.inputs.each |arg| {
- let mode = ty::resolved_mode(self.tcx, arg.mode);
do pat_util::pat_bindings(self.tcx.def_map, arg.pat)
|_bm, arg_id, _x, path| {
debug!("adding argument %d", arg_id);
let ident = ast_util::path_to_ident(path);
- fn_maps.add_variable(Arg(arg_id, ident, mode));
+ fn_maps.add_variable(Arg(arg_id, ident));
}
};
match method.self_ty.node {
sty_value | sty_region(*) | sty_box(_) | sty_uniq(_) => {
fn_maps.add_variable(Arg(method.self_id,
- special_idents::self_,
- by_copy));
+ special_idents::self_));
}
sty_static => {}
}
}
fk_dtor(_, _, self_id, _) => {
- fn_maps.add_variable(Arg(self_id,
- special_idents::self_,
- by_copy));
+ fn_maps.add_variable(Arg(self_id, special_idents::self_));
}
fk_item_fn(*) | fk_anon(*) | fk_fn_block(*) => {}
}
entry_ln
}
- fn propagate_through_fn_block(&self, decl: &fn_decl, blk: &blk)
- -> LiveNode {
- // inputs passed by & mode should be considered live on exit:
- for decl.inputs.each |arg| {
- match ty::resolved_mode(self.tcx, arg.mode) {
- by_ref => {
- // By val and by ref do not own, so register a
- // read at the end. This will prevent us from
- // moving out of such variables but also prevent
- // us from registering last uses and so forth.
- do pat_util::pat_bindings(self.tcx.def_map, arg.pat)
- |_bm, arg_id, _sp, _path|
- {
- let var = self.variable(arg_id, blk.span);
- self.acc(self.s.exit_ln, var, ACC_READ);
- }
- }
- by_copy => {
- // By copy is an owned mode. If we don't use the
- // variable, nobody will.
- }
- }
- }
-
+ fn propagate_through_fn_block(&self, _: &fn_decl, blk: &blk)
+ -> LiveNode {
// the fallthrough exit is only for those cases where we do not
// explicitly return:
self.init_from_succ(self.s.fallthrough_ln, self.s.exit_ln);
fn propagate_through_opt_expr(&self, opt_expr: Option<@expr>,
succ: LiveNode) -> LiveNode {
- do iter::foldl(&opt_expr, succ) |succ, expr| {
+ do old_iter::foldl(&opt_expr, succ) |succ, expr| {
self.propagate_through_expr(*expr, *succ)
}
}
// borrow checker
let vk = self.ir.var_kinds[*var];
match vk {
- Arg(_, name, _) => {
+ Arg(_, name) => {
self.tcx.sess.span_err(
move_expr.span,
fmt!("illegal move from argument `%s`, which is not \
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
/*!
* # Categorization
*
* then an index to jump forward to the relevant item.
*/
-use core::prelude::*;
-
use middle::ty;
use middle::typeck;
use util::ppaux::{ty_to_str, region_to_str};
use util::common::indenter;
-use core::uint;
use syntax::ast::{m_imm, m_const, m_mutbl};
use syntax::ast;
use syntax::codemap::span;
}
}
- ast::def_arg(vid, mode, mutbl) => {
+ ast::def_arg(vid, mutbl) => {
// Idea: make this could be rewritten to model by-ref
// stuff as `&const` and `&mut`?
// m: mutability of the argument
// lp: loan path, must be none for aliasable things
let m = if mutbl {McDeclared} else {McImmutable};
- let lp = match ty::resolved_mode(self.tcx, mode) {
- ast::by_copy => Some(@lp_arg(vid)),
- ast::by_ref => None,
- };
+ let lp = Some(@lp_arg(vid));
@cmt_ {
id:id,
span:span,
*/
-use core::prelude::*;
-
use middle::pat_util::{pat_bindings};
use middle::freevars;
use middle::ty;
use util::common::indenter;
use core::hashmap::{HashSet, HashMap};
-use core::vec;
use syntax::ast::*;
use syntax::ast_util;
use syntax::visit;
receiver_expr: @expr,
visitor: vt<VisitContext>)
{
- self.use_fn_arg(by_copy, receiver_expr, visitor);
+ self.use_fn_arg(receiver_expr, visitor);
}
fn use_fn_args(&self,
- callee_id: node_id,
+ _: node_id,
arg_exprs: &[@expr],
- visitor: vt<VisitContext>)
- {
- /*!
- *
- * Uses the argument expressions according to the function modes.
- */
-
- let arg_tys =
- ty::ty_fn_args(ty::node_id_to_type(self.tcx, callee_id));
- for vec::each2(arg_exprs, arg_tys) |arg_expr, arg_ty| {
- let arg_mode = ty::resolved_mode(self.tcx, arg_ty.mode);
- self.use_fn_arg(arg_mode, *arg_expr, visitor);
+ visitor: vt<VisitContext>) {
+ //! Uses the argument expressions.
+ for arg_exprs.each |arg_expr| {
+ self.use_fn_arg(*arg_expr, visitor);
}
}
- fn use_fn_arg(&self,
- arg_mode: rmode,
- arg_expr: @expr,
- visitor: vt<VisitContext>)
- {
- /*!
- *
- * Uses the argument according to the given argument mode.
- */
-
- match arg_mode {
- by_ref => self.use_expr(arg_expr, Read, visitor),
- by_copy => self.consume_expr(arg_expr, visitor)
- }
+ fn use_fn_arg(&self, arg_expr: @expr, visitor: vt<VisitContext>) {
+ //! Uses the argument.
+ self.consume_expr(arg_expr, visitor)
}
fn arms_have_by_move_bindings(&self,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use middle::resolve;
use core::hashmap::HashMap;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
// A pass that checks to make sure private fields and methods aren't used
// outside their scopes.
-use core::prelude::*;
-
use metadata::csearch;
use middle::ty::{ty_struct, ty_enum};
use middle::ty;
*/
-use core::prelude::*;
-
use driver::session::Session;
use metadata::csearch;
use middle::resolve;
use middle::ty;
use core::hashmap::{HashMap, HashSet};
-use core::vec;
use syntax::ast_map;
use syntax::codemap::span;
use syntax::print::pprust;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use driver::session;
use driver::session::Session;
use metadata::csearch::{each_path, get_trait_method_def_ids};
use middle::lint::{get_lint_level, get_lint_settings_level};
use middle::pat_util::pat_bindings;
-use core::str;
-use core::vec;
use syntax::ast::{RegionTyParamBound, TraitTyParamBound, _mod, add, arm};
use syntax::ast::{binding_mode, bitand, bitor, bitxor, blk};
use syntax::ast::{bind_infer, bind_by_ref, bind_by_copy};
use syntax::ast::{gt, ident, inherited, item, item_struct};
use syntax::ast::{item_const, item_enum, item_fn, item_foreign_mod};
use syntax::ast::{item_impl, item_mac, item_mod, item_trait, item_ty, le};
-use syntax::ast::{local, local_crate, lt, method, mode, mul};
+use syntax::ast::{local, local_crate, lt, method, mul};
use syntax::ast::{named_field, ne, neg, node_id, pat, pat_enum, pat_ident};
use syntax::ast::{Path, pat_lit, pat_range, pat_struct};
use syntax::ast::{prim_ty, private, provided};
pub enum PatternBindingMode {
RefutableMode,
LocalIrrefutableMode,
- ArgumentIrrefutableMode(mode)
+ ArgumentIrrefutableMode,
}
#[deriving(Eq)]
let imports: &mut ~[@ImportDirective] = &mut *module_.imports;
let import_count = imports.len();
if index != import_count {
- self.session.span_err(imports[index].span, ~"unresolved import");
+ let sn = self.session.codemap.span_to_snippet(imports[index].span);
+ if str::contains(sn, "::") {
+ self.session.span_err(imports[index].span, ~"unresolved import");
+ } else {
+ let err = fmt!("unresolved import (maybe you meant `%s::*`?)",
+ sn.slice(0, sn.len() - 1)); // -1 to adjust for semicolon
+ self.session.span_err(imports[index].span, err);
+ }
}
// Descend into children and anonymous children.
}
Some(declaration) => {
for declaration.inputs.each |argument| {
- let binding_mode =
- ArgumentIrrefutableMode(argument.mode);
+ let binding_mode = ArgumentIrrefutableMode;
let mutability =
if argument.is_mutbl {Mutable} else {Immutable};
self.resolve_pattern(argument.pat,
// But for locals, we use `def_local`.
def_local(pattern.id, is_mutable)
}
- ArgumentIrrefutableMode(argument_mode) => {
+ ArgumentIrrefutableMode => {
// And for function arguments, `def_arg`.
- def_arg(pattern.id, argument_mode,
- is_mutable)
+ def_arg(pattern.id, is_mutable)
}
};
// Type substitutions.
-use core::prelude::*;
use middle::ty;
use util::ppaux::Repr;
*
*/
-use core::prelude::*;
-
use back::abi;
use lib::llvm::{llvm, ValueRef, BasicBlockRef};
use middle::const_eval;
# Translation of inline assembly.
*/
-use core::prelude::*;
-
use lib;
use middle::trans::build::*;
use middle::trans::callee;
constraints.push(copy *c);
let aoutty = ty::arg {
- mode: ast::expl(ast::by_copy),
ty: expr_ty(bcx, out)
};
aoutputs.push(unpack_result!(bcx, {
- callee::trans_arg_expr(bcx, aoutty, out, &mut cleanups, None, callee::DontAutorefArg)
+ callee::trans_arg_expr(bcx,
+ aoutty,
+ ty::ByCopy,
+ out,
+ &mut cleanups,
+ None,
+ callee::DontAutorefArg)
}));
let e = match out.node {
};
let outty = ty::arg {
- mode: ast::expl(ast::by_copy),
ty: expr_ty(bcx, e)
};
unpack_result!(bcx, {
- callee::trans_arg_expr(bcx, outty, e, &mut cleanups, None, callee::DontAutorefArg)
+ callee::trans_arg_expr(bcx,
+ outty,
+ ty::ByCopy,
+ e,
+ &mut cleanups,
+ None,
+ callee::DontAutorefArg)
})
};
constraints.push(copy *c);
let inty = ty::arg {
- mode: ast::expl(ast::by_copy),
ty: expr_ty(bcx, in)
};
unpack_result!(bcx, {
- callee::trans_arg_expr(bcx, inty, in, &mut cleanups, None, callee::DontAutorefArg)
+ callee::trans_arg_expr(bcx,
+ inty,
+ ty::ByCopy,
+ in,
+ &mut cleanups,
+ None,
+ callee::DontAutorefArg)
})
};
// but many TypeRefs correspond to one ty::t; for instance, tup(int, int,
// int) and rec(x=int, y=int, z=int) will have the same TypeRef.
-use core::prelude::*;
-
use back::link::{mangle_exported_name};
use back::{link, abi, upcall};
use driver::session;
use core::hash;
use core::hashmap::{HashMap, HashSet};
-use core::int;
-use core::io;
use core::libc::c_uint;
-use core::uint;
use std::time;
use syntax::ast::ident;
use syntax::ast_map::{path, path_elt_to_str, path_name};
raw_llargs: &[ValueRef],
arg_tys: &[ty::arg]) -> block {
let _icx = fcx.insn_ctxt("copy_args_to_allocas");
- let tcx = bcx.tcx();
let mut bcx = bcx;
match fcx.llself {
// the argument would be passed by value, we store it into an alloca.
// This alloca should be optimized away by LLVM's mem-to-reg pass in
// the event it's not truly needed.
- let llarg;
- match ty::resolved_mode(tcx, arg_ty.mode) {
- ast::by_ref => {
- llarg = raw_llarg;
- }
- ast::by_copy => {
- // only by value if immediate:
- if datum::appropriate_mode(arg_ty.ty).is_by_value() {
- let alloc = alloc_ty(bcx, arg_ty.ty);
- Store(bcx, raw_llarg, alloc);
- llarg = alloc;
- } else {
- llarg = raw_llarg;
- }
+ // only by value if immediate:
+ let llarg = if datum::appropriate_mode(arg_ty.ty).is_by_value() {
+ let alloc = alloc_ty(bcx, arg_ty.ty);
+ Store(bcx, raw_llarg, alloc);
+ alloc
+ } else {
+ raw_llarg
+ };
- add_clean(bcx, llarg, arg_ty.ty);
- }
- }
+ add_clean(bcx, llarg, arg_ty.ty);
bcx = _match::bind_irrefutable_pat(bcx,
args[arg_n].pat,
// Translate variant arguments to function arguments.
let fn_args = do args.map |varg| {
ast::arg {
- mode: ast::expl(ast::by_copy),
is_mutbl: false,
ty: varg.ty,
pat: ast_util::ident_to_pat(
// Translate struct fields to function arguments.
let fn_args = do fields.map |field| {
ast::arg {
- mode: ast::expl(ast::by_copy),
is_mutbl: false,
ty: field.node.ty,
pat: ast_util::ident_to_pat(ccx.tcx.sess.next_node_id(),
} else {
let start_fn_type = csearch::get_type(ccx.tcx,
start_def_id).ty;
- trans_external_path(ccx, start_def_id, start_fn_type)
- };
+ trans_external_path(ccx, start_def_id, start_fn_type);
+ }
let retptr = llvm::LLVMBuildAlloca(bld, T_i8(), noname());
use middle::trans::common::*;
use syntax::codemap::span;
-use core::prelude::*;
-use core::cast;
use core::hashmap::HashMap;
use core::libc::{c_uint, c_ulonglong, c_char};
-use core::libc;
-use core::option::Some;
-use core::ptr;
-use core::str;
-use core::vec;
pub fn terminate(cx: block, _: &str) {
cx.terminated = true;
// This is a really awful way to get a zero-length c-string, but better (and a
// lot more efficient) than doing str::as_c_str("", ...) every time.
-pub fn noname() -> *libc::c_char {
+pub fn noname() -> *c_char {
unsafe {
static cnull: uint = 0u;
- return cast::transmute(ptr::addr_of(&cnull));
+ return cast::transmute(&cnull);
}
}
}
}
-pub fn GlobalString(cx: block, _Str: *libc::c_char) -> ValueRef {
+pub fn GlobalString(cx: block, _Str: *c_char) -> ValueRef {
unsafe {
if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(T_i8())); }
count_insn(cx, "globalstring");
}
}
-pub fn GlobalStringPtr(cx: block, _Str: *libc::c_char) -> ValueRef {
+pub fn GlobalStringPtr(cx: block, _Str: *c_char) -> ValueRef {
unsafe {
if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(T_i8())); }
count_insn(cx, "globalstringptr");
pub fn AddIncomingToPhi(phi: ValueRef, val: ValueRef, bb: BasicBlockRef) {
unsafe {
if llvm::LLVMIsUndef(phi) == lib::llvm::True { return; }
- let valptr = cast::transmute(ptr::addr_of(&val));
- let bbptr = cast::transmute(ptr::addr_of(&bb));
+ let valptr = cast::transmute(&val);
+ let bbptr = cast::transmute(&bb);
llvm::LLVMAddIncoming(phi, valptr, bbptr, 1 as c_uint);
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::{ptr, vec, uint};
-use core::option::*;
use core::libc::c_uint;
use lib::llvm::{llvm, TypeRef, Integer, Pointer, Float, Double};
use lib::llvm::{Struct, Array, Attribute};
// except according to those terms.
use driver::session::{os_win32, os_macos};
-use core::option::*;
use lib::llvm::*;
use lib::llvm::llvm::*;
use super::cabi::*;
// and methods are represented as just a fn ptr and not a full
// closure.
-use core::prelude::*;
-
use back::abi;
use driver::session;
use lib;
llfn: ValueRef,
llself: ValueRef,
self_ty: ty::t,
- self_mode: ast::rmode
+ self_mode: ty::SelfMode,
}
pub enum CalleeData {
csearch::get_type(bcx.ccx().tcx, did).ty
};
let rty = ty::ty_fn_ret(fty);
- return callee::trans_call_inner(
- bcx, None, fty, rty,
- |bcx| trans_fn_ref_with_vtables_to_callee(bcx, did, 0, ~[], None),
- ArgVals(args), dest, DontAutorefArg);
+ callee::trans_call_inner(bcx,
+ None,
+ fty,
+ rty,
+ |bcx| {
+ trans_fn_ref_with_vtables_to_callee(bcx,
+ did,
+ 0,
+ ~[],
+ None)
+ },
+ ArgVals(args),
+ dest,
+ DontAutorefArg)
}
pub fn trans_lang_call_with_type_params(bcx: block,
}
Method(d) => {
// Weird but true: we pass self in the *environment* slot!
- let llself = PointerCast(bcx, d.llself,
+ let llself = PointerCast(bcx,
+ d.llself,
T_opaque_box_ptr(ccx));
(d.llfn, llself)
}
// Now that the arguments have finished evaluating, we need to revoke
// the cleanup for the self argument, if it exists
match callee.data {
- Method(d) if d.self_mode == ast::by_copy => {
+ Method(d) if d.self_mode == ty::ByCopy => {
revoke_clean(bcx, d.llself);
}
_ => {}
let last = arg_exprs.len() - 1u;
for vec::eachi(arg_exprs) |i, arg_expr| {
let arg_val = unpack_result!(bcx, {
- trans_arg_expr(bcx, arg_tys[i], *arg_expr, &mut temp_cleanups,
+ trans_arg_expr(bcx,
+ arg_tys[i],
+ ty::ByCopy,
+ *arg_expr,
+ &mut temp_cleanups,
if i == last { ret_flag } else { None },
autoref_arg)
});
// call takes place:
pub fn trans_arg_expr(bcx: block,
formal_ty: ty::arg,
+ self_mode: ty::SelfMode,
arg_expr: @ast::expr,
temp_cleanups: &mut ~[ValueRef],
ret_flag: Option<ValueRef>,
let _icx = bcx.insn_ctxt("trans_arg_expr");
let ccx = bcx.ccx();
- debug!("trans_arg_expr(formal_ty=(%?,%s), arg_expr=%s, \
+ debug!("trans_arg_expr(formal_ty=(%s), self_mode=%?, arg_expr=%s, \
ret_flag=%?)",
- formal_ty.mode,
formal_ty.ty.repr(bcx.tcx()),
+ self_mode,
arg_expr.repr(bcx.tcx()),
ret_flag.map(|v| bcx.val_str(*v)));
let _indenter = indenter();
blk @ @ast::expr {
node: ast::expr_fn_block(ref decl, ref body),
_
- }) =>
- {
+ }) => {
let scratch_ty = expr_ty(bcx, arg_expr);
let scratch = alloc_ty(bcx, scratch_ty);
let arg_ty = expr_ty(bcx, arg_expr);
debug!(" arg datum: %s", arg_datum.to_str(bcx.ccx()));
- // finally, deal with the various modes
- let arg_mode = ty::resolved_mode(ccx.tcx, formal_ty.mode);
let mut val;
if ty::type_is_bot(arg_datum.ty) {
// For values of type _|_, we generate an
val = arg_datum.to_ref_llval(bcx);
}
DontAutorefArg => {
- match arg_mode {
- ast::by_ref => {
+ match self_mode {
+ ty::ByRef => {
// This assertion should really be valid, but because
// the explicit self code currently passes by-ref, it
// does not hold.
//
//assert !bcx.ccx().maps.moves_map.contains_key(
// &arg_expr.id);
+ debug!("by ref arg with type %s",
+ bcx.ty_to_str(arg_datum.ty));
val = arg_datum.to_ref_llval(bcx);
}
-
- ast::by_copy => {
+ ty::ByCopy => {
debug!("by copy arg with type %s, storing to scratch",
bcx.ty_to_str(arg_datum.ty));
let scratch = scratch_datum(bcx, arg_datum.ty, false);
- arg_datum.store_to_datum(bcx, arg_expr.id,
- INIT, scratch);
+ arg_datum.store_to_datum(bcx,
+ arg_expr.id,
+ INIT,
+ scratch);
// Technically, ownership of val passes to the callee.
// However, we must cleanup should we fail before the
temp_cleanups.push(scratch.val);
match arg_datum.appropriate_mode() {
- ByValue => {
- val = Load(bcx, scratch.val);
- }
- ByRef => {
- val = scratch.val;
- }
+ ByValue => val = Load(bcx, scratch.val),
+ ByRef => val = scratch.val,
}
}
}
if formal_ty.ty != arg_datum.ty {
// this could happen due to e.g. subtyping
let llformal_ty = type_of::type_of_explicit_arg(ccx, &formal_ty);
+ let llformal_ty = match self_mode {
+ ty::ByRef => T_ptr(llformal_ty),
+ ty::ByCopy => llformal_ty,
+ };
debug!("casting actual type (%s) to match formal (%s)",
bcx.val_str(val), bcx.llty_str(llformal_ty));
val = PointerCast(bcx, val, llformal_ty);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use back::abi;
use back::link::{mangle_internal_name_by_path_and_seq};
use lib::llvm::{llvm, ValueRef};
*/
-use core::prelude::*;
-
use back::{abi, upcall};
use driver::session;
use driver::session::Session;
use middle::typeck;
use util::ppaux::{Repr};
-use core::cast;
+use core::cast::transmute;
use core::hash;
use core::hashmap::{HashMap, HashSet};
use core::libc::{c_uint, c_longlong, c_ulonglong};
-use core::ptr;
-use core::str;
use core::to_bytes;
use core::vec::raw::to_ptr;
-use core::vec;
use syntax::ast::ident;
use syntax::ast_map::{path, path_elt};
use syntax::codemap::span;
t.repr(self.tcx())
}
fn to_str(@mut self) -> ~str {
- match self.node_info {
- Some(node_info) => {
- fmt!("[block %d]", node_info.id)
- }
- None => {
- fmt!("[block %x]", ptr::addr_of(&(*self)) as uint)
- }
+ unsafe {
+ match self.node_info {
+ Some(node_info) => fmt!("[block %d]", node_info.id),
+ None => fmt!("[block %x]", transmute(&*self)),
+ }
}
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use back::abi;
use lib::llvm::{llvm, SetLinkage, PrivateLinkage,
ValueRef, TypeRef, Bool, True, False};
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use back::link;
use lib;
use lib::llvm::*;
use util::common::indenter;
use util::ppaux;
-use core::str;
use syntax::ast;
use syntax::ast::ident;
use syntax::ast_map::path_mod;
* methods themselves. Most are only suitable for some types of
* values. */
-use core::prelude::*;
-
use lib;
use lib::llvm::ValueRef;
use middle::borrowck::{RootInfo, root_map_key};
use core::container::Set; // XXX: this should not be necessary
use core::to_bytes;
-use core::uint;
use syntax::ast;
use syntax::parse::token::special_idents;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
use driver::session;
use lib::llvm::ValueRef;
use core::hashmap::HashMap;
use core::libc;
-use core::option;
-use core::sys;
use syntax::codemap::span;
use syntax::parse::token::ident_interner;
use syntax::{ast, codemap, ast_util, ast_map};
*/
-use core::prelude::*;
-
use back::abi;
use lib;
use lib::llvm::{ValueRef, TypeRef, llvm};
}
}
}
- ast::def_arg(nid, _, _) => {
+ ast::def_arg(nid, _) => {
take_local(bcx, bcx.fcx.llargs, nid)
}
ast::def_local(nid, _) | ast::def_binding(nid, _) => {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use back::{link, abi};
use lib::llvm::{SequentiallyConsistent, Acquire, Release, Xchg};
use lib::llvm::{TypeRef, ValueRef};
}
}
~"forget" => {}
- ~"reinterpret_cast" => {
- let tp_ty = substs.tys[0];
- let lltp_ty = type_of::type_of(ccx, tp_ty);
- let llout_ty = type_of::type_of(ccx, substs.tys[1]);
- let tp_sz = machine::llbitsize_of_real(ccx, lltp_ty),
- out_sz = machine::llbitsize_of_real(ccx, llout_ty);
- if tp_sz != out_sz {
- let sp = match *ccx.tcx.items.get(&ref_id.get()) {
- ast_map::node_expr(e) => e.span,
- _ => fail!(~"reinterpret_cast or forget has non-expr arg")
- };
- ccx.sess.span_fatal(
- sp, fmt!("reinterpret_cast called on types \
- with different size: %s (%u bit(s)) to %s \
- (%u bit(s))",
- ty_to_str(ccx.tcx, tp_ty), tp_sz,
- ty_to_str(ccx.tcx, substs.tys[1]), out_sz));
- }
- if !ty::type_is_nil(substs.tys[1]) {
- // NB: Do not use a Load and Store here. This causes
- // massive code bloat when reinterpret_cast is used on
- // large structural types.
- let llretptr = fcx.llretptr.get();
- let llretptr = PointerCast(bcx, llretptr, T_ptr(T_i8()));
- let llcast = get_param(decl, first_real_arg);
- let llcast = PointerCast(bcx, llcast, T_ptr(T_i8()));
- call_memcpy(bcx, llretptr, llcast, llsize_of(ccx, lltp_ty));
- }
- }
- ~"addr_of" => {
- Store(bcx, get_param(decl, first_real_arg), fcx.llretptr.get());
+ ~"transmute" => {
+ let (in_type, out_type) = (substs.tys[0], substs.tys[1]);
+ let llintype = type_of::type_of(ccx, in_type);
+ let llouttype = type_of::type_of(ccx, out_type);
+
+ let in_type_size = machine::llbitsize_of_real(ccx, llintype);
+ let out_type_size = machine::llbitsize_of_real(ccx, llouttype);
+ if in_type_size != out_type_size {
+ let sp = match *ccx.tcx.items.get(&ref_id.get()) {
+ ast_map::node_expr(e) => e.span,
+ _ => fail!(~"transmute has non-expr arg"),
+ };
+ let pluralize = |n| if 1u == n { "" } else { "s" };
+ ccx.sess.span_fatal(sp,
+ fmt!("transmute called on types with \
+ different sizes: %s (%u bit%s) to \
+ %s (%u bit%s)",
+ ty_to_str(ccx.tcx, in_type),
+ in_type_size,
+ pluralize(in_type_size),
+ ty_to_str(ccx.tcx, out_type),
+ out_type_size,
+ pluralize(out_type_size)));
+ }
+
+ if !ty::type_is_nil(out_type) {
+ // NB: Do not use a Load and Store here. This causes massive
+ // code bloat when `transmute` is used on large structural
+ // types.
+ let lldestptr = fcx.llretptr.get();
+ let lldestptr = PointerCast(bcx, lldestptr, T_ptr(T_i8()));
+
+ let llsrcval = get_param(decl, first_real_arg);
+ let llsrcptr = if ty::type_is_immediate(in_type) {
+ let llsrcptr = alloca(bcx, llintype);
+ Store(bcx, llsrcval, llsrcptr);
+ llsrcptr
+ } else {
+ llsrcval
+ };
+ let llsrcptr = PointerCast(bcx, llsrcptr, T_ptr(T_i8()));
+
+ let llsize = llsize_of(ccx, llintype);
+ call_memcpy(bcx, lldestptr, llsrcptr, llsize);
+ }
}
~"needs_drop" => {
let tp_ty = substs.tys[0];
~"visit_tydesc" => {
let td = get_param(decl, first_real_arg);
let visitor = get_param(decl, first_real_arg + 1u);
+ //let llvisitorptr = alloca(bcx, val_ty(visitor));
+ //Store(bcx, visitor, llvisitorptr);
let td = PointerCast(bcx, td, T_ptr(ccx.tydesc_type));
- glue::call_tydesc_glue_full(bcx, visitor, td,
- abi::tydesc_field_visit_glue, None);
+ glue::call_tydesc_glue_full(bcx,
+ visitor,
+ td,
+ abi::tydesc_field_visit_glue,
+ None);
}
~"frame_address" => {
let frameaddress = *ccx.intrinsics.get(&~"llvm.frameaddress");
sigil: ast::BorrowedSigil,
onceness: ast::Many,
region: ty::re_bound(ty::br_anon(0)),
- sig: FnSig {bound_lifetime_names: opt_vec::Empty,
- inputs: ~[arg {mode: ast::expl(ast::by_copy),
- ty: star_u8}],
- output: ty::mk_nil()}
+ sig: FnSig {
+ bound_lifetime_names: opt_vec::Empty,
+ inputs: ~[ arg { ty: star_u8 } ],
+ output: ty::mk_nil()
+ }
});
let datum = Datum {val: get_param(decl, first_real_arg),
mode: ByRef, ty: fty, source: ZeroMem};
//
// Code relating to taking, dropping, etc as well as type descriptors.
-use core::prelude::*;
-
use back::abi;
use back::link::*;
use driver::session;
use util::ppaux;
use util::ppaux::ty_to_short_str;
-use core::io;
use core::libc::c_uint;
-use core::str;
use std::time;
use syntax::ast;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use metadata::csearch;
use middle::astencode;
use middle::trans::base::{get_insn_ctxt};
use middle::ty;
use util::ppaux::ty_to_str;
-use core::vec;
use syntax::ast;
use syntax::ast_map::path_name;
use syntax::ast_util::local_def;
// Information concerning the machine representation of various types.
-use core::prelude::*;
-
use lib::llvm::{ValueRef, TypeRef};
use lib::llvm::False;
use lib::llvm::llvm;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use back::abi;
use lib::llvm::llvm;
use lib::llvm::ValueRef;
let _icx = bcx.insn_ctxt("impl::trans_self_arg");
let mut temp_cleanups = ~[];
- // Compute the mode and type of self.
+ // Compute the type of self.
let self_arg = arg {
- mode: mentry.self_arg.mode,
ty: monomorphize_type(bcx, mentry.self_arg.ty)
};
- let result = trans_arg_expr(bcx, self_arg, base,
- &mut temp_cleanups, None, DontAutorefArg);
+ let result = trans_arg_expr(bcx,
+ self_arg,
+ mentry.self_mode,
+ base,
+ &mut temp_cleanups,
+ None,
+ DontAutorefArg);
// FIXME(#3446)---this is wrong, actually. The temp_cleanups
// should be revoked only after all arguments have been passed.
typeck::method_static(did) => {
let callee_fn = callee::trans_fn_ref(bcx, did, callee_id);
let Result {bcx, val} = trans_self_arg(bcx, self, mentry);
- let tcx = bcx.tcx();
Callee {
bcx: bcx,
data: Method(MethodData {
llfn: callee_fn.llfn,
llself: val,
self_ty: node_id_type(bcx, self.id),
- self_mode: ty::resolved_mode(tcx, mentry.self_arg.mode)
+ self_mode: mentry.self_mode,
})
}
}
trait_id: ast::def_id,
n_method: uint,
vtbl: typeck::vtable_origin)
- -> Callee {
+ -> Callee {
let _icx = bcx.insn_ctxt("impl::trans_monomorphized_callee");
return match vtbl {
typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => {
bcx, mth_id, impl_did, callee_id, rcvr_origins);
// translate the function
- let callee = trans_fn_ref_with_vtables(
- bcx, mth_id, callee_id, callee_substs, Some(callee_origins));
+ let callee = trans_fn_ref_with_vtables(bcx,
+ mth_id,
+ callee_id,
+ callee_substs,
+ Some(callee_origins));
// create a llvalue that represents the fn ptr
let fn_ty = node_id_type(bcx, callee_id);
let llfn_val = PointerCast(bcx, callee.llfn, llfn_ty);
// combine the self environment with the rest
- let tcx = bcx.tcx();
Callee {
bcx: bcx,
data: Method(MethodData {
llfn: llfn_val,
llself: llself_val,
self_ty: node_id_type(bcx, base.id),
- self_mode: ty::resolved_mode(tcx, mentry.self_arg.mode)
+ self_mode: mentry.self_mode,
})
}
}
impl_did: ast::def_id,
callee_id: ast::node_id,
rcvr_substs: &[ty::t])
- -> ~[ty::t] {
+ -> ~[ty::t] {
/*!
*
* Creates a concatenated set of substitutions which includes
Store(bcx, llself, llscratch);
llself = llscratch;
- self_mode = ast::by_ref;
+ self_mode = ty::ByRef;
}
ast::sty_box(_) => {
// Bump the reference count on the box.
Store(bcx, llself, llscratch);
llself = llscratch;
- self_mode = ast::by_ref;
+ self_mode = ty::ByRef;
}
ast::sty_uniq(_) => {
// Pass the unique pointer.
Store(bcx, llself, llscratch);
llself = llscratch;
- self_mode = ast::by_ref;
+ self_mode = ty::ByRef;
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use back::link::mangle_exported_name;
use driver::session;
use lib::llvm::ValueRef;
use middle::typeck;
use util::ppaux::Repr;
-use core::vec;
use syntax::ast;
use syntax::ast_map;
use syntax::ast_map::path_name;
Some(vts) => {
let item_ty = ty::lookup_item_type(ccx.tcx, item);
let mut i = 0;
- vec::map2(*item_ty.generics.type_param_defs, substs, |type_param_def, subst| {
+ vec::map_zip(*item_ty.generics.type_param_defs, substs, |type_param_def, subst| {
let mut v = ~[];
for type_param_def.bounds.each |bound| {
match *bound {
};
let param_ids = match param_uses {
Some(ref uses) => {
- vec::map2(precise_param_ids, **uses, |id, uses| {
+ vec::map_zip(precise_param_ids, **uses, |id, uses| {
if ccx.sess.no_monomorphic_collapse() {
match copy *id {
(a, b) => mono_precise(a, b)
use middle::ty;
use middle::typeck;
-use core::prelude::*;
use core::hashmap::HashSet;
use syntax::ast;
use syntax::ast::*;
let make_get_disr = || {
let sub_path = bcx.fcx.path + ~[path_name(special_idents::anon)];
- let sym = mangle_internal_name_by_path_and_seq(ccx, sub_path, ~"get_disr");
- let args = [ty::arg { mode: ast::expl(ast::by_copy),
- ty: opaqueptrty }];
+ let sym = mangle_internal_name_by_path_and_seq(ccx,
+ sub_path,
+ ~"get_disr");
+ let args = [
+ ty::arg {
+ ty: opaqueptrty
+ }
+ ];
+
let llfty = type_of_fn(ccx, args, ty::mk_int());
let llfdecl = decl_internal_cdecl_fn(ccx.llmod, sym, llfty);
let arg = unsafe {
fn visit_sig(&mut self, retval: uint, sig: &ty::FnSig) {
for sig.inputs.eachi |i, arg| {
- let modeval = match arg.mode {
- ast::infer(_) => 0u,
- ast::expl(e) => match e {
- ast::by_ref => 1u,
- ast::by_copy => 5u
- }
- };
+ let modeval = 5u; // "by copy"
let extra = ~[self.c_uint(i),
self.c_uint(modeval),
self.c_tydesc(arg.ty)];
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use lib::llvm::llvm;
use lib::llvm::{TypeRef};
use middle::trans::adt;
use middle::ty;
use util::ppaux;
-use core::option::None;
use syntax::ast;
-pub fn arg_is_indirect(ccx: @CrateContext, arg: &ty::arg) -> bool {
- match ty::resolved_mode(ccx.tcx, arg.mode) {
- ast::by_copy => !ty::type_is_immediate(arg.ty),
- ast::by_ref => true
- }
+pub fn arg_is_indirect(_: @CrateContext, arg: &ty::arg) -> bool {
+ !ty::type_is_immediate(arg.ty)
}
pub fn type_of_explicit_arg(ccx: @CrateContext, arg: &ty::arg) -> TypeRef {
// much information, but have the disadvantage of being very
// invasive.)
-use core::prelude::*;
-
use middle::freevars;
use middle::trans::common::*;
use middle::trans::inline;
ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, _}) |
ty::ty_closure(ty::ClosureTy {sig: ref sig, _}) => {
for vec::each(sig.inputs) |arg| {
- match ty::resolved_mode(ccx.tcx, arg.mode) {
- by_copy => {
- type_needs(cx, use_repr, arg.ty);
- }
- by_ref => {}
- }
+ type_needs(cx, use_repr, arg.ty);
}
}
_ => ()
_) => {
if abi.is_intrinsic() {
let flags = match *cx.ccx.sess.str_of(i.ident) {
- ~"size_of" | ~"pref_align_of" | ~"min_align_of" |
- ~"init" | ~"reinterpret_cast" |
- ~"move_val" | ~"move_val_init" => use_repr,
+ ~"size_of" | ~"pref_align_of" | ~"min_align_of" |
+ ~"init" | ~"transmute" | ~"move_val" |
+ ~"move_val_init" => use_repr,
~"get_tydesc" | ~"needs_drop" => use_tydesc,
~"atomic_xsub_acq" | ~"atomic_xchg_rel" |
~"atomic_xadd_rel" | ~"atomic_xsub_rel" => 0,
- ~"visit_tydesc" | ~"forget" | ~"addr_of" |
- ~"frame_address" | ~"morestack_addr" => 0,
+ ~"visit_tydesc" | ~"forget" | ~"frame_address" |
+ ~"morestack_addr" => 0,
~"memmove32" | ~"memmove64" => 0,
node_type_needs(cx, use_tydesc, val.id);
}
expr_call(f, _, _) => {
- for vec::each(
- ty::ty_fn_args(ty::node_id_to_type(cx.ccx.tcx, f.id))
- ) |a| {
- match a.mode {
- expl(by_copy) => {
- type_needs(cx, use_repr, a.ty);
- }
- _ => ()
- }
+ for vec::each(ty::ty_fn_args(ty::node_id_to_type(cx.ccx.tcx,
+ f.id))) |a| {
+ type_needs(cx, use_repr, a.ty);
}
}
expr_method_call(rcvr, _, _, _, _) => {
for ty::ty_fn_args(ty::node_id_to_type(cx.ccx.tcx,
e.callee_id)).each |a| {
- match a.mode {
- expl(by_copy) => {
- type_needs(cx, use_repr, a.ty);
- }
- _ => ()
- }
+ type_needs(cx, use_repr, a.ty);
}
mark_for_method_call(cx, e.id, e.callee_id);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
use driver::session;
use metadata::csearch;
use util::common::{indenter};
use core;
-use core::cast;
-use core::cmp;
-use core::ops;
use core::ptr::to_unsafe_ptr;
-use core::result::Result;
-use core::result;
use core::to_bytes;
-use core::uint;
-use core::vec;
use core::hashmap::{HashMap, HashSet};
use std::smallintmap::SmallIntMap;
use syntax::ast::*;
use syntax::attr;
use syntax::codemap::span;
use syntax::codemap;
-use syntax::print::pprust;
use syntax::parse::token::special_idents;
use syntax::{ast, ast_map};
use syntax::opt_vec::OptVec;
// Data types
-// Note: after typeck, you should use resolved_mode() to convert this mode
-// into an rmode, which will take into account the results of mode inference.
-#[deriving(Eq)]
+#[deriving(Eq, IterBytes)]
pub struct arg {
- mode: ast::mode,
ty: t
}
RegionTraitStore(Region), // &Trait
}
+// XXX: This should probably go away at some point. Maybe after destructors
+// do?
+#[auto_encode]
+#[auto_decode]
+#[deriving(Eq)]
+pub enum SelfMode {
+ ByCopy,
+ ByRef,
+}
+
pub struct field_ty {
ident: ident,
id: def_id,
ast_ty_to_ty_cache: @mut HashMap<node_id, ast_ty_to_ty_cache_entry>,
enum_var_cache: @mut HashMap<def_id, @~[VariantInfo]>,
ty_param_defs: @mut HashMap<ast::node_id, TypeParameterDef>,
- inferred_modes: @mut HashMap<ast::node_id, ast::mode>,
adjustments: @mut HashMap<ast::node_id, @AutoAdjustment>,
normalized_cache: @mut HashMap<t, t>,
lang_items: middle::lang_items::LanguageItems,
terr_record_mutability,
terr_record_fields(expected_found<ident>),
terr_arg_count,
- terr_mode_mismatch(expected_found<mode>),
terr_regions_does_not_outlive(Region, Region),
terr_regions_not_same(Region, Region),
terr_regions_no_overlap(Region, Region),
trait_method_def_ids: @mut HashMap::new(),
trait_methods_cache: @mut HashMap::new(),
ty_param_defs: @mut HashMap::new(),
- inferred_modes: @mut HashMap::new(),
adjustments: @mut HashMap::new(),
normalized_cache: new_ty_hash(),
lang_items: lang_items,
}
pub fn mk_ctor_fn(cx: ctxt, input_tys: &[ty::t], output: ty::t) -> t {
- let input_args = input_tys.map(|t| arg {mode: ast::expl(ast::by_copy),
- ty: *t});
+ let input_args = input_tys.map(|t| arg { ty: *t });
mk_bare_fn(cx,
BareFnTy {
purity: ast::pure_fn,
abis: AbiSet::Rust(),
- sig: FnSig {bound_lifetime_names: opt_vec::Empty,
- inputs: input_args,
- output: output}})
+ sig: FnSig {
+ bound_lifetime_names: opt_vec::Empty,
+ inputs: input_args,
+ output: output
+ }
+ })
}
}
}
-pub fn default_arg_mode_for_ty(tcx: ctxt, ty: ty::t) -> ast::rmode {
- // FIXME(#2202) --- We retain by-ref for &fn things to workaround a
- // memory leak that otherwise results when @fn is upcast to &fn.
- match ty::get(ty).sty {
- ty::ty_closure(ClosureTy {sigil: ast::BorrowedSigil, _}) => {
- return ast::by_ref;
- }
- _ => {}
- }
- return if tcx.legacy_modes {
- if type_is_borrowed(ty) {
- // the old mode default was ++ for things like &ptr, but to be
- // forward-compatible with non-legacy, we should use +
- ast::by_copy
- } else if ty::type_is_immediate(ty) {
- ast::by_copy
- } else {
- ast::by_ref
- }
- } else {
- ast::by_copy
- };
-
- fn type_is_borrowed(ty: t) -> bool {
- match ty::get(ty).sty {
- ty::ty_rptr(*) => true,
- ty_evec(_, vstore_slice(_)) => true,
- ty_estr(vstore_slice(_)) => true,
-
- // technically, we prob ought to include
- // &fn(), but that is treated specially due to #2202
- _ => false
- }
- }
-}
-
pub fn walk_ty(ty: t, f: &fn(t)) {
maybe_walk_ty(ty, |t| { f(t); true });
}
pub fn maybe_walk_ty(ty: t, f: &fn(t) -> bool) {
- if !f(ty) { return; }
+ if !f(ty) {
+ return;
+ }
match get(ty).sty {
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
ty_estr(_) | ty_type | ty_opaque_box | ty_self(_) |
pub fn fold_sig(sig: &FnSig, fldop: &fn(t) -> t) -> FnSig {
let args = do sig.inputs.map |arg| {
- arg { mode: arg.mode, ty: fldop(arg.ty) }
+ arg {
+ ty: fldop(arg.ty)
+ }
};
FnSig {
}
}
-impl to_bytes::IterBytes for arg {
- fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
- to_bytes::iter_bytes_2(&self.mode,
- &self.ty, lsb0, f)
- }
-}
-
impl to_bytes::IterBytes for FnSig {
fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
to_bytes::iter_bytes_2(&self.inputs,
}
}
-// Maintains a little union-set tree for inferred modes. `canon()` returns
-// the current head value for `m0`.
-fn canon<T:Copy + cmp::Eq>(tbl: &mut HashMap<ast::node_id, ast::inferable<T>>,
- m0: ast::inferable<T>) -> ast::inferable<T> {
- match m0 {
- ast::infer(id) => {
- let m1 = match tbl.find(&id) {
- None => return m0,
- Some(&m1) => m1
- };
- let cm1 = canon(tbl, m1);
- // path compression:
- if cm1 != m1 { tbl.insert(id, cm1); }
- cm1
- },
- _ => m0
- }
-}
-
-// Maintains a little union-set tree for inferred modes. `resolve_mode()`
-// returns the current head value for `m0`.
-pub fn canon_mode(cx: ctxt, m0: ast::mode) -> ast::mode {
- canon(cx.inferred_modes, m0)
-}
-
-// Returns the head value for mode, failing if `m` was a infer(_) that
-// was never inferred. This should be safe for use after typeck.
-pub fn resolved_mode(cx: ctxt, m: ast::mode) -> ast::rmode {
- match canon_mode(cx, m) {
- ast::infer(_) => {
- cx.sess.bug(fmt!("mode %? was never resolved", m));
- }
- ast::expl(m0) => m0
- }
-}
-
-pub fn arg_mode(cx: ctxt, a: arg) -> ast::rmode { resolved_mode(cx, a.mode) }
-
-// Unifies `m1` and `m2`. Returns unified value or failure code.
-pub fn unify_mode(cx: ctxt, modes: expected_found<ast::mode>)
- -> Result<ast::mode, type_err> {
- let m1 = modes.expected;
- let m2 = modes.found;
- match (canon_mode(cx, m1), canon_mode(cx, m2)) {
- (m1, m2) if (m1 == m2) => {
- result::Ok(m1)
- }
- (ast::infer(_), ast::infer(id2)) => {
- cx.inferred_modes.insert(id2, m1);
- result::Ok(m1)
- }
- (ast::infer(id), m) | (m, ast::infer(id)) => {
- cx.inferred_modes.insert(id, m);
- result::Ok(m1)
- }
- (_, _) => {
- result::Err(terr_mode_mismatch(modes))
- }
- }
-}
-
-// If `m` was never unified, unifies it with `m_def`. Returns the final value
-// for `m`.
-pub fn set_default_mode(cx: ctxt, m: ast::mode, m_def: ast::rmode) {
- match canon_mode(cx, m) {
- ast::infer(id) => {
- cx.inferred_modes.insert(id, ast::expl(m_def));
- }
- ast::expl(_) => ()
- }
-}
-
pub fn ty_sort_str(cx: ctxt, t: t) -> ~str {
match get(t).sty {
ty_nil | ty_bot | ty_bool | ty_int(_) |
*cx.sess.str_of(values.found))
}
terr_arg_count => ~"incorrect number of function parameters",
- terr_mode_mismatch(values) => {
- fmt!("expected argument mode %s, but found %s",
- pprust::mode_to_str(values.expected),
- pprust::mode_to_str(values.found))
- }
terr_regions_does_not_outlive(*) => {
fmt!("lifetime mismatch")
}
* an rptr (`&r.T`) use the region `r` that appears in the rptr.
*/
-use core::prelude::*;
-
use middle::const_eval;
use middle::ty::{arg, substs};
use middle::ty::{ty_param_substs_and_ty};
use middle::typeck::rscope::{region_scope, RegionError};
use middle::typeck::rscope::RegionParamNames;
-use core::result;
-use core::vec;
use syntax::abi::AbiSet;
use syntax::{ast, ast_util};
use syntax::codemap::span;
return typ;
}
-pub fn ty_of_arg<AC:AstConv,RS:region_scope + Copy + Durable>(
- self: &AC,
- rscope: &RS,
- a: ast::arg,
- expected_ty: Option<ty::arg>)
- -> ty::arg {
+pub fn ty_of_arg<AC:AstConv,
+ RS:region_scope + Copy + Durable>(
+ self: &AC,
+ rscope: &RS,
+ a: ast::arg,
+ expected_ty: Option<ty::arg>)
+ -> ty::arg {
let ty = match a.ty.node {
- ast::ty_infer if expected_ty.is_some() => expected_ty.get().ty,
- ast::ty_infer => self.ty_infer(a.ty.span),
- _ => ast_ty_to_ty(self, rscope, a.ty)
+ ast::ty_infer if expected_ty.is_some() => expected_ty.get().ty,
+ ast::ty_infer => self.ty_infer(a.ty.span),
+ _ => ast_ty_to_ty(self, rscope, a.ty),
};
- let mode = {
- match a.mode {
- ast::infer(_) if expected_ty.is_some() => {
- result::get(&ty::unify_mode(
- self.tcx(),
- ty::expected_found {expected: expected_ty.get().mode,
- found: a.mode}))
- }
- ast::infer(_) => {
- match ty::get(ty).sty {
- // If the type is not specified, then this must be a fn expr.
- // Leave the mode as infer(_), it will get inferred based
- // on constraints elsewhere.
- ty::ty_infer(_) => a.mode,
-
- // If the type is known, then use the default for that type.
- // Here we unify m and the default. This should update the
- // tables in tcx but should never fail, because nothing else
- // will have been unified with m yet:
- _ => {
- let m1 = ast::expl(ty::default_arg_mode_for_ty(self.tcx(),
- ty));
- result::get(&ty::unify_mode(
- self.tcx(),
- ty::expected_found {expected: m1,
- found: a.mode}))
- }
- }
- }
- ast::expl(_) => a.mode
- }
- };
-
- arg {mode: mode, ty: ty}
+ arg {
+ ty: ty
+ }
}
pub fn bound_lifetimes<AC:AstConv>(
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use middle::pat_util::{PatIdMap, pat_id_map, pat_is_binding, pat_is_const};
use middle::ty;
use middle::typeck::check::demand;
use middle::typeck::require_same_types;
use core::hashmap::{HashMap, HashSet};
-use core::vec;
use syntax::ast;
use syntax::ast_util;
use syntax::codemap::span;
*/
-use core::prelude::*;
-
use middle::resolve;
use middle::ty::*;
use middle::ty;
use util::common::indenter;
use core::hashmap::HashSet;
-use core::result;
-use core::uint;
-use core::vec;
use std::list::Nil;
use syntax::ast::{def_id, sty_value, sty_region, sty_box};
-use syntax::ast::{sty_uniq, sty_static, node_id, by_copy, by_ref};
+use syntax::ast::{sty_uniq, sty_static, node_id};
use syntax::ast::{m_const, m_mutbl, m_imm};
use syntax::ast;
use syntax::ast_map;
self.fcx.write_substs(self.callee_id, all_substs);
method_map_entry {
self_arg: arg {
- mode: ast::expl(self_mode),
ty: candidate.rcvr_ty,
},
+ self_mode: self_mode,
explicit_self: candidate.method_ty.self_ty,
origin: candidate.origin,
}
}
}
-pub fn get_mode_from_self_type(self_type: ast::self_ty_) -> ast::rmode {
- match self_type { sty_value => by_copy, _ => by_ref }
+pub fn get_mode_from_self_type(self_type: ast::self_ty_) -> SelfMode {
+ match self_type {
+ sty_value => ty::ByCopy,
+ _ => ty::ByRef,
+ }
}
*/
-use core::prelude::*;
-
use middle::const_eval;
use middle::pat_util::pat_id_map;
use middle::pat_util;
use util::ppaux::{bound_region_to_str};
use util::ppaux;
+use core::cast::transmute;
use core::hashmap::HashMap;
-use core::ptr;
-use core::result::{Result, Ok, Err};
-use core::result;
-use core::str;
-use core::vec;
use core::util::replace;
use std::list::Nil;
use syntax::abi::AbiSet;
}
pub impl FnCtxt {
- fn tag(&self) -> ~str { fmt!("%x", ptr::addr_of(&(*self)) as uint) }
+ fn tag(&self) -> ~str {
+ unsafe {
+ fmt!("%x", transmute(self))
+ }
+ }
fn local_ty(&self, span: span, nid: ast::node_id) -> ty::t {
match self.inh.locals.find(&nid) {
}
fn err_args(len: uint) -> ~[ty::arg] {
- vec::from_fn(len, |_| ty::arg {mode: ast::expl(ast::by_copy),
- ty: ty::mk_err()})
+ vec::from_fn(len, |_| ty::arg { ty: ty::mk_err() })
}
// A generic function for checking assignment expressions
let fty = if error_happened {
fty_sig = FnSig {
bound_lifetime_names: opt_vec::Empty,
- inputs: fn_ty.sig.inputs.map(|an_arg| {
- arg { mode: an_arg.mode,
- ty: ty::mk_err()
- }}),
+ inputs: fn_ty.sig.inputs.map(|_| {
+ arg {
+ ty: ty::mk_err()
+ }
+ }),
output: ty::mk_err()
};
ty::mk_err()
};
if bot_field {
fcx.write_bot(id);
- }
- else if err_field {
+ } else if err_field {
fcx.write_error(id);
- }
- else {
+ } else {
let typ = ty::mk_tup(tcx, elt_ts);
fcx.write_ty(id, typ);
}
check_expr(fcx, idx);
let raw_base_t = fcx.expr_ty(base);
let idx_t = fcx.expr_ty(idx);
- if ty::type_is_error(raw_base_t)
- || ty::type_is_bot(raw_base_t) {
+ if ty::type_is_error(raw_base_t) || ty::type_is_bot(raw_base_t) {
fcx.write_ty(id, raw_base_t);
- }
- else if ty::type_is_error(idx_t)
- || ty::type_is_bot(idx_t) {
+ } else if ty::type_is_error(idx_t) || ty::type_is_bot(idx_t) {
fcx.write_ty(id, idx_t);
- }
- else {
+ } else {
let (base_t, derefs) = do_autoderef(fcx, expr.span, raw_base_t);
let base_sty = structure_of(fcx, expr.span, base_t);
match ty::index_sty(&base_sty) {
}
None => {
let resolved = structurally_resolved_type(fcx,
- expr.span, raw_base_t);
- let ret_ty = lookup_op_method(fcx, expr, base, resolved,
- tcx.sess.ident_of(~"index"),
- ~[idx], DoDerefArgs, AutoderefReceiver,
- || {
- fcx.type_error_message(expr.span, |actual|
- fmt!("cannot index a value \
- of type `%s`", actual), base_t, None);
- }, expected);
+ expr.span,
+ raw_base_t);
+ let index_ident = tcx.sess.ident_of(~"index");
+ let error_message = || {
+ fcx.type_error_message(expr.span,
+ |actual| {
+ fmt!("cannot index a value \
+ of type `%s`",
+ actual)
+ },
+ base_t,
+ None);
+ };
+ let ret_ty = lookup_op_method(fcx,
+ expr,
+ base,
+ resolved,
+ index_ident,
+ ~[idx],
+ DoDerefArgs,
+ AutoderefReceiver,
+ error_message,
+ expected);
fcx.write_ty(id, ret_ty);
}
}
-> ty_param_bounds_and_ty {
match defn {
- ast::def_arg(nid, _, _) | ast::def_local(nid, _) |
- ast::def_self(nid, _) | ast::def_binding(nid, _) => {
+ ast::def_arg(nid, _) | ast::def_local(nid, _) | ast::def_self(nid, _) |
+ ast::def_binding(nid, _) => {
let typ = fcx.local_ty(sp, nid);
return no_params(typ);
}
fn param(ccx: @mut CrateCtxt, n: uint) -> ty::t {
ty::mk_param(ccx.tcx, n, local_def(0))
}
- fn arg(m: ast::rmode, ty: ty::t) -> ty::arg {
- arg {mode: ast::expl(m), ty: ty}
+ fn arg(ty: ty::t) -> ty::arg {
+ arg {
+ ty: ty
+ }
}
+
let tcx = ccx.tcx;
let (n_tps, inputs, output) = match *ccx.tcx.sess.str_of(it.ident) {
~"size_of" |
~"pref_align_of" | ~"min_align_of" => (1u, ~[], ty::mk_uint()),
~"init" => (1u, ~[], param(ccx, 0u)),
- ~"forget" => (1u, ~[arg(ast::by_copy, param(ccx, 0u))],
- ty::mk_nil()),
- ~"reinterpret_cast" => (2u, ~[arg(ast::by_ref, param(ccx, 0u))],
- param(ccx, 1u)),
- ~"addr_of" => (1u, ~[arg(ast::by_ref, param(ccx, 0u))],
- ty::mk_imm_ptr(tcx, param(ccx, 0u))),
+ ~"forget" => (1u, ~[arg(param(ccx, 0u))], ty::mk_nil()),
+ ~"transmute" => (2, ~[ arg(param(ccx, 0)) ], param(ccx, 1)),
~"move_val" | ~"move_val_init" => {
- (1u, ~[arg(ast::by_copy,
- ty::mk_mut_rptr(tcx, ty::re_bound(ty::br_anon(0)),
- param(ccx, 0u))),
- arg(ast::by_copy, param(ccx, 0u))],
+ (1u,
+ ~[
+ arg(ty::mk_mut_rptr(tcx,
+ ty::re_bound(ty::br_anon(0)),
+ param(ccx, 0))),
+ arg(param(ccx, 0u))
+ ],
ty::mk_nil())
}
~"needs_drop" => (1u, ~[], ty::mk_bool()),
~"atomic_cxchg" | ~"atomic_cxchg_acq"| ~"atomic_cxchg_rel" => {
- (0u, ~[arg(ast::by_copy,
- ty::mk_mut_rptr(tcx, ty::re_bound(ty::br_anon(0)),
- ty::mk_int())),
- arg(ast::by_copy, ty::mk_int()),
- arg(ast::by_copy, ty::mk_int())],
+ (0,
+ ~[
+ arg(ty::mk_mut_rptr(tcx,
+ ty::re_bound(ty::br_anon(0)),
+ ty::mk_int())),
+ arg(ty::mk_int()),
+ arg(ty::mk_int())
+ ],
ty::mk_int())
}
~"atomic_xchg" | ~"atomic_xadd" | ~"atomic_xsub" |
~"atomic_xchg_acq" | ~"atomic_xadd_acq" | ~"atomic_xsub_acq" |
~"atomic_xchg_rel" | ~"atomic_xadd_rel" | ~"atomic_xsub_rel" => {
- (0u, ~[arg(ast::by_copy,
- ty::mk_mut_rptr(tcx, ty::re_bound(ty::br_anon(0)),
- ty::mk_int())),
- arg(ast::by_copy, ty::mk_int())],
+ (0,
+ ~[
+ arg(ty::mk_mut_rptr(tcx,
+ ty::re_bound(ty::br_anon(0)),
+ ty::mk_int())),
+ arg(ty::mk_int())
+ ],
ty::mk_int())
}
(1u, ~[], ty::mk_nil_ptr(ccx.tcx))
}
~"visit_tydesc" => {
- let tydesc_name = special_idents::tydesc;
- assert!(tcx.intrinsic_defs.contains_key(&tydesc_name));
- let (_, tydesc_ty) = *tcx.intrinsic_defs.get(&tydesc_name);
- let (_, visitor_object_ty) = ty::visitor_object_ty(ccx.tcx);
- let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {ty: tydesc_ty,
- mutbl: ast::m_imm});
- (0u, ~[arg(ast::by_copy, td_ptr),
- arg(ast::by_ref, visitor_object_ty)], ty::mk_nil())
+ let tydesc_name = special_idents::tydesc;
+ assert!(tcx.intrinsic_defs.contains_key(&tydesc_name));
+ let (_, tydesc_ty) = *tcx.intrinsic_defs.get(&tydesc_name);
+ let (_, visitor_object_ty) = ty::visitor_object_ty(tcx);
+ let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
+ ty: tydesc_ty,
+ mutbl: ast::m_imm
+ });
+ (0, ~[ arg(td_ptr), arg(visitor_object_ty) ], ty::mk_nil())
}
~"frame_address" => {
let fty = ty::mk_closure(ccx.tcx, ty::ClosureTy {
region: ty::re_bound(ty::br_anon(0)),
sig: ty::FnSig {
bound_lifetime_names: opt_vec::Empty,
- inputs: ~[arg {mode: ast::expl(ast::by_copy),
- ty: ty::mk_imm_ptr(
- ccx.tcx,
- ty::mk_mach_uint(ast::ty_u8))}],
+ inputs: ~[
+ arg {
+ ty: ty::mk_imm_ptr(ccx.tcx,
+ ty::mk_mach_uint(ast::ty_u8))
+ }
+ ],
output: ty::mk_nil()
}
});
- (0u, ~[arg(ast::by_ref, fty)], ty::mk_nil())
+ (0u, ~[ arg(fty) ], ty::mk_nil())
}
~"morestack_addr" => {
(0u, ~[], ty::mk_nil_ptr(ccx.tcx))
}
~"memmove32" => {
- (0, ~[arg(ast::by_copy,
- ty::mk_ptr(tcx,
- ty::mt { ty: ty::mk_u8(), mutbl: ast::m_mutbl })),
- arg(ast::by_copy,
- ty::mk_ptr(tcx,
- ty::mt { ty: ty::mk_u8(), mutbl: ast::m_imm })),
- arg(ast::by_copy,
- ty::mk_u32())],
+ (0,
+ ~[
+ arg(ty::mk_ptr(tcx, ty::mt {
+ ty: ty::mk_u8(),
+ mutbl: ast::m_mutbl
+ })),
+ arg(ty::mk_ptr(tcx, ty::mt {
+ ty: ty::mk_u8(),
+ mutbl: ast::m_imm
+ })),
+ arg(ty::mk_u32())
+ ],
ty::mk_nil())
}
~"memmove64" => {
- (0, ~[arg(ast::by_copy,
- ty::mk_ptr(tcx,
- ty::mt { ty: ty::mk_u8(), mutbl: ast::m_mutbl })),
- arg(ast::by_copy,
- ty::mk_ptr(tcx,
- ty::mt { ty: ty::mk_u8(), mutbl: ast::m_imm })),
- arg(ast::by_copy,
- ty::mk_u64())],
+ (0,
+ ~[arg(ty::mk_ptr(tcx, ty::mt {
+ ty: ty::mk_u8(),
+ mutbl: ast::m_mutbl
+ })),
+ arg(ty::mk_ptr(tcx, ty::mt {
+ ty: ty::mk_u8(),
+ mutbl: ast::m_imm
+ })),
+ arg(ty::mk_u64())
+ ],
ty::mk_nil())
}
- ~"sqrtf32" => {
- (0u, ~[arg(ast::by_copy, ty::mk_f32())],
- ty::mk_f32())
- }
- ~"sqrtf64" => {
- (0u, ~[arg(ast::by_copy, ty::mk_f64())],
- ty::mk_f64())
- }
- ~"powif32" => {
- (0u, ~[arg(ast::by_copy, ty::mk_f32()),
- arg(ast::by_copy, ty::mk_i32())],
- ty::mk_f32())
- }
- ~"powif64" => {
- (0u, ~[arg(ast::by_copy, ty::mk_f64()),
- arg(ast::by_copy, ty::mk_i32())],
- ty::mk_f64())
- }
- ~"sinf32" => {
- (0u, ~[arg(ast::by_copy, ty::mk_f32())],
- ty::mk_f32())
- }
- ~"sinf64" => {
- (0u, ~[arg(ast::by_copy, ty::mk_f64())],
- ty::mk_f64())
- }
- ~"cosf32" => {
- (0u, ~[arg(ast::by_copy, ty::mk_f32())],
- ty::mk_f32())
- }
- ~"cosf64" => {
- (0u, ~[arg(ast::by_copy, ty::mk_f64())],
- ty::mk_f64())
- }
- ~"powf32" => {
- (0u, ~[arg(ast::by_copy, ty::mk_f32()),
- arg(ast::by_copy, ty::mk_f32())],
- ty::mk_f32())
- }
- ~"powf64" => {
- (0u, ~[arg(ast::by_copy, ty::mk_f64()),
- arg(ast::by_copy, ty::mk_f64())],
- ty::mk_f64())
- }
- ~"expf32" => {
- (0u, ~[arg(ast::by_copy, ty::mk_f32())],
- ty::mk_f32())
- }
- ~"expf64" => {
- (0u, ~[arg(ast::by_copy, ty::mk_f64())],
- ty::mk_f64())
- }
- ~"exp2f32" => {
- (0u, ~[arg(ast::by_copy, ty::mk_f32())],
- ty::mk_f32())
- }
- ~"exp2f64" => {
- (0u, ~[arg(ast::by_copy, ty::mk_f64())],
- ty::mk_f64())
- }
- ~"logf32" => {
- (0u, ~[arg(ast::by_copy, ty::mk_f32())],
- ty::mk_f32())
- }
- ~"logf64" => {
- (0u, ~[arg(ast::by_copy, ty::mk_f64())],
- ty::mk_f64())
- }
- ~"log10f32" => {
- (0u, ~[arg(ast::by_copy, ty::mk_f32())],
- ty::mk_f32())
- }
- ~"log10f64" => {
- (0u, ~[arg(ast::by_copy, ty::mk_f64())],
- ty::mk_f64())
- }
- ~"log2f32" => {
- (0u, ~[arg(ast::by_copy, ty::mk_f32())],
- ty::mk_f32())
- }
- ~"log2f64" => {
- (0u, ~[arg(ast::by_copy, ty::mk_f64())],
- ty::mk_f64())
- }
- ~"fmaf32" => {
- (0u, ~[arg(ast::by_copy, ty::mk_f32()),
- arg(ast::by_copy, ty::mk_f32()),
- arg(ast::by_copy, ty::mk_f32())],
- ty::mk_f32())
- }
- ~"fmaf64" => {
- (0u, ~[arg(ast::by_copy, ty::mk_f64()),
- arg(ast::by_copy, ty::mk_f64()),
- arg(ast::by_copy, ty::mk_f64())],
- ty::mk_f64())
- }
- ~"fabsf32" => {
- (0u, ~[arg(ast::by_copy, ty::mk_f32())],
- ty::mk_f32())
- }
- ~"fabsf64" => {
- (0u, ~[arg(ast::by_copy, ty::mk_f64())],
- ty::mk_f64())
- }
- ~"floorf32" => {
- (0u, ~[arg(ast::by_copy, ty::mk_f32())],
- ty::mk_f32())
- }
- ~"floorf64" => {
- (0u, ~[arg(ast::by_copy, ty::mk_f64())],
- ty::mk_f64())
- }
- ~"ceilf32" => {
- (0u, ~[arg(ast::by_copy, ty::mk_f32())],
- ty::mk_f32())
- }
- ~"ceilf64" => {
- (0u, ~[arg(ast::by_copy, ty::mk_f64())],
- ty::mk_f64())
- }
- ~"truncf32" => {
- (0u, ~[arg(ast::by_copy, ty::mk_f32())],
- ty::mk_f32())
- }
- ~"truncf64" => {
- (0u, ~[arg(ast::by_copy, ty::mk_f64())],
- ty::mk_f64())
- }
- ~"ctpop8" => {
- (0u, ~[arg(ast::by_copy, ty::mk_i8())],
- ty::mk_i8())
- }
- ~"ctpop16" => {
- (0u, ~[arg(ast::by_copy, ty::mk_i16())],
- ty::mk_i16())
- }
- ~"ctpop32" => {
- (0u, ~[arg(ast::by_copy, ty::mk_i32())],
- ty::mk_i32())
- }
- ~"ctpop64" => {
- (0u, ~[arg(ast::by_copy, ty::mk_i64())],
- ty::mk_i64())
- }
- ~"ctlz8" => {
- (0u, ~[arg(ast::by_copy, ty::mk_i8())],
- ty::mk_i8())
- }
- ~"ctlz16" => {
- (0u, ~[arg(ast::by_copy, ty::mk_i16())],
- ty::mk_i16())
- }
- ~"ctlz32" => {
- (0u, ~[arg(ast::by_copy, ty::mk_i32())],
- ty::mk_i32())
- }
- ~"ctlz64" => {
- (0u, ~[arg(ast::by_copy, ty::mk_i64())],
- ty::mk_i64())
- }
- ~"cttz8" => {
- (0u, ~[arg(ast::by_copy, ty::mk_i8())],
- ty::mk_i8())
- }
- ~"cttz16" => {
- (0u, ~[arg(ast::by_copy, ty::mk_i16())],
- ty::mk_i16())
- }
- ~"cttz32" => {
- (0u, ~[arg(ast::by_copy, ty::mk_i32())],
- ty::mk_i32())
- }
- ~"cttz64" => {
- (0u, ~[arg(ast::by_copy, ty::mk_i64())],
- ty::mk_i64())
- }
- ~"bswap16" => {
- (0u, ~[arg(ast::by_copy, ty::mk_i16())],
- ty::mk_i16())
- }
- ~"bswap32" => {
- (0u, ~[arg(ast::by_copy, ty::mk_i32())],
- ty::mk_i32())
- }
- ~"bswap64" => {
- (0u, ~[arg(ast::by_copy, ty::mk_i64())],
- ty::mk_i64())
- }
- ref other => {
- tcx.sess.span_err(it.span, ~"unrecognized intrinsic function: `" +
- (*other) + ~"`");
- return;
- }
+ ~"sqrtf32" => (0, ~[ arg(ty::mk_f32()) ], ty::mk_f32()),
+ ~"sqrtf64" => (0, ~[ arg(ty::mk_f64()) ], ty::mk_f64()),
+ ~"powif32" => {
+ (0,
+ ~[ arg(ty::mk_f32()), arg(ty::mk_i32()) ],
+ ty::mk_f32())
+ }
+ ~"powif64" => {
+ (0,
+ ~[ arg(ty::mk_f64()), arg(ty::mk_i32()) ],
+ ty::mk_f64())
+ }
+ ~"sinf32" => (0, ~[ arg(ty::mk_f32()) ], ty::mk_f32()),
+ ~"sinf64" => (0, ~[ arg(ty::mk_f64()) ], ty::mk_f64()),
+ ~"cosf32" => (0, ~[ arg(ty::mk_f32()) ], ty::mk_f32()),
+ ~"cosf64" => (0, ~[ arg(ty::mk_f64()) ], ty::mk_f64()),
+ ~"powf32" => {
+ (0,
+ ~[ arg(ty::mk_f32()), arg(ty::mk_f32()) ],
+ ty::mk_f32())
+ }
+ ~"powf64" => {
+ (0,
+ ~[ arg(ty::mk_f64()), arg(ty::mk_f64()) ],
+ ty::mk_f64())
+ }
+ ~"expf32" => (0, ~[ arg(ty::mk_f32()) ], ty::mk_f32()),
+ ~"expf64" => (0, ~[ arg(ty::mk_f64()) ], ty::mk_f64()),
+ ~"exp2f32" => (0, ~[ arg(ty::mk_f32()) ], ty::mk_f32()),
+ ~"exp2f64" => (0, ~[ arg(ty::mk_f64()) ], ty::mk_f64()),
+ ~"logf32" => (0, ~[ arg(ty::mk_f32()) ], ty::mk_f32()),
+ ~"logf64" => (0, ~[ arg(ty::mk_f64()) ], ty::mk_f64()),
+ ~"log10f32" => (0, ~[ arg(ty::mk_f32()) ], ty::mk_f32()),
+ ~"log10f64" => (0, ~[ arg(ty::mk_f64()) ], ty::mk_f64()),
+ ~"log2f32" => (0, ~[ arg(ty::mk_f32()) ], ty::mk_f32()),
+ ~"log2f64" => (0, ~[ arg(ty::mk_f64()) ], ty::mk_f64()),
+ ~"fmaf32" => {
+ (0,
+ ~[ arg(ty::mk_f32()), arg(ty::mk_f32()), arg(ty::mk_f32()) ],
+ ty::mk_f32())
+ }
+ ~"fmaf64" => {
+ (0,
+ ~[ arg(ty::mk_f64()), arg(ty::mk_f64()), arg(ty::mk_f64()) ],
+ ty::mk_f64())
+ }
+ ~"fabsf32" => (0, ~[ arg(ty::mk_f32()) ], ty::mk_f32()),
+ ~"fabsf64" => (0, ~[ arg(ty::mk_f64()) ], ty::mk_f64()),
+ ~"floorf32" => (0, ~[ arg(ty::mk_f32()) ], ty::mk_f32()),
+ ~"floorf64" => (0, ~[ arg(ty::mk_f64()) ], ty::mk_f64()),
+ ~"ceilf32" => (0, ~[ arg(ty::mk_f32()) ], ty::mk_f32()),
+ ~"ceilf64" => (0, ~[ arg(ty::mk_f64()) ], ty::mk_f64()),
+ ~"truncf32" => (0, ~[ arg(ty::mk_f32()) ], ty::mk_f32()),
+ ~"truncf64" => (0, ~[ arg(ty::mk_f64()) ], ty::mk_f64()),
+ ~"ctpop8" => (0, ~[ arg(ty::mk_i8()) ], ty::mk_i8()),
+ ~"ctpop16" => (0, ~[ arg(ty::mk_i16()) ], ty::mk_i16()),
+ ~"ctpop32" => (0, ~[ arg(ty::mk_i32()) ], ty::mk_i32()),
+ ~"ctpop64" => (0, ~[ arg(ty::mk_i64()) ], ty::mk_i64()),
+ ~"ctlz8" => (0, ~[ arg(ty::mk_i8()) ], ty::mk_i8()),
+ ~"ctlz16" => (0, ~[ arg(ty::mk_i16()) ], ty::mk_i16()),
+ ~"ctlz32" => (0, ~[ arg(ty::mk_i32()) ], ty::mk_i32()),
+ ~"ctlz64" => (0, ~[ arg(ty::mk_i64()) ], ty::mk_i64()),
+ ~"cttz8" => (0, ~[ arg(ty::mk_i8()) ], ty::mk_i8()),
+ ~"cttz16" => (0, ~[ arg(ty::mk_i16()) ], ty::mk_i16()),
+ ~"cttz32" => (0, ~[ arg(ty::mk_i32()) ], ty::mk_i32()),
+ ~"cttz64" => (0, ~[ arg(ty::mk_i64()) ], ty::mk_i64()),
+ ~"bswap16" => (0, ~[ arg(ty::mk_i16()) ], ty::mk_i16()),
+ ~"bswap32" => (0, ~[ arg(ty::mk_i32()) ], ty::mk_i32()),
+ ~"bswap64" => (0, ~[ arg(ty::mk_i64()) ], ty::mk_i64()),
+ ref other => {
+ tcx.sess.span_err(it.span,
+ ~"unrecognized intrinsic function: `" +
+ (*other) + ~"`");
+ return;
+ }
};
let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
purity: ast::unsafe_fn,
*/
-use core::prelude::*;
-
use middle::freevars::get_freevars;
use middle::pat_util::pat_bindings;
use middle::ty::{re_scope};
use util::ppaux::{note_and_explain_region, ty_to_str,
region_to_str};
-use core::result;
use syntax::ast::{ManagedSigil, OwnedSigil, BorrowedSigil};
use syntax::ast::{def_arg, def_binding, def_local, def_self, def_upvar};
use syntax::ast;
fn encl_region_of_def(fcx: @mut FnCtxt, def: ast::def) -> ty::Region {
let tcx = fcx.tcx();
match def {
- def_local(node_id, _) | def_arg(node_id, _, _) |
+ def_local(node_id, _) | def_arg(node_id, _) |
def_self(node_id, _) | def_binding(node_id, _) => {
tcx.region_maps.encl_region(node_id)
}
* but more special purpose.
*/
- use core::prelude::*;
use middle::typeck::check::regionck::{Rcx, infallibly_mk_subr};
use middle::ty;
use syntax::ast;
// #[warn(deprecated_mode)];
-use core::prelude::*;
-
use middle::ty;
use middle::typeck::isr_alist;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use middle::resolve::Impl;
use middle::ty::param_ty;
use middle::ty;
use util::ppaux::tys_to_str;
use util::ppaux;
-use core::result::{Ok, Err};
-use core::result;
-use core::uint;
use core::hashmap::HashSet;
use syntax::ast;
use syntax::ast_util;
// unresolved type variables and replaces "ty_var" types with their
// substitutions.
-use core::prelude::*;
-
use middle::pat_util;
use middle::ty::arg;
use middle::ty;
use middle::typeck::write_ty_to_tcx;
use util::ppaux;
-use core::result::{Ok, Err};
-use core::vec;
use syntax::ast;
use syntax::codemap::span;
use syntax::print::pprust::pat_to_str;
for resolve_type_vars_in_type(fcx, sp, mme.self_arg.ty).each |t| {
let method_map = fcx.ccx.method_map;
let new_entry = method_map_entry {
- self_arg: arg {mode: mme.self_arg.mode, ty: *t },
+ self_arg: arg {
+ ty: *t
+ },
..*mme
};
debug!("writeback::resolve_method_map_entry(id=%?, \
resolve_type_vars_for_node(wbcx, s.span, ty::stmt_node_id(s));
visit::visit_stmt(s, wbcx, v);
}
+
fn visit_expr(e: @ast::expr, wbcx: @mut WbCtxt, v: wb_vt) {
- if !wbcx.success { return; }
+ if !wbcx.success {
+ return;
+ }
+
resolve_type_vars_for_node(wbcx, e.span, e.id);
resolve_method_map_entry(wbcx.fcx, e.span, e.id);
resolve_method_map_entry(wbcx.fcx, e.span, e.callee_id);
resolve_vtable_map_entry(wbcx.fcx, e.span, e.id);
resolve_vtable_map_entry(wbcx.fcx, e.span, e.callee_id);
+
match e.node {
- ast::expr_fn_block(ref decl, _) => {
- for vec::each(decl.inputs) |input| {
- let r_ty = resolve_type_vars_for_node(wbcx, e.span, input.id);
-
- // Just in case we never constrained the mode to anything,
- // constrain it to the default for the type in question.
- match (r_ty, input.mode) {
- (Some(t), ast::infer(_)) => {
- let tcx = wbcx.fcx.ccx.tcx;
- let m_def = ty::default_arg_mode_for_ty(tcx, t);
- ty::set_default_mode(tcx, input.mode, m_def);
- }
- _ => ()
- }
- }
- }
+ ast::expr_fn_block(ref decl, _) => {
+ for vec::each(decl.inputs) |input| {
+ let _ = resolve_type_vars_for_node(wbcx, e.span, input.id);
+ }
+ }
- ast::expr_binary(*) | ast::expr_unary(*) | ast::expr_assign_op(*)
- | ast::expr_index(*) => {
- maybe_resolve_type_vars_for_node(wbcx, e.span, e.callee_id);
- }
+ ast::expr_binary(*) | ast::expr_unary(*) | ast::expr_assign_op(*) |
+ ast::expr_index(*) => {
+ maybe_resolve_type_vars_for_node(wbcx, e.span, e.callee_id);
+ }
- ast::expr_method_call(*) => {
- // We must always have written in a callee ID type for these.
- resolve_type_vars_for_node(wbcx, e.span, e.callee_id);
- }
+ ast::expr_method_call(*) => {
+ // We must always have written in a callee ID type for these.
+ resolve_type_vars_for_node(wbcx, e.span, e.callee_id);
+ }
- _ => ()
+ _ => ()
}
+
visit::visit_expr(e, wbcx, v);
}
+
fn visit_block(b: &ast::blk, wbcx: @mut WbCtxt, v: wb_vt) {
- if !wbcx.success { return; }
+ if !wbcx.success {
+ return;
+ }
+
resolve_type_vars_for_node(wbcx, b.span, b.node.id);
visit::visit_block(b, wbcx, v);
}
+
fn visit_pat(p: @ast::pat, wbcx: @mut WbCtxt, v: wb_vt) {
- if !wbcx.success { return; }
+ if !wbcx.success {
+ return;
+ }
+
resolve_type_vars_for_node(wbcx, p.span, p.id);
debug!("Type for pattern binding %s (id %d) resolved to %s",
pat_to_str(p, wbcx.fcx.ccx.tcx.sess.intr()), p.id,
p.id)));
visit::visit_pat(p, wbcx, v);
}
+
fn visit_local(l: @ast::local, wbcx: @mut WbCtxt, v: wb_vt) {
if !wbcx.success { return; }
let var_ty = wbcx.fcx.local_ty(l.span, l.node.id);
// has at most one implementation for each type. Then we build a mapping from
// each trait in the system to its implementations.
-use core::prelude::*;
use driver;
use metadata::csearch::{each_path, get_impl_traits};
use middle::typeck::infer::InferCtxt;
use middle::typeck::infer::{new_infer_ctxt, resolve_ivar};
use middle::typeck::infer::{resolve_nested_tvar, resolve_type};
-use syntax::ast::{crate, def_id, def_mod, def_trait};
-use syntax::ast::{item, item_impl, item_mod, local_crate, method, trait_ref};
+use syntax::ast::{crate, def_id, def_mod, def_struct, def_trait, def_ty};
+use syntax::ast::{item, item_enum, item_impl, item_mod, item_struct};
+use syntax::ast::{local_crate, method, trait_ref, ty_path};
use syntax::ast;
use syntax::ast_map::node_item;
use syntax::ast_map;
match item.node {
item_impl(_, opt_trait, _, _) => {
self.check_implementation(item,
- iter::to_vec(&opt_trait));
+ old_iter::to_vec(&opt_trait));
}
_ => {
// Nothing to do.
// Then visit the module items.
visit_mod(module_, item.span, item.id, (), visitor);
}
- item_impl(_, opt_trait, _, _) => {
+ item_impl(_, None, ast_ty, _) => {
+ if !self.ast_type_is_defined_in_local_crate(ast_ty) {
+ // This is an error.
+ let session = self.crate_context.tcx.sess;
+ session.span_err(item.span,
+ ~"cannot associate methods with \
+ a type outside the crate the \
+ type is defined in; define \
+ and implement a trait or new \
+ type instead");
+ }
+ }
+ item_impl(_, Some(trait_ref), _, _) => {
// `for_ty` is `Type` in `impl Trait for Type`
let for_ty =
ty::node_id_to_type(self.crate_context.tcx,
// type. This still might be OK if the trait is
// defined in the same crate.
- match opt_trait {
- None => {
- // There is no trait to implement, so
- // this is an error.
-
- let session = self.crate_context.tcx.sess;
- session.span_err(item.span,
- ~"cannot implement \
- inherent methods for a \
- type outside the crate \
- the type was defined \
- in; define and \
- implement a trait or \
- new type instead");
- }
+ let trait_def_id =
+ self.trait_ref_to_trait_def_id(trait_ref);
- Some(trait_ref) => {
- // This is OK if and only if the trait was
- // defined in this crate.
-
- let trait_def_id =
- self.trait_ref_to_trait_def_id(
- trait_ref);
-
- if trait_def_id.crate != local_crate {
- let session = self.crate_context.tcx.sess;
- session.span_err(item.span,
- ~"cannot provide an \
- extension \
- implementation for a \
- trait not defined in \
- this crate");
- }
- }
+ if trait_def_id.crate != local_crate {
+ let session = self.crate_context.tcx.sess;
+ session.span_err(item.span,
+ ~"cannot provide an \
+ extension implementation \
+ for a trait not defined \
+ in this crate");
}
}
}
}
+ /// For coherence, when we have `impl Type`, we need to guarantee that
+ /// `Type` is "local" to the crate. For our purposes, this means that it
+ /// must precisely name some nominal type defined in this crate.
+ pub fn ast_type_is_defined_in_local_crate(&self, original_type: @ast::Ty)
+ -> bool {
+ match original_type.node {
+ ty_path(_, path_id) => {
+ match *self.crate_context.tcx.def_map.get(&path_id) {
+ def_ty(def_id) | def_struct(def_id) => {
+ if def_id.crate != local_crate {
+ return false;
+ }
+
+ // Make sure that this type precisely names a nominal
+ // type.
+ match self.crate_context
+ .tcx
+ .items
+ .find(&def_id.node) {
+ None => {
+ self.crate_context.tcx.sess.span_bug(
+ original_type.span,
+ ~"resolve didn't resolve this type?!");
+ }
+ Some(&node_item(item, _)) => {
+ match item.node {
+ item_struct(*) | item_enum(*) => true,
+ _ => false,
+ }
+ }
+ Some(_) => false,
+ }
+ }
+ _ => false
+ }
+ }
+ _ => false
+ }
+ }
+
// Converts an implementation in the AST to an Impl structure.
fn create_impl_from_item(&self, item: @item) -> @Impl {
fn add_provided_methods(all_methods: &mut ~[@MethodInfo],
*/
-use core::prelude::*;
-
use metadata::csearch;
use middle::ty::{substs, ty_param_bounds_and_ty};
use middle::ty;
use util::common::{indenter, pluralize};
use util::ppaux;
-use core::vec;
use syntax::abi::AbiSet;
use syntax::ast::{RegionTyParamBound, TraitTyParamBound};
use syntax::ast;
// represent the self argument (unless this is a static method).
// This argument will have the *transformed* self type.
for trait_m.transformed_self_ty.each |&t| {
- trait_fn_args.push(ty::arg {mode: ast::expl(ast::by_copy), ty: t});
+ trait_fn_args.push(ty::arg {
+ ty: t
+ });
}
for impl_m.transformed_self_ty.each |&t| {
- impl_fn_args.push(ty::arg {mode: ast::expl(ast::by_copy), ty: t});
+ impl_fn_args.push(ty::arg {
+ ty: t
+ });
}
// Add in the normal arguments.
*/
-use core::prelude::*;
-
use middle::ty::{AutoPtr, AutoBorrowVec, AutoBorrowFn};
use middle::ty::{AutoDerefRef, AutoRef};
use middle::ty::{vstore_slice, vstore_box, vstore_uniq};
// terms of error reporting, although we do not do that properly right
// now.
-use core::prelude::*;
-
use middle::ty::{FloatVar, FnSig, IntVar, TyVar};
use middle::ty::{IntType, UintType, arg, substs};
use middle::ty;
use util::common::indent;
use core::result::{iter_vec2, map_vec2};
-use core::vec;
use syntax::ast::{Onceness, purity};
use syntax::ast;
use syntax::opt_vec;
b: &ty::ClosureTy) -> cres<ty::ClosureTy>;
fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig>;
fn flds(&self, a: ty::field, b: ty::field) -> cres<ty::field>;
- fn modes(&self, a: ast::mode, b: ast::mode) -> cres<ast::mode>;
fn args(&self, a: ty::arg, b: ty::arg) -> cres<ty::arg>;
fn sigils(&self, p1: ast::Sigil, p2: ast::Sigil) -> cres<ast::Sigil>;
fn purities(&self, a: purity, b: purity) -> cres<purity>;
}
}
-pub fn super_modes<C:Combine>(
- self: &C, a: ast::mode, b: ast::mode)
- -> cres<ast::mode> {
-
- let tcx = self.infcx().tcx;
- ty::unify_mode(tcx, expected_found(self, a, b))
-}
-
-pub fn super_args<C:Combine>(
- self: &C, a: ty::arg, b: ty::arg)
- -> cres<ty::arg> {
-
- do self.modes(a.mode, b.mode).chain |m| {
- do self.contratys(a.ty, b.ty).chain |t| {
- Ok(arg {mode: m, ty: t})
- }
+pub fn super_args<C:Combine>(self: &C, a: ty::arg, b: ty::arg)
+ -> cres<ty::arg> {
+ do self.contratys(a.ty, b.ty).chain |t| {
+ Ok(arg {
+ ty: t
+ })
}
}
-pub fn super_vstores<C:Combine>(
- self: &C, vk: ty::terr_vstore_kind,
- a: ty::vstore, b: ty::vstore) -> cres<ty::vstore> {
+pub fn super_vstores<C:Combine>(self: &C,
+ vk: ty::terr_vstore_kind,
+ a: ty::vstore,
+ b: ty::vstore)
+ -> cres<ty::vstore> {
debug!("%s.super_vstores(a=%?, b=%?)", self.tag(), a, b);
match (a, b) {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use middle::ty::RegionVid;
use middle::ty;
use middle::typeck::infer::combine::*;
super_trait_stores(self, vk, a, b)
}
- fn modes(&self, a: ast::mode, b: ast::mode) -> cres<ast::mode> {
- super_modes(self, a, b)
- }
-
fn args(&self, a: ty::arg, b: ty::arg) -> cres<ty::arg> {
super_args(self, a, b)
}
* a lattice.
*/
-use core::prelude::*;
-
use middle::ty::{RegionVid, TyVar, Vid};
use middle::ty;
use middle::typeck::isr_alist;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use middle::ty::RegionVid;
use middle::ty;
use middle::typeck::infer::combine::*;
super_trait_stores(self, vk, a, b)
}
- fn modes(&self, a: ast::mode, b: ast::mode) -> cres<ast::mode> {
- super_modes(self, a, b)
- }
-
fn args(&self, a: ty::arg, b: ty::arg) -> cres<ty::arg> {
super_args(self, a, b)
}
*/
-use core::prelude::*;
-
pub use middle::ty::IntVarValue;
pub use middle::typeck::infer::resolve::resolve_and_force_all_but_regions;
pub use middle::typeck::infer::resolve::{force_all, not_regions};
use util::common::indent;
use util::ppaux::{bound_region_to_str, ty_to_str, trait_ref_to_str};
-use core::cmp::Eq;
-use core::result::{Result, Ok, Err};
-use core::result;
-use core::vec;
use std::list::Nil;
use std::smallintmap::SmallIntMap;
use syntax::ast::{m_imm, m_mutbl};
*/
-use core::prelude::*;
-
use middle::ty;
use middle::ty::{FreeRegion, Region, RegionVid};
use middle::ty::{re_static, re_infer, re_free, re_bound};
use core::cell::{Cell, empty_cell};
use core::hashmap::{HashMap, HashSet};
-use core::result::{Err, Ok};
use core::to_bytes;
-use core::uint;
-use core::vec;
use syntax::codemap::span;
use syntax::ast;
// future). If you want to resolve everything but one type, you are
// probably better off writing `resolve_all - resolve_ivar`.
-use core::prelude::*;
-
use middle::ty::{FloatVar, FloatVid, IntVar, IntVid, RegionVid, TyVar, TyVid};
use middle::ty::{type_is_bot, IntType, UintType};
use middle::ty;
use syntax::ast;
-use core::vec;
-
pub static resolve_nested_tvar: uint = 0b0000000001;
pub static resolve_rvar: uint = 0b0000000010;
pub static resolve_ivar: uint = 0b0000000100;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use middle::ty;
use middle::ty::TyVar;
use middle::typeck::check::regionmanip::replace_bound_regions_in_fn_sig;
use syntax::ast::{Onceness, m_const, purity};
use syntax::codemap::span;
-
pub struct Sub(CombineFields); // "subtype", "subregion" etc
impl Combine for Sub {
vk: ty::terr_vstore_kind,
a: ty::TraitStore,
b: ty::TraitStore)
- -> cres<ty::TraitStore> {
+ -> cres<ty::TraitStore> {
super_trait_stores(self, vk, a, b)
}
- fn modes(&self, a: ast::mode, b: ast::mode) -> cres<ast::mode> {
- super_modes(self, a, b)
- }
-
fn args(&self, a: ty::arg, b: ty::arg) -> cres<ty::arg> {
super_args(self, a, b)
}
*/
-use core::prelude::*;
-
use driver::diagnostic;
use driver::driver::{optgroups, build_session_options, build_session};
use driver::driver::{str_input, build_configuration};
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use middle::ty::{FnSig, Vid};
use middle::ty::IntVarValue;
use middle::ty;
use syntax::ast;
-use core::uint;
-use core::str;
-
pub trait InferStr {
fn inf_str(&self, cx: &InferCtxt) -> ~str;
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
use std::smallintmap::SmallIntMap;
use middle::ty::{Vid, expected_found, IntVarValue};
*/
-use core::prelude::*;
-
use driver::session;
use middle::resolve;
use util::ppaux;
use core::hashmap::HashMap;
-use core::result;
-use core::vec;
use std::list::List;
use std::list;
use syntax::codemap::span;
}
pub struct method_map_entry {
- // the type and mode of the self parameter, which is not reflected
- // in the fn type (FIXME #3446)
+ // the type of the self parameter, which is not reflected in the fn type
+ // (FIXME #3446)
self_arg: ty::arg,
+ // the mode of `self`
+ self_mode: ty::SelfMode,
+
// the type of explicit self on the method
explicit_self: ast::self_ty_,
fn check_start_fn_ty(ccx: @mut CrateCtxt,
start_id: ast::node_id,
start_span: span) {
-
let tcx = ccx.tcx;
let start_t = ty::node_id_to_type(tcx, start_id);
match ty::get(start_t).sty {
_ => ()
}
- fn arg(m: ast::rmode, ty: ty::t) -> ty::arg {
- ty::arg {mode: ast::expl(m), ty: ty}
+ fn arg(ty: ty::t) -> ty::arg {
+ ty::arg {
+ ty: ty
+ }
}
let se_ty = ty::mk_bare_fn(tcx, ty::BareFnTy {
purity: ast::impure_fn,
abis: abi::AbiSet::Rust(),
- sig: ty::FnSig {bound_lifetime_names: opt_vec::Empty,
- inputs: ~[arg(ast::by_copy, ty::mk_int()),
- arg(ast::by_copy, ty::mk_imm_ptr(tcx,
- ty::mk_imm_ptr(tcx, ty::mk_u8()))),
- arg(ast::by_copy, ty::mk_imm_ptr(tcx, ty::mk_u8()))],
- output: ty::mk_int()}
+ sig: ty::FnSig {
+ bound_lifetime_names: opt_vec::Empty,
+ inputs: ~[
+ arg(ty::mk_int()),
+ arg(ty::mk_imm_ptr(tcx,
+ ty::mk_imm_ptr(tcx, ty::mk_u8()))),
+ arg(ty::mk_imm_ptr(tcx, ty::mk_u8()))
+ ],
+ output: ty::mk_int()
+ }
});
require_same_types(tcx, None, false, start_span, start_t, se_ty,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use middle::ty;
-use core::result::Result;
-use core::result;
use syntax::ast;
use syntax::codemap::span;
use syntax::opt_vec::OptVec;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
#[link(name = "rustc",
vers = "0.7-pre",
uuid = "0ce89b41-2f92-459e-bbc1-8f5fe32f16cf",
#[deny(deprecated_pattern)];
#[deny(deprecated_mode)];
-#[no_core];
-
-extern mod core(vers = "0.7-pre");
extern mod std(vers = "0.7-pre");
extern mod syntax(vers = "0.7-pre");
-use core::prelude::*;
use driver::driver::{host_triple, optgroups, early_error};
use driver::driver::{str_input, file_input, build_session_options};
use driver::session;
use middle::lint;
-use core::io::ReaderUtil;
-use core::result::{Ok, Err};
use std::getopts::{groups, opt_present};
use std::getopts;
use syntax::codemap;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use syntax::ast;
use syntax::codemap::{span};
use syntax::visit;
use core::hashmap::HashSet;
-use core::str;
use std;
pub fn time<T>(do_it: bool, what: ~str, thunk: &fn() -> T) -> T {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
-use middle::ty;
-use middle::typeck;
-use middle::ty::canon_mode;
-use middle::ty::{bound_region, br_anon, br_named, br_self, br_cap_avoid,
- br_fresh};
-use middle::ty::{ctxt, field, method};
+use metadata::encoder;
+use middle::ty::{ReSkolemized, ReVar};
+use middle::ty::{bound_region, br_anon, br_named, br_self, br_cap_avoid};
+use middle::ty::{br_fresh, ctxt, field, method};
use middle::ty::{mt, t, param_bound, param_ty};
use middle::ty::{re_bound, re_free, re_scope, re_infer, re_static, Region};
-use middle::ty::{ReSkolemized, ReVar};
use middle::ty::{ty_bool, ty_bot, ty_box, ty_struct, ty_enum};
use middle::ty::{ty_err, ty_estr, ty_evec, ty_float, ty_bare_fn, ty_closure};
-use middle::ty::{ty_trait, ty_int};
use middle::ty::{ty_nil, ty_opaque_box, ty_opaque_closure_ptr, ty_param};
use middle::ty::{ty_ptr, ty_rptr, ty_self, ty_tup, ty_type, ty_uniq};
+use middle::ty::{ty_trait, ty_int};
use middle::ty::{ty_uint, ty_unboxed_vec, ty_infer};
-use metadata::encoder;
+use middle::ty;
+use middle::typeck;
+use syntax::abi::AbiSet;
+use syntax::ast_map;
use syntax::codemap::span;
use syntax::print::pprust;
-use syntax::print::pprust::mode_to_str;
use syntax::{ast, ast_util};
-use syntax::ast_map;
-use syntax::abi::AbiSet;
-
-use core::str;
-use core::vec;
pub trait Repr {
fn repr(&self, tcx: ctxt) -> ~str;
pub fn ty_to_str(cx: ctxt, typ: t) -> ~str {
fn fn_input_to_str(cx: ctxt, input: ty::arg) -> ~str {
- let ty::arg {mode: mode, ty: ty} = input;
- let modestr = match canon_mode(cx, mode) {
- ast::infer(_) => ~"",
- ast::expl(m) => {
- if !ty::type_needs_infer(ty) &&
- m == ty::default_arg_mode_for_ty(cx, ty) {
- ~""
- } else {
- mode_to_str(ast::expl(m)) + ~":"
- }
- }
- };
- fmt!("%s%s", modestr, ty_to_str(cx, ty))
+ ty_to_str(cx, input.ty)
}
fn bare_fn_to_str(cx: ctxt,
purity: ast::purity,
abis: AbiSet,
ident: Option<ast::ident>,
- sig: &ty::FnSig) -> ~str
- {
+ sig: &ty::FnSig)
+ -> ~str {
let mut s = ~"extern ";
s.push_str(abis.to_str());
impl Repr for ty::arg {
fn repr(&self, tcx: ctxt) -> ~str {
- fmt!("%?(%s)", self.mode, self.ty.repr(tcx))
+ fmt!("(%s)", self.ty.repr(tcx))
}
}
non-sendableness.
*/
-use core::prelude::*;
-
use parse;
use core::cell::Cell;
an AST's attributes.
*/
-use core::prelude::*;
-
-use core::str;
use syntax::ast;
use syntax::attr;
use syntax::ast;
use syntax;
use super::{parse_hidden, parse_crate, parse_desc};
- use core::prelude::*;
fn parse_attributes(source: ~str) -> ~[ast::attribute] {
use syntax::parse;
let parse_sess = syntax::parse::new_parse_sess(None);
let parser = parse::new_parser_from_source_str(
- parse_sess, ~[], ~"-", codemap::FssNone, @source);
+ parse_sess, ~[], ~"-", @source);
parser.parse_outer_attributes()
}
of the natural-language documentation for a crate.
*/
-use core::prelude::*;
-
use astsrv;
use attr_parser;
use doc::ItemUtils;
use fold;
use pass::Pass;
-use core::vec;
use syntax::ast;
use syntax::ast_map;
}
};
- do vec::map2(docs, attrs) |doc, attrs| {
+ do vec::map_zip(docs, attrs) |doc, attrs| {
assert!(doc.name == attrs.first());
let desc = attrs.second();
use attr_pass::run;
use doc;
use extract;
- use core::prelude::*;
fn mk_doc(source: ~str) -> doc::Doc {
do astsrv::from_str(copy source) |srv| {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
use core::cell::Cell;
-use core::os;
-use core::result;
use core::run;
use core::run::ProgramOutput;
-use core::vec;
use core::result::Result;
use std::getopts;
#[cfg(test)]
mod test {
use config::*;
- use core::prelude::*;
use core::run::ProgramOutput;
fn parse_config(args: &[~str]) -> Result<Config, ~str> {
let config = parse_config(~[~"rustdoc", ~"crate.rc"]);
assert!(config.get().pandoc_cmd == Some(~"pandoc"));
}
-}
\ No newline at end of file
+}
* tests on this file
*/
-use core::prelude::*;
-
/// The base price of a muffin on a non-holiday
static price_of_a_muffin: float = 70f;
is interpreted as the brief description.
*/
-use core::prelude::*;
-
use astsrv;
use doc::ItemUtils;
use doc;
use fold;
use pass::Pass;
-use core::str;
-use core::vec;
use core::util;
pub fn mk_pass() -> Pass {
use super::{extract, paragraphs, run};
use doc;
use extract;
- use core::prelude::*;
fn mk_doc(source: ~str) -> doc::Doc {
do astsrv::from_str(copy source) |srv| {
//! The document model
-use core::prelude::*;
-
use doc;
-use core::vec;
-
pub type AstId = int;
#[deriving(Eq)]
//! Converts the Rust AST to the rustdoc document model
-use core::prelude::*;
-
use astsrv;
use doc::ItemUtils;
use doc;
-use core::cast;
use core::task::local_data::local_data_get;
-use core::vec;
use syntax::ast;
use syntax;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use doc;
#[cfg(test)] use extract;
#[cfg(test)] use parse;
-use core::vec;
-
pub struct Fold<T> {
ctxt: T,
fold_doc: FoldDoc<T>,
//! Build indexes as appropriate for the markdown pass
-use core::prelude::*;
-
use astsrv;
use config;
use doc::ItemUtils;
use markdown_writer;
use pass::Pass;
-use core::str;
-
pub fn mk_pass(config: config::Config) -> Pass {
Pass {
name: ~"markdown_index",
use markdown_index_pass::run;
use path_pass;
use super::pandoc_header_id;
- use core::prelude::*;
fn mk_doc(output_style: config::OutputStyle, source: ~str)
-> doc::Doc {
//! Generate markdown from a document tree
-use core::prelude::*;
-
use astsrv;
use doc::ItemUtils;
use doc;
use sort_pass;
use core::cell::Cell;
-use core::str;
-use core::vec;
use syntax;
pub fn mk_pass(writer_factory: WriterFactory) -> Pass {
use trim_pass;
use tystr_pass;
use unindent_pass;
- use core::prelude::*;
fn render(source: ~str) -> ~str {
let (srv, doc) = create_doc_srv(source);
let doc = (page_pass::mk_pass(config::DocPerMod).f)(srv, doc);
write_markdown(doc, writer_factory);
// We expect two pages to have been written
- for iter::repeat(2) {
+ for old_iter::repeat(2) {
po.recv();
}
}
~"#[link(name = \"core\")]; mod a { }");
let doc = (page_pass::mk_pass(config::DocPerMod).f)(srv, doc);
write_markdown(doc, writer_factory);
- for iter::repeat(2) {
+ for old_iter::repeat(2) {
let (page, markdown) = po.recv();
match page {
doc::CratePage(_) => {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use config;
use doc::ItemUtils;
use doc;
-use core::io;
use core::libc;
-use core::os;
-use core::comm;
-use core::result;
use core::run;
-use core::str;
-use core::task;
use core::comm::*;
use std::future;
use path_pass;
use config;
use super::make_local_filename;
- use core::prelude::*;
fn mk_doc(name: ~str, source: ~str) -> doc::Doc {
do astsrv::from_str(source) |srv| {
individual modules, pages for the crate, indexes, etc.
*/
-use core::prelude::*;
-
use astsrv;
use config;
use doc::ItemUtils;
//! AST-parsing helpers
-use core::prelude::*;
-
use rustc::driver::driver::{file_input, str_input};
use rustc::driver::driver;
use rustc::driver::session;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use astsrv;
use doc;
use time;
#[cfg(test)] use extract;
-use core::vec;
-
/// A single operation on the document model
pub struct Pass {
name: ~str,
//! Records the full path to items
-use core::prelude::*;
-
use astsrv;
use doc::ItemUtils;
use doc;
//! Prune things that are private
-use core::prelude::*;
-
use extract;
use syntax::ast;
use syntax::ast_map;
#[license = "MIT/ASL2"];
#[crate_type = "lib"];
-#[no_core];
-
#[allow(non_implicitly_copyable_typarams)];
-extern mod core(vers = "0.7-pre");
extern mod std(vers = "0.7-pre");
extern mod rustc(vers = "0.7-pre");
extern mod syntax(vers = "0.7-pre");
//! Breaks rustdocs into sections according to their headers
-use core::prelude::*;
-
use astsrv;
use doc::ItemUtils;
use doc;
use fold;
use pass::Pass;
-use core::str;
-
pub fn mk_pass() -> Pass {
Pass {
name: ~"sectionalize",
use doc;
use extract;
use sectionalize_pass::run;
- use core::prelude::*;
fn mk_doc(source: ~str) -> doc::Doc {
do astsrv::from_str(copy source) |srv| {
//! Generic pass for performing an operation on all descriptions
-use core::prelude::*;
-
use astsrv;
use doc::ItemUtils;
use doc;
use sectionalize_pass;
use text_pass::mk_pass;
- use core::prelude::*;
-
fn mk_doc(source: ~str) -> doc::Doc {
do astsrv::from_str(copy source) |srv| {
let doc = extract::from_srv(srv.clone(), ~"");
//! Pulls type information out of the AST and attaches it to the document
-use core::prelude::*;
-
use astsrv;
use doc::ItemUtils;
use doc;
use fold;
use pass::Pass;
-use core::vec;
use syntax::ast;
use syntax::print::pprust;
use syntax::ast_map;
use doc;
use extract;
use tystr_pass::run;
- use core::prelude::*;
fn mk_doc(source: ~str) -> doc::Doc {
do astsrv::from_str(copy source) |srv| {
middle of a line, and each of the following lines is indented.
*/
-use core::prelude::*;
-
use pass::Pass;
use text_pass;
-use core::str;
-use core::uint;
-use core::vec;
-
pub fn mk_pass() -> Pass {
text_pass::mk_pass(~"unindent", unindent)
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
// Just a named container for our op, so it can have impls
pub struct NominalOp<T> {
op: T
#[license = "MIT/ASL2"];
#[crate_type = "lib"];
-#[no_core];
-
#[allow(vecs_implicitly_copyable,
non_implicitly_copyable_typarams)];
-extern mod core(vers = "0.7-pre");
extern mod std(vers = "0.7-pre");
extern mod rustc(vers = "0.7-pre");
extern mod syntax(vers = "0.7-pre");
use core::*;
-use core::io::{ReaderUtil, WriterUtil};
use rustc::driver::{driver, session};
use syntax::{ast, diagnostic};
use syntax::ast_util::*;
-Right now (2013-04-11), only one package works, the branch of rust-sdl at:
-https://github.com/catamorphism/rust-sdl/tree/new-rustpkg
+Right now, commands that work are "build" and "clean".
-and only one command works, "build".
+`rustpkg build` and `rustpkg clean` should work
+
+for example:
+$ cd ~/rust/src/librustpkg/testsuite/pass
+$ rustpkg build hello-world
+... some output ...
+$ rustpkg clean hello-world
+
+-------------
+the following test packages in librustpkg/testsuite/pass:
+ * hello-world
+ * install-paths
+ * simple-lib
+ * deeply/nested/path
+ * fancy-lib
+
+ It fails on the following test packages:
+ * external-crate (no support for `extern mod` inference yet)
+
+and should fail with proper error messages
+on all of the test packages in librustpkg/testsuite/fail
+ * no-inferred-crates
// Useful conditions
pub use core::path::Path;
+pub use util::PkgId;
condition! {
bad_path: (super::Path, ~str) -> super::Path;
}
+
+condition! {
+ nonexistent_package: (super::PkgId, ~str) -> super::Path;
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Context data structure used by rustpkg
+
+use core::hashmap::HashMap;
+
+pub struct Ctx {
+ // I'm not sure what this is for
+ json: bool,
+ // Cache of hashes of things already installed
+ // though I'm not sure why the value is a bool
+ dep_cache: @mut HashMap<~str, bool>,
+}
// rustpkg utilities having to do with paths and directories
-use core::path::*;
-use core::{os, str};
-use core::option::*;
use util::PkgId;
+use core::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
-/// Returns the output directory to use.
-/// Right now is always the default, should
-/// support changing it.
-pub fn dest_dir(pkgid: PkgId) -> Path {
- default_dest_dir(&pkgid.path)
+#[deriving(Eq)]
+pub enum OutputType { Main, Lib, Bench, Test }
+
+/// Returns the value of RUST_PATH, as a list
+/// of Paths. In general this should be read from the
+/// environment; for now, it's hard-wired to just be "."
+pub fn rust_path() -> ~[Path] {
+ ~[Path(".")]
}
-/// Returns the default output directory for compilation.
-/// Creates that directory if it doesn't exist.
-pub fn default_dest_dir(pkg_dir: &Path) -> Path {
+static u_rwx: i32 = (S_IRUSR | S_IWUSR | S_IXUSR) as i32;
+
+/// Creates a directory that is readable, writeable,
+/// and executable by the user. Returns true iff creation
+/// succeeded.
+pub fn make_dir_rwx(p: &Path) -> bool {
use core::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
- use conditions::bad_path::cond;
- // For now: assumes that pkg_dir exists and is relative
- // to the CWD. Change this later when we do path searching.
- let rslt = pkg_dir.push("build");
- let is_dir = os::path_is_dir(&rslt);
- if os::path_exists(&rslt) {
- if is_dir {
- rslt
- }
- else {
- cond.raise((rslt, ~"Path names a file that isn't a directory"))
- }
- }
- else {
- // Create it
- if os::make_dir(&rslt, (S_IRUSR | S_IWUSR | S_IXUSR) as i32) {
- rslt
- }
- else {
- cond.raise((rslt, ~"Could not create directory"))
- }
- }
+ os::make_dir(p, u_rwx)
}
/// Replace all occurrences of '-' in the stem part of path with '_'
}
}
-#[cfg(test)]
-mod test {
- use core::{os, rand};
- use core::path::Path;
- use path_util::*;
- use core::rand::RngUtil;
-
- // Helper function to create a directory name that doesn't exist
- pub fn mk_nonexistent(tmpdir: &Path, suffix: &str) -> Path {
- let r = rand::rng();
- for 1000.times {
- let p = tmpdir.push(r.gen_str(16) + suffix);
- if !os::path_exists(&p) {
- return p;
- }
- }
- fail!(~"Couldn't compute a non-existent path name; this is worrisome")
+// n.b. So far this only handles local workspaces
+// n.b. The next three functions ignore the package version right
+// now. Should fix that.
+
+/// True if there's a directory in <workspace> with
+/// pkgid's short name
+pub fn workspace_contains_package_id(pkgid: PkgId, workspace: &Path) -> bool {
+ let pkgpath = workspace.push("src").push(pkgid.path.to_str());
+ os::path_is_dir(&pkgpath)
+}
+
+/// Return the directory for <pkgid>'s source files in <workspace>.
+/// Doesn't check that it exists.
+pub fn pkgid_src_in_workspace(pkgid: PkgId, workspace: &Path) -> Path {
+ let result = workspace.push("src");
+ result.push(pkgid.path.to_str())
+}
+
+/// Returns the executable that would be installed for <pkgid>
+/// in <workspace>
+pub fn target_executable_in_workspace(pkgid: PkgId, workspace: &Path) -> Path {
+ let result = workspace.push("bin");
+ // should use a target-specific subdirectory
+ mk_output_path(Main, pkgid.path.to_str(), result)
+}
+
+
+/// Returns the executable that would be installed for <pkgid>
+/// in <workspace>
+pub fn target_library_in_workspace(pkgid: PkgId, workspace: &Path) -> Path {
+ let result = workspace.push("lib");
+ mk_output_path(Lib, pkgid.path.to_str(), result)
+}
+
+/// Returns the test executable that would be installed for <pkgid>
+/// in <workspace>
+pub fn target_test_in_workspace(pkgid: PkgId, workspace: &Path) -> Path {
+ let result = workspace.push("build");
+ mk_output_path(Test, pkgid.path.to_str(), result)
+}
+
+/// Returns the bench executable that would be installed for <pkgid>
+/// in <workspace>
+pub fn target_bench_in_workspace(pkgid: PkgId, workspace: &Path) -> Path {
+ let result = workspace.push("build");
+ mk_output_path(Bench, pkgid.path.to_str(), result)
+}
+
+/// Return the directory for <pkgid>'s build artifacts in <workspace>.
+/// Creates it if it doesn't exist.
+pub fn build_pkg_id_in_workspace(pkgid: PkgId, workspace: &Path) -> Path {
+ use conditions::bad_path::cond;
+
+ let mut result = workspace.push("build");
+ // n.b. Should actually use a target-specific
+ // subdirectory of build/
+ result = result.push(normalize(~pkgid.path).to_str());
+ if os::path_exists(&result) || os::mkdir_recursive(&result, u_rwx) {
+ result
}
+ else {
+ cond.raise((result, fmt!("Could not create directory for package %s", pkgid.to_str())))
+ }
+}
- #[test]
- fn default_dir_ok() {
- let the_path = os::tmpdir();
- let substitute_path = Path("xyzzy");
- assert!(default_dest_dir(&the_path) == the_path.push(~"build"));
- let nonexistent_path = mk_nonexistent(&the_path, "quux");
- let bogus = do ::conditions::bad_path::cond.trap(|_| {
- substitute_path
- }).in { default_dest_dir(&nonexistent_path) };
- assert!(bogus == substitute_path);
+/// Return the output file for a given directory name,
+/// given whether we're building a library and whether we're building tests
+pub fn mk_output_path(what: OutputType, short_name: ~str, dir: Path) -> Path {
+ match what {
+ Lib => dir.push(os::dll_filename(short_name)),
+ _ => dir.push(fmt!("%s%s%s", short_name,
+ if what == Test { ~"test" } else { ~"" },
+ os::EXE_SUFFIX))
}
}
#[license = "MIT/ASL2"];
#[crate_type = "lib"];
-#[no_core];
#[allow(vecs_implicitly_copyable,
non_implicitly_copyable_typarams)];
-extern mod core(vers = "0.7-pre");
extern mod std(vers = "0.7-pre");
extern mod rustc(vers = "0.7-pre");
extern mod syntax(vers = "0.7-pre");
use core::*;
pub use core::path::Path;
-use core::container::Map;
use core::hashmap::HashMap;
-use core::io::WriterUtil;
use rustc::driver::{driver, session};
use rustc::metadata::filesearch;
use std::{getopts};
use syntax::{ast, diagnostic};
use util::*;
-use path_util::{dest_dir, normalize};
+use path_util::normalize;
+use path_util::{build_pkg_id_in_workspace, pkgid_src_in_workspace};
+use workspace::pkg_parent_workspaces;
use rustc::driver::session::{lib_crate, bin_crate, crate_type};
+use context::Ctx;
mod conditions;
+mod context;
mod usage;
mod path_util;
+mod tests;
mod util;
+mod workspace;
/// A PkgScript represents user-supplied custom logic for
/// special build hooks. This only exists for packages with
/// Given the path name for a package script
/// and a package ID, parse the package script into
/// a PkgScript that we can then execute
- fn parse(script: Path, id: PkgId) -> PkgScript {
+ fn parse(script: Path, workspace: &Path, id: PkgId) -> PkgScript {
// Get the executable name that was invoked
let binary = os::args()[0];
// Build the rustc session data structures to pass
let cfg = driver::build_configuration(sess, @binary, &input);
let (crate, _) = driver::compile_upto(sess, cfg, &input,
driver::cu_parse, None);
- let work_dir = dest_dir(id);
+ let work_dir = build_pkg_id_in_workspace(id, workspace);
debug!("Returning package script with id %?", id);
}
-struct Ctx {
- // I'm not sure what this is for
- json: bool,
- // Cache of hashes of things already installed
- // though I'm not sure why the value is a bool
- dep_cache: @mut HashMap<~str, bool>,
-}
-
impl Ctx {
fn run(&self, cmd: ~str, args: ~[~str]) {
// The package id is presumed to be the first command-line
// argument
let pkgid = PkgId::new(args[0]);
- // Should allow the build directory to be configured.
- // Right now it's always the "build" subdirectory in
- // the package directory
- let dst_dir = dest_dir(pkgid);
- debug!("Destination dir = %s", dst_dir.to_str());
- // Right now, we assume the pkgid path is a valid dir
- // relative to the CWD. In the future, we should search
- // paths
- let cwd = os::getcwd().normalize();
- debug!("Current working directory = %s", cwd.to_str());
-
- // Create the package source
- let mut src = PkgSrc::new(&cwd, &dst_dir, &pkgid);
- debug!("Package src = %?", src);
-
- // Is there custom build logic? If so, use it
- let pkg_src_dir = cwd.push_rel(&pkgid.path);
- let mut custom = false;;
- debug!("Package source directory = %s", pkg_src_dir.to_str());
- let cfgs = match src.package_script_option(&pkg_src_dir) {
- Some(package_script_path) => {
- let pscript = PkgScript::parse(package_script_path,
- pkgid);
- // Limited right now -- we're only running the post_build
- // hook and probably fail otherwise
- // also post_build should be called pre_build
- let (cfgs, hook_result) = pscript.run_custom(~"post_build");
- debug!("Command return code = %?", hook_result);
- if hook_result != 0 {
- fail!(fmt!("Error running custom build command"))
+ for pkg_parent_workspaces(pkgid) |workspace| {
+ let src_dir = pkgid_src_in_workspace(pkgid, workspace);
+ let build_dir = build_pkg_id_in_workspace(pkgid, workspace);
+ debug!("Destination dir = %s", build_dir.to_str());
+
+ // Create the package source
+ let mut src = PkgSrc::new(&workspace.push("src"), &build_dir, &pkgid);
+ debug!("Package src = %?", src);
+
+ // Is there custom build logic? If so, use it
+ let pkg_src_dir = src_dir;
+ let mut custom = false;
+ debug!("Package source directory = %s", pkg_src_dir.to_str());
+ let cfgs = match src.package_script_option(&pkg_src_dir) {
+ Some(package_script_path) => {
+ let pscript = PkgScript::parse(package_script_path,
+ workspace,
+ pkgid);
+ // Limited right now -- we're only running the post_build
+ // hook and probably fail otherwise
+ // also post_build should be called pre_build
+ let (cfgs, hook_result) = pscript.run_custom(~"post_build");
+ debug!("Command return code = %?", hook_result);
+ if hook_result != 0 {
+ fail!(fmt!("Error running custom build command"))
+ }
+ custom = true;
+ // otherwise, the package script succeeded
+ cfgs
}
- custom = true;
- // otherwise, the package script succeeded
- cfgs
- }
- None => {
- debug!("No package script, continuing");
- ~[]
+ None => {
+ debug!("No package script, continuing");
+ ~[]
+ }
+ };
+
+ // If there was a package script, it should have finished
+ // the build already. Otherwise...
+ if !custom {
+ // Find crates inside the workspace
+ src.find_crates();
+ // Build it!
+ src.build(&build_dir, cfgs);
}
- };
-
- // If there was a package script, it should have finished
- // the build already. Otherwise...
- if !custom {
- // Find crates inside the workspace
- src.find_crates();
- // Build it!
- src.build(&dst_dir, cfgs);
}
}
~"clean" => {
// The package id is presumed to be the first command-line
// argument
let pkgid = PkgId::new(args[0]);
-
- self.clean(pkgid);
+ let cwd = os::getcwd();
+ self.clean(&cwd, pkgid); // tjc: should use workspace, not cwd
}
~"do" => {
if args.len() < 2 {
self.info();
}
~"install" => {
- self.install(if args.len() >= 1 { Some(args[0]) }
- else { None },
- if args.len() >= 2 { Some(args[1]) }
- else { None }, false);
+ if args.len() < 1 {
+ return usage::install();
+ }
+
+ // The package id is presumed to be the first command-line
+ // argument
+ let pkgid = PkgId::new(args[0]);
+ for pkg_parent_workspaces(pkgid) |workspace| {
+ self.install(workspace, pkgid);
+ }
}
~"prefer" => {
if args.len() < 1 {
}
}
- fn do_cmd(&self, cmd: ~str, pkgname: ~str) {
- match cmd {
- ~"build" | ~"test" => {
- util::error(~"that command cannot be manually called");
- fail!(~"do_cmd");
- }
- _ => {}
- }
-
- let cwd = &os::getcwd();
- let pkgid = PkgId::new(pkgname);
- // Always use the "build" subdirectory of the package dir,
- // but we should allow this to be configured
- let dst_dir = dest_dir(pkgid);
-
- let mut src = PkgSrc::new(cwd, &dst_dir, &pkgid);
- match src.package_script_option(cwd) {
- Some(script_path) => {
- let script = PkgScript::parse(script_path, pkgid);
- let (_, status) = script.run_custom(cmd); // Ignore cfgs?
- if status == 42 {
- util::error(~"no fns are listening for that cmd");
- fail!(~"do_cmd");
- }
- }
- None => {
- util::error(fmt!("invoked `do`, but there is no package script in %s",
- cwd.to_str()));
- fail!(~"do_cmd");
- }
- }
- }
-
- fn build(&self, _dir: &Path, _verbose: bool, _opt: bool,
- _test: bool) -> Option<PkgScript> {
- // either not needed anymore,
- // or needed only when we don't have a package script. Not sure which one.
- fail!();
- }
-
- fn compile(&self, _crate: &Path, _dir: &Path, _flags: ~[~str],
- _cfgs: ~[~str], _opt: bool, _test: bool) {
- // What's the difference between build and compile?
- fail!(~"compile not yet implemented");
+ fn do_cmd(&self, _cmd: ~str, _pkgname: ~str) {
+ // stub
+ fail!(~"`do` not yet implemented");
}
- fn clean(&self, id: PkgId) {
+ fn clean(&self, workspace: &Path, id: PkgId) {
// Could also support a custom build hook in the pkg
// script for cleaning files rustpkg doesn't know about.
// Do something reasonable for now
- let dir = dest_dir(id);
+ let dir = build_pkg_id_in_workspace(id, workspace);
util::note(fmt!("Cleaning package %s (removing directory %s)",
id.to_str(), dir.to_str()));
if os::path_exists(&dir) {
fail!(~"info not yet implemented");
}
- fn install(&self, _url: Option<~str>,
- _target: Option<~str>, _cache: bool) {
+ fn install(&self, _workspace: &Path, _id: PkgId) {
// stub
fail!(~"install not yet implemented");
}
// except according to those terms.
// rustpkg unit tests
+
+use context::Ctx;
+use core::hashmap::HashMap;
+use core::path::Path;
+use std::tempfile::mkdtemp;
+use util::{PkgId, default_version};
+use path_util::{target_executable_in_workspace, target_library_in_workspace,
+ target_test_in_workspace, target_bench_in_workspace,
+ make_dir_rwx};
+
+fn fake_ctxt() -> Ctx {
+ Ctx {
+ json: false,
+ dep_cache: @mut HashMap::new()
+ }
+}
+
+fn fake_pkg() -> PkgId {
+ PkgId {
+ path: Path(~"bogus"),
+ version: default_version()
+ }
+}
+
+fn mk_temp_workspace() -> Path {
+ mkdtemp(&os::tmpdir(), "test").expect("couldn't create temp dir")
+}
+
+fn is_rwx(p: &Path) -> bool {
+ use core::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
+
+ match p.get_mode() {
+ None => return false,
+ Some(m) => {
+ ((m & S_IRUSR as uint) == S_IRUSR as uint
+ && (m & S_IWUSR as uint) == S_IWUSR as uint
+ && (m & S_IXUSR as uint) == S_IXUSR as uint)
+ }
+ }
+}
+
+#[test]
+fn test_make_dir_rwx() {
+ let temp = &os::tmpdir();
+ let dir = temp.push(~"quux");
+ let _ = os::remove_dir(&dir);
+ assert!(make_dir_rwx(&dir));
+ assert!(os::path_is_dir(&dir));
+ assert!(is_rwx(&dir));
+ assert!(os::remove_dir(&dir));
+}
+
+#[test]
+#[ignore(reason = "install not yet implemented")]
+fn test_install_valid() {
+ let ctxt = fake_ctxt();
+ let temp_pkg_id = fake_pkg();
+ let temp_workspace = mk_temp_workspace();
+ // should have test, bench, lib, and main
+ ctxt.install(&temp_workspace, temp_pkg_id);
+ // Check that all files exist
+ let exec = target_executable_in_workspace(temp_pkg_id, &temp_workspace);
+ assert!(os::path_exists(&exec));
+ assert!(is_rwx(&exec));
+ let lib = target_library_in_workspace(temp_pkg_id, &temp_workspace);
+ assert!(os::path_exists(&lib));
+ assert!(is_rwx(&lib));
+ // And that the test and bench executables aren't installed
+ assert!(!os::path_exists(&target_test_in_workspace(temp_pkg_id, &temp_workspace)));
+ assert!(!os::path_exists(&target_bench_in_workspace(temp_pkg_id, &temp_workspace)));
+}
+
+#[test]
+#[ignore(reason = "install not yet implemented")]
+fn test_install_invalid() {
+ use conditions::nonexistent_package::cond;
+
+ let ctxt = fake_ctxt();
+ let pkgid = fake_pkg();
+ let temp_workspace = mk_temp_workspace();
+ let expected_path = Path(~"quux");
+ let substituted: Path = do cond.trap(|_| {
+ expected_path
+ }).in {
+ ctxt.install(&temp_workspace, pkgid);
+ // ok
+ fail!(~"test_install_invalid failed, should have raised a condition");
+ };
+ assert!(substituted == expected_path);
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub fn assert_true() {
+ assert!(true);
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*
+The test runner should check that, after `rustpkg build fancy-lib`:
+ * testsuite/fancy-lib/build/ exists
+ * testsuite/fancy-lib/build/ contains a file called generated.rs
+ * testsuite/fancy-lib/build/ contains a library named libfancy_lib
+ * testsuite/fancy-lib/build/ does not contain an executable
+ *
+*/
+
+extern mod std;
+
+pub mod foo;
+pub mod bar;
+#[path = "../../build/fancy_lib/generated.rs"] pub mod generated;
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub fn do_nothing() {
+}
\ No newline at end of file
use core::run;
pub fn main() {
- let cwd = os::getcwd();
- debug!("cwd = %s", cwd.to_str());
- let file = io::file_writer(&Path(~"fancy-lib/build/generated.rs"),
+ use core::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
+
+ let out_path = Path(~"build/fancy_lib");
+ if !os::path_exists(&out_path) {
+ assert!(os::make_dir(&out_path, (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
+ }
+
+ let file = io::file_writer(&out_path.push("generated.rs"),
[io::Create]).get();
file.write_str("pub fn wheeeee() { for [1, 2, 3].each() |_| { assert!(true); } }");
// now compile the crate itself
- run::run_program("rustc", ~[~"fancy-lib/fancy-lib.rs", ~"--lib",
- ~"-o", ~"fancy-lib/build/fancy_lib"]);
+ run::run_program("rustc", ~[~"src/fancy-lib/fancy-lib.rs", ~"--lib",
+ ~"-o", out_path.push(~"fancy_lib").to_str()]);
}
\ No newline at end of file
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-pub fn assert_true() {
- assert!(true);
-}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/*
-The test runner should check that, after `rustpkg build fancy-lib`:
- * testsuite/fancy-lib/build/ exists
- * testsuite/fancy-lib/build/ contains a file called generated.rs
- * testsuite/fancy-lib/build/ contains a library named libfancy_lib
- * testsuite/fancy-lib/build/ does not contain an executable
- *
-*/
-
-extern mod std;
-
-pub mod foo;
-pub mod bar;
-#[path = "build/generated.rs"] pub mod generated;
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-pub fn do_nothing() {
-}
\ No newline at end of file
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*
+The test runner should check that, after `rustpkg build hello-world`:
+ * testsuite/pass/hello-world/build/ exists
+ * testsuite/pass/hello-world/build/ contains an executable named hello-world
+ * testsuite/pass/hello-world/build/ does not contain a library
+
+ It should also check that after `rustpkg clean hello-world`:
+ * testsuite/pass/hello-world/build is empty
+*/
+
+use core::io;
+
+fn main() {
+ io::println(~"Hello world!");
+}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/*
-The test runner should check that, after `rustpkg build hello-world`:
- * testsuite/pass/hello-world/build/ exists
- * testsuite/pass/hello-world/build/ contains an executable named hello-world
- * testsuite/pass/hello-world/build/ does not contain a library
-
- It should also check that after `rustpkg clean hello-world`:
- * testsuite/pass/hello-world/build is empty
-*/
-
-use core::io;
-
-fn main() {
- io::println(~"Hello world!");
-}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[bench]
+fn g() {
+ let mut x = 0;
+ while(x < 1000) {
+ x += 1;
+ }
+}
\ No newline at end of file
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn f() -> int { 42 }
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*
+The test runner should check that, after `rustpkg install install-paths`
+ with RUST_PATH undefined in the environment:
+ * ./.rust/install_paths exists and is an executable
+ * ./.rust/libinstall_paths exists and is a library
+ * ./.rust/install_pathstest does not exist
+ * ./.rust/install_pathsbench does not exist
+ * install-paths/build/install_pathstest exists and is an executable
+ * install-paths/build/install_pathsbench exists and is an executable
+*/
+
+fn main() {}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#[bench]
-fn g() {
- let mut x = 0;
- while(x < 1000) {
- x += 1;
- }
-}
\ No newline at end of file
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn f() -> int { 42 }
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/*
-The test runner should check that, after `rustpkg install install-paths`
- with RUST_PATH undefined in the environment:
- * ./.rust/install_paths exists and is an executable
- * ./.rust/libinstall_paths exists and is a library
- * ./.rust/install_pathstest does not exist
- * ./.rust/install_pathsbench does not exist
- * install-paths/build/install_pathstest exists and is an executable
- * install-paths/build/install_pathsbench exists and is an executable
-*/
-
-fn main() {}
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#[test]
-fn test_two_plus_two() {
- assert!(2 + 2 == 4);
-}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[test]
+fn test_two_plus_two() {
+ assert!(2 + 2 == 4);
+}
}
/// Placeholder
-fn default_version() -> Version { ExactRevision(0.1) }
+pub fn default_version() -> Version { ExactRevision(0.1) }
// Path-fragment identifier of a package such as
// 'github.com/graydon/test'; path must be a relative
impl ToStr for PkgId {
fn to_str(&self) -> ~str {
// should probably use the filestem and not the whole path
- fmt!("%s-%s", self.path.to_str(), self.version.to_str())
+ fmt!("%s-%s", self.path.to_str(),
+ // Replace dots with -s in the version
+ // this is because otherwise rustc will think
+ // that foo-0.1 has .1 as its extension
+ // (Temporary hack until I figure out how to
+ // get rustc to not name the object file
+ // foo-0.o if I pass in foo-0.1 to build_output_filenames)
+ str::replace(self.version.to_str(), ".", "-"))
}
}
test: bool,
crate_type: session::crate_type) -> bool {
- let short_name = pkg_id.to_str();
+ // Want just the directory component here
+ let pkg_filename = pkg_id.path.filename().expect(~"Weird pkg id");
+ let short_name = fmt!("%s-%s", pkg_filename, pkg_id.version.to_str());
assert!(in_file.components.len() > 1);
let input = driver::file_input(copy *in_file);
out_file: Path,
binary: ~str,
what: driver::compile_upto) -> @ast::crate {
- debug!("Calling build_output_filenames with %?", build_dir_opt);
+ debug!("Calling build_output_filenames with %? and %s", build_dir_opt, out_file.to_str());
let outputs = driver::build_output_filenames(&input, &build_dir_opt, &Some(out_file), sess);
debug!("Outputs are %? and output type = %?", outputs, sess.opts.output_type);
let cfg = driver::build_configuration(sess, @binary, &input);
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// rustpkg utilities having to do with workspaces
+
+use path_util::{rust_path, workspace_contains_package_id};
+use util::PkgId;
+use core::path::Path;
+
+pub fn pkg_parent_workspaces(pkgid: PkgId, action: &fn(&Path) -> bool) {
+ // Using the RUST_PATH, find workspaces that contain
+ // this package ID
+ let workspaces = rust_path().filtered(|ws|
+ workspace_contains_package_id(pkgid, ws));
+ if workspaces.is_empty() {
+ // tjc: make this a condition
+ fail!(fmt!("Package %s not found in any of \
+ the following workspaces: %s",
+ pkgid.path.to_str(),
+ rust_path().to_str()));
+ }
+ for workspaces.each |ws| {
+ if action(ws) {
+ break;
+ }
+ }
+}
\ No newline at end of file
use sync::{Mutex, mutex_with_condvars, RWlock, rwlock_with_condvars};
use core::cast;
-use core::prelude::*;
use core::unstable::{SharedMutableState, shared_mutable_state};
use core::unstable::{clone_shared_mutable_state};
use core::unstable::{get_shared_mutable_state, get_shared_immutable_state};
#[cfg(test)]
mod tests {
- use core::prelude::*;
use arc::*;
use arc;
use core::cast::transmute;
use core::cast;
use core::libc::size_t;
-use core::prelude::*;
use core::ptr;
use core::sys::TypeDesc;
use core::sys;
//! Base64 binary-to-text encoding
-use core::iter;
+use core::old_iter;
use core::str;
use core::vec;
impl FromBase64 for ~[u8] {
/**
* Convert base64 `u8` vector into u8 byte values.
- * Every 4 encoded characters is converted into 3 octets, rem padding.
+ * Every 4 encoded characters is converted into 3 octets, modulo padding.
*
* *Example*:
*
while i < len {
let mut n = 0u;
- for iter::repeat(4u) {
+ for old_iter::repeat(4u) {
let ch = self[i] as char;
n <<= 6u;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::container::{Container, Mutable, Set};
-use core::ops;
-use core::prelude::*;
-use core::uint;
use core::vec::from_elem;
-use core::vec;
struct SmallBitv {
/// only the lowest nbits of this value are used. the rest is undefined.
#[cfg(test)]
mod tests {
- use core::prelude::*;
use std::test::BenchHarness;
use bitv::*;
* still held if needed.
*/
-use core::option;
-use core::prelude::*;
-use core::ptr;
-
/**
* The type representing a foreign chunk of memory
*
#[cfg(test)]
mod tests {
- use core::prelude::*;
use c_vec::*;
use core::comm::{GenericChan, GenericSmartChan, GenericPort};
use core::comm::{Chan, Port, Selectable, Peekable};
use core::pipes;
-use core::prelude::*;
/// An extension of `pipes::stream` that allows both sending and receiving.
pub struct DuplexStream<T, U> {
//! Unsafe debugging functions for inspecting values.
use core::cast::transmute;
-use core::ptr;
use core::sys;
pub mod rustrt {
pub fn debug_opaque<T>(x: T) {
unsafe {
- rustrt::debug_opaque(sys::get_type_desc::<T>(),
- ptr::addr_of(&x) as *());
+ rustrt::debug_opaque(sys::get_type_desc::<T>(), transmute(&x));
}
}
pub fn debug_box<T>(x: @T) {
unsafe {
- rustrt::debug_box(sys::get_type_desc::<T>(),
- ptr::addr_of(&x) as *());
+ rustrt::debug_box(sys::get_type_desc::<T>(), transmute(&x));
}
}
pub fn debug_tag<T>(x: T) {
unsafe {
- rustrt::debug_tag(sys::get_type_desc::<T>(),
- ptr::addr_of(&x) as *());
+ rustrt::debug_tag(sys::get_type_desc::<T>(), transmute(&x));
}
}
pub fn debug_fn<T>(x: T) {
unsafe {
- rustrt::debug_fn(sys::get_type_desc::<T>(),
- ptr::addr_of(&x) as *());
+ rustrt::debug_fn(sys::get_type_desc::<T>(), transmute(&x));
}
}
pub unsafe fn ptr_cast<T, U>(x: @T) -> @U {
transmute(
- rustrt::debug_ptrcast(sys::get_type_desc::<T>(),
- transmute(x)))
+ rustrt::debug_ptrcast(sys::get_type_desc::<T>(), transmute(x)))
}
/// Triggers a debugger breakpoint
//! A double-ended queue implemented as a circular buffer
-use core::container::{Container, Mutable};
-use core::prelude::*;
-use core::vec;
-
static initial_capacity: uint = 32u; // 2^5
pub struct Deque<T> {
*/
-use core::prelude::*;
use core::managed;
pub type DListLink<T> = Option<@mut DListNode<T>>;
/// Get the elements of the list as a vector. O(n).
fn to_vec(@mut self) -> ~[T] {
let mut v = vec::with_capacity(self.size);
- for iter::eachi(&self) |index,data| {
+ for old_iter::eachi(&self) |index,data| {
v[index] = *data;
}
v
#[cfg(test)]
mod tests {
use super::*;
- use core::prelude::*;
#[test]
fn test_dlist_concat() {
#[test]
fn test_dlist_foldl() {
let l = from_vec(vec::from_fn(101, |x|x));
- assert_eq!(iter::foldl(&l, 0, |accum,elem| *accum+*elem), 5050);
+ assert_eq!(old_iter::foldl(&l, 0, |accum,elem| *accum+*elem), 5050);
}
#[test]
fn test_dlist_break_early() {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
// Simple Extensible Binary Markup Language (ebml) reader and writer on a
// cursor model. See the specification here:
// http://www.matroska.org/technical/specs/rfc/index.html
use core::cast::transmute;
use core::int;
use core::io;
- use core::prelude::*;
use core::ptr::offset;
use core::str;
use core::unstable::intrinsics::bswap32;
#[allow(deprecated_mutable_fields)];
-use core::prelude::*;
use core::io::ReaderUtil;
/**
#[cfg(test)]
mod test {
use core::io::WriterUtil;
- use core::prelude::*;
use super::{FileInput, pathify, input_vec, input_vec_state};
fn make_file(path : &Path, contents: &[~str]) {
use core::io;
use core::comm::GenericChan;
use core::comm::GenericPort;
-use core::prelude::*;
use core::sys::size_of;
use core::vec;
use core::io::{Reader, Writer};
use core::comm::{Port, Chan};
use core::comm;
- use core::prelude::*;
pub type ReaderPort<T, R> =
FlatPort<T, PodUnflattener<T>, ReaderBytePort<R>>;
use core::cast;
use core::io::{Writer, Reader, ReaderUtil};
- use core::prelude::*;
use core::ptr;
use core::sys::size_of;
use core::vec;
use core::io::{Writer, Reader, ReaderUtil};
use core::comm::{Port, Chan};
- use core::prelude::*;
pub struct ReaderBytePort<R> {
reader: R
#[cfg(test)]
mod test {
- use core::prelude::*;
-
use flatpipes::{Flattener, Unflattener};
use flatpipes::bytepipes::*;
use flatpipes::pod;
use flatpipes::{BytePort, FlatChan, FlatPort};
use net::tcp::TcpSocketBuf;
- use core::int;
use core::io::BytesWriter;
- use core::prelude::*;
- use core::result;
- use core::task;
#[test]
fn test_serializing_memory_stream() {
// Client task
let addr = copy addr0;
do task::spawn || {
-
// Wait for the server to start listening
begin_connect_port.recv();
// Tests that the different backends behave the same when the
// binary streaming protocol is broken
mod broken_protocol {
- use core::prelude::*;
-
use flatpipes::{BytePort, FlatPort};
use flatpipes::flatteners::PodUnflattener;
use flatpipes::pod;
use io_util::BufReader;
- use core::io;
- use core::sys;
- use core::task;
-
type PortLoader<P> =
~fn(~[u8]) -> FlatPort<int, PodUnflattener<int>, P>;
use core::cmp::{Eq, Ord};
use core::option::{Some, None};
-use core::prelude::*;
pub type Treemap<K, V> = @TreeNode<K, V>;
use core::cast;
use core::cell::Cell;
-use core::comm::{oneshot, PortOne, send_one};
+use core::comm::{ChanOne, PortOne, oneshot, send_one};
use core::pipes::recv;
-use core::prelude::*;
use core::task;
#[doc = "The future type"]
Future {state: Forced(val)}
}
-pub fn from_port<A:Owned>(port: PortOne<A>) ->
- Future<A> {
+pub fn from_port<A:Owned>(port: PortOne<A>) -> Future<A> {
/*!
* Create a future from a port
*
let port = Cell(port);
do from_fn || {
- let port = port.take();
+ let port = port.take().unwrap();
match recv(port) {
oneshot::send(data) => data
}
* value of the future.
*/
- let (chan, port) = oneshot::init();
+ let (port, chan) = oneshot();
let chan = Cell(chan);
- do task::spawn || {
+ do task::spawn {
let chan = chan.take();
send_one(chan, blk());
}
#[allow(non_implicitly_copyable_typarams)]
#[cfg(test)]
mod test {
- use core::prelude::*;
use future::*;
#[test]
fn test_from_port() {
- let (ch, po) = oneshot::init();
+ let (po, ch) = oneshot();
send_one(ch, ~"whale");
let f = from_port(po);
assert!(f.get() == ~"whale");
*/
use core::cmp::Eq;
-use core::prelude::*;
use core::result::{Err, Ok};
use core::result;
use core::option::{Some, None};
use getopts::{HasArg, Long, Maybe, Multi, No, Occur, Opt, Optional, Req};
use getopts::{Short, Yes};
- use core::prelude::*;
use core::str;
use core::vec;
#[cfg(test)]
mod tests {
- use core::prelude::*;
use getopts::groups::OptGroup;
use getopts::*;
//! json serialization
-use core::prelude::*;
use core::io::{WriterUtil, ReaderUtil};
use core::hashmap::HashMap;
mod tests {
use super::*;
- use core::prelude::*;
use core::hashmap::HashMap;
use std::serialize::Decodable;
//! A standard linked list
-use core::cmp::Eq;
-use core::option::*;
-use core::prelude::*;
-use core::vec;
-
#[deriving(Eq)]
pub enum List<T> {
Cons(T, @List<T>),
//! Types/fns concerning Internet Protocol (IP), versions 4 & 6
use core::libc;
-use core::prelude::*;
use core::comm::{stream, SharedChan};
use core::ptr;
use core::result;
* object in the case of failure
*/
pub fn get_addr(node: &str, iotask: &iotask)
- -> result::Result<~[IpAddr], IpGetAddrErr> {
+ -> result::Result<~[IpAddr], IpGetAddrErr> {
let (output_po, output_ch) = stream();
let mut output_ch = Some(SharedChan::new(output_ch));
do str::as_buf(node) |node_ptr, len| {
let output_ch = output_ch.swap_unwrap();
debug!("slice len %?", len);
let handle = create_uv_getaddrinfo_t();
- let handle_ptr = ptr::addr_of(&handle);
+ let handle_ptr: *uv_getaddrinfo_t = &handle;
let handle_data = GetAddrData {
output_ch: output_ch.clone()
};
- let handle_data_ptr = ptr::addr_of(&handle_data);
+ let handle_data_ptr: *GetAddrData = &handle_data;
do interact(iotask) |loop_ptr| {
unsafe {
let result = uv_getaddrinfo(
use uv_ip4_addr = uv::ll::ip4_addr;
use uv_ip4_name = uv::ll::ip4_name;
- use core::prelude::*;
- use core::ptr;
+ use core::cast::transmute;
use core::result;
use core::str;
use core::uint;
impl AsUnsafeU32 for Ipv4Rep {
// this is pretty dastardly, i know
unsafe fn as_u32(&self) -> u32 {
- *((ptr::addr_of(self)) as *u32)
+ let this: &mut u32 = transmute(self);
+ *this
}
}
pub fn parse_to_ipv4_rep(ip: &str) -> result::Result<Ipv4Rep, ~str> {
use uv_ip6_addr = uv::ll::ip6_addr;
use uv_ip6_name = uv::ll::ip6_name;
- use core::prelude::*;
use core::result;
use core::str;
output_ch: SharedChan<result::Result<~[IpAddr],IpGetAddrErr>>
}
-extern fn get_addr_cb(handle: *uv_getaddrinfo_t, status: libc::c_int,
+extern fn get_addr_cb(handle: *uv_getaddrinfo_t,
+ status: libc::c_int,
res: *addrinfo) {
unsafe {
debug!("in get_addr_cb");
#[cfg(test)]
mod test {
- use core::prelude::*;
use net_ip::*;
use net_ip::v4;
use core::libc::size_t;
use core::libc;
use core::comm::{stream, Port, SharedChan};
-use core::prelude::*;
use core::ptr;
use core::result::{Result};
use core::result;
result_ch: result_ch,
closed_signal_ch: closed_signal_ch
};
- let conn_data_ptr = ptr::addr_of(&conn_data);
+ let conn_data_ptr: *ConnectReqData = &conn_data;
let (reader_po, reader_ch) = stream::<Result<~[u8], TcpErrData>>();
let reader_ch = SharedChan::new(reader_ch);
let stream_handle_ptr = malloc_uv_tcp_t();
},
iotask: iotask.clone()
};
- let socket_data_ptr = ptr::addr_of(&(*socket_data));
+ let socket_data_ptr: *TcpSocketData = &*socket_data;
// get an unsafe representation of our stream_handle_ptr that
// we can send into the interact cb to be handled in libuv..
debug!("stream_handle_ptr outside interact %?",
0i32 => {
debug!("tcp_init successful");
debug!("dealing w/ ipv4 connection..");
- let connect_req_ptr =
- ptr::addr_of(&((*socket_data_ptr).connect_req));
+ let connect_req_ptr: *uv::ll::uv_connect_t =
+ &(*socket_data_ptr).connect_req;
let addr_str = ip::format_addr(&input_ip);
let connect_result = match input_ip {
ip::Ipv4(ref addr) => {
uv::ll::tcp_connect(
connect_req_ptr,
stream_handle_ptr,
- ptr::addr_of(&in_addr),
+ &in_addr,
tcp_connect_on_connect_cb)
}
ip::Ipv6(ref addr) => {
uv::ll::tcp_connect6(
connect_req_ptr,
stream_handle_ptr,
- ptr::addr_of(&in_addr),
+ &in_addr,
tcp_connect_on_connect_cb)
}
};
* `TcpErrData` value as the `Err` variant
*/
pub fn write(sock: &TcpSocket, raw_write_data: ~[u8])
- -> result::Result<(), TcpErrData>
-{
- let socket_data_ptr = ptr::addr_of(&(*(sock.socket_data)));
+ -> result::Result<(), TcpErrData> {
+ let socket_data_ptr: *TcpSocketData = &*sock.socket_data;
write_common_impl(socket_data_ptr, raw_write_data)
}
pub fn write_future(sock: &TcpSocket, raw_write_data: ~[u8])
-> future::Future<result::Result<(), TcpErrData>>
{
- let socket_data_ptr = ptr::addr_of(&(*(sock.socket_data)));
+ let socket_data_ptr: *TcpSocketData = &*sock.socket_data;
do future_spawn {
let data_copy = copy(raw_write_data);
write_common_impl(socket_data_ptr, data_copy)
* `TcpErrData` record
*/
pub fn read_start(sock: &TcpSocket)
- -> result::Result<@Port<
- result::Result<~[u8], TcpErrData>>, TcpErrData> {
- let socket_data = ptr::addr_of(&(*(sock.socket_data)));
+ -> result::Result<@Port<result::Result<~[u8],
+ TcpErrData>>,
+ TcpErrData> {
+ let socket_data: *TcpSocketData = &*sock.socket_data;
read_start_common_impl(socket_data)
}
* * `sock` - a `net::tcp::TcpSocket` that you wish to stop reading on
*/
pub fn read_stop(sock: &TcpSocket) -> result::Result<(), TcpErrData> {
- let socket_data = ptr::addr_of(&(*sock.socket_data));
+ let socket_data: *TcpSocketData = &*sock.socket_data;
read_stop_common_impl(socket_data)
}
* read attempt. Pass `0u` to wait indefinitely
*/
pub fn read(sock: &TcpSocket, timeout_msecs: uint)
- -> result::Result<~[u8],TcpErrData> {
- let socket_data = ptr::addr_of(&(*(sock.socket_data)));
+ -> result::Result<~[u8],TcpErrData> {
+ let socket_data: *TcpSocketData = &*sock.socket_data;
read_common_impl(socket_data, timeout_msecs)
}
* read attempt. Pass `0u` to wait indefinitely
*/
fn read_future(sock: &TcpSocket, timeout_msecs: uint)
- -> future::Future<result::Result<~[u8],TcpErrData>> {
- let socket_data = ptr::addr_of(&(*(sock.socket_data)));
+ -> future::Future<result::Result<~[u8],TcpErrData>> {
+ let socket_data: *TcpSocketData = &*sock.socket_data;
do future_spawn {
read_common_impl(socket_data, timeout_msecs)
}
ipv6: (*server_data_ptr).ipv6,
iotask : iotask.clone()
};
- let client_socket_data_ptr = ptr::addr_of(
- &(*client_socket_data));
+ let client_socket_data_ptr: *TcpSocketData =
+ &*client_socket_data;
let client_stream_handle_ptr =
(*client_socket_data_ptr).stream_handle_ptr;
let (kill_po, kill_ch) = stream::<Option<TcpErrData>>();
let kill_ch = SharedChan::new(kill_ch);
let server_stream = uv::ll::tcp_t();
- let server_stream_ptr = ptr::addr_of(&server_stream);
+ let server_stream_ptr: *uv::ll::uv_tcp_t = &server_stream;
let server_data: TcpListenFcData = TcpListenFcData {
server_stream_ptr: server_stream_ptr,
stream_closed_ch: stream_closed_ch,
},
mut active: true
};
- let server_data_ptr = ptr::addr_of(&server_data);
+ let server_data_ptr: *TcpListenFcData = &server_data;
let (setup_po, setup_ch) = stream();
let in_addr = uv::ll::ip4_addr(
addr_str,
port as int);
- uv::ll::tcp_bind(server_stream_ptr,
- ptr::addr_of(&in_addr))
+ uv::ll::tcp_bind(server_stream_ptr, &in_addr)
}
ip::Ipv6(ref addr) => {
debug!("addr: %?", addr);
let in_addr = uv::ll::ip6_addr(
addr_str,
port as int);
- uv::ll::tcp_bind6(server_stream_ptr,
- ptr::addr_of(&in_addr))
+ uv::ll::tcp_bind6(server_stream_ptr, &in_addr)
}
};
match bind_result {
if self.socket_data.ipv6 {
let addr = uv::ll::ip6_addr("", 0);
uv::ll::tcp_getpeername6(self.socket_data.stream_handle_ptr,
- ptr::addr_of(&addr));
+ &addr);
ip::Ipv6(addr)
} else {
let addr = uv::ll::ip4_addr("", 0);
uv::ll::tcp_getpeername(self.socket_data.stream_handle_ptr,
- ptr::addr_of(&addr));
+ &addr);
ip::Ipv4(addr)
}
}
impl io::Writer for TcpSocketBuf {
pub fn write(&self, data: &const [u8]) {
unsafe {
- let socket_data_ptr =
- ptr::addr_of(&(*((*(self.data)).sock).socket_data));
+ let socket_data_ptr: *TcpSocketData =
+ &(*((*(self.data)).sock).socket_data);
let w_result = write_common_impl(socket_data_ptr,
- vec::slice(data,
- 0,
- vec::len(data)
- ).to_vec());
+ vec::slice(data,
+ 0,
+ data.len()).to_vec());
if w_result.is_err() {
let err_data = w_result.get_err();
debug!(
let close_data = TcpSocketCloseData {
closed_ch: closed_ch
};
- let close_data_ptr = ptr::addr_of(&close_data);
+ let close_data_ptr: *TcpSocketCloseData = &close_data;
let stream_handle_ptr = (*socket_data).stream_handle_ptr;
do iotask::interact(&(*socket_data).iotask) |loop_ptr| {
unsafe {
raw_write_data: ~[u8])
-> result::Result<(), TcpErrData> {
unsafe {
- let write_req_ptr = ptr::addr_of(&((*socket_data_ptr).write_req));
+ let write_req_ptr: *uv::ll::uv_write_t =
+ &(*socket_data_ptr).write_req;
let stream_handle_ptr =
(*socket_data_ptr).stream_handle_ptr;
- let write_buf_vec = ~[ uv::ll::buf_init(
- vec::raw::to_ptr(raw_write_data),
- vec::len(raw_write_data)) ];
- let write_buf_vec_ptr = ptr::addr_of(&write_buf_vec);
+ let write_buf_vec = ~[
+ uv::ll::buf_init(vec::raw::to_ptr(raw_write_data),
+ raw_write_data.len())
+ ];
+ let write_buf_vec_ptr: *~[uv::ll::uv_buf_t] = &write_buf_vec;
let (result_po, result_ch) = stream::<TcpWriteResult>();
let result_ch = SharedChan::new(result_ch);
let write_data = WriteReqData {
result_ch: result_ch
};
- let write_data_ptr = ptr::addr_of(&write_data);
+ let write_data_ptr: *WriteReqData = &write_data;
do iotask::interact(&(*socket_data_ptr).iotask) |loop_ptr| {
unsafe {
debug!("in interact cb for tcp::write %?",
use core::io;
use core::comm::{stream, SharedChan};
- use core::prelude::*;
use core::result;
use core::str;
use core::task;
use core::from_str::FromStr;
use core::io::{Reader, ReaderUtil};
use core::io;
-use core::prelude::*;
use core::hashmap::HashMap;
use core::str;
use core::to_bytes::IterBytes;
#[cfg(test)]
mod tests {
- use core::prelude::*;
use net_url::*;
priv static hi_mask: uint = (-1 as uint) << bits;
priv static lo_mask: uint = (-1 as uint) >> bits;
+ #[inline(always)]
priv fn get_hi(n: uint) -> BigDigit { (n >> bits) as BigDigit }
+ #[inline(always)]
priv fn get_lo(n: uint) -> BigDigit { (n & lo_mask) as BigDigit }
/// Split one machine sized unsigned integer into two BigDigits.
+ #[inline(always)]
pub fn from_uint(n: uint) -> (BigDigit, BigDigit) {
(get_hi(n), get_lo(n))
}
/// Join two BigDigits into one machine sized unsigned integer
+ #[inline(always)]
pub fn to_uint(hi: BigDigit, lo: BigDigit) -> uint {
(lo as uint) | ((hi as uint) << bits)
}
}
impl Eq for BigUint {
+ #[inline(always)]
fn eq(&self, other: &BigUint) -> bool { self.equals(other) }
+ #[inline(always)]
fn ne(&self, other: &BigUint) -> bool { !self.equals(other) }
}
impl TotalEq for BigUint {
+ #[inline(always)]
fn equals(&self, other: &BigUint) -> bool {
match self.cmp(other) { Equal => true, _ => false }
}
}
impl Ord for BigUint {
+ #[inline(always)]
fn lt(&self, other: &BigUint) -> bool {
match self.cmp(other) { Less => true, _ => false}
}
+ #[inline(always)]
fn le(&self, other: &BigUint) -> bool {
match self.cmp(other) { Less | Equal => true, _ => false }
}
+ #[inline(always)]
fn ge(&self, other: &BigUint) -> bool {
match self.cmp(other) { Greater | Equal => true, _ => false }
}
+ #[inline(always)]
fn gt(&self, other: &BigUint) -> bool {
match self.cmp(other) { Greater => true, _ => false }
}
}
impl TotalOrd for BigUint {
+ #[inline(always)]
fn cmp(&self, other: &BigUint) -> Ordering {
let s_len = self.data.len(), o_len = other.data.len();
if s_len < o_len { return Less; }
}
impl ToStr for BigUint {
+ #[inline(always)]
fn to_str(&self) -> ~str { self.to_str_radix(10) }
}
impl from_str::FromStr for BigUint {
+ #[inline(always)]
fn from_str(s: &str) -> Option<BigUint> {
FromStrRadix::from_str_radix(s, 10)
}
}
impl Shl<uint, BigUint> for BigUint {
+ #[inline(always)]
fn shl(&self, rhs: &uint) -> BigUint {
let n_unit = *rhs / BigDigit::bits;
let n_bits = *rhs % BigDigit::bits;
}
impl Shr<uint, BigUint> for BigUint {
+ #[inline(always)]
fn shr(&self, rhs: &uint) -> BigUint {
let n_unit = *rhs / BigDigit::bits;
let n_bits = *rhs % BigDigit::bits;
}
impl Zero for BigUint {
+ #[inline(always)]
fn zero() -> BigUint { BigUint::new(~[]) }
+
+ #[inline(always)]
+ fn is_zero(&self) -> bool { self.data.is_empty() }
}
impl One for BigUint {
- pub fn one() -> BigUint { BigUint::new(~[1]) }
+ #[inline(always)]
+ fn one() -> BigUint { BigUint::new(~[1]) }
}
impl Unsigned for BigUint {}
impl Add<BigUint, BigUint> for BigUint {
+ #[inline(always)]
fn add(&self, other: &BigUint) -> BigUint {
let new_len = uint::max(self.data.len(), other.data.len());
}
impl Sub<BigUint, BigUint> for BigUint {
+ #[inline(always)]
fn sub(&self, other: &BigUint) -> BigUint {
let new_len = uint::max(self.data.len(), other.data.len());
return ll + mm.shl_unit(half_len) + hh.shl_unit(half_len * 2);
+ #[inline(always)]
fn mul_digit(a: &BigUint, n: BigDigit) -> BigUint {
if n == 0 { return Zero::zero(); }
if n == 1 { return copy *a; }
return BigUint::new(prod + [carry]);
}
+ #[inline(always)]
fn cut_at(a: &BigUint, n: uint) -> (BigUint, BigUint) {
let mid = uint::min(a.data.len(), n);
return (BigUint::from_slice(vec::slice(a.data, mid,
BigUint::from_slice(vec::slice(a.data, 0, mid)));
}
+ #[inline(always)]
fn sub_sign(a: BigUint, b: BigUint) -> (Ordering, BigUint) {
match a.cmp(&b) {
Less => (Less, b - a),
}
impl Quot<BigUint, BigUint> for BigUint {
+ #[inline(always)]
fn quot(&self, other: &BigUint) -> BigUint {
let (q, _) = self.quot_rem(other);
return q;
}
impl Rem<BigUint, BigUint> for BigUint {
+ #[inline(always)]
fn rem(&self, other: &BigUint) -> BigUint {
let (_, r) = self.quot_rem(other);
return r;
}
impl Neg<BigUint> for BigUint {
+ #[inline(always)]
fn neg(&self) -> BigUint { fail!() }
}
+impl Integer for BigUint {
+ #[inline(always)]
+ fn div(&self, other: &BigUint) -> BigUint {
+ let (d, _) = self.div_mod(other);
+ return d;
+ }
+
+ #[inline(always)]
+ fn modulo(&self, other: &BigUint) -> BigUint {
+ let (_, m) = self.div_mod(other);
+ return m;
+ }
+
+ #[inline(always)]
+ fn div_mod(&self, other: &BigUint) -> (BigUint, BigUint) {
+ if other.is_zero() { fail!() }
+ if self.is_zero() { return (Zero::zero(), Zero::zero()); }
+ if *other == One::one() { return (copy *self, Zero::zero()); }
+
+ match self.cmp(other) {
+ Less => return (Zero::zero(), copy *self),
+ Equal => return (One::one(), Zero::zero()),
+ Greater => {} // Do nothing
+ }
+
+ let mut shift = 0;
+ let mut n = *other.data.last();
+ while n < (1 << BigDigit::bits - 2) {
+ n <<= 1;
+ shift += 1;
+ }
+ assert!(shift < BigDigit::bits);
+ let (d, m) = div_mod_inner(self << shift, other << shift);
+ return (d, m >> shift);
+
+ #[inline(always)]
+ fn div_mod_inner(a: BigUint, b: BigUint) -> (BigUint, BigUint) {
+ let mut m = a;
+ let mut d = Zero::zero::<BigUint>();
+ let mut n = 1;
+ while m >= b {
+ let mut (d0, d_unit, b_unit) = div_estimate(&m, &b, n);
+ let mut prod = b * d0;
+ while prod > m {
+ d0 -= d_unit;
+ prod -= b_unit;
+ }
+ if d0.is_zero() {
+ n = 2;
+ loop;
+ }
+ n = 1;
+ d += d0;
+ m -= prod;
+ }
+ return (d, m);
+ }
+
+ #[inline(always)]
+ fn div_estimate(a: &BigUint, b: &BigUint, n: uint)
+ -> (BigUint, BigUint, BigUint) {
+ if a.data.len() < n {
+ return (Zero::zero(), Zero::zero(), copy *a);
+ }
+
+ let an = vec::slice(a.data, a.data.len() - n, a.data.len());
+ let bn = *b.data.last();
+ let mut d = ~[];
+ let mut carry = 0;
+ for an.each_reverse |elt| {
+ let ai = BigDigit::to_uint(carry, *elt);
+ let di = ai / (bn as uint);
+ assert!(di < BigDigit::base);
+ carry = (ai % (bn as uint)) as BigDigit;
+ d = ~[di as BigDigit] + d;
+ }
+
+ let shift = (a.data.len() - an.len()) - (b.data.len() - 1);
+ if shift == 0 {
+ return (BigUint::new(d), One::one(), copy *b);
+ }
+ return (BigUint::from_slice(d).shl_unit(shift),
+ One::one::<BigUint>().shl_unit(shift),
+ b.shl_unit(shift));
+ }
+ }
+
+ #[inline(always)]
+ fn quot_rem(&self, other: &BigUint) -> (BigUint, BigUint) {
+ self.div_mod(other)
+ }
+
+ /**
+ * Calculates the Greatest Common Divisor (GCD) of the number and `other`
+ *
+ * The result is always positive
+ */
+ #[inline(always)]
+ fn gcd(&self, other: &BigUint) -> BigUint {
+ // Use Euclid's algorithm
+ let mut m = *self, n = *other;
+ while !m.is_zero() {
+ let temp = m;
+ m = n % temp;
+ n = temp;
+ }
+ return n;
+ }
+
+ /**
+ * Calculates the Lowest Common Multiple (LCM) of the number and `other`
+ */
+ #[inline(always)]
+ fn lcm(&self, other: &BigUint) -> BigUint { ((*self * *other) / self.gcd(other)) }
+
+ /// Returns `true` if the number can be divided by `other` without leaving a remainder
+ #[inline(always)]
+ fn is_multiple_of(&self, other: &BigUint) -> bool { (*self % *other).is_zero() }
+
+ /// Returns `true` if the number is divisible by `2`
+ #[inline(always)]
+ fn is_even(&self) -> bool {
+ // Considering only the last digit.
+ if self.data.is_empty() {
+ true
+ } else {
+ self.data.last().is_even()
+ }
+ }
+
+ /// Returns `true` if the number is not divisible by `2`
+ #[inline(always)]
+ fn is_odd(&self) -> bool { !self.is_even() }
+}
+
impl IntConvertible for BigUint {
+ #[inline(always)]
fn to_int(&self) -> int {
uint::min(self.to_uint(), int::max_value as uint) as int
}
+ #[inline(always)]
fn from_int(n: int) -> BigUint {
if (n < 0) { Zero::zero() } else { BigUint::from_uint(n as uint) }
}
}
impl ToStrRadix for BigUint {
+ #[inline(always)]
fn to_str_radix(&self, radix: uint) -> ~str {
assert!(1 < radix && radix <= 16);
let (base, max_len) = get_radix_base(radix);
}
return fill_concat(convert_base(copy *self, base), radix, max_len);
+ #[inline(always)]
fn convert_base(n: BigUint, base: uint) -> ~[BigDigit] {
let divider = BigUint::from_uint(base);
let mut result = ~[];
result += [m0.to_uint() as BigDigit];
m = d;
}
- if m.is_not_zero() {
+ if !m.is_zero() {
result += [m.to_uint() as BigDigit];
}
return result;
}
+ #[inline(always)]
fn fill_concat(v: &[BigDigit], radix: uint, l: uint) -> ~str {
if v.is_empty() { return ~"0" }
let s = str::concat(vec::reversed(v).map(|n| {
impl FromStrRadix for BigUint {
/// Creates and initializes an BigUint.
+ #[inline(always)]
pub fn from_str_radix(s: &str, radix: uint)
-> Option<BigUint> {
BigUint::parse_bytes(str::to_bytes(s), radix)
}
}
-pub impl BigUint {
+impl BigUint {
/// Creates and initializes an BigUint.
+ #[inline(always)]
pub fn new(v: ~[BigDigit]) -> BigUint {
// omit trailing zeros
let new_len = v.rposition(|n| *n != 0).map_default(0, |p| *p + 1);
}
/// Creates and initializes an BigUint.
+ #[inline(always)]
pub fn from_uint(n: uint) -> BigUint {
match BigDigit::from_uint(n) {
(0, 0) => Zero::zero(),
}
/// Creates and initializes an BigUint.
+ #[inline(always)]
pub fn from_slice(slice: &[BigDigit]) -> BigUint {
return BigUint::new(vec::from_slice(slice));
}
/// Creates and initializes an BigUint.
+ #[inline(always)]
pub fn parse_bytes(buf: &[u8], radix: uint)
-> Option<BigUint> {
let (base, unit_len) = get_radix_base(radix);
}
}
- fn abs(&self) -> BigUint { copy *self }
-
- fn div(&self, other: &BigUint) -> BigUint {
- let (d, _) = self.div_mod(other);
- return d;
- }
- fn modulo(&self, other: &BigUint) -> BigUint {
- let (_, m) = self.div_mod(other);
- return m;
- }
-
- fn div_mod(&self, other: &BigUint) -> (BigUint, BigUint) {
- if other.is_zero() { fail!() }
- if self.is_zero() { return (Zero::zero(), Zero::zero()); }
- if *other == One::one() { return (copy *self, Zero::zero()); }
-
- match self.cmp(other) {
- Less => return (Zero::zero(), copy *self),
- Equal => return (One::one(), Zero::zero()),
- Greater => {} // Do nothing
- }
-
- let mut shift = 0;
- let mut n = *other.data.last();
- while n < (1 << BigDigit::bits - 2) {
- n <<= 1;
- shift += 1;
- }
- assert!(shift < BigDigit::bits);
- let (d, m) = div_mod_inner(self << shift, other << shift);
- return (d, m >> shift);
-
- fn div_mod_inner(a: BigUint, b: BigUint) -> (BigUint, BigUint) {
- let mut m = a;
- let mut d = Zero::zero::<BigUint>();
- let mut n = 1;
- while m >= b {
- let mut (d0, d_unit, b_unit) = div_estimate(&m, &b, n);
- let mut prod = b * d0;
- while prod > m {
- d0 -= d_unit;
- prod -= b_unit;
- }
- if d0.is_zero() {
- n = 2;
- loop;
- }
- n = 1;
- d += d0;
- m -= prod;
- }
- return (d, m);
- }
-
- fn div_estimate(a: &BigUint, b: &BigUint, n: uint)
- -> (BigUint, BigUint, BigUint) {
- if a.data.len() < n {
- return (Zero::zero(), Zero::zero(), copy *a);
- }
-
- let an = vec::slice(a.data, a.data.len() - n, a.data.len());
- let bn = *b.data.last();
- let mut d = ~[];
- let mut carry = 0;
- for an.each_reverse |elt| {
- let ai = BigDigit::to_uint(carry, *elt);
- let di = ai / (bn as uint);
- assert!(di < BigDigit::base);
- carry = (ai % (bn as uint)) as BigDigit;
- d = ~[di as BigDigit] + d;
- }
-
- let shift = (a.data.len() - an.len()) - (b.data.len() - 1);
- if shift == 0 {
- return (BigUint::new(d), One::one(), copy *b);
- }
- return (BigUint::from_slice(d).shl_unit(shift),
- One::one::<BigUint>().shl_unit(shift),
- b.shl_unit(shift));
- }
- }
-
- fn quot_rem(&self, other: &BigUint) -> (BigUint, BigUint) {
- self.div_mod(other)
- }
-
- fn is_zero(&self) -> bool { self.data.is_empty() }
-
- fn is_not_zero(&self) -> bool { !self.data.is_empty() }
-
- fn to_uint(&self) -> uint {
+ #[inline(always)]
+ pub fn to_uint(&self) -> uint {
match self.data.len() {
0 => 0,
1 => self.data[0] as uint,
}
}
+ #[inline(always)]
priv fn shl_unit(self, n_unit: uint) -> BigUint {
if n_unit == 0 || self.is_zero() { return self; }
return BigUint::new(vec::from_elem(n_unit, 0) + self.data);
}
+ #[inline(always)]
priv fn shl_bits(self, n_bits: uint) -> BigUint {
if n_bits == 0 || self.is_zero() { return self; }
return BigUint::new(shifted + [carry]);
}
+ #[inline(always)]
priv fn shr_unit(self, n_unit: uint) -> BigUint {
if n_unit == 0 { return self; }
if self.data.len() < n_unit { return Zero::zero(); }
);
}
+ #[inline(always)]
priv fn shr_bits(self, n_bits: uint) -> BigUint {
if n_bits == 0 || self.data.is_empty() { return self; }
}
#[cfg(target_arch = "x86_64")]
+#[inline(always)]
priv fn get_radix_base(radix: uint) -> (uint, uint) {
assert!(1 < radix && radix <= 16);
match radix {
#[cfg(target_arch = "arm")]
#[cfg(target_arch = "x86")]
#[cfg(target_arch = "mips")]
+#[inline(always)]
priv fn get_radix_base(radix: uint) -> (uint, uint) {
assert!(1 < radix && radix <= 16);
match radix {
pub enum Sign { Minus, Zero, Plus }
impl Ord for Sign {
+ #[inline(always)]
fn lt(&self, other: &Sign) -> bool {
match self.cmp(other) { Less => true, _ => false}
}
+ #[inline(always)]
fn le(&self, other: &Sign) -> bool {
match self.cmp(other) { Less | Equal => true, _ => false }
}
+ #[inline(always)]
fn ge(&self, other: &Sign) -> bool {
match self.cmp(other) { Greater | Equal => true, _ => false }
}
+ #[inline(always)]
fn gt(&self, other: &Sign) -> bool {
match self.cmp(other) { Greater => true, _ => false }
}
}
impl TotalOrd for Sign {
+ #[inline(always)]
fn cmp(&self, other: &Sign) -> Ordering {
match (*self, *other) {
(Minus, Minus) | (Zero, Zero) | (Plus, Plus) => Equal,
impl Neg<Sign> for Sign {
/// Negate Sign value.
+ #[inline(always)]
fn neg(&self) -> Sign {
match *self {
Minus => Plus,
}
impl Eq for BigInt {
+ #[inline(always)]
fn eq(&self, other: &BigInt) -> bool { self.equals(other) }
+ #[inline(always)]
fn ne(&self, other: &BigInt) -> bool { !self.equals(other) }
}
impl TotalEq for BigInt {
+ #[inline(always)]
fn equals(&self, other: &BigInt) -> bool {
match self.cmp(other) { Equal => true, _ => false }
}
}
impl Ord for BigInt {
+ #[inline(always)]
fn lt(&self, other: &BigInt) -> bool {
match self.cmp(other) { Less => true, _ => false}
}
+ #[inline(always)]
fn le(&self, other: &BigInt) -> bool {
match self.cmp(other) { Less | Equal => true, _ => false }
}
+ #[inline(always)]
fn ge(&self, other: &BigInt) -> bool {
match self.cmp(other) { Greater | Equal => true, _ => false }
}
+ #[inline(always)]
fn gt(&self, other: &BigInt) -> bool {
match self.cmp(other) { Greater => true, _ => false }
}
}
impl TotalOrd for BigInt {
+ #[inline(always)]
fn cmp(&self, other: &BigInt) -> Ordering {
let scmp = self.sign.cmp(&other.sign);
if scmp != Equal { return scmp; }
}
impl ToStr for BigInt {
+ #[inline(always)]
fn to_str(&self) -> ~str { self.to_str_radix(10) }
}
impl from_str::FromStr for BigInt {
+ #[inline(always)]
fn from_str(s: &str) -> Option<BigInt> {
FromStrRadix::from_str_radix(s, 10)
}
}
impl Shl<uint, BigInt> for BigInt {
+ #[inline(always)]
fn shl(&self, rhs: &uint) -> BigInt {
BigInt::from_biguint(self.sign, self.data << *rhs)
}
}
impl Shr<uint, BigInt> for BigInt {
+ #[inline(always)]
fn shr(&self, rhs: &uint) -> BigInt {
BigInt::from_biguint(self.sign, self.data >> *rhs)
}
}
impl Zero for BigInt {
- pub fn zero() -> BigInt {
+ #[inline(always)]
+ fn zero() -> BigInt {
BigInt::from_biguint(Zero, Zero::zero())
}
+
+ #[inline(always)]
+ fn is_zero(&self) -> bool { self.sign == Zero }
}
impl One for BigInt {
- pub fn one() -> BigInt {
+ #[inline(always)]
+ fn one() -> BigInt {
BigInt::from_biguint(Plus, One::one())
}
}
impl Signed for BigInt {
+ #[inline(always)]
fn abs(&self) -> BigInt {
match self.sign {
Plus | Zero => copy *self,
}
}
+ #[inline(always)]
fn signum(&self) -> BigInt {
match self.sign {
Plus => BigInt::from_biguint(Plus, One::one()),
}
}
+ #[inline(always)]
fn is_positive(&self) -> bool { self.sign == Plus }
+ #[inline(always)]
fn is_negative(&self) -> bool { self.sign == Minus }
}
impl Add<BigInt, BigInt> for BigInt {
+ #[inline(always)]
fn add(&self, other: &BigInt) -> BigInt {
match (self.sign, other.sign) {
(Zero, _) => copy *other,
}
impl Sub<BigInt, BigInt> for BigInt {
+ #[inline(always)]
fn sub(&self, other: &BigInt) -> BigInt {
match (self.sign, other.sign) {
(Zero, _) => -other,
}
impl Mul<BigInt, BigInt> for BigInt {
+ #[inline(always)]
fn mul(&self, other: &BigInt) -> BigInt {
match (self.sign, other.sign) {
(Zero, _) | (_, Zero) => Zero::zero(),
}
impl Quot<BigInt, BigInt> for BigInt {
+ #[inline(always)]
fn quot(&self, other: &BigInt) -> BigInt {
let (q, _) = self.quot_rem(other);
return q;
}
impl Rem<BigInt, BigInt> for BigInt {
+ #[inline(always)]
fn rem(&self, other: &BigInt) -> BigInt {
let (_, r) = self.quot_rem(other);
return r;
}
impl Neg<BigInt> for BigInt {
+ #[inline(always)]
fn neg(&self) -> BigInt {
BigInt::from_biguint(self.sign.neg(), copy self.data)
}
}
+impl Integer for BigInt {
+ #[inline(always)]
+ fn div(&self, other: &BigInt) -> BigInt {
+ let (d, _) = self.div_mod(other);
+ return d;
+ }
+
+ #[inline(always)]
+ fn modulo(&self, other: &BigInt) -> BigInt {
+ let (_, m) = self.div_mod(other);
+ return m;
+ }
+
+ #[inline(always)]
+ fn div_mod(&self, other: &BigInt) -> (BigInt, BigInt) {
+ // m.sign == other.sign
+ let (d_ui, m_ui) = self.data.quot_rem(&other.data);
+ let d = BigInt::from_biguint(Plus, d_ui),
+ m = BigInt::from_biguint(Plus, m_ui);
+ match (self.sign, other.sign) {
+ (_, Zero) => fail!(),
+ (Plus, Plus) | (Zero, Plus) => (d, m),
+ (Plus, Minus) | (Zero, Minus) => if m.is_zero() {
+ (-d, Zero::zero())
+ } else {
+ (-d - One::one(), m + *other)
+ },
+ (Minus, Plus) => if m.is_zero() {
+ (-d, Zero::zero())
+ } else {
+ (-d - One::one(), other - m)
+ },
+ (Minus, Minus) => (d, -m)
+ }
+ }
+
+ #[inline(always)]
+ fn quot_rem(&self, other: &BigInt) -> (BigInt, BigInt) {
+ // r.sign == self.sign
+ let (q_ui, r_ui) = self.data.div_mod(&other.data);
+ let q = BigInt::from_biguint(Plus, q_ui);
+ let r = BigInt::from_biguint(Plus, r_ui);
+ match (self.sign, other.sign) {
+ (_, Zero) => fail!(),
+ (Plus, Plus) | (Zero, Plus) => ( q, r),
+ (Plus, Minus) | (Zero, Minus) => (-q, r),
+ (Minus, Plus) => (-q, -r),
+ (Minus, Minus) => ( q, -r)
+ }
+ }
+
+ /**
+ * Calculates the Greatest Common Divisor (GCD) of the number and `other`
+ *
+ * The result is always positive
+ */
+ #[inline(always)]
+ fn gcd(&self, other: &BigInt) -> BigInt {
+ BigInt::from_biguint(Plus, self.data.gcd(&other.data))
+ }
+
+ /**
+ * Calculates the Lowest Common Multiple (LCM) of the number and `other`
+ */
+ #[inline(always)]
+ fn lcm(&self, other: &BigInt) -> BigInt {
+ BigInt::from_biguint(Plus, self.data.lcm(&other.data))
+ }
+
+ /// Returns `true` if the number can be divided by `other` without leaving a remainder
+ #[inline(always)]
+ fn is_multiple_of(&self, other: &BigInt) -> bool { self.data.is_multiple_of(&other.data) }
+
+ /// Returns `true` if the number is divisible by `2`
+ #[inline(always)]
+ fn is_even(&self) -> bool { self.data.is_even() }
+
+ /// Returns `true` if the number is not divisible by `2`
+ #[inline(always)]
+ fn is_odd(&self) -> bool { self.data.is_odd() }
+}
+
impl IntConvertible for BigInt {
+ #[inline(always)]
fn to_int(&self) -> int {
match self.sign {
Plus => uint::min(self.to_uint(), int::max_value as uint) as int,
}
}
+ #[inline(always)]
fn from_int(n: int) -> BigInt {
if n > 0 {
return BigInt::from_biguint(Plus, BigUint::from_uint(n as uint));
}
impl ToStrRadix for BigInt {
+ #[inline(always)]
fn to_str_radix(&self, radix: uint) -> ~str {
match self.sign {
Plus => self.data.to_str_radix(radix),
impl FromStrRadix for BigInt {
/// Creates and initializes an BigInt.
- pub fn from_str_radix(s: &str, radix: uint)
+ #[inline(always)]
+ fn from_str_radix(s: &str, radix: uint)
-> Option<BigInt> {
BigInt::parse_bytes(str::to_bytes(s), radix)
}
pub impl BigInt {
/// Creates and initializes an BigInt.
+ #[inline(always)]
pub fn new(sign: Sign, v: ~[BigDigit]) -> BigInt {
BigInt::from_biguint(sign, BigUint::new(v))
}
/// Creates and initializes an BigInt.
+ #[inline(always)]
pub fn from_biguint(sign: Sign, data: BigUint) -> BigInt {
if sign == Zero || data.is_zero() {
return BigInt { sign: Zero, data: Zero::zero() };
}
/// Creates and initializes an BigInt.
+ #[inline(always)]
pub fn from_uint(n: uint) -> BigInt {
if n == 0 { return Zero::zero(); }
return BigInt::from_biguint(Plus, BigUint::from_uint(n));
}
/// Creates and initializes an BigInt.
+ #[inline(always)]
pub fn from_slice(sign: Sign, slice: &[BigDigit]) -> BigInt {
BigInt::from_biguint(sign, BigUint::from_slice(slice))
}
/// Creates and initializes an BigInt.
+ #[inline(always)]
pub fn parse_bytes(buf: &[u8], radix: uint)
-> Option<BigInt> {
if buf.is_empty() { return None; }
.map(|bu| BigInt::from_biguint(sign, *bu));
}
- fn abs(&self) -> BigInt {
- BigInt::from_biguint(Plus, copy self.data)
- }
-
- fn div(&self, other: &BigInt) -> BigInt {
- let (d, _) = self.div_mod(other);
- return d;
- }
- fn modulo(&self, other: &BigInt) -> BigInt {
- let (_, m) = self.div_mod(other);
- return m;
- }
-
- fn div_mod(&self, other: &BigInt) -> (BigInt, BigInt) {
- // m.sign == other.sign
- let (d_ui, m_ui) = self.data.quot_rem(&other.data);
- let d = BigInt::from_biguint(Plus, d_ui),
- m = BigInt::from_biguint(Plus, m_ui);
- match (self.sign, other.sign) {
- (_, Zero) => fail!(),
- (Plus, Plus) | (Zero, Plus) => (d, m),
- (Plus, Minus) | (Zero, Minus) => if m.is_zero() {
- (-d, Zero::zero())
- } else {
- (-d - One::one(), m + *other)
- },
- (Minus, Plus) => if m.is_zero() {
- (-d, Zero::zero())
- } else {
- (-d - One::one(), other - m)
- },
- (Minus, Minus) => (d, -m)
- }
- }
-
- fn quot_rem(&self, other: &BigInt) -> (BigInt, BigInt) {
- // r.sign == self.sign
- let (q_ui, r_ui) = self.data.div_mod(&other.data);
- let q = BigInt::from_biguint(Plus, q_ui);
- let r = BigInt::from_biguint(Plus, r_ui);
- match (self.sign, other.sign) {
- (_, Zero) => fail!(),
- (Plus, Plus) | (Zero, Plus) => ( q, r),
- (Plus, Minus) | (Zero, Minus) => (-q, r),
- (Minus, Plus) => (-q, -r),
- (Minus, Minus) => ( q, -r)
- }
- }
-
- fn is_zero(&self) -> bool { self.sign == Zero }
-
- fn is_not_zero(&self) -> bool { self.sign != Zero }
-
+ #[inline(always)]
fn to_uint(&self) -> uint {
match self.sign {
Plus => self.data.to_uint(),
let b = BigUint::from_slice(bVec);
let c = BigUint::from_slice(cVec);
- if a.is_not_zero() {
+ if !a.is_zero() {
assert!(c.quot_rem(&a) == (b, Zero::zero()));
}
- if b.is_not_zero() {
+ if !b.is_zero() {
assert!(c.quot_rem(&b) == (a, Zero::zero()));
}
}
let c = BigUint::from_slice(cVec);
let d = BigUint::from_slice(dVec);
- if b.is_not_zero() { assert!(a.quot_rem(&b) == (c, d)); }
+ if !b.is_zero() { assert!(a.quot_rem(&b) == (c, d)); }
}
}
+ #[test]
+ fn test_gcd() {
+ fn check(a: uint, b: uint, c: uint) {
+ let big_a = BigUint::from_uint(a);
+ let big_b = BigUint::from_uint(b);
+ let big_c = BigUint::from_uint(c);
+
+ assert_eq!(big_a.gcd(&big_b), big_c);
+ }
+
+ check(10, 2, 2);
+ check(10, 3, 1);
+ check(0, 3, 3);
+ check(3, 3, 3);
+ check(56, 42, 14);
+ }
+
+ #[test]
+ fn test_lcm() {
+ fn check(a: uint, b: uint, c: uint) {
+ let big_a = BigUint::from_uint(a);
+ let big_b = BigUint::from_uint(b);
+ let big_c = BigUint::from_uint(c);
+
+ assert_eq!(big_a.lcm(&big_b), big_c);
+ }
+
+ check(1, 0, 0);
+ check(0, 1, 0);
+ check(1, 1, 1);
+ check(8, 9, 72);
+ check(11, 5, 55);
+ check(99, 17, 1683);
+ }
+
fn to_str_pairs() -> ~[ (BigUint, ~[(uint, ~str)]) ] {
let bits = BigDigit::bits;
~[( Zero::zero(), ~[
fn test_div_mod() {
fn check_sub(a: &BigInt, b: &BigInt, ans_d: &BigInt, ans_m: &BigInt) {
let (d, m) = a.div_mod(b);
- if m.is_not_zero() {
+ if !m.is_zero() {
assert!(m.sign == b.sign);
}
assert!(m.abs() <= b.abs());
let b = BigInt::from_slice(Plus, bVec);
let c = BigInt::from_slice(Plus, cVec);
- if a.is_not_zero() { check(&c, &a, &b, &Zero::zero()); }
- if b.is_not_zero() { check(&c, &b, &a, &Zero::zero()); }
+ if !a.is_zero() { check(&c, &a, &b, &Zero::zero()); }
+ if !b.is_zero() { check(&c, &b, &a, &Zero::zero()); }
}
for quot_rem_quadruples.each |elm| {
let c = BigInt::from_slice(Plus, cVec);
let d = BigInt::from_slice(Plus, dVec);
- if b.is_not_zero() {
+ if !b.is_zero() {
check(&a, &b, &c, &d);
}
}
fn test_quot_rem() {
fn check_sub(a: &BigInt, b: &BigInt, ans_q: &BigInt, ans_r: &BigInt) {
let (q, r) = a.quot_rem(b);
- if r.is_not_zero() {
+ if !r.is_zero() {
assert!(r.sign == a.sign);
}
assert!(r.abs() <= b.abs());
let b = BigInt::from_slice(Plus, bVec);
let c = BigInt::from_slice(Plus, cVec);
- if a.is_not_zero() { check(&c, &a, &b, &Zero::zero()); }
- if b.is_not_zero() { check(&c, &b, &a, &Zero::zero()); }
+ if !a.is_zero() { check(&c, &a, &b, &Zero::zero()); }
+ if !b.is_zero() { check(&c, &b, &a, &Zero::zero()); }
}
for quot_rem_quadruples.each |elm| {
let c = BigInt::from_slice(Plus, cVec);
let d = BigInt::from_slice(Plus, dVec);
- if b.is_not_zero() {
+ if !b.is_zero() {
check(&a, &b, &c, &d);
}
}
}
+ #[test]
+ fn test_gcd() {
+ fn check(a: int, b: int, c: int) {
+ let big_a: BigInt = IntConvertible::from_int(a);
+ let big_b: BigInt = IntConvertible::from_int(b);
+ let big_c: BigInt = IntConvertible::from_int(c);
+
+ assert_eq!(big_a.gcd(&big_b), big_c);
+ }
+
+ check(10, 2, 2);
+ check(10, 3, 1);
+ check(0, 3, 3);
+ check(3, 3, 3);
+ check(56, 42, 14);
+ check(3, -3, 3);
+ check(-6, 3, 3);
+ check(-4, -2, 2);
+ }
+
+ #[test]
+ fn test_lcm() {
+ fn check(a: int, b: int, c: int) {
+ let big_a: BigInt = IntConvertible::from_int(a);
+ let big_b: BigInt = IntConvertible::from_int(b);
+ let big_c: BigInt = IntConvertible::from_int(c);
+
+ assert_eq!(big_a.lcm(&big_b), big_c);
+ }
+
+ check(1, 0, 0);
+ check(0, 1, 0);
+ check(1, 1, 1);
+ check(-1, 1, 1);
+ check(1, -1, 1);
+ check(-1, -1, 1);
+ check(8, 9, 72);
+ check(11, 5, 55);
+ }
+
#[test]
fn test_to_str_radix() {
fn check(n: int, ans: &str) {
- assert!(ans == IntConvertible::from_int::<BigInt>(
- n).to_str_radix(10));
+ assert!(ans == IntConvertible::from_int::<BigInt>(n).to_str_radix(10));
}
check(10, "10");
check(1, "1");
//! Complex numbers.
use core::num::{Zero,One,ToStrRadix};
-use core::prelude::*;
// FIXME #1284: handle complex NaN & infinity etc. This
// probably doesn't map to C's _Complex correctly.
fn zero() -> Cmplx<T> {
Cmplx::new(Zero::zero(), Zero::zero())
}
+
+ #[inline]
+ fn is_zero(&self) -> bool {
+ *self == Zero::zero()
+ }
}
impl<T: Copy + Num> One for Cmplx<T> {
#[cfg(test)]
mod test {
- use core::prelude::*;
use super::*;
use core::num::{Zero,One};
use core::num::{Zero,One,ToStrRadix,FromStrRadix,Round};
use core::from_str::FromStr;
-use core::to_str::ToStr;
-use core::prelude::*;
-use core::cmp::TotalEq;
use super::bigint::BigInt;
/// Represents the ratio between 2 numbers.
fn zero() -> Ratio<T> {
Ratio::new_raw(Zero::zero(), One::one())
}
+
+ #[inline]
+ fn is_zero(&self) -> bool {
+ *self == Zero::zero()
+ }
}
impl<T: Copy + Num + Ord>
}
}
+impl<T: Copy + Num + Ord>
+ Num for Ratio<T> {}
+
/* Utils */
impl<T: Copy + Num + Ord>
Round for Ratio<T> {
- fn round(&self, mode: num::RoundMode) -> Ratio<T> {
- match mode {
- num::RoundUp => { self.ceil() }
- num::RoundDown => { self.floor()}
- num::RoundToZero => { Ratio::from_integer(self.numer / self.denom) }
- num::RoundFromZero => {
- if *self < Zero::zero() {
- Ratio::from_integer((self.numer - self.denom + One::one()) / self.denom)
- } else {
- Ratio::from_integer((self.numer + self.denom - One::one()) / self.denom)
- }
- }
- }
- }
fn floor(&self) -> Ratio<T> {
if *self < Zero::zero() {
Ratio::from_integer(self.numer / self.denom)
}
}
+
fn ceil(&self) -> Ratio<T> {
if *self < Zero::zero() {
Ratio::from_integer(self.numer / self.denom)
Ratio::from_integer((self.numer + self.denom - One::one()) / self.denom)
}
}
+
+ #[inline(always)]
+ fn round(&self) -> Ratio<T> {
+ if *self < Zero::zero() {
+ Ratio::from_integer((self.numer - self.denom + One::one()) / self.denom)
+ } else {
+ Ratio::from_integer((self.numer + self.denom - One::one()) / self.denom)
+ }
+ }
+
+ #[inline(always)]
+ fn trunc(&self) -> Ratio<T> {
+ Ratio::from_integer(self.numer / self.denom)
+ }
+
fn fract(&self) -> Ratio<T> {
Ratio::new_raw(self.numer % self.denom, self.denom)
}
}
+impl<T: Copy + Num + Ord> Fractional for Ratio<T> {
+ #[inline]
+ fn recip(&self) -> Ratio<T> {
+ Ratio::new_raw(self.denom, self.numer)
+ }
+}
/* String conversions */
impl<T: ToStr> ToStr for Ratio<T> {
#[cfg(test)]
mod test {
- use core::prelude::*;
use super::*;
use core::num::{Zero,One,FromStrRadix};
use core::from_str::FromStr;
fn test_round() {
assert_eq!(_1_2.ceil(), _1);
assert_eq!(_1_2.floor(), _0);
- assert_eq!(_1_2.round(num::RoundToZero), _0);
- assert_eq!(_1_2.round(num::RoundFromZero), _1);
+ assert_eq!(_1_2.round(), _1);
+ assert_eq!(_1_2.trunc(), _0);
assert_eq!(_neg1_2.ceil(), _0);
assert_eq!(_neg1_2.floor(), -_1);
- assert_eq!(_neg1_2.round(num::RoundToZero), _0);
- assert_eq!(_neg1_2.round(num::RoundFromZero), -_1);
+ assert_eq!(_neg1_2.round(), -_1);
+ assert_eq!(_neg1_2.trunc(), _0);
assert_eq!(_1.ceil(), _1);
assert_eq!(_1.floor(), _1);
- assert_eq!(_1.round(num::RoundToZero), _1);
- assert_eq!(_1.round(num::RoundFromZero), _1);
+ assert_eq!(_1.round(), _1);
+ assert_eq!(_1.trunc(), _1);
}
#[test]
assert_eq!(_3_2.fract(), _1_2);
}
+ #[test]
+ fn test_recip() {
+ assert_eq!(_1 * _1.recip(), _1);
+ assert_eq!(_2 * _2.recip(), _1);
+ assert_eq!(_1_2 * _1_2.recip(), _1);
+ assert_eq!(_3_2 * _3_2.recip(), _1);
+ assert_eq!(_neg1_2 * _neg1_2.recip(), _1);
+ }
+
#[test]
fn test_to_from_str() {
fn test(r: Rational, s: ~str) {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::cast;
-use core::prelude::*;
-use core::ptr;
-use core::sys;
-use core::uint;
-use core::vec;
-
use future_spawn = future::spawn;
-
/**
* The maximum number of tasks this module will spawn for a single
* operation.
//! A priority queue implemented with a binary heap
-use core::container::{Container, Mutable};
-use core::cmp::Ord;
-use core::iter::BaseIter;
-use core::prelude::*;
-use core::ptr::addr_of;
-use core::vec;
+use core::old_iter::BaseIter;
#[abi = "rust-intrinsic"]
extern "rust-intrinsic" mod rusti {
priv fn siftup(&mut self, start: uint, mut pos: uint) {
unsafe {
- let new = *addr_of(&self.data[pos]);
+ let new = *ptr::to_unsafe_ptr(&self.data[pos]);
while pos > start {
let parent = (pos - 1) >> 1;
priv fn siftdown_range(&mut self, mut pos: uint, end: uint) {
unsafe {
let start = pos;
- let new = *addr_of(&self.data[pos]);
+ let new = *ptr::to_unsafe_ptr(&self.data[pos]);
let mut child = 2 * pos + 1;
while child < end {
// state without mutexes.
use core::libc::{c_char, c_int};
-use core::prelude::*;
-use core::str;
-use core::task;
pub mod rustrt {
use core::libc::{c_char, c_int};
* * access to a character by index is logarithmic (linear in strings);
*/
-use core::option;
-use core::prelude::*;
-use core::str;
-use core::uint;
-use core::vec;
-
/// The type of ropes.
pub type Rope = node::Root;
match (rope) {
node::Empty => return rope,
node::Content(x) => match (node::bal(x)) {
- option::None => rope,
- option::Some(y) => node::Content(y)
+ None => rope,
+ Some(y) => node::Content(y)
}
}
}
pub mod leaf {
use rope::{Rope, node};
- use core::prelude::*;
pub fn start(rope: Rope) -> node::leaf_iterator::T {
match (rope) {
pub mod char {
use rope::{Rope, node};
- use core::prelude::*;
pub fn start(rope: Rope) -> node::char_iterator::T {
match (rope) {
pub mod node {
use rope::node;
- use core::cast;
- use core::char;
- use core::option;
- use core::prelude::*;
- use core::str;
- use core::uint;
- use core::vec;
-
/// Implementation of type `rope`
pub enum Root {
/// An empty rope
let mut it = leaf_iterator::start(node);
loop {
match leaf_iterator::next(&mut it) {
- option::None => break,
- option::Some(x) => {
+ None => break,
+ Some(x) => {
//FIXME (#2744): Replace with memcpy or something similar
let local_buf: ~[u8] = cast::transmute(*x.content);
let mut i = x.byte_offset;
*
* # Return value
*
- * * `option::None` if no transformation happened
- * * `option::Some(x)` otherwise, in which case `x` has the same contents
+ * * `None` if no transformation happened
+ * * `Some(x)` otherwise, in which case `x` has the same contents
* as `node` bot lower height and/or fragmentation.
*/
pub fn bal(node: @Node) -> Option<@Node> {
- if height(node) < hint_max_node_height { return option::None; }
+ if height(node) < hint_max_node_height { return None; }
//1. Gather all leaves as a forest
let mut forest = ~[];
let mut it = leaf_iterator::start(node);
loop {
match leaf_iterator::next(&mut it) {
- option::None => break,
- option::Some(x) => forest.push(@Leaf(x))
+ None => break,
+ Some(x) => forest.push(@Leaf(x))
}
}
//2. Rebuild tree from forest
let root = @*tree_from_forest_destructive(forest);
- return option::Some(root);
+ return Some(root);
}
while result == 0 {
match (char_iterator::next(&mut ita), char_iterator::next(&mut itb))
{
- (option::None, option::None) => break,
- (option::Some(chara), option::Some(charb)) => {
- result = char::cmp(chara, charb);
+ (None, None) => break,
+ (Some(chara), Some(charb)) => {
+ result = chara.cmp(&charb) as int;
}
- (option::Some(_), _) => {
+ (Some(_), _) => {
result = 1;
}
- (_, option::Some(_)) => {
+ (_, Some(_)) => {
result = -1;
}
}
pub mod leaf_iterator {
use rope::node::{Concat, Leaf, Node, height};
- use core::option;
- use core::prelude::*;
- use core::vec;
-
pub struct T {
stack: ~[@Node],
stackpos: int,
}
pub fn next(it: &mut T) -> Option<Leaf> {
- if it.stackpos < 0 { return option::None; }
+ if it.stackpos < 0 { return None; }
loop {
let current = it.stack[it.stackpos];
it.stackpos -= 1;
it.stackpos += 1;
it.stack[it.stackpos] = x.left;
}
- Leaf(x) => return option::Some(x)
+ Leaf(x) => return Some(x)
}
};
}
use rope::node::{Leaf, Node};
use rope::node::leaf_iterator;
- use core::option;
- use core::prelude::*;
- use core::str;
-
pub struct T {
leaf_iterator: leaf_iterator::T,
leaf: Option<Leaf>,
pub fn start(node: @Node) -> T {
T {
leaf_iterator: leaf_iterator::start(node),
- leaf: option::None,
+ leaf: None,
leaf_byte_pos: 0u,
}
}
pub fn empty() -> T {
T {
leaf_iterator: leaf_iterator::empty(),
- leaf: option::None,
+ leaf: None,
leaf_byte_pos: 0u,
}
}
pub fn next(it: &mut T) -> Option<char> {
loop {
match get_current_or_next_leaf(it) {
- option::None => return option::None,
- option::Some(_) => {
+ None => return None,
+ Some(_) => {
let next_char = get_next_char_in_leaf(it);
match next_char {
- option::None => loop,
- option::Some(_) => return next_char
+ None => loop,
+ Some(_) => return next_char
}
}
}
pub fn get_current_or_next_leaf(it: &mut T) -> Option<Leaf> {
match it.leaf {
- option::Some(_) => return it.leaf,
- option::None => {
+ Some(_) => return it.leaf,
+ None => {
let next = leaf_iterator::next(&mut it.leaf_iterator);
match next {
- option::None => return option::None,
- option::Some(_) => {
+ None => return None,
+ Some(_) => {
it.leaf = next;
it.leaf_byte_pos = 0u;
return next;
pub fn get_next_char_in_leaf(it: &mut T) -> Option<char> {
match copy it.leaf {
- option::None => return option::None,
- option::Some(aleaf) => {
+ None => return None,
+ Some(aleaf) => {
if it.leaf_byte_pos >= aleaf.byte_len {
//We are actually past the end of the leaf
- it.leaf = option::None;
- return option::None
+ it.leaf = None;
+ return None
} else {
let range =
str::char_range_at(*aleaf.content,
let ch = range.ch;
let next = range.next;
(*it).leaf_byte_pos = next - aleaf.byte_offset;
- return option::Some(ch)
+ return Some(ch)
}
}
}
#[cfg(test)]
mod tests {
use rope::*;
-
- use core::option;
- use core::str;
- use core::uint;
- use core::vec;
+ use core::prelude::*;
//Utility function, used for sanity check
fn rope_to_string(r: Rope) -> ~str {
let mut equal = true;
while equal {
match (node::char_iterator::next(&mut rope_iter)) {
- option::None => {
+ None => {
if string_iter < string_len {
equal = false;
} break; }
- option::Some(c) => {
+ Some(c) => {
let range = str::char_range_at(*sample, string_iter);
string_iter = range.next;
if range.ch != c { equal = false; break; }
let mut it = iterator::char::start(r);
loop {
match (node::char_iterator::next(&mut it)) {
- option::None => break,
- option::Some(_) => len += 1u
+ None => break,
+ Some(_) => len += 1u
}
}
#[forbid(non_camel_case_types)];
-use core::prelude::*;
use core::hashmap::{HashMap, HashSet};
use core::trie::{TrieMap, TrieSet};
use deque::Deque;
*/
use core::container::{Container, Mutable, Map, Set};
-use core::iter::{BaseIter};
+use core::old_iter::{BaseIter};
use core::option::{Some, None};
-use core::prelude::*;
pub struct SmallIntMap<T> {
priv v: ~[Option<T>],
#[cfg(test)]
mod tests {
use super::SmallIntMap;
- use core::prelude::*;
#[test]
fn test_find_mut() {
//! Sorting methods
use core::cmp::{Eq, Ord};
-use core::prelude::*;
use core::util;
use core::vec::len;
use core::vec;
#[cfg(test)]
mod tests {
- use core::prelude::*;
use sort::*;
#[cfg(test)]
mod test_tim_sort {
- use core::prelude::*;
use sort::tim_sort;
use core::rand::RngUtil;
#[cfg(test)]
mod big_tests {
- use core::prelude::*;
use sort::*;
use core::rand::RngUtil;
#[deny(non_camel_case_types)];
#[allow(deprecated_mutable_fields)];
-#[no_core];
-
-extern mod core(vers = "0.7-pre");
-use core::prelude::*;
-
pub mod uv_ll;
// General io and system-services modules
pub mod smallintmap;
pub mod sort;
pub mod dlist;
-#[cfg(stage1)]
-#[cfg(stage2)]
-#[cfg(stage3)]
+#[cfg(not(stage0))]
pub mod treemap;
// And ... other stuff
pub mod base64;
pub mod rl;
pub mod workcache;
-#[cfg(stage1)]
-#[cfg(stage2)]
-#[cfg(stage3)]
+#[cfg(not(stage0))]
#[path="num/bigint.rs"]
pub mod bigint;
-#[cfg(stage1)]
-#[cfg(stage2)]
-#[cfg(stage3)]
+#[cfg(not(stage0))]
#[path="num/rational.rs"]
pub mod rational;
-#[cfg(stage1)]
-#[cfg(stage2)]
-#[cfg(stage3)]
+#[cfg(not(stage0))]
#[path="num/complex.rs"]
pub mod complex;
pub mod stats;
* in std.
*/
-use core::prelude::*;
use core::unstable::{Exclusive, exclusive};
use core::ptr;
use core::task;
#[cfg(test)]
mod tests {
- use core::prelude::*;
use sync::*;
let m = ~Mutex();
let m2 = m.clone();
let mut sharedstate = ~0;
- let ptr = ptr::addr_of(&(*sharedstate));
- do task::spawn || {
- let sharedstate: &mut int =
- unsafe { cast::transmute(ptr) };
- access_shared(sharedstate, m2, 10);
- c.send(());
+ {
+ let ptr: *int = &*sharedstate;
+ do task::spawn || {
+ let sharedstate: &mut int =
+ unsafe { cast::transmute(ptr) };
+ access_shared(sharedstate, m2, 10);
+ c.send(());
+ }
}
- access_shared(sharedstate, m, 10);
- let _ = p.recv();
+ {
+ access_shared(sharedstate, m, 10);
+ let _ = p.recv();
- assert!(*sharedstate == 20);
+ assert!(*sharedstate == 20);
+ }
fn access_shared(sharedstate: &mut int, m: &Mutex, n: uint) {
for n.times {
let (p,c) = comm::stream();
let x2 = (*x).clone();
let mut sharedstate = ~0;
- let ptr = ptr::addr_of(&(*sharedstate));
- do task::spawn || {
- let sharedstate: &mut int =
- unsafe { cast::transmute(ptr) };
- access_shared(sharedstate, &x2, mode1, 10);
- c.send(());
+ {
+ let ptr: *int = &*sharedstate;
+ do task::spawn || {
+ let sharedstate: &mut int =
+ unsafe { cast::transmute(ptr) };
+ access_shared(sharedstate, &x2, mode1, 10);
+ c.send(());
+ }
}
- access_shared(sharedstate, x, mode2, 10);
- let _ = p.recv();
+ {
+ access_shared(sharedstate, x, mode2, 10);
+ let _ = p.recv();
- assert!(*sharedstate == 20);
+ assert!(*sharedstate == 20);
+ }
fn access_shared(sharedstate: &mut int, x: &RWlock, mode: RWlockMode,
n: uint) {
/// parallelism.
use core::comm::Chan;
-use core::prelude::*;
use core::task::SchedMode;
use core::task;
use core::vec;
//! Temporary files and directories
-use core::prelude::*;
use core::rand::RngUtil;
pub fn mkdtemp(tmpdir: &Path, suffix: &str) -> Option<Path> {
use core::to_str::ToStr;
use core::comm::{stream, SharedChan};
-use core::prelude::*;
pub mod rustrt {
use core::libc::size_t;
use time::precise_time_ns;
use test::{BenchHarness, BenchSamples};
use stats::Stats;
- use core::prelude::*;
use core::rand::RngUtil;
pub impl BenchHarness {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::cmp::{Eq, Ord};
-use core::int;
-use core::i32;
-use core::io::{Reader, ReaderUtil};
-use core::io;
-use core::prelude::*;
-use core::result::{Result, Ok, Err};
-use core::str;
-
static NSEC_PER_SEC: i32 = 1_000_000_000_i32;
pub mod rustrt {
use uv::iotask;
use uv::iotask::IoTask;
-use core::either;
use core::libc;
use core::libc::c_void;
use core::cast::transmute;
use core::comm::{stream, Chan, SharedChan, Port, select2i};
-use core::prelude::*;
-use core::ptr;
/**
* Wait for timeout period then send provided value over a channel
let (timer_done_po, timer_done_ch) = stream::<()>();
let timer_done_ch = SharedChan::new(timer_done_ch);
let timer = uv::ll::timer_t();
- let timer_ptr = ptr::addr_of(&timer);
+ let timer_ptr: *uv::ll::uv_timer_t = &timer;
do iotask::interact(iotask) |loop_ptr| {
unsafe {
let init_result = uv::ll::timer_init(loop_ptr, timer_ptr);
#[cfg(test)]
mod test {
- use core::prelude::*;
use timer::*;
use uv;
#[test]
fn test_gl_timer_sleep_stress1() {
let hl_loop = &uv::global_loop::get();
- for iter::repeat(50u) {
+ for old_iter::repeat(50u) {
sleep(hl_loop, 1u);
}
}
};
- for iter::repeat(repeat) {
+ for old_iter::repeat(repeat) {
let ch = ch.clone();
for spec.each |spec| {
do task::spawn {
use core::rand::*;
let rng = rng();
- for iter::repeat(times) {
+ for old_iter::repeat(times) {
sleep(&hl_loop_clone, rng.next() as uint % maxms);
}
ch.send(());
}
}
- for iter::repeat(repeat * spec.len()) {
+ for old_iter::repeat(repeat * spec.len()) {
po.recv()
}
}
let mut failures = 0;
let hl_loop = uv::global_loop::get();
- for iter::repeat(times as uint) {
+ for old_iter::repeat(times as uint) {
task::yield();
let expected = rand::rng().gen_str(16u);
let mut failures = 0;
let hl_loop = uv::global_loop::get();
- for iter::repeat(times as uint) {
+ for old_iter::repeat(times as uint) {
let expected = rand::rng().gen_str(16u);
let (test_po, test_ch) = stream::<~str>();
let hl_loop_clone = hl_loop.clone();
//! trees. The only requirement for the types is that the key implements
//! `TotalOrd`.
-use core::prelude::*;
use core::iterator::*;
// This is implemented as an AA tree, which is a simplified variation of
#[cfg(test)]
mod test_treemap {
- use core::prelude::*;
use core::iterator::*;
use super::*;
use core::rand::RngUtil;
#[cfg(test)]
mod test_set {
- use core::prelude::*;
use core::iterator::*;
use super::*;
use iotask = uv_iotask;
use uv_iotask::{IoTask, spawn_iotask};
-use core::clone::Clone;
use core::comm::Chan;
use core::option::{Some, None};
use core::task::task;
-use core::task;
use core::unstable::global::{global_data_clone_create, global_data_clone};
use core::unstable::weak_task::weaken_task;
#[cfg(test)]
mod test {
- use core::prelude::*;
use get_gl = uv_global_loop::get;
use uv::iotask;
use uv::ll;
use uv_iotask::IoTask;
- use core::iter;
+ use core::old_iter;
use core::libc;
use core::ptr;
use core::task;
debug!("EXIT_CH_PTR newly created exit_ch_ptr: %?",
exit_ch_ptr);
let timer_handle = ll::timer_t();
- let timer_ptr = ptr::addr_of(&timer_handle);
+ let timer_ptr: *ll::uv_timer_t = &timer_handle;
do iotask::interact(iotask) |loop_ptr| {
unsafe {
debug!(~"user code inside interact loop!!!");
let (exit_po, exit_ch) = stream::<()>();
let exit_ch = SharedChan::new(exit_ch);
let cycles = 5000u;
- for iter::repeat(cycles) {
+ for old_iter::repeat(cycles) {
let exit_ch_clone = exit_ch.clone();
task::spawn_sched(task::ManualThreads(1u), || {
let hl_loop = &get_gl();
exit_ch_clone.send(());
});
};
- for iter::repeat(cycles) {
+ for old_iter::repeat(cycles) {
exit_po.recv();
};
debug!(~"test_stress_gl_uv_global_loop_high_level_global_timer"+
use ll = uv_ll;
+use core::comm::{stream, Port, Chan, SharedChan};
use core::libc::c_void;
use core::libc;
-use core::comm::{stream, Port, Chan, SharedChan};
-use core::prelude::*;
-use core::ptr::addr_of;
-use core::task;
/// Used to abstract-away direct interaction with a libuv loop.
pub struct IoTask {
// set up the special async handle we'll use to allow multi-task
// communication with this loop
let async = ll::async_t();
- let async_handle = addr_of(&async);
+ let async_handle: *ll::uv_async_t = &async;
// associate the async handle with the loop
ll::async_init(loop_ptr, async_handle, wake_up_cb);
async_handle: async_handle,
msg_po: msg_po
};
- ll::set_data_for_uv_handle(async_handle, addr_of(&data));
+ ll::set_data_for_uv_handle(async_handle, &data);
// Send out a handle through which folks can talk to us
// while we dwell in the I/O loop
- let iotask = IoTask{
+ let iotask = IoTask {
async_handle: async_handle,
op_chan: SharedChan::new(msg_ch)
};
#[cfg(test)]
fn impl_uv_iotask_async(iotask: &IoTask) {
let async_handle = ll::async_t();
- let ah_ptr = ptr::addr_of(&async_handle);
+ let ah_ptr: *ll::uv_async_t = &async_handle;
let (exit_po, exit_ch) = stream::<()>();
let ah_data = AhData {
iotask: iotask.clone(),
// impl_uv_hl_async() runs have been called, at least.
let (work_exit_po, work_exit_ch) = stream::<()>();
let work_exit_ch = SharedChan::new(work_exit_ch);
- for iter::repeat(7u) {
+ for old_iter::repeat(7u) {
let iotask_clone = iotask.clone();
let work_exit_ch_clone = work_exit_ch.clone();
do task::spawn_sched(task::ManualThreads(1u)) {
work_exit_ch_clone.send(());
};
};
- for iter::repeat(7u) {
+ for old_iter::repeat(7u) {
debug!("waiting");
work_exit_po.recv();
};
use core::libc::size_t;
use core::libc::c_void;
-use core::prelude::*;
use core::ptr::to_unsafe_ptr;
pub type uv_handle_t = c_void;
}
pub unsafe fn buf_init(input: *u8, len: uint) -> uv_buf_t {
let out_buf = uv_buf_t { base: ptr::null(), len: 0 as libc::size_t };
- let out_buf_ptr = ptr::addr_of(&out_buf);
+ let out_buf_ptr: *uv_buf_t = &out_buf;
rustrt::rust_uv_buf_init(out_buf_ptr, input, len as size_t);
return out_buf;
}
-pub unsafe fn ip4_addr(ip: &str, port: int)
--> sockaddr_in {
+pub unsafe fn ip4_addr(ip: &str, port: int) -> sockaddr_in {
do str::as_c_str(ip) |ip_buf| {
rustrt::rust_uv_ip4_addr(ip_buf as *u8,
port as libc::c_int)
}
}
-pub unsafe fn ip6_addr(ip: &str, port: int)
--> sockaddr_in6 {
+pub unsafe fn ip6_addr(ip: &str, port: int) -> sockaddr_in6 {
do str::as_c_str(ip) |ip_buf| {
rustrt::rust_uv_ip6_addr(ip_buf as *u8,
port as libc::c_int)
pub unsafe fn get_last_err_info(uv_loop: *libc::c_void) -> ~str {
let err = last_error(uv_loop);
- let err_ptr = ptr::addr_of(&err);
+ let err_ptr: *uv_err_t = &err;
let err_name = str::raw::from_c_str(err_name(err_ptr));
let err_msg = str::raw::from_c_str(strerror(err_ptr));
return fmt!("LIBUV ERROR: name: %s msg: %s",
pub unsafe fn get_last_err_data(uv_loop: *libc::c_void) -> uv_err_data {
let err = last_error(uv_loop);
- let err_ptr = ptr::addr_of(&err);
+ let err_ptr: *uv_err_t = &err;
let err_name = str::raw::from_c_str(err_name(err_ptr));
let err_msg = str::raw::from_c_str(strerror(err_ptr));
uv_err_data { err_name: err_name, err_msg: err_msg }
#[cfg(test)]
mod test {
- use core::prelude::*;
use core::comm::{SharedChan, stream, GenericChan, GenericPort};
use super::*;
unsafe {
let test_loop = loop_new();
let tcp_handle = tcp_t();
- let tcp_handle_ptr = ptr::addr_of(&tcp_handle);
+ let tcp_handle_ptr: *uv_tcp_t = &tcp_handle;
let connect_handle = connect_t();
- let connect_req_ptr = ptr::addr_of(&connect_handle);
+ let connect_req_ptr: *uv_connect_t = &connect_handle;
// this is the persistent payload of data that we
// need to pass around to get this example to work.
// this is the enclosing record, we'll pass a ptr to
// this to C..
let write_handle = write_t();
- let write_handle_ptr = ptr::addr_of(&write_handle);
+ let write_handle_ptr: *uv_write_t = &write_handle;
debug!("tcp req: tcp stream: %d write_handle: %d",
tcp_handle_ptr as int,
write_handle_ptr as int);
let client_data = request_wrapper {
write_req: write_handle_ptr,
- req_buf: ptr::addr_of(&req_msg),
+ req_buf: &req_msg,
read_chan: client_chan
};
- let tcp_init_result = tcp_init(
- test_loop as *libc::c_void, tcp_handle_ptr);
- if (tcp_init_result == 0i32) {
+ let tcp_init_result = tcp_init(test_loop as *libc::c_void,
+ tcp_handle_ptr);
+ if (tcp_init_result == 0) {
debug!(~"sucessful tcp_init_result");
debug!(~"building addr...");
let addr = ip4_addr(ip, port);
// FIXME ref #2064
- let addr_ptr = ptr::addr_of(&addr);
+ let addr_ptr: *sockaddr_in = &addr;
debug!("after build addr in rust. port: %u",
- addr.sin_port as uint);
+ addr.sin_port as uint);
// this should set up the connection request..
debug!("b4 call tcp_connect connect cb: %u ",
- on_connect_cb as uint);
- let tcp_connect_result = tcp_connect(
- connect_req_ptr, tcp_handle_ptr,
- addr_ptr, on_connect_cb);
- if (tcp_connect_result == 0i32) {
+ on_connect_cb as uint);
+ let tcp_connect_result = tcp_connect(connect_req_ptr,
+ tcp_handle_ptr,
+ addr_ptr,
+ on_connect_cb);
+ if (tcp_connect_result == 0) {
// not set the data on the connect_req
// until its initialized
- set_data_for_req(
- connect_req_ptr as *libc::c_void,
- ptr::addr_of(&client_data) as *libc::c_void);
- set_data_for_uv_handle(
- tcp_handle_ptr as *libc::c_void,
- ptr::addr_of(&client_data) as *libc::c_void);
+ set_data_for_req(connect_req_ptr as *libc::c_void,
+ &client_data);
+ set_data_for_uv_handle(tcp_handle_ptr as *libc::c_void,
+ &client_data);
debug!(~"before run tcp req loop");
run(test_loop);
debug!(~"after run tcp req loop");
unsafe {
let test_loop = loop_new();
let tcp_server = tcp_t();
- let tcp_server_ptr = ptr::addr_of(&tcp_server);
+ let tcp_server_ptr: *uv_tcp_t = &tcp_server;
let tcp_client = tcp_t();
- let tcp_client_ptr = ptr::addr_of(&tcp_client);
+ let tcp_client_ptr: *uv_tcp_t = &tcp_client;
let server_write_req = write_t();
- let server_write_req_ptr = ptr::addr_of(&server_write_req);
+ let server_write_req_ptr: *uv_write_t = &server_write_req;
let resp_str_bytes = str::to_bytes(server_resp_msg);
let resp_msg_ptr: *u8 = vec::raw::to_ptr(resp_str_bytes);
debug!("resp_msg ptr: %u", resp_msg_ptr as uint);
let resp_msg = ~[
- buf_init(resp_msg_ptr, vec::len(resp_str_bytes))
+ buf_init(resp_msg_ptr, resp_str_bytes.len())
];
let continue_async_handle = async_t();
- let continue_async_handle_ptr =
- ptr::addr_of(&continue_async_handle);
+ let continue_async_handle_ptr: *uv_async_t =
+ &continue_async_handle;
let async_data =
async_handle_data { continue_chan: continue_chan };
- let async_data_ptr = ptr::addr_of(&async_data);
+ let async_data_ptr: *async_handle_data = &async_data;
let server_data = tcp_server_data {
client: tcp_client_ptr,
server: tcp_server_ptr,
server_kill_msg: kill_server_msg,
- server_resp_buf: ptr::addr_of(&resp_msg),
+ server_resp_buf: &resp_msg,
server_chan: server_chan,
server_write_req: server_write_req_ptr
};
- let server_data_ptr = ptr::addr_of(&server_data);
+ let server_data_ptr: *tcp_server_data = &server_data;
set_data_for_uv_handle(tcp_server_ptr as *libc::c_void,
server_data_ptr as *libc::c_void);
if (tcp_init_result == 0i32) {
let server_addr = ip4_addr(server_ip, server_port);
// FIXME ref #2064
- let server_addr_ptr = ptr::addr_of(&server_addr);
+ let server_addr_ptr: *sockaddr_in = &server_addr;
// uv_tcp_bind()
- let bind_result = tcp_bind(tcp_server_ptr,
- server_addr_ptr);
+ let bind_result = tcp_bind(tcp_server_ptr, server_addr_ptr);
if (bind_result == 0i32) {
debug!(~"successful uv_tcp_bind, listening");
use core::cell::Cell;
use core::cmp;
+use core::comm::{ChanOne, PortOne, oneshot, send_one};
use core::either::{Either, Left, Right};
+use core::hashmap::HashMap;
use core::io;
-use core::comm::{oneshot, PortOne, send_one};
use core::pipes::recv;
-use core::prelude::*;
-use core::result;
use core::run;
-use core::hashmap::HashMap;
-use core::task;
use core::to_bytes;
/**
}
_ => {
- let (chan, port) = oneshot::init();
+ let (port, chan) = oneshot();
let mut blk = None;
blk <-> bo;
let blk = blk.unwrap();
let chan = Cell(chan);
- do task::spawn || {
+ do task::spawn {
let exe = Exec {
discovered_inputs: WorkMap::new(),
discovered_outputs: WorkMap::new(),
None => fail!(),
Some(Left(v)) => v,
Some(Right(port)) => {
- let (exe, v) = match recv(port) {
+ let (exe, v) = match recv(port.unwrap()) {
oneshot::send(data) => data
};
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
use core::to_bytes;
-use core::to_str::ToStr;
#[deriving(Eq)]
pub enum Abi {
def_mod(def_id),
def_foreign_mod(def_id),
def_const(def_id),
- def_arg(node_id, mode, bool /* is_mutbl */),
+ def_arg(node_id, bool /* is_mutbl */),
def_local(node_id, bool /* is_mutbl */),
def_variant(def_id /* enum */, def_id /* variant */),
def_ty(def_id),
neg
}
-// Generally, after typeck you can get the inferred value
-// using ty::resolved_T(...).
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
-pub enum inferable<T> {
- expl(T),
- infer(node_id)
-}
-
-impl<T:to_bytes::IterBytes> to_bytes::IterBytes for inferable<T> {
- fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
- match *self {
- expl(ref t) =>
- to_bytes::iter_bytes_2(&0u8, t, lsb0, f),
-
- infer(ref n) =>
- to_bytes::iter_bytes_2(&1u8, n, lsb0, f),
- }
- }
-}
-
-// "resolved" mode: the real modes.
-#[auto_encode]
-#[auto_decode]
-#[deriving(Eq)]
-pub enum rmode { by_ref, by_copy }
-
-impl to_bytes::IterBytes for rmode {
- fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
- (*self as u8).iter_bytes(lsb0, f)
- }
-}
-
-// inferable mode.
-pub type mode = inferable<rmode>;
-
pub type stmt = spanned<stmt_>;
#[auto_encode]
#[auto_decode]
#[deriving(Eq)]
pub struct arg {
- mode: mode,
is_mutbl: bool,
ty: @Ty,
pat: @pat,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use abi::AbiSet;
use ast::*;
use ast;
use print::pprust;
use visit;
-use core::cmp;
use core::hashmap::HashMap;
-use core::str;
-use core::vec;
pub enum path_elt {
path_mod(ident),
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use ast::*;
use ast;
use ast_util;
use visit;
use opt_vec;
-use core::int;
-use core::option;
-use core::str;
use core::to_bytes;
-use core::vec;
-
pub fn path_name_i(idents: &[ident], intr: @token::ident_interner) -> ~str {
// FIXME: Bad copies (#2543 -- same for everything else that says "bad")
def_use(id) | def_struct(id) | def_trait(id) => {
id
}
- def_arg(id, _, _) | def_local(id, _) | def_self(id, _) | def_self_ty(id)
+ def_arg(id, _) | def_local(id, _) | def_self(id, _) | def_self_ty(id)
| def_upvar(id, _, _, _) | def_binding(id, _) | def_region(id)
| def_typaram_binder(id) | def_label(id) => {
local_def(id)
}
}
+/// Precedence of the `as` operator, which is a binary operator
+/// not appearing in the prior table.
+pub static as_prec: uint = 11u;
+
pub fn dtor_ty() -> @ast::Ty {
@ast::Ty {id: 0, node: ty_nil, span: dummy_sp()}
}
assert_eq!(refold_test_sc(3,&t),test_sc);
}
-
// extend a syntax context with a sequence of marks given
// in a vector. v[0] will be the outermost mark.
fn unfold_marks(mrks:~[Mrk],tail:SyntaxContext,table: &mut SCTable) -> SyntaxContext {
// Functions dealing with attributes and meta_items
-use core::prelude::*;
-
use ast;
use codemap::{spanned, dummy_spanned};
use attr;
use diagnostic::span_handler;
use parse::comments::{doc_comment_style, strip_doc_comment_decoration};
-use core::vec;
use core::hashmap::HashSet;
use std;
*/
-use core::prelude::*;
-
-use core::cmp;
-use core::str;
use core::to_bytes;
-use core::uint;
use std::serialize::{Encodable, Decodable, Encoder, Decoder};
pub trait Pos {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use codemap::{Pos, span};
use codemap;
-use core::io::WriterUtil;
-use core::io;
-use core::str;
-use core::vec;
-
use std::term;
pub type Emitter = @fn(cmsp: Option<(@codemap::CodeMap, span)>,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-
/*
* Inline assembly support.
*/
-use core::prelude::*;
-
use ast;
use codemap::span;
use ext::base;
let mut dialect = ast::asm_att;
let mut state = Asm;
- loop outer: {
+
+ // Not using labeled break to get us through one round of bootstrapping.
+ let mut continue = true;
+ while continue {
match state {
Asm => {
asm = expr_to_str(cx, p.parse_expr(),
p.bump();
match next_state(state) {
Some(x) => x,
- None => break outer
+ None => {
+ continue = false;
+ break
+ }
}
} else if *p.token == token::MOD_SEP {
p.bump();
let s = match next_state(state) {
Some(x) => x,
- None => break outer
+ None => {
+ continue = false;
+ break
+ }
};
match next_state(s) {
Some(x) => x,
- None => break outer
+ None => {
+ continue = false;
+ break
+ }
}
} else if *p.token == token::EOF {
- break outer;
+ continue = false;
+ break;
} else {
state
};
*/
-use core::prelude::*;
-
use ast;
use ast_util;
use attr;
use opt_vec::OptVec;
use ext::build;
-use core::vec;
-
// Transitional reexports so qquote can find the paths it is looking for
mod syntax {
pub use ext;
}
}
-priv impl @ext_ctxt {
+trait ExtCtxtMethods {
+ fn bind_path(&self,
+ span: span,
+ ident: ast::ident,
+ path: @ast::Path,
+ bounds: @OptVec<ast::TyParamBound>)
+ -> ast::TyParam;
+ fn expr(&self, span: span, node: ast::expr_) -> @ast::expr;
+ fn path(&self, span: span, strs: ~[ast::ident]) -> @ast::Path;
+ fn path_global(&self, span: span, strs: ~[ast::ident]) -> @ast::Path;
+ fn path_tps(&self, span: span, strs: ~[ast::ident], tps: ~[@ast::Ty])
+ -> @ast::Path;
+ fn path_tps_global(&self,
+ span: span,
+ strs: ~[ast::ident],
+ tps: ~[@ast::Ty])
+ -> @ast::Path;
+ fn ty_path(&self, span: span, strs: ~[ast::ident], tps: ~[@ast::Ty])
+ -> @ast::Ty;
+ fn binder_pat(&self, span: span, nm: ast::ident) -> @ast::pat;
+ fn stmt(&self, expr: @ast::expr) -> @ast::stmt;
+ fn lit_str(&self, span: span, s: @~str) -> @ast::expr;
+ fn lit_uint(&self, span: span, i: uint) -> @ast::expr;
+ fn lambda(&self, blk: ast::blk) -> @ast::expr;
+ fn blk(&self, span: span, stmts: ~[@ast::stmt]) -> ast::blk;
+ fn expr_blk(&self, expr: @ast::expr) -> ast::blk;
+ fn expr_path(&self, span: span, strs: ~[ast::ident]) -> @ast::expr;
+ fn expr_path_global(&self, span: span, strs: ~[ast::ident]) -> @ast::expr;
+ fn expr_var(&self, span: span, var: ~str) -> @ast::expr;
+ fn expr_field(&self, span: span, expr: @ast::expr, ident: ast::ident)
+ -> @ast::expr;
+ fn expr_call(&self, span: span, expr: @ast::expr, args: ~[@ast::expr])
+ -> @ast::expr;
+ fn expr_method_call(&self,
+ span: span,
+ expr: @ast::expr,
+ ident: ast::ident,
+ args: ~[@ast::expr])
+ -> @ast::expr;
+ fn lambda_expr(&self, expr: @ast::expr) -> @ast::expr;
+ fn lambda_stmts(&self, span: span, stmts: ~[@ast::stmt]) -> @ast::expr;
+}
+
+impl ExtCtxtMethods for @ext_ctxt {
fn bind_path(
&self,
_span: span,
};
let ser_inputs = ~[ast::arg {
- mode: ast::infer(cx.next_id()),
is_mutbl: false,
ty: ty_s,
pat: @ast::pat {
span: span,
};
- let deser_inputs = ~[ast::arg {
- mode: ast::infer(cx.next_id()),
- is_mutbl: false,
- ty: ty_d,
- pat: @ast::pat {
+ let deser_inputs = ~[
+ ast::arg {
+ is_mutbl: false,
+ ty: ty_d,
+ pat: @ast::pat {
+ id: cx.next_id(),
+ node: ast::pat_ident(ast::bind_by_copy,
+ ast_util::ident_to_path(span,
+ cx.ident_of(
+ ~"__d")),
+ None),
+ span: span,
+ },
id: cx.next_id(),
- node: ast::pat_ident(
- ast::bind_by_copy,
- ast_util::ident_to_path(span, cx.ident_of(~"__d")),
- None),
- span: span,
- },
- id: cx.next_id(),
- }];
+ }
+ ];
let deser_decl = ast::fn_decl {
inputs: deser_inputs,
};
let quoted_expr = copy quote_expr!(
- ::core::sys::begin_unwind(~"explicit failure", ~"empty", 1);
+ ::core::sys::FailWithCause::fail_with("explicit failure", "empty", 1);
).node;
let impossible_case = ast::arm {
ast::expr_fn_block(
ast::fn_decl {
inputs: ~[ast::arg {
- mode: ast::infer(ext_cx.next_id()),
is_mutbl: false,
ty: @ast::Ty {
id: ext_cx.next_id(),
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use ast;
use codemap;
use codemap::{CodeMap, span, ExpnInfo, ExpandedFrom};
use parse;
use parse::token;
-use core::vec;
use core::hashmap::HashMap;
// new-style macro! tt code:
// ugh: can't get this to compile with mut because of the
// lack of flow sensitivity.
- #[cfg(stage1)]
- #[cfg(stage2)]
- #[cfg(stage3)]
+ #[cfg(not(stage0))]
fn get_map<'a>(&'a self) -> &'a HashMap<K,@V> {
match *self {
BaseMapChain (~ref map) => map,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use ast;
use codemap;
use codemap::span;
use opt_vec::OptVec;
-use core::option;
-
pub struct Field {
ident: ast::ident,
ex: @ast::expr
-> ast::arg {
let arg_pat = mk_pat_ident(cx, span, ident);
ast::arg {
- mode: ast::infer(cx.next_id()),
is_mutbl: false,
ty: ty,
pat: arg_pat,
~[
cx.ident_of(~"core"),
cx.ident_of(~"sys"),
- cx.ident_of(~"begin_unwind"),
+ cx.ident_of(~"FailWithCause"),
+ cx.ident_of(~"fail_with"),
],
~[
- mk_uniq_str(cx, span, ~"internal error: entered unreachable code"),
- mk_uniq_str(cx, span, loc.file.name),
+ mk_base_str(cx, span, ~"internal error: entered unreachable code"),
+ mk_base_str(cx, span, loc.file.name),
mk_uint(cx, span, loc.line),
]
)
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use ast;
use codemap::span;
use ext::base::*;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use ast;
use ast::*;
use ext::base::ext_ctxt;
use ast_util;
use opt_vec;
-use core::uint;
-
pub fn expand_deriving_decodable(
cx: @ext_ctxt,
span: span,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use ast;
use ast::*;
use ext::base::ext_ctxt;
use ast_util;
use opt_vec;
-use core::uint;
-
pub fn expand_deriving_encodable(
cx: @ext_ctxt,
span: span,
*/
-use core::prelude::*;
-
use ast;
use ast::{
}
}
let field_tuples =
- do vec::map2(*self_vec,
+ do vec::map_zip(*self_vec,
enum_matching_fields) |&(id, self_f), &other| {
(id, self_f, other)
};
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use ast;
use ast::*;
use ext::base::ext_ctxt;
use ast_util;
use opt_vec;
-use core::uint;
-
pub fn expand_deriving_iter_bytes(cx: @ext_ctxt,
span: span,
_mitem: @meta_item,
/// The compiler code necessary to implement the #[deriving(Eq)] and
/// #[deriving(IterBytes)] extensions.
-use core::prelude::*;
-
use ast;
use ast::{Ty, bind_by_ref, deref, enum_def};
use ast::{expr, expr_match, ident, item, item_};
use parse::token::special_idents::clownshoes_extensions;
use opt_vec;
-use core::uint;
-
pub mod clone;
pub mod iter_bytes;
pub mod encodable;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
/*
* The compiler code necessary to support the env! extension. Eventually this
* should all get sucked into either the compiler syntax extension plugin
* interface.
*/
-use core::prelude::*;
-
use ast;
use codemap::span;
use ext::base::*;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use ast::{blk_, attribute_, attr_outer, meta_word};
use ast::{crate, expr_, expr_mac, mac_invoc_tt};
use ast::{item_mac, stmt_, stmt_mac, stmt_expr, stmt_semi};
use parse;
use parse::{parse_item_from_source_str};
-use core::vec;
-
pub fn expand_expr(extsbox: @mut SyntaxEnv,
cx: @ext_ctxt,
e: &expr_,
__log(1u32, fmt!( $($arg),+ ))
)
)
+
macro_rules! warn (
($arg:expr) => (
__log(2u32, fmt!( \"%?\", $arg ))
__log(2u32, fmt!( $($arg),+ ))
)
)
+
macro_rules! info (
($arg:expr) => (
__log(3u32, fmt!( \"%?\", $arg ))
__log(3u32, fmt!( $($arg),+ ))
)
)
+
macro_rules! debug (
($arg:expr) => (
__log(4u32, fmt!( \"%?\", $arg ))
)
macro_rules! fail(
- ($msg: expr) => (
- ::core::sys::begin_unwind($msg, file!().to_owned(), line!())
- );
() => (
- fail!(~\"explicit failure\")
+ fail!(\"explicit failure\")
+ );
+ ($msg:expr) => (
+ ::core::sys::FailWithCause::fail_with($msg, file!(), line!())
+ );
+ ($( $arg:expr ),+) => (
+ ::core::sys::FailWithCause::fail_with(fmt!( $($arg),+ ), file!(), line!())
)
)
macro_rules! assert(
($cond:expr) => {
if !$cond {
- ::core::sys::fail_assert(stringify!($cond), file!(), line!())
+ ::core::sys::FailWithCause::fail_with(
+ ~\"assertion failed: \" + stringify!($cond), file!(), line!())
}
};
($cond:expr, $msg:expr) => {
if !$cond {
- ::core::sys::fail_assert($msg, file!(), line!())
+ ::core::sys::FailWithCause::fail_with($msg, file!(), line!())
+ }
+ };
+ ($cond:expr, $( $arg:expr ),+) => {
+ if !$cond {
+ ::core::sys::FailWithCause::fail_with(fmt!( $($arg),+ ), file!(), line!())
}
}
)
macro_rules! assert_eq (
- ($given:expr , $expected:expr) =>
- ({let given_val = $given;
- let expected_val = $expected;
- // check both directions of equality....
- if !((given_val == expected_val) && (expected_val == given_val)) {
- fail!(fmt!(\"expected: %?, given: %?\",expected_val,given_val));
- }}))
+ ($given:expr , $expected:expr) => (
+ {
+ let given_val = $given;
+ let expected_val = $expected;
+ // check both directions of equality....
+ if !((given_val == expected_val) && (expected_val == given_val)) {
+ fail!(fmt!(\"left: %? != right: %?\", given_val, expected_val));
+ }
+ }
+ )
+ )
macro_rules! condition (
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-
/*
* The compiler code necessary to support the fmt! extension. Eventually this
* should all get sucked into either the standard library extfmt module or the
* compiler syntax extension plugin interface.
*/
-use core::prelude::*;
-
use ast;
use codemap::span;
use ext::base::*;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::io::WriterUtil;
-use core::prelude::*;
-
use ast;
use codemap;
use ext::base::*;
// To start with, it will be use dummy spans, but it might someday do
// something smarter.
-use core::prelude::*;
-
use abi::AbiSet;
use ast::ident;
use ast;
use opt_vec;
use opt_vec::OptVec;
-use core::vec;
-
// Transitional reexports so qquote can find the paths it is looking for
mod syntax {
pub use ext;
fn arg(&self, name: ident, ty: @ast::Ty) -> ast::arg {
ast::arg {
- mode: ast::infer(self.next_id()),
is_mutbl: false,
ty: ty,
pat: @ast::pat {
*/
-use core::prelude::*;
-
use ast;
use codemap::span;
use ext::base::ext_ctxt;
*/
-use core::prelude::*;
-
use ext::base::ext_ctxt;
use ext::pipes::proto::protocol;
-use core::str;
use std::bitv::Bitv;
pub fn analyze(proto: protocol, _cx: @ext_ctxt) {
use parse::parser;
use parse::token;
-use core::prelude::*;
-
pub trait proto_parser {
fn parse_proto(&self, id: ~str) -> protocol;
fn parse_state(&self, proto: protocol);
use opt_vec;
use opt_vec::OptVec;
-use core::prelude::*;
-use core::str;
-use core::to_str::ToStr;
-use core::vec;
-
pub trait gen_send {
fn gen_send(&mut self, cx: @ext_ctxt, try: bool) -> @ast::item;
fn to_ty(&mut self, cx: @ext_ctxt) -> @ast::Ty;
assert!(next_state.tys.len() ==
next.generics.ty_params.len());
let arg_names = tys.mapi(|i, _ty| cx.ident_of(~"x_"+i.to_str()));
- let args_ast = vec::map2(arg_names, *tys, |n, t| cx.arg(*n, *t));
+ let args_ast = vec::map_zip(arg_names, *tys, |n, t| cx.arg(*n, *t));
let pipe_ty = cx.ty_path_ast_builder(
path(~[this.data_name()], span)
body += ~"let b = pipe.reuse_buffer();\n";
body += fmt!("let %s = ::core::pipes::SendPacketBuffered(\
- ::ptr::addr_of(&(b.buffer.data.%s)));\n",
+ &(b.buffer.data.%s));\n",
sp, next.name);
body += fmt!("let %s = ::core::pipes::RecvPacketBuffered(\
- ::ptr::addr_of(&(b.buffer.data.%s)));\n",
+ &(b.buffer.data.%s));\n",
rp, next.name);
}
else {
debug!("pipec: no next state");
let arg_names = tys.mapi(|i, _ty| (~"x_" + i.to_str()));
- let args_ast = do vec::map2(arg_names, *tys) |n, t| {
+ let args_ast = do vec::map_zip(arg_names, *tys) |n, t| {
cx.arg(cx.ident_of(*n), *t)
};
|s| ext_cx.parse_stmt(
fmt!("data.%s.set_buffer(buffer)",
s.name))),
- ext_cx.parse_expr(
- fmt!("::ptr::addr_of(&(data.%s))",
- self.states[0].name))));
+ ext_cx.parse_expr(fmt!(
+ "::core::ptr::to_unsafe_ptr(&(data.%s))",
+ self.states[0].name))));
quote_expr!({
let buffer = $buffer;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use ast;
use codemap::span;
use ext::base::ext_ctxt;
use ext::pipes::ast_builder::{append_types, ext_ctxt_ast_builder, path};
-use core::to_str::ToStr;
-
#[deriving(Eq)]
pub enum direction { send, recv }
use parse::token;
use parse;
-use core::prelude::*;
-
/**
*
* Quasiquoting works via token trees.
use parse;
use print::pprust;
- use core::prelude::*;
use core::str;
pub use ast::*;
use parse;
use print::pprust;
-use core::io;
-use core::prelude::*;
-use core::result;
-use core::str;
-use core::vec;
-
// These macros all relate to the file system; they either return
// the column/row/filename of the expression, or they include
// a given file into the current one.
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use ast;
use codemap::span;
use ext::base::ext_ctxt;
use parse::token::{Token, EOF, to_str, nonterminal};
use parse::token;
-use core::prelude::*;
use core::hashmap::HashMap;
/* This is an Earley-like parser, without support for in-grammar nonterminals,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
use ast::{ident, matcher_, matcher, match_tok, match_nonterminal, match_seq};
use ast::{tt_delim};
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use ast;
use ast::{token_tree, tt_delim, tt_tok, tt_seq, tt_nonterminal,ident};
use codemap::{span, dummy_sp};
use parse::lexer::TokenAndSpan;
use core::hashmap::HashMap;
-use core::option;
-use core::vec;
///an unzipping of `token_tree`s
struct TtFrame {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use ast::*;
use ast;
use codemap::{span, spanned};
use opt_vec::OptVec;
-use core::vec;
-
pub trait ast_fold {
fn fold_crate(@self, &crate) -> crate;
fn fold_view_item(@self, @view_item) -> @view_item;
//used in noop_fold_foreign_item and noop_fold_fn_decl
fn fold_arg_(a: arg, fld: @ast_fold) -> arg {
ast::arg {
- mode: a.mode,
is_mutbl: a.is_mutbl,
ty: fld.fold_ty(a.ty),
pat: fld.fold_pat(a.pat),
}
}
-pub impl @ast_fold {
+pub trait AstFoldExtensions {
+ fn fold_attributes(&self, attrs: ~[attribute]) -> ~[attribute];
+}
+
+impl AstFoldExtensions for @ast_fold {
fn fold_attributes(&self, attrs: ~[attribute]) -> ~[attribute] {
attrs.map(|x| fold_attribute_(*x, *self))
}
*/
use core::prelude::*;
-use core::iter;
-use core::iter::BaseIter;
+use core::old_iter;
+use core::old_iter::BaseIter;
#[auto_encode]
#[auto_decode]
}
}
- #[cfg(stage1)]
- #[cfg(stage2)]
- #[cfg(stage3)]
+ #[cfg(not(stage0))]
fn get<'a>(&'a self, i: uint) -> &'a T {
match *self {
Empty => fail!(fmt!("Invalid index %u", i)),
#[inline(always)]
fn mapi_to_vec<B>(&self, op: &fn(uint, &T) -> B) -> ~[B] {
let mut index = 0;
- iter::map_to_vec(self, |a| {
+ old_iter::map_to_vec(self, |a| {
let i = index;
index += 1;
op(i, a)
}
}
-impl<A> iter::ExtendedIter<A> for OptVec<A> {
+impl<A> old_iter::ExtendedIter<A> for OptVec<A> {
#[inline(always)]
fn eachi(&self, blk: &fn(v: uint, v: &A) -> bool) {
- iter::eachi(self, blk)
+ old_iter::eachi(self, blk)
}
#[inline(always)]
fn all(&self, blk: &fn(&A) -> bool) -> bool {
- iter::all(self, blk)
+ old_iter::all(self, blk)
}
#[inline(always)]
fn any(&self, blk: &fn(&A) -> bool) -> bool {
- iter::any(self, blk)
+ old_iter::any(self, blk)
}
#[inline(always)]
fn foldl<B>(&self, b0: B, blk: &fn(&B, &A) -> B) -> B {
- iter::foldl(self, b0, blk)
+ old_iter::foldl(self, b0, blk)
}
#[inline(always)]
fn position(&self, f: &fn(&A) -> bool) -> Option<uint> {
- iter::position(self, f)
+ old_iter::position(self, f)
}
#[inline(always)]
fn map_to_vec<B>(&self, op: &fn(&A) -> B) -> ~[B] {
- iter::map_to_vec(self, op)
+ old_iter::map_to_vec(self, op)
}
#[inline(always)]
fn flat_map_to_vec<B,IB:BaseIter<B>>(&self, op: &fn(&A) -> IB)
-> ~[B] {
- iter::flat_map_to_vec(self, op)
+ old_iter::flat_map_to_vec(self, op)
}
}
-impl<A: Eq> iter::EqIter<A> for OptVec<A> {
+impl<A: Eq> old_iter::EqIter<A> for OptVec<A> {
#[inline(always)]
- fn contains(&self, x: &A) -> bool { iter::contains(self, x) }
+ fn contains(&self, x: &A) -> bool { old_iter::contains(self, x) }
#[inline(always)]
- fn count(&self, x: &A) -> uint { iter::count(self, x) }
+ fn count(&self, x: &A) -> uint { old_iter::count(self, x) }
}
-impl<A: Copy> iter::CopyableIter<A> for OptVec<A> {
+impl<A: Copy> old_iter::CopyableIter<A> for OptVec<A> {
#[inline(always)]
fn filter_to_vec(&self, pred: &fn(&A) -> bool) -> ~[A] {
- iter::filter_to_vec(self, pred)
+ old_iter::filter_to_vec(self, pred)
}
#[inline(always)]
- fn to_vec(&self) -> ~[A] { iter::to_vec(self) }
+ fn to_vec(&self) -> ~[A] { old_iter::to_vec(self) }
#[inline(always)]
fn find(&self, f: &fn(&A) -> bool) -> Option<A> {
- iter::find(self, f)
+ old_iter::find(self, f)
}
}
-impl<A: Copy+Ord> iter::CopyableOrderedIter<A> for OptVec<A> {
+impl<A: Copy+Ord> old_iter::CopyableOrderedIter<A> for OptVec<A> {
#[inline(always)]
- fn min(&self) -> A { iter::min(self) }
+ fn min(&self) -> A { old_iter::min(self) }
#[inline(always)]
- fn max(&self) -> A { iter::max(self) }
+ fn max(&self) -> A { old_iter::max(self) }
}
return attrs;
}
+ // matches attribute = # attribute_naked
fn parse_attribute(&self, style: ast::attr_style) -> ast::attribute {
let lo = self.span.lo;
self.expect(&token::POUND);
return self.parse_attribute_naked(style, lo);
}
+ // matches attribute_naked = [ meta_item ]
fn parse_attribute_naked(&self, style: ast::attr_style, lo: BytePos) ->
ast::attribute {
self.expect(&token::LBRACKET);
// is an inner attribute of the containing item or an outer attribute of
// the first contained item until we see the semi).
+ // matches inner_attrs* outer_attr?
// you can make the 'next' field an Option, but the result is going to be
// more useful as a vector.
fn parse_inner_attrs_and_next(&self) ->
(inner_attrs, next_outer_attrs)
}
+ // matches meta_item = IDENT
+ // | IDENT = lit
+ // | IDENT meta_seq
fn parse_meta_item(&self) -> @ast::meta_item {
let lo = self.span.lo;
let name = self.id_to_str(self.parse_ident());
}
}
+ // matches meta_seq = ( COMMASEP(meta_item) )
fn parse_meta_seq(&self) -> ~[@ast::meta_item] {
copy self.parse_seq(
&token::LPAREN,
use ast;
use codemap;
+// does this expression require a semicolon to be treated
+// as a statement? The negation of this: 'can this expression
+// be used as a statement without a semicolon' -- is used
+// as an early-bail-out in the parser so that, for instance,
+// 'if true {...} else {...}
+// |x| 5 '
+// isn't parsed as (if true {...} else {...} | x) | 5
pub fn expr_requires_semi_to_be_stmt(e: @ast::expr) -> bool {
match e.node {
ast::expr_if(*)
}
}
+// this statement requires a semicolon after it.
+// note that in one case (stmt_semi), we've already
+// seen the semicolon, and thus don't need another.
pub fn stmt_ends_with_semi(stmt: &ast::stmt) -> bool {
return match stmt.node {
ast::stmt_decl(d, _) => {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use ast;
use codemap::{BytePos, CharPos, CodeMap, Pos};
use diagnostic;
use parse::token;
use parse;
-use core::io::ReaderUtil;
-use core::io;
-use core::str;
-use core::uint;
-use core::vec;
-
#[deriving(Eq)]
pub enum cmnt_style {
isolated, // No code on either side of each line of the comment
pos: BytePos
}
+// it appears this function is called only from pprust... that's
+// probably not a good thing.
pub fn gather_comments_and_literals(span_diagnostic:
@diagnostic::span_handler,
path: ~str,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use ast;
use codemap::{BytePos, spanned};
use parse::lexer::reader;
use parse::parser::Parser;
use parse::token;
-use core::option::{None, Option, Some};
-
use opt_vec;
use opt_vec::OptVec;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use ast;
use codemap::{BytePos, CharPos, CodeMap, Pos, span};
use codemap;
use ext::tt::transcribe::{dup_tt_reader};
use parse::token;
-use core::char;
-use core::either;
-use core::str;
-use core::u64;
-
pub use ext::tt::transcribe::{TtReader, new_tt_reader};
//use std;
return c == ' ' || c == '\t' || c == '\r' || c == '\n';
}
-fn may_begin_ident(c: char) -> bool { return is_alpha(c) || c == '_'; }
-
fn in_range(c: char, lo: char, hi: char) -> bool {
return lo <= c && c <= hi
}
-fn is_alpha(c: char) -> bool {
- return in_range(c, 'a', 'z') || in_range(c, 'A', 'Z');
-}
-
fn is_dec_digit(c: char) -> bool { return in_range(c, '0', '9'); }
-fn is_alnum(c: char) -> bool { return is_alpha(c) || is_dec_digit(c); }
-
fn is_hex_digit(c: char) -> bool {
return in_range(c, '0', '9') || in_range(c, 'a', 'f') ||
in_range(c, 'A', 'F');
}
} else if rdr.curr == '#' {
if nextch(rdr) == '!' {
+ // I guess this is the only way to figure out if
+ // we're at the beginning of the file...
let cmap = @CodeMap::new();
(*cmap).files.push(rdr.filemap);
let loc = cmap.lookup_char_pos_adj(rdr.last_pos);
}
}
let mut is_float = false;
- if rdr.curr == '.' && !(is_alpha(nextch(rdr)) || nextch(rdr) == '_' ||
- nextch(rdr) == '.') {
+ if rdr.curr == '.' && !(ident_start(nextch(rdr)) || nextch(rdr) == '.') {
is_float = true;
bump(rdr);
let dec_part = scan_digits(rdr, 10u);
use ast::node_id;
use ast;
-use codemap::{span, CodeMap};
+use codemap::{span, CodeMap, FileMap, FileSubstr};
use codemap;
use diagnostic::{span_handler, mk_span_handler, mk_handler, Emitter};
use parse::attr::parser_attr;
use parse::token::{ident_interner, mk_ident_interner};
use core::io;
-use core::option::{None, Option};
+use core::option::{None, Option, Some};
use core::path::Path;
use core::result::{Err, Ok, Result};
/// Common routines shared by parser mods
pub mod common;
-/// Functions dealing with operator precedence
-pub mod prec;
-
/// Routines the parser uses to classify AST nodes
pub mod classify;
// uses a HOF to parse anything, and <source> includes file and
// source_str.
-// this appears to be the main entry point for rust parsing by
-// rustc and crate:
pub fn parse_crate_from_file(
input: &Path,
cfg: ast::crate_cfg,
sess: @mut ParseSess
) -> @ast::crate {
- let p = new_parser_from_file(sess, /*bad*/ copy cfg, input);
- p.parse_crate_mod(/*bad*/ copy cfg)
- // why is there no p.abort_if_errors here?
-}
-
-pub fn parse_crate_from_file_using_tts(
- input: &Path,
- cfg: ast::crate_cfg,
- sess: @mut ParseSess
-) -> @ast::crate {
- let p = new_parser_from_file(sess, /*bad*/ copy cfg, input);
- let tts = p.parse_all_token_trees();
- new_parser_from_tts(sess,cfg,tts).parse_crate_mod(/*bad*/ copy cfg)
+ new_parser_from_file(sess, /*bad*/ copy cfg, input).parse_crate_mod()
// why is there no p.abort_if_errors here?
}
-
-
pub fn parse_crate_from_source_str(
name: ~str,
source: @~str,
sess,
/*bad*/ copy cfg,
/*bad*/ copy name,
- codemap::FssNone,
source
);
- maybe_aborted(p.parse_crate_mod(/*bad*/ copy cfg),p)
+ maybe_aborted(p.parse_crate_mod(),p)
}
pub fn parse_expr_from_source_str(
sess,
cfg,
/*bad*/ copy name,
- codemap::FssNone,
source
);
maybe_aborted(p.parse_expr(), p)
sess,
cfg,
/*bad*/ copy name,
- codemap::FssNone,
source
);
maybe_aborted(p.parse_item(attrs),p)
sess,
cfg,
/*bad*/ copy name,
- codemap::FssNone,
source
);
maybe_aborted(p.parse_meta_item(),p)
sess,
cfg,
/*bad*/ copy name,
- codemap::FssNone,
source
);
maybe_aborted(p.parse_stmt(attrs),p)
sess,
cfg,
/*bad*/ copy name,
- codemap::FssNone,
source
);
*p.quote_depth += 1u;
+ // right now this is re-creating the token trees from ... token trees.
maybe_aborted(p.parse_all_token_trees(),p)
}
+// given a function and parsing information (source str,
+// filename, crate cfg, and sess), create a parser,
+// apply the function, and check that the parser
+// consumed all of the input before returning the function's
+// result.
pub fn parse_from_source_str<T>(
f: &fn(&Parser) -> T,
name: ~str, ss: codemap::FileSubstr,
cfg: ast::crate_cfg,
sess: @mut ParseSess
) -> T {
- let p = new_parser_from_source_str(
+ let p = new_parser_from_source_substr(
sess,
cfg,
name,
maybe_aborted(r,p)
}
+// return the next unused node id.
pub fn next_node_id(sess: @mut ParseSess) -> node_id {
let rv = sess.next_id;
sess.next_id += 1;
return rv;
}
+// Create a new parser from a source string
pub fn new_parser_from_source_str(sess: @mut ParseSess,
cfg: ast::crate_cfg,
name: ~str,
- ss: codemap::FileSubstr,
source: @~str)
-> Parser {
- let filemap = sess.cm.new_filemap_w_substr(name, ss, source);
- let srdr = lexer::new_string_reader(
- copy sess.span_diagnostic,
- filemap,
- sess.interner
- );
- Parser(sess, cfg, srdr as @reader)
+ filemap_to_parser(sess,string_to_filemap(sess,source,name),cfg)
}
-/// Read the entire source file, return a parser
-/// that draws from that string
-pub fn new_parser_result_from_file(
- sess: @mut ParseSess,
- cfg: ast::crate_cfg,
- path: &Path
-) -> Result<Parser, ~str> {
- match io::read_whole_file_str(path) {
- Ok(src) => {
- let filemap = sess.cm.new_filemap(path.to_str(), @src);
- let srdr = lexer::new_string_reader(copy sess.span_diagnostic,
- filemap,
- sess.interner);
- Ok(Parser(sess, cfg, srdr as @reader))
-
- }
- Err(e) => Err(e)
- }
+// Create a new parser from a source string where the origin
+// is specified as a substring of another file.
+pub fn new_parser_from_source_substr(sess: @mut ParseSess,
+ cfg: ast::crate_cfg,
+ name: ~str,
+ ss: codemap::FileSubstr,
+ source: @~str)
+ -> Parser {
+ filemap_to_parser(sess,substring_to_filemap(sess,source,name,ss),cfg)
}
/// Create a new parser, handling errors as appropriate
cfg: ast::crate_cfg,
path: &Path
) -> Parser {
- match new_parser_result_from_file(sess, cfg, path) {
- Ok(parser) => parser,
- Err(e) => {
- sess.span_diagnostic.handler().fatal(e)
- }
- }
+ filemap_to_parser(sess,file_to_filemap(sess,path,None),cfg)
}
-/// Create a new parser based on a span from an existing parser. Handles
-/// error messages correctly when the file does not exist.
+/// Given a session, a crate config, a path, and a span, add
+/// the file at the given path to the codemap, and return a parser.
+/// On an error, use the given span as the source of the problem.
pub fn new_sub_parser_from_file(
sess: @mut ParseSess,
cfg: ast::crate_cfg,
path: &Path,
sp: span
) -> Parser {
- match new_parser_result_from_file(sess, cfg, path) {
- Ok(parser) => parser,
+ filemap_to_parser(sess,file_to_filemap(sess,path,Some(sp)),cfg)
+}
+
+/// Given a filemap and config, return a parser
+pub fn filemap_to_parser(sess: @mut ParseSess,
+ filemap: @FileMap,
+ cfg: ast::crate_cfg) -> Parser {
+ tts_to_parser(sess,filemap_to_tts(sess,filemap),cfg)
+}
+
+// must preserve old name for now, because quote! from the *existing*
+// compiler expands into it
+pub fn new_parser_from_tts(sess: @mut ParseSess,
+ cfg: ast::crate_cfg,
+ tts: ~[ast::token_tree]) -> Parser {
+ tts_to_parser(sess,tts,cfg)
+}
+
+
+// base abstractions
+
+/// Given a session and a path and an optional span (for error reporting),
+/// add the path to the session's codemap and return the new filemap.
+pub fn file_to_filemap(sess: @mut ParseSess, path: &Path, spanopt: Option<span>)
+ -> @FileMap {
+ match io::read_whole_file_str(path) {
+ Ok(src) => string_to_filemap(sess, @src, path.to_str()),
Err(e) => {
- sess.span_diagnostic.span_fatal(sp, e)
+ match spanopt {
+ Some(span) => sess.span_diagnostic.span_fatal(span, e),
+ None => sess.span_diagnostic.handler().fatal(e)
+ }
}
}
}
-pub fn new_parser_from_tts(
- sess: @mut ParseSess,
- cfg: ast::crate_cfg,
- tts: ~[ast::token_tree]
-) -> Parser {
+// given a session and a string, add the string to
+// the session's codemap and return the new filemap
+pub fn string_to_filemap(sess: @mut ParseSess, source: @~str, path: ~str)
+ -> @FileMap {
+ sess.cm.new_filemap(path, source)
+}
+
+// given a session and a string and a path and a FileSubStr, add
+// the string to the CodeMap and return the new FileMap
+pub fn substring_to_filemap(sess: @mut ParseSess, source: @~str, path: ~str,
+ filesubstr: FileSubstr) -> @FileMap {
+ sess.cm.new_filemap_w_substr(path,filesubstr,source)
+}
+
+// given a filemap, produce a sequence of token-trees
+pub fn filemap_to_tts(sess: @mut ParseSess, filemap: @FileMap)
+ -> ~[ast::token_tree] {
+ // it appears to me that the cfg doesn't matter here... indeed,
+ // parsing tt's probably shouldn't require a parser at all.
+ let cfg = ~[];
+ let srdr = lexer::new_string_reader(copy sess.span_diagnostic,
+ filemap,
+ sess.interner);
+ let p1 = Parser(sess, cfg, srdr as @reader);
+ p1.parse_all_token_trees()
+}
+
+// given tts and cfg, produce a parser
+pub fn tts_to_parser(sess: @mut ParseSess,
+ tts: ~[ast::token_tree],
+ cfg: ast::crate_cfg) -> Parser {
let trdr = lexer::new_tt_reader(
copy sess.span_diagnostic,
sess.interner,
use std::serialize::Encodable;
use std;
use core::io;
+ use core::option::Option;
+ use core::option::Some;
use core::option::None;
+ use core::int;
+ use core::num::NumCast;
+ use core::path::Path;
+ use codemap::{dummy_sp, CodeMap, span, BytePos, spanned};
+ use opt_vec;
use ast;
+ use abi;
+ use ast_util::mk_ident;
+ use parse::parser::Parser;
+ use parse::token::{ident_interner, mk_ident_interner, mk_fresh_ident_interner};
+ use diagnostic::{span_handler, mk_span_handler, mk_handler, Emitter};
+
+ // add known names to interner for testing
+ fn mk_testing_interner() -> @ident_interner {
+ let i = mk_fresh_ident_interner();
+ // baby hack; in order to put the identifiers
+ // 'a' and 'b' at known locations, we're going
+ // to fill up the interner to length 100. If
+ // the # of preloaded items on the interner
+ // ever gets larger than 100, we'll have to
+ // adjust this number (say, to 200) and
+ // change the numbers in the identifier
+ // test cases below.
+
+ assert!(i.len() < 100);
+ for int::range(0,100-((i.len()).to_int())) |_dc| {
+ i.gensym(@~"dontcare");
+ }
+ i.intern(@~"a");
+ i.intern(@~"b");
+ i.intern(@~"c");
+ i.intern(@~"d");
+ i.intern(@~"return");
+ assert!(i.get(ast::ident{repr:101,ctxt:0}) == @~"b");
+ i
+ }
+
+ // make a parse_sess that's closed over a
+ // testing interner (where a -> 100, b -> 101)
+ fn mk_testing_parse_sess() -> @mut ParseSess {
+ let interner = mk_testing_interner();
+ let cm = @CodeMap::new();
+ @mut ParseSess {
+ cm: cm,
+ next_id: 1,
+ span_diagnostic: mk_span_handler(mk_handler(None), cm),
+ interner: interner,
+ }
+ }
+
+ // map a string to tts, using a made-up filename: return both the token_trees
+ // and the ParseSess
+ fn string_to_tts_t (source_str : @~str) -> (~[ast::token_tree],@mut ParseSess) {
+ let ps = mk_testing_parse_sess();
+ (filemap_to_tts(ps,string_to_filemap(ps,source_str,~"bogofile")),ps)
+ }
+
+ // map a string to tts, return the tt without its parsesess
+ fn string_to_tts_only(source_str : @~str) -> ~[ast::token_tree] {
+ let (tts,ps) = string_to_tts_t(source_str);
+ tts
+ }
+
+ // map string to parser (via tts)
+ fn string_to_parser(source_str: @~str) -> Parser {
+ let ps = mk_testing_parse_sess();
+ new_parser_from_source_str(ps,~[],~"bogofile",source_str)
+ }
#[test] fn to_json_str<E : Encodable<std::json::Encoder>>(val: @E) -> ~str {
do io::with_str_writer |writer| {
}
fn string_to_crate (source_str : @~str) -> @ast::crate {
- parse_crate_from_source_str(
- ~"bogofile",
- source_str,
- ~[],
- new_parse_sess(None))
+ string_to_parser(source_str).parse_crate_mod()
}
- fn string_to_tt_to_crate (source_str : @~str) -> @ast::crate {
- let tts = parse_tts_from_source_str(
- ~"bogofile",
- source_str,
- ~[],
- new_parse_sess(None));
- new_parser_from_tts(new_parse_sess(None),~[],tts)
- .parse_crate_mod(~[])
+ fn string_to_expr (source_str : @~str) -> @ast::expr {
+ string_to_parser(source_str).parse_expr()
}
- // make sure that parsing from TTs produces the same result
- // as parsing from strings
- #[test] fn tts_produce_the_same_result () {
- let source_str = @~"fn foo (x : int) { x; }";
- assert_eq!(string_to_tt_to_crate(source_str),
- string_to_crate(source_str));
+ fn string_to_item (source_str : @~str) -> Option<@ast::item> {
+ string_to_parser(source_str).parse_item(~[])
}
- // check the contents of the tt manually:
- #[test] fn alltts () {
- let source_str = @~"fn foo (x : int) { x; }";
- let tts = parse_tts_from_source_str(
- ~"bogofile",
- source_str,
- ~[],
- new_parse_sess(None));
- assert_eq!(
- to_json_str(@tts),
- ~"[\
+ fn string_to_stmt (source_str : @~str) -> @ast::stmt {
+ string_to_parser(source_str).parse_stmt(~[])
+ }
+
+ // produce a codemap::span
+ fn sp (a: uint, b: uint) -> span {
+ span{lo:BytePos(a),hi:BytePos(b),expn_info:None}
+ }
+
+ // convert a vector of uints to a vector of ast::idents
+ fn ints_to_idents(ids: ~[uint]) -> ~[ast::ident] {
+ ids.map(|u| mk_ident(*u))
+ }
+
+ #[test] fn path_exprs_1 () {
+ assert_eq!(string_to_expr(@~"a"),
+ @ast::expr{id:1,
+ callee_id:2,
+ node:ast::expr_path(@ast::Path {span:sp(0,1),
+ global:false,
+ idents:~[mk_ident(100)],
+ rp:None,
+ types:~[]}),
+ span:sp(0,1)})
+ }
+
+ #[test] fn path_exprs_2 () {
+ assert_eq!(string_to_expr(@~"::a::b"),
+ @ast::expr{id:1,
+ callee_id:2,
+ node:ast::expr_path(@ast::Path {span:sp(0,6),
+ global:true,
+ idents:ints_to_idents(~[100,101]),
+ rp:None,
+ types:~[]}),
+ span:sp(0,6)})
+ }
+
+ #[should_fail]
+ #[test] fn bad_path_expr_1() {
+ string_to_expr(@~"::abc::def::return");
+ }
+
+ #[test] fn string_to_tts_1 () {
+ let (tts,ps) = string_to_tts_t(@~"fn a (b : int) { b; }");
+ assert_eq!(to_json_str(@tts),
+ ~"[\
[\"tt_tok\",null,[\"IDENT\",\"fn\",false]],\
- [\"tt_tok\",null,[\"IDENT\",\"foo\",false]],\
+ [\"tt_tok\",null,[\"IDENT\",\"a\",false]],\
[\
\"tt_delim\",\
[\
[\"tt_tok\",null,\"LPAREN\"],\
- [\"tt_tok\",null,[\"IDENT\",\"x\",false]],\
+ [\"tt_tok\",null,[\"IDENT\",\"b\",false]],\
[\"tt_tok\",null,\"COLON\"],\
[\"tt_tok\",null,[\"IDENT\",\"int\",false]],\
[\"tt_tok\",null,\"RPAREN\"]\
\"tt_delim\",\
[\
[\"tt_tok\",null,\"LBRACE\"],\
- [\"tt_tok\",null,[\"IDENT\",\"x\",false]],\
+ [\"tt_tok\",null,[\"IDENT\",\"b\",false]],\
[\"tt_tok\",null,\"SEMI\"],\
[\"tt_tok\",null,\"RBRACE\"]\
]\
]\
]"
- );
- let ast1 = new_parser_from_tts(new_parse_sess(None),~[],tts)
- .parse_item(~[]);
- let ast2 = parse_item_from_source_str(
- ~"bogofile",
- @~"fn foo (x : int) { x; }",
- ~[],~[],
- new_parse_sess(None));
- assert_eq!(ast1,ast2);
+ );
+ }
+
+ #[test] fn ret_expr() {
+ assert_eq!(string_to_expr(@~"return d"),
+ @ast::expr{id:3,
+ callee_id:4,
+ node:ast::expr_ret(
+ Some(@ast::expr{id:1,callee_id:2,
+ node:ast::expr_path(
+ @ast::Path{span:sp(7,8),
+ global:false,
+ idents:~[mk_ident(103)],
+ rp:None,
+ types:~[]
+ }),
+ span:sp(7,8)})),
+ span:sp(0,8)})
+ }
+
+ #[test] fn parse_stmt_1 () {
+ assert_eq!(string_to_stmt(@~"b;"),
+ @spanned{
+ node: ast::stmt_expr(@ast::expr{
+ id: 1,
+ callee_id: 2,
+ node: ast::expr_path(
+ @ast::Path{
+ span:sp(0,1),
+ global:false,
+ idents:~[mk_ident(101)],
+ rp:None,
+ types: ~[]}),
+ span: sp(0,1)},
+ 3), // fixme
+ span: sp(0,1)})
+
+ }
+
+ fn parser_done(p: Parser){
+ assert_eq!(*p.token,token::EOF);
+ }
+
+ #[test] fn parse_ident_pat () {
+ let parser = string_to_parser(@~"b");
+ assert_eq!(parser.parse_pat(false),
+ @ast::pat{id:1, // fixme
+ node: ast::pat_ident(ast::bind_by_copy,
+ @ast::Path{
+ span:sp(0,1),
+ global:false,
+ idents:~[mk_ident(101)],
+ rp: None,
+ types: ~[]},
+ None // no idea
+ ),
+ span: sp(0,1)});
+ parser_done(parser);
+ }
+
+ #[test] fn parse_arg () {
+ let parser = string_to_parser(@~"b : int");
+ assert_eq!(parser.parse_arg_general(true),
+ ast::arg{
+ is_mutbl: false,
+ ty: @ast::Ty{id:3, // fixme
+ node: ast::ty_path(@ast::Path{
+ span:sp(4,4), // this is bizarre...
+ // check this in the original parser?
+ global:false,
+ idents:~[mk_ident(105)],
+ rp: None,
+ types: ~[]},
+ 2),
+ span:sp(4,7)},
+ pat: @ast::pat{id:1,
+ node: ast::pat_ident(ast::bind_by_copy,
+ @ast::Path{
+ span:sp(0,1),
+ global:false,
+ idents:~[mk_ident(101)],
+ rp: None,
+ types: ~[]},
+ None // no idea
+ ),
+ span: sp(0,3)}, // really?
+ id: 4 // fixme
+ })
+ }
+
+ // check the contents of the tt manually:
+ #[test] fn parse_fundecl () {
+ // this test depends on the intern order of "fn" and "int", and on the
+ // assignment order of the node_ids.
+ assert_eq!(string_to_item(@~"fn a (b : int) { b; }"),
+ Some(
+ @ast::item{ident:mk_ident(100),
+ attrs:~[],
+ id: 10, // fixme
+ node: ast::item_fn(ast::fn_decl{
+ inputs: ~[ast::arg{
+ is_mutbl: false,
+ ty: @ast::Ty{id:3, // fixme
+ node: ast::ty_path(@ast::Path{
+ span:sp(10,13),
+ global:false,
+ idents:~[mk_ident(106)],
+ rp: None,
+ types: ~[]},
+ 2),
+ span:sp(10,13)},
+ pat: @ast::pat{id:1, // fixme
+ node: ast::pat_ident(
+ ast::bind_by_copy,
+ @ast::Path{
+ span:sp(6,7),
+ global:false,
+ idents:~[mk_ident(101)],
+ rp: None,
+ types: ~[]},
+ None // no idea
+ ),
+ span: sp(6,9)}, // bleah.
+ id: 4 // fixme
+ }],
+ output: @ast::Ty{id:5, // fixme
+ node: ast::ty_nil,
+ span:sp(15,15)}, // not sure
+ cf: ast::return_val
+ },
+ ast::impure_fn,
+ abi::AbiSet::Rust(),
+ ast::Generics{ // no idea on either of these:
+ lifetimes: opt_vec::Empty,
+ ty_params: opt_vec::Empty,
+ },
+ spanned{
+ span: sp(15,21),
+ node: ast::blk_{
+ view_items: ~[],
+ stmts: ~[@spanned{
+ node: ast::stmt_semi(@ast::expr{
+ id: 6,
+ callee_id: 7,
+ node: ast::expr_path(
+ @ast::Path{
+ span:sp(17,18),
+ global:false,
+ idents:~[mk_ident(101)],
+ rp:None,
+ types: ~[]}),
+ span: sp(17,18)},
+ 8), // fixme
+ span: sp(17,18)}],
+ expr: None,
+ id: 9, // fixme
+ rules: ast::default_blk // no idea
+ }}),
+ vis: ast::inherited,
+ span: sp(0,21)}));
+ }
+
+
+ #[test] fn parse_exprs () {
+ // just make sure that they parse....
+ string_to_expr(@~"3 + 4");
+ string_to_expr(@~"a::z.froob(b,@(987+3))");
}
}
removed.
*/
-use core::prelude::*;
use ast::{expr, expr_lit, lit_nil};
use ast;
use parse::token::Token;
use parse::token;
-use core::str;
use core::to_bytes;
/// The specific types of unsupported syntax
fn try_parse_obsolete_struct_ctor(&self) -> bool {
if self.eat_obsolete_ident("new") {
self.obsolete(*self.last_span, ObsoleteStructCtor);
- self.parse_fn_decl(|p| p.parse_arg());
+ self.parse_fn_decl();
self.parse_block();
true
} else {
self.eat_keyword(&~"priv");
self.bump();
while *self.token != token::RBRACE {
- self.parse_single_class_item(ast::private);
+ self.parse_single_struct_field(ast::private);
}
self.bump();
true
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use abi;
use abi::AbiSet;
use ast::{Sigil, BorrowedSigil, ManagedSigil, OwnedSigil};
use ast::{provided, public, purity};
use ast::{_mod, add, arg, arm, attribute, bind_by_ref, bind_infer};
use ast::{bind_by_copy, bitand, bitor, bitxor, blk};
-use ast::{blk_check_mode, box, by_copy, by_ref};
+use ast::{blk_check_mode, box};
use ast::{crate, crate_cfg, decl, decl_item};
use ast::{decl_local, default_blk, deref, quot, enum_def};
-use ast::{expl, expr, expr_, expr_addr_of, expr_match, expr_again};
+use ast::{expr, expr_, expr_addr_of, expr_match, expr_again};
use ast::{expr_assign, expr_assign_op, expr_binary, expr_block};
use ast::{expr_break, expr_call, expr_cast, expr_copy, expr_do_body};
use ast::{expr_field, expr_fn_block, expr_if, expr_index};
use ast::{expr_vstore_mut_slice, expr_while, extern_fn, field, fn_decl};
use ast::{expr_vstore_uniq, TyClosure, TyBareFn, Onceness, Once, Many};
use ast::{foreign_item, foreign_item_const, foreign_item_fn, foreign_mod};
-use ast::{ident, impure_fn, infer, inherited, item, item_, item_const};
+use ast::{ident, impure_fn, inherited, item, item_, item_const};
use ast::{item_const, item_enum, item_fn, item_foreign_mod, item_impl};
use ast::{item_mac, item_mod, item_struct, item_trait, item_ty, lit, lit_};
use ast::{lit_bool, lit_float, lit_float_unsuffixed, lit_int};
use ast::{lit_int_unsuffixed, lit_nil, lit_str, lit_uint, local, m_const};
use ast::{m_imm, m_mutbl, mac_, mac_invoc_tt, matcher, match_nonterminal};
-use ast::{match_seq, match_tok, method, mode, mt, mul, mutability};
+use ast::{match_seq, match_tok, method, mt, mul, mutability};
use ast::{named_field, neg, node_id, noreturn, not, pat, pat_box, pat_enum};
use ast::{pat_ident, pat_lit, pat_range, pat_region, pat_struct};
use ast::{pat_tup, pat_uniq, pat_wild, private};
use ast::{view_path, view_path_glob, view_path_list, view_path_simple};
use ast::visibility;
use ast;
-use ast_util::{ident_to_path, operator_prec};
+use ast_util::{as_prec, ident_to_path, operator_prec};
use ast_util;
use codemap::{span, BytePos, spanned, mk_sp};
use codemap;
use parse::obsolete::{ObsoleteLifetimeNotation, ObsoleteConstManagedPointer};
use parse::obsolete::{ObsoletePurity, ObsoleteStaticMethod};
use parse::obsolete::{ObsoleteConstItem, ObsoleteFixedLengthVectorType};
-use parse::prec::{as_prec, token_to_binop};
use parse::token::{can_begin_expr, is_ident, is_ident_or_path};
-use parse::token::{is_plain_ident, INTERPOLATED, special_idents};
+use parse::token::{is_plain_ident, INTERPOLATED, special_idents, token_to_binop};
use parse::token;
use parse::{new_sub_parser_from_file, next_node_id, ParseSess};
use opt_vec;
enum restriction {
UNRESTRICTED,
RESTRICT_STMT_EXPR,
- RESTRICT_NO_CALL_EXPRS,
RESTRICT_NO_BAR_OP,
RESTRICT_NO_BAR_OR_DOUBLEBAR_OP,
}
self.token_is_keyword(&~"fn", tok)
}
+ fn token_is_lifetime(&self, tok: &token::Token) -> bool {
+ match *tok {
+ token::LIFETIME(*) => true,
+ _ => false,
+ }
+ }
+
+ fn get_lifetime(&self, tok: &token::Token) -> ast::ident {
+ match *tok {
+ token::LIFETIME(ref ident) => copy *ident,
+ _ => self.bug(~"not a lifetime"),
+ }
+ }
+
// parse a ty_bare_fun type:
fn parse_ty_bare_fn(&self) -> ty_
{
let opt_abis = self.parse_opt_abis();
let abis = opt_abis.get_or_default(AbiSet::Rust());
- let purity = self.parse_purity();
+ let purity = self.parse_unsafety();
self.expect_keyword(&~"fn");
let (decl, lifetimes) = self.parse_ty_fn_decl();
return ty_bare_fn(@TyBareFn {
// At this point, the allocation type and lifetime bound have been
// parsed.
- let purity = self.parse_purity();
+ let purity = self.parse_unsafety();
let onceness = parse_onceness(self);
self.expect_keyword(&~"fn");
}
}
- fn parse_purity(&self) -> purity {
+ // looks like this should be called parse_unsafety
+ fn parse_unsafety(&self) -> purity {
if self.eat_keyword(&~"pure") {
self.obsolete(*self.last_span, ObsoletePurity);
return impure_fn;
(decl, lifetimes)
}
+ // parse the methods in a trait declaration
fn parse_trait_methods(&self) -> ~[trait_method] {
do self.parse_unspanned_seq(
&token::LBRACE,
token::LBRACE => {
debug!("parse_trait_methods(): parsing provided method");
let (inner_attrs, body) =
- p.parse_inner_attrs_and_block(true);
+ p.parse_inner_attrs_and_block();
let attrs = vec::append(attrs, inner_attrs);
provided(@ast::method {
ident: ident,
}
// parse [mut/const/imm] ID : TY
+ // now used only by obsolete record syntax parser...
fn parse_ty_field(&self) -> ty_field {
let lo = self.span.lo;
let mutbl = self.parse_mutability();
return ty_rptr(opt_lifetime, mt);
}
- fn parse_arg_mode(&self) -> mode {
+ // parse an optional mode.
+ // XXX: Remove after snapshot.
+ fn parse_arg_mode(&self) {
if self.eat(&token::BINOP(token::MINUS)) {
self.obsolete(*self.span, ObsoleteMode);
- expl(by_copy)
} else if self.eat(&token::ANDAND) {
- expl(by_ref)
+ // Ignore.
} else if self.eat(&token::BINOP(token::PLUS)) {
if self.eat(&token::BINOP(token::PLUS)) {
// ++ mode is obsolete, but we need a snapshot
// to stop parsing it.
- expl(by_copy)
+ // Ignore.
} else {
- expl(by_copy)
+ // Ignore.
}
} else {
- infer(self.get_id())
+ // Ignore.
}
}
// This version of parse arg doesn't necessarily require
// identifier names.
fn parse_arg_general(&self, require_name: bool) -> arg {
- let m;
let mut is_mutbl = false;
let pat = if require_name || self.is_named_argument() {
- m = self.parse_arg_mode();
+ self.parse_arg_mode();
is_mutbl = self.eat_keyword(&~"mut");
let pat = self.parse_pat(false);
self.expect(&token::COLON);
pat
} else {
- m = infer(self.get_id());
ast_util::ident_to_pat(self.get_id(),
*self.last_span,
special_idents::invalid)
let t = self.parse_ty(false);
- ast::arg { mode: m, is_mutbl: is_mutbl,
- ty: t, pat: pat, id: self.get_id() }
+ ast::arg {
+ is_mutbl: is_mutbl,
+ ty: t,
+ pat: pat,
+ id: self.get_id(),
+ }
}
+ // parse a single function argument
fn parse_arg(&self) -> arg_or_capture_item {
either::Left(self.parse_arg_general(true))
}
+ // parse an argument in a lambda header e.g. |arg, arg|
fn parse_fn_block_arg(&self) -> arg_or_capture_item {
- let m = self.parse_arg_mode();
+ self.parse_arg_mode();
let is_mutbl = self.eat_keyword(&~"mut");
let pat = self.parse_pat(false);
let t = if self.eat(&token::COLON) {
}
};
either::Left(ast::arg {
- mode: m,
is_mutbl: is_mutbl,
ty: t,
pat: pat,
}
}
+ // matches token_lit = LIT_INT | ...
fn lit_from_token(&self, tok: &token::Token) -> lit_ {
match *tok {
token::LIT_INT(i, it) => lit_int(i, it),
}
}
+ // matches lit = true | false | token_lit
fn parse_lit(&self) -> lit {
let lo = self.span.lo;
let lit = if self.eat_keyword(&~"true") {
codemap::spanned { node: lit, span: mk_sp(lo, self.last_span.hi) }
}
- // parse a path that doesn't have type parameters attached
- fn parse_path_without_tps(&self)
- -> @ast::Path {
- maybe_whole!(self, nt_path);
+ // parse a path into a vector of idents, whether the path starts
+ // with ::, and a span.
+ fn parse_path(&self) -> (~[ast::ident],bool,span) {
+ let lo = self.span.lo;
+ let is_global = self.eat(&token::MOD_SEP);
+ let (ids,span{lo:_,hi,expn_info}) = self.parse_path_non_global();
+ (ids,is_global,span{lo:lo,hi:hi,expn_info:expn_info})
+ }
+
+ // parse a path beginning with an identifier into a vector of idents and a span
+ fn parse_path_non_global(&self) -> (~[ast::ident],span) {
let lo = self.span.lo;
- let global = self.eat(&token::MOD_SEP);
let mut ids = ~[];
+ // must be at least one to begin:
+ ids.push(self.parse_ident());
loop {
- // if there's a ::< coming, stop processing
- // the path.
- let is_not_last =
- self.look_ahead(2u) != token::LT
- && self.look_ahead(1u) == token::MOD_SEP;
-
- if is_not_last {
- ids.push(self.parse_ident());
- self.expect(&token::MOD_SEP);
- } else {
- ids.push(self.parse_ident());
- break;
+ match *self.token {
+ token::MOD_SEP => {
+ match self.look_ahead(1u) {
+ token::IDENT(id,_) => {
+ self.bump();
+ ids.push(self.parse_ident());
+ }
+ _ => break
+ }
+ }
+ _ => break
}
}
- @ast::Path { span: mk_sp(lo, self.last_span.hi),
- global: global,
+ (ids, mk_sp(lo, self.last_span.hi))
+ }
+
+ // parse a path that doesn't have type parameters attached
+ fn parse_path_without_tps(&self)
+ -> @ast::Path {
+ maybe_whole!(self, nt_path);
+ let (ids,is_global,sp) = self.parse_path();
+ @ast::Path { span: sp,
+ global: is_global,
idents: ids,
rp: None,
types: ~[] }
}
}
+ // matches lifetimes = ( lifetime ) | ( lifetime , lifetimes )
+ // actually, it matches the empty one too, but putting that in there
+ // messes up the grammar....
fn parse_lifetimes(&self) -> OptVec<ast::Lifetime> {
/*!
*
token::GT => { return res; }
token::BINOP(token::SHR) => { return res; }
_ => {
- self.fatal(~"expected `,` or `>` after lifetime name");
+ self.fatal(fmt!("expected `,` or `>` after lifetime name, got: %?",
+ *self.token));
}
}
}
}
}
- fn parse_field(&self, sep: token::Token) -> field {
+ // parse ident COLON expr
+ fn parse_field(&self) -> field {
let lo = self.span.lo;
let m = self.parse_mutability();
let i = self.parse_ident();
- self.expect(&sep);
+ self.expect(&token::COLON);
let e = self.parse_expr();
spanned(lo, e.span.hi, ast::field_ { mutbl: m, ident: i, expr: e })
}
self.bump();
// (e) is parenthesized e
// (e,) is a tuple with only one field, e
- let mut one_tuple = false;
+ let mut trailing_comma = false;
if *self.token == token::RPAREN {
hi = self.span.hi;
self.bump();
es.push(self.parse_expr());
}
else {
- one_tuple = true;
+ trailing_comma = true;
}
}
hi = self.span.hi;
self.expect(&token::RPAREN);
- return if es.len() == 1 && !one_tuple {
+ return if es.len() == 1 && !trailing_comma {
self.mk_expr(lo, self.span.hi, expr_paren(es[0]))
}
else {
expr_do_body);
} else if self.eat_keyword(&~"while") {
return self.parse_while_expr();
+ } else if self.token_is_lifetime(&*self.token) {
+ let lifetime = self.get_lifetime(&*self.token);
+ self.bump();
+ self.expect(&token::COLON);
+ self.expect_keyword(&~"loop");
+ return self.parse_loop_expr(Some(lifetime));
} else if self.eat_keyword(&~"loop") {
- return self.parse_loop_expr();
+ return self.parse_loop_expr(None);
} else if self.eat_keyword(&~"match") {
return self.parse_match_expr();
} else if self.eat_keyword(&~"unsafe") {
}
hi = self.span.hi;
} else if self.eat_keyword(&~"__log") {
+ // LOG expression
self.expect(&token::LPAREN);
let lvl = self.parse_expr();
self.expect(&token::COMMA);
hi = self.span.hi;
self.expect(&token::RPAREN);
} else if self.eat_keyword(&~"return") {
+ // RETURN expression
if can_begin_expr(&*self.token) {
let e = self.parse_expr();
hi = e.span.hi;
ex = expr_ret(Some(e));
} else { ex = expr_ret(None); }
} else if self.eat_keyword(&~"break") {
- if is_ident(&*self.token) {
- ex = expr_break(Some(self.parse_ident()));
+ // BREAK expression
+ if self.token_is_lifetime(&*self.token) {
+ let lifetime = self.get_lifetime(&*self.token);
+ self.bump();
+ ex = expr_break(Some(lifetime));
} else {
ex = expr_break(None);
}
hi = self.span.hi;
} else if self.eat_keyword(&~"copy") {
+ // COPY expression
let e = self.parse_expr();
ex = expr_copy(e);
hi = e.span.hi;
// `!`, as an operator, is prefix, so we know this isn't that
if *self.token == token::NOT {
+ // MACRO INVOCATION expression
self.bump();
match *self.token {
token::LPAREN | token::LBRACE => {}
let mut fields = ~[];
let mut base = None;
- fields.push(self.parse_field(token::COLON));
+ fields.push(self.parse_field());
while *self.token != token::RBRACE {
if self.try_parse_obsolete_with() {
break;
// Accept an optional trailing comma.
break;
}
- fields.push(self.parse_field(token::COLON));
+ fields.push(self.parse_field());
}
hi = pth.span.hi;
hi = pth.span.hi;
ex = expr_path(pth);
} else {
+ // other literal expression
let lit = self.parse_lit();
hi = lit.span.hi;
ex = expr_lit(@lit);
return self.mk_expr(lo, hi, ex);
}
+ // parse a block or unsafe block
fn parse_block_expr(
&self,
lo: BytePos,
return self.mk_expr(blk.span.lo, blk.span.hi, expr_block(blk));
}
- // parse a.b or a(13) or just a
+ // parse a.b or a(13) or a[4] or just a
fn parse_dot_or_call_expr(&self) -> @expr {
let b = self.parse_bottom_expr();
self.parse_dot_or_call_expr_with(b)
}
- fn permits_call(&self) -> bool {
- return *self.restriction != RESTRICT_NO_CALL_EXPRS;
- }
-
fn parse_dot_or_call_expr_with(&self, e0: @expr) -> @expr {
let mut e = e0;
let lo = e.span.lo;
// expr.f() method call
match *self.token {
- token::LPAREN if self.permits_call() => {
+ token::LPAREN => {
let es = self.parse_unspanned_seq(
&token::LPAREN,
&token::RPAREN,
if self.expr_is_complete(e) { break; }
match *self.token {
// expr(...)
- token::LPAREN if self.permits_call() => {
+ token::LPAREN => {
let es = self.parse_unspanned_seq(
&token::LPAREN,
&token::RPAREN,
let lo = self.span.lo;
let lhs = self.parse_binops();
match *self.token {
- token::EQ => {
- self.bump();
- let rhs = self.parse_expr();
- self.mk_expr(lo, rhs.span.hi, expr_assign(lhs, rhs))
+ token::EQ => {
+ self.bump();
+ let rhs = self.parse_expr();
+ self.mk_expr(lo, rhs.span.hi, expr_assign(lhs, rhs))
}
token::BINOPEQ(op) => {
self.bump();
}
}
+ // parse an 'if' expression ('if' token already eaten)
fn parse_if_expr(&self) -> @expr {
let lo = self.last_span.lo;
let cond = self.parse_expr();
self.mk_expr(lo, hi, expr_if(cond, thn, els))
}
- // `|args| { ... }` like in `do` expressions
+ // `|args| { ... }` or `{ ...}` like in `do` expressions
fn parse_lambda_block_expr(&self) -> @expr {
self.parse_lambda_expr_(
|| {
|| self.parse_expr())
}
+ // parse something of the form |args| expr
+ // this is used both in parsing a lambda expr
+ // and in parsing a block expr as e.g. in for...
fn parse_lambda_expr_(
&self,
parse_decl: &fn() -> fn_decl,
}
}
+ // parse a 'for' or 'do'.
+ // the 'for' and 'do' expressions parse as calls, but look like
+ // function calls followed by a closure expression.
fn parse_sugary_call_expr(&self, keyword: ~str,
sugar: CallSugar,
ctor: &fn(v: @expr) -> expr_) -> @expr {
fn parse_while_expr(&self) -> @expr {
let lo = self.last_span.lo;
let cond = self.parse_expr();
- let body = self.parse_block_no_value();
+ let body = self.parse_block();
let hi = body.span.hi;
return self.mk_expr(lo, hi, expr_while(cond, body));
}
- fn parse_loop_expr(&self) -> @expr {
+ fn parse_loop_expr(&self, opt_ident: Option<ast::ident>) -> @expr {
// loop headers look like 'loop {' or 'loop unsafe {'
let is_loop_header =
*self.token == token::LBRACE
|| (is_ident(&*self.token)
&& self.look_ahead(1) == token::LBRACE);
- // labeled loop headers look like 'loop foo: {'
- let is_labeled_loop_header =
- is_ident(&*self.token)
- && !self.is_any_keyword(© *self.token)
- && self.look_ahead(1) == token::COLON;
- if is_loop_header || is_labeled_loop_header {
+ if is_loop_header {
// This is a loop body
- let opt_ident;
- if is_labeled_loop_header {
- opt_ident = Some(self.parse_ident());
- self.expect(&token::COLON);
- } else {
- opt_ident = None;
- }
-
let lo = self.last_span.lo;
- let body = self.parse_block_no_value();
+ let body = self.parse_block();
let hi = body.span.hi;
return self.mk_expr(lo, hi, expr_loop(body, opt_ident));
} else {
// This is a 'continue' expression
+ if opt_ident.is_some() {
+ self.span_err(*self.last_span,
+ ~"a label may not be used with a `loop` \
+ expression");
+ }
+
let lo = self.span.lo;
- let ex = if is_ident(&*self.token) {
- expr_again(Some(self.parse_ident()))
+ let ex = if self.token_is_lifetime(&*self.token) {
+ let lifetime = self.get_lifetime(&*self.token);
+ self.bump();
+ expr_again(Some(lifetime))
} else {
expr_again(None)
};
}
}
+ // parse patterns, separated by '|' s
fn parse_pats(&self) -> ~[@pat] {
let mut pats = ~[];
loop {
(before, slice, after)
}
+ // parse the fields of a struct-like pattern
fn parse_pat_fields(&self, refutable: bool) -> (~[ast::field_pat], bool) {
let mut fields = ~[];
let mut etc = false;
return (fields, etc);
}
+ // parse a pattern. The 'refutable' argument
+ // appears to control whether the binding_mode
+ // 'bind_infer' or 'bind_by_copy' is used.
fn parse_pat(&self, refutable: bool) -> @pat {
maybe_whole!(self, nt_pat);
let mut hi = self.span.hi;
let pat;
match *self.token {
+ // parse _
token::UNDERSCORE => { self.bump(); pat = pat_wild; }
+ // parse @pat
token::AT => {
self.bump();
let sub = self.parse_pat(refutable);
};
}
token::TILDE => {
+ // parse ~pat
self.bump();
let sub = self.parse_pat(refutable);
hi = sub.span.hi;
};
}
token::BINOP(token::AND) => {
+ // parse &pat
let lo = self.span.lo;
self.bump();
let sub = self.parse_pat(refutable);
pat = pat_wild;
}
token::LPAREN => {
+ // parse (pat,pat,pat,...) as tuple
self.bump();
if *self.token == token::RPAREN {
hi = self.span.hi;
}
}
token::LBRACKET => {
+ // parse [pat,pat,...] as vector pattern
self.bump();
let (before, slice, after) =
self.parse_pat_vec_elements(refutable);
|| self.is_keyword(&~"true")
|| self.is_keyword(&~"false")
{
+ // parse an expression pattern or exp .. exp
let val = self.parse_expr_res(RESTRICT_NO_BAR_OP);
if self.eat(&token::DOTDOT) {
let end = self.parse_expr_res(RESTRICT_NO_BAR_OP);
pat = pat_lit(val);
}
} else if self.eat_keyword(&~"ref") {
+ // parse ref pat
let mutbl = self.parse_mutability();
pat = self.parse_pat_ident(refutable, bind_by_ref(mutbl));
} else if self.eat_keyword(&~"copy") {
+ // parse copy pat
pat = self.parse_pat_ident(refutable, bind_by_copy);
} else {
// XXX---refutable match bindings should work same as let
let binding_mode =
if refutable {bind_infer} else {bind_by_copy};
- let cannot_be_enum_or_struct;
+ let can_be_enum_or_struct;
match self.look_ahead(1) {
token::LPAREN | token::LBRACKET | token::LT |
token::LBRACE | token::MOD_SEP =>
- cannot_be_enum_or_struct = false,
+ can_be_enum_or_struct = true,
_ =>
- cannot_be_enum_or_struct = true
+ can_be_enum_or_struct = false
}
- if is_plain_ident(&*self.token) && cannot_be_enum_or_struct {
+ if is_plain_ident(&*self.token) && !can_be_enum_or_struct {
let name = self.parse_path_without_tps();
let sub;
if self.eat(&token::AT) {
+ // parse foo @ pat
sub = Some(self.parse_pat(refutable));
} else {
+ // or just foo
sub = None;
};
pat = pat_ident(binding_mode, name, sub);
} else {
+ // parse an enum pat
let enum_path = self.parse_path_with_tps(true);
match *self.token {
token::LBRACE => {
}
_ => {
let mut args: ~[@pat] = ~[];
- let mut star_pat = false;
match *self.token {
token::LPAREN => match self.look_ahead(1u) {
token::BINOP(token::STAR) => {
// This is a "top constructor only" pat
self.bump(); self.bump();
- star_pat = true;
self.expect(&token::RPAREN);
+ pat = pat_enum(enum_path, None);
}
_ => {
args = self.parse_unspanned_seq(
),
|p| p.parse_pat(refutable)
);
+ pat = pat_enum(enum_path, Some(args));
}
},
- _ => ()
- }
- // at this point, we're not sure whether it's a
- // enum or a bind
- if star_pat {
- pat = pat_enum(enum_path, None);
- }
- else if vec::is_empty(args) &&
- vec::len(enum_path.idents) == 1u {
- pat = pat_ident(binding_mode,
- enum_path,
- None);
- }
- else {
- pat = pat_enum(enum_path, Some(args));
+ _ => {
+ if vec::len(enum_path.idents)==1u {
+ // it could still be either an enum
+ // or an identifier pattern, resolve
+ // will sort it out:
+ pat = pat_ident(binding_mode,
+ enum_path,
+ None);
+ } else {
+ pat = pat_enum(enum_path, Some(args));
+ }
+ }
}
}
}
@ast::pat { id: self.get_id(), node: pat, span: mk_sp(lo, hi) }
}
- fn parse_pat_ident(&self, refutable: bool,
- binding_mode: ast::binding_mode) -> ast::pat_ {
+ // used by the copy foo and ref foo patterns to give a good
+ // error message when parsing mistakes like ref foo(a,b)
+ fn parse_pat_ident(&self,
+ refutable: bool,
+ binding_mode: ast::binding_mode)
+ -> ast::pat_ {
if !is_plain_ident(&*self.token) {
- self.span_fatal(
- *self.last_span,
- ~"expected identifier, found path");
+ self.span_fatal(*self.last_span,
+ ~"expected identifier, found path");
}
+ // why a path here, and not just an identifier?
let name = self.parse_path_without_tps();
let sub = if self.eat(&token::AT) {
Some(self.parse_pat(refutable))
- } else { None };
+ } else {
+ None
+ };
// just to be friendly, if they write something like
// ref Some(i)
}
// parse a local variable declaration
- fn parse_local(&self, is_mutbl: bool,
- allow_init: bool) -> @local {
+ fn parse_local(&self, is_mutbl: bool) -> @local {
let lo = self.span.lo;
let pat = self.parse_pat(false);
let mut ty = @Ty {
span: mk_sp(lo, lo),
};
if self.eat(&token::COLON) { ty = self.parse_ty(false); }
- let init = if allow_init { self.parse_initializer() } else { None };
+ let init = self.parse_initializer();
@spanned(
lo,
self.last_span.hi,
)
}
+ // parse a "let" stmt
fn parse_let(&self) -> @decl {
let is_mutbl = self.eat_keyword(&~"mut");
let lo = self.span.lo;
- let mut locals = ~[self.parse_local(is_mutbl, true)];
+ let mut locals = ~[self.parse_local(is_mutbl)];
while self.eat(&token::COMMA) {
- locals.push(self.parse_local(is_mutbl, true));
+ locals.push(self.parse_local(is_mutbl));
}
return @spanned(lo, self.last_span.hi, decl_local(locals));
}
- /* assumes "let" token has already been consumed */
- fn parse_instance_var(&self, pr: visibility) -> @struct_field {
+ // parse a structure field
+ fn parse_name_and_ty(&self, pr: visibility) -> @struct_field {
let mut is_mutbl = struct_immutable;
let lo = self.span.lo;
if self.eat_keyword(&~"mut") {
})
}
+ // parse a statement. may include decl
fn parse_stmt(&self, first_item_attrs: ~[attribute]) -> @stmt {
maybe_whole!(self, nt_stmt);
} else if is_ident(&*self.token)
&& !self.is_any_keyword(© *self.token)
&& self.look_ahead(1) == token::NOT {
+ // parse a macro invocation. Looks like there's serious
+ // overlap here; if this clause doesn't catch it (and it
+ // won't, for brace-delimited macros) it will fall through
+ // to the macro clause of parse_item_or_view_item. This
+ // could use some cleanup, it appears to me.
check_expected_item(self, first_item_attrs);
self.parse_outer_attributes());
match self.parse_item_or_view_item(/*bad*/ copy item_attrs,
- true, false, false) {
+ false) {
iovi_item(i) => {
let hi = i.span.hi;
let decl = @spanned(lo, hi, decl_item(i));
}
}
+ // is this expression a successfully-parsed statement?
fn expr_is_complete(&self, e: @expr) -> bool {
return *self.restriction == RESTRICT_STMT_EXPR &&
!classify::expr_requires_semi_to_be_stmt(e);
}
+ // parse a block. No inner attrs are allowed.
fn parse_block(&self) -> blk {
- // disallow inner attrs:
- let (attrs, blk) = self.parse_inner_attrs_and_block(false);
- assert!(vec::is_empty(attrs));
- return blk;
+ maybe_whole!(self, nt_block);
+
+ let lo = self.span.lo;
+ if self.eat_keyword(&~"unsafe") {
+ self.obsolete(copy *self.span, ObsoleteUnsafeBlock);
+ }
+ self.expect(&token::LBRACE);
+
+ return self.parse_block_tail_(lo, default_blk, ~[]);
}
- // I claim the existence of the 'parse_attrs' flag strongly
- // suggests a name-change or refactoring for this function.
- fn parse_inner_attrs_and_block(&self, parse_attrs: bool)
+ // parse a block. Inner attrs are allowed.
+ fn parse_inner_attrs_and_block(&self)
-> (~[attribute], blk) {
maybe_whole!(pair_empty self, nt_block);
- fn maybe_parse_inner_attrs_and_next(p: &Parser, parse_attrs: bool) ->
- (~[attribute], ~[attribute]) {
- if parse_attrs {
- p.parse_inner_attrs_and_next()
- } else {
- (~[], ~[])
- }
- }
-
let lo = self.span.lo;
if self.eat_keyword(&~"unsafe") {
self.obsolete(copy *self.span, ObsoleteUnsafeBlock);
}
self.expect(&token::LBRACE);
- let (inner, next) =
- maybe_parse_inner_attrs_and_next(self, parse_attrs);
+ let (inner, next) = self.parse_inner_attrs_and_next();
(inner, self.parse_block_tail_(lo, default_blk, next))
}
- fn parse_block_no_value(&self) -> blk {
- // We parse blocks that cannot have a value the same as any other
- // block; the type checker will make sure that the tail expression (if
- // any) has unit type.
- return self.parse_block();
- }
-
// Precondition: already parsed the '{' or '#{'
// I guess that also means "already parsed the 'impure'" if
// necessary, and this should take a qualifier.
items: items,
_
} = self.parse_items_and_view_items(first_item_attrs,
- IMPORTS_AND_ITEMS_ALLOWED, false);
+ false, false);
for items.each |item| {
let decl = @spanned(item.span.lo, item.span.hi, decl_item(*item));
if self.eat_keyword(&~"once") { ast::Once } else { ast::Many }
}
+ // matches optbounds = ( ( : ( boundseq )? )? )
+ // where boundseq = ( bound + boundseq ) | bound
+ // and bound = 'static | ty
fn parse_optional_ty_param_bounds(&self) -> @OptVec<TyParamBound> {
if !self.eat(&token::COLON) {
return @opt_vec::Empty;
return @result;
}
+ // matches typaram = IDENT optbounds
fn parse_ty_param(&self) -> TyParam {
let ident = self.parse_ident();
let bounds = self.parse_optional_ty_param_bounds();
(lifetimes, opt_vec::take_vec(result))
}
- fn parse_fn_decl(&self, parse_arg_fn: &fn(&Parser) -> arg_or_capture_item)
+ // parse the argument list and result type of a function declaration
+ fn parse_fn_decl(&self)
-> fn_decl
{
let args_or_capture_items: ~[arg_or_capture_item] =
&token::LPAREN,
&token::RPAREN,
seq_sep_trailing_disallowed(token::COMMA),
- parse_arg_fn
+ |p| p.parse_arg()
);
let inputs = either::lefts(args_or_capture_items);
self.bump();
}
+ // parse the argument list and result type of a function
+ // that may have a self type.
fn parse_fn_decl_with_self(
&self,
parse_arg_fn:
(spanned(lo, hi, self_ty), fn_decl)
}
+ // parse the |arg, arg| header on a lambda
fn parse_fn_block_decl(&self) -> fn_decl {
let inputs_captures = {
if self.eat(&token::OROR) {
}
}
+ // parse the name and optional generic types of a function header.
fn parse_fn_header(&self) -> (ident, ast::Generics) {
let id = self.parse_ident();
let generics = self.parse_generics();
span: mk_sp(lo, hi) }
}
+ // parse an item-position function declaration.
fn parse_item_fn(&self, purity: purity, abis: AbiSet) -> item_info {
let (ident, generics) = self.parse_fn_header();
- let decl = self.parse_fn_decl(|p| p.parse_arg());
- let (inner_attrs, body) = self.parse_inner_attrs_and_block(true);
+ let decl = self.parse_fn_decl();
+ let (inner_attrs, body) = self.parse_inner_attrs_and_block();
(ident,
item_fn(decl, purity, abis, generics, body),
Some(inner_attrs))
}
+ // parse a method in a trait impl
fn parse_method(&self) -> @method {
let attrs = self.parse_outer_attributes();
let lo = self.span.lo;
p.parse_arg()
};
- let (inner_attrs, body) = self.parse_inner_attrs_and_block(true);
+ let (inner_attrs, body) = self.parse_inner_attrs_and_block();
let hi = body.span.hi;
let attrs = vec::append(attrs, inner_attrs);
@ast::method {
is_tuple_like = false;
fields = ~[];
while *self.token != token::RBRACE {
- match self.parse_class_item() {
+ match self.parse_struct_decl_field() {
dtor_decl(ref blk, ref attrs, s) => {
match the_dtor {
Some((_, _, s_first)) => {
}
}
- fn parse_single_class_item(&self, vis: visibility) -> @struct_field {
+ // parse a structure field declaration
+ fn parse_single_struct_field(&self, vis: visibility) -> @struct_field {
if self.eat_obsolete_ident("let") {
self.obsolete(*self.last_span, ObsoleteLet);
}
- let a_var = self.parse_instance_var(vis);
+ let a_var = self.parse_name_and_ty(vis);
match *self.token {
token::SEMI => {
self.obsolete(copy *self.span, ObsoleteFieldTerminator);
self.span_fatal(
copy *self.span,
fmt!(
- "expected `;`, `,`, or '}' but found `%s`",
+ "expected `,`, or '}' but found `%s`",
self.this_token_to_str()
)
);
a_var
}
- fn parse_dtor(&self, attrs: ~[attribute]) -> class_contents {
- let lo = self.last_span.lo;
- let body = self.parse_block();
- dtor_decl(body, attrs, mk_sp(lo, self.last_span.hi))
- }
-
- fn parse_class_item(&self) -> class_contents {
+ // parse an element of a struct definition
+ fn parse_struct_decl_field(&self) -> class_contents {
if self.try_parse_obsolete_priv_section() {
return members(~[]);
let attrs = self.parse_outer_attributes();
if self.eat_keyword(&~"priv") {
- return members(~[self.parse_single_class_item(private)])
+ return members(~[self.parse_single_struct_field(private)])
}
if self.eat_keyword(&~"pub") {
- return members(~[self.parse_single_class_item(public)]);
+ return members(~[self.parse_single_struct_field(public)]);
}
if self.try_parse_obsolete_struct_ctor() {
}
if self.eat_keyword(&~"drop") {
- return self.parse_dtor(attrs);
+ let lo = self.last_span.lo;
+ let body = self.parse_block();
+ return dtor_decl(body, attrs, mk_sp(lo, self.last_span.hi))
}
else {
- return members(~[self.parse_single_class_item(inherited)]);
+ return members(~[self.parse_single_struct_field(inherited)]);
}
}
+ // parse visiility: PUB, PRIV, or nothing
fn parse_visibility(&self) -> visibility {
if self.eat_keyword(&~"pub") { public }
else if self.eat_keyword(&~"priv") { private }
items: starting_items,
_
} = self.parse_items_and_view_items(first_item_attrs,
- VIEW_ITEMS_AND_ITEMS_ALLOWED,
- true);
+ true, true);
let mut items: ~[@item] = starting_items;
let attrs_remaining_len = attrs_remaining.len();
- // looks like this code depends on the invariant that
- // outer attributes can't occur on view items (or macros
- // invocations?)
+ // don't think this other loop is even necessary....
+
let mut first = true;
while *self.token != term {
let mut attrs = self.parse_outer_attributes();
attrs);
match self.parse_item_or_view_item(
/*bad*/ copy attrs,
- true,
- false,
- true
+ true // macros allowed
) {
iovi_item(item) => items.push(item),
iovi_view_item(view_item) => {
self.mod_path_stack.pop();
}
+ // read a module from a source file.
fn eval_src_mod(&self, id: ast::ident,
outer_attrs: ~[ast::attribute],
id_sp: span) -> (ast::item_, ~[ast::attribute]) {
}
}
+ // parse a function declaration from a foreign module
fn parse_item_foreign_fn(&self, attrs: ~[attribute]) -> @foreign_item {
let lo = self.span.lo;
let vis = self.parse_visibility();
let purity = self.parse_fn_purity();
let (ident, generics) = self.parse_fn_header();
- let decl = self.parse_fn_decl(|p| p.parse_arg());
+ let decl = self.parse_fn_decl();
let hi = self.span.hi;
self.expect(&token::SEMI);
@ast::foreign_item { ident: ident,
vis: vis }
}
+ // parse a const definition from a foreign module
fn parse_item_foreign_const(&self, vis: ast::visibility,
attrs: ~[attribute]) -> @foreign_item {
let lo = self.span.lo;
vis: vis }
}
+ // parse safe/unsafe and fn
fn parse_fn_purity(&self) -> purity {
if self.eat_keyword(&~"fn") { impure_fn }
else if self.eat_keyword(&~"pure") {
else { self.unexpected(); }
}
- fn parse_foreign_item(&self, attrs: ~[attribute]) -> @foreign_item {
- let vis = self.parse_visibility();
- if self.is_keyword(&~"const") || self.is_keyword(&~"static") {
- self.parse_item_foreign_const(vis, attrs)
- } else {
- self.parse_item_foreign_fn(attrs)
- }
- }
+ // at this point, this is essentially a wrapper for
+ // parse_foreign_items.
fn parse_foreign_mod_items(&self, sort: ast::foreign_mod_sort,
abis: AbiSet,
first_item_attrs: ~[attribute])
-> foreign_mod {
- // Shouldn't be any view items since we've already parsed an item attr
let ParsedItemsAndViewItems {
attrs_remaining: attrs_remaining,
view_items: view_items,
items: _,
foreign_items: foreign_items
- } = self.parse_items_and_view_items(first_item_attrs,
- FOREIGN_ITEMS_ALLOWED,
- true);
-
- let mut items: ~[@foreign_item] = foreign_items;
+ } = self.parse_foreign_items(first_item_attrs, true);
let mut initial_attrs = attrs_remaining;
- while *self.token != token::RBRACE {
- let attrs = vec::append(initial_attrs,
- self.parse_outer_attributes());
- initial_attrs = ~[];
- items.push(self.parse_foreign_item(attrs));
- }
+ assert!(*self.token == token::RBRACE);
ast::foreign_mod {
sort: sort,
abis: abis,
view_items: view_items,
- items: items
+ items: foreign_items
}
}
+ // parse extern foo; or extern mod foo { ... } or extern { ... }
fn parse_item_foreign_mod(&self,
lo: BytePos,
opt_abis: Option<AbiSet>,
})
}
- fn parse_type_decl(&self) -> (BytePos, ident) {
- let lo = self.last_span.lo;
- let id = self.parse_ident();
- (lo, id)
- }
-
// parse type Foo = Bar;
fn parse_item_type(&self) -> item_info {
- let (_, ident) = self.parse_type_decl();
+ let ident = self.parse_ident();
self.parse_region_param();
let tps = self.parse_generics();
self.expect(&token::EQ);
}
}
+ // parse a structure-like enum variant definition
+ // this should probably be renamed or refactored...
fn parse_struct_def(&self) -> @struct_def {
let mut the_dtor: Option<(blk, ~[attribute], codemap::span)> = None;
let mut fields: ~[@struct_field] = ~[];
while *self.token != token::RBRACE {
- match self.parse_class_item() {
+ match self.parse_struct_decl_field() {
dtor_decl(ref blk, ref attrs, s) => {
match the_dtor {
Some((_, _, s_first)) => {
};
}
+ // parse the part of an "enum" decl following the '{'
fn parse_enum_def(&self, _generics: &ast::Generics) -> enum_def {
let mut variants = ~[];
let mut all_nullary = true, have_disr = false;
let vis = self.parse_visibility();
- let ident, needs_comma, kind;
+ let ident, kind;
let mut args = ~[], disr_expr = None;
ident = self.parse_ident();
if self.eat(&token::LBRACE) {
} else {
kind = tuple_variant_kind(~[]);
}
- needs_comma = true;
let vr = ast::variant_ {
name: ident,
};
variants.push(spanned(vlo, self.last_span.hi, vr));
- if needs_comma && !self.eat(&token::COMMA) { break; }
+ if !self.eat(&token::COMMA) { break; }
}
self.expect(&token::RBRACE);
if (have_disr && !all_nullary) {
ast::enum_def { variants: variants }
}
+ // parse an "enum" declaration
fn parse_item_enum(&self) -> item_info {
let id = self.parse_ident();
self.parse_region_param();
}
}
+ // parse a string as an ABI spec on an extern type or module
fn parse_opt_abis(&self) -> Option<AbiSet> {
match *self.token {
token::LIT_STR(s) => {
// parse one of the items or view items allowed by the
// flags; on failure, return iovi_none.
+ // NB: this function no longer parses the items inside an
+ // extern mod.
fn parse_item_or_view_item(
&self,
attrs: ~[attribute],
- items_allowed: bool,
- foreign_items_allowed: bool,
macros_allowed: bool
) -> item_or_view_item {
- assert!(items_allowed != foreign_items_allowed);
-
maybe_whole!(iovi self, nt_item);
let lo = self.span.lo;
- let visibility;
- if self.eat_keyword(&~"pub") {
- visibility = public;
- } else if self.eat_keyword(&~"priv") {
- visibility = private;
- } else {
- visibility = inherited;
+ let visibility = self.parse_visibility();
+
+ // must be a view item:
+ if self.eat_keyword(&~"use") {
+ // USE ITEM (iovi_view_item)
+ let view_item = self.parse_use();
+ self.expect(&token::SEMI);
+ return iovi_view_item(@ast::view_item {
+ node: view_item,
+ attrs: attrs,
+ vis: visibility,
+ span: mk_sp(lo, self.last_span.hi)
+ });
}
+ // either a view item or an item:
+ if self.eat_keyword(&~"extern") {
+ let opt_abis = self.parse_opt_abis();
- if items_allowed &&
- (self.is_keyword(&~"const") ||
- (self.is_keyword(&~"static") &&
- !self.token_is_keyword(&~"fn", &self.look_ahead(1)))) {
+ if self.eat_keyword(&~"fn") {
+ // EXTERN FUNCTION ITEM
+ let abis = opt_abis.get_or_default(AbiSet::C());
+ let (ident, item_, extra_attrs) =
+ self.parse_item_fn(extern_fn, abis);
+ return iovi_item(self.mk_item(lo, self.last_span.hi, ident,
+ item_, visibility,
+ maybe_append(attrs,
+ extra_attrs)));
+ } else {
+ // EXTERN MODULE ITEM (iovi_view_item)
+ return self.parse_item_foreign_mod(lo, opt_abis, visibility, attrs,
+ true);
+ }
+ }
+ // the rest are all guaranteed to be items:
+ if (self.is_keyword(&~"const") ||
+ (self.is_keyword(&~"static") &&
+ !self.token_is_keyword(&~"fn", &self.look_ahead(1)))) {
// CONST / STATIC ITEM
if self.is_keyword(&~"const") {
self.obsolete(*self.span, ObsoleteConstItem);
visibility,
maybe_append(attrs, extra_attrs)));
}
- if foreign_items_allowed &&
- (self.is_keyword(&~"const") || self.is_keyword(&~"static")) {
- // FOREIGN CONST ITEM
- let item = self.parse_item_foreign_const(visibility, attrs);
- return iovi_foreign_item(item);
- }
- if items_allowed && self.is_keyword(&~"fn") &&
+ if self.is_keyword(&~"fn") &&
!self.fn_expr_lookahead(self.look_ahead(1u)) {
// FUNCTION ITEM
self.bump();
visibility,
maybe_append(attrs, extra_attrs)));
}
- if items_allowed && self.eat_keyword(&~"pure") {
+ if self.eat_keyword(&~"pure") {
// PURE FUNCTION ITEM (obsolete)
self.obsolete(*self.last_span, ObsoletePurity);
self.expect_keyword(&~"fn");
visibility,
maybe_append(attrs, extra_attrs)));
}
- if foreign_items_allowed &&
- (self.is_keyword(&~"fn") || self.is_keyword(&~"pure") ||
- self.is_keyword(&~"unsafe")) {
- // FOREIGN FUNCTION ITEM (no items allowed)
- let item = self.parse_item_foreign_fn(attrs);
- return iovi_foreign_item(item);
- }
- if items_allowed && self.is_keyword(&~"unsafe")
+ if self.is_keyword(&~"unsafe")
&& self.look_ahead(1u) != token::LBRACE {
- // UNSAFE FUNCTION ITEM (where items are allowed)
+ // UNSAFE FUNCTION ITEM
self.bump();
self.expect_keyword(&~"fn");
let (ident, item_, extra_attrs) =
visibility,
maybe_append(attrs, extra_attrs)));
}
- if self.eat_keyword(&~"extern") {
- let opt_abis = self.parse_opt_abis();
-
- if items_allowed && self.eat_keyword(&~"fn") {
- // EXTERN FUNCTION ITEM
- let abis = opt_abis.get_or_default(AbiSet::C());
- let (ident, item_, extra_attrs) =
- self.parse_item_fn(extern_fn, abis);
- return iovi_item(self.mk_item(lo, self.last_span.hi, ident,
- item_, visibility,
- maybe_append(attrs,
- extra_attrs)));
- }
- if !foreign_items_allowed {
- // EXTERN MODULE ITEM
- return self.parse_item_foreign_mod(lo, opt_abis, visibility, attrs,
- items_allowed);
- }
- }
- if items_allowed && !foreign_items_allowed &&
- self.eat_keyword(&~"mod") {
+ if self.eat_keyword(&~"mod") {
// MODULE ITEM
let (ident, item_, extra_attrs) = self.parse_item_mod(attrs);
return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
visibility,
maybe_append(attrs, extra_attrs)));
}
- if items_allowed && !foreign_items_allowed &&
- self.eat_keyword(&~"type") {
+ if self.eat_keyword(&~"type") {
// TYPE ITEM
let (ident, item_, extra_attrs) = self.parse_item_type();
return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
visibility,
maybe_append(attrs, extra_attrs)));
}
- if items_allowed && !foreign_items_allowed &&
- self.eat_keyword(&~"enum") {
+ if self.eat_keyword(&~"enum") {
// ENUM ITEM
let (ident, item_, extra_attrs) = self.parse_item_enum();
return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
visibility,
maybe_append(attrs, extra_attrs)));
}
- if items_allowed && !foreign_items_allowed &&
- self.eat_keyword(&~"trait") {
+ if self.eat_keyword(&~"trait") {
// TRAIT ITEM
let (ident, item_, extra_attrs) = self.parse_item_trait();
return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
visibility,
maybe_append(attrs, extra_attrs)));
}
- if items_allowed && !foreign_items_allowed &&
- self.eat_keyword(&~"impl") {
+ if self.eat_keyword(&~"impl") {
// IMPL ITEM
let (ident, item_, extra_attrs) =
self.parse_item_impl(visibility);
visibility,
maybe_append(attrs, extra_attrs)));
}
- if items_allowed && !foreign_items_allowed &&
- self.eat_keyword(&~"struct") {
+ if self.eat_keyword(&~"struct") {
// STRUCT ITEM
let (ident, item_, extra_attrs) = self.parse_item_struct();
return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
visibility,
maybe_append(attrs, extra_attrs)));
}
- if !foreign_items_allowed && self.eat_keyword(&~"use") {
- // USE ITEM
- let view_item = self.parse_use();
- self.expect(&token::SEMI);
- return iovi_view_item(@ast::view_item {
- node: view_item,
- attrs: attrs,
- vis: visibility,
- span: mk_sp(lo, self.last_span.hi)
- });
+ self.parse_macro_use_or_failure(attrs,macros_allowed,lo,visibility)
+ }
+
+ // parse a foreign item; on failure, return iovi_none.
+ fn parse_foreign_item(
+ &self,
+ attrs: ~[attribute],
+ macros_allowed: bool
+ ) -> item_or_view_item {
+ maybe_whole!(iovi self, nt_item);
+ let lo = self.span.lo;
+
+ let visibility = self.parse_visibility();
+
+ if (self.is_keyword(&~"const") || self.is_keyword(&~"static")) {
+ // FOREIGN CONST ITEM
+ let item = self.parse_item_foreign_const(visibility, attrs);
+ return iovi_foreign_item(item);
+ }
+ if (self.is_keyword(&~"fn") || self.is_keyword(&~"pure") ||
+ self.is_keyword(&~"unsafe")) {
+ // FOREIGN FUNCTION ITEM
+ let item = self.parse_item_foreign_fn(attrs);
+ return iovi_foreign_item(item);
}
+ self.parse_macro_use_or_failure(attrs,macros_allowed,lo,visibility)
+ }
+
+ // this is the fall-through for parsing items.
+ fn parse_macro_use_or_failure(
+ &self,
+ attrs: ~[attribute],
+ macros_allowed: bool,
+ lo : BytePos,
+ visibility : visibility
+ ) -> item_or_view_item {
if macros_allowed && !self.is_any_keyword(© *self.token)
&& self.look_ahead(1) == token::NOT
&& (is_plain_ident(&self.look_ahead(2))
}
fn parse_item(&self, attrs: ~[attribute]) -> Option<@ast::item> {
- match self.parse_item_or_view_item(attrs, true, false, true) {
+ match self.parse_item_or_view_item(attrs, true) {
iovi_none =>
None,
iovi_view_item(_) =>
}
}
+ // parse, e.g., "use a::b::{z,y}"
fn parse_use(&self) -> view_item_ {
return view_item_use(self.parse_view_paths());
}
// Parses a sequence of items. Stops when it finds program
// text that can't be parsed as an item
- // - mod_items uses VIEW_ITEMS_AND_ITEMS_ALLOWED
- // - block_tail_ uses IMPORTS_AND_ITEMS_ALLOWED
- // - foreign_mod_items uses FOREIGN_ITEMS_ALLOWED
- fn parse_items_and_view_items(&self, first_item_attrs: ~[attribute],
- mode: view_item_parse_mode,
+ // - mod_items uses extern_mod_allowed = true
+ // - block_tail_ uses extern_mod_allowed = false
+ fn parse_items_and_view_items(&self,
+ first_item_attrs: ~[attribute],
+ mut extern_mod_allowed: bool,
macros_allowed: bool)
- -> ParsedItemsAndViewItems {
+ -> ParsedItemsAndViewItems {
let mut attrs = vec::append(first_item_attrs,
self.parse_outer_attributes());
-
- let items_allowed = match mode {
- VIEW_ITEMS_AND_ITEMS_ALLOWED | IMPORTS_AND_ITEMS_ALLOWED => true,
- FOREIGN_ITEMS_ALLOWED => false
- };
- let foreign_items_allowed = match mode {
- FOREIGN_ITEMS_ALLOWED => true,
- VIEW_ITEMS_AND_ITEMS_ALLOWED | IMPORTS_AND_ITEMS_ALLOWED => false
- };
-
// First, parse view items.
- let mut (view_items, items, foreign_items) = (~[], ~[], ~[]);
+ let mut (view_items, items) = (~[], ~[]);
let mut done = false;
- if mode != FOREIGN_ITEMS_ALLOWED {
- let mut extern_mod_allowed = match mode {
- VIEW_ITEMS_AND_ITEMS_ALLOWED => true,
- IMPORTS_AND_ITEMS_ALLOWED => false,
- FOREIGN_ITEMS_ALLOWED => {
- self.bug(~"couldn't get here with FOREIGN_ITEMS_ALLOWED")
+ // I think this code would probably read better as a single
+ // loop with a mutable three-state-variable (for extern mods,
+ // view items, and regular items) ... except that because
+ // of macros, I'd like to delay that entire check until later.
+ loop {
+ match self.parse_item_or_view_item(/*bad*/ copy attrs,
+ macros_allowed) {
+ iovi_none => {
+ done = true;
+ break;
}
- };
-
- loop {
- match self.parse_item_or_view_item(/*bad*/ copy attrs,
- items_allowed,
- foreign_items_allowed,
- macros_allowed) {
- iovi_none => {
- done = true;
- break;
- }
- iovi_view_item(view_item) => {
- match view_item.node {
- view_item_use(*) => {
- // `extern mod` must precede `use`.
- extern_mod_allowed = false;
- }
- view_item_extern_mod(*)
- if !extern_mod_allowed => {
- self.span_err(view_item.span,
- ~"\"extern mod\" \
- declarations are not \
- allowed here");
- }
- view_item_extern_mod(*) => {}
+ iovi_view_item(view_item) => {
+ match view_item.node {
+ view_item_use(*) => {
+ // `extern mod` must precede `use`.
+ extern_mod_allowed = false;
}
- view_items.push(view_item);
- }
- iovi_item(item) => {
- assert!(items_allowed);
- items.push(item);
- attrs = self.parse_outer_attributes();
- break;
- }
- iovi_foreign_item(foreign_item) => {
- assert!(foreign_items_allowed);
- foreign_items.push(foreign_item);
- attrs = self.parse_outer_attributes();
- break;
+ view_item_extern_mod(*)
+ if !extern_mod_allowed => {
+ self.span_err(view_item.span,
+ ~"\"extern mod\" \
+ declarations are not \
+ allowed here");
+ }
+ view_item_extern_mod(*) => {}
}
+ view_items.push(view_item);
+ }
+ iovi_item(item) => {
+ items.push(item);
+ attrs = self.parse_outer_attributes();
+ break;
+ }
+ iovi_foreign_item(_) => {
+ fail!();
}
- attrs = self.parse_outer_attributes();
}
+ attrs = self.parse_outer_attributes();
}
// Next, parse items.
if !done {
loop {
match self.parse_item_or_view_item(/*bad*/ copy attrs,
- items_allowed,
- foreign_items_allowed,
macros_allowed) {
iovi_none => break,
iovi_view_item(view_item) => {
self.span_err(view_item.span,
~"`use` and `extern mod` declarations \
must precede items");
- view_items.push(view_item);
}
iovi_item(item) => {
- assert!(items_allowed);
items.push(item)
}
- iovi_foreign_item(foreign_item) => {
- assert!(foreign_items_allowed);
- foreign_items.push(foreign_item);
+ iovi_foreign_item(_) => {
+ fail!();
}
}
attrs = self.parse_outer_attributes();
attrs_remaining: attrs,
view_items: view_items,
items: items,
+ foreign_items: ~[]
+ }
+ }
+
+ // Parses a sequence of foreign items. Stops when it finds program
+ // text that can't be parsed as an item
+ fn parse_foreign_items(&self, first_item_attrs: ~[attribute],
+ macros_allowed: bool)
+ -> ParsedItemsAndViewItems {
+ let mut attrs = vec::append(first_item_attrs,
+ self.parse_outer_attributes());
+ let mut foreign_items = ~[];
+ loop {
+ match self.parse_foreign_item(/*bad*/ copy attrs, macros_allowed) {
+ iovi_none => break,
+ iovi_view_item(view_item) => {
+ // I think this can't occur:
+ self.span_err(view_item.span,
+ ~"`use` and `extern mod` declarations \
+ must precede items");
+ }
+ iovi_item(_) => {
+ // FIXME #5668: this will occur for a macro invocation:
+ fail!();
+ }
+ iovi_foreign_item(foreign_item) => {
+ foreign_items.push(foreign_item);
+ }
+ }
+ attrs = self.parse_outer_attributes();
+ }
+
+ ParsedItemsAndViewItems {
+ attrs_remaining: attrs,
+ view_items: ~[],
+ items: ~[],
foreign_items: foreign_items
}
}
- // Parses a source module as a crate
- fn parse_crate_mod(&self, _cfg: crate_cfg) -> @crate {
+ // Parses a source module as a crate. This is the main
+ // entry point for the parser.
+ fn parse_crate_mod(&self) -> @crate {
let lo = self.span.lo;
// parse the crate's inner attrs, maybe (oops) one
// of the attrs of an item:
fn parse_str(&self) -> @~str {
match *self.token {
- token::LIT_STR(s) => { self.bump(); self.id_to_str(s) }
- _ => self.fatal(~"expected string literal")
+ token::LIT_STR(s) => {
+ self.bump();
+ self.id_to_str(s)
+ }
+ _ => self.fatal(~"expected string literal")
}
}
}
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use ast;
-use ast::*;
-use parse::token::*;
-use parse::token::Token;
-
-use core::prelude::*;
-
-/// Unary operators have higher precedence than binary
-pub static unop_prec: uint = 100u;
-
-/**
- * Precedence of the `as` operator, which is a binary operator
- * but is not represented in the precedence table.
- */
-pub static as_prec: uint = 11u;
-
-/**
- * Maps a token to a record specifying the corresponding binary
- * operator and its precedence
- */
-pub fn token_to_binop(tok: Token) -> Option<ast::binop> {
- match tok {
- BINOP(STAR) => Some(mul),
- BINOP(SLASH) => Some(quot),
- BINOP(PERCENT) => Some(rem),
- // 'as' sits between here with 11
- BINOP(PLUS) => Some(add),
- BINOP(MINUS) => Some(subtract),
- BINOP(SHL) => Some(shl),
- BINOP(SHR) => Some(shr),
- BINOP(AND) => Some(bitand),
- BINOP(CARET) => Some(bitxor),
- BINOP(OR) => Some(bitor),
- LT => Some(lt),
- LE => Some(le),
- GE => Some(ge),
- GT => Some(gt),
- EQEQ => Some(eq),
- NE => Some(ne),
- ANDAND => Some(and),
- OROR => Some(or),
- _ => None
- }
-}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use ast;
use ast_util;
use parse::token;
use util::interner::Interner;
use util::interner;
-use core::cast;
-use core::char;
use core::cmp::Equiv;
use core::hashmap::HashSet;
-use core::str;
-use core::task;
use core::to_bytes;
#[auto_encode]
}
}
+/**
+ * Maps a token to a record specifying the corresponding binary
+ * operator
+ */
+pub fn token_to_binop(tok: Token) -> Option<ast::binop> {
+ match tok {
+ BINOP(STAR) => Some(ast::mul),
+ BINOP(SLASH) => Some(ast::quot),
+ BINOP(PERCENT) => Some(ast::rem),
+ BINOP(PLUS) => Some(ast::add),
+ BINOP(MINUS) => Some(ast::subtract),
+ BINOP(SHL) => Some(ast::shl),
+ BINOP(SHR) => Some(ast::shr),
+ BINOP(AND) => Some(ast::bitand),
+ BINOP(CARET) => Some(ast::bitxor),
+ BINOP(OR) => Some(ast::bitor),
+ LT => Some(ast::lt),
+ LE => Some(ast::le),
+ GE => Some(ast::ge),
+ GT => Some(ast::gt),
+ EQEQ => Some(ast::eq),
+ NE => Some(ast::ne),
+ ANDAND => Some(ast::and),
+ OROR => Some(ast::or),
+ _ => None
+ }
+}
+
pub struct ident_interner {
priv interner: Interner<@~str>,
}
}
}
+// return a fresh interner, preloaded with special identifiers.
+// EFFECT: stores this interner in TLS
+pub fn mk_fresh_ident_interner() -> @ident_interner {
+ // the indices here must correspond to the numbers in
+ // special_idents.
+ let init_vec = ~[
+ @~"_", // 0
+ @~"anon", // 1
+ @~"drop", // 2
+ @~"", // 3
+ @~"unary", // 4
+ @~"!", // 5
+ @~"[]", // 6
+ @~"unary-", // 7
+ @~"__extensions__", // 8
+ @~"self", // 9
+ @~"item", // 10
+ @~"block", // 11
+ @~"stmt", // 12
+ @~"pat", // 13
+ @~"expr", // 14
+ @~"ty", // 15
+ @~"ident", // 16
+ @~"path", // 17
+ @~"tt", // 18
+ @~"matchers", // 19
+ @~"str", // 20
+ @~"TyVisitor", // 21
+ @~"arg", // 22
+ @~"descrim", // 23
+ @~"__rust_abi", // 24
+ @~"__rust_stack_shim", // 25
+ @~"TyDesc", // 26
+ @~"dtor", // 27
+ @~"main", // 28
+ @~"<opaque>", // 29
+ @~"blk", // 30
+ @~"static", // 31
+ @~"intrinsic", // 32
+ @~"__foreign_mod__", // 33
+ @~"__field__", // 34
+ @~"C", // 35
+ @~"Self", // 36
+ ];
+
+ let rv = @ident_interner {
+ interner: interner::Interner::prefill(init_vec)
+ };
+ unsafe {
+ task::local_data::local_data_set(interner_key!(), @rv);
+ }
+ rv
+}
+
+// if an interner exists in TLS, return it. Otherwise, prepare a
+// fresh one.
pub fn mk_ident_interner() -> @ident_interner {
unsafe {
match task::local_data::local_data_get(interner_key!()) {
Some(interner) => *interner,
None => {
- // the indices here must correspond to the numbers in
- // special_idents.
- let init_vec = ~[
- @~"_", // 0
- @~"anon", // 1
- @~"drop", // 2
- @~"", // 3
- @~"unary", // 4
- @~"!", // 5
- @~"[]", // 6
- @~"unary-", // 7
- @~"__extensions__", // 8
- @~"self", // 9
- @~"item", // 10
- @~"block", // 11
- @~"stmt", // 12
- @~"pat", // 13
- @~"expr", // 14
- @~"ty", // 15
- @~"ident", // 16
- @~"path", // 17
- @~"tt", // 18
- @~"matchers", // 19
- @~"str", // 20
- @~"TyVisitor", // 21
- @~"arg", // 22
- @~"descrim", // 23
- @~"__rust_abi", // 24
- @~"__rust_stack_shim", // 25
- @~"TyDesc", // 26
- @~"dtor", // 27
- @~"main", // 28
- @~"<opaque>", // 29
- @~"blk", // 30
- @~"static", // 31
- @~"intrinsic", // 32
- @~"__foreign_mod__", // 33
- @~"__field__", // 34
- @~"C", // 35
- @~"Self", // 36
- ];
-
- let rv = @ident_interner {
- interner: interner::Interner::prefill(init_vec)
- };
-
- task::local_data::local_data_set(interner_key!(), @rv);
-
- rv
+ mk_fresh_ident_interner()
}
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
-use core::io::WriterUtil;
-use core::io;
-use core::vec;
-
/*
* This pretty-printer is a direct reimplementation of Philip Karlton's
* Mesa pretty-printer, as described in appendix A of
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
use abi::AbiSet;
use ast::{RegionTyParamBound, TraitTyParamBound, required, provided};
use print::pp;
use print::pprust;
-use core::char;
-use core::io;
-use core::str;
-use core::u64;
-use core::vec;
-
// The @ps is stored here to prevent recursive type.
pub enum ann_node<'self> {
node_block(@ps, &'self ast::blk),
print_block(s, blk);
}
ast::expr_loop(ref blk, opt_ident) => {
- head(s, ~"loop");
- space(s.s);
for opt_ident.each |ident| {
+ word(s.s, ~"'");
print_ident(s, *ident);
word_space(s, ~":");
}
+ head(s, ~"loop");
+ space(s.s);
print_block(s, blk);
}
ast::expr_match(expr, ref arms) => {
ast::expr_break(opt_ident) => {
word(s.s, ~"break");
space(s.s);
- for opt_ident.each |ident| { print_ident(s, *ident); space(s.s) }
+ for opt_ident.each |ident| {
+ word(s.s, ~"'");
+ print_ident(s, *ident);
+ space(s.s);
+ }
}
ast::expr_again(opt_ident) => {
word(s.s, ~"loop");
space(s.s);
- for opt_ident.each |ident| { print_ident(s, *ident); space(s.s) }
+ for opt_ident.each |ident| {
+ word(s.s, ~"'");
+ print_ident(s, *ident);
+ space(s.s)
+ }
}
ast::expr_ret(result) => {
word(s.s, ~"return");
maybe_print_comment(s, decl.output.span.lo);
}
-pub fn mode_to_str(m: ast::mode) -> ~str {
- match m {
- ast::expl(ast::by_ref) => ~"&&",
- ast::expl(ast::by_copy) => ~"+",
- ast::infer(_) => ~""
- }
-}
-
-pub fn print_arg_mode(s: @ps, m: ast::mode) {
- let ms = mode_to_str(m);
- if ms != ~"" { word(s.s, ms); }
-}
-
pub fn print_bounds(s: @ps, bounds: @OptVec<ast::TyParamBound>) {
if !bounds.is_empty() {
word(s.s, ~":");
pub fn print_arg(s: @ps, input: ast::arg) {
ibox(s, indent_unit);
- print_arg_mode(s, input.mode);
if input.is_mutbl {
word_space(s, ~"mut");
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+/*! This module contains the Rust parser. It maps source text
+ * to token trees and to ASTs. It contains code for expanding
+ * macros.
+ */
+
#[link(name = "syntax",
vers = "0.7-pre",
uuid = "9311401b-d6ea-4cd9-a1d9-61f89499c645")];
-
-
#[license = "MIT/ASL2"];
#[crate_type = "lib"];
#[deny(deprecated_mode)];
#[deny(deprecated_pattern)];
-#[no_core];
-
-extern mod core(vers = "0.7-pre");
extern mod std(vers = "0.7-pre");
-use core::*;
-
// allow the interner_key macro
// to escape this module:
#[macro_escape]
// allow the interner_key macro to escape this module:
#[macro_escape];
-use core::prelude::*;
use core::cmp::Equiv;
use core::hashmap::HashMap;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::prelude::*;
-
use abi::AbiSet;
use ast::*;
use ast;
970719: use context, not global variables, for internal state
980324: make a portable version
010626: Note this is public domain
+ 100725: Mask on use of >32 bits, not on assignment: from Paul Eggert
------------------------------------------------------------------------------
*/
#ifndef STANDARD
void isaac(randctx *ctx)
{
- register ub4 a,b,x,y,*m,*mm,*m2,*r,*mend;
+ ub4 a,b,x,y,*m,*mm,*m2,*r,*mend;
mm=ctx->randmem; r=ctx->randrsl;
- a = ctx->randa; b = (ctx->randb + (++ctx->randc)) & 0xffffffff;
+ a = ctx->randa; b = ctx->randb + (++ctx->randc);
for (m = mm, mend = m2 = m+(RANDSIZ/2); m<mend; )
{
rngstep( a<<13, a, b, mm, m, m2, r, x);
- rngstep( a>>6 , a, b, mm, m, m2, r, x);
+ rngstep( (a & 0xffffffff) >>6 , a, b, mm, m, m2, r, x);
rngstep( a<<2 , a, b, mm, m, m2, r, x);
- rngstep( a>>16, a, b, mm, m, m2, r, x);
+ rngstep( (a & 0xffffffff) >>16, a, b, mm, m, m2, r, x);
}
for (m2 = mm; m2<mend; )
{
rngstep( a<<13, a, b, mm, m, m2, r, x);
- rngstep( a>>6 , a, b, mm, m, m2, r, x);
+ rngstep( (a & 0xffffffff) >>6 , a, b, mm, m, m2, r, x);
rngstep( a<<2 , a, b, mm, m, m2, r, x);
- rngstep( a>>16, a, b, mm, m, m2, r, x);
+ rngstep( (a & 0xffffffff) >>16, a, b, mm, m, m2, r, x);
}
ctx->randb = b; ctx->randa = a;
}
#define mix(a,b,c,d,e,f,g,h) \
{ \
- a^=b<<11; d+=a; b+=c; \
- b^=c>>2; e+=b; c+=d; \
- c^=d<<8; f+=c; d+=e; \
- d^=e>>16; g+=d; e+=f; \
- e^=f<<10; h+=e; f+=g; \
- f^=g>>4; a+=f; g+=h; \
- g^=h<<8; b+=g; h+=a; \
- h^=a>>9; c+=h; a+=b; \
+ a^=b<<11; d+=a; b+=c; \
+ b^=(c&0xffffffff)>>2; e+=b; c+=d; \
+ c^=d<<8; f+=c; d+=e; \
+ d^=(e&0xffffffff)>>16; g+=d; e+=f; \
+ e^=f<<10; h+=e; f+=g; \
+ f^=(g&0xffffffff)>>4; a+=f; g+=h; \
+ g^=h<<8; b+=g; h+=a; \
+ h^=(a&0xffffffff)>>9; c+=h; a+=b; \
}
/* if (flag==TRUE), then use the contents of randrsl[] to initialize mm[]. */
/* initialize using the contents of r[] as the seed */
for (i=0; i<RANDSIZ; i+=8)
{
- a+=r[i ]; b+=r[i+1]; c+=r[i+2]; d+=r[i+3];
- e+=r[i+4]; f+=r[i+5]; g+=r[i+6]; h+=r[i+7];
+ a+=r[i ]; b+=r[i+1];
+ c+=r[i+2]; d+=r[i+3];
+ e+=r[i+4]; f+=r[i+5];
+ g+=r[i+6]; h+=r[i+7];
mix(a,b,c,d,e,f,g,h);
m[i ]=a; m[i+1]=b; m[i+2]=c; m[i+3]=d;
m[i+4]=e; m[i+5]=f; m[i+6]=g; m[i+7]=h;
/* do a second pass to make all of the seed affect all of m */
for (i=0; i<RANDSIZ; i+=8)
{
- a+=m[i ]; b+=m[i+1]; c+=m[i+2]; d+=m[i+3];
- e+=m[i+4]; f+=m[i+5]; g+=m[i+6]; h+=m[i+7];
+ a+=m[i ]; b+=m[i+1];
+ c+=m[i+2]; d+=m[i+3];
+ e+=m[i+4]; f+=m[i+5];
+ g+=m[i+6]; h+=m[i+7];
mix(a,b,c,d,e,f,g,h);
m[i ]=a; m[i+1]=b; m[i+2]=c; m[i+3]=d;
m[i+4]=e; m[i+5]=f; m[i+6]=g; m[i+7]=h;
# include <stddef.h>
# define STDDEF
# endif
-typedef unsigned long long ub8;
+# ifndef STDINT
+# include <stdint.h>
+# define STDINT
+# endif
+
+typedef uint64_t ub8;
#define UB8MAXVAL 0xffffffffffffffffLL
#define UB8BITS 64
-typedef signed long long sb8;
+typedef int64_t sb8;
#define SB8MAXVAL 0x7fffffffffffffffLL
-typedef unsigned long int ub4; /* unsigned 4-byte quantities */
+typedef uint32_t ub4; /* unsigned 4-byte quantities */
#define UB4MAXVAL 0xffffffff
-typedef signed long int sb4;
+typedef int32_t sb4;
#define UB4BITS 32
#define SB4MAXVAL 0x7fffffff
-typedef unsigned short int ub2;
+typedef uint16_t ub2;
#define UB2MAXVAL 0xffff
#define UB2BITS 16
-typedef signed short int sb2;
+typedef int16_t sb2;
#define SB2MAXVAL 0x7fff
-typedef unsigned char ub1;
+typedef uint8_t ub1;
#define UB1MAXVAL 0xff
#define UB1BITS 8
-typedef signed char sb1; /* signed 1-byte quantities */
+typedef int8_t sb1; /* signed 1-byte quantities */
#define SB1MAXVAL 0x7f
-typedef int word; /* fastest type available */
+typedef int word; /* fastest type available */
#define bis(target,mask) ((target) |= (mask))
#define bic(target,mask) ((target) &= ~(mask))
return strtol(maxsz, NULL, 0);
}
else {
- return 1024*1024*8;
+ return 1024*1024*1024;
}
}
// arbitrarily selected as 2x the maximum stack size.
if (!unwinding && used_stack > max_stack) {
LOG_ERR(this, task, "task %" PRIxPTR " ran out of stack", this);
- fail();
+ abort();
} else if (unwinding && used_stack > max_stack * 2) {
LOG_ERR(this, task,
"task %" PRIxPTR " ran out of stack during unwinding", this);
- fail();
+ abort();
}
size_t sz = rust_stk_sz + RED_ZONE_SIZE;
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Unwinding stuff missing on some architectures (Mac OS X).
-
-#ifndef RUST_UNWIND_H
-#define RUST_UNWIND_H
-
-#ifdef __APPLE__
-#include <libunwind.h>
-
-typedef void _Unwind_Context;
-typedef int _Unwind_Reason_Code;
-
-#else
-
-#include <unwind.h>
-
-#endif
-
-#if (defined __APPLE__) || (defined __clang__)
-
-#ifndef __FreeBSD__
-
-typedef int _Unwind_Action;
-typedef void _Unwind_Exception;
-
-#endif
-
-#endif
-
-#endif
-
#include "rust_globals.h"
#include "rust_task.h"
#include "rust_sched_loop.h"
-#include "rust_unwind.h"
#include "rust_upcall.h"
#include "rust_util.h"
+//Unwinding ABI declarations.
+typedef int _Unwind_Reason_Code;
+typedef int _Unwind_Action;
+
+struct _Unwind_Context;
+struct _Unwind_Exception;
+
#ifdef __GNUC__
#define LOG_UPCALL_ENTRY(task) \
LOG(task, upcall, \
// except according to those terms.
#[link(name="cci_iter_lib", vers="0.0")];
-#[legacy_modes];
#[inline]
-pub fn iter<T>(v: ~[T], f: &fn(T)) {
+pub fn iter<T>(v: &[T], f: &fn(&T)) {
let mut i = 0u;
let n = vec::len(v);
while i < n {
- f(v[i]);
+ f(&v[i]);
i += 1u;
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#[legacy_modes];
-
-pub struct Entry<A,B> {key: A, value: B}
+pub struct Entry<A,B> {
+ key: A,
+ value: B
+}
-pub struct alist<A,B> { eq_fn: @fn(A,A) -> bool, data: @mut ~[Entry<A,B>] }
+pub struct alist<A,B> {
+ eq_fn: @fn(A,A) -> bool,
+ data: @mut ~[Entry<A,B>]
+}
-pub fn alist_add<A:Copy,B:Copy>(lst: alist<A,B>, k: A, v: B) {
+pub fn alist_add<A:Copy,B:Copy>(lst: &alist<A,B>, k: A, v: B) {
lst.data.push(Entry{key:k, value:v});
}
-pub fn alist_get<A:Copy,B:Copy>(lst: alist<A,B>, k: A) -> B {
+pub fn alist_get<A:Copy,B:Copy>(lst: &alist<A,B>, k: A) -> B {
let eq_fn = lst.eq_fn;
for lst.data.each |entry| {
if eq_fn(entry.key, k) { return entry.value; }
#[inline]
pub fn new_int_alist<B:Copy>() -> alist<int, B> {
- fn eq_int(&&a: int, &&b: int) -> bool { a == b }
+ fn eq_int(a: int, b: int) -> bool { a == b }
return alist {eq_fn: eq_int, data: @mut ~[]};
}
#[inline]
pub fn new_int_alist_2<B:Copy>() -> alist<int, B> {
#[inline]
- fn eq_int(&&a: int, &&b: int) -> bool { a == b }
+ fn eq_int(a: int, b: int) -> bool { a == b }
return alist {eq_fn: eq_int, data: @mut ~[]};
}
pub type context = arc_destruct<context_res>;
-pub impl context {
- fn socket(&self) { }
-}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#[legacy_modes];
#[allow(deprecated_mode)];
/*!
}
/// A parallel version of the bfs function.
-fn pbfs(&&graph: arc::ARC<graph>, key: node_id) -> bfs_result {
+fn pbfs(graph: &arc::ARC<graph>, key: node_id) -> bfs_result {
// This works by doing functional updates of a color vector.
enum color {
black(node_id)
};
- let graph_vec = arc::get(&graph); // FIXME #3387 requires this temp
+ let graph_vec = arc::get(graph); // FIXME #3387 requires this temp
let mut colors = do vec::from_fn(graph_vec.len()) |i| {
if i as node_id == key {
gray(key)
let color_vec = arc::get(&color); // FIXME #3387 requires this temp
colors = do par::mapi(*color_vec) {
let colors = arc::clone(&color);
- let graph = arc::clone(&graph);
+ let graph = arc::clone(graph);
let result: ~fn(+x: uint, +y: &color) -> color = |i, c| {
let colors = arc::get(&colors);
let graph = arc::get(&graph);
}
let start = time::precise_time_s();
- let bfs_tree = pbfs(graph_arc, *root);
+ let bfs_tree = pbfs(&graph_arc, *root);
let stop = time::precise_time_s();
total_par += stop - start;
// different scalability characteristics compared to the select
// version.
-#[legacy_modes];
-
extern mod std;
use core::io::Writer;
use core::io::WriterUtil;
use core::comm::{Port, Chan, SharedChan};
macro_rules! move_out (
- { $x:expr } => { unsafe { let y = *ptr::addr_of(&($x)); y } }
+ { $x:expr } => { unsafe { let y = *ptr::to_unsafe_ptr(&($x)); y } }
)
enum request {
stop
}
-fn server(requests: Port<request>, responses: comm::Chan<uint>) {
+fn server(requests: &Port<request>, responses: &comm::Chan<uint>) {
let mut count = 0u;
let mut done = false;
while !done {
};
}
do task::spawn || {
- server(from_parent, to_parent);
+ server(&from_parent, &to_parent);
}
for vec::each(worker_results) |r| {
//
// I *think* it's the same, more or less.
-#[legacy_modes];
-
extern mod std;
use core::io::Writer;
use core::io::WriterUtil;
use core::comm::{Port, PortSet, Chan, stream};
macro_rules! move_out (
- { $x:expr } => { unsafe { let y = *ptr::addr_of(&($x)); y } }
+ { $x:expr } => { unsafe { let y = *ptr::to_unsafe_ptr(&($x)); y } }
)
enum request {
stop
}
-fn server(requests: PortSet<request>, responses: Chan<uint>) {
+fn server(requests: &PortSet<request>, responses: &Chan<uint>) {
let mut count = 0;
let mut done = false;
while !done {
};
}
do task::spawn || {
- server(from_parent, to_parent);
+ server(&from_parent, &to_parent);
}
for vec::each(worker_results) |r| {
)
macro_rules! move_out (
- ($x:expr) => { unsafe { let y = *ptr::addr_of(&$x); y } }
+ ($x:expr) => { unsafe { let y = *ptr::to_unsafe_ptr(&$x); y } }
)
fn thread_ring(i: uint,
// This stuff should go in libcore::pipes
macro_rules! move_it (
- { $x:expr } => { let t = *ptr::addr_of(&($x)); t }
+ { $x:expr } => { let t = *ptr::to_unsafe_ptr(&($x)); t }
)
macro_rules! follow (
// xfail-pretty (extra blank line is inserted in vec::mapi call)
// multi tasking k-nucleotide
-#[legacy_modes];
-
extern mod std;
use std::sort;
use core::hashmap::HashMap;
return vec::slice(bb, len - (nn - 1u), len).to_vec();
}
-fn make_sequence_processor(sz: uint, from_parent: comm::Port<~[u8]>,
- to_parent: comm::Chan<~str>) {
-
+fn make_sequence_processor(sz: uint,
+ from_parent: &comm::Port<~[u8]>,
+ to_parent: &comm::Chan<~str>) {
let mut freqs: HashMap<~[u8], uint> = HashMap::new();
let mut carry: ~[u8] = ~[];
let mut total: uint = 0u;
// given a FASTA file on stdin, process sequence THREE
fn main() {
let args = os::args();
- let rdr = if os::getenv(~"RUST_BENCH").is_some() {
+ let rdr = if os::getenv(~"RUST_BENCH").is_some() {
// FIXME: Using this compile-time env variable is a crummy way to
// get to this massive data set, but include_bin! chokes on it (#2598)
let path = Path(env!("CFG_SRC_DIR"))
let (from_parent, to_child) = comm::stream();
do task::spawn_with(from_parent) |from_parent| {
- make_sequence_processor(sz, from_parent, to_parent_);
+ make_sequence_processor(sz, &from_parent, &to_parent_);
};
to_child
*/
-#[legacy_modes];
-
extern mod std;
use std::{time, getopts};
use core::result::{Ok, Err};
fn fib(n: int) -> int {
- fn pfib(c: Chan<int>, n: int) {
+ fn pfib(c: &Chan<int>, n: int) {
if n == 0 {
c.send(0);
} else if n <= 2 {
} else {
let p = PortSet::new();
let ch = p.chan();
- task::spawn(|| pfib(ch, n - 1) );
+ task::spawn(|| pfib(&ch, n - 1) );
let ch = p.chan();
- task::spawn(|| pfib(ch, n - 2) );
+ task::spawn(|| pfib(&ch, n - 2) );
c.send(p.recv() + p.recv());
}
}
let (p, ch) = stream();
- let _t = task::spawn(|| pfib(ch, n) );
+ let _t = task::spawn(|| pfib(&ch, n) );
p.recv()
}
}
fn run(repeat: int, depth: int) {
- for iter::repeat(repeat as uint) {
+ for old_iter::repeat(repeat as uint) {
debug!("starting %.4f", precise_time_s());
do task::try {
recurse_or_fail(depth, None)
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// error-pattern: mismatched types
-
-fn f(&&_x: int) {}
-fn g(_a: &fn(+v: int)) {}
-fn main() { g(f); }
--- /dev/null
+// error-pattern:illegal borrow: borrowed value does not live long enough
+
+fn main() {
+ let v = ~"test";
+ let sslice = str::slice(v, 0, v.len());
+ fail!(sslice);
+}
+++ /dev/null
-// error-pattern:mismatched types
-
-fn main() {
- fail!("test");
-}
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//error-pattern:unresolved enum variant
+
+fn main() {
+ // a bug in the parser is allowing this:
+ let a() = 13;
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// error-pattern:mismatched types
+// error-pattern:failed to find an implementation of trait core::sys::FailWithCause for int
fn main() { fail!(5); }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// error-pattern:expected `~str` but found `~[int]`
+// error-pattern:failed to find an implementation of trait core::sys::FailWithCause for ~[int]
fn main() { fail!(~[0i]); }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#[legacy_modes];
-
-fn takes_mut(&&x: @mut int) { }
-fn takes_imm(&&x: @int) { }
+fn takes_mut(x: @mut int) { }
+fn takes_imm(x: @int) { }
fn apply<T>(t: T, f: &fn(T)) {
f(t)
enum bottom { }
fn main() {
- let x = ptr::addr_of(&()) as *bottom;
+ let x = ptr::to_unsafe_ptr(&()) as *bottom;
match x { } //~ ERROR non-exhaustive patterns
}
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn take(_x: ~int) { }
-
-fn from_by_ref_arg(&&x: ~int) {
- take(x); //~ ERROR illegal move from argument `x`, which is not copy or move mode
-}
-
-fn from_copy_arg(+x: ~int) {
- take(x);
-}
-
-fn main() {
-}
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#[legacy_modes];
-
-// In this test, the mode gets inferred to ++ due to the apply_int(),
-// but then we get a failure in the generic apply().
-
-fn apply<A>(f: &fn(A) -> A, a: A) -> A { f(a) }
-fn apply_int(f: &fn(int) -> int, a: int) -> int { f(a) }
-
-fn main() {
- let f = {|i| i};
- assert!(apply_int(f, 2) == 2);
- assert!(apply(f, 2) == 2); //~ ERROR expected argument mode &&
-}
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Note: it would be nice to give fewer warnings in these cases.
-
-fn mutate_by_mut_ref(x: &mut uint) {
- *x = 0;
-}
-
-fn mutate_by_ref(&&x: uint) {
- //~^ WARNING unused variable: `x`
- x = 0; //~ ERROR assigning to argument
-}
-
-fn mutate_by_copy(+x: uint) {
- //~^ WARNING unused variable: `x`
- x = 0; //~ ERROR assigning to argument
- //~^ WARNING value assigned to `x` is never read
-}
-
-fn mutate_by_move(+x: uint) {
- //~^ WARNING unused variable: `x`
- x = 0; //~ ERROR assigning to argument
- //~^ WARNING value assigned to `x` is never read
-}
-
-fn main() {
-}
// except according to those terms.
fn main() {
- let x : *~[int] = ptr::addr_of(&~[1,2,3]);
+ let x : *~[int] = &~[1,2,3];
let y : *libc::c_void = x as *libc::c_void;
unsafe {
let _z = copy *y;
// the error points to the start of the file, not the line with the
// transmute
-// error-pattern: reinterpret_cast called on types with different size
+// error-pattern: transmute called on types with different size
#[packed]
struct Foo<T,S> {
// the error points to the start of the file, not the line with the
// transmute
-// error-pattern: reinterpret_cast called on types with different size
+// error-pattern: transmute called on types with different size
#[packed]
struct Foo {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#[legacy_modes];
-
enum ast<'self> {
num(uint),
add(&'self ast<'self>, &'self ast<'self>)
-// error-pattern:expected: 15, given: 14
+// error-pattern:left: 14 != right: 15
#[deriving(Eq)]
struct Point { x : int }
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// error-pattern:task failed at 'assertion failed: false'
+
+fn main() {
+ assert!(false);
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// error-pattern:task failed at 'test-assert-fmt 42 rust'
+
+fn main() {
+ assert!(false, "test-assert-fmt %d %s", 42, "rust");
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// error-pattern:task failed at 'test-assert-owned'
+
+fn main() {
+ assert!(false, ~"test-assert-owned");
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// error-pattern:task failed at 'test-assert-static'
+
+fn main() {
+ assert!(false, "test-assert-static");
+}
// Testing that runtime failure doesn't cause callbacks to abort abnormally.
// Instead the failure will be delivered after the callbacks return.
+use core::old_iter;
+
mod rustrt {
pub extern {
pub fn rust_dbg_call(cb: *u8, data: libc::uintptr_t)
}
fn main() {
- for iter::repeat(10u) {
+ for old_iter::repeat(10u) {
do task::spawn {
let result = count(5u);
debug!("result = %?", result);
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// error-pattern:task failed at 'explicit failure'
+
+fn main() {
+ fail!();
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// error-pattern:task failed at 'test-fail-fmt 42 rust'
+
+fn main() {
+ fail!("test-fail-fmt %d %s", 42, "rust");
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// error-pattern:task failed at 'test-fail-owned'
+
+fn main() {
+ fail!(~"test-fail-owned");
+}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// error-pattern:task failed at 'test-fail-static'
+
+fn main() {
+ fail!("test-fail-static");
+}
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// error-pattern:ran out of stack
-
-// Don't leak when the landing pads need to request more stack
-// than is allowed during normal execution
-
-fn useBlock(f: ~fn() -> uint) { useBlock(|| 22u ) }
-fn main() {
- useBlock(|| 22u );
-}
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// xfail-test iloops with optimizations on
-
-// NB: Not sure why this works. I expect the box argument to leak when
-// we run out of stack. Maybe the box annihilator works it out?
-
-// error-pattern:ran out of stack
-fn main() {
- eat(@0);
-}
-
-fn eat(
- +a: @int
-) {
- eat(a)
-}
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// xfail-test
-// error-pattern:ran out of stack
-fn main() {
- eat(~0);
-}
-
-fn eat(
- +a: ~int
-) {
- eat(a)
-}
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// error-pattern:ran out of stack
-
-// Test that the task fails after hiting the recursion limit
-
-fn main() {
- debug!(~"don't optimize me out");
- main();
-}
impl Drop for r {
fn finalize(&self) {
unsafe {
- let _v2: ~int = cast::reinterpret_cast(&self.v);
+ let _v2: ~int = cast::transmute(self.v);
}
}
}
fn main() {
unsafe {
let i1 = ~0;
- let i1p = cast::reinterpret_cast(&i1);
+ let i1p = cast::transmute_copy(&i1);
cast::forget(i1);
let x = @r(i1p);
failfn();
// xfail-pretty
-#[legacy_modes];
-
extern mod std;
extern mod syntax;
_ => { debug!("?"); fail!(); }
}
debug!(::core::sys::refcount(s));
- assert!((::core::sys::refcount(s) == count + 1u));
+ assert_eq!(::core::sys::refcount(s), count + 1u);
let _ = ::core::sys::refcount(s); // don't get bitten by last-use.
}
debug!("%u", ::core::sys::refcount(s));
let count2 = ::core::sys::refcount(s);
let _ = ::core::sys::refcount(s); // don't get bitten by last-use.
- assert!(count == count2);
+ assert_eq!(count, count2);
}
+++ /dev/null
-
-// xfail-test
-
-fn altsimple(any x) {
- match type (f) {
- case (int i) { print("int"); }
- case (str s) { print("str"); }
- }
-}
-
-pub fn main() {
- altsimple(5);
- altsimple("asdfasdfsDF");
-}
fn test_ptr() {
unsafe {
- let p1: *u8 = ::core::cast::reinterpret_cast(&0);
- let p2: *u8 = ::core::cast::reinterpret_cast(&0);
- let p3: *u8 = ::core::cast::reinterpret_cast(&1);
+ let p1: *u8 = ::core::cast::transmute(0);
+ let p2: *u8 = ::core::cast::transmute(0);
+ let p3: *u8 = ::core::cast::transmute(1);
assert!(p1 == p2);
assert!(p1 != p3);
unsafe {
error!("q = %x, r = %x",
- (::core::cast::reinterpret_cast::<*p, uint>(&ptr::addr_of(&q))),
- (::core::cast::reinterpret_cast::<*p, uint>(&ptr::addr_of(&r))));
+ (::core::cast::transmute::<*p, uint>(&q)),
+ (::core::cast::transmute::<*p, uint>(&r)));
}
assert!((q == r));
r.y = 17;
}
pub fn main() {
- do iter::repeat(10000) || {bitv_test()};
+ do old_iter::repeat(10000) || {bitv_test()};
}
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-extern mod std;
-
-pub fn main() {
- let v =
- vec::map2(~[1, 2, 3, 4, 5],
- ~[true, false, false, true, true],
- |i, b| if *b { -(*i) } else { *i } );
- error!(v.clone());
- assert!((v == ~[-1, 2, 3, -4, -5]));
-}
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+extern mod std;
+
+pub fn main() {
+ let v =
+ vec::map_zip(~[1, 2, 3, 4, 5],
+ ~[true, false, false, true, true],
+ |i, b| if *b { -(*i) } else { *i } );
+ error!(v.clone());
+ assert!((v == ~[-1, 2, 3, -4, -5]));
+}
fn test1(x: @~int) {
do borrow(&*(*x).clone()) |p| {
- let x_a = ptr::addr_of(&(**x));
+ let x_a = ptr::to_unsafe_ptr(&**x);
assert!((x_a as uint) != ptr::to_uint(p));
assert!(unsafe{*x_a} == *p);
}
match x {
@F {f: ref b_x} => {
assert!(**b_x == 3);
- assert!(ptr::addr_of(&(*x.f)) == ptr::addr_of(&(**b_x)));
+ assert!(ptr::to_unsafe_ptr(&(*x.f)) == ptr::to_unsafe_ptr(&(**b_x)));
x = @F {f: ~4};
- debug!("ptr::addr_of(*b_x) = %x", ptr::addr_of(&(**b_x)) as uint);
+ debug!("ptr::to_unsafe_ptr(*b_x) = %x",
+ ptr::to_unsafe_ptr(&(**b_x)) as uint);
assert!(**b_x == 3);
- assert!(ptr::addr_of(&(*x.f)) != ptr::addr_of(&(**b_x)));
+ assert!(ptr::to_unsafe_ptr(&(*x.f)) != ptr::to_unsafe_ptr(&(**b_x)));
}
}
}
let mut x = @F {f: ~3};
do borrow(x.f) |b_x| {
assert!(*b_x == 3);
- assert!(ptr::addr_of(&(*x.f)) == ptr::addr_of(&(*b_x)));
+ assert!(ptr::to_unsafe_ptr(&(*x.f)) == ptr::to_unsafe_ptr(&(*b_x)));
x = @F {f: ~4};
- debug!("ptr::addr_of(*b_x) = %x", ptr::addr_of(&(*b_x)) as uint);
+ debug!("ptr::to_unsafe_ptr(*b_x) = %x",
+ ptr::to_unsafe_ptr(&(*b_x)) as uint);
assert!(*b_x == 3);
- assert!(ptr::addr_of(&(*x.f)) != ptr::addr_of(&(*b_x)));
+ assert!(ptr::to_unsafe_ptr(&(*x.f)) != ptr::to_unsafe_ptr(&(*b_x)));
}
}
match x {
@@F{f: ref b_x} => {
assert!(**b_x == 3);
- assert!(ptr::addr_of(&(x.f)) == ptr::addr_of(b_x));
+ assert!(ptr::to_unsafe_ptr(&(x.f)) == ptr::to_unsafe_ptr(b_x));
*x = @F {f: ~4};
- debug!("ptr::addr_of(*b_x) = %x", ptr::addr_of(&(**b_x)) as uint);
+ debug!("ptr::to_unsafe_ptr(*b_x) = %x",
+ ptr::to_unsafe_ptr(&(**b_x)) as uint);
assert!(**b_x == 3);
- assert!(ptr::addr_of(&(*x.f)) != ptr::addr_of(&(**b_x)));
+ assert!(ptr::to_unsafe_ptr(&(*x.f)) != ptr::to_unsafe_ptr(&(**b_x)));
}
}
}
let mut x = ~@F{f: ~3};
do borrow(x.f) |b_x| {
assert!(*b_x == 3);
- assert!(ptr::addr_of(&(*x.f)) == ptr::addr_of(&(*b_x)));
+ assert!(ptr::to_unsafe_ptr(&(*x.f)) == ptr::to_unsafe_ptr(&(*b_x)));
*x = @F{f: ~4};
- debug!("ptr::addr_of(*b_x) = %x", ptr::addr_of(&(*b_x)) as uint);
+ debug!("ptr::to_unsafe_ptr(*b_x) = %x",
+ ptr::to_unsafe_ptr(&(*b_x)) as uint);
assert!(*b_x == 3);
- assert!(ptr::addr_of(&(*x.f)) != ptr::addr_of(&(*b_x)));
+ assert!(ptr::to_unsafe_ptr(&(*x.f)) != ptr::to_unsafe_ptr(&(*b_x)));
}
}
let mut x = @3;
do borrow(x) |b_x| {
assert!(*b_x == 3);
- assert!(ptr::addr_of(&(*x)) == ptr::addr_of(&(*b_x)));
+ assert!(ptr::to_unsafe_ptr(&(*x)) == ptr::to_unsafe_ptr(&(*b_x)));
x = @22;
- debug!("ptr::addr_of(*b_x) = %x", ptr::addr_of(&(*b_x)) as uint);
+ debug!("ptr::to_unsafe_ptr(*b_x) = %x",
+ ptr::to_unsafe_ptr(&(*b_x)) as uint);
assert!(*b_x == 3);
- assert!(ptr::addr_of(&(*x)) != ptr::addr_of(&(*b_x)));
+ assert!(ptr::to_unsafe_ptr(&(*x)) != ptr::to_unsafe_ptr(&(*b_x)));
}
}
let mut x = @F {f: ~3};
do borrow((*x).f) |b_x| {
assert!(*b_x == 3);
- assert!(ptr::addr_of(&(*x.f)) == ptr::addr_of(&(*b_x)));
+ assert!(ptr::to_unsafe_ptr(&(*x.f)) == ptr::to_unsafe_ptr(&(*b_x)));
x = @F {f: ~4};
- debug!("ptr::addr_of(*b_x) = %x", ptr::addr_of(&(*b_x)) as uint);
+ debug!("ptr::to_unsafe_ptr(*b_x) = %x",
+ ptr::to_unsafe_ptr(&(*b_x)) as uint);
assert!(*b_x == 3);
- assert!(ptr::addr_of(&(*x.f)) != ptr::addr_of(&(*b_x)));
+ assert!(ptr::to_unsafe_ptr(&(*x.f)) != ptr::to_unsafe_ptr(&(*b_x)));
}
}
pub fn main() {
let x = ~1;
- let y = ptr::addr_of(&(*x)) as uint;
- let lam_move: @fn() -> uint = || ptr::addr_of(&(*x)) as uint;
+ let y = ptr::to_unsafe_ptr(&(*x)) as uint;
+ let lam_move: @fn() -> uint = || ptr::to_unsafe_ptr(&(*x)) as uint;
assert!(lam_move() == y);
let x = ~2;
- let y = ptr::addr_of(&(*x)) as uint;
- let lam_move: @fn() -> uint = || ptr::addr_of(&(*x)) as uint;
+ let y = ptr::to_unsafe_ptr(&(*x)) as uint;
+ let lam_move: @fn() -> uint = || ptr::to_unsafe_ptr(&(*x)) as uint;
assert!(lam_move() == y);
let x = ~3;
- let y = ptr::addr_of(&(*x)) as uint;
- let snd_move: ~fn() -> uint = || ptr::addr_of(&(*x)) as uint;
+ let y = ptr::to_unsafe_ptr(&(*x)) as uint;
+ let snd_move: ~fn() -> uint = || ptr::to_unsafe_ptr(&(*x)) as uint;
assert!(snd_move() == y);
let x = ~4;
- let y = ptr::addr_of(&(*x)) as uint;
- let lam_move: ~fn() -> uint = || ptr::addr_of(&(*x)) as uint;
+ let y = ptr::to_unsafe_ptr(&(*x)) as uint;
+ let lam_move: ~fn() -> uint = || ptr::to_unsafe_ptr(&(*x)) as uint;
assert!(lam_move() == y);
}
// xfail-fast - check-fast doesn't understand aux-build
// aux-build:cci_iter_lib.rs
-#[legacy_modes];
-
extern mod cci_iter_lib;
pub fn main() {
//let bt0 = sys::rusti::frame_address(1u32);
//debug!("%?", bt0);
do cci_iter_lib::iter(~[1, 2, 3]) |i| {
- io::print(fmt!("%d", i));
+ io::print(fmt!("%d", *i));
//assert!(bt0 == sys::rusti::frame_address(2u32));
}
}
pub fn main() {
let lst = new_int_alist();
- alist_add(lst, 22, ~"hi");
- alist_add(lst, 44, ~"ho");
- assert!(alist_get(lst, 22) == ~"hi");
- assert!(alist_get(lst, 44) == ~"ho");
+ alist_add(&lst, 22, ~"hi");
+ alist_add(&lst, 44, ~"ho");
+ assert!(alist_get(&lst, 22) == ~"hi");
+ assert!(alist_get(&lst, 44) == ~"ho");
let lst = new_int_alist_2();
- alist_add(lst, 22, ~"hi");
- alist_add(lst, 44, ~"ho");
- assert!(alist_get(lst, 22) == ~"hi");
- assert!(alist_get(lst, 44) == ~"ho");
+ alist_add(&lst, 22, ~"hi");
+ alist_add(&lst, 44, ~"ho");
+ assert!(alist_get(&lst, 22) == ~"hi");
+ assert!(alist_get(&lst, 44) == ~"ho");
}
// xfail-fast
use core::container::{Container, Mutable, Map};
-use core::iter::BaseIter;
+use core::old_iter::BaseIter;
enum cat_type { tuxedo, tabby, tortoiseshell }
// except according to those terms.
// xfail-fast
-#[legacy_modes];
trait noisy {
fn speak(&mut self);
let mut nyan = cat(0u, 2, ~"nyan");
nyan.eat();
assert!((!nyan.eat()));
- for uint::range(1u, 10u) |_i| { make_speak(nyan); };
- assert!((nyan.eat()));
+ for uint::range(1u, 10u) |_i| {
+ make_speak(copy nyan);
+ }
}
use std::oldmap::{map, hashmap, int_hash};
class keys<K:Copy,V:Copy,M:Copy + map<K,V>>
- : iter::base_iter<K> {
+ : old_iter::base_iter<K> {
let map: M;
fn each(blk: &fn(K) -> bool) { self.map.each(|k, _v| blk(k) ) }
fn size_hint() -> Option<uint> { Some(self.map.size()) }
- fn eachi(blk: &fn(uint, K) -> bool) { iter::eachi(self, blk) }
+ fn eachi(blk: &fn(uint, K) -> bool) { old_iter::eachi(self, blk) }
}
pub fn main() {
let m = int_hash();
m.insert(1, 2);
m.insert(3, 4);
- assert!(iter::to_vec(keys(m)) == ~[1, 3]);
+ assert!(old_iter::to_vec(keys(m)) == ~[1, 3]);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-//xfail-test
-
extern mod std;
+use core::task::spawn;
-fn f(x : @{a:int, b:int}) {
- assert!((x.a == 10));
- assert!((x.b == 12));
+struct Pair {
+ a: int,
+ b: int
}
pub fn main() {
- let z : @{a:int, b:int} = @{ a : 10, b : 12};
- let p = task::_spawn(bind f(z));
- task::join_id(p);
+ let z = ~Pair { a : 10, b : 12};
+
+ let f: ~fn() = || {
+ assert!((z.a == 10));
+ assert!((z.b == 12));
+ };
+
+ spawn(f);
}
static y: &'static Pair<'static> = &Pair {a: 15, b: x};
pub fn main() {
- assert!(ptr::addr_of(x) == ptr::addr_of(y.b));
+ assert!(ptr::to_unsafe_ptr(x) == ptr::to_unsafe_ptr(y.b));
}
pub fn main() {
- for iter::eachi(&(Some(A {a: 0}))) |i, a| {
+ for old_iter::eachi(&(Some(A {a: 0}))) |i, a| {
debug!("%u %d", i, a.a);
}
// except according to those terms.
fn addr_of<T>(ptr: &T) -> uint {
- let ptr = ptr::addr_of(ptr);
+ let ptr = ptr::to_unsafe_ptr(ptr);
unsafe { ptr as uint }
}
fn is_aligned<T>(ptr: &T) -> bool {
- (addr_of(ptr) % sys::min_align_of::<T>()) == 0
+ unsafe {
+ let addr: uint = ::cast::transmute(ptr);
+ (addr % sys::min_align_of::<T>()) == 0
+ }
}
pub fn main() {
// except according to those terms.
// xfail-fast
-#[legacy_modes];
type compare<T> = @fn(T, T) -> bool;
}
fn test_vec() {
- fn compare_vec(&&v1: @int, &&v2: @int) -> bool { return v1 == v2; }
+ fn compare_vec(v1: @int, v2: @int) -> bool { return v1 == v2; }
test_generic::<@int>(@1, compare_vec);
}
// xfail-fast
// -*- rust -*-
-#[legacy_modes];
type compare<T> = @fn(T, T) -> bool;
}
fn test_vec() {
- fn compare_vec(&&v1: ~int, &&v2: ~int) -> bool { return v1 == v2; }
+ fn compare_vec(v1: ~int, v2: ~int) -> bool { return v1 == v2; }
test_generic::<~int>(~1, compare_vec);
}
// xfail-fast
// -*- rust -*-
-#[legacy_modes];
type compare<T> = @fn(T, T) -> bool;
}
fn test_vec() {
- fn compare_box(&&v1: @int, &&v2: @int) -> bool { return v1 == v2; }
+ fn compare_box(v1: @int, v2: @int) -> bool { return v1 == v2; }
test_generic::<@int>(@1, @2, compare_box);
}
}
pub fn main() {
- for iter::repeat(100u) {
+ for old_iter::repeat(100u) {
do task::spawn {
assert!(count(5u) == 16u);
};
}
pub fn main() {
- for iter::repeat(10u) {
+ for old_iter::repeat(10u) {
do task::spawn {
let result = count(5u);
debug!("result = %?", result);
extern mod std;
+use core::num::Float::{
+ NaN, infinity, neg_infinity
+};
+
pub fn main() {
- let nan = float::NaN;
- assert!((float::is_NaN(nan)));
+ let nan = NaN::<float>();
+ assert!((nan).is_NaN());
- let inf = float::infinity;
- assert!((-inf == float::neg_infinity));
+ let inf = infinity::<float>();
+ assert!(-inf == neg_infinity::<float>());
- assert!(( nan != nan));
- assert!(( nan != -nan));
- assert!((-nan != -nan));
- assert!((-nan != nan));
+ assert!( nan != nan);
+ assert!( nan != -nan);
+ assert!(-nan != -nan);
+ assert!(-nan != nan);
- assert!(( nan != 1.));
- assert!(( nan != 0.));
- assert!(( nan != inf));
- assert!(( nan != -inf));
+ assert!( nan != 1.);
+ assert!( nan != 0.);
+ assert!( nan != inf);
+ assert!( nan != -inf);
- assert!(( 1. != nan));
- assert!(( 0. != nan));
- assert!(( inf != nan));
- assert!((-inf != nan));
+ assert!( 1. != nan);
+ assert!( 0. != nan);
+ assert!( inf != nan);
+ assert!(-inf != nan);
- assert!((!( nan == nan)));
- assert!((!( nan == -nan)));
- assert!((!( nan == 1.)));
- assert!((!( nan == 0.)));
- assert!((!( nan == inf)));
- assert!((!( nan == -inf)));
- assert!((!( 1. == nan)));
- assert!((!( 0. == nan)));
- assert!((!( inf == nan)));
- assert!((!(-inf == nan)));
- assert!((!(-nan == nan)));
- assert!((!(-nan == -nan)));
+ assert!(!( nan == nan));
+ assert!(!( nan == -nan));
+ assert!(!( nan == 1.));
+ assert!(!( nan == 0.));
+ assert!(!( nan == inf));
+ assert!(!( nan == -inf));
+ assert!(!( 1. == nan));
+ assert!(!( 0. == nan));
+ assert!(!( inf == nan));
+ assert!(!(-inf == nan));
+ assert!(!(-nan == nan));
+ assert!(!(-nan == -nan));
- assert!((!( nan > nan)));
- assert!((!( nan > -nan)));
- assert!((!( nan > 0.)));
- assert!((!( nan > inf)));
- assert!((!( nan > -inf)));
- assert!((!( 0. > nan)));
- assert!((!( inf > nan)));
- assert!((!(-inf > nan)));
- assert!((!(-nan > nan)));
+ assert!(!( nan > nan));
+ assert!(!( nan > -nan));
+ assert!(!( nan > 0.));
+ assert!(!( nan > inf));
+ assert!(!( nan > -inf));
+ assert!(!( 0. > nan));
+ assert!(!( inf > nan));
+ assert!(!(-inf > nan));
+ assert!(!(-nan > nan));
- assert!((!(nan < 0.)));
- assert!((!(nan < 1.)));
- assert!((!(nan < -1.)));
- assert!((!(nan < inf)));
- assert!((!(nan < -inf)));
- assert!((!(nan < nan)));
- assert!((!(nan < -nan)));
+ assert!(!(nan < 0.));
+ assert!(!(nan < 1.));
+ assert!(!(nan < -1.));
+ assert!(!(nan < inf));
+ assert!(!(nan < -inf));
+ assert!(!(nan < nan));
+ assert!(!(nan < -nan));
- assert!((!( 0. < nan)));
- assert!((!( 1. < nan)));
- assert!((!( -1. < nan)));
- assert!((!( inf < nan)));
- assert!((!(-inf < nan)));
- assert!((!(-nan < nan)));
+ assert!(!( 0. < nan));
+ assert!(!( 1. < nan));
+ assert!(!( -1. < nan));
+ assert!(!( inf < nan));
+ assert!(!(-inf < nan));
+ assert!(!(-nan < nan));
- assert!((float::is_NaN(nan + inf)));
- assert!((float::is_NaN(nan + -inf)));
- assert!((float::is_NaN(nan + 0.)));
- assert!((float::is_NaN(nan + 1.)));
- assert!((float::is_NaN(nan * 1.)));
- assert!((float::is_NaN(nan / 1.)));
- assert!((float::is_NaN(nan / 0.)));
- assert!((float::is_NaN(0. / 0.)));
- assert!((float::is_NaN(-inf + inf)));
- assert!((float::is_NaN(inf - inf)));
+ assert!((nan + inf).is_NaN());
+ assert!((nan + -inf).is_NaN());
+ assert!((nan + 0.).is_NaN());
+ assert!((nan + 1.).is_NaN());
+ assert!((nan * 1.).is_NaN());
+ assert!((nan / 1.).is_NaN());
+ assert!((nan / 0.).is_NaN());
+ assert!((0f/0f).is_NaN());
+ assert!((-inf + inf).is_NaN());
+ assert!((inf - inf).is_NaN());
- assert!((!float::is_NaN(-1.)));
- assert!((!float::is_NaN(0.)));
- assert!((!float::is_NaN(0.1)));
- assert!((!float::is_NaN(1.)));
- assert!((!float::is_NaN(inf)));
- assert!((!float::is_NaN(-inf)));
- assert!((!float::is_NaN(1./-inf)));
+ assert!(!(-1f).is_NaN());
+ assert!(!(0f).is_NaN());
+ assert!(!(0.1f).is_NaN());
+ assert!(!(1f).is_NaN());
+ assert!(!(inf).is_NaN());
+ assert!(!(-inf).is_NaN());
+ assert!(!(1./-inf).is_NaN());
}
// xfail-test
extern mod std;
-use task::join;
-
-fn loop(n: int) {
- let t1: task;
- let t2: task;
-
- if n > 0 { t1 = spawn loop(n - 1); t2 = spawn loop(n - 1); }
-
+fn loopy(n: int) {
+ if n > 0 { do spawn { loopy(n - 1) }; do spawn { loopy(n - 1) }; }
loop { }
}
-pub fn main() { let t: task = spawn loop(5); join(t); }
+pub fn main() {
+ // Commenting this out, as this will hang forever otherwise.
+ // Even after seeing the comment above, I'm not sure what the
+ // intention of this test is.
+ // do spawn { loopy(5) };
+}
// except according to those terms.
// xfail-fast
-#[legacy_modes];
mod rusti {
#[abi = "rust-intrinsic"]
fn to_c_int(v: &mut int) -> &mut c_int {
unsafe {
- cast::reinterpret_cast(&v)
+ cast::transmute_copy(&v)
}
}
pub fn main() {
let mut x = 0;
- loop foo: {
- loop bar: {
- loop quux: {
+ 'foo: loop {
+ 'bar: loop {
+ 'quux: loop {
if 1 == 2 {
- break foo;
+ break 'foo;
}
else {
- break bar;
+ break 'bar;
}
}
- loop foo;
+ loop 'foo;
}
x = 42;
break;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::iter::BaseIter;
+use core::old_iter::BaseIter;
trait FlatMapToVec<A> {
fn flat_map_to_vec<B, IB:BaseIter<B>>(&self, op: &fn(&A) -> IB) -> ~[B];
impl<A:Copy> FlatMapToVec<A> for ~[A] {
fn flat_map_to_vec<B, IB:BaseIter<B>>(&self, op: &fn(&A) -> IB) -> ~[B] {
- iter::flat_map_to_vec(self, op)
+ old_iter::flat_map_to_vec(self, op)
}
}
pub fn liberate_ping(+p: ping) -> ::pipes::send_packet<pong> {
unsafe {
let addr : *::pipes::send_packet<pong> = match &p {
- &ping(ref x) => { cast::transmute(ptr::addr_of(x)) }
+ &ping(ref x) => { cast::transmute(x) }
};
let liberated_value = *addr;
cast::forget(p);
pub fn liberate_pong(+p: pong) -> ::pipes::send_packet<ping> {
unsafe {
let addr : *::pipes::send_packet<ping> = match &p {
- &pong(ref x) => { cast::transmute(ptr::addr_of(x)) }
+ &pong(ref x) => { cast::transmute(x) }
};
let liberated_value = *addr;
cast::forget(p);
assert!([2u, 4u].all(is_even));
assert!([].all(is_even));
- assert!(!iter::all(&Some(1u), is_even));
- assert!(iter::all(&Some(2u), is_even));
- assert!(iter::all(&None::<uint>, is_even));
+ assert!(!old_iter::all(&Some(1u), is_even));
+ assert!(old_iter::all(&Some(2u), is_even));
+ assert!(old_iter::all(&None::<uint>, is_even));
}
assert!([1u, 2u].any(is_even));
assert!(![].any(is_even));
- assert!(!iter::any(&Some(1u), is_even));
- assert!(iter::any(&Some(2u), is_even));
- assert!(!iter::any(&None::<uint>, is_even));
+ assert!(!old_iter::any(&Some(1u), is_even));
+ assert!(old_iter::any(&Some(2u), is_even));
+ assert!(!old_iter::any(&None::<uint>, is_even));
}
assert!([22u, 1u, 3u].contains(&22u) == true);
assert!([1u, 22u, 3u].contains(&22u) == true);
assert!([1u, 3u, 22u].contains(&22u) == true);
- assert!(iter::contains(&None::<uint>, &22u) == false);
- assert!(iter::contains(&Some(1u), &22u) == false);
- assert!(iter::contains(&Some(22u), &22u) == true);
+ assert!(old_iter::contains(&None::<uint>, &22u) == false);
+ assert!(old_iter::contains(&Some(1u), &22u) == false);
+ assert!(old_iter::contains(&Some(22u), &22u) == true);
}
assert!([1u, 3u].count(&22u) == 0u);
assert!([22u, 1u, 3u].count(&22u) == 1u);
assert!([22u, 1u, 22u].count(&22u) == 2u);
- assert!(iter::count(&None::<uint>, &22u) == 0u);
- assert!(iter::count(&Some(1u), &22u) == 0u);
- assert!(iter::count(&Some(22u), &22u) == 1u);
+ assert!(old_iter::count(&None::<uint>, &22u) == 0u);
+ assert!(old_iter::count(&Some(1u), &22u) == 0u);
+ assert!(old_iter::count(&Some(22u), &22u) == 1u);
}
}
assert!(c == 5u);
- for iter::eachi(&None::<uint>) |i, v| { fail!(); }
+ for old_iter::eachi(&None::<uint>) |i, v| { fail!(); }
let mut c = 0u;
- for iter::eachi(&Some(1u)) |i, v| {
+ for old_iter::eachi(&Some(1u)) |i, v| {
assert!((i + 1u) == *v);
c += 1u;
}
pub fn main() {
assert!([1, 3].filter_to_vec(is_even) == ~[]);
assert!([1, 2, 3].filter_to_vec(is_even) == ~[2]);
- assert!(iter::filter_to_vec(&None::<uint>, is_even) == ~[]);
- assert!(iter::filter_to_vec(&Some(1u), is_even) == ~[]);
- assert!(iter::filter_to_vec(&Some(2u), is_even) == ~[2]);
+ assert!(old_iter::filter_to_vec(&None::<uint>, is_even) == ~[]);
+ assert!(old_iter::filter_to_vec(&Some(1u), is_even) == ~[]);
+ assert!(old_iter::filter_to_vec(&Some(2u), is_even) == ~[2]);
}
pub fn main() {
assert!((~[1u, 3u]).flat_map_to_vec(repeat) == ~[1u, 1u, 3u, 3u]);
assert!((~[]).flat_map_to_vec(repeat) == ~[]);
- assert!(iter::flat_map_to_vec(&None::<uint>, repeat) == ~[]);
- assert!(iter::flat_map_to_vec(&Some(1u), repeat) == ~[1u, 1u]);
- assert!(iter::flat_map_to_vec(&Some(2u), repeat) == ~[2u, 2u]);
+ assert!(old_iter::flat_map_to_vec(&None::<uint>, repeat) == ~[]);
+ assert!(old_iter::flat_map_to_vec(&Some(1u), repeat) == ~[1u, 1u]);
+ assert!(old_iter::flat_map_to_vec(&Some(2u), repeat) == ~[2u, 2u]);
assert!((~[1u, 2u, 5u]).flat_map_to_vec(incd_if_even) == ~[3u]);
assert!((~[]).flat_map_to_vec(incd_if_even) == ~[]);
- assert!(iter::flat_map_to_vec(&None::<uint>, incd_if_even) == ~[]);
- assert!(iter::flat_map_to_vec(&Some(1u), incd_if_even) == ~[]);
- assert!(iter::flat_map_to_vec(&Some(2u), incd_if_even) == ~[3u]);
+ assert!(old_iter::flat_map_to_vec(&None::<uint>, incd_if_even) == ~[]);
+ assert!(old_iter::flat_map_to_vec(&Some(1u), incd_if_even) == ~[]);
+ assert!(old_iter::flat_map_to_vec(&Some(2u), incd_if_even) == ~[3u]);
}
pub fn main() {
assert!([1u, 3u].foldl(20f, add) == 24f);
assert!([].foldl(20f, add) == 20f);
- assert!(iter::foldl(&None::<uint>, 20f, add) == 20f);
- assert!(iter::foldl(&Some(1u), 20f, add) == 21f);
- assert!(iter::foldl(&Some(2u), 20f, add) == 22f);
+ assert!(old_iter::foldl(&None::<uint>, 20f, add) == 20f);
+ assert!(old_iter::foldl(&Some(1u), 20f, add) == 21f);
+ assert!(old_iter::foldl(&Some(2u), 20f, add) == 22f);
}
pub fn main() {
assert!([1, 3].map_to_vec(inc) == ~[2, 4]);
assert!([1, 2, 3].map_to_vec(inc) == ~[2, 3, 4]);
- assert!(iter::map_to_vec(&None::<uint>, inc) == ~[]);
- assert!(iter::map_to_vec(&Some(1u), inc) == ~[2]);
- assert!(iter::map_to_vec(&Some(2u), inc) == ~[3]);
+ assert!(old_iter::map_to_vec(&None::<uint>, inc) == ~[]);
+ assert!(old_iter::map_to_vec(&Some(1u), inc) == ~[2]);
+ assert!(old_iter::map_to_vec(&Some(2u), inc) == ~[3]);
}
pub fn main() {
assert!([1u, 3u].min() == 1u);
assert!([3u, 1u].min() == 1u);
- assert!(iter::min(&Some(1u)) == 1u);
+ assert!(old_iter::min(&Some(1u)) == 1u);
assert!([1u, 3u].max() == 3u);
assert!([3u, 1u].max() == 3u);
- assert!(iter::max(&Some(3u)) == 3u);
+ assert!(old_iter::max(&Some(3u)) == 3u);
}
assert!([1u, 3u].to_vec() == ~[1u, 3u]);
let e: ~[uint] = ~[];
assert!(e.to_vec() == ~[]);
- assert!(iter::to_vec(&None::<uint>) == ~[]);
- assert!(iter::to_vec(&Some(1u)) == ~[1u]);
- assert!(iter::to_vec(&Some(2u)) == ~[2u]);
+ assert!(old_iter::to_vec(&None::<uint>) == ~[]);
+ assert!(old_iter::to_vec(&Some(1u)) == ~[1u]);
+ assert!(old_iter::to_vec(&Some(2u)) == ~[2u]);
}
// xfail-test
pub fn main() {
- loop foo: {
+ 'foo: loop {
loop {
- break foo;
+ break 'foo;
}
}
}
)
macro_rules! move_it (
- { $x:expr } => { unsafe { let y = *ptr::addr_of(&($x)); y } }
+ { $x:expr } => { unsafe { let y = *ptr::to_unsafe_ptr(&($x)); y } }
)
fn switch<T:Owned,U>(+endp: pipes::RecvPacket<T>,
do pipes::entangle_buffer(buffer) |buffer, data| {
data.ping.set_buffer(buffer);
data.pong.set_buffer(buffer);
- ptr::addr_of(&(data.ping))
+ ptr::to_unsafe_ptr(&(data.ping))
}
}
pub struct ping(server::pong);
pub fn ping(+pipe: ping) -> pong {
{
let b = pipe.reuse_buffer();
- let s = SendPacketBuffered(ptr::addr_of(&(b.buffer.data.pong)));
- let c = RecvPacketBuffered(ptr::addr_of(&(b.buffer.data.pong)));
+ let s = SendPacketBuffered(&b.buffer.data.pong);
+ let c = RecvPacketBuffered(&b.buffer.data.pong);
let message = ::pingpong::ping(s);
send(pipe, message);
c
pub fn pong(+pipe: pong) -> ping {
{
let b = pipe.reuse_buffer();
- let s = SendPacketBuffered(ptr::addr_of(&(b.buffer.data.ping)));
- let c = RecvPacketBuffered(ptr::addr_of(&(b.buffer.data.ping)));
+ let s = SendPacketBuffered(&b.buffer.data.ping);
+ let c = RecvPacketBuffered(&b.buffer.data.ping);
let message = ::pingpong::pong(s);
send(pipe, message);
c
pub fn main() {
unsafe {
let r = (1,2,3,true,false, Triple {x:5,y:4,z:3}, (12,));
- let p = ptr::addr_of(&r) as *c_void;
+ let p = ptr::to_unsafe_ptr(&r) as *c_void;
let u = my_visitor(@mut Stuff {ptr1: p,
ptr2: p,
vals: ~[]});
fn alloc<'a>(_bcx : &'a arena) -> &'a Bcx<'a> {
unsafe {
- return cast::reinterpret_cast(
- &libc::malloc(sys::size_of::<Bcx<'blk>>() as libc::size_t));
+ cast::transmute(libc::malloc(sys::size_of::<Bcx<'blk>>()
+ as libc::size_t))
}
}
let bcx = Bcx { fcx: fcx };
let bcx2 = h(&bcx);
unsafe {
- libc::free(cast::reinterpret_cast(&bcx2));
+ libc::free(cast::transmute(bcx2));
}
}
fn finalize(&self) {
unsafe {
debug!("r's dtor: self = %x, self.v = %x, self.v's value = %x",
- cast::reinterpret_cast::<*r, uint>(&ptr::addr_of(self)),
- cast::reinterpret_cast::<**int, uint>(&ptr::addr_of(&(self.v))),
- cast::reinterpret_cast::<*int, uint>(&self.v));
- let v2: ~int = cast::reinterpret_cast(&self.v);
+ cast::transmute::<*r, uint>(self),
+ cast::transmute::<**int, uint>(&(self.v)),
+ cast::transmute::<*int, uint>(self.v));
+ let v2: ~int = cast::transmute(self.v);
}
}
}
pub fn main() {
unsafe {
let i1 = ~0;
- let i1p = cast::reinterpret_cast(&i1);
+ let i1p = cast::transmute_copy(&i1);
cast::forget(i1);
let i2 = ~0;
- let i2p = cast::reinterpret_cast(&i2);
+ let i2p = cast::transmute_copy(&i2);
cast::forget(i2);
let mut x1 = @mut t(Node{
next: None,
r: {
let rs = r(i1p);
- debug!("r = %x",
- cast::reinterpret_cast::<*r, uint>(&ptr::addr_of(&rs)));
+ debug!("r = %x", cast::transmute::<*r, uint>(&rs));
rs }
});
debug!("x1 = %x, x1.r = %x",
- cast::reinterpret_cast::<@mut t, uint>(&x1),
- cast::reinterpret_cast::<*r, uint>(&ptr::addr_of(&(x1.r))));
+ cast::transmute::<@mut t, uint>(x1),
+ cast::transmute::<*r, uint>(&x1.r));
let mut x2 = @mut t(Node{
next: None,
r: {
let rs = r(i2p);
- debug!("r2 = %x",
- cast::reinterpret_cast::<*r, uint>(&ptr::addr_of(&rs)));
+ debug!("r2 = %x", cast::transmute::<*r, uint>(&rs));
rs
}
});
debug!("x2 = %x, x2.r = %x",
- cast::reinterpret_cast::<@mut t, uint>(&x2),
- cast::reinterpret_cast::<*r, uint>(&ptr::addr_of(&(x2.r))));
+ cast::transmute::<@mut t, uint>(x2),
+ cast::transmute::<*r, uint>(&(x2.r)));
x1.next = Some(x2);
x2.next = Some(x1);
impl Drop for r {
fn finalize(&self) {
unsafe {
- let v2: ~int = cast::reinterpret_cast(&self.v.c);
+ let v2: ~int = cast::transmute(self.v.c);
}
}
}
pub fn main() {
unsafe {
let i1 = ~0xA;
- let i1p = cast::reinterpret_cast(&i1);
+ let i1p = cast::transmute_copy(&i1);
cast::forget(i1);
let i2 = ~0xA;
- let i2p = cast::reinterpret_cast(&i2);
+ let i2p = cast::transmute_copy(&i2);
cast::forget(i2);
let u1 = U {a: 0xB, b: 0xC, c: i1p};
impl Drop for R {
fn finalize(&self) {
unsafe {
- let _v2: ~int = cast::reinterpret_cast(&self.v.c);
- // let _v3: ~int = unsafe::reinterpret_cast(self.x);
+ let _v2: ~int = cast::transmute(self.v.c);
+ // let _v3: ~int = cast::transmute_copy(self.x);
}
}
}
R {
v: v,
w: w,
- x: cast::reinterpret_cast(&0)
+ x: cast::transmute(0)
}
}
}
pub fn main() {
unsafe {
let i1 = ~0xA;
- let i1p = cast::reinterpret_cast(&i1);
+ let i1p = cast::transmute_copy(&i1);
cast::forget(i1);
let i2 = ~0xA;
- let i2p = cast::reinterpret_cast(&i2);
+ let i2p = cast::transmute_copy(&i2);
cast::forget(i2);
let u1 = U {a: 0xB, b: 0xC, c: i1p};
ch.send(());
}
};
- let fptr = cast::reinterpret_cast(&ptr::addr_of(&f));
+ let fptr = cast::transmute(&f);
rustrt::start_task(new_task_id, fptr);
cast::forget(f);
po.recv();
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use core::cell::Cell;
+
pub fn main() { test05(); }
fn test05_start(&&f: ~fn(int)) {
error!(*three + n); // will copy x into the closure
assert!((*three == 3));
};
+ let fn_to_send = Cell(fn_to_send);
task::spawn(|| {
- test05_start(fn_to_send);
+ test05_start(fn_to_send.take());
});
}
pub fn main() {
let foo = 1;
- assert!(ptr::addr_of(&foo) == ptr::addr_of(&foo));
+ assert!(ptr::to_unsafe_ptr(&foo) == ptr::to_unsafe_ptr(&foo));
}
// except according to those terms.
// xfail-fast
-#[legacy_modes];
// A trait for objects that can be used to do an if-then-else
// (No actual need for this to be static, but it is a simple test.)
/// Apply a function to each element of an iterable and return the results
fn map<T, IT: BaseIter<T>, U, BU: buildable<U>>
- (v: IT, f: &fn(T) -> U) -> BU {
+ (v: IT, f: &fn(&T) -> U) -> BU {
do build |push| {
for v.each() |elem| {
- push(f(*elem));
+ push(f(elem));
}
}
}
let v: @[int] = seq_range(0, 10);
assert!(v == @[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
- let v: @[int] = map(&[1,2,3], |x| 1+x);
+ let v: @[int] = map(&[1,2,3], |&x| 1+x);
assert!(v == @[2, 3, 4]);
- let v: ~[int] = map(&[1,2,3], |x| 1+x);
+ let v: ~[int] = map(&[1,2,3], |&x| 1+x);
assert!(v == ~[2, 3, 4]);
assert!(bool_like::select(true, 9, 14) == 9);
}
fn is_8_byte_aligned(&&u: a_tag<u64>) -> bool {
- let p = ptr::addr_of(u) as uint;
+ let p = ptr::to_unsafe_ptr(u) as uint;
return (p & 7u) == 0u;
}
}
fn is_aligned<A>(amnt: uint, &&u: A) -> bool {
- let p = ptr::addr_of(u) as uint;
+ let p = ptr::to_unsafe_ptr(u) as uint;
return (p & (amnt-1u)) == 0u;
}
}
fn is_8_byte_aligned(&&u: a_tag) -> bool {
- let p = ptr::addr_of(u) as u64;
+ let p = ptr::to_unsafe_ptr(u) as u64;
return (p & 7u64) == 0u64;
}
}
fn test_color(color: color, val: int, name: ~str) {
- //assert!(unsafe::reinterpret_cast(color) == val);
+ //assert!(unsafe::transmute(color) == val);
assert!(color as int == val);
assert!(color as float == val as float);
assert!(get_color_alt(color) == name);
// except according to those terms.
// xfail-fast
-#[legacy_modes];
extern mod std;
pub fn main() { test05(); }
-fn test05_start(ch : Chan<int>) {
+fn test05_start(ch : &Chan<int>) {
ch.send(10);
error!("sent 10");
ch.send(20);
fn test05() {
let (po, ch) = comm::stream();
- task::spawn(|| test05_start(ch) );
- let mut value = po.recv();
+ task::spawn(|| test05_start(&ch) );
+ let mut value: int = po.recv();
error!(value);
value = po.recv();
error!(value);
// except according to those terms.
// xfail-fast
-#[legacy_modes];
extern mod std;
-fn start(c: comm::Chan<int>, start: int, number_of_messages: int) {
+fn start(c: &comm::Chan<int>, start: int, number_of_messages: int) {
let mut i: int = 0;
while i < number_of_messages { c.send(start + i); i += 1; }
}
pub fn main() {
debug!("Check that we don't deadlock.");
let (p, ch) = comm::stream();
- task::try(|| start(ch, 0, 10) );
+ task::try(|| start(&ch, 0, 10) );
debug!("Joined task");
}
// except according to those terms.
// xfail-fast
-#[legacy_modes];
extern mod std;
pub fn main() { test00(); }
-fn test00_start(c: comm::Chan<int>, start: int, number_of_messages: int) {
+fn test00_start(c: &comm::Chan<int>, start: int, number_of_messages: int) {
let mut i: int = 0;
while i < number_of_messages { c.send(start + i); i += 1; }
}
let c = p.chan();
do task::spawn || {
- test00_start(c, number_of_messages * 0, number_of_messages);
+ test00_start(&c, number_of_messages * 0, number_of_messages);
}
let c = p.chan();
do task::spawn || {
- test00_start(c, number_of_messages * 1, number_of_messages);
+ test00_start(&c, number_of_messages * 1, number_of_messages);
}
let c = p.chan();
do task::spawn || {
- test00_start(c, number_of_messages * 2, number_of_messages);
+ test00_start(&c, number_of_messages * 2, number_of_messages);
}
let c = p.chan();
do task::spawn || {
- test00_start(c, number_of_messages * 3, number_of_messages);
+ test00_start(&c, number_of_messages * 3, number_of_messages);
}
let mut i: int = 0;
unsafe {
error!("notify: task=%? v=%x unwinding=%b b=%b",
task::get_task(),
- ptr::addr_of(&(*(self.v))) as uint,
+ ptr::to_unsafe_ptr(&(*(self.v))) as uint,
task::failing(),
*(self.v));
let b = *(self.v);
let b = @mut false;
error!("wrapper: task=%? allocated v=%x",
task::get_task(),
- ptr::addr_of(&(*b)) as uint);
+ ptr::to_unsafe_ptr(&(*b)) as uint);
let _r = notify(c, b);
f();
*b = true;
let (p, ch) = stream::<uint>();
let x = ~1;
- let x_in_parent = ptr::addr_of(&(*x)) as uint;
+ let x_in_parent = ptr::to_unsafe_ptr(&(*x)) as uint;
task::spawn(|| {
- let x_in_child = ptr::addr_of(&(*x)) as uint;
+ let x_in_child = ptr::to_unsafe_ptr(&(*x)) as uint;
ch.send(x_in_child);
});
fn null<T>() -> *T {
unsafe {
- cast::reinterpret_cast(&0)
+ cast::transmute(0)
}
}
}
fn make_uniq_closure<A:Owned + Copy>(a: A) -> ~fn() -> uint {
- let result: ~fn() -> uint = || ptr::addr_of(&a) as uint;
+ let result: ~fn() -> uint = || ptr::to_unsafe_ptr(&a) as uint;
result
}