Merge remote-tracking branch 'original/incoming' into incoming
Conflicts: src/libstd/json.rs src/libstd/sort.rs
This commit is contained in:
commit
efcd2385ea
378 changed files with 11486 additions and 8500 deletions
|
|
@ -17,6 +17,7 @@ Ben Striegel <ben.striegel@gmail.com>
|
|||
Benjamin Herr <ben@0x539.de>
|
||||
Benjamin Jackman <ben@jackman.biz>
|
||||
Benjamin Kircher <benjamin.kircher@gmail.com>
|
||||
Benjamin Peterson <benjamin@python.org>
|
||||
Brendan Eich <brendan@mozilla.org>
|
||||
Brian Anderson <banderson@mozilla.com>
|
||||
Brian J. Burg <burg@cs.washington.edu>
|
||||
|
|
@ -66,6 +67,7 @@ Kevin Atkinson <kevina@cs.utah.edu>
|
|||
Kevin Cantu <me@kevincantu.org>
|
||||
Lennart Kudling
|
||||
Lindsey Kuper <lindsey@rockstargirl.org>
|
||||
Luca Bruno <lucab@debian.org>
|
||||
Magnus Auvinen <magnus.auvinen@gmail.com>
|
||||
Margaret Meyerhofer <mmeyerho@andrew.cmu.edu>
|
||||
Marijn Haverbeke <marijnh@gmail.com>
|
||||
|
|
@ -76,6 +78,7 @@ Michael Bebenita <mbebenita@mozilla.com>
|
|||
Michael Sullivan <sully@msully.net>
|
||||
Niko Matsakis <niko@alum.mit.edu>
|
||||
Or Brostovski <tohava@gmail.com>
|
||||
Orphée Lafond-Lummis <o@orftz.com>
|
||||
Patrick Walton <pwalton@mozilla.com>
|
||||
Patrik Kårlin <patrik.karlin@gmail.com>
|
||||
Paul Stansifer <paul.stansifer@gmail.com>
|
||||
|
|
|
|||
13
Makefile.in
13
Makefile.in
|
|
@ -357,6 +357,15 @@ EXTRAFLAGS_STAGE$(1) = $$(RUSTFLAGS_STAGE$(1))
|
|||
|
||||
CFGFLAG$(1)_T_$(2)_H_$(3) = stage$(1)
|
||||
|
||||
# Pass --cfg stage0 only for the build->host part of stage0;
|
||||
# if you're building a cross config, the host->* parts are
|
||||
# effectively stage1, since it uses the just-built stage0.
|
||||
ifeq ($(1),0)
|
||||
ifneq ($(strip $(CFG_HOST_TRIPLE)),$(strip $(3)))
|
||||
CFGFLAG$(1)_T_$(2)_H_$(3) = stage1
|
||||
endif
|
||||
endif
|
||||
|
||||
STAGE$(1)_T_$(2)_H_$(3) := \
|
||||
$$(Q)$$(call CFG_RUN_TARG,$(1), \
|
||||
$$(CFG_VALGRIND_COMPILE$(1)) \
|
||||
|
|
@ -528,8 +537,8 @@ endif
|
|||
|
||||
ifneq ($(findstring install,$(MAKECMDGOALS)),)
|
||||
ifdef DESTDIR
|
||||
CFG_INFO := $(info cfg: setting CFG_PREFIX via DESTDIR, $(DESTDIR))
|
||||
CFG_PREFIX:=$(DESTDIR)
|
||||
CFG_INFO := $(info cfg: setting CFG_PREFIX via DESTDIR, $(DESTDIR)/$(CFG_PREFIX))
|
||||
CFG_PREFIX:=$(DESTDIR)/$(CFG_PREFIX)
|
||||
export CFG_PREFIX
|
||||
endif
|
||||
|
||||
|
|
|
|||
14
RELEASES.txt
14
RELEASES.txt
|
|
@ -1,5 +1,5 @@
|
|||
Version 0.4 (September 2012)
|
||||
----------------------------
|
||||
Version 0.4 (October 2012)
|
||||
--------------------------
|
||||
|
||||
* ~1500 changes, numerous bugfixes
|
||||
|
||||
|
|
@ -8,13 +8,14 @@ Version 0.4 (September 2012)
|
|||
* Keyword removal: 'again', 'import', 'check', 'new', 'owned', 'send',
|
||||
'of', 'with', 'to', 'class'.
|
||||
* Classes are replaced with simpler structs
|
||||
* Method self types
|
||||
* Explicit method self types
|
||||
* `ret` became `return` and `alt` became `match`
|
||||
* `import` is now `use`; `use is now `extern mod`
|
||||
* `extern mod { ... }` is now `extern { ... }`
|
||||
* `use mod` is the recommended way to import modules
|
||||
* `pub` and `priv` replace deprecated export lists
|
||||
* The syntax of `match` pattern arms now uses fat arrow (=>)
|
||||
* `main` no longer accepts an args vector; use `os::args` instead
|
||||
|
||||
* Semantics
|
||||
* Trait implementations are now coherent, ala Haskell typeclasses
|
||||
|
|
@ -25,15 +26,13 @@ Version 0.4 (September 2012)
|
|||
* Typestate was removed
|
||||
* Resolution rewritten to be more reliable
|
||||
* Support for 'dual-mode' data structures (freezing and thawing)
|
||||
* Last-use analysis is only used for warnings now. Moves must be explicit
|
||||
for lvalues (TODO: confirm)
|
||||
|
||||
* Libraries
|
||||
* Most binary operators can now be overloaded via the traits in
|
||||
`core::ops'
|
||||
* `std::net::url` for representing URLs
|
||||
* Sendable hash maps in `core::send_map`
|
||||
* `core::task' gained a (currently very unsafe) task-local storage API
|
||||
* `core::task' gained a (currently unsafe) task-local storage API
|
||||
|
||||
* Concurrency
|
||||
* An efficient new intertask communication primitive called the pipe,
|
||||
|
|
@ -52,8 +51,7 @@ Version 0.4 (September 2012)
|
|||
* Extensive architectural improvements to rustc
|
||||
* Begun a transition away from buggy C++-based reflection (shape) code to
|
||||
Rust-based (visitor) code
|
||||
* Hash functions improved across the codebase (TODO: need details)
|
||||
* New lint checks (TODO: which?)
|
||||
* All hash functions and tables converted to secure, randomized SipHash
|
||||
|
||||
Version 0.3 (July 2012)
|
||||
------------------------
|
||||
|
|
|
|||
29
doc/rust.css
29
doc/rust.css
|
|
@ -1,9 +1,11 @@
|
|||
body {
|
||||
padding: 1em;
|
||||
margin: 0;
|
||||
margin-bottom: 4em;
|
||||
font-family: "Helvetica Neue", Helvetica, sans-serif;
|
||||
background-color: white;
|
||||
color: black;
|
||||
line-height: 1.6em;
|
||||
}
|
||||
|
||||
body {
|
||||
|
|
@ -12,12 +14,16 @@ body {
|
|||
}
|
||||
|
||||
h1 {
|
||||
font-size: 22pt;
|
||||
font-size: 20pt;
|
||||
margin-top: 2em;
|
||||
border-bottom: 2px solid silver;
|
||||
border-bottom: 1px solid silver;
|
||||
line-height: 1.6em;
|
||||
}
|
||||
h2 { font-size: 17pt; }
|
||||
h3 { font-size: 14pt; }
|
||||
h2 {
|
||||
font-size: 15pt;
|
||||
margin-top: 2em;
|
||||
}
|
||||
h3 { font-size: 13pt; }
|
||||
|
||||
pre {
|
||||
margin: 1.1em 0;
|
||||
|
|
@ -27,7 +33,7 @@ pre {
|
|||
|
||||
a, a:visited, a:link {
|
||||
text-decoration: none;
|
||||
color: #00438a;
|
||||
color: rgb(0, 105, 214);
|
||||
}
|
||||
|
||||
h1 a:link, h1 a:visited, h2 a:link, h2 a:visited,
|
||||
|
|
@ -54,20 +60,12 @@ h3 a:link, h3 a:visited { color: black; }
|
|||
.cm-s-default span.cm-tag {color: #170;}
|
||||
.cm-s-default span.cm-attribute {color: #00c;}
|
||||
|
||||
h1.title {
|
||||
background-image: url('http://www.rust-lang.org/logos/rust-logo-32x32-blk.png');
|
||||
background-repeat: no-repeat;
|
||||
background-position: right;
|
||||
}
|
||||
|
||||
#versioninfo {
|
||||
position: fixed;
|
||||
bottom: 0px;
|
||||
right: 0px;
|
||||
|
||||
background-color: white;
|
||||
border-left: solid 1px black;
|
||||
border-top: solid 1px black;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
|
|
@ -99,3 +97,8 @@ td {
|
|||
#TOC ul ul {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#TOC ul {
|
||||
list-style: none;
|
||||
padding-left: 0px;
|
||||
}
|
||||
186
doc/rust.md
186
doc/rust.md
|
|
@ -15,17 +15,16 @@ provides three kinds of material:
|
|||
|
||||
This document does not serve as a tutorial introduction to the
|
||||
language. Background familiarity with the language is assumed. A separate
|
||||
tutorial document is available at <http://doc.rust-lang.org/doc/tutorial.html>
|
||||
to help acquire such background familiarity.
|
||||
[tutorial] document is available to help acquire such background familiarity.
|
||||
|
||||
This document also does not serve as a reference to the core or standard
|
||||
This document also does not serve as a reference to the [core] or [standard]
|
||||
libraries included in the language distribution. Those libraries are
|
||||
documented separately by extracting documentation attributes from their
|
||||
source code. Formatted documentation can be found at the following
|
||||
locations:
|
||||
source code.
|
||||
|
||||
- Core library: <http://doc.rust-lang.org/doc/core>
|
||||
- Standard library: <http://doc.rust-lang.org/doc/std>
|
||||
[tutorial]: tutorial.html
|
||||
[core]: core/index.html
|
||||
[standard]: std/index.html
|
||||
|
||||
## Disclaimer
|
||||
|
||||
|
|
@ -42,14 +41,17 @@ If you have suggestions to make, please try to focus them on *reductions* to
|
|||
the language: possible features that can be combined or omitted. We aim to
|
||||
keep the size and complexity of the language under control.
|
||||
|
||||
**Note on grammar:** The grammar for Rust given in this document is rough and
|
||||
very incomplete; only a modest number of sections have accompanying grammar
|
||||
rules. Formalizing the grammar accepted by the Rust parser is ongoing work,
|
||||
but future versions of this document will contain a complete
|
||||
grammar. Moreover, we hope that this grammar will be extracted and verified
|
||||
as LL(1) by an automated grammar-analysis tool, and further tested against the
|
||||
Rust sources. Preliminary versions of this automation exist, but are not yet
|
||||
complete.
|
||||
> **Note:** This manual is very out of date. The best source of Rust
|
||||
> documentation is currently the tutorial.
|
||||
|
||||
> **Note:** The grammar for Rust given in this document is rough and
|
||||
> very incomplete; only a modest number of sections have accompanying grammar
|
||||
> rules. Formalizing the grammar accepted by the Rust parser is ongoing work,
|
||||
> but future versions of this document will contain a complete
|
||||
> grammar. Moreover, we hope that this grammar will be extracted and verified
|
||||
> as LL(1) by an automated grammar-analysis tool, and further tested against the
|
||||
> Rust sources. Preliminary versions of this automation exist, but are not yet
|
||||
> complete.
|
||||
|
||||
# Notation
|
||||
|
||||
|
|
@ -118,19 +120,16 @@ production. See [tokens](#tokens) for more information.
|
|||
|
||||
## Input format
|
||||
|
||||
Rust input is interpreted as a sequence of Unicode codepoints encoded in
|
||||
UTF-8. No normalization is performed during input processing. Most Rust
|
||||
grammar rules are defined in terms of printable ASCII-range codepoints, but
|
||||
a small number are defined in terms of Unicode properties or explicit
|
||||
codepoint lists. ^[Surrogate definitions for the special Unicode productions
|
||||
are provided to the grammar verifier, restricted to ASCII range, when
|
||||
verifying the grammar in this document.]
|
||||
Rust input is interpreted as a sequence of Unicode codepoints encoded in UTF-8,
|
||||
normalized to Unicode normalization form NFKC.
|
||||
Most Rust grammar rules are defined in terms of printable ASCII-range codepoints,
|
||||
but a small number are defined in terms of Unicode properties or explicit codepoint lists.
|
||||
^[Substitute definitions for the special Unicode productions are provided to the grammar verifier, restricted to ASCII range, when verifying the grammar in this document.]
|
||||
|
||||
## Special Unicode Productions
|
||||
|
||||
The following productions in the Rust grammar are defined in terms of
|
||||
Unicode properties: `ident`, `non_null`, `non_star`, `non_eol`, `non_slash`,
|
||||
`non_single_quote` and `non_double_quote`.
|
||||
The following productions in the Rust grammar are defined in terms of Unicode properties:
|
||||
`ident`, `non_null`, `non_star`, `non_eol`, `non_slash`, `non_single_quote` and `non_double_quote`.
|
||||
|
||||
### Identifiers
|
||||
|
||||
|
|
@ -203,26 +202,26 @@ grammar as double-quoted strings. Other tokens have exact rules given.
|
|||
The keywords in [crate files](#crate-files) are the following strings:
|
||||
|
||||
~~~~~~~~ {.keyword}
|
||||
export use mod
|
||||
mod priv pub use
|
||||
~~~~~~~~
|
||||
|
||||
The keywords in [source files](#source-files) are the following strings:
|
||||
|
||||
~~~~~~~~ {.keyword}
|
||||
again assert
|
||||
as assert
|
||||
break
|
||||
check const copy
|
||||
drop
|
||||
else enum export extern
|
||||
const copy
|
||||
do drop
|
||||
else enum extern
|
||||
fail false fn for
|
||||
if impl
|
||||
let log loop
|
||||
match mod mut
|
||||
pure
|
||||
return
|
||||
struct
|
||||
match mod move mut
|
||||
priv pub pure
|
||||
ref return
|
||||
self static struct
|
||||
true trait type
|
||||
unsafe
|
||||
unsafe use
|
||||
while
|
||||
~~~~~~~~
|
||||
|
||||
|
|
@ -619,7 +618,7 @@ or a *configuration* in Mesa.] A crate file describes:
|
|||
and copyright. These are used for linking, versioning and distributing
|
||||
crates.
|
||||
* The source-file and directory modules that make up the crate.
|
||||
* Any `use`, `extern mod` or `export` [view items](#view-items) that apply to
|
||||
* Any `use` or `extern mod` [view items](#view-items) that apply to
|
||||
the anonymous module at the top-level of the crate's module tree.
|
||||
|
||||
An example of a crate file:
|
||||
|
|
@ -767,7 +766,7 @@ mod math {
|
|||
#### View items
|
||||
|
||||
~~~~~~~~ {.ebnf .gram}
|
||||
view_item : extern_mod_decl | use_decl | export_decl ;
|
||||
view_item : extern_mod_decl | use_decl ;
|
||||
~~~~~~~~
|
||||
|
||||
A view item manages the namespace of a module; it does not define new items
|
||||
|
|
@ -776,7 +775,6 @@ view item:
|
|||
|
||||
* [extern mod declarations](#extern-mod-declarations)
|
||||
* [use declarations](#use-declarations)
|
||||
* [export declarations](#export-declarations)
|
||||
|
||||
##### Extern mod declarations
|
||||
|
||||
|
|
@ -786,9 +784,8 @@ link_attrs : link_attr [ ',' link_attrs ] + ;
|
|||
link_attr : ident '=' literal ;
|
||||
~~~~~~~~
|
||||
|
||||
An _extern mod declaration_ specifies a dependency on an external crate. The
|
||||
external crate is then imported into the declaring scope as the `ident`
|
||||
provided in the `extern_mod_decl`.
|
||||
An _extern mod declaration_ specifies a dependency on an external crate.
|
||||
The external crate is then bound into the declaring scope as the `ident` provided in the `extern_mod_decl`.
|
||||
|
||||
The external crate is resolved to a specific `soname` at compile time, and a
|
||||
runtime linkage requirement to that `soname` is passed to the linker for
|
||||
|
|
@ -828,16 +825,16 @@ linkage-dependency with external crates. Linkage dependencies are
|
|||
independently declared with
|
||||
[`extern mod` declarations](#extern-mod-declarations).
|
||||
|
||||
Imports support a number of "convenience" notations:
|
||||
Use declarations support a number of "convenience" notations:
|
||||
|
||||
* Importing as a different name than the imported name, using the
|
||||
* Rebinding the target name as a new local name, using the
|
||||
syntax `use x = p::q::r;`.
|
||||
* Importing a list of paths differing only in final element, using
|
||||
the glob-like brace syntax `use a::b::{c,d,e,f};`
|
||||
* Importing all paths matching a given prefix, using the glob-like
|
||||
asterisk syntax `use a::b::*;`
|
||||
* Simultaneously binding a list of paths differing only in final element,
|
||||
using the glob-like brace syntax `use a::b::{c,d,e,f};`
|
||||
* Binding all paths matching a given prefix,
|
||||
using the glob-like asterisk syntax `use a::b::*;`
|
||||
|
||||
An example of imports:
|
||||
An example of `use` declarations:
|
||||
|
||||
~~~~
|
||||
use foo = core::info;
|
||||
|
|
@ -858,82 +855,11 @@ fn main() {
|
|||
}
|
||||
~~~~
|
||||
|
||||
##### Export declarations
|
||||
|
||||
~~~~~~~~ {.ebnf .gram}
|
||||
export_decl : "export" ident [ ',' ident ] *
|
||||
| "export" ident "::{}"
|
||||
| "export" ident '{' ident [ ',' ident ] * '}' ;
|
||||
~~~~~~~~
|
||||
|
||||
An _export declaration_ restricts the set of local names within a module that
|
||||
can be accessed from code outside the module. By default, all _local items_ in
|
||||
a module are exported; imported paths are not automatically re-exported by
|
||||
default. If a module contains an explicit `export` declaration, this
|
||||
declaration replaces the default export with the export specified.
|
||||
|
||||
An example of an export:
|
||||
|
||||
~~~~~~~~
|
||||
pub mod foo {
|
||||
#[legacy_exports];
|
||||
export primary;
|
||||
|
||||
fn primary() {
|
||||
helper(1, 2);
|
||||
helper(3, 4);
|
||||
}
|
||||
|
||||
fn helper(x: int, y: int) {
|
||||
...
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
foo::primary(); // Will compile.
|
||||
}
|
||||
~~~~~~~~
|
||||
|
||||
If, instead of calling `foo::primary` in main, you were to call `foo::helper`
|
||||
then it would fail to compile:
|
||||
|
||||
~~~~~~~~{.ignore}
|
||||
foo::helper(2,3) // ERROR: will not compile.
|
||||
~~~~~~~~
|
||||
|
||||
Multiple names may be exported from a single export declaration:
|
||||
|
||||
~~~~~~~~
|
||||
mod foo {
|
||||
export primary, secondary;
|
||||
|
||||
fn primary() {
|
||||
helper(1, 2);
|
||||
helper(3, 4);
|
||||
}
|
||||
|
||||
fn secondary() {
|
||||
...
|
||||
}
|
||||
|
||||
fn helper(x: int, y: int) {
|
||||
...
|
||||
}
|
||||
}
|
||||
~~~~~~~~
|
||||
|
||||
When exporting the name of an `enum` type `t`, by default, the module does
|
||||
*not* implicitly export any of `t`'s constructors. For example:
|
||||
|
||||
~~~~~~~~
|
||||
mod foo {
|
||||
export t;
|
||||
|
||||
enum t {a, b, c}
|
||||
}
|
||||
~~~~~~~~
|
||||
|
||||
Here, `foo` imports `t`, but not `a`, `b`, and `c`.
|
||||
Like items, `use` declarations are private to the containing module, by default.
|
||||
Also like items, a `use` declaration can be public, if qualified by the `pub` keyword.
|
||||
A public `use` declaration can therefore be used to _redirect_ some public name to a different target definition,
|
||||
even a definition with a private canonical path, inside a different module.
|
||||
If a sequence of such redirections form a cycle or cannot be unambiguously resolved, they represent a compile-time error.
|
||||
|
||||
### Functions
|
||||
|
||||
|
|
@ -1076,7 +1002,7 @@ pure fn pure_length<T>(ls: List<T>) -> uint {
|
|||
Despite its name, `pure_foldl` is a `fn`, not a `pure fn`, because there is no
|
||||
way in Rust to specify that the higher-order function argument `f` is a pure
|
||||
function. So, to use `foldl` in a pure list length function that a pure function
|
||||
could then use, we must use an `unchecked` block wrapped around the call to
|
||||
could then use, we must use an `unsafe` block wrapped around the call to
|
||||
`pure_foldl` in the definition of `pure_length`.
|
||||
|
||||
#### Generic functions
|
||||
|
|
@ -1092,7 +1018,7 @@ fn iter<T>(seq: ~[T], f: fn(T)) {
|
|||
}
|
||||
fn map<T, U>(seq: ~[T], f: fn(T) -> U) -> ~[U] {
|
||||
let mut acc = ~[];
|
||||
for seq.each |elt| { vec::push(acc, f(elt)); }
|
||||
for seq.each |elt| { acc.push(f(elt)); }
|
||||
acc
|
||||
}
|
||||
~~~~
|
||||
|
|
@ -1300,14 +1226,6 @@ impl circle: shape {
|
|||
}
|
||||
~~~~
|
||||
|
||||
This defines an implementation named `circle_shape` of trait
|
||||
`shape` for type `circle`. The name of the implementation is the name
|
||||
by which it is imported and exported, but has no further significance.
|
||||
It may be omitted to default to the name of the trait that was
|
||||
implemented. Implementation names do not conflict the way other names
|
||||
do: multiple implementations with the same name may exist in a scope at
|
||||
the same time.
|
||||
|
||||
It is possible to define an implementation without referring to a
|
||||
trait. The methods in such an implementation can only be used
|
||||
statically (as direct calls on the values of the type that the
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
Borrowed pointers are one of the more flexible and powerful tools
|
||||
available in Rust. A borrowed pointer can be used to point anywhere:
|
||||
into the shared and exchange heaps, into the stack, and even into the
|
||||
into the managed and exchange heaps, into the stack, and even into the
|
||||
interior of another data structure. With regard to flexibility, it is
|
||||
comparable to a C pointer or C++ reference. However, unlike C and C++,
|
||||
the Rust compiler includes special checks that ensure that borrowed
|
||||
|
|
@ -29,10 +29,10 @@ a limit duration. Borrowed pointers never claim any kind of ownership
|
|||
over the data that they point at: instead, they are used for cases
|
||||
where you like to make use of data for a short time.
|
||||
|
||||
As an example, consider a simple record type `point`:
|
||||
As an example, consider a simple struct type `Point`:
|
||||
|
||||
~~~
|
||||
type point = {x: float, y: float};
|
||||
struct Point {x: float, y: float}
|
||||
~~~
|
||||
|
||||
We can use this simple definition to allocate points in many ways. For
|
||||
|
|
@ -40,10 +40,10 @@ example, in this code, each of these three local variables contains a
|
|||
point, but allocated in a different place:
|
||||
|
||||
~~~
|
||||
# type point = {x: float, y: float};
|
||||
let on_the_stack : point = {x: 3.0, y: 4.0};
|
||||
let shared_box : @point = @{x: 5.0, y: 1.0};
|
||||
let unique_box : ~point = ~{x: 7.0, y: 9.0};
|
||||
# struct Point {x: float, y: float}
|
||||
let on_the_stack : Point = Point {x: 3.0, y: 4.0};
|
||||
let shared_box : @Point = @Point {x: 5.0, y: 1.0};
|
||||
let unique_box : ~Point = ~Point {x: 7.0, y: 9.0};
|
||||
~~~
|
||||
|
||||
Suppose we wanted to write a procedure that computed the distance
|
||||
|
|
@ -59,9 +59,9 @@ define a function that takes the points by pointer. We can use
|
|||
borrowed pointers to do this:
|
||||
|
||||
~~~
|
||||
# type point = {x: float, y: float};
|
||||
# struct Point {x: float, y: float}
|
||||
# fn sqrt(f: float) -> float { 0f }
|
||||
fn compute_distance(p1: &point, p2: &point) -> float {
|
||||
fn compute_distance(p1: &Point, p2: &Point) -> float {
|
||||
let x_d = p1.x - p2.x;
|
||||
let y_d = p1.y - p2.y;
|
||||
sqrt(x_d * x_d + y_d * y_d)
|
||||
|
|
@ -71,26 +71,26 @@ fn compute_distance(p1: &point, p2: &point) -> float {
|
|||
Now we can call `compute_distance()` in various ways:
|
||||
|
||||
~~~
|
||||
# type point = {x: float, y: float};
|
||||
# let on_the_stack : point = {x: 3.0, y: 4.0};
|
||||
# let shared_box : @point = @{x: 5.0, y: 1.0};
|
||||
# let unique_box : ~point = ~{x: 7.0, y: 9.0};
|
||||
# fn compute_distance(p1: &point, p2: &point) -> float { 0f }
|
||||
# struct Point {x: float, y: float}
|
||||
# let on_the_stack : Point = Point{x: 3.0, y: 4.0};
|
||||
# let shared_box : @Point = @Point{x: 5.0, y: 1.0};
|
||||
# let unique_box : ~Point = ~Point{x: 7.0, y: 9.0};
|
||||
# fn compute_distance(p1: &Point, p2: &Point) -> float { 0f }
|
||||
compute_distance(&on_the_stack, shared_box);
|
||||
compute_distance(shared_box, unique_box);
|
||||
~~~
|
||||
|
||||
Here the `&` operator is used to take the address of the variable
|
||||
`on_the_stack`; this is because `on_the_stack` has the type `point`
|
||||
(that is, a record value) and we have to take its address to get a
|
||||
`on_the_stack`; this is because `on_the_stack` has the type `Point`
|
||||
(that is, a struct value) and we have to take its address to get a
|
||||
value. We also call this _borrowing_ the local variable
|
||||
`on_the_stack`, because we are created an alias: that is, another
|
||||
route to the same data.
|
||||
|
||||
In the case of the boxes `shared_box` and `unique_box`, however, no
|
||||
explicit action is necessary. The compiler will automatically convert
|
||||
a box like `@point` or `~point` to a borrowed pointer like
|
||||
`&point`. This is another form of borrowing; in this case, the
|
||||
a box like `@Point` or `~Point` to a borrowed pointer like
|
||||
`&Point`. This is another form of borrowing; in this case, the
|
||||
contents of the shared/unique box is being lent out.
|
||||
|
||||
Whenever a value is borrowed, there are some limitations on what you
|
||||
|
|
@ -108,8 +108,8 @@ it again.
|
|||
In the previous example, the value `on_the_stack` was defined like so:
|
||||
|
||||
~~~
|
||||
# type point = {x: float, y: float};
|
||||
let on_the_stack : point = {x: 3.0, y: 4.0};
|
||||
# struct Point {x: float, y: float}
|
||||
let on_the_stack: Point = Point {x: 3.0, y: 4.0};
|
||||
~~~
|
||||
|
||||
This results in a by-value variable. As a consequence, we had to
|
||||
|
|
@ -118,20 +118,20 @@ pointer. Sometimes however it is more convenient to move the &
|
|||
operator into the definition of `on_the_stack`:
|
||||
|
||||
~~~
|
||||
# type point = {x: float, y: float};
|
||||
let on_the_stack2 : &point = &{x: 3.0, y: 4.0};
|
||||
# struct Point {x: float, y: float}
|
||||
let on_the_stack2: &Point = &Point {x: 3.0, y: 4.0};
|
||||
~~~
|
||||
|
||||
Applying `&` to an rvalue (non-assignable location) is just a convenient
|
||||
shorthand for creating a temporary and taking its address:
|
||||
|
||||
~~~
|
||||
# type point = {x: float, y: float};
|
||||
let tmp = {x: 3.0, y: 4.0};
|
||||
let on_the_stack2 : &point = &tmp;
|
||||
# struct Point {x: float, y: float}
|
||||
let tmp = Point {x: 3.0, y: 4.0};
|
||||
let on_the_stack2 : &Point = &tmp;
|
||||
~~~
|
||||
|
||||
Taking the address of fields
|
||||
# Taking the address of fields
|
||||
|
||||
As in C, the `&` operator is not limited to taking the address of
|
||||
local variables. It can also be used to take the address of fields or
|
||||
|
|
@ -139,39 +139,45 @@ individual array elements. For example, consider this type definition
|
|||
for `rectangle`:
|
||||
|
||||
~~~
|
||||
type point = {x: float, y: float}; // as before
|
||||
type size = {w: float, h: float}; // as before
|
||||
type rectangle = {origin: point, size: size};
|
||||
struct Point {x: float, y: float} // as before
|
||||
struct Size {w: float, h: float} // as before
|
||||
struct Rectangle {origin: Point, size: Size}
|
||||
~~~
|
||||
|
||||
Now again I can define rectangles in a few different ways:
|
||||
|
||||
~~~
|
||||
let rect_stack = &{origin: {x: 1f, y: 2f}, size: {w: 3f, h: 4f}};
|
||||
let rect_shared = @{origin: {x: 3f, y: 4f}, size: {w: 3f, h: 4f}};
|
||||
let rect_unique = ~{origin: {x: 5f, y: 6f}, size: {w: 3f, h: 4f}};
|
||||
# struct Point {x: float, y: float}
|
||||
# struct Size {w: float, h: float} // as before
|
||||
# struct Rectangle {origin: Point, size: Size}
|
||||
let rect_stack = &Rectangle {origin: Point {x: 1f, y: 2f},
|
||||
size: Size {w: 3f, h: 4f}};
|
||||
let rect_managed = @Rectangle {origin: Point {x: 3f, y: 4f},
|
||||
size: Size {w: 3f, h: 4f}};
|
||||
let rect_unique = ~Rectangle {origin: Point {x: 5f, y: 6f},
|
||||
size: Size {w: 3f, h: 4f}};
|
||||
~~~
|
||||
|
||||
In each case I can use the `&` operator to extact out individual
|
||||
subcomponents. For example, I could write:
|
||||
|
||||
~~~
|
||||
# type point = {x: float, y: float};
|
||||
# type size = {w: float, h: float}; // as before
|
||||
# type rectangle = {origin: point, size: size};
|
||||
# let rect_stack = &{origin: {x: 1f, y: 2f}, size: {w: 3f, h: 4f}};
|
||||
# let rect_shared = @{origin: {x: 3f, y: 4f}, size: {w: 3f, h: 4f}};
|
||||
# let rect_unique = ~{origin: {x: 5f, y: 6f}, size: {w: 3f, h: 4f}};
|
||||
# fn compute_distance(p1: &point, p2: &point) -> float { 0f }
|
||||
compute_distance(&rect_stack.origin, &rect_shared.origin);
|
||||
# struct Point {x: float, y: float} // as before
|
||||
# struct Size {w: float, h: float} // as before
|
||||
# struct Rectangle {origin: Point, size: Size}
|
||||
# let rect_stack = &{origin: Point {x: 1f, y: 2f}, size: Size {w: 3f, h: 4f}};
|
||||
# let rect_managed = @{origin: Point {x: 3f, y: 4f}, size: Size {w: 3f, h: 4f}};
|
||||
# let rect_unique = ~{origin: Point {x: 5f, y: 6f}, size: Size {w: 3f, h: 4f}};
|
||||
# fn compute_distance(p1: &Point, p2: &Point) -> float { 0f }
|
||||
compute_distance(&rect_stack.origin, &rect_managed.origin);
|
||||
~~~
|
||||
|
||||
which would borrow the field `origin` from the rectangle on the stack
|
||||
from the shared box and then compute the distance between them.
|
||||
from the managed box and then compute the distance between them.
|
||||
|
||||
# Borrowing shared boxes and rooting
|
||||
# Borrowing managed boxes and rooting
|
||||
|
||||
We’ve seen a few examples so far where heap boxes (both shared and
|
||||
We’ve seen a few examples so far where heap boxes (both managed and
|
||||
unique) are borrowed. Up till this point, we’ve glossed over issues of
|
||||
safety. As stated in the introduction, at runtime a borrowed pointer
|
||||
is simply a pointer, nothing more. Therefore, if we wish to avoid the
|
||||
|
|
@ -192,8 +198,9 @@ relatively easy, such as when taking the address of a local variable
|
|||
or a field that is stored on the stack:
|
||||
|
||||
~~~
|
||||
struct X { f: int }
|
||||
fn example1() {
|
||||
let mut x = {f: 3};
|
||||
let mut x = X { f: 3 };
|
||||
let y = &mut x.f; // -+ L
|
||||
... // |
|
||||
} // -+
|
||||
|
|
@ -207,8 +214,9 @@ The situation gets more complex when borrowing data that resides in
|
|||
heap boxes:
|
||||
|
||||
~~~
|
||||
# struct X { f: int }
|
||||
fn example2() {
|
||||
let mut x = @{f: 3};
|
||||
let mut x = @X { f: 3 };
|
||||
let y = &x.f; // -+ L
|
||||
... // |
|
||||
} // -+
|
||||
|
|
@ -218,20 +226,21 @@ In this example, the value `x` is in fact a heap box, and `y` is
|
|||
therefore a pointer into that heap box. Again the lifetime of `y` will
|
||||
be L, the remainder of the function body. But there is a crucial
|
||||
difference: suppose `x` were reassigned during the lifetime L? If
|
||||
we’re not careful, that could mean that the shared box would become
|
||||
we’re not careful, that could mean that the managed box would become
|
||||
unrooted and therefore be subject to garbage collection
|
||||
|
||||
> ***Note:***In our current implementation, the garbage collector is
|
||||
> implemented using reference counting and cycle detection.
|
||||
|
||||
For this reason, whenever the interior of a shared box stored in a
|
||||
For this reason, whenever the interior of a managed box stored in a
|
||||
mutable location is borrowed, the compiler will insert a temporary
|
||||
that ensures that the shared box remains live for the entire
|
||||
that ensures that the managed box remains live for the entire
|
||||
lifetime. So, the above example would be compiled as:
|
||||
|
||||
~~~
|
||||
# struct X { f: int }
|
||||
fn example2() {
|
||||
let mut x = @{f: 3};
|
||||
let mut x = @X {f: 3};
|
||||
let x1 = x;
|
||||
let y = &x1.f; // -+ L
|
||||
... // |
|
||||
|
|
@ -239,19 +248,19 @@ fn example2() {
|
|||
~~~
|
||||
|
||||
Now if `x` is reassigned, the pointer `y` will still remain valid. This
|
||||
process is called “rooting”.
|
||||
process is called *rooting*.
|
||||
|
||||
# Borrowing unique boxes
|
||||
|
||||
The previous example demonstrated `rooting`, the process by which the
|
||||
compiler ensures that shared boxes remain live for the duration of a
|
||||
The previous example demonstrated *rooting*, the process by which the
|
||||
compiler ensures that managed boxes remain live for the duration of a
|
||||
borrow. Unfortunately, rooting does not work if the data being
|
||||
borrowed is a unique box, as it is not possible to have two references
|
||||
to a unique box.
|
||||
|
||||
For unique boxes, therefore, the compiler will only allow a borrow `if
|
||||
For unique boxes, therefore, the compiler will only allow a borrow *if
|
||||
the compiler can guarantee that the unique box will not be reassigned
|
||||
or moved for the lifetime of the pointer`. This does not necessarily
|
||||
or moved for the lifetime of the pointer*. This does not necessarily
|
||||
mean that the unique box is stored in immutable memory. For example,
|
||||
the following function is legal:
|
||||
|
||||
|
|
@ -283,7 +292,7 @@ rejected by the compiler):
|
|||
|
||||
~~~ {.xfail-test}
|
||||
fn example3() -> int {
|
||||
let mut x = ~{f: 3};
|
||||
let mut x = ~X {f: 3};
|
||||
let y = &x.f;
|
||||
x = ~{f: 4}; // Error reported here.
|
||||
*y
|
||||
|
|
@ -325,15 +334,18 @@ which has been freed.
|
|||
In fact, the compiler can apply this same kind of reasoning can be
|
||||
applied to any memory which is _(uniquely) owned by the stack
|
||||
frame_. So we could modify the previous example to introduce
|
||||
additional unique pointers and records, and the compiler will still be
|
||||
additional unique pointers and structs, and the compiler will still be
|
||||
able to detect possible mutations:
|
||||
|
||||
~~~ {.xfail-test}
|
||||
fn example3() -> int {
|
||||
let mut x = ~{mut f: ~{g: 3}};
|
||||
struct R { g: int }
|
||||
struct S { mut f: ~R }
|
||||
|
||||
let mut x = ~S {mut f: ~R {g: 3}};
|
||||
let y = &x.f.g;
|
||||
x = ~{mut f: ~{g: 4}}; // Error reported here.
|
||||
x.f = ~{g: 5}; // Error reported here.
|
||||
x = ~S {mut f: ~R {g: 4}}; // Error reported here.
|
||||
x.f = ~R {g: 5}; // Error reported here.
|
||||
*y
|
||||
}
|
||||
~~~
|
||||
|
|
@ -346,17 +358,20 @@ Things get tricker when the unique box is not uniquely owned by the
|
|||
stack frame (or when the compiler doesn’t know who the owner
|
||||
is). Consider a program like this:
|
||||
|
||||
~~~ {.xfail-test}
|
||||
fn example5a(x: @{mut f: ~{g: int}} ...) -> int {
|
||||
~~~
|
||||
struct R { g: int }
|
||||
struct S { mut f: ~R }
|
||||
fn example5a(x: @S ...) -> int {
|
||||
let y = &x.f.g; // Error reported here.
|
||||
...
|
||||
# return 0;
|
||||
}
|
||||
~~~
|
||||
|
||||
Here the heap looks something like:
|
||||
|
||||
~~~ {.notrust}
|
||||
Stack Shared Heap Exchange Heap
|
||||
Stack Managed Heap Exchange Heap
|
||||
|
||||
x +------+ +-------------+ +------+
|
||||
| @... | ----> | mut f: ~... | --+-> | g: 3 |
|
||||
|
|
@ -368,7 +383,7 @@ Here the heap looks something like:
|
|||
In this case, the owning reference to the value being borrowed is in
|
||||
fact `x.f`. Moreover, `x.f` is both mutable and aliasable. Aliasable
|
||||
means that it is possible that there are other pointers to that same
|
||||
shared box, so even if the compiler were to prevent `x.f` from being
|
||||
managed box, so even if the compiler were to prevent `x.f` from being
|
||||
mutated, the field might still be changed through some alias of
|
||||
`x`. Therefore, to be safe, the compiler only accepts pure actions
|
||||
during the lifetime of `y`. We’ll have a final example on purity but
|
||||
|
|
@ -379,7 +394,9 @@ unique found in aliasable memory is to ensure that it is stored within
|
|||
unique fields, as in the following example:
|
||||
|
||||
~~~
|
||||
fn example5b(x: @{f: ~{g: int}}) -> int {
|
||||
struct R { g: int }
|
||||
struct S { f: ~R }
|
||||
fn example5b(x: @S) -> int {
|
||||
let y = &x.f.g;
|
||||
...
|
||||
# return 0;
|
||||
|
|
@ -394,21 +411,32 @@ If you do have a unique box in a mutable field, and you wish to borrow
|
|||
it, one option is to use the swap operator to bring that unique box
|
||||
onto your stack:
|
||||
|
||||
~~~ {.xfail-test}
|
||||
fn example5c(x: @{mut f: ~int}) -> int {
|
||||
let mut v = ~0;
|
||||
~~~
|
||||
struct R { g: int }
|
||||
struct S { mut f: ~R }
|
||||
fn example5c(x: @S) -> int {
|
||||
let mut v = ~R {g: 0};
|
||||
v <-> x.f; // Swap v and x.f
|
||||
let y = &v;
|
||||
...
|
||||
{ // Block constrains the scope of `y`:
|
||||
let y = &v.g;
|
||||
...
|
||||
}
|
||||
x.f <- v; // Replace x.f
|
||||
...
|
||||
# return 0;
|
||||
}
|
||||
~~~
|
||||
|
||||
Of course, this has the side effect of modifying your shared box for
|
||||
the duration of the borrow, so it works best when you know that you
|
||||
won’t be accessing that same box again.
|
||||
Of course, this has the side effect of modifying your managed box for
|
||||
the duration of the borrow, so it only works when you know that you
|
||||
won’t be accessing that same box for the duration of the loan. Note
|
||||
also that sometimes it is necessary to introduce additional blocks to
|
||||
constrain the scope of the loan. In this example, the borrowed
|
||||
pointer `y` would still be in scope when you moved the value `v` back
|
||||
into `x.f`, and hence moving `v` would be considered illegal. You
|
||||
cannot move values if they are outstanding loans which are still
|
||||
valid. By introducing the block, the scope of `y` is restricted and so
|
||||
the move is legal.
|
||||
|
||||
# Borrowing and enums
|
||||
|
||||
|
|
@ -422,11 +450,11 @@ As an example, let’s look at the following `shape` type that can
|
|||
represent both rectangles and circles:
|
||||
|
||||
~~~
|
||||
type point = {x: float, y: float}; // as before
|
||||
type size = {w: float, h: float}; // as before
|
||||
enum shape {
|
||||
circle(point, float), // origin, radius
|
||||
rectangle(point, size) // upper-left, dimensions
|
||||
struct Point {x: float, y: float}; // as before
|
||||
struct Size {w: float, h: float}; // as before
|
||||
enum Shape {
|
||||
Circle(Point, float), // origin, radius
|
||||
Rectangle(Point, Size) // upper-left, dimensions
|
||||
}
|
||||
~~~
|
||||
|
||||
|
|
@ -435,17 +463,17 @@ function takes a borrowed pointer to a shape to avoid the need of
|
|||
copying them.
|
||||
|
||||
~~~
|
||||
# type point = {x: float, y: float}; // as before
|
||||
# type size = {w: float, h: float}; // as before
|
||||
# enum shape {
|
||||
# circle(point, float), // origin, radius
|
||||
# rectangle(point, size) // upper-left, dimensions
|
||||
# struct Point {x: float, y: float}; // as before
|
||||
# struct Size {w: float, h: float}; // as before
|
||||
# enum Shape {
|
||||
# Circle(Point, float), // origin, radius
|
||||
# Rectangle(Point, Size) // upper-left, dimensions
|
||||
# }
|
||||
# const tau: float = 6.28f;
|
||||
fn compute_area(shape: &shape) -> float {
|
||||
fn compute_area(shape: &Shape) -> float {
|
||||
match *shape {
|
||||
circle(_, radius) => 0.5 * tau * radius * radius,
|
||||
rectangle(_, ref size) => size.w * size.h
|
||||
Circle(_, radius) => 0.5 * tau * radius * radius,
|
||||
Rectangle(_, ref size) => size.w * size.h
|
||||
}
|
||||
}
|
||||
~~~
|
||||
|
|
@ -504,75 +532,82 @@ Stack Memory
|
|||
~~~
|
||||
|
||||
As you can see, the `size` pointer would not be pointing at a `float` and
|
||||
not a record. This is not good.
|
||||
not a struct. This is not good.
|
||||
|
||||
So, in fact, for every `ref` binding, the compiler will impose the
|
||||
same rules as the ones we saw for borrowing the interior of a unique
|
||||
box: it must be able to guarantee that the enum will not be
|
||||
overwritten for the duration of the borrow. In fact, the example I
|
||||
gave earlier would be considered safe. This is because the shape
|
||||
pointer has type `&shape`, which means “borrowed pointer to immutable
|
||||
pointer has type `&Shape`, which means “borrowed pointer to immutable
|
||||
memory containing a shape”. If however the type of that pointer were
|
||||
`&const shape` or `&mut shape`, then the ref binding would not be
|
||||
`&const Shape` or `&mut Shape`, then the ref binding would not be
|
||||
permitted. Just as with unique boxes, the compiler will permit ref
|
||||
bindings into data owned by the stack frame even if it is mutable, but
|
||||
otherwise it requires that the data reside in immutable memory.
|
||||
|
||||
> ***Note:*** Right now, all pattern bindings are by-reference. We
|
||||
> expect this to change so that copies are the default and references
|
||||
> must be noted explicitly.
|
||||
> ***Note:*** Right now, pattern bindings not explicitly annotated
|
||||
> with `ref` or `copy` use a special mode of "implicit by reference".
|
||||
> This is changing as soon as we finish updating all the existing code
|
||||
> in the compiler that relies on the current settings.
|
||||
|
||||
# Returning borrowed pointers
|
||||
|
||||
So far, all of the examples we’ve looked at use borrowed pointers in a
|
||||
“downward” direction. That is, the borrowed pointer is created and
|
||||
then used during the method or code block which created it. In some
|
||||
cases, it is also possible to return borrowed pointers to the caller,
|
||||
but as we’ll see this is more limited.
|
||||
then used during the method or code block which created it. It is also
|
||||
possible to return borrowed pointers to the caller, but as we'll see
|
||||
this requires some explicit annotation.
|
||||
|
||||
For example, we could write a subroutine like this:
|
||||
|
||||
~~~ {.xfail-test}
|
||||
type point = {x: float, y: float};
|
||||
fn get_x(p: &point) -> &float { &p.x }
|
||||
~~~
|
||||
struct Point {x: float, y: float}
|
||||
fn get_x(p: &r/Point) -> &r/float { &p.x }
|
||||
~~~
|
||||
|
||||
Here, the function `get_x()` returns a pointer into the structure it was
|
||||
given. You’ll note that _both_ the parameter and the return value are
|
||||
borrowed pointers; this is important. In general, it is only possible
|
||||
to return borrowed pointers if they are derived from a borrowed
|
||||
pointer which was given as input to the procedure.
|
||||
given. The type of the parameter (`&r/Point`) and return type (`&r/float`) both
|
||||
make use of a new syntactic form that we have not seen so far. Here the identifier `r`
|
||||
serves as an explicit name for the lifetime of the pointer. So in effect
|
||||
this function is declaring that it takes in a pointer with lifetime `r` and returns
|
||||
a pointer with that same lifetime.
|
||||
|
||||
In the example, `get_x()` took a borrowed pointer to a `point` as
|
||||
input. In general, for all borrowed pointers that appear in the
|
||||
signature of a function (such as the parameter and return types), the
|
||||
compiler assigns the same symbolic lifetime L (we will see later that
|
||||
there are ways to differentiate the lifetimes of different parameters
|
||||
if that should be necessary). This means that, from the compiler’s
|
||||
point of view, `get_x()` takes and returns two pointers with the same
|
||||
lifetime. Now, unlike other lifetimes, this lifetime is a bit
|
||||
abstract: it doesn’t refer to a specific expression within `get_x()`,
|
||||
but rather to some expression within the caller. This is called a
|
||||
_lifetime parameter_, because the lifetime L is effectively defined by
|
||||
the caller to `get_x()`, just as the value for the parameter `p` is
|
||||
defined by the caller.
|
||||
In general, it is only possible to return borrowed pointers if they
|
||||
are derived from a borrowed pointer which was given as input to the
|
||||
procedure. In that case, they will always have the same lifetime as
|
||||
one of the parameters; named lifetimes are used to indicate which
|
||||
parameter that is.
|
||||
|
||||
In any case, whatever the lifetime L is, the pointer produced by
|
||||
In the examples before, function parameter types did not include a
|
||||
lifetime name. In this case, the compiler simply creates a new,
|
||||
anonymous name, meaning that the parameter is assumed to have a
|
||||
distinct lifetime from all other parameters.
|
||||
|
||||
Named lifetimes that appear in function signatures are conceptually
|
||||
the same as the other lifetimes we've seen before, but they are a bit
|
||||
abstract: they don’t refer to a specific expression within `get_x()`,
|
||||
but rather to some expression within the *caller of `get_x()`*. The
|
||||
lifetime `r` is actually a kind of *lifetime parameter*: it is defined
|
||||
by the caller to `get_x()`, just as the value for the parameter `p` is
|
||||
defined by that caller.
|
||||
|
||||
In any case, whatever the lifetime `r` is, the pointer produced by
|
||||
`&p.x` always has the same lifetime as `p` itself, as a pointer to a
|
||||
field of a record is valid as long as the record is valid. Therefore,
|
||||
field of a struct is valid as long as the struct is valid. Therefore,
|
||||
the compiler is satisfied with the function `get_x()`.
|
||||
|
||||
To drill in this point, let’s look at a variation on the example, this
|
||||
time one which does not compile:
|
||||
|
||||
~~~ {.xfail-test}
|
||||
type point = {x: float, y: float};
|
||||
fn get_x_sh(p: @point) -> &float {
|
||||
struct Point {x: float, y: float}
|
||||
fn get_x_sh(p: @Point) -> &float {
|
||||
&p.x // Error reported here
|
||||
}
|
||||
~~~
|
||||
|
||||
Here, the function `get_x_sh()` takes a shared box as input and
|
||||
Here, the function `get_x_sh()` takes a managed box as input and
|
||||
returns a borrowed pointer. As before, the lifetime of the borrowed
|
||||
pointer that will be returned is a parameter (specified by the
|
||||
caller). That means that effectively `get_x_sh()` is promising to
|
||||
|
|
@ -582,121 +617,114 @@ promised to return a pointer that was valid for as long as the pointer
|
|||
it was given.
|
||||
|
||||
Within `get_x_sh()`, we see the expression `&p.x` which takes the
|
||||
address of a field of a shared box. This implies that the compiler
|
||||
address of a field of a managed box. This implies that the compiler
|
||||
must guarantee that, so long as the resulting pointer is valid, the
|
||||
shared box will not be reclaimed by the garbage collector. But recall
|
||||
that get_x_sh() also promised to return a pointer that was valid for
|
||||
managed box will not be reclaimed by the garbage collector. But recall
|
||||
that `get_x_sh()` also promised to return a pointer that was valid for
|
||||
as long as the caller wanted it to be. Clearly, `get_x_sh()` is not in
|
||||
a position to make both of these guarantees; in fact, it cannot
|
||||
guarantee that the pointer will remain valid at all once it returns,
|
||||
as the parameter `p` may or may not be live in the caller. Therefore,
|
||||
the compiler will report an error here.
|
||||
|
||||
In general, if you borrow a shared (or unique) box to create a
|
||||
In general, if you borrow a managed (or unique) box to create a
|
||||
borrowed pointer, the pointer will only be valid within the function
|
||||
and cannot be returned. Generally, the only way to return borrowed
|
||||
pointers is to take borrowed pointers as input.
|
||||
and cannot be returned. This is why the typical way to return borrowed
|
||||
pointers is to take borrowed pointers as input (the only other case in
|
||||
which it can be legal to return a borrowed pointer is if the pointer
|
||||
points at a static constant).
|
||||
|
||||
# Named lifetimes
|
||||
|
||||
So far we have always used the notation `&T` for a borrowed
|
||||
pointer. However, sometimes if a function takes many parameters, it is
|
||||
useful to be able to group those parameters by lifetime. For example,
|
||||
consider this function:
|
||||
Let's look at named lifetimes in more detail. In effect, the use of
|
||||
named lifetimes allows you to group parameters by lifetime. For
|
||||
example, consider this function:
|
||||
|
||||
~~~ {.xfail-test}
|
||||
# type point = {x: float, y: float}; // as before
|
||||
# type size = {w: float, h: float}; // as before
|
||||
# enum shape {
|
||||
# circle(point, float), // origin, radius
|
||||
# rectangle(point, size) // upper-left, dimensions
|
||||
~~~
|
||||
# struct Point {x: float, y: float}; // as before
|
||||
# struct Size {w: float, h: float}; // as before
|
||||
# enum Shape {
|
||||
# Circle(Point, float), // origin, radius
|
||||
# Rectangle(Point, Size) // upper-left, dimensions
|
||||
# }
|
||||
# fn compute_area(shape: &shape) -> float { 0f }
|
||||
fn select<T>(shape: &shape, threshold: float,
|
||||
a: &T, b: &T) -> &T {
|
||||
# fn compute_area(shape: &Shape) -> float { 0f }
|
||||
fn select<T>(shape: &r/Shape, threshold: float,
|
||||
a: &r/T, b: &r/T) -> &r/T {
|
||||
if compute_area(shape) > threshold {a} else {b}
|
||||
}
|
||||
~~~
|
||||
|
||||
This function takes three borrowed pointers. Because of the way that
|
||||
the system works, each will be assigned the same lifetime: the default
|
||||
lifetime parameter. In practice, this means that, in the caller, the
|
||||
lifetime of the returned value will be the intersection of the
|
||||
lifetime of the three region parameters. This may be overloy
|
||||
conservative, as in this example:
|
||||
This function takes three borrowed pointers and assigns each the same
|
||||
lifetime `r`. In practice, this means that, in the caller, the
|
||||
lifetime `r` will be the *intersection of the lifetime of the three
|
||||
region parameters*. This may be overly conservative, as in this
|
||||
example:
|
||||
|
||||
~~~ {.xfail-test}
|
||||
# type point = {x: float, y: float}; // as before
|
||||
# type size = {w: float, h: float}; // as before
|
||||
# enum shape {
|
||||
# circle(point, float), // origin, radius
|
||||
# rectangle(point, size) // upper-left, dimensions
|
||||
~~~
|
||||
# struct Point {x: float, y: float}; // as before
|
||||
# struct Size {w: float, h: float}; // as before
|
||||
# enum Shape {
|
||||
# Circle(Point, float), // origin, radius
|
||||
# Rectangle(Point, Size) // upper-left, dimensions
|
||||
# }
|
||||
# fn compute_area(shape: &shape) -> float { 0f }
|
||||
# fn select<T>(shape: &shape, threshold: float,
|
||||
# a: &T, b: &T) -> &T {
|
||||
# fn compute_area(shape: &Shape) -> float { 0f }
|
||||
# fn select<T>(shape: &Shape, threshold: float,
|
||||
# a: &r/T, b: &r/T) -> &r/T {
|
||||
# if compute_area(shape) > threshold {a} else {b}
|
||||
# }
|
||||
|
||||
// -+ L
|
||||
fn select_based_on_unit_circle<T>( // |-+ B
|
||||
threshold: float, a: &T, b: &T) -> &T { // | |
|
||||
// | |
|
||||
let shape = circle({x: 0, y: 0}, 1); // | |
|
||||
select(&shape, threshold, a, b) // | |
|
||||
} // |-+
|
||||
// -+
|
||||
// -+ r
|
||||
fn select_based_on_unit_circle<T>( // |-+ B
|
||||
threshold: float, a: &r/T, b: &r/T) -> &r/T { // | |
|
||||
// | |
|
||||
let shape = Circle(Point {x: 0., y: 0.}, 1.); // | |
|
||||
select(&shape, threshold, a, b) // | |
|
||||
} // |-+
|
||||
// -+
|
||||
~~~
|
||||
|
||||
In this call to `select()`, the lifetime of the first parameter shape
|
||||
is B, the function body. Both of the second two parameters `a` and `b`
|
||||
share the same lifetime, L, which is the lifetime parameter of
|
||||
share the same lifetime, `r`, which is a lifetime parameter of
|
||||
`select_based_on_unit_circle()`. The caller will infer the
|
||||
intersection of these three lifetimes as the lifetime of the returned
|
||||
intersection of these two lifetimes as the lifetime of the returned
|
||||
value, and hence the return value of `shape()` will be assigned a
|
||||
return value of B. This will in turn lead to a compilation error,
|
||||
because `select_based_on_unit_circle()` is supposed to return a value
|
||||
with the lifetime L.
|
||||
lifetime of B. This will in turn lead to a compilation error, because
|
||||
`select_based_on_unit_circle()` is supposed to return a value with the
|
||||
lifetime `r`.
|
||||
|
||||
To address this, we could modify the definition of `select()` to
|
||||
To address this, we can modify the definition of `select()` to
|
||||
distinguish the lifetime of the first parameter from the lifetime of
|
||||
the latter two. After all, the first parameter is not being
|
||||
returned. To do so, we make use of the notation `</T`, which is a
|
||||
borrowed pointer with an explicit lifetime. This effectively creates a
|
||||
second lifetime parameter for the function; named lifetime parameters
|
||||
do not need to be declared, you just use them. Here is how the new
|
||||
`select()` might look:
|
||||
returned. Here is how the new `select()` might look:
|
||||
|
||||
~~~ {.xfail-test}
|
||||
# type point = {x: float, y: float}; // as before
|
||||
# type size = {w: float, h: float}; // as before
|
||||
# enum shape {
|
||||
# circle(point, float), // origin, radius
|
||||
# rectangle(point, size) // upper-left, dimensions
|
||||
~~~
|
||||
# struct Point {x: float, y: float}; // as before
|
||||
# struct Size {w: float, h: float}; // as before
|
||||
# enum Shape {
|
||||
# Circle(Point, float), // origin, radius
|
||||
# Rectangle(Point, Size) // upper-left, dimensions
|
||||
# }
|
||||
# fn compute_area(shape: &shape) -> float { 0f }
|
||||
fn select<T>(shape: &tmp/shape, threshold: float,
|
||||
a: &T, b: &T) -> &T {
|
||||
# fn compute_area(shape: &Shape) -> float { 0f }
|
||||
fn select<T>(shape: &tmp/Shape, threshold: float,
|
||||
a: &r/T, b: &r/T) -> &r/T {
|
||||
if compute_area(shape) > threshold {a} else {b}
|
||||
}
|
||||
~~~
|
||||
|
||||
Here you can see the lifetime of shape is now being called `tmp`. The
|
||||
parameters `a`, `b`, and the return value all remain with the default
|
||||
lifetime parameter.
|
||||
parameters `a`, `b`, and the return value are all given the lifetime
|
||||
`r`. However, since the lifetime `tmp` is not returned, it would be shorter
|
||||
to just omit the named lifetime for `shape` altogether:
|
||||
|
||||
You could also write `select()` using all named lifetime parameters,
|
||||
which might look like:
|
||||
|
||||
~~~ {.xfail-test}
|
||||
# type point = {x: float, y: float}; // as before
|
||||
# type size = {w: float, h: float}; // as before
|
||||
# enum shape {
|
||||
# circle(point, float), // origin, radius
|
||||
# rectangle(point, size) // upper-left, dimensions
|
||||
~~~
|
||||
# struct Point {x: float, y: float}; // as before
|
||||
# struct Size {w: float, h: float}; // as before
|
||||
# enum Shape {
|
||||
# Circle(Point, float), // origin, radius
|
||||
# Rectangle(Point, Size) // upper-left, dimensions
|
||||
# }
|
||||
# fn compute_area(shape: &shape) -> float { 0f }
|
||||
fn select<T>(shape: &tmp/shape, threshold: float,
|
||||
# fn compute_area(shape: &Shape) -> float { 0f }
|
||||
fn select<T>(shape: &Shape, threshold: float,
|
||||
a: &r/T, b: &r/T) -> &r/T {
|
||||
if compute_area(shape) > threshold {a} else {b}
|
||||
}
|
||||
|
|
@ -721,7 +749,9 @@ a unique box found in an aliasable, mutable location, only now we’ve
|
|||
replaced the `...` with some specific code:
|
||||
|
||||
~~~
|
||||
fn example5a(x: @{mut f: ~{g: int}} ...) -> int {
|
||||
struct R { g: int }
|
||||
struct S { mut f: ~R }
|
||||
fn example5a(x: @S ...) -> int {
|
||||
let y = &x.f.g; // Unsafe
|
||||
*y + 1
|
||||
}
|
||||
|
|
@ -739,9 +769,11 @@ fn add_one(x: &int) -> int { *x + 1 }
|
|||
|
||||
We can now update `example5a()` to use `add_one()`:
|
||||
|
||||
~~~ {.xfail-test}
|
||||
# fn add_one(x: &int) -> int { *x + 1 }
|
||||
fn example5a(x: @{mut f: ~{g: int}} ...) -> int {
|
||||
~~~
|
||||
# struct R { g: int }
|
||||
# struct S { mut f: ~R }
|
||||
# pure fn add_one(x: &int) -> int { *x + 1 }
|
||||
fn example5a(x: @S ...) -> int {
|
||||
let y = &x.f.g;
|
||||
add_one(y) // Error reported here
|
||||
}
|
||||
|
|
@ -763,4 +795,4 @@ With this change, the modified version of `example5a()` will again compile.
|
|||
So there you have it. A (relatively) brief tour of borrowed pointer
|
||||
system. For more details, I refer to the (yet to be written) reference
|
||||
document on borrowed pointers, which will explain the full notation
|
||||
and give more examples.
|
||||
and give more examples.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
# Interacting with foreign code
|
||||
% Rust Foreign Function Interface Tutorial
|
||||
|
||||
# Introduction
|
||||
|
||||
One of Rust's aims, as a system programming language, is to
|
||||
interoperate well with C code.
|
||||
|
|
@ -38,7 +40,7 @@ fn main(args: ~[~str]) {
|
|||
}
|
||||
~~~~
|
||||
|
||||
## Foreign modules
|
||||
# Foreign modules
|
||||
|
||||
Before we can call `SHA1`, we have to declare it. That is what this
|
||||
part of the program is responsible for:
|
||||
|
|
@ -68,7 +70,7 @@ extern mod something {
|
|||
}
|
||||
~~~~
|
||||
|
||||
## Foreign calling conventions
|
||||
# Foreign calling conventions
|
||||
|
||||
Most foreign code will be C code, which usually uses the `cdecl` calling
|
||||
convention, so that is what Rust uses by default when calling foreign
|
||||
|
|
@ -88,7 +90,7 @@ The `"abi"` attribute applies to a foreign module (it can not be applied
|
|||
to a single function within a module), and must be either `"cdecl"`
|
||||
or `"stdcall"`. Other conventions may be defined in the future.
|
||||
|
||||
## Unsafe pointers
|
||||
# Unsafe pointers
|
||||
|
||||
The foreign `SHA1` function is declared to take three arguments, and
|
||||
return a pointer.
|
||||
|
|
@ -118,7 +120,7 @@ caution—unlike Rust's other pointer types, unsafe pointers are
|
|||
completely unmanaged, so they might point at invalid memory, or be
|
||||
null pointers.
|
||||
|
||||
## Unsafe blocks
|
||||
# Unsafe blocks
|
||||
|
||||
The `sha1` function is the most obscure part of the program.
|
||||
|
||||
|
|
@ -159,7 +161,7 @@ unsafe fn kaboom() { ~"I'm harmless!"; }
|
|||
This function can only be called from an unsafe block or another
|
||||
unsafe function.
|
||||
|
||||
## Pointer fiddling
|
||||
# Pointer fiddling
|
||||
|
||||
The standard library defines a number of helper functions for dealing
|
||||
with unsafe data, casting between types, and generally subverting
|
||||
|
|
@ -202,10 +204,10 @@ unsafe pointer that was returned by `SHA1`. SHA1 digests are always
|
|||
twenty bytes long, so we can pass `20u` for the length of the new
|
||||
vector.
|
||||
|
||||
## Passing structures
|
||||
# Passing structures
|
||||
|
||||
C functions often take pointers to structs as arguments. Since Rust
|
||||
records are binary-compatible with C structs, Rust programs can call
|
||||
structs are binary-compatible with C structs, Rust programs can call
|
||||
such functions directly.
|
||||
|
||||
This program uses the POSIX function `gettimeofday` to get a
|
||||
|
|
@ -215,15 +217,21 @@ microsecond-resolution timer.
|
|||
extern mod std;
|
||||
use libc::c_ulonglong;
|
||||
|
||||
type timeval = {mut tv_sec: c_ulonglong,
|
||||
mut tv_usec: c_ulonglong};
|
||||
struct timeval {
|
||||
mut tv_sec: c_ulonglong,
|
||||
mut tv_usec: c_ulonglong
|
||||
}
|
||||
|
||||
#[nolink]
|
||||
extern mod lib_c {
|
||||
fn gettimeofday(tv: *timeval, tz: *()) -> i32;
|
||||
}
|
||||
fn unix_time_in_microseconds() -> u64 unsafe {
|
||||
let x = {mut tv_sec: 0 as c_ulonglong, mut tv_usec: 0 as c_ulonglong};
|
||||
lib_c::gettimeofday(ptr::addr_of(x), ptr::null());
|
||||
let x = timeval {
|
||||
mut tv_sec: 0 as c_ulonglong,
|
||||
mut tv_usec: 0 as c_ulonglong
|
||||
};
|
||||
lib_c::gettimeofday(ptr::addr_of(&x), ptr::null());
|
||||
return (x.tv_sec as u64) * 1000_000_u64 + (x.tv_usec as u64);
|
||||
}
|
||||
|
||||
|
|
@ -234,8 +242,8 @@ The `#[nolink]` attribute indicates that there's no foreign library to
|
|||
link in. The standard C library is already linked with Rust programs.
|
||||
|
||||
A `timeval`, in C, is a struct with two 32-bit integers. Thus, we
|
||||
define a record type with the same contents, and declare
|
||||
`gettimeofday` to take a pointer to such a record.
|
||||
define a struct type with the same contents, and declare
|
||||
`gettimeofday` to take a pointer to such a struct.
|
||||
|
||||
The second argument to `gettimeofday` (the time zone) is not used by
|
||||
this program, so it simply declares it to be a pointer to the nil
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
# Macros
|
||||
% Rust Macros Tutorial
|
||||
|
||||
# Introduction
|
||||
|
||||
Functions are the programmer's primary tool of abstraction, but there are
|
||||
cases in which they are insufficient, because the programmer wants to
|
||||
|
|
@ -50,7 +52,7 @@ early_return!(input_2 special_b);
|
|||
|
||||
Macros are defined in pattern-matching style:
|
||||
|
||||
## Invocation syntax
|
||||
# Invocation syntax
|
||||
|
||||
On the left-hand-side of the `=>` is the macro invocation syntax. It is
|
||||
free-form, excepting the following rules:
|
||||
|
|
@ -69,7 +71,7 @@ rules of tokenization apply,
|
|||
So `($x:ident => (($e:expr)))`, though excessively fancy, would create a macro
|
||||
that could be invoked like `my_macro!(i=>(( 2+2 )))`.
|
||||
|
||||
## Transcription syntax
|
||||
# Transcription syntax
|
||||
|
||||
The right-hand side of the `=>` follows the same rules as the left-hand side,
|
||||
except that `$` need only be followed by the name of the syntactic fragment
|
||||
|
|
@ -80,9 +82,9 @@ an expression; currently, user-defined macros can only be invoked in
|
|||
expression position (even though `macro_rules!` itself can be in item
|
||||
position).
|
||||
|
||||
## Multiplicity
|
||||
# Multiplicity
|
||||
|
||||
### Invocation
|
||||
## Invocation
|
||||
|
||||
Going back to the motivating example, suppose that we wanted each invocation
|
||||
of `early_return` to potentially accept multiple "special" identifiers. The
|
||||
|
|
|
|||
|
|
@ -1,52 +1,165 @@
|
|||
% Tasks and communication in Rust
|
||||
% Rust Tasks and Communication Tutorial
|
||||
|
||||
Rust supports a system of lightweight tasks, similar to what is found
|
||||
in Erlang or other actor systems. Rust tasks communicate via messages
|
||||
and do not share data. However, it is possible to send data without
|
||||
copying it by making use of [the exchange heap](#unique-boxes), which
|
||||
allow the sending task to release ownership of a value, so that the
|
||||
receiving task can keep on using it.
|
||||
# Introduction
|
||||
|
||||
> ***Note:*** As Rust evolves, we expect the task API to grow and
|
||||
> change somewhat. The tutorial documents the API as it exists today.
|
||||
The Rust language is designed from the ground up to support pervasive
|
||||
and safe concurrency through lightweight, memory-isolated tasks and
|
||||
message passing.
|
||||
|
||||
# Spawning a task
|
||||
Rust tasks are not the same as traditional threads - they are what are
|
||||
often referred to as _green threads_, cooperatively scheduled by the
|
||||
Rust runtime onto a small number of operating system threads. Being
|
||||
significantly cheaper to create than traditional threads, Rust can
|
||||
create hundreds of thousands of concurrent tasks on a typical 32-bit
|
||||
system.
|
||||
|
||||
Spawning a task is done using the various spawn functions in the
|
||||
module `task`. Let's begin with the simplest one, `task::spawn()`:
|
||||
Tasks provide failure isolation and recovery. When an exception occurs
|
||||
in rust code (either by calling `fail` explicitly or by otherwise performing
|
||||
an invalid operation) the entire task is destroyed - there is no way
|
||||
to `catch` an exception as in other languages. Instead tasks may monitor
|
||||
each other to detect when failure has occurred.
|
||||
|
||||
Rust tasks have dynamically sized stacks. When a task is first created
|
||||
it starts off with a small amount of stack (currently in the low
|
||||
thousands of bytes, depending on platform) and more stack is acquired as
|
||||
needed. A Rust task will never run off the end of the stack as is
|
||||
possible in many other languages, but they do have a stack budget, and
|
||||
if a Rust task exceeds its stack budget then it will fail safely.
|
||||
|
||||
Tasks make use of Rust's type system to provide strong memory safety
|
||||
guarantees, disallowing shared mutable state. Communication between
|
||||
tasks is facilitated by the transfer of _owned_ data through the
|
||||
global _exchange heap_.
|
||||
|
||||
This tutorial will explain the basics of tasks and communication in Rust,
|
||||
explore some typical patterns in concurrent Rust code, and finally
|
||||
discuss some of the more exotic synchronization types in the standard
|
||||
library.
|
||||
|
||||
## A note about the libraries
|
||||
|
||||
While Rust's type system provides the building blocks needed for safe
|
||||
and efficient tasks, all of the task functionality itself is implemented
|
||||
in the core and standard libraries, which are still under development
|
||||
and do not always present a consistent interface.
|
||||
|
||||
In particular, there are currently two independent modules that provide
|
||||
a message passing interface to Rust code: `core::comm` and `core::pipes`.
|
||||
`core::comm` is an older, less efficient system that is being phased out
|
||||
in favor of `pipes`. At some point the existing `core::comm` API will
|
||||
be romoved and the user-facing portions of `core::pipes` will be moved
|
||||
to `core::comm`. In this tutorial we will discuss `pipes` and ignore
|
||||
the `comm` API.
|
||||
|
||||
For your reference, these are the standard modules involved in Rust
|
||||
concurrency at the moment.
|
||||
|
||||
* [`core::task`] - All code relating to tasks and task scheduling
|
||||
* [`core::comm`] - The deprecated message passing API
|
||||
* [`core::pipes`] - The new message passing infrastructure and API
|
||||
* [`std::comm`] - Higher level messaging types based on `core::pipes`
|
||||
* [`std::sync`] - More exotic synchronization tools, including locks
|
||||
* [`std::arc`] - The ARC type, for safely sharing immutable data
|
||||
* [`std::par`] - Some basic tools for implementing parallel algorithms
|
||||
|
||||
[`core::task`]: core/task.html
|
||||
[`core::comm`]: core/comm.html
|
||||
[`core::pipes`]: core/pipes.html
|
||||
[`std::comm`]: std/comm.html
|
||||
[`std::sync`]: std/sync.html
|
||||
[`std::arc`]: std/arc.html
|
||||
[`std::par`]: std/par.html
|
||||
|
||||
# Basics
|
||||
|
||||
The programming interface for creating and managing tasks is contained
|
||||
in the `task` module of the `core` library, making it available to all
|
||||
Rust code by default. At it's simplest, creating a task is a matter of
|
||||
calling the `spawn` function, passing a closure to run in the new
|
||||
task.
|
||||
|
||||
~~~~
|
||||
# use io::println;
|
||||
use task::spawn;
|
||||
use io::println;
|
||||
|
||||
let some_value = 22;
|
||||
// Print something profound in a different task using a named function
|
||||
fn print_message() { println("I am running in a different task!"); }
|
||||
spawn(print_message);
|
||||
|
||||
// Print something more profound in a different task using a lambda expression
|
||||
spawn( || println("I am also running in a different task!") );
|
||||
|
||||
// The canonical way to spawn is using `do` notation
|
||||
do spawn {
|
||||
println(~"This executes in the child task.");
|
||||
println(fmt!("%d", some_value));
|
||||
println("I too am running in a different task!");
|
||||
}
|
||||
~~~~
|
||||
|
||||
The argument to `task::spawn()` is a [unique
|
||||
closure](#unique-closures) of type `fn~()`, meaning that it takes no
|
||||
arguments and generates no return value. The effect of `task::spawn()`
|
||||
is to fire up a child task that will execute the closure in parallel
|
||||
with the creator.
|
||||
In Rust, there is nothing special about creating tasks - the language
|
||||
itself doesn't know what a 'task' is. Instead, Rust provides in the
|
||||
type system all the tools necessary to implement safe concurrency,
|
||||
_owned types_ in particular, and leaves the dirty work up to the
|
||||
core library.
|
||||
|
||||
# Communication
|
||||
The `spawn` function has a very simple type signature: `fn spawn(f:
|
||||
~fn())`. Because it accepts only owned closures, and owned closures
|
||||
contained only owned data, `spawn` can safely move the entire closure
|
||||
and all its associated state into an entirely different task for
|
||||
execution. Like any closure, the function passed to spawn may capture
|
||||
an environment that it carries across tasks.
|
||||
|
||||
Now that we have spawned a child task, it would be nice if we could
|
||||
communicate with it. This is done using *pipes*. Pipes are simply a
|
||||
pair of endpoints, with one for sending messages and another for
|
||||
receiving messages. The easiest way to create a pipe is to use
|
||||
`pipes::stream`. Imagine we wish to perform two expensive
|
||||
computations in parallel. We might write something like:
|
||||
~~~
|
||||
# use io::println;
|
||||
# use task::spawn;
|
||||
# fn generate_task_number() -> int { 0 }
|
||||
// Generate some state locally
|
||||
let child_task_number = generate_task_number();
|
||||
|
||||
do spawn {
|
||||
// Capture it in the remote task
|
||||
println(fmt!("I am child number %d", child_task_number));
|
||||
}
|
||||
~~~
|
||||
|
||||
By default tasks will be multiplexed across the available cores, running
|
||||
in parallel, thus on a multicore machine, running the following code
|
||||
should interleave the output in vaguely random order.
|
||||
|
||||
~~~
|
||||
# use io::print;
|
||||
# use task::spawn;
|
||||
|
||||
for int::range(0, 20) |child_task_number| {
|
||||
do spawn {
|
||||
print(fmt!("I am child number %d\n", child_task_number));
|
||||
}
|
||||
}
|
||||
~~~
|
||||
|
||||
## Communication
|
||||
|
||||
Now that we have spawned a new task, it would be nice if we could
|
||||
communicate with it. Recall that Rust does not have shared mutable
|
||||
state, so one task may not manipulate variables owned by another task.
|
||||
Instead we use *pipes*.
|
||||
|
||||
Pipes are simply a pair of endpoints, with one for sending messages
|
||||
and another for receiving messages. Pipes are low-level communication
|
||||
building-blocks and so come in a variety of forms, appropriate for
|
||||
different use cases, but there are just a few varieties that are most
|
||||
commonly used, which we will cover presently.
|
||||
|
||||
The simplest way to create a pipe is to use the `pipes::stream`
|
||||
function to create a `(Chan, Port)` pair. In Rust parlance a 'channel'
|
||||
is a sending endpoint of a pipe, and a 'port' is the recieving
|
||||
endpoint. Consider the following example of performing two calculations
|
||||
concurrently.
|
||||
|
||||
~~~~
|
||||
use task::spawn;
|
||||
use pipes::{stream, Port, Chan};
|
||||
|
||||
let (chan, port) = stream();
|
||||
let (chan, port): (Chan<int>, Port<int>) = stream();
|
||||
|
||||
do spawn {
|
||||
let result = some_expensive_computation();
|
||||
|
|
@ -55,43 +168,45 @@ do spawn {
|
|||
|
||||
some_other_expensive_computation();
|
||||
let result = port.recv();
|
||||
|
||||
# fn some_expensive_computation() -> int { 42 }
|
||||
# fn some_other_expensive_computation() {}
|
||||
~~~~
|
||||
|
||||
Let's walk through this code line-by-line. The first line creates a
|
||||
stream for sending and receiving integers:
|
||||
Let's examine this example in detail. The `let` statement first creates a
|
||||
stream for sending and receiving integers (recall that `let` can be
|
||||
used for destructuring patterns, in this case separating a tuple into
|
||||
its component parts).
|
||||
|
||||
~~~~ {.ignore}
|
||||
# use pipes::stream;
|
||||
let (chan, port) = stream();
|
||||
~~~~
|
||||
# use pipes::{stream, Chan, Port};
|
||||
let (chan, port): (Chan<int>, Port<int>) = stream();
|
||||
~~~~
|
||||
|
||||
This port is where we will receive the message from the child task
|
||||
once it is complete. The channel will be used by the child to send a
|
||||
message to the port. The next statement actually spawns the child:
|
||||
The channel will be used by the child task to send data to the parent task,
|
||||
which will wait to recieve the data on the port. The next statement
|
||||
spawns the child task.
|
||||
|
||||
~~~~
|
||||
# use task::{spawn};
|
||||
# use comm::{Port, Chan};
|
||||
# use task::spawn;
|
||||
# use pipes::{stream, Port, Chan};
|
||||
# fn some_expensive_computation() -> int { 42 }
|
||||
# let port = Port();
|
||||
# let chan = port.chan();
|
||||
# let (chan, port) = stream();
|
||||
do spawn {
|
||||
let result = some_expensive_computation();
|
||||
chan.send(result);
|
||||
}
|
||||
~~~~
|
||||
|
||||
This child will perform the expensive computation send the result
|
||||
over the channel. (Under the hood, `chan` was captured by the
|
||||
closure that forms the body of the child task. This capture is
|
||||
allowed because channels are sendable.)
|
||||
Notice that `chan` was transferred to the child task implicitly by
|
||||
capturing it in the task closure. Both `Chan` and `Port` are sendable
|
||||
types and may be captured into tasks or otherwise transferred between
|
||||
them. In the example, the child task performs an expensive computation
|
||||
then sends the result over the captured channel.
|
||||
|
||||
Finally, the parent continues by performing
|
||||
some other expensive computation and then waiting for the child's result
|
||||
to arrive on the port:
|
||||
Finally, the parent continues by performing some other expensive
|
||||
computation and then waiting for the child's result to arrive on the
|
||||
port:
|
||||
|
||||
~~~~
|
||||
# use pipes::{stream, Port, Chan};
|
||||
|
|
@ -102,7 +217,248 @@ some_other_expensive_computation();
|
|||
let result = port.recv();
|
||||
~~~~
|
||||
|
||||
# Creating a task with a bi-directional communication path
|
||||
The `Port` and `Chan` pair created by `stream` enable efficient
|
||||
communication between a single sender and a single receiver, but
|
||||
multiple senders cannot use a single `Chan`, nor can multiple
|
||||
receivers use a single `Port`. What if our example needed to perform
|
||||
multiple computations across a number of tasks? The following cannot
|
||||
be written:
|
||||
|
||||
~~~ {.xfail-test}
|
||||
# use task::{spawn};
|
||||
# use pipes::{stream, Port, Chan};
|
||||
# fn some_expensive_computation() -> int { 42 }
|
||||
let (chan, port) = stream();
|
||||
|
||||
do spawn {
|
||||
chan.send(some_expensive_computation());
|
||||
}
|
||||
|
||||
// ERROR! The previous spawn statement already owns the channel,
|
||||
// so the compiler will not allow it to be captured again
|
||||
do spawn {
|
||||
chan.send(some_expensive_computation());
|
||||
}
|
||||
~~~
|
||||
|
||||
Instead we can use a `SharedChan`, a type that allows a single
|
||||
`Chan` to be shared by multiple senders.
|
||||
|
||||
~~~
|
||||
# use task::spawn;
|
||||
use pipes::{stream, SharedChan};
|
||||
|
||||
let (chan, port) = stream();
|
||||
let chan = SharedChan(move chan);
|
||||
|
||||
for uint::range(0, 3) |init_val| {
|
||||
// Create a new channel handle to distribute to the child task
|
||||
let child_chan = chan.clone();
|
||||
do spawn {
|
||||
child_chan.send(some_expensive_computation(init_val));
|
||||
}
|
||||
}
|
||||
|
||||
let result = port.recv() + port.recv() + port.recv();
|
||||
# fn some_expensive_computation(_i: uint) -> int { 42 }
|
||||
~~~
|
||||
|
||||
Here we transfer ownership of the channel into a new `SharedChan`
|
||||
value. Like `Chan`, `SharedChan` is a non-copyable, owned type
|
||||
(sometimes also referred to as an 'affine' or 'linear' type). Unlike
|
||||
`Chan` though, `SharedChan` may be duplicated with the `clone()`
|
||||
method. A cloned `SharedChan` produces a new handle to the same
|
||||
channel, allowing multiple tasks to send data to a single port.
|
||||
Between `spawn`, `stream` and `SharedChan` we have enough tools
|
||||
to implement many useful concurrency patterns.
|
||||
|
||||
Note that the above `SharedChan` example is somewhat contrived since
|
||||
you could also simply use three `stream` pairs, but it serves to
|
||||
illustrate the point. For reference, written with multiple streams it
|
||||
might look like the example below.
|
||||
|
||||
~~~
|
||||
# use task::spawn;
|
||||
# use pipes::{stream, Port, Chan};
|
||||
|
||||
// Create a vector of ports, one for each child task
|
||||
let ports = do vec::from_fn(3) |init_val| {
|
||||
let (chan, port) = stream();
|
||||
do spawn {
|
||||
chan.send(some_expensive_computation(init_val));
|
||||
}
|
||||
port
|
||||
};
|
||||
|
||||
// Wait on each port, accumulating the results
|
||||
let result = ports.foldl(0, |accum, port| *accum + port.recv() );
|
||||
# fn some_expensive_computation(_i: uint) -> int { 42 }
|
||||
~~~
|
||||
|
||||
# TODO
|
||||
|
||||
# Handling task failure
|
||||
|
||||
Rust has a built-in mechanism for raising exceptions, written `fail`
|
||||
(or `fail ~"reason"`, or sometimes `assert expr`), and it causes the
|
||||
task to unwind its stack, running destructors and freeing memory along
|
||||
the way, and then exit itself. Unlike C++, exceptions in Rust are
|
||||
unrecoverable within a single task - once a task fails there is no way
|
||||
to "catch" the exception.
|
||||
|
||||
All tasks are, by default, _linked_ to each other, meaning their fate
|
||||
is interwined, and if one fails so do all of them.
|
||||
|
||||
~~~
|
||||
# use task::spawn;
|
||||
# fn do_some_work() { loop { task::yield() } }
|
||||
# do task::try {
|
||||
// Create a child task that fails
|
||||
do spawn { fail }
|
||||
|
||||
// This will also fail because the task we spawned failed
|
||||
do_some_work();
|
||||
# };
|
||||
~~~
|
||||
|
||||
While it isn't possible for a task to recover from failure,
|
||||
tasks may be notified when _other_ tasks fail. The simplest way
|
||||
of handling task failure is with the `try` function, which is
|
||||
similar to spawn, but immediately blocks waiting for the child
|
||||
task to finish.
|
||||
|
||||
~~~
|
||||
# fn some_condition() -> bool { false }
|
||||
# fn calculate_result() -> int { 0 }
|
||||
let result: Result<int, ()> = do task::try {
|
||||
if some_condition() {
|
||||
calculate_result()
|
||||
} else {
|
||||
fail ~"oops!";
|
||||
}
|
||||
};
|
||||
assert result.is_err();
|
||||
~~~
|
||||
|
||||
Unlike `spawn`, the function spawned using `try` may return a value,
|
||||
which `try` will dutifully propagate back to the caller in a [`Result`]
|
||||
enum. If the child task terminates successfully, `try` will
|
||||
return an `Ok` result; if the child task fails, `try` will return
|
||||
an `Error` result.
|
||||
|
||||
[`Result`]: core/result.html
|
||||
|
||||
> ***Note:*** A failed task does not currently produce a useful error
|
||||
> value (all error results from `try` are equal to `Err(())`). In the
|
||||
> future it may be possible for tasks to intercept the value passed to
|
||||
> `fail`.
|
||||
|
||||
TODO: Need discussion of `future_result` in order to make failure
|
||||
modes useful.
|
||||
|
||||
But not all failure is created equal. In some cases you might need to
|
||||
abort the entire program (perhaps you're writing an assert which, if
|
||||
it trips, indicates an unrecoverable logic error); in other cases you
|
||||
might want to contain the failure at a certain boundary (perhaps a
|
||||
small piece of input from the outside world, which you happen to be
|
||||
processing in parallel, is malformed and its processing task can't
|
||||
proceed). Hence the need for different _linked failure modes_.
|
||||
|
||||
## Failure modes
|
||||
|
||||
By default, task failure is _bidirectionally linked_, which means if
|
||||
either task dies, it kills the other one.
|
||||
|
||||
~~~
|
||||
# fn sleep_forever() { loop { task::yield() } }
|
||||
# do task::try {
|
||||
do task::spawn {
|
||||
do task::spawn {
|
||||
fail; // All three tasks will die.
|
||||
}
|
||||
sleep_forever(); // Will get woken up by force, then fail
|
||||
}
|
||||
sleep_forever(); // Will get woken up by force, then fail
|
||||
# };
|
||||
~~~
|
||||
|
||||
If you want parent tasks to kill their children, but not for a child
|
||||
task's failure to kill the parent, you can call
|
||||
`task::spawn_supervised` for _unidirectionally linked_ failure. The
|
||||
function `task::try`, which we saw previously, uses `spawn_supervised`
|
||||
internally, with additional logic to wait for the child task to finish
|
||||
before returning. Hence:
|
||||
|
||||
~~~
|
||||
# use pipes::{stream, Chan, Port};
|
||||
# use task::{spawn, try};
|
||||
# fn sleep_forever() { loop { task::yield() } }
|
||||
# do task::try {
|
||||
let (sender, receiver): (Chan<int>, Port<int>) = stream();
|
||||
do spawn { // Bidirectionally linked
|
||||
// Wait for the supervised child task to exist.
|
||||
let message = receiver.recv();
|
||||
// Kill both it and the parent task.
|
||||
assert message != 42;
|
||||
}
|
||||
do try { // Unidirectionally linked
|
||||
sender.send(42);
|
||||
sleep_forever(); // Will get woken up by force
|
||||
}
|
||||
// Flow never reaches here -- parent task was killed too.
|
||||
# };
|
||||
~~~
|
||||
|
||||
Supervised failure is useful in any situation where one task manages
|
||||
multiple fallible child tasks, and the parent task can recover
|
||||
if any child files. On the other hand, if the _parent_ (supervisor) fails
|
||||
then there is nothing the children can do to recover, so they should
|
||||
also fail.
|
||||
|
||||
Supervised task failure propagates across multiple generations even if
|
||||
an intermediate generation has already exited:
|
||||
|
||||
~~~
|
||||
# fn sleep_forever() { loop { task::yield() } }
|
||||
# fn wait_for_a_while() { for 1000.times { task::yield() } }
|
||||
# do task::try::<int> {
|
||||
do task::spawn_supervised {
|
||||
do task::spawn_supervised {
|
||||
sleep_forever(); // Will get woken up by force, then fail
|
||||
}
|
||||
// Intermediate task immediately exits
|
||||
}
|
||||
wait_for_a_while();
|
||||
fail; // Will kill grandchild even if child has already exited
|
||||
# };
|
||||
~~~
|
||||
|
||||
Finally, tasks can be configured to not propagate failure to each
|
||||
other at all, using `task::spawn_unlinked` for _isolated failure_.
|
||||
|
||||
~~~
|
||||
# fn random() -> int { 100 }
|
||||
# fn sleep_for(i: int) { for i.times { task::yield() } }
|
||||
# do task::try::<()> {
|
||||
let (time1, time2) = (random(), random());
|
||||
do task::spawn_unlinked {
|
||||
sleep_for(time2); // Won't get forced awake
|
||||
fail;
|
||||
}
|
||||
sleep_for(time1); // Won't get forced awake
|
||||
fail;
|
||||
// It will take MAX(time1,time2) for the program to finish.
|
||||
# };
|
||||
~~~
|
||||
|
||||
|
||||
# Unfinished notes
|
||||
|
||||
## Actor patterns
|
||||
|
||||
## Linearity, option dancing, owned closures
|
||||
|
||||
## Creating a task with a bi-directional communication path
|
||||
|
||||
A very common thing to do is to spawn a child task where the parent
|
||||
and child both need to exchange messages with each other. The
|
||||
|
|
@ -171,3 +527,4 @@ assert from_child.recv() == ~"0";
|
|||
|
||||
The parent task first calls `DuplexStream` to create a pair of bidirectional endpoints. It then uses `task::spawn` to create the child task, which captures one end of the communication channel. As a result, both parent
|
||||
and child can send and receive data to and from the other.
|
||||
|
||||
|
|
|
|||
128
doc/tutorial.md
128
doc/tutorial.md
|
|
@ -82,7 +82,7 @@ supported build environments that are most likely to work.
|
|||
|
||||
> ***Note:*** Windows users should read the detailed
|
||||
> [getting started][wiki-start] notes on the wiki. Even when using
|
||||
> the binary installer the windows build requires a MinGW installation,
|
||||
> the binary installer the Windows build requires a MinGW installation,
|
||||
> the precise details of which are not discussed in this tutorial.
|
||||
|
||||
To build from source you will also need the following prerequisite
|
||||
|
|
@ -111,12 +111,9 @@ can be adjusted by passing a `--prefix` argument to
|
|||
`configure`. Various other options are also supported, pass `--help`
|
||||
for more information on them.
|
||||
|
||||
When complete, `make install` will place the following programs into
|
||||
`/usr/local/bin`:
|
||||
|
||||
* `rustc`, the Rust compiler
|
||||
* `rustdoc`, the API-documentation tool
|
||||
* `cargo`, the Rust package manager
|
||||
When complete, `make install` will place several programs into
|
||||
`/usr/local/bin`: `rustc`, the Rust compiler; `rustdoc`, the
|
||||
API-documentation tool, and `cargo`, the Rust package manager.
|
||||
|
||||
[wiki-start]: https://github.com/mozilla/rust/wiki/Note-getting-started-developing-Rust
|
||||
[tarball]: http://dl.rust-lang.org/dist/rust-0.4.tar.gz
|
||||
|
|
@ -216,8 +213,8 @@ fn main() {
|
|||
}
|
||||
~~~~
|
||||
|
||||
The `let` keyword, introduces a local variable. By default, variables
|
||||
are immutable. `let mut` can be used to introduce a local variable
|
||||
The `let` keyword introduces a local variable. Variables are immutable
|
||||
by default, so `let mut` can be used to introduce a local variable
|
||||
that can be reassigned.
|
||||
|
||||
~~~~
|
||||
|
|
@ -232,14 +229,17 @@ while count < 10 {
|
|||
|
||||
Although Rust can almost always infer the types of local variables, it
|
||||
can help readability to specify a variable's type by following it with
|
||||
a colon, then the type name. Local variables may shadow earlier
|
||||
declarations, making the earlier variables inaccessible.
|
||||
a colon, then the type name.
|
||||
|
||||
~~~~
|
||||
let my_favorite_value: float = 57.8;
|
||||
let my_favorite_value: int = my_favorite_value as int;
|
||||
~~~~
|
||||
|
||||
Local variables may shadow earlier declarations, as in the previous
|
||||
example in which `my_favorite_value` is first declared as a `float`
|
||||
then a second `my_favorite_value` is declared as an int.
|
||||
|
||||
Rust identifiers follow the same rules as C; they start with an alphabetic
|
||||
character or an underscore, and after that may contain any sequence of
|
||||
alphabetic characters, numbers, or underscores. The preferred style is to
|
||||
|
|
@ -371,7 +371,7 @@ more detail later on (the `T`s here stand for any other type):
|
|||
`[T * N]` Vector (like an array in other languages) with N elements
|
||||
`[mut T * N]` Mutable vector with N elements
|
||||
`(T1, T2)` Tuple type. Any arity above 1 is supported
|
||||
`@T`, `~T`, `&T` [Pointer types](#boxes-and-pointers)
|
||||
`&T`, `~T`, `@T` [Pointer types](#boxes-and-pointers)
|
||||
------------------------- -----------------------------------------------
|
||||
|
||||
Some types can only be manipulated by pointer, never directly. For instance,
|
||||
|
|
@ -421,7 +421,7 @@ Rust will assume that an unsuffixed integer literal has type
|
|||
~~~~
|
||||
let a = 1; // a is an int
|
||||
let b = 10i; // b is an int, due to the 'i' suffix
|
||||
let c = 100u; // c as a uint
|
||||
let c = 100u; // c is a uint
|
||||
let d = 1000i32; // d is an i32
|
||||
~~~~
|
||||
|
||||
|
|
@ -619,7 +619,7 @@ literals and most enum variants.
|
|||
|
||||
`while` produces a loop that runs as long as its given condition
|
||||
(which must have type `bool`) evaluates to true. Inside a loop, the
|
||||
keyword `break` can be used to abort the loop, and `again` can be used
|
||||
keyword `break` can be used to abort the loop, and `loop` can be used
|
||||
to abort the current iteration and continue with the next.
|
||||
|
||||
~~~~
|
||||
|
|
@ -713,16 +713,16 @@ enum Shape {
|
|||
}
|
||||
~~~~
|
||||
|
||||
A value of this type is either a Circle, in which case it contains a
|
||||
point struct and a float, or a Rectangle, in which case it contains
|
||||
two point records. The run-time representation of such a value
|
||||
A value of this type is either a `Circle`, in which case it contains a
|
||||
`Point` struct and a float, or a `Rectangle`, in which case it contains
|
||||
two `Point` structs. The run-time representation of such a value
|
||||
includes an identifier of the actual form that it holds, much like the
|
||||
'tagged union' pattern in C, but with better ergonomics.
|
||||
|
||||
The above declaration will define a type `shape` that can be used to
|
||||
refer to such shapes, and two functions, `circle` and `rectangle`,
|
||||
The above declaration will define a type `Shape` that can be used to
|
||||
refer to such shapes, and two functions, `Circle` and `Rectangle`,
|
||||
which can be used to construct values of the type (taking arguments of
|
||||
the specified types). So `circle({x: 0f, y: 0f}, 10f)` is the way to
|
||||
the specified types). So `Circle(Point {x: 0f, y: 0f}, 10f)` is the way to
|
||||
create a new circle.
|
||||
|
||||
Enum variants need not have type parameters. This, for example, is
|
||||
|
|
@ -820,7 +820,7 @@ fn point_from_direction(dir: Direction) -> Point {
|
|||
|
||||
## Tuples
|
||||
|
||||
Tuples in Rust behave exactly like records, except that their fields
|
||||
Tuples in Rust behave exactly like structs, except that their fields
|
||||
do not have names (and can thus not be accessed with dot notation).
|
||||
Tuples can have any arity except for 0 or 1 (though you may consider
|
||||
nil, `()`, as the empty tuple if you like).
|
||||
|
|
@ -957,7 +957,7 @@ Rust has three competing goals that inform its view of memory:
|
|||
Most languages that offer strong memory safety guarantees rely upon a
|
||||
garbage-collected heap to manage all of the objects. This approach is
|
||||
straightforward both in concept and in implementation, but has
|
||||
significant costs. Languages that take this approach tend to
|
||||
significant costs. Languages that follow this path tend to
|
||||
aggressively pursue ways to ameliorate allocation costs (think the
|
||||
Java Virtual Machine). Rust supports this strategy with _managed
|
||||
boxes_: memory allocated on the heap whose lifetime is managed
|
||||
|
|
@ -982,7 +982,7 @@ tasks. Experience in other languages has proven that isolating each
|
|||
task's heap from the others is a reliable strategy and one that is
|
||||
easy for programmers to reason about. Heap isolation has the
|
||||
additional benefit that garbage collection must only be done
|
||||
per-heap. Rust never "stops the world" to garbage-collect memory.
|
||||
per-heap. Rust never "stops the world" to reclaim memory.
|
||||
|
||||
Complete isolation of heaps between tasks implies that any data
|
||||
transferred between tasks must be copied. While this is a fine and
|
||||
|
|
@ -995,27 +995,18 @@ _owned boxes_. All tasks may allocate objects on the exchange heap,
|
|||
then transfer ownership of those objects to other tasks, avoiding
|
||||
expensive copies.
|
||||
|
||||
## What to be aware of
|
||||
|
||||
Rust has three "realms" in which objects can be allocated: the stack,
|
||||
the local heap, and the exchange heap. These realms have corresponding
|
||||
pointer types: the borrowed pointer (`&T`), the managed box (`@T`),
|
||||
and the owned box (`~T`). These three sigils will appear
|
||||
repeatedly as we explore the language. Learning the appropriate role
|
||||
of each is key to using Rust effectively.
|
||||
|
||||
# Boxes and pointers
|
||||
|
||||
In contrast to a lot of modern languages, aggregate types like records
|
||||
In contrast to a lot of modern languages, aggregate types like structs
|
||||
and enums are _not_ represented as pointers to allocated memory in
|
||||
Rust. They are, as in C and C++, represented directly. This means that
|
||||
if you `let x = {x: 1f, y: 1f};`, you are creating a record on the
|
||||
stack. If you then copy it into a data structure, the whole record is
|
||||
if you `let x = Point {x: 1f, y: 1f};`, you are creating a struct on the
|
||||
stack. If you then copy it into a data structure, the whole struct is
|
||||
copied, not just a pointer.
|
||||
|
||||
For small records like `point`, this is usually more efficient than
|
||||
allocating memory and going through a pointer. But for big records, or
|
||||
records with mutable fields, it can be useful to have a single copy on
|
||||
For small structs like `Point`, this is usually more efficient than
|
||||
allocating memory and going through a pointer. But for big structs, or
|
||||
those with mutable fields, it can be useful to have a single copy on
|
||||
the heap, and refer to that through a pointer.
|
||||
|
||||
Rust supports several types of pointers. The safe pointer types are
|
||||
|
|
@ -1191,8 +1182,8 @@ compute_distance(shared_box, unique_box);
|
|||
~~~
|
||||
|
||||
Here the `&` operator is used to take the address of the variable
|
||||
`on_the_stack`; this is because `on_the_stack` has the type `point`
|
||||
(that is, a record value) and we have to take its address to get a
|
||||
`on_the_stack`; this is because `on_the_stack` has the type `Point`
|
||||
(that is, a struct value) and we have to take its address to get a
|
||||
value. We also call this _borrowing_ the local variable
|
||||
`on_the_stack`, because we are created an alias: that is, another
|
||||
route to the same data.
|
||||
|
|
@ -1517,7 +1508,7 @@ fn each(v: &[int], op: fn(v: &int)) {
|
|||
The reason we pass in a *pointer* to an integer rather than the
|
||||
integer itself is that this is how the actual `each()` function for
|
||||
vectors works. Using a pointer means that the function can be used
|
||||
for vectors of any type, even large records that would be impractical
|
||||
for vectors of any type, even large structs that would be impractical
|
||||
to copy out of the vector on each iteration. As a caller, if we use a
|
||||
closure to provide the final operator argument, we can write it in a
|
||||
way that has a pleasant, block-like structure.
|
||||
|
|
@ -1576,7 +1567,7 @@ Empty argument lists can be omitted from `do` expressions.
|
|||
|
||||
Most iteration in Rust is done with `for` loops. Like `do`,
|
||||
`for` is a nice syntax for doing control flow with closures.
|
||||
Additionally, within a `for` loop, `break`, `again`, and `return`
|
||||
Additionally, within a `for` loop, `break`, `loop`, and `return`
|
||||
work just as they do with `while` and `loop`.
|
||||
|
||||
Consider again our `each` function, this time improved to
|
||||
|
|
@ -1611,7 +1602,7 @@ With `for`, functions like `each` can be treated more
|
|||
like builtin looping structures. When calling `each`
|
||||
in a `for` loop, instead of returning `false` to break
|
||||
out of the loop, you just write `break`. To skip ahead
|
||||
to the next iteration, write `again`.
|
||||
to the next iteration, write `loop`.
|
||||
|
||||
~~~~
|
||||
# use each = vec::each;
|
||||
|
|
@ -1644,14 +1635,15 @@ fn contains(v: &[int], elt: int) -> bool {
|
|||
# Generics
|
||||
|
||||
Throughout this tutorial, we've been defining functions that act only on
|
||||
single data types. With type parameters we can also define functions that
|
||||
may be invoked on multiple types.
|
||||
specific data types. With type parameters we can also define functions whose
|
||||
arguments represent generic types, and which can be invoked with a variety
|
||||
of types. Consider a generic `map` function.
|
||||
|
||||
~~~~
|
||||
fn map<T, U>(vector: &[T], function: fn(v: &T) -> U) -> ~[U] {
|
||||
let mut accumulator = ~[];
|
||||
for vec::each(vector) |element| {
|
||||
vec::push(accumulator, function(element));
|
||||
accumulator.push(function(element));
|
||||
}
|
||||
return accumulator;
|
||||
}
|
||||
|
|
@ -1665,7 +1657,7 @@ each other.
|
|||
Inside a generic function, the names of the type parameters
|
||||
(capitalized by convention) stand for opaque types. You can't look
|
||||
inside them, but you can pass them around. Note that instances of
|
||||
generic types are almost always passed by pointer. For example, the
|
||||
generic types are often passed by pointer. For example, the
|
||||
parameter `function()` is supplied with a pointer to a value of type
|
||||
`T` and not a value of type `T` itself. This ensures that the
|
||||
function works with the broadest set of types possible, since some
|
||||
|
|
@ -1691,11 +1683,11 @@ These declarations produce valid types like `Set<int>`, `Stack<int>`
|
|||
and `Maybe<int>`.
|
||||
|
||||
Generic functions in Rust are compiled to very efficient runtime code
|
||||
through a process called _monomorphisation_. This big word just means
|
||||
that, for each generic function you call, the compiler generates a
|
||||
specialized version that is optimized specifically for the argument
|
||||
types. In this respect Rust's generics have similar performance
|
||||
characteristics to C++ templates.
|
||||
through a process called _monomorphisation_. This is a fancy way of
|
||||
saying that, for each generic function you call, the compiler
|
||||
generates a specialized version that is optimized specifically for the
|
||||
argument types. In this respect Rust's generics have similar
|
||||
performance characteristics to C++ templates.
|
||||
|
||||
## Traits
|
||||
|
||||
|
|
@ -1760,13 +1752,10 @@ types by the compiler, and may not be overridden:
|
|||
|
||||
## Declaring and implementing traits
|
||||
|
||||
A trait consists of a set of methods, or may be empty, as is the case
|
||||
with `Copy`, `Send`, and `Const`. A method is a function that
|
||||
can be applied to a `self` value and a number of arguments, using the
|
||||
dot notation: `self.foo(arg1, arg2)`.
|
||||
|
||||
For example, we could declare the trait `Printable` for things that
|
||||
can be printed to the console, with a single method:
|
||||
A trait consists of a set of methods, without bodies, or may be empty,
|
||||
as is the case with `Copy`, `Send`, and `Const`. For example, we could
|
||||
declare the trait `Printable` for things that can be printed to the
|
||||
console, with a single method:
|
||||
|
||||
~~~~
|
||||
trait Printable {
|
||||
|
|
@ -1774,9 +1763,12 @@ trait Printable {
|
|||
}
|
||||
~~~~
|
||||
|
||||
To actually implement a trait for a given type, the `impl` form is
|
||||
used. This defines implementations of `Printable` for the `int` and
|
||||
`~str` types.
|
||||
Traits may be implemented for specific types with [impls]. An impl
|
||||
that implements a trait includes the name of the trait at the start of
|
||||
the definition, as in the following impls of `Printable` for `int`
|
||||
and `~str`.
|
||||
|
||||
[impls]: #functions-and-methods
|
||||
|
||||
~~~~
|
||||
# trait Printable { fn print(); }
|
||||
|
|
@ -1792,14 +1784,10 @@ impl ~str: Printable {
|
|||
# (~"foo").print();
|
||||
~~~~
|
||||
|
||||
Given these, we may call `1.print()` to print `"1"`, or
|
||||
`(~"foo").print()` to print `"foo"` again, as with . This is basically a form of
|
||||
static overloading—when the Rust compiler sees the `print` method
|
||||
call, it looks for an implementation that matches the type with a
|
||||
method that matches the name, and simply calls that.
|
||||
|
||||
Traits may themselves contain type parameters. A trait for
|
||||
generalized sequence types might look like the following:
|
||||
Methods defined in an implementation of a trait may be called just as
|
||||
any other method, using dot notation, as in `1.print()`. Traits may
|
||||
themselves contain type parameters. A trait for generalized sequence
|
||||
types might look like the following:
|
||||
|
||||
~~~~
|
||||
trait Seq<T> {
|
||||
|
|
|
|||
14
man/rustc.1
14
man/rustc.1
|
|
@ -75,10 +75,7 @@ Write intermediate files (.bc, .opt.bc, .o)
|
|||
in addition to normal output
|
||||
.TP
|
||||
\fB\-\-static\fR
|
||||
Use or produce static libraries or binaries
|
||||
.TP
|
||||
\fB\-\-stats\fR
|
||||
Print compilation statistics
|
||||
Use or produce static libraries or binaries (experimental)
|
||||
.TP
|
||||
\fB\-\-sysroot\fR <path>
|
||||
Override the system root
|
||||
|
|
@ -87,10 +84,9 @@ Override the system root
|
|||
Build a test harness
|
||||
.TP
|
||||
\fB\-\-target\fR <triple>
|
||||
Target cpu\-manufacturer\-kernel[\-os] to compile for
|
||||
(default: host triple)
|
||||
(see http://sources.redhat.com/autobook/autobook/
|
||||
autobook_17.html for detail)
|
||||
Target cpu\-manufacturer\-kernel[\-os] to compile for (default: host triple)
|
||||
(see <\fBhttp://sources.redhat.com/autobook/autobook/autobook_17.html\fR> for
|
||||
detail)
|
||||
.TP
|
||||
\fB\-W\fR <foo>
|
||||
enable warning <foo>
|
||||
|
|
@ -121,7 +117,7 @@ To build either with a crate (.rc) file:
|
|||
$ rustc hello.rc
|
||||
|
||||
.SH "BUGS"
|
||||
See \fBhttps://github.com/mozilla/rust/issues\fR for a list of known bugs.
|
||||
See <\fBhttps://github.com/mozilla/rust/issues\fR> for a list of known bugs.
|
||||
|
||||
.SH "AUTHOR"
|
||||
See \fBAUTHORS.txt\fR in the rust source distribution. Graydon Hoare
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
#[allow(vecs_implicitly_copyable,
|
||||
non_implicitly_copyable_typarams)];
|
||||
#[allow(non_camel_case_types)];
|
||||
#[allow(deprecated_mode)];
|
||||
#[allow(deprecated_pattern)];
|
||||
|
||||
extern mod core(vers = "0.4");
|
||||
extern mod std(vers = "0.4");
|
||||
|
|
|
|||
|
|
@ -11,13 +11,14 @@ use syntax::diagnostic;
|
|||
|
||||
use result::{Ok, Err};
|
||||
use io::WriterUtil;
|
||||
use send_map::linear::LinearMap;
|
||||
use std::{map, json, tempfile, term, sort, getopts};
|
||||
use map::HashMap;
|
||||
use to_str::to_str;
|
||||
use getopts::{optflag, optopt, opt_present};
|
||||
use dvec::DVec;
|
||||
|
||||
type package = {
|
||||
struct Package {
|
||||
name: ~str,
|
||||
uuid: ~str,
|
||||
url: ~str,
|
||||
|
|
@ -26,10 +27,10 @@ type package = {
|
|||
reference: Option<~str>,
|
||||
tags: ~[~str],
|
||||
versions: ~[(~str, ~str)]
|
||||
};
|
||||
}
|
||||
|
||||
impl package : cmp::Ord {
|
||||
pure fn lt(other: &package) -> bool {
|
||||
impl Package : cmp::Ord {
|
||||
pure fn lt(other: &Package) -> bool {
|
||||
if self.name.lt(&(*other).name) { return true; }
|
||||
if (*other).name.lt(&self.name) { return false; }
|
||||
if self.uuid.lt(&(*other).uuid) { return true; }
|
||||
|
|
@ -45,28 +46,21 @@ impl package : cmp::Ord {
|
|||
if self.versions.lt(&(*other).versions) { return true; }
|
||||
return false;
|
||||
}
|
||||
pure fn le(other: &package) -> bool { !(*other).lt(&self) }
|
||||
pure fn ge(other: &package) -> bool { !self.lt(other) }
|
||||
pure fn gt(other: &package) -> bool { (*other).lt(&self) }
|
||||
pure fn le(other: &Package) -> bool { !(*other).lt(&self) }
|
||||
pure fn ge(other: &Package) -> bool { !self.lt(other) }
|
||||
pure fn gt(other: &Package) -> bool { (*other).lt(&self) }
|
||||
}
|
||||
|
||||
type local_package = {
|
||||
name: ~str,
|
||||
metaname: ~str,
|
||||
version: ~str,
|
||||
files: ~[~str]
|
||||
};
|
||||
|
||||
type source = @{
|
||||
struct Source {
|
||||
name: ~str,
|
||||
mut url: ~str,
|
||||
mut method: ~str,
|
||||
mut key: Option<~str>,
|
||||
mut keyfp: Option<~str>,
|
||||
packages: DVec<package>
|
||||
};
|
||||
packages: DVec<Package>
|
||||
}
|
||||
|
||||
type cargo = {
|
||||
struct Cargo {
|
||||
pgp: bool,
|
||||
root: Path,
|
||||
installdir: Path,
|
||||
|
|
@ -74,13 +68,13 @@ type cargo = {
|
|||
libdir: Path,
|
||||
workdir: Path,
|
||||
sourcedir: Path,
|
||||
sources: map::HashMap<~str, source>,
|
||||
sources: map::HashMap<~str, @Source>,
|
||||
mut current_install: ~str,
|
||||
dep_cache: map::HashMap<~str, bool>,
|
||||
opts: options
|
||||
};
|
||||
opts: Options
|
||||
}
|
||||
|
||||
type crate = {
|
||||
struct Crate {
|
||||
name: ~str,
|
||||
vers: ~str,
|
||||
uuid: ~str,
|
||||
|
|
@ -88,22 +82,22 @@ type crate = {
|
|||
sigs: Option<~str>,
|
||||
crate_type: Option<~str>,
|
||||
deps: ~[~str]
|
||||
};
|
||||
}
|
||||
|
||||
type options = {
|
||||
struct Options {
|
||||
test: bool,
|
||||
mode: mode,
|
||||
mode: Mode,
|
||||
free: ~[~str],
|
||||
help: bool,
|
||||
};
|
||||
}
|
||||
|
||||
enum mode { system_mode, user_mode, local_mode }
|
||||
enum Mode { SystemMode, UserMode, LocalMode }
|
||||
|
||||
impl mode : cmp::Eq {
|
||||
pure fn eq(other: &mode) -> bool {
|
||||
impl Mode : cmp::Eq {
|
||||
pure fn eq(other: &Mode) -> bool {
|
||||
(self as uint) == ((*other) as uint)
|
||||
}
|
||||
pure fn ne(other: &mode) -> bool { !self.eq(other) }
|
||||
pure fn ne(other: &Mode) -> bool { !self.eq(other) }
|
||||
}
|
||||
|
||||
fn opts() -> ~[getopts::Opt] {
|
||||
|
|
@ -150,7 +144,7 @@ fn is_uuid(id: ~str) -> bool {
|
|||
if vec::len(parts) == 5u {
|
||||
let mut correct = 0u;
|
||||
for vec::eachi(parts) |i, part| {
|
||||
fn is_hex_digit(ch: char) -> bool {
|
||||
fn is_hex_digit(+ch: char) -> bool {
|
||||
('0' <= ch && ch <= '9') ||
|
||||
('a' <= ch && ch <= 'f') ||
|
||||
('A' <= ch && ch <= 'F')
|
||||
|
|
@ -270,7 +264,7 @@ fn load_link(mis: ~[@ast::meta_item]) -> (Option<~str>,
|
|||
(name, vers, uuid)
|
||||
}
|
||||
|
||||
fn load_crate(filename: &Path) -> Option<crate> {
|
||||
fn load_crate(filename: &Path) -> Option<Crate> {
|
||||
let sess = parse::new_parse_sess(None);
|
||||
let c = parse::parse_crate_from_crate_file(filename, ~[], sess);
|
||||
|
||||
|
|
@ -351,7 +345,7 @@ fn load_crate(filename: &Path) -> Option<crate> {
|
|||
|
||||
match *ps.interner.get(attr_name) {
|
||||
~"std" | ~"core" => (),
|
||||
_ => vec::push(e.deps, query)
|
||||
_ => e.deps.push(query)
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
|
|
@ -375,7 +369,7 @@ fn load_crate(filename: &Path) -> Option<crate> {
|
|||
|
||||
match (name, vers, uuid) {
|
||||
(Some(name0), Some(vers0), Some(uuid0)) => {
|
||||
Some({
|
||||
Some(Crate {
|
||||
name: name0,
|
||||
vers: vers0,
|
||||
uuid: uuid0,
|
||||
|
|
@ -407,8 +401,8 @@ fn need_dir(s: &Path) {
|
|||
}
|
||||
}
|
||||
|
||||
fn valid_pkg_name(s: ~str) -> bool {
|
||||
fn is_valid_digit(c: char) -> bool {
|
||||
fn valid_pkg_name(s: &str) -> bool {
|
||||
fn is_valid_digit(+c: char) -> bool {
|
||||
('0' <= c && c <= '9') ||
|
||||
('a' <= c && c <= 'z') ||
|
||||
('A' <= c && c <= 'Z') ||
|
||||
|
|
@ -419,33 +413,33 @@ fn valid_pkg_name(s: ~str) -> bool {
|
|||
s.all(is_valid_digit)
|
||||
}
|
||||
|
||||
fn parse_source(name: ~str, j: json::Json) -> source {
|
||||
fn parse_source(name: ~str, j: &json::Json) -> @Source {
|
||||
if !valid_pkg_name(name) {
|
||||
fail fmt!("'%s' is an invalid source name", name);
|
||||
}
|
||||
|
||||
match j {
|
||||
json::Dict(j) => {
|
||||
let mut url = match j.find(~"url") {
|
||||
Some(json::String(u)) => *u,
|
||||
match *j {
|
||||
json::Object(j) => {
|
||||
let mut url = match j.find(&~"url") {
|
||||
Some(json::String(u)) => u,
|
||||
_ => fail ~"needed 'url' field in source"
|
||||
};
|
||||
let method = match j.find(~"method") {
|
||||
Some(json::String(u)) => *u,
|
||||
let method = match j.find(&~"method") {
|
||||
Some(json::String(u)) => u,
|
||||
_ => assume_source_method(url)
|
||||
};
|
||||
let key = match j.find(~"key") {
|
||||
Some(json::String(u)) => Some(*u),
|
||||
let key = match j.find(&~"key") {
|
||||
Some(json::String(u)) => Some(u),
|
||||
_ => None
|
||||
};
|
||||
let keyfp = match j.find(~"keyfp") {
|
||||
Some(json::String(u)) => Some(*u),
|
||||
let keyfp = match j.find(&~"keyfp") {
|
||||
Some(json::String(u)) => Some(u),
|
||||
_ => None
|
||||
};
|
||||
if method == ~"file" {
|
||||
url = os::make_absolute(&Path(url)).to_str();
|
||||
}
|
||||
return @{
|
||||
return @Source {
|
||||
name: name,
|
||||
mut url: url,
|
||||
mut method: method,
|
||||
|
|
@ -457,14 +451,14 @@ fn parse_source(name: ~str, j: json::Json) -> source {
|
|||
};
|
||||
}
|
||||
|
||||
fn try_parse_sources(filename: &Path, sources: map::HashMap<~str, source>) {
|
||||
fn try_parse_sources(filename: &Path, sources: map::HashMap<~str, @Source>) {
|
||||
if !os::path_exists(filename) { return; }
|
||||
let c = io::read_whole_file_str(filename);
|
||||
match json::from_str(result::get(c)) {
|
||||
Ok(json::Dict(j)) => {
|
||||
for j.each |k, v| {
|
||||
sources.insert(k, parse_source(k, v));
|
||||
debug!("source: %s", k);
|
||||
match json::from_str(c.get()) {
|
||||
Ok(json::Object(j)) => {
|
||||
for j.each |k, v| {
|
||||
sources.insert(copy *k, parse_source(*k, v));
|
||||
debug!("source: %s", *k);
|
||||
}
|
||||
}
|
||||
Ok(_) => fail ~"malformed sources.json",
|
||||
|
|
@ -472,17 +466,17 @@ fn try_parse_sources(filename: &Path, sources: map::HashMap<~str, source>) {
|
|||
}
|
||||
}
|
||||
|
||||
fn load_one_source_package(src: source, p: map::HashMap<~str, json::Json>) {
|
||||
let name = match p.find(~"name") {
|
||||
fn load_one_source_package(src: @Source, p: &json::Object) {
|
||||
let name = match p.find(&~"name") {
|
||||
Some(json::String(n)) => {
|
||||
if !valid_pkg_name(*n) {
|
||||
if !valid_pkg_name(n) {
|
||||
warn(~"malformed source json: "
|
||||
+ src.name + ~", '" + *n + ~"'"+
|
||||
+ src.name + ~", '" + n + ~"'"+
|
||||
~" is an invalid name (alphanumeric, underscores and" +
|
||||
~" dashes only)");
|
||||
return;
|
||||
}
|
||||
*n
|
||||
n
|
||||
}
|
||||
_ => {
|
||||
warn(~"malformed source json: " + src.name + ~" (missing name)");
|
||||
|
|
@ -490,15 +484,15 @@ fn load_one_source_package(src: source, p: map::HashMap<~str, json::Json>) {
|
|||
}
|
||||
};
|
||||
|
||||
let uuid = match p.find(~"uuid") {
|
||||
let uuid = match p.find(&~"uuid") {
|
||||
Some(json::String(n)) => {
|
||||
if !is_uuid(*n) {
|
||||
if !is_uuid(n) {
|
||||
warn(~"malformed source json: "
|
||||
+ src.name + ~", '" + *n + ~"'"+
|
||||
+ src.name + ~", '" + n + ~"'"+
|
||||
~" is an invalid uuid");
|
||||
return;
|
||||
}
|
||||
*n
|
||||
n
|
||||
}
|
||||
_ => {
|
||||
warn(~"malformed source json: " + src.name + ~" (missing uuid)");
|
||||
|
|
@ -506,16 +500,16 @@ fn load_one_source_package(src: source, p: map::HashMap<~str, json::Json>) {
|
|||
}
|
||||
};
|
||||
|
||||
let url = match p.find(~"url") {
|
||||
Some(json::String(n)) => *n,
|
||||
let url = match p.find(&~"url") {
|
||||
Some(json::String(n)) => n,
|
||||
_ => {
|
||||
warn(~"malformed source json: " + src.name + ~" (missing url)");
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let method = match p.find(~"method") {
|
||||
Some(json::String(n)) => *n,
|
||||
let method = match p.find(&~"method") {
|
||||
Some(json::String(n)) => n,
|
||||
_ => {
|
||||
warn(~"malformed source json: "
|
||||
+ src.name + ~" (missing method)");
|
||||
|
|
@ -523,17 +517,17 @@ fn load_one_source_package(src: source, p: map::HashMap<~str, json::Json>) {
|
|||
}
|
||||
};
|
||||
|
||||
let reference = match p.find(~"ref") {
|
||||
Some(json::String(n)) => Some(*n),
|
||||
let reference = match p.find(&~"ref") {
|
||||
Some(json::String(n)) => Some(n),
|
||||
_ => None
|
||||
};
|
||||
|
||||
let mut tags = ~[];
|
||||
match p.find(~"tags") {
|
||||
match p.find(&~"tags") {
|
||||
Some(json::List(js)) => {
|
||||
for (*js).each |j| {
|
||||
for js.each |j| {
|
||||
match *j {
|
||||
json::String(j) => vec::grow(tags, 1u, *j),
|
||||
json::String(ref j) => tags.grow(1u, j),
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
|
@ -541,8 +535,8 @@ fn load_one_source_package(src: source, p: map::HashMap<~str, json::Json>) {
|
|||
_ => ()
|
||||
}
|
||||
|
||||
let description = match p.find(~"description") {
|
||||
Some(json::String(n)) => *n,
|
||||
let description = match p.find(&~"description") {
|
||||
Some(json::String(n)) => n,
|
||||
_ => {
|
||||
warn(~"malformed source json: " + src.name
|
||||
+ ~" (missing description)");
|
||||
|
|
@ -550,7 +544,7 @@ fn load_one_source_package(src: source, p: map::HashMap<~str, json::Json>) {
|
|||
}
|
||||
};
|
||||
|
||||
let newpkg = {
|
||||
let newpkg = Package {
|
||||
name: name,
|
||||
uuid: uuid,
|
||||
url: url,
|
||||
|
|
@ -574,14 +568,14 @@ fn load_one_source_package(src: source, p: map::HashMap<~str, json::Json>) {
|
|||
log(debug, ~" loaded package: " + src.name + ~"/" + name);
|
||||
}
|
||||
|
||||
fn load_source_info(c: &cargo, src: source) {
|
||||
fn load_source_info(c: &Cargo, src: @Source) {
|
||||
let dir = c.sourcedir.push(src.name);
|
||||
let srcfile = dir.push("source.json");
|
||||
if !os::path_exists(&srcfile) { return; }
|
||||
let srcstr = io::read_whole_file_str(&srcfile);
|
||||
match json::from_str(result::get(srcstr)) {
|
||||
Ok(json::Dict(s)) => {
|
||||
let o = parse_source(src.name, json::Dict(s));
|
||||
match json::from_str(srcstr.get()) {
|
||||
Ok(ref json @ json::Object(_)) => {
|
||||
let o = parse_source(src.name, json);
|
||||
|
||||
src.key = o.key;
|
||||
src.keyfp = o.keyfp;
|
||||
|
|
@ -595,17 +589,17 @@ fn load_source_info(c: &cargo, src: source) {
|
|||
}
|
||||
};
|
||||
}
|
||||
fn load_source_packages(c: &cargo, src: source) {
|
||||
fn load_source_packages(c: &Cargo, src: @Source) {
|
||||
log(debug, ~"loading source: " + src.name);
|
||||
let dir = c.sourcedir.push(src.name);
|
||||
let pkgfile = dir.push("packages.json");
|
||||
if !os::path_exists(&pkgfile) { return; }
|
||||
let pkgstr = io::read_whole_file_str(&pkgfile);
|
||||
match json::from_str(result::get(pkgstr)) {
|
||||
match json::from_str(pkgstr.get()) {
|
||||
Ok(json::List(js)) => {
|
||||
for (*js).each |j| {
|
||||
for js.each |j| {
|
||||
match *j {
|
||||
json::Dict(p) => {
|
||||
json::Object(p) => {
|
||||
load_one_source_package(src, p);
|
||||
}
|
||||
_ => {
|
||||
|
|
@ -625,7 +619,7 @@ fn load_source_packages(c: &cargo, src: source) {
|
|||
};
|
||||
}
|
||||
|
||||
fn build_cargo_options(argv: ~[~str]) -> options {
|
||||
fn build_cargo_options(argv: ~[~str]) -> Options {
|
||||
let matches = match getopts::getopts(argv, opts()) {
|
||||
result::Ok(m) => m,
|
||||
result::Err(f) => {
|
||||
|
|
@ -649,34 +643,34 @@ fn build_cargo_options(argv: ~[~str]) -> options {
|
|||
}
|
||||
|
||||
let mode =
|
||||
if (!is_install && !is_uninstall) || g { user_mode }
|
||||
else if G { system_mode }
|
||||
else { local_mode };
|
||||
if (!is_install && !is_uninstall) || g { UserMode }
|
||||
else if G { SystemMode }
|
||||
else { LocalMode };
|
||||
|
||||
{test: test, mode: mode, free: matches.free, help: help}
|
||||
Options {test: test, mode: mode, free: matches.free, help: help}
|
||||
}
|
||||
|
||||
fn configure(opts: options) -> cargo {
|
||||
fn configure(opts: Options) -> Cargo {
|
||||
let home = match get_cargo_root() {
|
||||
Ok(home) => home,
|
||||
Err(_err) => result::get(get_cargo_sysroot())
|
||||
Err(_err) => get_cargo_sysroot().get()
|
||||
};
|
||||
|
||||
let get_cargo_dir = match opts.mode {
|
||||
system_mode => get_cargo_sysroot,
|
||||
user_mode => get_cargo_root,
|
||||
local_mode => get_cargo_root_nearest
|
||||
SystemMode => get_cargo_sysroot,
|
||||
UserMode => get_cargo_root,
|
||||
LocalMode => get_cargo_root_nearest
|
||||
};
|
||||
|
||||
let p = result::get(get_cargo_dir());
|
||||
let p = get_cargo_dir().get();
|
||||
|
||||
let sources = map::HashMap();
|
||||
let sources = HashMap();
|
||||
try_parse_sources(&home.push("sources.json"), sources);
|
||||
try_parse_sources(&home.push("local-sources.json"), sources);
|
||||
|
||||
let dep_cache = map::HashMap();
|
||||
let dep_cache = HashMap();
|
||||
|
||||
let mut c = {
|
||||
let mut c = Cargo {
|
||||
pgp: pgp::supported(),
|
||||
root: home,
|
||||
installdir: p,
|
||||
|
|
@ -714,10 +708,10 @@ fn configure(opts: options) -> cargo {
|
|||
c
|
||||
}
|
||||
|
||||
fn for_each_package(c: &cargo, b: fn(source, package)) {
|
||||
fn for_each_package(c: &Cargo, b: fn(s: @Source, p: &Package)) {
|
||||
for c.sources.each_value |v| {
|
||||
for v.packages.each |p| {
|
||||
b(v, *p);
|
||||
b(v, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -748,7 +742,7 @@ fn run_in_buildpath(what: &str, path: &Path, subdir: &Path, cf: &Path,
|
|||
Some(buildpath)
|
||||
}
|
||||
|
||||
fn test_one_crate(_c: &cargo, path: &Path, cf: &Path) {
|
||||
fn test_one_crate(_c: &Cargo, path: &Path, cf: &Path) {
|
||||
let buildpath = match run_in_buildpath(~"testing", path,
|
||||
&Path("test"),
|
||||
cf,
|
||||
|
|
@ -759,7 +753,7 @@ fn test_one_crate(_c: &cargo, path: &Path, cf: &Path) {
|
|||
run_programs(&buildpath);
|
||||
}
|
||||
|
||||
fn install_one_crate(c: &cargo, path: &Path, cf: &Path) {
|
||||
fn install_one_crate(c: &Cargo, path: &Path, cf: &Path) {
|
||||
let buildpath = match run_in_buildpath(~"installing", path,
|
||||
&Path("build"),
|
||||
cf, ~[]) {
|
||||
|
|
@ -776,7 +770,7 @@ fn install_one_crate(c: &cargo, path: &Path, cf: &Path) {
|
|||
~"lib")) {
|
||||
debug!(" bin: %s", ct.to_str());
|
||||
install_to_dir(*ct, &c.bindir);
|
||||
if c.opts.mode == system_mode {
|
||||
if c.opts.mode == SystemMode {
|
||||
// FIXME (#2662): Put this file in PATH / symlink it so it can
|
||||
// be used as a generic executable
|
||||
// `cargo install -G rustray` and `rustray file.obj`
|
||||
|
|
@ -800,14 +794,14 @@ fn rustc_sysroot() -> ~str {
|
|||
}
|
||||
}
|
||||
|
||||
fn install_source(c: &cargo, path: &Path) {
|
||||
fn install_source(c: &Cargo, path: &Path) {
|
||||
debug!("source: %s", path.to_str());
|
||||
os::change_dir(path);
|
||||
|
||||
let mut cratefiles = ~[];
|
||||
for os::walk_dir(&Path(".")) |p| {
|
||||
if p.filetype() == Some(~".rc") {
|
||||
vec::push(cratefiles, *p);
|
||||
cratefiles.push(*p);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -839,7 +833,7 @@ fn install_source(c: &cargo, path: &Path) {
|
|||
}
|
||||
}
|
||||
|
||||
fn install_git(c: &cargo, wd: &Path, url: ~str, reference: Option<~str>) {
|
||||
fn install_git(c: &Cargo, wd: &Path, url: ~str, reference: Option<~str>) {
|
||||
run::program_output(~"git", ~[~"clone", url, wd.to_str()]);
|
||||
if reference.is_some() {
|
||||
let r = reference.get();
|
||||
|
|
@ -850,7 +844,7 @@ fn install_git(c: &cargo, wd: &Path, url: ~str, reference: Option<~str>) {
|
|||
install_source(c, wd);
|
||||
}
|
||||
|
||||
fn install_curl(c: &cargo, wd: &Path, url: ~str) {
|
||||
fn install_curl(c: &Cargo, wd: &Path, url: ~str) {
|
||||
let tarpath = wd.push("pkg.tar");
|
||||
let p = run::program_output(~"curl", ~[~"-f", ~"-s", ~"-o",
|
||||
tarpath.to_str(), url]);
|
||||
|
|
@ -863,14 +857,14 @@ fn install_curl(c: &cargo, wd: &Path, url: ~str) {
|
|||
install_source(c, wd);
|
||||
}
|
||||
|
||||
fn install_file(c: &cargo, wd: &Path, path: &Path) {
|
||||
fn install_file(c: &Cargo, wd: &Path, path: &Path) {
|
||||
run::program_output(~"tar", ~[~"-x", ~"--strip-components=1",
|
||||
~"-C", wd.to_str(),
|
||||
~"-f", path.to_str()]);
|
||||
install_source(c, wd);
|
||||
}
|
||||
|
||||
fn install_package(c: &cargo, src: ~str, wd: &Path, pkg: package) {
|
||||
fn install_package(c: &Cargo, src: ~str, wd: &Path, pkg: Package) {
|
||||
let url = copy pkg.url;
|
||||
let method = match pkg.method {
|
||||
~"git" => ~"git",
|
||||
|
|
@ -883,12 +877,12 @@ fn install_package(c: &cargo, src: ~str, wd: &Path, pkg: package) {
|
|||
match method {
|
||||
~"git" => install_git(c, wd, url, copy pkg.reference),
|
||||
~"file" => install_file(c, wd, &Path(url)),
|
||||
~"curl" => install_curl(c, wd, copy url),
|
||||
~"curl" => install_curl(c, wd, url),
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
fn cargo_suggestion(c: &cargo, fallback: fn())
|
||||
fn cargo_suggestion(c: &Cargo, fallback: fn())
|
||||
{
|
||||
if c.sources.size() == 0u {
|
||||
error(~"no sources defined - you may wish to run " +
|
||||
|
|
@ -898,11 +892,11 @@ fn cargo_suggestion(c: &cargo, fallback: fn())
|
|||
fallback();
|
||||
}
|
||||
|
||||
fn install_uuid(c: &cargo, wd: &Path, uuid: ~str) {
|
||||
fn install_uuid(c: &Cargo, wd: &Path, uuid: ~str) {
|
||||
let mut ps = ~[];
|
||||
for_each_package(c, |s, p| {
|
||||
if p.uuid == uuid {
|
||||
vec::grow(ps, 1u, (s.name, copy p));
|
||||
vec::push(&mut ps, (s.name, copy *p));
|
||||
}
|
||||
});
|
||||
if vec::len(ps) == 1u {
|
||||
|
|
@ -922,11 +916,11 @@ fn install_uuid(c: &cargo, wd: &Path, uuid: ~str) {
|
|||
}
|
||||
}
|
||||
|
||||
fn install_named(c: &cargo, wd: &Path, name: ~str) {
|
||||
fn install_named(c: &Cargo, wd: &Path, name: ~str) {
|
||||
let mut ps = ~[];
|
||||
for_each_package(c, |s, p| {
|
||||
if p.name == name {
|
||||
vec::grow(ps, 1u, (s.name, copy p));
|
||||
vec::push(&mut ps, (s.name, copy *p));
|
||||
}
|
||||
});
|
||||
if vec::len(ps) == 1u {
|
||||
|
|
@ -946,7 +940,7 @@ fn install_named(c: &cargo, wd: &Path, name: ~str) {
|
|||
}
|
||||
}
|
||||
|
||||
fn install_uuid_specific(c: &cargo, wd: &Path, src: ~str, uuid: ~str) {
|
||||
fn install_uuid_specific(c: &Cargo, wd: &Path, src: ~str, uuid: ~str) {
|
||||
match c.sources.find(src) {
|
||||
Some(s) => {
|
||||
for s.packages.each |p| {
|
||||
|
|
@ -961,7 +955,7 @@ fn install_uuid_specific(c: &cargo, wd: &Path, src: ~str, uuid: ~str) {
|
|||
error(~"can't find package: " + src + ~"/" + uuid);
|
||||
}
|
||||
|
||||
fn install_named_specific(c: &cargo, wd: &Path, src: ~str, name: ~str) {
|
||||
fn install_named_specific(c: &Cargo, wd: &Path, src: ~str, name: ~str) {
|
||||
match c.sources.find(src) {
|
||||
Some(s) => {
|
||||
for s.packages.each |p| {
|
||||
|
|
@ -976,7 +970,7 @@ fn install_named_specific(c: &cargo, wd: &Path, src: ~str, name: ~str) {
|
|||
error(~"can't find package: " + src + ~"/" + name);
|
||||
}
|
||||
|
||||
fn cmd_uninstall(c: &cargo) {
|
||||
fn cmd_uninstall(c: &Cargo) {
|
||||
if vec::len(c.opts.free) < 3u {
|
||||
cmd_usage();
|
||||
return;
|
||||
|
|
@ -1028,7 +1022,7 @@ fn cmd_uninstall(c: &cargo) {
|
|||
}
|
||||
}
|
||||
|
||||
fn install_query(c: &cargo, wd: &Path, target: ~str) {
|
||||
fn install_query(c: &Cargo, wd: &Path, target: ~str) {
|
||||
match c.dep_cache.find(target) {
|
||||
Some(inst) => {
|
||||
if inst {
|
||||
|
|
@ -1088,7 +1082,7 @@ fn install_query(c: &cargo, wd: &Path, target: ~str) {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_temp_workdir(c: &cargo) -> Path {
|
||||
fn get_temp_workdir(c: &Cargo) -> Path {
|
||||
match tempfile::mkdtemp(&c.workdir, "cargo") {
|
||||
Some(wd) => wd,
|
||||
None => fail fmt!("needed temp dir: %s",
|
||||
|
|
@ -1096,7 +1090,7 @@ fn get_temp_workdir(c: &cargo) -> Path {
|
|||
}
|
||||
}
|
||||
|
||||
fn cmd_install(c: &cargo) unsafe {
|
||||
fn cmd_install(c: &Cargo) unsafe {
|
||||
let wd = get_temp_workdir(c);
|
||||
|
||||
if vec::len(c.opts.free) == 2u {
|
||||
|
|
@ -1120,7 +1114,7 @@ fn cmd_install(c: &cargo) unsafe {
|
|||
install_query(c, &wd, query);
|
||||
}
|
||||
|
||||
fn sync(c: &cargo) {
|
||||
fn sync(c: &Cargo) {
|
||||
for c.sources.each_key |k| {
|
||||
let mut s = c.sources.get(k);
|
||||
sync_one(c, s);
|
||||
|
|
@ -1128,7 +1122,7 @@ fn sync(c: &cargo) {
|
|||
}
|
||||
}
|
||||
|
||||
fn sync_one_file(c: &cargo, dir: &Path, src: source) -> bool {
|
||||
fn sync_one_file(c: &Cargo, dir: &Path, src: @Source) -> bool {
|
||||
let name = src.name;
|
||||
let srcfile = dir.push("source.json.new");
|
||||
let destsrcfile = dir.push("source.json");
|
||||
|
|
@ -1206,7 +1200,7 @@ fn sync_one_file(c: &cargo, dir: &Path, src: source) -> bool {
|
|||
return true;
|
||||
}
|
||||
|
||||
fn sync_one_git(c: &cargo, dir: &Path, src: source) -> bool {
|
||||
fn sync_one_git(c: &Cargo, dir: &Path, src: @Source) -> bool {
|
||||
let name = src.name;
|
||||
let srcfile = dir.push("source.json");
|
||||
let pkgfile = dir.push("packages.json");
|
||||
|
|
@ -1309,7 +1303,7 @@ fn sync_one_git(c: &cargo, dir: &Path, src: source) -> bool {
|
|||
return true;
|
||||
}
|
||||
|
||||
fn sync_one_curl(c: &cargo, dir: &Path, src: source) -> bool {
|
||||
fn sync_one_curl(c: &Cargo, dir: &Path, src: @Source) -> bool {
|
||||
let name = src.name;
|
||||
let srcfile = dir.push("source.json.new");
|
||||
let destsrcfile = dir.push("source.json");
|
||||
|
|
@ -1425,7 +1419,7 @@ fn sync_one_curl(c: &cargo, dir: &Path, src: source) -> bool {
|
|||
return true;
|
||||
}
|
||||
|
||||
fn sync_one(c: &cargo, src: source) {
|
||||
fn sync_one(c: &Cargo, src: @Source) {
|
||||
let name = src.name;
|
||||
let dir = c.sourcedir.push(name);
|
||||
|
||||
|
|
@ -1445,7 +1439,7 @@ fn sync_one(c: &cargo, src: source) {
|
|||
}
|
||||
}
|
||||
|
||||
fn cmd_init(c: &cargo) {
|
||||
fn cmd_init(c: &Cargo) {
|
||||
let srcurl = ~"http://www.rust-lang.org/cargo/sources.json";
|
||||
let sigurl = ~"http://www.rust-lang.org/cargo/sources.json.sig";
|
||||
|
||||
|
|
@ -1484,7 +1478,7 @@ fn cmd_init(c: &cargo) {
|
|||
info(fmt!("initialized .cargo in %s", c.root.to_str()));
|
||||
}
|
||||
|
||||
fn print_pkg(s: source, p: package) {
|
||||
fn print_pkg(s: @Source, p: &Package) {
|
||||
let mut m = s.name + ~"/" + p.name + ~" (" + p.uuid + ~")";
|
||||
if vec::len(p.tags) > 0u {
|
||||
m = m + ~" [" + str::connect(p.tags, ~", ") + ~"]";
|
||||
|
|
@ -1495,7 +1489,7 @@ fn print_pkg(s: source, p: package) {
|
|||
}
|
||||
}
|
||||
|
||||
fn print_source(s: source) {
|
||||
fn print_source(s: @Source) {
|
||||
info(s.name + ~" (" + s.url + ~")");
|
||||
|
||||
let pks = sort::merge_sort(s.packages.get(), sys::shape_lt);
|
||||
|
|
@ -1516,7 +1510,7 @@ fn print_source(s: source) {
|
|||
}));
|
||||
}
|
||||
|
||||
fn cmd_list(c: &cargo) {
|
||||
fn cmd_list(c: &Cargo) {
|
||||
sync(c);
|
||||
|
||||
if vec::len(c.opts.free) >= 3u {
|
||||
|
|
@ -1542,7 +1536,7 @@ fn cmd_list(c: &cargo) {
|
|||
}
|
||||
}
|
||||
|
||||
fn cmd_search(c: &cargo) {
|
||||
fn cmd_search(c: &Cargo) {
|
||||
if vec::len(c.opts.free) < 3u {
|
||||
cmd_usage();
|
||||
return;
|
||||
|
|
@ -1575,17 +1569,17 @@ fn install_to_dir(srcfile: &Path, destdir: &Path) {
|
|||
}
|
||||
}
|
||||
|
||||
fn dump_cache(c: &cargo) {
|
||||
fn dump_cache(c: &Cargo) {
|
||||
need_dir(&c.root);
|
||||
|
||||
let out = c.root.push("cache.json");
|
||||
let _root = json::Dict(map::HashMap());
|
||||
let _root = json::Object(~LinearMap());
|
||||
|
||||
if os::path_exists(&out) {
|
||||
copy_warn(&out, &c.root.push("cache.json.old"));
|
||||
}
|
||||
}
|
||||
fn dump_sources(c: &cargo) {
|
||||
fn dump_sources(c: &Cargo) {
|
||||
if c.sources.size() < 1u {
|
||||
return;
|
||||
}
|
||||
|
|
@ -1600,33 +1594,31 @@ fn dump_sources(c: &cargo) {
|
|||
|
||||
match io::buffered_file_writer(&out) {
|
||||
result::Ok(writer) => {
|
||||
let hash = map::HashMap();
|
||||
let root = json::Dict(hash);
|
||||
let mut hash = ~LinearMap();
|
||||
|
||||
for c.sources.each |k, v| {
|
||||
let chash = map::HashMap();
|
||||
let child = json::Dict(chash);
|
||||
for c.sources.each |k, v| {
|
||||
let mut chash = ~LinearMap();
|
||||
|
||||
chash.insert(~"url", json::String(@v.url));
|
||||
chash.insert(~"method", json::String(@v.method));
|
||||
chash.insert(~"url", json::String(v.url));
|
||||
chash.insert(~"method", json::String(v.method));
|
||||
|
||||
match copy v.key {
|
||||
Some(key) => {
|
||||
chash.insert(~"key", json::String(@key));
|
||||
chash.insert(~"key", json::String(copy key));
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
match copy v.keyfp {
|
||||
Some(keyfp) => {
|
||||
chash.insert(~"keyfp", json::String(@keyfp));
|
||||
chash.insert(~"keyfp", json::String(copy keyfp));
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
|
||||
hash.insert(k, child);
|
||||
hash.insert(copy k, json::Object(chash));
|
||||
}
|
||||
|
||||
writer.write_str(json::to_str(root));
|
||||
json::to_writer(writer, &json::Object(hash))
|
||||
}
|
||||
result::Err(e) => {
|
||||
error(fmt!("could not dump sources: %s", e));
|
||||
|
|
@ -1641,7 +1633,7 @@ fn copy_warn(srcfile: &Path, destfile: &Path) {
|
|||
}
|
||||
}
|
||||
|
||||
fn cmd_sources(c: &cargo) {
|
||||
fn cmd_sources(c: &Cargo) {
|
||||
if vec::len(c.opts.free) < 3u {
|
||||
for c.sources.each_value |v| {
|
||||
info(fmt!("%s (%s) via %s",
|
||||
|
|
@ -1677,7 +1669,7 @@ fn cmd_sources(c: &cargo) {
|
|||
if c.sources.contains_key(name) {
|
||||
error(fmt!("source already exists: %s", name));
|
||||
} else {
|
||||
c.sources.insert(name, @{
|
||||
c.sources.insert(name, @Source {
|
||||
name: name,
|
||||
mut url: url,
|
||||
mut method: assume_source_method(url),
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
#[allow(vecs_implicitly_copyable)];
|
||||
#[allow(non_camel_case_types)];
|
||||
#[allow(deprecated_mode)];
|
||||
#[allow(deprecated_pattern)];
|
||||
|
||||
extern mod core(vers = "0.4");
|
||||
extern mod std(vers = "0.4");
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ fn parse_config(args: ~[~str]) -> config {
|
|||
} else { option::None },
|
||||
logfile: option::map(&getopts::opt_maybe_str(matches,
|
||||
~"logfile"),
|
||||
|s| Path(s)),
|
||||
|s| Path(*s)),
|
||||
runtool: getopts::opt_maybe_str(matches, ~"runtool"),
|
||||
rustcflags: getopts::opt_maybe_str(matches, ~"rustcflags"),
|
||||
jit: getopts::opt_present(matches, ~"jit"),
|
||||
|
|
@ -141,7 +141,7 @@ fn make_tests(config: config) -> ~[test::TestDesc] {
|
|||
let file = copy *file;
|
||||
debug!("inspecting file %s", file.to_str());
|
||||
if is_test(config, file) {
|
||||
vec::push(tests, make_test(config, file))
|
||||
tests.push(make_test(config, file))
|
||||
}
|
||||
}
|
||||
return tests;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ type expected_error = { line: uint, kind: ~str, msg: ~str };
|
|||
// Load any test directives embedded in the file
|
||||
fn load_errors(testfile: &Path) -> ~[expected_error] {
|
||||
let mut error_patterns = ~[];
|
||||
let rdr = result::get(io::file_reader(testfile));
|
||||
let rdr = io::file_reader(testfile).get();
|
||||
let mut line_num = 1u;
|
||||
while !rdr.eof() {
|
||||
let ln = rdr.read_line();
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ fn load_props(testfile: &Path) -> test_props {
|
|||
let mut pp_exact = option::None;
|
||||
for iter_header(testfile) |ln| {
|
||||
match parse_error_pattern(ln) {
|
||||
option::Some(ep) => vec::push(error_patterns, ep),
|
||||
option::Some(ep) => error_patterns.push(ep),
|
||||
option::None => ()
|
||||
};
|
||||
|
||||
|
|
@ -41,11 +41,11 @@ fn load_props(testfile: &Path) -> test_props {
|
|||
}
|
||||
|
||||
do parse_aux_build(ln).iter |ab| {
|
||||
vec::push(aux_builds, ab);
|
||||
aux_builds.push(*ab);
|
||||
}
|
||||
|
||||
do parse_exec_env(ln).iter |ee| {
|
||||
vec::push(exec_env, ee);
|
||||
exec_env.push(*ee);
|
||||
}
|
||||
};
|
||||
return {
|
||||
|
|
@ -73,7 +73,7 @@ fn is_test_ignored(config: config, testfile: &Path) -> bool {
|
|||
}
|
||||
|
||||
fn iter_header(testfile: &Path, it: fn(~str) -> bool) -> bool {
|
||||
let rdr = result::get(io::file_reader(testfile));
|
||||
let rdr = io::file_reader(testfile).get();
|
||||
while !rdr.eof() {
|
||||
let ln = rdr.read_line();
|
||||
|
||||
|
|
@ -103,7 +103,7 @@ fn parse_compile_flags(line: ~str) -> Option<~str> {
|
|||
fn parse_exec_env(line: ~str) -> Option<(~str, ~str)> {
|
||||
do parse_name_value_directive(line, ~"exec-env").map |nv| {
|
||||
// nv is either FOO or FOO=BAR
|
||||
let strs = str::splitn_char(nv, '=', 1u);
|
||||
let strs = str::splitn_char(*nv, '=', 1u);
|
||||
match strs.len() {
|
||||
1u => (strs[0], ~""),
|
||||
2u => (strs[0], strs[1]),
|
||||
|
|
|
|||
|
|
@ -14,12 +14,12 @@ fn target_env(lib_path: ~str, prog: ~str) -> ~[(~str,~str)] {
|
|||
let aux_path = prog.slice(0u, prog.len() - 4u) + ~".libaux";
|
||||
|
||||
env = do vec::map(env) |pair| {
|
||||
let (k,v) = pair;
|
||||
let (k,v) = *pair;
|
||||
if k == ~"PATH" { (~"PATH", v + ~";" + lib_path + ~";" + aux_path) }
|
||||
else { (k,v) }
|
||||
};
|
||||
if str::ends_with(prog, ~"rustc.exe") {
|
||||
vec::push(env, (~"RUST_THREADS", ~"1"));
|
||||
env.push((~"RUST_THREADS", ~"1"));
|
||||
}
|
||||
return env;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ fn run_pretty_test(config: config, props: test_props, testfile: &Path) {
|
|||
let rounds =
|
||||
match props.pp_exact { option::Some(_) => 1, option::None => 2 };
|
||||
|
||||
let mut srcs = ~[result::get(io::read_whole_file_str(testfile))];
|
||||
let mut srcs = ~[io::read_whole_file_str(testfile).get()];
|
||||
|
||||
let mut round = 0;
|
||||
while round < rounds {
|
||||
|
|
@ -121,7 +121,7 @@ fn run_pretty_test(config: config, props: test_props, testfile: &Path) {
|
|||
procres);
|
||||
}
|
||||
|
||||
vec::push(srcs, procres.stdout);
|
||||
srcs.push(procres.stdout);
|
||||
round += 1;
|
||||
}
|
||||
|
||||
|
|
@ -129,7 +129,7 @@ fn run_pretty_test(config: config, props: test_props, testfile: &Path) {
|
|||
match props.pp_exact {
|
||||
option::Some(file) => {
|
||||
let filepath = testfile.dir_path().push_rel(&file);
|
||||
result::get(io::read_whole_file_str(&filepath))
|
||||
io::read_whole_file_str(&filepath).get()
|
||||
}
|
||||
option::None => { srcs[vec::len(srcs) - 2u] }
|
||||
};
|
||||
|
|
@ -503,10 +503,7 @@ fn make_run_args(config: config, _props: test_props, testfile: &Path) ->
|
|||
|
||||
fn split_maybe_args(argstr: Option<~str>) -> ~[~str] {
|
||||
fn rm_whitespace(v: ~[~str]) -> ~[~str] {
|
||||
fn flt(&&s: ~str) -> Option<~str> {
|
||||
if !str::is_whitespace(s) { option::Some(s) } else { option::None }
|
||||
}
|
||||
vec::filter_map(v, flt)
|
||||
vec::filter(v, |s| !str::is_whitespace(*s))
|
||||
}
|
||||
|
||||
match argstr {
|
||||
|
|
@ -561,8 +558,8 @@ fn dump_output(config: config, testfile: &Path, out: ~str, err: ~str) {
|
|||
fn dump_output_file(config: config, testfile: &Path,
|
||||
out: ~str, extension: ~str) {
|
||||
let outfile = make_out_name(config, testfile, extension);
|
||||
let writer = result::get(
|
||||
io::file_writer(&outfile, ~[io::Create, io::Truncate]));
|
||||
let writer =
|
||||
io::file_writer(&outfile, ~[io::Create, io::Truncate]).get();
|
||||
writer.write_str(out);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ for t in os.listdir(run_pass):
|
|||
"xfail-fast" in s or
|
||||
"xfail-win32" in s):
|
||||
stage2_tests.append(t)
|
||||
if "main(args: ~[~str])" in s:
|
||||
if "fn main(args:" in s or "fn main(++args:" in s:
|
||||
take_args[t] = True
|
||||
f.close()
|
||||
|
||||
|
|
@ -39,11 +39,13 @@ stage2_tests.sort()
|
|||
c = open("tmp/run_pass_stage2.rc", "w")
|
||||
i = 0
|
||||
c.write("// AUTO-GENERATED FILE: DO NOT EDIT\n")
|
||||
c.write("#[legacy_exports];\n")
|
||||
c.write("#[link(name=\"run_pass_stage2\", vers=\"0.1\")];\n")
|
||||
for t in stage2_tests:
|
||||
p = os.path.join(run_pass, t)
|
||||
p = p.replace("\\", "\\\\")
|
||||
c.write("#[path = \"%s\"]" % p);
|
||||
c.write("#[legacy_exports]");
|
||||
c.write("mod t_%d;\n" % i)
|
||||
i += 1
|
||||
c.close()
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@
|
|||
"let" "log" "loop"
|
||||
"move" "new"
|
||||
"pure" "pub" "priv"
|
||||
"return" "static"
|
||||
"ref" "return" "static"
|
||||
"unchecked" "unsafe"
|
||||
"while"))
|
||||
(puthash word t table))
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ fn test_cycles(r : rand::rng, k: uint, n: uint)
|
|||
|
||||
// Create a graph with no edges
|
||||
range(0u, vlen) {|_i|
|
||||
vec::push(v, empty_pointy());
|
||||
v.push(empty_pointy());
|
||||
}
|
||||
|
||||
// Fill in the graph with random edges, with density k/n
|
||||
|
|
@ -77,7 +77,7 @@ fn test_cycles(r : rand::rng, k: uint, n: uint)
|
|||
// https://github.com/mozilla/rust/issues/1899
|
||||
|
||||
if (likelihood(r, k, n)) { v[i].m = [p(choice(r, v))]; }
|
||||
if (likelihood(r, k, n)) { vec::push(v[i].n, mut p(choice(r, v))); }
|
||||
if (likelihood(r, k, n)) { v[i].n.push(mut p(choice(r, v))); }
|
||||
if (likelihood(r, k, n)) { v[i].o = {x: 0, y: p(choice(r, v))}; }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@
|
|||
|
||||
#[allow(vecs_implicitly_copyable)];
|
||||
#[allow(non_camel_case_types)];
|
||||
#[allow(deprecated_mode)];
|
||||
#[allow(deprecated_pattern)];
|
||||
|
||||
extern mod core(vers = "0.4");
|
||||
extern mod std(vers = "0.4");
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ impl test_mode : cmp::Eq {
|
|||
|
||||
fn write_file(filename: &Path, content: ~str) {
|
||||
result::get(
|
||||
io::file_writer(filename, ~[io::Create, io::Truncate]))
|
||||
&io::file_writer(filename, ~[io::Create, io::Truncate]))
|
||||
.write_str(content);
|
||||
}
|
||||
|
||||
|
|
@ -30,7 +30,7 @@ fn contains(haystack: ~str, needle: ~str) -> bool {
|
|||
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
|
||||
vec::push(*files, *path);
|
||||
files.push(*path);
|
||||
} else if os::path_is_dir(path)
|
||||
&& !contains(path.to_str(), ~"compile-fail")
|
||||
&& !contains(path.to_str(), ~"build") {
|
||||
|
|
@ -124,7 +124,7 @@ fn stash_ty_if(c: fn@(@ast::ty, test_mode)->bool,
|
|||
e: @ast::ty,
|
||||
tm: test_mode) {
|
||||
if c(e, tm) {
|
||||
vec::push(*es,*e);
|
||||
es.push(*e);
|
||||
} else {/* now my indices are wrong :( */ }
|
||||
}
|
||||
|
||||
|
|
@ -221,7 +221,7 @@ fn under(n: uint, it: fn(uint)) {
|
|||
while i < n { it(i); i += 1u; }
|
||||
}
|
||||
|
||||
fn as_str(f: fn@(io::Writer)) -> ~str {
|
||||
fn as_str(f: fn@(+x: io::Writer)) -> ~str {
|
||||
io::with_str_writer(f)
|
||||
}
|
||||
|
||||
|
|
@ -229,7 +229,7 @@ fn check_variants_of_ast(crate: ast::crate, codemap: codemap::codemap,
|
|||
filename: &Path, cx: context) {
|
||||
let stolen = steal(crate, cx.mode);
|
||||
let extra_exprs = vec::filter(common_exprs(),
|
||||
|a| safe_to_use_expr(a, cx.mode) );
|
||||
|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);
|
||||
|
|
@ -243,7 +243,7 @@ fn check_variants_T<T: Copy>(
|
|||
filename: &Path,
|
||||
thing_label: ~str,
|
||||
things: ~[T],
|
||||
stringifier: fn@(@T, syntax::parse::token::ident_interner) -> ~str,
|
||||
stringifier: fn@(@T, @syntax::parse::token::ident_interner) -> ~str,
|
||||
replacer: fn@(ast::crate, uint, T, test_mode) -> ast::crate,
|
||||
cx: context
|
||||
) {
|
||||
|
|
@ -543,7 +543,7 @@ fn check_convergence(files: &[Path]) {
|
|||
error!("pp convergence tests: %u files", vec::len(files));
|
||||
for files.each |file| {
|
||||
if !file_might_not_converge(file) {
|
||||
let s = @result::get(io::read_whole_file_str(file));
|
||||
let s = @result::get(&io::read_whole_file_str(file));
|
||||
if !content_might_not_converge(*s) {
|
||||
error!("pp converge: %s", file.to_str());
|
||||
// Change from 7u to 2u once
|
||||
|
|
@ -563,7 +563,7 @@ fn check_variants(files: &[Path], cx: context) {
|
|||
loop;
|
||||
}
|
||||
|
||||
let s = @result::get(io::read_whole_file_str(file));
|
||||
let s = @result::get(&io::read_whole_file_str(file));
|
||||
if contains(*s, ~"#") {
|
||||
loop; // Macros are confusing
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,11 +55,11 @@ fn vec_edits<T: copy>(v: ~[T], xs: ~[T]) -> ~[~[T]] {
|
|||
|
||||
if Lv != 1u {
|
||||
// When Lv == 1u, this is redundant with omit.
|
||||
vec::push(edits, ~[]);
|
||||
edits.push(~[]);
|
||||
}
|
||||
if Lv >= 3u {
|
||||
// When Lv == 2u, this is redundant with swap.
|
||||
vec::push(edits, vec::reversed(v));
|
||||
edits.push(vec::reversed(v));
|
||||
}
|
||||
ix(0u, 1u, Lv) {|i| edits += ~[vec_omit(v, i)]; }
|
||||
ix(0u, 1u, Lv) {|i| edits += ~[vec_dup(v, i)]; }
|
||||
|
|
@ -69,10 +69,10 @@ fn vec_edits<T: copy>(v: ~[T], xs: ~[T]) -> ~[~[T]] {
|
|||
|
||||
ix(0u, 1u, len(xs)) {|j|
|
||||
ix(0u, 1u, Lv) {|i|
|
||||
vec::push(edits, vec_poke(v, i, xs[j]));
|
||||
edits.push(vec_poke(v, i, xs[j]));
|
||||
}
|
||||
ix(0u, 0u, Lv) {|i|
|
||||
vec::push(edits, vec_insert(v, i, xs[j]));
|
||||
edits.push(vec_insert(v, i, xs[j]));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ fn weighted_vec<T: copy>(v : ~[weighted<T>]) -> ~[T] {
|
|||
for {weight: weight, item: item} in v {
|
||||
let i = 0u;
|
||||
while i < weight {
|
||||
vec::push(r, item);
|
||||
r.push(item);
|
||||
i += 1u;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,11 @@
|
|||
//! Managed vectors
|
||||
|
||||
use ptr::addr_of;
|
||||
// NB: transitionary, de-mode-ing.
|
||||
// tjc: re-forbid deprecated modes after snapshot
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
export init_op;
|
||||
export capacity;
|
||||
export build_sized, build, build_sized_opt;
|
||||
export map;
|
||||
export from_fn, from_elem;
|
||||
export raw;
|
||||
export traits;
|
||||
use cast::transmute;
|
||||
use ptr::addr_of;
|
||||
|
||||
/// Code for dealing with @-vectors. This is pretty incomplete, and
|
||||
/// contains a bunch of duplication from the code for ~-vectors.
|
||||
|
|
@ -29,10 +26,10 @@ extern mod rusti {
|
|||
|
||||
/// Returns the number of elements the vector can hold without reallocating
|
||||
#[inline(always)]
|
||||
pure fn capacity<T>(&&v: @[const T]) -> uint {
|
||||
pub pure fn capacity<T>(v: @[const T]) -> uint {
|
||||
unsafe {
|
||||
let repr: **raw::VecRepr =
|
||||
::cast::reinterpret_cast(&addr_of(v));
|
||||
::cast::reinterpret_cast(&addr_of(&v));
|
||||
(**repr).unboxed.alloc / sys::size_of::<T>()
|
||||
}
|
||||
}
|
||||
|
|
@ -50,12 +47,12 @@ pure fn capacity<T>(&&v: @[const T]) -> uint {
|
|||
* onto the vector being constructed.
|
||||
*/
|
||||
#[inline(always)]
|
||||
pure fn build_sized<A>(size: uint,
|
||||
builder: fn(push: pure fn(+v: A))) -> @[A] {
|
||||
let mut vec = @[];
|
||||
unsafe { raw::reserve(vec, size); }
|
||||
builder(|+x| unsafe { raw::push(vec, move x) });
|
||||
return vec;
|
||||
pub pure fn build_sized<A>(size: uint,
|
||||
builder: &fn(push: pure fn(v: A))) -> @[A] {
|
||||
let mut vec: @[const A] = @[];
|
||||
unsafe { raw::reserve(&mut vec, size); }
|
||||
builder(|+x| unsafe { raw::push(&mut vec, move x) });
|
||||
return unsafe { transmute(vec) };
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -69,7 +66,7 @@ pure fn build_sized<A>(size: uint,
|
|||
* onto the vector being constructed.
|
||||
*/
|
||||
#[inline(always)]
|
||||
pure fn build<A>(builder: fn(push: pure fn(+v: A))) -> @[A] {
|
||||
pub pure fn build<A>(builder: &fn(push: pure fn(v: A))) -> @[A] {
|
||||
build_sized(4, builder)
|
||||
}
|
||||
|
||||
|
|
@ -86,14 +83,14 @@ pure fn build<A>(builder: fn(push: pure fn(+v: A))) -> @[A] {
|
|||
* onto the vector being constructed.
|
||||
*/
|
||||
#[inline(always)]
|
||||
pure fn build_sized_opt<A>(size: Option<uint>,
|
||||
builder: fn(push: pure fn(+v: A))) -> @[A] {
|
||||
pub pure fn build_sized_opt<A>(size: Option<uint>,
|
||||
builder: &fn(push: pure fn(v: A))) -> @[A] {
|
||||
build_sized(size.get_default(4), builder)
|
||||
}
|
||||
|
||||
// Appending
|
||||
#[inline(always)]
|
||||
pure fn append<T: Copy>(lhs: @[T], rhs: &[const T]) -> @[T] {
|
||||
pub pure fn append<T: Copy>(lhs: @[T], rhs: &[const T]) -> @[T] {
|
||||
do build_sized(lhs.len() + rhs.len()) |push| {
|
||||
for vec::each(lhs) |x| { push(*x); }
|
||||
for uint::range(0, rhs.len()) |i| { push(rhs[i]); }
|
||||
|
|
@ -102,10 +99,10 @@ pure fn append<T: Copy>(lhs: @[T], rhs: &[const T]) -> @[T] {
|
|||
|
||||
|
||||
/// Apply a function to each element of a vector and return the results
|
||||
pure fn map<T, U>(v: &[T], f: fn(T) -> U) -> @[U] {
|
||||
pub pure fn map<T, U>(v: &[T], f: &fn(x: &T) -> U) -> @[U] {
|
||||
do build_sized(v.len()) |push| {
|
||||
for vec::each(v) |elem| {
|
||||
push(f(*elem));
|
||||
push(f(elem));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -116,7 +113,7 @@ pure fn map<T, U>(v: &[T], f: fn(T) -> U) -> @[U] {
|
|||
* Creates an immutable vector of size `n_elts` and initializes the elements
|
||||
* to the value returned by the function `op`.
|
||||
*/
|
||||
pure fn from_fn<T>(n_elts: uint, op: iter::InitOp<T>) -> @[T] {
|
||||
pub pure fn from_fn<T>(n_elts: uint, op: iter::InitOp<T>) -> @[T] {
|
||||
do build_sized(n_elts) |push| {
|
||||
let mut i: uint = 0u;
|
||||
while i < n_elts { push(op(i)); i += 1u; }
|
||||
|
|
@ -129,17 +126,17 @@ pure fn from_fn<T>(n_elts: uint, op: iter::InitOp<T>) -> @[T] {
|
|||
* Creates an immutable vector of size `n_elts` and initializes the elements
|
||||
* to the value `t`.
|
||||
*/
|
||||
pure fn from_elem<T: Copy>(n_elts: uint, t: T) -> @[T] {
|
||||
pub pure fn from_elem<T: Copy>(n_elts: uint, t: T) -> @[T] {
|
||||
do build_sized(n_elts) |push| {
|
||||
let mut i: uint = 0u;
|
||||
while i < n_elts { push(t); i += 1u; }
|
||||
while i < n_elts { push(copy t); i += 1u; }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(notest)]
|
||||
mod traits {
|
||||
pub mod traits {
|
||||
#[legacy_exports];
|
||||
impl<T: Copy> @[T] : Add<&[const T],@[T]> {
|
||||
pub impl<T: Copy> @[T] : Add<&[const T],@[T]> {
|
||||
#[inline(always)]
|
||||
pure fn add(rhs: & &[const T]) -> @[T] {
|
||||
append(self, (*rhs))
|
||||
|
|
@ -148,13 +145,12 @@ mod traits {
|
|||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod traits {
|
||||
pub mod traits {
|
||||
#[legacy_exports];}
|
||||
|
||||
mod raw {
|
||||
#[legacy_exports];
|
||||
type VecRepr = vec::raw::VecRepr;
|
||||
type SliceRepr = vec::raw::SliceRepr;
|
||||
pub mod raw {
|
||||
pub type VecRepr = vec::raw::VecRepr;
|
||||
pub type SliceRepr = vec::raw::SliceRepr;
|
||||
|
||||
/**
|
||||
* Sets the length of a vector
|
||||
|
|
@ -164,14 +160,14 @@ mod raw {
|
|||
* the vector is actually the specified size.
|
||||
*/
|
||||
#[inline(always)]
|
||||
unsafe fn set_len<T>(&&v: @[const T], new_len: uint) {
|
||||
let repr: **VecRepr = ::cast::reinterpret_cast(&addr_of(v));
|
||||
pub unsafe fn set_len<T>(v: @[const T], new_len: uint) {
|
||||
let repr: **VecRepr = ::cast::reinterpret_cast(&addr_of(&v));
|
||||
(**repr).unboxed.fill = new_len * sys::size_of::<T>();
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
unsafe fn push<T>(&v: @[const T], +initval: T) {
|
||||
let repr: **VecRepr = ::cast::reinterpret_cast(&addr_of(v));
|
||||
pub unsafe fn push<T>(v: &mut @[const T], initval: T) {
|
||||
let repr: **VecRepr = ::cast::reinterpret_cast(&v);
|
||||
let fill = (**repr).unboxed.fill;
|
||||
if (**repr).unboxed.alloc > fill {
|
||||
push_fast(v, move initval);
|
||||
|
|
@ -182,16 +178,16 @@ mod raw {
|
|||
}
|
||||
// This doesn't bother to make sure we have space.
|
||||
#[inline(always)] // really pretty please
|
||||
unsafe fn push_fast<T>(&v: @[const T], +initval: T) {
|
||||
let repr: **VecRepr = ::cast::reinterpret_cast(&addr_of(v));
|
||||
pub unsafe fn push_fast<T>(v: &mut @[const T], initval: T) {
|
||||
let repr: **VecRepr = ::cast::reinterpret_cast(&v);
|
||||
let fill = (**repr).unboxed.fill;
|
||||
(**repr).unboxed.fill += sys::size_of::<T>();
|
||||
let p = ptr::addr_of((**repr).unboxed.data);
|
||||
let p = addr_of(&((**repr).unboxed.data));
|
||||
let p = ptr::offset(p, fill) as *mut T;
|
||||
rusti::move_val_init(*p, move initval);
|
||||
}
|
||||
|
||||
unsafe fn push_slow<T>(&v: @[const T], +initval: T) {
|
||||
pub unsafe fn push_slow<T>(v: &mut @[const T], initval: T) {
|
||||
reserve_at_least(v, v.len() + 1u);
|
||||
push_fast(v, move initval);
|
||||
}
|
||||
|
|
@ -207,10 +203,10 @@ mod raw {
|
|||
* * v - A vector
|
||||
* * n - The number of elements to reserve space for
|
||||
*/
|
||||
unsafe fn reserve<T>(&v: @[const T], n: uint) {
|
||||
pub unsafe fn reserve<T>(v: &mut @[const T], n: uint) {
|
||||
// Only make the (slow) call into the runtime if we have to
|
||||
if capacity(v) < n {
|
||||
let ptr = addr_of(v) as **VecRepr;
|
||||
if capacity(*v) < n {
|
||||
let ptr: **VecRepr = transmute(copy v);
|
||||
rustrt::vec_reserve_shared_actual(sys::get_type_desc::<T>(),
|
||||
ptr, n as libc::size_t);
|
||||
}
|
||||
|
|
@ -231,14 +227,14 @@ mod raw {
|
|||
* * v - A vector
|
||||
* * n - The number of elements to reserve space for
|
||||
*/
|
||||
unsafe fn reserve_at_least<T>(&v: @[const T], n: uint) {
|
||||
pub unsafe fn reserve_at_least<T>(v: &mut @[const T], n: uint) {
|
||||
reserve(v, uint::next_power_of_two(n));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
pub fn test() {
|
||||
// Some code that could use that, then:
|
||||
fn seq_range(lo: uint, hi: uint) -> @[uint] {
|
||||
do build |push| {
|
||||
|
|
@ -254,7 +250,6 @@ fn test() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn append_test() {
|
||||
pub fn append_test() {
|
||||
assert @[1,2,3] + @[4,5,6] == @[1,2,3,4,5,6];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,43 +8,39 @@
|
|||
|
||||
use cmp::Eq;
|
||||
|
||||
export not, and, or, xor, implies;
|
||||
export eq, ne, is_true, is_false;
|
||||
export from_str, to_str, all_values, to_bit;
|
||||
|
||||
/// Negation / inverse
|
||||
pure fn not(v: bool) -> bool { !v }
|
||||
pub pure fn not(v: bool) -> bool { !v }
|
||||
|
||||
/// Conjunction
|
||||
pure fn and(a: bool, b: bool) -> bool { a && b }
|
||||
pub pure fn and(a: bool, b: bool) -> bool { a && b }
|
||||
|
||||
/// Disjunction
|
||||
pure fn or(a: bool, b: bool) -> bool { a || b }
|
||||
pub pure fn or(a: bool, b: bool) -> bool { a || b }
|
||||
|
||||
/**
|
||||
* Exclusive or
|
||||
*
|
||||
* Identical to `or(and(a, not(b)), and(not(a), b))`
|
||||
*/
|
||||
pure fn xor(a: bool, b: bool) -> bool { (a && !b) || (!a && b) }
|
||||
pub pure fn xor(a: bool, b: bool) -> bool { (a && !b) || (!a && b) }
|
||||
|
||||
/// Implication in the logic, i.e. from `a` follows `b`
|
||||
pure fn implies(a: bool, b: bool) -> bool { !a || b }
|
||||
pub pure fn implies(a: bool, b: bool) -> bool { !a || b }
|
||||
|
||||
/// true if truth values `a` and `b` are indistinguishable in the logic
|
||||
pure fn eq(a: bool, b: bool) -> bool { a == b }
|
||||
pub pure fn eq(a: bool, b: bool) -> bool { a == b }
|
||||
|
||||
/// true if truth values `a` and `b` are distinguishable in the logic
|
||||
pure fn ne(a: bool, b: bool) -> bool { a != b }
|
||||
pub pure fn ne(a: bool, b: bool) -> bool { a != b }
|
||||
|
||||
/// true if `v` represents truth in the logic
|
||||
pure fn is_true(v: bool) -> bool { v }
|
||||
pub pure fn is_true(v: bool) -> bool { v }
|
||||
|
||||
/// true if `v` represents falsehood in the logic
|
||||
pure fn is_false(v: bool) -> bool { !v }
|
||||
pub pure fn is_false(v: bool) -> bool { !v }
|
||||
|
||||
/// Parse logic value from `s`
|
||||
pure fn from_str(s: &str) -> Option<bool> {
|
||||
pub pure fn from_str(s: &str) -> Option<bool> {
|
||||
if s == "true" {
|
||||
Some(true)
|
||||
} else if s == "false" {
|
||||
|
|
@ -55,19 +51,19 @@ pure fn from_str(s: &str) -> Option<bool> {
|
|||
}
|
||||
|
||||
/// Convert `v` into a string
|
||||
pure fn to_str(v: bool) -> ~str { if v { ~"true" } else { ~"false" } }
|
||||
pub pure fn to_str(v: bool) -> ~str { if v { ~"true" } else { ~"false" } }
|
||||
|
||||
/**
|
||||
* Iterates over all truth values by passing them to `blk` in an unspecified
|
||||
* order
|
||||
*/
|
||||
fn all_values(blk: fn(v: bool)) {
|
||||
pub fn all_values(blk: fn(v: bool)) {
|
||||
blk(true);
|
||||
blk(false);
|
||||
}
|
||||
|
||||
/// converts truth value to an 8 bit byte
|
||||
pure fn to_bit(v: bool) -> u8 { if v { 1u8 } else { 0u8 } }
|
||||
pub pure fn to_bit(v: bool) -> u8 { if v { 1u8 } else { 0u8 } }
|
||||
|
||||
impl bool : cmp::Eq {
|
||||
pure fn eq(other: &bool) -> bool { self == (*other) }
|
||||
|
|
@ -75,20 +71,20 @@ impl bool : cmp::Eq {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_bool_from_str() {
|
||||
pub fn test_bool_from_str() {
|
||||
do all_values |v| {
|
||||
assert Some(v) == from_str(bool::to_str(v))
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bool_to_str() {
|
||||
pub fn test_bool_to_str() {
|
||||
assert to_str(false) == ~"false";
|
||||
assert to_str(true) == ~"true";
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bool_to_bit() {
|
||||
pub fn test_bool_to_bit() {
|
||||
do all_values |v| {
|
||||
assert to_bit(v) == if is_true(v) { 1u8 } else { 0u8 };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,28 +7,24 @@
|
|||
use cmp::{Eq, Ord};
|
||||
use intrinsic::TyDesc;
|
||||
|
||||
export ptr_eq, raw;
|
||||
|
||||
mod raw {
|
||||
#[legacy_exports];
|
||||
|
||||
struct BoxHeaderRepr {
|
||||
pub mod raw {
|
||||
pub struct BoxHeaderRepr {
|
||||
ref_count: uint,
|
||||
type_desc: *TyDesc,
|
||||
prev: *BoxRepr,
|
||||
next: *BoxRepr,
|
||||
}
|
||||
|
||||
struct BoxRepr {
|
||||
pub struct BoxRepr {
|
||||
header: BoxHeaderRepr,
|
||||
data: u8
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pure fn ptr_eq<T>(a: @T, b: @T) -> bool {
|
||||
pub pure fn ptr_eq<T>(a: @T, b: @T) -> bool {
|
||||
//! Determine if two shared boxes point to the same object
|
||||
unsafe { ptr::addr_of(*a) == ptr::addr_of(*b) }
|
||||
unsafe { ptr::addr_of(&(*a)) == ptr::addr_of(&(*b)) }
|
||||
}
|
||||
|
||||
impl<T:Eq> @const T : Eq {
|
||||
|
|
|
|||
|
|
@ -1,21 +1,14 @@
|
|||
//! Unsafe operations
|
||||
|
||||
export reinterpret_cast, forget, bump_box_refcount, transmute;
|
||||
export transmute_mut, transmute_immut, transmute_region, transmute_mut_region;
|
||||
export transmute_mut_unsafe, transmute_immut_unsafe;
|
||||
|
||||
export copy_lifetime, copy_lifetime_vec;
|
||||
|
||||
#[abi = "rust-intrinsic"]
|
||||
extern mod rusti {
|
||||
#[legacy_exports];
|
||||
fn forget<T>(-x: T);
|
||||
fn reinterpret_cast<T, U>(e: T) -> U;
|
||||
fn reinterpret_cast<T, U>(&&e: T) -> U;
|
||||
}
|
||||
|
||||
/// Casts the value at `src` to U. The two types must have the same length.
|
||||
#[inline(always)]
|
||||
unsafe fn reinterpret_cast<T, U>(src: &T) -> U {
|
||||
pub unsafe fn reinterpret_cast<T, U>(src: &T) -> U {
|
||||
rusti::reinterpret_cast(*src)
|
||||
}
|
||||
|
||||
|
|
@ -28,7 +21,7 @@ unsafe fn reinterpret_cast<T, U>(src: &T) -> U {
|
|||
* reinterpret_cast on managed pointer types.
|
||||
*/
|
||||
#[inline(always)]
|
||||
unsafe fn forget<T>(-thing: T) { rusti::forget(move thing); }
|
||||
pub unsafe fn forget<T>(thing: T) { rusti::forget(move thing); }
|
||||
|
||||
/**
|
||||
* Force-increment the reference count on a shared box. If used
|
||||
|
|
@ -36,7 +29,7 @@ unsafe fn forget<T>(-thing: T) { rusti::forget(move thing); }
|
|||
* and/or reinterpret_cast when such calls would otherwise scramble a box's
|
||||
* reference count
|
||||
*/
|
||||
unsafe fn bump_box_refcount<T>(+t: @T) { forget(move t); }
|
||||
pub unsafe fn bump_box_refcount<T>(t: @T) { forget(move t); }
|
||||
|
||||
/**
|
||||
* Transform a value of one type into a value of another type.
|
||||
|
|
@ -47,7 +40,7 @@ unsafe fn bump_box_refcount<T>(+t: @T) { forget(move t); }
|
|||
* assert transmute("L") == ~[76u8, 0u8];
|
||||
*/
|
||||
#[inline(always)]
|
||||
unsafe fn transmute<L, G>(-thing: L) -> G {
|
||||
pub unsafe fn transmute<L, G>(thing: L) -> G {
|
||||
let newthing: G = reinterpret_cast(&thing);
|
||||
forget(move thing);
|
||||
move newthing
|
||||
|
|
@ -55,39 +48,45 @@ unsafe fn transmute<L, G>(-thing: L) -> G {
|
|||
|
||||
/// Coerce an immutable reference to be mutable.
|
||||
#[inline(always)]
|
||||
unsafe fn transmute_mut<T>(+ptr: &a/T) -> &a/mut T { transmute(move ptr) }
|
||||
pub unsafe fn transmute_mut<T>(ptr: &a/T) -> &a/mut T { transmute(move ptr) }
|
||||
|
||||
/// Coerce a mutable reference to be immutable.
|
||||
#[inline(always)]
|
||||
unsafe fn transmute_immut<T>(+ptr: &a/mut T) -> &a/T { transmute(move ptr) }
|
||||
pub unsafe fn transmute_immut<T>(ptr: &a/mut T) -> &a/T {
|
||||
transmute(move ptr)
|
||||
}
|
||||
|
||||
/// Coerce a borrowed pointer to have an arbitrary associated region.
|
||||
#[inline(always)]
|
||||
unsafe fn transmute_region<T>(+ptr: &a/T) -> &b/T { transmute(move ptr) }
|
||||
pub unsafe fn transmute_region<T>(ptr: &a/T) -> &b/T { transmute(move ptr) }
|
||||
|
||||
/// Coerce an immutable reference to be mutable.
|
||||
#[inline(always)]
|
||||
unsafe fn transmute_mut_unsafe<T>(+ptr: *const T) -> *mut T { transmute(ptr) }
|
||||
pub unsafe fn transmute_mut_unsafe<T>(ptr: *const T) -> *mut T {
|
||||
transmute(ptr)
|
||||
}
|
||||
|
||||
/// Coerce an immutable reference to be mutable.
|
||||
#[inline(always)]
|
||||
unsafe fn transmute_immut_unsafe<T>(+ptr: *const T) -> *T { transmute(ptr) }
|
||||
pub unsafe fn transmute_immut_unsafe<T>(ptr: *const T) -> *T {
|
||||
transmute(ptr)
|
||||
}
|
||||
|
||||
/// Coerce a borrowed mutable pointer to have an arbitrary associated region.
|
||||
#[inline(always)]
|
||||
unsafe fn transmute_mut_region<T>(+ptr: &a/mut T) -> &b/mut T {
|
||||
pub unsafe fn transmute_mut_region<T>(ptr: &a/mut T) -> &b/mut T {
|
||||
transmute(move ptr)
|
||||
}
|
||||
|
||||
/// Transforms lifetime of the second pointer to match the first.
|
||||
#[inline(always)]
|
||||
unsafe fn copy_lifetime<S,T>(_ptr: &a/S, ptr: &T) -> &a/T {
|
||||
pub unsafe fn copy_lifetime<S,T>(_ptr: &a/S, ptr: &T) -> &a/T {
|
||||
transmute_region(ptr)
|
||||
}
|
||||
|
||||
/// Transforms lifetime of the second pointer to match the first.
|
||||
#[inline(always)]
|
||||
unsafe fn copy_lifetime_vec<S,T>(_ptr: &a/[S], ptr: &T) -> &a/T {
|
||||
pub unsafe fn copy_lifetime_vec<S,T>(_ptr: &a/[S], ptr: &T) -> &a/T {
|
||||
transmute_region(ptr)
|
||||
}
|
||||
|
||||
|
|
@ -97,16 +96,14 @@ unsafe fn copy_lifetime_vec<S,T>(_ptr: &a/[S], ptr: &T) -> &a/T {
|
|||
****************************************************************************/
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[legacy_exports];
|
||||
|
||||
pub mod tests {
|
||||
#[test]
|
||||
fn test_reinterpret_cast() {
|
||||
pub fn test_reinterpret_cast() {
|
||||
assert 1u == unsafe { reinterpret_cast(&1) };
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bump_box_refcount() {
|
||||
pub fn test_bump_box_refcount() {
|
||||
unsafe {
|
||||
let box = @~"box box box"; // refcount 1
|
||||
bump_box_refcount(box); // refcount 2
|
||||
|
|
@ -121,7 +118,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_transmute() {
|
||||
pub fn test_transmute() {
|
||||
unsafe {
|
||||
let x = @1;
|
||||
let x: *int = transmute(x);
|
||||
|
|
@ -131,7 +128,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_transmute2() {
|
||||
pub fn test_transmute2() {
|
||||
unsafe {
|
||||
assert ~[76u8, 0u8] == transmute(~"L");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,24 +39,16 @@ use cmp::Eq;
|
|||
Cn Unassigned a reserved unassigned code point or a noncharacter
|
||||
*/
|
||||
|
||||
export is_alphabetic,
|
||||
is_XID_start, is_XID_continue,
|
||||
is_lowercase, is_uppercase,
|
||||
is_whitespace, is_alphanumeric,
|
||||
is_ascii, is_digit,
|
||||
to_digit, cmp,
|
||||
escape_default, escape_unicode;
|
||||
|
||||
use is_alphabetic = unicode::derived_property::Alphabetic;
|
||||
use is_XID_start = unicode::derived_property::XID_Start;
|
||||
use is_XID_continue = unicode::derived_property::XID_Continue;
|
||||
pub use is_alphabetic = unicode::derived_property::Alphabetic;
|
||||
pub use is_XID_start = unicode::derived_property::XID_Start;
|
||||
pub use is_XID_continue = unicode::derived_property::XID_Continue;
|
||||
|
||||
|
||||
/**
|
||||
* Indicates whether a character is in lower case, defined
|
||||
* in terms of the Unicode General Category 'Ll'
|
||||
*/
|
||||
pure fn is_lowercase(c: char) -> bool {
|
||||
pub pure fn is_lowercase(c: char) -> bool {
|
||||
return unicode::general_category::Ll(c);
|
||||
}
|
||||
|
||||
|
|
@ -64,7 +56,7 @@ pure fn is_lowercase(c: char) -> bool {
|
|||
* Indicates whether a character is in upper case, defined
|
||||
* in terms of the Unicode General Category 'Lu'.
|
||||
*/
|
||||
pure fn is_uppercase(c: char) -> bool {
|
||||
pub pure fn is_uppercase(c: char) -> bool {
|
||||
return unicode::general_category::Lu(c);
|
||||
}
|
||||
|
||||
|
|
@ -73,7 +65,7 @@ pure fn is_uppercase(c: char) -> bool {
|
|||
* terms of the Unicode General Categories 'Zs', 'Zl', 'Zp'
|
||||
* additional 'Cc'-category control codes in the range [0x09, 0x0d]
|
||||
*/
|
||||
pure fn is_whitespace(c: char) -> bool {
|
||||
pub pure fn is_whitespace(c: char) -> bool {
|
||||
return ('\x09' <= c && c <= '\x0d')
|
||||
|| unicode::general_category::Zs(c)
|
||||
|| unicode::general_category::Zl(c)
|
||||
|
|
@ -85,7 +77,7 @@ pure fn is_whitespace(c: char) -> bool {
|
|||
* defined in terms of the Unicode General Categories 'Nd', 'Nl', 'No'
|
||||
* and the Derived Core Property 'Alphabetic'.
|
||||
*/
|
||||
pure fn is_alphanumeric(c: char) -> bool {
|
||||
pub pure fn is_alphanumeric(c: char) -> bool {
|
||||
return unicode::derived_property::Alphabetic(c) ||
|
||||
unicode::general_category::Nd(c) ||
|
||||
unicode::general_category::Nl(c) ||
|
||||
|
|
@ -93,12 +85,12 @@ pure fn is_alphanumeric(c: char) -> bool {
|
|||
}
|
||||
|
||||
/// Indicates whether the character is an ASCII character
|
||||
pure fn is_ascii(c: char) -> bool {
|
||||
pub pure fn is_ascii(c: char) -> bool {
|
||||
c - ('\x7F' & c) == '\x00'
|
||||
}
|
||||
|
||||
/// Indicates whether the character is numeric (Nd, Nl, or No)
|
||||
pure fn is_digit(c: char) -> bool {
|
||||
pub pure fn is_digit(c: char) -> bool {
|
||||
return unicode::general_category::Nd(c) ||
|
||||
unicode::general_category::Nl(c) ||
|
||||
unicode::general_category::No(c);
|
||||
|
|
@ -114,7 +106,7 @@ pure fn is_digit(c: char) -> bool {
|
|||
* 'b' or 'B', 11, etc. Returns none if the char does not
|
||||
* refer to a digit in the given radix.
|
||||
*/
|
||||
pure fn to_digit(c: char, radix: uint) -> Option<uint> {
|
||||
pub pure fn to_digit(c: char, radix: uint) -> Option<uint> {
|
||||
let val = match c {
|
||||
'0' .. '9' => c as uint - ('0' as uint),
|
||||
'a' .. 'z' => c as uint + 10u - ('a' as uint),
|
||||
|
|
@ -134,7 +126,7 @@ pure fn to_digit(c: char, radix: uint) -> Option<uint> {
|
|||
* - chars in [0x100,0xffff] get 4-digit escapes: `\\uNNNN`
|
||||
* - chars above 0x10000 get 8-digit escapes: `\\UNNNNNNNN`
|
||||
*/
|
||||
fn escape_unicode(c: char) -> ~str {
|
||||
pub fn escape_unicode(c: char) -> ~str {
|
||||
let s = u32::to_str(c as u32, 16u);
|
||||
let (c, pad) = (if c <= '\xff' { ('x', 2u) }
|
||||
else if c <= '\uffff' { ('u', 4u) }
|
||||
|
|
@ -159,7 +151,7 @@ fn escape_unicode(c: char) -> ~str {
|
|||
* - Any other chars in the range [0x20,0x7e] are not escaped.
|
||||
* - Any other chars are given hex unicode escapes; see `escape_unicode`.
|
||||
*/
|
||||
fn escape_default(c: char) -> ~str {
|
||||
pub fn escape_default(c: char) -> ~str {
|
||||
match c {
|
||||
'\t' => ~"\\t",
|
||||
'\r' => ~"\\r",
|
||||
|
|
@ -179,7 +171,7 @@ fn escape_default(c: char) -> ~str {
|
|||
*
|
||||
* -1 if a < b, 0 if a == b, +1 if a > b
|
||||
*/
|
||||
pure fn cmp(a: char, b: char) -> int {
|
||||
pub pure fn cmp(a: char, b: char) -> int {
|
||||
return if b > a { -1 }
|
||||
else if b < a { 1 }
|
||||
else { 0 }
|
||||
|
|
|
|||
|
|
@ -10,8 +10,6 @@ use repr::BoxRepr;
|
|||
use sys::TypeDesc;
|
||||
use cast::transmute;
|
||||
|
||||
export annihilate;
|
||||
|
||||
/**
|
||||
* Runtime structures
|
||||
*
|
||||
|
|
|
|||
|
|
@ -3,10 +3,6 @@
|
|||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
// uncomment once #1433 is fixed
|
||||
// FIXME (#1433): export c_float_math_consts;
|
||||
// FIXME (#1433): export c_double_math_consts;
|
||||
|
||||
use libc::c_int;
|
||||
use libc::c_float;
|
||||
use libc::c_double;
|
||||
|
|
@ -193,66 +189,62 @@ pub mod c_double_targ_consts {
|
|||
|
||||
FIXME use these once they can be parsed (see Issue #1433)
|
||||
|
||||
mod c_float_math_consts {
|
||||
#[legacy_exports];
|
||||
const pi: c_float = 0x1.921fb6p+1_f32;
|
||||
const div_1_pi: c_float = 0x1.45f306p-2_f32;
|
||||
const div_2_pi: c_float = 0x1.45f306p-1_f32;
|
||||
const div_pi_2: c_float = 0x1.921fb6p+0_f32;
|
||||
const div_pi_4: c_float = 0x1.921fb6p-1_f32;
|
||||
const div_2_sqrtpi: c_float = 0x1.20dd76p+0_f32;
|
||||
const e: c_float = 0x1.5bf0a8p+1_f32;
|
||||
const log2_e: c_float = 0x1.715476p+0_f32;
|
||||
const log10_e: c_float = 0x1.bcb7b2p-2_f32;
|
||||
const ln_2: c_float = 0x1.62e43p-1_f32;
|
||||
const ln_10: c_float = 0x1.26bb1cp+1_f32;
|
||||
const sqrt2: c_float = 0x1.6a09e6p+0_f32;
|
||||
const div_1_sqrt2: c_float = 0x1.6a09e6p-1_f32;
|
||||
pub mod c_float_math_consts {
|
||||
pub const pi: c_float = 0x1.921fb6p+1_f32;
|
||||
pub const div_1_pi: c_float = 0x1.45f306p-2_f32;
|
||||
pub const div_2_pi: c_float = 0x1.45f306p-1_f32;
|
||||
pub const div_pi_2: c_float = 0x1.921fb6p+0_f32;
|
||||
pub const div_pi_4: c_float = 0x1.921fb6p-1_f32;
|
||||
pub const div_2_sqrtpi: c_float = 0x1.20dd76p+0_f32;
|
||||
pub const e: c_float = 0x1.5bf0a8p+1_f32;
|
||||
pub const log2_e: c_float = 0x1.715476p+0_f32;
|
||||
pub const log10_e: c_float = 0x1.bcb7b2p-2_f32;
|
||||
pub const ln_2: c_float = 0x1.62e43p-1_f32;
|
||||
pub const ln_10: c_float = 0x1.26bb1cp+1_f32;
|
||||
pub const sqrt2: c_float = 0x1.6a09e6p+0_f32;
|
||||
pub const div_1_sqrt2: c_float = 0x1.6a09e6p-1_f32;
|
||||
}
|
||||
|
||||
mod c_double_math_consts {
|
||||
#[legacy_exports];
|
||||
const pi: c_double = 0x1.921fb54442d18p+1_f64;
|
||||
const div_1_pi: c_double = 0x1.45f306dc9c883p-2_f64;
|
||||
const div_2_pi: c_double = 0x1.45f306dc9c883p-1_f64;
|
||||
const div_pi_2: c_double = 0x1.921fb54442d18p+0_f64;
|
||||
const div_pi_4: c_double = 0x1.921fb54442d18p-1_f64;
|
||||
const div_2_sqrtpi: c_double = 0x1.20dd750429b6dp+0_f64;
|
||||
const e: c_double = 0x1.5bf0a8b145769p+1_f64;
|
||||
const log2_e: c_double = 0x1.71547652b82fep+0_f64;
|
||||
const log10_e: c_double = 0x1.bcb7b1526e50ep-2_f64;
|
||||
const ln_2: c_double = 0x1.62e42fefa39efp-1_f64;
|
||||
const ln_10: c_double = 0x1.26bb1bbb55516p+1_f64;
|
||||
const sqrt2: c_double = 0x1.6a09e667f3bcdp+0_f64;
|
||||
const div_1_sqrt2: c_double = 0x1.6a09e667f3bcdp-1_f64;
|
||||
pub mod c_double_math_consts {
|
||||
pub const pi: c_double = 0x1.921fb54442d18p+1_f64;
|
||||
pub const div_1_pi: c_double = 0x1.45f306dc9c883p-2_f64;
|
||||
pub const div_2_pi: c_double = 0x1.45f306dc9c883p-1_f64;
|
||||
pub const div_pi_2: c_double = 0x1.921fb54442d18p+0_f64;
|
||||
pub const div_pi_4: c_double = 0x1.921fb54442d18p-1_f64;
|
||||
pub const div_2_sqrtpi: c_double = 0x1.20dd750429b6dp+0_f64;
|
||||
pub const e: c_double = 0x1.5bf0a8b145769p+1_f64;
|
||||
pub const log2_e: c_double = 0x1.71547652b82fep+0_f64;
|
||||
pub const log10_e: c_double = 0x1.bcb7b1526e50ep-2_f64;
|
||||
pub const ln_2: c_double = 0x1.62e42fefa39efp-1_f64;
|
||||
pub const ln_10: c_double = 0x1.26bb1bbb55516p+1_f64;
|
||||
pub const sqrt2: c_double = 0x1.6a09e667f3bcdp+0_f64;
|
||||
pub const div_1_sqrt2: c_double = 0x1.6a09e667f3bcdp-1_f64;
|
||||
}
|
||||
|
||||
mod c_float_targ_consts {
|
||||
#[legacy_exports];
|
||||
const radix: uint = 2u;
|
||||
const mantissa_digits: uint = 24u;
|
||||
const digits: uint = 6u;
|
||||
const min_exp: int = -125;
|
||||
const max_exp: int = 128;
|
||||
const min_10_exp: int = -37;
|
||||
const max_10_exp: int = 38;
|
||||
const min_value: c_float = 0x1p-126_f32;
|
||||
const max_value: c_float = 0x1.fffffep+127_f32;
|
||||
const epsilon: c_float = 0x1p-23_f32;
|
||||
pub mod c_float_targ_consts {
|
||||
pub const radix: uint = 2u;
|
||||
pub const mantissa_digits: uint = 24u;
|
||||
pub const digits: uint = 6u;
|
||||
pub const min_exp: int = -125;
|
||||
pub const max_exp: int = 128;
|
||||
pub const min_10_exp: int = -37;
|
||||
pub const max_10_exp: int = 38;
|
||||
pub const min_value: c_float = 0x1p-126_f32;
|
||||
pub const max_value: c_float = 0x1.fffffep+127_f32;
|
||||
pub const epsilon: c_float = 0x1p-23_f32;
|
||||
}
|
||||
|
||||
mod c_double_targ_consts {
|
||||
#[legacy_exports];
|
||||
const radix: uint = 2u;
|
||||
const mantissa_digits: uint = 53u;
|
||||
const digits: uint = 15u;
|
||||
const min_exp: int = -1021;
|
||||
const max_exp: int = 1024;
|
||||
const min_10_exp: int = -307;
|
||||
const max_10_exp: int = 308;
|
||||
const min_value: c_double = 0x1p-1022_f64;
|
||||
const max_value: c_double = 0x1.fffffffffffffp+1023_f64;
|
||||
const epsilon: c_double = 0x1p-52_f64;
|
||||
pub mod c_double_targ_consts {
|
||||
pub const radix: uint = 2u;
|
||||
pub const mantissa_digits: uint = 53u;
|
||||
pub const digits: uint = 15u;
|
||||
pub const min_exp: int = -1021;
|
||||
pub const max_exp: int = 1024;
|
||||
pub const min_10_exp: int = -307;
|
||||
pub const max_10_exp: int = 308;
|
||||
pub const min_value: c_double = 0x1p-1022_f64;
|
||||
pub const max_value: c_double = 0x1.fffffffffffffp+1023_f64;
|
||||
pub const epsilon: c_double = 0x1p-52_f64;
|
||||
}
|
||||
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -14,17 +14,14 @@ and `Eq` to overload the `==` and `!=` operators.
|
|||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use nounittest::*;
|
||||
use unittest::*;
|
||||
export Ord;
|
||||
export Eq;
|
||||
pub use nounittest::*;
|
||||
pub use unittest::*;
|
||||
|
||||
/// Interfaces used for comparison.
|
||||
|
||||
// Awful hack to work around duplicate lang items in core test.
|
||||
#[cfg(notest)]
|
||||
mod nounittest {
|
||||
#[legacy_exports];
|
||||
/**
|
||||
* Trait for values that can be compared for a sort-order.
|
||||
*
|
||||
|
|
@ -33,7 +30,7 @@ mod nounittest {
|
|||
* default implementations.
|
||||
*/
|
||||
#[lang="ord"]
|
||||
trait Ord {
|
||||
pub trait Ord {
|
||||
pure fn lt(other: &self) -> bool;
|
||||
pure fn le(other: &self) -> bool;
|
||||
pure fn ge(other: &self) -> bool;
|
||||
|
|
@ -50,7 +47,7 @@ mod nounittest {
|
|||
* a default implementation.
|
||||
*/
|
||||
#[lang="eq"]
|
||||
trait Eq {
|
||||
pub trait Eq {
|
||||
pure fn eq(other: &self) -> bool;
|
||||
pure fn ne(other: &self) -> bool;
|
||||
}
|
||||
|
|
@ -63,14 +60,14 @@ mod nounittest {
|
|||
#[cfg(test)]
|
||||
mod unittest {
|
||||
#[legacy_exports];
|
||||
trait Ord {
|
||||
pub trait Ord {
|
||||
pure fn lt(other: &self) -> bool;
|
||||
pure fn le(other: &self) -> bool;
|
||||
pure fn ge(other: &self) -> bool;
|
||||
pure fn gt(other: &self) -> bool;
|
||||
}
|
||||
|
||||
trait Eq {
|
||||
pub trait Eq {
|
||||
pure fn eq(other: &self) -> bool;
|
||||
pure fn ne(other: &self) -> bool;
|
||||
}
|
||||
|
|
@ -80,27 +77,27 @@ mod unittest {
|
|||
mod unittest {
|
||||
#[legacy_exports];}
|
||||
|
||||
pure fn lt<T: Ord>(v1: &T, v2: &T) -> bool {
|
||||
pub pure fn lt<T: Ord>(v1: &T, v2: &T) -> bool {
|
||||
(*v1).lt(v2)
|
||||
}
|
||||
|
||||
pure fn le<T: Ord Eq>(v1: &T, v2: &T) -> bool {
|
||||
pub pure fn le<T: Ord Eq>(v1: &T, v2: &T) -> bool {
|
||||
(*v1).lt(v2) || (*v1).eq(v2)
|
||||
}
|
||||
|
||||
pure fn eq<T: Eq>(v1: &T, v2: &T) -> bool {
|
||||
pub pure fn eq<T: Eq>(v1: &T, v2: &T) -> bool {
|
||||
(*v1).eq(v2)
|
||||
}
|
||||
|
||||
pure fn ne<T: Eq>(v1: &T, v2: &T) -> bool {
|
||||
pub pure fn ne<T: Eq>(v1: &T, v2: &T) -> bool {
|
||||
(*v1).ne(v2)
|
||||
}
|
||||
|
||||
pure fn ge<T: Ord>(v1: &T, v2: &T) -> bool {
|
||||
pub pure fn ge<T: Ord>(v1: &T, v2: &T) -> bool {
|
||||
(*v1).ge(v2)
|
||||
}
|
||||
|
||||
pure fn gt<T: Ord>(v1: &T, v2: &T) -> bool {
|
||||
pub pure fn gt<T: Ord>(v1: &T, v2: &T) -> bool {
|
||||
(*v1).gt(v2)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,14 +32,13 @@ will once again be the preferred module for intertask communication.
|
|||
|
||||
*/
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
// NB: transitionary, de-mode-ing
|
||||
// tjc: re-forbid deprecated modes after snapshot
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use either::Either;
|
||||
use libc::size_t;
|
||||
|
||||
|
||||
// After snapshot, change p2::addr_of => addr_of
|
||||
|
||||
/**
|
||||
* A communication endpoint that can receive messages
|
||||
|
|
@ -76,7 +75,7 @@ pub fn Port<T: Send>() -> Port<T> {
|
|||
impl<T: Send> Port<T> {
|
||||
|
||||
fn chan() -> Chan<T> { Chan(self) }
|
||||
fn send(+v: T) { self.chan().send(move v) }
|
||||
fn send(v: T) { self.chan().send(move v) }
|
||||
fn recv() -> T { recv(self) }
|
||||
fn peek() -> bool { peek(self) }
|
||||
|
||||
|
|
@ -85,7 +84,7 @@ impl<T: Send> Port<T> {
|
|||
impl<T: Send> Chan<T> {
|
||||
|
||||
fn chan() -> Chan<T> { self }
|
||||
fn send(+v: T) { send(self, move v) }
|
||||
fn send(v: T) { send(self, move v) }
|
||||
fn recv() -> T { recv_chan(self) }
|
||||
fn peek() -> bool { peek_chan(self) }
|
||||
|
||||
|
|
@ -104,7 +103,7 @@ struct PortPtr<T:Send> {
|
|||
// Once the port is detached it's guaranteed not to receive further
|
||||
// messages
|
||||
let yield = 0;
|
||||
let yieldp = ptr::addr_of(yield);
|
||||
let yieldp = ptr::addr_of(&yield);
|
||||
rustrt::rust_port_begin_detach(self.po, yieldp);
|
||||
if yield != 0 {
|
||||
// Need to wait for the port to be detached
|
||||
|
|
@ -167,7 +166,7 @@ fn as_raw_port<T: Send, U>(ch: comm::Chan<T>, f: fn(*rust_port) -> U) -> U {
|
|||
* Constructs a channel. The channel is bound to the port used to
|
||||
* construct it.
|
||||
*/
|
||||
pub fn Chan<T: Send>(p: Port<T>) -> Chan<T> {
|
||||
pub fn Chan<T: Send>(&&p: Port<T>) -> Chan<T> {
|
||||
Chan_(rustrt::get_port_id((**p).po))
|
||||
}
|
||||
|
||||
|
|
@ -175,9 +174,9 @@ pub fn Chan<T: Send>(p: Port<T>) -> Chan<T> {
|
|||
* Sends data over a channel. The sent data is moved into the channel,
|
||||
* whereupon the caller loses access to it.
|
||||
*/
|
||||
pub fn send<T: Send>(ch: Chan<T>, +data: T) {
|
||||
pub fn send<T: Send>(ch: Chan<T>, data: T) {
|
||||
let Chan_(p) = ch;
|
||||
let data_ptr = ptr::addr_of(data) as *();
|
||||
let data_ptr = ptr::addr_of(&data) as *();
|
||||
let res = rustrt::rust_port_id_send(p, data_ptr);
|
||||
if res != 0 unsafe {
|
||||
// Data sent successfully
|
||||
|
|
@ -207,10 +206,10 @@ fn peek_chan<T: Send>(ch: comm::Chan<T>) -> bool {
|
|||
/// Receive on a raw port pointer
|
||||
fn recv_<T: Send>(p: *rust_port) -> T {
|
||||
let yield = 0;
|
||||
let yieldp = ptr::addr_of(yield);
|
||||
let yieldp = ptr::addr_of(&yield);
|
||||
let mut res;
|
||||
res = rusti::init::<T>();
|
||||
rustrt::port_recv(ptr::addr_of(res) as *uint, p, yieldp);
|
||||
rustrt::port_recv(ptr::addr_of(&res) as *uint, p, yieldp);
|
||||
|
||||
if yield != 0 {
|
||||
// Data isn't available yet, so res has not been initialized.
|
||||
|
|
@ -234,12 +233,12 @@ fn peek_(p: *rust_port) -> bool {
|
|||
pub fn select2<A: Send, B: Send>(p_a: Port<A>, p_b: Port<B>)
|
||||
-> Either<A, B> {
|
||||
let ports = ~[(**p_a).po, (**p_b).po];
|
||||
let yield = 0, yieldp = ptr::addr_of(yield);
|
||||
let yield = 0, yieldp = ptr::addr_of(&yield);
|
||||
|
||||
let mut resport: *rust_port;
|
||||
resport = rusti::init::<*rust_port>();
|
||||
do vec::as_imm_buf(ports) |ports, n_ports| {
|
||||
rustrt::rust_port_select(ptr::addr_of(resport), ports,
|
||||
rustrt::rust_port_select(ptr::addr_of(&resport), ports,
|
||||
n_ports as size_t, yieldp);
|
||||
}
|
||||
|
||||
|
|
@ -275,7 +274,6 @@ type port_id = int;
|
|||
|
||||
#[abi = "cdecl"]
|
||||
extern mod rustrt {
|
||||
#[legacy_exports];
|
||||
fn rust_port_id_send(target_port: port_id, data: *()) -> libc::uintptr_t;
|
||||
|
||||
fn new_port(unit_sz: libc::size_t) -> *rust_port;
|
||||
|
|
@ -298,7 +296,6 @@ extern mod rustrt {
|
|||
|
||||
#[abi = "rust-intrinsic"]
|
||||
extern mod rusti {
|
||||
#[legacy_exports];
|
||||
fn init<T>() -> T;
|
||||
}
|
||||
|
||||
|
|
@ -459,7 +456,7 @@ fn test_recv_chan_wrong_task() {
|
|||
let po = Port();
|
||||
let ch = Chan(po);
|
||||
send(ch, ~"flower");
|
||||
assert result::is_err(task::try(||
|
||||
assert result::is_err(&task::try(||
|
||||
recv_chan(ch)
|
||||
))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,10 @@ Implicitly, all crates behave as if they included the following prologue:
|
|||
// Don't link to core. We are core.
|
||||
#[no_core];
|
||||
|
||||
#[legacy_modes];
|
||||
#[legacy_exports];
|
||||
|
||||
#[warn(deprecated_mode)];
|
||||
#[warn(deprecated_pattern)];
|
||||
|
||||
#[warn(vecs_implicitly_copyable)];
|
||||
#[deny(non_camel_case_types)];
|
||||
|
|
@ -85,242 +88,158 @@ export private;
|
|||
/// Operations and constants for `int`
|
||||
#[path = "int-template"]
|
||||
mod int {
|
||||
#[legacy_exports];
|
||||
use inst::{ pow };
|
||||
export pow;
|
||||
pub use inst::{ pow };
|
||||
#[path = "int.rs"]
|
||||
#[legacy_exports]
|
||||
mod inst;
|
||||
}
|
||||
|
||||
/// Operations and constants for `i8`
|
||||
#[path = "int-template"]
|
||||
mod i8 {
|
||||
#[legacy_exports];
|
||||
#[path = "i8.rs"]
|
||||
#[legacy_exports]
|
||||
mod inst;
|
||||
}
|
||||
|
||||
/// Operations and constants for `i16`
|
||||
#[path = "int-template"]
|
||||
mod i16 {
|
||||
#[legacy_exports];
|
||||
#[path = "i16.rs"]
|
||||
#[legacy_exports]
|
||||
mod inst;
|
||||
}
|
||||
|
||||
/// Operations and constants for `i32`
|
||||
#[path = "int-template"]
|
||||
mod i32 {
|
||||
#[legacy_exports];
|
||||
#[path = "i32.rs"]
|
||||
#[legacy_exports]
|
||||
mod inst;
|
||||
}
|
||||
|
||||
/// Operations and constants for `i64`
|
||||
#[path = "int-template"]
|
||||
mod i64 {
|
||||
#[legacy_exports];
|
||||
#[path = "i64.rs"]
|
||||
#[legacy_exports]
|
||||
mod inst;
|
||||
}
|
||||
|
||||
/// Operations and constants for `uint`
|
||||
#[path = "uint-template"]
|
||||
mod uint {
|
||||
#[legacy_exports];
|
||||
use inst::{
|
||||
pub use inst::{
|
||||
div_ceil, div_round, div_floor, iterate,
|
||||
next_power_of_two
|
||||
};
|
||||
export div_ceil, div_round, div_floor, iterate,
|
||||
next_power_of_two;
|
||||
|
||||
#[path = "uint.rs"]
|
||||
#[legacy_exports]
|
||||
mod inst;
|
||||
}
|
||||
|
||||
/// Operations and constants for `u8`
|
||||
#[path = "uint-template"]
|
||||
mod u8 {
|
||||
#[legacy_exports];
|
||||
use inst::is_ascii;
|
||||
export is_ascii;
|
||||
|
||||
pub use inst::is_ascii;
|
||||
#[path = "u8.rs"]
|
||||
#[legacy_exports]
|
||||
mod inst;
|
||||
}
|
||||
|
||||
/// Operations and constants for `u16`
|
||||
#[path = "uint-template"]
|
||||
mod u16 {
|
||||
#[legacy_exports];
|
||||
#[path = "u16.rs"]
|
||||
#[legacy_exports]
|
||||
mod inst;
|
||||
}
|
||||
|
||||
/// Operations and constants for `u32`
|
||||
#[path = "uint-template"]
|
||||
mod u32 {
|
||||
#[legacy_exports];
|
||||
#[path = "u32.rs"]
|
||||
#[legacy_exports]
|
||||
mod inst;
|
||||
}
|
||||
|
||||
/// Operations and constants for `u64`
|
||||
#[path = "uint-template"]
|
||||
mod u64 {
|
||||
#[legacy_exports];
|
||||
#[path = "u64.rs"]
|
||||
#[legacy_exports]
|
||||
mod inst;
|
||||
}
|
||||
|
||||
|
||||
#[legacy_exports]
|
||||
mod box;
|
||||
#[legacy_exports]
|
||||
mod char;
|
||||
#[legacy_exports]
|
||||
mod float;
|
||||
#[legacy_exports]
|
||||
mod f32;
|
||||
#[legacy_exports]
|
||||
mod f64;
|
||||
#[legacy_exports]
|
||||
mod str;
|
||||
#[legacy_exports]
|
||||
mod ptr;
|
||||
#[legacy_exports]
|
||||
mod vec;
|
||||
#[legacy_exports]
|
||||
mod at_vec;
|
||||
#[legacy_exports]
|
||||
mod bool;
|
||||
#[legacy_exports]
|
||||
mod tuple;
|
||||
#[legacy_exports]
|
||||
mod unit;
|
||||
#[legacy_exports]
|
||||
mod uniq;
|
||||
|
||||
// Ubiquitous-utility-type modules
|
||||
|
||||
#[cfg(notest)]
|
||||
#[legacy_exports]
|
||||
mod ops;
|
||||
#[legacy_exports]
|
||||
mod cmp;
|
||||
#[legacy_exports]
|
||||
mod num;
|
||||
#[legacy_exports]
|
||||
mod hash;
|
||||
#[legacy_exports]
|
||||
mod either;
|
||||
#[legacy_exports]
|
||||
mod iter;
|
||||
#[legacy_exports]
|
||||
mod logging;
|
||||
#[legacy_exports]
|
||||
mod option;
|
||||
#[path="iter-trait"]
|
||||
mod option_iter {
|
||||
#[legacy_exports];
|
||||
#[path = "option.rs"]
|
||||
#[legacy_exports]
|
||||
mod inst;
|
||||
}
|
||||
#[legacy_exports]
|
||||
mod result;
|
||||
#[legacy_exports]
|
||||
mod to_str;
|
||||
#[legacy_exports]
|
||||
mod to_bytes;
|
||||
#[legacy_exports]
|
||||
mod from_str;
|
||||
#[legacy_exports]
|
||||
mod util;
|
||||
|
||||
// Data structure modules
|
||||
|
||||
#[legacy_exports]
|
||||
mod dvec;
|
||||
#[path="iter-trait"]
|
||||
mod dvec_iter {
|
||||
#[legacy_exports];
|
||||
#[path = "dvec.rs"]
|
||||
#[legacy_exports]
|
||||
mod inst;
|
||||
}
|
||||
#[legacy_exports]
|
||||
mod dlist;
|
||||
#[path="iter-trait"]
|
||||
mod dlist_iter {
|
||||
#[legacy_exports];
|
||||
#[path ="dlist.rs"]
|
||||
#[legacy_exports]
|
||||
mod inst;
|
||||
}
|
||||
#[legacy_exports]
|
||||
mod send_map;
|
||||
|
||||
// Concurrency
|
||||
#[legacy_exports]
|
||||
mod comm;
|
||||
#[legacy_exports]
|
||||
mod task {
|
||||
#[legacy_exports];
|
||||
#[legacy_exports]
|
||||
mod local_data;
|
||||
#[legacy_exports]
|
||||
pub mod local_data;
|
||||
mod local_data_priv;
|
||||
#[legacy_exports]
|
||||
mod spawn;
|
||||
#[legacy_exports]
|
||||
mod rt;
|
||||
pub mod spawn;
|
||||
pub mod rt;
|
||||
}
|
||||
#[legacy_exports]
|
||||
mod future;
|
||||
#[legacy_exports]
|
||||
mod pipes;
|
||||
|
||||
// Runtime and language-primitive support
|
||||
|
||||
#[legacy_exports]
|
||||
mod gc;
|
||||
#[legacy_exports]
|
||||
mod io;
|
||||
#[legacy_exports]
|
||||
mod libc;
|
||||
#[legacy_exports]
|
||||
mod os;
|
||||
#[legacy_exports]
|
||||
mod path;
|
||||
#[legacy_exports]
|
||||
mod rand;
|
||||
#[legacy_exports]
|
||||
mod run;
|
||||
#[legacy_exports]
|
||||
mod sys;
|
||||
#[legacy_exports]
|
||||
mod cast;
|
||||
#[legacy_exports]
|
||||
mod mutable;
|
||||
#[legacy_exports]
|
||||
mod flate;
|
||||
#[legacy_exports]
|
||||
mod repr;
|
||||
#[legacy_exports]
|
||||
mod cleanup;
|
||||
#[legacy_exports]
|
||||
mod reflect;
|
||||
|
||||
// Modules supporting compiler-generated code
|
||||
|
|
@ -336,9 +255,7 @@ mod rt;
|
|||
|
||||
// For internal use, not exported
|
||||
|
||||
#[legacy_exports]
|
||||
mod unicode;
|
||||
#[legacy_exports]
|
||||
mod private;
|
||||
mod cmath;
|
||||
mod stackwalk;
|
||||
|
|
|
|||
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
// Export various ubiquitous types, constructors, methods.
|
||||
|
||||
#[legacy_exports];
|
||||
|
||||
use option::{Some, None};
|
||||
use Option = option::Option;
|
||||
use result::{Result, Ok, Err};
|
||||
|
|
@ -17,6 +15,7 @@ use tuple::{TupleOps, ExtendedTupleOps};
|
|||
use str::{StrSlice, UniqueStr};
|
||||
use vec::{ConstVector, CopyableVector, ImmutableVector};
|
||||
use vec::{ImmutableEqVector, ImmutableCopyableVector};
|
||||
use vec::{MutableVector, MutableCopyableVector};
|
||||
use iter::{BaseIter, ExtendedIter, EqIter, CopyableIter};
|
||||
use iter::{CopyableOrderedIter, Times, TimesIx};
|
||||
use num::Num;
|
||||
|
|
@ -33,6 +32,7 @@ export Num, Times, TimesIx;
|
|||
export StrSlice, UniqueStr;
|
||||
export ConstVector, CopyableVector, ImmutableVector;
|
||||
export ImmutableEqVector, ImmutableCopyableVector, IterTraitExtensions;
|
||||
export MutableVector, MutableCopyableVector;
|
||||
export BaseIter, CopyableIter, CopyableOrderedIter, ExtendedIter, EqIter;
|
||||
export TupleOps, ExtendedTupleOps;
|
||||
export Ptr;
|
||||
|
|
|
|||
|
|
@ -9,12 +9,9 @@ Do not use ==, !=, <, etc on doubly-linked lists -- it may not terminate.
|
|||
*/
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
// tjc: re-forbid deprecated modes after snapshot
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
export DList;
|
||||
export new_dlist, from_elem, from_vec, extensions;
|
||||
|
||||
type DListLink<T> = Option<DListNode<T>>;
|
||||
|
||||
enum DListNode<T> = @{
|
||||
|
|
@ -24,7 +21,7 @@ enum DListNode<T> = @{
|
|||
mut next: DListLink<T>
|
||||
};
|
||||
|
||||
enum DList<T> {
|
||||
pub enum DList<T> {
|
||||
DList_(@{
|
||||
mut size: uint,
|
||||
mut hd: DListLink<T>,
|
||||
|
|
@ -83,7 +80,7 @@ impl<T> DListNode<T> {
|
|||
}
|
||||
|
||||
/// Creates a new dlist node with the given data.
|
||||
pure fn new_dlist_node<T>(+data: T) -> DListNode<T> {
|
||||
pure fn new_dlist_node<T>(data: T) -> DListNode<T> {
|
||||
DListNode(@{data: move data, mut linked: false,
|
||||
mut prev: None, mut next: None})
|
||||
}
|
||||
|
|
@ -94,15 +91,15 @@ pure fn DList<T>() -> DList<T> {
|
|||
}
|
||||
|
||||
/// Creates a new dlist with a single element
|
||||
pure fn from_elem<T>(+data: T) -> DList<T> {
|
||||
pub pure fn from_elem<T>(data: T) -> DList<T> {
|
||||
let list = DList();
|
||||
unsafe { list.push(move data); }
|
||||
list
|
||||
}
|
||||
|
||||
fn from_vec<T: Copy>(+vec: &[T]) -> DList<T> {
|
||||
pub fn from_vec<T: Copy>(vec: &[T]) -> DList<T> {
|
||||
do vec::foldl(DList(), vec) |list,data| {
|
||||
list.push(data); // Iterating left-to-right -- add newly to the tail.
|
||||
list.push(*data); // Iterating left-to-right -- add newly to the tail.
|
||||
list
|
||||
}
|
||||
}
|
||||
|
|
@ -118,7 +115,7 @@ fn concat<T>(lists: DList<DList<T>>) -> DList<T> {
|
|||
}
|
||||
|
||||
priv impl<T> DList<T> {
|
||||
pure fn new_link(-data: T) -> DListLink<T> {
|
||||
pure fn new_link(data: T) -> DListLink<T> {
|
||||
Some(DListNode(@{data: move data, mut linked: true,
|
||||
mut prev: None, mut next: None}))
|
||||
}
|
||||
|
|
@ -145,7 +142,7 @@ priv impl<T> DList<T> {
|
|||
// Link two nodes together. If either of them are 'none', also sets
|
||||
// the head and/or tail pointers appropriately.
|
||||
#[inline(always)]
|
||||
fn link(+before: DListLink<T>, +after: DListLink<T>) {
|
||||
fn link(before: DListLink<T>, after: DListLink<T>) {
|
||||
match before {
|
||||
Some(neighbour) => neighbour.next = after,
|
||||
None => self.hd = after
|
||||
|
|
@ -166,12 +163,12 @@ priv impl<T> DList<T> {
|
|||
self.size -= 1;
|
||||
}
|
||||
|
||||
fn add_head(+nobe: DListLink<T>) {
|
||||
fn add_head(nobe: DListLink<T>) {
|
||||
self.link(nobe, self.hd); // Might set tail too.
|
||||
self.hd = nobe;
|
||||
self.size += 1;
|
||||
}
|
||||
fn add_tail(+nobe: DListLink<T>) {
|
||||
fn add_tail(nobe: DListLink<T>) {
|
||||
self.link(self.tl, nobe); // Might set head too.
|
||||
self.tl = nobe;
|
||||
self.size += 1;
|
||||
|
|
@ -201,27 +198,27 @@ impl<T> DList<T> {
|
|||
pure fn is_not_empty() -> bool { self.len() != 0 }
|
||||
|
||||
/// Add data to the head of the list. O(1).
|
||||
fn push_head(+data: T) {
|
||||
fn push_head(data: T) {
|
||||
self.add_head(self.new_link(move data));
|
||||
}
|
||||
/**
|
||||
* Add data to the head of the list, and get the new containing
|
||||
* node. O(1).
|
||||
*/
|
||||
fn push_head_n(+data: T) -> DListNode<T> {
|
||||
fn push_head_n(data: T) -> DListNode<T> {
|
||||
let mut nobe = self.new_link(move data);
|
||||
self.add_head(nobe);
|
||||
option::get(&nobe)
|
||||
}
|
||||
/// Add data to the tail of the list. O(1).
|
||||
fn push(+data: T) {
|
||||
fn push(data: T) {
|
||||
self.add_tail(self.new_link(move data));
|
||||
}
|
||||
/**
|
||||
* Add data to the tail of the list, and get the new containing
|
||||
* node. O(1).
|
||||
*/
|
||||
fn push_n(+data: T) -> DListNode<T> {
|
||||
fn push_n(data: T) -> DListNode<T> {
|
||||
let mut nobe = self.new_link(move data);
|
||||
self.add_tail(nobe);
|
||||
option::get(&nobe)
|
||||
|
|
@ -230,7 +227,7 @@ impl<T> DList<T> {
|
|||
* Insert data into the middle of the list, left of the given node.
|
||||
* O(1).
|
||||
*/
|
||||
fn insert_before(+data: T, neighbour: DListNode<T>) {
|
||||
fn insert_before(data: T, neighbour: DListNode<T>) {
|
||||
self.insert_left(self.new_link(move data), neighbour);
|
||||
}
|
||||
/**
|
||||
|
|
@ -245,7 +242,7 @@ impl<T> DList<T> {
|
|||
* Insert data in the middle of the list, left of the given node,
|
||||
* and get its containing node. O(1).
|
||||
*/
|
||||
fn insert_before_n(+data: T, neighbour: DListNode<T>) -> DListNode<T> {
|
||||
fn insert_before_n(data: T, neighbour: DListNode<T>) -> DListNode<T> {
|
||||
let mut nobe = self.new_link(move data);
|
||||
self.insert_left(nobe, neighbour);
|
||||
option::get(&nobe)
|
||||
|
|
@ -254,7 +251,7 @@ impl<T> DList<T> {
|
|||
* Insert data into the middle of the list, right of the given node.
|
||||
* O(1).
|
||||
*/
|
||||
fn insert_after(+data: T, neighbour: DListNode<T>) {
|
||||
fn insert_after(data: T, neighbour: DListNode<T>) {
|
||||
self.insert_right(neighbour, self.new_link(move data));
|
||||
}
|
||||
/**
|
||||
|
|
@ -269,7 +266,7 @@ impl<T> DList<T> {
|
|||
* Insert data in the middle of the list, right of the given node,
|
||||
* and get its containing node. O(1).
|
||||
*/
|
||||
fn insert_after_n(+data: T, neighbour: DListNode<T>) -> DListNode<T> {
|
||||
fn insert_after_n(data: T, neighbour: DListNode<T>) -> DListNode<T> {
|
||||
let mut nobe = self.new_link(move data);
|
||||
self.insert_right(neighbour, nobe);
|
||||
option::get(&nobe)
|
||||
|
|
@ -278,13 +275,13 @@ impl<T> DList<T> {
|
|||
/// Remove a node from the head of the list. O(1).
|
||||
fn pop_n() -> Option<DListNode<T>> {
|
||||
let hd = self.peek_n();
|
||||
hd.map(|nobe| self.unlink(nobe));
|
||||
hd.map(|nobe| self.unlink(*nobe));
|
||||
hd
|
||||
}
|
||||
/// Remove a node from the tail of the list. O(1).
|
||||
fn pop_tail_n() -> Option<DListNode<T>> {
|
||||
let tl = self.peek_tail_n();
|
||||
tl.map(|nobe| self.unlink(nobe));
|
||||
tl.map(|nobe| self.unlink(*nobe));
|
||||
tl
|
||||
}
|
||||
/// Get the node at the list's head. O(1).
|
||||
|
|
@ -678,7 +675,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_dlist_foldl() {
|
||||
let l = from_vec(vec::from_fn(101, |x|x));
|
||||
assert iter::foldl(l, 0, |accum,elem| accum+elem) == 5050;
|
||||
assert iter::foldl(&l, 0, |accum,elem| *accum+*elem) == 5050;
|
||||
}
|
||||
#[test]
|
||||
fn test_dlist_break_early() {
|
||||
|
|
|
|||
|
|
@ -10,18 +10,12 @@ Note that recursive use is not permitted.
|
|||
*/
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
// tjc: re-forbid deprecated modes after snapshot
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use cast::reinterpret_cast;
|
||||
use ptr::null;
|
||||
|
||||
export DVec;
|
||||
export from_elem;
|
||||
export from_vec;
|
||||
export extensions;
|
||||
export unwrap;
|
||||
|
||||
/**
|
||||
* A growable, modifiable vector type that accumulates elements into a
|
||||
* unique vector.
|
||||
|
|
@ -57,27 +51,27 @@ type DVec_<A> = {
|
|||
mut data: ~[A]
|
||||
};
|
||||
|
||||
enum DVec<A> {
|
||||
pub enum DVec<A> {
|
||||
DVec_(DVec_<A>)
|
||||
}
|
||||
|
||||
/// Creates a new, empty dvec
|
||||
fn DVec<A>() -> DVec<A> {
|
||||
pub fn DVec<A>() -> DVec<A> {
|
||||
DVec_({mut data: ~[]})
|
||||
}
|
||||
|
||||
/// Creates a new dvec with a single element
|
||||
fn from_elem<A>(+e: A) -> DVec<A> {
|
||||
pub fn from_elem<A>(e: A) -> DVec<A> {
|
||||
DVec_({mut data: ~[move e]})
|
||||
}
|
||||
|
||||
/// Creates a new dvec with the contents of a vector
|
||||
fn from_vec<A>(+v: ~[A]) -> DVec<A> {
|
||||
pub fn from_vec<A>(v: ~[A]) -> DVec<A> {
|
||||
DVec_({mut data: move v})
|
||||
}
|
||||
|
||||
/// Consumes the vector and returns its contents
|
||||
fn unwrap<A>(+d: DVec<A>) -> ~[A] {
|
||||
pub fn unwrap<A>(d: DVec<A>) -> ~[A] {
|
||||
let DVec_({data: v}) <- d;
|
||||
move v
|
||||
}
|
||||
|
|
@ -93,7 +87,7 @@ priv impl<A> DVec<A> {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn check_out<B>(f: fn(-v: ~[A]) -> B) -> B {
|
||||
fn check_out<B>(f: &fn(v: ~[A]) -> B) -> B {
|
||||
unsafe {
|
||||
let mut data = cast::reinterpret_cast(&null::<()>());
|
||||
data <-> self.data;
|
||||
|
|
@ -104,7 +98,7 @@ priv impl<A> DVec<A> {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn give_back(+data: ~[A]) {
|
||||
fn give_back(data: ~[A]) {
|
||||
unsafe {
|
||||
self.data = move data;
|
||||
}
|
||||
|
|
@ -126,7 +120,7 @@ impl<A> DVec<A> {
|
|||
* and return a new vector to replace it with.
|
||||
*/
|
||||
#[inline(always)]
|
||||
fn swap(f: fn(-v: ~[A]) -> ~[A]) {
|
||||
fn swap(f: &fn(v: ~[A]) -> ~[A]) {
|
||||
self.check_out(|v| self.give_back(f(move v)))
|
||||
}
|
||||
|
||||
|
|
@ -136,7 +130,7 @@ impl<A> DVec<A> {
|
|||
* and return a new vector to replace it with.
|
||||
*/
|
||||
#[inline(always)]
|
||||
fn swap_mut(f: fn(-v: ~[mut A]) -> ~[mut A]) {
|
||||
fn swap_mut(f: &fn(v: ~[mut A]) -> ~[mut A]) {
|
||||
do self.swap |v| {
|
||||
vec::from_mut(f(vec::to_mut(move v)))
|
||||
}
|
||||
|
|
@ -154,7 +148,7 @@ impl<A> DVec<A> {
|
|||
}
|
||||
|
||||
/// Overwrite the current contents
|
||||
fn set(+w: ~[A]) {
|
||||
fn set(w: ~[A]) {
|
||||
self.check_not_borrowed();
|
||||
self.data <- w;
|
||||
}
|
||||
|
|
@ -163,14 +157,14 @@ impl<A> DVec<A> {
|
|||
fn pop() -> A {
|
||||
do self.check_out |v| {
|
||||
let mut v <- v;
|
||||
let result = vec::pop(v);
|
||||
let result = v.pop();
|
||||
self.give_back(move v);
|
||||
move result
|
||||
}
|
||||
}
|
||||
|
||||
/// Insert a single item at the front of the list
|
||||
fn unshift(-t: A) {
|
||||
fn unshift(t: A) {
|
||||
unsafe {
|
||||
let mut data = cast::reinterpret_cast(&null::<()>());
|
||||
data <-> self.data;
|
||||
|
|
@ -178,22 +172,22 @@ impl<A> DVec<A> {
|
|||
if data_ptr.is_null() { fail ~"Recursive use of dvec"; }
|
||||
log(error, ~"a");
|
||||
self.data <- ~[move t];
|
||||
vec::push_all_move(self.data, move data);
|
||||
self.data.push_all_move(move data);
|
||||
log(error, ~"b");
|
||||
}
|
||||
}
|
||||
|
||||
/// Append a single item to the end of the list
|
||||
fn push(+t: A) {
|
||||
fn push(t: A) {
|
||||
self.check_not_borrowed();
|
||||
vec::push(self.data, move t);
|
||||
self.data.push(move t);
|
||||
}
|
||||
|
||||
/// Remove and return the first element
|
||||
fn shift() -> A {
|
||||
do self.check_out |v| {
|
||||
let mut v = move v;
|
||||
let result = vec::shift(v);
|
||||
let result = v.shift();
|
||||
self.give_back(move v);
|
||||
move result
|
||||
}
|
||||
|
|
@ -246,7 +240,7 @@ impl<A: Copy> DVec<A> {
|
|||
vec::reserve(&mut v, new_len);
|
||||
let mut i = from_idx;
|
||||
while i < to_idx {
|
||||
vec::push(v, ts[i]);
|
||||
v.push(ts[i]);
|
||||
i += 1u;
|
||||
}
|
||||
move v
|
||||
|
|
@ -272,7 +266,7 @@ impl<A: Copy> DVec<A> {
|
|||
}
|
||||
};
|
||||
|
||||
for ts.each |t| { vec::push(v, *t) };
|
||||
for ts.each |t| { v.push(*t) };
|
||||
v
|
||||
}
|
||||
}
|
||||
|
|
@ -311,10 +305,10 @@ impl<A: Copy> DVec<A> {
|
|||
* growing the vector if necessary. New elements will be initialized
|
||||
* with `initval`
|
||||
*/
|
||||
fn grow_set_elt(idx: uint, initval: A, val: A) {
|
||||
fn grow_set_elt(idx: uint, initval: &A, val: A) {
|
||||
do self.swap |v| {
|
||||
let mut v = move v;
|
||||
vec::grow_set(v, idx, initval, val);
|
||||
v.grow_set(idx, initval, val);
|
||||
move v
|
||||
}
|
||||
}
|
||||
|
|
@ -325,11 +319,11 @@ impl<A: Copy> DVec<A> {
|
|||
self.check_not_borrowed();
|
||||
|
||||
let length = self.len();
|
||||
if length == 0u {
|
||||
if length == 0 {
|
||||
fail ~"attempt to retrieve the last element of an empty vector";
|
||||
}
|
||||
|
||||
return self.data[length - 1u];
|
||||
return self.data[length - 1];
|
||||
}
|
||||
|
||||
/// Iterates over the elements in reverse order
|
||||
|
|
@ -360,7 +354,7 @@ impl<A: Copy> DVec<A> {
|
|||
}
|
||||
|
||||
impl<A:Copy> DVec<A>: Index<uint,A> {
|
||||
pure fn index(&&idx: uint) -> A {
|
||||
pure fn index(idx: uint) -> A {
|
||||
self.get_elt(idx)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
// tjc: re-forbid deprecated modes after snapshot
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
//! A type that represents one of two alternatives
|
||||
|
|
@ -8,13 +8,13 @@ use cmp::Eq;
|
|||
use result::Result;
|
||||
|
||||
/// The either type
|
||||
enum Either<T, U> {
|
||||
pub enum Either<T, U> {
|
||||
Left(T),
|
||||
Right(U)
|
||||
}
|
||||
|
||||
fn either<T, U, V>(f_left: fn((&T)) -> V,
|
||||
f_right: fn((&U)) -> V, value: &Either<T, U>) -> V {
|
||||
pub fn either<T, U, V>(f_left: fn((&T)) -> V,
|
||||
f_right: fn((&U)) -> V, value: &Either<T, U>) -> V {
|
||||
/*!
|
||||
* Applies a function based on the given either value
|
||||
*
|
||||
|
|
@ -29,33 +29,34 @@ fn either<T, U, V>(f_left: fn((&T)) -> V,
|
|||
}
|
||||
}
|
||||
|
||||
fn lefts<T: Copy, U>(eithers: &[Either<T, U>]) -> ~[T] {
|
||||
pub fn lefts<T: Copy, U>(eithers: &[Either<T, U>]) -> ~[T] {
|
||||
//! Extracts from a vector of either all the left values
|
||||
|
||||
let mut result: ~[T] = ~[];
|
||||
for vec::each(eithers) |elt| {
|
||||
match *elt {
|
||||
Left(l) => vec::push(result, l),
|
||||
_ => { /* fallthrough */ }
|
||||
do vec::build_sized(eithers.len()) |push| {
|
||||
for vec::each(eithers) |elt| {
|
||||
match *elt {
|
||||
Left(ref l) => { push(*l); }
|
||||
_ => { /* fallthrough */ }
|
||||
}
|
||||
}
|
||||
}
|
||||
move result
|
||||
}
|
||||
|
||||
fn rights<T, U: Copy>(eithers: &[Either<T, U>]) -> ~[U] {
|
||||
pub fn rights<T, U: Copy>(eithers: &[Either<T, U>]) -> ~[U] {
|
||||
//! Extracts from a vector of either all the right values
|
||||
|
||||
let mut result: ~[U] = ~[];
|
||||
for vec::each(eithers) |elt| {
|
||||
match *elt {
|
||||
Right(r) => vec::push(result, r),
|
||||
_ => { /* fallthrough */ }
|
||||
do vec::build_sized(eithers.len()) |push| {
|
||||
for vec::each(eithers) |elt| {
|
||||
match *elt {
|
||||
Right(ref r) => { push(*r); }
|
||||
_ => { /* fallthrough */ }
|
||||
}
|
||||
}
|
||||
}
|
||||
move result
|
||||
}
|
||||
|
||||
fn partition<T: Copy, U: Copy>(eithers: &[Either<T, U>])
|
||||
// XXX bad copies. take arg by val
|
||||
pub fn partition<T: Copy, U: Copy>(eithers: &[Either<T, U>])
|
||||
-> {lefts: ~[T], rights: ~[U]} {
|
||||
/*!
|
||||
* Extracts from a vector of either all the left values and right values
|
||||
|
|
@ -68,23 +69,26 @@ fn partition<T: Copy, U: Copy>(eithers: &[Either<T, U>])
|
|||
let mut rights: ~[U] = ~[];
|
||||
for vec::each(eithers) |elt| {
|
||||
match *elt {
|
||||
Left(l) => vec::push(lefts, l),
|
||||
Right(r) => vec::push(rights, r)
|
||||
Left(copy l) => lefts.push(l),
|
||||
Right(copy r) => rights.push(r)
|
||||
}
|
||||
}
|
||||
return {lefts: move lefts, rights: move rights};
|
||||
}
|
||||
|
||||
pure fn flip<T: Copy, U: Copy>(eith: &Either<T, U>) -> Either<U, T> {
|
||||
// XXX bad copies
|
||||
pub pure fn flip<T: Copy, U: Copy>(eith: &Either<T, U>) -> Either<U, T> {
|
||||
//! Flips between left and right of a given either
|
||||
|
||||
match *eith {
|
||||
Right(r) => Left(r),
|
||||
Left(l) => Right(l)
|
||||
Right(copy r) => Left(r),
|
||||
Left(copy l) => Right(l)
|
||||
}
|
||||
}
|
||||
|
||||
pure fn to_result<T: Copy, U: Copy>(eith: &Either<T, U>) -> Result<U, T> {
|
||||
// XXX bad copies
|
||||
pub pure fn to_result<T: Copy, U: Copy>(eith: &Either<T, U>)
|
||||
-> Result<U, T> {
|
||||
/*!
|
||||
* Converts either::t to a result::t
|
||||
*
|
||||
|
|
@ -93,24 +97,25 @@ pure fn to_result<T: Copy, U: Copy>(eith: &Either<T, U>) -> Result<U, T> {
|
|||
*/
|
||||
|
||||
match *eith {
|
||||
Right(r) => result::Ok(r),
|
||||
Left(l) => result::Err(l)
|
||||
Right(copy r) => result::Ok(r),
|
||||
Left(copy l) => result::Err(l)
|
||||
}
|
||||
}
|
||||
|
||||
pure fn is_left<T, U>(eith: &Either<T, U>) -> bool {
|
||||
pub pure fn is_left<T, U>(eith: &Either<T, U>) -> bool {
|
||||
//! Checks whether the given value is a left
|
||||
|
||||
match *eith { Left(_) => true, _ => false }
|
||||
}
|
||||
|
||||
pure fn is_right<T, U>(eith: &Either<T, U>) -> bool {
|
||||
pub pure fn is_right<T, U>(eith: &Either<T, U>) -> bool {
|
||||
//! Checks whether the given value is a right
|
||||
|
||||
match *eith { Right(_) => true, _ => false }
|
||||
}
|
||||
|
||||
pure fn unwrap_left<T,U>(+eith: Either<T,U>) -> T {
|
||||
// tjc: fix the next two after a snapshot
|
||||
pub pure fn unwrap_left<T,U>(eith: Either<T,U>) -> T {
|
||||
//! Retrieves the value in the left branch. Fails if the either is Right.
|
||||
|
||||
match move eith {
|
||||
|
|
@ -118,7 +123,7 @@ pure fn unwrap_left<T,U>(+eith: Either<T,U>) -> T {
|
|||
}
|
||||
}
|
||||
|
||||
pure fn unwrap_right<T,U>(+eith: Either<T,U>) -> U {
|
||||
pub pure fn unwrap_right<T,U>(eith: Either<T,U>) -> U {
|
||||
//! Retrieves the value in the right branch. Fails if the either is Left.
|
||||
|
||||
match move eith {
|
||||
|
|
@ -129,16 +134,16 @@ pure fn unwrap_right<T,U>(+eith: Either<T,U>) -> U {
|
|||
impl<T:Eq,U:Eq> Either<T,U> : Eq {
|
||||
pure fn eq(other: &Either<T,U>) -> bool {
|
||||
match self {
|
||||
Left(a) => {
|
||||
Left(ref a) => {
|
||||
match (*other) {
|
||||
Left(ref b) => a.eq(b),
|
||||
Left(ref b) => (*a).eq(b),
|
||||
Right(_) => false
|
||||
}
|
||||
}
|
||||
Right(a) => {
|
||||
Right(ref a) => {
|
||||
match (*other) {
|
||||
Left(_) => false,
|
||||
Right(ref b) => a.eq(b)
|
||||
Right(ref b) => (*a).eq(b)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,16 +81,16 @@ mod ct {
|
|||
|
||||
// A fragment of the output sequence
|
||||
enum Piece { PieceString(~str), PieceConv(Conv), }
|
||||
type ErrorFn = fn@(~str) -> ! ;
|
||||
type ErrorFn = fn@(&str) -> ! ;
|
||||
|
||||
fn parse_fmt_string(s: ~str, error: ErrorFn) -> ~[Piece] {
|
||||
fn parse_fmt_string(s: &str, error: ErrorFn) -> ~[Piece] {
|
||||
let mut pieces: ~[Piece] = ~[];
|
||||
let lim = str::len(s);
|
||||
let mut buf = ~"";
|
||||
fn flush_buf(+buf: ~str, &pieces: ~[Piece]) -> ~str {
|
||||
if str::len(buf) > 0 {
|
||||
fn flush_buf(buf: ~str, pieces: &mut ~[Piece]) -> ~str {
|
||||
if buf.len() > 0 {
|
||||
let piece = PieceString(move buf);
|
||||
vec::push(pieces, move piece);
|
||||
pieces.push(move piece);
|
||||
}
|
||||
return ~"";
|
||||
}
|
||||
|
|
@ -108,17 +108,17 @@ mod ct {
|
|||
buf += curr2;
|
||||
i += 1;
|
||||
} else {
|
||||
buf = flush_buf(move buf, pieces);
|
||||
buf = flush_buf(move buf, &mut pieces);
|
||||
let rs = parse_conversion(s, i, lim, error);
|
||||
vec::push(pieces, copy rs.piece);
|
||||
pieces.push(copy rs.piece);
|
||||
i = rs.next;
|
||||
}
|
||||
} else { buf += curr; i += size; }
|
||||
}
|
||||
flush_buf(move buf, pieces);
|
||||
flush_buf(move buf, &mut pieces);
|
||||
move pieces
|
||||
}
|
||||
fn peek_num(s: ~str, i: uint, lim: uint) ->
|
||||
fn peek_num(s: &str, i: uint, lim: uint) ->
|
||||
Option<{num: uint, next: uint}> {
|
||||
let mut j = i;
|
||||
let mut accum = 0u;
|
||||
|
|
@ -140,7 +140,7 @@ mod ct {
|
|||
None
|
||||
}
|
||||
}
|
||||
fn parse_conversion(s: ~str, i: uint, lim: uint, error: ErrorFn) ->
|
||||
fn parse_conversion(s: &str, i: uint, lim: uint, error: ErrorFn) ->
|
||||
{piece: Piece, next: uint} {
|
||||
let parm = parse_parameter(s, i, lim);
|
||||
let flags = parse_flags(s, parm.next, lim);
|
||||
|
|
@ -155,7 +155,7 @@ mod ct {
|
|||
ty: ty.ty}),
|
||||
next: ty.next};
|
||||
}
|
||||
fn parse_parameter(s: ~str, i: uint, lim: uint) ->
|
||||
fn parse_parameter(s: &str, i: uint, lim: uint) ->
|
||||
{param: Option<int>, next: uint} {
|
||||
if i >= lim { return {param: None, next: i}; }
|
||||
let num = peek_num(s, i, lim);
|
||||
|
|
@ -170,12 +170,12 @@ mod ct {
|
|||
}
|
||||
};
|
||||
}
|
||||
fn parse_flags(s: ~str, i: uint, lim: uint) ->
|
||||
fn parse_flags(s: &str, i: uint, lim: uint) ->
|
||||
{flags: ~[Flag], next: uint} {
|
||||
let noflags: ~[Flag] = ~[];
|
||||
if i >= lim { return {flags: move noflags, next: i}; }
|
||||
|
||||
fn more_(f: Flag, s: ~str, i: uint, lim: uint) ->
|
||||
fn more(f: Flag, s: &str, i: uint, lim: uint) ->
|
||||
{flags: ~[Flag], next: uint} {
|
||||
let next = parse_flags(s, i + 1u, lim);
|
||||
let rest = copy next.flags;
|
||||
|
|
@ -183,21 +183,22 @@ mod ct {
|
|||
let curr: ~[Flag] = ~[f];
|
||||
return {flags: vec::append(move curr, rest), next: j};
|
||||
}
|
||||
let more = |x, copy s| more_(x, copy s, i, lim);
|
||||
// Unfortunate, but because s is borrowed, can't use a closure
|
||||
// fn more(f: Flag, s: &str) { more_(f, s, i, lim); }
|
||||
let f = s[i];
|
||||
return if f == '-' as u8 {
|
||||
more(FlagLeftJustify)
|
||||
more(FlagLeftJustify, s, i, lim)
|
||||
} else if f == '0' as u8 {
|
||||
more(FlagLeftZeroPad)
|
||||
more(FlagLeftZeroPad, s, i, lim)
|
||||
} else if f == ' ' as u8 {
|
||||
more(FlagSpaceForSign)
|
||||
more(FlagSpaceForSign, s, i, lim)
|
||||
} else if f == '+' as u8 {
|
||||
more(FlagSignAlways)
|
||||
more(FlagSignAlways, s, i, lim)
|
||||
} else if f == '#' as u8 {
|
||||
more(FlagAlternate)
|
||||
more(FlagAlternate, s, i, lim)
|
||||
} else { {flags: move noflags, next: i} };
|
||||
}
|
||||
fn parse_count(s: ~str, i: uint, lim: uint)
|
||||
fn parse_count(s: &str, i: uint, lim: uint)
|
||||
-> {count: Count, next: uint} {
|
||||
return if i >= lim {
|
||||
{count: CountImplied, next: i}
|
||||
|
|
@ -219,7 +220,7 @@ mod ct {
|
|||
}
|
||||
};
|
||||
}
|
||||
fn parse_precision(s: ~str, i: uint, lim: uint) ->
|
||||
fn parse_precision(s: &str, i: uint, lim: uint) ->
|
||||
{count: Count, next: uint} {
|
||||
return if i >= lim {
|
||||
{count: CountImplied, next: i}
|
||||
|
|
@ -235,7 +236,7 @@ mod ct {
|
|||
}
|
||||
} else { {count: CountImplied, next: i} };
|
||||
}
|
||||
fn parse_type(s: ~str, i: uint, lim: uint, error: ErrorFn) ->
|
||||
fn parse_type(s: &str, i: uint, lim: uint, error: ErrorFn) ->
|
||||
{ty: Ty, next: uint} {
|
||||
if i >= lim { error(~"missing type in conversion"); }
|
||||
let tstr = str::slice(s, i, i+1u);
|
||||
|
|
@ -288,7 +289,7 @@ mod rt {
|
|||
type Conv = {flags: u32, width: Count, precision: Count, ty: Ty};
|
||||
|
||||
pure fn conv_int(cv: Conv, i: int) -> ~str {
|
||||
let radix = 10u;
|
||||
let radix = 10;
|
||||
let prec = get_int_precision(cv);
|
||||
let mut s : ~str = int_to_str_prec(i, radix, prec);
|
||||
if 0 <= i {
|
||||
|
|
@ -350,8 +351,8 @@ mod rt {
|
|||
}
|
||||
return unsafe { pad(cv, s, PadFloat) };
|
||||
}
|
||||
pure fn conv_poly<T>(cv: Conv, v: T) -> ~str {
|
||||
let s = sys::log_str(&v);
|
||||
pure fn conv_poly<T>(cv: Conv, v: &T) -> ~str {
|
||||
let s = sys::log_str(v);
|
||||
return conv_str(cv, s);
|
||||
}
|
||||
|
||||
|
|
@ -404,16 +405,17 @@ mod rt {
|
|||
pure fn ne(other: &PadMode) -> bool { !self.eq(other) }
|
||||
}
|
||||
|
||||
fn pad(cv: Conv, &s: ~str, mode: PadMode) -> ~str {
|
||||
fn pad(cv: Conv, s: ~str, mode: PadMode) -> ~str {
|
||||
let mut s = move s; // sadtimes
|
||||
let uwidth : uint = match cv.width {
|
||||
CountImplied => return copy s,
|
||||
CountImplied => return s,
|
||||
CountIs(width) => {
|
||||
// FIXME: width should probably be uint (see Issue #1996)
|
||||
width as uint
|
||||
}
|
||||
};
|
||||
let strlen = str::char_len(s);
|
||||
if uwidth <= strlen { return copy s; }
|
||||
if uwidth <= strlen { return s; }
|
||||
let mut padchar = ' ';
|
||||
let diff = uwidth - strlen;
|
||||
if have_flag(cv.flags, flag_left_justify) {
|
||||
|
|
@ -444,7 +446,7 @@ mod rt {
|
|||
// zeros. It may make sense to convert zero padding to a precision
|
||||
// instead.
|
||||
|
||||
if signed && zero_padding && str::len(s) > 0u {
|
||||
if signed && zero_padding && s.len() > 0 {
|
||||
let head = str::shift_char(&mut s);
|
||||
if head == '+' || head == '-' || head == ' ' {
|
||||
let headstr = str::from_chars(vec::from_elem(1u, head));
|
||||
|
|
@ -461,7 +463,12 @@ mod rt {
|
|||
}
|
||||
}
|
||||
|
||||
// XXX remove after snapshots
|
||||
// Remove after snapshot
|
||||
|
||||
// Functions used by the fmt extension at runtime. For now there are a lot of
|
||||
// decisions made a runtime. If it proves worthwhile then some of these
|
||||
// conditions can be evaluated at compile-time. For now though it's cleaner to
|
||||
// implement it 0this way, I think.
|
||||
mod rt2 {
|
||||
#[legacy_exports];
|
||||
const flag_none : u32 = 0u32;
|
||||
|
|
@ -477,7 +484,7 @@ mod rt2 {
|
|||
type Conv = {flags: u32, width: Count, precision: Count, ty: Ty};
|
||||
|
||||
pure fn conv_int(cv: Conv, i: int) -> ~str {
|
||||
let radix = 10u;
|
||||
let radix = 10;
|
||||
let prec = get_int_precision(cv);
|
||||
let mut s : ~str = int_to_str_prec(i, radix, prec);
|
||||
if 0 <= i {
|
||||
|
|
@ -539,8 +546,8 @@ mod rt2 {
|
|||
}
|
||||
return unsafe { pad(cv, s, PadFloat) };
|
||||
}
|
||||
pure fn conv_poly<T>(cv: Conv, v: T) -> ~str {
|
||||
let s = sys::log_str(&v);
|
||||
pure fn conv_poly<T>(cv: Conv, v: &T) -> ~str {
|
||||
let s = sys::log_str(v);
|
||||
return conv_str(cv, s);
|
||||
}
|
||||
|
||||
|
|
@ -593,16 +600,17 @@ mod rt2 {
|
|||
pure fn ne(other: &PadMode) -> bool { !self.eq(other) }
|
||||
}
|
||||
|
||||
fn pad(cv: Conv, &s: ~str, mode: PadMode) -> ~str {
|
||||
fn pad(cv: Conv, s: ~str, mode: PadMode) -> ~str {
|
||||
let mut s = move s; // sadtimes
|
||||
let uwidth : uint = match cv.width {
|
||||
CountImplied => return copy s,
|
||||
CountImplied => return s,
|
||||
CountIs(width) => {
|
||||
// FIXME: width should probably be uint (see Issue #1996)
|
||||
width as uint
|
||||
}
|
||||
};
|
||||
let strlen = str::char_len(s);
|
||||
if uwidth <= strlen { return copy s; }
|
||||
if uwidth <= strlen { return s; }
|
||||
let mut padchar = ' ';
|
||||
let diff = uwidth - strlen;
|
||||
if have_flag(cv.flags, flag_left_justify) {
|
||||
|
|
@ -633,7 +641,7 @@ mod rt2 {
|
|||
// zeros. It may make sense to convert zero padding to a precision
|
||||
// instead.
|
||||
|
||||
if signed && zero_padding && str::len(s) > 0u {
|
||||
if signed && zero_padding && s.len() > 0 {
|
||||
let head = str::shift_char(&mut s);
|
||||
if head == '+' || head == '-' || head == ' ' {
|
||||
let headstr = str::from_chars(vec::from_elem(1u, head));
|
||||
|
|
|
|||
|
|
@ -4,68 +4,51 @@
|
|||
|
||||
//! Operations and constants for `f32`
|
||||
|
||||
// PORT
|
||||
|
||||
use cmath::c_float::*;
|
||||
use cmath::c_float_targ_consts::*;
|
||||
|
||||
export add, sub, mul, div, rem, lt, le, eq, ne, ge, gt;
|
||||
export is_positive, is_negative, is_nonpositive, is_nonnegative;
|
||||
export is_zero, is_infinite, is_finite;
|
||||
export NaN, is_NaN, infinity, neg_infinity;
|
||||
export consts;
|
||||
export logarithm;
|
||||
export acos, asin, atan, atan2, cbrt, ceil, copysign, cos, cosh, floor;
|
||||
export erf, erfc, exp, expm1, exp2, abs, abs_sub;
|
||||
export mul_add, fmax, fmin, nextafter, frexp, hypot, ldexp;
|
||||
export lgamma, ln, log_radix, ln1p, log10, log2, ilog_radix;
|
||||
export modf, pow, round, sin, sinh, sqrt, tan, tanh, tgamma, trunc;
|
||||
export signbit;
|
||||
|
||||
export num;
|
||||
pub use cmath::c_float::*;
|
||||
pub use cmath::c_float_targ_consts::*;
|
||||
|
||||
// These are not defined inside consts:: for consistency with
|
||||
// the integer types
|
||||
|
||||
const NaN: f32 = 0.0_f32/0.0_f32;
|
||||
pub const NaN: f32 = 0.0_f32/0.0_f32;
|
||||
|
||||
const infinity: f32 = 1.0_f32/0.0_f32;
|
||||
pub const infinity: f32 = 1.0_f32/0.0_f32;
|
||||
|
||||
const neg_infinity: f32 = -1.0_f32/0.0_f32;
|
||||
pub const neg_infinity: f32 = -1.0_f32/0.0_f32;
|
||||
|
||||
pure fn is_NaN(f: f32) -> bool { f != f }
|
||||
pub pure fn is_NaN(f: f32) -> bool { f != f }
|
||||
|
||||
pure fn add(x: f32, y: f32) -> f32 { return x + y; }
|
||||
pub pure fn add(x: f32, y: f32) -> f32 { return x + y; }
|
||||
|
||||
pure fn sub(x: f32, y: f32) -> f32 { return x - y; }
|
||||
pub pure fn sub(x: f32, y: f32) -> f32 { return x - y; }
|
||||
|
||||
pure fn mul(x: f32, y: f32) -> f32 { return x * y; }
|
||||
pub pure fn mul(x: f32, y: f32) -> f32 { return x * y; }
|
||||
|
||||
pure fn div(x: f32, y: f32) -> f32 { return x / y; }
|
||||
pub pure fn div(x: f32, y: f32) -> f32 { return x / y; }
|
||||
|
||||
pure fn rem(x: f32, y: f32) -> f32 { return x % y; }
|
||||
pub pure fn rem(x: f32, y: f32) -> f32 { return x % y; }
|
||||
|
||||
pure fn lt(x: f32, y: f32) -> bool { return x < y; }
|
||||
pub pure fn lt(x: f32, y: f32) -> bool { return x < y; }
|
||||
|
||||
pure fn le(x: f32, y: f32) -> bool { return x <= y; }
|
||||
pub pure fn le(x: f32, y: f32) -> bool { return x <= y; }
|
||||
|
||||
pure fn eq(x: f32, y: f32) -> bool { return x == y; }
|
||||
pub pure fn eq(x: f32, y: f32) -> bool { return x == y; }
|
||||
|
||||
pure fn ne(x: f32, y: f32) -> bool { return x != y; }
|
||||
pub pure fn ne(x: f32, y: f32) -> bool { return x != y; }
|
||||
|
||||
pure fn ge(x: f32, y: f32) -> bool { return x >= y; }
|
||||
pub pure fn ge(x: f32, y: f32) -> bool { return x >= y; }
|
||||
|
||||
pure fn gt(x: f32, y: f32) -> bool { return x > y; }
|
||||
pub pure fn gt(x: f32, y: f32) -> bool { 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 positive number, including +0.0f320 and +Infinity
|
||||
pure fn is_positive(x: f32) -> bool
|
||||
pub pure fn is_positive(x: f32) -> bool
|
||||
{ return x > 0.0f32 || (1.0f32/x) == infinity; }
|
||||
|
||||
/// Returns true if `x` is a negative number, including -0.0f320 and -Infinity
|
||||
pure fn is_negative(x: f32) -> bool
|
||||
pub pure fn is_negative(x: f32) -> bool
|
||||
{ return x < 0.0f32 || (1.0f32/x) == neg_infinity; }
|
||||
|
||||
/**
|
||||
|
|
@ -73,7 +56,7 @@ pure fn is_negative(x: f32) -> bool
|
|||
*
|
||||
* This is the same as `f32::is_negative`.
|
||||
*/
|
||||
pure fn is_nonpositive(x: f32) -> bool {
|
||||
pub pure fn is_nonpositive(x: f32) -> bool {
|
||||
return x < 0.0f32 || (1.0f32/x) == neg_infinity;
|
||||
}
|
||||
|
||||
|
|
@ -82,87 +65,85 @@ pure fn is_nonpositive(x: f32) -> bool {
|
|||
*
|
||||
* This is the same as `f32::is_positive`.)
|
||||
*/
|
||||
pure fn is_nonnegative(x: f32) -> bool {
|
||||
pub pure fn is_nonnegative(x: f32) -> bool {
|
||||
return x > 0.0f32 || (1.0f32/x) == infinity;
|
||||
}
|
||||
|
||||
/// Returns true if `x` is a zero number (positive or negative zero)
|
||||
pure fn is_zero(x: f32) -> bool {
|
||||
pub pure fn is_zero(x: f32) -> bool {
|
||||
return x == 0.0f32 || x == -0.0f32;
|
||||
}
|
||||
|
||||
/// Returns true if `x`is an infinite number
|
||||
pure fn is_infinite(x: f32) -> bool {
|
||||
pub pure fn is_infinite(x: f32) -> bool {
|
||||
return x == infinity || x == neg_infinity;
|
||||
}
|
||||
|
||||
/// Returns true if `x`is a finite number
|
||||
pure fn is_finite(x: f32) -> bool {
|
||||
pub pure fn is_finite(x: f32) -> bool {
|
||||
return !(is_NaN(x) || is_infinite(x));
|
||||
}
|
||||
|
||||
// FIXME (#1999): add is_normal, is_subnormal, and fpclassify.
|
||||
|
||||
/* Module: consts */
|
||||
mod consts {
|
||||
#[legacy_exports];
|
||||
|
||||
pub mod consts {
|
||||
// FIXME (requires Issue #1433 to fix): replace with mathematical
|
||||
// constants from cmath.
|
||||
/// Archimedes' constant
|
||||
const pi: f32 = 3.14159265358979323846264338327950288_f32;
|
||||
pub const pi: f32 = 3.14159265358979323846264338327950288_f32;
|
||||
|
||||
/// pi/2.0
|
||||
const frac_pi_2: f32 = 1.57079632679489661923132169163975144_f32;
|
||||
pub const frac_pi_2: f32 = 1.57079632679489661923132169163975144_f32;
|
||||
|
||||
/// pi/4.0
|
||||
const frac_pi_4: f32 = 0.785398163397448309615660845819875721_f32;
|
||||
pub const frac_pi_4: f32 = 0.785398163397448309615660845819875721_f32;
|
||||
|
||||
/// 1.0/pi
|
||||
const frac_1_pi: f32 = 0.318309886183790671537767526745028724_f32;
|
||||
pub const frac_1_pi: f32 = 0.318309886183790671537767526745028724_f32;
|
||||
|
||||
/// 2.0/pi
|
||||
const frac_2_pi: f32 = 0.636619772367581343075535053490057448_f32;
|
||||
pub const frac_2_pi: f32 = 0.636619772367581343075535053490057448_f32;
|
||||
|
||||
/// 2.0/sqrt(pi)
|
||||
const frac_2_sqrtpi: f32 = 1.12837916709551257389615890312154517_f32;
|
||||
pub const frac_2_sqrtpi: f32 = 1.12837916709551257389615890312154517_f32;
|
||||
|
||||
/// sqrt(2.0)
|
||||
const sqrt2: f32 = 1.41421356237309504880168872420969808_f32;
|
||||
pub const sqrt2: f32 = 1.41421356237309504880168872420969808_f32;
|
||||
|
||||
/// 1.0/sqrt(2.0)
|
||||
const frac_1_sqrt2: f32 = 0.707106781186547524400844362104849039_f32;
|
||||
pub const frac_1_sqrt2: f32 = 0.707106781186547524400844362104849039_f32;
|
||||
|
||||
/// Euler's number
|
||||
const e: f32 = 2.71828182845904523536028747135266250_f32;
|
||||
pub const e: f32 = 2.71828182845904523536028747135266250_f32;
|
||||
|
||||
/// log2(e)
|
||||
const log2_e: f32 = 1.44269504088896340735992468100189214_f32;
|
||||
pub const log2_e: f32 = 1.44269504088896340735992468100189214_f32;
|
||||
|
||||
/// log10(e)
|
||||
const log10_e: f32 = 0.434294481903251827651128918916605082_f32;
|
||||
pub const log10_e: f32 = 0.434294481903251827651128918916605082_f32;
|
||||
|
||||
/// ln(2.0)
|
||||
const ln_2: f32 = 0.693147180559945309417232121458176568_f32;
|
||||
pub const ln_2: f32 = 0.693147180559945309417232121458176568_f32;
|
||||
|
||||
/// ln(10.0)
|
||||
const ln_10: f32 = 2.30258509299404568401799145468436421_f32;
|
||||
pub const ln_10: f32 = 2.30258509299404568401799145468436421_f32;
|
||||
}
|
||||
|
||||
pure fn signbit(x: f32) -> int {
|
||||
pub pure fn signbit(x: f32) -> int {
|
||||
if is_negative(x) { return 1; } else { return 0; }
|
||||
}
|
||||
|
||||
pure fn logarithm(n: f32, b: f32) -> f32 {
|
||||
pub pure fn logarithm(n: f32, b: f32) -> f32 {
|
||||
return log2(n) / log2(b);
|
||||
}
|
||||
|
||||
impl f32: num::Num {
|
||||
pure fn add(&&other: f32) -> f32 { return self + other; }
|
||||
pure fn sub(&&other: f32) -> f32 { return self - other; }
|
||||
pure fn mul(&&other: f32) -> f32 { return self * other; }
|
||||
pure fn div(&&other: f32) -> f32 { return self / other; }
|
||||
pure fn modulo(&&other: f32) -> f32 { return self % other; }
|
||||
pure fn add(other: &f32) -> f32 { return self + *other; }
|
||||
pure fn sub(other: &f32) -> f32 { return self - *other; }
|
||||
pure fn mul(other: &f32) -> f32 { return self * *other; }
|
||||
pure fn div(other: &f32) -> f32 { return self / *other; }
|
||||
pure fn modulo(other: &f32) -> f32 { return self % *other; }
|
||||
pure fn neg() -> f32 { return -self; }
|
||||
|
||||
pure fn to_int() -> int { return self as int; }
|
||||
|
|
|
|||
|
|
@ -4,95 +4,70 @@
|
|||
|
||||
//! Operations and constants for `f64`
|
||||
|
||||
// PORT
|
||||
pub use cmath::c_double::*;
|
||||
pub use cmath::c_double_targ_consts::*;
|
||||
|
||||
use cmath::c_double::*;
|
||||
use cmath::c_double_targ_consts::*;
|
||||
|
||||
// Even though this module exports everything defined in it,
|
||||
// because it contains re-exports, we also have to explicitly
|
||||
// export locally defined things. That's a bit annoying.
|
||||
export add, sub, mul, div, rem, lt, le, eq, ne, ge, gt;
|
||||
export is_positive, is_negative, is_nonpositive, is_nonnegative;
|
||||
export is_zero, is_infinite, is_finite;
|
||||
export NaN, is_NaN, infinity, neg_infinity;
|
||||
export consts;
|
||||
export logarithm;
|
||||
export acos, asin, atan, atan2, cbrt, ceil, copysign, cos, cosh, floor;
|
||||
export erf, erfc, exp, expm1, exp2, abs, abs_sub;
|
||||
export mul_add, fmax, fmin, nextafter, frexp, hypot, ldexp;
|
||||
export lgamma, ln, log_radix, ln1p, log10, log2, ilog_radix;
|
||||
export modf, pow, round, sin, sinh, sqrt, tan, tanh, tgamma, trunc;
|
||||
export signbit;
|
||||
export epsilon;
|
||||
|
||||
export j0, j1, jn, y0, y1, yn;
|
||||
|
||||
export num;
|
||||
// FIXME (#1433): obtain these in a different way
|
||||
|
||||
// These are not defined inside consts:: for consistency with
|
||||
// the integer types
|
||||
|
||||
// PORT check per architecture
|
||||
pub const radix: uint = 2u;
|
||||
|
||||
// FIXME (#1433): obtain these in a different way
|
||||
pub const mantissa_digits: uint = 53u;
|
||||
pub const digits: uint = 15u;
|
||||
|
||||
const radix: uint = 2u;
|
||||
pub const epsilon: f64 = 2.2204460492503131e-16_f64;
|
||||
|
||||
const mantissa_digits: uint = 53u;
|
||||
const digits: uint = 15u;
|
||||
pub const min_value: f64 = 2.2250738585072014e-308_f64;
|
||||
pub const max_value: f64 = 1.7976931348623157e+308_f64;
|
||||
|
||||
const epsilon: f64 = 2.2204460492503131e-16_f64;
|
||||
pub const min_exp: int = -1021;
|
||||
pub const max_exp: int = 1024;
|
||||
|
||||
const min_value: f64 = 2.2250738585072014e-308_f64;
|
||||
const max_value: f64 = 1.7976931348623157e+308_f64;
|
||||
pub const min_10_exp: int = -307;
|
||||
pub const max_10_exp: int = 308;
|
||||
|
||||
const min_exp: int = -1021;
|
||||
const max_exp: int = 1024;
|
||||
pub const NaN: f64 = 0.0_f64/0.0_f64;
|
||||
|
||||
const min_10_exp: int = -307;
|
||||
const max_10_exp: int = 308;
|
||||
pub const infinity: f64 = 1.0_f64/0.0_f64;
|
||||
|
||||
const NaN: f64 = 0.0_f64/0.0_f64;
|
||||
pub const neg_infinity: f64 = -1.0_f64/0.0_f64;
|
||||
|
||||
const infinity: f64 = 1.0_f64/0.0_f64;
|
||||
pub pure fn is_NaN(f: f64) -> bool { f != f }
|
||||
|
||||
const neg_infinity: f64 = -1.0_f64/0.0_f64;
|
||||
pub pure fn add(x: f64, y: f64) -> f64 { return x + y; }
|
||||
|
||||
pure fn is_NaN(f: f64) -> bool { f != f }
|
||||
pub pure fn sub(x: f64, y: f64) -> f64 { return x - y; }
|
||||
|
||||
pure fn add(x: f64, y: f64) -> f64 { return x + y; }
|
||||
pub pure fn mul(x: f64, y: f64) -> f64 { return x * y; }
|
||||
|
||||
pure fn sub(x: f64, y: f64) -> f64 { return x - y; }
|
||||
pub pure fn div(x: f64, y: f64) -> f64 { return x / y; }
|
||||
|
||||
pure fn mul(x: f64, y: f64) -> f64 { return x * y; }
|
||||
pub pure fn rem(x: f64, y: f64) -> f64 { return x % y; }
|
||||
|
||||
pure fn div(x: f64, y: f64) -> f64 { return x / y; }
|
||||
pub pure fn lt(x: f64, y: f64) -> bool { return x < y; }
|
||||
|
||||
pure fn rem(x: f64, y: f64) -> f64 { return x % y; }
|
||||
pub pure fn le(x: f64, y: f64) -> bool { return x <= y; }
|
||||
|
||||
pure fn lt(x: f64, y: f64) -> bool { return x < y; }
|
||||
pub pure fn eq(x: f64, y: f64) -> bool { return x == y; }
|
||||
|
||||
pure fn le(x: f64, y: f64) -> bool { return x <= y; }
|
||||
pub pure fn ne(x: f64, y: f64) -> bool { return x != y; }
|
||||
|
||||
pure fn eq(x: f64, y: f64) -> bool { return x == y; }
|
||||
pub pure fn ge(x: f64, y: f64) -> bool { return x >= y; }
|
||||
|
||||
pure fn ne(x: f64, y: f64) -> bool { return x != y; }
|
||||
pub pure fn gt(x: f64, y: f64) -> bool { return x > y; }
|
||||
|
||||
pure fn ge(x: f64, y: f64) -> bool { return x >= y; }
|
||||
|
||||
pure fn gt(x: f64, y: f64) -> bool { return x > y; }
|
||||
|
||||
pure fn sqrt(x: f64) -> f64 {
|
||||
pub pure fn sqrt(x: f64) -> f64 {
|
||||
cmath::c_double::sqrt(x as libc::c_double) as f64
|
||||
}
|
||||
|
||||
/// Returns true if `x` is a positive number, including +0.0f640 and +Infinity
|
||||
pure fn is_positive(x: f64) -> bool
|
||||
pub pure fn is_positive(x: f64) -> bool
|
||||
{ return x > 0.0f64 || (1.0f64/x) == infinity; }
|
||||
|
||||
/// Returns true if `x` is a negative number, including -0.0f640 and -Infinity
|
||||
pure fn is_negative(x: f64) -> bool
|
||||
pub pure fn is_negative(x: f64) -> bool
|
||||
{ return x < 0.0f64 || (1.0f64/x) == neg_infinity; }
|
||||
|
||||
/**
|
||||
|
|
@ -100,7 +75,7 @@ pure fn is_negative(x: f64) -> bool
|
|||
*
|
||||
* This is the same as `f64::is_negative`.
|
||||
*/
|
||||
pure fn is_nonpositive(x: f64) -> bool {
|
||||
pub pure fn is_nonpositive(x: f64) -> bool {
|
||||
return x < 0.0f64 || (1.0f64/x) == neg_infinity;
|
||||
}
|
||||
|
||||
|
|
@ -109,87 +84,85 @@ pure fn is_nonpositive(x: f64) -> bool {
|
|||
*
|
||||
* This is the same as `f64::positive`.
|
||||
*/
|
||||
pure fn is_nonnegative(x: f64) -> bool {
|
||||
pub pure fn is_nonnegative(x: f64) -> bool {
|
||||
return x > 0.0f64 || (1.0f64/x) == infinity;
|
||||
}
|
||||
|
||||
/// Returns true if `x` is a zero number (positive or negative zero)
|
||||
pure fn is_zero(x: f64) -> bool {
|
||||
pub pure fn is_zero(x: f64) -> bool {
|
||||
return x == 0.0f64 || x == -0.0f64;
|
||||
}
|
||||
|
||||
/// Returns true if `x`is an infinite number
|
||||
pure fn is_infinite(x: f64) -> bool {
|
||||
pub pure fn is_infinite(x: f64) -> bool {
|
||||
return x == infinity || x == neg_infinity;
|
||||
}
|
||||
|
||||
/// Returns true if `x`is a finite number
|
||||
pure fn is_finite(x: f64) -> bool {
|
||||
pub pure fn is_finite(x: f64) -> bool {
|
||||
return !(is_NaN(x) || is_infinite(x));
|
||||
}
|
||||
|
||||
// FIXME (#1999): add is_normal, is_subnormal, and fpclassify
|
||||
|
||||
/* Module: consts */
|
||||
mod consts {
|
||||
#[legacy_exports];
|
||||
|
||||
pub mod consts {
|
||||
// FIXME (requires Issue #1433 to fix): replace with mathematical
|
||||
// constants from cmath.
|
||||
/// Archimedes' constant
|
||||
const pi: f64 = 3.14159265358979323846264338327950288_f64;
|
||||
pub const pi: f64 = 3.14159265358979323846264338327950288_f64;
|
||||
|
||||
/// pi/2.0
|
||||
const frac_pi_2: f64 = 1.57079632679489661923132169163975144_f64;
|
||||
pub const frac_pi_2: f64 = 1.57079632679489661923132169163975144_f64;
|
||||
|
||||
/// pi/4.0
|
||||
const frac_pi_4: f64 = 0.785398163397448309615660845819875721_f64;
|
||||
pub const frac_pi_4: f64 = 0.785398163397448309615660845819875721_f64;
|
||||
|
||||
/// 1.0/pi
|
||||
const frac_1_pi: f64 = 0.318309886183790671537767526745028724_f64;
|
||||
pub const frac_1_pi: f64 = 0.318309886183790671537767526745028724_f64;
|
||||
|
||||
/// 2.0/pi
|
||||
const frac_2_pi: f64 = 0.636619772367581343075535053490057448_f64;
|
||||
pub const frac_2_pi: f64 = 0.636619772367581343075535053490057448_f64;
|
||||
|
||||
/// 2.0/sqrt(pi)
|
||||
const frac_2_sqrtpi: f64 = 1.12837916709551257389615890312154517_f64;
|
||||
pub const frac_2_sqrtpi: f64 = 1.12837916709551257389615890312154517_f64;
|
||||
|
||||
/// sqrt(2.0)
|
||||
const sqrt2: f64 = 1.41421356237309504880168872420969808_f64;
|
||||
pub const sqrt2: f64 = 1.41421356237309504880168872420969808_f64;
|
||||
|
||||
/// 1.0/sqrt(2.0)
|
||||
const frac_1_sqrt2: f64 = 0.707106781186547524400844362104849039_f64;
|
||||
pub const frac_1_sqrt2: f64 = 0.707106781186547524400844362104849039_f64;
|
||||
|
||||
/// Euler's number
|
||||
const e: f64 = 2.71828182845904523536028747135266250_f64;
|
||||
pub const e: f64 = 2.71828182845904523536028747135266250_f64;
|
||||
|
||||
/// log2(e)
|
||||
const log2_e: f64 = 1.44269504088896340735992468100189214_f64;
|
||||
pub const log2_e: f64 = 1.44269504088896340735992468100189214_f64;
|
||||
|
||||
/// log10(e)
|
||||
const log10_e: f64 = 0.434294481903251827651128918916605082_f64;
|
||||
pub const log10_e: f64 = 0.434294481903251827651128918916605082_f64;
|
||||
|
||||
/// ln(2.0)
|
||||
const ln_2: f64 = 0.693147180559945309417232121458176568_f64;
|
||||
pub const ln_2: f64 = 0.693147180559945309417232121458176568_f64;
|
||||
|
||||
/// ln(10.0)
|
||||
const ln_10: f64 = 2.30258509299404568401799145468436421_f64;
|
||||
pub const ln_10: f64 = 2.30258509299404568401799145468436421_f64;
|
||||
}
|
||||
|
||||
pure fn signbit(x: f64) -> int {
|
||||
pub pure fn signbit(x: f64) -> int {
|
||||
if is_negative(x) { return 1; } else { return 0; }
|
||||
}
|
||||
|
||||
pure fn logarithm(n: f64, b: f64) -> f64 {
|
||||
pub pure fn logarithm(n: f64, b: f64) -> f64 {
|
||||
return log2(n) / log2(b);
|
||||
}
|
||||
|
||||
impl f64: num::Num {
|
||||
pure fn add(&&other: f64) -> f64 { return self + other; }
|
||||
pure fn sub(&&other: f64) -> f64 { return self - other; }
|
||||
pure fn mul(&&other: f64) -> f64 { return self * other; }
|
||||
pure fn div(&&other: f64) -> f64 { return self / other; }
|
||||
pure fn modulo(&&other: f64) -> f64 { return self % other; }
|
||||
pure fn add(other: &f64) -> f64 { return self + *other; }
|
||||
pure fn sub(other: &f64) -> f64 { return self - *other; }
|
||||
pure fn mul(other: &f64) -> f64 { return self * *other; }
|
||||
pure fn div(other: &f64) -> f64 { return self / *other; }
|
||||
pure fn modulo(other: &f64) -> f64 { return self % *other; }
|
||||
pure fn neg() -> f64 { return -self; }
|
||||
|
||||
pure fn to_int() -> int { return self as int; }
|
||||
|
|
|
|||
|
|
@ -11,8 +11,6 @@ Simple compression
|
|||
use libc::{c_void, size_t, c_int};
|
||||
|
||||
extern mod rustrt {
|
||||
#[legacy_exports];
|
||||
|
||||
fn tdefl_compress_mem_to_heap(psrc_buf: *const c_void,
|
||||
src_buf_len: size_t,
|
||||
pout_len: *size_t,
|
||||
|
|
@ -29,14 +27,14 @@ const lz_fast : c_int = 0x1; // LZ with only one probe
|
|||
const lz_norm : c_int = 0x80; // LZ with 128 probes, "normal"
|
||||
const lz_best : c_int = 0xfff; // LZ with 4095 probes, "best"
|
||||
|
||||
fn deflate_bytes(bytes: &[const u8]) -> ~[u8] {
|
||||
pub fn deflate_bytes(bytes: &[const u8]) -> ~[u8] {
|
||||
do vec::as_const_buf(bytes) |b, len| {
|
||||
unsafe {
|
||||
let mut outsz : size_t = 0;
|
||||
let res =
|
||||
rustrt::tdefl_compress_mem_to_heap(b as *c_void,
|
||||
len as size_t,
|
||||
ptr::addr_of(outsz),
|
||||
ptr::addr_of(&outsz),
|
||||
lz_norm);
|
||||
assert res as int != 0;
|
||||
let out = vec::raw::from_buf(res as *u8,
|
||||
|
|
@ -47,14 +45,14 @@ fn deflate_bytes(bytes: &[const u8]) -> ~[u8] {
|
|||
}
|
||||
}
|
||||
|
||||
fn inflate_bytes(bytes: &[const u8]) -> ~[u8] {
|
||||
pub fn inflate_bytes(bytes: &[const u8]) -> ~[u8] {
|
||||
do vec::as_const_buf(bytes) |b, len| {
|
||||
unsafe {
|
||||
let mut outsz : size_t = 0;
|
||||
let res =
|
||||
rustrt::tinfl_decompress_mem_to_heap(b as *c_void,
|
||||
len as size_t,
|
||||
ptr::addr_of(outsz),
|
||||
ptr::addr_of(&outsz),
|
||||
0);
|
||||
assert res as int != 0;
|
||||
let out = vec::raw::from_buf(res as *u8,
|
||||
|
|
@ -71,12 +69,12 @@ fn test_flate_round_trip() {
|
|||
let r = rand::Rng();
|
||||
let mut words = ~[];
|
||||
for 20.times {
|
||||
vec::push(words, r.gen_bytes(r.gen_uint_range(1, 10)));
|
||||
words.push(r.gen_bytes(r.gen_uint_range(1, 10)));
|
||||
}
|
||||
for 20.times {
|
||||
let mut in = ~[];
|
||||
for 2000.times {
|
||||
vec::push_all(in, r.choose(words));
|
||||
in.push_all(r.choose(words));
|
||||
}
|
||||
debug!("de/inflate of %u bytes of random word-sequences",
|
||||
in.len());
|
||||
|
|
|
|||
|
|
@ -7,26 +7,10 @@
|
|||
// Even though this module exports everything defined in it,
|
||||
// because it contains re-exports, we also have to explicitly
|
||||
// export locally defined things. That's a bit annoying.
|
||||
export to_str_common, to_str_exact, to_str, from_str;
|
||||
export add, sub, mul, div, rem, lt, le, eq, ne, ge, gt;
|
||||
export is_positive, is_negative, is_nonpositive, is_nonnegative;
|
||||
export is_zero, is_infinite, is_finite;
|
||||
export NaN, is_NaN, infinity, neg_infinity;
|
||||
export consts;
|
||||
export logarithm;
|
||||
export acos, asin, atan, atan2, cbrt, ceil, copysign, cos, cosh, floor;
|
||||
export erf, erfc, exp, expm1, exp2, abs, abs_sub;
|
||||
export mul_add, fmax, fmin, nextafter, frexp, hypot, ldexp;
|
||||
export lgamma, ln, log_radix, ln1p, log10, log2, ilog_radix;
|
||||
export modf, pow, round, sin, sinh, sqrt, tan, tanh, tgamma, trunc;
|
||||
export signbit;
|
||||
export pow_with_uint;
|
||||
|
||||
export num;
|
||||
|
||||
// export when m_float == c_double
|
||||
|
||||
export j0, j1, jn, y0, y1, yn;
|
||||
|
||||
// PORT this must match in width according to architecture
|
||||
|
||||
|
|
@ -44,56 +28,54 @@ use f64::{j0, j1, jn, y0, y1, yn};
|
|||
use cmp::{Eq, Ord};
|
||||
use num::from_int;
|
||||
|
||||
const NaN: float = 0.0/0.0;
|
||||
pub const NaN: float = 0.0/0.0;
|
||||
|
||||
const infinity: float = 1.0/0.0;
|
||||
pub const infinity: float = 1.0/0.0;
|
||||
|
||||
const neg_infinity: float = -1.0/0.0;
|
||||
pub const neg_infinity: float = -1.0/0.0;
|
||||
|
||||
/* Module: consts */
|
||||
mod consts {
|
||||
#[legacy_exports];
|
||||
|
||||
pub mod consts {
|
||||
// FIXME (requires Issue #1433 to fix): replace with mathematical
|
||||
// constants from cmath.
|
||||
/// Archimedes' constant
|
||||
const pi: float = 3.14159265358979323846264338327950288;
|
||||
pub const pi: float = 3.14159265358979323846264338327950288;
|
||||
|
||||
/// pi/2.0
|
||||
const frac_pi_2: float = 1.57079632679489661923132169163975144;
|
||||
pub const frac_pi_2: float = 1.57079632679489661923132169163975144;
|
||||
|
||||
/// pi/4.0
|
||||
const frac_pi_4: float = 0.785398163397448309615660845819875721;
|
||||
pub const frac_pi_4: float = 0.785398163397448309615660845819875721;
|
||||
|
||||
/// 1.0/pi
|
||||
const frac_1_pi: float = 0.318309886183790671537767526745028724;
|
||||
pub const frac_1_pi: float = 0.318309886183790671537767526745028724;
|
||||
|
||||
/// 2.0/pi
|
||||
const frac_2_pi: float = 0.636619772367581343075535053490057448;
|
||||
pub const frac_2_pi: float = 0.636619772367581343075535053490057448;
|
||||
|
||||
/// 2.0/sqrt(pi)
|
||||
const frac_2_sqrtpi: float = 1.12837916709551257389615890312154517;
|
||||
pub const frac_2_sqrtpi: float = 1.12837916709551257389615890312154517;
|
||||
|
||||
/// sqrt(2.0)
|
||||
const sqrt2: float = 1.41421356237309504880168872420969808;
|
||||
pub const sqrt2: float = 1.41421356237309504880168872420969808;
|
||||
|
||||
/// 1.0/sqrt(2.0)
|
||||
const frac_1_sqrt2: float = 0.707106781186547524400844362104849039;
|
||||
pub const frac_1_sqrt2: float = 0.707106781186547524400844362104849039;
|
||||
|
||||
/// Euler's number
|
||||
const e: float = 2.71828182845904523536028747135266250;
|
||||
pub const e: float = 2.71828182845904523536028747135266250;
|
||||
|
||||
/// log2(e)
|
||||
const log2_e: float = 1.44269504088896340735992468100189214;
|
||||
pub const log2_e: float = 1.44269504088896340735992468100189214;
|
||||
|
||||
/// log10(e)
|
||||
const log10_e: float = 0.434294481903251827651128918916605082;
|
||||
pub const log10_e: float = 0.434294481903251827651128918916605082;
|
||||
|
||||
/// ln(2.0)
|
||||
const ln_2: float = 0.693147180559945309417232121458176568;
|
||||
pub const ln_2: float = 0.693147180559945309417232121458176568;
|
||||
|
||||
/// ln(10.0)
|
||||
const ln_10: float = 2.30258509299404568401799145468436421;
|
||||
pub const ln_10: float = 2.30258509299404568401799145468436421;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -109,7 +91,7 @@ mod consts {
|
|||
* * digits - The number of significant digits
|
||||
* * exact - Whether to enforce the exact number of significant digits
|
||||
*/
|
||||
fn to_str_common(num: float, digits: uint, exact: bool) -> ~str {
|
||||
pub fn to_str_common(num: float, digits: uint, exact: bool) -> ~str {
|
||||
if is_NaN(num) { return ~"NaN"; }
|
||||
if num == infinity { return ~"inf"; }
|
||||
if num == neg_infinity { return ~"-inf"; }
|
||||
|
|
@ -139,11 +121,11 @@ fn to_str_common(num: float, digits: uint, exact: bool) -> ~str {
|
|||
|
||||
// while we still need digits
|
||||
// build stack of digits
|
||||
while ii > 0u && (frac >= epsilon_prime || exact) {
|
||||
while ii > 0 && (frac >= epsilon_prime || exact) {
|
||||
// store the next digit
|
||||
frac *= 10.0;
|
||||
let digit = frac as uint;
|
||||
vec::push(fractionalParts, digit);
|
||||
fractionalParts.push(digit);
|
||||
|
||||
// calculate the next frac
|
||||
frac -= digit as float;
|
||||
|
|
@ -153,25 +135,25 @@ fn to_str_common(num: float, digits: uint, exact: bool) -> ~str {
|
|||
|
||||
let mut acc;
|
||||
let mut racc = ~"";
|
||||
let mut carry = if frac * 10.0 as uint >= 5u { 1u } else { 0u };
|
||||
let mut carry = if frac * 10.0 as uint >= 5 { 1 } else { 0 };
|
||||
|
||||
// turn digits into string
|
||||
// using stack of digits
|
||||
while vec::len(fractionalParts) > 0u {
|
||||
let mut adjusted_digit = carry + vec::pop(fractionalParts);
|
||||
while fractionalParts.is_not_empty() {
|
||||
let mut adjusted_digit = carry + fractionalParts.pop();
|
||||
|
||||
if adjusted_digit == 10u {
|
||||
carry = 1u;
|
||||
adjusted_digit %= 10u
|
||||
if adjusted_digit == 10 {
|
||||
carry = 1;
|
||||
adjusted_digit %= 10
|
||||
} else {
|
||||
carry = 0u
|
||||
carry = 0;
|
||||
};
|
||||
|
||||
racc = uint::str(adjusted_digit) + racc;
|
||||
}
|
||||
|
||||
// pad decimals with trailing zeroes
|
||||
while str::len(racc) < digits && exact {
|
||||
while racc.len() < digits && exact {
|
||||
racc += ~"0"
|
||||
}
|
||||
|
||||
|
|
@ -194,12 +176,12 @@ fn to_str_common(num: float, digits: uint, exact: bool) -> ~str {
|
|||
* * num - The float value
|
||||
* * digits - The number of significant digits
|
||||
*/
|
||||
fn to_str_exact(num: float, digits: uint) -> ~str {
|
||||
pub fn to_str_exact(num: float, digits: uint) -> ~str {
|
||||
to_str_common(num, digits, true)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_str_exact_do_decimal() {
|
||||
pub fn test_to_str_exact_do_decimal() {
|
||||
let s = to_str_exact(5.0, 4u);
|
||||
assert s == ~"5.0000";
|
||||
}
|
||||
|
|
@ -214,7 +196,7 @@ fn test_to_str_exact_do_decimal() {
|
|||
* * num - The float value
|
||||
* * digits - The number of significant digits
|
||||
*/
|
||||
fn to_str(num: float, digits: uint) -> ~str {
|
||||
pub fn to_str(num: float, digits: uint) -> ~str {
|
||||
to_str_common(num, digits, false)
|
||||
}
|
||||
|
||||
|
|
@ -244,7 +226,7 @@ fn to_str(num: float, digits: uint) -> ~str {
|
|||
* `none` if the string did not represent a valid number. Otherwise,
|
||||
* `Some(n)` where `n` is the floating-point number represented by `[num]`.
|
||||
*/
|
||||
fn from_str(num: &str) -> Option<float> {
|
||||
pub fn from_str(num: &str) -> Option<float> {
|
||||
if num == "inf" {
|
||||
return Some(infinity as float);
|
||||
} else if num == "-inf" {
|
||||
|
|
@ -379,7 +361,7 @@ fn from_str(num: &str) -> Option<float> {
|
|||
*
|
||||
* `NaN` if both `x` and `pow` are `0u`, otherwise `x^pow`
|
||||
*/
|
||||
fn pow_with_uint(base: uint, pow: uint) -> float {
|
||||
pub fn pow_with_uint(base: uint, pow: uint) -> float {
|
||||
if base == 0u {
|
||||
if pow == 0u {
|
||||
return NaN as float;
|
||||
|
|
@ -399,40 +381,40 @@ fn pow_with_uint(base: uint, pow: uint) -> float {
|
|||
return total;
|
||||
}
|
||||
|
||||
pure fn is_positive(x: float) -> bool { f64::is_positive(x as f64) }
|
||||
pure fn is_negative(x: float) -> bool { f64::is_negative(x as f64) }
|
||||
pure fn is_nonpositive(x: float) -> bool { f64::is_nonpositive(x as f64) }
|
||||
pure fn is_nonnegative(x: float) -> bool { f64::is_nonnegative(x as f64) }
|
||||
pure fn is_zero(x: float) -> bool { f64::is_zero(x as f64) }
|
||||
pure fn is_infinite(x: float) -> bool { f64::is_infinite(x as f64) }
|
||||
pure fn is_finite(x: float) -> bool { f64::is_finite(x as f64) }
|
||||
pure fn is_NaN(x: float) -> bool { f64::is_NaN(x as f64) }
|
||||
pub pure fn is_positive(x: float) -> bool { f64::is_positive(x as f64) }
|
||||
pub pure fn is_negative(x: float) -> bool { f64::is_negative(x as f64) }
|
||||
pub pure fn is_nonpositive(x: float) -> bool { f64::is_nonpositive(x as f64) }
|
||||
pub pure fn is_nonnegative(x: float) -> bool { f64::is_nonnegative(x as f64) }
|
||||
pub pure fn is_zero(x: float) -> bool { f64::is_zero(x as f64) }
|
||||
pub pure fn is_infinite(x: float) -> bool { f64::is_infinite(x as f64) }
|
||||
pub pure fn is_finite(x: float) -> bool { f64::is_finite(x as f64) }
|
||||
pub pure fn is_NaN(x: float) -> bool { f64::is_NaN(x as f64) }
|
||||
|
||||
pure fn abs(x: float) -> float { f64::abs(x as f64) as float }
|
||||
pure fn sqrt(x: float) -> float { f64::sqrt(x as f64) as float }
|
||||
pure fn atan(x: float) -> float { f64::atan(x as f64) as float }
|
||||
pure fn sin(x: float) -> float { f64::sin(x as f64) as float }
|
||||
pure fn cos(x: float) -> float { f64::cos(x as f64) as float }
|
||||
pure fn tan(x: float) -> float { f64::tan(x as f64) as float }
|
||||
pub pure fn abs(x: float) -> float { f64::abs(x as f64) as float }
|
||||
pub pure fn sqrt(x: float) -> float { f64::sqrt(x as f64) as float }
|
||||
pub pure fn atan(x: float) -> float { f64::atan(x as f64) as float }
|
||||
pub pure fn sin(x: float) -> float { f64::sin(x as f64) as float }
|
||||
pub pure fn cos(x: float) -> float { f64::cos(x as f64) as float }
|
||||
pub pure fn tan(x: float) -> float { f64::tan(x as f64) as float }
|
||||
|
||||
impl float : Eq {
|
||||
pure fn eq(other: &float) -> bool { self == (*other) }
|
||||
pure fn ne(other: &float) -> bool { self != (*other) }
|
||||
pub pure fn eq(other: &float) -> bool { self == (*other) }
|
||||
pub pure fn ne(other: &float) -> bool { self != (*other) }
|
||||
}
|
||||
|
||||
impl float : Ord {
|
||||
pure fn lt(other: &float) -> bool { self < (*other) }
|
||||
pure fn le(other: &float) -> bool { self <= (*other) }
|
||||
pure fn ge(other: &float) -> bool { self >= (*other) }
|
||||
pure fn gt(other: &float) -> bool { self > (*other) }
|
||||
pub pure fn lt(other: &float) -> bool { self < (*other) }
|
||||
pub pure fn le(other: &float) -> bool { self <= (*other) }
|
||||
pub pure fn ge(other: &float) -> bool { self >= (*other) }
|
||||
pub pure fn gt(other: &float) -> bool { self > (*other) }
|
||||
}
|
||||
|
||||
impl float: num::Num {
|
||||
pure fn add(&&other: float) -> float { return self + other; }
|
||||
pure fn sub(&&other: float) -> float { return self - other; }
|
||||
pure fn mul(&&other: float) -> float { return self * other; }
|
||||
pure fn div(&&other: float) -> float { return self / other; }
|
||||
pure fn modulo(&&other: float) -> float { return self % other; }
|
||||
pub pure fn add(other: &float) -> float { return self + *other; }
|
||||
pub pure fn sub(other: &float) -> float { return self - *other; }
|
||||
pub pure fn mul(other: &float) -> float { return self * *other; }
|
||||
pub pure fn div(other: &float) -> float { return self / *other; }
|
||||
pure fn modulo(other: &float) -> float { return self % *other; }
|
||||
pure fn neg() -> float { return -self; }
|
||||
|
||||
pure fn to_int() -> int { return self as int; }
|
||||
|
|
@ -440,7 +422,7 @@ impl float: num::Num {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_str() {
|
||||
pub fn test_from_str() {
|
||||
assert from_str(~"3") == Some(3.);
|
||||
assert from_str(~"3") == Some(3.);
|
||||
assert from_str(~"3.14") == Some(3.14);
|
||||
|
|
@ -483,7 +465,7 @@ fn test_from_str() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_positive() {
|
||||
pub fn test_positive() {
|
||||
assert(is_positive(infinity));
|
||||
assert(is_positive(1.));
|
||||
assert(is_positive(0.));
|
||||
|
|
@ -494,7 +476,7 @@ fn test_positive() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_negative() {
|
||||
pub fn test_negative() {
|
||||
assert(!is_negative(infinity));
|
||||
assert(!is_negative(1.));
|
||||
assert(!is_negative(0.));
|
||||
|
|
@ -505,7 +487,7 @@ fn test_negative() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_nonpositive() {
|
||||
pub fn test_nonpositive() {
|
||||
assert(!is_nonpositive(infinity));
|
||||
assert(!is_nonpositive(1.));
|
||||
assert(!is_nonpositive(0.));
|
||||
|
|
@ -516,7 +498,7 @@ fn test_nonpositive() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_nonnegative() {
|
||||
pub fn test_nonnegative() {
|
||||
assert(is_nonnegative(infinity));
|
||||
assert(is_nonnegative(1.));
|
||||
assert(is_nonnegative(0.));
|
||||
|
|
@ -527,24 +509,24 @@ fn test_nonnegative() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_str_inf() {
|
||||
pub fn test_to_str_inf() {
|
||||
assert to_str(infinity, 10u) == ~"inf";
|
||||
assert to_str(-infinity, 10u) == ~"-inf";
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_traits() {
|
||||
pub fn test_traits() {
|
||||
fn test<U:num::Num cmp::Eq>(ten: &U) {
|
||||
assert (ten.to_int() == 10);
|
||||
|
||||
let two: U = from_int(2);
|
||||
assert (two.to_int() == 2);
|
||||
|
||||
assert (ten.add(two) == from_int(12));
|
||||
assert (ten.sub(two) == from_int(8));
|
||||
assert (ten.mul(two) == from_int(20));
|
||||
assert (ten.div(two) == from_int(5));
|
||||
assert (ten.modulo(two) == from_int(0));
|
||||
assert (ten.add(&two) == from_int(12));
|
||||
assert (ten.sub(&two) == from_int(8));
|
||||
assert (ten.mul(&two) == from_int(20));
|
||||
assert (ten.div(&two) == from_int(5));
|
||||
assert (ten.modulo(&two) == from_int(0));
|
||||
}
|
||||
|
||||
test(&10.0);
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
use option::Option;
|
||||
|
||||
trait FromStr {
|
||||
pub trait FromStr {
|
||||
static fn from_str(s: &str) -> Option<self>;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
// tjc: re-forbid deprecated modes after snapshot
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
/*!
|
||||
|
|
@ -19,20 +19,8 @@ use either::Either;
|
|||
use pipes::recv;
|
||||
use cast::copy_lifetime;
|
||||
|
||||
export Future;
|
||||
export extensions;
|
||||
export from_value;
|
||||
export from_port;
|
||||
export from_fn;
|
||||
export get;
|
||||
export with;
|
||||
export spawn;
|
||||
|
||||
// for task.rs
|
||||
export future_pipe;
|
||||
|
||||
#[doc = "The future type"]
|
||||
struct Future<A> {
|
||||
pub struct Future<A> {
|
||||
/*priv*/ mut state: FutureState<A>,
|
||||
|
||||
// FIXME(#2829) -- futures should not be copyable, because they close
|
||||
|
|
@ -67,7 +55,7 @@ impl<A> Future<A> {
|
|||
}
|
||||
}
|
||||
|
||||
fn from_value<A>(+val: A) -> Future<A> {
|
||||
pub fn from_value<A>(val: A) -> Future<A> {
|
||||
/*!
|
||||
* Create a future from a value
|
||||
*
|
||||
|
|
@ -78,7 +66,8 @@ fn from_value<A>(+val: A) -> Future<A> {
|
|||
Future {state: Forced(~(move val))}
|
||||
}
|
||||
|
||||
fn from_port<A:Send>(+port: future_pipe::client::waiting<A>) -> Future<A> {
|
||||
pub fn from_port<A:Send>(port: future_pipe::client::waiting<A>) ->
|
||||
Future<A> {
|
||||
/*!
|
||||
* Create a future from a port
|
||||
*
|
||||
|
|
@ -97,7 +86,7 @@ fn from_port<A:Send>(+port: future_pipe::client::waiting<A>) -> Future<A> {
|
|||
}
|
||||
}
|
||||
|
||||
fn from_fn<A>(+f: ~fn() -> A) -> Future<A> {
|
||||
pub fn from_fn<A>(+f: ~fn() -> A) -> Future<A> {
|
||||
/*!
|
||||
* Create a future from a function.
|
||||
*
|
||||
|
|
@ -109,7 +98,7 @@ fn from_fn<A>(+f: ~fn() -> A) -> Future<A> {
|
|||
Future {state: Pending(move f)}
|
||||
}
|
||||
|
||||
fn spawn<A:Send>(+blk: fn~() -> A) -> Future<A> {
|
||||
pub fn spawn<A:Send>(+blk: fn~() -> A) -> Future<A> {
|
||||
/*!
|
||||
* Create a future from a unique closure.
|
||||
*
|
||||
|
|
@ -122,7 +111,7 @@ fn spawn<A:Send>(+blk: fn~() -> A) -> Future<A> {
|
|||
}))
|
||||
}
|
||||
|
||||
fn get_ref<A>(future: &r/Future<A>) -> &r/A {
|
||||
pub fn get_ref<A>(future: &r/Future<A>) -> &r/A {
|
||||
/*!
|
||||
* Executes the future's closure and then returns a borrowed
|
||||
* pointer to the result. The borrowed pointer lasts as long as
|
||||
|
|
@ -160,13 +149,13 @@ fn get_ref<A>(future: &r/Future<A>) -> &r/A {
|
|||
}
|
||||
}
|
||||
|
||||
fn get<A:Copy>(future: &Future<A>) -> A {
|
||||
pub fn get<A:Copy>(future: &Future<A>) -> A {
|
||||
//! Get the value of the future
|
||||
|
||||
*get_ref(future)
|
||||
}
|
||||
|
||||
fn with<A,B>(future: &Future<A>, blk: fn((&A)) -> B) -> B {
|
||||
pub fn with<A,B>(future: &Future<A>, blk: fn((&A)) -> B) -> B {
|
||||
//! Work with the value without copying it
|
||||
|
||||
blk(get_ref(future))
|
||||
|
|
@ -179,16 +168,15 @@ proto! future_pipe (
|
|||
)
|
||||
|
||||
#[allow(non_implicitly_copyable_typarams)]
|
||||
mod test {
|
||||
#[legacy_exports];
|
||||
pub mod test {
|
||||
#[test]
|
||||
fn test_from_value() {
|
||||
pub fn test_from_value() {
|
||||
let f = from_value(~"snail");
|
||||
assert get(&f) == ~"snail";
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_port() {
|
||||
pub fn test_from_port() {
|
||||
let (po, ch) = future_pipe::init();
|
||||
future_pipe::server::completed(ch, ~"whale");
|
||||
let f = from_port(po);
|
||||
|
|
@ -196,43 +184,43 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_fn() {
|
||||
pub fn test_from_fn() {
|
||||
let f = from_fn(|| ~"brail");
|
||||
assert get(&f) == ~"brail";
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_interface_get() {
|
||||
pub fn test_interface_get() {
|
||||
let f = from_value(~"fail");
|
||||
assert f.get() == ~"fail";
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_with() {
|
||||
pub fn test_with() {
|
||||
let f = from_value(~"nail");
|
||||
assert with(&f, |v| copy *v) == ~"nail";
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_ref_method() {
|
||||
pub fn test_get_ref_method() {
|
||||
let f = from_value(22);
|
||||
assert *f.get_ref() == 22;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_ref_fn() {
|
||||
pub fn test_get_ref_fn() {
|
||||
let f = from_value(22);
|
||||
assert *get_ref(&f) == 22;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_interface_with() {
|
||||
pub fn test_interface_with() {
|
||||
let f = from_value(~"kale");
|
||||
assert f.with(|v| copy *v) == ~"kale";
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_spawn() {
|
||||
pub fn test_spawn() {
|
||||
let f = spawn(|| ~"bale");
|
||||
assert get(&f) == ~"bale";
|
||||
}
|
||||
|
|
@ -240,13 +228,13 @@ mod test {
|
|||
#[test]
|
||||
#[should_fail]
|
||||
#[ignore(cfg(target_os = "win32"))]
|
||||
fn test_futurefail() {
|
||||
pub fn test_futurefail() {
|
||||
let f = spawn(|| fail);
|
||||
let _x: ~str = get(&f);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sendable_future() {
|
||||
pub fn test_sendable_future() {
|
||||
let expected = ~"schlorf";
|
||||
let f = do spawn |copy expected| { copy expected };
|
||||
do task::spawn {
|
||||
|
|
|
|||
|
|
@ -29,15 +29,11 @@ with destructors.
|
|||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use stackwalk::Word;
|
||||
pub use stackwalk::Word;
|
||||
use libc::size_t;
|
||||
use libc::uintptr_t;
|
||||
use send_map::linear::LinearMap;
|
||||
|
||||
export Word;
|
||||
export gc;
|
||||
export cleanup_stack_for_failure;
|
||||
|
||||
// Mirrors rust_stack.h stk_seg
|
||||
struct StackSegment {
|
||||
prev: *StackSegment,
|
||||
|
|
@ -268,7 +264,7 @@ unsafe fn walk_gc_roots(mem: Memory, sentinel: **Word, visitor: Visitor) {
|
|||
}
|
||||
}
|
||||
|
||||
fn gc() {
|
||||
pub fn gc() {
|
||||
unsafe {
|
||||
// Abort when GC is disabled.
|
||||
if get_safe_point_count() == 0 {
|
||||
|
|
@ -301,7 +297,7 @@ fn expect_sentinel() -> bool { false }
|
|||
// This should only be called from fail, as it will drop the roots
|
||||
// which are *live* on the stack, rather than dropping those that are
|
||||
// dead.
|
||||
fn cleanup_stack_for_failure() {
|
||||
pub fn cleanup_stack_for_failure() {
|
||||
unsafe {
|
||||
// Abort when GC is disabled.
|
||||
if get_safe_point_count() == 0 {
|
||||
|
|
@ -320,7 +316,7 @@ fn cleanup_stack_for_failure() {
|
|||
// own stack roots on the stack anyway.
|
||||
let sentinel_box = ~0;
|
||||
let sentinel: **Word = if expect_sentinel() {
|
||||
cast::reinterpret_cast(&ptr::addr_of(sentinel_box))
|
||||
cast::reinterpret_cast(&ptr::addr_of(&sentinel_box))
|
||||
} else {
|
||||
ptr::null()
|
||||
};
|
||||
|
|
|
|||
|
|
@ -17,9 +17,6 @@ use io::Writer;
|
|||
use io::WriterUtil;
|
||||
use to_bytes::IterBytes;
|
||||
|
||||
export Streaming, State, Hash, HashUtil;
|
||||
export default_state;
|
||||
|
||||
/**
|
||||
* Types that can meaningfully be hashed should implement this.
|
||||
*
|
||||
|
|
@ -32,7 +29,7 @@ export default_state;
|
|||
* the rest. This is the recommended approach, since constructing
|
||||
* good keyed hash functions is quite difficult.
|
||||
*/
|
||||
trait Hash {
|
||||
pub trait Hash {
|
||||
/**
|
||||
* Compute a "keyed" hash of the value implementing the trait,
|
||||
* taking `k0` and `k1` as "keying" parameters that randomize or
|
||||
|
|
@ -49,7 +46,7 @@ trait Hash {
|
|||
}
|
||||
|
||||
// When we have default methods, won't need this.
|
||||
trait HashUtil {
|
||||
pub trait HashUtil {
|
||||
pure fn hash() -> u64;
|
||||
}
|
||||
|
||||
|
|
@ -59,7 +56,7 @@ impl <A: Hash> A: HashUtil {
|
|||
}
|
||||
|
||||
/// Streaming hash-functions should implement this.
|
||||
trait Streaming {
|
||||
pub trait Streaming {
|
||||
fn input((&[const u8]));
|
||||
// These can be refactored some when we have default methods.
|
||||
fn result_bytes() -> ~[u8];
|
||||
|
|
@ -139,15 +136,15 @@ pure fn hash_keyed_5<A: IterBytes,
|
|||
|
||||
// Implement State as SipState
|
||||
|
||||
type State = SipState;
|
||||
pub type State = SipState;
|
||||
|
||||
#[inline(always)]
|
||||
fn State(k0: u64, k1: u64) -> State {
|
||||
pub fn State(k0: u64, k1: u64) -> State {
|
||||
SipState(k0, k1)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn default_state() -> State {
|
||||
pub fn default_state() -> State {
|
||||
State(0,0)
|
||||
}
|
||||
|
||||
|
|
@ -361,7 +358,7 @@ impl &SipState : Streaming {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_siphash() {
|
||||
pub fn test_siphash() {
|
||||
let vecs : [[u8]/8]/64 = [
|
||||
[ 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, ]/_,
|
||||
[ 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, ]/_,
|
||||
|
|
@ -468,26 +465,26 @@ fn test_siphash() {
|
|||
}
|
||||
|
||||
#[test] #[cfg(target_arch = "arm")]
|
||||
fn test_hash_uint() {
|
||||
pub fn test_hash_uint() {
|
||||
let val = 0xdeadbeef_deadbeef_u64;
|
||||
assert (val as u64).hash() != (val as uint).hash();
|
||||
assert (val as u32).hash() == (val as uint).hash();
|
||||
}
|
||||
#[test] #[cfg(target_arch = "x86_64")]
|
||||
fn test_hash_uint() {
|
||||
pub fn test_hash_uint() {
|
||||
let val = 0xdeadbeef_deadbeef_u64;
|
||||
assert (val as u64).hash() == (val as uint).hash();
|
||||
assert (val as u32).hash() != (val as uint).hash();
|
||||
}
|
||||
#[test] #[cfg(target_arch = "x86")]
|
||||
fn test_hash_uint() {
|
||||
pub fn test_hash_uint() {
|
||||
let val = 0xdeadbeef_deadbeef_u64;
|
||||
assert (val as u64).hash() != (val as uint).hash();
|
||||
assert (val as u32).hash() == (val as uint).hash();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hash_idempotent() {
|
||||
pub fn test_hash_idempotent() {
|
||||
let val64 = 0xdeadbeef_deadbeef_u64;
|
||||
val64.hash() == val64.hash();
|
||||
let val32 = 0xdeadbeef_u32;
|
||||
|
|
@ -495,7 +492,7 @@ fn test_hash_idempotent() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_hash_no_bytes_dropped_64() {
|
||||
pub fn test_hash_no_bytes_dropped_64() {
|
||||
let val = 0xdeadbeef_deadbeef_u64;
|
||||
|
||||
assert val.hash() != zero_byte(val, 0).hash();
|
||||
|
|
@ -514,7 +511,7 @@ fn test_hash_no_bytes_dropped_64() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_hash_no_bytes_dropped_32() {
|
||||
pub fn test_hash_no_bytes_dropped_32() {
|
||||
let val = 0xdeadbeef_u32;
|
||||
|
||||
assert val.hash() != zero_byte(val, 0).hash();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
// tjc: re-forbid deprecated modes after snapshot
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use T = inst::T;
|
||||
|
|
@ -7,49 +7,36 @@ use cmp::{Eq, Ord};
|
|||
use from_str::FromStr;
|
||||
use num::from_int;
|
||||
|
||||
export min_value, max_value;
|
||||
export min, max;
|
||||
export add, sub, mul, div, rem;
|
||||
export lt, le, eq, ne, ge, gt;
|
||||
export is_positive, is_negative;
|
||||
export is_nonpositive, is_nonnegative;
|
||||
export range;
|
||||
export compl;
|
||||
export abs;
|
||||
export parse_bytes, from_str, to_str, to_str_bytes, str;
|
||||
export num, ord, eq, times, timesi;
|
||||
export bits, bytes;
|
||||
pub const bits : uint = inst::bits;
|
||||
pub const bytes : uint = (inst::bits / 8);
|
||||
|
||||
const bits : uint = inst::bits;
|
||||
const bytes : uint = (inst::bits / 8);
|
||||
pub const min_value: T = (-1 as T) << (bits - 1);
|
||||
pub const max_value: T = min_value - 1 as T;
|
||||
|
||||
const min_value: T = (-1 as T) << (bits - 1);
|
||||
const max_value: T = min_value - 1 as T;
|
||||
pub pure fn min(x: T, y: T) -> T { if x < y { x } else { y } }
|
||||
pub pure fn max(x: T, y: T) -> T { if x > y { x } else { y } }
|
||||
|
||||
pure fn min(x: T, y: T) -> T { if x < y { x } else { y } }
|
||||
pure fn max(x: T, y: T) -> T { if x > y { x } else { y } }
|
||||
pub pure fn add(x: T, y: T) -> T { x + y }
|
||||
pub pure fn sub(x: T, y: T) -> T { x - y }
|
||||
pub pure fn mul(x: T, y: T) -> T { x * y }
|
||||
pub pure fn div(x: T, y: T) -> T { x / y }
|
||||
pub pure fn rem(x: T, y: T) -> T { x % y }
|
||||
|
||||
pure fn add(x: T, y: T) -> T { x + y }
|
||||
pure fn sub(x: T, y: T) -> T { x - y }
|
||||
pure fn mul(x: T, y: T) -> T { x * y }
|
||||
pure fn div(x: T, y: T) -> T { x / y }
|
||||
pure fn rem(x: T, y: T) -> T { x % y }
|
||||
pub pure fn lt(x: T, y: T) -> bool { x < y }
|
||||
pub pure fn le(x: T, y: T) -> bool { x <= y }
|
||||
pub pure fn eq(x: T, y: T) -> bool { x == y }
|
||||
pub pure fn ne(x: T, y: T) -> bool { x != y }
|
||||
pub pure fn ge(x: T, y: T) -> bool { x >= y }
|
||||
pub pure fn gt(x: T, y: T) -> bool { x > y }
|
||||
|
||||
pure fn lt(x: T, y: T) -> bool { x < y }
|
||||
pure fn le(x: T, y: T) -> bool { x <= y }
|
||||
pure fn eq(x: T, y: T) -> bool { x == y }
|
||||
pure fn ne(x: T, y: T) -> bool { x != y }
|
||||
pure fn ge(x: T, y: T) -> bool { x >= y }
|
||||
pure fn gt(x: T, y: T) -> bool { x > y }
|
||||
|
||||
pure fn is_positive(x: T) -> bool { x > 0 as T }
|
||||
pure fn is_negative(x: T) -> bool { x < 0 as T }
|
||||
pure fn is_nonpositive(x: T) -> bool { x <= 0 as T }
|
||||
pure fn is_nonnegative(x: T) -> bool { x >= 0 as T }
|
||||
pub pure fn is_positive(x: T) -> bool { x > 0 as T }
|
||||
pub pure fn is_negative(x: T) -> bool { x < 0 as T }
|
||||
pub pure fn is_nonpositive(x: T) -> bool { x <= 0 as T }
|
||||
pub pure fn is_nonnegative(x: T) -> bool { x >= 0 as T }
|
||||
|
||||
#[inline(always)]
|
||||
/// Iterate over the range [`lo`..`hi`)
|
||||
fn range(lo: T, hi: T, it: fn(T) -> bool) {
|
||||
pub fn range(lo: T, hi: T, it: fn(T) -> bool) {
|
||||
let mut i = lo;
|
||||
while i < hi {
|
||||
if !it(i) { break }
|
||||
|
|
@ -58,13 +45,13 @@ fn range(lo: T, hi: T, it: fn(T) -> bool) {
|
|||
}
|
||||
|
||||
/// Computes the bitwise complement
|
||||
pure fn compl(i: T) -> T {
|
||||
pub pure fn compl(i: T) -> T {
|
||||
-1 as T ^ i
|
||||
}
|
||||
|
||||
/// Computes the absolute value
|
||||
// FIXME: abs should return an unsigned int (#2353)
|
||||
pure fn abs(i: T) -> T {
|
||||
pub pure fn abs(i: T) -> T {
|
||||
if is_negative(i) { -i } else { i }
|
||||
}
|
||||
|
||||
|
|
@ -81,11 +68,11 @@ impl T : Eq {
|
|||
}
|
||||
|
||||
impl T: num::Num {
|
||||
pure fn add(&&other: T) -> T { return self + other; }
|
||||
pure fn sub(&&other: T) -> T { return self - other; }
|
||||
pure fn mul(&&other: T) -> T { return self * other; }
|
||||
pure fn div(&&other: T) -> T { return self / other; }
|
||||
pure fn modulo(&&other: T) -> T { return self % other; }
|
||||
pure fn add(other: &T) -> T { return self + *other; }
|
||||
pure fn sub(other: &T) -> T { return self - *other; }
|
||||
pure fn mul(other: &T) -> T { return self * *other; }
|
||||
pure fn div(other: &T) -> T { return self / *other; }
|
||||
pure fn modulo(other: &T) -> T { return self % *other; }
|
||||
pure fn neg() -> T { return -self; }
|
||||
|
||||
pure fn to_int() -> int { return self as int; }
|
||||
|
|
@ -137,7 +124,7 @@ impl T: iter::TimesIx {
|
|||
* * buf - A byte buffer
|
||||
* * radix - The base of the number
|
||||
*/
|
||||
fn parse_bytes(buf: &[u8], radix: uint) -> Option<T> {
|
||||
pub fn parse_bytes(buf: &[u8], radix: uint) -> Option<T> {
|
||||
if vec::len(buf) == 0u { return None; }
|
||||
let mut i = vec::len(buf) - 1u;
|
||||
let mut start = 0u;
|
||||
|
|
@ -160,14 +147,14 @@ fn parse_bytes(buf: &[u8], radix: uint) -> Option<T> {
|
|||
}
|
||||
|
||||
/// Parse a string to an int
|
||||
fn from_str(s: &str) -> Option<T> { parse_bytes(str::to_bytes(s), 10u) }
|
||||
pub fn from_str(s: &str) -> Option<T> { parse_bytes(str::to_bytes(s), 10u) }
|
||||
|
||||
impl T : FromStr {
|
||||
static fn from_str(s: &str) -> Option<T> { from_str(s) }
|
||||
}
|
||||
|
||||
/// Convert to a string in a given base
|
||||
fn to_str(n: T, radix: uint) -> ~str {
|
||||
pub fn to_str(n: T, radix: uint) -> ~str {
|
||||
do to_str_bytes(n, radix) |slice| {
|
||||
do vec::as_imm_buf(slice) |p, len| {
|
||||
unsafe { str::raw::from_buf_len(p, len) }
|
||||
|
|
@ -175,7 +162,7 @@ fn to_str(n: T, radix: uint) -> ~str {
|
|||
}
|
||||
}
|
||||
|
||||
fn to_str_bytes<U>(n: T, radix: uint, f: fn(v: &[u8]) -> U) -> U {
|
||||
pub fn to_str_bytes<U>(n: T, radix: uint, f: fn(v: &[u8]) -> U) -> U {
|
||||
if n < 0 as T {
|
||||
uint::to_str_bytes(true, -n as uint, radix, f)
|
||||
} else {
|
||||
|
|
@ -184,7 +171,7 @@ fn to_str_bytes<U>(n: T, radix: uint, f: fn(v: &[u8]) -> U) -> U {
|
|||
}
|
||||
|
||||
/// Convert to a string
|
||||
fn str(i: T) -> ~str { return to_str(i, 10u); }
|
||||
pub fn str(i: T) -> ~str { return to_str(i, 10u); }
|
||||
|
||||
// FIXME: Has alignment issues on windows and 32-bit linux (#2609)
|
||||
#[test]
|
||||
|
|
@ -244,17 +231,17 @@ fn test_to_str() {
|
|||
|
||||
#[test]
|
||||
fn test_interfaces() {
|
||||
fn test<U:num::Num cmp::Eq>(+ten: U) {
|
||||
fn test<U:num::Num cmp::Eq>(ten: U) {
|
||||
assert (ten.to_int() == 10);
|
||||
|
||||
let two: U = from_int(2);
|
||||
assert (two.to_int() == 2);
|
||||
|
||||
assert (ten.add(two) == from_int(12));
|
||||
assert (ten.sub(two) == from_int(8));
|
||||
assert (ten.mul(two) == from_int(20));
|
||||
assert (ten.div(two) == from_int(5));
|
||||
assert (ten.modulo(two) == from_int(0));
|
||||
assert (ten.add(&two) == from_int(12));
|
||||
assert (ten.sub(&two) == from_int(8));
|
||||
assert (ten.mul(&two) == from_int(20));
|
||||
assert (ten.div(&two) == from_int(5));
|
||||
assert (ten.modulo(&two) == from_int(0));
|
||||
assert (ten.neg() == from_int(-10));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
type T = i16;
|
||||
const bits: uint = u16::bits;
|
||||
pub type T = i16;
|
||||
pub const bits: uint = u16::bits;
|
||||
|
|
@ -1,2 +1,2 @@
|
|||
type T = i32;
|
||||
const bits: uint = u32::bits;
|
||||
pub type T = i32;
|
||||
pub const bits: uint = u32::bits;
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
type T = i64;
|
||||
const bits: uint = u64::bits;
|
||||
pub type T = i64;
|
||||
pub const bits: uint = u64::bits;
|
||||
|
|
@ -1,2 +1,2 @@
|
|||
type T = i8;
|
||||
const bits: uint = u8::bits;
|
||||
pub type T = i8;
|
||||
pub const bits: uint = u8::bits;
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
type T = int;
|
||||
const bits: uint = uint::bits;
|
||||
pub type T = int;
|
||||
pub const bits: uint = uint::bits;
|
||||
|
||||
/// Returns `base` raised to the power of `exponent`
|
||||
fn pow(base: int, exponent: uint) -> int {
|
||||
pub fn pow(base: int, exponent: uint) -> int {
|
||||
if exponent == 0u { return 1; } //Not mathemtically true if ~[base == 0]
|
||||
if base == 0 { return 0; }
|
||||
let mut my_pow = exponent;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ type fd_t = c_int;
|
|||
|
||||
#[abi = "cdecl"]
|
||||
extern mod rustrt {
|
||||
#[legacy_exports];
|
||||
fn rust_get_stdin() -> *libc::FILE;
|
||||
fn rust_get_stdout() -> *libc::FILE;
|
||||
fn rust_get_stderr() -> *libc::FILE;
|
||||
|
|
@ -27,11 +26,11 @@ extern mod rustrt {
|
|||
|
||||
// FIXME (#2004): This is all buffered. We might need an unbuffered variant
|
||||
// as well
|
||||
enum SeekStyle { SeekSet, SeekEnd, SeekCur, }
|
||||
pub enum SeekStyle { SeekSet, SeekEnd, SeekCur, }
|
||||
|
||||
|
||||
// The raw underlying reader trait. All readers must implement this.
|
||||
trait Reader {
|
||||
pub trait Reader {
|
||||
// FIXME (#2004): Seekable really should be orthogonal.
|
||||
|
||||
// FIXME (#2982): This should probably return an error.
|
||||
|
|
@ -45,19 +44,30 @@ trait Reader {
|
|||
|
||||
// Generic utility functions defined on readers
|
||||
|
||||
trait ReaderUtil {
|
||||
pub trait ReaderUtil {
|
||||
fn read_bytes(len: uint) -> ~[u8];
|
||||
fn read_line() -> ~str;
|
||||
|
||||
fn read_chars(n: uint) -> ~[char];
|
||||
fn read_char() -> char;
|
||||
fn read_c_str() -> ~str;
|
||||
fn read_le_uint(size: uint) -> uint;
|
||||
fn read_le_int(size: uint) -> int;
|
||||
fn read_be_uint(size: uint) -> uint;
|
||||
fn read_whole_stream() -> ~[u8];
|
||||
fn each_byte(it: fn(int) -> bool);
|
||||
fn each_char(it: fn(char) -> bool);
|
||||
fn each_line(it: fn((&str)) -> bool);
|
||||
}
|
||||
|
||||
impl<T: Reader> T : ReaderUtil {
|
||||
fn read_bytes(len: uint) -> ~[u8] {
|
||||
let mut buf = vec::with_capacity(len);
|
||||
unsafe { vec::raw::set_len(buf, len); }
|
||||
unsafe { vec::raw::set_len(&mut buf, len); }
|
||||
|
||||
let count = self.read(buf, len);
|
||||
|
||||
unsafe { vec::raw::set_len(buf, count); }
|
||||
unsafe { vec::raw::set_len(&mut buf, count); }
|
||||
move buf
|
||||
}
|
||||
fn read_line() -> ~str {
|
||||
|
|
@ -65,78 +75,78 @@ impl<T: Reader> T : ReaderUtil {
|
|||
loop {
|
||||
let ch = self.read_byte();
|
||||
if ch == -1 || ch == 10 { break; }
|
||||
vec::push(buf, ch as u8);
|
||||
buf.push(ch as u8);
|
||||
}
|
||||
str::from_bytes(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl Reader {
|
||||
fn read_chars(n: uint) -> ~[char] {
|
||||
// returns the (consumed offset, n_req), appends characters to &chars
|
||||
fn chars_from_bytes(buf: ~[u8], &chars: ~[char]) -> (uint, uint) {
|
||||
let mut i = 0u;
|
||||
while i < vec::len(buf) {
|
||||
fn chars_from_bytes<T: Reader>(buf: &~[u8], chars: &mut ~[char])
|
||||
-> (uint, uint) {
|
||||
let mut i = 0;
|
||||
let buf_len = buf.len();
|
||||
while i < buf_len {
|
||||
let b0 = buf[i];
|
||||
let w = str::utf8_char_width(b0);
|
||||
let end = i + w;
|
||||
i += 1u;
|
||||
assert (w > 0u);
|
||||
if w == 1u {
|
||||
vec::push(chars, b0 as char );
|
||||
i += 1;
|
||||
assert (w > 0);
|
||||
if w == 1 {
|
||||
chars.push(b0 as char);
|
||||
loop;
|
||||
}
|
||||
// can't satisfy this char with the existing data
|
||||
if end > vec::len(buf) {
|
||||
return (i - 1u, end - vec::len(buf));
|
||||
if end > buf_len {
|
||||
return (i - 1, end - buf_len);
|
||||
}
|
||||
let mut val = 0u;
|
||||
let mut val = 0;
|
||||
while i < end {
|
||||
let next = buf[i] as int;
|
||||
i += 1u;
|
||||
i += 1;
|
||||
assert (next > -1);
|
||||
assert (next & 192 == 128);
|
||||
val <<= 6u;
|
||||
val <<= 6;
|
||||
val += (next & 63) as uint;
|
||||
}
|
||||
// See str::char_at
|
||||
val += ((b0 << ((w + 1u) as u8)) as uint)
|
||||
<< (w - 1u) * 6u - w - 1u;
|
||||
vec::push(chars, val as char );
|
||||
val += ((b0 << ((w + 1) as u8)) as uint)
|
||||
<< (w - 1) * 6 - w - 1u;
|
||||
chars.push(val as char);
|
||||
}
|
||||
return (i, 0u);
|
||||
return (i, 0);
|
||||
}
|
||||
let mut buf: ~[u8] = ~[];
|
||||
let mut chars: ~[char] = ~[];
|
||||
// might need more bytes, but reading n will never over-read
|
||||
let mut nbread = n;
|
||||
while nbread > 0u {
|
||||
while nbread > 0 {
|
||||
let data = self.read_bytes(nbread);
|
||||
if vec::len(data) == 0u {
|
||||
if data.is_empty() {
|
||||
// eof - FIXME (#2004): should we do something if
|
||||
// we're split in a unicode char?
|
||||
break;
|
||||
}
|
||||
vec::push_all(buf, data);
|
||||
let (offset, nbreq) = chars_from_bytes(buf, chars);
|
||||
let ncreq = n - vec::len(chars);
|
||||
buf.push_all(data);
|
||||
let (offset, nbreq) = chars_from_bytes::<T>(&buf, &mut chars);
|
||||
let ncreq = n - chars.len();
|
||||
// again we either know we need a certain number of bytes
|
||||
// to complete a character, or we make sure we don't
|
||||
// over-read by reading 1-byte per char needed
|
||||
nbread = if ncreq > nbreq { ncreq } else { nbreq };
|
||||
if nbread > 0u {
|
||||
buf = vec::slice(buf, offset, vec::len(buf));
|
||||
if nbread > 0 {
|
||||
buf = vec::slice(buf, offset, buf.len());
|
||||
}
|
||||
}
|
||||
move chars
|
||||
}
|
||||
|
||||
fn read_char() -> char {
|
||||
let c = self.read_chars(1u);
|
||||
if vec::len(c) == 0u {
|
||||
let c = self.read_chars(1);
|
||||
if vec::len(c) == 0 {
|
||||
return -1 as char; // FIXME will this stay valid? // #2004
|
||||
}
|
||||
assert(vec::len(c) == 1u);
|
||||
assert(vec::len(c) == 1);
|
||||
return c[0];
|
||||
}
|
||||
|
||||
|
|
@ -144,7 +154,7 @@ impl Reader {
|
|||
let mut buf: ~[u8] = ~[];
|
||||
loop {
|
||||
let ch = self.read_byte();
|
||||
if ch < 1 { break; } else { vec::push(buf, ch as u8); }
|
||||
if ch < 1 { break; } else { buf.push(ch as u8); }
|
||||
}
|
||||
str::from_bytes(buf)
|
||||
}
|
||||
|
|
@ -179,7 +189,7 @@ impl Reader {
|
|||
|
||||
fn read_whole_stream() -> ~[u8] {
|
||||
let mut buf: ~[u8] = ~[];
|
||||
while !self.eof() { vec::push_all(buf, self.read_bytes(2048u)); }
|
||||
while !self.eof() { buf.push_all(self.read_bytes(2048u)); }
|
||||
move buf
|
||||
}
|
||||
|
||||
|
|
@ -195,7 +205,7 @@ impl Reader {
|
|||
}
|
||||
}
|
||||
|
||||
fn each_line(it: fn(~str) -> bool) {
|
||||
fn each_line(it: fn(s: &str) -> bool) {
|
||||
while !self.eof() {
|
||||
if !it(self.read_line()) { break; }
|
||||
}
|
||||
|
|
@ -256,7 +266,7 @@ fn FILERes(f: *libc::FILE) -> FILERes {
|
|||
}
|
||||
}
|
||||
|
||||
fn FILE_reader(f: *libc::FILE, cleanup: bool) -> Reader {
|
||||
pub fn FILE_reader(f: *libc::FILE, cleanup: bool) -> Reader {
|
||||
if cleanup {
|
||||
{base: f, cleanup: FILERes(f)} as Reader
|
||||
} else {
|
||||
|
|
@ -268,9 +278,9 @@ fn FILE_reader(f: *libc::FILE, cleanup: bool) -> Reader {
|
|||
// top-level functions that take a reader, or a set of default methods on
|
||||
// reader (which can then be called reader)
|
||||
|
||||
fn stdin() -> Reader { rustrt::rust_get_stdin() as Reader }
|
||||
pub fn stdin() -> Reader { rustrt::rust_get_stdin() as Reader }
|
||||
|
||||
fn file_reader(path: &Path) -> Result<Reader, ~str> {
|
||||
pub fn file_reader(path: &Path) -> Result<Reader, ~str> {
|
||||
let f = os::as_c_charp(path.to_str(), |pathbuf| {
|
||||
os::as_c_charp("r", |modebuf|
|
||||
libc::fopen(pathbuf, modebuf)
|
||||
|
|
@ -286,7 +296,7 @@ fn file_reader(path: &Path) -> Result<Reader, ~str> {
|
|||
|
||||
// Byte buffer readers
|
||||
|
||||
type ByteBuf = {buf: &[const u8], mut pos: uint};
|
||||
pub type ByteBuf = {buf: &[const u8], mut pos: uint};
|
||||
|
||||
impl ByteBuf: Reader {
|
||||
fn read(buf: &[mut u8], len: uint) -> uint {
|
||||
|
|
@ -315,21 +325,21 @@ impl ByteBuf: Reader {
|
|||
fn tell() -> uint { self.pos }
|
||||
}
|
||||
|
||||
fn with_bytes_reader<t>(bytes: &[u8], f: fn(Reader) -> t) -> t {
|
||||
pub fn with_bytes_reader<t>(bytes: &[u8], f: fn(Reader) -> t) -> t {
|
||||
f({buf: bytes, mut pos: 0u} as Reader)
|
||||
}
|
||||
|
||||
fn with_str_reader<T>(s: &str, f: fn(Reader) -> T) -> T {
|
||||
pub fn with_str_reader<T>(s: &str, f: fn(Reader) -> T) -> T {
|
||||
str::byte_slice(s, |bytes| with_bytes_reader(bytes, f))
|
||||
}
|
||||
|
||||
// Writing
|
||||
enum FileFlag { Append, Create, Truncate, NoFlag, }
|
||||
pub enum FileFlag { Append, Create, Truncate, NoFlag, }
|
||||
|
||||
// What type of writer are we?
|
||||
enum WriterType { Screen, File }
|
||||
pub enum WriterType { Screen, File }
|
||||
|
||||
impl WriterType : Eq {
|
||||
pub impl WriterType : Eq {
|
||||
pure fn eq(other: &WriterType) -> bool {
|
||||
match (self, (*other)) {
|
||||
(Screen, Screen) | (File, File) => true,
|
||||
|
|
@ -341,7 +351,7 @@ impl WriterType : Eq {
|
|||
|
||||
// FIXME (#2004): Seekable really should be orthogonal.
|
||||
// FIXME (#2004): eventually u64
|
||||
trait Writer {
|
||||
pub trait Writer {
|
||||
fn write(v: &[const u8]);
|
||||
fn seek(int, SeekStyle);
|
||||
fn tell() -> uint;
|
||||
|
|
@ -382,7 +392,7 @@ impl *libc::FILE: Writer {
|
|||
}
|
||||
}
|
||||
|
||||
fn FILE_writer(f: *libc::FILE, cleanup: bool) -> Writer {
|
||||
pub fn FILE_writer(f: *libc::FILE, cleanup: bool) -> Writer {
|
||||
if cleanup {
|
||||
{base: f, cleanup: FILERes(f)} as Writer
|
||||
} else {
|
||||
|
|
@ -431,7 +441,7 @@ fn FdRes(fd: fd_t) -> FdRes {
|
|||
}
|
||||
}
|
||||
|
||||
fn fd_writer(fd: fd_t, cleanup: bool) -> Writer {
|
||||
pub fn fd_writer(fd: fd_t, cleanup: bool) -> Writer {
|
||||
if cleanup {
|
||||
{base: fd, cleanup: FdRes(fd)} as Writer
|
||||
} else {
|
||||
|
|
@ -440,7 +450,7 @@ fn fd_writer(fd: fd_t, cleanup: bool) -> Writer {
|
|||
}
|
||||
|
||||
|
||||
fn mk_file_writer(path: &Path, flags: ~[FileFlag])
|
||||
pub fn mk_file_writer(path: &Path, flags: &[FileFlag])
|
||||
-> Result<Writer, ~str> {
|
||||
|
||||
#[cfg(windows)]
|
||||
|
|
@ -470,7 +480,8 @@ fn mk_file_writer(path: &Path, flags: ~[FileFlag])
|
|||
}
|
||||
}
|
||||
|
||||
fn u64_to_le_bytes<T>(n: u64, size: uint, f: fn(v: &[u8]) -> T) -> T {
|
||||
pub fn u64_to_le_bytes<T>(n: u64, size: uint,
|
||||
f: fn(v: &[u8]) -> T) -> T {
|
||||
assert size <= 8u;
|
||||
match size {
|
||||
1u => f(&[n as u8]),
|
||||
|
|
@ -492,7 +503,7 @@ fn u64_to_le_bytes<T>(n: u64, size: uint, f: fn(v: &[u8]) -> T) -> T {
|
|||
|
||||
let mut bytes: ~[u8] = ~[], i = size, n = n;
|
||||
while i > 0u {
|
||||
vec::push(bytes, (n & 255_u64) as u8);
|
||||
bytes.push((n & 255_u64) as u8);
|
||||
n >>= 8_u64;
|
||||
i -= 1u;
|
||||
}
|
||||
|
|
@ -501,7 +512,8 @@ fn u64_to_le_bytes<T>(n: u64, size: uint, f: fn(v: &[u8]) -> T) -> T {
|
|||
}
|
||||
}
|
||||
|
||||
fn u64_to_be_bytes<T>(n: u64, size: uint, f: fn(v: &[u8]) -> T) -> T {
|
||||
pub fn u64_to_be_bytes<T>(n: u64, size: uint,
|
||||
f: fn(v: &[u8]) -> T) -> T {
|
||||
assert size <= 8u;
|
||||
match size {
|
||||
1u => f(&[n as u8]),
|
||||
|
|
@ -524,7 +536,7 @@ fn u64_to_be_bytes<T>(n: u64, size: uint, f: fn(v: &[u8]) -> T) -> T {
|
|||
let mut i = size;
|
||||
while i > 0u {
|
||||
let shift = ((i - 1u) * 8u) as u64;
|
||||
vec::push(bytes, (n >> shift) as u8);
|
||||
bytes.push((n >> shift) as u8);
|
||||
i -= 1u;
|
||||
}
|
||||
f(bytes)
|
||||
|
|
@ -532,7 +544,8 @@ fn u64_to_be_bytes<T>(n: u64, size: uint, f: fn(v: &[u8]) -> T) -> T {
|
|||
}
|
||||
}
|
||||
|
||||
fn u64_from_be_bytes(data: &[const u8], start: uint, size: uint) -> u64 {
|
||||
pub fn u64_from_be_bytes(data: &[const u8],
|
||||
start: uint, size: uint) -> u64 {
|
||||
let mut sz = size;
|
||||
assert (sz <= 8u);
|
||||
let mut val = 0_u64;
|
||||
|
|
@ -547,7 +560,7 @@ fn u64_from_be_bytes(data: &[const u8], start: uint, size: uint) -> u64 {
|
|||
|
||||
// FIXME: #3048 combine trait+impl (or just move these to
|
||||
// default methods on writer)
|
||||
trait WriterUtil {
|
||||
pub trait WriterUtil {
|
||||
fn write_char(ch: char);
|
||||
fn write_str(s: &str);
|
||||
fn write_line(s: &str);
|
||||
|
|
@ -644,13 +657,13 @@ impl<T: Writer> T : WriterUtil {
|
|||
}
|
||||
|
||||
#[allow(non_implicitly_copyable_typarams)]
|
||||
fn file_writer(path: &Path, flags: ~[FileFlag]) -> Result<Writer, ~str> {
|
||||
result::chain(mk_file_writer(path, flags), |w| result::Ok(w))
|
||||
pub fn file_writer(path: &Path, flags: &[FileFlag]) -> Result<Writer, ~str> {
|
||||
mk_file_writer(path, flags).chain(|w| result::Ok(w))
|
||||
}
|
||||
|
||||
|
||||
// FIXME: fileflags // #2004
|
||||
fn buffered_file_writer(path: &Path) -> Result<Writer, ~str> {
|
||||
pub fn buffered_file_writer(path: &Path) -> Result<Writer, ~str> {
|
||||
let f = do os::as_c_charp(path.to_str()) |pathbuf| {
|
||||
do os::as_c_charp("w") |modebuf| {
|
||||
libc::fopen(pathbuf, modebuf)
|
||||
|
|
@ -664,13 +677,13 @@ fn buffered_file_writer(path: &Path) -> Result<Writer, ~str> {
|
|||
// FIXME (#2004) it would be great if this could be a const
|
||||
// FIXME (#2004) why are these different from the way stdin() is
|
||||
// implemented?
|
||||
fn stdout() -> Writer { fd_writer(libc::STDOUT_FILENO as c_int, false) }
|
||||
fn stderr() -> Writer { fd_writer(libc::STDERR_FILENO as c_int, false) }
|
||||
pub fn stdout() -> Writer { fd_writer(libc::STDOUT_FILENO as c_int, false) }
|
||||
pub fn stderr() -> Writer { fd_writer(libc::STDERR_FILENO as c_int, false) }
|
||||
|
||||
fn print(s: &str) { stdout().write_str(s); }
|
||||
fn println(s: &str) { stdout().write_line(s); }
|
||||
pub fn print(s: &str) { stdout().write_str(s); }
|
||||
pub fn println(s: &str) { stdout().write_line(s); }
|
||||
|
||||
struct BytesWriter {
|
||||
pub struct BytesWriter {
|
||||
buf: DVec<u8>,
|
||||
mut pos: uint,
|
||||
}
|
||||
|
|
@ -684,10 +697,12 @@ impl BytesWriter: Writer {
|
|||
|
||||
let count = uint::max(buf_len, self.pos + v_len);
|
||||
vec::reserve(&mut buf, count);
|
||||
unsafe { vec::raw::set_len(buf, count); }
|
||||
unsafe { vec::raw::set_len(&mut buf, count); }
|
||||
|
||||
let view = vec::mut_view(buf, self.pos, count);
|
||||
vec::bytes::memcpy(view, v, v_len);
|
||||
{
|
||||
let view = vec::mut_view(buf, self.pos, count);
|
||||
vec::bytes::memcpy(view, v, v_len);
|
||||
}
|
||||
|
||||
self.pos += v_len;
|
||||
|
||||
|
|
@ -712,28 +727,28 @@ impl @BytesWriter : Writer {
|
|||
fn get_type() -> WriterType { (*self).get_type() }
|
||||
}
|
||||
|
||||
fn BytesWriter() -> BytesWriter {
|
||||
pub fn BytesWriter() -> BytesWriter {
|
||||
BytesWriter { buf: DVec(), mut pos: 0u }
|
||||
}
|
||||
|
||||
fn with_bytes_writer(f: fn(Writer)) -> ~[u8] {
|
||||
pub fn with_bytes_writer(f: fn(Writer)) -> ~[u8] {
|
||||
let wr = @BytesWriter();
|
||||
f(wr as Writer);
|
||||
wr.buf.check_out(|buf| buf)
|
||||
}
|
||||
|
||||
fn with_str_writer(f: fn(Writer)) -> ~str {
|
||||
pub fn with_str_writer(f: fn(Writer)) -> ~str {
|
||||
let mut v = with_bytes_writer(f);
|
||||
|
||||
// Make sure the vector has a trailing null and is proper utf8.
|
||||
vec::push(v, 0);
|
||||
v.push(0);
|
||||
assert str::is_utf8(v);
|
||||
|
||||
unsafe { move ::cast::transmute(v) }
|
||||
}
|
||||
|
||||
// Utility functions
|
||||
fn seek_in_buf(offset: int, pos: uint, len: uint, whence: SeekStyle) ->
|
||||
pub fn seek_in_buf(offset: int, pos: uint, len: uint, whence: SeekStyle) ->
|
||||
uint {
|
||||
let mut bpos = pos as int;
|
||||
let blen = len as int;
|
||||
|
|
@ -747,7 +762,7 @@ fn seek_in_buf(offset: int, pos: uint, len: uint, whence: SeekStyle) ->
|
|||
}
|
||||
|
||||
#[allow(non_implicitly_copyable_typarams)]
|
||||
fn read_whole_file_str(file: &Path) -> Result<~str, ~str> {
|
||||
pub fn read_whole_file_str(file: &Path) -> Result<~str, ~str> {
|
||||
result::chain(read_whole_file(file), |bytes| {
|
||||
if str::is_utf8(bytes) {
|
||||
result::Ok(str::from_bytes(bytes))
|
||||
|
|
@ -760,7 +775,7 @@ fn read_whole_file_str(file: &Path) -> Result<~str, ~str> {
|
|||
// FIXME (#2004): implement this in a low-level way. Going through the
|
||||
// abstractions is pointless.
|
||||
#[allow(non_implicitly_copyable_typarams)]
|
||||
fn read_whole_file(file: &Path) -> Result<~[u8], ~str> {
|
||||
pub fn read_whole_file(file: &Path) -> Result<~[u8], ~str> {
|
||||
result::chain(file_reader(file), |rdr| {
|
||||
result::Ok(rdr.read_whole_stream())
|
||||
})
|
||||
|
|
@ -768,10 +783,9 @@ fn read_whole_file(file: &Path) -> Result<~[u8], ~str> {
|
|||
|
||||
// fsync related
|
||||
|
||||
mod fsync {
|
||||
#[legacy_exports];
|
||||
pub mod fsync {
|
||||
|
||||
enum Level {
|
||||
pub enum Level {
|
||||
// whatever fsync does on that platform
|
||||
FSync,
|
||||
|
||||
|
|
@ -786,7 +800,7 @@ mod fsync {
|
|||
|
||||
|
||||
// Artifacts that need to fsync on destruction
|
||||
struct Res<t> {
|
||||
pub struct Res<t: Copy> {
|
||||
arg: Arg<t>,
|
||||
drop {
|
||||
match self.arg.opt_level {
|
||||
|
|
@ -799,51 +813,51 @@ mod fsync {
|
|||
}
|
||||
}
|
||||
|
||||
fn Res<t>(-arg: Arg<t>) -> Res<t>{
|
||||
pub fn Res<t: Copy>(arg: Arg<t>) -> Res<t>{
|
||||
Res {
|
||||
arg: move arg
|
||||
}
|
||||
}
|
||||
|
||||
type Arg<t> = {
|
||||
pub type Arg<t> = {
|
||||
val: t,
|
||||
opt_level: Option<Level>,
|
||||
fsync_fn: fn@(t, Level) -> int
|
||||
fsync_fn: fn@(f: t, Level) -> int
|
||||
};
|
||||
|
||||
// fsync file after executing blk
|
||||
// FIXME (#2004) find better way to create resources within lifetime of
|
||||
// outer res
|
||||
fn FILE_res_sync(&&file: FILERes, opt_level: Option<Level>,
|
||||
blk: fn(&&v: Res<*libc::FILE>)) {
|
||||
blk(Res({
|
||||
pub fn FILE_res_sync(file: &FILERes, opt_level: Option<Level>,
|
||||
blk: fn(v: Res<*libc::FILE>)) {
|
||||
blk(move Res({
|
||||
val: file.f, opt_level: opt_level,
|
||||
fsync_fn: fn@(&&file: *libc::FILE, l: Level) -> int {
|
||||
fsync_fn: fn@(file: *libc::FILE, l: Level) -> int {
|
||||
return os::fsync_fd(libc::fileno(file), l) as int;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
// fsync fd after executing blk
|
||||
fn fd_res_sync(&&fd: FdRes, opt_level: Option<Level>,
|
||||
blk: fn(&&v: Res<fd_t>)) {
|
||||
blk(Res({
|
||||
pub fn fd_res_sync(fd: &FdRes, opt_level: Option<Level>,
|
||||
blk: fn(v: Res<fd_t>)) {
|
||||
blk(move Res({
|
||||
val: fd.fd, opt_level: opt_level,
|
||||
fsync_fn: fn@(&&fd: fd_t, l: Level) -> int {
|
||||
fsync_fn: fn@(fd: fd_t, l: Level) -> int {
|
||||
return os::fsync_fd(fd, l) as int;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
// Type of objects that may want to fsync
|
||||
trait FSyncable { fn fsync(l: Level) -> int; }
|
||||
pub trait FSyncable { fn fsync(l: Level) -> int; }
|
||||
|
||||
// Call o.fsync after executing blk
|
||||
fn obj_sync(&&o: FSyncable, opt_level: Option<Level>,
|
||||
blk: fn(&&v: Res<FSyncable>)) {
|
||||
pub fn obj_sync(o: FSyncable, opt_level: Option<Level>,
|
||||
blk: fn(v: Res<FSyncable>)) {
|
||||
blk(Res({
|
||||
val: o, opt_level: opt_level,
|
||||
fsync_fn: fn@(&&o: FSyncable, l: Level) -> int {
|
||||
fsync_fn: fn@(o: FSyncable, l: Level) -> int {
|
||||
return o.fsync(l);
|
||||
}
|
||||
}));
|
||||
|
|
@ -852,7 +866,6 @@ mod fsync {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[legacy_exports];
|
||||
|
||||
#[test]
|
||||
fn test_simple() {
|
||||
|
|
@ -864,10 +877,10 @@ mod tests {
|
|||
{
|
||||
let out: io::Writer =
|
||||
result::get(
|
||||
io::file_writer(tmpfile, ~[io::Create, io::Truncate]));
|
||||
&io::file_writer(tmpfile, ~[io::Create, io::Truncate]));
|
||||
out.write_str(frood);
|
||||
}
|
||||
let inp: io::Reader = result::get(io::file_reader(tmpfile));
|
||||
let inp: io::Reader = result::get(&io::file_reader(tmpfile));
|
||||
let frood2: ~str = inp.read_c_str();
|
||||
log(debug, frood2);
|
||||
assert frood == frood2;
|
||||
|
|
@ -876,8 +889,8 @@ mod tests {
|
|||
#[test]
|
||||
fn test_readchars_empty() {
|
||||
do io::with_str_reader(~"") |inp| {
|
||||
let res : ~[char] = inp.read_chars(128u);
|
||||
assert(vec::len(res) == 0u);
|
||||
let res : ~[char] = inp.read_chars(128);
|
||||
assert(vec::len(res) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -890,7 +903,7 @@ mod tests {
|
|||
104, 101, 108, 108, 111,
|
||||
29983, 38152, 30340, 27748,
|
||||
21273, 20999, 32905, 27748];
|
||||
fn check_read_ln(len : uint, s: ~str, ivals: ~[int]) {
|
||||
fn check_read_ln(len : uint, s: &str, ivals: &[int]) {
|
||||
do io::with_str_reader(s) |inp| {
|
||||
let res : ~[char] = inp.read_chars(len);
|
||||
if (len <= vec::len(ivals)) {
|
||||
|
|
@ -900,13 +913,13 @@ mod tests {
|
|||
vec::map(res, |x| *x as int));
|
||||
}
|
||||
}
|
||||
let mut i = 0u;
|
||||
while i < 8u {
|
||||
let mut i = 0;
|
||||
while i < 8 {
|
||||
check_read_ln(i, wide_test, ivals);
|
||||
i += 1u;
|
||||
i += 1;
|
||||
}
|
||||
// check a long read for good measure
|
||||
check_read_ln(128u, wide_test, ivals);
|
||||
check_read_ln(128, wide_test, ivals);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -928,7 +941,7 @@ mod tests {
|
|||
#[test]
|
||||
fn file_reader_not_exist() {
|
||||
match io::file_reader(&Path("not a file")) {
|
||||
result::Err(e) => {
|
||||
result::Err(copy e) => {
|
||||
assert e == ~"error opening not a file";
|
||||
}
|
||||
result::Ok(_) => fail
|
||||
|
|
@ -938,7 +951,7 @@ mod tests {
|
|||
#[test]
|
||||
fn file_writer_bad_name() {
|
||||
match io::file_writer(&Path("?/?"), ~[]) {
|
||||
result::Err(e) => {
|
||||
result::Err(copy e) => {
|
||||
assert str::starts_with(e, "error opening");
|
||||
}
|
||||
result::Ok(_) => fail
|
||||
|
|
@ -948,7 +961,7 @@ mod tests {
|
|||
#[test]
|
||||
fn buffered_file_writer_bad_name() {
|
||||
match io::buffered_file_writer(&Path("?/?")) {
|
||||
result::Err(e) => {
|
||||
result::Err(copy e) => {
|
||||
assert str::starts_with(e, "error opening");
|
||||
}
|
||||
result::Ok(_) => fail
|
||||
|
|
|
|||
|
|
@ -2,51 +2,52 @@
|
|||
// workaround our lack of traits and lack of macros. See core.{rc,rs} for
|
||||
// how this file is used.
|
||||
|
||||
#[warn(deprecated_mode)];
|
||||
|
||||
use cmp::{Eq, Ord};
|
||||
use inst::{IMPL_T, EACH, SIZE_HINT};
|
||||
export extensions;
|
||||
|
||||
impl<A> IMPL_T<A>: iter::BaseIter<A> {
|
||||
pure fn each(blk: fn(v: &A) -> bool) { EACH(self, blk) }
|
||||
pure fn size_hint() -> Option<uint> { SIZE_HINT(self) }
|
||||
pure fn each(blk: fn(v: &A) -> bool) { EACH(&self, blk) }
|
||||
pure fn size_hint() -> Option<uint> { SIZE_HINT(&self) }
|
||||
}
|
||||
|
||||
impl<A> IMPL_T<A>: iter::ExtendedIter<A> {
|
||||
pure fn eachi(blk: fn(uint, v: &A) -> bool) { iter::eachi(self, blk) }
|
||||
pure fn all(blk: fn(A) -> bool) -> bool { iter::all(self, blk) }
|
||||
pure fn any(blk: fn(A) -> bool) -> bool { iter::any(self, blk) }
|
||||
pure fn foldl<B>(+b0: B, blk: fn(B, A) -> B) -> B {
|
||||
iter::foldl(self, move b0, blk)
|
||||
pure fn eachi(blk: fn(uint, v: &A) -> bool) { iter::eachi(&self, blk) }
|
||||
pure fn all(blk: fn(&A) -> bool) -> bool { iter::all(&self, blk) }
|
||||
pure fn any(blk: fn(&A) -> bool) -> bool { iter::any(&self, blk) }
|
||||
pure fn foldl<B>(b0: B, blk: fn(&B, &A) -> B) -> B {
|
||||
iter::foldl(&self, move b0, blk)
|
||||
}
|
||||
pure fn position(f: fn(A) -> bool) -> Option<uint> {
|
||||
iter::position(self, f)
|
||||
pure fn position(f: fn(&A) -> bool) -> Option<uint> {
|
||||
iter::position(&self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Eq> IMPL_T<A>: iter::EqIter<A> {
|
||||
pure fn contains(x: A) -> bool { iter::contains(self, x) }
|
||||
pure fn count(x: A) -> uint { iter::count(self, x) }
|
||||
pure fn contains(x: &A) -> bool { iter::contains(&self, x) }
|
||||
pure fn count(x: &A) -> uint { iter::count(&self, x) }
|
||||
}
|
||||
|
||||
impl<A: Copy> IMPL_T<A>: iter::CopyableIter<A> {
|
||||
pure fn filter_to_vec(pred: fn(A) -> bool) -> ~[A] {
|
||||
iter::filter_to_vec(self, pred)
|
||||
pure fn filter_to_vec(pred: fn(a: A) -> bool) -> ~[A] {
|
||||
iter::filter_to_vec(&self, pred)
|
||||
}
|
||||
pure fn map_to_vec<B>(op: fn(v: &A) -> B) -> ~[B] {
|
||||
iter::map_to_vec(self, op)
|
||||
pure fn map_to_vec<B>(op: fn(v: A) -> B) -> ~[B] {
|
||||
iter::map_to_vec(&self, op)
|
||||
}
|
||||
pure fn to_vec() -> ~[A] { iter::to_vec(self) }
|
||||
pure fn to_vec() -> ~[A] { iter::to_vec(&self) }
|
||||
|
||||
// FIXME--bug in resolve prevents this from working (#2611)
|
||||
// fn flat_map_to_vec<B:copy,IB:base_iter<B>>(op: fn(A) -> IB) -> ~[B] {
|
||||
// iter::flat_map_to_vec(self, op)
|
||||
// }
|
||||
pure fn flat_map_to_vec<B:Copy,IB:BaseIter<B>>(op: fn(a: A) -> IB)
|
||||
-> ~[B] {
|
||||
iter::flat_map_to_vec(&self, op)
|
||||
}
|
||||
|
||||
pure fn find(p: fn(A) -> bool) -> Option<A> { iter::find(self, p) }
|
||||
pure fn find(p: fn(a: A) -> bool) -> Option<A> { iter::find(&self, p) }
|
||||
}
|
||||
|
||||
impl<A: Copy Ord> IMPL_T<A>: iter::CopyableOrderedIter<A> {
|
||||
pure fn min() -> A { iter::min(self) }
|
||||
pure fn max() -> A { iter::max(self) }
|
||||
pure fn min() -> A { iter::min(&self) }
|
||||
pure fn max() -> A { iter::max(&self) }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#[allow(non_camel_case_types)]
|
||||
type IMPL_T<A> = dlist::DList<A>;
|
||||
pub type IMPL_T<A> = dlist::DList<A>;
|
||||
|
||||
/**
|
||||
* Iterates through the current contents.
|
||||
|
|
@ -8,7 +8,7 @@ type IMPL_T<A> = dlist::DList<A>;
|
|||
* e.g. breadth-first search with in-place enqueues), but removing the current
|
||||
* node is forbidden.
|
||||
*/
|
||||
pure fn EACH<A>(self: IMPL_T<A>, f: fn(v: &A) -> bool) {
|
||||
pub pure fn EACH<A>(self: &IMPL_T<A>, f: fn(v: &A) -> bool) {
|
||||
let mut link = self.peek_n();
|
||||
while option::is_some(&link) {
|
||||
let nobe = option::get(&link);
|
||||
|
|
@ -29,6 +29,6 @@ pure fn EACH<A>(self: IMPL_T<A>, f: fn(v: &A) -> bool) {
|
|||
}
|
||||
}
|
||||
|
||||
pure fn SIZE_HINT<A>(self: IMPL_T<A>) -> Option<uint> {
|
||||
pub pure fn SIZE_HINT<A>(self: &IMPL_T<A>) -> Option<uint> {
|
||||
Some(self.len())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
#[allow(non_camel_case_types)]
|
||||
type IMPL_T<A> = dvec::DVec<A>;
|
||||
pub type IMPL_T<A> = dvec::DVec<A>;
|
||||
|
||||
/**
|
||||
* Iterates through the current contents.
|
||||
*
|
||||
* Attempts to access this dvec during iteration will fail.
|
||||
*/
|
||||
pure fn EACH<A>(self: IMPL_T<A>, f: fn(v: &A) -> bool) {
|
||||
pub pure fn EACH<A>(self: &IMPL_T<A>, f: fn(v: &A) -> bool) {
|
||||
unsafe {
|
||||
do self.swap |v| {
|
||||
v.each(f);
|
||||
|
|
@ -15,6 +15,6 @@ pure fn EACH<A>(self: IMPL_T<A>, f: fn(v: &A) -> bool) {
|
|||
}
|
||||
}
|
||||
|
||||
pure fn SIZE_HINT<A>(self: IMPL_T<A>) -> Option<uint> {
|
||||
pub pure fn SIZE_HINT<A>(self: &IMPL_T<A>) -> Option<uint> {
|
||||
Some(self.len())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
#[allow(non_camel_case_types)]
|
||||
type IMPL_T<A> = Option<A>;
|
||||
pub type IMPL_T<A> = Option<A>;
|
||||
|
||||
pure fn EACH<A>(self: IMPL_T<A>, f: fn(v: &A) -> bool) {
|
||||
match self {
|
||||
pub pure fn EACH<A>(self: &IMPL_T<A>, f: fn(v: &A) -> bool) {
|
||||
match *self {
|
||||
None => (),
|
||||
Some(ref a) => { f(a); }
|
||||
}
|
||||
}
|
||||
|
||||
pure fn SIZE_HINT<A>(self: IMPL_T<A>) -> Option<uint> {
|
||||
match self {
|
||||
None => Some(0u),
|
||||
Some(_) => Some(1u)
|
||||
pub pure fn SIZE_HINT<A>(self: &IMPL_T<A>) -> Option<uint> {
|
||||
match *self {
|
||||
None => Some(0),
|
||||
Some(_) => Some(1)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,48 +7,49 @@ The iteration traits and common implementation
|
|||
use cmp::{Eq, Ord};
|
||||
|
||||
/// A function used to initialize the elements of a sequence
|
||||
type InitOp<T> = fn(uint) -> T;
|
||||
pub type InitOp<T> = &fn(uint) -> T;
|
||||
|
||||
trait BaseIter<A> {
|
||||
pub trait BaseIter<A> {
|
||||
pure fn each(blk: fn(v: &A) -> bool);
|
||||
pure fn size_hint() -> Option<uint>;
|
||||
}
|
||||
|
||||
trait ExtendedIter<A> {
|
||||
pub trait ExtendedIter<A> {
|
||||
pure fn eachi(blk: fn(uint, v: &A) -> bool);
|
||||
pure fn all(blk: fn(A) -> bool) -> bool;
|
||||
pure fn any(blk: fn(A) -> bool) -> bool;
|
||||
pure fn foldl<B>(+b0: B, blk: fn(B, A) -> B) -> B;
|
||||
pure fn position(f: fn(A) -> bool) -> Option<uint>;
|
||||
pure fn all(blk: fn(&A) -> bool) -> bool;
|
||||
pure fn any(blk: fn(&A) -> bool) -> bool;
|
||||
pure fn foldl<B>(b0: B, blk: fn(&B, &A) -> B) -> B;
|
||||
pure fn position(f: fn(&A) -> bool) -> Option<uint>;
|
||||
}
|
||||
|
||||
trait EqIter<A:Eq> {
|
||||
pure fn contains(x: A) -> bool;
|
||||
pure fn count(x: A) -> uint;
|
||||
pub trait EqIter<A:Eq> {
|
||||
pure fn contains(x: &A) -> bool;
|
||||
pure fn count(x: &A) -> uint;
|
||||
}
|
||||
|
||||
trait Times {
|
||||
pub trait Times {
|
||||
pure fn times(it: fn() -> bool);
|
||||
}
|
||||
trait TimesIx{
|
||||
|
||||
pub trait TimesIx{
|
||||
pure fn timesi(it: fn(uint) -> bool);
|
||||
}
|
||||
|
||||
trait CopyableIter<A:Copy> {
|
||||
pure fn filter_to_vec(pred: fn(A) -> bool) -> ~[A];
|
||||
pure fn map_to_vec<B>(op: fn(v: &A) -> B) -> ~[B];
|
||||
pub trait CopyableIter<A:Copy> {
|
||||
pure fn filter_to_vec(pred: fn(a: A) -> bool) -> ~[A];
|
||||
pure fn map_to_vec<B>(op: fn(v: A) -> B) -> ~[B];
|
||||
pure fn to_vec() -> ~[A];
|
||||
pure fn find(p: fn(A) -> bool) -> Option<A>;
|
||||
pure fn find(p: fn(a: A) -> bool) -> Option<A>;
|
||||
}
|
||||
|
||||
trait CopyableOrderedIter<A:Copy Ord> {
|
||||
pub trait CopyableOrderedIter<A:Copy Ord> {
|
||||
pure fn min() -> A;
|
||||
pure fn max() -> A;
|
||||
}
|
||||
|
||||
// A trait for sequences that can be by imperatively pushing elements
|
||||
// onto them.
|
||||
trait Buildable<A> {
|
||||
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
|
||||
|
|
@ -63,33 +64,36 @@ trait Buildable<A> {
|
|||
* onto the sequence being constructed.
|
||||
*/
|
||||
static pure fn build_sized(size: uint,
|
||||
builder: fn(push: pure fn(+v: A))) -> self;
|
||||
builder: fn(push: pure fn(v: A))) -> self;
|
||||
}
|
||||
|
||||
pure fn eachi<A,IA:BaseIter<A>>(self: IA, blk: fn(uint, v: &A) -> bool) {
|
||||
let mut i = 0u;
|
||||
pub pure fn eachi<A,IA:BaseIter<A>>(self: &IA,
|
||||
blk: fn(uint, v: &A) -> bool) {
|
||||
let mut i = 0;
|
||||
for self.each |a| {
|
||||
if !blk(i, a) { break; }
|
||||
i += 1u;
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
pure fn all<A,IA:BaseIter<A>>(self: IA, blk: fn(A) -> bool) -> bool {
|
||||
pub pure fn all<A,IA:BaseIter<A>>(self: &IA,
|
||||
blk: fn(&A) -> bool) -> bool {
|
||||
for self.each |a| {
|
||||
if !blk(*a) { return false; }
|
||||
if !blk(a) { return false; }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
pure fn any<A,IA:BaseIter<A>>(self: IA, blk: fn(A) -> bool) -> bool {
|
||||
pub pure fn any<A,IA:BaseIter<A>>(self: &IA,
|
||||
blk: fn(&A) -> bool) -> bool {
|
||||
for self.each |a| {
|
||||
if blk(*a) { return true; }
|
||||
if blk(a) { return true; }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
pure fn filter_to_vec<A:Copy,IA:BaseIter<A>>(self: IA,
|
||||
prd: fn(A) -> bool) -> ~[A] {
|
||||
pub pure fn filter_to_vec<A:Copy,IA:BaseIter<A>>(
|
||||
self: &IA, prd: fn(a: A) -> bool) -> ~[A] {
|
||||
do vec::build_sized_opt(self.size_hint()) |push| {
|
||||
for self.each |a| {
|
||||
if prd(*a) { push(*a); }
|
||||
|
|
@ -97,18 +101,18 @@ pure fn filter_to_vec<A:Copy,IA:BaseIter<A>>(self: IA,
|
|||
}
|
||||
}
|
||||
|
||||
pure fn map_to_vec<A:Copy,B,IA:BaseIter<A>>(self: IA, op: fn(v: &A) -> B)
|
||||
pub pure fn map_to_vec<A:Copy,B,IA:BaseIter<A>>(self: &IA,
|
||||
op: fn(v: A) -> B)
|
||||
-> ~[B] {
|
||||
do vec::build_sized_opt(self.size_hint()) |push| {
|
||||
for self.each |a| {
|
||||
push(op(a));
|
||||
push(op(*a));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pure fn flat_map_to_vec<A:Copy,B:Copy,IA:BaseIter<A>,IB:BaseIter<B>>(
|
||||
self: IA, op: fn(A) -> IB) -> ~[B] {
|
||||
|
||||
pub pure fn flat_map_to_vec<A:Copy,B:Copy,IA:BaseIter<A>,IB:BaseIter<B>>(
|
||||
self: &IA, op: fn(a: A) -> IB) -> ~[B] {
|
||||
do vec::build |push| {
|
||||
for self.each |a| {
|
||||
for op(*a).each |b| {
|
||||
|
|
@ -118,41 +122,43 @@ pure fn flat_map_to_vec<A:Copy,B:Copy,IA:BaseIter<A>,IB:BaseIter<B>>(
|
|||
}
|
||||
}
|
||||
|
||||
pure fn foldl<A,B,IA:BaseIter<A>>(self: IA, +b0: B, blk: fn(B, A) -> B) -> B {
|
||||
pub pure 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 = blk(&b, a);
|
||||
}
|
||||
move b
|
||||
}
|
||||
|
||||
pure fn to_vec<A:Copy,IA:BaseIter<A>>(self: IA) -> ~[A] {
|
||||
foldl::<A,~[A],IA>(self, ~[], |r, a| vec::append(copy r, ~[a]))
|
||||
pub pure fn to_vec<A:Copy,IA:BaseIter<A>>(self: &IA) -> ~[A] {
|
||||
foldl::<A,~[A],IA>(self, ~[], |r, a| vec::append(copy (*r), ~[*a]))
|
||||
}
|
||||
|
||||
pure fn contains<A:Eq,IA:BaseIter<A>>(self: IA, x: A) -> bool {
|
||||
pub pure fn contains<A:Eq,IA:BaseIter<A>>(self: &IA, x: &A) -> bool {
|
||||
for self.each |a| {
|
||||
if *a == x { return true; }
|
||||
if *a == *x { return true; }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
pure fn count<A:Eq,IA:BaseIter<A>>(self: IA, x: A) -> uint {
|
||||
do foldl(self, 0u) |count, value| {
|
||||
if value == x {
|
||||
count + 1u
|
||||
pub pure 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
|
||||
*count
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pure fn position<A,IA:BaseIter<A>>(self: IA, f: fn(A) -> bool)
|
||||
pub pure 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); }
|
||||
if f(a) { return Some(i); }
|
||||
i += 1;
|
||||
}
|
||||
return None;
|
||||
|
|
@ -162,48 +168,44 @@ pure fn position<A,IA:BaseIter<A>>(self: IA, f: fn(A) -> bool)
|
|||
// 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.
|
||||
|
||||
pure fn repeat(times: uint, blk: fn() -> bool) {
|
||||
let mut i = 0u;
|
||||
pub pure fn repeat(times: uint, blk: fn() -> bool) {
|
||||
let mut i = 0;
|
||||
while i < times {
|
||||
if !blk() { break }
|
||||
i += 1u;
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
pure fn min<A:Copy Ord,IA:BaseIter<A>>(self: IA) -> A {
|
||||
pub pure 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(a_) if a_ < b => {
|
||||
// FIXME (#2005): Not sure if this is successfully optimized to
|
||||
// a move
|
||||
a
|
||||
&Some(ref a_) if *a_ < *b => {
|
||||
*(move a)
|
||||
}
|
||||
_ => Some(b)
|
||||
_ => Some(*b)
|
||||
}
|
||||
} {
|
||||
Some(val) => val,
|
||||
Some(move val) => val,
|
||||
None => fail ~"min called on empty iterator"
|
||||
}
|
||||
}
|
||||
|
||||
pure fn max<A:Copy Ord,IA:BaseIter<A>>(self: IA) -> A {
|
||||
pub pure 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(a_) if a_ > b => {
|
||||
// FIXME (#2005): Not sure if this is successfully optimized to
|
||||
// a move.
|
||||
a
|
||||
&Some(ref a_) if *a_ > *b => {
|
||||
*(move a)
|
||||
}
|
||||
_ => Some(b)
|
||||
_ => Some(*b)
|
||||
}
|
||||
} {
|
||||
Some(val) => val,
|
||||
Some(move val) => val,
|
||||
None => fail ~"max called on empty iterator"
|
||||
}
|
||||
}
|
||||
|
||||
pure fn find<A: Copy,IA:BaseIter<A>>(self: IA,
|
||||
p: fn(A) -> bool) -> Option<A> {
|
||||
pub pure fn find<A: Copy,IA:BaseIter<A>>(self: &IA,
|
||||
p: fn(a: A) -> bool) -> Option<A> {
|
||||
for self.each |i| {
|
||||
if p(*i) { return Some(*i) }
|
||||
}
|
||||
|
|
@ -223,7 +225,8 @@ pure fn find<A: Copy,IA:BaseIter<A>>(self: IA,
|
|||
* onto the sequence being constructed.
|
||||
*/
|
||||
#[inline(always)]
|
||||
pure fn build<A,B: Buildable<A>>(builder: fn(push: pure fn(+v: A))) -> B {
|
||||
pub pure fn build<A,B: Buildable<A>>(builder: fn(push: pure fn(v: A)))
|
||||
-> B {
|
||||
build_sized(4, builder)
|
||||
}
|
||||
|
||||
|
|
@ -241,9 +244,9 @@ pure fn build<A,B: Buildable<A>>(builder: fn(push: pure fn(+v: A))) -> B {
|
|||
* onto the sequence being constructed.
|
||||
*/
|
||||
#[inline(always)]
|
||||
pure fn build_sized_opt<A,B: Buildable<A>>(
|
||||
pub pure fn build_sized_opt<A,B: Buildable<A>>(
|
||||
size: Option<uint>,
|
||||
builder: fn(push: pure fn(+v: A))) -> B {
|
||||
builder: fn(push: pure fn(v: A))) -> B {
|
||||
|
||||
build_sized(size.get_default(4), builder)
|
||||
}
|
||||
|
|
@ -251,10 +254,11 @@ pure fn build_sized_opt<A,B: Buildable<A>>(
|
|||
// Functions that combine iteration and building
|
||||
|
||||
/// 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 {
|
||||
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));
|
||||
push(f(elem));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -265,7 +269,8 @@ fn map<T,IT: BaseIter<T>,U,BU: Buildable<U>>(v: IT, f: fn(T) -> U) -> BU {
|
|||
* Creates a generic sequence of size `n_elts` and initializes the elements
|
||||
* to the value returned by the function `op`.
|
||||
*/
|
||||
pure fn from_fn<T,BT: Buildable<T>>(n_elts: uint, op: InitOp<T>) -> BT {
|
||||
pub pure fn from_fn<T,BT: Buildable<T>>(n_elts: uint,
|
||||
op: InitOp<T>) -> BT {
|
||||
do build_sized(n_elts) |push| {
|
||||
let mut i: uint = 0u;
|
||||
while i < n_elts { push(op(i)); i += 1u; }
|
||||
|
|
@ -278,19 +283,20 @@ pure fn from_fn<T,BT: Buildable<T>>(n_elts: uint, op: InitOp<T>) -> BT {
|
|||
* Creates an immutable vector of size `n_elts` and initializes the elements
|
||||
* to the value `t`.
|
||||
*/
|
||||
pure fn from_elem<T: Copy,BT: Buildable<T>>(n_elts: uint, t: T) -> BT {
|
||||
pub pure fn from_elem<T: Copy,BT: Buildable<T>>(n_elts: uint,
|
||||
t: T) -> BT {
|
||||
do build_sized(n_elts) |push| {
|
||||
let mut i: uint = 0u;
|
||||
while i < n_elts { push(t); i += 1u; }
|
||||
let mut i: uint = 0;
|
||||
while i < n_elts { push(t); i += 1; }
|
||||
}
|
||||
}
|
||||
|
||||
/// Appending two generic sequences
|
||||
#[inline(always)]
|
||||
pure fn append<T: Copy,IT: BaseIter<T>,BT: Buildable<T>>(
|
||||
lhs: IT, rhs: IT) -> BT {
|
||||
let size_opt = lhs.size_hint().chain(
|
||||
|sz1| rhs.size_hint().map(|sz2| sz1+sz2));
|
||||
pub pure 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); }
|
||||
|
|
@ -300,8 +306,8 @@ pure fn append<T: Copy,IT: BaseIter<T>,BT: Buildable<T>>(
|
|||
/// Copies a generic sequence, possibly converting it to a different
|
||||
/// type of sequence.
|
||||
#[inline(always)]
|
||||
pure fn copy_seq<T: Copy,IT: BaseIter<T>,BT: Buildable<T>>(
|
||||
v: IT) -> BT {
|
||||
pub pure 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); }
|
||||
}
|
||||
|
|
|
|||
1439
src/libcore/libc.rs
1439
src/libcore/libc.rs
File diff suppressed because it is too large
Load diff
|
|
@ -6,18 +6,15 @@
|
|||
|
||||
use cast::transmute;
|
||||
|
||||
export console_on, console_off, log_type;
|
||||
|
||||
#[nolink]
|
||||
extern mod rustrt {
|
||||
#[legacy_exports];
|
||||
fn rust_log_console_on();
|
||||
fn rust_log_console_off();
|
||||
fn rust_log_str(level: u32, string: *libc::c_char, size: libc::size_t);
|
||||
}
|
||||
|
||||
/// Turns on logging to stdout globally
|
||||
fn console_on() {
|
||||
pub fn console_on() {
|
||||
rustrt::rust_log_console_on();
|
||||
}
|
||||
|
||||
|
|
@ -28,7 +25,7 @@ fn console_on() {
|
|||
* runtime environment's logging spec, e.g. by setting
|
||||
* the RUST_LOG environment variable
|
||||
*/
|
||||
fn console_off() {
|
||||
pub fn console_off() {
|
||||
rustrt::rust_log_console_off();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,15 +8,12 @@ dynamic checks: your program will fail if you attempt to perform
|
|||
mutation when the data structure should be immutable.
|
||||
|
||||
*/
|
||||
|
||||
#[forbid(deprecated_mode)];
|
||||
// tjc: re-forbid deprecated modes after snapshot
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use util::with;
|
||||
use cast::transmute_immut;
|
||||
|
||||
export Mut;
|
||||
|
||||
enum Mode { ReadOnly, Mutable, Immutable }
|
||||
|
||||
struct Data<T> {
|
||||
|
|
@ -24,18 +21,18 @@ struct Data<T> {
|
|||
priv mut mode: Mode
|
||||
}
|
||||
|
||||
type Mut<T> = Data<T>;
|
||||
pub type Mut<T> = Data<T>;
|
||||
|
||||
fn Mut<T>(+t: T) -> Mut<T> {
|
||||
pub fn Mut<T>(t: T) -> Mut<T> {
|
||||
Data {value: t, mode: ReadOnly}
|
||||
}
|
||||
|
||||
fn unwrap<T>(+m: Mut<T>) -> T {
|
||||
pub fn unwrap<T>(m: Mut<T>) -> T {
|
||||
// Borrowck should prevent us from calling unwrap while the value
|
||||
// is in use, as that would be a move from a borrowed value.
|
||||
assert (m.mode as uint) == (ReadOnly as uint);
|
||||
let Data {value, mode: _} <- m;
|
||||
return move value;
|
||||
let Data {value: move value, mode: _} = move m;
|
||||
return value;
|
||||
}
|
||||
|
||||
impl<T> Data<T> {
|
||||
|
|
@ -71,7 +68,7 @@ impl<T> Data<T> {
|
|||
#[test]
|
||||
#[ignore(cfg(windows))]
|
||||
#[should_fail]
|
||||
fn test_mut_in_imm() {
|
||||
pub fn test_mut_in_imm() {
|
||||
let m = @Mut(1);
|
||||
do m.borrow_imm |_p| {
|
||||
do m.borrow_mut |_q| {
|
||||
|
|
@ -83,7 +80,7 @@ fn test_mut_in_imm() {
|
|||
#[test]
|
||||
#[ignore(cfg(windows))]
|
||||
#[should_fail]
|
||||
fn test_imm_in_mut() {
|
||||
pub fn test_imm_in_mut() {
|
||||
let m = @Mut(1);
|
||||
do m.borrow_mut |_p| {
|
||||
do m.borrow_imm |_q| {
|
||||
|
|
@ -93,7 +90,7 @@ fn test_imm_in_mut() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_const_in_mut() {
|
||||
pub fn test_const_in_mut() {
|
||||
let m = @Mut(1);
|
||||
do m.borrow_mut |p| {
|
||||
do m.borrow_const |q| {
|
||||
|
|
@ -105,7 +102,7 @@ fn test_const_in_mut() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_mut_in_const() {
|
||||
pub fn test_mut_in_const() {
|
||||
let m = @Mut(1);
|
||||
do m.borrow_const |p| {
|
||||
do m.borrow_mut |q| {
|
||||
|
|
@ -117,7 +114,7 @@ fn test_mut_in_const() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_imm_in_const() {
|
||||
pub fn test_imm_in_const() {
|
||||
let m = @Mut(1);
|
||||
do m.borrow_const |p| {
|
||||
do m.borrow_imm |q| {
|
||||
|
|
@ -127,7 +124,7 @@ fn test_imm_in_const() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_const_in_imm() {
|
||||
pub fn test_const_in_imm() {
|
||||
let m = @Mut(1);
|
||||
do m.borrow_imm |p| {
|
||||
do m.borrow_const |q| {
|
||||
|
|
@ -140,7 +137,7 @@ fn test_const_in_imm() {
|
|||
#[test]
|
||||
#[ignore(cfg(windows))]
|
||||
#[should_fail]
|
||||
fn test_mut_in_imm_in_const() {
|
||||
pub fn test_mut_in_imm_in_const() {
|
||||
let m = @Mut(1);
|
||||
do m.borrow_const |_p| {
|
||||
do m.borrow_imm |_q| {
|
||||
|
|
@ -149,3 +146,4 @@ fn test_mut_in_imm_in_const() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
//! An interface for numeric types
|
||||
|
||||
trait Num {
|
||||
pub trait Num {
|
||||
// FIXME: Trait composition. (#2616)
|
||||
pure fn add(&&other: self) -> self;
|
||||
pure fn sub(&&other: self) -> self;
|
||||
pure fn mul(&&other: self) -> self;
|
||||
pure fn div(&&other: self) -> self;
|
||||
pure fn modulo(&&other: self) -> self;
|
||||
pure fn add(other: &self) -> self;
|
||||
pure fn sub(other: &self) -> self;
|
||||
pure fn mul(other: &self) -> self;
|
||||
pure fn div(other: &self) -> self;
|
||||
pure fn modulo(other: &self) -> self;
|
||||
pure fn neg() -> self;
|
||||
|
||||
pure fn to_int() -> int;
|
||||
|
|
|
|||
|
|
@ -1,82 +1,82 @@
|
|||
// Core operators and kinds.
|
||||
|
||||
#[lang="const"]
|
||||
trait Const {
|
||||
pub trait Const {
|
||||
// Empty.
|
||||
}
|
||||
|
||||
#[lang="copy"]
|
||||
trait Copy {
|
||||
pub trait Copy {
|
||||
// Empty.
|
||||
}
|
||||
|
||||
#[lang="send"]
|
||||
trait Send {
|
||||
pub trait Send {
|
||||
// Empty.
|
||||
}
|
||||
|
||||
#[lang="owned"]
|
||||
trait Owned {
|
||||
pub trait Owned {
|
||||
// Empty.
|
||||
}
|
||||
|
||||
#[lang="add"]
|
||||
trait Add<RHS,Result> {
|
||||
pub trait Add<RHS,Result> {
|
||||
pure fn add(rhs: &RHS) -> Result;
|
||||
}
|
||||
|
||||
#[lang="sub"]
|
||||
trait Sub<RHS,Result> {
|
||||
pub trait Sub<RHS,Result> {
|
||||
pure fn sub(rhs: &RHS) -> Result;
|
||||
}
|
||||
|
||||
#[lang="mul"]
|
||||
trait Mul<RHS,Result> {
|
||||
pub trait Mul<RHS,Result> {
|
||||
pure fn mul(rhs: &RHS) -> Result;
|
||||
}
|
||||
|
||||
#[lang="div"]
|
||||
trait Div<RHS,Result> {
|
||||
pub trait Div<RHS,Result> {
|
||||
pure fn div(rhs: &RHS) -> Result;
|
||||
}
|
||||
|
||||
#[lang="modulo"]
|
||||
trait Modulo<RHS,Result> {
|
||||
pub trait Modulo<RHS,Result> {
|
||||
pure fn modulo(rhs: &RHS) -> Result;
|
||||
}
|
||||
|
||||
#[lang="neg"]
|
||||
trait Neg<Result> {
|
||||
pub trait Neg<Result> {
|
||||
pure fn neg() -> Result;
|
||||
}
|
||||
|
||||
#[lang="bitand"]
|
||||
trait BitAnd<RHS,Result> {
|
||||
pub trait BitAnd<RHS,Result> {
|
||||
pure fn bitand(rhs: &RHS) -> Result;
|
||||
}
|
||||
|
||||
#[lang="bitor"]
|
||||
trait BitOr<RHS,Result> {
|
||||
pub trait BitOr<RHS,Result> {
|
||||
pure fn bitor(rhs: &RHS) -> Result;
|
||||
}
|
||||
|
||||
#[lang="bitxor"]
|
||||
trait BitXor<RHS,Result> {
|
||||
pub trait BitXor<RHS,Result> {
|
||||
pure fn bitxor(rhs: &RHS) -> Result;
|
||||
}
|
||||
|
||||
#[lang="shl"]
|
||||
trait Shl<RHS,Result> {
|
||||
pub trait Shl<RHS,Result> {
|
||||
pure fn shl(rhs: &RHS) -> Result;
|
||||
}
|
||||
|
||||
#[lang="shr"]
|
||||
trait Shr<RHS,Result> {
|
||||
pub trait Shr<RHS,Result> {
|
||||
pure fn shr(rhs: &RHS) -> Result;
|
||||
}
|
||||
|
||||
#[lang="index"]
|
||||
trait Index<Index,Result> {
|
||||
pub trait Index<Index,Result> {
|
||||
pure fn index(index: Index) -> Result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,18 +9,18 @@
|
|||
*/
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[warn(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use cmp::Eq;
|
||||
|
||||
/// The option type
|
||||
enum Option<T> {
|
||||
pub enum Option<T> {
|
||||
None,
|
||||
Some(T),
|
||||
}
|
||||
|
||||
pure fn get<T: Copy>(opt: &Option<T>) -> T {
|
||||
pub pure fn get<T: Copy>(opt: &Option<T>) -> T {
|
||||
/*!
|
||||
* Gets the value out of an option
|
||||
*
|
||||
|
|
@ -30,12 +30,12 @@ pure fn get<T: Copy>(opt: &Option<T>) -> T {
|
|||
*/
|
||||
|
||||
match *opt {
|
||||
Some(x) => return x,
|
||||
Some(copy x) => return x,
|
||||
None => fail ~"option::get none"
|
||||
}
|
||||
}
|
||||
|
||||
pure fn get_ref<T>(opt: &r/Option<T>) -> &r/T {
|
||||
pub pure fn get_ref<T>(opt: &r/Option<T>) -> &r/T {
|
||||
/*!
|
||||
* Gets an immutable reference to the value inside an option.
|
||||
*
|
||||
|
|
@ -49,7 +49,7 @@ pure fn get_ref<T>(opt: &r/Option<T>) -> &r/T {
|
|||
}
|
||||
}
|
||||
|
||||
pure fn expect<T: Copy>(opt: &Option<T>, +reason: ~str) -> T {
|
||||
pub pure fn expect<T: Copy>(opt: &Option<T>, reason: ~str) -> T {
|
||||
/*!
|
||||
* Gets the value out of an option, printing a specified message on
|
||||
* failure
|
||||
|
|
@ -58,22 +58,17 @@ pure fn expect<T: Copy>(opt: &Option<T>, +reason: ~str) -> T {
|
|||
*
|
||||
* Fails if the value equals `none`
|
||||
*/
|
||||
match *opt { Some(x) => x, None => fail reason }
|
||||
match *opt { Some(copy x) => x, None => fail reason }
|
||||
}
|
||||
|
||||
pure fn map<T, U>(opt: &Option<T>, f: fn(T) -> U) -> Option<U> {
|
||||
//! Maps a `some` value from one type to another
|
||||
|
||||
match *opt { Some(x) => Some(f(x)), None => None }
|
||||
}
|
||||
|
||||
pure fn map_ref<T, U>(opt: &Option<T>, f: fn(x: &T) -> U) -> Option<U> {
|
||||
pub pure fn map<T, U>(opt: &Option<T>, f: fn(x: &T) -> U) -> Option<U> {
|
||||
//! Maps a `some` value by reference from one type to another
|
||||
|
||||
match *opt { Some(ref x) => Some(f(x)), None => None }
|
||||
}
|
||||
|
||||
pure fn map_consume<T, U>(+opt: Option<T>, f: fn(+v: T) -> U) -> Option<U> {
|
||||
pub pure fn map_consume<T, U>(opt: Option<T>,
|
||||
f: fn(v: T) -> U) -> Option<U> {
|
||||
/*!
|
||||
* As `map`, but consumes the option and gives `f` ownership to avoid
|
||||
* copying.
|
||||
|
|
@ -81,17 +76,23 @@ pure fn map_consume<T, U>(+opt: Option<T>, f: fn(+v: T) -> U) -> Option<U> {
|
|||
if opt.is_some() { Some(f(option::unwrap(move opt))) } else { None }
|
||||
}
|
||||
|
||||
pure fn chain<T, U>(opt: &Option<T>, f: fn(T) -> Option<U>) -> Option<U> {
|
||||
pub pure fn chain<T, U>(opt: Option<T>,
|
||||
f: fn(t: T) -> Option<U>) -> Option<U> {
|
||||
/*!
|
||||
* Update an optional value by optionally running its content through a
|
||||
* function that returns an option.
|
||||
*/
|
||||
|
||||
match *opt { Some(x) => f(x), None => None }
|
||||
// XXX write with move match
|
||||
if opt.is_some() {
|
||||
f(unwrap(opt))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pure fn chain_ref<T, U>(opt: &Option<T>,
|
||||
f: fn(x: &T) -> Option<U>) -> Option<U> {
|
||||
pub pure fn chain_ref<T, U>(opt: &Option<T>,
|
||||
f: fn(x: &T) -> Option<U>) -> Option<U> {
|
||||
/*!
|
||||
* Update an optional value by optionally running its content by reference
|
||||
* through a function that returns an option.
|
||||
|
|
@ -100,7 +101,7 @@ pure fn chain_ref<T, U>(opt: &Option<T>,
|
|||
match *opt { Some(ref x) => f(x), None => None }
|
||||
}
|
||||
|
||||
pure fn or<T>(+opta: Option<T>, +optb: Option<T>) -> Option<T> {
|
||||
pub pure fn or<T>(opta: Option<T>, optb: Option<T>) -> Option<T> {
|
||||
/*!
|
||||
* Returns the leftmost some() value, or none if both are none.
|
||||
*/
|
||||
|
|
@ -111,7 +112,7 @@ pure fn or<T>(+opta: Option<T>, +optb: Option<T>) -> Option<T> {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
pure fn while_some<T>(+x: Option<T>, blk: fn(+v: T) -> Option<T>) {
|
||||
pub pure fn while_some<T>(x: Option<T>, blk: fn(v: T) -> Option<T>) {
|
||||
//! Applies a function zero or more times until the result is none.
|
||||
|
||||
let mut opt <- x;
|
||||
|
|
@ -120,54 +121,38 @@ pure fn while_some<T>(+x: Option<T>, blk: fn(+v: T) -> Option<T>) {
|
|||
}
|
||||
}
|
||||
|
||||
pure fn is_none<T>(opt: &Option<T>) -> bool {
|
||||
pub pure fn is_none<T>(opt: &Option<T>) -> bool {
|
||||
//! Returns true if the option equals `none`
|
||||
|
||||
match *opt { None => true, Some(_) => false }
|
||||
}
|
||||
|
||||
pure fn is_some<T>(opt: &Option<T>) -> bool {
|
||||
pub pure fn is_some<T>(opt: &Option<T>) -> bool {
|
||||
//! Returns true if the option contains some value
|
||||
|
||||
!is_none(opt)
|
||||
}
|
||||
|
||||
pure fn get_default<T: Copy>(opt: &Option<T>, +def: T) -> T {
|
||||
pub pure fn get_default<T: Copy>(opt: &Option<T>, def: T) -> T {
|
||||
//! Returns the contained value or a default
|
||||
|
||||
match *opt { Some(x) => x, None => def }
|
||||
match *opt { Some(copy x) => x, None => def }
|
||||
}
|
||||
|
||||
pure fn map_default<T, U>(opt: &Option<T>, +def: U, f: fn(T) -> U) -> U {
|
||||
//! Applies a function to the contained value or returns a default
|
||||
|
||||
match *opt { None => move def, Some(t) => f(t) }
|
||||
}
|
||||
|
||||
// This should replace map_default.
|
||||
pure fn map_default_ref<T, U>(opt: &Option<T>, +def: U,
|
||||
pub pure fn map_default<T, U>(opt: &Option<T>, def: U,
|
||||
f: fn(x: &T) -> U) -> U {
|
||||
//! Applies a function to the contained value or returns a default
|
||||
|
||||
match *opt { None => move def, Some(ref t) => f(t) }
|
||||
}
|
||||
|
||||
// This should change to by-copy mode; use iter_ref below for by reference
|
||||
pure fn iter<T>(opt: &Option<T>, f: fn(T)) {
|
||||
//! Performs an operation on the contained value or does nothing
|
||||
|
||||
match *opt { None => (), Some(t) => f(t) }
|
||||
}
|
||||
|
||||
pure fn iter_ref<T>(opt: &Option<T>, f: fn(x: &T)) {
|
||||
pub pure fn iter<T>(opt: &Option<T>, f: fn(x: &T)) {
|
||||
//! Performs an operation on the contained value by reference
|
||||
match *opt { None => (), Some(ref t) => f(t) }
|
||||
}
|
||||
|
||||
// tjc: shouldn't this be - instead of +?
|
||||
// then could get rid of some superfluous moves
|
||||
#[inline(always)]
|
||||
pure fn unwrap<T>(+opt: Option<T>) -> T {
|
||||
pub pure fn unwrap<T>(opt: Option<T>) -> T {
|
||||
/*!
|
||||
* Moves a value out of an option type and returns it.
|
||||
*
|
||||
|
|
@ -182,12 +167,12 @@ pure fn unwrap<T>(+opt: Option<T>) -> T {
|
|||
|
||||
/// The ubiquitous option dance.
|
||||
#[inline(always)]
|
||||
fn swap_unwrap<T>(opt: &mut Option<T>) -> T {
|
||||
pub fn swap_unwrap<T>(opt: &mut Option<T>) -> T {
|
||||
if opt.is_none() { fail ~"option::swap_unwrap none" }
|
||||
unwrap(util::replace(opt, None))
|
||||
}
|
||||
|
||||
pure fn unwrap_expect<T>(+opt: Option<T>, reason: &str) -> T {
|
||||
pub pure fn unwrap_expect<T>(opt: Option<T>, reason: &str) -> T {
|
||||
//! As unwrap, but with a specified failure message.
|
||||
if opt.is_none() { fail reason.to_unique(); }
|
||||
unwrap(move opt)
|
||||
|
|
@ -195,22 +180,10 @@ pure fn unwrap_expect<T>(+opt: Option<T>, reason: &str) -> T {
|
|||
|
||||
// Some of these should change to be &Option<T>, some should not. See below.
|
||||
impl<T> Option<T> {
|
||||
/**
|
||||
* Update an optional value by optionally running its content through a
|
||||
* function that returns an option.
|
||||
*/
|
||||
pure fn chain<U>(f: fn(T) -> Option<U>) -> Option<U> { chain(&self, f) }
|
||||
/// Applies a function to the contained value or returns a default
|
||||
pure fn map_default<U>(+def: U, f: fn(T) -> U) -> U
|
||||
{ map_default(&self, move def, f) }
|
||||
/// Performs an operation on the contained value or does nothing
|
||||
pure fn iter(f: fn(T)) { iter(&self, f) }
|
||||
/// Returns true if the option equals `none`
|
||||
pure fn is_none() -> bool { is_none(&self) }
|
||||
/// Returns true if the option contains some value
|
||||
pure fn is_some() -> bool { is_some(&self) }
|
||||
/// Maps a `some` value from one type to another
|
||||
pure fn map<U>(f: fn(T) -> U) -> Option<U> { map(&self, f) }
|
||||
}
|
||||
|
||||
impl<T> &Option<T> {
|
||||
|
|
@ -222,12 +195,12 @@ impl<T> &Option<T> {
|
|||
chain_ref(self, f)
|
||||
}
|
||||
/// Applies a function to the contained value or returns a default
|
||||
pure fn map_default_ref<U>(+def: U, f: fn(x: &T) -> U) -> U
|
||||
{ map_default_ref(self, move def, f) }
|
||||
pure fn map_default<U>(def: U, f: fn(x: &T) -> U) -> U
|
||||
{ map_default(self, move def, f) }
|
||||
/// Performs an operation on the contained value by reference
|
||||
pure fn iter_ref(f: fn(x: &T)) { iter_ref(self, f) }
|
||||
pure fn iter(f: fn(x: &T)) { iter(self, f) }
|
||||
/// Maps a `some` value from one type to another by reference
|
||||
pure fn map_ref<U>(f: fn(x: &T) -> U) -> Option<U> { map_ref(self, f) }
|
||||
pure fn map<U>(f: fn(x: &T) -> U) -> Option<U> { map(self, f) }
|
||||
/// Gets an immutable reference to the value inside a `some`.
|
||||
pure fn get_ref() -> &self/T { get_ref(self) }
|
||||
}
|
||||
|
|
@ -241,7 +214,7 @@ impl<T: Copy> Option<T> {
|
|||
* Fails if the value equals `none`
|
||||
*/
|
||||
pure fn get() -> T { get(&self) }
|
||||
pure fn get_default(+def: T) -> T { get_default(&self, def) }
|
||||
pure fn get_default(def: T) -> T { get_default(&self, def) }
|
||||
/**
|
||||
* Gets the value out of an option, printing a specified message on
|
||||
* failure
|
||||
|
|
@ -250,9 +223,9 @@ impl<T: Copy> Option<T> {
|
|||
*
|
||||
* Fails if the value equals `none`
|
||||
*/
|
||||
pure fn expect(+reason: ~str) -> T { expect(&self, reason) }
|
||||
pure fn expect(reason: ~str) -> T { expect(&self, reason) }
|
||||
/// Applies a function zero or more times until the result is none.
|
||||
pure fn while_some(blk: fn(+v: T) -> Option<T>) { while_some(self, blk) }
|
||||
pure fn while_some(blk: fn(v: T) -> Option<T>) { while_some(self, blk) }
|
||||
}
|
||||
|
||||
impl<T: Eq> Option<T> : Eq {
|
||||
|
|
@ -264,11 +237,11 @@ impl<T: Eq> Option<T> : Eq {
|
|||
Some(_) => false
|
||||
}
|
||||
}
|
||||
Some(self_contents) => {
|
||||
Some(ref self_contents) => {
|
||||
match (*other) {
|
||||
None => false,
|
||||
Some(ref other_contents) =>
|
||||
self_contents.eq(other_contents)
|
||||
(*self_contents).eq(other_contents)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -279,20 +252,20 @@ impl<T: Eq> Option<T> : Eq {
|
|||
#[test]
|
||||
fn test_unwrap_ptr() {
|
||||
let x = ~0;
|
||||
let addr_x = ptr::addr_of(*x);
|
||||
let addr_x = ptr::p2::addr_of(&(*x));
|
||||
let opt = Some(x);
|
||||
let y = unwrap(opt);
|
||||
let addr_y = ptr::addr_of(*y);
|
||||
let addr_y = ptr::p2::addr_of(&(*y));
|
||||
assert addr_x == addr_y;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unwrap_str() {
|
||||
let x = ~"test";
|
||||
let addr_x = str::as_buf(x, |buf, _len| ptr::addr_of(buf));
|
||||
let opt = Some(x);
|
||||
let y = unwrap(opt);
|
||||
let addr_y = str::as_buf(y, |buf, _len| ptr::addr_of(buf));
|
||||
let addr_x = str::as_buf(x, |buf, _len| buf);
|
||||
let opt = Some(move x);
|
||||
let y = unwrap(move opt);
|
||||
let addr_y = str::as_buf(y, |buf, _len| buf);
|
||||
assert addr_x == addr_y;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
// tjc: re-forbid
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
/*!
|
||||
|
|
@ -21,34 +21,23 @@
|
|||
*/
|
||||
|
||||
use libc::{c_char, c_void, c_int, c_uint, size_t, ssize_t,
|
||||
mode_t, pid_t, FILE};
|
||||
use libc::{close, fclose};
|
||||
mode_t, pid_t, FILE};
|
||||
pub use libc::{close, fclose};
|
||||
|
||||
use option::{Some, None};
|
||||
|
||||
use consts::*;
|
||||
pub use consts::*;
|
||||
use task::TaskBuilder;
|
||||
|
||||
export close, fclose, fsync_fd, waitpid;
|
||||
export env, getenv, setenv, fdopen, pipe;
|
||||
export getcwd, dll_filename, self_exe_path;
|
||||
export exe_suffix, dll_suffix, sysname, arch, family;
|
||||
export homedir, tmpdir, list_dir, list_dir_path, path_is_dir, path_exists,
|
||||
make_absolute, make_dir, remove_dir, change_dir, remove_file,
|
||||
copy_file;
|
||||
export last_os_error;
|
||||
export set_exit_status;
|
||||
export walk_dir;
|
||||
|
||||
// FIXME: move these to str perhaps? #2620
|
||||
export as_c_charp, fill_charp_buf;
|
||||
|
||||
extern mod rustrt {
|
||||
#[legacy_exports];
|
||||
fn rust_get_argc() -> c_int;
|
||||
fn rust_get_argv() -> **c_char;
|
||||
fn rust_getcwd() -> ~str;
|
||||
fn rust_path_is_dir(path: *libc::c_char) -> c_int;
|
||||
fn rust_path_exists(path: *libc::c_char) -> c_int;
|
||||
fn rust_list_files(path: ~str) -> ~[~str];
|
||||
fn rust_list_files2(&&path: ~str) -> ~[~str];
|
||||
fn rust_process_wait(handle: c_int) -> c_int;
|
||||
fn last_os_error() -> ~str;
|
||||
fn rust_set_exit_status(code: libc::intptr_t);
|
||||
|
|
@ -57,15 +46,15 @@ extern mod rustrt {
|
|||
|
||||
const tmpbuf_sz : uint = 1000u;
|
||||
|
||||
fn getcwd() -> Path {
|
||||
pub fn getcwd() -> Path {
|
||||
Path(rustrt::rust_getcwd())
|
||||
}
|
||||
|
||||
fn as_c_charp<T>(s: &str, f: fn(*c_char) -> T) -> T {
|
||||
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))
|
||||
}
|
||||
|
||||
fn fill_charp_buf(f: fn(*mut c_char, size_t) -> bool)
|
||||
pub fn fill_charp_buf(f: fn(*mut c_char, size_t) -> bool)
|
||||
-> Option<~str> {
|
||||
let buf = vec::to_mut(vec::from_elem(tmpbuf_sz, 0u8 as c_char));
|
||||
do vec::as_mut_buf(buf) |b, sz| {
|
||||
|
|
@ -79,29 +68,23 @@ fn fill_charp_buf(f: fn(*mut c_char, size_t) -> bool)
|
|||
|
||||
#[cfg(windows)]
|
||||
mod win32 {
|
||||
#[legacy_exports];
|
||||
use dword = libc::types::os::arch::extra::DWORD;
|
||||
use libc::DWORD;
|
||||
|
||||
fn fill_utf16_buf_and_decode(f: fn(*mut u16, dword) -> dword)
|
||||
pub fn fill_utf16_buf_and_decode(f: fn(*mut u16, DWORD) -> DWORD)
|
||||
-> Option<~str> {
|
||||
|
||||
// FIXME: remove these when export globs work properly. #1238
|
||||
use libc::funcs::extra::kernel32::*;
|
||||
use libc::consts::os::extra::*;
|
||||
|
||||
let mut n = tmpbuf_sz as dword;
|
||||
let mut n = tmpbuf_sz as DWORD;
|
||||
let mut res = None;
|
||||
let mut done = false;
|
||||
while !done {
|
||||
let buf = vec::to_mut(vec::from_elem(n as uint, 0u16));
|
||||
do vec::as_mut_buf(buf) |b, _sz| {
|
||||
let k : dword = f(b, tmpbuf_sz as dword);
|
||||
if k == (0 as dword) {
|
||||
let k : DWORD = f(b, tmpbuf_sz as DWORD);
|
||||
if k == (0 as DWORD) {
|
||||
done = true;
|
||||
} else if (k == n &&
|
||||
GetLastError() ==
|
||||
ERROR_INSUFFICIENT_BUFFER as dword) {
|
||||
n *= (2 as dword);
|
||||
libc::GetLastError() ==
|
||||
libc::ERROR_INSUFFICIENT_BUFFER as DWORD) {
|
||||
n *= (2 as DWORD);
|
||||
} else {
|
||||
let sub = vec::slice(buf, 0u, k as uint);
|
||||
res = option::Some(str::from_utf16(sub));
|
||||
|
|
@ -112,7 +95,7 @@ mod win32 {
|
|||
return res;
|
||||
}
|
||||
|
||||
fn as_utf16_p<T>(s: &str, f: fn(*u16) -> T) -> T {
|
||||
pub fn as_utf16_p<T>(s: &str, f: fn(*u16) -> T) -> T {
|
||||
let mut t = str::to_utf16(s);
|
||||
// Null terminate before passing on.
|
||||
t += ~[0u16];
|
||||
|
|
@ -120,28 +103,22 @@ mod win32 {
|
|||
}
|
||||
}
|
||||
|
||||
fn getenv(n: &str) -> Option<~str> {
|
||||
pub fn getenv(n: &str) -> Option<~str> {
|
||||
global_env::getenv(n)
|
||||
}
|
||||
|
||||
fn setenv(n: &str, v: &str) {
|
||||
pub fn setenv(n: &str, v: &str) {
|
||||
global_env::setenv(n, v)
|
||||
}
|
||||
|
||||
fn env() -> ~[(~str,~str)] {
|
||||
pub fn env() -> ~[(~str,~str)] {
|
||||
global_env::env()
|
||||
}
|
||||
|
||||
mod global_env {
|
||||
#[legacy_exports];
|
||||
//! Internal module for serializing access to getenv/setenv
|
||||
|
||||
export getenv;
|
||||
export setenv;
|
||||
export env;
|
||||
|
||||
extern mod rustrt {
|
||||
#[legacy_exports];
|
||||
fn rust_global_env_chan_ptr() -> *libc::uintptr_t;
|
||||
}
|
||||
|
||||
|
|
@ -151,7 +128,7 @@ mod global_env {
|
|||
MsgEnv(comm::Chan<~[(~str,~str)]>)
|
||||
}
|
||||
|
||||
fn getenv(n: &str) -> Option<~str> {
|
||||
pub fn getenv(n: &str) -> Option<~str> {
|
||||
let env_ch = get_global_env_chan();
|
||||
let po = comm::Port();
|
||||
comm::send(env_ch, MsgGetEnv(str::from_slice(n),
|
||||
|
|
@ -159,7 +136,7 @@ mod global_env {
|
|||
comm::recv(po)
|
||||
}
|
||||
|
||||
fn setenv(n: &str, v: &str) {
|
||||
pub fn setenv(n: &str, v: &str) {
|
||||
let env_ch = get_global_env_chan();
|
||||
let po = comm::Port();
|
||||
comm::send(env_ch, MsgSetEnv(str::from_slice(n),
|
||||
|
|
@ -168,7 +145,7 @@ mod global_env {
|
|||
comm::recv(po)
|
||||
}
|
||||
|
||||
fn env() -> ~[(~str,~str)] {
|
||||
pub fn env() -> ~[(~str,~str)] {
|
||||
let env_ch = get_global_env_chan();
|
||||
let po = comm::Port();
|
||||
comm::send(env_ch, MsgEnv(comm::Chan(po)));
|
||||
|
|
@ -191,11 +168,11 @@ mod global_env {
|
|||
do private::weaken_task |weak_po| {
|
||||
loop {
|
||||
match comm::select2(msg_po, weak_po) {
|
||||
either::Left(MsgGetEnv(n, resp_ch)) => {
|
||||
comm::send(resp_ch, impl_::getenv(n))
|
||||
either::Left(MsgGetEnv(ref n, resp_ch)) => {
|
||||
comm::send(resp_ch, impl_::getenv(*n))
|
||||
}
|
||||
either::Left(MsgSetEnv(n, v, resp_ch)) => {
|
||||
comm::send(resp_ch, impl_::setenv(n, v))
|
||||
either::Left(MsgSetEnv(ref n, ref v, resp_ch)) => {
|
||||
comm::send(resp_ch, impl_::setenv(*n, *v))
|
||||
}
|
||||
either::Left(MsgEnv(resp_ch)) => {
|
||||
comm::send(resp_ch, impl_::env())
|
||||
|
|
@ -208,24 +185,22 @@ mod global_env {
|
|||
}
|
||||
|
||||
mod impl_ {
|
||||
#[legacy_exports];
|
||||
extern mod rustrt {
|
||||
#[legacy_exports];
|
||||
fn rust_env_pairs() -> ~[~str];
|
||||
}
|
||||
|
||||
fn env() -> ~[(~str,~str)] {
|
||||
pub fn env() -> ~[(~str,~str)] {
|
||||
let mut pairs = ~[];
|
||||
for vec::each(rustrt::rust_env_pairs()) |p| {
|
||||
let vs = str::splitn_char(*p, '=', 1u);
|
||||
assert vec::len(vs) == 2u;
|
||||
vec::push(pairs, (copy vs[0], copy vs[1]));
|
||||
pairs.push((copy vs[0], copy vs[1]));
|
||||
}
|
||||
move pairs
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn getenv(n: &str) -> Option<~str> {
|
||||
pub fn getenv(n: &str) -> Option<~str> {
|
||||
unsafe {
|
||||
let s = str::as_c_str(n, libc::getenv);
|
||||
return if ptr::null::<u8>() == cast::reinterpret_cast(&s) {
|
||||
|
|
@ -238,39 +213,32 @@ mod global_env {
|
|||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn getenv(n: &str) -> Option<~str> {
|
||||
use libc::types::os::arch::extra::*;
|
||||
use libc::funcs::extra::kernel32::*;
|
||||
pub fn getenv(n: &str) -> Option<~str> {
|
||||
use win32::*;
|
||||
do as_utf16_p(n) |u| {
|
||||
do fill_utf16_buf_and_decode() |buf, sz| {
|
||||
GetEnvironmentVariableW(u, buf, sz)
|
||||
libc::GetEnvironmentVariableW(u, buf, sz)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(unix)]
|
||||
fn setenv(n: &str, v: &str) {
|
||||
|
||||
// FIXME: remove this when export globs work properly. #1238
|
||||
use libc::funcs::posix01::unistd::setenv;
|
||||
pub fn setenv(n: &str, v: &str) {
|
||||
do str::as_c_str(n) |nbuf| {
|
||||
do str::as_c_str(v) |vbuf| {
|
||||
setenv(nbuf, vbuf, 1i32);
|
||||
libc::funcs::posix01::unistd::setenv(nbuf, vbuf, 1i32);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(windows)]
|
||||
fn setenv(n: &str, v: &str) {
|
||||
// FIXME: remove imports when export globs work properly. #1238
|
||||
use libc::funcs::extra::kernel32::*;
|
||||
pub fn setenv(n: &str, v: &str) {
|
||||
use win32::*;
|
||||
do as_utf16_p(n) |nbuf| {
|
||||
do as_utf16_p(v) |vbuf| {
|
||||
SetEnvironmentVariableW(nbuf, vbuf);
|
||||
libc::SetEnvironmentVariableW(nbuf, vbuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -278,7 +246,7 @@ mod global_env {
|
|||
}
|
||||
}
|
||||
|
||||
fn fdopen(fd: c_int) -> *FILE {
|
||||
pub fn fdopen(fd: c_int) -> *FILE {
|
||||
return do as_c_charp("r") |modebuf| {
|
||||
libc::fdopen(fd, modebuf)
|
||||
};
|
||||
|
|
@ -288,13 +256,13 @@ fn fdopen(fd: c_int) -> *FILE {
|
|||
// fsync related
|
||||
|
||||
#[cfg(windows)]
|
||||
fn fsync_fd(fd: c_int, _level: io::fsync::Level) -> c_int {
|
||||
pub fn fsync_fd(fd: c_int, _level: io::fsync::Level) -> c_int {
|
||||
use libc::funcs::extra::msvcrt::*;
|
||||
return commit(fd);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn fsync_fd(fd: c_int, level: io::fsync::Level) -> c_int {
|
||||
pub fn fsync_fd(fd: c_int, level: io::fsync::Level) -> c_int {
|
||||
use libc::funcs::posix01::unistd::*;
|
||||
match level {
|
||||
io::fsync::FSync
|
||||
|
|
@ -304,7 +272,7 @@ fn fsync_fd(fd: c_int, level: io::fsync::Level) -> c_int {
|
|||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
fn fsync_fd(fd: c_int, level: io::fsync::Level) -> c_int {
|
||||
pub fn fsync_fd(fd: c_int, level: io::fsync::Level) -> c_int {
|
||||
use libc::consts::os::extra::*;
|
||||
use libc::funcs::posix88::fcntl::*;
|
||||
use libc::funcs::posix01::unistd::*;
|
||||
|
|
@ -321,52 +289,50 @@ fn fsync_fd(fd: c_int, level: io::fsync::Level) -> c_int {
|
|||
}
|
||||
|
||||
#[cfg(target_os = "freebsd")]
|
||||
fn fsync_fd(fd: c_int, _l: io::fsync::Level) -> c_int {
|
||||
pub fn fsync_fd(fd: c_int, _l: io::fsync::Level) -> c_int {
|
||||
use libc::funcs::posix01::unistd::*;
|
||||
return fsync(fd);
|
||||
}
|
||||
|
||||
|
||||
#[cfg(windows)]
|
||||
fn waitpid(pid: pid_t) -> c_int {
|
||||
pub fn waitpid(pid: pid_t) -> c_int {
|
||||
return rustrt::rust_process_wait(pid);
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn waitpid(pid: pid_t) -> c_int {
|
||||
pub fn waitpid(pid: pid_t) -> c_int {
|
||||
use libc::funcs::posix01::wait::*;
|
||||
let status = 0 as c_int;
|
||||
|
||||
assert (waitpid(pid, ptr::mut_addr_of(status),
|
||||
assert (waitpid(pid, ptr::mut_addr_of(&status),
|
||||
0 as c_int) != (-1 as c_int));
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
#[cfg(unix)]
|
||||
fn pipe() -> {in: c_int, out: c_int} {
|
||||
pub fn pipe() -> {in: c_int, out: c_int} {
|
||||
let fds = {mut in: 0 as c_int,
|
||||
mut out: 0 as c_int };
|
||||
assert (libc::pipe(ptr::mut_addr_of(fds.in)) == (0 as c_int));
|
||||
assert (libc::pipe(ptr::mut_addr_of(&(fds.in))) == (0 as c_int));
|
||||
return {in: fds.in, out: fds.out};
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[cfg(windows)]
|
||||
fn pipe() -> {in: c_int, out: c_int} {
|
||||
// FIXME: remove this when export globs work properly. #1238
|
||||
use libc::consts::os::extra::*;
|
||||
pub fn pipe() -> {in: c_int, out: c_int} {
|
||||
// Windows pipes work subtly differently than unix pipes, and their
|
||||
// inheritance has to be handled in a different way that I do not fully
|
||||
// understand. Here we explicitly make the pipe non-inheritable, which
|
||||
// means to pass it to a subprocess they need to be duplicated first, as
|
||||
// in rust_run_program.
|
||||
let fds = { mut in: 0 as c_int,
|
||||
mut out: 0 as c_int };
|
||||
let res = libc::pipe(ptr::mut_addr_of(fds.in),
|
||||
mut out: 0 as c_int };
|
||||
let res = libc::pipe(ptr::mut_addr_of(&(fds.in)),
|
||||
1024 as c_uint,
|
||||
(O_BINARY | O_NOINHERIT) as c_int);
|
||||
(libc::O_BINARY | libc::O_NOINHERIT) as c_int);
|
||||
assert (res == 0 as c_int);
|
||||
assert (fds.in != -1 as c_int && fds.in != 0 as c_int);
|
||||
assert (fds.out != -1 as c_int && fds.in != 0 as c_int);
|
||||
|
|
@ -378,7 +344,7 @@ fn dup2(src: c_int, dst: c_int) -> c_int {
|
|||
}
|
||||
|
||||
|
||||
fn dll_filename(base: &str) -> ~str {
|
||||
pub fn dll_filename(base: &str) -> ~str {
|
||||
return pre() + str::from_slice(base) + dll_suffix();
|
||||
|
||||
#[cfg(unix)]
|
||||
|
|
@ -389,7 +355,7 @@ fn dll_filename(base: &str) -> ~str {
|
|||
}
|
||||
|
||||
|
||||
fn self_exe_path() -> Option<Path> {
|
||||
pub fn self_exe_path() -> Option<Path> {
|
||||
|
||||
#[cfg(target_os = "freebsd")]
|
||||
fn load_self() -> Option<~str> {
|
||||
|
|
@ -401,7 +367,7 @@ fn self_exe_path() -> Option<Path> {
|
|||
KERN_PROC as c_int,
|
||||
KERN_PROC_PATHNAME as c_int, -1 as c_int];
|
||||
sysctl(vec::raw::to_ptr(mib), vec::len(mib) as c_uint,
|
||||
buf as *mut c_void, ptr::mut_addr_of(sz),
|
||||
buf as *mut c_void, ptr::mut_addr_of(&sz),
|
||||
ptr::null(), 0u as size_t) == (0 as c_int)
|
||||
}
|
||||
}
|
||||
|
|
@ -419,27 +385,22 @@ fn self_exe_path() -> Option<Path> {
|
|||
|
||||
#[cfg(target_os = "macos")]
|
||||
fn load_self() -> Option<~str> {
|
||||
// FIXME: remove imports when export globs work properly. #1238
|
||||
use libc::funcs::extra::*;
|
||||
do fill_charp_buf() |buf, sz| {
|
||||
_NSGetExecutablePath(buf, ptr::mut_addr_of(sz as u32))
|
||||
== (0 as c_int)
|
||||
libc::funcs::extra::_NSGetExecutablePath(
|
||||
buf, ptr::mut_addr_of(&(sz as u32))) == (0 as c_int)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn load_self() -> Option<~str> {
|
||||
// FIXME: remove imports when export globs work properly. #1238
|
||||
use libc::types::os::arch::extra::*;
|
||||
use libc::funcs::extra::kernel32::*;
|
||||
use win32::*;
|
||||
do fill_utf16_buf_and_decode() |buf, sz| {
|
||||
GetModuleFileNameW(0u as dword, buf, sz)
|
||||
libc::GetModuleFileNameW(0u as libc::DWORD, buf, sz)
|
||||
}
|
||||
}
|
||||
|
||||
do load_self().map |pth| {
|
||||
Path(pth).dir_path()
|
||||
Path(*pth).dir_path()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -457,10 +418,10 @@ fn self_exe_path() -> Option<Path> {
|
|||
*
|
||||
* Otherwise, homedir returns option::none.
|
||||
*/
|
||||
fn homedir() -> Option<Path> {
|
||||
pub fn homedir() -> Option<Path> {
|
||||
return match getenv(~"HOME") {
|
||||
Some(p) => if !str::is_empty(p) {
|
||||
Some(Path(p))
|
||||
Some(ref p) => if !str::is_empty(*p) {
|
||||
Some(Path(*p))
|
||||
} else {
|
||||
secondary()
|
||||
},
|
||||
|
|
@ -474,7 +435,7 @@ fn homedir() -> Option<Path> {
|
|||
|
||||
#[cfg(windows)]
|
||||
fn secondary() -> Option<Path> {
|
||||
do option::chain(&getenv(~"USERPROFILE")) |p| {
|
||||
do option::chain(getenv(~"USERPROFILE")) |p| {
|
||||
if !str::is_empty(p) {
|
||||
Some(Path(p))
|
||||
} else {
|
||||
|
|
@ -494,12 +455,12 @@ fn homedir() -> Option<Path> {
|
|||
* 'USERPROFILE' environment variable if any are set and not the empty
|
||||
* string. Otherwise, tmpdir returns the path to the Windows directory.
|
||||
*/
|
||||
fn tmpdir() -> Path {
|
||||
pub fn tmpdir() -> Path {
|
||||
return lookup();
|
||||
|
||||
fn getenv_nonempty(v: &str) -> Option<Path> {
|
||||
match getenv(v) {
|
||||
Some(x) =>
|
||||
Some(move x) =>
|
||||
if str::is_empty(x) {
|
||||
None
|
||||
} else {
|
||||
|
|
@ -528,7 +489,7 @@ fn tmpdir() -> Path {
|
|||
}
|
||||
}
|
||||
/// Recursively walk a directory structure
|
||||
fn walk_dir(p: &Path, f: fn((&Path)) -> bool) {
|
||||
pub fn walk_dir(p: &Path, f: fn((&Path)) -> bool) {
|
||||
|
||||
walk_dir_(p, f);
|
||||
|
||||
|
|
@ -557,21 +518,19 @@ fn walk_dir(p: &Path, f: fn((&Path)) -> bool) {
|
|||
}
|
||||
|
||||
/// Indicates whether a path represents a directory
|
||||
fn path_is_dir(p: &Path) -> bool {
|
||||
pub fn path_is_dir(p: &Path) -> bool {
|
||||
do str::as_c_str(p.to_str()) |buf| {
|
||||
rustrt::rust_path_is_dir(buf) != 0 as c_int
|
||||
}
|
||||
}
|
||||
|
||||
/// Indicates whether a path exists
|
||||
fn path_exists(p: &Path) -> bool {
|
||||
pub fn path_exists(p: &Path) -> bool {
|
||||
do str::as_c_str(p.to_str()) |buf| {
|
||||
rustrt::rust_path_exists(buf) != 0 as c_int
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME (#2622): under Windows, we should prepend the current drive letter
|
||||
// to paths that start with a slash.
|
||||
/**
|
||||
* Convert a relative path to an absolute path
|
||||
*
|
||||
|
|
@ -582,7 +541,7 @@ fn path_exists(p: &Path) -> bool {
|
|||
// NB: this is here rather than in path because it is a form of environment
|
||||
// querying; what it does depends on the process working directory, not just
|
||||
// the input paths.
|
||||
fn make_absolute(p: &Path) -> Path {
|
||||
pub fn make_absolute(p: &Path) -> Path {
|
||||
if p.is_absolute {
|
||||
copy *p
|
||||
} else {
|
||||
|
|
@ -592,19 +551,18 @@ fn make_absolute(p: &Path) -> Path {
|
|||
|
||||
|
||||
/// Creates a directory at the specified path
|
||||
fn make_dir(p: &Path, mode: c_int) -> bool {
|
||||
pub fn make_dir(p: &Path, mode: c_int) -> bool {
|
||||
return mkdir(p, mode);
|
||||
|
||||
#[cfg(windows)]
|
||||
fn mkdir(p: &Path, _mode: c_int) -> bool {
|
||||
// FIXME: remove imports when export globs work properly. #1238
|
||||
use libc::types::os::arch::extra::*;
|
||||
use libc::funcs::extra::kernel32::*;
|
||||
use win32::*;
|
||||
// FIXME: turn mode into something useful? #2623
|
||||
do as_utf16_p(p.to_str()) |buf| {
|
||||
CreateDirectoryW(buf, unsafe { cast::reinterpret_cast(&0) })
|
||||
!= (0 as BOOL)
|
||||
libc::CreateDirectoryW(buf, unsafe {
|
||||
cast::reinterpret_cast(&0)
|
||||
})
|
||||
!= (0 as libc::BOOL)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -618,7 +576,7 @@ fn make_dir(p: &Path, mode: c_int) -> bool {
|
|||
|
||||
/// Lists the contents of a directory
|
||||
#[allow(non_implicitly_copyable_typarams)]
|
||||
fn list_dir(p: &Path) -> ~[~str] {
|
||||
pub fn list_dir(p: &Path) -> ~[~str] {
|
||||
|
||||
#[cfg(unix)]
|
||||
fn star(p: &Path) -> Path { copy *p }
|
||||
|
|
@ -626,8 +584,8 @@ fn list_dir(p: &Path) -> ~[~str] {
|
|||
#[cfg(windows)]
|
||||
fn star(p: &Path) -> Path { p.push("*") }
|
||||
|
||||
do rustrt::rust_list_files(star(p).to_str()).filter |filename| {
|
||||
filename != ~"." && filename != ~".."
|
||||
do rustrt::rust_list_files2(star(p).to_str()).filter |filename| {
|
||||
*filename != ~"." && *filename != ~".."
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -636,22 +594,19 @@ fn list_dir(p: &Path) -> ~[~str] {
|
|||
*
|
||||
* This version prepends each entry with the directory.
|
||||
*/
|
||||
fn list_dir_path(p: &Path) -> ~[~Path] {
|
||||
pub fn list_dir_path(p: &Path) -> ~[~Path] {
|
||||
os::list_dir(p).map(|f| ~p.push(*f))
|
||||
}
|
||||
|
||||
/// Removes a directory at the specified path
|
||||
fn remove_dir(p: &Path) -> bool {
|
||||
pub fn remove_dir(p: &Path) -> bool {
|
||||
return rmdir(p);
|
||||
|
||||
#[cfg(windows)]
|
||||
fn rmdir(p: &Path) -> bool {
|
||||
// FIXME: remove imports when export globs work properly. #1238
|
||||
use libc::funcs::extra::kernel32::*;
|
||||
use libc::types::os::arch::extra::*;
|
||||
use win32::*;
|
||||
return do as_utf16_p(p.to_str()) |buf| {
|
||||
RemoveDirectoryW(buf) != (0 as BOOL)
|
||||
libc::RemoveDirectoryW(buf) != (0 as libc::BOOL)
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -663,17 +618,14 @@ fn remove_dir(p: &Path) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
fn change_dir(p: &Path) -> bool {
|
||||
pub fn change_dir(p: &Path) -> bool {
|
||||
return chdir(p);
|
||||
|
||||
#[cfg(windows)]
|
||||
fn chdir(p: &Path) -> bool {
|
||||
// FIXME: remove imports when export globs work properly. #1238
|
||||
use libc::funcs::extra::kernel32::*;
|
||||
use libc::types::os::arch::extra::*;
|
||||
use win32::*;
|
||||
return do as_utf16_p(p.to_str()) |buf| {
|
||||
SetCurrentDirectoryW(buf) != (0 as BOOL)
|
||||
libc::SetCurrentDirectoryW(buf) != (0 as libc::BOOL)
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -686,18 +638,16 @@ fn change_dir(p: &Path) -> bool {
|
|||
}
|
||||
|
||||
/// Copies a file from one location to another
|
||||
fn copy_file(from: &Path, to: &Path) -> bool {
|
||||
pub fn copy_file(from: &Path, to: &Path) -> bool {
|
||||
return do_copy_file(from, to);
|
||||
|
||||
#[cfg(windows)]
|
||||
fn do_copy_file(from: &Path, to: &Path) -> bool {
|
||||
// FIXME: remove imports when export globs work properly. #1238
|
||||
use libc::funcs::extra::kernel32::*;
|
||||
use libc::types::os::arch::extra::*;
|
||||
use win32::*;
|
||||
return do as_utf16_p(from.to_str()) |fromp| {
|
||||
do as_utf16_p(to.to_str()) |top| {
|
||||
CopyFileW(fromp, top, (0 as BOOL)) != (0 as BOOL)
|
||||
libc::CopyFileW(fromp, top, (0 as libc::BOOL)) !=
|
||||
(0 as libc::BOOL)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -748,18 +698,14 @@ fn copy_file(from: &Path, to: &Path) -> bool {
|
|||
}
|
||||
|
||||
/// Deletes an existing file
|
||||
fn remove_file(p: &Path) -> bool {
|
||||
pub fn remove_file(p: &Path) -> bool {
|
||||
return unlink(p);
|
||||
|
||||
#[cfg(windows)]
|
||||
fn unlink(p: &Path) -> bool {
|
||||
// FIXME (similar to Issue #2006): remove imports when export globs
|
||||
// work properly.
|
||||
use libc::funcs::extra::kernel32::*;
|
||||
use libc::types::os::arch::extra::*;
|
||||
use win32::*;
|
||||
return do as_utf16_p(p.to_str()) |buf| {
|
||||
DeleteFileW(buf) != (0 as BOOL)
|
||||
libc::DeleteFileW(buf) != (0 as libc::BOOL)
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -772,7 +718,7 @@ fn remove_file(p: &Path) -> bool {
|
|||
}
|
||||
|
||||
/// Get a string representing the platform-dependent last error
|
||||
fn last_os_error() -> ~str {
|
||||
pub fn last_os_error() -> ~str {
|
||||
rustrt::last_os_error()
|
||||
}
|
||||
|
||||
|
|
@ -784,67 +730,175 @@ fn last_os_error() -> ~str {
|
|||
* and is supervised by the scheduler then any user-specified exit status is
|
||||
* ignored and the process exits with the default failure status
|
||||
*/
|
||||
fn set_exit_status(code: int) {
|
||||
pub fn set_exit_status(code: int) {
|
||||
rustrt::rust_set_exit_status(code as libc::intptr_t);
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn family() -> ~str { ~"unix" }
|
||||
unsafe fn load_argc_and_argv(argc: c_int, argv: **c_char) -> ~[~str] {
|
||||
let mut args = ~[];
|
||||
for uint::range(0, argc as uint) |i| {
|
||||
vec::push(&mut args, str::raw::from_c_str(*argv.offset(i)));
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the command line arguments
|
||||
*
|
||||
* Returns a list of the command line arguments.
|
||||
*/
|
||||
#[cfg(target_os = "macos")]
|
||||
fn real_args() -> ~[~str] {
|
||||
unsafe {
|
||||
let (argc, argv) = (*_NSGetArgc() as c_int,
|
||||
*_NSGetArgv() as **c_char);
|
||||
load_argc_and_argv(argc, argv)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[cfg(target_os = "freebsd")]
|
||||
fn real_args() -> ~[~str] {
|
||||
unsafe {
|
||||
let argc = rustrt::rust_get_argc();
|
||||
let argv = rustrt::rust_get_argv();
|
||||
load_argc_and_argv(argc, argv)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn family() -> ~str { ~"windows" }
|
||||
fn real_args() -> ~[~str] {
|
||||
let mut nArgs: c_int = 0;
|
||||
let lpArgCount = ptr::to_mut_unsafe_ptr(&mut nArgs);
|
||||
let lpCmdLine = GetCommandLineW();
|
||||
let szArgList = CommandLineToArgvW(lpCmdLine, lpArgCount);
|
||||
|
||||
let mut args = ~[];
|
||||
for uint::range(0, nArgs as uint) |i| {
|
||||
unsafe {
|
||||
// Determine the length of this argument.
|
||||
let ptr = *szArgList.offset(i);
|
||||
let mut len = 0;
|
||||
while *ptr.offset(len) != 0 { len += 1; }
|
||||
|
||||
// Push it onto the list.
|
||||
vec::push(&mut args,
|
||||
vec::raw::buf_as_slice(ptr, len,
|
||||
str::from_utf16));
|
||||
}
|
||||
}
|
||||
|
||||
unsafe {
|
||||
LocalFree(cast::transmute(szArgList));
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
type LPCWSTR = *u16;
|
||||
|
||||
#[cfg(windows)]
|
||||
#[link_name="kernel32"]
|
||||
#[abi="stdcall"]
|
||||
extern {
|
||||
fn GetCommandLineW() -> LPCWSTR;
|
||||
fn LocalFree(ptr: *c_void);
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
#[link_name="shell32"]
|
||||
#[abi="stdcall"]
|
||||
extern {
|
||||
fn CommandLineToArgvW(lpCmdLine: LPCWSTR, pNumArgs: *mut c_int) -> **u16;
|
||||
}
|
||||
|
||||
struct OverriddenArgs {
|
||||
val: ~[~str]
|
||||
}
|
||||
|
||||
fn overridden_arg_key(_v: @OverriddenArgs) {}
|
||||
|
||||
pub fn args() -> ~[~str] {
|
||||
unsafe {
|
||||
match task::local_data::local_data_get(overridden_arg_key) {
|
||||
None => real_args(),
|
||||
Some(args) => copy args.val
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_args(new_args: ~[~str]) {
|
||||
unsafe {
|
||||
let overridden_args = @OverriddenArgs { val: copy new_args };
|
||||
task::local_data::local_data_set(overridden_arg_key, overridden_args);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
extern {
|
||||
// These functions are in crt_externs.h.
|
||||
pub fn _NSGetArgc() -> *c_int;
|
||||
pub fn _NSGetArgv() -> ***c_char;
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
pub fn family() -> ~str { ~"unix" }
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn family() -> ~str { ~"windows" }
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
mod consts {
|
||||
#[legacy_exports];
|
||||
fn sysname() -> ~str { ~"macos" }
|
||||
fn exe_suffix() -> ~str { ~"" }
|
||||
fn dll_suffix() -> ~str { ~".dylib" }
|
||||
pub fn sysname() -> ~str { ~"macos" }
|
||||
pub fn exe_suffix() -> ~str { ~"" }
|
||||
pub fn dll_suffix() -> ~str { ~".dylib" }
|
||||
}
|
||||
|
||||
#[cfg(target_os = "freebsd")]
|
||||
mod consts {
|
||||
#[legacy_exports];
|
||||
fn sysname() -> ~str { ~"freebsd" }
|
||||
fn exe_suffix() -> ~str { ~"" }
|
||||
fn dll_suffix() -> ~str { ~".so" }
|
||||
pub fn sysname() -> ~str { ~"freebsd" }
|
||||
pub fn exe_suffix() -> ~str { ~"" }
|
||||
pub fn dll_suffix() -> ~str { ~".so" }
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
mod consts {
|
||||
#[legacy_exports];
|
||||
fn sysname() -> ~str { ~"linux" }
|
||||
fn exe_suffix() -> ~str { ~"" }
|
||||
fn dll_suffix() -> ~str { ~".so" }
|
||||
pub fn sysname() -> ~str { ~"linux" }
|
||||
pub fn exe_suffix() -> ~str { ~"" }
|
||||
pub fn dll_suffix() -> ~str { ~".so" }
|
||||
}
|
||||
|
||||
#[cfg(target_os = "win32")]
|
||||
mod consts {
|
||||
#[legacy_exports];
|
||||
fn sysname() -> ~str { ~"win32" }
|
||||
fn exe_suffix() -> ~str { ~".exe" }
|
||||
fn dll_suffix() -> ~str { ~".dll" }
|
||||
pub fn sysname() -> ~str { ~"win32" }
|
||||
pub fn exe_suffix() -> ~str { ~".exe" }
|
||||
pub fn dll_suffix() -> ~str { ~".dll" }
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86")]
|
||||
fn arch() -> ~str { ~"x86" }
|
||||
pub fn arch() -> ~str { ~"x86" }
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
fn arch() -> ~str { ~"x86_64" }
|
||||
pub fn arch() -> ~str { ~"x86_64" }
|
||||
|
||||
#[cfg(target_arch = "arm")]
|
||||
fn arch() -> str { ~"arm" }
|
||||
pub fn arch() -> str { ~"arm" }
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(non_implicitly_copyable_typarams)]
|
||||
mod tests {
|
||||
#[legacy_exports];
|
||||
|
||||
#[test]
|
||||
fn last_os_error() {
|
||||
pub fn last_os_error() {
|
||||
log(debug, last_os_error());
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_args() {
|
||||
let a = real_args();
|
||||
assert a.len() >= 1;
|
||||
}
|
||||
|
||||
fn make_rand_name() -> ~str {
|
||||
let rng: rand::Rng = rand::Rng();
|
||||
let n = ~"TEST" + rng.gen_str(10u);
|
||||
|
|
@ -919,10 +973,10 @@ mod tests {
|
|||
|
||||
let mut e = env();
|
||||
setenv(n, ~"VALUE");
|
||||
assert !vec::contains(e, (copy n, ~"VALUE"));
|
||||
assert !vec::contains(e, &(copy n, ~"VALUE"));
|
||||
|
||||
e = env();
|
||||
assert vec::contains(e, (n, ~"VALUE"));
|
||||
assert vec::contains(e, &(n, ~"VALUE"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -946,7 +1000,7 @@ mod tests {
|
|||
setenv(~"HOME", ~"");
|
||||
assert os::homedir().is_none();
|
||||
|
||||
oldhome.iter(|s| setenv(~"HOME", s));
|
||||
oldhome.iter(|s| setenv(~"HOME", *s));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -973,9 +1027,9 @@ mod tests {
|
|||
setenv(~"USERPROFILE", ~"/home/PaloAlto");
|
||||
assert os::homedir() == Some(Path("/home/MountainView"));
|
||||
|
||||
option::iter(&oldhome, |s| setenv(~"HOME", s));
|
||||
option::iter(&oldhome, |s| setenv(~"HOME", *s));
|
||||
option::iter(&olduserprofile,
|
||||
|s| setenv(~"USERPROFILE", s));
|
||||
|s| setenv(~"USERPROFILE", *s));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -10,19 +10,19 @@ Cross-platform file path handling
|
|||
|
||||
use cmp::Eq;
|
||||
|
||||
struct WindowsPath {
|
||||
pub struct WindowsPath {
|
||||
host: Option<~str>,
|
||||
device: Option<~str>,
|
||||
is_absolute: bool,
|
||||
components: ~[~str],
|
||||
}
|
||||
|
||||
struct PosixPath {
|
||||
pub struct PosixPath {
|
||||
is_absolute: bool,
|
||||
components: ~[~str],
|
||||
}
|
||||
|
||||
trait GenericPath {
|
||||
pub trait GenericPath {
|
||||
|
||||
static pure fn from_str((&str)) -> self;
|
||||
|
||||
|
|
@ -45,18 +45,18 @@ trait GenericPath {
|
|||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
type Path = WindowsPath;
|
||||
pub type Path = WindowsPath;
|
||||
|
||||
#[cfg(windows)]
|
||||
pure fn Path(s: &str) -> Path {
|
||||
pub pure fn Path(s: &str) -> Path {
|
||||
from_str::<WindowsPath>(s)
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
type Path = PosixPath;
|
||||
pub type Path = PosixPath;
|
||||
|
||||
#[cfg(unix)]
|
||||
pure fn Path(s: &str) -> Path {
|
||||
pub pure fn Path(s: &str) -> Path {
|
||||
from_str::<PosixPath>(s)
|
||||
}
|
||||
|
||||
|
|
@ -167,7 +167,7 @@ impl PosixPath : GenericPath {
|
|||
if t.len() == 0 {
|
||||
match self.filestem() {
|
||||
None => copy self,
|
||||
Some(s) => self.with_filename(s)
|
||||
Some(ref s) => self.with_filename(*s)
|
||||
}
|
||||
} else {
|
||||
let t = ~"." + str::from_slice(t);
|
||||
|
|
@ -206,7 +206,7 @@ impl PosixPath : GenericPath {
|
|||
let mut ss = str::split_nonempty(
|
||||
*e,
|
||||
|c| windows::is_sep(c as u8));
|
||||
unsafe { vec::push_all_move(v, move ss); }
|
||||
unsafe { v.push_all_move(move ss); }
|
||||
}
|
||||
PosixPath { components: move v, ..self }
|
||||
}
|
||||
|
|
@ -214,14 +214,14 @@ impl PosixPath : GenericPath {
|
|||
pure fn push(s: &str) -> PosixPath {
|
||||
let mut v = copy self.components;
|
||||
let mut ss = str::split_nonempty(s, |c| windows::is_sep(c as u8));
|
||||
unsafe { vec::push_all_move(v, move ss); }
|
||||
unsafe { v.push_all_move(move ss); }
|
||||
PosixPath { components: move v, ..self }
|
||||
}
|
||||
|
||||
pure fn pop() -> PosixPath {
|
||||
let mut cs = copy self.components;
|
||||
if cs.len() != 0 {
|
||||
unsafe { vec::pop(cs); }
|
||||
unsafe { cs.pop(); }
|
||||
}
|
||||
return PosixPath { components: move cs, ..self }
|
||||
}
|
||||
|
|
@ -239,11 +239,11 @@ impl WindowsPath : ToStr {
|
|||
fn to_str() -> ~str {
|
||||
let mut s = ~"";
|
||||
match self.host {
|
||||
Some(h) => { s += "\\\\"; s += h; }
|
||||
Some(ref h) => { s += "\\\\"; s += *h; }
|
||||
None => { }
|
||||
}
|
||||
match self.device {
|
||||
Some(d) => { s += d; s += ":"; }
|
||||
Some(ref d) => { s += *d; s += ":"; }
|
||||
None => { }
|
||||
}
|
||||
if self.is_absolute {
|
||||
|
|
@ -358,7 +358,7 @@ impl WindowsPath : GenericPath {
|
|||
if t.len() == 0 {
|
||||
match self.filestem() {
|
||||
None => copy self,
|
||||
Some(s) => self.with_filename(s)
|
||||
Some(ref s) => self.with_filename(*s)
|
||||
}
|
||||
} else {
|
||||
let t = ~"." + str::from_slice(t);
|
||||
|
|
@ -400,7 +400,7 @@ impl WindowsPath : GenericPath {
|
|||
let mut ss = str::split_nonempty(
|
||||
*e,
|
||||
|c| windows::is_sep(c as u8));
|
||||
unsafe { vec::push_all_move(v, move ss); }
|
||||
unsafe { v.push_all_move(move ss); }
|
||||
}
|
||||
return WindowsPath { components: move v, ..self }
|
||||
}
|
||||
|
|
@ -408,14 +408,14 @@ impl WindowsPath : GenericPath {
|
|||
pure fn push(s: &str) -> WindowsPath {
|
||||
let mut v = copy self.components;
|
||||
let mut ss = str::split_nonempty(s, |c| windows::is_sep(c as u8));
|
||||
unsafe { vec::push_all_move(v, move ss); }
|
||||
unsafe { v.push_all_move(move ss); }
|
||||
return WindowsPath { components: move v, ..self }
|
||||
}
|
||||
|
||||
pure fn pop() -> WindowsPath {
|
||||
let mut cs = copy self.components;
|
||||
if cs.len() != 0 {
|
||||
unsafe { vec::pop(cs); }
|
||||
unsafe { cs.pop(); }
|
||||
}
|
||||
return WindowsPath { components: move cs, ..self }
|
||||
}
|
||||
|
|
@ -429,7 +429,7 @@ impl WindowsPath : GenericPath {
|
|||
}
|
||||
|
||||
|
||||
pure fn normalize(components: &[~str]) -> ~[~str] {
|
||||
pub pure fn normalize(components: &[~str]) -> ~[~str] {
|
||||
let mut cs = ~[];
|
||||
unsafe {
|
||||
for components.each |c| {
|
||||
|
|
@ -437,10 +437,10 @@ pure fn normalize(components: &[~str]) -> ~[~str] {
|
|||
if *c == ~"." && components.len() > 1 { loop; }
|
||||
if *c == ~"" { loop; }
|
||||
if *c == ~".." && cs.len() != 0 {
|
||||
vec::pop(cs);
|
||||
cs.pop();
|
||||
loop;
|
||||
}
|
||||
vec::push(cs, copy *c);
|
||||
cs.push(copy *c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -462,7 +462,6 @@ fn test_double_slash_collapsing()
|
|||
}
|
||||
|
||||
mod posix {
|
||||
#[legacy_exports];
|
||||
|
||||
#[cfg(test)]
|
||||
fn mk(s: &str) -> PosixPath { from_str::<PosixPath>(s) }
|
||||
|
|
@ -553,14 +552,13 @@ mod posix {
|
|||
|
||||
// Various windows helpers, and tests for the impl.
|
||||
mod windows {
|
||||
#[legacy_exports];
|
||||
|
||||
#[inline(always)]
|
||||
pure fn is_sep(u: u8) -> bool {
|
||||
pub pure fn is_sep(u: u8) -> bool {
|
||||
u == '/' as u8 || u == '\\' as u8
|
||||
}
|
||||
|
||||
pure fn extract_unc_prefix(s: &str) -> Option<(~str,~str)> {
|
||||
pub pure fn extract_unc_prefix(s: &str) -> Option<(~str,~str)> {
|
||||
if (s.len() > 1 &&
|
||||
s[0] == '\\' as u8 &&
|
||||
s[1] == '\\' as u8) {
|
||||
|
|
@ -577,7 +575,7 @@ mod windows {
|
|||
None
|
||||
}
|
||||
|
||||
pure fn extract_drive_prefix(s: &str) -> Option<(~str,~str)> {
|
||||
pub pure fn extract_drive_prefix(s: &str) -> Option<(~str,~str)> {
|
||||
unsafe {
|
||||
if (s.len() > 1 &&
|
||||
libc::isalpha(s[0] as libc::c_int) != 0 &&
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ bounded and unbounded protocols allows for less code duplication.
|
|||
*/
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
// tjc: re-forbid deprecated modes after snapshot
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use cmp::Eq;
|
||||
|
|
@ -81,31 +81,11 @@ use cast::{forget, reinterpret_cast, transmute};
|
|||
use either::{Either, Left, Right};
|
||||
use option::unwrap;
|
||||
|
||||
// Things used by code generated by the pipe compiler.
|
||||
export entangle, get_buffer, drop_buffer;
|
||||
export SendPacketBuffered, RecvPacketBuffered;
|
||||
export Packet, packet, mk_packet, entangle_buffer, HasBuffer, BufferHeader;
|
||||
|
||||
// export these so we can find them in the buffer_resource
|
||||
// destructor. This is probably a symptom of #3005.
|
||||
export atomic_add_acq, atomic_sub_rel;
|
||||
|
||||
// User-level things
|
||||
export SendPacket, RecvPacket, send, recv, try_recv, peek;
|
||||
export select, select2, selecti, select2i, selectable;
|
||||
export spawn_service, spawn_service_recv;
|
||||
export stream, Port, Chan, SharedChan, PortSet, Channel;
|
||||
export oneshot, ChanOne, PortOne;
|
||||
export recv_one, try_recv_one, send_one, try_send_one;
|
||||
|
||||
// Functions used by the protocol compiler
|
||||
export rt;
|
||||
|
||||
#[doc(hidden)]
|
||||
const SPIN_COUNT: uint = 0;
|
||||
|
||||
macro_rules! move_it (
|
||||
{ $x:expr } => { unsafe { let y <- *ptr::addr_of($x); move y } }
|
||||
{ $x:expr } => { unsafe { let y <- *ptr::addr_of(&($x)); move y } }
|
||||
)
|
||||
|
||||
#[doc(hidden)]
|
||||
|
|
@ -123,7 +103,7 @@ impl State : Eq {
|
|||
pure fn ne(other: &State) -> bool { !self.eq(other) }
|
||||
}
|
||||
|
||||
struct BufferHeader {
|
||||
pub struct BufferHeader {
|
||||
// Tracks whether this buffer needs to be freed. We can probably
|
||||
// get away with restricting it to 0 or 1, if we're careful.
|
||||
mut ref_count: int,
|
||||
|
|
@ -132,7 +112,7 @@ struct BufferHeader {
|
|||
// thing along.
|
||||
}
|
||||
|
||||
fn BufferHeader() -> BufferHeader{
|
||||
pub fn BufferHeader() -> BufferHeader{
|
||||
BufferHeader {
|
||||
ref_count: 0
|
||||
}
|
||||
|
|
@ -195,13 +175,13 @@ impl PacketHeader {
|
|||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
type Packet<T: Send> = {
|
||||
pub type Packet<T: Send> = {
|
||||
header: PacketHeader,
|
||||
mut payload: Option<T>,
|
||||
};
|
||||
|
||||
#[doc(hidden)]
|
||||
trait HasBuffer {
|
||||
pub trait HasBuffer {
|
||||
// XXX This should not have a trailing underscore
|
||||
fn set_buffer_(b: *libc::c_void);
|
||||
}
|
||||
|
|
@ -213,7 +193,7 @@ impl<T: Send> Packet<T>: HasBuffer {
|
|||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
fn mk_packet<T: Send>() -> Packet<T> {
|
||||
pub fn mk_packet<T: Send>() -> Packet<T> {
|
||||
{
|
||||
header: PacketHeader(),
|
||||
mut payload: None
|
||||
|
|
@ -237,17 +217,17 @@ fn unibuffer<T: Send>() -> ~Buffer<Packet<T>> {
|
|||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
fn packet<T: Send>() -> *Packet<T> {
|
||||
pub fn packet<T: Send>() -> *Packet<T> {
|
||||
let b = unibuffer();
|
||||
let p = ptr::addr_of(b.data);
|
||||
let p = ptr::addr_of(&(b.data));
|
||||
// We'll take over memory management from here.
|
||||
unsafe { forget(move b) }
|
||||
p
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
fn entangle_buffer<T: Send, Tstart: Send>(
|
||||
+buffer: ~Buffer<T>,
|
||||
pub fn entangle_buffer<T: Send, Tstart: Send>(
|
||||
buffer: ~Buffer<T>,
|
||||
init: fn(*libc::c_void, x: &T) -> *Packet<Tstart>)
|
||||
-> (SendPacketBuffered<Tstart, T>, RecvPacketBuffered<Tstart, T>)
|
||||
{
|
||||
|
|
@ -256,52 +236,36 @@ fn entangle_buffer<T: Send, Tstart: Send>(
|
|||
(SendPacketBuffered(p), RecvPacketBuffered(p))
|
||||
}
|
||||
|
||||
#[cfg(stage0)]
|
||||
#[abi = "rust-intrinsic"]
|
||||
#[doc(hidden)]
|
||||
extern mod rusti {
|
||||
#[legacy_exports];
|
||||
fn atomic_xchg(dst: &mut int, ++src: int) -> int;
|
||||
fn atomic_xchg_acq(dst: &mut int, ++src: int) -> int;
|
||||
fn atomic_xchg_rel(dst: &mut int, ++src: int) -> int;
|
||||
fn atomic_xchg(dst: &mut int, src: int) -> int;
|
||||
fn atomic_xchg_acq(dst: &mut int, src: int) -> int;
|
||||
fn atomic_xchg_rel(dst: &mut int, src: int) -> int;
|
||||
|
||||
fn atomic_xadd_acq(dst: &mut int, ++src: int) -> int;
|
||||
fn atomic_xsub_rel(dst: &mut int, ++src: int) -> int;
|
||||
}
|
||||
|
||||
#[cfg(stage1)]
|
||||
#[cfg(stage2)]
|
||||
#[abi = "rust-intrinsic"]
|
||||
#[doc(hidden)]
|
||||
extern mod rusti {
|
||||
#[legacy_exports];
|
||||
fn atomic_xchg(dst: &mut int, +src: int) -> int;
|
||||
fn atomic_xchg_acq(dst: &mut int, +src: int) -> int;
|
||||
fn atomic_xchg_rel(dst: &mut int, +src: int) -> int;
|
||||
|
||||
fn atomic_xadd_acq(dst: &mut int, +src: int) -> int;
|
||||
fn atomic_xsub_rel(dst: &mut int, +src: int) -> int;
|
||||
fn atomic_xadd_acq(dst: &mut int, src: int) -> int;
|
||||
fn atomic_xsub_rel(dst: &mut int, src: int) -> int;
|
||||
}
|
||||
|
||||
// If I call the rusti versions directly from a polymorphic function,
|
||||
// I get link errors. This is a bug that needs investigated more.
|
||||
#[doc(hidden)]
|
||||
fn atomic_xchng_rel(dst: &mut int, src: int) -> int {
|
||||
pub fn atomic_xchng_rel(dst: &mut int, src: int) -> int {
|
||||
rusti::atomic_xchg_rel(dst, src)
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
fn atomic_add_acq(dst: &mut int, src: int) -> int {
|
||||
pub fn atomic_add_acq(dst: &mut int, src: int) -> int {
|
||||
rusti::atomic_xadd_acq(dst, src)
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
fn atomic_sub_rel(dst: &mut int, src: int) -> int {
|
||||
pub fn atomic_sub_rel(dst: &mut int, src: int) -> int {
|
||||
rusti::atomic_xsub_rel(dst, src)
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
fn swap_task(+dst: &mut *rust_task, src: *rust_task) -> *rust_task {
|
||||
pub fn swap_task(dst: &mut *rust_task, src: *rust_task) -> *rust_task {
|
||||
// It might be worth making both acquire and release versions of
|
||||
// this.
|
||||
unsafe {
|
||||
|
|
@ -315,7 +279,6 @@ type rust_task = libc::c_void;
|
|||
|
||||
#[doc(hidden)]
|
||||
extern mod rustrt {
|
||||
#[legacy_exports];
|
||||
#[rust_stack]
|
||||
fn rust_get_task() -> *rust_task;
|
||||
#[rust_stack]
|
||||
|
|
@ -341,21 +304,21 @@ fn wait_event(this: *rust_task) -> *libc::c_void {
|
|||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
fn swap_state_acq(+dst: &mut State, src: State) -> State {
|
||||
fn swap_state_acq(dst: &mut State, src: State) -> State {
|
||||
unsafe {
|
||||
transmute(rusti::atomic_xchg_acq(transmute(move dst), src as int))
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
fn swap_state_rel(+dst: &mut State, src: State) -> State {
|
||||
fn swap_state_rel(dst: &mut State, src: State) -> State {
|
||||
unsafe {
|
||||
transmute(rusti::atomic_xchg_rel(transmute(move dst), src as int))
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
unsafe fn get_buffer<T: Send>(p: *PacketHeader) -> ~Buffer<T> {
|
||||
pub unsafe fn get_buffer<T: Send>(p: *PacketHeader) -> ~Buffer<T> {
|
||||
transmute((*p).buf_header())
|
||||
}
|
||||
|
||||
|
|
@ -380,7 +343,7 @@ struct BufferResource<T: Send> {
|
|||
}
|
||||
}
|
||||
|
||||
fn BufferResource<T: Send>(+b: ~Buffer<T>) -> BufferResource<T> {
|
||||
fn BufferResource<T: Send>(b: ~Buffer<T>) -> BufferResource<T> {
|
||||
//let p = ptr::addr_of(*b);
|
||||
//error!("take %?", p);
|
||||
atomic_add_acq(&mut b.header.ref_count, 1);
|
||||
|
|
@ -391,12 +354,12 @@ fn BufferResource<T: Send>(+b: ~Buffer<T>) -> BufferResource<T> {
|
|||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
fn send<T: Send, Tbuffer: Send>(+p: SendPacketBuffered<T, Tbuffer>,
|
||||
+payload: T) -> bool {
|
||||
pub fn send<T: Send, Tbuffer: Send>(p: SendPacketBuffered<T, Tbuffer>,
|
||||
payload: T) -> bool {
|
||||
let header = p.header();
|
||||
let p_ = p.unwrap();
|
||||
let p = unsafe { &*p_ };
|
||||
assert ptr::addr_of(p.header) == header;
|
||||
assert ptr::addr_of(&(p.header)) == header;
|
||||
assert p.payload.is_none();
|
||||
p.payload <- Some(move payload);
|
||||
let old_state = swap_state_rel(&mut p.header.state, Full);
|
||||
|
|
@ -414,7 +377,7 @@ fn send<T: Send, Tbuffer: Send>(+p: SendPacketBuffered<T, Tbuffer>,
|
|||
let old_task = swap_task(&mut p.header.blocked_task, ptr::null());
|
||||
if !old_task.is_null() {
|
||||
rustrt::task_signal_event(
|
||||
old_task, ptr::addr_of(p.header) as *libc::c_void);
|
||||
old_task, ptr::addr_of(&(p.header)) as *libc::c_void);
|
||||
rustrt::rust_task_deref(old_task);
|
||||
}
|
||||
|
||||
|
|
@ -435,7 +398,7 @@ fn send<T: Send, Tbuffer: Send>(+p: SendPacketBuffered<T, Tbuffer>,
|
|||
Fails if the sender closes the connection.
|
||||
|
||||
*/
|
||||
fn recv<T: Send, Tbuffer: Send>(+p: RecvPacketBuffered<T, Tbuffer>) -> T {
|
||||
pub fn recv<T: Send, Tbuffer: Send>(p: RecvPacketBuffered<T, Tbuffer>) -> T {
|
||||
option::unwrap_expect(try_recv(move p), "connection closed")
|
||||
}
|
||||
|
||||
|
|
@ -445,7 +408,7 @@ Returns `none` if the sender has closed the connection without sending
|
|||
a message, or `Some(T)` if a message was received.
|
||||
|
||||
*/
|
||||
fn try_recv<T: Send, Tbuffer: Send>(+p: RecvPacketBuffered<T, Tbuffer>)
|
||||
pub fn try_recv<T: Send, Tbuffer: Send>(p: RecvPacketBuffered<T, Tbuffer>)
|
||||
-> Option<T>
|
||||
{
|
||||
let p_ = p.unwrap();
|
||||
|
|
@ -539,7 +502,7 @@ fn try_recv<T: Send, Tbuffer: Send>(+p: RecvPacketBuffered<T, Tbuffer>)
|
|||
}
|
||||
|
||||
/// Returns true if messages are available.
|
||||
pure fn peek<T: Send, Tb: Send>(p: &RecvPacketBuffered<T, Tb>) -> bool {
|
||||
pub pure fn peek<T: Send, Tb: Send>(p: &RecvPacketBuffered<T, Tb>) -> bool {
|
||||
match unsafe {(*p.header()).state} {
|
||||
Empty => false,
|
||||
Blocked => fail ~"peeking on blocked packet",
|
||||
|
|
@ -566,7 +529,7 @@ fn sender_terminate<T: Send>(p: *Packet<T>) {
|
|||
if !old_task.is_null() {
|
||||
rustrt::task_signal_event(
|
||||
old_task,
|
||||
ptr::addr_of(p.header) as *libc::c_void);
|
||||
ptr::addr_of(&(p.header)) as *libc::c_void);
|
||||
rustrt::rust_task_deref(old_task);
|
||||
}
|
||||
// The receiver will eventually clean up.
|
||||
|
|
@ -691,9 +654,9 @@ Sometimes messages will be available on both endpoints at once. In
|
|||
this case, `select2` may return either `left` or `right`.
|
||||
|
||||
*/
|
||||
fn select2<A: Send, Ab: Send, B: Send, Bb: Send>(
|
||||
+a: RecvPacketBuffered<A, Ab>,
|
||||
+b: RecvPacketBuffered<B, Bb>)
|
||||
pub fn select2<A: Send, Ab: Send, B: Send, Bb: Send>(
|
||||
a: RecvPacketBuffered<A, Ab>,
|
||||
b: RecvPacketBuffered<B, Bb>)
|
||||
-> Either<(Option<A>, RecvPacketBuffered<B, Bb>),
|
||||
(RecvPacketBuffered<A, Ab>, Option<B>)>
|
||||
{
|
||||
|
|
@ -716,12 +679,13 @@ impl *PacketHeader: Selectable {
|
|||
}
|
||||
|
||||
/// Returns the index of an endpoint that is ready to receive.
|
||||
fn selecti<T: Selectable>(endpoints: &[T]) -> uint {
|
||||
pub fn selecti<T: Selectable>(endpoints: &[T]) -> uint {
|
||||
wait_many(endpoints)
|
||||
}
|
||||
|
||||
/// Returns 0 or 1 depending on which endpoint is ready to receive
|
||||
fn select2i<A: Selectable, B: Selectable>(a: &A, b: &B) -> Either<(), ()> {
|
||||
pub fn select2i<A: Selectable, B: Selectable>(a: &A, b: &B) ->
|
||||
Either<(), ()> {
|
||||
match wait_many([a.header(), b.header()]/_) {
|
||||
0 => Left(()),
|
||||
1 => Right(()),
|
||||
|
|
@ -733,12 +697,12 @@ fn select2i<A: Selectable, B: Selectable>(a: &A, b: &B) -> Either<(), ()> {
|
|||
list of the remaining endpoints.
|
||||
|
||||
*/
|
||||
fn select<T: Send, Tb: Send>(+endpoints: ~[RecvPacketBuffered<T, Tb>])
|
||||
pub fn select<T: Send, Tb: Send>(endpoints: ~[RecvPacketBuffered<T, Tb>])
|
||||
-> (uint, Option<T>, ~[RecvPacketBuffered<T, Tb>])
|
||||
{
|
||||
let ready = wait_many(endpoints.map(|p| p.header()));
|
||||
let mut remaining <- endpoints;
|
||||
let port = vec::swap_remove(remaining, ready);
|
||||
let port = remaining.swap_remove(ready);
|
||||
let result = try_recv(move port);
|
||||
(ready, move result, move remaining)
|
||||
}
|
||||
|
|
@ -747,14 +711,14 @@ fn select<T: Send, Tb: Send>(+endpoints: ~[RecvPacketBuffered<T, Tb>])
|
|||
message.
|
||||
|
||||
*/
|
||||
type SendPacket<T: Send> = SendPacketBuffered<T, Packet<T>>;
|
||||
pub type SendPacket<T: Send> = SendPacketBuffered<T, Packet<T>>;
|
||||
|
||||
#[doc(hidden)]
|
||||
fn SendPacket<T: Send>(p: *Packet<T>) -> SendPacket<T> {
|
||||
pub fn SendPacket<T: Send>(p: *Packet<T>) -> SendPacket<T> {
|
||||
SendPacketBuffered(p)
|
||||
}
|
||||
|
||||
struct SendPacketBuffered<T: Send, Tbuffer: Send> {
|
||||
pub struct SendPacketBuffered<T: Send, Tbuffer: Send> {
|
||||
mut p: Option<*Packet<T>>,
|
||||
mut buffer: Option<BufferResource<Tbuffer>>,
|
||||
drop {
|
||||
|
|
@ -773,14 +737,14 @@ struct SendPacketBuffered<T: Send, Tbuffer: Send> {
|
|||
}
|
||||
}
|
||||
|
||||
fn SendPacketBuffered<T: Send, Tbuffer: Send>(p: *Packet<T>)
|
||||
pub fn SendPacketBuffered<T: Send, Tbuffer: Send>(p: *Packet<T>)
|
||||
-> SendPacketBuffered<T, Tbuffer> {
|
||||
//debug!("take send %?", p);
|
||||
SendPacketBuffered {
|
||||
p: Some(p),
|
||||
buffer: unsafe {
|
||||
Some(BufferResource(
|
||||
get_buffer(ptr::addr_of((*p).header))))
|
||||
get_buffer(ptr::addr_of(&((*p).header)))))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -796,7 +760,7 @@ impl<T: Send, Tbuffer: Send> SendPacketBuffered<T, Tbuffer> {
|
|||
match self.p {
|
||||
Some(packet) => unsafe {
|
||||
let packet = &*packet;
|
||||
let header = ptr::addr_of(packet.header);
|
||||
let header = ptr::addr_of(&(packet.header));
|
||||
//forget(packet);
|
||||
header
|
||||
},
|
||||
|
|
@ -814,14 +778,14 @@ impl<T: Send, Tbuffer: Send> SendPacketBuffered<T, Tbuffer> {
|
|||
|
||||
/// Represents the receive end of a pipe. It can receive exactly one
|
||||
/// message.
|
||||
type RecvPacket<T: Send> = RecvPacketBuffered<T, Packet<T>>;
|
||||
pub type RecvPacket<T: Send> = RecvPacketBuffered<T, Packet<T>>;
|
||||
|
||||
#[doc(hidden)]
|
||||
fn RecvPacket<T: Send>(p: *Packet<T>) -> RecvPacket<T> {
|
||||
pub fn RecvPacket<T: Send>(p: *Packet<T>) -> RecvPacket<T> {
|
||||
RecvPacketBuffered(p)
|
||||
}
|
||||
|
||||
struct RecvPacketBuffered<T: Send, Tbuffer: Send> {
|
||||
pub struct RecvPacketBuffered<T: Send, Tbuffer: Send> {
|
||||
mut p: Option<*Packet<T>>,
|
||||
mut buffer: Option<BufferResource<Tbuffer>>,
|
||||
drop {
|
||||
|
|
@ -851,7 +815,7 @@ impl<T: Send, Tbuffer: Send> RecvPacketBuffered<T, Tbuffer> : Selectable {
|
|||
match self.p {
|
||||
Some(packet) => unsafe {
|
||||
let packet = &*packet;
|
||||
let header = ptr::addr_of(packet.header);
|
||||
let header = ptr::addr_of(&(packet.header));
|
||||
//forget(packet);
|
||||
header
|
||||
},
|
||||
|
|
@ -867,20 +831,20 @@ impl<T: Send, Tbuffer: Send> RecvPacketBuffered<T, Tbuffer> : Selectable {
|
|||
}
|
||||
}
|
||||
|
||||
fn RecvPacketBuffered<T: Send, Tbuffer: Send>(p: *Packet<T>)
|
||||
pub fn RecvPacketBuffered<T: Send, Tbuffer: Send>(p: *Packet<T>)
|
||||
-> RecvPacketBuffered<T, Tbuffer> {
|
||||
//debug!("take recv %?", p);
|
||||
RecvPacketBuffered {
|
||||
p: Some(p),
|
||||
buffer: unsafe {
|
||||
Some(BufferResource(
|
||||
get_buffer(ptr::addr_of((*p).header))))
|
||||
get_buffer(ptr::addr_of(&((*p).header)))))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
fn entangle<T: Send>() -> (SendPacket<T>, RecvPacket<T>) {
|
||||
pub fn entangle<T: Send>() -> (SendPacket<T>, RecvPacket<T>) {
|
||||
let p = packet();
|
||||
(SendPacket(p), RecvPacket(p))
|
||||
}
|
||||
|
|
@ -892,10 +856,10 @@ endpoint. The send endpoint is returned to the caller and the receive
|
|||
endpoint is passed to the new task.
|
||||
|
||||
*/
|
||||
fn spawn_service<T: Send, Tb: Send>(
|
||||
pub fn spawn_service<T: Send, Tb: Send>(
|
||||
init: extern fn() -> (SendPacketBuffered<T, Tb>,
|
||||
RecvPacketBuffered<T, Tb>),
|
||||
+service: fn~(+v: RecvPacketBuffered<T, Tb>))
|
||||
+service: fn~(v: RecvPacketBuffered<T, Tb>))
|
||||
-> SendPacketBuffered<T, Tb>
|
||||
{
|
||||
let (client, server) = init();
|
||||
|
|
@ -916,10 +880,10 @@ fn spawn_service<T: Send, Tb: Send>(
|
|||
receive state.
|
||||
|
||||
*/
|
||||
fn spawn_service_recv<T: Send, Tb: Send>(
|
||||
pub fn spawn_service_recv<T: Send, Tb: Send>(
|
||||
init: extern fn() -> (RecvPacketBuffered<T, Tb>,
|
||||
SendPacketBuffered<T, Tb>),
|
||||
+service: fn~(+v: SendPacketBuffered<T, Tb>))
|
||||
+service: fn~(v: SendPacketBuffered<T, Tb>))
|
||||
-> RecvPacketBuffered<T, Tb>
|
||||
{
|
||||
let (client, server) = init();
|
||||
|
|
@ -945,19 +909,19 @@ proto! streamp (
|
|||
)
|
||||
|
||||
/// A trait for things that can send multiple messages.
|
||||
trait Channel<T: Send> {
|
||||
pub trait Channel<T: Send> {
|
||||
// It'd be nice to call this send, but it'd conflict with the
|
||||
// built in send kind.
|
||||
|
||||
/// Sends a message.
|
||||
fn send(+x: T);
|
||||
fn send(x: T);
|
||||
|
||||
/// Sends a message, or report if the receiver has closed the connection.
|
||||
fn try_send(+x: T) -> bool;
|
||||
fn try_send(x: T) -> bool;
|
||||
}
|
||||
|
||||
/// A trait for things that can receive multiple messages.
|
||||
trait Recv<T: Send> {
|
||||
pub trait Recv<T: Send> {
|
||||
/// Receives a message, or fails if the connection closes.
|
||||
fn recv() -> T;
|
||||
|
||||
|
|
@ -978,7 +942,7 @@ trait Recv<T: Send> {
|
|||
type Chan_<T:Send> = { mut endp: Option<streamp::client::Open<T>> };
|
||||
|
||||
/// An endpoint that can send many messages.
|
||||
enum Chan<T:Send> {
|
||||
pub enum Chan<T:Send> {
|
||||
Chan_(Chan_<T>)
|
||||
}
|
||||
|
||||
|
|
@ -986,7 +950,7 @@ enum Chan<T:Send> {
|
|||
type Port_<T:Send> = { mut endp: Option<streamp::server::Open<T>> };
|
||||
|
||||
/// An endpoint that can receive many messages.
|
||||
enum Port<T:Send> {
|
||||
pub enum Port<T:Send> {
|
||||
Port_(Port_<T>)
|
||||
}
|
||||
|
||||
|
|
@ -995,21 +959,21 @@ enum Port<T:Send> {
|
|||
These allow sending or receiving an unlimited number of messages.
|
||||
|
||||
*/
|
||||
fn stream<T:Send>() -> (Chan<T>, Port<T>) {
|
||||
pub fn stream<T:Send>() -> (Chan<T>, Port<T>) {
|
||||
let (c, s) = streamp::init();
|
||||
|
||||
(Chan_({ mut endp: Some(move c) }), Port_({ mut endp: Some(move s) }))
|
||||
}
|
||||
|
||||
impl<T: Send> Chan<T>: Channel<T> {
|
||||
fn send(+x: T) {
|
||||
fn send(x: T) {
|
||||
let mut endp = None;
|
||||
endp <-> self.endp;
|
||||
self.endp = Some(
|
||||
streamp::client::data(unwrap(move endp), move x))
|
||||
}
|
||||
|
||||
fn try_send(+x: T) -> bool {
|
||||
fn try_send(x: T) -> bool {
|
||||
let mut endp = None;
|
||||
endp <-> self.endp;
|
||||
match move streamp::client::try_data(unwrap(move endp), move x) {
|
||||
|
|
@ -1047,7 +1011,7 @@ impl<T: Send> Port<T>: Recv<T> {
|
|||
let mut endp = None;
|
||||
endp <-> self.endp;
|
||||
let peek = match endp {
|
||||
Some(endp) => pipes::peek(&endp),
|
||||
Some(ref endp) => pipes::peek(endp),
|
||||
None => fail ~"peeking empty stream"
|
||||
};
|
||||
self.endp <-> endp;
|
||||
|
|
@ -1058,18 +1022,18 @@ impl<T: Send> Port<T>: Recv<T> {
|
|||
impl<T: Send> Port<T>: Selectable {
|
||||
pure fn header() -> *PacketHeader unsafe {
|
||||
match self.endp {
|
||||
Some(endp) => endp.header(),
|
||||
Some(ref endp) => endp.header(),
|
||||
None => fail ~"peeking empty stream"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Treat many ports as one.
|
||||
struct PortSet<T: Send> {
|
||||
pub struct PortSet<T: Send> {
|
||||
mut ports: ~[pipes::Port<T>],
|
||||
}
|
||||
|
||||
fn PortSet<T: Send>() -> PortSet<T>{
|
||||
pub fn PortSet<T: Send>() -> PortSet<T>{
|
||||
PortSet {
|
||||
ports: ~[]
|
||||
}
|
||||
|
|
@ -1077,8 +1041,8 @@ fn PortSet<T: Send>() -> PortSet<T>{
|
|||
|
||||
impl<T: Send> PortSet<T> : Recv<T> {
|
||||
|
||||
fn add(+port: pipes::Port<T>) {
|
||||
vec::push(self.ports, move port)
|
||||
fn add(port: pipes::Port<T>) {
|
||||
self.ports.push(move port)
|
||||
}
|
||||
|
||||
fn chan() -> Chan<T> {
|
||||
|
|
@ -1101,7 +1065,7 @@ impl<T: Send> PortSet<T> : Recv<T> {
|
|||
}
|
||||
None => {
|
||||
// Remove this port.
|
||||
let _ = vec::swap_remove(ports, i);
|
||||
let _ = ports.swap_remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1124,10 +1088,10 @@ impl<T: Send> PortSet<T> : Recv<T> {
|
|||
}
|
||||
|
||||
/// A channel that can be shared between many senders.
|
||||
type SharedChan<T: Send> = private::Exclusive<Chan<T>>;
|
||||
pub type SharedChan<T: Send> = private::Exclusive<Chan<T>>;
|
||||
|
||||
impl<T: Send> SharedChan<T>: Channel<T> {
|
||||
fn send(+x: T) {
|
||||
fn send(x: T) {
|
||||
let mut xx = Some(move x);
|
||||
do self.with_imm |chan| {
|
||||
let mut x = None;
|
||||
|
|
@ -1136,7 +1100,7 @@ impl<T: Send> SharedChan<T>: Channel<T> {
|
|||
}
|
||||
}
|
||||
|
||||
fn try_send(+x: T) -> bool {
|
||||
fn try_send(x: T) -> bool {
|
||||
let mut xx = Some(move x);
|
||||
do self.with_imm |chan| {
|
||||
let mut x = None;
|
||||
|
|
@ -1147,12 +1111,12 @@ impl<T: Send> SharedChan<T>: Channel<T> {
|
|||
}
|
||||
|
||||
/// Converts a `chan` into a `shared_chan`.
|
||||
fn SharedChan<T:Send>(+c: Chan<T>) -> SharedChan<T> {
|
||||
pub fn SharedChan<T:Send>(c: Chan<T>) -> SharedChan<T> {
|
||||
private::exclusive(move c)
|
||||
}
|
||||
|
||||
/// Receive a message from one of two endpoints.
|
||||
trait Select2<T: Send, U: Send> {
|
||||
pub trait Select2<T: Send, U: Send> {
|
||||
/// Receive a message or return `none` if a connection closes.
|
||||
fn try_select() -> Either<Option<T>, Option<U>>;
|
||||
/// Receive a message or fail if a connection closes.
|
||||
|
|
@ -1164,7 +1128,7 @@ impl<T: Send, U: Send, Left: Selectable Recv<T>, Right: Selectable Recv<U>>
|
|||
|
||||
fn select() -> Either<T, U> {
|
||||
match self {
|
||||
(lp, rp) => match select2i(&lp, &rp) {
|
||||
(ref lp, ref rp) => match select2i(lp, rp) {
|
||||
Left(()) => Left (lp.recv()),
|
||||
Right(()) => Right(rp.recv())
|
||||
}
|
||||
|
|
@ -1173,7 +1137,7 @@ impl<T: Send, U: Send, Left: Selectable Recv<T>, Right: Selectable Recv<U>>
|
|||
|
||||
fn try_select() -> Either<Option<T>, Option<U>> {
|
||||
match self {
|
||||
(lp, rp) => match select2i(&lp, &rp) {
|
||||
(ref lp, ref rp) => match select2i(lp, rp) {
|
||||
Left(()) => Left (lp.try_recv()),
|
||||
Right(()) => Right(rp.try_recv())
|
||||
}
|
||||
|
|
@ -1188,12 +1152,12 @@ proto! oneshot (
|
|||
)
|
||||
|
||||
/// The send end of a oneshot pipe.
|
||||
type ChanOne<T: Send> = oneshot::client::Oneshot<T>;
|
||||
pub type ChanOne<T: Send> = oneshot::client::Oneshot<T>;
|
||||
/// The receive end of a oneshot pipe.
|
||||
type PortOne<T: Send> = oneshot::server::Oneshot<T>;
|
||||
pub type PortOne<T: Send> = oneshot::server::Oneshot<T>;
|
||||
|
||||
/// Initialiase a (send-endpoint, recv-endpoint) oneshot pipe pair.
|
||||
fn oneshot<T: Send>() -> (ChanOne<T>, PortOne<T>) {
|
||||
pub fn oneshot<T: Send>() -> (ChanOne<T>, PortOne<T>) {
|
||||
oneshot::init()
|
||||
}
|
||||
|
||||
|
|
@ -1201,13 +1165,13 @@ fn oneshot<T: Send>() -> (ChanOne<T>, PortOne<T>) {
|
|||
* Receive a message from a oneshot pipe, failing if the connection was
|
||||
* closed.
|
||||
*/
|
||||
fn recv_one<T: Send>(+port: PortOne<T>) -> T {
|
||||
pub fn recv_one<T: Send>(port: PortOne<T>) -> T {
|
||||
let oneshot::send(message) = recv(move port);
|
||||
move message
|
||||
}
|
||||
|
||||
/// Receive a message from a oneshot pipe unless the connection was closed.
|
||||
fn try_recv_one<T: Send> (+port: PortOne<T>) -> Option<T> {
|
||||
pub fn try_recv_one<T: Send> (port: PortOne<T>) -> Option<T> {
|
||||
let message = try_recv(move port);
|
||||
|
||||
if message.is_none() { None }
|
||||
|
|
@ -1218,7 +1182,7 @@ fn try_recv_one<T: Send> (+port: PortOne<T>) -> Option<T> {
|
|||
}
|
||||
|
||||
/// Send a message on a oneshot pipe, failing if the connection was closed.
|
||||
fn send_one<T: Send>(+chan: ChanOne<T>, +data: T) {
|
||||
pub fn send_one<T: Send>(chan: ChanOne<T>, data: T) {
|
||||
oneshot::client::send(move chan, move data);
|
||||
}
|
||||
|
||||
|
|
@ -1226,24 +1190,22 @@ fn send_one<T: Send>(+chan: ChanOne<T>, +data: T) {
|
|||
* Send a message on a oneshot pipe, or return false if the connection was
|
||||
* closed.
|
||||
*/
|
||||
fn try_send_one<T: Send>(+chan: ChanOne<T>, +data: T)
|
||||
pub fn try_send_one<T: Send>(chan: ChanOne<T>, data: T)
|
||||
-> bool {
|
||||
oneshot::client::try_send(move chan, move data).is_some()
|
||||
}
|
||||
|
||||
mod rt {
|
||||
#[legacy_exports];
|
||||
pub mod rt {
|
||||
// These are used to hide the option constructors from the
|
||||
// compiler because their names are changing
|
||||
fn make_some<T>(+val: T) -> Option<T> { Some(move val) }
|
||||
fn make_none<T>() -> Option<T> { None }
|
||||
pub fn make_some<T>(val: T) -> Option<T> { Some(move val) }
|
||||
pub fn make_none<T>() -> Option<T> { None }
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
#[legacy_exports];
|
||||
pub mod test {
|
||||
#[test]
|
||||
fn test_select2() {
|
||||
pub fn test_select2() {
|
||||
let (c1, p1) = pipes::stream();
|
||||
let (c2, p2) = pipes::stream();
|
||||
|
||||
|
|
@ -1258,7 +1220,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_oneshot() {
|
||||
pub fn test_oneshot() {
|
||||
let (c, p) = oneshot::init();
|
||||
|
||||
oneshot::client::send(c, ());
|
||||
|
|
|
|||
|
|
@ -1,16 +1,9 @@
|
|||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
// tjc: re-forbid deprecated modes after snapshot
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
#[doc(hidden)];
|
||||
|
||||
export chan_from_global_ptr, weaken_task;
|
||||
|
||||
export SharedMutableState, shared_mutable_state, clone_shared_mutable_state;
|
||||
export get_shared_mutable_state, get_shared_immutable_state;
|
||||
export unwrap_shared_mutable_state;
|
||||
export Exclusive, exclusive, unwrap_exclusive;
|
||||
|
||||
use compare_and_swap = rustrt::rust_compare_and_swap_ptr;
|
||||
use task::TaskBuilder;
|
||||
use task::atomically;
|
||||
|
|
@ -49,7 +42,7 @@ type GlobalPtr = *libc::uintptr_t;
|
|||
* or, if no channel exists creates and installs a new channel and sets up a
|
||||
* new task to receive from it.
|
||||
*/
|
||||
unsafe fn chan_from_global_ptr<T: Send>(
|
||||
pub unsafe fn chan_from_global_ptr<T: Send>(
|
||||
global: GlobalPtr,
|
||||
task_fn: fn() -> task::TaskBuilder,
|
||||
+f: fn~(comm::Port<T>)
|
||||
|
|
@ -110,13 +103,13 @@ unsafe fn chan_from_global_ptr<T: Send>(
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_global_chan1() {
|
||||
pub fn test_from_global_chan1() {
|
||||
|
||||
// This is unreadable, right?
|
||||
|
||||
// The global channel
|
||||
let globchan = 0u;
|
||||
let globchanp = ptr::addr_of(globchan);
|
||||
let globchan = 0;
|
||||
let globchanp = ptr::p2::addr_of(&globchan);
|
||||
|
||||
// Create the global channel, attached to a new task
|
||||
let ch = unsafe {
|
||||
|
|
@ -147,25 +140,25 @@ fn test_from_global_chan1() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_global_chan2() {
|
||||
pub fn test_from_global_chan2() {
|
||||
|
||||
for iter::repeat(100u) {
|
||||
for iter::repeat(100) {
|
||||
// The global channel
|
||||
let globchan = 0u;
|
||||
let globchanp = ptr::addr_of(globchan);
|
||||
let globchan = 0;
|
||||
let globchanp = ptr::p2::addr_of(&globchan);
|
||||
|
||||
let resultpo = comm::Port();
|
||||
let resultch = comm::Chan(resultpo);
|
||||
|
||||
// Spawn a bunch of tasks that all want to compete to
|
||||
// create the global channel
|
||||
for uint::range(0u, 10u) |i| {
|
||||
for uint::range(0, 10) |i| {
|
||||
do task::spawn {
|
||||
let ch = unsafe {
|
||||
do chan_from_global_ptr(
|
||||
globchanp, task::task) |po| {
|
||||
|
||||
for uint::range(0u, 10u) |_j| {
|
||||
for uint::range(0, 10) |_j| {
|
||||
let ch = comm::recv(po);
|
||||
comm::send(ch, {i});
|
||||
}
|
||||
|
|
@ -208,7 +201,7 @@ fn test_from_global_chan2() {
|
|||
* * Weak tasks must not be supervised. A supervised task keeps
|
||||
* a reference to its parent, so the parent will not die.
|
||||
*/
|
||||
unsafe fn weaken_task(f: fn(comm::Port<()>)) {
|
||||
pub unsafe fn weaken_task(f: fn(comm::Port<()>)) {
|
||||
let po = comm::Port();
|
||||
let ch = comm::Chan(po);
|
||||
unsafe {
|
||||
|
|
@ -232,7 +225,7 @@ unsafe fn weaken_task(f: fn(comm::Port<()>)) {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_weaken_task_then_unweaken() {
|
||||
pub fn test_weaken_task_then_unweaken() {
|
||||
do task::try {
|
||||
unsafe {
|
||||
do weaken_task |_po| {
|
||||
|
|
@ -242,7 +235,7 @@ fn test_weaken_task_then_unweaken() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_weaken_task_wait() {
|
||||
pub fn test_weaken_task_wait() {
|
||||
do task::spawn_unlinked {
|
||||
unsafe {
|
||||
do weaken_task |po| {
|
||||
|
|
@ -253,7 +246,7 @@ fn test_weaken_task_wait() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_weaken_task_stress() {
|
||||
pub fn test_weaken_task_stress() {
|
||||
// Create a bunch of weak tasks
|
||||
for iter::repeat(100u) {
|
||||
do task::spawn {
|
||||
|
|
@ -275,7 +268,7 @@ fn test_weaken_task_stress() {
|
|||
|
||||
#[test]
|
||||
#[ignore(cfg(windows))]
|
||||
fn test_weaken_task_fail() {
|
||||
pub fn test_weaken_task_fail() {
|
||||
let res = do task::try {
|
||||
unsafe {
|
||||
do weaken_task |_po| {
|
||||
|
|
@ -283,7 +276,7 @@ fn test_weaken_task_fail() {
|
|||
}
|
||||
}
|
||||
};
|
||||
assert result::is_err(res);
|
||||
assert result::is_err(&res);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
|
@ -347,7 +340,7 @@ fn ArcDestruct<T>(data: *libc::c_void) -> ArcDestruct<T> {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe fn unwrap_shared_mutable_state<T: Send>(+rc: SharedMutableState<T>)
|
||||
pub unsafe fn unwrap_shared_mutable_state<T: Send>(rc: SharedMutableState<T>)
|
||||
-> T {
|
||||
struct DeathThroes<T> {
|
||||
mut ptr: Option<~ArcData<T>>,
|
||||
|
|
@ -418,9 +411,10 @@ unsafe fn unwrap_shared_mutable_state<T: Send>(+rc: SharedMutableState<T>)
|
|||
* Data races between tasks can result in crashes and, with sufficient
|
||||
* cleverness, arbitrary type coercion.
|
||||
*/
|
||||
type SharedMutableState<T: Send> = ArcDestruct<T>;
|
||||
pub type SharedMutableState<T: Send> = ArcDestruct<T>;
|
||||
|
||||
unsafe fn shared_mutable_state<T: Send>(+data: T) -> SharedMutableState<T> {
|
||||
pub unsafe fn shared_mutable_state<T: Send>(data: T) ->
|
||||
SharedMutableState<T> {
|
||||
let data = ~ArcData { count: 1, unwrapper: 0, data: Some(move data) };
|
||||
unsafe {
|
||||
let ptr = cast::transmute(move data);
|
||||
|
|
@ -429,7 +423,7 @@ unsafe fn shared_mutable_state<T: Send>(+data: T) -> SharedMutableState<T> {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
unsafe fn get_shared_mutable_state<T: Send>(rc: &a/SharedMutableState<T>)
|
||||
pub unsafe fn get_shared_mutable_state<T: Send>(rc: &a/SharedMutableState<T>)
|
||||
-> &a/mut T {
|
||||
unsafe {
|
||||
let ptr: ~ArcData<T> = cast::reinterpret_cast(&(*rc).data);
|
||||
|
|
@ -441,8 +435,8 @@ unsafe fn get_shared_mutable_state<T: Send>(rc: &a/SharedMutableState<T>)
|
|||
}
|
||||
}
|
||||
#[inline(always)]
|
||||
unsafe fn get_shared_immutable_state<T: Send>(rc: &a/SharedMutableState<T>)
|
||||
-> &a/T {
|
||||
pub unsafe fn get_shared_immutable_state<T: Send>(
|
||||
rc: &a/SharedMutableState<T>) -> &a/T {
|
||||
unsafe {
|
||||
let ptr: ~ArcData<T> = cast::reinterpret_cast(&(*rc).data);
|
||||
assert ptr.count > 0;
|
||||
|
|
@ -453,7 +447,7 @@ unsafe fn get_shared_immutable_state<T: Send>(rc: &a/SharedMutableState<T>)
|
|||
}
|
||||
}
|
||||
|
||||
unsafe fn clone_shared_mutable_state<T: Send>(rc: &SharedMutableState<T>)
|
||||
pub unsafe fn clone_shared_mutable_state<T: Send>(rc: &SharedMutableState<T>)
|
||||
-> SharedMutableState<T> {
|
||||
unsafe {
|
||||
let ptr: ~ArcData<T> = cast::reinterpret_cast(&(*rc).data);
|
||||
|
|
@ -506,9 +500,9 @@ struct ExData<T: Send> { lock: LittleLock, mut failed: bool, mut data: T, }
|
|||
/**
|
||||
* An arc over mutable data that is protected by a lock. For library use only.
|
||||
*/
|
||||
struct Exclusive<T: Send> { x: SharedMutableState<ExData<T>> }
|
||||
pub struct Exclusive<T: Send> { x: SharedMutableState<ExData<T>> }
|
||||
|
||||
fn exclusive<T:Send >(+user_data: T) -> Exclusive<T> {
|
||||
pub fn exclusive<T:Send >(user_data: T) -> Exclusive<T> {
|
||||
let data = ExData {
|
||||
lock: LittleLock(), mut failed: false, mut data: user_data
|
||||
};
|
||||
|
|
@ -550,7 +544,7 @@ impl<T: Send> Exclusive<T> {
|
|||
}
|
||||
|
||||
// FIXME(#2585) make this a by-move method on the exclusive
|
||||
fn unwrap_exclusive<T: Send>(+arc: Exclusive<T>) -> T {
|
||||
pub fn unwrap_exclusive<T: Send>(arc: Exclusive<T>) -> T {
|
||||
let Exclusive { x: x } <- arc;
|
||||
let inner = unsafe { unwrap_shared_mutable_state(move x) };
|
||||
let ExData { data: data, _ } <- inner;
|
||||
|
|
@ -558,11 +552,9 @@ fn unwrap_exclusive<T: Send>(+arc: Exclusive<T>) -> T {
|
|||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[legacy_exports];
|
||||
|
||||
pub mod tests {
|
||||
#[test]
|
||||
fn exclusive_arc() {
|
||||
pub fn exclusive_arc() {
|
||||
let mut futures = ~[];
|
||||
|
||||
let num_tasks = 10u;
|
||||
|
|
@ -572,7 +564,7 @@ mod tests {
|
|||
|
||||
for uint::range(0u, num_tasks) |_i| {
|
||||
let total = total.clone();
|
||||
vec::push(futures, future::spawn(|| {
|
||||
futures.push(future::spawn(|| {
|
||||
for uint::range(0u, count) |_i| {
|
||||
do total.with |count| {
|
||||
**count += 1u;
|
||||
|
|
@ -589,7 +581,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test] #[should_fail] #[ignore(cfg(windows))]
|
||||
fn exclusive_poison() {
|
||||
pub fn exclusive_poison() {
|
||||
// Tests that if one task fails inside of an exclusive, subsequent
|
||||
// accesses will also fail.
|
||||
let x = exclusive(1);
|
||||
|
|
@ -605,13 +597,13 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn exclusive_unwrap_basic() {
|
||||
pub fn exclusive_unwrap_basic() {
|
||||
let x = exclusive(~~"hello");
|
||||
assert unwrap_exclusive(x) == ~~"hello";
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exclusive_unwrap_contended() {
|
||||
pub fn exclusive_unwrap_contended() {
|
||||
let x = exclusive(~~"hello");
|
||||
let x2 = ~mut Some(x.clone());
|
||||
do task::spawn {
|
||||
|
|
@ -636,7 +628,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test] #[should_fail] #[ignore(cfg(windows))]
|
||||
fn exclusive_unwrap_conflict() {
|
||||
pub fn exclusive_unwrap_conflict() {
|
||||
let x = exclusive(~~"hello");
|
||||
let x2 = ~mut Some(x.clone());
|
||||
let mut res = None;
|
||||
|
|
@ -650,7 +642,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test] #[ignore(cfg(windows))]
|
||||
fn exclusive_unwrap_deadlock() {
|
||||
pub fn exclusive_unwrap_deadlock() {
|
||||
// This is not guaranteed to get to the deadlock before being killed,
|
||||
// but it will show up sometimes, and if the deadlock were not there,
|
||||
// the test would nondeterministically fail.
|
||||
|
|
|
|||
|
|
@ -1,33 +1,11 @@
|
|||
//! Unsafe pointer utility functions
|
||||
|
||||
export addr_of;
|
||||
export to_unsafe_ptr;
|
||||
export to_const_unsafe_ptr;
|
||||
export to_mut_unsafe_ptr;
|
||||
export mut_addr_of;
|
||||
export offset;
|
||||
export const_offset;
|
||||
export mut_offset;
|
||||
export null;
|
||||
export mut_null;
|
||||
export is_null;
|
||||
export is_not_null;
|
||||
export memcpy;
|
||||
export memmove;
|
||||
export memset;
|
||||
export to_uint;
|
||||
export ref_eq;
|
||||
export buf_len;
|
||||
export position;
|
||||
export Ptr;
|
||||
|
||||
use cmp::{Eq, Ord};
|
||||
use libc::{c_void, size_t};
|
||||
|
||||
#[nolink]
|
||||
#[abi = "cdecl"]
|
||||
extern mod libc_ {
|
||||
#[legacy_exports];
|
||||
#[rust_stack]
|
||||
fn memcpy(dest: *mut c_void, src: *const c_void,
|
||||
n: libc::size_t) -> *c_void;
|
||||
|
|
@ -43,25 +21,30 @@ extern mod libc_ {
|
|||
|
||||
#[abi = "rust-intrinsic"]
|
||||
extern mod rusti {
|
||||
#[legacy_exports];
|
||||
fn addr_of<T>(val: T) -> *T;
|
||||
fn addr_of<T>(&&val: T) -> *T;
|
||||
}
|
||||
|
||||
/// Get an unsafe pointer to a value
|
||||
#[inline(always)]
|
||||
pure fn addr_of<T>(val: T) -> *T { unsafe { rusti::addr_of(val) } }
|
||||
pub pure fn addr_of<T>(val: &T) -> *T { unsafe { rusti::addr_of(*val) } }
|
||||
|
||||
pub mod p2 {
|
||||
/// Get an unsafe pointer to a value
|
||||
#[inline(always)]
|
||||
pub pure fn addr_of<T>(val: &T) -> *T { unsafe { rusti::addr_of(*val) } }
|
||||
}
|
||||
|
||||
/// Get an unsafe mut pointer to a value
|
||||
#[inline(always)]
|
||||
pure fn mut_addr_of<T>(val: T) -> *mut T {
|
||||
pub pure fn mut_addr_of<T>(val: &T) -> *mut T {
|
||||
unsafe {
|
||||
cast::reinterpret_cast(&rusti::addr_of(val))
|
||||
cast::reinterpret_cast(&rusti::addr_of(*val))
|
||||
}
|
||||
}
|
||||
|
||||
/// Calculate the offset from a pointer
|
||||
#[inline(always)]
|
||||
fn offset<T>(ptr: *T, count: uint) -> *T {
|
||||
pub pure fn offset<T>(ptr: *T, count: uint) -> *T {
|
||||
unsafe {
|
||||
(ptr as uint + count * sys::size_of::<T>()) as *T
|
||||
}
|
||||
|
|
@ -69,7 +52,7 @@ fn offset<T>(ptr: *T, count: uint) -> *T {
|
|||
|
||||
/// Calculate the offset from a const pointer
|
||||
#[inline(always)]
|
||||
fn const_offset<T>(ptr: *const T, count: uint) -> *const T {
|
||||
pub pure fn const_offset<T>(ptr: *const T, count: uint) -> *const T {
|
||||
unsafe {
|
||||
(ptr as uint + count * sys::size_of::<T>()) as *T
|
||||
}
|
||||
|
|
@ -77,39 +60,39 @@ fn const_offset<T>(ptr: *const T, count: uint) -> *const T {
|
|||
|
||||
/// Calculate the offset from a mut pointer
|
||||
#[inline(always)]
|
||||
fn mut_offset<T>(ptr: *mut T, count: uint) -> *mut T {
|
||||
pub pure fn mut_offset<T>(ptr: *mut T, count: uint) -> *mut T {
|
||||
(ptr as uint + count * sys::size_of::<T>()) as *mut T
|
||||
}
|
||||
|
||||
/// Return the offset of the first null pointer in `buf`.
|
||||
#[inline(always)]
|
||||
unsafe fn buf_len<T>(buf: **T) -> uint {
|
||||
position(buf, |i| i == null())
|
||||
pub unsafe fn buf_len<T>(buf: **T) -> uint {
|
||||
position(buf, |i| *i == null())
|
||||
}
|
||||
|
||||
/// Return the first offset `i` such that `f(buf[i]) == true`.
|
||||
#[inline(always)]
|
||||
unsafe fn position<T>(buf: *T, f: fn(T) -> bool) -> uint {
|
||||
let mut i = 0u;
|
||||
pub unsafe fn position<T>(buf: *T, f: fn(&T) -> bool) -> uint {
|
||||
let mut i = 0;
|
||||
loop {
|
||||
if f(*offset(buf, i)) { return i; }
|
||||
else { i += 1u; }
|
||||
if f(&(*offset(buf, i))) { return i; }
|
||||
else { i += 1; }
|
||||
}
|
||||
}
|
||||
|
||||
/// Create an unsafe null pointer
|
||||
#[inline(always)]
|
||||
pure fn null<T>() -> *T { unsafe { cast::reinterpret_cast(&0u) } }
|
||||
pub pure fn null<T>() -> *T { unsafe { cast::reinterpret_cast(&0u) } }
|
||||
|
||||
/// Create an unsafe mutable null pointer
|
||||
#[inline(always)]
|
||||
pure fn mut_null<T>() -> *mut T { unsafe { cast::reinterpret_cast(&0u) } }
|
||||
pub pure fn mut_null<T>() -> *mut T { unsafe { cast::reinterpret_cast(&0u) } }
|
||||
|
||||
/// Returns true if the pointer is equal to the null pointer.
|
||||
pure fn is_null<T>(ptr: *const T) -> bool { ptr == null() }
|
||||
pub pure fn is_null<T>(ptr: *const T) -> bool { ptr == null() }
|
||||
|
||||
/// Returns true if the pointer is not equal to the null pointer.
|
||||
pure fn is_not_null<T>(ptr: *const T) -> bool { !is_null(ptr) }
|
||||
pub pure fn is_not_null<T>(ptr: *const T) -> bool { !is_null(ptr) }
|
||||
|
||||
/**
|
||||
* Copies data from one location to another
|
||||
|
|
@ -118,7 +101,7 @@ pure fn is_not_null<T>(ptr: *const T) -> bool { !is_null(ptr) }
|
|||
* and destination may not overlap.
|
||||
*/
|
||||
#[inline(always)]
|
||||
unsafe fn memcpy<T>(dst: *mut T, src: *const T, count: uint) {
|
||||
pub unsafe fn memcpy<T>(dst: *mut T, src: *const T, count: uint) {
|
||||
let n = count * sys::size_of::<T>();
|
||||
libc_::memcpy(dst as *mut c_void, src as *c_void, n as size_t);
|
||||
}
|
||||
|
|
@ -130,13 +113,13 @@ unsafe fn memcpy<T>(dst: *mut T, src: *const T, count: uint) {
|
|||
* and destination may overlap.
|
||||
*/
|
||||
#[inline(always)]
|
||||
unsafe fn memmove<T>(dst: *mut T, src: *const T, count: uint) {
|
||||
pub unsafe fn memmove<T>(dst: *mut T, src: *const T, count: uint) {
|
||||
let n = count * sys::size_of::<T>();
|
||||
libc_::memmove(dst as *mut c_void, src as *c_void, n as size_t);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
unsafe fn memset<T>(dst: *mut T, c: int, count: uint) {
|
||||
pub unsafe fn memset<T>(dst: *mut T, c: int, count: uint) {
|
||||
let n = count * sys::size_of::<T>();
|
||||
libc_::memset(dst as *mut c_void, c as libc::c_int, n as size_t);
|
||||
}
|
||||
|
|
@ -148,7 +131,7 @@ unsafe fn memset<T>(dst: *mut T, c: int, count: uint) {
|
|||
reinterpret_cast.
|
||||
*/
|
||||
#[inline(always)]
|
||||
fn to_unsafe_ptr<T>(thing: &T) -> *T {
|
||||
pub pure fn to_unsafe_ptr<T>(thing: &T) -> *T {
|
||||
unsafe { cast::reinterpret_cast(&thing) }
|
||||
}
|
||||
|
||||
|
|
@ -158,7 +141,7 @@ fn to_unsafe_ptr<T>(thing: &T) -> *T {
|
|||
reinterpret_cast.
|
||||
*/
|
||||
#[inline(always)]
|
||||
fn to_const_unsafe_ptr<T>(thing: &const T) -> *const T {
|
||||
pub pure fn to_const_unsafe_ptr<T>(thing: &const T) -> *const T {
|
||||
unsafe { cast::reinterpret_cast(&thing) }
|
||||
}
|
||||
|
||||
|
|
@ -168,7 +151,7 @@ fn to_const_unsafe_ptr<T>(thing: &const T) -> *const T {
|
|||
reinterpret_cast.
|
||||
*/
|
||||
#[inline(always)]
|
||||
fn to_mut_unsafe_ptr<T>(thing: &mut T) -> *mut T {
|
||||
pub pure fn to_mut_unsafe_ptr<T>(thing: &mut T) -> *mut T {
|
||||
unsafe { cast::reinterpret_cast(&thing) }
|
||||
}
|
||||
|
||||
|
|
@ -180,28 +163,35 @@ fn to_mut_unsafe_ptr<T>(thing: &mut T) -> *mut T {
|
|||
(I couldn't think of a cutesy name for this one.)
|
||||
*/
|
||||
#[inline(always)]
|
||||
fn to_uint<T>(thing: &T) -> uint unsafe {
|
||||
pub fn to_uint<T>(thing: &T) -> uint unsafe {
|
||||
cast::reinterpret_cast(&thing)
|
||||
}
|
||||
|
||||
/// Determine if two borrowed pointers point to the same thing.
|
||||
#[inline(always)]
|
||||
fn ref_eq<T>(thing: &a/T, other: &b/T) -> bool {
|
||||
pub fn ref_eq<T>(thing: &a/T, other: &b/T) -> bool {
|
||||
to_uint(thing) == to_uint(other)
|
||||
}
|
||||
|
||||
trait Ptr {
|
||||
pub trait Ptr<T> {
|
||||
pure fn is_null() -> bool;
|
||||
pure fn is_not_null() -> bool;
|
||||
pure fn offset(count: uint) -> self;
|
||||
}
|
||||
|
||||
/// Extension methods for pointers
|
||||
impl<T> *T: Ptr {
|
||||
impl<T> *T: Ptr<T> {
|
||||
/// Returns true if the pointer is equal to the null pointer.
|
||||
#[inline(always)]
|
||||
pure fn is_null() -> bool { is_null(self) }
|
||||
|
||||
/// Returns true if the pointer is not equal to the null pointer.
|
||||
#[inline(always)]
|
||||
pure fn is_not_null() -> bool { is_not_null(self) }
|
||||
|
||||
/// Calculates the offset from a pointer.
|
||||
#[inline(always)]
|
||||
pure fn offset(count: uint) -> *T { offset(self, count) }
|
||||
}
|
||||
|
||||
// Equality for pointers
|
||||
|
|
@ -253,11 +243,11 @@ impl<T:Ord> &const T : Ord {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
pub fn test() {
|
||||
unsafe {
|
||||
type Pair = {mut fst: int, mut snd: int};
|
||||
let p = {mut fst: 10, mut snd: 20};
|
||||
let pptr: *mut Pair = mut_addr_of(p);
|
||||
let pptr: *mut Pair = mut_addr_of(&p);
|
||||
let iptr: *mut int = cast::reinterpret_cast(&pptr);
|
||||
assert (*iptr == 10);;
|
||||
*iptr = 30;
|
||||
|
|
@ -285,20 +275,20 @@ fn test() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_position() {
|
||||
pub fn test_position() {
|
||||
use str::as_c_str;
|
||||
use libc::c_char;
|
||||
|
||||
let s = ~"hello";
|
||||
unsafe {
|
||||
assert 2u == as_c_str(s, |p| position(p, |c| c == 'l' as c_char));
|
||||
assert 4u == as_c_str(s, |p| position(p, |c| c == 'o' as c_char));
|
||||
assert 5u == as_c_str(s, |p| position(p, |c| c == 0 as c_char));
|
||||
assert 2u == as_c_str(s, |p| position(p, |c| *c == 'l' as c_char));
|
||||
assert 4u == as_c_str(s, |p| position(p, |c| *c == 'o' as c_char));
|
||||
assert 5u == as_c_str(s, |p| position(p, |c| *c == 0 as c_char));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_buf_len() {
|
||||
pub fn test_buf_len() {
|
||||
let s0 = ~"hello";
|
||||
let s1 = ~"there";
|
||||
let s2 = ~"thing";
|
||||
|
|
@ -316,7 +306,7 @@ fn test_buf_len() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_is_null() {
|
||||
pub fn test_is_null() {
|
||||
let p: *int = ptr::null();
|
||||
assert p.is_null();
|
||||
assert !p.is_not_null();
|
||||
|
|
|
|||
|
|
@ -1,29 +1,29 @@
|
|||
//! Random number generation
|
||||
|
||||
export Rng, seed, seeded_rng, Weighted, extensions;
|
||||
export xorshift, seeded_xorshift;
|
||||
// NB: transitional, de-mode-ing.
|
||||
#[warn(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
#[allow(non_camel_case_types)] // runtime type
|
||||
enum rctx {}
|
||||
|
||||
#[abi = "cdecl"]
|
||||
extern mod rustrt {
|
||||
#[legacy_exports];
|
||||
fn rand_seed() -> ~[u8];
|
||||
fn rand_new() -> *rctx;
|
||||
fn rand_new_seeded(seed: ~[u8]) -> *rctx;
|
||||
fn rand_new_seeded2(&&seed: ~[u8]) -> *rctx;
|
||||
fn rand_next(c: *rctx) -> u32;
|
||||
fn rand_free(c: *rctx);
|
||||
}
|
||||
|
||||
/// A random number generator
|
||||
trait Rng {
|
||||
pub trait Rng {
|
||||
/// Return the next random integer
|
||||
fn next() -> u32;
|
||||
}
|
||||
|
||||
/// A value with a particular weight compared to other values
|
||||
type Weighted<T> = { weight: uint, item: T };
|
||||
pub type Weighted<T> = { weight: uint, item: T };
|
||||
|
||||
/// Extension methods for random number generators
|
||||
impl Rng {
|
||||
|
|
@ -123,7 +123,7 @@ impl Rng {
|
|||
/**
|
||||
* Return a char randomly chosen from chars, failing if chars is empty
|
||||
*/
|
||||
fn gen_char_from(chars: ~str) -> char {
|
||||
fn gen_char_from(chars: &str) -> char {
|
||||
assert !chars.is_empty();
|
||||
self.choose(str::chars(chars))
|
||||
}
|
||||
|
|
@ -218,7 +218,7 @@ impl Rng {
|
|||
let mut r = ~[];
|
||||
for v.each |item| {
|
||||
for uint::range(0u, item.weight) |_i| {
|
||||
vec::push(r, item.item);
|
||||
r.push(item.item);
|
||||
}
|
||||
}
|
||||
move r
|
||||
|
|
@ -260,12 +260,12 @@ impl @RandRes: Rng {
|
|||
}
|
||||
|
||||
/// Create a new random seed for seeded_rng
|
||||
fn seed() -> ~[u8] {
|
||||
pub fn seed() -> ~[u8] {
|
||||
rustrt::rand_seed()
|
||||
}
|
||||
|
||||
/// Create a random number generator with a system specified seed
|
||||
fn Rng() -> Rng {
|
||||
pub fn Rng() -> Rng {
|
||||
@RandRes(rustrt::rand_new()) as Rng
|
||||
}
|
||||
|
||||
|
|
@ -275,8 +275,8 @@ fn Rng() -> Rng {
|
|||
* all other generators constructed with the same seed. The seed may be any
|
||||
* length.
|
||||
*/
|
||||
fn seeded_rng(seed: ~[u8]) -> Rng {
|
||||
@RandRes(rustrt::rand_new_seeded(seed)) as Rng
|
||||
pub fn seeded_rng(seed: &~[u8]) -> Rng {
|
||||
@RandRes(rustrt::rand_new_seeded2(*seed)) as Rng
|
||||
}
|
||||
|
||||
type XorShiftState = {
|
||||
|
|
@ -299,40 +299,72 @@ impl XorShiftState: Rng {
|
|||
}
|
||||
}
|
||||
|
||||
fn xorshift() -> Rng {
|
||||
pub fn xorshift() -> Rng {
|
||||
// constants taken from http://en.wikipedia.org/wiki/Xorshift
|
||||
seeded_xorshift(123456789u32, 362436069u32, 521288629u32, 88675123u32)
|
||||
}
|
||||
|
||||
fn seeded_xorshift(x: u32, y: u32, z: u32, w: u32) -> Rng {
|
||||
pub fn seeded_xorshift(x: u32, y: u32, z: u32, w: u32) -> Rng {
|
||||
{mut x: x, mut y: y, mut z: z, mut w: w} as Rng
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[legacy_exports];
|
||||
|
||||
// used to make space in TLS for a random number generator
|
||||
fn tls_rng_state(+_v: @RandRes) {}
|
||||
|
||||
/**
|
||||
* Gives back a lazily initialized task-local random number generator,
|
||||
* seeded by the system. Intended to be used in method chaining style, ie
|
||||
* task_rng().gen_int().
|
||||
*/
|
||||
pub fn task_rng() -> Rng {
|
||||
let r : Option<@RandRes>;
|
||||
unsafe {
|
||||
r = task::local_data::local_data_get(tls_rng_state);
|
||||
}
|
||||
match r {
|
||||
None => {
|
||||
let rng = @RandRes(rustrt::rand_new());
|
||||
unsafe {
|
||||
task::local_data::local_data_set(tls_rng_state, rng);
|
||||
}
|
||||
rng as Rng
|
||||
}
|
||||
Some(rng) => rng as Rng
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a random uint, using the task's based random number generator.
|
||||
*/
|
||||
pub fn random() -> uint {
|
||||
task_rng().gen_uint()
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
#[test]
|
||||
fn rng_seeded() {
|
||||
pub fn rng_seeded() {
|
||||
let seed = rand::seed();
|
||||
let ra = rand::seeded_rng(seed);
|
||||
let rb = rand::seeded_rng(seed);
|
||||
let ra = rand::seeded_rng(&seed);
|
||||
let rb = rand::seeded_rng(&seed);
|
||||
assert ra.gen_str(100u) == rb.gen_str(100u);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rng_seeded_custom_seed() {
|
||||
pub fn rng_seeded_custom_seed() {
|
||||
// much shorter than generated seeds which are 1024 bytes
|
||||
let seed = ~[2u8, 32u8, 4u8, 32u8, 51u8];
|
||||
let ra = rand::seeded_rng(seed);
|
||||
let rb = rand::seeded_rng(seed);
|
||||
let ra = rand::seeded_rng(&seed);
|
||||
let rb = rand::seeded_rng(&seed);
|
||||
assert ra.gen_str(100u) == rb.gen_str(100u);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rng_seeded_custom_seed2() {
|
||||
pub fn rng_seeded_custom_seed2() {
|
||||
let seed = ~[2u8, 32u8, 4u8, 32u8, 51u8];
|
||||
let ra = rand::seeded_rng(seed);
|
||||
let ra = rand::seeded_rng(&seed);
|
||||
// Regression test that isaac is actually using the above vector
|
||||
let r = ra.next();
|
||||
error!("%?", r);
|
||||
|
|
@ -341,7 +373,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn gen_int_range() {
|
||||
pub fn gen_int_range() {
|
||||
let r = rand::Rng();
|
||||
let a = r.gen_int_range(-3, 42);
|
||||
assert a >= -3 && a < 42;
|
||||
|
|
@ -352,12 +384,12 @@ mod tests {
|
|||
#[test]
|
||||
#[should_fail]
|
||||
#[ignore(cfg(windows))]
|
||||
fn gen_int_from_fail() {
|
||||
pub fn gen_int_from_fail() {
|
||||
rand::Rng().gen_int_range(5, -2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gen_uint_range() {
|
||||
pub fn gen_uint_range() {
|
||||
let r = rand::Rng();
|
||||
let a = r.gen_uint_range(3u, 42u);
|
||||
assert a >= 3u && a < 42u;
|
||||
|
|
@ -368,12 +400,12 @@ mod tests {
|
|||
#[test]
|
||||
#[should_fail]
|
||||
#[ignore(cfg(windows))]
|
||||
fn gen_uint_range_fail() {
|
||||
pub fn gen_uint_range_fail() {
|
||||
rand::Rng().gen_uint_range(5u, 2u);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gen_float() {
|
||||
pub fn gen_float() {
|
||||
let r = rand::Rng();
|
||||
let a = r.gen_float();
|
||||
let b = r.gen_float();
|
||||
|
|
@ -381,14 +413,14 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn gen_weighted_bool() {
|
||||
pub fn gen_weighted_bool() {
|
||||
let r = rand::Rng();
|
||||
assert r.gen_weighted_bool(0u) == true;
|
||||
assert r.gen_weighted_bool(1u) == true;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gen_str() {
|
||||
pub fn gen_str() {
|
||||
let r = rand::Rng();
|
||||
log(debug, r.gen_str(10u));
|
||||
log(debug, r.gen_str(10u));
|
||||
|
|
@ -399,7 +431,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn gen_bytes() {
|
||||
pub fn gen_bytes() {
|
||||
let r = rand::Rng();
|
||||
assert r.gen_bytes(0u).len() == 0u;
|
||||
assert r.gen_bytes(10u).len() == 10u;
|
||||
|
|
@ -407,13 +439,13 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn choose() {
|
||||
pub fn choose() {
|
||||
let r = rand::Rng();
|
||||
assert r.choose([1, 1, 1]) == 1;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn choose_option() {
|
||||
pub fn choose_option() {
|
||||
let r = rand::Rng();
|
||||
let x: Option<int> = r.choose_option([]);
|
||||
assert x.is_none();
|
||||
|
|
@ -421,7 +453,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn choose_weighted() {
|
||||
pub fn choose_weighted() {
|
||||
let r = rand::Rng();
|
||||
assert r.choose_weighted(~[{weight: 1u, item: 42}]) == 42;
|
||||
assert r.choose_weighted(~[
|
||||
|
|
@ -431,7 +463,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn choose_weighted_option() {
|
||||
pub fn choose_weighted_option() {
|
||||
let r = rand::Rng();
|
||||
assert r.choose_weighted_option(~[{weight: 1u, item: 42}]) ==
|
||||
Some(42);
|
||||
|
|
@ -444,7 +476,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn weighted_vec() {
|
||||
pub fn weighted_vec() {
|
||||
let r = rand::Rng();
|
||||
let empty: ~[int] = ~[];
|
||||
assert r.weighted_vec(~[]) == empty;
|
||||
|
|
@ -456,12 +488,26 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn shuffle() {
|
||||
pub fn shuffle() {
|
||||
let r = rand::Rng();
|
||||
let empty: ~[int] = ~[];
|
||||
assert r.shuffle(~[]) == empty;
|
||||
assert r.shuffle(~[1, 1, 1]) == ~[1, 1, 1];
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn task_rng() {
|
||||
let r = rand::task_rng();
|
||||
r.gen_int();
|
||||
assert r.shuffle(~[1, 1, 1]) == ~[1, 1, 1];
|
||||
assert r.gen_uint_range(0u, 1u) == 0u;
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn random() {
|
||||
// not sure how to test this aside from just getting a number
|
||||
let _n : uint = rand::random();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ use libc::c_void;
|
|||
* data structure, and implement both `MovePtr` for it as well as `TyVisitor`;
|
||||
* then build a MovePtrAdaptor wrapped around your struct.
|
||||
*/
|
||||
trait MovePtr {
|
||||
pub trait MovePtr {
|
||||
fn move_ptr(adjustment: fn(*c_void) -> *c_void);
|
||||
}
|
||||
|
||||
|
|
@ -27,7 +27,7 @@ fn align(size: uint, align: uint) -> uint {
|
|||
struct MovePtrAdaptor<V: TyVisitor MovePtr> {
|
||||
inner: V
|
||||
}
|
||||
pub fn MovePtrAdaptor<V: TyVisitor MovePtr>(+v: V) -> MovePtrAdaptor<V> {
|
||||
pub fn MovePtrAdaptor<V: TyVisitor MovePtr>(v: V) -> MovePtrAdaptor<V> {
|
||||
MovePtrAdaptor { inner: move v }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@ use cast::transmute;
|
|||
use intrinsic::{TyDesc, TyVisitor, visit_tydesc};
|
||||
use reflect::{MovePtr, MovePtrAdaptor};
|
||||
use vec::raw::{VecRepr, UnboxedVecRepr, SliceRepr};
|
||||
use box::raw::{BoxRepr, BoxHeaderRepr};
|
||||
pub use box::raw::BoxRepr;
|
||||
use box::raw::BoxHeaderRepr;
|
||||
|
||||
/// Helpers
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,14 @@
|
|||
//! A type representing either success or failure
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
// tjc: re-forbid deprecated modes after snapshot
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use cmp::Eq;
|
||||
use either::Either;
|
||||
|
||||
/// The result type
|
||||
enum Result<T, U> {
|
||||
pub enum Result<T, U> {
|
||||
/// Contains the successful result value
|
||||
Ok(T),
|
||||
/// Contains the error value
|
||||
|
|
@ -18,11 +22,11 @@ enum Result<T, U> {
|
|||
*
|
||||
* If the result is an error
|
||||
*/
|
||||
pure fn get<T: Copy, U>(res: Result<T, U>) -> T {
|
||||
match res {
|
||||
Ok(t) => t,
|
||||
Err(the_err) => unsafe {
|
||||
fail fmt!("get called on error result: %?", the_err)
|
||||
pub pure fn get<T: Copy, U>(res: &Result<T, U>) -> T {
|
||||
match *res {
|
||||
Ok(copy t) => t,
|
||||
Err(ref the_err) => unsafe {
|
||||
fail fmt!("get called on error result: %?", *the_err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -34,11 +38,11 @@ pure fn get<T: Copy, U>(res: Result<T, U>) -> T {
|
|||
*
|
||||
* If the result is an error
|
||||
*/
|
||||
pure fn get_ref<T, U>(res: &a/Result<T, U>) -> &a/T {
|
||||
pub pure fn get_ref<T, U>(res: &a/Result<T, U>) -> &a/T {
|
||||
match *res {
|
||||
Ok(ref t) => t,
|
||||
Err(ref the_err) => unsafe {
|
||||
fail fmt!("get_ref called on error result: %?", the_err)
|
||||
fail fmt!("get_ref called on error result: %?", *the_err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -50,23 +54,23 @@ pure fn get_ref<T, U>(res: &a/Result<T, U>) -> &a/T {
|
|||
*
|
||||
* If the result is not an error
|
||||
*/
|
||||
pure fn get_err<T, U: Copy>(res: Result<T, U>) -> U {
|
||||
match res {
|
||||
Err(u) => u,
|
||||
pub pure fn get_err<T, U: Copy>(res: &Result<T, U>) -> U {
|
||||
match *res {
|
||||
Err(copy u) => u,
|
||||
Ok(_) => fail ~"get_err called on ok result"
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if the result is `ok`
|
||||
pure fn is_ok<T, U>(res: Result<T, U>) -> bool {
|
||||
match res {
|
||||
pub pure fn is_ok<T, U>(res: &Result<T, U>) -> bool {
|
||||
match *res {
|
||||
Ok(_) => true,
|
||||
Err(_) => false
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if the result is `err`
|
||||
pure fn is_err<T, U>(res: Result<T, U>) -> bool {
|
||||
pub pure fn is_err<T, U>(res: &Result<T, U>) -> bool {
|
||||
!is_ok(res)
|
||||
}
|
||||
|
||||
|
|
@ -76,10 +80,11 @@ pure fn is_err<T, U>(res: Result<T, U>) -> bool {
|
|||
* `ok` result variants are converted to `either::right` variants, `err`
|
||||
* result variants are converted to `either::left`.
|
||||
*/
|
||||
pure fn to_either<T: Copy, U: Copy>(res: Result<U, T>) -> Either<T, U> {
|
||||
match res {
|
||||
Ok(res) => either::Right(res),
|
||||
Err(fail_) => either::Left(fail_)
|
||||
pub pure fn to_either<T: Copy, U: Copy>(res: &Result<U, T>)
|
||||
-> Either<T, U> {
|
||||
match *res {
|
||||
Ok(copy res) => either::Right(res),
|
||||
Err(copy fail_) => either::Left(fail_)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -97,11 +102,13 @@ pure fn to_either<T: Copy, U: Copy>(res: Result<U, T>) -> Either<T, U> {
|
|||
* ok(parse_bytes(buf))
|
||||
* }
|
||||
*/
|
||||
fn chain<T, U: Copy, V: Copy>(res: Result<T, V>, op: fn(T) -> Result<U, V>)
|
||||
-> Result<U, V> {
|
||||
match res {
|
||||
Ok(t) => op(t),
|
||||
Err(e) => Err(e)
|
||||
pub fn chain<T, U: Copy, V: Copy>(res: Result<T, V>, op: fn(t: T)
|
||||
-> Result<U, V>) -> Result<U, V> {
|
||||
// XXX: Should be writable with move + match
|
||||
if res.is_ok() {
|
||||
op(unwrap(res))
|
||||
} else {
|
||||
Err(unwrap_err(res))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -113,13 +120,13 @@ fn chain<T, U: Copy, V: Copy>(res: Result<T, V>, op: fn(T) -> Result<U, V>)
|
|||
* immediately returned. This function can be used to pass through a
|
||||
* successful result while handling an error.
|
||||
*/
|
||||
fn chain_err<T: Copy, U: Copy, V: Copy>(
|
||||
pub fn chain_err<T: Copy, U: Copy, V: Copy>(
|
||||
res: Result<T, V>,
|
||||
op: fn(V) -> Result<T, U>)
|
||||
op: fn(t: V) -> Result<T, U>)
|
||||
-> Result<T, U> {
|
||||
match res {
|
||||
Ok(t) => Ok(t),
|
||||
Err(v) => op(v)
|
||||
match move res {
|
||||
Ok(move t) => Ok(t),
|
||||
Err(move v) => op(v)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -137,9 +144,9 @@ fn chain_err<T: Copy, U: Copy, V: Copy>(
|
|||
* print_buf(buf)
|
||||
* }
|
||||
*/
|
||||
fn iter<T, E>(res: Result<T, E>, f: fn(T)) {
|
||||
match res {
|
||||
Ok(t) => f(t),
|
||||
pub fn iter<T, E>(res: &Result<T, E>, f: fn((&T))) {
|
||||
match *res {
|
||||
Ok(ref t) => f(t),
|
||||
Err(_) => ()
|
||||
}
|
||||
}
|
||||
|
|
@ -152,10 +159,10 @@ fn iter<T, E>(res: Result<T, E>, f: fn(T)) {
|
|||
* This function can be used to pass through a successful result while
|
||||
* handling an error.
|
||||
*/
|
||||
fn iter_err<T, E>(res: Result<T, E>, f: fn(E)) {
|
||||
match res {
|
||||
pub fn iter_err<T, E>(res: &Result<T, E>, f: fn((&E))) {
|
||||
match *res {
|
||||
Ok(_) => (),
|
||||
Err(e) => f(e)
|
||||
Err(ref e) => f(e)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -173,11 +180,11 @@ fn iter_err<T, E>(res: Result<T, E>, f: fn(E)) {
|
|||
* parse_bytes(buf)
|
||||
* }
|
||||
*/
|
||||
fn map<T, E: Copy, U: Copy>(res: Result<T, E>, op: fn(T) -> U)
|
||||
pub fn map<T, E: Copy, U: Copy>(res: &Result<T, E>, op: fn((&T)) -> U)
|
||||
-> Result<U, E> {
|
||||
match res {
|
||||
Ok(t) => Ok(op(t)),
|
||||
Err(e) => Err(e)
|
||||
match *res {
|
||||
Ok(ref t) => Ok(op(t)),
|
||||
Err(copy e) => Err(e)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -189,63 +196,65 @@ fn map<T, E: Copy, U: Copy>(res: Result<T, E>, op: fn(T) -> U)
|
|||
* is immediately returned. This function can be used to pass through a
|
||||
* successful result while handling an error.
|
||||
*/
|
||||
fn map_err<T: Copy, E, F: Copy>(res: Result<T, E>, op: fn(E) -> F)
|
||||
pub fn map_err<T: Copy, E, F: Copy>(res: &Result<T, E>, op: fn((&E)) -> F)
|
||||
-> Result<T, F> {
|
||||
match res {
|
||||
Ok(t) => Ok(t),
|
||||
Err(e) => Err(op(e))
|
||||
match *res {
|
||||
Ok(copy t) => Ok(t),
|
||||
Err(ref e) => Err(op(e))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, E> Result<T, E> {
|
||||
fn is_ok() -> bool { is_ok(self) }
|
||||
fn is_ok() -> bool { is_ok(&self) }
|
||||
|
||||
fn is_err() -> bool { is_err(self) }
|
||||
fn is_err() -> bool { is_err(&self) }
|
||||
|
||||
fn iter(f: fn(T)) {
|
||||
fn iter(f: fn((&T))) {
|
||||
match self {
|
||||
Ok(t) => f(t),
|
||||
Ok(ref t) => f(t),
|
||||
Err(_) => ()
|
||||
}
|
||||
}
|
||||
|
||||
fn iter_err(f: fn(E)) {
|
||||
fn iter_err(f: fn((&E))) {
|
||||
match self {
|
||||
Ok(_) => (),
|
||||
Err(e) => f(e)
|
||||
Err(ref e) => f(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, E> Result<T, E> {
|
||||
fn get() -> T { get(self) }
|
||||
fn get() -> T { get(&self) }
|
||||
|
||||
fn map_err<F:Copy>(op: fn(E) -> F) -> Result<T,F> {
|
||||
fn map_err<F:Copy>(op: fn((&E)) -> F) -> Result<T,F> {
|
||||
match self {
|
||||
Ok(t) => Ok(t),
|
||||
Err(e) => Err(op(e))
|
||||
Ok(copy t) => Ok(t),
|
||||
Err(ref e) => Err(op(e))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, E: Copy> Result<T, E> {
|
||||
fn get_err() -> E { get_err(self) }
|
||||
fn get_err() -> E { get_err(&self) }
|
||||
|
||||
fn map<U:Copy>(op: fn(T) -> U) -> Result<U,E> {
|
||||
fn map<U:Copy>(op: fn((&T)) -> U) -> Result<U,E> {
|
||||
match self {
|
||||
Ok(t) => Ok(op(t)),
|
||||
Err(e) => Err(e)
|
||||
Ok(ref t) => Ok(op(t)),
|
||||
Err(copy e) => Err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, E: Copy> Result<T, E> {
|
||||
fn chain<U:Copy>(op: fn(T) -> Result<U,E>) -> Result<U,E> {
|
||||
chain(self, op)
|
||||
fn chain<U:Copy>(op: fn(t: T) -> Result<U,E>) -> Result<U,E> {
|
||||
// XXX: Bad copy
|
||||
chain(copy self, op)
|
||||
}
|
||||
|
||||
fn chain_err<F:Copy>(op: fn(E) -> Result<T,F>) -> Result<T,F> {
|
||||
chain_err(self, op)
|
||||
fn chain_err<F:Copy>(op: fn(t: E) -> Result<T,F>) -> Result<T,F> {
|
||||
// XXX: Bad copy
|
||||
chain_err(copy self, op)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -266,27 +275,27 @@ impl<T: Copy, E: Copy> Result<T, E> {
|
|||
* assert incd == ~[2u, 3u, 4u];
|
||||
* }
|
||||
*/
|
||||
fn map_vec<T,U:Copy,V:Copy>(
|
||||
pub fn map_vec<T,U:Copy,V:Copy>(
|
||||
ts: &[T], op: fn((&T)) -> Result<V,U>) -> Result<~[V],U> {
|
||||
|
||||
let mut vs: ~[V] = vec::with_capacity(vec::len(ts));
|
||||
for vec::each(ts) |t| {
|
||||
match op(t) {
|
||||
Ok(v) => vec::push(vs, v),
|
||||
Err(u) => return Err(u)
|
||||
Ok(copy v) => vs.push(v),
|
||||
Err(copy u) => return Err(u)
|
||||
}
|
||||
}
|
||||
return Ok(move vs);
|
||||
}
|
||||
|
||||
fn map_opt<T,U:Copy,V:Copy>(
|
||||
o_t: Option<T>, op: fn(T) -> Result<V,U>) -> Result<Option<V>,U> {
|
||||
pub fn map_opt<T,U:Copy,V:Copy>(
|
||||
o_t: &Option<T>, op: fn((&T)) -> Result<V,U>) -> Result<Option<V>,U> {
|
||||
|
||||
match o_t {
|
||||
match *o_t {
|
||||
None => Ok(None),
|
||||
Some(t) => match op(t) {
|
||||
Ok(v) => Ok(Some(v)),
|
||||
Err(e) => Err(e)
|
||||
Some(ref t) => match op(t) {
|
||||
Ok(copy v) => Ok(Some(v)),
|
||||
Err(copy e) => Err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -300,17 +309,17 @@ fn map_opt<T,U:Copy,V:Copy>(
|
|||
* used in 'careful' code contexts where it is both appropriate and easy
|
||||
* to accommodate an error like the vectors being of different lengths.
|
||||
*/
|
||||
fn map_vec2<S,T,U:Copy,V:Copy>(ss: &[S], ts: &[T],
|
||||
op: fn(S,T) -> Result<V,U>) -> Result<~[V],U> {
|
||||
pub fn map_vec2<S,T,U:Copy,V:Copy>(ss: &[S], ts: &[T],
|
||||
op: fn((&S),(&T)) -> Result<V,U>) -> Result<~[V],U> {
|
||||
|
||||
assert vec::same_length(ss, ts);
|
||||
let n = vec::len(ts);
|
||||
let mut vs = vec::with_capacity(n);
|
||||
let mut i = 0u;
|
||||
while i < n {
|
||||
match op(ss[i],ts[i]) {
|
||||
Ok(v) => vec::push(vs, v),
|
||||
Err(u) => return Err(u)
|
||||
match op(&ss[i],&ts[i]) {
|
||||
Ok(copy v) => vs.push(v),
|
||||
Err(copy u) => return Err(u)
|
||||
}
|
||||
i += 1u;
|
||||
}
|
||||
|
|
@ -322,16 +331,16 @@ fn map_vec2<S,T,U:Copy,V:Copy>(ss: &[S], ts: &[T],
|
|||
* error. This could be implemented using `map2()` but it is more efficient
|
||||
* on its own as no result vector is built.
|
||||
*/
|
||||
fn iter_vec2<S,T,U:Copy>(ss: &[S], ts: &[T],
|
||||
op: fn(S,T) -> Result<(),U>) -> Result<(),U> {
|
||||
pub fn iter_vec2<S,T,U:Copy>(ss: &[S], ts: &[T],
|
||||
op: fn((&S),(&T)) -> Result<(),U>) -> Result<(),U> {
|
||||
|
||||
assert vec::same_length(ss, ts);
|
||||
let n = vec::len(ts);
|
||||
let mut i = 0u;
|
||||
while i < n {
|
||||
match op(ss[i],ts[i]) {
|
||||
match op(&ss[i],&ts[i]) {
|
||||
Ok(()) => (),
|
||||
Err(u) => return Err(u)
|
||||
Err(copy u) => return Err(u)
|
||||
}
|
||||
i += 1u;
|
||||
}
|
||||
|
|
@ -339,7 +348,7 @@ fn iter_vec2<S,T,U:Copy>(ss: &[S], ts: &[T],
|
|||
}
|
||||
|
||||
/// Unwraps a result, assuming it is an `ok(T)`
|
||||
fn unwrap<T, U>(+res: Result<T, U>) -> T {
|
||||
pub fn unwrap<T, U>(res: Result<T, U>) -> T {
|
||||
match move res {
|
||||
Ok(move t) => move t,
|
||||
Err(_) => fail ~"unwrap called on an err result"
|
||||
|
|
@ -347,7 +356,7 @@ fn unwrap<T, U>(+res: Result<T, U>) -> T {
|
|||
}
|
||||
|
||||
/// Unwraps a result, assuming it is an `err(U)`
|
||||
fn unwrap_err<T, U>(+res: Result<T, U>) -> U {
|
||||
pub fn unwrap_err<T, U>(res: Result<T, U>) -> U {
|
||||
match move res {
|
||||
Err(move u) => move u,
|
||||
Ok(_) => fail ~"unwrap called on an ok result"
|
||||
|
|
@ -357,15 +366,15 @@ fn unwrap_err<T, U>(+res: Result<T, U>) -> U {
|
|||
impl<T:Eq,U:Eq> Result<T,U> : Eq {
|
||||
pure fn eq(other: &Result<T,U>) -> bool {
|
||||
match self {
|
||||
Ok(e0a) => {
|
||||
Ok(ref e0a) => {
|
||||
match (*other) {
|
||||
Ok(e0b) => e0a == e0b,
|
||||
Ok(ref e0b) => *e0a == *e0b,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
Err(e0a) => {
|
||||
Err(ref e0a) => {
|
||||
match (*other) {
|
||||
Err(e0b) => e0a == e0b,
|
||||
Err(ref e0b) => *e0a == *e0b,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
|
@ -380,7 +389,7 @@ mod tests {
|
|||
#[legacy_exports];
|
||||
fn op1() -> result::Result<int, ~str> { result::Ok(666) }
|
||||
|
||||
fn op2(&&i: int) -> result::Result<uint, ~str> {
|
||||
fn op2(i: int) -> result::Result<uint, ~str> {
|
||||
result::Ok(i as uint + 1u)
|
||||
}
|
||||
|
||||
|
|
@ -388,12 +397,12 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn chain_success() {
|
||||
assert get(chain(op1(), op2)) == 667u;
|
||||
assert get(&chain(op1(), op2)) == 667u;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn chain_failure() {
|
||||
assert get_err(chain(op3(), op2)) == ~"sadface";
|
||||
assert get_err(&chain(op3(), op2)) == ~"sadface";
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -11,10 +11,9 @@ use libc::uintptr_t;
|
|||
use gc::{cleanup_stack_for_failure, gc, Word};
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
type rust_task = c_void;
|
||||
pub type rust_task = c_void;
|
||||
|
||||
extern mod rustrt {
|
||||
#[legacy_exports];
|
||||
#[rust_stack]
|
||||
fn rust_upcall_fail(expr: *c_char, file: *c_char, line: size_t);
|
||||
|
||||
|
|
@ -35,13 +34,23 @@ extern mod rustrt {
|
|||
// 'rt_', otherwise the compiler won't find it. To fix this, see
|
||||
// gather_rust_rtcalls.
|
||||
#[rt(fail_)]
|
||||
fn rt_fail_(expr: *c_char, file: *c_char, line: size_t) {
|
||||
pub fn rt_fail_(expr: *c_char, file: *c_char, line: size_t) {
|
||||
cleanup_stack_for_failure();
|
||||
rustrt::rust_upcall_fail(expr, file, line);
|
||||
}
|
||||
|
||||
#[rt(fail_bounds_check)]
|
||||
pub fn rt_fail_bounds_check(file: *c_char, line: size_t,
|
||||
index: size_t, len: size_t) {
|
||||
let msg = fmt!("index out of bounds: the len is %d but the index is %d",
|
||||
len as int, index as int);
|
||||
do str::as_buf(msg) |p, _len| {
|
||||
rt_fail_(p as *c_char, file, line);
|
||||
}
|
||||
}
|
||||
|
||||
#[rt(exchange_malloc)]
|
||||
fn rt_exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char {
|
||||
pub fn rt_exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char {
|
||||
return rustrt::rust_upcall_exchange_malloc(td, size);
|
||||
}
|
||||
|
||||
|
|
@ -49,12 +58,12 @@ fn rt_exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char {
|
|||
// inside a landing pad may corrupt the state of the exception handler. If a
|
||||
// problem occurs, call exit instead.
|
||||
#[rt(exchange_free)]
|
||||
fn rt_exchange_free(ptr: *c_char) {
|
||||
pub fn rt_exchange_free(ptr: *c_char) {
|
||||
rustrt::rust_upcall_exchange_free(ptr);
|
||||
}
|
||||
|
||||
#[rt(malloc)]
|
||||
fn rt_malloc(td: *c_char, size: uintptr_t) -> *c_char {
|
||||
pub fn rt_malloc(td: *c_char, size: uintptr_t) -> *c_char {
|
||||
return rustrt::rust_upcall_malloc(td, size);
|
||||
}
|
||||
|
||||
|
|
@ -62,7 +71,7 @@ fn rt_malloc(td: *c_char, size: uintptr_t) -> *c_char {
|
|||
// inside a landing pad may corrupt the state of the exception handler. If a
|
||||
// problem occurs, call exit instead.
|
||||
#[rt(free)]
|
||||
fn rt_free(ptr: *c_char) {
|
||||
pub fn rt_free(ptr: *c_char) {
|
||||
rustrt::rust_upcall_free(ptr);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
// tjc: re-forbid deprecated modes after snapshot
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
//! Process spawning
|
||||
|
|
@ -7,16 +7,8 @@ use option::{Some, None};
|
|||
use libc::{pid_t, c_void, c_int};
|
||||
use io::ReaderUtil;
|
||||
|
||||
export Program;
|
||||
export run_program;
|
||||
export start_program;
|
||||
export program_output;
|
||||
export spawn_process;
|
||||
export waitpid;
|
||||
|
||||
#[abi = "cdecl"]
|
||||
extern mod rustrt {
|
||||
#[legacy_exports];
|
||||
fn rust_run_program(argv: **libc::c_char, envp: *c_void,
|
||||
dir: *libc::c_char,
|
||||
in_fd: c_int, out_fd: c_int, err_fd: c_int)
|
||||
|
|
@ -24,7 +16,7 @@ extern mod rustrt {
|
|||
}
|
||||
|
||||
/// A value representing a child process
|
||||
trait Program {
|
||||
pub trait Program {
|
||||
/// Returns the process id of the program
|
||||
fn get_id() -> pid_t;
|
||||
|
||||
|
|
@ -68,7 +60,7 @@ trait Program {
|
|||
*
|
||||
* The process id of the spawned process
|
||||
*/
|
||||
fn spawn_process(prog: &str, args: &[~str],
|
||||
pub fn spawn_process(prog: &str, args: &[~str],
|
||||
env: &Option<~[(~str,~str)]>,
|
||||
dir: &Option<~str>,
|
||||
in_fd: c_int, out_fd: c_int, err_fd: c_int)
|
||||
|
|
@ -89,10 +81,10 @@ fn with_argv<T>(prog: &str, args: &[~str],
|
|||
let mut tmps = ~[];
|
||||
for vec::each(args) |arg| {
|
||||
let t = @copy *arg;
|
||||
vec::push(tmps, t);
|
||||
vec::push_all(argptrs, str::as_c_str(*t, |b| ~[b]));
|
||||
tmps.push(t);
|
||||
argptrs.push_all(str::as_c_str(*t, |b| ~[b]));
|
||||
}
|
||||
vec::push(argptrs, ptr::null());
|
||||
argptrs.push(ptr::null());
|
||||
vec::as_imm_buf(argptrs, |buf, _len| cb(buf))
|
||||
}
|
||||
|
||||
|
|
@ -102,17 +94,17 @@ fn with_envp<T>(env: &Option<~[(~str,~str)]>,
|
|||
// On posixy systems we can pass a char** for envp, which is
|
||||
// a null-terminated array of "k=v\n" strings.
|
||||
match *env {
|
||||
Some(es) if !vec::is_empty(es) => {
|
||||
Some(ref es) if !vec::is_empty(*es) => {
|
||||
let mut tmps = ~[];
|
||||
let mut ptrs = ~[];
|
||||
|
||||
for vec::each(es) |e| {
|
||||
for vec::each(*es) |e| {
|
||||
let (k,v) = copy *e;
|
||||
let t = @(fmt!("%s=%s", k, v));
|
||||
vec::push(tmps, t);
|
||||
vec::push_all(ptrs, str::as_c_str(*t, |b| ~[b]));
|
||||
tmps.push(t);
|
||||
ptrs.push_all(str::as_c_str(*t, |b| ~[b]));
|
||||
}
|
||||
vec::push(ptrs, ptr::null());
|
||||
ptrs.push(ptr::null());
|
||||
vec::as_imm_buf(ptrs, |p, _len|
|
||||
unsafe { cb(::cast::reinterpret_cast(&p)) }
|
||||
)
|
||||
|
|
@ -149,7 +141,7 @@ fn with_envp<T>(env: &Option<~[(~str,~str)]>,
|
|||
fn with_dirp<T>(d: &Option<~str>,
|
||||
cb: fn(*libc::c_char) -> T) -> T {
|
||||
match *d {
|
||||
Some(dir) => str::as_c_str(dir, cb),
|
||||
Some(ref dir) => str::as_c_str(*dir, cb),
|
||||
None => cb(ptr::null())
|
||||
}
|
||||
}
|
||||
|
|
@ -166,7 +158,7 @@ fn with_dirp<T>(d: &Option<~str>,
|
|||
*
|
||||
* The process id
|
||||
*/
|
||||
fn run_program(prog: &str, args: &[~str]) -> int {
|
||||
pub fn run_program(prog: &str, args: &[~str]) -> int {
|
||||
let pid = spawn_process(prog, args, &None, &None,
|
||||
0i32, 0i32, 0i32);
|
||||
if pid == -1 as pid_t { fail; }
|
||||
|
|
@ -189,7 +181,7 @@ fn run_program(prog: &str, args: &[~str]) -> int {
|
|||
*
|
||||
* A class with a <program> field
|
||||
*/
|
||||
fn start_program(prog: &str, args: &[~str]) -> Program {
|
||||
pub fn start_program(prog: &str, args: &[~str]) -> Program {
|
||||
let pipe_input = os::pipe();
|
||||
let pipe_output = os::pipe();
|
||||
let pipe_err = os::pipe();
|
||||
|
|
@ -232,7 +224,7 @@ fn start_program(prog: &str, args: &[~str]) -> Program {
|
|||
drop { destroy_repr(&self.r); }
|
||||
}
|
||||
|
||||
fn ProgRes(+r: ProgRepr) -> ProgRes {
|
||||
fn ProgRes(r: ProgRepr) -> ProgRes {
|
||||
ProgRes {
|
||||
r: r
|
||||
}
|
||||
|
|
@ -278,7 +270,7 @@ fn read_all(rd: io::Reader) -> ~str {
|
|||
* A record, {status: int, out: str, err: str} containing the exit code,
|
||||
* the contents of stdout and the contents of stderr.
|
||||
*/
|
||||
fn program_output(prog: &str, args: &[~str]) ->
|
||||
pub fn program_output(prog: &str, args: &[~str]) ->
|
||||
{status: int, out: ~str, err: ~str} {
|
||||
|
||||
let pipe_in = os::pipe();
|
||||
|
|
@ -320,11 +312,11 @@ fn program_output(prog: &str, args: &[~str]) ->
|
|||
while count > 0 {
|
||||
let stream = comm::recv(p);
|
||||
match stream {
|
||||
(1, s) => {
|
||||
outs = copy s;
|
||||
(1, copy s) => {
|
||||
outs = s;
|
||||
}
|
||||
(2, s) => {
|
||||
errs = copy s;
|
||||
(2, copy s) => {
|
||||
errs = s;
|
||||
}
|
||||
(n, _) => {
|
||||
fail(fmt!("program_output received an unexpected file \
|
||||
|
|
@ -336,7 +328,7 @@ fn program_output(prog: &str, args: &[~str]) ->
|
|||
return {status: status, out: move outs, err: move errs};
|
||||
}
|
||||
|
||||
fn writeclose(fd: c_int, s: &str) {
|
||||
fn writeclose(fd: c_int, s: ~str) {
|
||||
use io::WriterUtil;
|
||||
|
||||
error!("writeclose %d, %s", fd as int, s);
|
||||
|
|
@ -359,7 +351,7 @@ fn readclose(fd: c_int) -> ~str {
|
|||
}
|
||||
|
||||
/// Waits for a process to exit and returns the exit code
|
||||
fn waitpid(pid: pid_t) -> int {
|
||||
pub fn waitpid(pid: pid_t) -> int {
|
||||
return waitpid_os(pid);
|
||||
|
||||
#[cfg(windows)]
|
||||
|
|
@ -402,20 +394,19 @@ fn waitpid(pid: pid_t) -> int {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[legacy_exports];
|
||||
|
||||
use io::WriterUtil;
|
||||
|
||||
// Regression test for memory leaks
|
||||
#[ignore(cfg(windows))] // FIXME (#2626)
|
||||
fn test_leaks() {
|
||||
pub fn test_leaks() {
|
||||
run::run_program("echo", []);
|
||||
run::start_program("echo", []);
|
||||
run::program_output("echo", []);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pipes() {
|
||||
#[allow(non_implicitly_copyable_typarams)]
|
||||
pub fn test_pipes() {
|
||||
let pipe_in = os::pipe();
|
||||
let pipe_out = os::pipe();
|
||||
let pipe_err = os::pipe();
|
||||
|
|
@ -430,7 +421,7 @@ mod tests {
|
|||
|
||||
if pid == -1i32 { fail; }
|
||||
let expected = ~"test";
|
||||
writeclose(pipe_in.out, expected);
|
||||
writeclose(pipe_in.out, copy expected);
|
||||
let actual = readclose(pipe_out.in);
|
||||
readclose(pipe_err.in);
|
||||
os::waitpid(pid);
|
||||
|
|
@ -441,7 +432,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn waitpid() {
|
||||
pub fn waitpid() {
|
||||
let pid = run::spawn_process("false", [],
|
||||
&None, &None,
|
||||
0i32, 0i32, 0i32);
|
||||
|
|
|
|||
|
|
@ -12,10 +12,10 @@ use cmp::Eq;
|
|||
use hash::Hash;
|
||||
use to_bytes::IterBytes;
|
||||
|
||||
trait SendMap<K:Eq Hash, V: Copy> {
|
||||
pub trait SendMap<K:Eq Hash, V: Copy> {
|
||||
// FIXME(#3148) ^^^^ once find_ref() works, we can drop V:copy
|
||||
|
||||
fn insert(&mut self, +k: K, +v: V) -> bool;
|
||||
fn insert(&mut self, k: K, +v: V) -> bool;
|
||||
fn remove(&mut self, k: &K) -> bool;
|
||||
fn clear(&mut self);
|
||||
pure fn len(&const self) -> uint;
|
||||
|
|
@ -31,17 +31,15 @@ trait SendMap<K:Eq Hash, V: Copy> {
|
|||
}
|
||||
|
||||
/// Open addressing with linear probing.
|
||||
mod linear {
|
||||
#[legacy_exports];
|
||||
export LinearMap, linear_map, linear_map_with_capacity, public_methods;
|
||||
|
||||
pub mod linear {
|
||||
const initial_capacity: uint = 32u; // 2^5
|
||||
|
||||
struct Bucket<K:Eq Hash,V> {
|
||||
hash: uint,
|
||||
key: K,
|
||||
value: V,
|
||||
}
|
||||
struct LinearMap<K:Eq Hash,V> {
|
||||
pub struct LinearMap<K:Eq Hash,V> {
|
||||
k0: u64,
|
||||
k1: u64,
|
||||
resize_at: uint,
|
||||
|
|
@ -60,11 +58,11 @@ mod linear {
|
|||
((capacity as float) * 3. / 4.) as uint
|
||||
}
|
||||
|
||||
fn LinearMap<K:Eq Hash,V>() -> LinearMap<K,V> {
|
||||
pub fn LinearMap<K:Eq Hash,V>() -> LinearMap<K,V> {
|
||||
linear_map_with_capacity(32)
|
||||
}
|
||||
|
||||
fn linear_map_with_capacity<K:Eq Hash,V>(
|
||||
pub fn linear_map_with_capacity<K:Eq Hash,V>(
|
||||
initial_capacity: uint) -> LinearMap<K,V> {
|
||||
let r = rand::Rng();
|
||||
linear_map_with_capacity_and_keys(r.gen_u64(), r.gen_u64(),
|
||||
|
|
@ -137,7 +135,7 @@ mod linear {
|
|||
k: &K) -> SearchResult {
|
||||
let _ = for self.bucket_sequence(hash) |i| {
|
||||
match buckets[i] {
|
||||
Some(bkt) => if bkt.hash == hash && *k == bkt.key {
|
||||
Some(ref bkt) => if bkt.hash == hash && *k == bkt.key {
|
||||
return FoundEntry(i);
|
||||
},
|
||||
None => return FoundHole(i)
|
||||
|
|
@ -163,7 +161,7 @@ mod linear {
|
|||
}
|
||||
}
|
||||
|
||||
fn insert_opt_bucket(&mut self, +bucket: Option<Bucket<K,V>>) {
|
||||
fn insert_opt_bucket(&mut self, bucket: Option<Bucket<K,V>>) {
|
||||
match move bucket {
|
||||
Some(Bucket {hash: move hash,
|
||||
key: move key,
|
||||
|
|
@ -177,7 +175,7 @@ mod linear {
|
|||
/// Inserts the key value pair into the buckets.
|
||||
/// Assumes that there will be a bucket.
|
||||
/// True if there was no previous entry with that key
|
||||
fn insert_internal(&mut self, hash: uint, +k: K, +v: V) -> bool {
|
||||
fn insert_internal(&mut self, hash: uint, k: K, v: V) -> bool {
|
||||
match self.bucket_for_key_with_hash(self.buckets, hash, &k) {
|
||||
TableFull => { fail ~"Internal logic error"; }
|
||||
FoundHole(idx) => {
|
||||
|
|
@ -208,7 +206,7 @@ mod linear {
|
|||
}
|
||||
|
||||
impl<K:Hash IterBytes Eq,V> LinearMap<K,V> {
|
||||
fn insert(&mut self, +k: K, +v: V) -> bool {
|
||||
fn insert(&mut self, k: K, v: V) -> bool {
|
||||
if self.size >= self.resize_at {
|
||||
// n.b.: We could also do this after searching, so
|
||||
// that we do not resize if this call to insert is
|
||||
|
|
@ -285,18 +283,9 @@ mod linear {
|
|||
FoundEntry(idx) => {
|
||||
match self.buckets[idx] {
|
||||
Some(ref bkt) => {
|
||||
let ptr = unsafe {
|
||||
// FIXME(#3148)--region inference
|
||||
// fails to capture needed deps.
|
||||
// Here, the bucket value is known to
|
||||
// live as long as self, because self
|
||||
// is immutable. But the region
|
||||
// inference stupidly infers a
|
||||
// lifetime for `ref bkt` that is
|
||||
// shorter than it needs to be.
|
||||
cast::copy_lifetime(self, &bkt.value)
|
||||
};
|
||||
Some(ptr)
|
||||
// FIXME(#3148)---should be inferred
|
||||
let bkt: &self/Bucket<K,V> = bkt;
|
||||
Some(&bkt.value)
|
||||
}
|
||||
None => {
|
||||
fail ~"LinearMap::find: internal logic error"
|
||||
|
|
@ -344,7 +333,7 @@ mod linear {
|
|||
// FIXME (#3148): Once we rewrite found_entry, this
|
||||
// failure case won't be necessary
|
||||
match self.buckets[idx] {
|
||||
Some(bkt) => {Some(copy bkt.value)}
|
||||
Some(Bucket {value: copy value, _}) => {Some(value)}
|
||||
None => fail ~"LinearMap::find: internal logic error"
|
||||
}
|
||||
}
|
||||
|
|
@ -366,13 +355,11 @@ mod linear {
|
|||
}
|
||||
|
||||
#[test]
|
||||
mod test {
|
||||
#[legacy_exports];
|
||||
|
||||
pub mod test {
|
||||
use linear::LinearMap;
|
||||
|
||||
#[test]
|
||||
fn inserts() {
|
||||
pub fn inserts() {
|
||||
let mut m = ~LinearMap();
|
||||
assert m.insert(1, 2);
|
||||
assert m.insert(2, 4);
|
||||
|
|
@ -381,7 +368,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn overwrite() {
|
||||
pub fn overwrite() {
|
||||
let mut m = ~LinearMap();
|
||||
assert m.insert(1, 2);
|
||||
assert m.get(&1) == 2;
|
||||
|
|
@ -390,7 +377,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn conflicts() {
|
||||
pub fn conflicts() {
|
||||
let mut m = linear::linear_map_with_capacity(4);
|
||||
assert m.insert(1, 2);
|
||||
assert m.insert(5, 3);
|
||||
|
|
@ -401,7 +388,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn conflict_remove() {
|
||||
pub fn conflict_remove() {
|
||||
let mut m = linear::linear_map_with_capacity(4);
|
||||
assert m.insert(1, 2);
|
||||
assert m.insert(5, 3);
|
||||
|
|
@ -412,7 +399,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn empty() {
|
||||
pub fn empty() {
|
||||
let mut m = linear::linear_map_with_capacity(4);
|
||||
assert m.insert(1, 2);
|
||||
assert !m.is_empty();
|
||||
|
|
@ -421,7 +408,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn iterate() {
|
||||
pub fn iterate() {
|
||||
let mut m = linear::linear_map_with_capacity(4);
|
||||
for uint::range(0, 32) |i| {
|
||||
assert m.insert(i, i*2);
|
||||
|
|
@ -435,7 +422,7 @@ mod test {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn find_ref() {
|
||||
pub fn find_ref() {
|
||||
let mut m = ~LinearMap();
|
||||
assert m.find_ref(&1).is_none();
|
||||
m.insert(1, 2);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
#[doc(hidden)]; // FIXME #3538
|
||||
|
||||
#[legacy_modes]; // tjc: remove after snapshot
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
// XXX: Can't do this because frame_address needs a deprecated mode.
|
||||
//#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use cast::reinterpret_cast;
|
||||
|
|
@ -74,7 +77,7 @@ fn breakpoint() {
|
|||
rustrt::rust_dbg_breakpoint()
|
||||
}
|
||||
|
||||
fn frame_address(f: fn(*u8)) {
|
||||
fn frame_address(f: fn(++x: *u8)) {
|
||||
rusti::frame_address(f)
|
||||
}
|
||||
|
||||
|
|
@ -86,5 +89,5 @@ extern mod rustrt {
|
|||
#[abi = "rust-intrinsic"]
|
||||
extern mod rusti {
|
||||
#[legacy_exports];
|
||||
fn frame_address(f: fn(*u8));
|
||||
fn frame_address(f: fn(++x: *u8));
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -7,21 +7,10 @@
|
|||
use cmp::{Eq, Ord};
|
||||
use libc::c_void;
|
||||
|
||||
export FreeGlue;
|
||||
export TypeDesc;
|
||||
export Closure;
|
||||
export get_type_desc;
|
||||
export size_of;
|
||||
export min_align_of;
|
||||
export pref_align_of;
|
||||
export refcount;
|
||||
export log_str;
|
||||
export shape_eq, shape_lt, shape_le;
|
||||
|
||||
type FreeGlue = fn(*TypeDesc, *c_void);
|
||||
pub type FreeGlue = fn(*TypeDesc, *c_void);
|
||||
|
||||
// Corresponds to runtime type_desc type
|
||||
enum TypeDesc = {
|
||||
pub enum TypeDesc = {
|
||||
size: uint,
|
||||
align: uint,
|
||||
take_glue: uint,
|
||||
|
|
@ -31,14 +20,13 @@ enum TypeDesc = {
|
|||
};
|
||||
|
||||
/// The representation of a Rust closure
|
||||
struct Closure {
|
||||
pub struct Closure {
|
||||
code: *(),
|
||||
env: *(),
|
||||
}
|
||||
|
||||
#[abi = "rust-intrinsic"]
|
||||
extern mod rusti {
|
||||
#[legacy_exports];
|
||||
fn get_tydesc<T>() -> *();
|
||||
fn size_of<T>() -> uint;
|
||||
fn pref_align_of<T>() -> uint;
|
||||
|
|
@ -47,15 +35,15 @@ extern mod rusti {
|
|||
|
||||
/// Compares contents of two pointers using the default method.
|
||||
/// Equivalent to `*x1 == *x2`. Useful for hashtables.
|
||||
pure fn shape_eq<T:Eq>(x1: &T, x2: &T) -> bool {
|
||||
pub pure fn shape_eq<T:Eq>(x1: &T, x2: &T) -> bool {
|
||||
*x1 == *x2
|
||||
}
|
||||
|
||||
pure fn shape_lt<T:Ord>(x1: &T, x2: &T) -> bool {
|
||||
pub pure fn shape_lt<T:Ord>(x1: &T, x2: &T) -> bool {
|
||||
*x1 < *x2
|
||||
}
|
||||
|
||||
pure fn shape_le<T:Ord>(x1: &T, x2: &T) -> bool {
|
||||
pub pure fn shape_le<T:Ord>(x1: &T, x2: &T) -> bool {
|
||||
*x1 <= *x2
|
||||
}
|
||||
|
||||
|
|
@ -66,13 +54,13 @@ pure fn shape_le<T:Ord>(x1: &T, x2: &T) -> bool {
|
|||
* performing dark magick.
|
||||
*/
|
||||
#[inline(always)]
|
||||
pure fn get_type_desc<T>() -> *TypeDesc {
|
||||
pub pure fn get_type_desc<T>() -> *TypeDesc {
|
||||
unsafe { rusti::get_tydesc::<T>() as *TypeDesc }
|
||||
}
|
||||
|
||||
/// Returns the size of a type
|
||||
#[inline(always)]
|
||||
pure fn size_of<T>() -> uint {
|
||||
pub pure fn size_of<T>() -> uint {
|
||||
unsafe { rusti::size_of::<T>() }
|
||||
}
|
||||
|
||||
|
|
@ -83,26 +71,26 @@ pure fn size_of<T>() -> uint {
|
|||
* than the preferred alignment.
|
||||
*/
|
||||
#[inline(always)]
|
||||
pure fn min_align_of<T>() -> uint {
|
||||
pub pure fn min_align_of<T>() -> uint {
|
||||
unsafe { rusti::min_align_of::<T>() }
|
||||
}
|
||||
|
||||
/// Returns the preferred alignment of a type
|
||||
#[inline(always)]
|
||||
pure fn pref_align_of<T>() -> uint {
|
||||
pub pure fn pref_align_of<T>() -> uint {
|
||||
unsafe { rusti::pref_align_of::<T>() }
|
||||
}
|
||||
|
||||
/// Returns the refcount of a shared box (as just before calling this)
|
||||
#[inline(always)]
|
||||
pure fn refcount<T>(+t: @T) -> uint {
|
||||
pub pure fn refcount<T>(t: @T) -> uint {
|
||||
unsafe {
|
||||
let ref_ptr: *uint = cast::reinterpret_cast(&t);
|
||||
*ref_ptr - 1
|
||||
}
|
||||
}
|
||||
|
||||
pure fn log_str<T>(t: &T) -> ~str {
|
||||
pub pure fn log_str<T>(t: &T) -> ~str {
|
||||
unsafe {
|
||||
do io::with_str_writer |wr| {
|
||||
repr::write_repr(wr, t)
|
||||
|
|
@ -111,11 +99,10 @@ pure fn log_str<T>(t: &T) -> ~str {
|
|||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[legacy_exports];
|
||||
pub mod tests {
|
||||
|
||||
#[test]
|
||||
fn size_of_basic() {
|
||||
pub fn size_of_basic() {
|
||||
assert size_of::<u8>() == 1u;
|
||||
assert size_of::<u16>() == 2u;
|
||||
assert size_of::<u32>() == 4u;
|
||||
|
|
@ -125,20 +112,20 @@ mod tests {
|
|||
#[test]
|
||||
#[cfg(target_arch = "x86")]
|
||||
#[cfg(target_arch = "arm")]
|
||||
fn size_of_32() {
|
||||
pub fn size_of_32() {
|
||||
assert size_of::<uint>() == 4u;
|
||||
assert size_of::<*uint>() == 4u;
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
fn size_of_64() {
|
||||
pub fn size_of_64() {
|
||||
assert size_of::<uint>() == 8u;
|
||||
assert size_of::<*uint>() == 8u;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn align_of_basic() {
|
||||
pub fn align_of_basic() {
|
||||
assert pref_align_of::<u8>() == 1u;
|
||||
assert pref_align_of::<u16>() == 2u;
|
||||
assert pref_align_of::<u32>() == 4u;
|
||||
|
|
@ -147,20 +134,20 @@ mod tests {
|
|||
#[test]
|
||||
#[cfg(target_arch = "x86")]
|
||||
#[cfg(target_arch = "arm")]
|
||||
fn align_of_32() {
|
||||
pub fn align_of_32() {
|
||||
assert pref_align_of::<uint>() == 4u;
|
||||
assert pref_align_of::<*uint>() == 4u;
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
fn align_of_64() {
|
||||
pub fn align_of_64() {
|
||||
assert pref_align_of::<uint>() == 8u;
|
||||
assert pref_align_of::<*uint>() == 8u;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn synthesize_closure() unsafe {
|
||||
pub fn synthesize_closure() unsafe {
|
||||
let x = 10;
|
||||
let f: fn(int) -> int = |y| x + y;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
// tjc: re-forbid deprecated modes after snapshot
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
/*!
|
||||
|
|
@ -32,54 +32,11 @@ use result::Result;
|
|||
use pipes::{stream, Chan, Port};
|
||||
use local_data_priv::{local_get, local_set};
|
||||
|
||||
export Task;
|
||||
export TaskResult;
|
||||
export Notification;
|
||||
export SchedMode;
|
||||
export SchedOpts;
|
||||
export TaskOpts;
|
||||
export TaskBuilder;
|
||||
|
||||
export task;
|
||||
export default_task_opts;
|
||||
export get_opts;
|
||||
export set_opts;
|
||||
export set_sched_mode;
|
||||
export add_wrapper;
|
||||
export run;
|
||||
|
||||
export future_result;
|
||||
export run_listener;
|
||||
export run_with;
|
||||
|
||||
export spawn;
|
||||
export spawn_unlinked;
|
||||
export spawn_supervised;
|
||||
export spawn_with;
|
||||
export spawn_listener;
|
||||
export spawn_conversation;
|
||||
export spawn_sched;
|
||||
export try;
|
||||
|
||||
export yield;
|
||||
export failing;
|
||||
export get_task;
|
||||
export unkillable, rekillable;
|
||||
export atomically;
|
||||
|
||||
export local_data;
|
||||
|
||||
export SingleThreaded;
|
||||
export ThreadPerCore;
|
||||
export ThreadPerTask;
|
||||
export ManualThreads;
|
||||
export PlatformThread;
|
||||
|
||||
use rt::task_id;
|
||||
use rt::rust_task;
|
||||
|
||||
/// A handle to a task
|
||||
enum Task {
|
||||
pub enum Task {
|
||||
TaskHandle(task_id)
|
||||
}
|
||||
|
||||
|
|
@ -99,7 +56,7 @@ impl Task : cmp::Eq {
|
|||
* If you wish for this result's delivery to block until all linked and/or
|
||||
* children tasks complete, recommend using a result future.
|
||||
*/
|
||||
enum TaskResult {
|
||||
pub enum TaskResult {
|
||||
Success,
|
||||
Failure,
|
||||
}
|
||||
|
|
@ -115,7 +72,7 @@ impl TaskResult : Eq {
|
|||
}
|
||||
|
||||
/// A message type for notifying of task lifecycle events
|
||||
enum Notification {
|
||||
pub enum Notification {
|
||||
/// Sent when a task exits with the task handle and result
|
||||
Exit(Task, TaskResult)
|
||||
}
|
||||
|
|
@ -134,7 +91,7 @@ impl Notification : cmp::Eq {
|
|||
}
|
||||
|
||||
/// Scheduler modes
|
||||
enum SchedMode {
|
||||
pub enum SchedMode {
|
||||
/// All tasks run in the same OS thread
|
||||
SingleThreaded,
|
||||
/// Tasks are distributed among available CPUs
|
||||
|
|
@ -207,7 +164,7 @@ impl SchedMode : cmp::Eq {
|
|||
* default these foreign stacks have unspecified size, but with this
|
||||
* option their size can be precisely specified.
|
||||
*/
|
||||
type SchedOpts = {
|
||||
pub type SchedOpts = {
|
||||
mode: SchedMode,
|
||||
foreign_stack_size: Option<uint>
|
||||
};
|
||||
|
|
@ -239,7 +196,7 @@ type SchedOpts = {
|
|||
* into foreign code that blocks. Without doing so in a different
|
||||
* scheduler other tasks will be impeded or even blocked indefinitely.
|
||||
*/
|
||||
type TaskOpts = {
|
||||
pub type TaskOpts = {
|
||||
linked: bool,
|
||||
supervised: bool,
|
||||
mut notify_chan: Option<Chan<Notification>>,
|
||||
|
|
@ -260,7 +217,7 @@ type TaskOpts = {
|
|||
// the run function move them in.
|
||||
|
||||
// FIXME (#2585): Replace the 'consumed' bit with move mode on self
|
||||
enum TaskBuilder = {
|
||||
pub enum TaskBuilder = {
|
||||
opts: TaskOpts,
|
||||
gen_body: fn@(+v: fn~()) -> fn~(),
|
||||
can_not_copy: Option<util::NonCopyable>,
|
||||
|
|
@ -272,10 +229,10 @@ enum TaskBuilder = {
|
|||
* configuration methods can be chained.
|
||||
* For example, task().unlinked().spawn is equivalent to spawn_unlinked.
|
||||
*/
|
||||
fn task() -> TaskBuilder {
|
||||
pub fn task() -> TaskBuilder {
|
||||
TaskBuilder({
|
||||
opts: default_task_opts(),
|
||||
gen_body: |body| move body, // Identity function
|
||||
gen_body: |+body| move body, // Identity function
|
||||
can_not_copy: None,
|
||||
mut consumed: false,
|
||||
})
|
||||
|
|
@ -390,7 +347,7 @@ impl TaskBuilder {
|
|||
* # Failure
|
||||
* Fails if a future_result was already set for this task.
|
||||
*/
|
||||
fn future_result(blk: fn(+v: future::Future<TaskResult>)) -> TaskBuilder {
|
||||
fn future_result(blk: fn(v: future::Future<TaskResult>)) -> TaskBuilder {
|
||||
// FIXME (#1087, #1857): Once linked failure and notification are
|
||||
// handled in the library, I can imagine implementing this by just
|
||||
// registering an arbitrary number of task::on_exit handlers and
|
||||
|
|
@ -473,7 +430,7 @@ impl TaskBuilder {
|
|||
}
|
||||
|
||||
/**
|
||||
* Creates and exucutes a new child task
|
||||
* Creates and executes a new child task
|
||||
*
|
||||
* Sets up a new task with its own call stack and schedules it to run
|
||||
* the provided unique closure. The task has the properties and behavior
|
||||
|
|
@ -502,9 +459,9 @@ impl TaskBuilder {
|
|||
spawn::spawn_raw(move opts, x.gen_body(move f));
|
||||
}
|
||||
/// Runs a task, while transfering ownership of one argument to the child.
|
||||
fn spawn_with<A: Send>(+arg: A, +f: fn~(+v: A)) {
|
||||
fn spawn_with<A: Send>(arg: A, +f: fn~(+v: A)) {
|
||||
let arg = ~mut Some(move arg);
|
||||
do self.spawn |move arg, move f|{
|
||||
do self.spawn |move arg, move f| {
|
||||
f(option::swap_unwrap(arg))
|
||||
}
|
||||
}
|
||||
|
|
@ -516,7 +473,7 @@ impl TaskBuilder {
|
|||
* child task, passes the port to child's body, and returns a channel
|
||||
* linked to the port to the parent.
|
||||
*
|
||||
* This encapsulates Some boilerplate handshaking logic that would
|
||||
* This encapsulates some boilerplate handshaking logic that would
|
||||
* otherwise be required to establish communication from the parent
|
||||
* to the child.
|
||||
*/
|
||||
|
|
@ -580,7 +537,7 @@ impl TaskBuilder {
|
|||
|
||||
/* Task construction */
|
||||
|
||||
fn default_task_opts() -> TaskOpts {
|
||||
pub fn default_task_opts() -> TaskOpts {
|
||||
/*!
|
||||
* The default task options
|
||||
*
|
||||
|
|
@ -598,7 +555,7 @@ fn default_task_opts() -> TaskOpts {
|
|||
|
||||
/* Spawn convenience functions */
|
||||
|
||||
fn spawn(+f: fn~()) {
|
||||
pub fn spawn(+f: fn~()) {
|
||||
/*!
|
||||
* Creates and executes a new child task
|
||||
*
|
||||
|
|
@ -611,7 +568,7 @@ fn spawn(+f: fn~()) {
|
|||
task().spawn(move f)
|
||||
}
|
||||
|
||||
fn spawn_unlinked(+f: fn~()) {
|
||||
pub fn spawn_unlinked(+f: fn~()) {
|
||||
/*!
|
||||
* Creates a child task unlinked from the current one. If either this
|
||||
* task or the child task fails, the other will not be killed.
|
||||
|
|
@ -620,7 +577,7 @@ fn spawn_unlinked(+f: fn~()) {
|
|||
task().unlinked().spawn(move f)
|
||||
}
|
||||
|
||||
fn spawn_supervised(+f: fn~()) {
|
||||
pub fn spawn_supervised(+f: fn~()) {
|
||||
/*!
|
||||
* Creates a child task unlinked from the current one. If either this
|
||||
* task or the child task fails, the other will not be killed.
|
||||
|
|
@ -629,7 +586,7 @@ fn spawn_supervised(+f: fn~()) {
|
|||
task().supervised().spawn(move f)
|
||||
}
|
||||
|
||||
fn spawn_with<A:Send>(+arg: A, +f: fn~(+v: A)) {
|
||||
pub fn spawn_with<A:Send>(+arg: A, +f: fn~(+v: A)) {
|
||||
/*!
|
||||
* Runs a task, while transfering ownership of one argument to the
|
||||
* child.
|
||||
|
|
@ -643,7 +600,7 @@ fn spawn_with<A:Send>(+arg: A, +f: fn~(+v: A)) {
|
|||
task().spawn_with(move arg, move f)
|
||||
}
|
||||
|
||||
fn spawn_listener<A:Send>(+f: fn~(comm::Port<A>)) -> comm::Chan<A> {
|
||||
pub fn spawn_listener<A:Send>(+f: fn~(comm::Port<A>)) -> comm::Chan<A> {
|
||||
/*!
|
||||
* Runs a new task while providing a channel from the parent to the child
|
||||
*
|
||||
|
|
@ -653,7 +610,7 @@ fn spawn_listener<A:Send>(+f: fn~(comm::Port<A>)) -> comm::Chan<A> {
|
|||
task().spawn_listener(move f)
|
||||
}
|
||||
|
||||
fn spawn_conversation<A: Send, B: Send>
|
||||
pub fn spawn_conversation<A: Send, B: Send>
|
||||
(+f: fn~(comm::Port<A>, comm::Chan<B>))
|
||||
-> (comm::Port<B>, comm::Chan<A>) {
|
||||
/*!
|
||||
|
|
@ -665,7 +622,7 @@ fn spawn_conversation<A: Send, B: Send>
|
|||
task().spawn_conversation(move f)
|
||||
}
|
||||
|
||||
fn spawn_sched(mode: SchedMode, +f: fn~()) {
|
||||
pub fn spawn_sched(mode: SchedMode, +f: fn~()) {
|
||||
/*!
|
||||
* Creates a new scheduler and executes a task on it
|
||||
*
|
||||
|
|
@ -682,7 +639,7 @@ fn spawn_sched(mode: SchedMode, +f: fn~()) {
|
|||
task().sched_mode(mode).spawn(move f)
|
||||
}
|
||||
|
||||
fn try<T:Send>(+f: fn~() -> T) -> Result<T,()> {
|
||||
pub fn try<T:Send>(+f: fn~() -> T) -> Result<T,()> {
|
||||
/*!
|
||||
* Execute a function in another task and return either the return value
|
||||
* of the function or result::err.
|
||||
|
|
@ -696,7 +653,7 @@ fn try<T:Send>(+f: fn~() -> T) -> Result<T,()> {
|
|||
|
||||
/* Lifecycle functions */
|
||||
|
||||
fn yield() {
|
||||
pub fn yield() {
|
||||
//! Yield control to the task scheduler
|
||||
|
||||
let task_ = rt::rust_get_task();
|
||||
|
|
@ -706,13 +663,13 @@ fn yield() {
|
|||
}
|
||||
}
|
||||
|
||||
fn failing() -> bool {
|
||||
pub fn failing() -> bool {
|
||||
//! True if the running task has failed
|
||||
|
||||
rt::rust_task_is_unwinding(rt::rust_get_task())
|
||||
}
|
||||
|
||||
fn get_task() -> Task {
|
||||
pub fn get_task() -> Task {
|
||||
//! Get a handle to the running task
|
||||
|
||||
TaskHandle(rt::get_task_id())
|
||||
|
|
@ -733,7 +690,7 @@ fn get_task() -> Task {
|
|||
* }
|
||||
* ~~~
|
||||
*/
|
||||
unsafe fn unkillable<U>(f: fn() -> U) -> U {
|
||||
pub unsafe fn unkillable<U>(f: fn() -> U) -> U {
|
||||
struct AllowFailure {
|
||||
t: *rust_task,
|
||||
drop { rt::rust_task_allow_kill(self.t); }
|
||||
|
|
@ -752,7 +709,7 @@ unsafe fn unkillable<U>(f: fn() -> U) -> U {
|
|||
}
|
||||
|
||||
/// The inverse of unkillable. Only ever to be used nested in unkillable().
|
||||
unsafe fn rekillable<U>(f: fn() -> U) -> U {
|
||||
pub unsafe fn rekillable<U>(f: fn() -> U) -> U {
|
||||
struct DisallowFailure {
|
||||
t: *rust_task,
|
||||
drop { rt::rust_task_inhibit_kill(self.t); }
|
||||
|
|
@ -774,7 +731,7 @@ unsafe fn rekillable<U>(f: fn() -> U) -> U {
|
|||
* A stronger version of unkillable that also inhibits scheduling operations.
|
||||
* For use with exclusive ARCs, which use pthread mutexes directly.
|
||||
*/
|
||||
unsafe fn atomically<U>(f: fn() -> U) -> U {
|
||||
pub unsafe fn atomically<U>(f: fn() -> U) -> U {
|
||||
struct DeferInterrupts {
|
||||
t: *rust_task,
|
||||
drop {
|
||||
|
|
@ -1102,7 +1059,6 @@ fn test_spawn_sched_childs_on_same_sched() {
|
|||
#[nolink]
|
||||
#[cfg(test)]
|
||||
extern mod testrt {
|
||||
#[legacy_exports];
|
||||
fn rust_dbg_lock_create() -> *libc::c_void;
|
||||
fn rust_dbg_lock_destroy(lock: *libc::c_void);
|
||||
fn rust_dbg_lock_lock(lock: *libc::c_void);
|
||||
|
|
@ -1175,10 +1131,10 @@ fn avoid_copying_the_body(spawnfn: fn(+v: fn~())) {
|
|||
let ch = comm::Chan(p);
|
||||
|
||||
let x = ~1;
|
||||
let x_in_parent = ptr::addr_of(*x) as uint;
|
||||
let x_in_parent = ptr::p2::addr_of(&(*x)) as uint;
|
||||
|
||||
do spawnfn {
|
||||
let x_in_child = ptr::addr_of(*x) as uint;
|
||||
let x_in_child = ptr::p2::addr_of(&(*x)) as uint;
|
||||
comm::send(ch, x_in_child);
|
||||
}
|
||||
|
||||
|
|
@ -1193,7 +1149,7 @@ fn test_avoid_copying_the_body_spawn() {
|
|||
|
||||
#[test]
|
||||
fn test_avoid_copying_the_body_spawn_listener() {
|
||||
do avoid_copying_the_body |f| {
|
||||
do avoid_copying_the_body |+f| {
|
||||
spawn_listener(fn~(move f, _po: comm::Port<int>) {
|
||||
f();
|
||||
});
|
||||
|
|
@ -1211,7 +1167,7 @@ fn test_avoid_copying_the_body_task_spawn() {
|
|||
|
||||
#[test]
|
||||
fn test_avoid_copying_the_body_spawn_listener_1() {
|
||||
do avoid_copying_the_body |f| {
|
||||
do avoid_copying_the_body |+f| {
|
||||
task().spawn_listener(fn~(move f, _po: comm::Port<int>) {
|
||||
f();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -16,12 +16,6 @@ magic.
|
|||
|
||||
*/
|
||||
|
||||
export LocalDataKey;
|
||||
export local_data_pop;
|
||||
export local_data_get;
|
||||
export local_data_set;
|
||||
export local_data_modify;
|
||||
|
||||
use local_data_priv::{
|
||||
local_pop,
|
||||
local_get,
|
||||
|
|
@ -43,13 +37,13 @@ use local_data_priv::{
|
|||
*
|
||||
* These two cases aside, the interface is safe.
|
||||
*/
|
||||
type LocalDataKey<T: Owned> = &fn(+v: @T);
|
||||
pub type LocalDataKey<T: Owned> = &fn(v: @T);
|
||||
|
||||
/**
|
||||
* Remove a task-local data value from the table, returning the
|
||||
* reference that was originally created to insert it.
|
||||
*/
|
||||
unsafe fn local_data_pop<T: Owned>(
|
||||
pub unsafe fn local_data_pop<T: Owned>(
|
||||
key: LocalDataKey<T>) -> Option<@T> {
|
||||
|
||||
local_pop(rt::rust_get_task(), key)
|
||||
|
|
@ -58,7 +52,7 @@ unsafe fn local_data_pop<T: Owned>(
|
|||
* Retrieve a task-local data value. It will also be kept alive in the
|
||||
* table until explicitly removed.
|
||||
*/
|
||||
unsafe fn local_data_get<T: Owned>(
|
||||
pub unsafe fn local_data_get<T: Owned>(
|
||||
key: LocalDataKey<T>) -> Option<@T> {
|
||||
|
||||
local_get(rt::rust_get_task(), key)
|
||||
|
|
@ -67,8 +61,8 @@ unsafe fn local_data_get<T: Owned>(
|
|||
* Store a value in task-local data. If this key already has a value,
|
||||
* that value is overwritten (and its destructor is run).
|
||||
*/
|
||||
unsafe fn local_data_set<T: Owned>(
|
||||
key: LocalDataKey<T>, +data: @T) {
|
||||
pub unsafe fn local_data_set<T: Owned>(
|
||||
key: LocalDataKey<T>, data: @T) {
|
||||
|
||||
local_set(rt::rust_get_task(), key, data)
|
||||
}
|
||||
|
|
@ -76,7 +70,7 @@ unsafe fn local_data_set<T: Owned>(
|
|||
* Modify a task-local data value. If the function returns 'None', the
|
||||
* data is removed (and its reference dropped).
|
||||
*/
|
||||
unsafe fn local_data_modify<T: Owned>(
|
||||
pub unsafe fn local_data_modify<T: Owned>(
|
||||
key: LocalDataKey<T>,
|
||||
modify_fn: fn(Option<@T>) -> Option<@T>) {
|
||||
|
||||
|
|
@ -84,8 +78,8 @@ unsafe fn local_data_modify<T: Owned>(
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_tls_multitask() unsafe {
|
||||
fn my_key(+_x: @~str) { }
|
||||
pub fn test_tls_multitask() unsafe {
|
||||
fn my_key(_x: @~str) { }
|
||||
local_data_set(my_key, @~"parent data");
|
||||
do task::spawn unsafe {
|
||||
assert local_data_get(my_key).is_none(); // TLS shouldn't carry over.
|
||||
|
|
@ -100,16 +94,16 @@ fn test_tls_multitask() unsafe {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_tls_overwrite() unsafe {
|
||||
fn my_key(+_x: @~str) { }
|
||||
pub fn test_tls_overwrite() unsafe {
|
||||
fn my_key(_x: @~str) { }
|
||||
local_data_set(my_key, @~"first data");
|
||||
local_data_set(my_key, @~"next data"); // Shouldn't leak.
|
||||
assert *(local_data_get(my_key).get()) == ~"next data";
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tls_pop() unsafe {
|
||||
fn my_key(+_x: @~str) { }
|
||||
pub fn test_tls_pop() unsafe {
|
||||
fn my_key(_x: @~str) { }
|
||||
local_data_set(my_key, @~"weasel");
|
||||
assert *(local_data_pop(my_key).get()) == ~"weasel";
|
||||
// Pop must remove the data from the map.
|
||||
|
|
@ -117,18 +111,18 @@ fn test_tls_pop() unsafe {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_tls_modify() unsafe {
|
||||
fn my_key(+_x: @~str) { }
|
||||
pub fn test_tls_modify() unsafe {
|
||||
fn my_key(_x: @~str) { }
|
||||
local_data_modify(my_key, |data| {
|
||||
match data {
|
||||
Some(@val) => fail ~"unwelcome value: " + val,
|
||||
Some(@ref val) => fail ~"unwelcome value: " + *val,
|
||||
None => Some(@~"first data")
|
||||
}
|
||||
});
|
||||
local_data_modify(my_key, |data| {
|
||||
match data {
|
||||
Some(@~"first data") => Some(@~"next data"),
|
||||
Some(@val) => fail ~"wrong value: " + val,
|
||||
Some(@ref val) => fail ~"wrong value: " + *val,
|
||||
None => fail ~"missing value"
|
||||
}
|
||||
});
|
||||
|
|
@ -136,23 +130,23 @@ fn test_tls_modify() unsafe {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_tls_crust_automorestack_memorial_bug() unsafe {
|
||||
pub fn test_tls_crust_automorestack_memorial_bug() unsafe {
|
||||
// This might result in a stack-canary clobber if the runtime fails to set
|
||||
// sp_limit to 0 when calling the cleanup extern - it might automatically
|
||||
// jump over to the rust stack, which causes next_c_sp to get recorded as
|
||||
// Something within a rust stack segment. Then a subsequent upcall (esp.
|
||||
// for logging, think vsnprintf) would run on a stack smaller than 1 MB.
|
||||
fn my_key(+_x: @~str) { }
|
||||
fn my_key(_x: @~str) { }
|
||||
do task::spawn {
|
||||
unsafe { local_data_set(my_key, @~"hax"); }
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tls_multiple_types() unsafe {
|
||||
fn str_key(+_x: @~str) { }
|
||||
fn box_key(+_x: @@()) { }
|
||||
fn int_key(+_x: @int) { }
|
||||
pub fn test_tls_multiple_types() unsafe {
|
||||
fn str_key(_x: @~str) { }
|
||||
fn box_key(_x: @@()) { }
|
||||
fn int_key(_x: @int) { }
|
||||
do task::spawn unsafe {
|
||||
local_data_set(str_key, @~"string data");
|
||||
local_data_set(box_key, @@());
|
||||
|
|
@ -161,10 +155,10 @@ fn test_tls_multiple_types() unsafe {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_tls_overwrite_multiple_types() {
|
||||
fn str_key(+_x: @~str) { }
|
||||
fn box_key(+_x: @@()) { }
|
||||
fn int_key(+_x: @int) { }
|
||||
pub fn test_tls_overwrite_multiple_types() {
|
||||
fn str_key(_x: @~str) { }
|
||||
fn box_key(_x: @@()) { }
|
||||
fn int_key(_x: @int) { }
|
||||
do task::spawn unsafe {
|
||||
local_data_set(str_key, @~"string data");
|
||||
local_data_set(int_key, @42);
|
||||
|
|
@ -177,10 +171,10 @@ fn test_tls_overwrite_multiple_types() {
|
|||
#[test]
|
||||
#[should_fail]
|
||||
#[ignore(cfg(windows))]
|
||||
fn test_tls_cleanup_on_failure() unsafe {
|
||||
fn str_key(+_x: @~str) { }
|
||||
fn box_key(+_x: @@()) { }
|
||||
fn int_key(+_x: @int) { }
|
||||
pub fn test_tls_cleanup_on_failure() unsafe {
|
||||
fn str_key(_x: @~str) { }
|
||||
fn box_key(_x: @@()) { }
|
||||
fn int_key(_x: @int) { }
|
||||
local_data_set(str_key, @~"parent data");
|
||||
local_data_set(box_key, @@());
|
||||
do task::spawn unsafe { // spawn_linked
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
use local_data::LocalDataKey;
|
||||
use rt::rust_task;
|
||||
|
||||
trait LocalData { }
|
||||
pub trait LocalData { }
|
||||
impl<T: Owned> @T: LocalData { }
|
||||
|
||||
impl LocalData: Eq {
|
||||
|
|
@ -17,11 +17,11 @@ impl LocalData: Eq {
|
|||
|
||||
// We use dvec because it's the best data structure in core. If TLS is used
|
||||
// heavily in future, this could be made more efficient with a proper map.
|
||||
type TaskLocalElement = (*libc::c_void, *libc::c_void, LocalData);
|
||||
pub type TaskLocalElement = (*libc::c_void, *libc::c_void, LocalData);
|
||||
// Has to be a pointer at outermost layer; the foreign call returns void *.
|
||||
type TaskLocalMap = @dvec::DVec<Option<TaskLocalElement>>;
|
||||
pub type TaskLocalMap = @dvec::DVec<Option<TaskLocalElement>>;
|
||||
|
||||
extern fn cleanup_task_local_map(map_ptr: *libc::c_void) unsafe {
|
||||
pub extern fn cleanup_task_local_map(map_ptr: *libc::c_void) unsafe {
|
||||
assert !map_ptr.is_null();
|
||||
// Get and keep the single reference that was created at the beginning.
|
||||
let _map: TaskLocalMap = cast::reinterpret_cast(&map_ptr);
|
||||
|
|
@ -29,7 +29,7 @@ extern fn cleanup_task_local_map(map_ptr: *libc::c_void) unsafe {
|
|||
}
|
||||
|
||||
// Gets the map from the runtime. Lazily initialises if not done so already.
|
||||
unsafe fn get_task_local_map(task: *rust_task) -> TaskLocalMap {
|
||||
pub unsafe fn get_task_local_map(task: *rust_task) -> TaskLocalMap {
|
||||
|
||||
// Relies on the runtime initialising the pointer to null.
|
||||
// NOTE: The map's box lives in TLS invisibly referenced once. Each time
|
||||
|
|
@ -52,7 +52,7 @@ unsafe fn get_task_local_map(task: *rust_task) -> TaskLocalMap {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe fn key_to_key_value<T: Owned>(
|
||||
pub unsafe fn key_to_key_value<T: Owned>(
|
||||
key: LocalDataKey<T>) -> *libc::c_void {
|
||||
|
||||
// Keys are closures, which are (fnptr,envptr) pairs. Use fnptr.
|
||||
|
|
@ -62,25 +62,25 @@ unsafe fn key_to_key_value<T: Owned>(
|
|||
}
|
||||
|
||||
// If returning Some(..), returns with @T with the map's reference. Careful!
|
||||
unsafe fn local_data_lookup<T: Owned>(
|
||||
pub unsafe fn local_data_lookup<T: Owned>(
|
||||
map: TaskLocalMap, key: LocalDataKey<T>)
|
||||
-> Option<(uint, *libc::c_void)> {
|
||||
|
||||
let key_value = key_to_key_value(key);
|
||||
let map_pos = (*map).position(|entry|
|
||||
match entry {
|
||||
match *entry {
|
||||
Some((k,_,_)) => k == key_value,
|
||||
None => false
|
||||
}
|
||||
);
|
||||
do map_pos.map |index| {
|
||||
// .get() is guaranteed because of "None { false }" above.
|
||||
let (_, data_ptr, _) = (*map)[index].get();
|
||||
(index, data_ptr)
|
||||
let (_, data_ptr, _) = (*map)[*index].get();
|
||||
(*index, data_ptr)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn local_get_helper<T: Owned>(
|
||||
pub unsafe fn local_get_helper<T: Owned>(
|
||||
task: *rust_task, key: LocalDataKey<T>,
|
||||
do_pop: bool) -> Option<@T> {
|
||||
|
||||
|
|
@ -91,7 +91,7 @@ unsafe fn local_get_helper<T: Owned>(
|
|||
// was referenced in the local_data box, though, not here, so before
|
||||
// overwriting the local_data_box we need to give an extra reference.
|
||||
// We must also give an extra reference when not removing.
|
||||
let (index, data_ptr) = result;
|
||||
let (index, data_ptr) = *result;
|
||||
let data: @T = cast::transmute(move data_ptr);
|
||||
cast::bump_box_refcount(data);
|
||||
if do_pop {
|
||||
|
|
@ -102,22 +102,22 @@ unsafe fn local_get_helper<T: Owned>(
|
|||
}
|
||||
|
||||
|
||||
unsafe fn local_pop<T: Owned>(
|
||||
pub unsafe fn local_pop<T: Owned>(
|
||||
task: *rust_task,
|
||||
key: LocalDataKey<T>) -> Option<@T> {
|
||||
|
||||
local_get_helper(task, key, true)
|
||||
}
|
||||
|
||||
unsafe fn local_get<T: Owned>(
|
||||
pub unsafe fn local_get<T: Owned>(
|
||||
task: *rust_task,
|
||||
key: LocalDataKey<T>) -> Option<@T> {
|
||||
|
||||
local_get_helper(task, key, false)
|
||||
}
|
||||
|
||||
unsafe fn local_set<T: Owned>(
|
||||
task: *rust_task, key: LocalDataKey<T>, +data: @T) {
|
||||
pub unsafe fn local_set<T: Owned>(
|
||||
task: *rust_task, key: LocalDataKey<T>, data: @T) {
|
||||
|
||||
let map = get_task_local_map(task);
|
||||
// Store key+data as *voids. Data is invisibly referenced once; key isn't.
|
||||
|
|
@ -148,7 +148,7 @@ unsafe fn local_set<T: Owned>(
|
|||
}
|
||||
}
|
||||
|
||||
unsafe fn local_modify<T: Owned>(
|
||||
pub unsafe fn local_modify<T: Owned>(
|
||||
task: *rust_task, key: LocalDataKey<T>,
|
||||
modify_fn: fn(Option<@T>) -> Option<@T>) {
|
||||
|
||||
|
|
|
|||
|
|
@ -7,16 +7,16 @@ The task interface to the runtime
|
|||
#[doc(hidden)]; // FIXME #3538
|
||||
|
||||
#[allow(non_camel_case_types)] // runtime type
|
||||
type sched_id = int;
|
||||
pub type sched_id = int;
|
||||
#[allow(non_camel_case_types)] // runtime type
|
||||
type task_id = int;
|
||||
pub type task_id = int;
|
||||
|
||||
// These are both opaque runtime/compiler types that we don't know the
|
||||
// structure of and should only deal with via unsafe pointer
|
||||
#[allow(non_camel_case_types)] // runtime type
|
||||
type rust_task = libc::c_void;
|
||||
pub type rust_task = libc::c_void;
|
||||
#[allow(non_camel_case_types)] // runtime type
|
||||
type rust_closure = libc::c_void;
|
||||
pub type rust_closure = libc::c_void;
|
||||
|
||||
extern {
|
||||
#[rust_stack]
|
||||
|
|
|
|||
|
|
@ -66,28 +66,28 @@ use rt::rust_task;
|
|||
use rt::rust_closure;
|
||||
|
||||
macro_rules! move_it (
|
||||
{ $x:expr } => { unsafe { let y <- *ptr::addr_of($x); move y } }
|
||||
{ $x:expr } => { unsafe { let y <- *ptr::addr_of(&($x)); move y } }
|
||||
)
|
||||
|
||||
type TaskSet = send_map::linear::LinearMap<*rust_task,()>;
|
||||
pub type TaskSet = send_map::linear::LinearMap<*rust_task,()>;
|
||||
|
||||
fn new_taskset() -> TaskSet {
|
||||
pub fn new_taskset() -> TaskSet {
|
||||
send_map::linear::LinearMap()
|
||||
}
|
||||
fn taskset_insert(tasks: &mut TaskSet, task: *rust_task) {
|
||||
pub fn taskset_insert(tasks: &mut TaskSet, task: *rust_task) {
|
||||
let didnt_overwrite = tasks.insert(task, ());
|
||||
assert didnt_overwrite;
|
||||
}
|
||||
fn taskset_remove(tasks: &mut TaskSet, task: *rust_task) {
|
||||
pub fn taskset_remove(tasks: &mut TaskSet, task: *rust_task) {
|
||||
let was_present = tasks.remove(&task);
|
||||
assert was_present;
|
||||
}
|
||||
fn taskset_each(tasks: &TaskSet, blk: fn(+v: *rust_task) -> bool) {
|
||||
pub fn taskset_each(tasks: &TaskSet, blk: fn(v: *rust_task) -> bool) {
|
||||
tasks.each_key(|k| blk(*k))
|
||||
}
|
||||
|
||||
// One of these per group of linked-failure tasks.
|
||||
type TaskGroupData = {
|
||||
pub type TaskGroupData = {
|
||||
// All tasks which might kill this group. When this is empty, the group
|
||||
// can be "GC"ed (i.e., its link in the ancestor list can be removed).
|
||||
mut members: TaskSet,
|
||||
|
|
@ -95,12 +95,12 @@ type TaskGroupData = {
|
|||
// tasks in this group.
|
||||
mut descendants: TaskSet,
|
||||
};
|
||||
type TaskGroupArc = private::Exclusive<Option<TaskGroupData>>;
|
||||
pub type TaskGroupArc = private::Exclusive<Option<TaskGroupData>>;
|
||||
|
||||
type TaskGroupInner = &mut Option<TaskGroupData>;
|
||||
pub type TaskGroupInner = &mut Option<TaskGroupData>;
|
||||
|
||||
// A taskgroup is 'dead' when nothing can cause it to fail; only members can.
|
||||
pure fn taskgroup_is_dead(tg: &TaskGroupData) -> bool {
|
||||
pub pure fn taskgroup_is_dead(tg: &TaskGroupData) -> bool {
|
||||
(&tg.members).is_empty()
|
||||
}
|
||||
|
||||
|
|
@ -111,7 +111,7 @@ pure fn taskgroup_is_dead(tg: &TaskGroupData) -> bool {
|
|||
// taskgroup which was spawned-unlinked. Tasks from intermediate generations
|
||||
// have references to the middle of the list; when intermediate generations
|
||||
// die, their node in the list will be collected at a descendant's spawn-time.
|
||||
type AncestorNode = {
|
||||
pub type AncestorNode = {
|
||||
// Since the ancestor list is recursive, we end up with references to
|
||||
// exclusives within other exclusives. This is dangerous business (if
|
||||
// circular references arise, deadlock and memory leaks are imminent).
|
||||
|
|
@ -124,16 +124,16 @@ type AncestorNode = {
|
|||
// Recursive rest of the list.
|
||||
mut ancestors: AncestorList,
|
||||
};
|
||||
enum AncestorList = Option<private::Exclusive<AncestorNode>>;
|
||||
pub enum AncestorList = Option<private::Exclusive<AncestorNode>>;
|
||||
|
||||
// Accessors for taskgroup arcs and ancestor arcs that wrap the unsafety.
|
||||
#[inline(always)]
|
||||
fn access_group<U>(x: &TaskGroupArc, blk: fn(TaskGroupInner) -> U) -> U {
|
||||
pub fn access_group<U>(x: &TaskGroupArc, blk: fn(TaskGroupInner) -> U) -> U {
|
||||
unsafe { x.with(blk) }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn access_ancestors<U>(x: &private::Exclusive<AncestorNode>,
|
||||
pub fn access_ancestors<U>(x: &private::Exclusive<AncestorNode>,
|
||||
blk: fn(x: &mut AncestorNode) -> U) -> U {
|
||||
unsafe { x.with(blk) }
|
||||
}
|
||||
|
|
@ -146,9 +146,9 @@ fn access_ancestors<U>(x: &private::Exclusive<AncestorNode>,
|
|||
// (3) As a bonus, coalesces away all 'dead' taskgroup nodes in the list.
|
||||
// FIXME(#2190): Change Option<fn@(...)> to Option<fn&(...)>, to save on
|
||||
// allocations. Once that bug is fixed, changing the sigil should suffice.
|
||||
fn each_ancestor(list: &mut AncestorList,
|
||||
bail_opt: Option<fn@(TaskGroupInner)>,
|
||||
forward_blk: fn(TaskGroupInner) -> bool)
|
||||
pub fn each_ancestor(list: &mut AncestorList,
|
||||
bail_opt: Option<fn@(TaskGroupInner)>,
|
||||
forward_blk: fn(TaskGroupInner) -> bool)
|
||||
-> bool {
|
||||
// "Kickoff" call - there was no last generation.
|
||||
return !coalesce(list, bail_opt, forward_blk, uint::max_value);
|
||||
|
|
@ -200,7 +200,7 @@ fn each_ancestor(list: &mut AncestorList,
|
|||
// the end of the list, which doesn't make sense to coalesce.
|
||||
return do (**ancestors).map_default((None,false)) |ancestor_arc| {
|
||||
// NB: Takes a lock! (this ancestor node)
|
||||
do access_ancestors(&ancestor_arc) |nobe| {
|
||||
do access_ancestors(ancestor_arc) |nobe| {
|
||||
// Check monotonicity
|
||||
assert last_generation > nobe.generation;
|
||||
/*##########################################################*
|
||||
|
|
@ -240,7 +240,7 @@ fn each_ancestor(list: &mut AncestorList,
|
|||
if need_unwind && !nobe_is_dead {
|
||||
do bail_opt.iter |bail_blk| {
|
||||
do with_parent_tg(&mut nobe.parent_group) |tg_opt| {
|
||||
bail_blk(tg_opt)
|
||||
(*bail_blk)(tg_opt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -271,7 +271,7 @@ fn each_ancestor(list: &mut AncestorList,
|
|||
}
|
||||
|
||||
// One of these per task.
|
||||
struct TCB {
|
||||
pub struct TCB {
|
||||
me: *rust_task,
|
||||
// List of tasks with whose fates this one's is intertwined.
|
||||
tasks: TaskGroupArc, // 'none' means the group has failed.
|
||||
|
|
@ -303,8 +303,8 @@ struct TCB {
|
|||
}
|
||||
}
|
||||
|
||||
fn TCB(me: *rust_task, +tasks: TaskGroupArc, +ancestors: AncestorList,
|
||||
is_main: bool, +notifier: Option<AutoNotify>) -> TCB {
|
||||
pub fn TCB(me: *rust_task, tasks: TaskGroupArc, ancestors: AncestorList,
|
||||
is_main: bool, notifier: Option<AutoNotify>) -> TCB {
|
||||
|
||||
let notifier = move notifier;
|
||||
notifier.iter(|x| { x.failed = false; });
|
||||
|
|
@ -318,7 +318,7 @@ fn TCB(me: *rust_task, +tasks: TaskGroupArc, +ancestors: AncestorList,
|
|||
}
|
||||
}
|
||||
|
||||
struct AutoNotify {
|
||||
pub struct AutoNotify {
|
||||
notify_chan: Chan<Notification>,
|
||||
mut failed: bool,
|
||||
drop {
|
||||
|
|
@ -327,15 +327,15 @@ struct AutoNotify {
|
|||
}
|
||||
}
|
||||
|
||||
fn AutoNotify(+chan: Chan<Notification>) -> AutoNotify {
|
||||
pub fn AutoNotify(chan: Chan<Notification>) -> AutoNotify {
|
||||
AutoNotify {
|
||||
notify_chan: chan,
|
||||
failed: true // Un-set above when taskgroup successfully made.
|
||||
}
|
||||
}
|
||||
|
||||
fn enlist_in_taskgroup(state: TaskGroupInner, me: *rust_task,
|
||||
is_member: bool) -> bool {
|
||||
pub fn enlist_in_taskgroup(state: TaskGroupInner, me: *rust_task,
|
||||
is_member: bool) -> bool {
|
||||
let newstate = util::replace(state, None);
|
||||
// If 'None', the group was failing. Can't enlist.
|
||||
if newstate.is_some() {
|
||||
|
|
@ -350,7 +350,8 @@ fn enlist_in_taskgroup(state: TaskGroupInner, me: *rust_task,
|
|||
}
|
||||
|
||||
// NB: Runs in destructor/post-exit context. Can't 'fail'.
|
||||
fn leave_taskgroup(state: TaskGroupInner, me: *rust_task, is_member: bool) {
|
||||
pub fn leave_taskgroup(state: TaskGroupInner, me: *rust_task,
|
||||
is_member: bool) {
|
||||
let newstate = util::replace(state, None);
|
||||
// If 'None', already failing and we've already gotten a kill signal.
|
||||
if newstate.is_some() {
|
||||
|
|
@ -362,7 +363,7 @@ fn leave_taskgroup(state: TaskGroupInner, me: *rust_task, is_member: bool) {
|
|||
}
|
||||
|
||||
// NB: Runs in destructor/post-exit context. Can't 'fail'.
|
||||
fn kill_taskgroup(state: TaskGroupInner, me: *rust_task, is_main: bool) {
|
||||
pub fn kill_taskgroup(state: TaskGroupInner, me: *rust_task, is_main: bool) {
|
||||
// NB: We could do the killing iteration outside of the group arc, by
|
||||
// having "let mut newstate" here, swapping inside, and iterating after.
|
||||
// But that would let other exiting tasks fall-through and exit while we
|
||||
|
|
@ -377,13 +378,13 @@ fn kill_taskgroup(state: TaskGroupInner, me: *rust_task, is_main: bool) {
|
|||
// see 'None' if Somebody already failed and we got a kill signal.)
|
||||
if newstate.is_some() {
|
||||
let group = option::unwrap(move newstate);
|
||||
for taskset_each(&group.members) |+sibling| {
|
||||
for taskset_each(&group.members) |sibling| {
|
||||
// Skip self - killing ourself won't do much good.
|
||||
if sibling != me {
|
||||
rt::rust_task_kill_other(sibling);
|
||||
}
|
||||
}
|
||||
for taskset_each(&group.descendants) |+child| {
|
||||
for taskset_each(&group.descendants) |child| {
|
||||
assert child != me;
|
||||
rt::rust_task_kill_other(child);
|
||||
}
|
||||
|
|
@ -404,8 +405,8 @@ macro_rules! taskgroup_key (
|
|||
() => (cast::transmute((-2 as uint, 0u)))
|
||||
)
|
||||
|
||||
fn gen_child_taskgroup(linked: bool, supervised: bool)
|
||||
-> (TaskGroupArc, AncestorList, bool) {
|
||||
pub fn gen_child_taskgroup(linked: bool, supervised: bool)
|
||||
-> (TaskGroupArc, AncestorList, bool) {
|
||||
let spawner = rt::rust_get_task();
|
||||
/*######################################################################*
|
||||
* Step 1. Get spawner's taskgroup info.
|
||||
|
|
@ -451,7 +452,9 @@ fn gen_child_taskgroup(linked: bool, supervised: bool)
|
|||
// it should be enabled only in debug builds.
|
||||
let new_generation =
|
||||
match *old_ancestors {
|
||||
Some(arc) => access_ancestors(&arc, |a| a.generation+1),
|
||||
Some(ref arc) => {
|
||||
access_ancestors(arc, |a| a.generation+1)
|
||||
}
|
||||
None => 0 // the actual value doesn't really matter.
|
||||
};
|
||||
assert new_generation < uint::max_value;
|
||||
|
|
@ -484,7 +487,7 @@ fn gen_child_taskgroup(linked: bool, supervised: bool)
|
|||
}
|
||||
}
|
||||
|
||||
fn spawn_raw(+opts: TaskOpts, +f: fn~()) {
|
||||
pub fn spawn_raw(opts: TaskOpts, +f: fn~()) {
|
||||
let (child_tg, ancestors, is_main) =
|
||||
gen_child_taskgroup(opts.linked, opts.supervised);
|
||||
|
||||
|
|
@ -509,8 +512,8 @@ fn spawn_raw(+opts: TaskOpts, +f: fn~()) {
|
|||
|
||||
let child_wrapper = make_child_wrapper(new_task, move child_tg,
|
||||
move ancestors, is_main, move notify_chan, move f);
|
||||
let fptr = ptr::addr_of(child_wrapper);
|
||||
let closure: *rust_closure = cast::reinterpret_cast(&fptr);
|
||||
|
||||
let closure = cast::transmute(&child_wrapper);
|
||||
|
||||
// Getting killed between these two calls would free the child's
|
||||
// closure. (Reordering them wouldn't help - then getting killed
|
||||
|
|
@ -526,9 +529,9 @@ fn spawn_raw(+opts: TaskOpts, +f: fn~()) {
|
|||
// (3a) If any of those fails, it leaves all groups, and does nothing.
|
||||
// (3b) Otherwise it builds a task control structure and puts it in TLS,
|
||||
// (4) ...and runs the provided body function.
|
||||
fn make_child_wrapper(child: *rust_task, +child_arc: TaskGroupArc,
|
||||
+ancestors: AncestorList, is_main: bool,
|
||||
+notify_chan: Option<Chan<Notification>>,
|
||||
fn make_child_wrapper(child: *rust_task, child_arc: TaskGroupArc,
|
||||
ancestors: AncestorList, is_main: bool,
|
||||
notify_chan: Option<Chan<Notification>>,
|
||||
+f: fn~()) -> fn~() {
|
||||
let child_data = ~mut Some((move child_arc, move ancestors));
|
||||
return fn~(move notify_chan, move child_data, move f) {
|
||||
|
|
@ -541,8 +544,8 @@ fn spawn_raw(+opts: TaskOpts, +f: fn~()) {
|
|||
|
||||
//let mut notifier = None;//notify_chan.map(|c| AutoNotify(c));
|
||||
let notifier = match notify_chan {
|
||||
Some(notify_chan_value) => {
|
||||
let moved_ncv = move_it!(notify_chan_value);
|
||||
Some(ref notify_chan_value) => {
|
||||
let moved_ncv = move_it!(*notify_chan_value);
|
||||
Some(AutoNotify(move moved_ncv))
|
||||
}
|
||||
_ => None
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ The `ToBytes` and `IterBytes` traits
|
|||
|
||||
use io::Writer;
|
||||
|
||||
type Cb = fn(buf: &[const u8]) -> bool;
|
||||
pub type Cb = fn(buf: &[const u8]) -> bool;
|
||||
|
||||
/**
|
||||
* A trait to implement in order to make a type hashable;
|
||||
|
|
@ -19,7 +19,7 @@ type Cb = fn(buf: &[const u8]) -> bool;
|
|||
* modified when default methods and trait inheritence are
|
||||
* completed.
|
||||
*/
|
||||
trait IterBytes {
|
||||
pub trait IterBytes {
|
||||
/**
|
||||
* Call the provided callback `f` one or more times with
|
||||
* byte-slices that should be used when computing a hash
|
||||
|
|
@ -211,7 +211,7 @@ impl<A: IterBytes> @[A]: IterBytes {
|
|||
}
|
||||
}
|
||||
|
||||
pure fn iter_bytes_2<A: IterBytes, B: IterBytes>(a: &A, b: &B,
|
||||
pub pure fn iter_bytes_2<A: IterBytes, B: IterBytes>(a: &A, b: &B,
|
||||
lsb0: bool, z: Cb) {
|
||||
let mut flag = true;
|
||||
a.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
|
||||
|
|
@ -219,7 +219,7 @@ pure fn iter_bytes_2<A: IterBytes, B: IterBytes>(a: &A, b: &B,
|
|||
b.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
|
||||
}
|
||||
|
||||
pure fn iter_bytes_3<A: IterBytes,
|
||||
pub pure fn iter_bytes_3<A: IterBytes,
|
||||
B: IterBytes,
|
||||
C: IterBytes>(a: &A, b: &B, c: &C,
|
||||
lsb0: bool, z: Cb) {
|
||||
|
|
@ -231,7 +231,7 @@ pure fn iter_bytes_3<A: IterBytes,
|
|||
c.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
|
||||
}
|
||||
|
||||
pure fn iter_bytes_4<A: IterBytes,
|
||||
pub pure fn iter_bytes_4<A: IterBytes,
|
||||
B: IterBytes,
|
||||
C: IterBytes,
|
||||
D: IterBytes>(a: &A, b: &B, c: &C,
|
||||
|
|
@ -247,7 +247,7 @@ pure fn iter_bytes_4<A: IterBytes,
|
|||
d.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
|
||||
}
|
||||
|
||||
pure fn iter_bytes_5<A: IterBytes,
|
||||
pub pure fn iter_bytes_5<A: IterBytes,
|
||||
B: IterBytes,
|
||||
C: IterBytes,
|
||||
D: IterBytes,
|
||||
|
|
@ -266,7 +266,7 @@ pure fn iter_bytes_5<A: IterBytes,
|
|||
e.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
|
||||
}
|
||||
|
||||
pure fn iter_bytes_6<A: IterBytes,
|
||||
pub pure fn iter_bytes_6<A: IterBytes,
|
||||
B: IterBytes,
|
||||
C: IterBytes,
|
||||
D: IterBytes,
|
||||
|
|
@ -288,7 +288,7 @@ pure fn iter_bytes_6<A: IterBytes,
|
|||
f.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag});
|
||||
}
|
||||
|
||||
pure fn iter_bytes_7<A: IterBytes,
|
||||
pub pure fn iter_bytes_7<A: IterBytes,
|
||||
B: IterBytes,
|
||||
C: IterBytes,
|
||||
D: IterBytes,
|
||||
|
|
@ -345,7 +345,7 @@ impl<A: IterBytes> Option<A>: IterBytes {
|
|||
#[inline(always)]
|
||||
pure fn iter_bytes(lsb0: bool, f: Cb) {
|
||||
match self {
|
||||
Some(a) => iter_bytes_2(&0u8, &a, lsb0, f),
|
||||
Some(ref a) => iter_bytes_2(&0u8, a, lsb0, f),
|
||||
None => 1u8.iter_bytes(lsb0, f)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ The `ToStr` trait for converting to strings
|
|||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
trait ToStr { fn to_str() -> ~str; }
|
||||
pub trait ToStr { fn to_str() -> ~str; }
|
||||
|
||||
impl int: ToStr {
|
||||
fn to_str() -> ~str { int::str(self) }
|
||||
|
|
@ -101,7 +101,6 @@ impl<A: ToStr> ~A: ToStr {
|
|||
#[cfg(test)]
|
||||
#[allow(non_implicitly_copyable_typarams)]
|
||||
mod tests {
|
||||
#[legacy_exports];
|
||||
#[test]
|
||||
fn test_simple_types() {
|
||||
assert 1.to_str() == ~"1";
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
use cmp::{Eq, Ord};
|
||||
|
||||
trait TupleOps<T,U> {
|
||||
pub trait TupleOps<T,U> {
|
||||
pure fn first() -> T;
|
||||
pure fn second() -> U;
|
||||
pure fn swap() -> (U, T);
|
||||
|
|
@ -34,49 +34,54 @@ impl<T: Copy, U: Copy> (T, U): TupleOps<T,U> {
|
|||
|
||||
}
|
||||
|
||||
trait ExtendedTupleOps<A,B> {
|
||||
fn zip() -> ~[(A, B)];
|
||||
fn map<C>(f: fn(A, B) -> C) -> ~[C];
|
||||
pub trait ExtendedTupleOps<A,B> {
|
||||
fn zip(&self) -> ~[(A, B)];
|
||||
fn map<C>(&self, f: &fn(a: &A, b: &B) -> C) -> ~[C];
|
||||
}
|
||||
|
||||
impl<A: Copy, B: Copy> (&[A], &[B]): ExtendedTupleOps<A,B> {
|
||||
|
||||
fn zip() -> ~[(A, B)] {
|
||||
let (a, b) = self;
|
||||
vec::zip_slice(a, b)
|
||||
fn zip(&self) -> ~[(A, B)] {
|
||||
match *self {
|
||||
(ref a, ref b) => {
|
||||
vec::zip_slice(*a, *b)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn map<C>(f: fn(A, B) -> C) -> ~[C] {
|
||||
let (a, b) = self;
|
||||
vec::map2(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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Copy, B: Copy> (~[A], ~[B]): ExtendedTupleOps<A,B> {
|
||||
|
||||
fn zip() -> ~[(A, B)] {
|
||||
// FIXME #2543: Bad copy
|
||||
let (a, b) = copy self;
|
||||
vec::zip(move a, move b)
|
||||
fn zip(&self) -> ~[(A, B)] {
|
||||
match *self {
|
||||
(ref a, ref b) => {
|
||||
vec::zip_slice(*a, *b)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn map<C>(f: fn(A, B) -> C) -> ~[C] {
|
||||
// FIXME #2543: Bad copy
|
||||
let (a, b) = copy self;
|
||||
vec::map2(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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Eq, B: Eq> (A, B) : Eq {
|
||||
pure fn eq(other: &(A, B)) -> bool {
|
||||
// XXX: This would be a lot less wordy with ref bindings, but I don't
|
||||
// trust that they work yet.
|
||||
match self {
|
||||
(self_a, self_b) => {
|
||||
match (*other) {
|
||||
(ref other_a, ref other_b) => {
|
||||
self_a.eq(other_a) && self_b.eq(other_b)
|
||||
}
|
||||
(ref self_a, ref self_b) => match other {
|
||||
&(ref other_a, ref other_b) => {
|
||||
(*self_a).eq(other_a) && (*self_b).eq(other_b)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -106,16 +111,11 @@ impl<A: Ord, B: Ord> (A, B) : Ord {
|
|||
|
||||
impl<A: Eq, B: Eq, C: Eq> (A, B, C) : Eq {
|
||||
pure fn eq(other: &(A, B, C)) -> bool {
|
||||
// XXX: This would be a lot less wordy with ref bindings, but I don't
|
||||
// trust that they work yet.
|
||||
match self {
|
||||
(self_a, self_b, self_c) => {
|
||||
match (*other) {
|
||||
(ref other_a, ref other_b, ref other_c) => {
|
||||
self_a.eq(other_a) &&
|
||||
self_b.eq(other_b) &&
|
||||
self_c.eq(other_c)
|
||||
}
|
||||
(ref self_a, ref self_b, ref self_c) => match other {
|
||||
&(ref other_a, ref other_b, ref other_c) => {
|
||||
(*self_a).eq(other_a) && (*self_b).eq(other_b)
|
||||
&& (*self_c).eq(other_c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,49 +6,36 @@ use T = inst::T;
|
|||
use cmp::{Eq, Ord};
|
||||
use from_str::FromStr;
|
||||
|
||||
export min_value, max_value;
|
||||
export min, max;
|
||||
export add, sub, mul, div, rem;
|
||||
export lt, le, eq, ne, ge, gt;
|
||||
export is_positive, is_negative;
|
||||
export is_nonpositive, is_nonnegative;
|
||||
export range;
|
||||
export compl;
|
||||
export to_str, to_str_bytes;
|
||||
export from_str, from_str_radix, str, parse_bytes;
|
||||
export num, ord, eq, times, timesi;
|
||||
export bits, bytes;
|
||||
pub const bits : uint = inst::bits;
|
||||
pub const bytes : uint = (inst::bits / 8);
|
||||
|
||||
const bits : uint = inst::bits;
|
||||
const bytes : uint = (inst::bits / 8);
|
||||
pub const min_value: T = 0 as T;
|
||||
pub const max_value: T = 0 as T - 1 as T;
|
||||
|
||||
const min_value: T = 0 as T;
|
||||
const max_value: T = 0 as T - 1 as T;
|
||||
pub pure fn min(x: T, y: T) -> T { if x < y { x } else { y } }
|
||||
pub pure fn max(x: T, y: T) -> T { if x > y { x } else { y } }
|
||||
|
||||
pure fn min(x: T, y: T) -> T { if x < y { x } else { y } }
|
||||
pure fn max(x: T, y: T) -> T { if x > y { x } else { y } }
|
||||
pub pure fn add(x: T, y: T) -> T { x + y }
|
||||
pub pure fn sub(x: T, y: T) -> T { x - y }
|
||||
pub pure fn mul(x: T, y: T) -> T { x * y }
|
||||
pub pure fn div(x: T, y: T) -> T { x / y }
|
||||
pub pure fn rem(x: T, y: T) -> T { x % y }
|
||||
|
||||
pure fn add(x: T, y: T) -> T { x + y }
|
||||
pure fn sub(x: T, y: T) -> T { x - y }
|
||||
pure fn mul(x: T, y: T) -> T { x * y }
|
||||
pure fn div(x: T, y: T) -> T { x / y }
|
||||
pure fn rem(x: T, y: T) -> T { x % y }
|
||||
pub pure fn lt(x: T, y: T) -> bool { x < y }
|
||||
pub pure fn le(x: T, y: T) -> bool { x <= y }
|
||||
pub pure fn eq(x: T, y: T) -> bool { x == y }
|
||||
pub pure fn ne(x: T, y: T) -> bool { x != y }
|
||||
pub pure fn ge(x: T, y: T) -> bool { x >= y }
|
||||
pub pure fn gt(x: T, y: T) -> bool { x > y }
|
||||
|
||||
pure fn lt(x: T, y: T) -> bool { x < y }
|
||||
pure fn le(x: T, y: T) -> bool { x <= y }
|
||||
pure fn eq(x: T, y: T) -> bool { x == y }
|
||||
pure fn ne(x: T, y: T) -> bool { x != y }
|
||||
pure fn ge(x: T, y: T) -> bool { x >= y }
|
||||
pure fn gt(x: T, y: T) -> bool { x > y }
|
||||
|
||||
pure fn is_positive(x: T) -> bool { x > 0 as T }
|
||||
pure fn is_negative(x: T) -> bool { x < 0 as T }
|
||||
pure fn is_nonpositive(x: T) -> bool { x <= 0 as T }
|
||||
pure fn is_nonnegative(x: T) -> bool { x >= 0 as T }
|
||||
pub pure fn is_positive(x: T) -> bool { x > 0 as T }
|
||||
pub pure fn is_negative(x: T) -> bool { x < 0 as T }
|
||||
pub pure fn is_nonpositive(x: T) -> bool { x <= 0 as T }
|
||||
pub pure fn is_nonnegative(x: T) -> bool { x >= 0 as T }
|
||||
|
||||
#[inline(always)]
|
||||
/// Iterate over the range [`lo`..`hi`)
|
||||
pure fn range(lo: T, hi: T, it: fn(T) -> bool) {
|
||||
pub pure fn range(lo: T, hi: T, it: fn(T) -> bool) {
|
||||
let mut i = lo;
|
||||
while i < hi {
|
||||
if !it(i) { break }
|
||||
|
|
@ -57,7 +44,7 @@ pure fn range(lo: T, hi: T, it: fn(T) -> bool) {
|
|||
}
|
||||
|
||||
/// Computes the bitwise complement
|
||||
pure fn compl(i: T) -> T {
|
||||
pub pure fn compl(i: T) -> T {
|
||||
max_value ^ i
|
||||
}
|
||||
|
||||
|
|
@ -74,11 +61,11 @@ impl T : Eq {
|
|||
}
|
||||
|
||||
impl T: num::Num {
|
||||
pure fn add(&&other: T) -> T { return self + other; }
|
||||
pure fn sub(&&other: T) -> T { return self - other; }
|
||||
pure fn mul(&&other: T) -> T { return self * other; }
|
||||
pure fn div(&&other: T) -> T { return self / other; }
|
||||
pure fn modulo(&&other: T) -> T { return self % other; }
|
||||
pure fn add(other: &T) -> T { return self + *other; }
|
||||
pure fn sub(other: &T) -> T { return self - *other; }
|
||||
pure fn mul(other: &T) -> T { return self * *other; }
|
||||
pure fn div(other: &T) -> T { return self / *other; }
|
||||
pure fn modulo(other: &T) -> T { return self % *other; }
|
||||
pure fn neg() -> T { return -self; }
|
||||
|
||||
pure fn to_int() -> int { return self as int; }
|
||||
|
|
@ -126,7 +113,7 @@ impl T: iter::TimesIx {
|
|||
*
|
||||
* `buf` must not be empty
|
||||
*/
|
||||
fn parse_bytes(buf: &[const u8], radix: uint) -> Option<T> {
|
||||
pub fn parse_bytes(buf: &[const u8], radix: uint) -> Option<T> {
|
||||
if vec::len(buf) == 0u { return None; }
|
||||
let mut i = vec::len(buf) - 1u;
|
||||
let mut power = 1u as T;
|
||||
|
|
@ -143,14 +130,14 @@ fn parse_bytes(buf: &[const u8], radix: uint) -> Option<T> {
|
|||
}
|
||||
|
||||
/// Parse a string to an int
|
||||
fn from_str(s: &str) -> Option<T> { parse_bytes(str::to_bytes(s), 10u) }
|
||||
pub fn from_str(s: &str) -> Option<T> { parse_bytes(str::to_bytes(s), 10u) }
|
||||
|
||||
impl T : FromStr {
|
||||
static fn from_str(s: &str) -> Option<T> { from_str(s) }
|
||||
}
|
||||
|
||||
/// Parse a string as an unsigned integer.
|
||||
fn from_str_radix(buf: &str, radix: u64) -> Option<u64> {
|
||||
pub fn from_str_radix(buf: &str, radix: u64) -> Option<u64> {
|
||||
if str::len(buf) == 0u { return None; }
|
||||
let mut i = str::len(buf) - 1u;
|
||||
let mut power = 1u64, n = 0u64;
|
||||
|
|
@ -172,7 +159,7 @@ fn from_str_radix(buf: &str, radix: u64) -> Option<u64> {
|
|||
*
|
||||
* Fails if `radix` < 2 or `radix` > 16
|
||||
*/
|
||||
pure fn to_str(num: T, radix: uint) -> ~str {
|
||||
pub pure fn to_str(num: T, radix: uint) -> ~str {
|
||||
do to_str_bytes(false, num, radix) |slice| {
|
||||
do vec::as_imm_buf(slice) |p, len| {
|
||||
unsafe { str::raw::from_buf_len(p, len) }
|
||||
|
|
@ -181,7 +168,7 @@ pure fn to_str(num: T, radix: uint) -> ~str {
|
|||
}
|
||||
|
||||
/// Low-level helper routine for string conversion.
|
||||
pure fn to_str_bytes<U>(neg: bool, num: T, radix: uint,
|
||||
pub pure fn to_str_bytes<U>(neg: bool, num: T, radix: uint,
|
||||
f: fn(v: &[u8]) -> U) -> U {
|
||||
|
||||
#[inline(always)]
|
||||
|
|
@ -239,17 +226,16 @@ pure fn to_str_bytes<U>(neg: bool, num: T, radix: uint,
|
|||
*ptr::mut_offset(mp, i) = '-' as u8;
|
||||
}
|
||||
|
||||
vec::raw::form_slice(ptr::offset(p, i),
|
||||
len - i, f)
|
||||
vec::raw::buf_as_slice(ptr::offset(p, i), len - i, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert to a string
|
||||
fn str(i: T) -> ~str { return to_str(i, 10u); }
|
||||
pub fn str(i: T) -> ~str { return to_str(i, 10u); }
|
||||
|
||||
#[test]
|
||||
fn test_to_str() {
|
||||
pub fn test_to_str() {
|
||||
assert to_str(0 as T, 10u) == ~"0";
|
||||
assert to_str(1 as T, 10u) == ~"1";
|
||||
assert to_str(2 as T, 10u) == ~"2";
|
||||
|
|
@ -261,7 +247,7 @@ fn test_to_str() {
|
|||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn test_from_str() {
|
||||
pub fn test_from_str() {
|
||||
assert from_str(~"0") == Some(0u as T);
|
||||
assert from_str(~"3") == Some(3u as T);
|
||||
assert from_str(~"10") == Some(10u as T);
|
||||
|
|
@ -275,7 +261,7 @@ fn test_from_str() {
|
|||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn test_parse_bytes() {
|
||||
pub fn test_parse_bytes() {
|
||||
use str::to_bytes;
|
||||
assert parse_bytes(to_bytes(~"123"), 10u) == Some(123u as T);
|
||||
assert parse_bytes(to_bytes(~"1001"), 2u) == Some(9u as T);
|
||||
|
|
@ -291,19 +277,19 @@ fn test_parse_bytes() {
|
|||
#[test]
|
||||
#[should_fail]
|
||||
#[ignore(cfg(windows))]
|
||||
fn to_str_radix1() {
|
||||
pub fn to_str_radix1() {
|
||||
uint::to_str(100u, 1u);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_fail]
|
||||
#[ignore(cfg(windows))]
|
||||
fn to_str_radix17() {
|
||||
pub fn to_str_radix17() {
|
||||
uint::to_str(100u, 17u);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_times() {
|
||||
pub fn test_times() {
|
||||
use iter::Times;
|
||||
let ten = 10 as T;
|
||||
let mut accum = 0;
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
type T = u16;
|
||||
const bits: uint = 16;
|
||||
pub type T = u16;
|
||||
pub const bits: uint = 16;
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
type T = u32;
|
||||
const bits: uint = 32;
|
||||
pub type T = u32;
|
||||
pub const bits: uint = 32;
|
||||
|
|
@ -1,2 +1,2 @@
|
|||
type T = u64;
|
||||
const bits: uint = 64;
|
||||
pub type T = u64;
|
||||
pub const bits: uint = 64;
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
type T = u8;
|
||||
const bits: uint = 8;
|
||||
pub type T = u8;
|
||||
pub const bits: uint = 8;
|
||||
|
||||
// Type-specific functions here. These must be reexported by the
|
||||
// parent module so that they appear in core::u8 and not core::u8::u8;
|
||||
|
||||
pure fn is_ascii(x: T) -> bool { return 0 as T == x & 128 as T; }
|
||||
pub pure fn is_ascii(x: T) -> bool { return 0 as T == x & 128 as T; }
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
type T = uint;
|
||||
pub type T = uint;
|
||||
|
||||
#[cfg(target_arch = "x86")]
|
||||
#[cfg(target_arch = "arm")]
|
||||
const bits: uint = 32;
|
||||
pub const bits: uint = 32;
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
const bits: uint = 64;
|
||||
pub const bits: uint = 64;
|
||||
|
||||
/**
|
||||
* Divide two numbers, return the result, rounded up.
|
||||
|
|
@ -19,7 +19,7 @@ const bits: uint = 64;
|
|||
*
|
||||
* The smallest integer `q` such that `x/y <= q`.
|
||||
*/
|
||||
pure fn div_ceil(x: uint, y: uint) -> uint {
|
||||
pub pure fn div_ceil(x: uint, y: uint) -> uint {
|
||||
let div = x / y;
|
||||
if x % y == 0u { div }
|
||||
else { div + 1u }
|
||||
|
|
@ -37,7 +37,7 @@ pure fn div_ceil(x: uint, y: uint) -> uint {
|
|||
*
|
||||
* The integer `q` closest to `x/y`.
|
||||
*/
|
||||
pure fn div_round(x: uint, y: uint) -> uint {
|
||||
pub pure fn div_round(x: uint, y: uint) -> uint {
|
||||
let div = x / y;
|
||||
if x % y * 2u < y { div }
|
||||
else { div + 1u }
|
||||
|
|
@ -58,7 +58,7 @@ pure fn div_round(x: uint, y: uint) -> uint {
|
|||
* The smallest integer `q` such that `x/y <= q`. This
|
||||
* is either `x/y` or `x/y + 1`.
|
||||
*/
|
||||
pure fn div_floor(x: uint, y: uint) -> uint { return x / y; }
|
||||
pub pure fn div_floor(x: uint, y: uint) -> uint { return x / y; }
|
||||
|
||||
/**
|
||||
* Iterate over the range [`lo`..`hi`), or stop when requested
|
||||
|
|
@ -75,7 +75,7 @@ pure fn div_floor(x: uint, y: uint) -> uint { return x / y; }
|
|||
* `true` If execution proceeded correctly, `false` if it was interrupted,
|
||||
* that is if `it` returned `false` at any point.
|
||||
*/
|
||||
pure fn iterate(lo: uint, hi: uint, it: fn(uint) -> bool) -> bool {
|
||||
pub pure fn iterate(lo: uint, hi: uint, it: fn(uint) -> bool) -> bool {
|
||||
let mut i = lo;
|
||||
while i < hi {
|
||||
if (!it(i)) { return false; }
|
||||
|
|
@ -86,7 +86,7 @@ pure fn iterate(lo: uint, hi: uint, it: fn(uint) -> bool) -> bool {
|
|||
|
||||
/// Returns the smallest power of 2 greater than or equal to `n`
|
||||
#[inline(always)]
|
||||
fn next_power_of_two(n: uint) -> uint {
|
||||
pub fn next_power_of_two(n: uint) -> uint {
|
||||
let halfbits: uint = sys::size_of::<uint>() * 4u;
|
||||
let mut tmp: uint = n - 1u;
|
||||
let mut shift: uint = 1u;
|
||||
|
|
|
|||
|
|
@ -3,9 +3,8 @@
|
|||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
mod general_category {
|
||||
#[legacy_exports];
|
||||
pure fn Cc(c: char) -> bool {
|
||||
pub mod general_category {
|
||||
pub pure fn Cc(c: char) -> bool {
|
||||
return match c {
|
||||
'\x00' .. '\x1f'
|
||||
| '\x7f' .. '\x9f' => true,
|
||||
|
|
@ -13,7 +12,7 @@ mod general_category {
|
|||
};
|
||||
}
|
||||
|
||||
pure fn Cf(c: char) -> bool {
|
||||
pub pure fn Cf(c: char) -> bool {
|
||||
return match c {
|
||||
'\xad'
|
||||
| '\u0600' .. '\u0603'
|
||||
|
|
@ -32,21 +31,21 @@ mod general_category {
|
|||
};
|
||||
}
|
||||
|
||||
pure fn Co(c: char) -> bool {
|
||||
pub pure fn Co(c: char) -> bool {
|
||||
return match c {
|
||||
'\ue000' .. '\uf8ff' => true,
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
|
||||
pure fn Cs(c: char) -> bool {
|
||||
pub pure fn Cs(c: char) -> bool {
|
||||
return match c {
|
||||
'\ud800' .. '\udfff' => true,
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
|
||||
pure fn Ll(c: char) -> bool {
|
||||
pub pure fn Ll(c: char) -> bool {
|
||||
return match c {
|
||||
'\x61' .. '\x7a'
|
||||
| '\xaa'
|
||||
|
|
@ -651,7 +650,7 @@ mod general_category {
|
|||
};
|
||||
}
|
||||
|
||||
pure fn Lm(c: char) -> bool {
|
||||
pub pure fn Lm(c: char) -> bool {
|
||||
return match c {
|
||||
'\u02b0' .. '\u02c1'
|
||||
| '\u02c6' .. '\u02d1'
|
||||
|
|
@ -707,7 +706,7 @@ mod general_category {
|
|||
};
|
||||
}
|
||||
|
||||
pure fn Lo(c: char) -> bool {
|
||||
pub pure fn Lo(c: char) -> bool {
|
||||
return match c {
|
||||
'\u01bb'
|
||||
| '\u01c0' .. '\u01c3'
|
||||
|
|
@ -893,7 +892,7 @@ mod general_category {
|
|||
};
|
||||
}
|
||||
|
||||
pure fn Lt(c: char) -> bool {
|
||||
pub pure fn Lt(c: char) -> bool {
|
||||
return match c {
|
||||
'\u01c5'
|
||||
| '\u01c8'
|
||||
|
|
@ -910,7 +909,7 @@ mod general_category {
|
|||
};
|
||||
}
|
||||
|
||||
pure fn Lu(c: char) -> bool {
|
||||
pub pure fn Lu(c: char) -> bool {
|
||||
return match c {
|
||||
'\x41' .. '\x5a'
|
||||
| '\xc0' .. '\xd6'
|
||||
|
|
@ -1502,7 +1501,7 @@ mod general_category {
|
|||
};
|
||||
}
|
||||
|
||||
pure fn Mc(c: char) -> bool {
|
||||
pub pure fn Mc(c: char) -> bool {
|
||||
return match c {
|
||||
'\u0903'
|
||||
| '\u093b'
|
||||
|
|
@ -1613,7 +1612,7 @@ mod general_category {
|
|||
};
|
||||
}
|
||||
|
||||
pure fn Me(c: char) -> bool {
|
||||
pub pure fn Me(c: char) -> bool {
|
||||
return match c {
|
||||
'\u0488' .. '\u0489'
|
||||
| '\u20dd' .. '\u20e0'
|
||||
|
|
@ -1624,7 +1623,7 @@ mod general_category {
|
|||
};
|
||||
}
|
||||
|
||||
pure fn Mn(c: char) -> bool {
|
||||
pub pure fn Mn(c: char) -> bool {
|
||||
return match c {
|
||||
'\u0300' .. '\u036f'
|
||||
| '\u0483' .. '\u0487'
|
||||
|
|
@ -1817,7 +1816,7 @@ mod general_category {
|
|||
};
|
||||
}
|
||||
|
||||
pure fn Nd(c: char) -> bool {
|
||||
pub pure fn Nd(c: char) -> bool {
|
||||
return match c {
|
||||
'\x30' .. '\x39'
|
||||
| '\u0660' .. '\u0669'
|
||||
|
|
@ -1861,7 +1860,7 @@ mod general_category {
|
|||
};
|
||||
}
|
||||
|
||||
pure fn Nl(c: char) -> bool {
|
||||
pub pure fn Nl(c: char) -> bool {
|
||||
return match c {
|
||||
'\u16ee' .. '\u16f0'
|
||||
| '\u2160' .. '\u2182'
|
||||
|
|
@ -1880,7 +1879,7 @@ mod general_category {
|
|||
};
|
||||
}
|
||||
|
||||
pure fn No(c: char) -> bool {
|
||||
pub pure fn No(c: char) -> bool {
|
||||
return match c {
|
||||
'\xb2' .. '\xb3'
|
||||
| '\xb9'
|
||||
|
|
@ -1928,7 +1927,7 @@ mod general_category {
|
|||
};
|
||||
}
|
||||
|
||||
pure fn Pc(c: char) -> bool {
|
||||
pub pure fn Pc(c: char) -> bool {
|
||||
return match c {
|
||||
'\x5f'
|
||||
| '\u203f' .. '\u2040'
|
||||
|
|
@ -1941,7 +1940,7 @@ mod general_category {
|
|||
};
|
||||
}
|
||||
|
||||
pure fn Pd(c: char) -> bool {
|
||||
pub pure fn Pd(c: char) -> bool {
|
||||
return match c {
|
||||
'\x2d'
|
||||
| '\u058a'
|
||||
|
|
@ -1963,7 +1962,7 @@ mod general_category {
|
|||
};
|
||||
}
|
||||
|
||||
pure fn Pe(c: char) -> bool {
|
||||
pub pure fn Pe(c: char) -> bool {
|
||||
return match c {
|
||||
'\x29'
|
||||
| '\x5d'
|
||||
|
|
@ -2040,7 +2039,7 @@ mod general_category {
|
|||
};
|
||||
}
|
||||
|
||||
pure fn Pf(c: char) -> bool {
|
||||
pub pure fn Pf(c: char) -> bool {
|
||||
return match c {
|
||||
'\xbb'
|
||||
| '\u2019'
|
||||
|
|
@ -2057,7 +2056,7 @@ mod general_category {
|
|||
};
|
||||
}
|
||||
|
||||
pure fn Pi(c: char) -> bool {
|
||||
pub pure fn Pi(c: char) -> bool {
|
||||
return match c {
|
||||
'\xab'
|
||||
| '\u2018'
|
||||
|
|
@ -2075,7 +2074,7 @@ mod general_category {
|
|||
};
|
||||
}
|
||||
|
||||
pure fn Po(c: char) -> bool {
|
||||
pub pure fn Po(c: char) -> bool {
|
||||
return match c {
|
||||
'\x21' .. '\x23'
|
||||
| '\x25' .. '\x27'
|
||||
|
|
@ -2208,7 +2207,7 @@ mod general_category {
|
|||
};
|
||||
}
|
||||
|
||||
pure fn Ps(c: char) -> bool {
|
||||
pub pure fn Ps(c: char) -> bool {
|
||||
return match c {
|
||||
'\x28'
|
||||
| '\x5b'
|
||||
|
|
@ -2287,7 +2286,7 @@ mod general_category {
|
|||
};
|
||||
}
|
||||
|
||||
pure fn Sc(c: char) -> bool {
|
||||
pub pure fn Sc(c: char) -> bool {
|
||||
return match c {
|
||||
'\x24'
|
||||
| '\xa2' .. '\xa5'
|
||||
|
|
@ -2310,7 +2309,7 @@ mod general_category {
|
|||
};
|
||||
}
|
||||
|
||||
pure fn Sk(c: char) -> bool {
|
||||
pub pure fn Sk(c: char) -> bool {
|
||||
return match c {
|
||||
'\x5e'
|
||||
| '\x60'
|
||||
|
|
@ -2344,7 +2343,7 @@ mod general_category {
|
|||
};
|
||||
}
|
||||
|
||||
pure fn Sm(c: char) -> bool {
|
||||
pub pure fn Sm(c: char) -> bool {
|
||||
return match c {
|
||||
'\x2b'
|
||||
| '\x3c' .. '\x3e'
|
||||
|
|
@ -2415,7 +2414,7 @@ mod general_category {
|
|||
};
|
||||
}
|
||||
|
||||
pure fn So(c: char) -> bool {
|
||||
pub pure fn So(c: char) -> bool {
|
||||
return match c {
|
||||
'\xa6' .. '\xa7'
|
||||
| '\xa9'
|
||||
|
|
@ -2534,21 +2533,21 @@ mod general_category {
|
|||
};
|
||||
}
|
||||
|
||||
pure fn Zl(c: char) -> bool {
|
||||
pub pure fn Zl(c: char) -> bool {
|
||||
return match c {
|
||||
'\u2028' => true,
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
|
||||
pure fn Zp(c: char) -> bool {
|
||||
pub pure fn Zp(c: char) -> bool {
|
||||
return match c {
|
||||
'\u2029' => true,
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
|
||||
pure fn Zs(c: char) -> bool {
|
||||
pub pure fn Zs(c: char) -> bool {
|
||||
return match c {
|
||||
'\x20'
|
||||
| '\xa0'
|
||||
|
|
@ -2567,7 +2566,7 @@ mod general_category {
|
|||
mod derived_property {
|
||||
#[legacy_exports];
|
||||
/// Check if a character has the alphabetic unicode property
|
||||
pure fn Alphabetic(c: char) -> bool {
|
||||
pub pure fn Alphabetic(c: char) -> bool {
|
||||
return match c {
|
||||
'\x41' .. '\x5a'
|
||||
| '\x61' .. '\x7a'
|
||||
|
|
@ -3305,7 +3304,7 @@ mod derived_property {
|
|||
};
|
||||
}
|
||||
|
||||
pure fn XID_Continue(c: char) -> bool {
|
||||
pub pure fn XID_Continue(c: char) -> bool {
|
||||
return match c {
|
||||
'\x30' .. '\x39'
|
||||
| '\x41' .. '\x5a'
|
||||
|
|
@ -4176,7 +4175,7 @@ mod derived_property {
|
|||
};
|
||||
}
|
||||
|
||||
pure fn XID_Start(c: char) -> bool {
|
||||
pub pure fn XID_Start(c: char) -> bool {
|
||||
return match c {
|
||||
'\x41' .. '\x5a'
|
||||
| '\x61' .. '\x7a'
|
||||
|
|
|
|||
|
|
@ -5,25 +5,25 @@ Miscellaneous helpers for common patterns.
|
|||
*/
|
||||
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
// tjc: re-forbid deprecated modes after snapshot
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
use cmp::Eq;
|
||||
|
||||
/// The identity function.
|
||||
#[inline(always)]
|
||||
pure fn id<T>(+x: T) -> T { move x }
|
||||
pub pure fn id<T>(x: T) -> T { move x }
|
||||
|
||||
/// Ignores a value.
|
||||
#[inline(always)]
|
||||
pure fn ignore<T>(+_x: T) { }
|
||||
pub pure fn ignore<T>(_x: T) { }
|
||||
|
||||
/// Sets `*ptr` to `new_value`, invokes `op()`, and then restores the
|
||||
/// original value of `*ptr`.
|
||||
#[inline(always)]
|
||||
fn with<T: Copy, R>(
|
||||
pub fn with<T: Copy, R>(
|
||||
ptr: &mut T,
|
||||
+new_value: T,
|
||||
new_value: T,
|
||||
op: &fn() -> R) -> R
|
||||
{
|
||||
// NDM: if swap operator were defined somewhat differently,
|
||||
|
|
@ -41,7 +41,7 @@ fn with<T: Copy, R>(
|
|||
* deinitialising or copying either one.
|
||||
*/
|
||||
#[inline(always)]
|
||||
fn swap<T>(x: &mut T, y: &mut T) {
|
||||
pub fn swap<T>(x: &mut T, y: &mut T) {
|
||||
*x <-> *y;
|
||||
}
|
||||
|
||||
|
|
@ -50,19 +50,19 @@ fn swap<T>(x: &mut T, y: &mut T) {
|
|||
* value, without deinitialising or copying either one.
|
||||
*/
|
||||
#[inline(always)]
|
||||
fn replace<T>(dest: &mut T, +src: T) -> T {
|
||||
pub fn replace<T>(dest: &mut T, src: T) -> T {
|
||||
let mut tmp <- src;
|
||||
swap(dest, &mut tmp);
|
||||
move tmp
|
||||
}
|
||||
|
||||
/// A non-copyable dummy type.
|
||||
struct NonCopyable {
|
||||
pub struct NonCopyable {
|
||||
i: (),
|
||||
drop { }
|
||||
}
|
||||
|
||||
fn NonCopyable() -> NonCopyable { NonCopyable { i: () } }
|
||||
pub fn NonCopyable() -> NonCopyable { NonCopyable { i: () } }
|
||||
|
||||
/**
|
||||
A utility function for indicating unreachable code. It will fail if
|
||||
|
|
@ -88,7 +88,7 @@ fn choose_weighted_item(v: &[Item]) -> Item {
|
|||
~~~
|
||||
|
||||
*/
|
||||
fn unreachable() -> ! {
|
||||
pub fn unreachable() -> ! {
|
||||
fail ~"internal error: entered unreachable code";
|
||||
}
|
||||
|
||||
|
|
|
|||
1562
src/libcore/vec.rs
1562
src/libcore/vec.rs
File diff suppressed because it is too large
Load diff
|
|
@ -1,6 +1,5 @@
|
|||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
// tjc: forbid deprecated modes again after snap
|
||||
/**
|
||||
* Concurrency-enabled mechanisms for sharing mutable and/or immutable state
|
||||
* between tasks.
|
||||
|
|
@ -12,14 +11,9 @@ use private::{SharedMutableState, shared_mutable_state,
|
|||
use sync::{Mutex, mutex_with_condvars,
|
||||
RWlock, rwlock_with_condvars};
|
||||
|
||||
export ARC, clone, get;
|
||||
export Condvar;
|
||||
export MutexARC, mutex_arc_with_condvars, unwrap_mutex_arc;
|
||||
export RWARC, rw_arc_with_condvars, RWWriteMode, RWReadMode;
|
||||
export unwrap_rw_arc;
|
||||
|
||||
/// As sync::condvar, a mechanism for unlock-and-descheduling and signalling.
|
||||
struct Condvar { is_mutex: bool, failed: &mut bool, cond: &sync::Condvar }
|
||||
pub struct Condvar { is_mutex: bool, failed: &mut bool, cond: &sync::Condvar }
|
||||
|
||||
impl &Condvar {
|
||||
/// Atomically exit the associated ARC and block until a signal is sent.
|
||||
|
|
@ -72,7 +66,7 @@ impl &Condvar {
|
|||
struct ARC<T: Const Send> { x: SharedMutableState<T> }
|
||||
|
||||
/// Create an atomically reference counted wrapper.
|
||||
fn ARC<T: Const Send>(+data: T) -> ARC<T> {
|
||||
pub fn ARC<T: Const Send>(data: T) -> ARC<T> {
|
||||
ARC { x: unsafe { shared_mutable_state(move data) } }
|
||||
}
|
||||
|
||||
|
|
@ -80,7 +74,7 @@ fn ARC<T: Const Send>(+data: T) -> ARC<T> {
|
|||
* Access the underlying data in an atomically reference counted
|
||||
* wrapper.
|
||||
*/
|
||||
fn get<T: Const Send>(rc: &a/ARC<T>) -> &a/T {
|
||||
pub fn get<T: Const Send>(rc: &a/ARC<T>) -> &a/T {
|
||||
unsafe { get_shared_immutable_state(&rc.x) }
|
||||
}
|
||||
|
||||
|
|
@ -91,7 +85,7 @@ fn get<T: Const Send>(rc: &a/ARC<T>) -> &a/T {
|
|||
* object. However, one of the `arc` objects can be sent to another task,
|
||||
* allowing them to share the underlying data.
|
||||
*/
|
||||
fn clone<T: Const Send>(rc: &ARC<T>) -> ARC<T> {
|
||||
pub fn clone<T: Const Send>(rc: &ARC<T>) -> ARC<T> {
|
||||
ARC { x: unsafe { clone_shared_mutable_state(&rc.x) } }
|
||||
}
|
||||
|
||||
|
|
@ -104,7 +98,7 @@ fn clone<T: Const Send>(rc: &ARC<T>) -> ARC<T> {
|
|||
* unwrap from a task that holds another reference to the same ARC; it is
|
||||
* guaranteed to deadlock.
|
||||
*/
|
||||
fn unwrap<T: Const Send>(+rc: ARC<T>) -> T {
|
||||
fn unwrap<T: Const Send>(rc: ARC<T>) -> T {
|
||||
let ARC { x: x } <- rc;
|
||||
unsafe { unwrap_shared_mutable_state(move x) }
|
||||
}
|
||||
|
|
@ -119,14 +113,14 @@ struct MutexARCInner<T: Send> { lock: Mutex, failed: bool, data: T }
|
|||
struct MutexARC<T: Send> { x: SharedMutableState<MutexARCInner<T>> }
|
||||
|
||||
/// Create a mutex-protected ARC with the supplied data.
|
||||
fn MutexARC<T: Send>(+user_data: T) -> MutexARC<T> {
|
||||
pub fn MutexARC<T: Send>(user_data: T) -> MutexARC<T> {
|
||||
mutex_arc_with_condvars(move user_data, 1)
|
||||
}
|
||||
/**
|
||||
* Create a mutex-protected ARC with the supplied data and a specified number
|
||||
* of condvars (as sync::mutex_with_condvars).
|
||||
*/
|
||||
fn mutex_arc_with_condvars<T: Send>(+user_data: T,
|
||||
pub fn mutex_arc_with_condvars<T: Send>(user_data: T,
|
||||
num_condvars: uint) -> MutexARC<T> {
|
||||
let data =
|
||||
MutexARCInner { lock: mutex_with_condvars(num_condvars),
|
||||
|
|
@ -197,7 +191,7 @@ impl<T: Send> &MutexARC<T> {
|
|||
* Will additionally fail if another task has failed while accessing the arc.
|
||||
*/
|
||||
// FIXME(#2585) make this a by-move method on the arc
|
||||
fn unwrap_mutex_arc<T: Send>(+arc: MutexARC<T>) -> T {
|
||||
pub fn unwrap_mutex_arc<T: Send>(arc: MutexARC<T>) -> T {
|
||||
let MutexARC { x: x } <- arc;
|
||||
let inner = unsafe { unwrap_shared_mutable_state(move x) };
|
||||
let MutexARCInner { failed: failed, data: data, _ } <- inner;
|
||||
|
|
@ -253,14 +247,14 @@ struct RWARC<T: Const Send> {
|
|||
}
|
||||
|
||||
/// Create a reader/writer ARC with the supplied data.
|
||||
fn RWARC<T: Const Send>(+user_data: T) -> RWARC<T> {
|
||||
pub fn RWARC<T: Const Send>(user_data: T) -> RWARC<T> {
|
||||
rw_arc_with_condvars(move user_data, 1)
|
||||
}
|
||||
/**
|
||||
* Create a reader/writer ARC with the supplied data and a specified number
|
||||
* of condvars (as sync::rwlock_with_condvars).
|
||||
*/
|
||||
fn rw_arc_with_condvars<T: Const Send>(+user_data: T,
|
||||
pub fn rw_arc_with_condvars<T: Const Send>(user_data: T,
|
||||
num_condvars: uint) -> RWARC<T> {
|
||||
let data =
|
||||
RWARCInner { lock: rwlock_with_condvars(num_condvars),
|
||||
|
|
@ -340,7 +334,7 @@ impl<T: Const Send> &RWARC<T> {
|
|||
* }
|
||||
* ~~~
|
||||
*/
|
||||
fn write_downgrade<U>(blk: fn(+v: RWWriteMode<T>) -> U) -> U {
|
||||
fn write_downgrade<U>(blk: fn(v: RWWriteMode<T>) -> U) -> U {
|
||||
let state = unsafe { get_shared_mutable_state(&self.x) };
|
||||
do borrow_rwlock(state).write_downgrade |write_mode| {
|
||||
check_poison(false, state.failed);
|
||||
|
|
@ -350,7 +344,7 @@ impl<T: Const Send> &RWARC<T> {
|
|||
}
|
||||
|
||||
/// To be called inside of the write_downgrade block.
|
||||
fn downgrade(+token: RWWriteMode/&a<T>) -> RWReadMode/&a<T> {
|
||||
fn downgrade(token: RWWriteMode/&a<T>) -> RWReadMode/&a<T> {
|
||||
// The rwlock should assert that the token belongs to us for us.
|
||||
let state = unsafe { get_shared_immutable_state(&self.x) };
|
||||
let RWWriteMode((data, t, _poison)) <- token;
|
||||
|
|
@ -375,7 +369,7 @@ impl<T: Const Send> &RWARC<T> {
|
|||
* in write mode.
|
||||
*/
|
||||
// FIXME(#2585) make this a by-move method on the arc
|
||||
fn unwrap_rw_arc<T: Const Send>(+arc: RWARC<T>) -> T {
|
||||
pub fn unwrap_rw_arc<T: Const Send>(arc: RWARC<T>) -> T {
|
||||
let RWARC { x: x, _ } <- arc;
|
||||
let inner = unsafe { unwrap_shared_mutable_state(move x) };
|
||||
let RWARCInner { failed: failed, data: data, _ } <- inner;
|
||||
|
|
@ -396,10 +390,10 @@ fn borrow_rwlock<T: Const Send>(state: &r/mut RWARCInner<T>) -> &r/RWlock {
|
|||
// FIXME (#3154) ice with struct/&<T> prevents these from being structs.
|
||||
|
||||
/// The "write permission" token used for RWARC.write_downgrade().
|
||||
enum RWWriteMode<T: Const Send> =
|
||||
pub enum RWWriteMode<T: Const Send> =
|
||||
(&mut T, sync::RWlockWriteMode, PoisonOnFail);
|
||||
/// The "read permission" token used for RWARC.write_downgrade().
|
||||
enum RWReadMode<T:Const Send> = (&T, sync::RWlockReadMode);
|
||||
pub enum RWReadMode<T:Const Send> = (&T, sync::RWlockReadMode);
|
||||
|
||||
impl<T: Const Send> &RWWriteMode<T> {
|
||||
/// Access the pre-downgrade RWARC in write mode.
|
||||
|
|
@ -648,7 +642,7 @@ mod tests {
|
|||
let mut children = ~[];
|
||||
for 5.times {
|
||||
let arc3 = ~arc.clone();
|
||||
do task::task().future_result(|+r| vec::push(children, r)).spawn {
|
||||
do task::task().future_result(|+r| children.push(r)).spawn {
|
||||
do arc3.read |num| {
|
||||
assert *num >= 0;
|
||||
}
|
||||
|
|
@ -676,7 +670,7 @@ mod tests {
|
|||
let mut reader_convos = ~[];
|
||||
for 10.times {
|
||||
let ((rc1,rp1),(rc2,rp2)) = (pipes::stream(),pipes::stream());
|
||||
vec::push(reader_convos, (rc1,rp2));
|
||||
reader_convos.push((rc1,rp2));
|
||||
let arcn = ~arc.clone();
|
||||
do task::spawn {
|
||||
rp1.recv(); // wait for downgrader to give go-ahead
|
||||
|
|
@ -719,7 +713,7 @@ mod tests {
|
|||
// send to other readers
|
||||
for vec::each(reader_convos) |x| {
|
||||
match *x {
|
||||
(rc, _) => rc.send(()),
|
||||
(ref rc, _) => rc.send(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -728,7 +722,7 @@ mod tests {
|
|||
// complete handshake with other readers
|
||||
for vec::each(reader_convos) |x| {
|
||||
match *x {
|
||||
(_, rp) => rp.recv(),
|
||||
(_, ref rp) => rp.recv(),
|
||||
}
|
||||
}
|
||||
wc1.send(()); // tell writer to try again
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue