This commit is contained in:
Tim Chevalier 2012-06-06 22:30:52 -07:00
commit cd02046de4
76 changed files with 749 additions and 574 deletions

View file

@ -421,9 +421,9 @@ else
TSREQS := \
$(foreach target,$(CFG_TARGET_TRIPLES), \
$(SREQ3_T_$(target)_H_$(CFG_HOST_TRIPLE)))
FUZZ := $(HBIN3_H_$(CFG_HOST_TRIPLE))/fuzzer$(X)
CARGO := $(HBIN3_H_$(CFG_HOST_TRIPLE))/cargo$(X)
RUSTDOC := $(HBIN3_H_$(CFG_HOST_TRIPLE))/rustdoc$(X)
FUZZ := $(HBIN2_H_$(CFG_HOST_TRIPLE))/fuzzer$(X)
CARGO := $(HBIN2_H_$(CFG_HOST_TRIPLE))/cargo$(X)
RUSTDOC := $(HBIN2_H_$(CFG_HOST_TRIPLE))/rustdoc$(X)
all: rustc $(GENERATED) docs $(FUZZ) $(CARGO) $(RUSTDOC)

View file

@ -332,7 +332,7 @@ fn try_parse_sources(filename: str, sources: map::hashmap<str, source>) {
}
}
fn load_one_source_package(&src: source, p: map::hashmap<str, json::json>) {
fn load_one_source_package(&&src: source, p: map::hashmap<str, json::json>) {
let name = alt p.find("name") {
some(json::string(_n)) { _n }
_ {
@ -404,8 +404,8 @@ fn load_one_source_package(&src: source, p: map::hashmap<str, json::json>) {
log(debug, " loaded package: " + src.name + "/" + name);
}
fn load_source_packages(&c: cargo, &src: source) {
log(debug, "loading source: " + src.name);
fn load_source_packages(&&c: cargo, &&src: source) {
log(debug, "Loading source: " + src.name);
let dir = path::connect(c.sourcedir, src.name);
let pkgfile = path::connect(dir, "packages.json");
if !os::path_exists(pkgfile) { ret; }

10
src/libcore/cmp.rs Normal file
View file

@ -0,0 +1,10 @@
#[doc="Interfaces used for comparison."]
iface ord {
fn lt(&&other: self) -> bool;
}
iface eq {
fn eq(&&other: self) -> bool;
}

View file

@ -44,6 +44,7 @@ export extfmt;
export tuple;
export to_str;
export dvec, dvec_iter;
export cmp;
// NDM seems to be necessary for resolve to work
export option_iter;
@ -152,6 +153,7 @@ mod tuple;
// Ubiquitous-utility-type modules
mod cmp;
mod either;
mod iter;
mod logging;

View file

@ -57,6 +57,11 @@ fn dvec<A>() -> dvec<A> {
{mut data: [mut]}
}
#[doc = "Creates a new dvec with a single element"]
fn from_elt<A>(+e: A) -> dvec<A> {
{mut data: [mut e]}
}
#[doc = "Creates a new dvec with the contents of a vector"]
fn from_vec<A>(+v: [mut A]) -> dvec<A> {
{mut data: v}
@ -234,7 +239,9 @@ impl extensions<A:copy> for dvec<A> {
self.data[idx] = a;
}
#[doc = "Overwrites the contents of the element at `idx` with `a`"]
#[doc = "Overwrites the contents of the element at `idx` with `a`,
growing the vector if necessary. New elements will be initialized
with `initval`"]
fn grow_set_elt(idx: uint, initval: A, val: A) {
self.swap { |v|
let mut v <- v;
@ -242,4 +249,9 @@ impl extensions<A:copy> for dvec<A> {
v
}
}
#[doc = "Returns the last element, failing if the vector is empty"]
fn last() -> A {
self.get_elt(self.len() - 1u)
}
}

View file

@ -108,7 +108,7 @@ fn get<A:copy>(future: future<A>) -> A {
fn with<A,B>(future: future<A>, blk: fn(A) -> B) -> B {
#[doc = "Work with the value without copying it"];
let v = alt future.v {
let v = alt copy future.v {
either::left(v) { v }
either::right(f) {
let v = @f();

View file

@ -1,4 +1,5 @@
import T = inst::T;
import cmp::{eq, ord};
export min_value, max_value;
export min, max;
@ -10,6 +11,7 @@ export range;
export compl;
export abs;
export parse_buf, from_str, to_str, to_str_bytes, str;
export ord, eq;
const min_value: T = -1 as T << (inst::bits - 1 as T);
const max_value: T = min_value - 1 as T;
@ -108,6 +110,18 @@ fn to_str_bytes<U>(n: T, radix: uint, f: fn([u8]/&) -> U) -> U {
#[doc = "Convert to a string"]
fn str(i: T) -> str { ret to_str(i, 10u); }
impl ord of ord for T {
fn lt(&&other: T) -> bool {
ret self < other;
}
}
impl eq of eq for T {
fn eq(&&other: T) -> bool {
ret self == other;
}
}
// FIXME: Has alignment issues on windows and 32-bit linux
#[test]

View file

@ -613,7 +613,7 @@ impl of writer for mem_buffer {
// FIXME #2004--use memcpy here?
let mut pos = self.pos, vpos = 0u;
while vpos < vlen && pos < buf_len {
self.buf.set_elt(pos, v[vpos]);
self.buf.set_elt(pos, copy v[vpos]);
pos += 1u;
vpos += 1u;
}

View file

@ -218,7 +218,7 @@ impl extensions for rng {
}
#[doc = "Shuffle a mutable vec in place"]
fn shuffle_mut<T>(&values: [mut T]) {
fn shuffle_mut<T>(&&values: [mut T]) {
let mut i = values.len();
while i >= 2u {
// invariant: elements with index >= i have been locked in place.

View file

@ -122,7 +122,7 @@ Convert a vector of bytes to a UTF-8 string
Fails if invalid UTF-8
"]
fn from_bytes(vv: [u8]) -> str unsafe {
pure fn from_bytes(vv: [u8]) -> str unsafe {
assert is_utf8(vv);
ret unsafe::from_bytes(vv);
}
@ -134,7 +134,7 @@ Convert a byte to a UTF-8 string
Fails if invalid UTF-8
"]
fn from_byte(b: u8) -> str unsafe {
pure fn from_byte(b: u8) -> str unsafe {
assert b < 128u8;
let mut v = [b, 0u8];
let s: str = ::unsafe::reinterpret_cast(v);
@ -217,22 +217,24 @@ fn push_char(&s: str, ch: char) unsafe {
}
#[doc = "Convert a char to a string"]
fn from_char(ch: char) -> str {
pure fn from_char(ch: char) -> str {
let mut buf = "";
push_char(buf, ch);
unchecked { push_char(buf, ch); }
ret buf;
}
#[doc = "Convert a vector of chars to a string"]
fn from_chars(chs: [char]) -> str {
pure fn from_chars(chs: [char]) -> str {
let mut buf = "";
reserve(buf, chs.len());
for vec::each(chs) {|ch| push_char(buf, ch); }
unchecked {
reserve(buf, chs.len());
for vec::each(chs) {|ch| push_char(buf, ch); }
}
ret buf;
}
#[doc = "Concatenate a vector of strings"]
fn concat(v: [str]) -> str {
pure fn concat(v: [str]) -> str {
let mut s: str = "";
for vec::each(v) {|ss| s += ss; }
ret s;
@ -241,7 +243,7 @@ fn concat(v: [str]) -> str {
#[doc = "
Concatenate a vector of strings, placing a given separator between each
"]
fn connect(v: [str], sep: str) -> str {
pure fn connect(v: [str], sep: str) -> str {
let mut s = "", first = true;
for vec::each(v) {|ss|
if first { first = false; } else { s += sep; }
@ -286,7 +288,7 @@ fn shift_char(&s: str) -> char unsafe {
fn unshift_char(&s: str, ch: char) { s = from_char(ch) + s; }
#[doc = "Returns a string with leading whitespace removed"]
fn trim_left(+s: str) -> str {
pure fn trim_left(+s: str) -> str {
alt find(s, {|c| !char::is_whitespace(c)}) {
none { "" }
some(first) {
@ -297,7 +299,7 @@ fn trim_left(+s: str) -> str {
}
#[doc = "Returns a string with trailing whitespace removed"]
fn trim_right(+s: str) -> str {
pure fn trim_right(+s: str) -> str {
alt rfind(s, {|c| !char::is_whitespace(c)}) {
none { "" }
some(last) {
@ -309,7 +311,7 @@ fn trim_right(+s: str) -> str {
}
#[doc = "Returns a string with leading and trailing whitespace removed"]
fn trim(+s: str) -> str { trim_left(trim_right(s)) }
pure fn trim(+s: str) -> str { trim_left(trim_right(s)) }
/*
Section: Transforming strings
@ -320,7 +322,7 @@ Converts a string to a vector of bytes
The result vector is not null-terminated.
"]
fn bytes(s: str) -> [u8] unsafe {
pure fn bytes(s: str) -> [u8] unsafe {
let mut s_copy = s;
let mut v: [u8] = ::unsafe::reinterpret_cast(s_copy);
::unsafe::forget(s_copy);
@ -332,14 +334,14 @@ fn bytes(s: str) -> [u8] unsafe {
Work with the string as a byte slice, not including trailing null.
"]
#[inline(always)]
fn byte_slice<T>(s: str/&, f: fn([u8]/&) -> T) -> T unsafe {
pure fn byte_slice<T>(s: str/&, f: fn([u8]/&) -> T) -> T unsafe {
unpack_slice(s) {|p,n|
vec::unsafe::form_slice(p, n-1u, f)
}
}
#[doc = "Convert a string to a vector of characters"]
fn chars(s: str) -> [char] {
pure fn chars(s: str) -> [char] {
let mut buf = [], i = 0u;
let len = len(s);
while i < len {
@ -356,7 +358,7 @@ Take a substring of another.
Returns a string containing `n` characters starting at byte offset
`begin`.
"]
fn substr(s: str, begin: uint, n: uint) -> str {
pure fn substr(s: str, begin: uint, n: uint) -> str {
slice(s, begin, begin + count_bytes(s, begin, n))
}
@ -366,7 +368,7 @@ Returns a slice of the given string from the byte range [`begin`..`end`)
Fails when `begin` and `end` do not point to valid characters or
beyond the last character of the string
"]
fn slice(s: str, begin: uint, end: uint) -> str unsafe {
pure fn slice(s: str, begin: uint, end: uint) -> str unsafe {
assert is_char_boundary(s, begin);
assert is_char_boundary(s, end);
unsafe::slice_bytes(s, begin, end)
@ -375,7 +377,7 @@ fn slice(s: str, begin: uint, end: uint) -> str unsafe {
#[doc = "
Splits a string into substrings at each occurrence of a given character
"]
fn split_char(s: str, sep: char) -> [str] {
pure fn split_char(s: str, sep: char) -> [str] {
split_char_inner(s, sep, len(s), true)
}
@ -385,18 +387,18 @@ character up to 'count' times
The byte must be a valid UTF-8/ASCII byte
"]
fn splitn_char(s: str, sep: char, count: uint) -> [str] {
pure fn splitn_char(s: str, sep: char, count: uint) -> [str] {
split_char_inner(s, sep, count, true)
}
#[doc = "
Like `split_char`, but omits empty strings from the returned vector
"]
fn split_char_nonempty(s: str, sep: char) -> [str] {
pure fn split_char_nonempty(s: str, sep: char) -> [str] {
split_char_inner(s, sep, len(s), false)
}
fn split_char_inner(s: str, sep: char, count: uint, allow_empty: bool)
pure fn split_char_inner(s: str, sep: char, count: uint, allow_empty: bool)
-> [str] unsafe {
if sep < 128u as char {
let b = sep as u8, l = len(s);
@ -423,7 +425,7 @@ fn split_char_inner(s: str, sep: char, count: uint, allow_empty: bool)
#[doc = "Splits a string into substrings using a character function"]
fn split(s: str, sepfn: fn(char) -> bool) -> [str] {
pure fn split(s: str, sepfn: fn(char) -> bool) -> [str] {
split_inner(s, sepfn, len(s), true)
}
@ -431,16 +433,16 @@ fn split(s: str, sepfn: fn(char) -> bool) -> [str] {
Splits a string into substrings using a character function, cutting at
most `count` times.
"]
fn splitn(s: str, sepfn: fn(char) -> bool, count: uint) -> [str] {
pure fn splitn(s: str, sepfn: fn(char) -> bool, count: uint) -> [str] {
split_inner(s, sepfn, count, true)
}
#[doc = "Like `split`, but omits empty strings from the returned vector"]
fn split_nonempty(s: str, sepfn: fn(char) -> bool) -> [str] {
pure fn split_nonempty(s: str, sepfn: fn(char) -> bool) -> [str] {
split_inner(s, sepfn, len(s), false)
}
fn split_inner(s: str, sepfn: fn(cc: char) -> bool, count: uint,
pure fn split_inner(s: str, sepfn: fn(cc: char) -> bool, count: uint,
allow_empty: bool) -> [str] unsafe {
let l = len(s);
let mut result = [], i = 0u, start = 0u, done = 0u;
@ -462,7 +464,7 @@ fn split_inner(s: str, sepfn: fn(cc: char) -> bool, count: uint,
}
// See Issue #1932 for why this is a naive search
fn iter_matches(s: str, sep: str, f: fn(uint, uint)) {
pure fn iter_matches(s: str, sep: str, f: fn(uint, uint)) {
let sep_len = len(sep), l = len(s);
assert sep_len > 0u;
let mut i = 0u, match_start = 0u, match_i = 0u;
@ -489,7 +491,7 @@ fn iter_matches(s: str, sep: str, f: fn(uint, uint)) {
}
}
fn iter_between_matches(s: str, sep: str, f: fn(uint, uint)) {
pure fn iter_between_matches(s: str, sep: str, f: fn(uint, uint)) {
let mut last_end = 0u;
iter_matches(s, sep) {|from, to|
f(last_end, from);
@ -507,7 +509,7 @@ Splits a string into a vector of the substrings separated by a given string
assert [\"\", \"XXX\", \"YYY\", \"\"] == split_str(\".XXX.YYY.\", \".\")
~~~
"]
fn split_str(s: str, sep: str) -> [str] {
pure fn split_str(s: str, sep: str) -> [str] {
let mut result = [];
iter_between_matches(s, sep) {|from, to|
unsafe { result += [unsafe::slice_bytes(s, from, to)]; }
@ -515,7 +517,7 @@ fn split_str(s: str, sep: str) -> [str] {
result
}
fn split_str_nonempty(s: str, sep: str) -> [str] {
pure fn split_str_nonempty(s: str, sep: str) -> [str] {
let mut result = [];
iter_between_matches(s, sep) {|from, to|
if to > from {
@ -528,13 +530,13 @@ fn split_str_nonempty(s: str, sep: str) -> [str] {
#[doc = "
Splits a string into a vector of the substrings separated by LF ('\\n')
"]
fn lines(s: str) -> [str] { split_char(s, '\n') }
pure fn lines(s: str) -> [str] { split_char(s, '\n') }
#[doc = "
Splits a string into a vector of the substrings separated by LF ('\\n')
and/or CR LF ('\\r\\n')
"]
fn lines_any(s: str) -> [str] {
pure fn lines_any(s: str) -> [str] {
vec::map(lines(s), {|s|
let l = len(s);
let mut cp = s;
@ -548,18 +550,22 @@ fn lines_any(s: str) -> [str] {
#[doc = "
Splits a string into a vector of the substrings separated by whitespace
"]
fn words(s: str) -> [str] {
pure fn words(s: str) -> [str] {
split_nonempty(s, {|c| char::is_whitespace(c)})
}
#[doc = "Convert a string to lowercase. ASCII only"]
fn to_lower(s: str) -> str {
map(s, {|c| (libc::tolower(c as libc::c_char)) as char})
pure fn to_lower(s: str) -> str {
map(s, {|c|
unchecked{(libc::tolower(c as libc::c_char)) as char}
})
}
#[doc = "Convert a string to uppercase. ASCII only"]
fn to_upper(s: str) -> str {
map(s, {|c| (libc::toupper(c as libc::c_char)) as char})
pure fn to_upper(s: str) -> str {
map(s, {|c|
unchecked{(libc::toupper(c as libc::c_char)) as char}
})
}
#[doc = "
@ -575,7 +581,7 @@ Replace all occurances of one string with another
The original string with all occurances of `from` replaced with `to`
"]
fn replace(s: str, from: str, to: str) -> str unsafe {
pure fn replace(s: str, from: str, to: str) -> str unsafe {
let mut result = "", first = true;
iter_between_matches(s, from) {|start, end|
if first { first = false; } else { result += to; }
@ -595,7 +601,7 @@ pure fn eq(&&a: str, &&b: str) -> bool { a == b }
pure fn le(&&a: str, &&b: str) -> bool { a <= b }
#[doc = "String hash function"]
fn hash(&&s: str) -> uint {
pure fn hash(&&s: str) -> uint {
// djb hash.
// FIXME: replace with murmur. (see #859 and #1616)
let mut u: uint = 5381u;
@ -611,7 +617,7 @@ Section: Iterating through strings
Return true if a predicate matches all characters or if the string
contains no characters
"]
fn all(s: str, it: fn(char) -> bool) -> bool {
pure fn all(s: str, it: fn(char) -> bool) -> bool {
all_between(s, 0u, len(s), it)
}
@ -619,20 +625,24 @@ fn all(s: str, it: fn(char) -> bool) -> bool {
Return true if a predicate matches any character (and false if it
matches none or there are no characters)
"]
fn any(ss: str, pred: fn(char) -> bool) -> bool {
pure fn any(ss: str, pred: fn(char) -> bool) -> bool {
!all(ss, {|cc| !pred(cc)})
}
#[doc = "Apply a function to each character"]
fn map(ss: str, ff: fn(char) -> char) -> str {
pure fn map(ss: str, ff: fn(char) -> char) -> str {
let mut result = "";
reserve(result, len(ss));
chars_iter(ss) {|cc| str::push_char(result, ff(cc));}
unchecked {
reserve(result, len(ss));
chars_iter(ss) {|cc|
str::push_char(result, ff(cc));
}
}
result
}
#[doc = "Iterate over the bytes in a string"]
fn bytes_iter(ss: str, it: fn(u8)) {
pure fn bytes_iter(ss: str, it: fn(u8)) {
let mut pos = 0u;
let len = len(ss);
@ -644,7 +654,7 @@ fn bytes_iter(ss: str, it: fn(u8)) {
#[doc = "Iterate over the bytes in a string"]
#[inline(always)]
fn each(s: str, it: fn(u8) -> bool) {
pure fn each(s: str, it: fn(u8) -> bool) {
let mut i = 0u, l = len(s);
while (i < l) {
if !it(s[i]) { break; }
@ -654,7 +664,7 @@ fn each(s: str, it: fn(u8) -> bool) {
#[doc = "Iterates over the chars in a string"]
#[inline(always)]
fn each_char(s: str, it: fn(char) -> bool) {
pure fn each_char(s: str, it: fn(char) -> bool) {
let mut pos = 0u;
let len = len(s);
while pos < len {
@ -665,7 +675,7 @@ fn each_char(s: str, it: fn(char) -> bool) {
}
#[doc = "Iterate over the characters in a string"]
fn chars_iter(s: str, it: fn(char)) {
pure fn chars_iter(s: str, it: fn(char)) {
let mut pos = 0u;
let len = len(s);
while (pos < len) {
@ -678,7 +688,7 @@ fn chars_iter(s: str, it: fn(char)) {
#[doc = "
Apply a function to each substring after splitting by character
"]
fn split_char_iter(ss: str, cc: char, ff: fn(&&str)) {
pure fn split_char_iter(ss: str, cc: char, ff: fn(&&str)) {
vec::iter(split_char(ss, cc), ff)
}
@ -686,17 +696,18 @@ fn split_char_iter(ss: str, cc: char, ff: fn(&&str)) {
Apply a function to each substring after splitting by character, up to
`count` times
"]
fn splitn_char_iter(ss: str, sep: char, count: uint, ff: fn(&&str)) unsafe {
pure fn splitn_char_iter(ss: str, sep: char, count: uint,
ff: fn(&&str)) unsafe {
vec::iter(splitn_char(ss, sep, count), ff)
}
#[doc = "Apply a function to each word"]
fn words_iter(ss: str, ff: fn(&&str)) {
pure fn words_iter(ss: str, ff: fn(&&str)) {
vec::iter(words(ss), ff)
}
#[doc = "Apply a function to each line (by '\\n')"]
fn lines_iter(ss: str, ff: fn(&&str)) {
pure fn lines_iter(ss: str, ff: fn(&&str)) {
vec::iter(lines(ss), ff)
}
@ -717,7 +728,7 @@ Returns the byte index of the first matching character
An `option` containing the byte index of the first matching character
or `none` if there is no match
"]
fn find_char(s: str, c: char) -> option<uint> {
pure fn find_char(s: str, c: char) -> option<uint> {
find_char_between(s, c, 0u, len(s))
}
@ -741,7 +752,7 @@ or `none` if there is no match
`start` must be less than or equal to `len(s)`. `start` must be the
index of a character boundary, as defined by `is_char_boundary`.
"]
fn find_char_from(s: str, c: char, start: uint) -> option<uint> {
pure fn find_char_from(s: str, c: char, start: uint) -> option<uint> {
find_char_between(s, c, start, len(s))
}
@ -766,7 +777,7 @@ or `none` if there is no match
or equal to `len(s)`. `start` must be the index of a character boundary,
as defined by `is_char_boundary`.
"]
fn find_char_between(s: str, c: char, start: uint, end: uint)
pure fn find_char_between(s: str, c: char, start: uint, end: uint)
-> option<uint> {
if c < 128u as char {
assert start <= end;
@ -796,7 +807,7 @@ Returns the byte index of the last matching character
An `option` containing the byte index of the last matching character
or `none` if there is no match
"]
fn rfind_char(s: str, c: char) -> option<uint> {
pure fn rfind_char(s: str, c: char) -> option<uint> {
rfind_char_between(s, c, len(s), 0u)
}
@ -820,7 +831,7 @@ or `none` if there is no match
`start` must be less than or equal to `len(s)`. `start` must be
the index of a character boundary, as defined by `is_char_boundary`.
"]
fn rfind_char_from(s: str, c: char, start: uint) -> option<uint> {
pure fn rfind_char_from(s: str, c: char, start: uint) -> option<uint> {
rfind_char_between(s, c, start, 0u)
}
@ -845,7 +856,7 @@ or `none` if there is no match
or equal to `len(s)`. `start` must be the index of a character boundary,
as defined by `is_char_boundary`.
"]
fn rfind_char_between(s: str, c: char, start: uint, end: uint)
pure fn rfind_char_between(s: str, c: char, start: uint, end: uint)
-> option<uint> {
if c < 128u as char {
assert start >= end;
@ -876,7 +887,7 @@ the given predicate
An `option` containing the byte index of the first matching character
or `none` if there is no match
"]
fn find(s: str, f: fn(char) -> bool) -> option<uint> {
pure fn find(s: str, f: fn(char) -> bool) -> option<uint> {
find_between(s, 0u, len(s), f)
}
@ -900,7 +911,7 @@ or `none` if there is no match
`start` must be less than or equal to `len(s)`. `start` must be the
index of a character boundary, as defined by `is_char_boundary`.
"]
fn find_from(s: str, start: uint, f: fn(char) -> bool) -> option<uint> {
pure fn find_from(s: str, start: uint, f: fn(char) -> bool) -> option<uint> {
find_between(s, start, len(s), f)
}
@ -926,7 +937,7 @@ or `none` if there is no match
or equal to `len(s)`. `start` must be the index of a character
boundary, as defined by `is_char_boundary`.
"]
fn find_between(s: str, start: uint, end: uint, f: fn(char) -> bool)
pure fn find_between(s: str, start: uint, end: uint, f: fn(char) -> bool)
-> option<uint> {
assert start <= end;
assert end <= len(s);
@ -954,7 +965,7 @@ the given predicate
An option containing the byte index of the last matching character
or `none` if there is no match
"]
fn rfind(s: str, f: fn(char) -> bool) -> option<uint> {
pure fn rfind(s: str, f: fn(char) -> bool) -> option<uint> {
rfind_between(s, len(s), 0u, f)
}
@ -978,7 +989,7 @@ or `none` if there is no match
`start` must be less than or equal to `len(s)', `start` must be the
index of a character boundary, as defined by `is_char_boundary`
"]
fn rfind_from(s: str, start: uint, f: fn(char) -> bool) -> option<uint> {
pure fn rfind_from(s: str, start: uint, f: fn(char) -> bool) -> option<uint> {
rfind_between(s, start, 0u, f)
}
@ -1004,7 +1015,7 @@ or `none` if there is no match
than or equal to `len(s)`. `start` must be the index of a character
boundary, as defined by `is_char_boundary`
"]
fn rfind_between(s: str, start: uint, end: uint, f: fn(char) -> bool)
pure fn rfind_between(s: str, start: uint, end: uint, f: fn(char) -> bool)
-> option<uint> {
assert start >= end;
assert start <= len(s);
@ -1019,7 +1030,7 @@ fn rfind_between(s: str, start: uint, end: uint, f: fn(char) -> bool)
}
// Utility used by various searching functions
fn match_at(haystack: str, needle: str, at: uint) -> bool {
pure fn match_at(haystack: str, needle: str, at: uint) -> bool {
let mut i = at;
for each(needle) {|c| if haystack[i] != c { ret false; } i += 1u; }
ret true;
@ -1038,7 +1049,7 @@ Returns the byte index of the first matching substring
An `option` containing the byte index of the first matching substring
or `none` if there is no match
"]
fn find_str(haystack: str, needle: str) -> option<uint> {
pure fn find_str(haystack: str, needle: str) -> option<uint> {
find_str_between(haystack, needle, 0u, len(haystack))
}
@ -1061,7 +1072,7 @@ or `none` if there is no match
`start` must be less than or equal to `len(s)`
"]
fn find_str_from(haystack: str, needle: str, start: uint)
pure fn find_str_from(haystack: str, needle: str, start: uint)
-> option<uint> {
find_str_between(haystack, needle, start, len(haystack))
}
@ -1086,7 +1097,7 @@ or `none` if there is no match
`start` must be less than or equal to `end` and `end` must be less than
or equal to `len(s)`.
"]
fn find_str_between(haystack: str, needle: str, start: uint, end:uint)
pure fn find_str_between(haystack: str, needle: str, start: uint, end:uint)
-> option<uint> {
// See Issue #1932 for why this is a naive search
assert end <= len(haystack);
@ -1111,7 +1122,7 @@ Returns true if one string contains another
* haystack - The string to look in
* needle - The string to look for
"]
fn contains(haystack: str, needle: str) -> bool {
pure fn contains(haystack: str, needle: str) -> bool {
option::is_some(find_str(haystack, needle))
}
@ -1123,7 +1134,7 @@ Returns true if one string starts with another
* haystack - The string to look in
* needle - The string to look for
"]
fn starts_with(haystack: str, needle: str) -> bool unsafe {
pure fn starts_with(haystack: str, needle: str) -> bool unsafe {
let haystack_len = len(haystack), needle_len = len(needle);
if needle_len == 0u { true }
else if needle_len > haystack_len { false }
@ -1138,7 +1149,7 @@ Returns true if one string ends with another
* haystack - The string to look in
* needle - The string to look for
"]
fn ends_with(haystack: str, needle: str) -> bool {
pure fn ends_with(haystack: str, needle: str) -> bool {
let haystack_len = len(haystack), needle_len = len(needle);
if needle_len == 0u { true }
else if needle_len > haystack_len { false }
@ -1150,7 +1161,7 @@ Section: String properties
*/
#[doc = "Determines if a string contains only ASCII characters"]
fn is_ascii(s: str) -> bool {
pure fn is_ascii(s: str) -> bool {
let mut i: uint = len(s);
while i > 0u { i -= 1u; if !u8::is_ascii(s[i]) { ret false; } }
ret true;
@ -1167,7 +1178,7 @@ Returns true if the string contains only whitespace
Whitespace characters are determined by `char::is_whitespace`
"]
fn is_whitespace(s: str) -> bool {
pure fn is_whitespace(s: str) -> bool {
ret all(s, char::is_whitespace);
}
@ -1189,14 +1200,14 @@ pure fn len(s: str) -> uint unsafe {
}
#[doc = "Returns the number of characters that a string holds"]
fn char_len(s: str) -> uint { count_chars(s, 0u, len(s)) }
pure fn char_len(s: str) -> uint { count_chars(s, 0u, len(s)) }
/*
Section: Misc
*/
#[doc = "Determines if a vector of bytes contains valid UTF-8"]
fn is_utf8(v: [const u8]) -> bool {
pure fn is_utf8(v: [const u8]) -> bool {
let mut i = 0u;
let total = vec::len::<u8>(v);
while i < total {
@ -1214,7 +1225,7 @@ fn is_utf8(v: [const u8]) -> bool {
}
#[doc = "Determines if a vector of `u16` contains valid UTF-16"]
fn is_utf16(v: [const u16]) -> bool {
pure fn is_utf16(v: [const u16]) -> bool {
let len = vec::len(v);
let mut i = 0u;
while (i < len) {
@ -1235,7 +1246,7 @@ fn is_utf16(v: [const u16]) -> bool {
}
#[doc = "Converts to a vector of `u16` encoded as UTF-16"]
fn to_utf16(s: str) -> [u16] {
pure fn to_utf16(s: str) -> [u16] {
let mut u = [];
chars_iter(s) {|cch|
// Arithmetic with u32 literals is easier on the eyes than chars.
@ -1257,7 +1268,7 @@ fn to_utf16(s: str) -> [u16] {
ret u;
}
fn utf16_chars(v: [const u16], f: fn(char)) {
pure fn utf16_chars(v: [const u16], f: fn(char)) {
let len = vec::len(v);
let mut i = 0u;
while (i < len && v[i] != 0u16) {
@ -1282,10 +1293,12 @@ fn utf16_chars(v: [const u16], f: fn(char)) {
}
fn from_utf16(v: [const u16]) -> str {
pure fn from_utf16(v: [const u16]) -> str {
let mut buf = "";
reserve(buf, vec::len(v));
utf16_chars(v) {|ch| push_char(buf, ch); }
unchecked {
reserve(buf, vec::len(v));
utf16_chars(v) {|ch| push_char(buf, ch); }
}
ret buf;
}
@ -1303,7 +1316,7 @@ As char_len but for a slice of a string
The number of Unicode characters in `s` between the given indices.
"]
fn count_chars(s: str, start: uint, end: uint) -> uint {
pure fn count_chars(s: str, start: uint, end: uint) -> uint {
assert is_char_boundary(s, start);
assert is_char_boundary(s, end);
let mut i = start, len = 0u;
@ -1318,7 +1331,7 @@ fn count_chars(s: str, start: uint, end: uint) -> uint {
#[doc = "
Counts the number of bytes taken by the `n` in `s` starting from `start`.
"]
fn count_bytes(s: str, start: uint, n: uint) -> uint {
pure fn count_bytes(s: str, start: uint, n: uint) -> uint {
assert is_char_boundary(s, start);
let mut end = start, cnt = n;
let l = len(s);
@ -1403,7 +1416,7 @@ index of the next unicode character.
If `i` is greater than or equal to the length of the string.
If `i` is not the index of the beginning of a valid UTF-8 character.
"]
fn char_range_at(s: str, i: uint) -> {ch: char, next: uint} {
pure fn char_range_at(s: str, i: uint) -> {ch: char, next: uint} {
let b0 = s[i];
let w = utf8_char_width(b0);
assert (w != 0u);
@ -1426,14 +1439,16 @@ fn char_range_at(s: str, i: uint) -> {ch: char, next: uint} {
}
#[doc = "Pluck a character out of a string"]
fn char_at(s: str, i: uint) -> char { ret char_range_at(s, i).ch; }
pure fn char_at(s: str, i: uint) -> char { ret char_range_at(s, i).ch; }
#[doc = "
Given a byte position and a str, return the previous char and its position
This function can be used to iterate over a unicode string in reverse.
"]
fn char_range_at_reverse(ss: str, start: uint) -> {ch: char, prev: uint} {
pure fn char_range_at_reverse(ss: str, start: uint)
-> {ch: char, prev: uint} {
let mut prev = start;
// while there is a previous byte == 10......
@ -1470,7 +1485,8 @@ Loop through a substring, char by char
`true` If execution proceeded correctly, `false` if it was interrupted,
that is if `it` returned `false` at any point.
"]
fn all_between(s: str, start: uint, end: uint, it: fn(char) -> bool) -> bool {
pure fn all_between(s: str, start: uint, end: uint,
it: fn(char) -> bool) -> bool {
assert is_char_boundary(s, start);
let mut i = start;
while i < end {
@ -1502,7 +1518,8 @@ Loop through a substring, char by char
`true` if `it` returns `true` for any character
"]
fn any_between(s: str, start: uint, end: uint, it: fn(char) -> bool) -> bool {
pure fn any_between(s: str, start: uint, end: uint,
it: fn(char) -> bool) -> bool {
!all_between(s, start, end, {|c| !it(c)})
}
@ -1533,7 +1550,7 @@ interop.
let i = str::as_bytes(\"Hello World\") { |bytes| vec::len(bytes) };
~~~
"]
fn as_bytes<T>(s: str, f: fn([u8]) -> T) -> T unsafe {
pure fn as_bytes<T>(s: str, f: fn([u8]) -> T) -> T unsafe {
let v: *[u8] = ::unsafe::reinterpret_cast(ptr::addr_of(s));
f(*v)
}
@ -1544,7 +1561,7 @@ Work with the byte buffer of a string.
Allows for unsafe manipulation of strings, which is useful for native
interop.
"]
fn as_buf<T>(s: str, f: fn(*u8) -> T) -> T unsafe {
pure fn as_buf<T>(s: str, f: fn(*u8) -> T) -> T unsafe {
as_bytes(s) { |v| vec::as_buf(v, f) }
}
@ -1560,7 +1577,7 @@ interop, without copying the original string.
let s = str::as_buf(\"PATH\", { |path_buf| libc::getenv(path_buf) });
~~~
"]
fn as_c_str<T>(s: str, f: fn(*libc::c_char) -> T) -> T unsafe {
pure fn as_c_str<T>(s: str, f: fn(*libc::c_char) -> T) -> T unsafe {
as_buf(s) {|buf| f(buf as *libc::c_char) }
}
@ -1574,7 +1591,7 @@ indexable area for a null byte, as is the case in slices pointing
to full strings, or suffixes of them.
"]
#[inline(always)]
fn unpack_slice<T>(s: str/&, f: fn(*u8, uint) -> T) -> T unsafe {
pure fn unpack_slice<T>(s: str/&, f: fn(*u8, uint) -> T) -> T unsafe {
let v : *(*u8,uint) = ::unsafe::reinterpret_cast(ptr::addr_of(s));
let (buf,len) = *v;
f(buf, len)
@ -1639,18 +1656,22 @@ pure fn capacity(&&s: str) -> uint unsafe {
}
#[doc = "Escape each char in `s` with char::escape_default."]
fn escape_default(s: str) -> str {
pure fn escape_default(s: str) -> str {
let mut out: str = "";
reserve_at_least(out, str::len(s));
chars_iter(s) {|c| out += char::escape_default(c); }
unchecked {
reserve_at_least(out, str::len(s));
chars_iter(s) {|c| out += char::escape_default(c); }
}
ret out;
}
#[doc = "Escape each char in `s` with char::escape_unicode."]
fn escape_unicode(s: str) -> str {
pure fn escape_unicode(s: str) -> str {
let mut out: str = "";
reserve_at_least(out, str::len(s));
chars_iter(s) {|c| out += char::escape_unicode(c); }
unchecked {
reserve_at_least(out, str::len(s));
chars_iter(s) {|c| out += char::escape_unicode(c); }
}
ret out;
}

View file

@ -17,9 +17,9 @@ enum type_desc = {
#[abi = "cdecl"]
native mod rustrt {
fn refcount(t: *()) -> libc::intptr_t;
pure fn refcount(t: *()) -> libc::intptr_t;
fn unsupervise();
fn shape_log_str(t: *sys::type_desc, data: *()) -> str;
pure fn shape_log_str(t: *sys::type_desc, data: *()) -> str;
}
#[abi = "rust-intrinsic"]
@ -36,13 +36,13 @@ Returns a pointer to a type descriptor.
Useful for calling certain function in the Rust runtime or otherwise
performing dark magick.
"]
fn get_type_desc<T>() -> *type_desc {
rusti::get_tydesc::<T>() as *type_desc
pure fn get_type_desc<T>() -> *type_desc {
unchecked { rusti::get_tydesc::<T>() as *type_desc }
}
#[doc = "Returns the size of a type"]
fn size_of<T>() -> uint unsafe {
rusti::size_of::<T>()
pure fn size_of<T>() -> uint unsafe {
unchecked { rusti::size_of::<T>() }
}
#[doc = "
@ -51,23 +51,23 @@ Returns the ABI-required minimum alignment of a type
This is the alignment used for struct fields. It may be smaller
than the preferred alignment.
"]
fn min_align_of<T>() -> uint unsafe {
rusti::min_align_of::<T>()
pure fn min_align_of<T>() -> uint unsafe {
unchecked { rusti::min_align_of::<T>() }
}
#[doc = "Returns the preferred alignment of a type"]
fn pref_align_of<T>() -> uint unsafe {
rusti::pref_align_of::<T>()
pure fn pref_align_of<T>() -> uint unsafe {
unchecked { rusti::pref_align_of::<T>() }
}
#[doc = "Returns the refcount of a shared box"]
fn refcount<T>(t: @T) -> uint {
pure fn refcount<T>(t: @T) -> uint {
unsafe {
ret rustrt::refcount(unsafe::reinterpret_cast(t)) as uint;
}
}
fn log_str<T>(t: T) -> str {
pure fn log_str<T>(t: T) -> str {
unsafe {
let data_ptr: *() = unsafe::reinterpret_cast(ptr::addr_of(t));
rustrt::shape_log_str(get_type_desc::<T>(), data_ptr)

View file

@ -1,4 +1,5 @@
import T = inst::T;
import cmp::{eq, ord};
export min_value, max_value;
export min, max;
@ -10,6 +11,7 @@ export range;
export compl;
export to_str, to_str_bytes;
export from_str, from_str_radix, str, parse_buf;
export ord, eq;
const min_value: T = 0 as T;
const max_value: T = 0 as T - 1 as T;
@ -49,6 +51,18 @@ pure fn compl(i: T) -> T {
max_value ^ i
}
impl ord of ord for T {
fn lt(&&other: T) -> bool {
ret self < other;
}
}
impl eq of eq for T {
fn eq(&&other: T) -> bool {
ret self == other;
}
}
#[doc = "
Parse a buffer of bytes

View file

@ -211,18 +211,18 @@ fn from_mut<T>(+v: [mut T]) -> [T] unsafe {
pure fn head<T: copy>(v: [const T]/&) -> T { v[0] }
#[doc = "Returns a vector containing all but the first element of a slice"]
fn tail<T: copy>(v: [const T]/&) -> [T] {
pure fn tail<T: copy>(v: [const T]/&) -> [T] {
ret slice(v, 1u, len(v));
}
#[doc = "Returns a vector containing all but the first `n` \
elements of a slice"]
fn tailn<T: copy>(v: [const T]/&, n: uint) -> [T] {
pure fn tailn<T: copy>(v: [const T]/&, n: uint) -> [T] {
slice(v, n, len(v))
}
#[doc = "Returns a vector containing all but the last element of a slice"]
fn init<T: copy>(v: [const T]/&) -> [T] {
pure fn init<T: copy>(v: [const T]/&) -> [T] {
assert len(v) != 0u;
slice(v, 0u, len(v) - 1u)
}
@ -798,7 +798,7 @@ Swaps two elements in a vector
* a - The index of the first element
* b - The index of the second element
"]
fn swap<T>(v: [mut T], a: uint, b: uint) {
fn swap<T>(&&v: [mut T], a: uint, b: uint) {
v[a] <-> v[b];
}
@ -1033,10 +1033,10 @@ pure fn unpack_mut_slice<T,U>(s: [mut T]/&,
impl extensions/&<T> for [const T]/& {
#[doc = "Returns true if a vector contains no elements"]
#[inline]
fn is_empty() -> bool { is_empty(self) }
pure fn is_empty() -> bool { is_empty(self) }
#[doc = "Returns true if a vector contains some elements"]
#[inline]
fn is_not_empty() -> bool { is_not_empty(self) }
pure fn is_not_empty() -> bool { is_not_empty(self) }
#[doc = "Returns the length of a vector"]
#[inline]
pure fn len() -> uint { len(self) }
@ -1046,28 +1046,28 @@ impl extensions/&<T> for [const T]/& {
impl extensions/&<T: copy> for [const T]/& {
#[doc = "Returns the first element of a vector"]
#[inline]
fn head() -> T { head(self) }
pure fn head() -> T { head(self) }
#[doc = "Returns all but the last elemnt of a vector"]
#[inline]
fn init() -> [T] { init(self) }
pure fn init() -> [T] { init(self) }
#[doc = "
Returns the last element of a `v`, failing if the vector is empty.
"]
#[inline]
fn last() -> T { last(self) }
pure fn last() -> T { last(self) }
#[doc = "Returns a copy of the elements from [`start`..`end`) from `v`."]
#[inline]
fn slice(start: uint, end: uint) -> [T] { slice(self, start, end) }
pure fn slice(start: uint, end: uint) -> [T] { slice(self, start, end) }
#[doc = "Returns all but the first element of a vector"]
#[inline]
fn tail() -> [T] { tail(self) }
pure fn tail() -> [T] { tail(self) }
}
#[doc = "Extension methods for vectors"]
impl extensions/&<T> for [T]/& {
#[doc = "Reduce a vector from right to left"]
#[inline]
fn foldr<U: copy>(z: U, p: fn(T, U) -> U) -> U { foldr(self, z, p) }
pure fn foldr<U: copy>(z: U, p: fn(T, U) -> U) -> U { foldr(self, z, p) }
#[doc = "
Iterates over a vector
@ -1075,7 +1075,7 @@ impl extensions/&<T> for [T]/& {
the element's value.
"]
#[inline]
fn iter(f: fn(T)) { iter(self, f) }
pure fn iter(f: fn(T)) { iter(self, f) }
#[doc = "
Iterates over a vector's elements and indexes
@ -1083,7 +1083,7 @@ impl extensions/&<T> for [T]/& {
the element's value and index.
"]
#[inline]
fn iteri(f: fn(uint, T)) { iteri(self, f) }
pure fn iteri(f: fn(uint, T)) { iteri(self, f) }
#[doc = "
Find the first index matching some predicate
@ -1092,10 +1092,10 @@ impl extensions/&<T> for [T]/& {
elements then none is returned.
"]
#[inline]
fn position(f: fn(T) -> bool) -> option<uint> { position(self, f) }
pure fn position(f: fn(T) -> bool) -> option<uint> { position(self, f) }
#[doc = "Find the first index containing a matching value"]
#[inline]
fn position_elem(x: T) -> option<uint> { position_elem(self, x) }
pure fn position_elem(x: T) -> option<uint> { position_elem(self, x) }
#[doc = "
Iterates over a vector in reverse
@ -1103,7 +1103,7 @@ impl extensions/&<T> for [T]/& {
the element's value.
"]
#[inline]
fn riter(f: fn(T)) { riter(self, f) }
pure fn riter(f: fn(T)) { riter(self, f) }
#[doc ="
Iterates over a vector's elements and indexes in reverse
@ -1111,7 +1111,7 @@ impl extensions/&<T> for [T]/& {
the element's value and index.
"]
#[inline]
fn riteri(f: fn(uint, T)) { riteri(self, f) }
pure fn riteri(f: fn(uint, T)) { riteri(self, f) }
#[doc = "
Find the last index matching some predicate
@ -1120,20 +1120,20 @@ impl extensions/&<T> for [T]/& {
matches no elements then none is returned.
"]
#[inline]
fn rposition(f: fn(T) -> bool) -> option<uint> { rposition(self, f) }
pure fn rposition(f: fn(T) -> bool) -> option<uint> { rposition(self, f) }
#[doc = "Find the last index containing a matching value"]
#[inline]
fn rposition_elem(x: T) -> option<uint> { rposition_elem(self, x) }
pure fn rposition_elem(x: T) -> option<uint> { rposition_elem(self, x) }
#[doc = "
Apply a function to each element of a vector and return the results
"]
#[inline]
fn map<U>(f: fn(T) -> U) -> [U] { map(self, f) }
pure fn map<U>(f: fn(T) -> U) -> [U] { map(self, f) }
#[doc = "
Apply a function to the index and value of each element in the vector
and return the results
"]
fn mapi<U>(f: fn(uint, T) -> U) -> [U] {
pure fn mapi<U>(f: fn(uint, T) -> U) -> [U] {
mapi(self, f)
}
#[doc = "Returns true if the function returns true for all elements.
@ -1147,7 +1147,7 @@ impl extensions/&<T> for [T]/& {
of each result vector
"]
#[inline]
fn flat_map<U>(f: fn(T) -> [U]) -> [U] { flat_map(self, f) }
pure fn flat_map<U>(f: fn(T) -> [U]) -> [U] { flat_map(self, f) }
#[doc = "
Apply a function to each element of a vector and return the results
@ -1155,7 +1155,7 @@ impl extensions/&<T> for [T]/& {
the resulting vector.
"]
#[inline]
fn filter_map<U: copy>(f: fn(T) -> option<U>) -> [U] {
pure fn filter_map<U: copy>(f: fn(T) -> option<U>) -> [U] {
filter_map(self, f)
}
}
@ -1170,7 +1170,7 @@ impl extensions/&<T: copy> for [T]/& {
only those elements for which `f` returned true.
"]
#[inline]
fn filter(f: fn(T) -> bool) -> [T] { filter(self, f) }
pure fn filter(f: fn(T) -> bool) -> [T] { filter(self, f) }
#[doc = "
Search for the first element that matches a given predicate
@ -1179,7 +1179,7 @@ impl extensions/&<T: copy> for [T]/& {
is returned. If `f` matches no elements then none is returned.
"]
#[inline]
fn find(f: fn(T) -> bool) -> option<T> { find(self, f) }
pure fn find(f: fn(T) -> bool) -> option<T> { find(self, f) }
#[doc = "
Search for the last element that matches a given predicate
@ -1188,7 +1188,7 @@ impl extensions/&<T: copy> for [T]/& {
matches no elements then none is returned.
"]
#[inline]
fn rfind(f: fn(T) -> bool) -> option<T> { rfind(self, f) }
pure fn rfind(f: fn(T) -> bool) -> option<T> { rfind(self, f) }
}
#[doc = "Unsafe operations"]
@ -1221,12 +1221,12 @@ mod unsafe {
#[doc = "
Sets the length of a vector
This well explicitly set the size of the vector, without actually
This will explicitly set the size of the vector, without actually
modifing its buffers, so it is up to the caller to ensure that
the vector is actually the specified size.
"]
#[inline(always)]
unsafe fn set_len<T>(&v: [const T], new_len: uint) {
unsafe fn set_len<T>(&&v: [const T], new_len: uint) {
let repr: **vec_repr = ::unsafe::reinterpret_cast(addr_of(v));
(**repr).fill = new_len * sys::size_of::<T>();
}

View file

@ -24,9 +24,7 @@ type arc_data<T: const> = {
resource arc_destruct<T: const>(data: *libc::c_void) {
unsafe {
let data: ~arc_data<T> = unsafe::reinterpret_cast(data);
let ref_ptr = &mut data.count;
let new_count = rustrt::rust_atomic_decrement(ref_ptr);
let new_count = rustrt::rust_atomic_decrement(&mut data.count);
assert new_count >= 0;
if new_count == 0 {
// drop glue takes over.

View file

@ -1,6 +1,7 @@
#[doc = "A deque. Untested as of yet. Likely buggy"];
import option::{some, none};
import dvec::{dvec, extensions};
iface t<T> {
fn size() -> uint;
@ -23,7 +24,7 @@ fn create<T: copy>() -> t<T> {
* Grow is only called on full elts, so nelts is also len(elts), unlike
* elsewhere.
*/
fn grow<T: copy>(nelts: uint, lo: uint, elts: [mut cell<T>]) ->
fn grow<T: copy>(nelts: uint, lo: uint, -elts: [mut cell<T>]) ->
[mut cell<T>] {
assert (nelts == vec::len(elts));
let mut rv = [mut];
@ -39,38 +40,38 @@ fn create<T: copy>() -> t<T> {
ret rv;
}
fn get<T: copy>(elts: [mut cell<T>], i: uint) -> T {
ret alt elts[i] { some(t) { t } _ { fail } };
fn get<T: copy>(elts: dvec<cell<T>>, i: uint) -> T {
alt elts.get_elt(i) { some(t) { t } _ { fail } }
}
type repr<T> = {mut nelts: uint,
mut lo: uint,
mut hi: uint,
mut elts: [mut cell<T>]};
elts: dvec<cell<T>>};
impl <T: copy> of t<T> for repr<T> {
fn size() -> uint { ret self.nelts; }
fn add_front(t: T) {
let oldlo: uint = self.lo;
if self.lo == 0u {
self.lo = vec::len(self.elts) - 1u;
self.lo = self.elts.len() - 1u;
} else { self.lo -= 1u; }
if self.lo == self.hi {
self.elts = grow(self.nelts, oldlo, self.elts);
self.lo = vec::len(self.elts) - 1u;
self.elts.swap({ |v| grow(self.nelts, oldlo, v) });
self.lo = self.elts.len() - 1u;
self.hi = self.nelts;
}
self.elts[self.lo] = some(t);
self.elts.set_elt(self.lo, some(t));
self.nelts += 1u;
}
fn add_back(t: T) {
if self.lo == self.hi && self.nelts != 0u {
self.elts = grow(self.nelts, self.lo, self.elts);
self.elts.swap({ |v| grow(self.nelts, self.lo, v) });
self.lo = 0u;
self.hi = self.nelts;
}
self.elts[self.hi] = some(t);
self.hi = (self.hi + 1u) % vec::len(self.elts);
self.elts.set_elt(self.hi, some(t));
self.hi = (self.hi + 1u) % self.elts.len();
self.nelts += 1u;
}
/**
@ -79,24 +80,24 @@ fn create<T: copy>() -> t<T> {
*/
fn pop_front() -> T {
let t: T = get(self.elts, self.lo);
self.elts[self.lo] = none;
self.lo = (self.lo + 1u) % vec::len(self.elts);
self.elts.set_elt(self.lo, none);
self.lo = (self.lo + 1u) % self.elts.len();
self.nelts -= 1u;
ret t;
}
fn pop_back() -> T {
if self.hi == 0u {
self.hi = vec::len(self.elts) - 1u;
self.hi = self.elts.len() - 1u;
} else { self.hi -= 1u; }
let t: T = get(self.elts, self.hi);
self.elts[self.hi] = none;
self.elts.set_elt(self.hi, none);
self.nelts -= 1u;
ret t;
}
fn peek_front() -> T { ret get(self.elts, self.lo); }
fn peek_back() -> T { ret get(self.elts, self.hi - 1u); }
fn get(i: int) -> T {
let idx = (self.lo + (i as uint)) % vec::len(self.elts);
let idx = (self.lo + (i as uint)) % self.elts.len();
ret get(self.elts, idx);
}
}
@ -105,7 +106,10 @@ fn create<T: copy>() -> t<T> {
mut nelts: 0u,
mut lo: 0u,
mut hi: 0u,
mut elts: vec::to_mut(vec::from_elem(initial_capacity, none))
elts:
dvec::from_vec(
vec::to_mut(
vec::from_elem(initial_capacity, none)))
};
repr as t::<T>
}

View file

@ -1,5 +1,6 @@
#[doc = "Sorting methods"];
import vec::len;
import int::{eq, ord};
export le;
export merge_sort;
@ -141,7 +142,6 @@ fn qsort3<T: copy>(compare_func_lt: le<T>, compare_func_eq: le<T>,
qsort3::<T>(compare_func_lt, compare_func_eq, arr, i, right);
}
// FIXME: This should take lt and eq types (#2348)
#[doc = "
Fancy quicksort. Sorts a mut vector in place.
@ -152,10 +152,9 @@ According to these slides this is the algorithm of choice for
This is an unstable sort.
"]
fn quick_sort3<T: copy>(compare_func_lt: le<T>, compare_func_eq: le<T>,
arr: [mut T]) {
fn quick_sort3<T: copy ord eq>(arr: [mut T]) {
if len::<T>(arr) == 0u { ret; }
qsort3::<T>(compare_func_lt, compare_func_eq, arr, 0,
qsort3::<T>({ |x, y| x.lt(y) }, { |x, y| x.eq(y) }, arr, 0,
(len::<T>(arr) as int) - 1);
}
@ -163,11 +162,7 @@ fn quick_sort3<T: copy>(compare_func_lt: le<T>, compare_func_eq: le<T>,
mod test_qsort3 {
fn check_sort(v1: [mut int], v2: [mut int]) {
let len = vec::len::<int>(v1);
fn lt(&&a: int, &&b: int) -> bool { ret a < b; }
fn equal(&&a: int, &&b: int) -> bool { ret a == b; }
let f1 = lt;
let f2 = equal;
quick_sort3::<int>(f1, f2, v1);
quick_sort3::<int>(v1);
let mut i = 0u;
while i < len {
log(debug, v2[i]);

View file

@ -313,7 +313,7 @@ enum expr_ {
expr_fn(proto, fn_decl, blk, capture_clause),
expr_fn_block(fn_decl, blk, capture_clause),
// Inner expr is always an expr_fn_block. We need the wrapping node to
// sanely type this (a function returning nil on the inside but bool on
// easily type this (a function returning nil on the inside but bool on
// the outside).
expr_loop_body(@expr),
expr_block(blk),

View file

@ -21,17 +21,17 @@ pure fn mk_sp(lo: uint, hi: uint) -> span {
// make this a const, once the compiler supports it
pure fn dummy_sp() -> span { ret mk_sp(0u, 0u); }
fn path_name(p: @path) -> str { path_name_i(p.idents) }
pure fn path_name(p: @path) -> str { path_name_i(p.idents) }
fn path_name_i(idents: [ident]) -> str { str::connect(idents, "::") }
pure fn path_name_i(idents: [ident]) -> str { str::connect(idents, "::") }
fn path_to_ident(p: @path) -> ident { vec::last(p.idents) }
pure fn path_to_ident(p: @path) -> ident { vec::last(p.idents) }
fn local_def(id: node_id) -> def_id { {crate: local_crate, node: id} }
pure fn local_def(id: node_id) -> def_id { {crate: local_crate, node: id} }
pure fn is_local(did: ast::def_id) -> bool { did.crate == local_crate }
fn stmt_id(s: stmt) -> node_id {
pure fn stmt_id(s: stmt) -> node_id {
alt s.node {
stmt_decl(_, id) { id }
stmt_expr(_, id) { id }
@ -45,7 +45,7 @@ fn variant_def_ids(d: def) -> {enm: def_id, var: def_id} {
_ { fail "non-variant in variant_def_ids"; } }
}
fn def_id_of_def(d: def) -> def_id {
pure fn def_id_of_def(d: def) -> def_id {
alt d {
def_fn(id, _) | def_mod(id) |
def_native_mod(id) | def_const(id) |
@ -60,7 +60,7 @@ fn def_id_of_def(d: def) -> def_id {
}
}
fn binop_to_str(op: binop) -> str {
pure fn binop_to_str(op: binop) -> str {
alt op {
add { ret "+"; }
subtract { ret "-"; }
@ -95,7 +95,7 @@ pure fn is_shift_binop(b: binop) -> bool {
}
}
fn unop_to_str(op: unop) -> str {
pure fn unop_to_str(op: unop) -> str {
alt op {
box(mt) { if mt == m_mutbl { ret "@mut "; } ret "@"; }
uniq(mt) { if mt == m_mutbl { ret "~mut "; } ret "~"; }
@ -105,11 +105,11 @@ fn unop_to_str(op: unop) -> str {
}
}
fn is_path(e: @expr) -> bool {
pure fn is_path(e: @expr) -> bool {
ret alt e.node { expr_path(_) { true } _ { false } };
}
fn int_ty_to_str(t: int_ty) -> str {
pure fn int_ty_to_str(t: int_ty) -> str {
alt t {
ty_char { "u8" } // ???
ty_i { "" } ty_i8 { "i8" } ty_i16 { "i16" }
@ -117,7 +117,7 @@ fn int_ty_to_str(t: int_ty) -> str {
}
}
fn int_ty_max(t: int_ty) -> u64 {
pure fn int_ty_max(t: int_ty) -> u64 {
alt t {
ty_i8 { 0x80u64 }
ty_i16 { 0x8000u64 }
@ -126,14 +126,14 @@ fn int_ty_max(t: int_ty) -> u64 {
}
}
fn uint_ty_to_str(t: uint_ty) -> str {
pure fn uint_ty_to_str(t: uint_ty) -> str {
alt t {
ty_u { "u" } ty_u8 { "u8" } ty_u16 { "u16" }
ty_u32 { "u32" } ty_u64 { "u64" }
}
}
fn uint_ty_max(t: uint_ty) -> u64 {
pure fn uint_ty_max(t: uint_ty) -> u64 {
alt t {
ty_u8 { 0xffu64 }
ty_u16 { 0xffffu64 }
@ -142,7 +142,7 @@ fn uint_ty_max(t: uint_ty) -> u64 {
}
}
fn float_ty_to_str(t: float_ty) -> str {
pure fn float_ty_to_str(t: float_ty) -> str {
alt t { ty_f { "" } ty_f32 { "f32" } ty_f64 { "f64" } }
}

View file

@ -77,7 +77,7 @@ fn next_line(file: filemap, chpos: uint, byte_pos: uint) {
file.lines += [{ch: chpos, byte: byte_pos + file.start_pos.byte}];
}
type lookup_fn = fn@(file_pos) -> uint;
type lookup_fn = pure fn(file_pos) -> uint;
fn lookup_line(map: codemap, pos: uint, lookup: lookup_fn)
-> {fm: filemap, line: uint}
@ -108,12 +108,12 @@ fn lookup_pos(map: codemap, pos: uint, lookup: lookup_fn) -> loc {
}
fn lookup_char_pos(map: codemap, pos: uint) -> loc {
fn lookup(pos: file_pos) -> uint { ret pos.ch; }
pure fn lookup(pos: file_pos) -> uint { ret pos.ch; }
ret lookup_pos(map, pos, lookup);
}
fn lookup_byte_pos(map: codemap, pos: uint) -> loc {
fn lookup(pos: file_pos) -> uint { ret pos.byte; }
pure fn lookup(pos: file_pos) -> uint { ret pos.byte; }
ret lookup_pos(map, pos, lookup);
}
@ -139,7 +139,7 @@ fn lookup_char_pos_adj(map: codemap, pos: uint)
}
fn adjust_span(map: codemap, sp: span) -> span {
fn lookup(pos: file_pos) -> uint { ret pos.ch; }
pure fn lookup(pos: file_pos) -> uint { ret pos.ch; }
let line = lookup_line(map, sp.lo, lookup);
alt (line.fm.substr) {
fss_none {sp}
@ -198,7 +198,8 @@ fn get_line(fm: filemap, line: int) -> str unsafe {
fn lookup_byte_offset(cm: codemap::codemap, chpos: uint)
-> {fm: filemap, pos: uint} {
let {fm, line} = lookup_line(cm, chpos, {|pos| pos.ch});
pure fn lookup(pos: file_pos) -> uint { ret pos.ch; }
let {fm, line} = lookup_line(cm, chpos, lookup);
let line_offset = fm.lines[line].byte - fm.start_pos.byte;
let col = chpos - fm.lines[line].ch;
let col_offset = str::count_bytes(*fm.src, line_offset, col);

View file

@ -86,11 +86,14 @@ impl codemap_handler of handler for handler_t {
}
fn has_errors() -> bool { self.err_count > 0u }
fn abort_if_errors() {
if self.err_count > 0u {
let s = #fmt["aborting due to %u previous errors",
self.err_count];
self.fatal(s);
let s;
alt self.err_count {
0u { ret; }
1u { s = "aborting due to previous error"; }
_ { s = #fmt["aborting due to %u previous errors",
self.err_count]; }
}
self.fatal(s);
}
fn warn(msg: str) {
self.emit(none, msg, warning);

View file

@ -212,7 +212,7 @@ fn finish<T: qq_helper>
state = skip(str::char_len(repl));
str2 += repl;
}
alt state {
alt copy state {
active {str::push_char(str2, ch);}
skip(1u) {state = blank;}
skip(sk) {state = skip (sk-1u);}

View file

@ -1,5 +1,6 @@
import codemap::span;
import std::map::{hashmap, str_hash};
import dvec::{dvec, extensions};
import base::*;
@ -134,7 +135,7 @@ fn compose_sels(s1: selector, s2: selector) -> selector {
type binders =
{real_binders: hashmap<ident, selector>,
mut literal_ast_matchers: [selector]};
literal_ast_matchers: dvec<selector>};
type bindings = hashmap<ident, arb_depth<matchable>>;
fn acumm_bindings(_cx: ext_ctxt, _b_dest: bindings, _b_src: bindings) { }
@ -146,7 +147,7 @@ fn acumm_bindings(_cx: ext_ctxt, _b_dest: bindings, _b_src: bindings) { }
fn pattern_to_selectors(cx: ext_ctxt, e: @expr) -> binders {
let res: binders =
{real_binders: str_hash::<selector>(),
mut literal_ast_matchers: []};
literal_ast_matchers: dvec()};
//this oughta return binders instead, but macro args are a sequence of
//expressions, rather than a single expression
fn trivial_selector(m: matchable) -> match_result { ret some(leaf(m)); }
@ -474,7 +475,7 @@ fn p_t_s_rec(cx: ext_ctxt, m: matchable, s: selector, b: binders) {
_ { cx.bug("broken traversal in p_t_s_r") }
}
}
b.literal_ast_matchers += [bind select(cx, _, e)];
b.literal_ast_matchers.push(bind select(cx, _, e));
}
}
}
@ -640,8 +641,8 @@ fn p_t_s_r_length(cx: ext_ctxt, len: uint, at_least: bool, s: selector,
_ { none }
}
}
b.literal_ast_matchers +=
[compose_sels(s, bind len_select(cx, _, at_least, len))];
b.literal_ast_matchers.push(
compose_sels(s, bind len_select(cx, _, at_least, len)));
}
fn p_t_s_r_actual_vector(cx: ext_ctxt, elts: [@expr], _repeat_after: bool,

View file

@ -18,7 +18,7 @@ fn seq_sep_none() -> seq_sep {
}
fn token_to_str(reader: reader, token: token::token) -> str {
fn token_to_str(reader: reader, ++token: token::token) -> str {
token::to_str(*reader.interner, token)
}
@ -27,8 +27,9 @@ fn token_to_str(reader: reader, token: token::token) -> str {
impl parser_common for parser {
fn unexpected_last(t: token::token) -> ! {
self.span_fatal(self.last_span, "unexpected token: '"
+ token_to_str(self.reader, t) + "'");
self.span_fatal(
copy self.last_span,
"unexpected token: '" + token_to_str(self.reader, t) + "'");
}
fn unexpected() -> ! {
@ -49,7 +50,7 @@ impl parser_common for parser {
}
fn parse_ident() -> ast::ident {
alt self.token {
alt copy self.token {
token::IDENT(i, _) { self.bump(); ret self.get_str(i); }
_ { self.fatal("expecting ident, found "
+ token_to_str(self.reader, self.token)); }
@ -79,7 +80,7 @@ impl parser_common for parser {
}
}
fn token_is_keyword(word: str, tok: token::token) -> bool {
fn token_is_keyword(word: str, ++tok: token::token) -> bool {
self.require_keyword(word);
alt tok {
token::IDENT(sid, false) { str::eq(word, self.get_str(sid)) }
@ -93,8 +94,11 @@ impl parser_common for parser {
fn eat_keyword(word: str) -> bool {
self.require_keyword(word);
alt self.token {
token::IDENT(sid, false) {
// FIXME: this gratuitous use of @ is to
// workaround LLVM bug #13042
alt @self.token {
@token::IDENT(sid, false) {
if str::eq(word, self.get_str(sid)) {
self.bump();
ret true;

View file

@ -121,16 +121,16 @@ class parser {
ret self.buffer[distance - 1u].tok;
}
fn fatal(m: str) -> ! {
self.sess.span_diagnostic.span_fatal(self.span, m)
self.sess.span_diagnostic.span_fatal(copy self.span, m)
}
fn span_fatal(sp: span, m: str) -> ! {
self.sess.span_diagnostic.span_fatal(sp, m)
}
fn bug(m: str) -> ! {
self.sess.span_diagnostic.span_bug(self.span, m)
self.sess.span_diagnostic.span_bug(copy self.span, m)
}
fn warn(m: str) {
self.sess.span_diagnostic.span_warn(self.span, m)
self.sess.span_diagnostic.span_warn(copy self.span, m)
}
fn get_str(i: token::str_num) -> str {
interner::get(*self.reader.interner, i)
@ -307,7 +307,7 @@ class parser {
// Parses something like "&x"
fn parse_region() -> @region {
self.expect(token::BINOP(token::AND));
alt self.token {
alt copy self.token {
token::IDENT(sid, _) {
self.bump();
let n = self.get_str(sid);
@ -322,7 +322,7 @@ class parser {
// Parses something like "&x." (note the trailing dot)
fn parse_region_dot() -> @region {
let name =
alt self.token {
alt copy self.token {
token::IDENT(sid, _) if self.look_ahead(1u) == token::DOT {
self.bump(); self.bump();
some(self.get_str(sid))
@ -483,11 +483,11 @@ class parser {
}
fn maybe_parse_dollar_mac() -> option<mac_> {
alt self.token {
alt copy self.token {
token::DOLLAR {
let lo = self.span.lo;
self.bump();
alt self.token {
alt copy self.token {
token::LIT_INT(num, ty_i) {
self.bump();
some(mac_var(num as uint))
@ -511,7 +511,7 @@ class parser {
fn maybe_parse_vstore() -> option<vstore> {
if self.token == token::BINOP(token::SLASH) {
self.bump();
alt self.token {
alt copy self.token {
token::AT {
self.bump(); some(vstore_box)
}
@ -968,7 +968,7 @@ class parser {
loop {
// expr.f
if self.eat(token::DOT) {
alt self.token {
alt copy self.token {
token::IDENT(i, _) {
hi = self.span.hi;
self.bump();
@ -986,7 +986,7 @@ class parser {
cont;
}
if self.expr_is_complete(e) { break; }
alt self.token {
alt copy self.token {
// expr(...)
token::LPAREN if self.permits_call() {
let es_opt = self.parse_seq(token::LPAREN, token::RPAREN,
@ -1042,7 +1042,7 @@ class parser {
let mut hi;
let mut ex;
alt self.token {
alt copy self.token {
token::NOT {
self.bump();
let e = self.to_expr(self.parse_prefix_expr());
@ -1134,7 +1134,7 @@ class parser {
fn parse_assign_expr() -> @expr {
let lo = self.span.lo;
let lhs = self.parse_binops();
alt self.token {
alt copy self.token {
token::EQ {
self.bump();
let rhs = self.parse_expr();
@ -1831,7 +1831,7 @@ class parser {
}
fn parse_method_name() -> ident {
alt self.token {
alt copy self.token {
token::BINOP(op) { self.bump(); token::binop_to_str(op) }
token::NOT { self.bump(); "!" }
token::LBRACKET { self.bump(); self.expect(token::RBRACKET); "[]" }
@ -2375,7 +2375,7 @@ class parser {
while self.token == token::MOD_SEP {
self.bump();
alt self.token {
alt copy self.token {
token::IDENT(i, _) {
self.bump();
@ -2477,7 +2477,7 @@ class parser {
}
fn parse_str() -> str {
alt self.token {
alt copy self.token {
token::LIT_STR(s) { self.bump(); self.get_str(s) }
_ {
self.fatal("expected string literal")

View file

@ -184,16 +184,16 @@ fn is_lit(t: token::token) -> bool {
}
}
fn is_ident(t: token::token) -> bool {
pure fn is_ident(t: token::token) -> bool {
alt t { token::IDENT(_, _) { ret true; } _ { } }
ret false;
}
fn is_plain_ident(t: token::token) -> bool {
pure fn is_plain_ident(t: token::token) -> bool {
ret alt t { token::IDENT(_, false) { true } _ { false } };
}
fn is_bar(t: token::token) -> bool {
pure fn is_bar(t: token::token) -> bool {
alt t { token::BINOP(token::OR) | token::OROR { true } _ { false } }
}

View file

@ -59,11 +59,11 @@ type break_t = {offset: int, blank_space: int};
type begin_t = {offset: int, breaks: breaks};
enum token { STRING(str, int), BREAK(break_t), BEGIN(begin_t), END, EOF, }
enum token { STRING(@str, int), BREAK(break_t), BEGIN(begin_t), END, EOF, }
fn tok_str(t: token) -> str {
fn tok_str(++t: token) -> str {
alt t {
STRING(s, len) { ret #fmt["STR(%s,%d)", s, len]; }
STRING(s, len) { ret #fmt["STR(%s,%d)", *s, len]; }
BREAK(_) { ret "BREAK"; }
BEGIN(_) { ret "BEGIN"; }
END { ret "END"; }
@ -109,8 +109,8 @@ fn mk_printer(out: io::writer, linewidth: uint) -> printer {
mut space: linewidth as int,
mut left: 0u,
mut right: 0u,
mut token: token,
mut size: size,
token: token,
size: size,
mut left_total: 0,
mut right_total: 0,
mut scan_stack: scan_stack,
@ -206,8 +206,8 @@ type printer = @{
mut space: int, // number of spaces left on line
mut left: uint, // index of left side of input stream
mut right: uint, // index of right side of input stream
mut token: [mut token], // ring-buffr stream goes through
mut size: [mut int], // ring-buffer of calculated sizes
token: [mut token], // ring-buffr stream goes through
size: [mut int], // ring-buffer of calculated sizes
mut left_total: int, // running size of stream "...left"
mut right_total: int, // running size of stream "...right"
// pseudo-stack, really a ring too. Holds the
@ -346,7 +346,7 @@ impl printer for printer {
self.right %= self.buf_len;
assert (self.right != self.left);
}
fn advance_left(x: token, L: int) {
fn advance_left(++x: token, L: int) {
#debug("advnce_left [%u,%u], sizeof(%u)=%d", self.left, self.right,
self.left, L);
if L >= 0 {
@ -367,7 +367,7 @@ impl printer for printer {
fn check_stack(k: int) {
if !self.scan_stack_empty {
let x = self.scan_top();
alt self.token[x] {
alt copy self.token[x] {
BEGIN(b) {
if k > 0 {
self.size[self.scan_pop()] = self.size[x] +
@ -465,7 +465,7 @@ impl printer for printer {
assert (L == len);
// assert L <= space;
self.space -= len;
self.write_str(s);
self.write_str(*s);
}
EOF {
// EOF should never get here.
@ -493,14 +493,14 @@ fn end(p: printer) { p.pretty_print(END); }
fn eof(p: printer) { p.pretty_print(EOF); }
fn word(p: printer, wrd: str) {
p.pretty_print(STRING(wrd, str::len(wrd) as int));
p.pretty_print(STRING(@wrd, str::len(wrd) as int));
}
fn huge_word(p: printer, wrd: str) {
p.pretty_print(STRING(wrd, size_infinity));
p.pretty_print(STRING(@wrd, size_infinity));
}
fn zero_word(p: printer, wrd: str) { p.pretty_print(STRING(wrd, 0)); }
fn zero_word(p: printer, wrd: str) { p.pretty_print(STRING(@wrd, 0)); }
fn spaces(p: printer, n: uint) { break_offset(p, n, 0); }

View file

@ -539,6 +539,7 @@ fn print_item(s: ps, &&item: @ast::item) {
print_block(s, ctor.node.body);
option::iter(m_dtor) {|dtor|
hardbreak_if_not_bol(s);
maybe_print_comment(s, dtor.span.lo);
head(s, "drop");
print_block(s, dtor.node.body);
}
@ -1703,7 +1704,7 @@ fn print_comment(s: ps, cmnt: comments::cmnt) {
// We need to do at least one, possibly two hardbreaks.
let is_semi =
alt s.s.last_token() {
pp::STRING(s, _) { s == ";" }
pp::STRING(s, _) { *s == ";" }
_ { false }
};
if is_semi || is_begin(s) || is_end(s) { hardbreak(s.s); }

View file

@ -637,6 +637,11 @@ fn link_binary(sess: session,
// and binutils 2.22+ won't add them automatically
if sess.targ_cfg.os == session::os_linux {
cc_args += ["-lrt", "-ldl"];
// LLVM implements the `frem` instruction as a call to `fmod`,
// which lives in libm. Similar to above, on some linuxes we
// have to be explicit about linking to it. See #2510
cc_args += ["-lm"];
}
if sess.targ_cfg.os == session::os_freebsd {

View file

@ -194,7 +194,7 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
bind middle::check_loop::check_crate(ty_cx, crate));
time(time_passes, "alt checking",
bind middle::check_alt::check_crate(ty_cx, crate));
let (last_use_map, spill_map) =
let last_use_map =
time(time_passes, "liveness checking",
bind middle::liveness::check_crate(ty_cx, method_map, crate));
time(time_passes, "typestate checking",
@ -216,7 +216,7 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
let maps = {mutbl_map: mutbl_map, root_map: root_map,
copy_map: copy_map, last_use_map: last_use_map,
impl_map: impl_map, method_map: method_map,
vtable_map: vtable_map, spill_map: spill_map};
vtable_map: vtable_map};
let (llmod, link_meta) =
time(time_passes, "translation",

View file

@ -15,7 +15,8 @@ import std::map::hashmap;
import getopts::{opt_present};
import rustc::driver::driver::*;
import syntax::codemap;
import rustc::driver::{diagnostic, session};
import syntax::diagnostic;
import rustc::driver::session;
import rustc::middle::lint;
import io::reader_util;

View file

@ -9,6 +9,7 @@ import syntax::codemap::span;
import driver::session;
import session::session;
import syntax::attr;
import dvec::{dvec, extensions};
export modify_for_testing;
@ -20,7 +21,7 @@ type test_ctxt =
@{sess: session::session,
crate: @ast::crate,
mut path: [ast::ident],
mut testfns: [test]};
testfns: dvec<test>};
// Traverse the crate, collecting all the test functions, eliding any
// existing main functions, and synthesizing a main test harness
@ -40,7 +41,7 @@ fn generate_test_harness(sess: session::session,
@{sess: sess,
crate: crate,
mut path: [],
mut testfns: []};
testfns: dvec()};
let precursor =
@{fold_crate: fold::wrap(bind fold_crate(cx, _, _)),
@ -110,8 +111,8 @@ fn fold_item(cx: test_ctxt, &&i: @ast::item, fld: fold::ast_fold) ->
let test = {span: i.span,
path: cx.path, ignore: is_ignored(cx, i),
should_fail: should_fail(i)};
cx.testfns += [test];
#debug("have %u test functions", vec::len(cx.testfns));
cx.testfns.push(test);
#debug("have %u test functions", cx.testfns.len());
}
}
}
@ -269,11 +270,10 @@ fn mk_test_desc_vec_ty(cx: test_ctxt) -> @ast::ty {
}
fn mk_test_desc_vec(cx: test_ctxt) -> @ast::expr {
#debug("building test vector from %u tests", vec::len(cx.testfns));
#debug("building test vector from %u tests", cx.testfns.len());
let mut descs = [];
for cx.testfns.each {|test|
let test_ = test; // Satisfy alias analysis
descs += [mk_test_desc_rec(cx, test_)];
descs += [mk_test_desc_rec(cx, test)];
}
ret @{id: cx.sess.next_node_id(),

View file

@ -13,6 +13,7 @@ import std::map::{hashmap, int_hash};
import syntax::print::pprust;
import filesearch::filesearch;
import common::*;
import dvec::{dvec, extensions};
export read_crates;
@ -26,7 +27,7 @@ fn read_crates(diag: span_handler, crate: ast::crate,
cstore: cstore,
os: os,
static: static,
mut crate_cache: [],
crate_cache: dvec(),
mut next_crate_num: 1};
let v =
visit::mk_simple_visitor(@{visit_view_item:
@ -35,7 +36,7 @@ fn read_crates(diag: span_handler, crate: ast::crate,
with *visit::default_simple_visitor()});
visit::visit_crate(crate, (), v);
dump_crates(e.crate_cache);
warn_if_multiple_versions(diag, copy e.crate_cache);
warn_if_multiple_versions(diag, e.crate_cache.get());
}
type cache_entry = {
@ -45,7 +46,7 @@ type cache_entry = {
metas: @[@ast::meta_item]
};
fn dump_crates(crate_cache: [cache_entry]) {
fn dump_crates(crate_cache: dvec<cache_entry>) {
#debug("resolved crates:");
for crate_cache.each {|entry|
#debug("cnum: %?", entry.cnum);
@ -64,10 +65,10 @@ fn warn_if_multiple_versions(diag: span_handler,
crate_cache: [cache_entry]) {
import either::*;
if crate_cache.is_not_empty() {
if crate_cache.len() != 0u {
let name = loader::crate_name_from_metas(*crate_cache.last().metas);
let {lefts: matches, rights: non_matches} =
partition(crate_cache.map {|entry|
partition(crate_cache.map_to_vec {|entry|
let othername = loader::crate_name_from_metas(*entry.metas);
if name == othername {
left(entry)
@ -99,7 +100,7 @@ type env = @{diag: span_handler,
cstore: cstore::cstore,
os: loader::os,
static: bool,
mut crate_cache: [cache_entry],
crate_cache: dvec<cache_entry>,
mut next_crate_num: ast::crate_num};
fn visit_view_item(e: env, i: @ast::view_item) {
@ -176,12 +177,14 @@ fn metas_with_ident(ident: ast::ident,
fn existing_match(e: env, metas: [@ast::meta_item], hash: str) ->
option<int> {
let maybe_entry = e.crate_cache.find {|c|
loader::metadata_matches(*c.metas, metas) &&
(hash.is_empty() || c.hash == hash)
};
maybe_entry.map {|c| c.cnum }
for e.crate_cache.each {|c|
if loader::metadata_matches(*c.metas, metas)
&& (hash.is_empty() || c.hash == hash) {
ret some(c.cnum);
}
}
ret none;
}
fn resolve_crate(e: env, ident: ast::ident, metas: [@ast::meta_item],
@ -211,8 +214,8 @@ fn resolve_crate(e: env, ident: ast::ident, metas: [@ast::meta_item],
// Claim this crate number and cache it
let cnum = e.next_crate_num;
e.crate_cache += [{cnum: cnum, span: span,
hash: hash, metas: @linkage_metas}];
e.crate_cache.push({cnum: cnum, span: span,
hash: hash, metas: @linkage_metas});
e.next_crate_num += 1;
// Now resolve the crates referenced by this crate

View file

@ -63,7 +63,9 @@ type cstore_private =
type use_crate_map = map::hashmap<ast::node_id, ast::crate_num>;
// Internal method to retrieve the data from the cstore
fn p(cstore: cstore) -> cstore_private { alt cstore { private(p) { p } } }
pure fn p(cstore: cstore) -> cstore_private {
alt cstore { private(p) { p } }
}
fn mk_cstore() -> cstore {
let meta_cache = map::int_hash::<crate_metadata>();

View file

@ -7,7 +7,6 @@ import syntax::{ast, ast_util};
import syntax::attr;
import middle::ty;
import syntax::ast_map;
import common::*;
import tydecode::{parse_ty_data, parse_def_id, parse_bounds_data,
parse_ident};
import syntax::print::pprust;
@ -15,6 +14,7 @@ import cmd=cstore::crate_metadata;
import util::ppaux::ty_to_str;
import ebml::deserializer;
import syntax::diagnostic::span_handler;
import common::*;
export class_dtor;
export get_class_fields;

View file

@ -57,7 +57,6 @@ type maps = {
impl_map: middle::resolve::impl_map,
method_map: middle::typeck::method_map,
vtable_map: middle::typeck::vtable_map,
spill_map: middle::liveness::spill_map
};
type decode_ctxt = @{
@ -839,12 +838,6 @@ fn encode_side_tables_for_id(ecx: @e::encode_ctxt,
}
}
option::iter(maps.spill_map.find(id)) {|_m|
ebml_w.tag(c::tag_table_spill) {||
ebml_w.id(id);
}
}
option::iter(maps.last_use_map.find(id)) {|m|
ebml_w.tag(c::tag_table_last_use) {||
ebml_w.id(id);
@ -953,8 +946,6 @@ fn decode_side_tables(xcx: extended_decode_ctxt,
dcx.maps.mutbl_map.insert(id, ());
} else if tag == (c::tag_table_copy as uint) {
dcx.maps.copy_map.insert(id, ());
} else if tag == (c::tag_table_spill as uint) {
dcx.maps.spill_map.insert(id, ());
} else {
let val_doc = entry_doc[c::tag_table_val];
let val_dsr = ebml::ebml_deserializer(val_doc);

View file

@ -164,6 +164,7 @@ import util::common::indenter;
import ast_util::op_expr_callee_id;
import ty::to_str;
import driver::session::session;
import dvec::{dvec, extensions};
export check_crate, root_map, mutbl_map;
@ -298,7 +299,7 @@ type loan = {lp: @loan_path, cmt: cmt, mutbl: ast::mutability};
// maps computed by `gather_loans` that are then used by `check_loans`
type req_maps = {
req_loan_map: hashmap<ast::node_id, @mut [@const [loan]]>,
req_loan_map: hashmap<ast::node_id, @dvec<@dvec<loan>>>,
pure_map: hashmap<ast::node_id, bckerr>
};

View file

@ -7,7 +7,15 @@ determine what kind of memory is used in evaluating it (for example,
where dereferences occur and what kind of pointer is dereferenced;
whether the memory is mutable; etc)
Categorization effectively transforms all of our expressions into
expressions of the following forms (the actual enum has many more
possibilities, naturally, but they are all variants of these base
forms):
E = rvalue // some computed rvalue
| x // address of a local variable, arg, or upvar
| *E // deref of a ptr
| E.comp // access to an interior component
Imagine a routine ToAddr(Expr) that evaluates an expression and returns an
address where the result is to be found. If Expr is an lvalue, then this

View file

@ -7,6 +7,7 @@
// 3. assignments do not affect things loaned out as immutable
// 4. moves to dnot affect things loaned out in any way
import dvec::{dvec, extensions};
import categorization::public_methods;
export check_loans;
@ -22,7 +23,7 @@ enum check_loan_ctxt = @{
// we are in a ctor, we track the self id
mut in_ctor: bool,
mut declared_purity: ast::purity,
mut fn_args: [ast::node_id]
mut fn_args: @[ast::node_id]
};
// if we are enforcing purity, why are we doing so?
@ -44,7 +45,7 @@ fn check_loans(bccx: borrowck_ctxt,
reported: int_hash(),
mut in_ctor: false,
mut declared_purity: ast::impure_fn,
mut fn_args: []});
mut fn_args: @[]});
let vt = visit::mk_vt(@{visit_expr: check_loans_in_expr,
visit_block: check_loans_in_block,
visit_fn: check_loans_in_fn
@ -179,7 +180,7 @@ impl methods for check_loan_ctxt {
let did = ast_util::def_id_of_def(def);
let is_fn_arg =
did.crate == ast::local_crate &&
self.fn_args.contains(did.node);
(*self.fn_args).contains(did.node);
if is_fn_arg { ret; } // case (a) above
}
ast::expr_fn_block(*) | ast::expr_fn(*) |
@ -225,7 +226,8 @@ impl methods for check_loan_ctxt {
ast::expr_path(_) {
let def = self.tcx().def_map.get(expr.id);
let did = ast_util::def_id_of_def(def);
did.crate == ast::local_crate && self.fn_args.contains(did.node)
did.crate == ast::local_crate &&
(*self.fn_args).contains(did.node)
}
ast::expr_fn_block(*) | ast::expr_fn(*) {
self.is_stack_closure(expr.id)
@ -484,7 +486,7 @@ fn check_loans_in_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk,
sp: span, id: ast::node_id, &&self: check_loan_ctxt,
visitor: visit::vt<check_loan_ctxt>) {
#debug["purity on entry=%?", self.declared_purity];
#debug["purity on entry=%?", copy self.declared_purity];
save_and_restore(self.in_ctor) {||
save_and_restore(self.declared_purity) {||
save_and_restore(self.fn_args) {||
@ -500,7 +502,7 @@ fn check_loans_in_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk,
visit::fk_ctor(*) {
self.in_ctor = true;
self.declared_purity = decl.purity;
self.fn_args = decl.inputs.map({|i| i.id});
self.fn_args = @decl.inputs.map({|i| i.id});
}
visit::fk_anon(*) |
visit::fk_fn_block(*) if is_stack_closure {
@ -512,7 +514,7 @@ fn check_loans_in_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk,
visit::fk_res(*) | visit::fk_dtor(*) {
self.in_ctor = false;
self.declared_purity = decl.purity;
self.fn_args = decl.inputs.map({|i| i.id});
self.fn_args = @decl.inputs.map({|i| i.id});
}
}
@ -520,7 +522,7 @@ fn check_loans_in_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk,
}
}
}
#debug["purity on exit=%?", self.declared_purity];
#debug["purity on exit=%?", copy self.declared_purity];
}
fn check_loans_in_expr(expr: @ast::expr,

View file

@ -84,15 +84,24 @@ fn req_loans_in_expr(ex: @ast::expr,
// the pointer to be borrowed as immutable even if it
// is mutable in the caller's frame, thus effectively
// passing the buck onto us to enforce this)
//
// FIXME---this handling is not really adequate. For
// example, if there is a type like, {f: [int]}, we
// will ignore it, but we ought to be requiring it to
// be immutable (whereas something like {f:int} would
// be fine).
alt opt_deref_kind(arg_ty.ty) {
some(deref_ptr(region_ptr)) {
some(deref_ptr(region_ptr)) |
some(deref_ptr(unsafe_ptr)) {
/* region pointers are (by induction) guaranteed */
/* unsafe pointers are the user's problem */
}
some(deref_comp(_)) |
none {
/* not a pointer, no worries */
}
some(_) {
some(deref_ptr(_)) {
let arg_cmt = self.bccx.cat_borrow_of_expr(arg);
self.guarantee_valid(arg_cmt, m_const, scope_r);
}
@ -264,13 +273,14 @@ impl methods for gather_loan_ctxt {
}
}
fn add_loans(scope_id: ast::node_id, loans: @const [loan]) {
fn add_loans(scope_id: ast::node_id, loans: @dvec<loan>) {
alt self.req_maps.req_loan_map.find(scope_id) {
some(l) {
*l += [loans];
(*l).push(loans);
}
none {
self.req_maps.req_loan_map.insert(scope_id, @mut [loans]);
self.req_maps.req_loan_map.insert(
scope_id, @dvec::from_vec([mut loans]));
}
}
}

View file

@ -5,8 +5,8 @@
export public_methods;
impl public_methods for borrowck_ctxt {
fn loan(cmt: cmt, mutbl: ast::mutability) -> @const [loan] {
let lc = @{bccx: self, loans: @mut []};
fn loan(cmt: cmt, mutbl: ast::mutability) -> @dvec<loan> {
let lc = @{bccx: self, loans: @dvec()};
lc.loan(cmt, mutbl);
ret lc.loans;
}
@ -14,7 +14,7 @@ impl public_methods for borrowck_ctxt {
type loan_ctxt = @{
bccx: borrowck_ctxt,
loans: @mut [loan]
loans: @dvec<loan>
};
impl loan_methods for loan_ctxt {
@ -23,9 +23,9 @@ impl loan_methods for loan_ctxt {
// Note: all cmt's that we deal with will have a non-none lp, because
// the entry point into this routine, `borrowck_ctxt::loan()`, rejects
// any cmt with a none-lp.
*self.loans += [{lp:option::get(cmt.lp),
cmt:cmt,
mutbl:mutbl}];
(*self.loans).push({lp:option::get(cmt.lp),
cmt:cmt,
mutbl:mutbl});
}
fn loan(cmt: cmt, req_mutbl: ast::mutability) {

View file

@ -2,6 +2,7 @@ import syntax::ast::*;
import syntax::{visit, ast_util, ast_map};
import driver::session::session;
import std::map::hashmap;
import dvec::{dvec, extensions};
fn check_crate(sess: session, crate: @crate, ast_map: ast_map::map,
def_map: resolve::def_map,
@ -130,7 +131,7 @@ fn check_item_recursion(sess: session, ast_map: ast_map::map,
sess: session,
ast_map: ast_map::map,
def_map: resolve::def_map,
idstack: @mut [node_id],
idstack: @dvec<node_id>,
};
let env = {
@ -138,7 +139,7 @@ fn check_item_recursion(sess: session, ast_map: ast_map::map,
sess: sess,
ast_map: ast_map,
def_map: def_map,
idstack: @mut []
idstack: @dvec()
};
let visitor = visit::mk_vt(@{
@ -152,9 +153,9 @@ fn check_item_recursion(sess: session, ast_map: ast_map::map,
if (*env.idstack).contains(it.id) {
env.sess.span_fatal(env.root_it.span, "recursive constant");
}
vec::push(*env.idstack, it.id);
(*env.idstack).push(it.id);
visit::visit_item(it, env, v);
vec::pop(*env.idstack);
(*env.idstack).pop();
}
fn visit_expr(e: @expr, &&env: env, v: visit::vt<env>) {

View file

@ -57,7 +57,6 @@ import capture::{cap_move, cap_drop, cap_copy, cap_ref};
export check_crate;
export last_use_map;
export spill_map;
// Maps from an expr id to a list of variable ids for which this expr
// is the last use. Typically, the expr is a path and the node id is
@ -66,13 +65,6 @@ export spill_map;
// list of closed over variables that can be moved into the closure.
type last_use_map = hashmap<node_id, @dvec<node_id>>;
// A set of variable ids which must be spilled (stored on the stack).
// We add in any variables or arguments where:
// (1) the variables are moved;
// (2) the address of the variable/argument is taken;
// or (3) we find a last use (as they may be moved).
type spill_map = hashmap<node_id, ()>;
enum variable = uint;
enum live_node = uint;
@ -85,7 +77,7 @@ enum live_node_kind {
fn check_crate(tcx: ty::ctxt,
method_map: typeck::method_map,
crate: @crate) -> (last_use_map, spill_map) {
crate: @crate) -> last_use_map {
let visitor = visit::mk_vt(@{
visit_fn: visit_fn,
visit_local: visit_local,
@ -94,12 +86,11 @@ fn check_crate(tcx: ty::ctxt,
});
let last_use_map = int_hash();
let spill_map = int_hash();
let initial_maps = @ir_maps(tcx, method_map,
last_use_map, spill_map);
last_use_map);
visit::visit_crate(*crate, initial_maps, visitor);
tcx.sess.abort_if_errors();
ret (last_use_map, spill_map);
ret last_use_map;
}
impl of to_str::to_str for live_node {
@ -133,7 +124,7 @@ impl of to_str::to_str for variable {
// assignment. And so forth.
impl methods for live_node {
fn is_valid() -> bool { *self != uint::max_value }
pure fn is_valid() -> bool { *self != uint::max_value }
}
fn invalid_node() -> live_node { live_node(uint::max_value) }
@ -162,7 +153,6 @@ class ir_maps {
let tcx: ty::ctxt;
let method_map: typeck::method_map;
let last_use_map: last_use_map;
let spill_map: spill_map;
let mut num_live_nodes: uint;
let mut num_vars: uint;
@ -174,11 +164,10 @@ class ir_maps {
let mut lnks: [live_node_kind];
new(tcx: ty::ctxt, method_map: typeck::method_map,
last_use_map: last_use_map, spill_map: spill_map) {
last_use_map: last_use_map) {
self.tcx = tcx;
self.method_map = method_map;
self.last_use_map = last_use_map;
self.spill_map = spill_map;
self.num_live_nodes = 0u;
self.num_vars = 0u;
@ -264,17 +253,6 @@ class ir_maps {
self.lnks[*ln]
}
fn add_spill(var: variable) {
let vk = self.var_kinds[*var];
alt vk {
vk_local(id, _) | vk_arg(id, _, by_val) {
#debug["adding spill for %?", vk];
self.spill_map.insert(id, ());
}
vk_arg(*) | vk_field(_) | vk_self | vk_implicit_ret {}
}
}
fn add_last_use(expr_id: node_id, var: variable) {
let vk = self.var_kinds[*var];
#debug["Node %d is a last use of variable %?", expr_id, vk];
@ -308,7 +286,7 @@ fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk,
// swap in a new set of IR maps for this function body:
let fn_maps = @ir_maps(self.tcx, self.method_map,
self.last_use_map, self.spill_map);
self.last_use_map);
#debug["creating fn_maps: %x", ptr::addr_of(*fn_maps) as uint];
@ -571,7 +549,7 @@ class liveness {
fn live_on_exit(ln: live_node, var: variable)
-> option<live_node_kind> {
self.live_on_entry(self.successors[*ln], var)
self.live_on_entry(copy self.successors[*ln], var)
}
fn used_on_entry(ln: live_node, var: variable) -> bool {
@ -590,7 +568,7 @@ class liveness {
fn assigned_on_exit(ln: live_node, var: variable)
-> option<live_node_kind> {
self.assigned_on_entry(self.successors[*ln], var)
self.assigned_on_entry(copy self.successors[*ln], var)
}
fn indices(ln: live_node, op: fn(uint)) {
@ -627,14 +605,14 @@ class liveness {
wr.write_str("[ln(");
wr.write_uint(*ln);
wr.write_str(") of kind ");
wr.write_str(#fmt["%?", self.ir.lnks[*ln]]);
wr.write_str(#fmt["%?", copy self.ir.lnks[*ln]]);
wr.write_str(" reads");
self.write_vars(wr, ln, {|idx| self.users[idx].reader});
wr.write_str(" writes");
self.write_vars(wr, ln, {|idx| self.users[idx].writer});
wr.write_str(" ");
wr.write_str(" precedes ");
wr.write_str(self.successors[*ln].to_str());
wr.write_str((copy self.successors[*ln]).to_str());
wr.write_str("]");
}
}
@ -668,9 +646,9 @@ class liveness {
let mut changed = false;
self.indices2(ln, succ_ln) { |idx, succ_idx|
changed |= copy_if_invalid(self.users[succ_idx].reader,
changed |= copy_if_invalid(copy self.users[succ_idx].reader,
self.users[idx].reader);
changed |= copy_if_invalid(self.users[succ_idx].writer,
changed |= copy_if_invalid(copy self.users[succ_idx].writer,
self.users[idx].writer);
if self.users[succ_idx].used && !self.users[idx].used {
self.users[idx].used = true;
@ -1407,11 +1385,7 @@ fn check_expr(expr: @expr, &&self: @liveness, vt: vt<@liveness>) {
vt.visit_expr(f, self, vt);
vec::iter2(args, targs) { |arg_expr, arg_ty|
alt ty::resolved_mode(self.tcx, arg_ty.mode) {
by_val | by_copy {
vt.visit_expr(arg_expr, self, vt);
}
by_ref | by_mutbl_ref {
self.spill_expr(arg_expr);
by_val | by_copy | by_ref | by_mutbl_ref{
vt.visit_expr(arg_expr, self, vt);
}
by_move {
@ -1421,10 +1395,6 @@ fn check_expr(expr: @expr, &&self: @liveness, vt: vt<@liveness>) {
}
}
expr_addr_of(_, arg_expr) {
self.spill_expr(arg_expr);
}
// no correctness conditions related to liveness
expr_if_check(*) | expr_if(*) | expr_alt(*) |
expr_while(*) | expr_loop(*) |
@ -1434,7 +1404,7 @@ fn check_expr(expr: @expr, &&self: @liveness, vt: vt<@liveness>) {
expr_assert(*) | expr_check(*) | expr_copy(*) |
expr_loop_body(*) | expr_cast(*) | expr_unary(*) | expr_fail(*) |
expr_ret(*) | expr_break | expr_cont | expr_lit(_) |
expr_block(*) | expr_swap(*) | expr_mac(*) {
expr_block(*) | expr_swap(*) | expr_mac(*) | expr_addr_of(*) {
visit::visit_expr(expr, self, vt);
}
}
@ -1501,10 +1471,7 @@ impl check_methods for @liveness {
ln.to_str(), var.to_str()];
alt (*self).live_on_exit(ln, var) {
none {
// update spill map to include this variable, as it is moved:
(*self.ir).add_spill(var);
}
none { }
some(lnk) {
self.report_illegal_move(span, lnk, var);
}
@ -1516,20 +1483,10 @@ impl check_methods for @liveness {
some(_) {}
none {
(*self.ir).add_last_use(expr.id, var);
// update spill map to include this variable, as it may be moved:
(*self.ir).add_spill(var);
}
}
}
fn spill_expr(expr: @expr) {
alt (*self).variable_from_path(expr) {
some(var) {(*self.ir).add_spill(var)}
none {}
}
}
fn check_move_from_expr(expr: @expr, vt: vt<@liveness>) {
#debug["check_move_from_expr(node %d: %s)",
expr.id, expr_to_str(expr)];
@ -1775,4 +1732,4 @@ impl check_methods for @liveness {
}
}
}
}
}

View file

@ -100,7 +100,7 @@ type glob_imp_def = {def: def, path: @ast::view_path};
type indexed_mod = {
m: option<ast::_mod>,
index: mod_index,
mut glob_imports: [glob_imp_def],
glob_imports: dvec<glob_imp_def>,
mut globbed_exports: [ident],
glob_imported_names: hashmap<str, glob_import_state>,
path: str
@ -123,7 +123,7 @@ type env =
def_map: def_map,
ast_map: ast_map::map,
imports: hashmap<node_id, import_state>,
mut exp_map: exp_map,
exp_map: exp_map,
mod_map: hashmap<node_id, @indexed_mod>,
block_map: hashmap<node_id, [glob_imp_def]>,
ext_map: ext_map,
@ -132,7 +132,7 @@ type env =
ext_cache: ext_hash,
used_imports: {mut track: bool,
mut data: [node_id]},
mut reported: [{ident: str, sc: scope}],
reported: dvec<{ident: str, sc: scope}>,
mut ignored_imports: [node_id],
mut current_tp: option<uint>,
mut resolve_unexported: bool,
@ -174,7 +174,7 @@ fn create_env(sess: session, amap: ast_map::map) -> @env {
def_map: int_hash(),
ast_map: amap,
imports: int_hash(),
mut exp_map: int_hash(),
exp_map: int_hash(),
mod_map: int_hash(),
block_map: int_hash(),
ext_map: new_def_hash(),
@ -182,7 +182,7 @@ fn create_env(sess: session, amap: ast_map::map) -> @env {
impl_cache: new_def_hash(),
ext_cache: new_ext_hash(),
used_imports: {mut track: false, mut data: []},
mut reported: [],
reported: dvec(),
mut ignored_imports: [],
mut current_tp: none,
mut resolve_unexported: false,
@ -270,7 +270,7 @@ fn map_crate(e: @env, c: @ast::crate) {
e.mod_map.insert(i.id,
@{m: some(md),
index: index_mod(md),
mut glob_imports: [],
glob_imports: dvec(),
mut globbed_exports: [],
glob_imported_names: str_hash(),
path: path_from_scope(sc, i.ident)});
@ -279,7 +279,7 @@ fn map_crate(e: @env, c: @ast::crate) {
e.mod_map.insert(i.id,
@{m: none::<ast::_mod>,
index: index_nmod(nmd),
mut glob_imports: [],
glob_imports: dvec(),
mut globbed_exports: [],
glob_imported_names: str_hash(),
path: path_from_scope(sc, i.ident)});
@ -301,7 +301,7 @@ fn map_crate(e: @env, c: @ast::crate) {
let glob = {def: imp, path: vp};
alt list::head(sc) {
scope_item(i) {
e.mod_map.get(i.id).glob_imports += [glob];
e.mod_map.get(i.id).glob_imports.push(glob);
}
scope_block(b, _, _) {
let globs = alt e.block_map.find(b.node.id) {
@ -311,8 +311,8 @@ fn map_crate(e: @env, c: @ast::crate) {
e.block_map.insert(b.node.id, globs);
}
scope_crate {
e.mod_map.get(ast::crate_node_id).glob_imports
+= [glob];
e.mod_map.get(ast::crate_node_id).
glob_imports.push(glob);
}
_ { e.sess.span_bug(vi.span, "unexpected scope in a \
glob import"); }
@ -338,7 +338,7 @@ fn map_crate(e: @env, c: @ast::crate) {
e.mod_map.insert(ast::crate_node_id,
@{m: some(c.node.module),
index: index_mod(c.node.module),
mut glob_imports: [],
glob_imports: dvec(),
mut globbed_exports: [],
glob_imported_names: str_hash(),
path: ""});
@ -899,7 +899,7 @@ fn unresolved_err(e: env, cx: ctxt, sp: span, name: ident, kind: str) {
for e.reported.each {|rs|
if str::eq(rs.ident, name) && err_scope == rs.sc { ret; }
}
e.reported += [{ident: name, sc: err_scope}];
e.reported.push({ident: name, sc: err_scope});
}
_ {}
}
@ -1536,7 +1536,7 @@ fn lookup_glob_in_mod(e: env, info: @indexed_mod, sp: span, id: ident,
// absence takes the place of todo()
if !info.glob_imported_names.contains_key(id) {
info.glob_imported_names.insert(id, glob_resolving(sp));
let globs = info.glob_imports;
let globs = info.glob_imports.get();
let val = lookup_in_globs(e, globs, sp, id, ns_val, dr);
let typ = lookup_in_globs(e, globs, sp, id, ns_type, dr);
let md = lookup_in_globs(e, globs, sp, id, ns_module, dr);

View file

@ -62,6 +62,12 @@ enum dest {
ignore,
}
// Heap selectors. Indicate which heap something should go on.
enum heap {
heap_shared,
heap_exchange,
}
fn dest_str(ccx: @crate_ctxt, d: dest) -> str {
alt d {
by_val(v) { #fmt["by_val(%s)", val_str(ccx.tn, *v)] }
@ -341,75 +347,61 @@ fn opaque_box_body(bcx: block,
PointerCast(bcx, bodyptr, T_ptr(type_of(ccx, body_t)))
}
// trans_malloc_boxed_raw: expects an unboxed type and returns a pointer to
// malloc_raw: expects an unboxed type and returns a pointer to
// enough space for a box of that type. This includes a rust_opaque_box
// header.
fn malloc_boxed_raw(bcx: block, t: ty::t,
&static_ti: option<@tydesc_info>) -> ValueRef {
let _icx = bcx.insn_ctxt("trans_malloc_boxed_raw");
fn malloc_raw(bcx: block, t: ty::t, heap: heap) -> ValueRef {
let _icx = bcx.insn_ctxt("malloc_raw");
let ccx = bcx.ccx();
// Grab the TypeRef type of box_ptr, because that's what trans_raw_malloc
// wants.
let box_ptr = ty::mk_imm_box(ccx.tcx, t);
let llty = type_of(ccx, box_ptr);
let (mk_fn, upcall) = alt heap {
heap_shared { (ty::mk_imm_box, ccx.upcalls.malloc) }
heap_exchange {
(ty::mk_imm_uniq, ccx.upcalls.exchange_malloc )
}
};
// Get the tydesc for the body:
let lltydesc = get_tydesc(ccx, t, static_ti);
lazily_emit_all_tydesc_glue(ccx, copy static_ti);
// Allocate space:
let rval = Call(bcx, ccx.upcalls.malloc, [lltydesc]);
ret PointerCast(bcx, rval, llty);
}
// trans_malloc_boxed: usefully wraps trans_malloc_box_raw; allocates a box,
// initializes the reference count to 1, and pulls out the body and rc
fn malloc_boxed(bcx: block, t: ty::t) -> {box: ValueRef, body: ValueRef} {
let _icx = bcx.insn_ctxt("trans_malloc_boxed");
let mut ti = none;
let box = malloc_boxed_raw(bcx, t, ti);
let box_no_addrspace = non_gc_box_cast(
bcx, box, ty::mk_imm_box(bcx.tcx(), t));
let body = GEPi(bcx, box_no_addrspace, [0u, abi::box_field_body]);
ret {box: box, body: body};
}
fn malloc_unique_raw(bcx: block, t: ty::t) -> ValueRef {
let _icx = bcx.insn_ctxt("malloc_unique_box_raw");
let ccx = bcx.ccx();
// Grab the TypeRef type of box_ptr, because that's what trans_raw_malloc
// wants.
let box_ptr = ty::mk_imm_uniq(ccx.tcx, t);
let llty = type_of(ccx, box_ptr);
// Grab the TypeRef type of box_ptr_ty.
let box_ptr_ty = mk_fn(bcx.tcx(), t);
let llty = type_of(ccx, box_ptr_ty);
// Get the tydesc for the body:
let mut static_ti = none;
let lltydesc = get_tydesc(ccx, t, static_ti);
lazily_emit_all_tydesc_glue(ccx, static_ti);
lazily_emit_all_tydesc_glue(ccx, copy static_ti);
// Allocate space:
let rval = Call(bcx, ccx.upcalls.exchange_malloc, [lltydesc]);
let rval = Call(bcx, upcall, [lltydesc]);
ret PointerCast(bcx, rval, llty);
}
fn malloc_unique(bcx: block, t: ty::t) -> {box: ValueRef, body: ValueRef} {
let _icx = bcx.insn_ctxt("malloc_unique_box");
let box = malloc_unique_raw(bcx, t);
let non_gc_box = non_gc_box_cast(bcx, box, ty::mk_imm_uniq(bcx.tcx(), t));
// malloc_general: usefully wraps malloc_raw; allocates a box,
// and pulls out the body
fn malloc_general(bcx: block, t: ty::t, heap: heap) ->
{box: ValueRef, body: ValueRef} {
let _icx = bcx.insn_ctxt("malloc_general");
let mk_ty = alt heap { heap_shared { ty::mk_imm_box }
heap_exchange { ty::mk_imm_uniq } };
let box = malloc_raw(bcx, t, heap);
let non_gc_box = non_gc_box_cast(bcx, box, mk_ty(bcx.tcx(), t));
let body = GEPi(bcx, non_gc_box, [0u, abi::box_field_body]);
ret {box: box, body: body};
}
fn malloc_boxed(bcx: block, t: ty::t) -> {box: ValueRef, body: ValueRef} {
malloc_general(bcx, t, heap_shared)
}
fn malloc_unique(bcx: block, t: ty::t) -> {box: ValueRef, body: ValueRef} {
malloc_general(bcx, t, heap_exchange)
}
fn malloc_unique_dyn_raw(bcx: block, t: ty::t, size: ValueRef) -> ValueRef {
let _icx = bcx.insn_ctxt("malloc_unique_box_raw");
let _icx = bcx.insn_ctxt("malloc_unique_dyn_raw");
let ccx = bcx.ccx();
// Grab the TypeRef type of box_ptr, because that's what trans_raw_malloc
// wants.
let box_ptr = ty::mk_imm_uniq(ccx.tcx, t);
let llty = type_of(ccx, box_ptr);
// Grab the TypeRef type of box_ptr_ty.
let box_ptr_ty = ty::mk_imm_uniq(ccx.tcx, t);
let llty = type_of(ccx, box_ptr_ty);
// Get the tydesc for the body:
let mut static_ti = none;
@ -423,7 +415,7 @@ fn malloc_unique_dyn_raw(bcx: block, t: ty::t, size: ValueRef) -> ValueRef {
fn malloc_unique_dyn(bcx: block, t: ty::t, size: ValueRef
) -> {box: ValueRef, body: ValueRef} {
let _icx = bcx.insn_ctxt("malloc_unique_box");
let _icx = bcx.insn_ctxt("malloc_unique_dyn");
let box = malloc_unique_dyn_raw(bcx, t, size);
let body = GEPi(bcx, box, [0u, abi::box_field_body]);
ret {box: box, body: body};
@ -1194,7 +1186,7 @@ fn lazily_emit_tydesc_glue(ccx: @crate_ctxt, field: uint,
}
}
} else if field == abi::tydesc_field_visit_glue {
alt ti.free_glue {
alt ti.visit_glue {
some(_) { }
none {
#debug("+++ lazily_emit_tydesc_glue VISIT %s",
@ -1230,6 +1222,8 @@ fn call_tydesc_glue_full(cx: block, v: ValueRef, tydesc: ValueRef,
static_glue_fn = sti.drop_glue;
} else if field == abi::tydesc_field_free_glue {
static_glue_fn = sti.free_glue;
} else if field == abi::tydesc_field_visit_glue {
static_glue_fn = sti.visit_glue;
}
}
}
@ -3749,6 +3743,8 @@ fn lval_to_dps(bcx: block, e: @ast::expr, dest: dest) -> block {
let ty = expr_ty(bcx, e);
let lv = trans_lval(bcx, e);
let last_use = (lv.kind == owned && last_use_map.contains_key(e.id));
#debug["is last use (%s) = %b, %d", expr_to_str(e), last_use,
lv.kind as int];
lval_result_to_dps(lv, ty, last_use, dest)
}
@ -4039,29 +4035,10 @@ fn init_local(bcx: block, local: @ast::local) -> block {
let ty = node_id_type(bcx, local.node.id);
let llptr = alt bcx.fcx.lllocals.find(local.node.id) {
some(local_mem(v)) { v }
some(_) { bcx.tcx().sess.span_bug(local.span,
_ { bcx.tcx().sess.span_bug(local.span,
"init_local: Someone forgot to document why it's\
safe to assume local.node.init must be local_mem!");
}
// This is a local that is kept immediate
none {
let initexpr = alt local.node.init {
some({expr, _}) { expr }
none { bcx.tcx().sess.span_bug(local.span,
"init_local: late-initialized var appears to \
be an immediate -- possibly init_local was called \
without calling alloc_local"); }
};
let mut {bcx, val, kind} = trans_temp_lval(bcx, initexpr);
if kind != temporary {
if kind == owned { val = Load(bcx, val); }
let rs = take_ty_immediate(bcx, val, ty);
bcx = rs.bcx; val = rs.val;
add_clean_temp(bcx, val, ty);
}
bcx.fcx.lllocals.insert(local.node.pat.id, local_imm(val));
ret bcx;
}
};
let mut bcx = bcx;
@ -4341,17 +4318,6 @@ fn alloc_local(cx: block, local: @ast::local) -> block {
ast::pat_ident(pth, none) { some(path_to_ident(pth)) }
_ { none }
};
// Do not allocate space for locals that can be kept immediate.
let ccx = cx.ccx();
if option::is_some(simple_name) &&
!ccx.maps.mutbl_map.contains_key(local.node.pat.id) &&
!ccx.maps.spill_map.contains_key(local.node.pat.id) &&
ty::type_is_immediate(t) {
alt local.node.init {
some({op: ast::init_assign, _}) { ret cx; }
_ {}
}
}
let val = alloc_ty(cx, t);
if cx.sess().opts.debuginfo {
option::iter(simple_name) {|name|

View file

@ -175,11 +175,12 @@ fn allocate_cbox(bcx: block,
let mut temp_cleanups = [];
let (bcx, box) = alt ck {
ty::ck_box {
let box = malloc_boxed_raw(bcx, cdata_ty, ti);
get_tydesc(ccx, cdata_ty, ti);
let box = malloc_raw(bcx, cdata_ty, heap_shared);
(bcx, box)
}
ty::ck_uniq {
let box = malloc_unique_raw(bcx, cdata_ty);
let box = malloc_raw(bcx, cdata_ty, heap_exchange);
(bcx, box)
}
ty::ck_block {

View file

@ -24,29 +24,30 @@ fn visit_ty_steps(bcx: block, t: ty::t,
ty::ty_bool { step(bcx, "visit_bool", []) }
ty::ty_int(ast::ty_i) { step(bcx, "visit_int", []) }
ty::ty_int(ast::ty_char) { step(bcx, "visit_char", []) }
ty::ty_int(ast::ty_i8) { step(bcx, "visit_i8", []) }
ty::ty_int(ast::ty_i16) { step(bcx, "visit_i16", []) }
ty::ty_int(ast::ty_i32) { step(bcx, "visit_i32", []) }
ty::ty_int(ast::ty_i64) { step(bcx, "visit_i64", []) }
ty::ty_uint(ast::ty_u) { step(bcx, "visit_uint", []) }
ty::ty_uint(ast::ty_u8) { step(bcx, "visit_u8", []) }
ty::ty_uint(ast::ty_u16) { step(bcx, "visit_u16", []) }
ty::ty_uint(ast::ty_u32) { step(bcx, "visit_u32", []) }
ty::ty_uint(ast::ty_u64) { step(bcx, "visit_u64", []) }
ty::ty_float(ast::ty_f) { step(bcx, "visit_float", []) }
ty::ty_float(ast::ty_f32) { step(bcx, "visit_f32", []) }
ty::ty_float(ast::ty_f64) { step(bcx, "visit_f64", []) }
ty::ty_str { step(bcx, "visit_str", []) }
ty::ty_int(ast::ty_i8) { step(bcx, "visit_i8", []) }
ty::ty_int(ast::ty_i16) { step(bcx, "visit_i16", []) }
ty::ty_int(ast::ty_i32) { step(bcx, "visit_i32", []) }
ty::ty_int(ast::ty_i64) { step(bcx, "visit_i64", []) }
ty::ty_uint(ast::ty_u) { step(bcx, "visit_uint", []) }
ty::ty_uint(ast::ty_u8) { step(bcx, "visit_u8", []) }
ty::ty_uint(ast::ty_u16) { step(bcx, "visit_u16", []) }
ty::ty_uint(ast::ty_u32) { step(bcx, "visit_u32", []) }
ty::ty_uint(ast::ty_u64) { step(bcx, "visit_u64", []) }
ty::ty_float(ast::ty_f) { step(bcx, "visit_float", []) }
ty::ty_float(ast::ty_f32) { step(bcx, "visit_f32", []) }
ty::ty_float(ast::ty_f64) { step(bcx, "visit_f64", []) }
ty::ty_str { step(bcx, "visit_str", []) }
ty::ty_vec(mt) {
let bcx = step(bcx, "visit_vec_of",
[C_uint(ccx, mt.mutbl as uint)]);
sub(bcx, mt.ty)
}
ty::ty_vec(mt) {
let bcx = step(bcx, "visit_vec_of",
[C_uint(ccx, mt.mutbl as uint)]);
sub(bcx, mt.ty)
}
_ {
bcx.sess().unimpl("trans::reflect::visit_ty_args on "
+ ty_to_str(bcx.ccx().tcx, t));
// Ideally this would be an unimpl, but sadly we have
// to pretend we can visit everything at this point.
step(bcx, "visit_bot", [])
}
}
}

View file

@ -13,9 +13,9 @@ import tstate::ann::{pre_and_post, pre_and_post_state, empty_ann, prestate,
set_postcondition, ts_ann,
clear_in_postcond,
clear_in_poststate_};
import tritv::*;
import bitvectors::promises_;
import driver::session::session;
import dvec::{dvec, extensions};
import tritv::{dont_care, tfalse, tritv_get, ttrue};
import syntax::print::pprust::{constr_args_to_str, lit_to_str};
@ -197,7 +197,7 @@ type constraint = {
path: @path,
// FIXME: really only want it to be mut during collect_locals.
// freeze it after that.
descs: @mut [pred_args]
descs: @dvec<pred_args>
};
type tsconstr = {
@ -473,8 +473,7 @@ fn node_id_to_def(ccx: crate_ctxt, id: node_id) -> option<def> {
fn norm_a_constraint(id: def_id, c: constraint) -> [norm_constraint] {
let mut rslt: [norm_constraint] = [];
let descs = *c.descs;
for vec::each(descs) {|pd|
for (*c.descs).each {|pd|
rslt +=
[{bit_num: pd.node.bit_num,
c: respan(pd.span, {path: c.path,
@ -498,11 +497,11 @@ fn constraints(fcx: fn_ctxt) -> [norm_constraint] {
// FIXME
// Would rather take an immutable vec as an argument,
// should freeze it at some earlier point.
fn match_args(fcx: fn_ctxt, occs: @mut [pred_args],
fn match_args(fcx: fn_ctxt, occs: @dvec<pred_args>,
occ: [@constr_arg_use]) -> uint {
#debug("match_args: looking at %s",
constr_args_to_str(fn@(i: inst) -> str { ret i.ident; }, occ));
for vec::each(*occs) {|pd|
for (*occs).each {|pd|
log(debug,
"match_args: candidate " + pred_args_to_str(pd));
fn eq(p: inst, q: inst) -> bool { ret p.node == q.node; }
@ -613,7 +612,8 @@ fn substitute_arg(cx: ty::ctxt, actuals: [@expr], a: @constr_arg) ->
}
}
fn pred_args_matches(pattern: [constr_arg_general_<inst>], desc: pred_args) ->
fn pred_args_matches(pattern: [constr_arg_general_<inst>],
desc: pred_args) ->
bool {
let mut i = 0u;
for desc.node.args.each {|c|
@ -638,7 +638,8 @@ fn pred_args_matches(pattern: [constr_arg_general_<inst>], desc: pred_args) ->
ret true;
}
fn find_instance_(pattern: [constr_arg_general_<inst>], descs: [pred_args]) ->
fn find_instance_(pattern: [constr_arg_general_<inst>],
descs: [pred_args]) ->
option<uint> {
for descs.each {|d|
if pred_args_matches(pattern, d) { ret some(d.node.bit_num); }
@ -660,15 +661,19 @@ fn find_instances(_fcx: fn_ctxt, subst: subst,
if vec::len(subst) == 0u { ret []; }
let mut res = [];
for (*c.descs).each { |d|
if args_mention(d.node.args, find_in_subst_bool, subst) {
let old_bit_num = d.node.bit_num;
let newv = replace(subst, d);
alt find_instance_(newv, *c.descs) {
some(d1) {res += [{from: old_bit_num, to: d1}]}
_ {}
}
} else {}
(*c.descs).swap { |v|
let v <- vec::from_mut(v);
for v.each { |d|
if args_mention(d.node.args, find_in_subst_bool, subst) {
let old_bit_num = d.node.bit_num;
let newv = replace(subst, d);
alt find_instance_(newv, v) {
some(d1) {res += [{from: old_bit_num, to: d1}]}
_ {}
}
} else {}
}
vec::to_mut(v)
}
ret res;
}
@ -811,7 +816,7 @@ fn copy_in_poststate_two(fcx: fn_ctxt, src_post: poststate,
// dest def_id
let insts = find_instances(fcx, subst, val);
for insts.each {|p|
if promises_(p.from, src_post) {
if bitvectors::promises_(p.from, src_post) {
set_in_poststate_(p.to, target_post);
}
}
@ -897,12 +902,6 @@ fn args_mention<T>(args: [@constr_arg_use],
fn use_var(fcx: fn_ctxt, v: node_id) { *fcx.enclosing.used_vars += [v]; }
// FIXME: This should be a function in vec::.
fn vec_contains(v: @mut [node_id], i: node_id) -> bool {
for vec::each(*v) {|d| if d == i { ret true; } }
ret false;
}
fn op_to_oper_ty(io: init_op) -> oper_type {
alt io { init_move { oper_move } _ { oper_assign } }
}

View file

@ -8,6 +8,7 @@ import syntax::ast_util::respan;
import driver::session::session;
import aux::*;
import std::map::hashmap;
import dvec::{dvec, extensions};
type ctxt = {cs: @mut [sp_constr], tcx: ty::ctxt};
@ -57,12 +58,11 @@ fn add_constraint(tcx: ty::ctxt, c: sp_constr, next: uint, tbl: constr_map) ->
let {path: p, def_id: d_id, args: args} = c.node;
alt tbl.find(d_id) {
some(ct) {
let {path: _, descs: pds} = ct;
*pds += [respan(c.span, {args: args, bit_num: next})];
(*ct.descs).push(respan(c.span, {args: args, bit_num: next}));
}
none {
let rslt: @mut [pred_args] =
@mut [respan(c.span, {args: args, bit_num: next})];
let rslt = @dvec();
(*rslt).push(respan(c.span, {args: args, bit_num: next}));
tbl.insert(d_id, {path:p, descs:rslt});
}
}

View file

@ -4,19 +4,19 @@ import std::map::hashmap;
import driver::session;
import session::session;
import syntax::{ast, ast_map};
import syntax::ast::*;
import syntax::ast_util;
import syntax::ast_util::{is_local, local_def, split_class_items,
new_def_hash};
import syntax::codemap::span;
import metadata::csearch;
import util::common::*;
import util::ppaux::region_to_str;
import util::ppaux::vstore_to_str;
import util::ppaux::{ty_to_str, tys_to_str, ty_constr_to_str};
import syntax::print::pprust::*;
import middle::lint::{get_warning_level, vecs_not_implicitly_copyable,
ignore};
import syntax::ast::*;
import syntax::print::pprust::*;
export ty_vid, region_vid, vid;
export br_hashmap;
export is_instantiable;
@ -63,7 +63,6 @@ export mt;
export node_type_table;
export pat_ty;
export sequence_element_type;
export sort_methods;
export stmt_node_id;
export sty;
export subst, subst_tps, substs_is_noop, substs_to_str, substs;
@ -2311,13 +2310,6 @@ fn method_idx(id: ast::ident, meths: [method]) -> option<uint> {
ret none;
}
fn sort_methods(meths: [method]) -> [method] {
fn method_lteq(a: method, b: method) -> bool {
ret str::le(a.ident, b.ident);
}
ret std::sort::merge_sort(bind method_lteq(_, _), meths);
}
fn occurs_check(tcx: ctxt, sp: span, vid: ty_vid, rt: t) {
// Fast path
if !type_needs_infer(rt) { ret; }

View file

@ -45,7 +45,8 @@ an rptr (`&r.T`) use the region `r` that appears in the rptr.
"];
import check::fn_ctxt;
import rscope::*;
import rscope::{anon_rscope, binding_rscope, empty_rscope, in_anon_rscope};
import rscope::{in_binding_rscope, region_scope, type_rscope};
iface ast_conv {
fn tcx() -> ty::ctxt;

View file

@ -71,7 +71,8 @@ import collect::{methods}; // ccx.to_ty()
import method::{methods}; // methods for method::lookup
import middle::ty::tys_in_fn_ty;
import regionmanip::{replace_bound_regions_in_fn_ty, region_of};
import rscope::*;
import rscope::{anon_rscope, binding_rscope, empty_rscope, in_anon_rscope};
import rscope::{in_binding_rscope, region_scope, type_rscope};
type fn_ctxt =
// var_bindings, locals and next_var_id are shared
@ -386,6 +387,12 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) {
};
// typecheck the members
for members.each {|m| check_class_member(class_ccx, class_t, m); }
// Check that there's at least one field
let (fields,_) = split_class_items(members);
if fields.len() < 1u {
ccx.tcx.sess.span_err(it.span, "A class must have at least one \
field");
}
// Check that the class is instantiable
check_instantiable(ccx.tcx, it.span, it.id);
}

View file

@ -369,31 +369,23 @@ fn convert(ccx: @crate_ctxt, it: @ast::item) {
let t_ctor =
ty::mk_fn(
tcx,
ty_of_fn_decl(ccx,
empty_rscope,
ast::proto_any,
ctor.node.dec,
none));
ty_of_fn_decl(ccx, type_rscope(rp), ast::proto_any,
ctor.node.dec, none));
write_ty_to_tcx(tcx, ctor.node.id, t_ctor);
tcx.tcache.insert(local_def(ctor.node.id),
{bounds: tpt.bounds,
rp: ast::rp_none,
rp: rp,
ty: t_ctor});
option::iter(m_dtor) {|dtor|
// Write the dtor type
let t_dtor = ty::mk_fn(
tcx,
// not sure about empty_rscope
// FIXME
ty_of_fn_decl(ccx,
empty_rscope,
ast::proto_any,
ast_util::dtor_dec(),
none));
ty_of_fn_decl(ccx, type_rscope(rp), ast::proto_any,
ast_util::dtor_dec(), none));
write_ty_to_tcx(tcx, dtor.node.id, t_dtor);
tcx.tcache.insert(local_def(dtor.node.id),
{bounds: tpt.bounds,
rp: ast::rp_none,
rp: rp,
ty: t_dtor});
};
ensure_iface_methods(ccx, it.id);

View file

@ -1,6 +1,14 @@
import std::map::hashmap;
import middle::ty;
import middle::ty::*;
import middle::ty::{arg, bound_region, br_anon, br_named, canon_mode};
import middle::ty::{ck_block, ck_box, ck_uniq, constr, ctxt, field, method};
import middle::ty::{mt, re_bound, re_free, re_scope, re_var, region, t};
import middle::ty::{ty_bool, ty_bot, ty_box, ty_class, ty_constr, ty_enum};
import middle::ty::{ty_estr, ty_evec, ty_float, ty_fn, ty_iface, ty_int};
import middle::ty::{ty_nil, ty_opaque_box, ty_opaque_closure_ptr, ty_param};
import middle::ty::{ty_ptr, ty_rec, ty_res, ty_rptr, ty_self, ty_str, ty_tup};
import middle::ty::{ty_type, ty_uniq, ty_uint, ty_var, ty_var_integral};
import middle::ty::{ty_vec, vid};
import metadata::encoder;
import syntax::codemap;
import syntax::print::pprust;

View file

@ -6,6 +6,14 @@ S 2012-06-06 db31969
macos-x86_64 bd99c6745ae0b41b2ac749fdc58fe76a3ccb50a6
macos-i386 cba5620bbfe9195917799dd02fac5b9e2be997cd
S 2012-06-05 fec3b91
winnt-i386 36348a2b016f25d9e3b7e1a8814a352c18123839
linux-x86_64 7308f0eb3d6a9985c14dfbbde7e1f9eb901cc966
linux-i386 d4c1e1733fd30945f96ae67dbc10289f2a9ec380
freebsd-x86_64 d0ee6054d7d8320d64aa4dbb9b041537fa2665d5
macos-x86_64 652501172b4fee6631f595c90538fd95914ef444
macos-i386 5c54b5ecf54cc2631fdd48caa326ab44b5a2e494
S 2012-06-04 7213274
winnt-i386 94b9414433fd83c086b349ded3159f0541aace16
linux-x86_64 eb9cf0de4cc09e8b8bfcf741eff4b20510e13a5b

View file

@ -1,14 +1,16 @@
type alist<A,B> = { eq_fn: fn@(A,A) -> bool, mut data: [(A,B)] };
import dvec::{dvec,extensions};
type entry<A,B> = {key: A, value: B};
type alist<A,B> = { eq_fn: fn@(A,A) -> bool, data: dvec<entry<A,B>> };
fn alist_add<A: copy, B: copy>(lst: alist<A,B>, k: A, v: B) {
lst.data += [(k, v)];
lst.data.push({key:k, value:v});
}
fn alist_get<A: copy, B: copy>(lst: alist<A,B>, k: A) -> B {
let eq_fn = lst.eq_fn;
for lst.data.each {|pair|
let (ki, vi) = pair; // copy req'd for alias analysis
if eq_fn(k, ki) { ret vi; }
for lst.data.each {|entry|
if eq_fn(entry.key, k) { ret entry.value; }
}
fail;
}
@ -16,14 +18,12 @@ fn alist_get<A: copy, B: copy>(lst: alist<A,B>, k: A) -> B {
#[inline]
fn new_int_alist<B: copy>() -> alist<int, B> {
fn eq_int(&&a: int, &&b: int) -> bool { a == b }
ret {eq_fn: eq_int,
mut data: []};
ret {eq_fn: eq_int, data: dvec()};
}
#[inline]
fn new_int_alist_2<B: copy>() -> alist<int, B> {
#[inline]
fn eq_int(&&a: int, &&b: int) -> bool { a == b }
ret {eq_fn: eq_int,
mut data: []};
ret {eq_fn: eq_int, data: dvec()};
}

View file

@ -0,0 +1,19 @@
class socket {
let sock: int;
new() { self.sock = 1; }
drop { }
fn set_identity() {
closure { ||
setsockopt_bytes(self.sock) //! ERROR copying a noncopyable value
}
}
}
fn closure(f: fn@()) { f() }
fn setsockopt_bytes(+_sock: int) { }
fn main() {}

View file

@ -0,0 +1,9 @@
class c { //! ERROR A class must have at least one field
new() { }
}
fn main() {
let a = c();
let x = [a];
let _y = x[0];
}

View file

@ -8,4 +8,8 @@ fn f<T>(&o: option<T>) {
fn main() {
f::<int>(option::none);
//!^ ERROR taking mut reference to static item
// Additional errors reported by borrowck:
//^^ ERROR illegal borrow unless pure: creating mutable alias to aliasable, immutable memory
//^^^ NOTE impure due to access to impure function
}

View file

@ -3,14 +3,15 @@
// Test that a class with a non-copyable field can't be
// copied
class bar {
new() {}
let x: int;
new(x:int) {self.x = x;}
drop {}
}
class foo {
let i: int;
let j: bar;
new(i:int) { self.i = i; self.j = bar(); }
new(i:int) { self.i = i; self.j = bar(5); }
}
fn main() { let x <- foo(10); let y = x; log(error, x); }

View file

@ -4,7 +4,7 @@
enum an_enum/& { }
iface an_iface/& { }
class a_class/& { new() { } }
class a_class/& { let x:int; new(x:int) { self.x = x; } }
fn a_fn1(e: an_enum/&a) -> an_enum/&b {
ret e; //! ERROR mismatched types: expected `an_enum/&b` but found `an_enum/&a`

View file

@ -1,7 +1,8 @@
// error-pattern: copying a noncopyable value
class r {
new(_i:int) {}
let i:int;
new(i:int) {self.i = i;}
drop {}
}

View file

@ -0,0 +1,17 @@
// xfail-test
// error-pattern:bounds check
fn main() {
let x = [1u,2u,3u];
// This should cause a bounds-check failure, but may not if we do our
// bounds checking by comparing a scaled index value to the vector's
// length (in bytes), because the scaling of the index will cause it to
// wrap around to a small number.
let idx = uint::max_value & !(uint::max_value >> 1u);
#error("ov2 idx = 0x%x", idx);
// This should fail.
#error("ov2 0x%x", x[idx]);
}

View file

@ -0,0 +1,28 @@
// xfail-test
// error-pattern:bounds check
#[cfg(target_arch="x86")]
fn main() {
let x = [1u,2u,3u];
// This should cause a bounds-check failure, but may not if we do our
// bounds checking by truncating the index value to the size of the
// machine word, losing relevant bits of the index value.
// This test is only meaningful on 32-bit hosts.
let idx = u64::max_value & !(u64::max_value >> 1u);
#error("ov3 idx = 0x%8.8x%8.8x",
(idx >> 32) as uint,
idx as uint);
// This should fail.
#error("ov3 0x%x", x[idx]);
}
#[cfg(target_arch="x86_64")]
fn main() {
// This version just fails anyways, for symmetry on 64-bit hosts.
let x = [1u,2u,3u];
#error("ov3 0x%x", x[200]);
}

View file

@ -0,0 +1,24 @@
// error-pattern:bounds check
fn main() {
// This should cause a bounds-check failure, but may not if we do our
// bounds checking by comparing the scaled index to the vector's
// address-bounds, since we've scaled the index to wrap around to the
// address of the 0th cell in the array (even though the index is
// huge).
let x = [1u,2u,3u];
vec::unpack_slice(x) {|p, _len|
let base = p as uint; // base = 0x1230 say
let idx = base / sys::size_of::<uint>(); // idx = 0x0246 say
#error("ov1 base = 0x%x", base);
#error("ov1 idx = 0x%x", idx);
#error("ov1 sizeof::<uint>() = 0x%x", sys::size_of::<uint>());
#error("ov1 idx * sizeof::<uint>() = 0x%x",
idx * sys::size_of::<uint>());
// This should fail.
#error("ov1 0x%x", x[idx]);
}
}

View file

@ -21,7 +21,8 @@ fn getbig_call_c_and_fail(i: int) {
}
class and_then_get_big_again {
new() {}
let x:int;
new(x:int) {self.x = x;}
drop {
fn getbig(i: int) {
if i != 0 {
@ -34,7 +35,7 @@ class and_then_get_big_again {
fn main() {
task::spawn {||
let r = and_then_get_big_again();
let r = and_then_get_big_again(4);
getbig_call_c_and_fail(10000);
};
}

View file

@ -5,7 +5,7 @@
use std;
fn getbig_and_fail(&&i: int) {
let _r = and_then_get_big_again();
let _r = and_then_get_big_again(5);
if i != 0 {
getbig_and_fail(i - 1);
} else {
@ -14,7 +14,8 @@ fn getbig_and_fail(&&i: int) {
}
class and_then_get_big_again {
new() {}
let x:int;
new(x:int) {self.x = x;}
drop {
fn getbig(i: int) {
if i != 0 {

View file

@ -5,7 +5,7 @@
use std;
fn getbig_and_fail(&&i: int) {
let r = and_then_get_big_again();
let r = and_then_get_big_again(5);
if i != 0 {
getbig_and_fail(i - 1);
} else {
@ -14,7 +14,8 @@ fn getbig_and_fail(&&i: int) {
}
class and_then_get_big_again {
new() {}
let x:int;
new(x:int) {self.x = x;}
drop {}
}

View file

@ -1,19 +1,20 @@
// error-pattern:whatever
class r {
let x:int;
// Setting the exit status after the runtime has already
// failed has no effect and the process exits with the
// runtime's exit code
drop {
os::set_exit_status(50);
}
new() {}
new(x:int) {self.x = x;}
}
fn main() {
log(error, "whatever");
task::spawn {||
let i = r();
let i = r(5);
};
fail;
}

View file

@ -25,8 +25,10 @@ fn foo(s: @int) {
fn main() {
let s: @int = @0; // ref up
let count = dbg::refcount(s);
foo(s); // ref up then down
log(debug, dbg::refcount(s));
assert (dbg::refcount(s) == 1u);
assert (dbg::refcount(s) == count);
}

View file

@ -1,6 +1,7 @@
use std;
import std::map::*;
import vec::*;
import dvec::{dvec, extensions};
enum furniture { chair, couch, bed }
enum body_part { finger, toe, nose, ear }
@ -26,7 +27,7 @@ fn vec_includes<T>(xs: [T], x: T) -> bool {
class cat implements noisy, scratchy, bitey {
priv {
let meows : @mut uint;
let scratched : @mut [furniture];
let scratched : dvec<furniture>;
let bite_counts : hashmap<body_part, uint>;
fn meow() -> uint {
@ -44,7 +45,7 @@ class cat implements noisy, scratchy, bitey {
new(in_x : uint, in_y : int, in_name: str)
{ self.meows = @mut in_x; self.how_hungry = @mut in_y;
self.name = in_name; self.scratched = @mut [];
self.name = in_name; self.scratched = dvec();
let hsher: hashfn<body_part> =
fn@(p: body_part) -> uint { int::hash(p as int) };
let eqer : eqfn<body_part> =
@ -61,10 +62,10 @@ class cat implements noisy, scratchy, bitey {
fn meow_count() -> uint { *self.meows }
fn scratch() -> option<furniture> {
let all = [chair, couch, bed];
log(error, *(self.scratched));
log(error, self.scratched);
let mut rslt = none;
for each(all) {|thing| if !vec_includes(*(self.scratched), thing) {
*self.scratched += [thing];
for each(all) {|thing| if !self.scratched.contains(thing) {
self.scratched.push(thing);
ret some(thing); }}
rslt
}

View file

@ -26,11 +26,13 @@ enum tg { bar, }
#[cfg(bogus)]
class r {
new(i:int) {}
let i: int;
new(i:int) { self.i = i; }
}
class r {
new(i:int) {}
let i: int;
new(i:int) { self.i = i; }
}
#[cfg(bogus)]

View file

@ -26,10 +26,9 @@ impl of to_str for int {
impl of to_str for Tree {
fn to_str() -> str {
#fmt["[%s, %s, %s]",
self.val.to_str(),
self.left.to_str(),
self.right.to_str()]
let l = self.left, r = self.right;
#fmt["[%s, %s, %s]", self.val.to_str(),
l.to_str(), r.to_str()]
}
}

View file

@ -0,0 +1,19 @@
class socket {
let sock: int;
new() { self.sock = 1; }
drop { }
fn set_identity() {
closure { ||
setsockopt_bytes(copy self.sock)
}
}
}
fn closure(f: fn()) { f() }
fn setsockopt_bytes(_sock: int) { }
fn main() {}

View file

@ -0,0 +1,13 @@
class font/& {
let fontbuf: &self.[u8];
new(fontbuf: &self.[u8]) {
self.fontbuf = fontbuf;
}
fn buf() -> &self.[u8] {
self.fontbuf
}
}
fn main() { }

View file

@ -4,7 +4,7 @@
// -*- rust -*-
fn len(v: [const int]) -> uint {
let mut i = 0u;
for v.each {|x| i += 1u; }
while i < vec::len(v) { i += 1u; }
ret i;
}

View file

@ -1,7 +1,3 @@
// xfail-test
//
// This doesn't work quite yet in check-fast mode. Not sure why. Crashes.
enum my_visitor = @{ mut types: [str] };
impl of intrinsic::ty_visitor for my_visitor {