diff --git a/.gitignore b/.gitignore index 7ef656055ecc6..eef182a12233d 100644 --- a/.gitignore +++ b/.gitignore @@ -73,6 +73,7 @@ src/.DS_Store /doc/html /doc/latex /doc/std +/doc/extra /nd/ /llvm/ version.md @@ -81,7 +82,6 @@ keywords.md x86_64-apple-darwin/ x86_64-unknown-linux-gnu/ i686-unknown-linux-gnu/ -doc/core/ tmp.*.rs config.stamp .DS_Store diff --git a/.mailmap b/.mailmap new file mode 100644 index 0000000000000..637b9ec8c4efb --- /dev/null +++ b/.mailmap @@ -0,0 +1,12 @@ +# +# This list is used by git-shortlog to aggregate contributions. It is +# necessary when either the author's full name is not always written +# the same way, and/or the same author contributes from different +# email addresses. +# + +Elly Jones +ILyoan +Junyoung Cho +Matthijs Hofstra +Rob Arnold diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d934e38c35d24..3cba6f2891a5a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,27 +1,42 @@ ## Pull request procedure -Pull requests should be targeted at Rust's `incoming` branch (note that by default Github will aim them at the `master` branch) -- -see "Changing The Commit Range and Destination Repository" in Github's documentation on [pull requests](https://help.github.com/articles/using-pull-requests). -Before pushing to your Github repo and issuing the pull request, please do two things: +Pull requests should be targeted at Rust's `incoming` branch (note +that by default Github will aim them at the `master` branch) -- see +"Changing The Commit Range and Destination Repository" in Github's +documentation on [pull +requests](https://help.github.com/articles/using-pull-requests). +Before pushing to your Github repo and issuing the pull request, +please do two things: -1. [Rebase](http://git-scm.com/book/en/Git-Branching-Rebasing) your local changes against the `incoming` branch. Resolve any conflicts that arise. -2. Run the full Rust test suite with the `make check` command. -You're not off the hook even if you just stick to documentation; code examples in the docs are tested as well! +1. [Rebase](http://git-scm.com/book/en/Git-Branching-Rebasing) your + local changes against the `incoming` branch. Resolve any conflicts + that arise. -Pull requests will be treated as "review requests", -and we will give feedback we expect to see corrected on [style](https://github.com/mozilla/rust/wiki/Note-style-guide) and substance before pulling. -Changes contributed via pull request should focus on a single issue at a time, like any other. -We will not accept pull-requests that try to "sneak" unrelated changes in. +2. Run the full Rust test suite with the `make check` command. You're + not off the hook even if you just stick to documentation; code + examples in the docs are tested as well! -Normally, all pull requests must include regression tests (see [Note-testsuite](https://github.com/mozilla/rust/wiki/Note-testsuite)) that test your change. -Occasionally, a change will be very difficult to test for. -In those cases, please include a note in your commit message explaining why. +Pull requests will be treated as "review requests", and we will give +feedback we expect to see corrected on +[style](https://github.com/mozilla/rust/wiki/Note-style-guide) and +substance before pulling. Changes contributed via pull request should +focus on a single issue at a time, like any other. We will not accept +pull-requests that try to "sneak" unrelated changes in. -In the licensing header at the beginning of any files you change, please make sure the listed date range includes the current year. -For example, if it's 2013, and you change a Rust file that was created in 2010, it should begin: +Normally, all pull requests must include regression tests (see +[Note-testsuite](https://github.com/mozilla/rust/wiki/Note-testsuite)) +that test your change. Occasionally, a change will be very difficult +to test for. In those cases, please include a note in your commit +message explaining why. + +In the licensing header at the beginning of any files you change, +please make sure the listed date range includes the current year. For +example, if it's 2013, and you change a Rust file that was created in +2010, it should begin: ``` // Copyright 2010-2013 The Rust Project Developers. ``` -For more details, please refer to [Note-development-policy](https://github.com/mozilla/rust/wiki/Note-development-policy). \ No newline at end of file +For more details, please refer to +[Note-development-policy](https://github.com/mozilla/rust/wiki/Note-development-policy). diff --git a/Makefile.in b/Makefile.in index 8ab704ebe1719..ca82f29602278 100644 --- a/Makefile.in +++ b/Makefile.in @@ -122,6 +122,10 @@ endif ifdef TRACE CFG_RUSTC_FLAGS += -Z trace endif +ifndef DEBUG_BORROWS + RUSTFLAGS_STAGE1 += -Z no-debug-borrows + RUSTFLAGS_STAGE2 += -Z no-debug-borrows +endif # platform-specific auto-configuration include $(CFG_SRC_DIR)mk/platform.mk @@ -142,8 +146,7 @@ ifneq ($(wildcard $(CFG_GIT)),) ifneq ($(wildcard $(CFG_GIT_DIR)),) CFG_VERSION += $(shell git --git-dir=$(CFG_GIT_DIR) log -1 \ --pretty=format:'(%h %ci)') - CFG_VER_HASH = $(shell git --git-dir=$(CFG_GIT_DIR) log -1 \ - --pretty=format:'%H') + CFG_VER_HASH = $(shell git --git-dir=$(CFG_GIT_DIR) rev-parse HEAD) endif endif @@ -201,8 +204,8 @@ define DEF_LIBS CFG_RUNTIME_$(1) :=$(call CFG_LIB_NAME_$(1),rustrt) CFG_RUSTLLVM_$(1) :=$(call CFG_LIB_NAME_$(1),rustllvm) -CFG_CORELIB_$(1) :=$(call CFG_LIB_NAME_$(1),core) CFG_STDLIB_$(1) :=$(call CFG_LIB_NAME_$(1),std) +CFG_EXTRALIB_$(1) :=$(call CFG_LIB_NAME_$(1),extra) CFG_LIBRUSTC_$(1) :=$(call CFG_LIB_NAME_$(1),rustc) CFG_LIBSYNTAX_$(1) :=$(call CFG_LIB_NAME_$(1),syntax) CFG_LIBFUZZER_$(1) :=$(call CFG_LIB_NAME_$(1),fuzzer) @@ -211,8 +214,8 @@ CFG_LIBRUSTDOC_$(1) :=$(call CFG_LIB_NAME_$(1),rustdoc) CFG_LIBRUSTI_$(1) :=$(call CFG_LIB_NAME_$(1),rusti) CFG_LIBRUST_$(1) :=$(call CFG_LIB_NAME_$(1),rust) +EXTRALIB_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),extra) STDLIB_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),std) -CORELIB_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),core) LIBRUSTC_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),rustc) LIBSYNTAX_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),syntax) LIBFUZZER_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),fuzzer) @@ -220,8 +223,8 @@ LIBRUSTPKG_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),rustpkg) LIBRUSTDOC_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),rustdoc) LIBRUSTI_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),rusti) LIBRUST_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),rust) +EXTRALIB_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),extra) STDLIB_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),std) -CORELIB_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),core) LIBRUSTC_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),rustc) LIBSYNTAX_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),syntax) LIBFUZZER_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),fuzzer) @@ -236,19 +239,19 @@ $(foreach target,$(CFG_TARGET_TRIPLES),\ $(eval $(call DEF_LIBS,$(target)))) ###################################################################### -# Core library variables +# Standard library variables ###################################################################### -CORELIB_CRATE := $(S)src/libcore/core.rc -CORELIB_INPUTS := $(wildcard $(addprefix $(S)src/libcore/, \ +STDLIB_CRATE := $(S)src/libstd/core.rc +STDLIB_INPUTS := $(wildcard $(addprefix $(S)src/libstd/, \ core.rc *.rs */*.rs */*/*rs */*/*/*rs)) ###################################################################### -# Standard library variables +# Extra library variables ###################################################################### -STDLIB_CRATE := $(S)src/libstd/std.rc -STDLIB_INPUTS := $(wildcard $(addprefix $(S)src/libstd/, \ +EXTRALIB_CRATE := $(S)src/libextra/std.rc +EXTRALIB_INPUTS := $(wildcard $(addprefix $(S)src/libextra/, \ std.rc *.rs */*.rs)) ###################################################################### @@ -271,7 +274,7 @@ DRIVER_CRATE := $(S)src/driver/driver.rs # FIXME: x86-ism LLVM_COMPONENTS=x86 arm mips ipo bitreader bitwriter linker asmparser jit mcjit \ - interpreter + interpreter instrumentation define DEF_LLVM_VARS # The configure script defines these variables with the target triples @@ -340,33 +343,33 @@ TROOT$(1)_T_$(2)_H_$(3) = $$(HLIB$(1)_H_$(3))/rustc/$(2) TBIN$(1)_T_$(2)_H_$(3) = $$(TROOT$(1)_T_$(2)_H_$(3))/bin TLIB$(1)_T_$(2)_H_$(3) = $$(TROOT$(1)_T_$(2)_H_$(3))/$$(CFG_LIBDIR) -# The name of the core and standard libraries used by rustc +# The name of the standard and extra libraries used by rustc ifdef CFG_DISABLE_SHAREDSTD - HCORELIB_DEFAULT$(1)_H_$(3) = \ - $$(HLIB$(1)_H_$(3))/libcore.rlib - TCORELIB_DEFAULT$(1)_T_$(2)_H_$(3) = \ - $$(TLIB$(1)_T_$(2)_H_$(3))/libcore.rlib - HSTDLIB_DEFAULT$(1)_H_$(3) = \ $$(HLIB$(1)_H_$(3))/libstd.rlib TSTDLIB_DEFAULT$(1)_T_$(2)_H_$(3) = \ $$(TLIB$(1)_T_$(2)_H_$(3))/libstd.rlib + HEXTRALIB_DEFAULT$(1)_H_$(3) = \ + $$(HLIB$(1)_H_$(3))/libextra.rlib + TEXTRALIB_DEFAULT$(1)_T_$(2)_H_$(3) = \ + $$(TLIB$(1)_T_$(2)_H_$(3))/libextra.rlib + HLIBRUSTC_DEFAULT$(1)_H_$(3) = \ $$(HLIB$(1)_H_$(3))/librustc.rlib TLIBRUSTC_DEFAULT$(1)_T_$(2)_H_$(3) = \ $$(TLIB$(1)_T_$(2)_H_$(3))/librustc.rlib else - HCORELIB_DEFAULT$(1)_H_$(3) = \ - $$(HLIB$(1)_H_$(3))/$(CFG_CORELIB_$(3)) - TCORELIB_DEFAULT$(1)_T_$(2)_H_$(3) = \ - $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_CORELIB_$(2)) - HSTDLIB_DEFAULT$(1)_H_$(3) = \ $$(HLIB$(1)_H_$(3))/$(CFG_STDLIB_$(3)) TSTDLIB_DEFAULT$(1)_T_$(2)_H_$(3) = \ $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_STDLIB_$(2)) + HEXTRALIB_DEFAULT$(1)_H_$(3) = \ + $$(HLIB$(1)_H_$(3))/$(CFG_EXTRALIB_$(3)) + TEXTRALIB_DEFAULT$(1)_T_$(2)_H_$(3) = \ + $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_EXTRALIB_$(2)) + HLIBRUSTC_DEFAULT$(1)_H_$(3) = \ $$(HLIB$(1)_H_$(3))/$(CFG_LIBRUSTC_$(3)) TLIBRUSTC_DEFAULT$(1)_T_$(2)_H_$(3) = \ @@ -378,8 +381,8 @@ HSREQ$(1)_H_$(3) = \ $$(HBIN$(1)_H_$(3))/rustc$$(X_$(3)) \ $$(HLIB$(1)_H_$(3))/$(CFG_RUNTIME_$(3)) \ $$(HLIB$(1)_H_$(3))/$(CFG_RUSTLLVM_$(3)) \ - $$(HCORELIB_DEFAULT$(1)_H_$(3)) \ $$(HSTDLIB_DEFAULT$(1)_H_$(3)) \ + $$(HEXTRALIB_DEFAULT$(1)_H_$(3)) \ $$(HLIBSYNTAX_DEFAULT$(1)_H_$(3)) \ $$(HLIBRUSTC_DEFAULT$(1)_H_$(3)) \ $$(MKFILE_DEPS) @@ -393,8 +396,8 @@ TSREQ$(1)_T_$(2)_H_$(3) = \ # Prerequisites for a working stageN compiler and libraries, for a specific target SREQ$(1)_T_$(2)_H_$(3) = \ $$(TSREQ$(1)_T_$(2)_H_$(3)) \ - $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_CORELIB_$(2)) \ - $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_STDLIB_$(2)) + $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_STDLIB_$(2)) \ + $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_EXTRALIB_$(2)) # Prerequisites for a working stageN compiler and libraries, for a specific target CSREQ$(1)_T_$(2)_H_$(3) = \ @@ -409,8 +412,8 @@ CSREQ$(1)_T_$(2)_H_$(3) = \ $$(HLIB$(1)_H_$(3))/$(CFG_LIBRUSTDOC_$(3)) \ $$(HLIB$(1)_H_$(3))/$(CFG_LIBRUSTI_$(3)) \ $$(HLIB$(1)_H_$(3))/$(CFG_LIBRUST_$(3)) \ - $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_CORELIB_$(2)) \ - $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_STDLIB_$(2)) \ + $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_STDLIB_$(2)) \ + $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_EXTRALIB_$(2)) \ $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBSYNTAX_$(2)) \ $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTC_$(2)) \ $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBFUZZER_$(2)) \ diff --git a/configure b/configure index e4ca72737db9e..767eb332ac190 100755 --- a/configure +++ b/configure @@ -376,6 +376,7 @@ opt fast-make 0 "use .gitmodules as timestamp for submodule deps" opt manage-submodules 1 "let the build manage the git submodules" opt mingw-cross 0 "cross-compile for win32 using mingw" opt clang 0 "prefer clang to gcc for building the runtime" +opt ccache 0 "invoke gcc/clang via ccache to reuse object files between builds" opt local-rust 0 "use an installed rustc rather than downloading a snapshot" opt pax-flags 0 "apply PaX flags to rustc binaries (required for GRSecurity/PaX-patched kernels)" valopt prefix "/usr/local" "set installation prefix" @@ -421,6 +422,7 @@ else fi probe CFG_CLANG clang++ +probe CFG_CCACHE ccache probe CFG_GCC gcc probe CFG_LD ld probe CFG_VALGRIND valgrind @@ -555,11 +557,11 @@ then CFG_CLANG_VERSION=$("$CFG_CLANG" \ --version \ | grep version \ - | sed 's/.*\(version .*\)/\1/' \ + | sed 's/.*\(version .*\)/\1/; s/.*based on \(LLVM .*\))/\1/' \ | cut -d ' ' -f 2) case $CFG_CLANG_VERSION in - (3.0svn | 3.0 | 3.1* | 3.2* | 3.3* | 4.0* | 4.1* | 4.2*) + (3.0svn | 3.0 | 3.1* | 3.2* | 3.3* | 3.4* ) step_msg "found ok version of CLANG: $CFG_CLANG_VERSION" CFG_C_COMPILER="clang" ;; @@ -571,6 +573,16 @@ else CFG_C_COMPILER="gcc" fi +if [ ! -z "$CFG_ENABLE_CCACHE" ] +then + if [ -z "$CFG_CCACHE" ] + then + err "ccache requested but not found" + fi + + CFG_C_COMPILER="ccache $CFG_C_COMPILER" +fi + # a little post-processing of various config values CFG_PREFIX=${CFG_PREFIX%/} @@ -643,7 +655,7 @@ fi step_msg "making directories" for i in \ - doc doc/core doc/std \ + doc doc/std doc/extra \ dl tmp do make_dir $i @@ -665,12 +677,16 @@ make_dir rt for t in $CFG_TARGET_TRIPLES do make_dir rt/$t - for i in \ - isaac linenoise sync test \ - arch/i386 arch/x86_64 arch/arm arch/mips \ - libuv libuv/src/ares libuv/src/eio libuv/src/ev + for s in 0 1 2 3 do - make_dir rt/$t/$i + make_dir rt/$t/stage$s + for i in \ + isaac linenoise sync test \ + arch/i386 arch/x86_64 arch/arm arch/mips \ + libuv libuv/src/ares libuv/src/eio libuv/src/ev + do + make_dir rt/$t/stage$s/$i + done done done @@ -821,20 +837,35 @@ do --enable-bindings=none --disable-threads \ --disable-pthreads" - if [ "$CFG_C_COMPILER" = "clang" ] - then + case "$CFG_C_COMPILER" in + ("ccache clang") + LLVM_CXX_32="ccache clang++ -m32 -Qunused-arguments" + LLVM_CC_32="ccache clang -m32 -Qunused-arguments" + + LLVM_CXX_64="ccache clang++ -Qunused-arguments" + LLVM_CC_64="ccache clang -Qunused-arguments" + ;; + ("clang") LLVM_CXX_32="clang++ -m32" LLVM_CC_32="clang -m32" LLVM_CXX_64="clang++" LLVM_CC_64="clang" - else + ;; + ("ccache gcc") + LLVM_CXX_32="ccache g++ -m32" + LLVM_CC_32="ccache gcc -m32" + + LLVM_CXX_64="ccache g++" + LLVM_CC_64="ccache gcc" + ;; + ("gcc") LLVM_CXX_32="g++ -m32" LLVM_CC_32="gcc -m32" LLVM_CXX_64="g++" LLVM_CC_64="gcc" - fi + esac LLVM_CFLAGS_32="-m32" LLVM_CXXFLAGS_32="-m32" @@ -931,6 +962,21 @@ then putvar CFG_PAXCTL fi +# Avoid spurious warnings from clang by feeding it original source on +# ccache-miss rather than preprocessed input. +if [ ! -z "$CFG_ENABLE_CCACHE" ] && [ ! -z "$CFG_ENABLE_CLANG" ] +then + CFG_CCACHE_CPP2=1 + putvar CFG_CCACHE_CPP2 +fi + +if [ ! -z "$CFG_ENABLE_CCACHE" ] +then + CFG_CCACHE_BASEDIR=${CFG_SRC_DIR} + putvar CFG_CCACHE_BASEDIR +fi + + if [ ! -z $BAD_PANDOC ] then CFG_PANDOC= diff --git a/doc/rust.md b/doc/rust.md index 9839e9e8afd74..787d0191b0930 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -17,14 +17,14 @@ This document does not serve as a tutorial introduction to the language. Background familiarity with the language is assumed. A separate [tutorial] document is available to help acquire such background familiarity. -This document also does not serve as a reference to the [core] or [standard] +This document also does not serve as a reference to the [standard] or [extra] libraries included in the language distribution. Those libraries are documented separately by extracting documentation attributes from their source code. [tutorial]: tutorial.html -[core]: core/index.html [standard]: std/index.html +[extra]: extra/index.html ## Disclaimer @@ -301,10 +301,10 @@ num_lit : nonzero_dec [ dec_digit | '_' ] * num_suffix ? num_suffix : int_suffix | float_suffix ; int_suffix : 'u' int_suffix_size ? - | 'i' int_suffix_size ; + | 'i' int_suffix_size ? ; int_suffix_size : [ '8' | '1' '6' | '3' '2' | '6' '4' ] ; -float_suffix : [ exponent | '.' dec_lit exponent ? ] float_suffix_ty ? ; +float_suffix : [ exponent | '.' dec_lit exponent ? ] ? float_suffix_ty ? ; float_suffix_ty : 'f' [ '3' '2' | '6' '4' ] ; exponent : ['E' | 'e'] ['-' | '+' ] ? dec_lit ; dec_lit : [ dec_digit | '_' ] + ; @@ -441,7 +441,7 @@ expression context, the final namespace qualifier is omitted. Two examples of paths with type arguments: ~~~~ -# use core::hashmap::HashMap; +# use std::hashmap::HashMap; # fn f() { # fn id(t: T) -> T { t } type t = HashMap; // Type arguments used in a type expression @@ -768,9 +768,9 @@ Three examples of `extern mod` declarations: ~~~~~~~~{.xfail-test} extern mod pcre (uuid = "54aba0f8-a7b1-4beb-92f1-4cf625264841"); -extern mod std; // equivalent to: extern mod std ( name = "std" ); +extern mod extra; // equivalent to: extern mod extra ( name = "extra" ); -extern mod ruststd (name = "std"); // linking to 'std' under another name +extern mod rustextra (name = "extra"); // linking to 'extra' under another name ~~~~~~~~ ##### Use declarations @@ -802,19 +802,19 @@ Use declarations support a number of convenient shortcuts: An example of `use` declarations: ~~~~ -use core::float::sin; -use core::str::{slice, contains}; -use core::option::Some; +use std::float::sin; +use std::str::{slice, contains}; +use std::option::Some; fn main() { - // Equivalent to 'info!(core::float::sin(1.0));' + // Equivalent to 'info!(std::float::sin(1.0));' info!(sin(1.0)); - // Equivalent to 'info!(core::option::Some(1.0));' + // Equivalent to 'info!(std::option::Some(1.0));' info!(Some(1.0)); // Equivalent to - // 'info!(core::str::contains(core::str::slice("foo", 0, 1), "oo"));' + // 'info!(std::str::contains(std::str::slice("foo", 0, 1), "oo"));' info!(contains(slice("foo", 0, 1), "oo")); } ~~~~ @@ -1327,7 +1327,7 @@ with the exception that they may not have a body and are instead terminated by a semicolon. ~~~ -# use core::libc::{c_char, FILE}; +# use std::libc::{c_char, FILE}; # #[nolink] extern { @@ -1426,6 +1426,7 @@ names are effectively reserved. Some significant attributes include: by the compiler can be found via `rustc -W help`. * The `deriving` attribute, for automatically generating implementations of certain traits. +* The `static_assert` attribute, for asserting that a static bool is true at compiletime Other attributes may be added or removed during development of the language. @@ -1435,7 +1436,7 @@ Some primitive Rust operations are defined in Rust code, rather than being implemented directly in C or assembly language. The definitions of these operations have to be easy for the compiler to find. The `lang` attribute makes it possible to declare these operations. -For example, the `str` module in the Rust core library defines the string equality function: +For example, the `str` module in the Rust standard library defines the string equality function: ~~~ {.xfail-test} #[lang="str_eq"] @@ -1561,7 +1562,7 @@ impl Eq for Foo { Supported traits for `deriving` are: * Comparison traits: `Eq`, `TotalEq`, `Ord`, `TotalOrd`. -* Serialization: `Encodable`, `Decodable`. These require `std`. +* Serialization: `Encodable`, `Decodable`. These require `extra`. * `Clone` and `DeepClone`, to perform (deep) copies. * `IterBytes`, to iterate over the bytes in a data type. * `Rand`, to create a random instance of a data type. @@ -1839,6 +1840,7 @@ is bounds-checked at run-time. When the check fails, it will put the task in a _failing state_. ~~~~ +# use std::task; # do task::spawn_unlinked { ([1, 2, 3, 4])[0]; @@ -1884,25 +1886,25 @@ Binary operators expressions are given in terms of #### Arithmetic operators Binary arithmetic expressions are syntactic sugar for calls to built-in traits, -defined in the `core::ops` module of the `core` library. +defined in the `std::ops` module of the `std` library. This means that arithmetic operators can be overridden for user-defined types. The default meaning of the operators on standard types is given here. `+` : Addition and vector/string concatenation. - Calls the `add` method on the `core::ops::Add` trait. + Calls the `add` method on the `std::ops::Add` trait. `-` : Subtraction. - Calls the `sub` method on the `core::ops::Sub` trait. + Calls the `sub` method on the `std::ops::Sub` trait. `*` : Multiplication. - Calls the `mul` method on the `core::ops::Mul` trait. + Calls the `mul` method on the `std::ops::Mul` trait. `/` : Quotient. - Calls the `div` method on the `core::ops::Div` trait. + Calls the `div` method on the `std::ops::Div` trait. `%` : Remainder. - Calls the `rem` method on the `core::ops::Rem` trait. + Calls the `rem` method on the `std::ops::Rem` trait. #### Bitwise operators @@ -1913,19 +1915,19 @@ The default meaning of the operators on standard types is given here. `&` : And. - Calls the `bitand` method of the `core::ops::BitAnd` trait. + Calls the `bitand` method of the `std::ops::BitAnd` trait. `|` : Inclusive or. - Calls the `bitor` method of the `core::ops::BitOr` trait. + Calls the `bitor` method of the `std::ops::BitOr` trait. `^` : Exclusive or. - Calls the `bitxor` method of the `core::ops::BitXor` trait. + Calls the `bitxor` method of the `std::ops::BitXor` trait. `<<` : Logical left shift. - Calls the `shl` method of the `core::ops::Shl` trait. + Calls the `shl` method of the `std::ops::Shl` trait. `>>` : Logical right shift. - Calls the `shr` method of the `core::ops::Shr` trait. + Calls the `shr` method of the `std::ops::Shr` trait. #### Lazy boolean operators @@ -1946,22 +1948,22 @@ The default meaning of the operators on standard types is given here. `==` : Equal to. - Calls the `eq` method on the `core::cmp::Eq` trait. + Calls the `eq` method on the `std::cmp::Eq` trait. `!=` : Unequal to. - Calls the `ne` method on the `core::cmp::Eq` trait. + Calls the `ne` method on the `std::cmp::Eq` trait. `<` : Less than. - Calls the `lt` method on the `core::cmp::Ord` trait. + Calls the `lt` method on the `std::cmp::Ord` trait. `>` : Greater than. - Calls the `gt` method on the `core::cmp::Ord` trait. + Calls the `gt` method on the `std::cmp::Ord` trait. `<=` : Less than or equal. - Calls the `le` method on the `core::cmp::Ord` trait. + Calls the `le` method on the `std::cmp::Ord` trait. `>=` : Greater than or equal. - Calls the `ge` method on the `core::cmp::Ord` trait. + Calls the `ge` method on the `std::cmp::Ord` trait. #### Type cast expressions @@ -2031,7 +2033,8 @@ as = ~~~~ -Operators at the same precedence level are evaluated left-to-right. +Operators at the same precedence level are evaluated left-to-right. [Unary operators](#unary-operator-expressions) +have the same precedence level and it is stronger than any of the binary operators'. ### Grouped expressions @@ -2120,11 +2123,11 @@ then the expression completes. Some examples of call expressions: ~~~~ -# use core::from_str::FromStr::from_str; +# use std::from_str::FromStr; # fn add(x: int, y: int) -> int { 0 } let x: int = add(1, 2); -let pi = from_str::("3.14"); +let pi = FromStr::from_str::("3.14"); ~~~~ ### Lambda expressions @@ -2167,7 +2170,7 @@ fn ten_times(f: &fn(int)) { } } -ten_times(|j| io::println(fmt!("hello, %d", j))); +ten_times(|j| println(fmt!("hello, %d", j))); ~~~~ @@ -2188,7 +2191,7 @@ An example: let mut i = 0; while i < 10 { - io::println("hello\n"); + println("hello\n"); i = i + 1; } ~~~~ @@ -2250,6 +2253,14 @@ do_expr : "do" expr [ '|' ident_list '|' ] ? '{' block '}' ; A _do expression_ provides a more-familiar block-syntax for a [lambda expression](#lambda-expressions), including a special translation of [return expressions](#return-expressions) inside the supplied block. +Any occurrence of a [return expression](#return-expressions) +inside this `block` expression is rewritten +as a reference to an (anonymous) flag set in the caller's environment, +which is checked on return from the `expr` and, if set, +causes a corresponding return from the caller. +In this way, the meaning of `return` statements in language built-in control blocks is preserved, +if they are rewritten using lambda functions and `do` expressions as abstractions. + The optional `ident_list` and `block` provided in a `do` expression are parsed as though they constitute a lambda expression; if the `ident_list` is missing, an empty `ident_list` is implied. @@ -2296,19 +2307,15 @@ A _for expression_ is similar to a [`do` expression](#do-expressions), in that it provides a special block-form of lambda expression, suited to passing the `block` function to a higher-order function implementing a loop. -Like a `do` expression, a `return` expression inside a `for` expresison is rewritten, -to access a local flag that causes an early return in the caller. - -Additionally, any occurrence of a [return expression](#return-expressions) -inside the `block` of a `for` expression is rewritten -as a reference to an (anonymous) flag set in the caller's environment, -which is checked on return from the `expr` and, if set, -causes a corresponding return from the caller. -In this way, the meaning of `return` statements in language built-in control blocks is preserved, -if they are rewritten using lambda functions and `do` expressions as abstractions. +In contrast to a `do` expression, a `for` expression is designed to work +with methods such as `each` and `times`, that require the body block to +return a boolean. The `for` expression accommodates this by implicitly +returning `true` at the end of each block, unless a `break` expression +is evaluated. -Like `return` expressions, any [`break`](#break-expressions) and [`loop`](#loop-expressions) expressions -are rewritten inside `for` expressions, with a combination of local flag variables, +In addition, [`break`](#break-expressions) and [`loop`](#loop-expressions) expressions +are rewritten inside `for` expressions in the same way that `return` expressions are, +with a combination of local flag variables, and early boolean-valued returns from the `block` function, such that the meaning of `break` and `loop` is preserved in a primitive loop when rewritten as a `for` loop controlled by a higher order function. @@ -2318,7 +2325,9 @@ An example of a for loop over the contents of a vector: ~~~~ # type foo = int; # fn bar(f: foo) { } -# let a = 0, b = 0, c = 0; +# let a = 0; +# let b = 0; +# let c = 0; let v: &[foo] = &[a, b, c]; @@ -2330,6 +2339,7 @@ for v.each |e| { An example of a for loop over a series of integers: ~~~~ +# use std::uint; # fn bar(b:uint) { } for uint::range(0, 256) |i| { bar(i); @@ -2430,10 +2440,11 @@ match x { } ~~~~ -Patterns that bind variables default to binding to a copy of the matched value. This can be made -explicit using the ```copy``` keyword, changed to bind to a borrowed pointer by using the ```ref``` -keyword, or to a mutable borrowed pointer using ```ref mut```, or the value can be moved into -the new binding using ```move```. +Patterns that bind variables default to binding to a copy or move of the matched value +(depending on the matched value's type). +This can be made explicit using the ```copy``` keyword, +changed to bind to a borrowed pointer by using the ```ref``` keyword, +or to a mutable borrowed pointer using ```ref mut```. A pattern that's just an identifier, like `Nil` in the previous answer, @@ -2792,6 +2803,7 @@ the vtable pointer for the `T` implementation of `R`, and the pointer value of ` An example of an object type: ~~~~~~~~ +# use std::int; trait Printable { fn to_str(&self) -> ~str; } @@ -2801,7 +2813,7 @@ impl Printable for int { } fn print(a: @Printable) { - io::println(a.to_str()); + println(a.to_str()); } fn main() { @@ -2990,7 +3002,7 @@ allocated within the stack's memory. The value is a part of the stack frame. Local variables are immutable unless declared with `let mut`. The `mut` keyword applies to all local variables declared within that -declaration (so `let mut x, y` declares two mutable variables, `x` and +declaration (so `let mut (x, y) = ...` declares two mutable variables, `x` and `y`). Function parameters are immutable unless declared with `mut`. The @@ -3163,7 +3175,7 @@ execute, after which it is *descheduled* at a loop-edge or similar preemption point, and another task within is scheduled, pseudo-randomly. An executing task can yield control at any time, by making a library call to -`core::task::yield`, which deschedules it immediately. Entering any other +`std::task::yield`, which deschedules it immediately. Entering any other non-executing state (blocked, dead) similarly deschedules the task. @@ -3176,7 +3188,7 @@ run-time. It is smaller and simpler than many modern language runtimes. It is tightly integrated into the language's execution model of memory, tasks, communication and logging. -> **Note:** The runtime library will merge with the `core` library in future versions of Rust. +> **Note:** The runtime library will merge with the `std` library in future versions of Rust. ### Memory allocation diff --git a/doc/rustpkg.md b/doc/rustpkg.md index ac3d32dcd8e61..b12bce5a0afdf 100644 --- a/doc/rustpkg.md +++ b/doc/rustpkg.md @@ -30,6 +30,12 @@ or the equivalent on Windows. Each workspace may contain one or more packages. +When building code that contains one or more directives of the form `extern mod P`, +rustpkg automatically searches for packages named `P` in the `RUST_PATH` (as described above). +It builds those dependencies if necessary. +Thus, when using rustpkg, +there is no need for `-L` flags to tell the linker where to find libraries for external crates. + # Package structure A valid workspace must contain each of the following subdirectories: @@ -66,6 +72,10 @@ A package can be stored in a workspace on the local file system, or on a remote Web server, in which case the package ID resembles a URL. For example, `github.com/mozilla/rust` is a package ID that would refer to the git repository browsable at `http://github.com/mozilla/rust`. +A package ID can also specify a version, like: +`github.com/mozilla/rust#0.3`. +In this case, `rustpkg` will check that the repository `github.com/mozilla/rust` has a tag named `0.3`, +and report an error otherwise. ## Source files @@ -76,6 +86,15 @@ rustpkg searches for four different fixed filenames in order to determine the cr * `test.rs`: Assumed to contain tests declared with the `#[test]` attribute. * `bench.rs`: Assumed to contain benchmarks declared with the `#[bench]` attribute. +## Versions + +`rustpkg` packages do not need to declare their versions with an attribute inside one of the source files, +because `rustpkg` infers it from the version control system. +When building a package that is in a `git` repository, +`rustpkg` assumes that the most recent tag specifies the current version. +When building a package that is not under version control, +or that has no tags, `rustpkg` assumes the intended version is 0.1. + # Custom build scripts A file called `pkg.rs` at the root level in a workspace is called a *package script*. diff --git a/doc/tutorial-ffi.md b/doc/tutorial-ffi.md index b2c2a8824eee6..d3c682ce1adcd 100644 --- a/doc/tutorial-ffi.md +++ b/doc/tutorial-ffi.md @@ -12,7 +12,7 @@ The following is a minimal example of calling a foreign function which will comp installed: ~~~~ {.xfail-test} -use core::libc::size_t; +use std::libc::size_t; #[link_args = "-lsnappy"] extern { @@ -42,7 +42,7 @@ runtime. The `extern` block can be extended to cover the entire snappy API: ~~~~ {.xfail-test} -use core::libc::{c_int, size_t}; +use std::libc::{c_int, size_t}; #[link_args = "-lsnappy"] extern { @@ -149,19 +149,20 @@ A type with the same functionality as owned boxes can be implemented by wrapping `malloc` and `free`: ~~~~ -use core::libc::{c_void, size_t, malloc, free}; -use core::unstable::intrinsics; -use core::util; +use std::cast; +use std::libc::{c_void, size_t, malloc, free}; +use std::ptr; +use std::unstable::intrinsics; // a wrapper around the handle returned by the foreign code pub struct Unique { priv ptr: *mut T } -pub impl Unique { - fn new(value: T) -> Unique { +impl Unique { + pub fn new(value: T) -> Unique { unsafe { - let ptr = malloc(core::sys::size_of::() as size_t) as *mut T; + let ptr = malloc(std::sys::size_of::() as size_t) as *mut T; assert!(!ptr::is_null(ptr)); // `*ptr` is uninitialized, and `*ptr = value` would attempt to destroy it intrinsics::move_val_init(&mut *ptr, value); @@ -170,12 +171,12 @@ pub impl Unique { } // the 'r lifetime results in the same semantics as `&*x` with ~T - fn borrow<'r>(&'r self) -> &'r T { + pub fn borrow<'r>(&'r self) -> &'r T { unsafe { cast::copy_lifetime(self, &*self.ptr) } } // the 'r lifetime results in the same semantics as `&mut *x` with ~T - fn borrow_mut<'r>(&'r mut self) -> &'r mut T { + pub fn borrow_mut<'r>(&'r mut self) -> &'r mut T { unsafe { cast::copy_mut_lifetime(self, &mut *self.ptr) } } } @@ -184,9 +185,9 @@ pub impl Unique { impl Drop for Unique { fn finalize(&self) { unsafe { - let mut x = intrinsics::init(); // dummy value to swap in + let x = intrinsics::init(); // dummy value to swap in // moving the object out is needed to call the destructor - util::replace_ptr(self.ptr, x); + ptr::replace_ptr(self.ptr, x); free(self.ptr as *c_void) } } diff --git a/doc/tutorial-macros.md b/doc/tutorial-macros.md index 7e8ad2f582d5e..f1f4ade0542d5 100644 --- a/doc/tutorial-macros.md +++ b/doc/tutorial-macros.md @@ -13,7 +13,8 @@ doing nothing otherwise: ~~~~ # enum t { special_a(uint), special_b(uint) }; # fn f() -> uint { -# let input_1 = special_a(0), input_2 = special_a(0); +# let input_1 = special_a(0); +# let input_2 = special_a(0); match input_1 { special_a(x) => { return x; } _ => {} @@ -38,7 +39,8 @@ the pattern in the above code: ~~~~ # enum t { special_a(uint), special_b(uint) }; # fn f() -> uint { -# let input_1 = special_a(0), input_2 = special_a(0); +# let input_1 = special_a(0); +# let input_2 = special_a(0); macro_rules! early_return( ($inp:expr $sp:ident) => ( // invoke it like `(input_5 special_e)` match $inp { @@ -155,7 +157,8 @@ instead of `*` to mean "at least one". ~~~~ # enum t { special_a(uint),special_b(uint),special_c(uint),special_d(uint)}; # fn f() -> uint { -# let input_1 = special_a(0), input_2 = special_a(0); +# let input_1 = special_a(0); +# let input_2 = special_a(0); macro_rules! early_return( ($inp:expr, [ $($sp:ident)|+ ]) => ( match $inp { diff --git a/doc/tutorial-tasks.md b/doc/tutorial-tasks.md index 402cfa84afcba..2f150755fc2d9 100644 --- a/doc/tutorial-tasks.md +++ b/doc/tutorial-tasks.md @@ -39,38 +39,40 @@ data through the global _exchange heap_. While Rust's type system provides the building blocks needed for safe and efficient tasks, all of the task functionality itself is implemented -in the core and standard libraries, which are still under development +in the standard and extra libraries, which are still under development and do not always present a consistent or complete interface. For your reference, these are the standard modules involved in Rust -concurrency at this writing. - -* [`core::task`] - All code relating to tasks and task scheduling -* [`core::comm`] - The message passing interface -* [`core::pipes`] - The underlying messaging infrastructure -* [`std::comm`] - Additional messaging types based on `core::pipes` -* [`std::sync`] - More exotic synchronization tools, including locks -* [`std::arc`] - The ARC (atomically reference counted) type, - for safely sharing immutable data - -[`core::task`]: core/task.html -[`core::comm`]: core/comm.html -[`core::pipes`]: core/pipes.html +concurrency at this writing: + +* [`std::task`] - All code relating to tasks and task scheduling, +* [`std::comm`] - The message passing interface, +* [`std::pipes`] - The underlying messaging infrastructure, +* [`extra::comm`] - Additional messaging types based on `std::pipes`, +* [`extra::sync`] - More exotic synchronization tools, including locks, +* [`extra::arc`] - The ARC (atomically reference counted) type, + for safely sharing immutable data, +* [`extra::future`] - A type representing values that may be computed concurrently and retrieved at a later time. + +[`std::task`]: std/task.html [`std::comm`]: std/comm.html -[`std::sync`]: std/sync.html -[`std::arc`]: std/arc.html +[`std::pipes`]: std/pipes.html +[`extra::comm`]: extra/comm.html +[`extra::sync`]: extra/sync.html +[`extra::arc`]: extra/arc.html +[`extra::future`]: extra/future.html # Basics The programming interface for creating and managing tasks lives -in the `task` module of the `core` library, and is thus available to all +in the `task` module of the `std` library, and is thus available to all Rust code by default. At its simplest, creating a task is a matter of calling the `spawn` function with a closure argument. `spawn` executes the closure in the new task. ~~~~ -# use core::io::println; -use core::task::spawn; +# use std::io::println; +# use std::task::spawn; // Print something profound in a different task using a named function fn print_message() { println("I am running in a different task!"); } @@ -88,7 +90,7 @@ do spawn { In Rust, there is nothing special about creating tasks: a task is not a concept that appears in the language semantics. Instead, Rust's type system provides all the tools necessary to implement safe concurrency: particularly, -_owned types_. The language leaves the implementation details to the core +_owned types_. The language leaves the implementation details to the standard library. The `spawn` function has a very simple type signature: `fn spawn(f: @@ -99,8 +101,8 @@ execution. Like any closure, the function passed to `spawn` may capture an environment that it carries across tasks. ~~~ -# use core::io::println; -# use core::task::spawn; +# use std::io::println; +# use std::task::spawn; # fn generate_task_number() -> int { 0 } // Generate some state locally let child_task_number = generate_task_number(); @@ -116,8 +118,9 @@ in parallel. Thus, on a multicore machine, running the following code should interleave the output in vaguely random order. ~~~ -# use core::io::print; -# use core::task::spawn; +# use std::io::print; +# use std::task::spawn; +# use std::int; for int::range(0, 20) |child_task_number| { do spawn { @@ -145,8 +148,8 @@ endpoint. Consider the following example of calculating two results concurrently: ~~~~ -use core::task::spawn; -use core::comm::{stream, Port, Chan}; +# use std::task::spawn; +# use std::comm::{stream, Port, Chan}; let (port, chan): (Port, Chan) = stream(); @@ -167,7 +170,7 @@ stream for sending and receiving integers (the left-hand side of the `let`, a tuple into its component parts). ~~~~ -# use core::comm::{stream, Chan, Port}; +# use std::comm::{stream, Chan, Port}; let (port, chan): (Port, Chan) = stream(); ~~~~ @@ -176,8 +179,8 @@ which will wait to receive the data on the port. The next statement spawns the child task. ~~~~ -# use core::task::spawn; -# use core::comm::stream; +# use std::task::spawn; +# use std::comm::stream; # fn some_expensive_computation() -> int { 42 } # let (port, chan) = stream(); do spawn || { @@ -197,7 +200,7 @@ computation, then waits for the child's result to arrive on the port: ~~~~ -# use core::comm::{stream}; +# use std::comm::{stream}; # fn some_other_expensive_computation() {} # let (port, chan) = stream::(); # chan.send(0); @@ -212,8 +215,8 @@ example needed to compute multiple results across a number of tasks? The following program is ill-typed: ~~~ {.xfail-test} -# use core::task::{spawn}; -# use core::comm::{stream, Port, Chan}; +# use std::task::{spawn}; +# use std::comm::{stream, Port, Chan}; # fn some_expensive_computation() -> int { 42 } let (port, chan) = stream(); @@ -232,8 +235,9 @@ Instead we can use a `SharedChan`, a type that allows a single `Chan` to be shared by multiple senders. ~~~ -# use core::task::spawn; -use core::comm::{stream, SharedChan}; +# use std::task::spawn; +# use std::comm::{stream, SharedChan}; +# use std::uint; let (port, chan) = stream(); let chan = SharedChan::new(chan); @@ -265,8 +269,9 @@ illustrate the point. For reference, written with multiple streams, it might look like the example below. ~~~ -# use core::task::spawn; -# use core::comm::stream; +# use std::task::spawn; +# use std::comm::stream; +# use std::vec; // Create a vector of ports, one for each child task let ports = do vec::from_fn(3) |init_val| { @@ -282,6 +287,133 @@ let result = ports.foldl(0, |accum, port| *accum + port.recv() ); # fn some_expensive_computation(_i: uint) -> int { 42 } ~~~ +## Backgrounding computations: Futures +With `extra::future`, rust has a mechanism for requesting a computation and getting the result +later. + +The basic example below illustrates this. +~~~ +# fn make_a_sandwich() {}; +fn fib(n: uint) -> uint { + // lengthy computation returning an uint + 12586269025 +} + +let mut delayed_fib = extra::future::spawn (|| fib(50) ); +make_a_sandwich(); +println(fmt!("fib(50) = %?", delayed_fib.get())) +~~~ + +The call to `future::spawn` returns immediately a `future` object regardless of how long it +takes to run `fib(50)`. You can then make yourself a sandwich while the computation of `fib` is +running. The result of the execution of the method is obtained by calling `get` on the future. +This call will block until the value is available (*i.e.* the computation is complete). Note that +the future needs to be mutable so that it can save the result for next time `get` is called. + +Here is another example showing how futures allow you to background computations. The workload will +be distributed on the available cores. +~~~ +# use std::vec; +# use std::uint; +fn partial_sum(start: uint) -> f64 { + let mut local_sum = 0f64; + for uint::range(start*100000, (start+1)*100000) |num| { + local_sum += (num as f64 + 1.0).pow(-2.0); + } + local_sum +} + +fn main() { + let mut futures = vec::from_fn(1000, |ind| do extra::future::spawn { partial_sum(ind) }); + + let mut final_res = 0f64; + for futures.each_mut |ft| { + final_res += ft.get(); + } + println(fmt!("π^2/6 is not far from : %?", final_res)); +} +~~~ + +## Sharing immutable data without copy: ARC + +To share immutable data between tasks, a first approach would be to only use pipes as we have seen +previously. A copy of the data to share would then be made for each task. In some cases, this would +add up to a significant amount of wasted memory and would require copying the same data more than +necessary. + +To tackle this issue, one can use an Atomically Reference Counted wrapper (`ARC`) as implemented in +the `extra` library of Rust. With an ARC, the data will no longer be copied for each task. The ARC +acts as a reference to the shared data and only this reference is shared and cloned. + +Here is a small example showing how to use ARCs. We wish to run concurrently several computations on +a single large vector of floats. Each task needs the full vector to perform its duty. +~~~ +# use std::vec; +# use std::uint; +# use std::rand; +use extra::arc::ARC; + +fn pnorm(nums: &~[float], p: uint) -> float { + (vec::foldl(0.0, *nums, |a,b| a+(*b).pow(p as float) )).pow(1f / (p as float)) +} + +fn main() { + let numbers = vec::from_fn(1000000, |_| rand::random::()); + println(fmt!("Inf-norm = %?", numbers.max())); + + let numbers_arc = ARC(numbers); + + for uint::range(1,10) |num| { + let (port, chan) = stream(); + chan.send(numbers_arc.clone()); + + do spawn { + let local_arc : ARC<~[float]> = port.recv(); + let task_numbers = local_arc.get(); + println(fmt!("%u-norm = %?", num, pnorm(task_numbers, num))); + } + } +} +~~~ + +The function `pnorm` performs a simple computation on the vector (it computes the sum of its items +at the power given as argument and takes the inverse power of this value). The ARC on the vector is +created by the line +~~~ +# use extra::arc::ARC; +# use std::vec; +# use std::rand; +# let numbers = vec::from_fn(1000000, |_| rand::random::()); +let numbers_arc=ARC(numbers); +~~~ +and a clone of it is sent to each task +~~~ +# use extra::arc::ARC; +# use std::vec; +# use std::rand; +# let numbers=vec::from_fn(1000000, |_| rand::random::()); +# let numbers_arc = ARC(numbers); +# let (port, chan) = stream(); +chan.send(numbers_arc.clone()); +~~~ +copying only the wrapper and not its contents. + +Each task recovers the underlying data by +~~~ +# use extra::arc::ARC; +# use std::vec; +# use std::rand; +# let numbers=vec::from_fn(1000000, |_| rand::random::()); +# let numbers_arc=ARC(numbers); +# let (port, chan) = stream(); +# chan.send(numbers_arc.clone()); +# let local_arc : ARC<~[float]> = port.recv(); +let task_numbers = local_arc.get(); +~~~ +and can use it as if it were local. + +The `arc` module also implements ARCs around mutable data that are not covered here. + # Handling task failure Rust has a built-in mechanism for raising exceptions. The `fail!()` macro @@ -297,7 +429,8 @@ All tasks are, by default, _linked_ to each other. That means that the fates of all tasks are intertwined: if one fails, so do all the others. ~~~ -# use core::task::spawn; +# use std::task::spawn; +# use std::task; # fn do_some_work() { loop { task::yield() } } # do task::try { // Create a child task that fails @@ -319,6 +452,7 @@ field (representing a successful result) or an `Err` result (representing termination with an error). ~~~ +# use std::task; # fn some_condition() -> bool { false } # fn calculate_result() -> int { 0 } let result: Result = do task::try { @@ -337,7 +471,7 @@ enum. If the child task terminates successfully, `try` will return an `Ok` result; if the child task fails, `try` will return an `Error` result. -[`Result`]: core/result.html +[`Result`]: std/result.html > ***Note:*** A failed task does not currently produce a useful error > value (`try` always returns `Err(())`). In the @@ -361,10 +495,11 @@ By default, task failure is _bidirectionally linked_, which means that if either task fails, it kills the other one. ~~~ +# use std::task; # fn sleep_forever() { loop { task::yield() } } # do task::try { -do task::spawn { - do task::spawn { +do spawn { + do spawn { fail!(); // All three tasks will fail. } sleep_forever(); // Will get woken up by force, then fail @@ -381,8 +516,9 @@ internally, with additional logic to wait for the child task to finish before returning. Hence: ~~~ -# use core::comm::{stream, Chan, Port}; -# use core::task::{spawn, try}; +# use std::comm::{stream, Chan, Port}; +# use std::task::{spawn, try}; +# use std::task; # fn sleep_forever() { loop { task::yield() } } # do task::try { let (receiver, sender): (Port, Chan) = stream(); @@ -410,6 +546,7 @@ Supervised task failure propagates across multiple generations even if an intermediate generation has already exited: ~~~ +# use std::task; # fn sleep_forever() { loop { task::yield() } } # fn wait_for_a_while() { for 1000.times { task::yield() } } # do task::try:: { @@ -428,6 +565,7 @@ Finally, tasks can be configured to not propagate failure to each other at all, using `task::spawn_unlinked` for _isolated failure_. ~~~ +# use std::task; # fn random() -> uint { 100 } # fn sleep_for(i: uint) { for i.times { task::yield() } } # do task::try::<()> { @@ -446,7 +584,7 @@ fail!(); A very common thing to do is to spawn a child task where the parent and child both need to exchange messages with each other. The -function `std::comm::DuplexStream()` supports this pattern. We'll +function `extra::comm::DuplexStream()` supports this pattern. We'll look briefly at how to use it. To see how `DuplexStream()` works, we will create a child task @@ -455,7 +593,8 @@ the string in response. The child terminates when it receives `0`. Here is the function that implements the child task: ~~~~ -# use std::comm::DuplexStream; +# use extra::comm::DuplexStream; +# use std::uint; fn stringifier(channel: &DuplexStream<~str, uint>) { let mut value: uint; loop { @@ -477,8 +616,9 @@ response itself is simply the stringified version of the received value, Here is the code for the parent task: ~~~~ -# use core::task::spawn; -# use std::comm::DuplexStream; +# use std::task::spawn; +# use std::uint; +# use extra::comm::DuplexStream; # fn stringifier(channel: &DuplexStream<~str, uint>) { # let mut value: uint; # loop { diff --git a/doc/tutorial.md b/doc/tutorial.md index a01423d3fd3fc..14a0c6fdcfe27 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -502,6 +502,7 @@ types. > items. ~~~~ +# use std::float; fn angle(vector: (float, float)) -> float { let pi = float::consts::pi; match vector { @@ -556,6 +557,7 @@ while cake_amount > 0 { `loop` denotes an infinite loop, and is the preferred way of writing `while true`: ~~~~ +# use std::int; let mut x = 5; loop { x += x - 3; @@ -699,6 +701,7 @@ get at their contents. All variant constructors can be used as patterns, as in this definition of `area`: ~~~~ +# use std::float; # struct Point {x: float, y: float} # enum Shape { Circle(Point, float), Rectangle(Point, Point) } fn area(sh: Shape) -> float { @@ -730,7 +733,7 @@ fn point_from_direction(dir: Direction) -> Point { Enum variants may also be structs. For example: ~~~~ -# use core::float; +# use std::float; # struct Point { x: float, y: float } # fn square(x: float) -> float { x * x } enum Shape { @@ -1366,11 +1369,11 @@ let exchange_crayons: ~str = ~"Black, BlizzardBlue, Blue"; ~~~ Both vectors and strings support a number of useful -[methods](#functions-and-methods), defined in [`core::vec`] -and [`core::str`]. Here are some examples. +[methods](#functions-and-methods), defined in [`std::vec`] +and [`std::str`]. Here are some examples. -[`core::vec`]: core/vec.html -[`core::str`]: core/str.html +[`std::vec`]: std/vec.html +[`std::str`]: std/str.html ~~~ # enum Crayon { @@ -1480,7 +1483,6 @@ This code creates a closure that adds a given string to its argument, returns it from a function, and then calls it: ~~~~ -# extern mod std; fn mk_appender(suffix: ~str) -> @fn(~str) -> ~str { // The compiler knows that we intend this closure to be of type @fn return |s| s + suffix; @@ -1583,7 +1585,7 @@ words, it is a function that takes an owned closure that takes no arguments. ~~~~ -use core::task::spawn; +use std::task::spawn; do spawn() || { debug!("I'm a task, whatever"); @@ -1595,7 +1597,7 @@ lists back to back. Since that is so unsightly, empty argument lists may be omitted from `do` expressions. ~~~~ -# use core::task::spawn; +# use std::task::spawn; do spawn { debug!("Kablam!"); } @@ -1629,7 +1631,7 @@ fn each(v: &[int], op: &fn(v: &int) -> bool) { And using this function to iterate over a vector: ~~~~ -# use each = core::vec::each; +# use each = std::vec::each; each([2, 4, 8, 5, 16], |n| { if *n % 2 != 0 { println("found odd number!"); @@ -1645,7 +1647,7 @@ out of the loop, you just write `break`. To skip ahead to the next iteration, write `loop`. ~~~~ -# use each = core::vec::each; +# use each = std::vec::each; for each([2, 4, 8, 5, 16]) |n| { if *n % 2 != 0 { println("found odd number!"); @@ -1660,7 +1662,7 @@ normally allowed in closures, in a block that appears as the body of a the enclosing function, not just the loop body. ~~~~ -# use each = core::vec::each; +# use each = std::vec::each; fn contains(v: &[int], elt: int) -> bool { for each(v) |x| { if (*x == elt) { return true; } @@ -1675,7 +1677,7 @@ In these situations it can be convenient to lean on Rust's argument patterns to bind `x` to the actual value, not the pointer. ~~~~ -# use each = core::vec::each; +# use each = std::vec::each; # fn contains(v: &[int], elt: int) -> bool { for each(v) |&x| { if (x == elt) { return true; } @@ -1810,8 +1812,8 @@ impl Circle { To call such a method, just prefix it with the type name and a double colon: ~~~~ -# use core::float::consts::pi; -# use core::float::sqrt; +# use std::float::consts::pi; +# use std::float::sqrt; struct Circle { radius: float } impl Circle { fn new(area: float) -> Circle { Circle { radius: sqrt(area / pi) } } @@ -1830,6 +1832,7 @@ vector consisting of the result of applying `function` to each element of `vector`: ~~~~ +# use std::vec; fn map(vector: &[T], function: &fn(v: &T) -> U) -> ~[U] { let mut accumulator = ~[]; for vec::each(vector) |element| { @@ -1857,7 +1860,7 @@ illegal to copy and pass by value. Generic `type`, `struct`, and `enum` declarations follow the same pattern: ~~~~ -# use core::hashmap::HashMap; +# use std::hashmap::HashMap; type Set = HashMap; struct Stack { @@ -1977,7 +1980,7 @@ struct TimeBomb { impl Drop for TimeBomb { fn finalize(&self) { - for old_iter::repeat(self.explosivity) { + for self.explosivity.times { println("blam!"); } } @@ -2027,6 +2030,7 @@ themselves contain type parameters. A trait for generalized sequence types might look like the following: ~~~~ +# use std::vec; trait Seq { fn len(&self) -> uint; fn iter(&self, b: &fn(v: &T)); @@ -2081,8 +2085,8 @@ name and a double colon. The compiler uses type inference to decide which implementation to use. ~~~~ -# use core::float::consts::pi; -# use core::float::sqrt; +# use std::float::consts::pi; +# use std::float::sqrt; trait Shape { fn new(area: float) -> Self; } struct Circle { radius: float } struct Square { length: float } @@ -2238,8 +2242,8 @@ trait Circle : Shape { fn radius(&self) -> float; } Now, we can implement `Circle` on a type only if we also implement `Shape`. ~~~~ -# use core::float::consts::pi; -# use core::float::sqrt; +# use std::float::consts::pi; +# use std::float::sqrt; # trait Shape { fn area(&self) -> float; } # trait Circle : Shape { fn radius(&self) -> float; } # struct Point { x: float, y: float } @@ -2274,8 +2278,8 @@ fn radius_times_area(c: T) -> float { Likewise, supertrait methods may also be called on trait objects. ~~~ {.xfail-test} -# use core::float::consts::pi; -# use core::float::sqrt; +# use std::float::consts::pi; +# use std::float::sqrt; # trait Shape { fn area(&self) -> float; } # trait Circle : Shape { fn radius(&self) -> float; } # struct Point { x: float, y: float } @@ -2292,7 +2296,7 @@ let nonsense = mycircle.radius() * mycircle.area(); ## Deriving implementations for traits -A small number of traits in `core` and `std` can have implementations +A small number of traits in `std` and `extra` can have implementations that can be automatically derived. These instances are specified by placing the `deriving` attribute on a data type declaration. For example, the following will mean that `Circle` has an implementation @@ -2541,17 +2545,17 @@ as well as an inscrutable string of alphanumerics. These are both part of Rust's library versioning scheme. The alphanumerics are a hash representing the crate metadata. -## The core library +## The standard library -The Rust core library provides runtime features required by the language, +The Rust standard library provides runtime features required by the language, including the task scheduler and memory allocators, as well as library support for Rust built-in types, platform abstractions, and other commonly used features. -[`core`] includes modules corresponding to each of the integer types, each of +[`std`] includes modules corresponding to each of the integer types, each of the floating point types, the [`bool`] type, [tuples], [characters], [strings], [vectors], [managed boxes], [owned boxes], -and unsafe and borrowed [pointers]. Additionally, `core` provides +and unsafe and borrowed [pointers]. Additionally, `std` provides some pervasive types ([`option`] and [`result`]), [task] creation and [communication] primitives, platform abstractions ([`os`] and [`path`]), basic @@ -2559,49 +2563,49 @@ I/O abstractions ([`io`]), [containers] like [`hashmap`], common traits ([`kinds`], [`ops`], [`cmp`], [`num`], [`to_str`], [`clone`]), and complete bindings to the C standard library ([`libc`]). -### Core injection and the Rust prelude +### Standard Library injection and the Rust prelude -`core` is imported at the topmost level of every crate by default, as +`std` is imported at the topmost level of every crate by default, as if the first line of each crate was - extern mod core; + extern mod std; -This means that the contents of core can be accessed from from any context -with the `core::` path prefix, as in `use core::vec`, `use core::task::spawn`, +This means that the contents of std can be accessed from from any context +with the `std::` path prefix, as in `use std::vec`, `use std::task::spawn`, etc. -Additionally, `core` contains a `prelude` module that reexports many of the -most common core modules, types and traits. The contents of the prelude are +Additionally, `std` contains a `prelude` module that reexports many of the +most common standard modules, types and traits. The contents of the prelude are imported into every *module* by default. Implicitly, all modules behave as if they contained the following prologue: - use core::prelude::*; - -[`core`]: core/index.html -[`bool`]: core/bool.html -[tuples]: core/tuple.html -[characters]: core/char.html -[strings]: core/str.html -[vectors]: core/vec.html -[managed boxes]: core/managed.html -[owned boxes]: core/owned.html -[pointers]: core/ptr.html -[`option`]: core/option.html -[`result`]: core/result.html -[task]: core/task.html -[communication]: core/comm.html -[`os`]: core/os.html -[`path`]: core/path.html -[`io`]: core/io.html -[containers]: core/container.html -[`hashmap`]: core/hashmap.html -[`kinds`]: core/kinds.html -[`ops`]: core/ops.html -[`cmp`]: core/cmp.html -[`num`]: core/num.html -[`to_str`]: core/to_str.html -[`clone`]: core/clone.html -[`libc`]: core/libc.html + use std::prelude::*; + +[`std`]: std/index.html +[`bool`]: std/bool.html +[tuples]: std/tuple.html +[characters]: std/char.html +[strings]: std/str.html +[vectors]: std/vec.html +[managed boxes]: std/managed.html +[owned boxes]: std/owned.html +[pointers]: std/ptr.html +[`option`]: std/option.html +[`result`]: std/result.html +[task]: std/task.html +[communication]: std/comm.html +[`os`]: std/os.html +[`path`]: std/path.html +[`io`]: std/io.html +[containers]: std/container.html +[`hashmap`]: std/hashmap.html +[`kinds`]: std/kinds.html +[`ops`]: std/ops.html +[`cmp`]: std/cmp.html +[`num`]: std/num.html +[`to_str`]: std/to_str.html +[`clone`]: std/clone.html +[`libc`]: std/libc.html # What next? diff --git a/mk/clean.mk b/mk/clean.mk index 660793b1c347e..9a074b29d8b1c 100644 --- a/mk/clean.mk +++ b/mk/clean.mk @@ -73,14 +73,14 @@ clean$(1)_H_$(2): $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_LIBRUSTPKG_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_LIBRUSTDOC_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_RUNTIME_$(2)) - $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_CORELIB_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_STDLIB_$(2)) + $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_EXTRALIB_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_LIBRUSTC_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_LIBSYNTAX_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_LIBRUSTI_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_LIBRUST_$(2)) - $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CORELIB_GLOB_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(STDLIB_GLOB_$(2)) + $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(EXTRALIB_GLOB_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBRUSTC_GLOB_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBSYNTAX_GLOB_$(2)) $(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBFUZZER_GLOB_$(2)) @@ -111,14 +111,14 @@ clean$(1)_T_$(2)_H_$(3): $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTPKG_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTDOC_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_RUNTIME_$(2)) - $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_CORELIB_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_STDLIB_$(2)) + $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_EXTRALIB_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTC_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBSYNTAX_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTI_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUST_$(2)) - $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CORELIB_GLOB_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(STDLIB_GLOB_$(2)) + $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(EXTRALIB_GLOB_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBRUSTC_GLOB_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBSYNTAX_GLOB_$(2)) $(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBFUZZER_GLOB_$(2)) diff --git a/mk/dist.mk b/mk/dist.mk index f71abc48620d1..96f35031de930 100644 --- a/mk/dist.mk +++ b/mk/dist.mk @@ -33,9 +33,9 @@ PKG_FILES := \ compiletest \ etc \ libfuzzer \ - libcore \ - libsyntax \ + libextra \ libstd \ + libsyntax \ rt \ librustdoc \ rustllvm \ diff --git a/mk/docs.mk b/mk/docs.mk index f49c75d6acb01..8470da7c07b2c 100644 --- a/mk/docs.mk +++ b/mk/docs.mk @@ -173,7 +173,7 @@ endif ###################################################################### -# Rustdoc (libcore/std) +# Rustdoc (libstd/extra) ###################################################################### ifeq ($(CFG_PANDOC),) @@ -199,8 +199,8 @@ doc/$(1)/rust.css: rust.css DOCS += doc/$(1)/index.html endef -$(eval $(call libdoc,core,$(CORELIB_CRATE),$(CORELIB_INPUTS))) $(eval $(call libdoc,std,$(STDLIB_CRATE),$(STDLIB_INPUTS))) +$(eval $(call libdoc,extra,$(EXTRALIB_CRATE),$(EXTRALIB_INPUTS))) endif diff --git a/mk/host.mk b/mk/host.mk index 92c6ffbbe172f..ac3bc8ad8cbf9 100644 --- a/mk/host.mk +++ b/mk/host.mk @@ -28,8 +28,8 @@ $$(HBIN$(2)_H_$(4))/rustc$$(X_$(4)): \ $$(HLIB$(2)_H_$(4))/$(CFG_RUNTIME_$(4)) \ $$(HLIB$(2)_H_$(4))/$(CFG_RUSTLLVM_$(4)) \ $$(HLIB$(2)_H_$(4))/$(CFG_LIBRUSTC_$(4)) \ - $$(HCORELIB_DEFAULT$(2)_H_$(4)) \ $$(HSTDLIB_DEFAULT$(2)_H_$(4)) \ + $$(HEXTRALIB_DEFAULT$(2)_H_$(4)) \ | $$(HBIN$(2)_H_$(4))/ @$$(call E, cp: $$@) @@ -40,8 +40,8 @@ $$(HLIB$(2)_H_$(4))/$(CFG_LIBRUSTC_$(4)): \ $$(HLIB$(2)_H_$(4))/$(CFG_LIBSYNTAX_$(4)) \ $$(HLIB$(2)_H_$(4))/$(CFG_RUNTIME_$(4)) \ $$(HLIB$(2)_H_$(4))/$(CFG_RUSTLLVM_$(4)) \ - $$(HCORELIB_DEFAULT$(2)_H_$(4)) \ $$(HSTDLIB_DEFAULT$(2)_H_$(4)) \ + $$(HEXTRALIB_DEFAULT$(2)_H_$(4)) \ | $$(HLIB$(2)_H_$(4))/ @$$(call E, cp: $$@) @@ -54,8 +54,8 @@ $$(HLIB$(2)_H_$(4))/$(CFG_LIBSYNTAX_$(4)): \ $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBSYNTAX_$(4)) \ $$(HLIB$(2)_H_$(4))/$(CFG_RUNTIME_$(4)) \ $$(HLIB$(2)_H_$(4))/$(CFG_RUSTLLVM_$(4)) \ - $$(HCORELIB_DEFAULT$(2)_H_$(4)) \ $$(HSTDLIB_DEFAULT$(2)_H_$(4)) \ + $$(HEXTRALIB_DEFAULT$(2)_H_$(4)) \ | $$(HLIB$(2)_H_$(4))/ @$$(call E, cp: $$@) $$(Q)cp $$< $$@ @@ -69,44 +69,44 @@ $$(HLIB$(2)_H_$(4))/$(CFG_RUNTIME_$(4)): \ @$$(call E, cp: $$@) $$(Q)cp $$< $$@ -$$(HLIB$(2)_H_$(4))/$(CFG_CORELIB_$(4)): \ - $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_CORELIB_$(4)) \ +$$(HLIB$(2)_H_$(4))/$(CFG_STDLIB_$(4)): \ + $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_STDLIB_$(4)) \ $$(HLIB$(2)_H_$(4))/$(CFG_RUNTIME_$(4)) \ | $$(HLIB$(2)_H_$(4))/ @$$(call E, cp: $$@) $$(Q)cp $$< $$@ -# Subtle: We do not let the shell expand $(CORELIB_DSYM_GLOB) directly rather +# Subtle: We do not let the shell expand $(STDLIB_DSYM_GLOB) directly rather # we use Make's $$(wildcard) facility. The reason is that, on mac, when using -# USE_SNAPSHOT_CORELIB, we copy the core.dylib file out of the snapshot. +# USE_SNAPSHOT_STDLIB, we copy the std.dylib file out of the snapshot. # In that case, there is no .dSYM file. Annoyingly, bash then refuses to expand -# glob, and cp reports an error because libcore-*.dylib.dsym does not exist. +# glob, and cp reports an error because libstd-*.dylib.dsym does not exist. # Make instead expands the glob to nothing, which gives us the correct behavior. # (Copy .dsym file if it exists, but do nothing otherwise) - $$(Q)cp -R $$(TLIB$(1)_T_$(4)_H_$(3))/$(CORELIB_GLOB_$(4)) \ - $$(wildcard $$(TLIB$(1)_T_$(4)_H_$(3))/$(CORELIB_DSYM_GLOB_$(4))) \ + $$(Q)cp -R $$(TLIB$(1)_T_$(4)_H_$(3))/$(STDLIB_GLOB_$(4)) \ + $$(wildcard $$(TLIB$(1)_T_$(4)_H_$(3))/$(STDLIB_DSYM_GLOB_$(4))) \ $$(HLIB$(2)_H_$(4)) -$$(HLIB$(2)_H_$(4))/$(CFG_STDLIB_$(4)): \ - $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_STDLIB_$(4)) \ - $$(HLIB$(2)_H_$(4))/$(CFG_CORELIB_$(4)) \ +$$(HLIB$(2)_H_$(4))/$(CFG_EXTRALIB_$(4)): \ + $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_EXTRALIB_$(4)) \ + $$(HLIB$(2)_H_$(4))/$(CFG_STDLIB_$(4)) \ $$(HLIB$(2)_H_$(4))/$(CFG_RUNTIME_$(4)) \ | $$(HLIB$(2)_H_$(4))/ @$$(call E, cp: $$@) $$(Q)cp $$< $$@ - $$(Q)cp -R $$(TLIB$(1)_T_$(4)_H_$(3))/$(STDLIB_GLOB_$(4)) \ - $$(wildcard $$(TLIB$(1)_T_$(4)_H_$(3))/$(STDLIB_DSYM_GLOB_$(4))) \ + $$(Q)cp -R $$(TLIB$(1)_T_$(4)_H_$(3))/$(EXTRALIB_GLOB_$(4)) \ + $$(wildcard $$(TLIB$(1)_T_$(4)_H_$(3))/$(EXTRALIB_DSYM_GLOB_$(4))) \ $$(HLIB$(2)_H_$(4)) -$$(HLIB$(2)_H_$(4))/libcore.rlib: \ - $$(TLIB$(1)_T_$(4)_H_$(3))/libcore.rlib \ +$$(HLIB$(2)_H_$(4))/libstd.rlib: \ + $$(TLIB$(1)_T_$(4)_H_$(3))/libstd.rlib \ $$(HLIB$(2)_H_$(4))/$$(CFG_RUNTIME_$(4)) \ | $$(HLIB$(2)_H_$(4))/ @$$(call E, cp: $$@) $$(Q)cp $$< $$@ -$$(HLIB$(2)_H_$(4))/libstd.rlib: \ - $$(TLIB$(1)_T_$(4)_H_$(3))/libstd.rlib \ - $$(HLIB$(2)_H_$(4))/libcore.rlib \ +$$(HLIB$(2)_H_$(4))/libextra.rlib: \ + $$(TLIB$(1)_T_$(4)_H_$(3))/libextra.rlib \ + $$(HLIB$(2)_H_$(4))/libstd.rlib \ $$(HLIB$(2)_H_$(4))/$$(CFG_RUNTIME_$(4)) \ | $$(HLIB$(2)_H_$(4))/ @$$(call E, cp: $$@) @@ -114,8 +114,8 @@ $$(HLIB$(2)_H_$(4))/libstd.rlib: \ $$(HLIB$(2)_H_$(4))/librustc.rlib: \ $$(TLIB$(1)_T_$(4)_H_$(3))/librustc.rlib \ - $$(HLIB$(2)_H_$(4))/libcore.rlib \ $$(HLIB$(2)_H_$(4))/libstd.rlib \ + $$(HLIB$(2)_H_$(4))/libextra.rlib \ $$(HLIB$(2)_H_$(4))/$$(CFG_RUNTIME_$(4)) \ | $$(HLIB$(2)_H_$(4))/ @$$(call E, cp: $$@) diff --git a/mk/install.mk b/mk/install.mk index 47fcb224a7348..ae6bd29228f0b 100644 --- a/mk/install.mk +++ b/mk/install.mk @@ -52,10 +52,10 @@ define INSTALL_TARGET_N install-target-$(1)-host-$(2): $$(TSREQ$$(ISTAGE)_T_$(1)_H_$(2)) $$(SREQ$$(ISTAGE)_T_$(1)_H_$(2)) $$(Q)mkdir -p $$(PTL$(1)$(2)) $$(Q)$$(call INSTALL_LIB,$$(TL$(1)$(2)),$$(PTL$(1)$(2)),$$(CFG_RUNTIME_$(1))) - $$(Q)$$(call INSTALL_LIB, \ - $$(TL$(1)$(2)),$$(PTL$(1)$(2)),$$(CORELIB_GLOB_$(1))) $$(Q)$$(call INSTALL_LIB, \ $$(TL$(1)$(2)),$$(PTL$(1)$(2)),$$(STDLIB_GLOB_$(1))) + $$(Q)$$(call INSTALL_LIB, \ + $$(TL$(1)$(2)),$$(PTL$(1)$(2)),$$(EXTRALIB_GLOB_$(1))) $$(Q)$$(call INSTALL_LIB,$$(TL$(1)$(2)),$$(PTL$(1)$(2)),libmorestack.a) endef @@ -64,10 +64,10 @@ define INSTALL_HOST_N install-target-$(1)-host-$(2): $$(CSREQ$$(ISTAGE)_T_$(1)_H_$(2)) $$(Q)mkdir -p $$(PTL$(1)$(2)) $$(Q)$$(call INSTALL_LIB,$$(TL$(1)$(2)),$$(PTL$(1)$(2)),$$(CFG_RUNTIME_$(1))) - $$(Q)$$(call INSTALL_LIB, \ - $$(TL$(1)$(2)),$$(PTL$(1)$(2)),$$(CORELIB_GLOB_$(1))) $$(Q)$$(call INSTALL_LIB, \ $$(TL$(1)$(2)),$$(PTL$(1)$(2)),$$(STDLIB_GLOB_$(1))) + $$(Q)$$(call INSTALL_LIB, \ + $$(TL$(1)$(2)),$$(PTL$(1)$(2)),$$(EXTRALIB_GLOB_$(1))) $$(Q)$$(call INSTALL_LIB, \ $$(TL$(1)$(2)),$$(PTL$(1)$(2)),$$(LIBRUSTC_GLOB_$(1))) $$(Q)$$(call INSTALL_LIB, \ @@ -113,8 +113,8 @@ install-host: $(CSREQ$(ISTAGE)_T_$(CFG_BUILD_TRIPLE)_H_$(CFG_BUILD_TRIPLE)) $(Q)$(call INSTALL,$(HB2),$(PHB),rustdoc$(X_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL,$(HB2),$(PHB),rusti$(X_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL,$(HB2),$(PHB),rust$(X_$(CFG_BUILD_TRIPLE))) - $(Q)$(call INSTALL_LIB,$(HL),$(PHL),$(CORELIB_GLOB_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL_LIB,$(HL),$(PHL),$(STDLIB_GLOB_$(CFG_BUILD_TRIPLE))) + $(Q)$(call INSTALL_LIB,$(HL),$(PHL),$(EXTRALIB_GLOB_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL_LIB,$(HL),$(PHL),$(LIBRUSTC_GLOB_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL_LIB,$(HL),$(PHL),$(LIBSYNTAX_GLOB_$(CFG_BUILD_TRIPLE))) $(Q)$(call INSTALL_LIB,$(HL),$(PHL),$(LIBRUSTI_GLOB_$(CFG_BUILD_TRIPLE))) @@ -141,8 +141,8 @@ uninstall: $(Q)rm -f $(PHL)/$(CFG_RUSTLLVM_$(CFG_BUILD_TRIPLE)) $(Q)rm -f $(PHL)/$(CFG_RUNTIME_$(CFG_BUILD_TRIPLE)) $(Q)for i in \ - $(call HOST_LIB_FROM_HL_GLOB,$(CORELIB_GLOB_$(CFG_BUILD_TRIPLE))) \ $(call HOST_LIB_FROM_HL_GLOB,$(STDLIB_GLOB_$(CFG_BUILD_TRIPLE))) \ + $(call HOST_LIB_FROM_HL_GLOB,$(EXTRALIB_GLOB_$(CFG_BUILD_TRIPLE))) \ $(call HOST_LIB_FROM_HL_GLOB,$(LIBRUSTC_GLOB_$(CFG_BUILD_TRIPLE))) \ $(call HOST_LIB_FROM_HL_GLOB,$(LIBSYNTAX_GLOB_$(CFG_BUILD_TRIPLE))) \ $(call HOST_LIB_FROM_HL_GLOB,$(LIBRUSTPKG_GLOB_$(CFG_BUILD_TRIPLE))) \ @@ -203,16 +203,16 @@ define INSTALL_RUNTIME_TARGET_N install-runtime-target-$(1)-host-$(2): $$(TSREQ$$(ISTAGE)_T_$(1)_H_$(2)) $$(SREQ$$(ISTAGE)_T_$(1)_H_$(2)) $(Q)$(call ADB_SHELL,mkdir,$(CFG_RUNTIME_PUSH_DIR)) $(Q)$(call ADB_PUSH,$$(TL$(1)$(2))/$$(CFG_RUNTIME_$(1)),$(CFG_RUNTIME_PUSH_DIR)) - $(Q)$(call ADB_PUSH,$$(TL$(1)$(2))/$$(CORELIB_GLOB_$(1)),$(CFG_RUNTIME_PUSH_DIR)) $(Q)$(call ADB_PUSH,$$(TL$(1)$(2))/$$(STDLIB_GLOB_$(1)),$(CFG_RUNTIME_PUSH_DIR)) + $(Q)$(call ADB_PUSH,$$(TL$(1)$(2))/$$(EXTRALIB_GLOB_$(1)),$(CFG_RUNTIME_PUSH_DIR)) endef define INSTALL_RUNTIME_TARGET_CLEANUP_N install-runtime-target-$(1)-cleanup: $(Q)$(call ADB,remount) $(Q)$(call ADB_SHELL,rm,$(CFG_RUNTIME_PUSH_DIR)/$(CFG_RUNTIME_$(1))) - $(Q)$(call ADB_SHELL,rm,$(CFG_RUNTIME_PUSH_DIR)/$(CORELIB_GLOB_$(1))) $(Q)$(call ADB_SHELL,rm,$(CFG_RUNTIME_PUSH_DIR)/$(STDLIB_GLOB_$(1))) + $(Q)$(call ADB_SHELL,rm,$(CFG_RUNTIME_PUSH_DIR)/$(EXTRALIB_GLOB_$(1))) endef $(eval $(call INSTALL_RUNTIME_TARGET_N,arm-linux-androideabi,$(CFG_BUILD_TRIPLE))) diff --git a/mk/platform.mk b/mk/platform.mk index efba83e6ad4c7..9236bf57f2f4e 100644 --- a/mk/platform.mk +++ b/mk/platform.mk @@ -29,7 +29,7 @@ $(foreach t,$(CFG_TARGET_TRIPLES),$(info cfg: os for $(t) is $(OSTYPE_$(t)))) # FIXME: no-omit-frame-pointer is just so that task_start_wrapper # has a frame pointer and the stack walker can understand it. Turning off # frame pointers everywhere is overkill -CFG_GCCISH_CFLAGS += -fno-omit-frame-pointer +CFG_GCCISH_CFLAGS += -fno-omit-frame-pointer -DUSE_UTF8 # On Darwin, we need to run dsymutil so the debugging information ends # up in the right place. On other platforms, it automatically gets @@ -105,10 +105,35 @@ ifeq ($(CFG_C_COMPILER),gcc) ifeq ($(origin CPP),default) CPP=gcc endif +else +ifeq ($(CFG_C_COMPILER),ccache clang) + # The -Qunused-arguments sidesteps spurious warnings from clang + ifeq ($(origin CC),default) + CC=ccache clang -Qunused-arguments + endif + ifeq ($(origin CXX),default) + CXX=ccache clang++ -Qunused-arguments + endif + ifeq ($(origin CPP),default) + CPP=ccache clang -Qunused-arguments + endif +else +ifeq ($(CFG_C_COMPILER),ccache gcc) + ifeq ($(origin CC),default) + CC=ccache gcc + endif + ifeq ($(origin CXX),default) + CXX=ccache g++ + endif + ifeq ($(origin CPP),default) + CPP=ccache gcc + endif else CFG_ERR := $(error please try on a system with gcc or clang) endif endif +endif +endif # x86_64-unknown-linux-gnu configuration @@ -239,6 +264,32 @@ CFG_RUN_arm-linux-androideabi= CFG_RUN_TARG_arm-linux-androideabi= RUSTC_FLAGS_arm-linux-androideabi :=--android-cross-path=$(CFG_ANDROID_CROSS_PATH) +# arm-unknown-linux-gnueabihf configuration +CC_arm-unknown-linux-gnueabihf=arm-linux-gnueabihf-gcc +CXX_arm-unknown-linux-gnueabihf=arm-linux-gnueabihf-g++ +CPP_arm-unknown-linux-gnueabihf=arm-linux-gnueabihf-gcc -E +AR_arm-unknown-linux-gnueabihf=arm-linux-gnueabihf-ar +CFG_LIB_NAME_arm-unknown-linux-gnueabihf=lib$(1).so +CFG_LIB_GLOB_arm-unknown-linux-gnueabihf=lib$(1)-*.so +CFG_LIB_DSYM_GLOB_arm-unknown-linux-gnueabihf=lib$(1)-*.dylib.dSYM +CFG_GCCISH_CFLAGS_arm-unknown-linux-gnueabihf := -Wall -g -fPIC +CFG_GCCISH_CXXFLAGS_arm-unknown-linux-gnueabihf := -fno-rtti +CFG_GCCISH_LINK_FLAGS_arm-unknown-linux-gnueabihf := -shared -fPIC -g +CFG_GCCISH_DEF_FLAG_arm-unknown-linux-gnueabihf := -Wl,--export-dynamic,--dynamic-list= +CFG_GCCISH_PRE_LIB_FLAGS_arm-unknown-linux-gnueabihf := -Wl,-whole-archive +CFG_GCCISH_POST_LIB_FLAGS_arm-unknown-linux-gnueabihf := -Wl,-no-whole-archive +CFG_DEF_SUFFIX_arm-unknown-linux-gnueabihf := .linux.def +CFG_INSTALL_NAME_ar,-unknown-linux-gnueabihf = +CFG_LIBUV_LINK_FLAGS_arm-unknown-linux-gnueabihf = +CFG_EXE_SUFFIX_arm-unknown-linux-gnueabihf := +CFG_WINDOWSY_arm-unknown-linux-gnueabihf := +CFG_UNIXY_arm-unknown-linux-gnueabihf := 1 +CFG_PATH_MUNGE_arm-unknown-linux-gnueabihf := true +CFG_LDPATH_arm-unknown-linux-gnueabihf := +CFG_RUN_arm-unknown-linux-gnueabihf= +CFG_RUN_TARG_arm-unknown-linux-gnueabihf= +RUSTC_FLAGS_arm-unknown-linux-gnueabihf := --linker=$(CC_arm-unknown-linux-gnueabihf) + # mips-unknown-linux-gnu configuration CC_mips-unknown-linux-gnu=mips-linux-gnu-gcc CXX_mips-unknown-linux-gnu=mips-linux-gnu-g++ @@ -340,6 +391,15 @@ CFG_LDPATH_x86_64-unknown-freebsd := CFG_RUN_x86_64-unknown-freebsd=$(2) CFG_RUN_TARG_x86_64-unknown-freebsd=$(call CFG_RUN_x86_64-unknown-freebsd,,$(2)) +ifeq ($(CFG_CCACHE_CPP2),1) + CCACHE_CPP2=1 + export CCACHE_CPP +endif + +ifdef CFG_CCACHE_BASEDIR + CCACHE_BASEDIR=$(CFG_CCACHE_BASEDIR) + export CCACHE_BASEDIR +endif define CFG_MAKE_TOOLCHAIN CFG_COMPILE_C_$(1) = $$(CC_$(1)) \ diff --git a/mk/pp.mk b/mk/pp.mk index c7f316bcfc72d..0a24d9e87979d 100644 --- a/mk/pp.mk +++ b/mk/pp.mk @@ -12,8 +12,8 @@ ifdef PPFILES PP_INPUTS_FILTERED := $(wildcard $(PPFILES)) else - PP_INPUTS = $(wildcard $(addprefix $(S)src/libcore/,*.rs */*.rs)) \ - $(wildcard $(addprefix $(S)src/libstd/,*.rs */*.rs)) \ + PP_INPUTS = $(wildcard $(addprefix $(S)src/libstd/,*.rs */*.rs)) \ + $(wildcard $(addprefix $(S)src/libextra/,*.rs */*.rs)) \ $(wildcard $(addprefix $(S)src/rustc/,*.rs */*.rs */*/*.rs)) \ $(wildcard $(S)src/test/*/*.rs \ $(S)src/test/*/*/*.rs) \ diff --git a/mk/rt.mk b/mk/rt.mk index ab91dca62182c..d8d74d0d0e3fa 100644 --- a/mk/rt.mk +++ b/mk/rt.mk @@ -26,7 +26,11 @@ # Hack for passing flags into LIBUV, see below. LIBUV_FLAGS_i386 = -m32 -fPIC LIBUV_FLAGS_x86_64 = -m64 -fPIC +ifeq ($(OSTYPE_$(1)), linux-androideabi) LIBUV_FLAGS_arm = -fPIC -DANDROID -std=gnu99 +else +LIBUV_FLAGS_arm = -fPIC -std=gnu99 +endif LIBUV_FLAGS_mips = -fPIC -mips32r2 -msoft-float -mabi=32 # when we're doing a snapshot build, we intentionally degrade as many @@ -37,14 +41,19 @@ ifneq ($(strip $(findstring snap,$(MAKECMDGOALS))),) SNAP_DEFINES=-DRUST_SNAPSHOT endif - define DEF_RUNTIME_TARGETS ###################################################################### # Runtime (C++) library variables ###################################################################### -RUNTIME_CXXS_$(1) := \ +# $(1) is the target triple +# $(2) is the stage number + +RUNTIME_CFLAGS_$(1)_$(2) = -D_RUST_STAGE$(2) +RUNTIME_CXXFLAGS_$(1)_$(2) = -D_RUST_STAGE$(2) + +RUNTIME_CXXS_$(1)_$(2) := \ rt/sync/timer.cpp \ rt/sync/lock_and_signal.cpp \ rt/sync/rust_thread.cpp \ @@ -79,70 +88,70 @@ RUNTIME_CXXS_$(1) := \ rt/rust_android_dummy.cpp \ rt/rust_test_helpers.cpp -RUNTIME_CS_$(1) := rt/linenoise/linenoise.c rt/linenoise/utf8.c +RUNTIME_CS_$(1)_$(2) := rt/linenoise/linenoise.c rt/linenoise/utf8.c -RUNTIME_S_$(1) := rt/arch/$$(HOST_$(1))/_context.S \ - rt/arch/$$(HOST_$(1))/ccall.S \ - rt/arch/$$(HOST_$(1))/record_sp.S +RUNTIME_S_$(1)_$(2) := rt/arch/$$(HOST_$(1))/_context.S \ + rt/arch/$$(HOST_$(1))/ccall.S \ + rt/arch/$$(HOST_$(1))/record_sp.S ifeq ($$(CFG_WINDOWSY_$(1)), 1) - LIBUV_OSTYPE_$(1) := win - LIBUV_LIB_$(1) := rt/$(1)/libuv/libuv.a + LIBUV_OSTYPE_$(1)_$(2) := win + LIBUV_LIB_$(1)_$(2) := rt/$(1)/stage$(2)/libuv/libuv.a else ifeq ($(OSTYPE_$(1)), apple-darwin) - LIBUV_OSTYPE_$(1) := mac - LIBUV_LIB_$(1) := rt/$(1)/libuv/libuv.a + LIBUV_OSTYPE_$(1)_$(2) := mac + LIBUV_LIB_$(1)_$(2) := rt/$(1)/stage$(2)/libuv/libuv.a else ifeq ($(OSTYPE_$(1)), unknown-freebsd) - LIBUV_OSTYPE_$(1) := unix/freebsd - LIBUV_LIB_$(1) := rt/$(1)/libuv/libuv.a + LIBUV_OSTYPE_$(1)_$(2) := unix/freebsd + LIBUV_LIB_$(1)_$(2) := rt/$(1)/stage$(2)/libuv/libuv.a else ifeq ($(OSTYPE_$(1)), linux-androideabi) - LIBUV_OSTYPE_$(1) := unix/android - LIBUV_LIB_$(1) := rt/$(1)/libuv/libuv.a + LIBUV_OSTYPE_$(1)_$(2) := unix/android + LIBUV_LIB_$(1)_$(2) := rt/$(1)/stage$(2)/libuv/libuv.a else - LIBUV_OSTYPE_$(1) := unix/linux - LIBUV_LIB_$(1) := rt/$(1)/libuv/libuv.a + LIBUV_OSTYPE_$(1)_$(2) := unix/linux + LIBUV_LIB_$(1)_$(2) := rt/$(1)/stage$(2)/libuv/libuv.a endif -RUNTIME_DEF_$(1) := rt/rustrt$(CFG_DEF_SUFFIX_$(1)) -RUNTIME_INCS_$(1) := -I $$(S)src/rt -I $$(S)src/rt/isaac -I $$(S)src/rt/uthash \ +RUNTIME_DEF_$(1)_$(2) := rt/rustrt$(CFG_DEF_SUFFIX_$(1)) +RUNTIME_INCS_$(1)_$(2) := -I $$(S)src/rt -I $$(S)src/rt/isaac -I $$(S)src/rt/uthash \ -I $$(S)src/rt/arch/$$(HOST_$(1)) \ -I $$(S)src/rt/linenoise \ -I $$(S)src/libuv/include -RUNTIME_OBJS_$(1) := $$(RUNTIME_CXXS_$(1):rt/%.cpp=rt/$(1)/%.o) \ - $$(RUNTIME_CS_$(1):rt/%.c=rt/$(1)/%.o) \ - $$(RUNTIME_S_$(1):rt/%.S=rt/$(1)/%.o) -ALL_OBJ_FILES += $$(RUNTIME_OBJS_$(1)) +RUNTIME_OBJS_$(1)_$(2) := $$(RUNTIME_CXXS_$(1)_$(2):rt/%.cpp=rt/$(1)/stage$(2)/%.o) \ + $$(RUNTIME_CS_$(1)_$(2):rt/%.c=rt/$(1)/stage$(2)/%.o) \ + $$(RUNTIME_S_$(1)_$(2):rt/%.S=rt/$(1)/stage$(2)/%.o) +ALL_OBJ_FILES += $$(RUNTIME_OBJS_$(1)_$(2)) -MORESTACK_OBJ_$(1) := rt/$(1)/arch/$$(HOST_$(1))/morestack.o -ALL_OBJ_FILES += $$(MORESTACK_OBJS_$(1)) +MORESTACK_OBJ_$(1)_$(2) := rt/$(1)/stage$(2)/arch/$$(HOST_$(1))/morestack.o +ALL_OBJ_FILES += $$(MORESTACK_OBJS_$(1)_$(2)) -RUNTIME_LIBS_$(1) := $$(LIBUV_LIB_$(1)) +RUNTIME_LIBS_$(1)_$(2) := $$(LIBUV_LIB_$(1)_$(2)) -rt/$(1)/%.o: rt/%.cpp $$(MKFILE_DEPS) +rt/$(1)/stage$(2)/%.o: rt/%.cpp $$(MKFILE_DEPS) @$$(call E, compile: $$@) - $$(Q)$$(call CFG_COMPILE_CXX_$(1), $$@, $$(RUNTIME_INCS_$(1)) \ - $$(SNAP_DEFINES)) $$< + $$(Q)$$(call CFG_COMPILE_CXX_$(1), $$@, $$(RUNTIME_INCS_$(1)_$(2)) \ + $$(SNAP_DEFINES) $$(RUNTIME_CXXFLAGS_$(1)_$(2))) $$< -rt/$(1)/%.o: rt/%.c $$(MKFILE_DEPS) +rt/$(1)/stage$(2)/%.o: rt/%.c $$(MKFILE_DEPS) @$$(call E, compile: $$@) - $$(Q)$$(call CFG_COMPILE_C_$(1), $$@, $$(RUNTIME_INCS_$(1)) \ - $$(SNAP_DEFINES)) $$< + $$(Q)$$(call CFG_COMPILE_C_$(1), $$@, $$(RUNTIME_INCS_$(1)_$(2)) \ + $$(SNAP_DEFINES) $$(RUNTIME_CFLAGS_$(1)_$(2))) $$< -rt/$(1)/%.o: rt/%.S $$(MKFILE_DEPS) \ +rt/$(1)/stage$(2)/%.o: rt/%.S $$(MKFILE_DEPS) \ $$(LLVM_CONFIG_$$(CFG_BUILD_TRIPLE)) @$$(call E, compile: $$@) $$(Q)$$(call CFG_ASSEMBLE_$(1),$$@,$$<) -rt/$(1)/arch/$$(HOST_$(1))/libmorestack.a: $$(MORESTACK_OBJ_$(1)) +rt/$(1)/stage$(2)/arch/$$(HOST_$(1))/libmorestack.a: $$(MORESTACK_OBJ_$(1)_$(2)) @$$(call E, link: $$@) $$(Q)$(AR_$(1)) rcs $$@ $$< -rt/$(1)/$(CFG_RUNTIME_$(1)): $$(RUNTIME_OBJS_$(1)) $$(MKFILE_DEPS) \ - $$(RUNTIME_DEF_$(1)) \ - $$(RUNTIME_LIBS_$(1)) +rt/$(1)/stage$(2)/$(CFG_RUNTIME_$(1)): $$(RUNTIME_OBJS_$(1)_$(2)) $$(MKFILE_DEPS) \ + $$(RUNTIME_DEF_$(1)_$(2)) \ + $$(RUNTIME_LIBS_$(1)_$(2)) @$$(call E, link: $$@) - $$(Q)$$(call CFG_LINK_CXX_$(1),$$@, $$(RUNTIME_OBJS_$(1)) \ - $$(CFG_GCCISH_POST_LIB_FLAGS_$(1)) $$(RUNTIME_LIBS_$(1)) \ - $$(CFG_LIBUV_LINK_FLAGS_$(1)),$$(RUNTIME_DEF_$(1)),$$(CFG_RUNTIME_$(1))) + $$(Q)$$(call CFG_LINK_CXX_$(1),$$@, $$(RUNTIME_OBJS_$(1)_$(2)) \ + $$(CFG_GCCISH_POST_LIB_FLAGS_$(1)) $$(RUNTIME_LIBS_$(1)_$(2)) \ + $$(CFG_LIBUV_LINK_FLAGS_$(1)),$$(RUNTIME_DEF_$(1)_$(2)),$$(CFG_RUNTIME_$(1))) # FIXME: For some reason libuv's makefiles can't figure out the # correct definition of CC on the mingw I'm using, so we are @@ -161,13 +170,13 @@ endif # XXX: Shouldn't need platform-specific conditions here ifdef CFG_WINDOWSY_$(1) -$$(LIBUV_LIB_$(1)): $$(LIBUV_DEPS) +$$(LIBUV_LIB_$(1)_$(2)): $$(LIBUV_DEPS) $$(Q)$$(MAKE) -C $$(S)src/libuv/ \ - builddir_name="$$(CFG_BUILD_DIR)/rt/$(1)/libuv" \ + builddir_name="$$(CFG_BUILD_DIR)/rt/$(1)/stage$(2)/libuv" \ OS=mingw \ V=$$(VERBOSE) else ifeq ($(OSTYPE_$(1)), linux-androideabi) -$$(LIBUV_LIB_$(1)): $$(LIBUV_DEPS) +$$(LIBUV_LIB_$(1)_$(2)): $$(LIBUV_DEPS) $$(Q)$$(MAKE) -C $$(S)src/libuv/ \ CFLAGS="$$(CFG_GCCISH_CFLAGS) $$(LIBUV_FLAGS_$$(HOST_$(1))) $$(SNAP_DEFINES)" \ LDFLAGS="$$(CFG_GCCISH_LINK_FLAGS) $$(LIBUV_FLAGS_$$(HOST_$(1)))" \ @@ -175,18 +184,18 @@ $$(LIBUV_LIB_$(1)): $$(LIBUV_DEPS) CXX="$$(CXX_$(1))" \ AR="$$(AR_$(1))" \ BUILDTYPE=Release \ - builddir_name="$$(CFG_BUILD_DIR)/rt/$(1)/libuv" \ + builddir_name="$$(CFG_BUILD_DIR)/rt/$(1)/stage$(2)/libuv" \ host=android OS=linux \ V=$$(VERBOSE) else -$$(LIBUV_LIB_$(1)): $$(LIBUV_DEPS) +$$(LIBUV_LIB_$(1)_$(2)): $$(LIBUV_DEPS) $$(Q)$$(MAKE) -C $$(S)src/libuv/ \ CFLAGS="$$(CFG_GCCISH_CFLAGS) $$(LIBUV_FLAGS_$$(HOST_$(1))) $$(SNAP_DEFINES)" \ LDFLAGS="$$(CFG_GCCISH_LINK_FLAGS) $$(LIBUV_FLAGS_$$(HOST_$(1)))" \ CC="$$(CC_$(1))" \ CXX="$$(CXX_$(1))" \ AR="$$(AR_$(1))" \ - builddir_name="$$(CFG_BUILD_DIR)/rt/$(1)/libuv" \ + builddir_name="$$(CFG_BUILD_DIR)/rt/$(1)/stage$(2)/libuv" \ V=$$(VERBOSE) endif @@ -225,5 +234,6 @@ endif endef # Instantiate template for all stages -$(foreach target,$(CFG_TARGET_TRIPLES), \ - $(eval $(call DEF_RUNTIME_TARGETS,$(target)))) +$(foreach stage,$(STAGES), \ + $(foreach target,$(CFG_TARGET_TRIPLES), \ + $(eval $(call DEF_RUNTIME_TARGETS,$(target),$(stage))))) diff --git a/mk/rustllvm.mk b/mk/rustllvm.mk index f1ce4445c61fb..ffe03598e5311 100644 --- a/mk/rustllvm.mk +++ b/mk/rustllvm.mk @@ -22,7 +22,7 @@ LLVM_EXTRA_INCDIRS_$(1)= -iquote $(S)src/llvm/include \ -iquote llvm/$(1)/include endif -RUSTLLVM_OBJS_CS_$(1) := $$(addprefix rustllvm/, RustWrapper.cpp) +RUSTLLVM_OBJS_CS_$(1) := $$(addprefix rustllvm/, RustWrapper.cpp PassWrapper.cpp) RUSTLLVM_DEF_$(1) := rustllvm/rustllvm$(CFG_DEF_SUFFIX_$(1)) diff --git a/mk/stage0.mk b/mk/stage0.mk index ac1b3e86ac918..a1aaef4d554ad 100644 --- a/mk/stage0.mk +++ b/mk/stage0.mk @@ -25,11 +25,11 @@ $(HLIB0_H_$(CFG_BUILD_TRIPLE))/$(CFG_RUNTIME_$(CFG_BUILD_TRIPLE)): \ $(HBIN0_H_$(CFG_BUILD_TRIPLE))/rustc$(X_$(CFG_BUILD_TRIPLE)) $(Q)touch $@ -$(HLIB0_H_$(CFG_BUILD_TRIPLE))/$(CFG_CORELIB_$(CFG_BUILD_TRIPLE)): \ +$(HLIB0_H_$(CFG_BUILD_TRIPLE))/$(CFG_STDLIB_$(CFG_BUILD_TRIPLE)): \ $(HBIN0_H_$(CFG_BUILD_TRIPLE))/rustc$(X_$(CFG_BUILD_TRIPLE)) $(Q)touch $@ -$(HLIB0_H_$(CFG_BUILD_TRIPLE))/$(CFG_STDLIB_$(CFG_BUILD_TRIPLE)): \ +$(HLIB0_H_$(CFG_BUILD_TRIPLE))/$(CFG_EXTRALIB_$(CFG_BUILD_TRIPLE)): \ $(HBIN0_H_$(CFG_BUILD_TRIPLE))/rustc$(X_$(CFG_BUILD_TRIPLE)) $(Q)touch $@ @@ -58,16 +58,16 @@ $$(HLIB0_H_$(1))/$(CFG_RUNTIME_$(1)): \ @$$(call E, cp: $$@) $$(Q)cp $$< $$@ -$$(HLIB0_H_$(1))/$(CFG_CORELIB_$(1)): \ - $$(TLIB$(2)_T_$(1)_H_$(3))/$(CFG_CORELIB_$(1)) - @$$(call E, cp: $$@) - $$(Q)cp $$(TLIB$(2)_T_$(1)_H_$(3))/$(CORELIB_GLOB_$(1)) $$@ - $$(HLIB0_H_$(1))/$(CFG_STDLIB_$(1)): \ $$(TLIB$(2)_T_$(1)_H_$(3))/$(CFG_STDLIB_$(1)) @$$(call E, cp: $$@) $$(Q)cp $$(TLIB$(2)_T_$(1)_H_$(3))/$(STDLIB_GLOB_$(1)) $$@ +$$(HLIB0_H_$(1))/$(CFG_EXTRALIB_$(1)): \ + $$(TLIB$(2)_T_$(1)_H_$(3))/$(CFG_EXTRALIB_$(1)) + @$$(call E, cp: $$@) + $$(Q)cp $$(TLIB$(2)_T_$(1)_H_$(3))/$(EXTRALIB_GLOB_$(1)) $$@ + $$(HLIB0_H_$(1))/$(CFG_LIBRUSTC_$(1)): \ $$(TLIB$(2)_T_$(1)_H_$(3))/$(CFG_LIBRUSTC_$(1)) @$$(call E, cp: $$@) diff --git a/mk/target.mk b/mk/target.mk index 3cecc3940e62f..737b3b82c00de 100644 --- a/mk/target.mk +++ b/mk/target.mk @@ -8,6 +8,11 @@ # option. This file may not be copied, modified, or distributed # except according to those terms. +# This is the compile-time target-triple for the compiler. For the compiler at +# runtime, this should be considered the host-triple. More explanation for why +# this exists can be found on issue #2400 +export CFG_COMPILER_TRIPLE + # TARGET_STAGE_N template: This defines how target artifacts are built # for all stage/target architecture combinations. The arguments: # $(1) is the stage @@ -18,27 +23,27 @@ define TARGET_STAGE_N $$(TLIB$(1)_T_$(2)_H_$(3))/libmorestack.a: \ - rt/$(2)/arch/$$(HOST_$(2))/libmorestack.a \ + rt/$(2)/stage$(1)/arch/$$(HOST_$(2))/libmorestack.a \ | $$(TLIB$(1)_T_$(2)_H_$(3))/ @$$(call E, cp: $$@) $$(Q)cp $$< $$@ $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_RUNTIME_$(2)): \ - rt/$(2)/$(CFG_RUNTIME_$(2)) \ + rt/$(2)/stage$(1)/$(CFG_RUNTIME_$(2)) \ | $$(TLIB$(1)_T_$(2)_H_$(3))/ @$$(call E, cp: $$@) $$(Q)cp $$< $$@ -$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_CORELIB_$(2)): \ - $$(CORELIB_CRATE) $$(CORELIB_INPUTS) \ +$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_STDLIB_$(2)): \ + $$(STDLIB_CRATE) $$(STDLIB_INPUTS) \ $$(TSREQ$(1)_T_$(2)_H_$(3)) \ | $$(TLIB$(1)_T_$(2)_H_$(3))/ @$$(call E, compile_and_link: $$@) $$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$< && touch $$@ -$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_STDLIB_$(2)): \ - $$(STDLIB_CRATE) $$(STDLIB_INPUTS) \ - $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_CORELIB_$(2)) \ +$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_EXTRALIB_$(2)): \ + $$(EXTRALIB_CRATE) $$(EXTRALIB_INPUTS) \ + $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_STDLIB_$(2)) \ $$(TSREQ$(1)_T_$(2)_H_$(3)) \ | $$(TLIB$(1)_T_$(2)_H_$(3))/ @$$(call E, compile_and_link: $$@) @@ -47,8 +52,8 @@ $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_STDLIB_$(2)): \ $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBSYNTAX_$(3)): \ $$(LIBSYNTAX_CRATE) $$(LIBSYNTAX_INPUTS) \ $$(TSREQ$(1)_T_$(2)_H_$(3)) \ - $$(TCORELIB_DEFAULT$(1)_T_$(2)_H_$(3)) \ - $$(TSTDLIB_DEFAULT$(1)_T_$(2)_H_$(3)) \ + $$(TSTDLIB_DEFAULT$(1)_T_$(2)_H_$(3)) \ + $$(TEXTRALIB_DEFAULT$(1)_T_$(2)_H_$(3)) \ | $$(TLIB$(1)_T_$(2)_H_$(3))/ @$$(call E, compile_and_link: $$@) $$(STAGE$(1)_T_$(2)_H_$(3)) $(BORROWCK) -o $$@ $$< && touch $$@ @@ -62,6 +67,7 @@ $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_RUSTLLVM_$(3)): \ @$$(call E, cp: $$@) $$(Q)cp $$< $$@ +$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTC_$(3)): CFG_COMPILER_TRIPLE = $(2) $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTC_$(3)): \ $$(COMPILER_CRATE) $$(COMPILER_INPUTS) \ $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBSYNTAX_$(3)) \ diff --git a/mk/tests.mk b/mk/tests.mk index 5cdd900d65f9c..3858de3f264df 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -14,7 +14,7 @@ ###################################################################### # The names of crates that must be tested -TEST_TARGET_CRATES = core std +TEST_TARGET_CRATES = std extra TEST_HOST_CRATES = syntax rustc rustdoc rusti rust rustpkg TEST_CRATES = $(TEST_TARGET_CRATES) $(TEST_HOST_CRATES) @@ -122,8 +122,18 @@ CFG_ADB_TEST_DIR=/data/tmp $(info check: android device test dir $(CFG_ADB_TEST_DIR) ready \ $(shell adb remount 1>/dev/null) \ $(shell adb shell mkdir $(CFG_ADB_TEST_DIR) 1>/dev/null) \ + $(shell adb shell rm $(CFG_ADB_TEST_DIR)/*.so 1>/dev/null) \ + $(shell adb shell rm $(CFG_ADB_TEST_DIR)/*-arm-linux-androideabi 1>/dev/null) \ + $(shell adb shell rm $(CFG_ADB_TEST_DIR)/*-arm-linux-androideabi.* 1>/dev/null) \ + $(shell adb push $(S)src/etc/adb_run_wrapper.sh $(CFG_ADB_TEST_DIR) 1>/dev/null) \ $(shell adb push $(CFG_ANDROID_CROSS_PATH)/arm-linux-androideabi/lib/armv7-a/libgnustl_shared.so \ $(CFG_ADB_TEST_DIR) 1>/dev/null) \ + $(shell adb push $(TLIB2_T_arm-linux-androideabi_H_$(CFG_BUILD_TRIPLE))/$(CFG_RUNTIME_arm-linux-androideabi) \ + $(CFG_ADB_TEST_DIR)) \ + $(shell adb push $(TLIB2_T_arm-linux-androideabi_H_$(CFG_BUILD_TRIPLE))/$(STDLIB_GLOB_arm-linux-androideabi) \ + $(CFG_ADB_TEST_DIR)) \ + $(shell adb push $(TLIB2_T_arm-linux-androideabi_H_$(CFG_BUILD_TRIPLE))/$(EXTRALIB_GLOB_arm-linux-androideabi) \ + $(CFG_ADB_TEST_DIR)) \ ) else CFG_ADB_TEST_DIR= @@ -148,7 +158,7 @@ check-test: cleantestlibs cleantmptestlogs all check-stage2-rfail $(Q)$(CFG_PYTHON) $(S)src/etc/check-summary.py tmp/*.log check-lite: cleantestlibs cleantmptestlogs \ - check-stage2-core check-stage2-std check-stage2-rpass \ + check-stage2-std check-stage2-extra check-stage2-rpass \ check-stage2-rfail check-stage2-cfail $(Q)$(CFG_PYTHON) $(S)src/etc/check-summary.py tmp/*.log @@ -281,22 +291,22 @@ $(foreach host,$(CFG_HOST_TRIPLES), \ define TEST_RUNNER -# If NO_REBUILD is set then break the dependencies on std so we can -# test crates without rebuilding core and std first +# If NO_REBUILD is set then break the dependencies on extra so we can +# test crates without rebuilding std and extra first ifeq ($(NO_REBUILD),) -STDTESTDEP_$(1)_$(2)_$(3) = $$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_STDLIB_$(2)) +STDTESTDEP_$(1)_$(2)_$(3) = $$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_EXTRALIB_$(2)) else STDTESTDEP_$(1)_$(2)_$(3) = endif -$(3)/stage$(1)/test/coretest-$(2)$$(X_$(2)): \ - $$(CORELIB_CRATE) $$(CORELIB_INPUTS) \ +$(3)/stage$(1)/test/stdtest-$(2)$$(X_$(2)): \ + $$(STDLIB_CRATE) $$(STDLIB_INPUTS) \ $$(STDTESTDEP_$(1)_$(2)_$(3)) @$$(call E, compile_and_link: $$@) $$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$< --test -$(3)/stage$(1)/test/stdtest-$(2)$$(X_$(2)): \ - $$(STDLIB_CRATE) $$(STDLIB_INPUTS) \ +$(3)/stage$(1)/test/extratest-$(2)$$(X_$(2)): \ + $$(EXTRALIB_CRATE) $$(EXTRALIB_INPUTS) \ $$(STDTESTDEP_$(1)_$(2)_$(3)) @$$(call E, compile_and_link: $$@) $$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$< --test @@ -307,6 +317,7 @@ $(3)/stage$(1)/test/syntaxtest-$(2)$$(X_$(2)): \ @$$(call E, compile_and_link: $$@) $$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$< --test +$(3)/stage$(1)/test/rustctest-$(2)$$(X_$(2)): CFG_COMPILER_TRIPLE = $(2) $(3)/stage$(1)/test/rustctest-$(2)$$(X_$(2)): \ $$(COMPILER_CRATE) $$(COMPILER_INPUTS) \ $$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_RUSTLLVM_$(2)) \ @@ -665,7 +676,7 @@ TEST_GROUPS = \ perf \ debuginfo \ doc \ - $(foreach docname,$(DOC_TEST_NAMES),$(docname)) \ + $(foreach docname,$(DOC_TEST_NAMES),doc-$(docname)) \ pretty \ pretty-rpass \ pretty-rpass-full \ diff --git a/mk/tools.mk b/mk/tools.mk index 2900aa711dc6d..018da2a640169 100644 --- a/mk/tools.mk +++ b/mk/tools.mk @@ -41,8 +41,8 @@ define TOOLS_STAGE_N_TARGET $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBFUZZER_$(4)): \ $$(FUZZER_LIB) $$(FUZZER_INPUTS) \ $$(TSREQ$(1)_T_$(4)_H_$(3)) \ - $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_CORELIB_$(4)) \ $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_STDLIB_$(4)) \ + $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_EXTRALIB_$(4)) \ $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTC_$(4)) @$$(call E, compile_and_link: $$@) $$(STAGE$(1)_T_$(4)_H_$(3)) -o $$@ $$< && touch $$@ @@ -56,16 +56,16 @@ $$(TBIN$(1)_T_$(4)_H_$(3))/fuzzer$$(X_$(4)): \ $$(TBIN$(1)_T_$(4)_H_$(3))/compiletest$$(X_$(4)): \ $$(COMPILETEST_CRATE) $$(COMPILETEST_INPUTS) \ $$(TSREQ$(1)_T_$(4)_H_$(3)) \ - $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_CORELIB_$(4)) \ - $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_STDLIB_$(4)) + $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_STDLIB_$(4)) \ + $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_EXTRALIB_$(4)) @$$(call E, compile_and_link: $$@) $$(STAGE$(1)_T_$(4)_H_$(3)) -o $$@ $$< $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTPKG_$(4)): \ $$(RUSTPKG_LIB) $$(RUSTPKG_INPUTS) \ $$(TSREQ$(1)_T_$(4)_H_$(3)) \ - $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_CORELIB_$(4)) \ $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_STDLIB_$(4)) \ + $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_EXTRALIB_$(4)) \ $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTC_$(4)) @$$(call E, compile_and_link: $$@) $$(STAGE$(1)_T_$(4)_H_$(3)) -o $$@ $$< && touch $$@ @@ -79,8 +79,8 @@ $$(TBIN$(1)_T_$(4)_H_$(3))/rustpkg$$(X_$(4)): \ $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTDOC_$(4)): \ $$(RUSTDOC_LIB) $$(RUSTDOC_INPUTS) \ $$(TSREQ$(1)_T_$(4)_H_$(3)) \ - $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_CORELIB_$(4)) \ $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_STDLIB_$(4)) \ + $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_EXTRALIB_$(4)) \ $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTC_$(4)) @$$(call E, compile_and_link: $$@) $$(STAGE$(1)_T_$(4)_H_$(3)) -o $$@ $$< && touch $$@ @@ -94,8 +94,8 @@ $$(TBIN$(1)_T_$(4)_H_$(3))/rustdoc$$(X_$(4)): \ $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTI_$(4)): \ $$(RUSTI_LIB) $$(RUSTI_INPUTS) \ $$(TSREQ$(1)_T_$(4)_H_$(3)) \ - $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_CORELIB_$(4)) \ $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_STDLIB_$(4)) \ + $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_EXTRALIB_$(4)) \ $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTC_$(4)) @$$(call E, compile_and_link: $$@) $$(STAGE$(1)_T_$(4)_H_$(3)) -o $$@ $$< && touch $$@ @@ -109,8 +109,8 @@ $$(TBIN$(1)_T_$(4)_H_$(3))/rusti$$(X_$(4)): \ $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUST_$(4)): \ $$(RUST_LIB) $$(RUST_INPUTS) \ $$(TSREQ$(1)_T_$(4)_H_$(3)) \ - $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_CORELIB_$(4)) \ $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_STDLIB_$(4)) \ + $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_EXTRALIB_$(4)) \ $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTPKG_$(4)) \ $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTI_$(4)) \ $$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTDOC_$(4)) \ diff --git a/src/compiletest/common.rs b/src/compiletest/common.rs index 38289f6274180..869657326b7d2 100644 --- a/src/compiletest/common.rs +++ b/src/compiletest/common.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + #[deriving(Eq)] pub enum mode { mode_compile_fail, diff --git a/src/compiletest/compiletest.rc b/src/compiletest/compiletest.rc index dedf465b56d8b..c40cec262f822 100644 --- a/src/compiletest/compiletest.rc +++ b/src/compiletest/compiletest.rc @@ -12,13 +12,17 @@ #[allow(non_camel_case_types)]; -extern mod std(vers = "0.7-pre"); +#[no_core]; // XXX: Remove after snapshot +#[no_std]; -use core::*; +extern mod core(name = "std", vers = "0.7-pre"); +extern mod extra(name = "extra", vers = "0.7-pre"); +use core::prelude::*; +use core::*; -use std::getopts; -use std::test; +use extra::getopts; +use extra::test; use core::result::{Ok, Err}; @@ -38,6 +42,13 @@ pub mod runtest; pub mod common; pub mod errors; +mod std { + pub use core::cmp; + pub use core::str; + pub use core::sys; + pub use core::unstable; +} + pub fn main() { let args = os::args(); let config = parse_config(args); @@ -47,20 +58,20 @@ pub fn main() { pub fn parse_config(args: ~[~str]) -> config { let opts = - ~[getopts::reqopt(~"compile-lib-path"), - getopts::reqopt(~"run-lib-path"), - getopts::reqopt(~"rustc-path"), getopts::reqopt(~"src-base"), - getopts::reqopt(~"build-base"), getopts::reqopt(~"aux-base"), - getopts::reqopt(~"stage-id"), - getopts::reqopt(~"mode"), getopts::optflag(~"ignored"), - getopts::optopt(~"runtool"), getopts::optopt(~"rustcflags"), - getopts::optflag(~"verbose"), - getopts::optopt(~"logfile"), - getopts::optflag(~"jit"), - getopts::optflag(~"newrt"), - getopts::optopt(~"target"), - getopts::optopt(~"adb-path"), - getopts::optopt(~"adb-test-dir") + ~[getopts::reqopt("compile-lib-path"), + getopts::reqopt("run-lib-path"), + getopts::reqopt("rustc-path"), getopts::reqopt("src-base"), + getopts::reqopt("build-base"), getopts::reqopt("aux-base"), + getopts::reqopt("stage-id"), + getopts::reqopt("mode"), getopts::optflag("ignored"), + getopts::optopt("runtool"), getopts::optopt("rustcflags"), + getopts::optflag("verbose"), + getopts::optopt("logfile"), + getopts::optflag("jit"), + getopts::optflag("newrt"), + getopts::optopt("target"), + getopts::optopt("adb-path"), + getopts::optopt("adb-test-dir") ]; assert!(!args.is_empty()); @@ -71,43 +82,43 @@ pub fn parse_config(args: ~[~str]) -> config { Err(f) => fail!(getopts::fail_str(f)) }; - fn opt_path(m: &getopts::Matches, nm: ~str) -> Path { + fn opt_path(m: &getopts::Matches, nm: &str) -> Path { Path(getopts::opt_str(m, nm)) } config { - compile_lib_path: getopts::opt_str(matches, ~"compile-lib-path"), - run_lib_path: getopts::opt_str(matches, ~"run-lib-path"), - rustc_path: opt_path(matches, ~"rustc-path"), - src_base: opt_path(matches, ~"src-base"), - build_base: opt_path(matches, ~"build-base"), - aux_base: opt_path(matches, ~"aux-base"), - stage_id: getopts::opt_str(matches, ~"stage-id"), - mode: str_mode(getopts::opt_str(matches, ~"mode")), - run_ignored: getopts::opt_present(matches, ~"ignored"), + compile_lib_path: getopts::opt_str(matches, "compile-lib-path"), + run_lib_path: getopts::opt_str(matches, "run-lib-path"), + rustc_path: opt_path(matches, "rustc-path"), + src_base: opt_path(matches, "src-base"), + build_base: opt_path(matches, "build-base"), + aux_base: opt_path(matches, "aux-base"), + stage_id: getopts::opt_str(matches, "stage-id"), + mode: str_mode(getopts::opt_str(matches, "mode")), + run_ignored: getopts::opt_present(matches, "ignored"), filter: if vec::len(matches.free) > 0u { option::Some(copy matches.free[0]) } else { option::None }, - logfile: getopts::opt_maybe_str(matches, ~"logfile").map(|s| Path(*s)), - runtool: getopts::opt_maybe_str(matches, ~"runtool"), - rustcflags: getopts::opt_maybe_str(matches, ~"rustcflags"), - jit: getopts::opt_present(matches, ~"jit"), - newrt: getopts::opt_present(matches, ~"newrt"), - target: opt_str2(getopts::opt_maybe_str(matches, ~"target")).to_str(), - adb_path: opt_str2(getopts::opt_maybe_str(matches, ~"adb-path")).to_str(), + logfile: getopts::opt_maybe_str(matches, "logfile").map(|s| Path(*s)), + runtool: getopts::opt_maybe_str(matches, "runtool"), + rustcflags: getopts::opt_maybe_str(matches, "rustcflags"), + jit: getopts::opt_present(matches, "jit"), + newrt: getopts::opt_present(matches, "newrt"), + target: opt_str2(getopts::opt_maybe_str(matches, "target")).to_str(), + adb_path: opt_str2(getopts::opt_maybe_str(matches, "adb-path")).to_str(), adb_test_dir: - opt_str2(getopts::opt_maybe_str(matches, ~"adb-test-dir")).to_str(), + opt_str2(getopts::opt_maybe_str(matches, "adb-test-dir")).to_str(), adb_device_status: - if (opt_str2(getopts::opt_maybe_str(matches, ~"target")) == + if (opt_str2(getopts::opt_maybe_str(matches, "target")) == ~"arm-linux-androideabi") { - if (opt_str2(getopts::opt_maybe_str(matches, ~"adb-test-dir")) != + if (opt_str2(getopts::opt_maybe_str(matches, "adb-test-dir")) != ~"(none)" && - opt_str2(getopts::opt_maybe_str(matches, ~"adb-test-dir")) != + opt_str2(getopts::opt_maybe_str(matches, "adb-test-dir")) != ~"") { true } else { false } } else { false }, - verbose: getopts::opt_present(matches, ~"verbose") + verbose: getopts::opt_present(matches, "verbose") } } @@ -249,7 +260,7 @@ pub fn make_test_name(config: &config, testfile: &Path) -> test::TestName { pub fn make_test_closure(config: &config, testfile: &Path) -> test::TestFn { use core::cell::Cell; - let config = Cell(copy *config); - let testfile = Cell(testfile.to_str()); + let config = Cell::new(copy *config); + let testfile = Cell::new(testfile.to_str()); test::DynTestFn(|| { runtest::run(config.take(), testfile.take()) }) } diff --git a/src/compiletest/errors.rs b/src/compiletest/errors.rs index aa8d61027b3c3..728548caf77c1 100644 --- a/src/compiletest/errors.rs +++ b/src/compiletest/errors.rs @@ -8,6 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + +use core::io; +use core::str; + pub struct ExpectedError { line: uint, kind: ~str, msg: ~str } // Load any test directives embedded in the file diff --git a/src/compiletest/header.rs b/src/compiletest/header.rs index b1f4c9f515bb0..b147dc806e211 100644 --- a/src/compiletest/header.rs +++ b/src/compiletest/header.rs @@ -8,8 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use common; +use core::prelude::*; + use common::config; +use common; + +use core::io; +use core::os; +use core::str; pub struct TestProps { // Lines that should be expected, in order, on standard out @@ -85,15 +91,15 @@ pub fn load_props(testfile: &Path) -> TestProps { pub fn is_test_ignored(config: &config, testfile: &Path) -> bool { for iter_header(testfile) |ln| { - if parse_name_directive(ln, ~"xfail-test") { return true; } + if parse_name_directive(ln, "xfail-test") { return true; } if parse_name_directive(ln, xfail_target()) { return true; } if config.mode == common::mode_pretty && - parse_name_directive(ln, ~"xfail-pretty") { return true; } + parse_name_directive(ln, "xfail-pretty") { return true; } }; return false; fn xfail_target() -> ~str { - ~"xfail-" + str::to_owned(os::SYSNAME) + ~"xfail-" + os::SYSNAME } } @@ -105,8 +111,7 @@ fn iter_header(testfile: &Path, it: &fn(~str) -> bool) -> bool { // Assume that any directives will be found before the first // module or function. This doesn't seem to be an optimization // with a warm page cache. Maybe with a cold one. - if str::starts_with(ln, ~"fn") - || str::starts_with(ln, ~"mod") { + if str::starts_with(ln, "fn") || str::starts_with(ln, "mod") { return false; } else { if !(it(ln)) { return false; } } } @@ -168,7 +173,7 @@ fn parse_name_directive(line: &str, directive: &str) -> bool { fn parse_name_value_directive(line: &str, directive: ~str) -> Option<~str> { - let keycolon = directive + ~":"; + let keycolon = directive + ":"; match str::find_str(line, keycolon) { Some(colon) => { let value = str::slice(line, colon + str::len(keycolon), diff --git a/src/compiletest/procsrv.rs b/src/compiletest/procsrv.rs index 71efa5596a8ad..8285986d67e11 100644 --- a/src/compiletest/procsrv.rs +++ b/src/compiletest/procsrv.rs @@ -8,10 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; +use core::comm; +use core::io; use core::libc::c_int; -use core::run::spawn_process; +use core::os; use core::run; +use core::str; +use core::task; #[cfg(target_os = "win32")] fn target_env(lib_path: &str, prog: &str) -> ~[(~str,~str)] { @@ -19,12 +24,12 @@ fn target_env(lib_path: &str, prog: &str) -> ~[(~str,~str)] { let mut env = os::env(); // Make sure we include the aux directory in the path - assert!(prog.ends_with(~".exe")); - let aux_path = prog.slice(0u, prog.len() - 4u).to_owned() + ~".libaux"; + assert!(prog.ends_with(".exe")); + let aux_path = prog.slice(0u, prog.len() - 4u).to_owned() + ".libaux"; env = do vec::map(env) |pair| { let (k,v) = *pair; - if k == ~"PATH" { (~"PATH", v + ~";" + lib_path + ~";" + aux_path) } + if k == ~"PATH" { (~"PATH", v + ";" + lib_path + ";" + aux_path) } else { (k,v) } }; if str::ends_with(prog, "rustc.exe") { @@ -37,86 +42,35 @@ fn target_env(lib_path: &str, prog: &str) -> ~[(~str,~str)] { #[cfg(target_os = "macos")] #[cfg(target_os = "freebsd")] fn target_env(_lib_path: &str, _prog: &str) -> ~[(~str,~str)] { - ~[] + os::env() } pub struct Result {status: int, out: ~str, err: ~str} -// FIXME (#2659): This code is duplicated in core::run::program_output pub fn run(lib_path: &str, prog: &str, args: &[~str], env: ~[(~str, ~str)], input: Option<~str>) -> Result { - let pipe_in = os::pipe(); - let pipe_out = os::pipe(); - let pipe_err = os::pipe(); - let pid = spawn_process(prog, args, - &Some(env + target_env(lib_path, prog)), - &None, pipe_in.in, pipe_out.out, pipe_err.out); - - os::close(pipe_in.in); - os::close(pipe_out.out); - os::close(pipe_err.out); - if pid == -1i32 { - os::close(pipe_in.out); - os::close(pipe_out.in); - os::close(pipe_err.in); - fail!(); - } + let env = env + target_env(lib_path, prog); + let mut proc = run::Process::new(prog, args, run::ProcessOptions { + env: Some(env.slice(0, env.len())), + dir: None, + in_fd: None, + out_fd: None, + err_fd: None + }); - writeclose(pipe_in.out, input); - let p = comm::PortSet::new(); - let ch = p.chan(); - do task::spawn_sched(task::SingleThreaded) || { - let errput = readclose(pipe_err.in); - ch.send((2, errput)); + for input.each |input| { + proc.input().write_str(*input); } - let ch = p.chan(); - do task::spawn_sched(task::SingleThreaded) || { - let output = readclose(pipe_out.in); - ch.send((1, output)); - } - let status = run::waitpid(pid); - let mut errs = ~""; - let mut outs = ~""; - let mut count = 2; - while count > 0 { - match p.recv() { - (1, s) => { - outs = s; - } - (2, s) => { - errs = s; - } - _ => { fail!() } - }; - count -= 1; - }; - return Result {status: status, out: outs, err: errs}; -} + let output = proc.finish_with_output(); -fn writeclose(fd: c_int, s: Option<~str>) { - if s.is_some() { - let writer = io::fd_writer(fd, false); - writer.write_str(s.get()); + Result { + status: output.status, + out: str::from_bytes(output.output), + err: str::from_bytes(output.error) } - - os::close(fd); } -fn readclose(fd: c_int) -> ~str { - unsafe { - // Copied from run::program_output - let file = os::fdopen(fd); - let reader = io::FILE_reader(file, false); - let mut buf = ~""; - while !reader.eof() { - let bytes = reader.read_bytes(4096u); - str::push_str(&mut buf, str::from_bytes(bytes)); - } - os::fclose(file); - return buf; - } -} diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index d58c2e596bd75..c174057aaaa85 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use common::mode_run_pass; use common::mode_run_fail; use common::mode_compile_fail; @@ -20,10 +22,16 @@ use procsrv; use util; use util::logv; +use core::io; +use core::os; +use core::str; +use core::uint; +use core::vec; + pub fn run(config: config, testfile: ~str) { if config.verbose { // We're going to be dumping a lot of info. Start on a new line. - io::stdout().write_str(~"\n\n"); + io::stdout().write_str("\n\n"); } let testfile = Path(testfile); debug!("running %s", testfile.to_str()); @@ -229,7 +237,7 @@ fn run_debuginfo_test(config: &config, props: &TestProps, testfile: &Path) { // do not optimize debuginfo tests let mut config = match config.rustcflags { Some(ref flags) => config { - rustcflags: Some(str::replace(*flags, ~"-O", ~"")), + rustcflags: Some(str::replace(*flags, "-O", "")), .. copy *config }, None => copy *config @@ -247,19 +255,19 @@ fn run_debuginfo_test(config: &config, props: &TestProps, testfile: &Path) { // write debugger script let script_str = str::append(cmds, "\nquit\n"); debug!("script_str = %s", script_str); - dump_output_file(config, testfile, script_str, ~"debugger.script"); + dump_output_file(config, testfile, script_str, "debugger.script"); // run debugger script with gdb #[cfg(windows)] fn debugger() -> ~str { ~"gdb.exe" } #[cfg(unix)] fn debugger() -> ~str { ~"gdb" } - let debugger_script = make_out_name(config, testfile, ~"debugger.script"); + let debugger_script = make_out_name(config, testfile, "debugger.script"); let debugger_opts = ~[~"-quiet", ~"-batch", ~"-nx", ~"-command=" + debugger_script.to_str(), make_exe_name(config, testfile).to_str()]; let ProcArgs = ProcArgs {prog: debugger(), args: debugger_opts}; - ProcRes = compose_and_run(config, testfile, ProcArgs, ~[], ~"", None); + ProcRes = compose_and_run(config, testfile, ProcArgs, ~[], "", None); if ProcRes.status != 0 { fatal(~"gdb failed to execute"); } @@ -366,11 +374,11 @@ fn check_expected_errors(expected_errors: ~[errors::ExpectedError], } // ignore this msg which gets printed at the end - if str::contains(line, ~"aborting due to") { + if str::contains(line, "aborting due to") { was_expected = true; } - if !was_expected && is_compiler_error_or_warning(str::to_owned(line)) { + if !was_expected && is_compiler_error_or_warning(line) { fatal_ProcRes(fmt!("unexpected compiler error or warning: '%s'", line), ProcRes); @@ -588,8 +596,7 @@ fn make_lib_name(config: &config, auxfile: &Path, testfile: &Path) -> Path { } fn make_exe_name(config: &config, testfile: &Path) -> Path { - Path(output_base_name(config, testfile).to_str() + - str::to_owned(os::EXE_SUFFIX)) + Path(output_base_name(config, testfile).to_str() + os::EXE_SUFFIX) } fn make_run_args(config: &config, _props: &TestProps, testfile: &Path) -> @@ -598,7 +605,7 @@ fn make_run_args(config: &config, _props: &TestProps, testfile: &Path) -> // then split apart its command let toolargs = split_maybe_args(&config.runtool); - let mut args = toolargs + ~[make_exe_name(config, testfile).to_str()]; + let mut args = toolargs + [make_exe_name(config, testfile).to_str()]; let prog = args.shift(); return ProcArgs {prog: prog, args: args}; } @@ -641,13 +648,13 @@ fn program_output(config: &config, testfile: &Path, lib_path: &str, prog: ~str, #[cfg(target_os = "macos")] #[cfg(target_os = "freebsd")] fn make_cmdline(_libpath: &str, prog: &str, args: &[~str]) -> ~str { - fmt!("%s %s", prog, str::connect(args, ~" ")) + fmt!("%s %s", prog, str::connect(args, " ")) } #[cfg(target_os = "win32")] fn make_cmdline(libpath: &str, prog: &str, args: &[~str]) -> ~str { fmt!("%s %s %s", lib_path_cmd_prefix(libpath), prog, - str::connect(args, ~" ")) + str::connect(args, " ")) } // Build the LD_LIBRARY_PATH variable as it would be seen on the command line @@ -666,7 +673,7 @@ fn dump_output_file(config: &config, testfile: &Path, out: &str, extension: &str) { let outfile = make_out_name(config, testfile, extension); let writer = - io::file_writer(&outfile, ~[io::Create, io::Truncate]).get(); + io::file_writer(&outfile, [io::Create, io::Truncate]).get(); writer.write_str(out); } @@ -690,8 +697,8 @@ fn output_base_name(config: &config, testfile: &Path) -> Path { fn maybe_dump_to_stdout(config: &config, out: &str, err: &str) { if config.verbose { - let sep1 = fmt!("------%s------------------------------", ~"stdout"); - let sep2 = fmt!("------%s------------------------------", ~"stderr"); + let sep1 = fmt!("------%s------------------------------", "stdout"); + let sep2 = fmt!("------%s------------------------------", "stderr"); let sep3 = ~"------------------------------------------"; io::stdout().write_line(sep1); io::stdout().write_line(out); @@ -746,53 +753,62 @@ fn _arm_exec_compiled_test(config: &config, props: &TestProps, copy_result.out, copy_result.err)); } - // execute program logv(config, fmt!("executing (%s) %s", config.target, cmdline)); - // adb shell dose not forward stdout and stderr of internal result - // to stdout and stderr separately but to stdout only - let mut newargs_out = ~[]; - let mut newargs_err = ~[]; - newargs_out.push(~"shell"); - newargs_err.push(~"shell"); + let mut runargs = ~[]; - let mut newcmd_out = ~""; - let mut newcmd_err = ~""; + // run test via adb_run_wrapper + runargs.push(~"shell"); + runargs.push(fmt!("%s/adb_run_wrapper.sh", config.adb_test_dir)); + runargs.push(fmt!("%s", config.adb_test_dir)); + runargs.push(fmt!("%s", prog_short)); - newcmd_out.push_str(fmt!("LD_LIBRARY_PATH=%s %s/%s", - config.adb_test_dir, config.adb_test_dir, prog_short)); + for args.args.each |tv| { + runargs.push(tv.to_owned()); + } - newcmd_err.push_str(fmt!("LD_LIBRARY_PATH=%s %s/%s", - config.adb_test_dir, config.adb_test_dir, prog_short)); + procsrv::run("", config.adb_path, runargs, ~[(~"",~"")], Some(~"")); - for args.args.each |tv| { - newcmd_out.push_str(" "); - newcmd_err.push_str(" "); - newcmd_out.push_str(tv.to_owned()); - newcmd_err.push_str(tv.to_owned()); + // get exitcode of result + runargs = ~[]; + runargs.push(~"shell"); + runargs.push(~"cat"); + runargs.push(fmt!("%s/%s.exitcode", config.adb_test_dir, prog_short)); + + let procsrv::Result{ out: exitcode_out, err: _, status: _ } = + procsrv::run("", config.adb_path, runargs, ~[(~"",~"")], + Some(~"")); + + let mut exitcode : int = 0; + for str::each_char(exitcode_out) |c| { + if !c.is_digit() { break; } + exitcode = exitcode * 10 + match c { + '0' .. '9' => c as int - ('0' as int), + _ => 101, + } } - newcmd_out.push_str(" 2>/dev/null"); - newcmd_err.push_str(" 1>/dev/null"); + // get stdout of result + runargs = ~[]; + runargs.push(~"shell"); + runargs.push(~"cat"); + runargs.push(fmt!("%s/%s.stdout", config.adb_test_dir, prog_short)); - newargs_out.push(newcmd_out); - newargs_err.push(newcmd_err); + let procsrv::Result{ out: stdout_out, err: _, status: _ } = + procsrv::run("", config.adb_path, runargs, ~[(~"",~"")], Some(~"")); - let procsrv::Result{ out: out_out, err: _out_err, status: out_status } = - procsrv::run(~"", config.adb_path, newargs_out, ~[(~"",~"")], - Some(~"")); - let procsrv::Result{ out: err_out, err: _err_err, status: _err_status } = - procsrv::run(~"", config.adb_path, newargs_err, ~[(~"",~"")], - Some(~"")); + // get stderr of result + runargs = ~[]; + runargs.push(~"shell"); + runargs.push(~"cat"); + runargs.push(fmt!("%s/%s.stderr", config.adb_test_dir, prog_short)); - dump_output(config, testfile, out_out, err_out); + let procsrv::Result{ out: stderr_out, err: _, status: _ } = + procsrv::run("", config.adb_path, runargs, ~[(~"",~"")], Some(~"")); - match err_out { - ~"" => ProcRes {status: out_status, stdout: out_out, - stderr: err_out, cmdline: cmdline }, - _ => ProcRes {status: 101, stdout: out_out, - stderr: err_out, cmdline: cmdline } - } + dump_output(config, testfile, stdout_out, stderr_out); + + ProcRes {status: exitcode, stdout: stdout_out, stderr: stderr_out, cmdline: cmdline } } fn _dummy_exec_compiled_test(config: &config, props: &TestProps, @@ -816,8 +832,8 @@ fn _arm_push_aux_shared_library(config: &config, testfile: &Path) { if (file.filetype() == Some(~".so")) { - let copy_result = procsrv::run(~"", config.adb_path, - ~[~"push", file.to_str(), copy config.adb_test_dir], + let copy_result = procsrv::run("", config.adb_path, + [~"push", file.to_str(), copy config.adb_test_dir], ~[(~"",~"")], Some(~"")); if config.verbose { diff --git a/src/compiletest/util.rs b/src/compiletest/util.rs index 05e5d902a47c9..26a62f8a5b224 100644 --- a/src/compiletest/util.rs +++ b/src/compiletest/util.rs @@ -8,8 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use common::config; +use core::io; use core::os::getenv; pub fn make_new_path(path: &str) -> ~str { diff --git a/src/driver/driver.rs b/src/driver/driver.rs index 70dc9e895c01e..97e01d1bcdc01 100644 --- a/src/driver/driver.rs +++ b/src/driver/driver.rs @@ -8,22 +8,27 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[no_core]; +#[no_std]; + +extern mod core(name = "std", vers = "0.7-pre"); + #[cfg(rustpkg)] -extern mod this(name = "rustpkg", vers = "0.7-pre"); +extern mod this(name = "rustpkg"); #[cfg(fuzzer)] -extern mod this(name = "fuzzer", vers = "0.7-pre"); +extern mod this(name = "fuzzer"); #[cfg(rustdoc)] -extern mod this(name = "rustdoc", vers = "0.7-pre"); +extern mod this(name = "rustdoc"); #[cfg(rusti)] -extern mod this(name = "rusti", vers = "0.7-pre"); +extern mod this(name = "rusti"); #[cfg(rust)] -extern mod this(name = "rust", vers = "0.7-pre"); +extern mod this(name = "rust"); #[cfg(rustc)] -extern mod this(name = "rustc", vers = "0.7-pre"); +extern mod this(name = "rustc"); fn main() { this::main() } diff --git a/src/etc/adb_run_wrapper.sh b/src/etc/adb_run_wrapper.sh new file mode 100755 index 0000000000000..68ac6b4242c3e --- /dev/null +++ b/src/etc/adb_run_wrapper.sh @@ -0,0 +1,35 @@ +# +# usage : adb_run_wrapper [test dir - where test executables exist] [test executable] +# + +# Sometimes android shell produce exitcode "1 : Text File Busy" +# Retry after $WAIT seconds, expecting resource cleaned-up +WAIT=10 +PATH=$1 +if [ -d "$PATH" ] +then + shift + RUN=$1 + + if [ ! -z "$RUN" ] + then + shift + + L_RET=1 + L_COUNT=0 + while [ $L_RET -eq 1 ] + do + LD_LIBRARY_PATH=$PATH $PATH/$RUN $@ 1>$PATH/$RUN.stdout 2>$PATH/$RUN.stderr + L_RET=$? + if [ $L_COUNT -gt 0 ] + then + /system/bin/sleep $WAIT + /system/bin/sync + fi + L_COUNT=`expr $L_COUNT+1` + done + + echo $L_RET > $PATH/$RUN.exitcode + + fi +fi diff --git a/src/etc/combine-tests.py b/src/etc/combine-tests.py index 93989f8e4a901..8e9caf189c220 100755 --- a/src/etc/combine-tests.py +++ b/src/etc/combine-tests.py @@ -49,10 +49,11 @@ def scrub(b): d = open("tmp/run_pass_stage2_driver.rs", "w") d.write("// AUTO-GENERATED FILE: DO NOT EDIT\n") -d.write("extern mod std;\n") +d.write("extern mod extra;\n") d.write("extern mod run_pass_stage2;\n") d.write("use run_pass_stage2::*;\n") -d.write("use core::io::WriterUtil;\n"); +d.write("use std::io::WriterUtil;\n"); +d.write("use std::io;\n"); d.write("fn main() {\n"); d.write(" let out = io::stdout();\n"); i = 0 diff --git a/src/etc/ctags.rust b/src/etc/ctags.rust index e08db63d0c925..4654116bc4d2b 100644 --- a/src/etc/ctags.rust +++ b/src/etc/ctags.rust @@ -4,9 +4,7 @@ --regex-rust=/[ \t]*type[ \t]+([a-zA-Z0-9_]+)/\1/T,types/ --regex-rust=/[ \t]*enum[ \t]+([a-zA-Z0-9_]+)/\1/T,types/ --regex-rust=/[ \t]*struct[ \t]+([a-zA-Z0-9_]+)/\1/m,types/ ---regex-rust=/[ \t]*class[ \t]+([a-zA-Z0-9_]+)/\1/m,types/ --regex-rust=/[ \t]*mod[ \t]+([a-zA-Z0-9_]+)/\1/m,modules/ ---regex-rust=/[ \t]*const[ \t]+([a-zA-Z0-9_]+)/\1/m,consts/ +--regex-rust=/[ \t]*static[ \t]+([a-zA-Z0-9_]+)/\1/m,consts/ --regex-rust=/[ \t]*trait[ \t]+([a-zA-Z0-9_]+)/\1/m,traits/ --regex-rust=/[ \t]*impl[ \t]+([a-zA-Z0-9_]+)/\1/m,impls/ ---regex-rust=/[ \t]*impl[ \t]+of[ \t]([a-zA-Z0-9_]+)/\1/m,impls/ diff --git a/src/etc/extract-tests.py b/src/etc/extract-tests.py index 12740a5616b8d..0260789adfc23 100644 --- a/src/etc/extract-tests.py +++ b/src/etc/extract-tests.py @@ -57,8 +57,8 @@ if not ignore: if not re.search(r"\bfn main\b", block): block = "fn main() {\n" + block + "\n}\n" - if not re.search(r"\bextern mod std\b", block): - block = "extern mod std;\n" + block + if not re.search(r"\bextern mod extra\b", block): + block = "extern mod extra;\n" + block block = """#[ forbid(ctypes) ]; #[ forbid(deprecated_pattern) ]; #[ forbid(implicit_copies) ]; diff --git a/src/etc/kate/rust.xml b/src/etc/kate/rust.xml index 6a751bd1c8588..44d0ce1a27fc5 100644 --- a/src/etc/kate/rust.xml +++ b/src/etc/kate/rust.xml @@ -49,6 +49,7 @@ Copy Send Owned + Sized Eq Ord Num diff --git a/src/etc/vim/after/ftplugin/rust.vim b/src/etc/vim/after/ftplugin/rust.vim deleted file mode 100644 index a053f8b40f863..0000000000000 --- a/src/etc/vim/after/ftplugin/rust.vim +++ /dev/null @@ -1,5 +0,0 @@ -"Highlight the 100th text column -"Feature became available in v7.3 -if version >= 703 - setlocal colorcolumn=100 -endif diff --git a/src/etc/vim/syntax/rust.vim b/src/etc/vim/syntax/rust.vim index cd794df0a8d89..5c08fdfecca55 100644 --- a/src/etc/vim/syntax/rust.vim +++ b/src/etc/vim/syntax/rust.vim @@ -44,7 +44,7 @@ syn keyword rustType size_t ptrdiff_t clock_t time_t syn keyword rustType c_longlong c_ulonglong intptr_t uintptr_t syn keyword rustType off_t dev_t ino_t pid_t mode_t ssize_t -syn keyword rustTrait Const Copy Send Owned " inherent traits +syn keyword rustTrait Const Copy Send Owned Sized " inherent traits syn keyword rustTrait Eq Ord Num Ptr syn keyword rustTrait Drop Add Sub Mul Quot Rem Neg BitAnd BitOr syn keyword rustTrait BitXor Shl Shr Index diff --git a/src/etc/zsh/_rust b/src/etc/zsh/_rust new file mode 100644 index 0000000000000..faa21a2961694 --- /dev/null +++ b/src/etc/zsh/_rust @@ -0,0 +1,102 @@ +#compdef rustc + +local -a _rustc_opts_switches _rustc_opts_lint _rustc_opts_debug + +typeset -A opt_args + +_rustc_opts_switches=( + --bin'[Compile an executable crate (default)]' + -c'[Compile and assemble, but do not link]' + --cfg'[Configure the compilation environment]' + --emit-llvm'[Produce an LLVM bitcode file]' + {-h,--help}'[Display this message]' + -L'[Add a directory to the library search path]' + --lib'[Compile a library crate]' + --linker'[Program to use for linking instead of the default.]' + --link-args'[FLAGS is a space-separated list of flags passed to the linker]' + --ls'[List the symbols defined by a library crate]' + --no-trans'[Run all passes except translation; no output]' + -O'[Equivalent to --opt-level=2]' + -o'[Write output to ]' + --opt-level'[Optimize with possible levels 0-3]' + --out-dir'[Write output to compiler-chosen filename in ]' + --parse-only'[Parse only; do not compile, assemble, or link]' + --pretty'[Pretty-print the input instead of compiling]' + -S'[Compile only; do not assemble or link]' + --save-temps'[Write intermediate files (.bc, .opt.bc, .o) in addition to normal output]' + --sysroot'[Override the system root]' + --test'[Build a test harness]' + --target'[Target triple cpu-manufacturer-kernel\[-os\] to compile]' + --target-feature'[Target specific attributes (llc -mattr=help for detail)]' + --android-cross-path'[The path to the Android NDK]' + {-W,--warn}'[Set lint warnings]' + {-A,--allow}'[Set lint allowed]' + {-D,--deny}'[Set lint denied]' + {-F,--forbid}'[Set lint forbidden]' + -Z'[Set internal debugging options]' + {-v,--version}'[Print version info and exit]' +) + +_rustc_opts_lint=( + 'path-statement:path statements with no effect' + 'deprecated-pattern:warn about deprecated uses of pattern bindings' + 'non-implicitly-copyable-typarams:passing non implicitly copyable types as copy type params' + 'missing-trait-doc:detects missing documentation for traits' + 'missing-struct-doc:detects missing documentation for structs' + 'ctypes:proper use of core::libc types in foreign modules' + 'implicit-copies:implicit copies of non implicitly copyable data' + "unused-mut:detect mut variables which don't need to be mutable" + 'unused-imports:imports that are never used' + 'heap-memory:use of any (~ type or @ type) heap memory' + 'default-methods:allow default methods' + 'unused-variable:detect variables which are not used in any way' + 'dead-assignment:detect assignments that will never be read' + 'unrecognized-lint:unrecognized lint attribute' + 'type-limits:comparisons made useless by limits of the types involved' + 'unused-unsafe:unnecessary use of an `unsafe` block' + 'while-true:suggest using loop { } instead of while(true) { }' + 'non-camel-case-types:types, variants and traits should have camel case names' + 'managed-heap-memory:use of managed (@ type) heap memory' + 'unnecessary-allocation:detects unnecessary allocations that can be eliminated' + 'owned-heap-memory:use of owned (~ type) heap memory' +) + +_rustc_opts_debug=( + 'verbose:in general, enable more debug printouts' + 'time-passes:measure time of each rustc pass' + 'count-llvm-insns:count where LLVM instrs originate' + 'time-llvm-passes:measure time of each LLVM pass' + 'trans-stats:gather trans statistics' + 'asm-comments:generate comments into the assembly (may change behavior)' + 'no-verify:skip LLVM verification' + 'trace:emit trace logs' + 'coherence:perform coherence checking' + 'borrowck-stats:gather borrowck statistics' + "borrowck-note-pure:note where purity is req'd" + "borrowck-note-loan:note where loans are req'd" + 'no-landing-pads:omit landing pads for unwinding' + 'debug-llvm:enable debug output from LLVM' + 'count-type-sizes:count the sizes of aggregate types' + 'meta-stats:gather metadata statistics' + 'no-opt:do not optimize, even if -O is passed' + 'no-monomorphic-collapse:do not collapse template instantiations' + 'print-link-args:Print the arguments passed to the linker' + 'gc:Garbage collect shared data (experimental)' + 'jit:Execute using JIT (experimental)' + 'extra-debug-info:Extra debugging info (experimental)' + 'debug-info:Produce debug info (experimental)' + 'static:Use or produce static libraries or binaries (experimental)' + 'no-debug-borrows:do not show where borrow checks fail' + 'lint-llvm:Run the LLVM lint pass on the pre-optimization IR' +) + +_rustc() { + case $words[2] in + -[WADF]) _describe 'options' _rustc_opts_lint ;; + -Z) _describe 'options' _rustc_opts_debug ;; + -) _arguments -s -w : "$_rustc_opts_switches[@]" ;; + *) _files -g "*.rs" ;; + esac +} + +_rustc "$@" diff --git a/src/libcore/bool.rs b/src/libcore/bool.rs deleted file mode 100644 index 76a8f456cd5f3..0000000000000 --- a/src/libcore/bool.rs +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Boolean logic - -#[cfg(not(test))] -use cmp::{Eq, Ord, TotalOrd, Ordering}; -use option::{None, Option, Some}; -use from_str::FromStr; - -/// Negation / inverse -pub fn not(v: bool) -> bool { !v } - -/// Conjunction -pub fn and(a: bool, b: bool) -> bool { a && b } - -/// Disjunction -pub fn or(a: bool, b: bool) -> bool { a || b } - -/** - * Exclusive or - * - * Identical to `or(and(a, not(b)), and(not(a), b))` - */ -pub fn xor(a: bool, b: bool) -> bool { (a && !b) || (!a && b) } - -/// Implication in the logic, i.e. from `a` follows `b` -pub fn implies(a: bool, b: bool) -> bool { !a || b } - -/// true if truth values `a` and `b` are indistinguishable in the logic -pub fn eq(a: bool, b: bool) -> bool { a == b } - -/// true if truth values `a` and `b` are distinguishable in the logic -pub fn ne(a: bool, b: bool) -> bool { a != b } - -/// true if `v` represents truth in the logic -pub fn is_true(v: bool) -> bool { v } - -/// true if `v` represents falsehood in the logic -pub fn is_false(v: bool) -> bool { !v } - -/// Parse logic value from `s` -impl FromStr for bool { - fn from_str(s: &str) -> Option { - if s == "true" { - Some(true) - } else if s == "false" { - Some(false) - } else { - None - } - } -} - -/// Convert `v` into a string -pub fn to_str(v: bool) -> ~str { if v { ~"true" } else { ~"false" } } - -/** - * Iterates over all truth values by passing them to `blk` in an unspecified - * order - */ -pub fn all_values(blk: &fn(v: bool)) { - blk(true); - blk(false); -} - -/// converts truth value to an 8 bit byte -#[inline(always)] -pub fn to_bit(v: bool) -> u8 { if v { 1u8 } else { 0u8 } } - -#[cfg(not(test))] -impl Ord for bool { - #[inline(always)] - fn lt(&self, other: &bool) -> bool { to_bit(*self) < to_bit(*other) } - #[inline(always)] - fn le(&self, other: &bool) -> bool { to_bit(*self) <= to_bit(*other) } - #[inline(always)] - fn gt(&self, other: &bool) -> bool { to_bit(*self) > to_bit(*other) } - #[inline(always)] - fn ge(&self, other: &bool) -> bool { to_bit(*self) >= to_bit(*other) } -} - -#[cfg(not(test))] -impl TotalOrd for bool { - #[inline(always)] - fn cmp(&self, other: &bool) -> Ordering { to_bit(*self).cmp(&to_bit(*other)) } -} - -#[cfg(not(test))] -impl Eq for bool { - #[inline(always)] - fn eq(&self, other: &bool) -> bool { (*self) == (*other) } - #[inline(always)] - fn ne(&self, other: &bool) -> bool { (*self) != (*other) } -} - -#[cfg(test)] -mod tests { - use super::*; - use prelude::*; - - #[test] - fn test_bool_from_str() { - do all_values |v| { - assert!(Some(v) == FromStr::from_str(to_str(v))) - } - } - - #[test] - fn test_bool_to_str() { - assert!(to_str(false) == ~"false"); - assert!(to_str(true) == ~"true"); - } - - #[test] - fn test_bool_to_bit() { - do all_values |v| { - assert!(to_bit(v) == if is_true(v) { 1u8 } else { 0u8 }); - } - } - - #[test] - fn test_bool_ord() { - assert!(true > false); - assert!(!(false > true)); - - assert!(false < true); - assert!(!(true < false)); - - assert!(false <= false); - assert!(false >= false); - assert!(true <= true); - assert!(true >= true); - - assert!(false <= true); - assert!(!(false >= true)); - assert!(true >= false); - assert!(!(true <= false)); - } - - #[test] - fn test_bool_totalord() { - assert_eq!(true.cmp(&true), Equal); - assert_eq!(false.cmp(&false), Equal); - assert_eq!(true.cmp(&false), Greater); - assert_eq!(false.cmp(&true), Less); - } -} diff --git a/src/libcore/char.rs b/src/libcore/char.rs deleted file mode 100644 index 68f283f1ad848..0000000000000 --- a/src/libcore/char.rs +++ /dev/null @@ -1,349 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Utilities for manipulating the char type - -#[cfg(not(test))] -use cmp::Ord; -use option::{None, Option, Some}; -use str; -use u32; -use uint; -use unicode::{derived_property, general_category}; - -#[cfg(not(test))] use cmp::Eq; - -/* - Lu Uppercase_Letter an uppercase letter - Ll Lowercase_Letter a lowercase letter - Lt Titlecase_Letter a digraphic character, with first part uppercase - Lm Modifier_Letter a modifier letter - Lo Other_Letter other letters, including syllables and ideographs - Mn Nonspacing_Mark a nonspacing combining mark (zero advance width) - Mc Spacing_Mark a spacing combining mark (positive advance width) - Me Enclosing_Mark an enclosing combining mark - Nd Decimal_Number a decimal digit - Nl Letter_Number a letterlike numeric character - No Other_Number a numeric character of other type - Pc Connector_Punctuation a connecting punctuation mark, like a tie - Pd Dash_Punctuation a dash or hyphen punctuation mark - Ps Open_Punctuation an opening punctuation mark (of a pair) - Pe Close_Punctuation a closing punctuation mark (of a pair) - Pi Initial_Punctuation an initial quotation mark - Pf Final_Punctuation a final quotation mark - Po Other_Punctuation a punctuation mark of other type - Sm Math_Symbol a symbol of primarily mathematical use - Sc Currency_Symbol a currency sign - Sk Modifier_Symbol a non-letterlike modifier symbol - So Other_Symbol a symbol of other type - Zs Space_Separator a space character (of various non-zero widths) - Zl Line_Separator U+2028 LINE SEPARATOR only - Zp Paragraph_Separator U+2029 PARAGRAPH SEPARATOR only - Cc Control a C0 or C1 control code - Cf Format a format control character - Cs Surrogate a surrogate code point - Co Private_Use a private-use character - Cn Unassigned a reserved unassigned code point or a noncharacter -*/ - -pub fn is_alphabetic(c: char) -> bool { derived_property::Alphabetic(c) } -pub fn is_XID_start(c: char) -> bool { derived_property::XID_Start(c) } -pub fn is_XID_continue(c: char) -> bool { derived_property::XID_Continue(c) } - -/** - * Indicates whether a character is in lower case, defined - * in terms of the Unicode General Category 'Ll' - */ -#[inline(always)] -pub fn is_lowercase(c: char) -> bool { - return general_category::Ll(c); -} - -/** - * Indicates whether a character is in upper case, defined - * in terms of the Unicode General Category 'Lu'. - */ -#[inline(always)] -pub fn is_uppercase(c: char) -> bool { - return general_category::Lu(c); -} - -/** - * Indicates whether a character is whitespace. Whitespace is defined in - * terms of the Unicode General Categories 'Zs', 'Zl', 'Zp' - * additional 'Cc'-category control codes in the range [0x09, 0x0d] - */ -#[inline(always)] -pub fn is_whitespace(c: char) -> bool { - return ('\x09' <= c && c <= '\x0d') - || general_category::Zs(c) - || general_category::Zl(c) - || general_category::Zp(c); -} - -/** - * Indicates whether a character is alphanumeric. Alphanumericness is - * defined in terms of the Unicode General Categories 'Nd', 'Nl', 'No' - * and the Derived Core Property 'Alphabetic'. - */ -#[inline(always)] -pub fn is_alphanumeric(c: char) -> bool { - return derived_property::Alphabetic(c) || - general_category::Nd(c) || - general_category::Nl(c) || - general_category::No(c); -} - -/// Indicates whether the character is numeric (Nd, Nl, or No) -#[inline(always)] -pub fn is_digit(c: char) -> bool { - return general_category::Nd(c) || - general_category::Nl(c) || - general_category::No(c); -} - -/** - * Checks if a character parses as a numeric digit in the given radix. - * Compared to `is_digit()`, this function only recognizes the - * characters `0-9`, `a-z` and `A-Z`. - * - * Returns `true` if `c` is a valid digit under `radix`, and `false` - * otherwise. - * - * Fails if given a `radix` > 36. - * - * Note: This just wraps `to_digit()`. - */ -#[inline(always)] -pub fn is_digit_radix(c: char, radix: uint) -> bool { - match to_digit(c, radix) { - Some(_) => true, - None => false - } -} - -/** - * Convert a char to the corresponding digit. - * - * # Return value - * - * If `c` is between '0' and '9', the corresponding value - * between 0 and 9. If `c` is 'a' or 'A', 10. If `c` is - * 'b' or 'B', 11, etc. Returns none if the char does not - * refer to a digit in the given radix. - * - * # Failure - * Fails if given a `radix` outside the range `[0..36]`. - */ -#[inline] -pub fn to_digit(c: char, radix: uint) -> Option { - if radix > 36 { - fail!("to_digit: radix %? is to high (maximum 36)", radix); - } - let val = match c { - '0' .. '9' => c as uint - ('0' as uint), - 'a' .. 'z' => c as uint + 10u - ('a' as uint), - 'A' .. 'Z' => c as uint + 10u - ('A' as uint), - _ => return None - }; - if val < radix { Some(val) } - else { None } -} - -/** - * Converts a number to the character representing it. - * - * Returns `Some(char)` if `num` represents one digit under `radix`, - * using one character of `0-9` or `a-z`, or `None` if it doesn't. - * - * Fails if given an `radix` > 36. - */ -#[inline] -pub fn from_digit(num: uint, radix: uint) -> Option { - if radix > 36 { - fail!("from_digit: radix %? is to high (maximum 36)", num); - } - if num < radix { - if num < 10 { - Some(('0' as uint + num) as char) - } else { - Some(('a' as uint + num - 10u) as char) - } - } else { - None - } -} - -/** - * Return the hexadecimal unicode escape of a char. - * - * The rules are as follows: - * - * - chars in [0,0xff] get 2-digit escapes: `\\xNN` - * - chars in [0x100,0xffff] get 4-digit escapes: `\\uNNNN` - * - chars above 0x10000 get 8-digit escapes: `\\UNNNNNNNN` - */ -pub fn escape_unicode(c: char) -> ~str { - let s = u32::to_str_radix(c as u32, 16u); - let (c, pad) = (if c <= '\xff' { ('x', 2u) } - else if c <= '\uffff' { ('u', 4u) } - else { ('U', 8u) }); - assert!(str::len(s) <= pad); - let mut out = ~"\\"; - str::push_str(&mut out, str::from_char(c)); - for uint::range(str::len(s), pad) |_i| - { str::push_str(&mut out, ~"0"); } - str::push_str(&mut out, s); - out -} - -/** - * Return a 'default' ASCII and C++11-like char-literal escape of a char. - * - * The default is chosen with a bias toward producing literals that are - * legal in a variety of languages, including C++11 and similar C-family - * languages. The exact rules are: - * - * - Tab, CR and LF are escaped as '\t', '\r' and '\n' respectively. - * - Single-quote, double-quote and backslash chars are backslash-escaped. - * - Any other chars in the range [0x20,0x7e] are not escaped. - * - Any other chars are given hex unicode escapes; see `escape_unicode`. - */ -pub fn escape_default(c: char) -> ~str { - match c { - '\t' => ~"\\t", - '\r' => ~"\\r", - '\n' => ~"\\n", - '\\' => ~"\\\\", - '\'' => ~"\\'", - '"' => ~"\\\"", - '\x20' .. '\x7e' => str::from_char(c), - _ => escape_unicode(c) - } -} - -/// Returns the amount of bytes this character would need if encoded in utf8 -pub fn len_utf8_bytes(c: char) -> uint { - static max_one_b: uint = 128u; - static max_two_b: uint = 2048u; - static max_three_b: uint = 65536u; - static max_four_b: uint = 2097152u; - - let code = c as uint; - if code < max_one_b { 1u } - else if code < max_two_b { 2u } - else if code < max_three_b { 3u } - else if code < max_four_b { 4u } - else { fail!("invalid character!") } -} - -#[cfg(not(test))] -impl Eq for char { - #[inline(always)] - fn eq(&self, other: &char) -> bool { (*self) == (*other) } - #[inline(always)] - fn ne(&self, other: &char) -> bool { (*self) != (*other) } -} - -#[cfg(not(test))] -impl Ord for char { - #[inline(always)] - fn lt(&self, other: &char) -> bool { *self < *other } - #[inline(always)] - fn le(&self, other: &char) -> bool { *self <= *other } - #[inline(always)] - fn gt(&self, other: &char) -> bool { *self > *other } - #[inline(always)] - fn ge(&self, other: &char) -> bool { *self >= *other } -} - -#[test] -fn test_is_lowercase() { - assert!(is_lowercase('a')); - assert!(is_lowercase('ö')); - assert!(is_lowercase('ß')); - assert!(!is_lowercase('Ü')); - assert!(!is_lowercase('P')); -} - -#[test] -fn test_is_uppercase() { - assert!(!is_uppercase('h')); - assert!(!is_uppercase('ä')); - assert!(!is_uppercase('ß')); - assert!(is_uppercase('Ö')); - assert!(is_uppercase('T')); -} - -#[test] -fn test_is_whitespace() { - assert!(is_whitespace(' ')); - assert!(is_whitespace('\u2007')); - assert!(is_whitespace('\t')); - assert!(is_whitespace('\n')); - - assert!(!is_whitespace('a')); - assert!(!is_whitespace('_')); - assert!(!is_whitespace('\u0000')); -} - -#[test] -fn test_to_digit() { - assert_eq!(to_digit('0', 10u), Some(0u)); - assert_eq!(to_digit('1', 2u), Some(1u)); - assert_eq!(to_digit('2', 3u), Some(2u)); - assert_eq!(to_digit('9', 10u), Some(9u)); - assert_eq!(to_digit('a', 16u), Some(10u)); - assert_eq!(to_digit('A', 16u), Some(10u)); - assert_eq!(to_digit('b', 16u), Some(11u)); - assert_eq!(to_digit('B', 16u), Some(11u)); - assert_eq!(to_digit('z', 36u), Some(35u)); - assert_eq!(to_digit('Z', 36u), Some(35u)); - - assert!(to_digit(' ', 10u).is_none()); - assert!(to_digit('$', 36u).is_none()); -} - -#[test] -fn test_is_digit() { - assert!(is_digit('2')); - assert!(is_digit('7')); - assert!(! is_digit('c')); - assert!(! is_digit('i')); - assert!(! is_digit('z')); - assert!(! is_digit('Q')); -} - -#[test] -fn test_escape_default() { - assert_eq!(escape_default('\n'), ~"\\n"); - assert_eq!(escape_default('\r'), ~"\\r"); - assert_eq!(escape_default('\''), ~"\\'"); - assert_eq!(escape_default('"'), ~"\\\""); - assert_eq!(escape_default(' '), ~" "); - assert_eq!(escape_default('a'), ~"a"); - assert_eq!(escape_default('~'), ~"~"); - assert_eq!(escape_default('\x00'), ~"\\x00"); - assert_eq!(escape_default('\x1f'), ~"\\x1f"); - assert_eq!(escape_default('\x7f'), ~"\\x7f"); - assert_eq!(escape_default('\xff'), ~"\\xff"); - assert_eq!(escape_default('\u011b'), ~"\\u011b"); - assert_eq!(escape_default('\U0001d4b6'), ~"\\U0001d4b6"); -} - -#[test] -fn test_escape_unicode() { - assert_eq!(escape_unicode('\x00'), ~"\\x00"); - assert_eq!(escape_unicode('\n'), ~"\\x0a"); - assert_eq!(escape_unicode(' '), ~"\\x20"); - assert_eq!(escape_unicode('a'), ~"\\x61"); - assert_eq!(escape_unicode('\u011b'), ~"\\u011b"); - assert_eq!(escape_unicode('\U0001d4b6'), ~"\\U0001d4b6"); -} diff --git a/src/libcore/comm.rs b/src/libcore/comm.rs deleted file mode 100644 index 34c60202b3f12..0000000000000 --- a/src/libcore/comm.rs +++ /dev/null @@ -1,619 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/*! -Message passing -*/ - -use cast::{transmute, transmute_mut}; -use container::Container; -use either::{Either, Left, Right}; -use kinds::Owned; -use option::{Option, Some, None}; -use uint; -use vec; -use vec::OwnedVector; -use util::replace; -use unstable::sync::{Exclusive, exclusive}; - -use pipes::{recv, try_recv, wait_many, peek, PacketHeader}; - -// FIXME #5160: Making this public exposes some plumbing from -// pipes. Needs some refactoring -pub use pipes::Selectable; - -/// A trait for things that can send multiple messages. -pub trait GenericChan { - /// Sends a message. - fn send(&self, x: T); -} - -/// Things that can send multiple messages and can detect when the receiver -/// is closed -pub trait GenericSmartChan { - /// Sends a message, or report if the receiver has closed the connection. - fn try_send(&self, x: T) -> bool; -} - -/// A trait for things that can receive multiple messages. -pub trait GenericPort { - /// Receives a message, or fails if the connection closes. - fn recv(&self) -> T; - - /** Receives a message, or returns `none` if - the connection is closed or closes. - */ - fn try_recv(&self) -> Option; -} - -/// Ports that can `peek` -pub trait Peekable { - /// Returns true if a message is available - fn peek(&self) -> bool; -} - - -// Streams - Make pipes a little easier in general. - -/*proto! streamp ( - Open:send { - data(T) -> Open - } -)*/ - -#[allow(non_camel_case_types)] -pub mod streamp { - priv use core::kinds::Owned; - - pub fn init() -> (client::Open, server::Open) { - pub use core::pipes::HasBuffer; - ::core::pipes::entangle() - } - - #[allow(non_camel_case_types)] - pub enum Open { pub data(T, server::Open), } - - #[allow(non_camel_case_types)] - pub mod client { - priv use core::kinds::Owned; - - #[allow(non_camel_case_types)] - pub fn try_data(pipe: Open, x_0: T) -> - ::core::option::Option> { - { - use super::data; - let (c, s) = ::core::pipes::entangle(); - let message = data(x_0, s); - if ::core::pipes::send(pipe, message) { - ::core::pipes::rt::make_some(c) - } else { ::core::pipes::rt::make_none() } - } - } - - #[allow(non_camel_case_types)] - pub fn data(pipe: Open, x_0: T) -> Open { - { - use super::data; - let (c, s) = ::core::pipes::entangle(); - let message = data(x_0, s); - ::core::pipes::send(pipe, message); - c - } - } - - #[allow(non_camel_case_types)] - pub type Open = ::core::pipes::SendPacket>; - } - - #[allow(non_camel_case_types)] - pub mod server { - #[allow(non_camel_case_types)] - pub type Open = ::core::pipes::RecvPacket>; - } -} - -/// An endpoint that can send many messages. -#[unsafe_mut_field(endp)] -pub struct Chan { - endp: Option> -} - -/// An endpoint that can receive many messages. -#[unsafe_mut_field(endp)] -pub struct Port { - endp: Option>, -} - -/** Creates a `(Port, Chan)` pair. - -These allow sending or receiving an unlimited number of messages. - -*/ -pub fn stream() -> (Port, Chan) { - let (c, s) = streamp::init(); - - (Port { - endp: Some(s) - }, Chan { - endp: Some(c) - }) -} - -impl GenericChan for Chan { - #[inline(always)] - fn send(&self, x: T) { - unsafe { - let self_endp = transmute_mut(&self.endp); - let endp = replace(self_endp, None); - *self_endp = Some(streamp::client::data(endp.unwrap(), x)) - } - } -} - -impl GenericSmartChan for Chan { - #[inline(always)] - fn try_send(&self, x: T) -> bool { - unsafe { - let self_endp = transmute_mut(&self.endp); - let endp = replace(self_endp, None); - match streamp::client::try_data(endp.unwrap(), x) { - Some(next) => { - *self_endp = Some(next); - true - } - None => false - } - } - } -} - -impl GenericPort for Port { - #[inline(always)] - fn recv(&self) -> T { - unsafe { - let self_endp = transmute_mut(&self.endp); - let endp = replace(self_endp, None); - let streamp::data(x, endp) = recv(endp.unwrap()); - *self_endp = Some(endp); - x - } - } - - #[inline(always)] - fn try_recv(&self) -> Option { - unsafe { - let self_endp = transmute_mut(&self.endp); - let endp = replace(self_endp, None); - match try_recv(endp.unwrap()) { - Some(streamp::data(x, endp)) => { - *self_endp = Some(endp); - Some(x) - } - None => None - } - } - } -} - -impl Peekable for Port { - #[inline(always)] - fn peek(&self) -> bool { - unsafe { - let self_endp = transmute_mut(&self.endp); - let mut endp = replace(self_endp, None); - let peek = match endp { - Some(ref mut endp) => peek(endp), - None => fail!("peeking empty stream") - }; - *self_endp = endp; - peek - } - } -} - -impl Selectable for Port { - fn header(&mut self) -> *mut PacketHeader { - match self.endp { - Some(ref mut endp) => endp.header(), - None => fail!("peeking empty stream") - } - } -} - -/// Treat many ports as one. -#[unsafe_mut_field(ports)] -pub struct PortSet { - ports: ~[Port], -} - -pub impl PortSet { - fn new() -> PortSet { - PortSet { - ports: ~[] - } - } - - fn add(&self, port: Port) { - unsafe { - let self_ports = transmute_mut(&self.ports); - self_ports.push(port) - } - } - - fn chan(&self) -> Chan { - let (po, ch) = stream(); - self.add(po); - ch - } -} - -impl GenericPort for PortSet { - fn try_recv(&self) -> Option { - unsafe { - let self_ports = transmute_mut(&self.ports); - let mut result = None; - // we have to swap the ports array so we aren't borrowing - // aliasable mutable memory. - let mut ports = replace(self_ports, ~[]); - while result.is_none() && ports.len() > 0 { - let i = wait_many(ports); - match ports[i].try_recv() { - Some(m) => { - result = Some(m); - } - None => { - // Remove this port. - let _ = ports.swap_remove(i); - } - } - } - *self_ports = ports; - result - } - } - fn recv(&self) -> T { - self.try_recv().expect("port_set: endpoints closed") - } -} - -impl Peekable for PortSet { - fn peek(&self) -> bool { - // It'd be nice to use self.port.each, but that version isn't - // pure. - for uint::range(0, vec::uniq_len(&const self.ports)) |i| { - let port: &Port = &self.ports[i]; - if port.peek() { - return true; - } - } - false - } -} - -/// A channel that can be shared between many senders. -pub struct SharedChan { - ch: Exclusive> -} - -impl SharedChan { - /// Converts a `chan` into a `shared_chan`. - pub fn new(c: Chan) -> SharedChan { - SharedChan { ch: exclusive(c) } - } -} - -impl GenericChan for SharedChan { - fn send(&self, x: T) { - let mut xx = Some(x); - do self.ch.with_imm |chan| { - let x = replace(&mut xx, None); - chan.send(x.unwrap()) - } - } -} - -impl GenericSmartChan for SharedChan { - fn try_send(&self, x: T) -> bool { - let mut xx = Some(x); - do self.ch.with_imm |chan| { - let x = replace(&mut xx, None); - chan.try_send(x.unwrap()) - } - } -} - -impl ::clone::Clone for SharedChan { - fn clone(&self) -> SharedChan { - SharedChan { ch: self.ch.clone() } - } -} - -/*proto! oneshot ( - Oneshot:send { - send(T) -> ! - } -)*/ - -#[allow(non_camel_case_types)] -pub mod oneshot { - priv use core::kinds::Owned; - use ptr::to_mut_unsafe_ptr; - - pub fn init() -> (client::Oneshot, server::Oneshot) { - pub use core::pipes::HasBuffer; - - let buffer = ~::core::pipes::Buffer { - header: ::core::pipes::BufferHeader(), - data: __Buffer { - Oneshot: ::core::pipes::mk_packet::>() - }, - }; - do ::core::pipes::entangle_buffer(buffer) |buffer, data| { - data.Oneshot.set_buffer(buffer); - to_mut_unsafe_ptr(&mut data.Oneshot) - } - } - #[allow(non_camel_case_types)] - pub enum Oneshot { pub send(T), } - #[allow(non_camel_case_types)] - pub struct __Buffer { - Oneshot: ::core::pipes::Packet>, - } - - #[allow(non_camel_case_types)] - pub mod client { - - priv use core::kinds::Owned; - - #[allow(non_camel_case_types)] - pub fn try_send(pipe: Oneshot, x_0: T) -> - ::core::option::Option<()> { - { - use super::send; - let message = send(x_0); - if ::core::pipes::send(pipe, message) { - ::core::pipes::rt::make_some(()) - } else { ::core::pipes::rt::make_none() } - } - } - - #[allow(non_camel_case_types)] - pub fn send(pipe: Oneshot, x_0: T) { - { - use super::send; - let message = send(x_0); - ::core::pipes::send(pipe, message); - } - } - - #[allow(non_camel_case_types)] - pub type Oneshot = - ::core::pipes::SendPacketBuffered, - super::__Buffer>; - } - - #[allow(non_camel_case_types)] - pub mod server { - #[allow(non_camel_case_types)] - pub type Oneshot = - ::core::pipes::RecvPacketBuffered, - super::__Buffer>; - } -} - -/// The send end of a oneshot pipe. -pub struct ChanOne { - contents: oneshot::client::Oneshot -} - -impl ChanOne { - pub fn new(contents: oneshot::client::Oneshot) -> ChanOne { - ChanOne { - contents: contents - } - } -} - -/// The receive end of a oneshot pipe. -pub struct PortOne { - contents: oneshot::server::Oneshot -} - -impl PortOne { - pub fn new(contents: oneshot::server::Oneshot) -> PortOne { - PortOne { - contents: contents - } - } -} - -/// Initialiase a (send-endpoint, recv-endpoint) oneshot pipe pair. -pub fn oneshot() -> (PortOne, ChanOne) { - let (chan, port) = oneshot::init(); - (PortOne::new(port), ChanOne::new(chan)) -} - -pub impl PortOne { - fn recv(self) -> T { recv_one(self) } - fn try_recv(self) -> Option { try_recv_one(self) } - fn unwrap(self) -> oneshot::server::Oneshot { - match self { - PortOne { contents: s } => s - } - } -} - -pub impl ChanOne { - fn send(self, data: T) { send_one(self, data) } - fn try_send(self, data: T) -> bool { try_send_one(self, data) } - fn unwrap(self) -> oneshot::client::Oneshot { - match self { - ChanOne { contents: s } => s - } - } -} - -/** - * Receive a message from a oneshot pipe, failing if the connection was - * closed. - */ -pub fn recv_one(port: PortOne) -> T { - match port { - PortOne { contents: port } => { - let oneshot::send(message) = recv(port); - message - } - } -} - -/// Receive a message from a oneshot pipe unless the connection was closed. -pub fn try_recv_one (port: PortOne) -> Option { - match port { - PortOne { contents: port } => { - let message = try_recv(port); - - if message.is_none() { - None - } else { - let oneshot::send(message) = message.unwrap(); - Some(message) - } - } - } -} - -/// Send a message on a oneshot pipe, failing if the connection was closed. -pub fn send_one(chan: ChanOne, data: T) { - match chan { - ChanOne { contents: chan } => oneshot::client::send(chan, data), - } -} - -/** - * Send a message on a oneshot pipe, or return false if the connection was - * closed. - */ -pub fn try_send_one(chan: ChanOne, data: T) -> bool { - match chan { - ChanOne { contents: chan } => { - oneshot::client::try_send(chan, data).is_some() - } - } -} - - - -/// Returns the index of an endpoint that is ready to receive. -pub fn selecti(endpoints: &mut [T]) -> uint { - wait_many(endpoints) -} - -/// Returns 0 or 1 depending on which endpoint is ready to receive -pub fn select2i(a: &mut A, b: &mut B) - -> Either<(), ()> { - let mut endpoints = [ a.header(), b.header() ]; - match wait_many(endpoints) { - 0 => Left(()), - 1 => Right(()), - _ => fail!("wait returned unexpected index"), - } -} - -/// Receive a message from one of two endpoints. -pub trait Select2 { - /// Receive a message or return `None` if a connection closes. - fn try_select(&mut self) -> Either, Option>; - /// Receive a message or fail if a connection closes. - fn select(&mut self) -> Either; -} - -impl, - Right:Selectable + GenericPort> - Select2 - for (Left, Right) { - fn select(&mut self) -> Either { - // XXX: Bad borrow check workaround. - unsafe { - let this: &(Left, Right) = transmute(self); - match *this { - (ref lp, ref rp) => { - let lp: &mut Left = transmute(lp); - let rp: &mut Right = transmute(rp); - match select2i(lp, rp) { - Left(()) => Left(lp.recv()), - Right(()) => Right(rp.recv()), - } - } - } - } - } - - fn try_select(&mut self) -> Either, Option> { - // XXX: Bad borrow check workaround. - unsafe { - let this: &(Left, Right) = transmute(self); - match *this { - (ref lp, ref rp) => { - let lp: &mut Left = transmute(lp); - let rp: &mut Right = transmute(rp); - match select2i(lp, rp) { - Left(()) => Left (lp.try_recv()), - Right(()) => Right(rp.try_recv()), - } - } - } - } - } -} - -#[cfg(test)] -mod test { - use either::Right; - use super::{Chan, Port, oneshot, stream}; - - #[test] - fn test_select2() { - let (p1, c1) = stream(); - let (p2, c2) = stream(); - - c1.send(~"abc"); - - let mut tuple = (p1, p2); - match tuple.select() { - Right(_) => fail!(), - _ => (), - } - - c2.send(123); - } - - #[test] - fn test_oneshot() { - let (p, c) = oneshot(); - - c.send(()); - - p.recv() - } - - #[test] - fn test_peek_terminated() { - let (port, chan): (Port, Chan) = stream(); - - { - // Destroy the channel - let _chan = chan; - } - - assert!(!port.peek()); - } -} diff --git a/src/libcore/iterator.rs b/src/libcore/iterator.rs deleted file mode 100644 index 40c9637f692bc..0000000000000 --- a/src/libcore/iterator.rs +++ /dev/null @@ -1,526 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/*! Composable external iterators - -The `Iterator` trait defines an interface for objects which implement iteration as a state machine. - -Algorithms like `zip` are provided as `Iterator` implementations which wrap other objects -implementing the `Iterator` trait. - -*/ - -use prelude::*; - -pub trait Iterator { - /// Advance the iterator and return the next value. Return `None` when the end is reached. - fn next(&mut self) -> Option; -} - -/// Iterator adaptors provided for every `Iterator` implementation. The adaptor objects are also -/// implementations of the `Iterator` trait. -/// -/// In the future these will be default methods instead of a utility trait. -pub trait IteratorUtil { - fn chain>(self, other: U) -> ChainIterator; - fn zip>(self, other: U) -> ZipIterator; - // FIXME: #5898: should be called map - fn transform<'r, B>(self, f: &'r fn(A) -> B) -> MapIterator<'r, A, B, Self>; - fn filter<'r>(self, predicate: &'r fn(&A) -> bool) -> FilterIterator<'r, A, Self>; - fn enumerate(self) -> EnumerateIterator; - fn skip_while<'r>(self, predicate: &'r fn(&A) -> bool) -> SkipWhileIterator<'r, A, Self>; - fn take_while<'r>(self, predicate: &'r fn(&A) -> bool) -> TakeWhileIterator<'r, A, Self>; - fn skip(self, n: uint) -> SkipIterator; - fn take(self, n: uint) -> TakeIterator; - fn scan<'r, St, B>(self, initial_state: St, f: &'r fn(&mut St, A) -> Option) - -> ScanIterator<'r, A, B, Self, St>; - #[cfg(stage0)] - fn advance(&mut self, f: &fn(A) -> bool); - #[cfg(not(stage0))] - fn advance(&mut self, f: &fn(A) -> bool) -> bool; -} - -/// Iterator adaptors provided for every `Iterator` implementation. The adaptor objects are also -/// implementations of the `Iterator` trait. -/// -/// In the future these will be default methods instead of a utility trait. -impl> IteratorUtil for T { - #[inline(always)] - fn chain>(self, other: U) -> ChainIterator { - ChainIterator{a: self, b: other, flag: false} - } - - #[inline(always)] - fn zip>(self, other: U) -> ZipIterator { - ZipIterator{a: self, b: other} - } - - // FIXME: #5898: should be called map - #[inline(always)] - fn transform<'r, B>(self, f: &'r fn(A) -> B) -> MapIterator<'r, A, B, T> { - MapIterator{iter: self, f: f} - } - - #[inline(always)] - fn filter<'r>(self, predicate: &'r fn(&A) -> bool) -> FilterIterator<'r, A, T> { - FilterIterator{iter: self, predicate: predicate} - } - - #[inline(always)] - fn enumerate(self) -> EnumerateIterator { - EnumerateIterator{iter: self, count: 0} - } - - #[inline(always)] - fn skip_while<'r>(self, predicate: &'r fn(&A) -> bool) -> SkipWhileIterator<'r, A, T> { - SkipWhileIterator{iter: self, flag: false, predicate: predicate} - } - - #[inline(always)] - fn take_while<'r>(self, predicate: &'r fn(&A) -> bool) -> TakeWhileIterator<'r, A, T> { - TakeWhileIterator{iter: self, flag: false, predicate: predicate} - } - - #[inline(always)] - fn skip(self, n: uint) -> SkipIterator { - SkipIterator{iter: self, n: n} - } - - #[inline(always)] - fn take(self, n: uint) -> TakeIterator { - TakeIterator{iter: self, n: n} - } - - #[inline(always)] - fn scan<'r, St, B>(self, initial_state: St, f: &'r fn(&mut St, A) -> Option) - -> ScanIterator<'r, A, B, T, St> { - ScanIterator{iter: self, f: f, state: initial_state} - } - - /// A shim implementing the `for` loop iteration protocol for iterator objects - #[inline] - #[cfg(stage0)] - fn advance(&mut self, f: &fn(A) -> bool) { - loop { - match self.next() { - Some(x) => { - if !f(x) { return; } - } - None => { return; } - } - } - } - - /// A shim implementing the `for` loop iteration protocol for iterator objects - #[inline] - #[cfg(not(stage0))] - fn advance(&mut self, f: &fn(A) -> bool) -> bool { - loop { - match self.next() { - Some(x) => { - if !f(x) { return false; } - } - None => { return true; } - } - } - } -} - -pub struct ChainIterator { - priv a: T, - priv b: U, - priv flag: bool -} - -impl, U: Iterator> Iterator for ChainIterator { - #[inline] - fn next(&mut self) -> Option { - if self.flag { - self.b.next() - } else { - match self.a.next() { - Some(x) => return Some(x), - _ => () - } - self.flag = true; - self.b.next() - } - } -} - -pub struct ZipIterator { - priv a: T, - priv b: U -} - -impl, U: Iterator> Iterator<(A, B)> for ZipIterator { - #[inline] - fn next(&mut self) -> Option<(A, B)> { - match (self.a.next(), self.b.next()) { - (Some(x), Some(y)) => Some((x, y)), - _ => None - } - } -} - -pub struct MapIterator<'self, A, B, T> { - priv iter: T, - priv f: &'self fn(A) -> B -} - -impl<'self, A, B, T: Iterator> Iterator for MapIterator<'self, A, B, T> { - #[inline] - fn next(&mut self) -> Option { - match self.iter.next() { - Some(a) => Some((self.f)(a)), - _ => None - } - } -} - -pub struct FilterIterator<'self, A, T> { - priv iter: T, - priv predicate: &'self fn(&A) -> bool -} - -impl<'self, A, T: Iterator> Iterator for FilterIterator<'self, A, T> { - #[inline] - fn next(&mut self) -> Option { - for self.iter.advance |x| { - if (self.predicate)(&x) { - return Some(x); - } else { - loop - } - } - None - } -} - -pub struct EnumerateIterator { - priv iter: T, - priv count: uint -} - -impl> Iterator<(uint, A)> for EnumerateIterator { - #[inline] - fn next(&mut self) -> Option<(uint, A)> { - match self.iter.next() { - Some(a) => { - let ret = Some((self.count, a)); - self.count += 1; - ret - } - _ => None - } - } -} - -pub struct SkipWhileIterator<'self, A, T> { - priv iter: T, - priv flag: bool, - priv predicate: &'self fn(&A) -> bool -} - -impl<'self, A, T: Iterator> Iterator for SkipWhileIterator<'self, A, T> { - #[inline] - fn next(&mut self) -> Option { - let mut next = self.iter.next(); - if self.flag { - next - } else { - loop { - match next { - Some(x) => { - if (self.predicate)(&x) { - next = self.iter.next(); - loop - } else { - self.flag = true; - return Some(x) - } - } - None => return None - } - } - } - } -} - -pub struct TakeWhileIterator<'self, A, T> { - priv iter: T, - priv flag: bool, - priv predicate: &'self fn(&A) -> bool -} - -impl<'self, A, T: Iterator> Iterator for TakeWhileIterator<'self, A, T> { - #[inline] - fn next(&mut self) -> Option { - if self.flag { - None - } else { - match self.iter.next() { - Some(x) => { - if (self.predicate)(&x) { - Some(x) - } else { - self.flag = true; - None - } - } - None => None - } - } - } -} - -pub struct SkipIterator { - priv iter: T, - priv n: uint -} - -impl> Iterator for SkipIterator { - #[inline] - fn next(&mut self) -> Option { - let mut next = self.iter.next(); - if self.n == 0 { - next - } else { - let n = self.n; - for n.times { - match next { - Some(_) => { - next = self.iter.next(); - loop - } - None => { - self.n = 0; - return None - } - } - } - self.n = 0; - next - } - } -} - -pub struct TakeIterator { - priv iter: T, - priv n: uint -} - -impl> Iterator for TakeIterator { - #[inline] - fn next(&mut self) -> Option { - let next = self.iter.next(); - if self.n != 0 { - self.n -= 1; - next - } else { - None - } - } -} - -pub struct ScanIterator<'self, A, B, T, St> { - priv iter: T, - priv f: &'self fn(&mut St, A) -> Option, - state: St -} - -impl<'self, A, B, T: Iterator, St> Iterator for ScanIterator<'self, A, B, T, St> { - #[inline] - fn next(&mut self) -> Option { - self.iter.next().chain(|a| (self.f)(&mut self.state, a)) - } -} - -pub struct UnfoldrIterator<'self, A, St> { - priv f: &'self fn(&mut St) -> Option, - state: St -} - -pub impl<'self, A, St> UnfoldrIterator<'self, A, St> { - #[inline] - fn new(f: &'self fn(&mut St) -> Option, initial_state: St) - -> UnfoldrIterator<'self, A, St> { - UnfoldrIterator { - f: f, - state: initial_state - } - } -} - -impl<'self, A, St> Iterator for UnfoldrIterator<'self, A, St> { - #[inline] - fn next(&mut self) -> Option { - (self.f)(&mut self.state) - } -} - -/// An infinite iterator starting at `start` and advancing by `step` with each iteration -pub struct Counter { - state: A, - step: A -} - -pub impl Counter { - #[inline(always)] - fn new(start: A, step: A) -> Counter { - Counter{state: start, step: step} - } -} - -impl + Clone> Iterator for Counter { - #[inline(always)] - fn next(&mut self) -> Option { - let result = self.state.clone(); - self.state = self.state.add(&self.step); // FIXME: #6050 - Some(result) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use prelude::*; - - #[test] - fn test_counter_to_vec() { - let mut it = Counter::new(0, 5).take(10); - let xs = iter::to_vec(|f| it.advance(f)); - assert_eq!(xs, ~[0, 5, 10, 15, 20, 25, 30, 35, 40, 45]); - } - - #[test] - fn test_iterator_chain() { - let xs = [0u, 1, 2, 3, 4, 5]; - let ys = [30u, 40, 50, 60]; - let expected = [0, 1, 2, 3, 4, 5, 30, 40, 50, 60]; - let mut it = xs.iter().chain(ys.iter()); - let mut i = 0; - for it.advance |&x: &uint| { - assert_eq!(x, expected[i]); - i += 1; - } - assert_eq!(i, expected.len()); - - let ys = Counter::new(30u, 10).take(4); - let mut it = xs.iter().transform(|&x| x).chain(ys); - let mut i = 0; - for it.advance |x: uint| { - assert_eq!(x, expected[i]); - i += 1; - } - assert_eq!(i, expected.len()); - } - - #[test] - fn test_iterator_enumerate() { - let xs = [0u, 1, 2, 3, 4, 5]; - let mut it = xs.iter().enumerate(); - for it.advance |(i, &x): (uint, &uint)| { - assert_eq!(i, x); - } - } - - #[test] - fn test_iterator_take_while() { - let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19]; - let ys = [0u, 1, 2, 3, 5, 13]; - let mut it = xs.iter().take_while(|&x| *x < 15u); - let mut i = 0; - for it.advance |&x: &uint| { - assert_eq!(x, ys[i]); - i += 1; - } - assert_eq!(i, ys.len()); - } - - #[test] - fn test_iterator_skip_while() { - let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19]; - let ys = [15, 16, 17, 19]; - let mut it = xs.iter().skip_while(|&x| *x < 15u); - let mut i = 0; - for it.advance |&x: &uint| { - assert_eq!(x, ys[i]); - i += 1; - } - assert_eq!(i, ys.len()); - } - - #[test] - fn test_iterator_skip() { - let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30]; - let ys = [13, 15, 16, 17, 19, 20, 30]; - let mut it = xs.iter().skip(5); - let mut i = 0; - for it.advance |&x: &uint| { - assert_eq!(x, ys[i]); - i += 1; - } - assert_eq!(i, ys.len()); - } - - #[test] - fn test_iterator_take() { - let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19]; - let ys = [0u, 1, 2, 3, 5]; - let mut it = xs.iter().take(5); - let mut i = 0; - for it.advance |&x: &uint| { - assert_eq!(x, ys[i]); - i += 1; - } - assert_eq!(i, ys.len()); - } - - #[test] - fn test_iterator_scan() { - // test the type inference - fn add(old: &mut int, new: &uint) -> Option { - *old += *new as int; - Some(*old as float) - } - let xs = [0u, 1, 2, 3, 4]; - let ys = [0f, 1f, 3f, 6f, 10f]; - - let mut it = xs.iter().scan(0, add); - let mut i = 0; - for it.advance |x| { - assert_eq!(x, ys[i]); - i += 1; - } - assert_eq!(i, ys.len()); - } - - #[test] - fn test_unfoldr() { - fn count(st: &mut uint) -> Option { - if *st < 10 { - let ret = Some(*st); - *st += 1; - ret - } else { - None - } - } - - let mut it = UnfoldrIterator::new(count, 0); - let mut i = 0; - for it.advance |counted| { - assert_eq!(counted, i); - i += 1; - } - assert_eq!(i, 10); - } -} diff --git a/src/libcore/num/int-template/i16.rs b/src/libcore/num/int-template/i16.rs deleted file mode 100644 index 282633785553b..0000000000000 --- a/src/libcore/num/int-template/i16.rs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Operations and constants for `i16` - -mod inst { - use num::{Primitive, BitCount}; - use unstable::intrinsics; - - pub type T = i16; - pub static bits: uint = ::u16::bits; - - impl Primitive for i16 { - #[inline(always)] - fn bits() -> uint { 16 } - - #[inline(always)] - fn bytes() -> uint { Primitive::bits::() / 8 } - } - - impl BitCount for i16 { - /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic. - #[inline(always)] - fn population_count(&self) -> i16 { unsafe { intrinsics::ctpop16(*self) } } - - /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic. - #[inline(always)] - fn leading_zeros(&self) -> i16 { unsafe { intrinsics::ctlz16(*self) } } - - /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic. - #[inline(always)] - fn trailing_zeros(&self) -> i16 { unsafe { intrinsics::cttz16(*self) } } - } -} diff --git a/src/libcore/num/int-template/i32.rs b/src/libcore/num/int-template/i32.rs deleted file mode 100644 index 959cf8f7d77ca..0000000000000 --- a/src/libcore/num/int-template/i32.rs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Operations and constants for `i32` - -mod inst { - use num::{Primitive, BitCount}; - use unstable::intrinsics; - - pub type T = i32; - pub static bits: uint = ::u32::bits; - - impl Primitive for i32 { - #[inline(always)] - fn bits() -> uint { 32 } - - #[inline(always)] - fn bytes() -> uint { Primitive::bits::() / 8 } - } - - impl BitCount for i32 { - /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic. - #[inline(always)] - fn population_count(&self) -> i32 { unsafe { intrinsics::ctpop32(*self) } } - - /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic. - #[inline(always)] - fn leading_zeros(&self) -> i32 { unsafe { intrinsics::ctlz32(*self) } } - - /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic. - #[inline(always)] - fn trailing_zeros(&self) -> i32 { unsafe { intrinsics::cttz32(*self) } } - } -} diff --git a/src/libcore/num/int-template/i64.rs b/src/libcore/num/int-template/i64.rs deleted file mode 100644 index 3b51c70be12e5..0000000000000 --- a/src/libcore/num/int-template/i64.rs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Operations and constants for `i64` - -mod inst { - use num::{Primitive, BitCount}; - use unstable::intrinsics; - - pub type T = i64; - pub static bits: uint = ::u64::bits; - - impl Primitive for i64 { - #[inline(always)] - fn bits() -> uint { 64 } - - #[inline(always)] - fn bytes() -> uint { Primitive::bits::() / 8 } - } - - impl BitCount for i64 { - /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic. - #[inline(always)] - fn population_count(&self) -> i64 { unsafe { intrinsics::ctpop64(*self) } } - - /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic. - #[inline(always)] - fn leading_zeros(&self) -> i64 { unsafe { intrinsics::ctlz64(*self) } } - - /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic. - #[inline(always)] - fn trailing_zeros(&self) -> i64 { unsafe { intrinsics::cttz64(*self) } } - } -} diff --git a/src/libcore/num/int-template/i8.rs b/src/libcore/num/int-template/i8.rs deleted file mode 100644 index 896fb4dbf50f8..0000000000000 --- a/src/libcore/num/int-template/i8.rs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Operations and constants for `i8` - -mod inst { - use num::{Primitive, BitCount}; - use unstable::intrinsics; - - pub type T = i8; - pub static bits: uint = ::u8::bits; - - impl Primitive for i8 { - #[inline(always)] - fn bits() -> uint { 8 } - - #[inline(always)] - fn bytes() -> uint { Primitive::bits::() / 8 } - } - - impl BitCount for i8 { - /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic. - #[inline(always)] - fn population_count(&self) -> i8 { unsafe { intrinsics::ctpop8(*self) } } - - /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic. - #[inline(always)] - fn leading_zeros(&self) -> i8 { unsafe { intrinsics::ctlz8(*self) } } - - /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic. - #[inline(always)] - fn trailing_zeros(&self) -> i8 { unsafe { intrinsics::cttz8(*self) } } - } -} diff --git a/src/libcore/num/int-template/int.rs b/src/libcore/num/int-template/int.rs deleted file mode 100644 index 7a44bfdf16038..0000000000000 --- a/src/libcore/num/int-template/int.rs +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Operations and constants for `int` - -pub use self::inst::pow; - -mod inst { - use num::{Primitive, BitCount}; - - pub type T = int; - pub static bits: uint = ::uint::bits; - - impl Primitive for int { - #[cfg(target_word_size = "32")] - #[inline(always)] - fn bits() -> uint { 32 } - - #[cfg(target_word_size = "64")] - #[inline(always)] - fn bits() -> uint { 64 } - - #[inline(always)] - fn bytes() -> uint { Primitive::bits::() / 8 } - } - - #[cfg(target_word_size = "32")] - #[inline(always)] - impl BitCount for int { - /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic. - #[inline(always)] - fn population_count(&self) -> int { (*self as i32).population_count() as int } - - /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic. - #[inline(always)] - fn leading_zeros(&self) -> int { (*self as i32).leading_zeros() as int } - - /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic. - #[inline(always)] - fn trailing_zeros(&self) -> int { (*self as i32).trailing_zeros() as int } - } - - #[cfg(target_word_size = "64")] - #[inline(always)] - impl BitCount for int { - /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic. - #[inline(always)] - fn population_count(&self) -> int { (*self as i64).population_count() as int } - - /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic. - #[inline(always)] - fn leading_zeros(&self) -> int { (*self as i64).leading_zeros() as int } - - /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic. - #[inline(always)] - fn trailing_zeros(&self) -> int { (*self as i64).trailing_zeros() as int } - } - - /// Returns `base` raised to the power of `exponent` - pub fn pow(base: int, exponent: uint) -> int { - if exponent == 0u { - //Not mathemtically true if ~[base == 0] - return 1; - } - if base == 0 { return 0; } - let mut my_pow = exponent; - let mut acc = 1; - let mut multiplier = base; - while(my_pow > 0u) { - if my_pow % 2u == 1u { - acc *= multiplier; - } - my_pow /= 2u; - multiplier *= multiplier; - } - return acc; - } - - #[test] - fn test_pow() { - assert!((pow(0, 0u) == 1)); - assert!((pow(0, 1u) == 0)); - assert!((pow(0, 2u) == 0)); - assert!((pow(-1, 0u) == 1)); - assert!((pow(1, 0u) == 1)); - assert!((pow(-3, 2u) == 9)); - assert!((pow(-3, 3u) == -27)); - assert!((pow(4, 9u) == 262144)); - } - - #[test] - fn test_overflows() { - assert!((::int::max_value > 0)); - assert!((::int::min_value <= 0)); - assert!((::int::min_value + ::int::max_value + 1 == 0)); - } -} diff --git a/src/libcore/num/uint-template.rs b/src/libcore/num/uint-template.rs deleted file mode 100644 index da0815c264b06..0000000000000 --- a/src/libcore/num/uint-template.rs +++ /dev/null @@ -1,658 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use T = self::inst::T; -use T_SIGNED = self::inst::T_SIGNED; - -use num::{ToStrRadix, FromStrRadix}; -use num::{Zero, One, strconv}; -use prelude::*; - -pub use cmp::{min, max}; - -pub static bits : uint = inst::bits; -pub static bytes : uint = (inst::bits / 8); - -pub static min_value: T = 0 as T; -pub static max_value: T = 0 as T - 1 as T; - -#[inline(always)] -pub fn add(x: T, y: T) -> T { x + y } -#[inline(always)] -pub fn sub(x: T, y: T) -> T { x - y } -#[inline(always)] -pub fn mul(x: T, y: T) -> T { x * y } -#[inline(always)] -pub fn div(x: T, y: T) -> T { x / y } -#[inline(always)] -pub fn rem(x: T, y: T) -> T { x % y } - -#[inline(always)] -pub fn lt(x: T, y: T) -> bool { x < y } -#[inline(always)] -pub fn le(x: T, y: T) -> bool { x <= y } -#[inline(always)] -pub fn eq(x: T, y: T) -> bool { x == y } -#[inline(always)] -pub fn ne(x: T, y: T) -> bool { x != y } -#[inline(always)] -pub fn ge(x: T, y: T) -> bool { x >= y } -#[inline(always)] -pub fn gt(x: T, y: T) -> bool { x > y } - -#[inline(always)] -/// -/// Iterate over the range [`start`,`start`+`step`..`stop`) -/// -pub fn _range_step(start: T, - stop: T, - step: T_SIGNED, - it: &fn(T) -> bool) -> bool { - let mut i = start; - if step == 0 { - fail!("range_step called with step == 0"); - } - if step >= 0 { - while i < stop { - if !it(i) { return false; } - // avoiding overflow. break if i + step > max_value - if i > max_value - (step as T) { return true; } - i += step as T; - } - } else { - while i > stop { - if !it(i) { return false; } - // avoiding underflow. break if i + step < min_value - if i < min_value + ((-step) as T) { return true; } - i -= -step as T; - } - } - return true; -} - -#[cfg(stage0)] -pub fn range_step(start: T, stop: T, step: T_SIGNED, it: &fn(T) -> bool) { - _range_step(start, stop, step, it); -} -#[cfg(not(stage0))] -pub fn range_step(start: T, stop: T, step: T_SIGNED, it: &fn(T) -> bool) -> bool { - _range_step(start, stop, step, it) -} - -#[inline(always)] -#[cfg(stage0)] -/// Iterate over the range [`lo`..`hi`) -pub fn range(lo: T, hi: T, it: &fn(T) -> bool) { - range_step(lo, hi, 1 as T_SIGNED, it); -} - -#[inline(always)] -#[cfg(not(stage0))] -/// Iterate over the range [`lo`..`hi`) -pub fn range(lo: T, hi: T, it: &fn(T) -> bool) -> bool { - range_step(lo, hi, 1 as T_SIGNED, it) -} - -#[inline(always)] -#[cfg(stage0)] -/// Iterate over the range [`hi`..`lo`) -pub fn range_rev(hi: T, lo: T, it: &fn(T) -> bool) { - range_step(hi, lo, -1 as T_SIGNED, it); -} - -#[inline(always)] -#[cfg(not(stage0))] -/// Iterate over the range [`hi`..`lo`) -pub fn range_rev(hi: T, lo: T, it: &fn(T) -> bool) -> bool { - range_step(hi, lo, -1 as T_SIGNED, it) -} - -/// Computes the bitwise complement -#[inline(always)] -pub fn compl(i: T) -> T { - max_value ^ i -} - -impl Num for T {} - -#[cfg(not(test))] -impl Ord for T { - #[inline(always)] - fn lt(&self, other: &T) -> bool { (*self) < (*other) } - #[inline(always)] - fn le(&self, other: &T) -> bool { (*self) <= (*other) } - #[inline(always)] - fn ge(&self, other: &T) -> bool { (*self) >= (*other) } - #[inline(always)] - fn gt(&self, other: &T) -> bool { (*self) > (*other) } -} - -#[cfg(not(test))] -impl Eq for T { - #[inline(always)] - fn eq(&self, other: &T) -> bool { return (*self) == (*other); } - #[inline(always)] - fn ne(&self, other: &T) -> bool { return (*self) != (*other); } -} - -impl Orderable for T { - #[inline(always)] - fn min(&self, other: &T) -> T { - if *self < *other { *self } else { *other } - } - - #[inline(always)] - fn max(&self, other: &T) -> T { - if *self > *other { *self } else { *other } - } - - #[inline(always)] - fn clamp(&self, mn: &T, mx: &T) -> T { - if *self > *mx { *mx } else - if *self < *mn { *mn } else { *self } - } -} - -impl Zero for T { - #[inline(always)] - fn zero() -> T { 0 } - - #[inline(always)] - fn is_zero(&self) -> bool { *self == 0 } -} - -impl One for T { - #[inline(always)] - fn one() -> T { 1 } -} - -#[cfg(not(test))] -impl Add for T { - #[inline(always)] - fn add(&self, other: &T) -> T { *self + *other } -} - -#[cfg(not(test))] -impl Sub for T { - #[inline(always)] - fn sub(&self, other: &T) -> T { *self - *other } -} - -#[cfg(not(test))] -impl Mul for T { - #[inline(always)] - fn mul(&self, other: &T) -> T { *self * *other } -} - -#[cfg(not(test))] -impl Div for T { - #[inline(always)] - fn div(&self, other: &T) -> T { *self / *other } -} - -#[cfg(not(test))] -impl Rem for T { - #[inline(always)] - fn rem(&self, other: &T) -> T { *self % *other } -} - -#[cfg(not(test))] -impl Neg for T { - #[inline(always)] - fn neg(&self) -> T { -*self } -} - -impl Unsigned for T {} - -impl Integer for T { - /// Calculates `div` (`\`) and `rem` (`%`) simultaneously - #[inline(always)] - fn div_rem(&self, other: &T) -> (T,T) { - (*self / *other, *self % *other) - } - - /// Unsigned integer division. Returns the same result as `div` (`/`). - #[inline(always)] - fn div_floor(&self, other: &T) -> T { *self / *other } - - /// Unsigned integer modulo operation. Returns the same result as `rem` (`%`). - #[inline(always)] - fn mod_floor(&self, other: &T) -> T { *self / *other } - - /// Calculates `div_floor` and `modulo_floor` simultaneously - #[inline(always)] - fn div_mod_floor(&self, other: &T) -> (T,T) { - (*self / *other, *self % *other) - } - - /// Calculates the Greatest Common Divisor (GCD) of the number and `other` - #[inline(always)] - fn gcd(&self, other: &T) -> T { - // Use Euclid's algorithm - let mut m = *self, n = *other; - while m != 0 { - let temp = m; - m = n % temp; - n = temp; - } - n - } - - /// Calculates the Lowest Common Multiple (LCM) of the number and `other` - #[inline(always)] - fn lcm(&self, other: &T) -> T { - (*self * *other) / self.gcd(other) - } - - /// Returns `true` if the number can be divided by `other` without leaving a remainder - #[inline(always)] - fn is_multiple_of(&self, other: &T) -> bool { *self % *other == 0 } - - /// Returns `true` if the number is divisible by `2` - #[inline(always)] - fn is_even(&self) -> bool { self.is_multiple_of(&2) } - - /// Returns `true` if the number is not divisible by `2` - #[inline(always)] - fn is_odd(&self) -> bool { !self.is_even() } -} - -impl Bitwise for T {} - -#[cfg(not(test))] -impl BitOr for T { - #[inline(always)] - fn bitor(&self, other: &T) -> T { *self | *other } -} - -#[cfg(not(test))] -impl BitAnd for T { - #[inline(always)] - fn bitand(&self, other: &T) -> T { *self & *other } -} - -#[cfg(not(test))] -impl BitXor for T { - #[inline(always)] - fn bitxor(&self, other: &T) -> T { *self ^ *other } -} - -#[cfg(not(test))] -impl Shl for T { - #[inline(always)] - fn shl(&self, other: &T) -> T { *self << *other } -} - -#[cfg(not(test))] -impl Shr for T { - #[inline(always)] - fn shr(&self, other: &T) -> T { *self >> *other } -} - -#[cfg(not(test))] -impl Not for T { - #[inline(always)] - fn not(&self) -> T { !*self } -} - -impl Bounded for T { - #[inline(always)] - fn min_value() -> T { min_value } - - #[inline(always)] - fn max_value() -> T { max_value } -} - -impl Int for T {} - -// String conversion functions and impl str -> num - -/// Parse a string as a number in base 10. -#[inline(always)] -pub fn from_str(s: &str) -> Option { - strconv::from_str_common(s, 10u, false, false, false, - strconv::ExpNone, false, false) -} - -/// Parse a string as a number in the given base. -#[inline(always)] -pub fn from_str_radix(s: &str, radix: uint) -> Option { - strconv::from_str_common(s, radix, false, false, false, - strconv::ExpNone, false, false) -} - -/// Parse a byte slice as a number in the given base. -#[inline(always)] -pub fn parse_bytes(buf: &[u8], radix: uint) -> Option { - strconv::from_str_bytes_common(buf, radix, false, false, false, - strconv::ExpNone, false, false) -} - -impl FromStr for T { - #[inline(always)] - fn from_str(s: &str) -> Option { - from_str(s) - } -} - -impl FromStrRadix for T { - #[inline(always)] - fn from_str_radix(s: &str, radix: uint) -> Option { - from_str_radix(s, radix) - } -} - -// String conversion functions and impl num -> str - -/// Convert to a string as a byte slice in a given base. -#[inline(always)] -pub fn to_str_bytes(n: T, radix: uint, f: &fn(v: &[u8]) -> U) -> U { - let (buf, _) = strconv::to_str_bytes_common(&n, radix, false, - strconv::SignNeg, strconv::DigAll); - f(buf) -} - -/// Convert to a string in base 10. -#[inline(always)] -pub fn to_str(num: T) -> ~str { - let (buf, _) = strconv::to_str_common(&num, 10u, false, - strconv::SignNeg, strconv::DigAll); - buf -} - -/// Convert to a string in a given base. -#[inline(always)] -pub fn to_str_radix(num: T, radix: uint) -> ~str { - let (buf, _) = strconv::to_str_common(&num, radix, false, - strconv::SignNeg, strconv::DigAll); - buf -} - -impl ToStr for T { - #[inline(always)] - fn to_str(&self) -> ~str { - to_str(*self) - } -} - -impl ToStrRadix for T { - #[inline(always)] - fn to_str_radix(&self, radix: uint) -> ~str { - to_str_radix(*self, radix) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use super::inst::T; - use prelude::*; - - #[test] - fn test_num() { - num::test_num(10 as T, 2 as T); - } - - #[test] - fn test_orderable() { - assert_eq!((1 as T).min(&(2 as T)), 1 as T); - assert_eq!((2 as T).min(&(1 as T)), 1 as T); - assert_eq!((1 as T).max(&(2 as T)), 2 as T); - assert_eq!((2 as T).max(&(1 as T)), 2 as T); - assert_eq!((1 as T).clamp(&(2 as T), &(4 as T)), 2 as T); - assert_eq!((8 as T).clamp(&(2 as T), &(4 as T)), 4 as T); - assert_eq!((3 as T).clamp(&(2 as T), &(4 as T)), 3 as T); - } - - #[test] - fn test_gcd() { - assert_eq!((10 as T).gcd(&2), 2 as T); - assert_eq!((10 as T).gcd(&3), 1 as T); - assert_eq!((0 as T).gcd(&3), 3 as T); - assert_eq!((3 as T).gcd(&3), 3 as T); - assert_eq!((56 as T).gcd(&42), 14 as T); - } - - #[test] - fn test_lcm() { - assert_eq!((1 as T).lcm(&0), 0 as T); - assert_eq!((0 as T).lcm(&1), 0 as T); - assert_eq!((1 as T).lcm(&1), 1 as T); - assert_eq!((8 as T).lcm(&9), 72 as T); - assert_eq!((11 as T).lcm(&5), 55 as T); - assert_eq!((99 as T).lcm(&17), 1683 as T); - } - - #[test] - fn test_multiple_of() { - assert!((6 as T).is_multiple_of(&(6 as T))); - assert!((6 as T).is_multiple_of(&(3 as T))); - assert!((6 as T).is_multiple_of(&(1 as T))); - } - - #[test] - fn test_even() { - assert_eq!((0 as T).is_even(), true); - assert_eq!((1 as T).is_even(), false); - assert_eq!((2 as T).is_even(), true); - assert_eq!((3 as T).is_even(), false); - assert_eq!((4 as T).is_even(), true); - } - - #[test] - fn test_odd() { - assert_eq!((0 as T).is_odd(), false); - assert_eq!((1 as T).is_odd(), true); - assert_eq!((2 as T).is_odd(), false); - assert_eq!((3 as T).is_odd(), true); - assert_eq!((4 as T).is_odd(), false); - } - - #[test] - fn test_bitwise() { - assert_eq!(0b1110 as T, (0b1100 as T).bitor(&(0b1010 as T))); - assert_eq!(0b1000 as T, (0b1100 as T).bitand(&(0b1010 as T))); - assert_eq!(0b0110 as T, (0b1100 as T).bitxor(&(0b1010 as T))); - assert_eq!(0b1110 as T, (0b0111 as T).shl(&(1 as T))); - assert_eq!(0b0111 as T, (0b1110 as T).shr(&(1 as T))); - assert_eq!(max_value - (0b1011 as T), (0b1011 as T).not()); - } - - #[test] - fn test_bitcount() { - assert_eq!((0b010101 as T).population_count(), 3); - } - - #[test] - fn test_primitive() { - assert_eq!(Primitive::bits::(), sys::size_of::() * 8); - assert_eq!(Primitive::bytes::(), sys::size_of::()); - } - - #[test] - pub fn test_to_str() { - assert_eq!(to_str_radix(0 as T, 10u), ~"0"); - assert_eq!(to_str_radix(1 as T, 10u), ~"1"); - assert_eq!(to_str_radix(2 as T, 10u), ~"2"); - assert_eq!(to_str_radix(11 as T, 10u), ~"11"); - assert_eq!(to_str_radix(11 as T, 16u), ~"b"); - assert_eq!(to_str_radix(255 as T, 16u), ~"ff"); - assert_eq!(to_str_radix(0xff as T, 10u), ~"255"); - } - - #[test] - pub fn test_from_str() { - assert_eq!(from_str(~"0"), Some(0u as T)); - assert_eq!(from_str(~"3"), Some(3u as T)); - assert_eq!(from_str(~"10"), Some(10u as T)); - assert_eq!(u32::from_str(~"123456789"), Some(123456789 as u32)); - assert_eq!(from_str(~"00100"), Some(100u as T)); - - assert!(from_str(~"").is_none()); - assert!(from_str(~" ").is_none()); - assert!(from_str(~"x").is_none()); - } - - #[test] - pub fn test_parse_bytes() { - use str::to_bytes; - assert_eq!(parse_bytes(to_bytes(~"123"), 10u), Some(123u as T)); - assert_eq!(parse_bytes(to_bytes(~"1001"), 2u), Some(9u as T)); - assert_eq!(parse_bytes(to_bytes(~"123"), 8u), Some(83u as T)); - assert_eq!(u16::parse_bytes(to_bytes(~"123"), 16u), Some(291u as u16)); - assert_eq!(u16::parse_bytes(to_bytes(~"ffff"), 16u), Some(65535u as u16)); - assert_eq!(parse_bytes(to_bytes(~"z"), 36u), Some(35u as T)); - - assert!(parse_bytes(to_bytes(~"Z"), 10u).is_none()); - assert!(parse_bytes(to_bytes(~"_"), 2u).is_none()); - } - - #[test] - fn test_uint_to_str_overflow() { - let mut u8_val: u8 = 255_u8; - assert_eq!(u8::to_str(u8_val), ~"255"); - - u8_val += 1 as u8; - assert_eq!(u8::to_str(u8_val), ~"0"); - - let mut u16_val: u16 = 65_535_u16; - assert_eq!(u16::to_str(u16_val), ~"65535"); - - u16_val += 1 as u16; - assert_eq!(u16::to_str(u16_val), ~"0"); - - let mut u32_val: u32 = 4_294_967_295_u32; - assert_eq!(u32::to_str(u32_val), ~"4294967295"); - - u32_val += 1 as u32; - assert_eq!(u32::to_str(u32_val), ~"0"); - - let mut u64_val: u64 = 18_446_744_073_709_551_615_u64; - assert_eq!(u64::to_str(u64_val), ~"18446744073709551615"); - - u64_val += 1 as u64; - assert_eq!(u64::to_str(u64_val), ~"0"); - } - - #[test] - fn test_uint_from_str_overflow() { - let mut u8_val: u8 = 255_u8; - assert_eq!(u8::from_str(~"255"), Some(u8_val)); - assert!(u8::from_str(~"256").is_none()); - - u8_val += 1 as u8; - assert_eq!(u8::from_str(~"0"), Some(u8_val)); - assert!(u8::from_str(~"-1").is_none()); - - let mut u16_val: u16 = 65_535_u16; - assert_eq!(u16::from_str(~"65535"), Some(u16_val)); - assert!(u16::from_str(~"65536").is_none()); - - u16_val += 1 as u16; - assert_eq!(u16::from_str(~"0"), Some(u16_val)); - assert!(u16::from_str(~"-1").is_none()); - - let mut u32_val: u32 = 4_294_967_295_u32; - assert_eq!(u32::from_str(~"4294967295"), Some(u32_val)); - assert!(u32::from_str(~"4294967296").is_none()); - - u32_val += 1 as u32; - assert_eq!(u32::from_str(~"0"), Some(u32_val)); - assert!(u32::from_str(~"-1").is_none()); - - let mut u64_val: u64 = 18_446_744_073_709_551_615_u64; - assert_eq!(u64::from_str(~"18446744073709551615"), Some(u64_val)); - assert!(u64::from_str(~"18446744073709551616").is_none()); - - u64_val += 1 as u64; - assert_eq!(u64::from_str(~"0"), Some(u64_val)); - assert!(u64::from_str(~"-1").is_none()); - } - - #[test] - #[should_fail] - #[ignore(cfg(windows))] - pub fn to_str_radix1() { - uint::to_str_radix(100u, 1u); - } - - #[test] - #[should_fail] - #[ignore(cfg(windows))] - pub fn to_str_radix37() { - uint::to_str_radix(100u, 37u); - } - - #[test] - pub fn test_ranges() { - let mut l = ~[]; - - for range(0,3) |i| { - l.push(i); - } - for range_rev(13,10) |i| { - l.push(i); - } - for range_step(20,26,2) |i| { - l.push(i); - } - for range_step(36,30,-2) |i| { - l.push(i); - } - for range_step(max_value - 2, max_value, 2) |i| { - l.push(i); - } - for range_step(max_value - 3, max_value, 2) |i| { - l.push(i); - } - for range_step(min_value + 2, min_value, -2) |i| { - l.push(i); - } - for range_step(min_value + 3, min_value, -2) |i| { - l.push(i); - } - - assert_eq!(l, ~[0,1,2, - 13,12,11, - 20,22,24, - 36,34,32, - max_value-2, - max_value-3,max_value-1, - min_value+2, - min_value+3,min_value+1]); - - // None of the `fail`s should execute. - for range(0,0) |_i| { - fail!("unreachable"); - } - for range_rev(0,0) |_i| { - fail!("unreachable"); - } - for range_step(10,0,1) |_i| { - fail!("unreachable"); - } - for range_step(0,1,-10) |_i| { - fail!("unreachable"); - } - } - - #[test] - #[should_fail] - #[ignore(cfg(windows))] - fn test_range_step_zero_step_up() { - for range_step(0,10,0) |_i| {} - } - #[test] - #[should_fail] - #[ignore(cfg(windows))] - fn test_range_step_zero_step_down() { - for range_step(0,-10,0) |_i| {} - } -} diff --git a/src/libcore/num/uint-template/u16.rs b/src/libcore/num/uint-template/u16.rs deleted file mode 100644 index cc262f6b4dee7..0000000000000 --- a/src/libcore/num/uint-template/u16.rs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Operations and constants for `u16` - -mod inst { - use num::{Primitive, BitCount}; - use unstable::intrinsics; - - pub type T = u16; - #[allow(non_camel_case_types)] - pub type T_SIGNED = i16; - pub static bits: uint = 16; - - impl Primitive for u16 { - #[inline(always)] - fn bits() -> uint { 16 } - - #[inline(always)] - fn bytes() -> uint { Primitive::bits::() / 8 } - } - - impl BitCount for u16 { - /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic. - #[inline(always)] - fn population_count(&self) -> u16 { unsafe { intrinsics::ctpop16(*self as i16) as u16 } } - - /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic. - #[inline(always)] - fn leading_zeros(&self) -> u16 { unsafe { intrinsics::ctlz16(*self as i16) as u16 } } - - /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic. - #[inline(always)] - fn trailing_zeros(&self) -> u16 { unsafe { intrinsics::cttz16(*self as i16) as u16 } } - } -} diff --git a/src/libcore/num/uint-template/u32.rs b/src/libcore/num/uint-template/u32.rs deleted file mode 100644 index 7d7c8e3be302e..0000000000000 --- a/src/libcore/num/uint-template/u32.rs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Operations and constants for `u32` - -mod inst { - use num::{Primitive, BitCount}; - use unstable::intrinsics; - - pub type T = u32; - #[allow(non_camel_case_types)] - pub type T_SIGNED = i32; - pub static bits: uint = 32; - - impl Primitive for u32 { - #[inline(always)] - fn bits() -> uint { 32 } - - #[inline(always)] - fn bytes() -> uint { Primitive::bits::() / 8 } - } - - impl BitCount for u32 { - /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic. - #[inline(always)] - fn population_count(&self) -> u32 { unsafe { intrinsics::ctpop32(*self as i32) as u32 } } - - /// Counts the number of leading zeros. Wraps LLVM's `ctlp` intrinsic. - #[inline(always)] - fn leading_zeros(&self) -> u32 { unsafe { intrinsics::ctlz32(*self as i32) as u32 } } - - /// Counts the number of trailing zeros. Wraps LLVM's `cttp` intrinsic. - #[inline(always)] - fn trailing_zeros(&self) -> u32 { unsafe { intrinsics::cttz32(*self as i32) as u32 } } - } -} diff --git a/src/libcore/num/uint-template/u64.rs b/src/libcore/num/uint-template/u64.rs deleted file mode 100644 index 756c29950c35b..0000000000000 --- a/src/libcore/num/uint-template/u64.rs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Operations and constants for `u64` - -mod inst { - use num::{Primitive, BitCount}; - use unstable::intrinsics; - - pub type T = u64; - #[allow(non_camel_case_types)] - pub type T_SIGNED = i64; - pub static bits: uint = 64; - - impl Primitive for u64 { - #[inline(always)] - fn bits() -> uint { 64 } - - #[inline(always)] - fn bytes() -> uint { Primitive::bits::() / 8 } - } - - impl BitCount for u64 { - /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic. - #[inline(always)] - fn population_count(&self) -> u64 { unsafe { intrinsics::ctpop64(*self as i64) as u64 } } - - /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic. - #[inline(always)] - fn leading_zeros(&self) -> u64 { unsafe { intrinsics::ctlz64(*self as i64) as u64 } } - - /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic. - #[inline(always)] - fn trailing_zeros(&self) -> u64 { unsafe { intrinsics::cttz64(*self as i64) as u64 } } - } -} diff --git a/src/libcore/num/uint-template/u8.rs b/src/libcore/num/uint-template/u8.rs deleted file mode 100644 index 5ac860c0359c5..0000000000000 --- a/src/libcore/num/uint-template/u8.rs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Operations and constants for `u8` - -mod inst { - use num::{Primitive, BitCount}; - use unstable::intrinsics; - - pub type T = u8; - #[allow(non_camel_case_types)] - pub type T_SIGNED = i8; - pub static bits: uint = 8; - - impl Primitive for u8 { - #[inline(always)] - fn bits() -> uint { 8 } - - #[inline(always)] - fn bytes() -> uint { Primitive::bits::() / 8 } - } - - impl BitCount for u8 { - /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic. - #[inline(always)] - fn population_count(&self) -> u8 { unsafe { intrinsics::ctpop8(*self as i8) as u8 } } - - /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic. - #[inline(always)] - fn leading_zeros(&self) -> u8 { unsafe { intrinsics::ctlz8(*self as i8) as u8 } } - - /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic. - #[inline(always)] - fn trailing_zeros(&self) -> u8 { unsafe { intrinsics::cttz8(*self as i8) as u8 } } - } -} diff --git a/src/libcore/num/uint-template/uint.rs b/src/libcore/num/uint-template/uint.rs deleted file mode 100644 index d8a4ec19304f3..0000000000000 --- a/src/libcore/num/uint-template/uint.rs +++ /dev/null @@ -1,279 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Operations and constants for `uint` - -pub use self::inst::{ - div_ceil, div_round, div_floor, iterate, - next_power_of_two -}; - -pub mod inst { - use iter; - use num::{Primitive, BitCount}; - use sys; - - pub type T = uint; - #[allow(non_camel_case_types)] - pub type T_SIGNED = int; - - #[cfg(target_arch = "x86")] - #[cfg(target_arch = "arm")] - #[cfg(target_arch = "mips")] - pub static bits: uint = 32; - - #[cfg(target_arch = "x86_64")] - pub static bits: uint = 64; - - impl Primitive for uint { - #[cfg(target_word_size = "32")] - #[inline(always)] - fn bits() -> uint { 32 } - - #[cfg(target_word_size = "64")] - #[inline(always)] - fn bits() -> uint { 64 } - - #[inline(always)] - fn bytes() -> uint { Primitive::bits::() / 8 } - } - - #[cfg(target_word_size = "32")] - #[inline(always)] - impl BitCount for uint { - /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic. - #[inline(always)] - fn population_count(&self) -> uint { (*self as i32).population_count() as uint } - - /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic. - #[inline(always)] - fn leading_zeros(&self) -> uint { (*self as i32).leading_zeros() as uint } - - /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic. - #[inline(always)] - fn trailing_zeros(&self) -> uint { (*self as i32).trailing_zeros() as uint } - } - - #[cfg(target_word_size = "64")] - #[inline(always)] - impl BitCount for uint { - /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic. - #[inline(always)] - fn population_count(&self) -> uint { (*self as i64).population_count() as uint } - - /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic. - #[inline(always)] - fn leading_zeros(&self) -> uint { (*self as i64).leading_zeros() as uint } - - /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic. - #[inline(always)] - fn trailing_zeros(&self) -> uint { (*self as i64).trailing_zeros() as uint } - } - - /// - /// Divide two numbers, return the result, rounded up. - /// - /// # Arguments - /// - /// * x - an integer - /// * y - an integer distinct from 0u - /// - /// # Return value - /// - /// The smallest integer `q` such that `x/y <= q`. - /// - pub fn div_ceil(x: uint, y: uint) -> uint { - let div = x / y; - if x % y == 0u { div } - else { div + 1u } - } - - /// - /// Divide two numbers, return the result, rounded to the closest integer. - /// - /// # Arguments - /// - /// * x - an integer - /// * y - an integer distinct from 0u - /// - /// # Return value - /// - /// The integer `q` closest to `x/y`. - /// - pub fn div_round(x: uint, y: uint) -> uint { - let div = x / y; - if x % y * 2u < y { div } - else { div + 1u } - } - - /// - /// Divide two numbers, return the result, rounded down. - /// - /// Note: This is the same function as `div`. - /// - /// # Arguments - /// - /// * x - an integer - /// * y - an integer distinct from 0u - /// - /// # Return value - /// - /// The smallest integer `q` such that `x/y <= q`. This - /// is either `x/y` or `x/y + 1`. - /// - pub fn div_floor(x: uint, y: uint) -> uint { return x / y; } - - /// - /// Iterate over the range [`lo`..`hi`), or stop when requested - /// - /// # Arguments - /// - /// * lo - The integer at which to start the loop (included) - /// * hi - The integer at which to stop the loop (excluded) - /// * it - A block to execute with each consecutive integer of the range. - /// Return `true` to continue, `false` to stop. - /// - /// # Return value - /// - /// `true` If execution proceeded correctly, `false` if it was interrupted, - /// that is if `it` returned `false` at any point. - /// - pub fn iterate(lo: uint, hi: uint, it: &fn(uint) -> bool) -> bool { - let mut i = lo; - while i < hi { - if (!it(i)) { return false; } - i += 1u; - } - return true; - } - - #[cfg(stage0)] - impl iter::Times for uint { - #[inline(always)] - /// - /// A convenience form for basic iteration. Given a uint `x`, - /// `for x.times { ... }` executes the given block x times. - /// - /// Equivalent to `for uint::range(0, x) |_| { ... }`. - /// - /// Not defined on all integer types to permit unambiguous - /// use with integer literals of inferred integer-type as - /// the self-value (eg. `for 100.times { ... }`). - /// - fn times(&self, it: &fn() -> bool) { - let mut i = *self; - while i > 0 { - if !it() { break } - i -= 1; - } - } - } - - #[cfg(not(stage0))] - impl iter::Times for uint { - #[inline(always)] - /// - /// A convenience form for basic iteration. Given a uint `x`, - /// `for x.times { ... }` executes the given block x times. - /// - /// Equivalent to `for uint::range(0, x) |_| { ... }`. - /// - /// Not defined on all integer types to permit unambiguous - /// use with integer literals of inferred integer-type as - /// the self-value (eg. `for 100.times { ... }`). - /// - fn times(&self, it: &fn() -> bool) -> bool { - let mut i = *self; - while i > 0 { - if !it() { return false; } - i -= 1; - } - return true; - } - } - - /// Returns the smallest power of 2 greater than or equal to `n` - #[inline(always)] - pub fn next_power_of_two(n: uint) -> uint { - let halfbits: uint = sys::size_of::() * 4u; - let mut tmp: uint = n - 1u; - let mut shift: uint = 1u; - while shift <= halfbits { tmp |= tmp >> shift; shift <<= 1u; } - return tmp + 1u; - } - - #[test] - fn test_next_power_of_two() { - assert!((next_power_of_two(0u) == 0u)); - assert!((next_power_of_two(1u) == 1u)); - assert!((next_power_of_two(2u) == 2u)); - assert!((next_power_of_two(3u) == 4u)); - assert!((next_power_of_two(4u) == 4u)); - assert!((next_power_of_two(5u) == 8u)); - assert!((next_power_of_two(6u) == 8u)); - assert!((next_power_of_two(7u) == 8u)); - assert!((next_power_of_two(8u) == 8u)); - assert!((next_power_of_two(9u) == 16u)); - assert!((next_power_of_two(10u) == 16u)); - assert!((next_power_of_two(11u) == 16u)); - assert!((next_power_of_two(12u) == 16u)); - assert!((next_power_of_two(13u) == 16u)); - assert!((next_power_of_two(14u) == 16u)); - assert!((next_power_of_two(15u) == 16u)); - assert!((next_power_of_two(16u) == 16u)); - assert!((next_power_of_two(17u) == 32u)); - assert!((next_power_of_two(18u) == 32u)); - assert!((next_power_of_two(19u) == 32u)); - assert!((next_power_of_two(20u) == 32u)); - assert!((next_power_of_two(21u) == 32u)); - assert!((next_power_of_two(22u) == 32u)); - assert!((next_power_of_two(23u) == 32u)); - assert!((next_power_of_two(24u) == 32u)); - assert!((next_power_of_two(25u) == 32u)); - assert!((next_power_of_two(26u) == 32u)); - assert!((next_power_of_two(27u) == 32u)); - assert!((next_power_of_two(28u) == 32u)); - assert!((next_power_of_two(29u) == 32u)); - assert!((next_power_of_two(30u) == 32u)); - assert!((next_power_of_two(31u) == 32u)); - assert!((next_power_of_two(32u) == 32u)); - assert!((next_power_of_two(33u) == 64u)); - assert!((next_power_of_two(34u) == 64u)); - assert!((next_power_of_two(35u) == 64u)); - assert!((next_power_of_two(36u) == 64u)); - assert!((next_power_of_two(37u) == 64u)); - assert!((next_power_of_two(38u) == 64u)); - assert!((next_power_of_two(39u) == 64u)); - } - - #[test] - fn test_overflows() { - use uint; - assert!((uint::max_value > 0u)); - assert!((uint::min_value <= 0u)); - assert!((uint::min_value + uint::max_value + 1u == 0u)); - } - - #[test] - fn test_div() { - assert!((div_floor(3u, 4u) == 0u)); - assert!((div_ceil(3u, 4u) == 1u)); - assert!((div_round(3u, 4u) == 1u)); - } - - #[test] - pub fn test_times() { - use iter::Times; - let ten = 10 as uint; - let mut accum = 0; - for ten.times { accum += 1; } - assert!((accum == 10)); - } -} diff --git a/src/libcore/rt/io/extensions.rs b/src/libcore/rt/io/extensions.rs deleted file mode 100644 index bb025b0ccb6d5..0000000000000 --- a/src/libcore/rt/io/extensions.rs +++ /dev/null @@ -1,469 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Utility mixins that apply to all Readers and Writers - -// XXX: Not sure how this should be structured -// XXX: Iteration should probably be considered separately - -pub trait ReaderUtil { - - /// Reads `len` bytes and gives you back a new vector - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. Returns an empty - /// vector if the condition is handled. - fn read_bytes(&mut self, len: uint) -> ~[u8]; - - /// Reads all remaining bytes from the stream. - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. Returns an empty - /// vector if the condition is handled. - fn read_to_end(&mut self) -> ~[u8]; - -} - -pub trait ReaderByteConversions { - /// Reads `n` little-endian unsigned integer bytes. - /// - /// `n` must be between 1 and 8, inclusive. - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. Returns `0` if - /// the condition is handled. - fn read_le_uint_n(&mut self, nbytes: uint) -> u64; - - /// Reads `n` little-endian signed integer bytes. - /// - /// `n` must be between 1 and 8, inclusive. - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. Returns `0` if - /// the condition is handled. - fn read_le_int_n(&mut self, nbytes: uint) -> i64; - - /// Reads `n` big-endian unsigned integer bytes. - /// - /// `n` must be between 1 and 8, inclusive. - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. Returns `0` if - /// the condition is handled. - fn read_be_uint_n(&mut self, nbytes: uint) -> u64; - - /// Reads `n` big-endian signed integer bytes. - /// - /// `n` must be between 1 and 8, inclusive. - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. Returns `0` if - /// the condition is handled. - fn read_be_int_n(&mut self, nbytes: uint) -> i64; - - /// Reads a little-endian unsigned integer. - /// - /// The number of bytes returned is system-dependant. - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. Returns `0` if - /// the condition is handled. - fn read_le_uint(&mut self) -> uint; - - /// Reads a little-endian integer. - /// - /// The number of bytes returned is system-dependant. - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. Returns `0` if - /// the condition is handled. - fn read_le_int(&mut self) -> int; - - /// Reads a big-endian unsigned integer. - /// - /// The number of bytes returned is system-dependant. - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. Returns `0` if - /// the condition is handled. - fn read_be_uint(&mut self) -> uint; - - /// Reads a big-endian integer. - /// - /// The number of bytes returned is system-dependant. - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. Returns `0` if - /// the condition is handled. - fn read_be_int(&mut self) -> int; - - /// Reads a big-endian `u64`. - /// - /// `u64`s are 8 bytes long. - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. Returns `0` if - /// the condition is handled. - fn read_be_u64(&mut self) -> u64; - - /// Reads a big-endian `u32`. - /// - /// `u32`s are 4 bytes long. - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. Returns `0` if - /// the condition is handled. - fn read_be_u32(&mut self) -> u32; - - /// Reads a big-endian `u16`. - /// - /// `u16`s are 2 bytes long. - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. Returns `0` if - /// the condition is handled. - fn read_be_u16(&mut self) -> u16; - - /// Reads a big-endian `i64`. - /// - /// `i64`s are 8 bytes long. - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. Returns `0` if - /// the condition is handled. - fn read_be_i64(&mut self) -> i64; - - /// Reads a big-endian `i32`. - /// - /// `i32`s are 4 bytes long. - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. Returns `0` if - /// the condition is handled. - fn read_be_i32(&mut self) -> i32; - - /// Reads a big-endian `i16`. - /// - /// `i16`s are 2 bytes long. - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. Returns `0` if - /// the condition is handled. - fn read_be_i16(&mut self) -> i16; - - /// Reads a big-endian `f64`. - /// - /// `f64`s are 8 byte, IEEE754 double-precision floating point numbers. - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. Returns `0` if - /// the condition is handled. - fn read_be_f64(&mut self) -> f64; - - /// Reads a big-endian `f32`. - /// - /// `f32`s are 4 byte, IEEE754 single-precision floating point numbers. - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. Returns `0` if - /// the condition is handled. - fn read_be_f32(&mut self) -> f32; - - /// Reads a little-endian `u64`. - /// - /// `u64`s are 8 bytes long. - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. Returns `0` if - /// the condition is handled. - fn read_le_u64(&mut self) -> u64; - - /// Reads a little-endian `u32`. - /// - /// `u32`s are 4 bytes long. - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. Returns `0` if - /// the condition is handled. - fn read_le_u32(&mut self) -> u32; - - /// Reads a little-endian `u16`. - /// - /// `u16`s are 2 bytes long. - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. Returns `0` if - /// the condition is handled. - fn read_le_u16(&mut self) -> u16; - - /// Reads a little-endian `i64`. - /// - /// `i64`s are 8 bytes long. - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. Returns `0` if - /// the condition is handled. - fn read_le_i64(&mut self) -> i64; - - /// Reads a little-endian `i32`. - /// - /// `i32`s are 4 bytes long. - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. Returns `0` if - /// the condition is handled. - fn read_le_i32(&mut self) -> i32; - - /// Reads a little-endian `i16`. - /// - /// `i16`s are 2 bytes long. - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. Returns `0` if - /// the condition is handled. - fn read_le_i16(&mut self) -> i16; - - /// Reads a little-endian `f64`. - /// - /// `f64`s are 8 byte, IEEE754 double-precision floating point numbers. - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. Returns `0` if - /// the condition is handled. - fn read_le_f64(&mut self) -> f64; - - /// Reads a little-endian `f32`. - /// - /// `f32`s are 4 byte, IEEE754 single-precision floating point numbers. - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. Returns `0` if - /// the condition is handled. - fn read_le_f32(&mut self) -> f32; - - /// Read a u8. - /// - /// `u8`s are 1 byte. - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. Returns `0` if - /// the condition is handled. - fn read_u8(&mut self) -> u8; - - /// Read an i8. - /// - /// `i8`s are 1 byte. - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. Returns `0` if - /// the condition is handled. - fn read_i8(&mut self) -> i8; - -} - -pub trait WriterByteConversions { - /// Write the result of passing n through `int::to_str_bytes`. - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. - fn write_int(&mut self, n: int); - - /// Write the result of passing n through `uint::to_str_bytes`. - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. - fn write_uint(&mut self, n: uint); - - /// Write a little-endian uint (number of bytes depends on system). - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. - fn write_le_uint(&mut self, n: uint); - - /// Write a little-endian int (number of bytes depends on system). - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. - fn write_le_int(&mut self, n: int); - - /// Write a big-endian uint (number of bytes depends on system). - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. - fn write_be_uint(&mut self, n: uint); - - /// Write a big-endian int (number of bytes depends on system). - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. - fn write_be_int(&mut self, n: int); - - /// Write a big-endian u64 (8 bytes). - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. - fn write_be_u64(&mut self, n: u64); - - /// Write a big-endian u32 (4 bytes). - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. - fn write_be_u32(&mut self, n: u32); - - /// Write a big-endian u16 (2 bytes). - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. - fn write_be_u16(&mut self, n: u16); - - /// Write a big-endian i64 (8 bytes). - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. - fn write_be_i64(&mut self, n: i64); - - /// Write a big-endian i32 (4 bytes). - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. - fn write_be_i32(&mut self, n: i32); - - /// Write a big-endian i16 (2 bytes). - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. - fn write_be_i16(&mut self, n: i16); - - /// Write a big-endian IEEE754 double-precision floating-point (8 bytes). - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. - fn write_be_f64(&mut self, f: f64); - - /// Write a big-endian IEEE754 single-precision floating-point (4 bytes). - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. - fn write_be_f32(&mut self, f: f32); - - /// Write a little-endian u64 (8 bytes). - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. - fn write_le_u64(&mut self, n: u64); - - /// Write a little-endian u32 (4 bytes). - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. - fn write_le_u32(&mut self, n: u32); - - /// Write a little-endian u16 (2 bytes). - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. - fn write_le_u16(&mut self, n: u16); - - /// Write a little-endian i64 (8 bytes). - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. - fn write_le_i64(&mut self, n: i64); - - /// Write a little-endian i32 (4 bytes). - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. - fn write_le_i32(&mut self, n: i32); - - /// Write a little-endian i16 (2 bytes). - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. - fn write_le_i16(&mut self, n: i16); - - /// Write a little-endian IEEE754 double-precision floating-point - /// (8 bytes). - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. - fn write_le_f64(&mut self, f: f64); - - /// Write a litten-endian IEEE754 single-precision floating-point - /// (4 bytes). - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. - fn write_le_f32(&mut self, f: f32); - - /// Write a u8 (1 byte). - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. - fn write_u8(&mut self, n: u8); - - /// Write a i8 (1 byte). - /// - /// # Failure - /// - /// Raises the `io_error` condition on error. - fn write_i8(&mut self, n: i8); -} diff --git a/src/libcore/rt/io/net/tcp.rs b/src/libcore/rt/io/net/tcp.rs deleted file mode 100644 index c95b4344fe75d..0000000000000 --- a/src/libcore/rt/io/net/tcp.rs +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use prelude::*; -use super::super::*; -use super::ip::IpAddr; - -pub struct TcpStream; - -impl TcpStream { - pub fn connect(_addr: IpAddr) -> Option { - fail!() - } -} - -impl Reader for TcpStream { - fn read(&mut self, _buf: &mut [u8]) -> Option { fail!() } - - fn eof(&mut self) -> bool { fail!() } -} - -impl Writer for TcpStream { - fn write(&mut self, _buf: &[u8]) { fail!() } - - fn flush(&mut self) { fail!() } -} - -impl Close for TcpStream { - fn close(&mut self) { fail!() } -} - -pub struct TcpListener; - -impl TcpListener { - pub fn bind(_addr: IpAddr) -> Option { - fail!() - } -} - -impl Listener for TcpListener { - fn accept(&mut self) -> Option { fail!() } -} - -#[cfg(test)] -mod test { - - #[test] #[ignore] - fn smoke_test() { - /*do run_in_newsched_task { - let addr = next_test_ip4(); - - do spawn_immediately { - let listener = TcpListener::bind(addr); - do listener.accept() { - let mut buf = [0]; - listener.read(buf); - assert!(buf[0] == 99); - } - } - - do spawn_immediately { - let stream = TcpStream::connect(addr); - stream.write([99]); - } - }*/ - } -} diff --git a/src/libcore/rt/mod.rs b/src/libcore/rt/mod.rs deleted file mode 100644 index fbbc82743407c..0000000000000 --- a/src/libcore/rt/mod.rs +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/*! The Rust runtime, including the scheduler and I/O interface */ - -#[doc(hidden)]; - -use libc::c_char; -use ptr::Ptr; - -#[path = "sched/mod.rs"] -mod sched; -mod rtio; -pub mod uvll; -mod uvio; -#[path = "uv/mod.rs"] -mod uv; -#[path = "io/mod.rs"] -mod io; -// FIXME #5248: The import in `sched` doesn't resolve unless this is pub! -pub mod thread_local_storage; -mod work_queue; -mod stack; -mod context; -mod thread; -pub mod env; -pub mod local_services; -mod local_heap; - -/// Tools for testing the runtime -#[cfg(test)] -pub mod test; - -pub fn start(main: *u8, _argc: int, _argv: **c_char, _crate_map: *u8) -> int { - - use self::sched::{Scheduler, Task}; - use self::uvio::UvEventLoop; - use sys::Closure; - use ptr; - use cast; - - let loop_ = ~UvEventLoop::new(); - let mut sched = ~Scheduler::new(loop_); - - let main_task = ~do Task::new(&mut sched.stack_pool) { - - unsafe { - // `main` is an `fn() -> ()` that doesn't take an environment - // XXX: Could also call this as an `extern "Rust" fn` once they work - let main = Closure { - code: main as *(), - env: ptr::null(), - }; - let mainfn: &fn() = cast::transmute(main); - - mainfn(); - } - }; - - sched.task_queue.push_back(main_task); - sched.run(); - - return 0; -} - -/// Possible contexts in which Rust code may be executing. -/// Different runtime services are available depending on context. -#[deriving(Eq)] -pub enum RuntimeContext { - // Only the exchange heap is available - GlobalContext, - // The scheduler may be accessed - SchedulerContext, - // Full task services, e.g. local heap, unwinding - TaskContext, - // Running in an old-style task - OldTaskContext -} - -pub fn context() -> RuntimeContext { - - use task::rt::rust_task; - use self::sched::local_sched; - - // XXX: Hitting TLS twice to check if the scheduler exists - // then to check for the task is not good for perf - if unsafe { rust_try_get_task().is_not_null() } { - return OldTaskContext; - } else { - if local_sched::exists() { - let context = ::cell::empty_cell(); - do local_sched::borrow |sched| { - if sched.in_task_context() { - context.put_back(TaskContext); - } else { - context.put_back(SchedulerContext); - } - } - return context.take(); - } else { - return GlobalContext; - } - } - - pub extern { - #[rust_stack] - fn rust_try_get_task() -> *rust_task; - } -} - -#[test] -fn test_context() { - use unstable::run_in_bare_thread; - use self::sched::{local_sched, Task}; - use self::uvio::UvEventLoop; - use cell::Cell; - - assert!(context() == OldTaskContext); - do run_in_bare_thread { - assert!(context() == GlobalContext); - let mut sched = ~UvEventLoop::new_scheduler(); - let task = ~do Task::new(&mut sched.stack_pool) { - assert!(context() == TaskContext); - let sched = local_sched::take(); - do sched.deschedule_running_task_and_then() |task| { - assert!(context() == SchedulerContext); - let task = Cell(task); - do local_sched::borrow |sched| { - sched.task_queue.push_back(task.take()); - } - } - }; - sched.task_queue.push_back(task); - sched.run(); - } -} diff --git a/src/libcore/rt/sched/local_sched.rs b/src/libcore/rt/sched/local_sched.rs deleted file mode 100644 index a7e02f30e0167..0000000000000 --- a/src/libcore/rt/sched/local_sched.rs +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Access to the thread-local Scheduler - -use prelude::*; -use ptr::mut_null; -use libc::c_void; -use cast::transmute; - -use super::Scheduler; -use super::super::rtio::IoFactoryObject; -use tls = super::super::thread_local_storage; -#[cfg(test)] use super::super::uvio::UvEventLoop; - -/// Give the Scheduler to thread-local storage -pub fn put(sched: ~Scheduler) { - unsafe { - let key = tls_key(); - let void_sched: *mut c_void = transmute::<~Scheduler, *mut c_void>(sched); - tls::set(key, void_sched); - } -} - -/// Take ownership of the Scheduler from thread-local storage -pub fn take() -> ~Scheduler { - unsafe { - let key = tls_key(); - let void_sched: *mut c_void = tls::get(key); - assert!(void_sched.is_not_null()); - let sched = transmute::<*mut c_void, ~Scheduler>(void_sched); - tls::set(key, mut_null()); - return sched; - } -} - -/// Check whether there is a thread-local Scheduler attached to the running thread -pub fn exists() -> bool { - unsafe { - match maybe_tls_key() { - Some(key) => tls::get(key).is_not_null(), - None => false - } - } -} - -/// Borrow the thread-local scheduler from thread-local storage. -/// While the scheduler is borrowed it is not available in TLS. -pub fn borrow(f: &fn(&mut Scheduler)) { - let mut sched = take(); - f(sched); - put(sched); -} - -/// Borrow a mutable reference to the thread-local Scheduler -/// -/// # Safety Note -/// -/// Because this leaves the Scheduler in thread-local storage it is possible -/// For the Scheduler pointer to be aliased -pub unsafe fn unsafe_borrow() -> &mut Scheduler { - let key = tls_key(); - let mut void_sched: *mut c_void = tls::get(key); - assert!(void_sched.is_not_null()); - { - let void_sched_ptr = &mut void_sched; - let sched: &mut ~Scheduler = { - transmute::<&mut *mut c_void, &mut ~Scheduler>(void_sched_ptr) - }; - let sched: &mut Scheduler = &mut **sched; - return sched; - } -} - -pub unsafe fn unsafe_borrow_io() -> &mut IoFactoryObject { - let sched = unsafe_borrow(); - return sched.event_loop.io().unwrap(); -} - -fn tls_key() -> tls::Key { - maybe_tls_key().get() -} - -fn maybe_tls_key() -> Option { - unsafe { - let key: *mut c_void = rust_get_sched_tls_key(); - let key: &mut tls::Key = transmute(key); - let key = *key; - // Check that the key has been initialized. - - // NB: This is a little racy because, while the key is - // initalized under a mutex and it's assumed to be initalized - // in the Scheduler ctor by any thread that needs to use it, - // we are not accessing the key under a mutex. Threads that - // are not using the new Scheduler but still *want to check* - // whether they are running under a new Scheduler may see a 0 - // value here that is in the process of being initialized in - // another thread. I think this is fine since the only action - // they could take if it was initialized would be to check the - // thread-local value and see that it's not set. - if key != 0 { - return Some(key); - } else { - return None; - } - } -} - -extern { - fn rust_get_sched_tls_key() -> *mut c_void; -} - -#[test] -fn thread_local_scheduler_smoke_test() { - let scheduler = ~UvEventLoop::new_scheduler(); - put(scheduler); - let _scheduler = take(); -} - -#[test] -fn thread_local_scheduler_two_instances() { - let scheduler = ~UvEventLoop::new_scheduler(); - put(scheduler); - let _scheduler = take(); - let scheduler = ~UvEventLoop::new_scheduler(); - put(scheduler); - let _scheduler = take(); -} - -#[test] -fn borrow_smoke_test() { - let scheduler = ~UvEventLoop::new_scheduler(); - put(scheduler); - unsafe { - let _scheduler = unsafe_borrow(); - } - let _scheduler = take(); -} diff --git a/src/libcore/rt/sched/mod.rs b/src/libcore/rt/sched/mod.rs deleted file mode 100644 index dda1f27550f08..0000000000000 --- a/src/libcore/rt/sched/mod.rs +++ /dev/null @@ -1,497 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use option::*; -use sys; -use cast::transmute; - -use super::work_queue::WorkQueue; -use super::stack::{StackPool, StackSegment}; -use super::rtio::{EventLoop, EventLoopObject}; -use super::context::Context; -use super::local_services::LocalServices; -use cell::Cell; - -#[cfg(test)] use super::uvio::UvEventLoop; -#[cfg(test)] use unstable::run_in_bare_thread; -#[cfg(test)] use int; - -// A more convenient name for external callers, e.g. `local_sched::take()` -pub mod local_sched; - -/// The Scheduler is responsible for coordinating execution of Tasks -/// on a single thread. When the scheduler is running it is owned by -/// thread local storage and the running task is owned by the -/// scheduler. -pub struct Scheduler { - task_queue: WorkQueue<~Task>, - stack_pool: StackPool, - /// The event loop used to drive the scheduler and perform I/O - event_loop: ~EventLoopObject, - /// The scheduler's saved context. - /// Always valid when a task is executing, otherwise not - priv saved_context: Context, - /// The currently executing task - current_task: Option<~Task>, - /// An action performed after a context switch on behalf of the - /// code running before the context switch - priv cleanup_job: Option -} - -// XXX: Some hacks to put a &fn in Scheduler without borrowck -// complaining -type UnsafeTaskReceiver = sys::Closure; -trait ClosureConverter { - fn from_fn(&fn(~Task)) -> Self; - fn to_fn(self) -> &fn(~Task); -} -impl ClosureConverter for UnsafeTaskReceiver { - fn from_fn(f: &fn(~Task)) -> UnsafeTaskReceiver { unsafe { transmute(f) } } - fn to_fn(self) -> &fn(~Task) { unsafe { transmute(self) } } -} - -enum CleanupJob { - DoNothing, - GiveTask(~Task, UnsafeTaskReceiver) -} - -pub impl Scheduler { - - fn in_task_context(&self) -> bool { self.current_task.is_some() } - - fn new(event_loop: ~EventLoopObject) -> Scheduler { - - // Lazily initialize the global state, currently the scheduler TLS key - unsafe { rust_initialize_global_state(); } - extern { - fn rust_initialize_global_state(); - } - - Scheduler { - event_loop: event_loop, - task_queue: WorkQueue::new(), - stack_pool: StackPool::new(), - saved_context: Context::empty(), - current_task: None, - cleanup_job: None - } - } - - // XXX: This may eventually need to be refactored so that - // the scheduler itself doesn't have to call event_loop.run. - // That will be important for embedding the runtime into external - // event loops. - fn run(~self) -> ~Scheduler { - assert!(!self.in_task_context()); - - // Give ownership of the scheduler (self) to the thread - local_sched::put(self); - - unsafe { - let scheduler = local_sched::unsafe_borrow(); - fn run_scheduler_once() { - let scheduler = local_sched::take(); - if scheduler.resume_task_from_queue() { - // Ok, a task ran. Nice! We'll do it again later - do local_sched::borrow |scheduler| { - scheduler.event_loop.callback(run_scheduler_once); - } - } - } - - scheduler.event_loop.callback(run_scheduler_once); - scheduler.event_loop.run(); - } - - return local_sched::take(); - } - - // * Scheduler-context operations - - fn resume_task_from_queue(~self) -> bool { - assert!(!self.in_task_context()); - - let mut this = self; - match this.task_queue.pop_front() { - Some(task) => { - this.resume_task_immediately(task); - return true; - } - None => { - rtdebug!("no tasks in queue"); - local_sched::put(this); - return false; - } - } - } - - // * Task-context operations - - /// Called by a running task to end execution, after which it will - /// be recycled by the scheduler for reuse in a new task. - fn terminate_current_task(~self) { - assert!(self.in_task_context()); - - rtdebug!("ending running task"); - - do self.deschedule_running_task_and_then |dead_task| { - let dead_task = Cell(dead_task); - do local_sched::borrow |sched| { - dead_task.take().recycle(&mut sched.stack_pool); - } - } - - abort!("control reached end of task"); - } - - fn schedule_new_task(~self, task: ~Task) { - assert!(self.in_task_context()); - - do self.switch_running_tasks_and_then(task) |last_task| { - let last_task = Cell(last_task); - do local_sched::borrow |sched| { - sched.task_queue.push_front(last_task.take()); - } - } - } - - // Core scheduling ops - - fn resume_task_immediately(~self, task: ~Task) { - let mut this = self; - assert!(!this.in_task_context()); - - rtdebug!("scheduling a task"); - - // Store the task in the scheduler so it can be grabbed later - this.current_task = Some(task); - this.enqueue_cleanup_job(DoNothing); - - local_sched::put(this); - - // Take pointers to both the task and scheduler's saved registers. - unsafe { - let sched = local_sched::unsafe_borrow(); - let (sched_context, _, next_task_context) = sched.get_contexts(); - let next_task_context = next_task_context.unwrap(); - // Context switch to the task, restoring it's registers - // and saving the scheduler's - Context::swap(sched_context, next_task_context); - - let sched = local_sched::unsafe_borrow(); - // The running task should have passed ownership elsewhere - assert!(sched.current_task.is_none()); - - // Running tasks may have asked us to do some cleanup - sched.run_cleanup_job(); - } - } - - /// Block a running task, context switch to the scheduler, then pass the - /// blocked task to a closure. - /// - /// # Safety note - /// - /// The closure here is a *stack* closure that lives in the - /// running task. It gets transmuted to the scheduler's lifetime - /// and called while the task is blocked. - fn deschedule_running_task_and_then(~self, f: &fn(~Task)) { - let mut this = self; - assert!(this.in_task_context()); - - rtdebug!("blocking task"); - - let blocked_task = this.current_task.swap_unwrap(); - let f_fake_region = unsafe { transmute::<&fn(~Task), &fn(~Task)>(f) }; - let f_opaque = ClosureConverter::from_fn(f_fake_region); - this.enqueue_cleanup_job(GiveTask(blocked_task, f_opaque)); - - local_sched::put(this); - - let sched = unsafe { local_sched::unsafe_borrow() }; - let (sched_context, last_task_context, _) = sched.get_contexts(); - let last_task_context = last_task_context.unwrap(); - Context::swap(last_task_context, sched_context); - - // We could be executing in a different thread now - let sched = unsafe { local_sched::unsafe_borrow() }; - sched.run_cleanup_job(); - } - - /// Switch directly to another task, without going through the scheduler. - /// You would want to think hard about doing this, e.g. if there are - /// pending I/O events it would be a bad idea. - fn switch_running_tasks_and_then(~self, next_task: ~Task, f: &fn(~Task)) { - let mut this = self; - assert!(this.in_task_context()); - - rtdebug!("switching tasks"); - - let old_running_task = this.current_task.swap_unwrap(); - let f_fake_region = unsafe { transmute::<&fn(~Task), &fn(~Task)>(f) }; - let f_opaque = ClosureConverter::from_fn(f_fake_region); - this.enqueue_cleanup_job(GiveTask(old_running_task, f_opaque)); - this.current_task = Some(next_task); - - local_sched::put(this); - - unsafe { - let sched = local_sched::unsafe_borrow(); - let (_, last_task_context, next_task_context) = sched.get_contexts(); - let last_task_context = last_task_context.unwrap(); - let next_task_context = next_task_context.unwrap(); - Context::swap(last_task_context, next_task_context); - - // We could be executing in a different thread now - let sched = local_sched::unsafe_borrow(); - sched.run_cleanup_job(); - } - } - - - - // * Other stuff - - fn enqueue_cleanup_job(&mut self, job: CleanupJob) { - assert!(self.cleanup_job.is_none()); - self.cleanup_job = Some(job); - } - - fn run_cleanup_job(&mut self) { - rtdebug!("running cleanup job"); - - assert!(self.cleanup_job.is_some()); - - let cleanup_job = self.cleanup_job.swap_unwrap(); - match cleanup_job { - DoNothing => { } - GiveTask(task, f) => (f.to_fn())(task) - } - } - - /// Get mutable references to all the contexts that may be involved in a - /// context switch. - /// - /// Returns (the scheduler context, the optional context of the - /// task in the cleanup list, the optional context of the task in - /// the current task slot). When context switching to a task, - /// callers should first arrange for that task to be located in the - /// Scheduler's current_task slot and set up the - /// post-context-switch cleanup job. - fn get_contexts<'a>(&'a mut self) -> (&'a mut Context, - Option<&'a mut Context>, - Option<&'a mut Context>) { - let last_task = match self.cleanup_job { - Some(GiveTask(~ref task, _)) => { - Some(task) - } - Some(DoNothing) => { - None - } - None => fail!("all context switches should have a cleanup job") - }; - // XXX: Pattern matching mutable pointers above doesn't work - // because borrowck thinks the three patterns are conflicting - // borrows - unsafe { - let last_task = transmute::, Option<&mut Task>>(last_task); - let last_task_context = match last_task { - Some(t) => Some(&mut t.saved_context), None => None - }; - let next_task_context = match self.current_task { - Some(ref mut t) => Some(&mut t.saved_context), None => None - }; - // XXX: These transmutes can be removed after snapshot - return (transmute(&mut self.saved_context), - last_task_context, - transmute(next_task_context)); - } - } -} - -static TASK_MIN_STACK_SIZE: uint = 10000000; // XXX: Too much stack - -pub struct Task { - /// The segment of stack on which the task is currently running or, - /// if the task is blocked, on which the task will resume execution - priv current_stack_segment: StackSegment, - /// These are always valid when the task is not running, unless - /// the task is dead - priv saved_context: Context, - /// The heap, GC, unwinding, local storage, logging - local_services: LocalServices -} - -pub impl Task { - fn new(stack_pool: &mut StackPool, start: ~fn()) -> Task { - Task::with_local(stack_pool, LocalServices::new(), start) - } - - fn with_local(stack_pool: &mut StackPool, - local_services: LocalServices, - start: ~fn()) -> Task { - let start = Task::build_start_wrapper(start); - let mut stack = stack_pool.take_segment(TASK_MIN_STACK_SIZE); - // NB: Context holds a pointer to that ~fn - let initial_context = Context::new(start, &mut stack); - return Task { - current_stack_segment: stack, - saved_context: initial_context, - local_services: local_services - }; - } - - priv fn build_start_wrapper(start: ~fn()) -> ~fn() { - // XXX: The old code didn't have this extra allocation - let wrapper: ~fn() = || { - // This is the first code to execute after the initial - // context switch to the task. The previous context may - // have asked us to do some cleanup. - unsafe { - let sched = local_sched::unsafe_borrow(); - sched.run_cleanup_job(); - - let sched = local_sched::unsafe_borrow(); - let task = sched.current_task.get_mut_ref(); - // FIXME #6141: shouldn't neet to put `start()` in another closure - task.local_services.run(||start()); - } - - let sched = local_sched::take(); - sched.terminate_current_task(); - }; - return wrapper; - } - - /// Destroy the task and try to reuse its components - fn recycle(~self, stack_pool: &mut StackPool) { - match self { - ~Task {current_stack_segment, _} => { - stack_pool.give_segment(current_stack_segment); - } - } - } -} - -#[test] -fn test_simple_scheduling() { - do run_in_bare_thread { - let mut task_ran = false; - let task_ran_ptr: *mut bool = &mut task_ran; - - let mut sched = ~UvEventLoop::new_scheduler(); - let task = ~do Task::new(&mut sched.stack_pool) { - unsafe { *task_ran_ptr = true; } - }; - sched.task_queue.push_back(task); - sched.run(); - assert!(task_ran); - } -} - -#[test] -fn test_several_tasks() { - do run_in_bare_thread { - let total = 10; - let mut task_count = 0; - let task_count_ptr: *mut int = &mut task_count; - - let mut sched = ~UvEventLoop::new_scheduler(); - for int::range(0, total) |_| { - let task = ~do Task::new(&mut sched.stack_pool) { - unsafe { *task_count_ptr = *task_count_ptr + 1; } - }; - sched.task_queue.push_back(task); - } - sched.run(); - assert!(task_count == total); - } -} - -#[test] -fn test_swap_tasks_then() { - do run_in_bare_thread { - let mut count = 0; - let count_ptr: *mut int = &mut count; - - let mut sched = ~UvEventLoop::new_scheduler(); - let task1 = ~do Task::new(&mut sched.stack_pool) { - unsafe { *count_ptr = *count_ptr + 1; } - let mut sched = local_sched::take(); - let task2 = ~do Task::new(&mut sched.stack_pool) { - unsafe { *count_ptr = *count_ptr + 1; } - }; - // Context switch directly to the new task - do sched.switch_running_tasks_and_then(task2) |task1| { - let task1 = Cell(task1); - do local_sched::borrow |sched| { - sched.task_queue.push_front(task1.take()); - } - } - unsafe { *count_ptr = *count_ptr + 1; } - }; - sched.task_queue.push_back(task1); - sched.run(); - assert!(count == 3); - } -} - -#[bench] #[test] #[ignore(reason = "long test")] -fn test_run_a_lot_of_tasks_queued() { - do run_in_bare_thread { - static MAX: int = 1000000; - let mut count = 0; - let count_ptr: *mut int = &mut count; - - let mut sched = ~UvEventLoop::new_scheduler(); - - let start_task = ~do Task::new(&mut sched.stack_pool) { - run_task(count_ptr); - }; - sched.task_queue.push_back(start_task); - sched.run(); - - assert!(count == MAX); - - fn run_task(count_ptr: *mut int) { - do local_sched::borrow |sched| { - let task = ~do Task::new(&mut sched.stack_pool) { - unsafe { - *count_ptr = *count_ptr + 1; - if *count_ptr != MAX { - run_task(count_ptr); - } - } - }; - sched.task_queue.push_back(task); - } - }; - } -} - -#[test] -fn test_block_task() { - do run_in_bare_thread { - let mut sched = ~UvEventLoop::new_scheduler(); - let task = ~do Task::new(&mut sched.stack_pool) { - let sched = local_sched::take(); - assert!(sched.in_task_context()); - do sched.deschedule_running_task_and_then() |task| { - let task = Cell(task); - do local_sched::borrow |sched| { - assert!(!sched.in_task_context()); - sched.task_queue.push_back(task.take()); - } - } - }; - sched.task_queue.push_back(task); - sched.run(); - } -} diff --git a/src/libcore/rt/stack.rs b/src/libcore/rt/stack.rs deleted file mode 100644 index 061d7dab9a162..0000000000000 --- a/src/libcore/rt/stack.rs +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use container::Container; -use ptr::Ptr; -use vec; - -pub struct StackSegment { - buf: ~[u8] -} - -pub impl StackSegment { - fn new(size: uint) -> StackSegment { - // Crate a block of uninitialized values - let mut stack = vec::with_capacity(size); - unsafe { - vec::raw::set_len(&mut stack, size); - } - - StackSegment { - buf: stack - } - } - - /// Point one word beyond the high end of the allocated stack - fn end(&self) -> *uint { - vec::raw::to_ptr(self.buf).offset(self.buf.len()) as *uint - } -} - -pub struct StackPool(()); - -impl StackPool { - pub fn new() -> StackPool { StackPool(()) } - - fn take_segment(&self, min_size: uint) -> StackSegment { - StackSegment::new(min_size) - } - - fn give_segment(&self, _stack: StackSegment) { - } -} diff --git a/src/libcore/rt/test.rs b/src/libcore/rt/test.rs deleted file mode 100644 index 0c6843c605d15..0000000000000 --- a/src/libcore/rt/test.rs +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use cell::Cell; -use result::{Result, Ok, Err}; -use super::io::net::ip::{IpAddr, Ipv4}; -use rt::local_services::LocalServices; - -/// Creates a new scheduler in a new thread and runs a task in it, -/// then waits for the scheduler to exit. Failure of the task -/// will abort the process. -pub fn run_in_newsched_task(f: ~fn()) { - use unstable::run_in_bare_thread; - use super::sched::Task; - use super::uvio::UvEventLoop; - - let f = Cell(f); - - do run_in_bare_thread { - let mut sched = ~UvEventLoop::new_scheduler(); - let task = ~Task::with_local(&mut sched.stack_pool, - LocalServices::without_unwinding(), - f.take()); - sched.task_queue.push_back(task); - sched.run(); - } -} - -/// Test tasks will abort on failure instead of unwinding -pub fn spawntask(f: ~fn()) { - use super::sched::*; - - let mut sched = local_sched::take(); - let task = ~Task::with_local(&mut sched.stack_pool, - LocalServices::without_unwinding(), - f); - do sched.switch_running_tasks_and_then(task) |task| { - let task = Cell(task); - let sched = local_sched::take(); - sched.schedule_new_task(task.take()); - } -} - -/// Create a new task and run it right now. Aborts on failure -pub fn spawntask_immediately(f: ~fn()) { - use super::sched::*; - - let mut sched = local_sched::take(); - let task = ~Task::with_local(&mut sched.stack_pool, - LocalServices::without_unwinding(), - f); - do sched.switch_running_tasks_and_then(task) |task| { - let task = Cell(task); - do local_sched::borrow |sched| { - sched.task_queue.push_front(task.take()); - } - } -} - -/// Spawn a task and wait for it to finish, returning whether it completed successfully or failed -pub fn spawntask_try(f: ~fn()) -> Result<(), ()> { - use cell::Cell; - use super::sched::*; - use task; - use unstable::finally::Finally; - - // Our status variables will be filled in from the scheduler context - let mut failed = false; - let failed_ptr: *mut bool = &mut failed; - - // Switch to the scheduler - let f = Cell(Cell(f)); - let sched = local_sched::take(); - do sched.deschedule_running_task_and_then() |old_task| { - let old_task = Cell(old_task); - let f = f.take(); - let mut sched = local_sched::take(); - let new_task = ~do Task::new(&mut sched.stack_pool) { - do (|| { - (f.take())() - }).finally { - // Check for failure then resume the parent task - unsafe { *failed_ptr = task::failing(); } - let sched = local_sched::take(); - do sched.switch_running_tasks_and_then(old_task.take()) |new_task| { - let new_task = Cell(new_task); - do local_sched::borrow |sched| { - sched.task_queue.push_front(new_task.take()); - } - } - } - }; - - sched.resume_task_immediately(new_task); - } - - if !failed { Ok(()) } else { Err(()) } -} - -/// Get a port number, starting at 9600, for use in tests -pub fn next_test_port() -> u16 { - unsafe { - return rust_dbg_next_port() as u16; - } - extern { - fn rust_dbg_next_port() -> ::libc::uintptr_t; - } -} - -/// Get a unique localhost:port pair starting at 9600 -pub fn next_test_ip4() -> IpAddr { - Ipv4(127, 0, 0, 1, next_test_port()) -} diff --git a/src/libcore/rt/work_queue.rs b/src/libcore/rt/work_queue.rs deleted file mode 100644 index 495cd75a0bf8e..0000000000000 --- a/src/libcore/rt/work_queue.rs +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use container::Container; -use option::*; -use vec::OwnedVector; - -pub struct WorkQueue { - priv queue: ~[T] -} - -pub impl WorkQueue { - fn new() -> WorkQueue { - WorkQueue { - queue: ~[] - } - } - - fn push_back(&mut self, value: T) { - self.queue.push(value) - } - - fn pop_back(&mut self) -> Option { - if !self.queue.is_empty() { - Some(self.queue.pop()) - } else { - None - } - } - - fn push_front(&mut self, value: T) { - self.queue.unshift(value) - } - - fn pop_front(&mut self) -> Option { - if !self.queue.is_empty() { - Some(self.queue.shift()) - } else { - None - } - } -} diff --git a/src/libcore/run.rs b/src/libcore/run.rs deleted file mode 100644 index c84e920a17202..0000000000000 --- a/src/libcore/run.rs +++ /dev/null @@ -1,856 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Process spawning -use cast; -use io; -use libc; -use libc::{pid_t, c_void, c_int}; -use comm::{stream, SharedChan, GenericChan, GenericPort}; -use option::{Some, None}; -use os; -use prelude::*; -use ptr; -use str; -use task; -use vec; - -/// A value representing a child process -pub struct Program { - priv pid: pid_t, - priv handle: *(), - priv in_fd: c_int, - priv out_file: *libc::FILE, - priv err_file: *libc::FILE, - priv finished: bool, -} - -impl Drop for Program { - fn finalize(&self) { - // FIXME #4943: transmute is bad. - let mut_self: &mut Program = unsafe { cast::transmute(self) }; - - mut_self.finish(); - mut_self.close_outputs(); - free_handle(self.handle); - } -} - -pub impl Program { - - /// Returns the process id of the program - fn get_id(&mut self) -> pid_t { self.pid } - - /// Returns an io::Writer that can be used to write to stdin - fn input(&mut self) -> @io::Writer { - io::fd_writer(self.in_fd, false) - } - - /// Returns an io::Reader that can be used to read from stdout - fn output(&mut self) -> @io::Reader { - io::FILE_reader(self.out_file, false) - } - - /// Returns an io::Reader that can be used to read from stderr - fn err(&mut self) -> @io::Reader { - io::FILE_reader(self.err_file, false) - } - - /// Closes the handle to the child processes standard input - fn close_input(&mut self) { - let invalid_fd = -1i32; - if self.in_fd != invalid_fd { - unsafe { - libc::close(self.in_fd); - } - self.in_fd = invalid_fd; - } - } - - priv fn close_outputs(&mut self) { - unsafe { - fclose_and_null(&mut self.out_file); - fclose_and_null(&mut self.err_file); - } - } - - /** - * Waits for the child process to terminate. Closes the handle - * to stdin if necessary. - */ - fn finish(&mut self) -> int { - if self.finished { return 0; } - self.finished = true; - self.close_input(); - return waitpid(self.pid); - } - - priv fn destroy_internal(&mut self, force: bool) { - killpid(self.pid, force); - self.finish(); - self.close_outputs(); - - #[cfg(windows)] - fn killpid(pid: pid_t, _force: bool) { - unsafe { - libc::funcs::extra::kernel32::TerminateProcess( - cast::transmute(pid), 1); - } - } - - #[cfg(unix)] - fn killpid(pid: pid_t, force: bool) { - let signal = if force { - libc::consts::os::posix88::SIGKILL - } else { - libc::consts::os::posix88::SIGTERM - }; - - unsafe { - libc::funcs::posix88::signal::kill(pid, signal as c_int); - } - } - } - - /** - * Terminate the program, giving it a chance to clean itself up if - * this is supported by the operating system. - * - * On Posix OSs SIGTERM will be sent to the process. On Win32 - * TerminateProcess(..) will be called. - */ - fn destroy(&mut self) { self.destroy_internal(false); } - - /** - * Terminate the program as soon as possible without giving it a - * chance to clean itself up. - * - * On Posix OSs SIGKILL will be sent to the process. On Win32 - * TerminateProcess(..) will be called. - */ - fn force_destroy(&mut self) { self.destroy_internal(true); } -} - - -/** - * Run a program, providing stdin, stdout and stderr handles - * - * # Arguments - * - * * prog - The path to an executable - * * args - Vector of arguments to pass to the child process - * * env - optional env-modification for child - * * dir - optional dir to run child in (default current dir) - * * in_fd - A file descriptor for the child to use as std input - * * out_fd - A file descriptor for the child to use as std output - * * err_fd - A file descriptor for the child to use as std error - * - * # Return value - * - * The process id of the spawned process - */ -pub fn spawn_process(prog: &str, args: &[~str], - env: &Option<~[(~str,~str)]>, - dir: &Option<~str>, - in_fd: c_int, out_fd: c_int, err_fd: c_int) -> pid_t { - - let res = spawn_process_internal(prog, args, env, dir, in_fd, out_fd, err_fd); - free_handle(res.handle); - return res.pid; -} - -struct RunProgramResult { - // the process id of the program (this should never be negative) - pid: pid_t, - // a handle to the process - on unix this will always be NULL, but on windows it will be a - // HANDLE to the process, which will prevent the pid being re-used until the handle is closed. - handle: *(), -} - -#[cfg(windows)] -fn spawn_process_internal(prog: &str, args: &[~str], - env: &Option<~[(~str,~str)]>, - dir: &Option<~str>, - in_fd: c_int, out_fd: c_int, err_fd: c_int) -> RunProgramResult { - - use libc::types::os::arch::extra::{DWORD, HANDLE, STARTUPINFO}; - use libc::consts::os::extra::{ - TRUE, FALSE, - STARTF_USESTDHANDLES, - INVALID_HANDLE_VALUE, - DUPLICATE_SAME_ACCESS - }; - use libc::funcs::extra::kernel32::{ - GetCurrentProcess, - DuplicateHandle, - CloseHandle, - CreateProcessA - }; - use libc::funcs::extra::msvcrt::get_osfhandle; - - unsafe { - - let mut si = zeroed_startupinfo(); - si.cb = sys::size_of::() as DWORD; - si.dwFlags = STARTF_USESTDHANDLES; - - let cur_proc = GetCurrentProcess(); - - let orig_std_in = get_osfhandle(if in_fd > 0 { in_fd } else { 0 }) as HANDLE; - if orig_std_in == INVALID_HANDLE_VALUE as HANDLE { - fail!("failure in get_osfhandle: %s", os::last_os_error()); - } - if DuplicateHandle(cur_proc, orig_std_in, cur_proc, &mut si.hStdInput, - 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE { - fail!("failure in DuplicateHandle: %s", os::last_os_error()); - } - - let orig_std_out = get_osfhandle(if out_fd > 0 { out_fd } else { 1 }) as HANDLE; - if orig_std_out == INVALID_HANDLE_VALUE as HANDLE { - fail!("failure in get_osfhandle: %s", os::last_os_error()); - } - if DuplicateHandle(cur_proc, orig_std_out, cur_proc, &mut si.hStdOutput, - 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE { - fail!("failure in DuplicateHandle: %s", os::last_os_error()); - } - - let orig_std_err = get_osfhandle(if err_fd > 0 { err_fd } else { 2 }) as HANDLE; - if orig_std_err as HANDLE == INVALID_HANDLE_VALUE as HANDLE { - fail!("failure in get_osfhandle: %s", os::last_os_error()); - } - if DuplicateHandle(cur_proc, orig_std_err, cur_proc, &mut si.hStdError, - 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE { - fail!("failure in DuplicateHandle: %s", os::last_os_error()); - } - - let cmd = make_command_line(prog, args); - let mut pi = zeroed_process_information(); - let mut create_err = None; - - do with_envp(env) |envp| { - do with_dirp(dir) |dirp| { - do str::as_c_str(cmd) |cmdp| { - let created = CreateProcessA(ptr::null(), cast::transmute(cmdp), - ptr::mut_null(), ptr::mut_null(), TRUE, - 0, envp, dirp, &mut si, &mut pi); - if created == FALSE { - create_err = Some(os::last_os_error()); - } - } - } - } - - CloseHandle(si.hStdInput); - CloseHandle(si.hStdOutput); - CloseHandle(si.hStdError); - - for create_err.each |msg| { - fail!("failure in CreateProcess: %s", *msg); - } - - // We close the thread handle because we don't care about keeping the thread id valid, - // and we aren't keeping the thread handle around to be able to close it later. We don't - // close the process handle however because we want the process id to stay valid at least - // until the calling code closes the process handle. - CloseHandle(pi.hThread); - - RunProgramResult { - pid: pi.dwProcessId as pid_t, - handle: pi.hProcess as *() - } - } -} - -#[cfg(windows)] -fn zeroed_startupinfo() -> libc::types::os::arch::extra::STARTUPINFO { - libc::types::os::arch::extra::STARTUPINFO { - cb: 0, - lpReserved: ptr::mut_null(), - lpDesktop: ptr::mut_null(), - lpTitle: ptr::mut_null(), - dwX: 0, - dwY: 0, - dwXSize: 0, - dwYSize: 0, - dwXCountChars: 0, - dwYCountCharts: 0, - dwFillAttribute: 0, - dwFlags: 0, - wShowWindow: 0, - cbReserved2: 0, - lpReserved2: ptr::mut_null(), - hStdInput: ptr::mut_null(), - hStdOutput: ptr::mut_null(), - hStdError: ptr::mut_null() - } -} - -#[cfg(windows)] -fn zeroed_process_information() -> libc::types::os::arch::extra::PROCESS_INFORMATION { - libc::types::os::arch::extra::PROCESS_INFORMATION { - hProcess: ptr::mut_null(), - hThread: ptr::mut_null(), - dwProcessId: 0, - dwThreadId: 0 - } -} - -// FIXME: this is only pub so it can be tested (see issue #4536) -#[cfg(windows)] -pub fn make_command_line(prog: &str, args: &[~str]) -> ~str { - - let mut cmd = ~""; - append_arg(&mut cmd, prog); - for args.each |arg| { - cmd.push_char(' '); - append_arg(&mut cmd, *arg); - } - return cmd; - - fn append_arg(cmd: &mut ~str, arg: &str) { - let quote = arg.any(|c| c == ' ' || c == '\t'); - if quote { - cmd.push_char('"'); - } - for uint::range(0, arg.len()) |i| { - append_char_at(cmd, arg, i); - } - if quote { - cmd.push_char('"'); - } - } - - fn append_char_at(cmd: &mut ~str, arg: &str, i: uint) { - match arg[i] as char { - '"' => { - // Escape quotes. - cmd.push_str("\\\""); - } - '\\' => { - if backslash_run_ends_in_quote(arg, i) { - // Double all backslashes that are in runs before quotes. - cmd.push_str("\\\\"); - } else { - // Pass other backslashes through unescaped. - cmd.push_char('\\'); - } - } - c => { - cmd.push_char(c); - } - } - } - - fn backslash_run_ends_in_quote(s: &str, mut i: uint) -> bool { - while i < s.len() && s[i] as char == '\\' { - i += 1; - } - return i < s.len() && s[i] as char == '"'; - } -} - -#[cfg(unix)] -fn spawn_process_internal(prog: &str, args: &[~str], - env: &Option<~[(~str,~str)]>, - dir: &Option<~str>, - in_fd: c_int, out_fd: c_int, err_fd: c_int) -> RunProgramResult { - - use libc::funcs::posix88::unistd::{fork, dup2, close, chdir, execvp}; - use libc::funcs::bsd44::getdtablesize; - - mod rustrt { - use libc::c_void; - - #[abi = "cdecl"] - pub extern { - unsafe fn rust_unset_sigprocmask(); - unsafe fn rust_set_environ(envp: *c_void); - } - } - - unsafe { - - let pid = fork(); - if pid < 0 { - fail!("failure in fork: %s", os::last_os_error()); - } else if pid > 0 { - return RunProgramResult {pid: pid, handle: ptr::null()}; - } - - rustrt::rust_unset_sigprocmask(); - - if in_fd > 0 && dup2(in_fd, 0) == -1 { - fail!("failure in dup2(in_fd, 0): %s", os::last_os_error()); - } - if out_fd > 0 && dup2(out_fd, 1) == -1 { - fail!("failure in dup2(out_fd, 1): %s", os::last_os_error()); - } - if err_fd > 0 && dup2(err_fd, 2) == -1 { - fail!("failure in dup3(err_fd, 2): %s", os::last_os_error()); - } - // close all other fds - for int::range_rev(getdtablesize() as int - 1, 2) |fd| { - close(fd as c_int); - } - - for dir.each |dir| { - do str::as_c_str(*dir) |dirp| { - if chdir(dirp) == -1 { - fail!("failure in chdir: %s", os::last_os_error()); - } - } - } - - do with_envp(env) |envp| { - if !envp.is_null() { - rustrt::rust_set_environ(envp); - } - do with_argv(prog, args) |argv| { - execvp(*argv, argv); - // execvp only returns if an error occurred - fail!("failure in execvp: %s", os::last_os_error()); - } - } - } -} - -#[cfg(unix)] -fn with_argv(prog: &str, args: &[~str], - cb: &fn(**libc::c_char) -> T) -> T { - let mut argptrs = str::as_c_str(prog, |b| ~[b]); - let mut tmps = ~[]; - for args.each |arg| { - let t = @copy *arg; - tmps.push(t); - argptrs.push_all(str::as_c_str(*t, |b| ~[b])); - } - argptrs.push(ptr::null()); - vec::as_imm_buf(argptrs, |buf, _len| cb(buf)) -} - -#[cfg(unix)] -fn with_envp(env: &Option<~[(~str,~str)]>, - cb: &fn(*c_void) -> T) -> T { - // On posixy systems we can pass a char** for envp, which is - // a null-terminated array of "k=v\n" strings. - match *env { - Some(ref es) if !vec::is_empty(*es) => { - let mut tmps = ~[]; - let mut ptrs = ~[]; - - for (*es).each |e| { - let (k,v) = copy *e; - let t = @(fmt!("%s=%s", k, v)); - tmps.push(t); - ptrs.push_all(str::as_c_str(*t, |b| ~[b])); - } - ptrs.push(ptr::null()); - vec::as_imm_buf(ptrs, |p, _len| - unsafe { cb(::cast::transmute(p)) } - ) - } - _ => cb(ptr::null()) - } -} - -#[cfg(windows)] -fn with_envp(env: &Option<~[(~str,~str)]>, - cb: &fn(*mut c_void) -> T) -> T { - // On win32 we pass an "environment block" which is not a char**, but - // rather a concatenation of null-terminated k=v\0 sequences, with a final - // \0 to terminate. - unsafe { - match *env { - Some(ref es) if !vec::is_empty(*es) => { - let mut blk : ~[u8] = ~[]; - for (*es).each |e| { - let (k,v) = copy *e; - let t = fmt!("%s=%s", k, v); - let mut v : ~[u8] = ::cast::transmute(t); - blk += v; - ::cast::forget(v); - } - blk += ~[0_u8]; - vec::as_imm_buf(blk, |p, _len| cb(::cast::transmute(p))) - } - _ => cb(ptr::mut_null()) - } - } -} - -#[cfg(windows)] -fn with_dirp(d: &Option<~str>, - cb: &fn(*libc::c_char) -> T) -> T { - match *d { - Some(ref dir) => str::as_c_str(*dir, cb), - None => cb(ptr::null()) - } -} - -/// helper function that closes non-NULL files and then makes them NULL -priv unsafe fn fclose_and_null(f: &mut *libc::FILE) { - if *f != 0 as *libc::FILE { - libc::fclose(*f); - *f = 0 as *libc::FILE; - } -} - -#[cfg(windows)] -priv fn free_handle(handle: *()) { - unsafe { - libc::funcs::extra::kernel32::CloseHandle(cast::transmute(handle)); - } -} - -#[cfg(unix)] -priv fn free_handle(_handle: *()) { - // unix has no process handle object, just a pid -} - -/** - * Spawns a process and waits for it to terminate - * - * # Arguments - * - * * prog - The path to an executable - * * args - Vector of arguments to pass to the child process - * - * # Return value - * - * The process's exit code - */ -pub fn run_program(prog: &str, args: &[~str]) -> int { - let res = spawn_process_internal(prog, args, &None, &None, - 0i32, 0i32, 0i32); - let code = waitpid(res.pid); - free_handle(res.handle); - return code; -} - -/** - * Spawns a process and returns a Program - * - * The returned value is a object that can be used for sending and - * receiving data over the standard file descriptors. The class will ensure - * that file descriptors are closed properly. - * - * # Arguments - * - * * prog - The path to an executable - * * args - Vector of arguments to pass to the child process - * - * # Return value - * - * A object - */ -pub fn start_program(prog: &str, args: &[~str]) -> Program { - let pipe_input = os::pipe(); - let pipe_output = os::pipe(); - let pipe_err = os::pipe(); - let res = - spawn_process_internal(prog, args, &None, &None, - pipe_input.in, pipe_output.out, - pipe_err.out); - - unsafe { - libc::close(pipe_input.in); - libc::close(pipe_output.out); - libc::close(pipe_err.out); - } - - Program { - pid: res.pid, - handle: res.handle, - in_fd: pipe_input.out, - out_file: os::fdopen(pipe_output.in), - err_file: os::fdopen(pipe_err.in), - finished: false, - } -} - -fn read_all(rd: @io::Reader) -> ~str { - let buf = io::with_bytes_writer(|wr| { - let mut bytes = [0, ..4096]; - while !rd.eof() { - let nread = rd.read(bytes, bytes.len()); - wr.write(bytes.slice(0, nread)); - } - }); - str::from_bytes(buf) -} - -pub struct ProgramOutput {status: int, out: ~str, err: ~str} - -/** - * Spawns a process, waits for it to exit, and returns the exit code, and - * contents of stdout and stderr. - * - * # Arguments - * - * * prog - The path to an executable - * * args - Vector of arguments to pass to the child process - * - * # Return value - * - * A record, {status: int, out: str, err: str} containing the exit code, - * the contents of stdout and the contents of stderr. - */ -pub fn program_output(prog: &str, args: &[~str]) -> ProgramOutput { - let pipe_in = os::pipe(); - let pipe_out = os::pipe(); - let pipe_err = os::pipe(); - let res = spawn_process_internal(prog, args, &None, &None, - pipe_in.in, pipe_out.out, pipe_err.out); - - os::close(pipe_in.in); - os::close(pipe_out.out); - os::close(pipe_err.out); - os::close(pipe_in.out); - - // Spawn two entire schedulers to read both stdout and sterr - // in parallel so we don't deadlock while blocking on one - // or the other. FIXME (#2625): Surely there's a much more - // clever way to do this. - let (p, ch) = stream(); - let ch = SharedChan::new(ch); - let ch_clone = ch.clone(); - do task::spawn_sched(task::SingleThreaded) { - let errput = readclose(pipe_err.in); - ch.send((2, errput)); - }; - do task::spawn_sched(task::SingleThreaded) { - let output = readclose(pipe_out.in); - ch_clone.send((1, output)); - }; - - let status = waitpid(res.pid); - free_handle(res.handle); - - let mut errs = ~""; - let mut outs = ~""; - let mut count = 2; - while count > 0 { - let stream = p.recv(); - match stream { - (1, copy s) => { - outs = s; - } - (2, copy s) => { - errs = s; - } - (n, _) => { - fail!("program_output received an unexpected file number: %u", n); - } - }; - count -= 1; - }; - return ProgramOutput {status: status, - out: outs, - err: errs}; -} - -pub fn writeclose(fd: c_int, s: ~str) { - use io::WriterUtil; - - error!("writeclose %d, %s", fd as int, s); - let writer = io::fd_writer(fd, false); - writer.write_str(s); - - os::close(fd); -} - -pub fn readclose(fd: c_int) -> ~str { - unsafe { - let file = os::fdopen(fd); - let reader = io::FILE_reader(file, false); - let buf = io::with_bytes_writer(|writer| { - let mut bytes = [0, ..4096]; - while !reader.eof() { - let nread = reader.read(bytes, bytes.len()); - writer.write(bytes.slice(0, nread)); - } - }); - os::fclose(file); - str::from_bytes(buf) - } -} - -/** - * Waits for a process to exit and returns the exit code, failing - * if there is no process with the specified id. - */ -pub fn waitpid(pid: pid_t) -> int { - return waitpid_os(pid); - - #[cfg(windows)] - fn waitpid_os(pid: pid_t) -> int { - - use libc::types::os::arch::extra::DWORD; - use libc::consts::os::extra::{ - SYNCHRONIZE, - PROCESS_QUERY_INFORMATION, - FALSE, - STILL_ACTIVE, - INFINITE, - WAIT_FAILED - }; - use libc::funcs::extra::kernel32::{ - OpenProcess, - GetExitCodeProcess, - CloseHandle, - WaitForSingleObject - }; - - unsafe { - - let proc = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION, FALSE, pid as DWORD); - if proc.is_null() { - fail!("failure in OpenProcess: %s", os::last_os_error()); - } - - loop { - let mut status = 0; - if GetExitCodeProcess(proc, &mut status) == FALSE { - CloseHandle(proc); - fail!("failure in GetExitCodeProcess: %s", os::last_os_error()); - } - if status != STILL_ACTIVE { - CloseHandle(proc); - return status as int; - } - if WaitForSingleObject(proc, INFINITE) == WAIT_FAILED { - CloseHandle(proc); - fail!("failure in WaitForSingleObject: %s", os::last_os_error()); - } - } - } - } - - #[cfg(unix)] - fn waitpid_os(pid: pid_t) -> int { - - use libc::funcs::posix01::wait::*; - - #[cfg(target_os = "linux")] - #[cfg(target_os = "android")] - fn WIFEXITED(status: i32) -> bool { - (status & 0xffi32) == 0i32 - } - - #[cfg(target_os = "macos")] - #[cfg(target_os = "freebsd")] - fn WIFEXITED(status: i32) -> bool { - (status & 0x7fi32) == 0i32 - } - - #[cfg(target_os = "linux")] - #[cfg(target_os = "android")] - fn WEXITSTATUS(status: i32) -> i32 { - (status >> 8i32) & 0xffi32 - } - - #[cfg(target_os = "macos")] - #[cfg(target_os = "freebsd")] - fn WEXITSTATUS(status: i32) -> i32 { - status >> 8i32 - } - - let mut status = 0 as c_int; - if unsafe { waitpid(pid, &mut status, 0) } == -1 { - fail!("failure in waitpid: %s", os::last_os_error()); - } - - return if WIFEXITED(status) { - WEXITSTATUS(status) as int - } else { - 1 - }; - } -} - -#[cfg(test)] -mod tests { - use option::None; - use os; - use run::{readclose, writeclose}; - use run; - - #[test] - #[cfg(windows)] - fn test_make_command_line() { - assert_eq!( - run::make_command_line("prog", [~"aaa", ~"bbb", ~"ccc"]), - ~"prog aaa bbb ccc" - ); - assert_eq!( - run::make_command_line("C:\\Program Files\\blah\\blah.exe", [~"aaa"]), - ~"\"C:\\Program Files\\blah\\blah.exe\" aaa" - ); - assert_eq!( - run::make_command_line("C:\\Program Files\\test", [~"aa\"bb"]), - ~"\"C:\\Program Files\\test\" aa\\\"bb" - ); - assert_eq!( - run::make_command_line("echo", [~"a b c"]), - ~"echo \"a b c\"" - ); - } - - // Regression test for memory leaks - #[test] - fn test_leaks() { - run::run_program("echo", []); - run::start_program("echo", []); - run::program_output("echo", []); - } - - #[test] - #[allow(non_implicitly_copyable_typarams)] - fn test_pipes() { - let pipe_in = os::pipe(); - let pipe_out = os::pipe(); - let pipe_err = os::pipe(); - - let pid = - run::spawn_process( - "cat", [], &None, &None, - pipe_in.in, pipe_out.out, pipe_err.out); - os::close(pipe_in.in); - os::close(pipe_out.out); - os::close(pipe_err.out); - - if pid == -1i32 { fail!(); } - let expected = ~"test"; - writeclose(pipe_in.out, copy expected); - let actual = readclose(pipe_out.in); - readclose(pipe_err.in); - run::waitpid(pid); - - debug!(copy expected); - debug!(copy actual); - assert!((expected == actual)); - } - - #[test] - fn waitpid() { - let pid = run::spawn_process("false", [], - &None, &None, - 0i32, 0i32, 0i32); - let status = run::waitpid(pid); - assert!(status == 1); - } - - #[test] - #[should_fail] - #[ignore(cfg(windows))] - fn waitpid_non_existant_pid() { - run::waitpid(123456789); // assume that this pid doesn't exist - } -} diff --git a/src/libcore/to_bytes.rs b/src/libcore/to_bytes.rs deleted file mode 100644 index ad42881ffa028..0000000000000 --- a/src/libcore/to_bytes.rs +++ /dev/null @@ -1,698 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/*! - -The `ToBytes` and `IterBytes` traits - -*/ - -use io; -use io::Writer; -use option::{None, Option, Some}; -use old_iter::BaseIter; -use str; - -pub type Cb<'self> = &'self fn(buf: &[u8]) -> bool; - -#[cfg(stage0)] -pub trait IterBytes { - fn iter_bytes(&self, lsb0: bool, f: Cb); -} - -/** - * A trait to implement in order to make a type hashable; - * This works in combination with the trait `Hash::Hash`, and - * may in the future be merged with that trait or otherwise - * modified when default methods and trait inheritence are - * completed. - */ -#[cfg(not(stage0))] -pub trait IterBytes { - /** - * Call the provided callback `f` one or more times with - * byte-slices that should be used when computing a hash - * value or otherwise "flattening" the structure into - * a sequence of bytes. The `lsb0` parameter conveys - * whether the caller is asking for little-endian bytes - * (`true`) or big-endian (`false`); this should only be - * relevant in implementations that represent a single - * multi-byte datum such as a 32 bit integer or 64 bit - * floating-point value. It can be safely ignored for - * larger structured types as they are usually processed - * left-to-right in declaration order, regardless of - * underlying memory endianness. - */ - fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool; -} - -#[cfg(stage0)] -impl IterBytes for bool { - #[inline(always)] - fn iter_bytes(&self, _lsb0: bool, f: Cb) { - f([ - *self as u8 - ]); - } -} -#[cfg(not(stage0))] -impl IterBytes for bool { - #[inline(always)] - fn iter_bytes(&self, _lsb0: bool, f: Cb) -> bool { - f([ - *self as u8 - ]) - } -} - -#[cfg(stage0)] -impl IterBytes for u8 { - #[inline(always)] - fn iter_bytes(&self, _lsb0: bool, f: Cb) { - f([ - *self - ]); - } -} -#[cfg(not(stage0))] -impl IterBytes for u8 { - #[inline(always)] - fn iter_bytes(&self, _lsb0: bool, f: Cb) -> bool { - f([ - *self - ]) - } -} - -#[cfg(stage0)] -impl IterBytes for u16 { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) { - if lsb0 { - f([ - *self as u8, - (*self >> 8) as u8 - ]); - } else { - f([ - (*self >> 8) as u8, - *self as u8 - ]); - } - } -} -#[cfg(not(stage0))] -impl IterBytes for u16 { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { - if lsb0 { - f([ - *self as u8, - (*self >> 8) as u8 - ]) - } else { - f([ - (*self >> 8) as u8, - *self as u8 - ]) - } - } -} - -#[cfg(stage0)] -impl IterBytes for u32 { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) { - if lsb0 { - f([ - *self as u8, - (*self >> 8) as u8, - (*self >> 16) as u8, - (*self >> 24) as u8, - ]); - } else { - f([ - (*self >> 24) as u8, - (*self >> 16) as u8, - (*self >> 8) as u8, - *self as u8 - ]); - } - } -} -#[cfg(not(stage0))] -impl IterBytes for u32 { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { - if lsb0 { - f([ - *self as u8, - (*self >> 8) as u8, - (*self >> 16) as u8, - (*self >> 24) as u8, - ]) - } else { - f([ - (*self >> 24) as u8, - (*self >> 16) as u8, - (*self >> 8) as u8, - *self as u8 - ]) - } - } -} - -#[cfg(stage0)] -impl IterBytes for u64 { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) { - if lsb0 { - f([ - *self as u8, - (*self >> 8) as u8, - (*self >> 16) as u8, - (*self >> 24) as u8, - (*self >> 32) as u8, - (*self >> 40) as u8, - (*self >> 48) as u8, - (*self >> 56) as u8 - ]); - } else { - f([ - (*self >> 56) as u8, - (*self >> 48) as u8, - (*self >> 40) as u8, - (*self >> 32) as u8, - (*self >> 24) as u8, - (*self >> 16) as u8, - (*self >> 8) as u8, - *self as u8 - ]); - } - } -} -#[cfg(not(stage0))] -impl IterBytes for u64 { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { - if lsb0 { - f([ - *self as u8, - (*self >> 8) as u8, - (*self >> 16) as u8, - (*self >> 24) as u8, - (*self >> 32) as u8, - (*self >> 40) as u8, - (*self >> 48) as u8, - (*self >> 56) as u8 - ]) - } else { - f([ - (*self >> 56) as u8, - (*self >> 48) as u8, - (*self >> 40) as u8, - (*self >> 32) as u8, - (*self >> 24) as u8, - (*self >> 16) as u8, - (*self >> 8) as u8, - *self as u8 - ]) - } - } -} - -#[cfg(stage0)] -impl IterBytes for i8 { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) { - (*self as u8).iter_bytes(lsb0, f) - } -} -#[cfg(not(stage0))] -impl IterBytes for i8 { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { - (*self as u8).iter_bytes(lsb0, f) - } -} - -#[cfg(stage0)] -impl IterBytes for i16 { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) { - (*self as u16).iter_bytes(lsb0, f) - } -} -#[cfg(not(stage0))] -impl IterBytes for i16 { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { - (*self as u16).iter_bytes(lsb0, f) - } -} - -#[cfg(stage0)] -impl IterBytes for i32 { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) { - (*self as u32).iter_bytes(lsb0, f) - } -} -#[cfg(not(stage0))] -impl IterBytes for i32 { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { - (*self as u32).iter_bytes(lsb0, f) - } -} - -#[cfg(stage0)] -impl IterBytes for i64 { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) { - (*self as u64).iter_bytes(lsb0, f) - } -} -#[cfg(not(stage0))] -impl IterBytes for i64 { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { - (*self as u64).iter_bytes(lsb0, f) - } -} - -#[cfg(stage0)] -impl IterBytes for char { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) { - (*self as u32).iter_bytes(lsb0, f) - } -} -#[cfg(not(stage0))] -impl IterBytes for char { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { - (*self as u32).iter_bytes(lsb0, f) - } -} - -#[cfg(target_word_size = "32", stage0)] -impl IterBytes for uint { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) { - (*self as u32).iter_bytes(lsb0, f) - } -} -#[cfg(target_word_size = "32", not(stage0))] -impl IterBytes for uint { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { - (*self as u32).iter_bytes(lsb0, f) - } -} - -#[cfg(target_word_size = "64", stage0)] -impl IterBytes for uint { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) { - (*self as u64).iter_bytes(lsb0, f) - } -} -#[cfg(target_word_size = "64", not(stage0))] -impl IterBytes for uint { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { - (*self as u64).iter_bytes(lsb0, f) - } -} - -#[cfg(stage0)] -impl IterBytes for int { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) { - (*self as uint).iter_bytes(lsb0, f) - } -} -#[cfg(not(stage0))] -impl IterBytes for int { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { - (*self as uint).iter_bytes(lsb0, f) - } -} - -#[cfg(stage0)] -impl<'self,A:IterBytes> IterBytes for &'self [A] { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) { - for (*self).each |elt| { - do elt.iter_bytes(lsb0) |bytes| { - f(bytes) - } - } - } -} -#[cfg(not(stage0))] -impl<'self,A:IterBytes> IterBytes for &'self [A] { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { - self.each(|elt| elt.iter_bytes(lsb0, |b| f(b))) - } -} - -#[cfg(stage0)] -impl IterBytes for (A,B) { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) { - match *self { - (ref a, ref b) => { - iter_bytes_2(a, b, lsb0, f); - } - } - } -} -#[cfg(not(stage0))] -impl IterBytes for (A,B) { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { - match *self { - (ref a, ref b) => { a.iter_bytes(lsb0, f) && b.iter_bytes(lsb0, f) } - } - } -} - -#[cfg(stage0)] -impl IterBytes for (A,B,C) { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) { - match *self { - (ref a, ref b, ref c) => { - iter_bytes_3(a, b, c, lsb0, f); - } - } - } -} -#[cfg(not(stage0))] -impl IterBytes for (A,B,C) { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { - match *self { - (ref a, ref b, ref c) => { - a.iter_bytes(lsb0, f) && b.iter_bytes(lsb0, f) && c.iter_bytes(lsb0, f) - } - } - } -} - -// Move this to vec, probably. -fn borrow<'x,A>(a: &'x [A]) -> &'x [A] { - a -} - -#[cfg(stage0)] -impl IterBytes for ~[A] { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) { - borrow(*self).iter_bytes(lsb0, f) - } -} -#[cfg(not(stage0))] -impl IterBytes for ~[A] { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { - borrow(*self).iter_bytes(lsb0, f) - } -} - -#[cfg(stage0)] -impl IterBytes for @[A] { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) { - borrow(*self).iter_bytes(lsb0, f) - } -} -#[cfg(not(stage0))] -impl IterBytes for @[A] { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { - borrow(*self).iter_bytes(lsb0, f) - } -} - -// NOTE: remove all of these after a snapshot, the new for-loop iteration -// protocol makes these unnecessary. - -#[cfg(stage0)] -pub fn iter_bytes_2(a: &A, b: &B, - lsb0: bool, z: Cb) { - let mut flag = true; - a.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag}); - if !flag { return; } - b.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag}); -} -#[cfg(not(stage0))] -#[inline(always)] -pub fn iter_bytes_2(a: &A, b: &B, - lsb0: bool, z: Cb) -> bool { - a.iter_bytes(lsb0, z) && b.iter_bytes(lsb0, z) -} - -#[cfg(stage0)] -pub fn iter_bytes_3(a: &A, b: &B, c: &C, - lsb0: bool, z: Cb) { - let mut flag = true; - a.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag}); - if !flag { return; } - b.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag}); - if !flag { return; } - c.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag}); -} -#[cfg(not(stage0))] -pub fn iter_bytes_3(a: &A, b: &B, c: &C, lsb0: bool, z: Cb) -> bool { - a.iter_bytes(lsb0, z) && b.iter_bytes(lsb0, z) && c.iter_bytes(lsb0, z) -} - -#[cfg(stage0)] -pub fn iter_bytes_4(a: &A, b: &B, c: &C, - d: &D, - lsb0: bool, z: Cb) { - let mut flag = true; - a.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag}); - if !flag { return; } - b.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag}); - if !flag { return; } - c.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag}); - if !flag { return; } - d.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag}); -} -#[cfg(not(stage0))] -pub fn iter_bytes_4(a: &A, b: &B, c: &C, - d: &D, - lsb0: bool, z: Cb) -> bool { - a.iter_bytes(lsb0, z) && b.iter_bytes(lsb0, z) && c.iter_bytes(lsb0, z) && - d.iter_bytes(lsb0, z) -} - -#[cfg(stage0)] -pub fn iter_bytes_5(a: &A, b: &B, c: &C, - d: &D, e: &E, - lsb0: bool, z: Cb) { - let mut flag = true; - a.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag}); - if !flag { return; } - b.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag}); - if !flag { return; } - c.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag}); - if !flag { return; } - d.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag}); - if !flag { return; } - e.iter_bytes(lsb0, |bytes| {flag = z(bytes); flag}); -} -#[cfg(not(stage0))] -pub fn iter_bytes_5(a: &A, b: &B, c: &C, - d: &D, e: &E, - lsb0: bool, z: Cb) -> bool { - a.iter_bytes(lsb0, z) && b.iter_bytes(lsb0, z) && c.iter_bytes(lsb0, z) && - d.iter_bytes(lsb0, z) && e.iter_bytes(lsb0, z) -} - -#[cfg(stage0)] -impl<'self> IterBytes for &'self str { - #[inline(always)] - fn iter_bytes(&self, _lsb0: bool, f: Cb) { - do str::byte_slice(*self) |bytes| { - f(bytes); - } - } -} -#[cfg(not(stage0))] -impl<'self> IterBytes for &'self str { - #[inline(always)] - fn iter_bytes(&self, _lsb0: bool, f: Cb) -> bool { - do str::byte_slice(*self) |bytes| { - f(bytes) - } - } -} - -#[cfg(stage0)] -impl IterBytes for ~str { - #[inline(always)] - fn iter_bytes(&self, _lsb0: bool, f: Cb) { - do str::byte_slice(*self) |bytes| { - f(bytes); - } - } -} -#[cfg(not(stage0))] -impl IterBytes for ~str { - #[inline(always)] - fn iter_bytes(&self, _lsb0: bool, f: Cb) -> bool { - do str::byte_slice(*self) |bytes| { - f(bytes) - } - } -} - -#[cfg(stage0)] -impl IterBytes for @str { - #[inline(always)] - fn iter_bytes(&self, _lsb0: bool, f: Cb) { - do str::byte_slice(*self) |bytes| { - f(bytes); - } - } -} -#[cfg(not(stage0))] -impl IterBytes for @str { - #[inline(always)] - fn iter_bytes(&self, _lsb0: bool, f: Cb) -> bool { - do str::byte_slice(*self) |bytes| { - f(bytes) - } - } -} - -#[cfg(stage0)] -impl IterBytes for Option { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) { - match *self { - Some(ref a) => iter_bytes_2(&0u8, a, lsb0, f), - None => 1u8.iter_bytes(lsb0, f) - } - } -} -#[cfg(not(stage0))] -impl IterBytes for Option { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { - match *self { - Some(ref a) => 0u8.iter_bytes(lsb0, f) && a.iter_bytes(lsb0, f), - None => 1u8.iter_bytes(lsb0, f) - } - } -} - -#[cfg(stage0)] -impl<'self,A:IterBytes> IterBytes for &'self A { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) { - (**self).iter_bytes(lsb0, f); - } -} -#[cfg(not(stage0))] -impl<'self,A:IterBytes> IterBytes for &'self A { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { - (**self).iter_bytes(lsb0, f) - } -} - -#[cfg(stage0)] -impl IterBytes for @A { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) { - (**self).iter_bytes(lsb0, f); - } -} -#[cfg(not(stage0))] -impl IterBytes for @A { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { - (**self).iter_bytes(lsb0, f) - } -} - -#[cfg(stage0)] -impl IterBytes for ~A { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) { - (**self).iter_bytes(lsb0, f); - } -} -#[cfg(not(stage0))] -impl IterBytes for ~A { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { - (**self).iter_bytes(lsb0, f) - } -} - -// NB: raw-pointer IterBytes does _not_ dereference -// to the target; it just gives you the pointer-bytes. -#[cfg(stage0)] -impl IterBytes for *const A { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) { - (*self as uint).iter_bytes(lsb0, f); - } -} -// NB: raw-pointer IterBytes does _not_ dereference -// to the target; it just gives you the pointer-bytes. -#[cfg(not(stage0))] -impl IterBytes for *const A { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { - (*self as uint).iter_bytes(lsb0, f) - } -} - -pub trait ToBytes { - fn to_bytes(&self, lsb0: bool) -> ~[u8]; -} - -impl ToBytes for A { - fn to_bytes(&self, lsb0: bool) -> ~[u8] { - do io::with_bytes_writer |wr| { - for self.iter_bytes(lsb0) |bytes| { - wr.write(bytes) - } - } - } -} diff --git a/src/libcore/tuple.rs b/src/libcore/tuple.rs deleted file mode 100644 index b29a4e55426df..0000000000000 --- a/src/libcore/tuple.rs +++ /dev/null @@ -1,270 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Operations on tuples - -use clone::Clone; -use kinds::Copy; -use vec; - -#[cfg(not(test))] use cmp::{Eq, Ord}; - -pub trait CopyableTuple { - fn first(&self) -> T; - fn second(&self) -> U; - fn swap(&self) -> (U, T); -} - -impl CopyableTuple for (T, U) { - - /// Return the first element of self - #[inline(always)] - fn first(&self) -> T { - let (t, _) = *self; - return t; - } - - /// Return the second element of self - #[inline(always)] - fn second(&self) -> U { - let (_, u) = *self; - return u; - } - - /// Return the results of swapping the two elements of self - #[inline(always)] - fn swap(&self) -> (U, T) { - let (t, u) = *self; - return (u, t); - } - -} - -impl Clone for (T, U) { - fn clone(&self) -> (T, U) { - let (a, b) = match *self { - (ref a, ref b) => (a, b) - }; - (a.clone(), b.clone()) - } -} - -pub trait ImmutableTuple { - fn first_ref<'a>(&'a self) -> &'a T; - fn second_ref<'a>(&'a self) -> &'a U; -} - -impl ImmutableTuple for (T, U) { - #[inline(always)] - fn first_ref<'a>(&'a self) -> &'a T { - match *self { - (ref t, _) => t, - } - } - #[inline(always)] - fn second_ref<'a>(&'a self) -> &'a U { - match *self { - (_, ref u) => u, - } - } -} - -pub trait ExtendedTupleOps { - fn zip(&self) -> ~[(A, B)]; - fn map(&self, f: &fn(a: &A, b: &B) -> C) -> ~[C]; -} - -impl<'self,A:Copy,B:Copy> ExtendedTupleOps for (&'self [A], &'self [B]) { - #[inline(always)] - fn zip(&self) -> ~[(A, B)] { - match *self { - (ref a, ref b) => { - vec::zip_slice(*a, *b) - } - } - } - - #[inline(always)] - fn map(&self, f: &fn(a: &A, b: &B) -> C) -> ~[C] { - match *self { - (ref a, ref b) => { - vec::map_zip(*a, *b, f) - } - } - } -} - -impl ExtendedTupleOps for (~[A], ~[B]) { - - #[inline(always)] - fn zip(&self) -> ~[(A, B)] { - match *self { - (ref a, ref b) => { - vec::zip_slice(*a, *b) - } - } - } - - #[inline(always)] - fn map(&self, f: &fn(a: &A, b: &B) -> C) -> ~[C] { - match *self { - (ref a, ref b) => { - vec::map_zip(*a, *b, f) - } - } - } -} - -#[cfg(not(test))] -impl Eq for (A,) { - #[inline(always)] - fn eq(&self, other: &(A,)) -> bool { - match (*self) { - (ref self_a,) => match other { - &(ref other_a,) => { - (*self_a).eq(other_a) - } - } - } - } - #[inline(always)] - fn ne(&self, other: &(A,)) -> bool { !(*self).eq(other) } -} - -#[cfg(not(test))] -impl Ord for (A,) { - #[inline(always)] - fn lt(&self, other: &(A,)) -> bool { - match (*self) { - (ref self_a,) => { - match (*other) { - (ref other_a,) => { - if (*self_a).lt(other_a) { return true; } - return false; - } - } - } - } - } - #[inline(always)] - fn le(&self, other: &(A,)) -> bool { !other.lt(&(*self)) } - #[inline(always)] - fn ge(&self, other: &(A,)) -> bool { !self.lt(other) } - #[inline(always)] - fn gt(&self, other: &(A,)) -> bool { other.lt(&(*self)) } -} - -#[cfg(not(test))] -impl Eq for (A, B) { - #[inline(always)] - fn eq(&self, other: &(A, B)) -> bool { - match (*self) { - (ref self_a, ref self_b) => match other { - &(ref other_a, ref other_b) => { - (*self_a).eq(other_a) && (*self_b).eq(other_b) - } - } - } - } - #[inline(always)] - fn ne(&self, other: &(A, B)) -> bool { !(*self).eq(other) } -} - -#[cfg(not(test))] -impl Ord for (A, B) { - #[inline(always)] - fn lt(&self, other: &(A, B)) -> bool { - match (*self) { - (ref self_a, ref self_b) => { - match (*other) { - (ref other_a, ref other_b) => { - if (*self_a).lt(other_a) { return true; } - if (*other_a).lt(self_a) { return false; } - if (*self_b).lt(other_b) { return true; } - return false; - } - } - } - } - } - #[inline(always)] - fn le(&self, other: &(A, B)) -> bool { !(*other).lt(&(*self)) } - #[inline(always)] - fn ge(&self, other: &(A, B)) -> bool { !(*self).lt(other) } - #[inline(always)] - fn gt(&self, other: &(A, B)) -> bool { (*other).lt(&(*self)) } -} - -#[cfg(not(test))] -impl Eq for (A, B, C) { - #[inline(always)] - fn eq(&self, other: &(A, B, C)) -> bool { - match (*self) { - (ref self_a, ref self_b, ref self_c) => match other { - &(ref other_a, ref other_b, ref other_c) => { - (*self_a).eq(other_a) && (*self_b).eq(other_b) - && (*self_c).eq(other_c) - } - } - } - } - #[inline(always)] - fn ne(&self, other: &(A, B, C)) -> bool { !(*self).eq(other) } -} - -#[cfg(not(test))] -impl Ord for (A, B, C) { - #[inline(always)] - fn lt(&self, other: &(A, B, C)) -> bool { - match (*self) { - (ref self_a, ref self_b, ref self_c) => { - match (*other) { - (ref other_a, ref other_b, ref other_c) => { - if (*self_a).lt(other_a) { return true; } - if (*other_a).lt(self_a) { return false; } - if (*self_b).lt(other_b) { return true; } - if (*other_b).lt(self_b) { return false; } - if (*self_c).lt(other_c) { return true; } - return false; - } - } - } - } - } - #[inline(always)] - fn le(&self, other: &(A, B, C)) -> bool { !(*other).lt(&(*self)) } - #[inline(always)] - fn ge(&self, other: &(A, B, C)) -> bool { !(*self).lt(other) } - #[inline(always)] - fn gt(&self, other: &(A, B, C)) -> bool { (*other).lt(&(*self)) } -} - -#[test] -fn test_tuple_ref() { - let x = (~"foo", ~"bar"); - assert!(x.first_ref() == &~"foo"); - assert!(x.second_ref() == &~"bar"); -} - -#[test] -#[allow(non_implicitly_copyable_typarams)] -fn test_tuple() { - assert!((948, 4039.48).first() == 948); - assert!((34.5, ~"foo").second() == ~"foo"); - assert!(('a', 2).swap() == (2, 'a')); -} - -#[test] -fn test_clone() { - let a = (1, ~"2"); - let b = a.clone(); - assert!(a.first() == b.first()); - assert!(a.second() == b.second()); -} diff --git a/src/libcore/unicode.rs b/src/libcore/unicode.rs deleted file mode 100644 index d6e2c5eee6aca..0000000000000 --- a/src/libcore/unicode.rs +++ /dev/null @@ -1,2644 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[doc(hidden)]; // FIXME #3538 - -// The following code was generated by "src/etc/unicode.py" - -pub mod general_category { - - fn bsearch_range_table(c: char, r: &'static [(char,char)]) -> bool { - use cmp::{Equal, Less, Greater}; - use vec::bsearch; - use option::None; - (do bsearch(r) |&(lo,hi)| { - if lo <= c && c <= hi { Equal } - else if hi < c { Less } - else { Greater } - }) != None - } - - - static Cc_table : &'static [(char,char)] = &[ - ('\x00', '\x1f'), ('\x7f', '\x9f') - ]; - - pub fn Cc(c: char) -> bool { - bsearch_range_table(c, Cc_table) - } - - static Cf_table : &'static [(char,char)] = &[ - ('\xad', '\xad'), ('\u0600', '\u0604'), - ('\u06dd', '\u06dd'), ('\u070f', '\u070f'), - ('\u200b', '\u200f'), ('\u202a', '\u202e'), - ('\u2060', '\u206f'), ('\ufeff', '\ufeff'), - ('\ufff9', '\ufffb'), ('\U000110bd', '\U000110bd'), - ('\U0001d173', '\U0001d17a'), ('\U000e0001', '\U000e007f') - ]; - - pub fn Cf(c: char) -> bool { - bsearch_range_table(c, Cf_table) - } - - static Co_table : &'static [(char,char)] = &[ - ('\ue000', '\uf8ff') - ]; - - pub fn Co(c: char) -> bool { - bsearch_range_table(c, Co_table) - } - - static Cs_table : &'static [(char,char)] = &[ - ('\ud800', '\udfff') - ]; - - pub fn Cs(c: char) -> bool { - bsearch_range_table(c, Cs_table) - } - - static Ll_table : &'static [(char,char)] = &[ - ('\x61', '\x7a'), ('\xb5', '\xb5'), - ('\xdf', '\xf6'), ('\xf8', '\xff'), - ('\u0101', '\u0101'), ('\u0103', '\u0103'), - ('\u0105', '\u0105'), ('\u0107', '\u0107'), - ('\u0109', '\u0109'), ('\u010b', '\u010b'), - ('\u010d', '\u010d'), ('\u010f', '\u010f'), - ('\u0111', '\u0111'), ('\u0113', '\u0113'), - ('\u0115', '\u0115'), ('\u0117', '\u0117'), - ('\u0119', '\u0119'), ('\u011b', '\u011b'), - ('\u011d', '\u011d'), ('\u011f', '\u011f'), - ('\u0121', '\u0121'), ('\u0123', '\u0123'), - ('\u0125', '\u0125'), ('\u0127', '\u0127'), - ('\u0129', '\u0129'), ('\u012b', '\u012b'), - ('\u012d', '\u012d'), ('\u012f', '\u012f'), - ('\u0131', '\u0131'), ('\u0133', '\u0133'), - ('\u0135', '\u0135'), ('\u0137', '\u0138'), - ('\u013a', '\u013a'), ('\u013c', '\u013c'), - ('\u013e', '\u013e'), ('\u0140', '\u0140'), - ('\u0142', '\u0142'), ('\u0144', '\u0144'), - ('\u0146', '\u0146'), ('\u0148', '\u0149'), - ('\u014b', '\u014b'), ('\u014d', '\u014d'), - ('\u014f', '\u014f'), ('\u0151', '\u0151'), - ('\u0153', '\u0153'), ('\u0155', '\u0155'), - ('\u0157', '\u0157'), ('\u0159', '\u0159'), - ('\u015b', '\u015b'), ('\u015d', '\u015d'), - ('\u015f', '\u015f'), ('\u0161', '\u0161'), - ('\u0163', '\u0163'), ('\u0165', '\u0165'), - ('\u0167', '\u0167'), ('\u0169', '\u0169'), - ('\u016b', '\u016b'), ('\u016d', '\u016d'), - ('\u016f', '\u016f'), ('\u0171', '\u0171'), - ('\u0173', '\u0173'), ('\u0175', '\u0175'), - ('\u0177', '\u0177'), ('\u017a', '\u017a'), - ('\u017c', '\u017c'), ('\u017e', '\u0180'), - ('\u0183', '\u0183'), ('\u0185', '\u0185'), - ('\u0188', '\u0188'), ('\u018c', '\u018d'), - ('\u0192', '\u0192'), ('\u0195', '\u0195'), - ('\u0199', '\u019b'), ('\u019e', '\u019e'), - ('\u01a1', '\u01a1'), ('\u01a3', '\u01a3'), - ('\u01a5', '\u01a5'), ('\u01a8', '\u01a8'), - ('\u01aa', '\u01ab'), ('\u01ad', '\u01ad'), - ('\u01b0', '\u01b0'), ('\u01b4', '\u01b4'), - ('\u01b6', '\u01b6'), ('\u01b9', '\u01ba'), - ('\u01bd', '\u01bf'), ('\u01c6', '\u01c6'), - ('\u01c9', '\u01c9'), ('\u01cc', '\u01cc'), - ('\u01ce', '\u01ce'), ('\u01d0', '\u01d0'), - ('\u01d2', '\u01d2'), ('\u01d4', '\u01d4'), - ('\u01d6', '\u01d6'), ('\u01d8', '\u01d8'), - ('\u01da', '\u01da'), ('\u01dc', '\u01dd'), - ('\u01df', '\u01df'), ('\u01e1', '\u01e1'), - ('\u01e3', '\u01e3'), ('\u01e5', '\u01e5'), - ('\u01e7', '\u01e7'), ('\u01e9', '\u01e9'), - ('\u01eb', '\u01eb'), ('\u01ed', '\u01ed'), - ('\u01ef', '\u01f0'), ('\u01f3', '\u01f3'), - ('\u01f5', '\u01f5'), ('\u01f9', '\u01f9'), - ('\u01fb', '\u01fb'), ('\u01fd', '\u01fd'), - ('\u01ff', '\u01ff'), ('\u0201', '\u0201'), - ('\u0203', '\u0203'), ('\u0205', '\u0205'), - ('\u0207', '\u0207'), ('\u0209', '\u0209'), - ('\u020b', '\u020b'), ('\u020d', '\u020d'), - ('\u020f', '\u020f'), ('\u0211', '\u0211'), - ('\u0213', '\u0213'), ('\u0215', '\u0215'), - ('\u0217', '\u0217'), ('\u0219', '\u0219'), - ('\u021b', '\u021b'), ('\u021d', '\u021d'), - ('\u021f', '\u021f'), ('\u0221', '\u0221'), - ('\u0223', '\u0223'), ('\u0225', '\u0225'), - ('\u0227', '\u0227'), ('\u0229', '\u0229'), - ('\u022b', '\u022b'), ('\u022d', '\u022d'), - ('\u022f', '\u022f'), ('\u0231', '\u0231'), - ('\u0233', '\u0239'), ('\u023c', '\u023c'), - ('\u023f', '\u0240'), ('\u0242', '\u0242'), - ('\u0247', '\u0247'), ('\u0249', '\u0249'), - ('\u024b', '\u024b'), ('\u024d', '\u024d'), - ('\u024f', '\u0293'), ('\u0295', '\u02af'), - ('\u0371', '\u0371'), ('\u0373', '\u0373'), - ('\u0377', '\u0377'), ('\u037b', '\u037d'), - ('\u0390', '\u0390'), ('\u03ac', '\u03ce'), - ('\u03d0', '\u03d1'), ('\u03d5', '\u03d7'), - ('\u03d9', '\u03d9'), ('\u03db', '\u03db'), - ('\u03dd', '\u03dd'), ('\u03df', '\u03df'), - ('\u03e1', '\u03e1'), ('\u03e3', '\u03e3'), - ('\u03e5', '\u03e5'), ('\u03e7', '\u03e7'), - ('\u03e9', '\u03e9'), ('\u03eb', '\u03eb'), - ('\u03ed', '\u03ed'), ('\u03ef', '\u03f3'), - ('\u03f5', '\u03f5'), ('\u03f8', '\u03f8'), - ('\u03fb', '\u03fc'), ('\u0430', '\u045f'), - ('\u0461', '\u0461'), ('\u0463', '\u0463'), - ('\u0465', '\u0465'), ('\u0467', '\u0467'), - ('\u0469', '\u0469'), ('\u046b', '\u046b'), - ('\u046d', '\u046d'), ('\u046f', '\u046f'), - ('\u0471', '\u0471'), ('\u0473', '\u0473'), - ('\u0475', '\u0475'), ('\u0477', '\u0477'), - ('\u0479', '\u0479'), ('\u047b', '\u047b'), - ('\u047d', '\u047d'), ('\u047f', '\u047f'), - ('\u0481', '\u0481'), ('\u048b', '\u048b'), - ('\u048d', '\u048d'), ('\u048f', '\u048f'), - ('\u0491', '\u0491'), ('\u0493', '\u0493'), - ('\u0495', '\u0495'), ('\u0497', '\u0497'), - ('\u0499', '\u0499'), ('\u049b', '\u049b'), - ('\u049d', '\u049d'), ('\u049f', '\u049f'), - ('\u04a1', '\u04a1'), ('\u04a3', '\u04a3'), - ('\u04a5', '\u04a5'), ('\u04a7', '\u04a7'), - ('\u04a9', '\u04a9'), ('\u04ab', '\u04ab'), - ('\u04ad', '\u04ad'), ('\u04af', '\u04af'), - ('\u04b1', '\u04b1'), ('\u04b3', '\u04b3'), - ('\u04b5', '\u04b5'), ('\u04b7', '\u04b7'), - ('\u04b9', '\u04b9'), ('\u04bb', '\u04bb'), - ('\u04bd', '\u04bd'), ('\u04bf', '\u04bf'), - ('\u04c2', '\u04c2'), ('\u04c4', '\u04c4'), - ('\u04c6', '\u04c6'), ('\u04c8', '\u04c8'), - ('\u04ca', '\u04ca'), ('\u04cc', '\u04cc'), - ('\u04ce', '\u04cf'), ('\u04d1', '\u04d1'), - ('\u04d3', '\u04d3'), ('\u04d5', '\u04d5'), - ('\u04d7', '\u04d7'), ('\u04d9', '\u04d9'), - ('\u04db', '\u04db'), ('\u04dd', '\u04dd'), - ('\u04df', '\u04df'), ('\u04e1', '\u04e1'), - ('\u04e3', '\u04e3'), ('\u04e5', '\u04e5'), - ('\u04e7', '\u04e7'), ('\u04e9', '\u04e9'), - ('\u04eb', '\u04eb'), ('\u04ed', '\u04ed'), - ('\u04ef', '\u04ef'), ('\u04f1', '\u04f1'), - ('\u04f3', '\u04f3'), ('\u04f5', '\u04f5'), - ('\u04f7', '\u04f7'), ('\u04f9', '\u04f9'), - ('\u04fb', '\u04fb'), ('\u04fd', '\u04fd'), - ('\u04ff', '\u04ff'), ('\u0501', '\u0501'), - ('\u0503', '\u0503'), ('\u0505', '\u0505'), - ('\u0507', '\u0507'), ('\u0509', '\u0509'), - ('\u050b', '\u050b'), ('\u050d', '\u050d'), - ('\u050f', '\u050f'), ('\u0511', '\u0511'), - ('\u0513', '\u0513'), ('\u0515', '\u0515'), - ('\u0517', '\u0517'), ('\u0519', '\u0519'), - ('\u051b', '\u051b'), ('\u051d', '\u051d'), - ('\u051f', '\u051f'), ('\u0521', '\u0521'), - ('\u0523', '\u0523'), ('\u0525', '\u0525'), - ('\u0527', '\u0527'), ('\u0561', '\u0587'), - ('\u1d00', '\u1d2b'), ('\u1d6b', '\u1d77'), - ('\u1d79', '\u1d9a'), ('\u1e01', '\u1e01'), - ('\u1e03', '\u1e03'), ('\u1e05', '\u1e05'), - ('\u1e07', '\u1e07'), ('\u1e09', '\u1e09'), - ('\u1e0b', '\u1e0b'), ('\u1e0d', '\u1e0d'), - ('\u1e0f', '\u1e0f'), ('\u1e11', '\u1e11'), - ('\u1e13', '\u1e13'), ('\u1e15', '\u1e15'), - ('\u1e17', '\u1e17'), ('\u1e19', '\u1e19'), - ('\u1e1b', '\u1e1b'), ('\u1e1d', '\u1e1d'), - ('\u1e1f', '\u1e1f'), ('\u1e21', '\u1e21'), - ('\u1e23', '\u1e23'), ('\u1e25', '\u1e25'), - ('\u1e27', '\u1e27'), ('\u1e29', '\u1e29'), - ('\u1e2b', '\u1e2b'), ('\u1e2d', '\u1e2d'), - ('\u1e2f', '\u1e2f'), ('\u1e31', '\u1e31'), - ('\u1e33', '\u1e33'), ('\u1e35', '\u1e35'), - ('\u1e37', '\u1e37'), ('\u1e39', '\u1e39'), - ('\u1e3b', '\u1e3b'), ('\u1e3d', '\u1e3d'), - ('\u1e3f', '\u1e3f'), ('\u1e41', '\u1e41'), - ('\u1e43', '\u1e43'), ('\u1e45', '\u1e45'), - ('\u1e47', '\u1e47'), ('\u1e49', '\u1e49'), - ('\u1e4b', '\u1e4b'), ('\u1e4d', '\u1e4d'), - ('\u1e4f', '\u1e4f'), ('\u1e51', '\u1e51'), - ('\u1e53', '\u1e53'), ('\u1e55', '\u1e55'), - ('\u1e57', '\u1e57'), ('\u1e59', '\u1e59'), - ('\u1e5b', '\u1e5b'), ('\u1e5d', '\u1e5d'), - ('\u1e5f', '\u1e5f'), ('\u1e61', '\u1e61'), - ('\u1e63', '\u1e63'), ('\u1e65', '\u1e65'), - ('\u1e67', '\u1e67'), ('\u1e69', '\u1e69'), - ('\u1e6b', '\u1e6b'), ('\u1e6d', '\u1e6d'), - ('\u1e6f', '\u1e6f'), ('\u1e71', '\u1e71'), - ('\u1e73', '\u1e73'), ('\u1e75', '\u1e75'), - ('\u1e77', '\u1e77'), ('\u1e79', '\u1e79'), - ('\u1e7b', '\u1e7b'), ('\u1e7d', '\u1e7d'), - ('\u1e7f', '\u1e7f'), ('\u1e81', '\u1e81'), - ('\u1e83', '\u1e83'), ('\u1e85', '\u1e85'), - ('\u1e87', '\u1e87'), ('\u1e89', '\u1e89'), - ('\u1e8b', '\u1e8b'), ('\u1e8d', '\u1e8d'), - ('\u1e8f', '\u1e8f'), ('\u1e91', '\u1e91'), - ('\u1e93', '\u1e93'), ('\u1e95', '\u1e9d'), - ('\u1e9f', '\u1e9f'), ('\u1ea1', '\u1ea1'), - ('\u1ea3', '\u1ea3'), ('\u1ea5', '\u1ea5'), - ('\u1ea7', '\u1ea7'), ('\u1ea9', '\u1ea9'), - ('\u1eab', '\u1eab'), ('\u1ead', '\u1ead'), - ('\u1eaf', '\u1eaf'), ('\u1eb1', '\u1eb1'), - ('\u1eb3', '\u1eb3'), ('\u1eb5', '\u1eb5'), - ('\u1eb7', '\u1eb7'), ('\u1eb9', '\u1eb9'), - ('\u1ebb', '\u1ebb'), ('\u1ebd', '\u1ebd'), - ('\u1ebf', '\u1ebf'), ('\u1ec1', '\u1ec1'), - ('\u1ec3', '\u1ec3'), ('\u1ec5', '\u1ec5'), - ('\u1ec7', '\u1ec7'), ('\u1ec9', '\u1ec9'), - ('\u1ecb', '\u1ecb'), ('\u1ecd', '\u1ecd'), - ('\u1ecf', '\u1ecf'), ('\u1ed1', '\u1ed1'), - ('\u1ed3', '\u1ed3'), ('\u1ed5', '\u1ed5'), - ('\u1ed7', '\u1ed7'), ('\u1ed9', '\u1ed9'), - ('\u1edb', '\u1edb'), ('\u1edd', '\u1edd'), - ('\u1edf', '\u1edf'), ('\u1ee1', '\u1ee1'), - ('\u1ee3', '\u1ee3'), ('\u1ee5', '\u1ee5'), - ('\u1ee7', '\u1ee7'), ('\u1ee9', '\u1ee9'), - ('\u1eeb', '\u1eeb'), ('\u1eed', '\u1eed'), - ('\u1eef', '\u1eef'), ('\u1ef1', '\u1ef1'), - ('\u1ef3', '\u1ef3'), ('\u1ef5', '\u1ef5'), - ('\u1ef7', '\u1ef7'), ('\u1ef9', '\u1ef9'), - ('\u1efb', '\u1efb'), ('\u1efd', '\u1efd'), - ('\u1eff', '\u1f07'), ('\u1f10', '\u1f15'), - ('\u1f20', '\u1f27'), ('\u1f30', '\u1f37'), - ('\u1f40', '\u1f45'), ('\u1f50', '\u1f57'), - ('\u1f60', '\u1f67'), ('\u1f70', '\u1f87'), - ('\u1f90', '\u1f97'), ('\u1fa0', '\u1fa7'), - ('\u1fb0', '\u1fb7'), ('\u1fbe', '\u1fbe'), - ('\u1fc2', '\u1fc7'), ('\u1fd0', '\u1fd7'), - ('\u1fe0', '\u1fe7'), ('\u1ff2', '\u1ff7'), - ('\u210a', '\u210a'), ('\u210e', '\u210f'), - ('\u2113', '\u2113'), ('\u212f', '\u212f'), - ('\u2134', '\u2134'), ('\u2139', '\u2139'), - ('\u213c', '\u213d'), ('\u2146', '\u2149'), - ('\u214e', '\u214e'), ('\u2184', '\u2184'), - ('\u2c30', '\u2c5e'), ('\u2c61', '\u2c61'), - ('\u2c65', '\u2c66'), ('\u2c68', '\u2c68'), - ('\u2c6a', '\u2c6a'), ('\u2c6c', '\u2c6c'), - ('\u2c71', '\u2c71'), ('\u2c73', '\u2c74'), - ('\u2c76', '\u2c7b'), ('\u2c81', '\u2c81'), - ('\u2c83', '\u2c83'), ('\u2c85', '\u2c85'), - ('\u2c87', '\u2c87'), ('\u2c89', '\u2c89'), - ('\u2c8b', '\u2c8b'), ('\u2c8d', '\u2c8d'), - ('\u2c8f', '\u2c8f'), ('\u2c91', '\u2c91'), - ('\u2c93', '\u2c93'), ('\u2c95', '\u2c95'), - ('\u2c97', '\u2c97'), ('\u2c99', '\u2c99'), - ('\u2c9b', '\u2c9b'), ('\u2c9d', '\u2c9d'), - ('\u2c9f', '\u2c9f'), ('\u2ca1', '\u2ca1'), - ('\u2ca3', '\u2ca3'), ('\u2ca5', '\u2ca5'), - ('\u2ca7', '\u2ca7'), ('\u2ca9', '\u2ca9'), - ('\u2cab', '\u2cab'), ('\u2cad', '\u2cad'), - ('\u2caf', '\u2caf'), ('\u2cb1', '\u2cb1'), - ('\u2cb3', '\u2cb3'), ('\u2cb5', '\u2cb5'), - ('\u2cb7', '\u2cb7'), ('\u2cb9', '\u2cb9'), - ('\u2cbb', '\u2cbb'), ('\u2cbd', '\u2cbd'), - ('\u2cbf', '\u2cbf'), ('\u2cc1', '\u2cc1'), - ('\u2cc3', '\u2cc3'), ('\u2cc5', '\u2cc5'), - ('\u2cc7', '\u2cc7'), ('\u2cc9', '\u2cc9'), - ('\u2ccb', '\u2ccb'), ('\u2ccd', '\u2ccd'), - ('\u2ccf', '\u2ccf'), ('\u2cd1', '\u2cd1'), - ('\u2cd3', '\u2cd3'), ('\u2cd5', '\u2cd5'), - ('\u2cd7', '\u2cd7'), ('\u2cd9', '\u2cd9'), - ('\u2cdb', '\u2cdb'), ('\u2cdd', '\u2cdd'), - ('\u2cdf', '\u2cdf'), ('\u2ce1', '\u2ce1'), - ('\u2ce3', '\u2ce4'), ('\u2cec', '\u2cec'), - ('\u2cee', '\u2cee'), ('\u2cf3', '\u2cf3'), - ('\u2d00', '\u2d2d'), ('\ua641', '\ua641'), - ('\ua643', '\ua643'), ('\ua645', '\ua645'), - ('\ua647', '\ua647'), ('\ua649', '\ua649'), - ('\ua64b', '\ua64b'), ('\ua64d', '\ua64d'), - ('\ua64f', '\ua64f'), ('\ua651', '\ua651'), - ('\ua653', '\ua653'), ('\ua655', '\ua655'), - ('\ua657', '\ua657'), ('\ua659', '\ua659'), - ('\ua65b', '\ua65b'), ('\ua65d', '\ua65d'), - ('\ua65f', '\ua65f'), ('\ua661', '\ua661'), - ('\ua663', '\ua663'), ('\ua665', '\ua665'), - ('\ua667', '\ua667'), ('\ua669', '\ua669'), - ('\ua66b', '\ua66b'), ('\ua66d', '\ua66d'), - ('\ua681', '\ua681'), ('\ua683', '\ua683'), - ('\ua685', '\ua685'), ('\ua687', '\ua687'), - ('\ua689', '\ua689'), ('\ua68b', '\ua68b'), - ('\ua68d', '\ua68d'), ('\ua68f', '\ua68f'), - ('\ua691', '\ua691'), ('\ua693', '\ua693'), - ('\ua695', '\ua695'), ('\ua697', '\ua697'), - ('\ua723', '\ua723'), ('\ua725', '\ua725'), - ('\ua727', '\ua727'), ('\ua729', '\ua729'), - ('\ua72b', '\ua72b'), ('\ua72d', '\ua72d'), - ('\ua72f', '\ua731'), ('\ua733', '\ua733'), - ('\ua735', '\ua735'), ('\ua737', '\ua737'), - ('\ua739', '\ua739'), ('\ua73b', '\ua73b'), - ('\ua73d', '\ua73d'), ('\ua73f', '\ua73f'), - ('\ua741', '\ua741'), ('\ua743', '\ua743'), - ('\ua745', '\ua745'), ('\ua747', '\ua747'), - ('\ua749', '\ua749'), ('\ua74b', '\ua74b'), - ('\ua74d', '\ua74d'), ('\ua74f', '\ua74f'), - ('\ua751', '\ua751'), ('\ua753', '\ua753'), - ('\ua755', '\ua755'), ('\ua757', '\ua757'), - ('\ua759', '\ua759'), ('\ua75b', '\ua75b'), - ('\ua75d', '\ua75d'), ('\ua75f', '\ua75f'), - ('\ua761', '\ua761'), ('\ua763', '\ua763'), - ('\ua765', '\ua765'), ('\ua767', '\ua767'), - ('\ua769', '\ua769'), ('\ua76b', '\ua76b'), - ('\ua76d', '\ua76d'), ('\ua76f', '\ua76f'), - ('\ua771', '\ua778'), ('\ua77a', '\ua77a'), - ('\ua77c', '\ua77c'), ('\ua77f', '\ua77f'), - ('\ua781', '\ua781'), ('\ua783', '\ua783'), - ('\ua785', '\ua785'), ('\ua787', '\ua787'), - ('\ua78c', '\ua78c'), ('\ua78e', '\ua78e'), - ('\ua791', '\ua791'), ('\ua793', '\ua793'), - ('\ua7a1', '\ua7a1'), ('\ua7a3', '\ua7a3'), - ('\ua7a5', '\ua7a5'), ('\ua7a7', '\ua7a7'), - ('\ua7a9', '\ua7a9'), ('\ua7fa', '\ua7fa'), - ('\ufb00', '\ufb17'), ('\uff41', '\uff5a'), - ('\U00010428', '\U0001044f'), ('\U0001d41a', '\U0001d433'), - ('\U0001d44e', '\U0001d467'), ('\U0001d482', '\U0001d49b'), - ('\U0001d4b6', '\U0001d4cf'), ('\U0001d4ea', '\U0001d503'), - ('\U0001d51e', '\U0001d537'), ('\U0001d552', '\U0001d56b'), - ('\U0001d586', '\U0001d59f'), ('\U0001d5ba', '\U0001d5d3'), - ('\U0001d5ee', '\U0001d607'), ('\U0001d622', '\U0001d63b'), - ('\U0001d656', '\U0001d66f'), ('\U0001d68a', '\U0001d6a5'), - ('\U0001d6c2', '\U0001d6da'), ('\U0001d6dc', '\U0001d6e1'), - ('\U0001d6fc', '\U0001d714'), ('\U0001d716', '\U0001d71b'), - ('\U0001d736', '\U0001d74e'), ('\U0001d750', '\U0001d755'), - ('\U0001d770', '\U0001d788'), ('\U0001d78a', '\U0001d78f'), - ('\U0001d7aa', '\U0001d7c2'), ('\U0001d7c4', '\U0001d7c9'), - ('\U0001d7cb', '\U0001d7cb') - ]; - - pub fn Ll(c: char) -> bool { - bsearch_range_table(c, Ll_table) - } - - static Lm_table : &'static [(char,char)] = &[ - ('\u02b0', '\u02c1'), ('\u02c6', '\u02d1'), - ('\u02e0', '\u02e4'), ('\u02ec', '\u02ec'), - ('\u02ee', '\u02ee'), ('\u0374', '\u0374'), - ('\u037a', '\u037a'), ('\u0559', '\u0559'), - ('\u0640', '\u0640'), ('\u06e5', '\u06e6'), - ('\u07f4', '\u07f5'), ('\u07fa', '\u07fa'), - ('\u081a', '\u081a'), ('\u0824', '\u0824'), - ('\u0828', '\u0828'), ('\u0971', '\u0971'), - ('\u0e46', '\u0e46'), ('\u0ec6', '\u0ec6'), - ('\u10fc', '\u10fc'), ('\u17d7', '\u17d7'), - ('\u1843', '\u1843'), ('\u1aa7', '\u1aa7'), - ('\u1c78', '\u1c7d'), ('\u1d2c', '\u1d6a'), - ('\u1d78', '\u1d78'), ('\u1d9b', '\u1dbf'), - ('\u2071', '\u2071'), ('\u207f', '\u207f'), - ('\u2090', '\u209c'), ('\u2c7c', '\u2c7d'), - ('\u2d6f', '\u2d6f'), ('\u2e2f', '\u2e2f'), - ('\u3005', '\u3005'), ('\u3031', '\u3035'), - ('\u303b', '\u303b'), ('\u309d', '\u309e'), - ('\u30fc', '\u30fe'), ('\ua015', '\ua015'), - ('\ua4f8', '\ua4fd'), ('\ua60c', '\ua60c'), - ('\ua67f', '\ua67f'), ('\ua717', '\ua71f'), - ('\ua770', '\ua770'), ('\ua788', '\ua788'), - ('\ua7f8', '\ua7f9'), ('\ua9cf', '\ua9cf'), - ('\uaa70', '\uaa70'), ('\uaadd', '\uaadd'), - ('\uaaf3', '\uaaf4'), ('\uff70', '\uff70'), - ('\uff9e', '\uff9f'), ('\U00016f93', '\U00016f9f') - ]; - - pub fn Lm(c: char) -> bool { - bsearch_range_table(c, Lm_table) - } - - static Lo_table : &'static [(char,char)] = &[ - ('\xaa', '\xaa'), ('\xba', '\xba'), - ('\u01bb', '\u01bb'), ('\u01c0', '\u01c3'), - ('\u0294', '\u0294'), ('\u05d0', '\u05f2'), - ('\u0620', '\u063f'), ('\u0641', '\u064a'), - ('\u066e', '\u066f'), ('\u0671', '\u06d3'), - ('\u06d5', '\u06d5'), ('\u06ee', '\u06ef'), - ('\u06fa', '\u06fc'), ('\u06ff', '\u06ff'), - ('\u0710', '\u0710'), ('\u0712', '\u072f'), - ('\u074d', '\u07a5'), ('\u07b1', '\u07b1'), - ('\u07ca', '\u07ea'), ('\u0800', '\u0815'), - ('\u0840', '\u0858'), ('\u08a0', '\u08ac'), - ('\u0904', '\u0939'), ('\u093d', '\u093d'), - ('\u0950', '\u0950'), ('\u0958', '\u0961'), - ('\u0972', '\u097f'), ('\u0985', '\u09b9'), - ('\u09bd', '\u09bd'), ('\u09ce', '\u09ce'), - ('\u09dc', '\u09e1'), ('\u09f0', '\u09f1'), - ('\u0a05', '\u0a39'), ('\u0a59', '\u0a5e'), - ('\u0a72', '\u0a74'), ('\u0a85', '\u0ab9'), - ('\u0abd', '\u0abd'), ('\u0ad0', '\u0ae1'), - ('\u0b05', '\u0b39'), ('\u0b3d', '\u0b3d'), - ('\u0b5c', '\u0b61'), ('\u0b71', '\u0b71'), - ('\u0b83', '\u0bb9'), ('\u0bd0', '\u0bd0'), - ('\u0c05', '\u0c3d'), ('\u0c58', '\u0c61'), - ('\u0c85', '\u0cb9'), ('\u0cbd', '\u0cbd'), - ('\u0cde', '\u0ce1'), ('\u0cf1', '\u0cf2'), - ('\u0d05', '\u0d3d'), ('\u0d4e', '\u0d4e'), - ('\u0d60', '\u0d61'), ('\u0d7a', '\u0d7f'), - ('\u0d85', '\u0dc6'), ('\u0e01', '\u0e30'), - ('\u0e32', '\u0e33'), ('\u0e40', '\u0e45'), - ('\u0e81', '\u0eb0'), ('\u0eb2', '\u0eb3'), - ('\u0ebd', '\u0ec4'), ('\u0edc', '\u0f00'), - ('\u0f40', '\u0f6c'), ('\u0f88', '\u0f8c'), - ('\u1000', '\u102a'), ('\u103f', '\u103f'), - ('\u1050', '\u1055'), ('\u105a', '\u105d'), - ('\u1061', '\u1061'), ('\u1065', '\u1066'), - ('\u106e', '\u1070'), ('\u1075', '\u1081'), - ('\u108e', '\u108e'), ('\u10d0', '\u10fa'), - ('\u10fd', '\u135a'), ('\u1380', '\u138f'), - ('\u13a0', '\u13f4'), ('\u1401', '\u166c'), - ('\u166f', '\u167f'), ('\u1681', '\u169a'), - ('\u16a0', '\u16ea'), ('\u1700', '\u1711'), - ('\u1720', '\u1731'), ('\u1740', '\u1751'), - ('\u1760', '\u1770'), ('\u1780', '\u17b3'), - ('\u17dc', '\u17dc'), ('\u1820', '\u1842'), - ('\u1844', '\u18a8'), ('\u18aa', '\u191c'), - ('\u1950', '\u19ab'), ('\u19c1', '\u19c7'), - ('\u1a00', '\u1a16'), ('\u1a20', '\u1a54'), - ('\u1b05', '\u1b33'), ('\u1b45', '\u1b4b'), - ('\u1b83', '\u1ba0'), ('\u1bae', '\u1baf'), - ('\u1bba', '\u1be5'), ('\u1c00', '\u1c23'), - ('\u1c4d', '\u1c4f'), ('\u1c5a', '\u1c77'), - ('\u1ce9', '\u1cec'), ('\u1cee', '\u1cf1'), - ('\u1cf5', '\u1cf6'), ('\u2135', '\u2138'), - ('\u2d30', '\u2d67'), ('\u2d80', '\u2dde'), - ('\u3006', '\u3006'), ('\u303c', '\u303c'), - ('\u3041', '\u3096'), ('\u309f', '\u309f'), - ('\u30a1', '\u30fa'), ('\u30ff', '\u318e'), - ('\u31a0', '\u31ba'), ('\u31f0', '\u31ff'), - ('\u3400', '\u4db5'), ('\u4e00', '\ua014'), - ('\ua016', '\ua48c'), ('\ua4d0', '\ua4f7'), - ('\ua500', '\ua60b'), ('\ua610', '\ua61f'), - ('\ua62a', '\ua62b'), ('\ua66e', '\ua66e'), - ('\ua6a0', '\ua6e5'), ('\ua7fb', '\ua801'), - ('\ua803', '\ua805'), ('\ua807', '\ua80a'), - ('\ua80c', '\ua822'), ('\ua840', '\ua873'), - ('\ua882', '\ua8b3'), ('\ua8f2', '\ua8f7'), - ('\ua8fb', '\ua8fb'), ('\ua90a', '\ua925'), - ('\ua930', '\ua946'), ('\ua960', '\ua97c'), - ('\ua984', '\ua9b2'), ('\uaa00', '\uaa28'), - ('\uaa40', '\uaa42'), ('\uaa44', '\uaa4b'), - ('\uaa60', '\uaa6f'), ('\uaa71', '\uaa76'), - ('\uaa7a', '\uaa7a'), ('\uaa80', '\uaaaf'), - ('\uaab1', '\uaab1'), ('\uaab5', '\uaab6'), - ('\uaab9', '\uaabd'), ('\uaac0', '\uaac0'), - ('\uaac2', '\uaadc'), ('\uaae0', '\uaaea'), - ('\uaaf2', '\uaaf2'), ('\uab01', '\uabe2'), - ('\uac00', '\ud7fb'), ('\uf900', '\ufad9'), - ('\ufb1d', '\ufb1d'), ('\ufb1f', '\ufb28'), - ('\ufb2a', '\ufbb1'), ('\ufbd3', '\ufd3d'), - ('\ufd50', '\ufdfb'), ('\ufe70', '\ufefc'), - ('\uff66', '\uff6f'), ('\uff71', '\uff9d'), - ('\uffa0', '\uffdc'), ('\U00010000', '\U000100fa'), - ('\U00010280', '\U0001031e'), ('\U00010330', '\U00010340'), - ('\U00010342', '\U00010349'), ('\U00010380', '\U0001039d'), - ('\U000103a0', '\U000103cf'), ('\U00010450', '\U0001049d'), - ('\U00010800', '\U00010855'), ('\U00010900', '\U00010915'), - ('\U00010920', '\U00010939'), ('\U00010980', '\U00010a00'), - ('\U00010a10', '\U00010a33'), ('\U00010a60', '\U00010a7c'), - ('\U00010b00', '\U00010b35'), ('\U00010b40', '\U00010b55'), - ('\U00010b60', '\U00010b72'), ('\U00010c00', '\U00010c48'), - ('\U00011003', '\U00011037'), ('\U00011083', '\U000110af'), - ('\U000110d0', '\U000110e8'), ('\U00011103', '\U00011126'), - ('\U00011183', '\U000111b2'), ('\U000111c1', '\U000111c4'), - ('\U00011680', '\U000116aa'), ('\U00012000', '\U0001236e'), - ('\U00013000', '\U00016f50'), ('\U0001b000', '\U0001b001'), - ('\U0001ee00', '\U0001eebb'), ('\U00020000', '\U0002fa1d') - ]; - - pub fn Lo(c: char) -> bool { - bsearch_range_table(c, Lo_table) - } - - static Lt_table : &'static [(char,char)] = &[ - ('\u01c5', '\u01c5'), ('\u01c8', '\u01c8'), - ('\u01cb', '\u01cb'), ('\u01f2', '\u01f2'), - ('\u1f88', '\u1f8f'), ('\u1f98', '\u1f9f'), - ('\u1fa8', '\u1faf'), ('\u1fbc', '\u1fbc'), - ('\u1fcc', '\u1fcc'), ('\u1ffc', '\u1ffc') - ]; - - pub fn Lt(c: char) -> bool { - bsearch_range_table(c, Lt_table) - } - - static Lu_table : &'static [(char,char)] = &[ - ('\x41', '\x5a'), ('\xc0', '\xd6'), - ('\xd8', '\xde'), ('\u0100', '\u0100'), - ('\u0102', '\u0102'), ('\u0104', '\u0104'), - ('\u0106', '\u0106'), ('\u0108', '\u0108'), - ('\u010a', '\u010a'), ('\u010c', '\u010c'), - ('\u010e', '\u010e'), ('\u0110', '\u0110'), - ('\u0112', '\u0112'), ('\u0114', '\u0114'), - ('\u0116', '\u0116'), ('\u0118', '\u0118'), - ('\u011a', '\u011a'), ('\u011c', '\u011c'), - ('\u011e', '\u011e'), ('\u0120', '\u0120'), - ('\u0122', '\u0122'), ('\u0124', '\u0124'), - ('\u0126', '\u0126'), ('\u0128', '\u0128'), - ('\u012a', '\u012a'), ('\u012c', '\u012c'), - ('\u012e', '\u012e'), ('\u0130', '\u0130'), - ('\u0132', '\u0132'), ('\u0134', '\u0134'), - ('\u0136', '\u0136'), ('\u0139', '\u0139'), - ('\u013b', '\u013b'), ('\u013d', '\u013d'), - ('\u013f', '\u013f'), ('\u0141', '\u0141'), - ('\u0143', '\u0143'), ('\u0145', '\u0145'), - ('\u0147', '\u0147'), ('\u014a', '\u014a'), - ('\u014c', '\u014c'), ('\u014e', '\u014e'), - ('\u0150', '\u0150'), ('\u0152', '\u0152'), - ('\u0154', '\u0154'), ('\u0156', '\u0156'), - ('\u0158', '\u0158'), ('\u015a', '\u015a'), - ('\u015c', '\u015c'), ('\u015e', '\u015e'), - ('\u0160', '\u0160'), ('\u0162', '\u0162'), - ('\u0164', '\u0164'), ('\u0166', '\u0166'), - ('\u0168', '\u0168'), ('\u016a', '\u016a'), - ('\u016c', '\u016c'), ('\u016e', '\u016e'), - ('\u0170', '\u0170'), ('\u0172', '\u0172'), - ('\u0174', '\u0174'), ('\u0176', '\u0176'), - ('\u0178', '\u0179'), ('\u017b', '\u017b'), - ('\u017d', '\u017d'), ('\u0181', '\u0182'), - ('\u0184', '\u0184'), ('\u0186', '\u0187'), - ('\u0189', '\u018b'), ('\u018e', '\u0191'), - ('\u0193', '\u0194'), ('\u0196', '\u0198'), - ('\u019c', '\u019d'), ('\u019f', '\u01a0'), - ('\u01a2', '\u01a2'), ('\u01a4', '\u01a4'), - ('\u01a6', '\u01a7'), ('\u01a9', '\u01a9'), - ('\u01ac', '\u01ac'), ('\u01ae', '\u01af'), - ('\u01b1', '\u01b3'), ('\u01b5', '\u01b5'), - ('\u01b7', '\u01b8'), ('\u01bc', '\u01bc'), - ('\u01c4', '\u01c4'), ('\u01c7', '\u01c7'), - ('\u01ca', '\u01ca'), ('\u01cd', '\u01cd'), - ('\u01cf', '\u01cf'), ('\u01d1', '\u01d1'), - ('\u01d3', '\u01d3'), ('\u01d5', '\u01d5'), - ('\u01d7', '\u01d7'), ('\u01d9', '\u01d9'), - ('\u01db', '\u01db'), ('\u01de', '\u01de'), - ('\u01e0', '\u01e0'), ('\u01e2', '\u01e2'), - ('\u01e4', '\u01e4'), ('\u01e6', '\u01e6'), - ('\u01e8', '\u01e8'), ('\u01ea', '\u01ea'), - ('\u01ec', '\u01ec'), ('\u01ee', '\u01ee'), - ('\u01f1', '\u01f1'), ('\u01f4', '\u01f4'), - ('\u01f6', '\u01f8'), ('\u01fa', '\u01fa'), - ('\u01fc', '\u01fc'), ('\u01fe', '\u01fe'), - ('\u0200', '\u0200'), ('\u0202', '\u0202'), - ('\u0204', '\u0204'), ('\u0206', '\u0206'), - ('\u0208', '\u0208'), ('\u020a', '\u020a'), - ('\u020c', '\u020c'), ('\u020e', '\u020e'), - ('\u0210', '\u0210'), ('\u0212', '\u0212'), - ('\u0214', '\u0214'), ('\u0216', '\u0216'), - ('\u0218', '\u0218'), ('\u021a', '\u021a'), - ('\u021c', '\u021c'), ('\u021e', '\u021e'), - ('\u0220', '\u0220'), ('\u0222', '\u0222'), - ('\u0224', '\u0224'), ('\u0226', '\u0226'), - ('\u0228', '\u0228'), ('\u022a', '\u022a'), - ('\u022c', '\u022c'), ('\u022e', '\u022e'), - ('\u0230', '\u0230'), ('\u0232', '\u0232'), - ('\u023a', '\u023b'), ('\u023d', '\u023e'), - ('\u0241', '\u0241'), ('\u0243', '\u0246'), - ('\u0248', '\u0248'), ('\u024a', '\u024a'), - ('\u024c', '\u024c'), ('\u024e', '\u024e'), - ('\u0370', '\u0370'), ('\u0372', '\u0372'), - ('\u0376', '\u0376'), ('\u0386', '\u0386'), - ('\u0388', '\u038f'), ('\u0391', '\u03ab'), - ('\u03cf', '\u03cf'), ('\u03d2', '\u03d4'), - ('\u03d8', '\u03d8'), ('\u03da', '\u03da'), - ('\u03dc', '\u03dc'), ('\u03de', '\u03de'), - ('\u03e0', '\u03e0'), ('\u03e2', '\u03e2'), - ('\u03e4', '\u03e4'), ('\u03e6', '\u03e6'), - ('\u03e8', '\u03e8'), ('\u03ea', '\u03ea'), - ('\u03ec', '\u03ec'), ('\u03ee', '\u03ee'), - ('\u03f4', '\u03f4'), ('\u03f7', '\u03f7'), - ('\u03f9', '\u03fa'), ('\u03fd', '\u042f'), - ('\u0460', '\u0460'), ('\u0462', '\u0462'), - ('\u0464', '\u0464'), ('\u0466', '\u0466'), - ('\u0468', '\u0468'), ('\u046a', '\u046a'), - ('\u046c', '\u046c'), ('\u046e', '\u046e'), - ('\u0470', '\u0470'), ('\u0472', '\u0472'), - ('\u0474', '\u0474'), ('\u0476', '\u0476'), - ('\u0478', '\u0478'), ('\u047a', '\u047a'), - ('\u047c', '\u047c'), ('\u047e', '\u047e'), - ('\u0480', '\u0480'), ('\u048a', '\u048a'), - ('\u048c', '\u048c'), ('\u048e', '\u048e'), - ('\u0490', '\u0490'), ('\u0492', '\u0492'), - ('\u0494', '\u0494'), ('\u0496', '\u0496'), - ('\u0498', '\u0498'), ('\u049a', '\u049a'), - ('\u049c', '\u049c'), ('\u049e', '\u049e'), - ('\u04a0', '\u04a0'), ('\u04a2', '\u04a2'), - ('\u04a4', '\u04a4'), ('\u04a6', '\u04a6'), - ('\u04a8', '\u04a8'), ('\u04aa', '\u04aa'), - ('\u04ac', '\u04ac'), ('\u04ae', '\u04ae'), - ('\u04b0', '\u04b0'), ('\u04b2', '\u04b2'), - ('\u04b4', '\u04b4'), ('\u04b6', '\u04b6'), - ('\u04b8', '\u04b8'), ('\u04ba', '\u04ba'), - ('\u04bc', '\u04bc'), ('\u04be', '\u04be'), - ('\u04c0', '\u04c1'), ('\u04c3', '\u04c3'), - ('\u04c5', '\u04c5'), ('\u04c7', '\u04c7'), - ('\u04c9', '\u04c9'), ('\u04cb', '\u04cb'), - ('\u04cd', '\u04cd'), ('\u04d0', '\u04d0'), - ('\u04d2', '\u04d2'), ('\u04d4', '\u04d4'), - ('\u04d6', '\u04d6'), ('\u04d8', '\u04d8'), - ('\u04da', '\u04da'), ('\u04dc', '\u04dc'), - ('\u04de', '\u04de'), ('\u04e0', '\u04e0'), - ('\u04e2', '\u04e2'), ('\u04e4', '\u04e4'), - ('\u04e6', '\u04e6'), ('\u04e8', '\u04e8'), - ('\u04ea', '\u04ea'), ('\u04ec', '\u04ec'), - ('\u04ee', '\u04ee'), ('\u04f0', '\u04f0'), - ('\u04f2', '\u04f2'), ('\u04f4', '\u04f4'), - ('\u04f6', '\u04f6'), ('\u04f8', '\u04f8'), - ('\u04fa', '\u04fa'), ('\u04fc', '\u04fc'), - ('\u04fe', '\u04fe'), ('\u0500', '\u0500'), - ('\u0502', '\u0502'), ('\u0504', '\u0504'), - ('\u0506', '\u0506'), ('\u0508', '\u0508'), - ('\u050a', '\u050a'), ('\u050c', '\u050c'), - ('\u050e', '\u050e'), ('\u0510', '\u0510'), - ('\u0512', '\u0512'), ('\u0514', '\u0514'), - ('\u0516', '\u0516'), ('\u0518', '\u0518'), - ('\u051a', '\u051a'), ('\u051c', '\u051c'), - ('\u051e', '\u051e'), ('\u0520', '\u0520'), - ('\u0522', '\u0522'), ('\u0524', '\u0524'), - ('\u0526', '\u0526'), ('\u0531', '\u0556'), - ('\u10a0', '\u10cd'), ('\u1e00', '\u1e00'), - ('\u1e02', '\u1e02'), ('\u1e04', '\u1e04'), - ('\u1e06', '\u1e06'), ('\u1e08', '\u1e08'), - ('\u1e0a', '\u1e0a'), ('\u1e0c', '\u1e0c'), - ('\u1e0e', '\u1e0e'), ('\u1e10', '\u1e10'), - ('\u1e12', '\u1e12'), ('\u1e14', '\u1e14'), - ('\u1e16', '\u1e16'), ('\u1e18', '\u1e18'), - ('\u1e1a', '\u1e1a'), ('\u1e1c', '\u1e1c'), - ('\u1e1e', '\u1e1e'), ('\u1e20', '\u1e20'), - ('\u1e22', '\u1e22'), ('\u1e24', '\u1e24'), - ('\u1e26', '\u1e26'), ('\u1e28', '\u1e28'), - ('\u1e2a', '\u1e2a'), ('\u1e2c', '\u1e2c'), - ('\u1e2e', '\u1e2e'), ('\u1e30', '\u1e30'), - ('\u1e32', '\u1e32'), ('\u1e34', '\u1e34'), - ('\u1e36', '\u1e36'), ('\u1e38', '\u1e38'), - ('\u1e3a', '\u1e3a'), ('\u1e3c', '\u1e3c'), - ('\u1e3e', '\u1e3e'), ('\u1e40', '\u1e40'), - ('\u1e42', '\u1e42'), ('\u1e44', '\u1e44'), - ('\u1e46', '\u1e46'), ('\u1e48', '\u1e48'), - ('\u1e4a', '\u1e4a'), ('\u1e4c', '\u1e4c'), - ('\u1e4e', '\u1e4e'), ('\u1e50', '\u1e50'), - ('\u1e52', '\u1e52'), ('\u1e54', '\u1e54'), - ('\u1e56', '\u1e56'), ('\u1e58', '\u1e58'), - ('\u1e5a', '\u1e5a'), ('\u1e5c', '\u1e5c'), - ('\u1e5e', '\u1e5e'), ('\u1e60', '\u1e60'), - ('\u1e62', '\u1e62'), ('\u1e64', '\u1e64'), - ('\u1e66', '\u1e66'), ('\u1e68', '\u1e68'), - ('\u1e6a', '\u1e6a'), ('\u1e6c', '\u1e6c'), - ('\u1e6e', '\u1e6e'), ('\u1e70', '\u1e70'), - ('\u1e72', '\u1e72'), ('\u1e74', '\u1e74'), - ('\u1e76', '\u1e76'), ('\u1e78', '\u1e78'), - ('\u1e7a', '\u1e7a'), ('\u1e7c', '\u1e7c'), - ('\u1e7e', '\u1e7e'), ('\u1e80', '\u1e80'), - ('\u1e82', '\u1e82'), ('\u1e84', '\u1e84'), - ('\u1e86', '\u1e86'), ('\u1e88', '\u1e88'), - ('\u1e8a', '\u1e8a'), ('\u1e8c', '\u1e8c'), - ('\u1e8e', '\u1e8e'), ('\u1e90', '\u1e90'), - ('\u1e92', '\u1e92'), ('\u1e94', '\u1e94'), - ('\u1e9e', '\u1e9e'), ('\u1ea0', '\u1ea0'), - ('\u1ea2', '\u1ea2'), ('\u1ea4', '\u1ea4'), - ('\u1ea6', '\u1ea6'), ('\u1ea8', '\u1ea8'), - ('\u1eaa', '\u1eaa'), ('\u1eac', '\u1eac'), - ('\u1eae', '\u1eae'), ('\u1eb0', '\u1eb0'), - ('\u1eb2', '\u1eb2'), ('\u1eb4', '\u1eb4'), - ('\u1eb6', '\u1eb6'), ('\u1eb8', '\u1eb8'), - ('\u1eba', '\u1eba'), ('\u1ebc', '\u1ebc'), - ('\u1ebe', '\u1ebe'), ('\u1ec0', '\u1ec0'), - ('\u1ec2', '\u1ec2'), ('\u1ec4', '\u1ec4'), - ('\u1ec6', '\u1ec6'), ('\u1ec8', '\u1ec8'), - ('\u1eca', '\u1eca'), ('\u1ecc', '\u1ecc'), - ('\u1ece', '\u1ece'), ('\u1ed0', '\u1ed0'), - ('\u1ed2', '\u1ed2'), ('\u1ed4', '\u1ed4'), - ('\u1ed6', '\u1ed6'), ('\u1ed8', '\u1ed8'), - ('\u1eda', '\u1eda'), ('\u1edc', '\u1edc'), - ('\u1ede', '\u1ede'), ('\u1ee0', '\u1ee0'), - ('\u1ee2', '\u1ee2'), ('\u1ee4', '\u1ee4'), - ('\u1ee6', '\u1ee6'), ('\u1ee8', '\u1ee8'), - ('\u1eea', '\u1eea'), ('\u1eec', '\u1eec'), - ('\u1eee', '\u1eee'), ('\u1ef0', '\u1ef0'), - ('\u1ef2', '\u1ef2'), ('\u1ef4', '\u1ef4'), - ('\u1ef6', '\u1ef6'), ('\u1ef8', '\u1ef8'), - ('\u1efa', '\u1efa'), ('\u1efc', '\u1efc'), - ('\u1efe', '\u1efe'), ('\u1f08', '\u1f0f'), - ('\u1f18', '\u1f1d'), ('\u1f28', '\u1f2f'), - ('\u1f38', '\u1f3f'), ('\u1f48', '\u1f4d'), - ('\u1f59', '\u1f5f'), ('\u1f68', '\u1f6f'), - ('\u1fb8', '\u1fbb'), ('\u1fc8', '\u1fcb'), - ('\u1fd8', '\u1fdb'), ('\u1fe8', '\u1fec'), - ('\u1ff8', '\u1ffb'), ('\u2102', '\u2102'), - ('\u2107', '\u2107'), ('\u210b', '\u210d'), - ('\u2110', '\u2112'), ('\u2115', '\u2115'), - ('\u2119', '\u211d'), ('\u2124', '\u2124'), - ('\u2126', '\u2126'), ('\u2128', '\u2128'), - ('\u212a', '\u212d'), ('\u2130', '\u2133'), - ('\u213e', '\u213f'), ('\u2145', '\u2145'), - ('\u2183', '\u2183'), ('\u2c00', '\u2c2e'), - ('\u2c60', '\u2c60'), ('\u2c62', '\u2c64'), - ('\u2c67', '\u2c67'), ('\u2c69', '\u2c69'), - ('\u2c6b', '\u2c6b'), ('\u2c6d', '\u2c70'), - ('\u2c72', '\u2c72'), ('\u2c75', '\u2c75'), - ('\u2c7e', '\u2c80'), ('\u2c82', '\u2c82'), - ('\u2c84', '\u2c84'), ('\u2c86', '\u2c86'), - ('\u2c88', '\u2c88'), ('\u2c8a', '\u2c8a'), - ('\u2c8c', '\u2c8c'), ('\u2c8e', '\u2c8e'), - ('\u2c90', '\u2c90'), ('\u2c92', '\u2c92'), - ('\u2c94', '\u2c94'), ('\u2c96', '\u2c96'), - ('\u2c98', '\u2c98'), ('\u2c9a', '\u2c9a'), - ('\u2c9c', '\u2c9c'), ('\u2c9e', '\u2c9e'), - ('\u2ca0', '\u2ca0'), ('\u2ca2', '\u2ca2'), - ('\u2ca4', '\u2ca4'), ('\u2ca6', '\u2ca6'), - ('\u2ca8', '\u2ca8'), ('\u2caa', '\u2caa'), - ('\u2cac', '\u2cac'), ('\u2cae', '\u2cae'), - ('\u2cb0', '\u2cb0'), ('\u2cb2', '\u2cb2'), - ('\u2cb4', '\u2cb4'), ('\u2cb6', '\u2cb6'), - ('\u2cb8', '\u2cb8'), ('\u2cba', '\u2cba'), - ('\u2cbc', '\u2cbc'), ('\u2cbe', '\u2cbe'), - ('\u2cc0', '\u2cc0'), ('\u2cc2', '\u2cc2'), - ('\u2cc4', '\u2cc4'), ('\u2cc6', '\u2cc6'), - ('\u2cc8', '\u2cc8'), ('\u2cca', '\u2cca'), - ('\u2ccc', '\u2ccc'), ('\u2cce', '\u2cce'), - ('\u2cd0', '\u2cd0'), ('\u2cd2', '\u2cd2'), - ('\u2cd4', '\u2cd4'), ('\u2cd6', '\u2cd6'), - ('\u2cd8', '\u2cd8'), ('\u2cda', '\u2cda'), - ('\u2cdc', '\u2cdc'), ('\u2cde', '\u2cde'), - ('\u2ce0', '\u2ce0'), ('\u2ce2', '\u2ce2'), - ('\u2ceb', '\u2ceb'), ('\u2ced', '\u2ced'), - ('\u2cf2', '\u2cf2'), ('\ua640', '\ua640'), - ('\ua642', '\ua642'), ('\ua644', '\ua644'), - ('\ua646', '\ua646'), ('\ua648', '\ua648'), - ('\ua64a', '\ua64a'), ('\ua64c', '\ua64c'), - ('\ua64e', '\ua64e'), ('\ua650', '\ua650'), - ('\ua652', '\ua652'), ('\ua654', '\ua654'), - ('\ua656', '\ua656'), ('\ua658', '\ua658'), - ('\ua65a', '\ua65a'), ('\ua65c', '\ua65c'), - ('\ua65e', '\ua65e'), ('\ua660', '\ua660'), - ('\ua662', '\ua662'), ('\ua664', '\ua664'), - ('\ua666', '\ua666'), ('\ua668', '\ua668'), - ('\ua66a', '\ua66a'), ('\ua66c', '\ua66c'), - ('\ua680', '\ua680'), ('\ua682', '\ua682'), - ('\ua684', '\ua684'), ('\ua686', '\ua686'), - ('\ua688', '\ua688'), ('\ua68a', '\ua68a'), - ('\ua68c', '\ua68c'), ('\ua68e', '\ua68e'), - ('\ua690', '\ua690'), ('\ua692', '\ua692'), - ('\ua694', '\ua694'), ('\ua696', '\ua696'), - ('\ua722', '\ua722'), ('\ua724', '\ua724'), - ('\ua726', '\ua726'), ('\ua728', '\ua728'), - ('\ua72a', '\ua72a'), ('\ua72c', '\ua72c'), - ('\ua72e', '\ua72e'), ('\ua732', '\ua732'), - ('\ua734', '\ua734'), ('\ua736', '\ua736'), - ('\ua738', '\ua738'), ('\ua73a', '\ua73a'), - ('\ua73c', '\ua73c'), ('\ua73e', '\ua73e'), - ('\ua740', '\ua740'), ('\ua742', '\ua742'), - ('\ua744', '\ua744'), ('\ua746', '\ua746'), - ('\ua748', '\ua748'), ('\ua74a', '\ua74a'), - ('\ua74c', '\ua74c'), ('\ua74e', '\ua74e'), - ('\ua750', '\ua750'), ('\ua752', '\ua752'), - ('\ua754', '\ua754'), ('\ua756', '\ua756'), - ('\ua758', '\ua758'), ('\ua75a', '\ua75a'), - ('\ua75c', '\ua75c'), ('\ua75e', '\ua75e'), - ('\ua760', '\ua760'), ('\ua762', '\ua762'), - ('\ua764', '\ua764'), ('\ua766', '\ua766'), - ('\ua768', '\ua768'), ('\ua76a', '\ua76a'), - ('\ua76c', '\ua76c'), ('\ua76e', '\ua76e'), - ('\ua779', '\ua779'), ('\ua77b', '\ua77b'), - ('\ua77d', '\ua77e'), ('\ua780', '\ua780'), - ('\ua782', '\ua782'), ('\ua784', '\ua784'), - ('\ua786', '\ua786'), ('\ua78b', '\ua78b'), - ('\ua78d', '\ua78d'), ('\ua790', '\ua790'), - ('\ua792', '\ua792'), ('\ua7a0', '\ua7a0'), - ('\ua7a2', '\ua7a2'), ('\ua7a4', '\ua7a4'), - ('\ua7a6', '\ua7a6'), ('\ua7a8', '\ua7a8'), - ('\ua7aa', '\ua7aa'), ('\uff21', '\uff3a'), - ('\U00010400', '\U00010427'), ('\U0001d400', '\U0001d419'), - ('\U0001d434', '\U0001d44d'), ('\U0001d468', '\U0001d481'), - ('\U0001d49c', '\U0001d4b5'), ('\U0001d4d0', '\U0001d4e9'), - ('\U0001d504', '\U0001d51c'), ('\U0001d538', '\U0001d550'), - ('\U0001d56c', '\U0001d585'), ('\U0001d5a0', '\U0001d5b9'), - ('\U0001d5d4', '\U0001d5ed'), ('\U0001d608', '\U0001d621'), - ('\U0001d63c', '\U0001d655'), ('\U0001d670', '\U0001d689'), - ('\U0001d6a8', '\U0001d6c0'), ('\U0001d6e2', '\U0001d6fa'), - ('\U0001d71c', '\U0001d734'), ('\U0001d756', '\U0001d76e'), - ('\U0001d790', '\U0001d7a8'), ('\U0001d7ca', '\U0001d7ca') - ]; - - pub fn Lu(c: char) -> bool { - bsearch_range_table(c, Lu_table) - } - - static Mc_table : &'static [(char,char)] = &[ - ('\u0903', '\u0903'), ('\u093b', '\u093b'), - ('\u093e', '\u0940'), ('\u0949', '\u094c'), - ('\u094e', '\u094f'), ('\u0982', '\u0983'), - ('\u09be', '\u09c0'), ('\u09c7', '\u09cc'), - ('\u09d7', '\u09d7'), ('\u0a03', '\u0a03'), - ('\u0a3e', '\u0a40'), ('\u0a83', '\u0a83'), - ('\u0abe', '\u0ac0'), ('\u0ac9', '\u0acc'), - ('\u0b02', '\u0b03'), ('\u0b3e', '\u0b3e'), - ('\u0b40', '\u0b40'), ('\u0b47', '\u0b4c'), - ('\u0b57', '\u0b57'), ('\u0bbe', '\u0bbf'), - ('\u0bc1', '\u0bcc'), ('\u0bd7', '\u0bd7'), - ('\u0c01', '\u0c03'), ('\u0c41', '\u0c44'), - ('\u0c82', '\u0c83'), ('\u0cbe', '\u0cbe'), - ('\u0cc0', '\u0cc4'), ('\u0cc7', '\u0ccb'), - ('\u0cd5', '\u0cd6'), ('\u0d02', '\u0d03'), - ('\u0d3e', '\u0d40'), ('\u0d46', '\u0d4c'), - ('\u0d57', '\u0d57'), ('\u0d82', '\u0d83'), - ('\u0dcf', '\u0dd1'), ('\u0dd8', '\u0df3'), - ('\u0f3e', '\u0f3f'), ('\u0f7f', '\u0f7f'), - ('\u102b', '\u102c'), ('\u1031', '\u1031'), - ('\u1038', '\u1038'), ('\u103b', '\u103c'), - ('\u1056', '\u1057'), ('\u1062', '\u1064'), - ('\u1067', '\u106d'), ('\u1083', '\u1084'), - ('\u1087', '\u108c'), ('\u108f', '\u108f'), - ('\u109a', '\u109c'), ('\u17b6', '\u17b6'), - ('\u17be', '\u17c5'), ('\u17c7', '\u17c8'), - ('\u1923', '\u1926'), ('\u1929', '\u1931'), - ('\u1933', '\u1938'), ('\u19b0', '\u19c0'), - ('\u19c8', '\u19c9'), ('\u1a19', '\u1a1b'), - ('\u1a55', '\u1a55'), ('\u1a57', '\u1a57'), - ('\u1a61', '\u1a61'), ('\u1a63', '\u1a64'), - ('\u1a6d', '\u1a72'), ('\u1b04', '\u1b04'), - ('\u1b35', '\u1b35'), ('\u1b3b', '\u1b3b'), - ('\u1b3d', '\u1b41'), ('\u1b43', '\u1b44'), - ('\u1b82', '\u1b82'), ('\u1ba1', '\u1ba1'), - ('\u1ba6', '\u1ba7'), ('\u1baa', '\u1baa'), - ('\u1bac', '\u1bad'), ('\u1be7', '\u1be7'), - ('\u1bea', '\u1bec'), ('\u1bee', '\u1bee'), - ('\u1bf2', '\u1bf3'), ('\u1c24', '\u1c2b'), - ('\u1c34', '\u1c35'), ('\u1ce1', '\u1ce1'), - ('\u1cf2', '\u1cf3'), ('\u302e', '\u302f'), - ('\ua823', '\ua824'), ('\ua827', '\ua827'), - ('\ua880', '\ua881'), ('\ua8b4', '\ua8c3'), - ('\ua952', '\ua953'), ('\ua983', '\ua983'), - ('\ua9b4', '\ua9b5'), ('\ua9ba', '\ua9bb'), - ('\ua9bd', '\ua9c0'), ('\uaa2f', '\uaa30'), - ('\uaa33', '\uaa34'), ('\uaa4d', '\uaa4d'), - ('\uaa7b', '\uaa7b'), ('\uaaeb', '\uaaeb'), - ('\uaaee', '\uaaef'), ('\uaaf5', '\uaaf5'), - ('\uabe3', '\uabe4'), ('\uabe6', '\uabe7'), - ('\uabe9', '\uabea'), ('\uabec', '\uabec'), - ('\U00011000', '\U00011000'), ('\U00011002', '\U00011002'), - ('\U00011082', '\U00011082'), ('\U000110b0', '\U000110b2'), - ('\U000110b7', '\U000110b8'), ('\U0001112c', '\U0001112c'), - ('\U00011182', '\U00011182'), ('\U000111b3', '\U000111b5'), - ('\U000111bf', '\U000111c0'), ('\U000116ac', '\U000116ac'), - ('\U000116ae', '\U000116af'), ('\U000116b6', '\U000116b6'), - ('\U00016f51', '\U00016f7e'), ('\U0001d165', '\U0001d166'), - ('\U0001d16d', '\U0001d172') - ]; - - pub fn Mc(c: char) -> bool { - bsearch_range_table(c, Mc_table) - } - - static Me_table : &'static [(char,char)] = &[ - ('\u0488', '\u0489'), ('\u20dd', '\u20e0'), - ('\u20e2', '\u20e4'), ('\ua670', '\ua672') - ]; - - pub fn Me(c: char) -> bool { - bsearch_range_table(c, Me_table) - } - - static Mn_table : &'static [(char,char)] = &[ - ('\u0300', '\u036f'), ('\u0483', '\u0487'), - ('\u0591', '\u05bd'), ('\u05bf', '\u05bf'), - ('\u05c1', '\u05c2'), ('\u05c4', '\u05c5'), - ('\u05c7', '\u05c7'), ('\u0610', '\u061a'), - ('\u064b', '\u065f'), ('\u0670', '\u0670'), - ('\u06d6', '\u06dc'), ('\u06df', '\u06e4'), - ('\u06e7', '\u06e8'), ('\u06ea', '\u06ed'), - ('\u0711', '\u0711'), ('\u0730', '\u074a'), - ('\u07a6', '\u07b0'), ('\u07eb', '\u07f3'), - ('\u0816', '\u0819'), ('\u081b', '\u0823'), - ('\u0825', '\u0827'), ('\u0829', '\u082d'), - ('\u0859', '\u085b'), ('\u08e4', '\u0902'), - ('\u093a', '\u093a'), ('\u093c', '\u093c'), - ('\u0941', '\u0948'), ('\u094d', '\u094d'), - ('\u0951', '\u0957'), ('\u0962', '\u0963'), - ('\u0981', '\u0981'), ('\u09bc', '\u09bc'), - ('\u09c1', '\u09c4'), ('\u09cd', '\u09cd'), - ('\u09e2', '\u09e3'), ('\u0a01', '\u0a02'), - ('\u0a3c', '\u0a3c'), ('\u0a41', '\u0a51'), - ('\u0a70', '\u0a71'), ('\u0a75', '\u0a82'), - ('\u0abc', '\u0abc'), ('\u0ac1', '\u0ac8'), - ('\u0acd', '\u0acd'), ('\u0ae2', '\u0ae3'), - ('\u0b01', '\u0b01'), ('\u0b3c', '\u0b3c'), - ('\u0b3f', '\u0b3f'), ('\u0b41', '\u0b44'), - ('\u0b4d', '\u0b56'), ('\u0b62', '\u0b63'), - ('\u0b82', '\u0b82'), ('\u0bc0', '\u0bc0'), - ('\u0bcd', '\u0bcd'), ('\u0c3e', '\u0c40'), - ('\u0c46', '\u0c56'), ('\u0c62', '\u0c63'), - ('\u0cbc', '\u0cbc'), ('\u0cbf', '\u0cbf'), - ('\u0cc6', '\u0cc6'), ('\u0ccc', '\u0ccd'), - ('\u0ce2', '\u0ce3'), ('\u0d41', '\u0d44'), - ('\u0d4d', '\u0d4d'), ('\u0d62', '\u0d63'), - ('\u0dca', '\u0dca'), ('\u0dd2', '\u0dd6'), - ('\u0e31', '\u0e31'), ('\u0e34', '\u0e3a'), - ('\u0e47', '\u0e4e'), ('\u0eb1', '\u0eb1'), - ('\u0eb4', '\u0ebc'), ('\u0ec8', '\u0ecd'), - ('\u0f18', '\u0f19'), ('\u0f35', '\u0f35'), - ('\u0f37', '\u0f37'), ('\u0f39', '\u0f39'), - ('\u0f71', '\u0f7e'), ('\u0f80', '\u0f84'), - ('\u0f86', '\u0f87'), ('\u0f8d', '\u0fbc'), - ('\u0fc6', '\u0fc6'), ('\u102d', '\u1030'), - ('\u1032', '\u1037'), ('\u1039', '\u103a'), - ('\u103d', '\u103e'), ('\u1058', '\u1059'), - ('\u105e', '\u1060'), ('\u1071', '\u1074'), - ('\u1082', '\u1082'), ('\u1085', '\u1086'), - ('\u108d', '\u108d'), ('\u109d', '\u109d'), - ('\u135d', '\u135f'), ('\u1712', '\u1714'), - ('\u1732', '\u1734'), ('\u1752', '\u1753'), - ('\u1772', '\u1773'), ('\u17b4', '\u17b5'), - ('\u17b7', '\u17bd'), ('\u17c6', '\u17c6'), - ('\u17c9', '\u17d3'), ('\u17dd', '\u17dd'), - ('\u180b', '\u180d'), ('\u18a9', '\u18a9'), - ('\u1920', '\u1922'), ('\u1927', '\u1928'), - ('\u1932', '\u1932'), ('\u1939', '\u193b'), - ('\u1a17', '\u1a18'), ('\u1a56', '\u1a56'), - ('\u1a58', '\u1a60'), ('\u1a62', '\u1a62'), - ('\u1a65', '\u1a6c'), ('\u1a73', '\u1a7f'), - ('\u1b00', '\u1b03'), ('\u1b34', '\u1b34'), - ('\u1b36', '\u1b3a'), ('\u1b3c', '\u1b3c'), - ('\u1b42', '\u1b42'), ('\u1b6b', '\u1b73'), - ('\u1b80', '\u1b81'), ('\u1ba2', '\u1ba5'), - ('\u1ba8', '\u1ba9'), ('\u1bab', '\u1bab'), - ('\u1be6', '\u1be6'), ('\u1be8', '\u1be9'), - ('\u1bed', '\u1bed'), ('\u1bef', '\u1bf1'), - ('\u1c2c', '\u1c33'), ('\u1c36', '\u1c37'), - ('\u1cd0', '\u1cd2'), ('\u1cd4', '\u1ce0'), - ('\u1ce2', '\u1ce8'), ('\u1ced', '\u1ced'), - ('\u1cf4', '\u1cf4'), ('\u1dc0', '\u1dff'), - ('\u20d0', '\u20dc'), ('\u20e1', '\u20e1'), - ('\u20e5', '\u20f0'), ('\u2cef', '\u2cf1'), - ('\u2d7f', '\u2d7f'), ('\u2de0', '\u2dff'), - ('\u302a', '\u302d'), ('\u3099', '\u309a'), - ('\ua66f', '\ua66f'), ('\ua674', '\ua67d'), - ('\ua69f', '\ua69f'), ('\ua6f0', '\ua6f1'), - ('\ua802', '\ua802'), ('\ua806', '\ua806'), - ('\ua80b', '\ua80b'), ('\ua825', '\ua826'), - ('\ua8c4', '\ua8c4'), ('\ua8e0', '\ua8f1'), - ('\ua926', '\ua92d'), ('\ua947', '\ua951'), - ('\ua980', '\ua982'), ('\ua9b3', '\ua9b3'), - ('\ua9b6', '\ua9b9'), ('\ua9bc', '\ua9bc'), - ('\uaa29', '\uaa2e'), ('\uaa31', '\uaa32'), - ('\uaa35', '\uaa36'), ('\uaa43', '\uaa43'), - ('\uaa4c', '\uaa4c'), ('\uaab0', '\uaab0'), - ('\uaab2', '\uaab4'), ('\uaab7', '\uaab8'), - ('\uaabe', '\uaabf'), ('\uaac1', '\uaac1'), - ('\uaaec', '\uaaed'), ('\uaaf6', '\uaaf6'), - ('\uabe5', '\uabe5'), ('\uabe8', '\uabe8'), - ('\uabed', '\uabed'), ('\ufb1e', '\ufb1e'), - ('\ufe00', '\ufe0f'), ('\ufe20', '\ufe26'), - ('\U000101fd', '\U000101fd'), ('\U00010a01', '\U00010a0f'), - ('\U00010a38', '\U00010a3f'), ('\U00011001', '\U00011001'), - ('\U00011038', '\U00011046'), ('\U00011080', '\U00011081'), - ('\U000110b3', '\U000110b6'), ('\U000110b9', '\U000110ba'), - ('\U00011100', '\U00011102'), ('\U00011127', '\U0001112b'), - ('\U0001112d', '\U00011134'), ('\U00011180', '\U00011181'), - ('\U000111b6', '\U000111be'), ('\U000116ab', '\U000116ab'), - ('\U000116ad', '\U000116ad'), ('\U000116b0', '\U000116b5'), - ('\U000116b7', '\U000116b7'), ('\U00016f8f', '\U00016f92'), - ('\U0001d167', '\U0001d169'), ('\U0001d17b', '\U0001d182'), - ('\U0001d185', '\U0001d18b'), ('\U0001d1aa', '\U0001d1ad'), - ('\U0001d242', '\U0001d244'), ('\U000e0100', '\U000e01ef') - ]; - - pub fn Mn(c: char) -> bool { - bsearch_range_table(c, Mn_table) - } - - static Nd_table : &'static [(char,char)] = &[ - ('\x30', '\x39'), ('\u0660', '\u0669'), - ('\u06f0', '\u06f9'), ('\u07c0', '\u07c9'), - ('\u0966', '\u096f'), ('\u09e6', '\u09ef'), - ('\u0a66', '\u0a6f'), ('\u0ae6', '\u0aef'), - ('\u0b66', '\u0b6f'), ('\u0be6', '\u0bef'), - ('\u0c66', '\u0c6f'), ('\u0ce6', '\u0cef'), - ('\u0d66', '\u0d6f'), ('\u0e50', '\u0e59'), - ('\u0ed0', '\u0ed9'), ('\u0f20', '\u0f29'), - ('\u1040', '\u1049'), ('\u1090', '\u1099'), - ('\u17e0', '\u17e9'), ('\u1810', '\u1819'), - ('\u1946', '\u194f'), ('\u19d0', '\u19d9'), - ('\u1a80', '\u1a99'), ('\u1b50', '\u1b59'), - ('\u1bb0', '\u1bb9'), ('\u1c40', '\u1c49'), - ('\u1c50', '\u1c59'), ('\ua620', '\ua629'), - ('\ua8d0', '\ua8d9'), ('\ua900', '\ua909'), - ('\ua9d0', '\ua9d9'), ('\uaa50', '\uaa59'), - ('\uabf0', '\uabf9'), ('\uff10', '\uff19'), - ('\U000104a0', '\U000104a9'), ('\U00011066', '\U0001106f'), - ('\U000110f0', '\U000110f9'), ('\U00011136', '\U0001113f'), - ('\U000111d0', '\U000111d9'), ('\U000116c0', '\U000116c9'), - ('\U0001d7ce', '\U0001d7ff') - ]; - - pub fn Nd(c: char) -> bool { - bsearch_range_table(c, Nd_table) - } - - static Nl_table : &'static [(char,char)] = &[ - ('\u16ee', '\u16f0'), ('\u2160', '\u2182'), - ('\u2185', '\u2188'), ('\u3007', '\u3007'), - ('\u3021', '\u3029'), ('\u3038', '\u303a'), - ('\ua6e6', '\ua6ef'), ('\U00010140', '\U00010174'), - ('\U00010341', '\U00010341'), ('\U0001034a', '\U0001034a'), - ('\U000103d1', '\U000103d5'), ('\U00012400', '\U00012462') - ]; - - pub fn Nl(c: char) -> bool { - bsearch_range_table(c, Nl_table) - } - - static No_table : &'static [(char,char)] = &[ - ('\xb2', '\xb3'), ('\xb9', '\xb9'), - ('\xbc', '\xbe'), ('\u09f4', '\u09f9'), - ('\u0b72', '\u0b77'), ('\u0bf0', '\u0bf2'), - ('\u0c78', '\u0c7e'), ('\u0d70', '\u0d75'), - ('\u0f2a', '\u0f33'), ('\u1369', '\u137c'), - ('\u17f0', '\u17f9'), ('\u19da', '\u19da'), - ('\u2070', '\u2070'), ('\u2074', '\u2079'), - ('\u2080', '\u2089'), ('\u2150', '\u215f'), - ('\u2189', '\u2189'), ('\u2460', '\u249b'), - ('\u24ea', '\u24ff'), ('\u2776', '\u2793'), - ('\u2cfd', '\u2cfd'), ('\u3192', '\u3195'), - ('\u3220', '\u3229'), ('\u3248', '\u324f'), - ('\u3251', '\u325f'), ('\u3280', '\u3289'), - ('\u32b1', '\u32bf'), ('\ua830', '\ua835'), - ('\U00010107', '\U00010133'), ('\U00010175', '\U00010178'), - ('\U0001018a', '\U0001018a'), ('\U00010320', '\U00010323'), - ('\U00010858', '\U0001085f'), ('\U00010916', '\U0001091b'), - ('\U00010a40', '\U00010a47'), ('\U00010a7d', '\U00010a7e'), - ('\U00010b58', '\U00010b5f'), ('\U00010b78', '\U00010b7f'), - ('\U00010e60', '\U00010e7e'), ('\U00011052', '\U00011065'), - ('\U0001d360', '\U0001d371'), ('\U0001f100', '\U0001f10a') - ]; - - pub fn No(c: char) -> bool { - bsearch_range_table(c, No_table) - } - - static Pc_table : &'static [(char,char)] = &[ - ('\x5f', '\x5f'), ('\u203f', '\u2040'), - ('\u2054', '\u2054'), ('\ufe33', '\ufe34'), - ('\ufe4d', '\ufe4f'), ('\uff3f', '\uff3f') - ]; - - pub fn Pc(c: char) -> bool { - bsearch_range_table(c, Pc_table) - } - - static Pd_table : &'static [(char,char)] = &[ - ('\x2d', '\x2d'), ('\u058a', '\u058a'), - ('\u05be', '\u05be'), ('\u1400', '\u1400'), - ('\u1806', '\u1806'), ('\u2010', '\u2015'), - ('\u2e17', '\u2e17'), ('\u2e1a', '\u2e1a'), - ('\u2e3a', '\u2e3b'), ('\u301c', '\u301c'), - ('\u3030', '\u3030'), ('\u30a0', '\u30a0'), - ('\ufe31', '\ufe32'), ('\ufe58', '\ufe58'), - ('\ufe63', '\ufe63'), ('\uff0d', '\uff0d') - ]; - - pub fn Pd(c: char) -> bool { - bsearch_range_table(c, Pd_table) - } - - static Pe_table : &'static [(char,char)] = &[ - ('\x29', '\x29'), ('\x5d', '\x5d'), - ('\x7d', '\x7d'), ('\u0f3b', '\u0f3b'), - ('\u0f3d', '\u0f3d'), ('\u169c', '\u169c'), - ('\u2046', '\u2046'), ('\u207e', '\u207e'), - ('\u208e', '\u208e'), ('\u232a', '\u232a'), - ('\u2769', '\u2769'), ('\u276b', '\u276b'), - ('\u276d', '\u276d'), ('\u276f', '\u276f'), - ('\u2771', '\u2771'), ('\u2773', '\u2773'), - ('\u2775', '\u2775'), ('\u27c6', '\u27c6'), - ('\u27e7', '\u27e7'), ('\u27e9', '\u27e9'), - ('\u27eb', '\u27eb'), ('\u27ed', '\u27ed'), - ('\u27ef', '\u27ef'), ('\u2984', '\u2984'), - ('\u2986', '\u2986'), ('\u2988', '\u2988'), - ('\u298a', '\u298a'), ('\u298c', '\u298c'), - ('\u298e', '\u298e'), ('\u2990', '\u2990'), - ('\u2992', '\u2992'), ('\u2994', '\u2994'), - ('\u2996', '\u2996'), ('\u2998', '\u2998'), - ('\u29d9', '\u29d9'), ('\u29db', '\u29db'), - ('\u29fd', '\u29fd'), ('\u2e23', '\u2e23'), - ('\u2e25', '\u2e25'), ('\u2e27', '\u2e27'), - ('\u2e29', '\u2e29'), ('\u3009', '\u3009'), - ('\u300b', '\u300b'), ('\u300d', '\u300d'), - ('\u300f', '\u300f'), ('\u3011', '\u3011'), - ('\u3015', '\u3015'), ('\u3017', '\u3017'), - ('\u3019', '\u3019'), ('\u301b', '\u301b'), - ('\u301e', '\u301f'), ('\ufd3f', '\ufd3f'), - ('\ufe18', '\ufe18'), ('\ufe36', '\ufe36'), - ('\ufe38', '\ufe38'), ('\ufe3a', '\ufe3a'), - ('\ufe3c', '\ufe3c'), ('\ufe3e', '\ufe3e'), - ('\ufe40', '\ufe40'), ('\ufe42', '\ufe42'), - ('\ufe44', '\ufe44'), ('\ufe48', '\ufe48'), - ('\ufe5a', '\ufe5a'), ('\ufe5c', '\ufe5c'), - ('\ufe5e', '\ufe5e'), ('\uff09', '\uff09'), - ('\uff3d', '\uff3d'), ('\uff5d', '\uff5d'), - ('\uff60', '\uff60'), ('\uff63', '\uff63') - ]; - - pub fn Pe(c: char) -> bool { - bsearch_range_table(c, Pe_table) - } - - static Pf_table : &'static [(char,char)] = &[ - ('\xbb', '\xbb'), ('\u2019', '\u2019'), - ('\u201d', '\u201d'), ('\u203a', '\u203a'), - ('\u2e03', '\u2e03'), ('\u2e05', '\u2e05'), - ('\u2e0a', '\u2e0a'), ('\u2e0d', '\u2e0d'), - ('\u2e1d', '\u2e1d'), ('\u2e21', '\u2e21') - ]; - - pub fn Pf(c: char) -> bool { - bsearch_range_table(c, Pf_table) - } - - static Pi_table : &'static [(char,char)] = &[ - ('\xab', '\xab'), ('\u2018', '\u2018'), - ('\u201b', '\u201c'), ('\u201f', '\u201f'), - ('\u2039', '\u2039'), ('\u2e02', '\u2e02'), - ('\u2e04', '\u2e04'), ('\u2e09', '\u2e09'), - ('\u2e0c', '\u2e0c'), ('\u2e1c', '\u2e1c'), - ('\u2e20', '\u2e20') - ]; - - pub fn Pi(c: char) -> bool { - bsearch_range_table(c, Pi_table) - } - - static Po_table : &'static [(char,char)] = &[ - ('\x21', '\x23'), ('\x25', '\x27'), - ('\x2a', '\x2a'), ('\x2c', '\x2c'), - ('\x2e', '\x2f'), ('\x3a', '\x3b'), - ('\x3f', '\x40'), ('\x5c', '\x5c'), - ('\xa1', '\xa1'), ('\xa7', '\xa7'), - ('\xb6', '\xb7'), ('\xbf', '\xbf'), - ('\u037e', '\u037e'), ('\u0387', '\u0387'), - ('\u055a', '\u055f'), ('\u0589', '\u0589'), - ('\u05c0', '\u05c0'), ('\u05c3', '\u05c3'), - ('\u05c6', '\u05c6'), ('\u05f3', '\u05f4'), - ('\u0609', '\u060a'), ('\u060c', '\u060d'), - ('\u061b', '\u061f'), ('\u066a', '\u066d'), - ('\u06d4', '\u06d4'), ('\u0700', '\u070d'), - ('\u07f7', '\u07f9'), ('\u0830', '\u083e'), - ('\u085e', '\u085e'), ('\u0964', '\u0965'), - ('\u0970', '\u0970'), ('\u0af0', '\u0af0'), - ('\u0df4', '\u0df4'), ('\u0e4f', '\u0e4f'), - ('\u0e5a', '\u0e5b'), ('\u0f04', '\u0f12'), - ('\u0f14', '\u0f14'), ('\u0f85', '\u0f85'), - ('\u0fd0', '\u0fd4'), ('\u0fd9', '\u0fda'), - ('\u104a', '\u104f'), ('\u10fb', '\u10fb'), - ('\u1360', '\u1368'), ('\u166d', '\u166e'), - ('\u16eb', '\u16ed'), ('\u1735', '\u1736'), - ('\u17d4', '\u17d6'), ('\u17d8', '\u17da'), - ('\u1800', '\u1805'), ('\u1807', '\u180a'), - ('\u1944', '\u1945'), ('\u1a1e', '\u1a1f'), - ('\u1aa0', '\u1aa6'), ('\u1aa8', '\u1aad'), - ('\u1b5a', '\u1b60'), ('\u1bfc', '\u1bff'), - ('\u1c3b', '\u1c3f'), ('\u1c7e', '\u1cc7'), - ('\u1cd3', '\u1cd3'), ('\u2016', '\u2017'), - ('\u2020', '\u2027'), ('\u2030', '\u2038'), - ('\u203b', '\u203e'), ('\u2041', '\u2043'), - ('\u2047', '\u2051'), ('\u2053', '\u2053'), - ('\u2055', '\u205e'), ('\u2cf9', '\u2cfc'), - ('\u2cfe', '\u2cff'), ('\u2d70', '\u2d70'), - ('\u2e00', '\u2e01'), ('\u2e06', '\u2e08'), - ('\u2e0b', '\u2e0b'), ('\u2e0e', '\u2e16'), - ('\u2e18', '\u2e19'), ('\u2e1b', '\u2e1b'), - ('\u2e1e', '\u2e1f'), ('\u2e2a', '\u2e2e'), - ('\u2e30', '\u2e39'), ('\u3001', '\u3003'), - ('\u303d', '\u303d'), ('\u30fb', '\u30fb'), - ('\ua4fe', '\ua4ff'), ('\ua60d', '\ua60f'), - ('\ua673', '\ua673'), ('\ua67e', '\ua67e'), - ('\ua6f2', '\ua6f7'), ('\ua874', '\ua877'), - ('\ua8ce', '\ua8cf'), ('\ua8f8', '\ua8fa'), - ('\ua92e', '\ua92f'), ('\ua95f', '\ua95f'), - ('\ua9c1', '\ua9cd'), ('\ua9de', '\ua9df'), - ('\uaa5c', '\uaa5f'), ('\uaade', '\uaadf'), - ('\uaaf0', '\uaaf1'), ('\uabeb', '\uabeb'), - ('\ufe10', '\ufe16'), ('\ufe19', '\ufe19'), - ('\ufe30', '\ufe30'), ('\ufe45', '\ufe46'), - ('\ufe49', '\ufe4c'), ('\ufe50', '\ufe57'), - ('\ufe5f', '\ufe61'), ('\ufe68', '\ufe68'), - ('\ufe6a', '\ufe6b'), ('\uff01', '\uff03'), - ('\uff05', '\uff07'), ('\uff0a', '\uff0a'), - ('\uff0c', '\uff0c'), ('\uff0e', '\uff0f'), - ('\uff1a', '\uff1b'), ('\uff1f', '\uff20'), - ('\uff3c', '\uff3c'), ('\uff61', '\uff61'), - ('\uff64', '\uff65'), ('\U00010100', '\U00010102'), - ('\U0001039f', '\U0001039f'), ('\U000103d0', '\U000103d0'), - ('\U00010857', '\U00010857'), ('\U0001091f', '\U0001091f'), - ('\U0001093f', '\U0001093f'), ('\U00010a50', '\U00010a58'), - ('\U00010a7f', '\U00010a7f'), ('\U00010b39', '\U00010b3f'), - ('\U00011047', '\U0001104d'), ('\U000110bb', '\U000110bc'), - ('\U000110be', '\U000110c1'), ('\U00011140', '\U00011143'), - ('\U000111c5', '\U000111c8'), ('\U00012470', '\U00012473') - ]; - - pub fn Po(c: char) -> bool { - bsearch_range_table(c, Po_table) - } - - static Ps_table : &'static [(char,char)] = &[ - ('\x28', '\x28'), ('\x5b', '\x5b'), - ('\x7b', '\x7b'), ('\u0f3a', '\u0f3a'), - ('\u0f3c', '\u0f3c'), ('\u169b', '\u169b'), - ('\u201a', '\u201a'), ('\u201e', '\u201e'), - ('\u2045', '\u2045'), ('\u207d', '\u207d'), - ('\u208d', '\u208d'), ('\u2329', '\u2329'), - ('\u2768', '\u2768'), ('\u276a', '\u276a'), - ('\u276c', '\u276c'), ('\u276e', '\u276e'), - ('\u2770', '\u2770'), ('\u2772', '\u2772'), - ('\u2774', '\u2774'), ('\u27c5', '\u27c5'), - ('\u27e6', '\u27e6'), ('\u27e8', '\u27e8'), - ('\u27ea', '\u27ea'), ('\u27ec', '\u27ec'), - ('\u27ee', '\u27ee'), ('\u2983', '\u2983'), - ('\u2985', '\u2985'), ('\u2987', '\u2987'), - ('\u2989', '\u2989'), ('\u298b', '\u298b'), - ('\u298d', '\u298d'), ('\u298f', '\u298f'), - ('\u2991', '\u2991'), ('\u2993', '\u2993'), - ('\u2995', '\u2995'), ('\u2997', '\u2997'), - ('\u29d8', '\u29d8'), ('\u29da', '\u29da'), - ('\u29fc', '\u29fc'), ('\u2e22', '\u2e22'), - ('\u2e24', '\u2e24'), ('\u2e26', '\u2e26'), - ('\u2e28', '\u2e28'), ('\u3008', '\u3008'), - ('\u300a', '\u300a'), ('\u300c', '\u300c'), - ('\u300e', '\u300e'), ('\u3010', '\u3010'), - ('\u3014', '\u3014'), ('\u3016', '\u3016'), - ('\u3018', '\u3018'), ('\u301a', '\u301a'), - ('\u301d', '\u301d'), ('\ufd3e', '\ufd3e'), - ('\ufe17', '\ufe17'), ('\ufe35', '\ufe35'), - ('\ufe37', '\ufe37'), ('\ufe39', '\ufe39'), - ('\ufe3b', '\ufe3b'), ('\ufe3d', '\ufe3d'), - ('\ufe3f', '\ufe3f'), ('\ufe41', '\ufe41'), - ('\ufe43', '\ufe43'), ('\ufe47', '\ufe47'), - ('\ufe59', '\ufe59'), ('\ufe5b', '\ufe5b'), - ('\ufe5d', '\ufe5d'), ('\uff08', '\uff08'), - ('\uff3b', '\uff3b'), ('\uff5b', '\uff5b'), - ('\uff5f', '\uff5f'), ('\uff62', '\uff62') - ]; - - pub fn Ps(c: char) -> bool { - bsearch_range_table(c, Ps_table) - } - - static Sc_table : &'static [(char,char)] = &[ - ('\x24', '\x24'), ('\xa2', '\xa5'), - ('\u058f', '\u058f'), ('\u060b', '\u060b'), - ('\u09f2', '\u09f3'), ('\u09fb', '\u09fb'), - ('\u0af1', '\u0af1'), ('\u0bf9', '\u0bf9'), - ('\u0e3f', '\u0e3f'), ('\u17db', '\u17db'), - ('\u20a0', '\u20ba'), ('\ua838', '\ua838'), - ('\ufdfc', '\ufdfc'), ('\ufe69', '\ufe69'), - ('\uff04', '\uff04'), ('\uffe0', '\uffe1'), - ('\uffe5', '\uffe6') - ]; - - pub fn Sc(c: char) -> bool { - bsearch_range_table(c, Sc_table) - } - - static Sk_table : &'static [(char,char)] = &[ - ('\x5e', '\x5e'), ('\x60', '\x60'), - ('\xa8', '\xa8'), ('\xaf', '\xaf'), - ('\xb4', '\xb4'), ('\xb8', '\xb8'), - ('\u02c2', '\u02c5'), ('\u02d2', '\u02df'), - ('\u02e5', '\u02eb'), ('\u02ed', '\u02ed'), - ('\u02ef', '\u02ff'), ('\u0375', '\u0375'), - ('\u0384', '\u0385'), ('\u1fbd', '\u1fbd'), - ('\u1fbf', '\u1fc1'), ('\u1fcd', '\u1fcf'), - ('\u1fdd', '\u1fdf'), ('\u1fed', '\u1fef'), - ('\u1ffd', '\u1ffe'), ('\u309b', '\u309c'), - ('\ua700', '\ua716'), ('\ua720', '\ua721'), - ('\ua789', '\ua78a'), ('\ufbb2', '\ufbc1'), - ('\uff3e', '\uff3e'), ('\uff40', '\uff40'), - ('\uffe3', '\uffe3') - ]; - - pub fn Sk(c: char) -> bool { - bsearch_range_table(c, Sk_table) - } - - static Sm_table : &'static [(char,char)] = &[ - ('\x2b', '\x2b'), ('\x3c', '\x3e'), - ('\x7c', '\x7c'), ('\x7e', '\x7e'), - ('\xac', '\xac'), ('\xb1', '\xb1'), - ('\xd7', '\xd7'), ('\xf7', '\xf7'), - ('\u03f6', '\u03f6'), ('\u0606', '\u0608'), - ('\u2044', '\u2044'), ('\u2052', '\u2052'), - ('\u207a', '\u207c'), ('\u208a', '\u208c'), - ('\u2118', '\u2118'), ('\u2140', '\u2144'), - ('\u214b', '\u214b'), ('\u2190', '\u2194'), - ('\u219a', '\u219b'), ('\u21a0', '\u21a0'), - ('\u21a3', '\u21a3'), ('\u21a6', '\u21a6'), - ('\u21ae', '\u21ae'), ('\u21ce', '\u21cf'), - ('\u21d2', '\u21d2'), ('\u21d4', '\u21d4'), - ('\u21f4', '\u22ff'), ('\u2308', '\u230b'), - ('\u2320', '\u2321'), ('\u237c', '\u237c'), - ('\u239b', '\u23b3'), ('\u23dc', '\u23e1'), - ('\u25b7', '\u25b7'), ('\u25c1', '\u25c1'), - ('\u25f8', '\u25ff'), ('\u266f', '\u266f'), - ('\u27c0', '\u27c4'), ('\u27c7', '\u27e5'), - ('\u27f0', '\u27ff'), ('\u2900', '\u2982'), - ('\u2999', '\u29d7'), ('\u29dc', '\u29fb'), - ('\u29fe', '\u2aff'), ('\u2b30', '\u2b44'), - ('\u2b47', '\u2b4c'), ('\ufb29', '\ufb29'), - ('\ufe62', '\ufe62'), ('\ufe64', '\ufe66'), - ('\uff0b', '\uff0b'), ('\uff1c', '\uff1e'), - ('\uff5c', '\uff5c'), ('\uff5e', '\uff5e'), - ('\uffe2', '\uffe2'), ('\uffe9', '\uffec'), - ('\U0001d6c1', '\U0001d6c1'), ('\U0001d6db', '\U0001d6db'), - ('\U0001d6fb', '\U0001d6fb'), ('\U0001d715', '\U0001d715'), - ('\U0001d735', '\U0001d735'), ('\U0001d74f', '\U0001d74f'), - ('\U0001d76f', '\U0001d76f'), ('\U0001d789', '\U0001d789'), - ('\U0001d7a9', '\U0001d7a9'), ('\U0001d7c3', '\U0001d7c3'), - ('\U0001eef0', '\U0001eef1') - ]; - - pub fn Sm(c: char) -> bool { - bsearch_range_table(c, Sm_table) - } - - static So_table : &'static [(char,char)] = &[ - ('\xa6', '\xa6'), ('\xa9', '\xa9'), - ('\xae', '\xae'), ('\xb0', '\xb0'), - ('\u0482', '\u0482'), ('\u060e', '\u060f'), - ('\u06de', '\u06de'), ('\u06e9', '\u06e9'), - ('\u06fd', '\u06fe'), ('\u07f6', '\u07f6'), - ('\u09fa', '\u09fa'), ('\u0b70', '\u0b70'), - ('\u0bf3', '\u0bf8'), ('\u0bfa', '\u0bfa'), - ('\u0c7f', '\u0c7f'), ('\u0d79', '\u0d79'), - ('\u0f01', '\u0f03'), ('\u0f13', '\u0f13'), - ('\u0f15', '\u0f17'), ('\u0f1a', '\u0f1f'), - ('\u0f34', '\u0f34'), ('\u0f36', '\u0f36'), - ('\u0f38', '\u0f38'), ('\u0fbe', '\u0fc5'), - ('\u0fc7', '\u0fcf'), ('\u0fd5', '\u0fd8'), - ('\u109e', '\u109f'), ('\u1390', '\u1399'), - ('\u1940', '\u1940'), ('\u19de', '\u19ff'), - ('\u1b61', '\u1b6a'), ('\u1b74', '\u1b7c'), - ('\u2100', '\u2101'), ('\u2103', '\u2106'), - ('\u2108', '\u2109'), ('\u2114', '\u2114'), - ('\u2116', '\u2117'), ('\u211e', '\u2123'), - ('\u2125', '\u2125'), ('\u2127', '\u2127'), - ('\u2129', '\u2129'), ('\u212e', '\u212e'), - ('\u213a', '\u213b'), ('\u214a', '\u214a'), - ('\u214c', '\u214d'), ('\u214f', '\u214f'), - ('\u2195', '\u2199'), ('\u219c', '\u219f'), - ('\u21a1', '\u21a2'), ('\u21a4', '\u21a5'), - ('\u21a7', '\u21ad'), ('\u21af', '\u21cd'), - ('\u21d0', '\u21d1'), ('\u21d3', '\u21d3'), - ('\u21d5', '\u21f3'), ('\u2300', '\u2307'), - ('\u230c', '\u231f'), ('\u2322', '\u2328'), - ('\u232b', '\u237b'), ('\u237d', '\u239a'), - ('\u23b4', '\u23db'), ('\u23e2', '\u244a'), - ('\u249c', '\u24e9'), ('\u2500', '\u25b6'), - ('\u25b8', '\u25c0'), ('\u25c2', '\u25f7'), - ('\u2600', '\u266e'), ('\u2670', '\u2767'), - ('\u2794', '\u27bf'), ('\u2800', '\u28ff'), - ('\u2b00', '\u2b2f'), ('\u2b45', '\u2b46'), - ('\u2b50', '\u2b59'), ('\u2ce5', '\u2cea'), - ('\u2e80', '\u2ffb'), ('\u3004', '\u3004'), - ('\u3012', '\u3013'), ('\u3020', '\u3020'), - ('\u3036', '\u3037'), ('\u303e', '\u303f'), - ('\u3190', '\u3191'), ('\u3196', '\u319f'), - ('\u31c0', '\u31e3'), ('\u3200', '\u321e'), - ('\u322a', '\u3247'), ('\u3250', '\u3250'), - ('\u3260', '\u327f'), ('\u328a', '\u32b0'), - ('\u32c0', '\u33ff'), ('\u4dc0', '\u4dff'), - ('\ua490', '\ua4c6'), ('\ua828', '\ua82b'), - ('\ua836', '\ua837'), ('\ua839', '\ua839'), - ('\uaa77', '\uaa79'), ('\ufdfd', '\ufdfd'), - ('\uffe4', '\uffe4'), ('\uffe8', '\uffe8'), - ('\uffed', '\uffee'), ('\ufffc', '\ufffd'), - ('\U00010137', '\U0001013f'), ('\U00010179', '\U00010189'), - ('\U00010190', '\U000101fc'), ('\U0001d000', '\U0001d164'), - ('\U0001d16a', '\U0001d16c'), ('\U0001d183', '\U0001d184'), - ('\U0001d18c', '\U0001d1a9'), ('\U0001d1ae', '\U0001d241'), - ('\U0001d245', '\U0001d356'), ('\U0001f000', '\U0001f0df'), - ('\U0001f110', '\U0001f773') - ]; - - pub fn So(c: char) -> bool { - bsearch_range_table(c, So_table) - } - - static Zl_table : &'static [(char,char)] = &[ - ('\u2028', '\u2028') - ]; - - pub fn Zl(c: char) -> bool { - bsearch_range_table(c, Zl_table) - } - - static Zp_table : &'static [(char,char)] = &[ - ('\u2029', '\u2029') - ]; - - pub fn Zp(c: char) -> bool { - bsearch_range_table(c, Zp_table) - } - - static Zs_table : &'static [(char,char)] = &[ - ('\x20', '\x20'), ('\xa0', '\xa0'), - ('\u1680', '\u1680'), ('\u180e', '\u180e'), - ('\u2000', '\u200a'), ('\u202f', '\u202f'), - ('\u205f', '\u205f'), ('\u3000', '\u3000') - ]; - - pub fn Zs(c: char) -> bool { - bsearch_range_table(c, Zs_table) - } - -} - -pub mod derived_property { - - - fn bsearch_range_table(c: char, r: &'static [(char,char)]) -> bool { - use cmp::{Equal, Less, Greater}; - use vec::bsearch; - use option::None; - (do bsearch(r) |&(lo,hi)| { - if lo <= c && c <= hi { Equal } - else if hi < c { Less } - else { Greater } - }) != None - } - - - static Alphabetic_table : &'static [(char,char)] = &[ - ('\x41', '\x5a'), ('\x61', '\x7a'), - ('\xaa', '\xaa'), ('\xb5', '\xb5'), - ('\xba', '\xba'), ('\xc0', '\xd6'), - ('\xd8', '\xf6'), ('\xf8', '\u01ba'), - ('\u01bb', '\u01bb'), ('\u01bc', '\u01bf'), - ('\u01c0', '\u01c3'), ('\u01c4', '\u0293'), - ('\u0294', '\u0294'), ('\u0295', '\u02af'), - ('\u02b0', '\u02c1'), ('\u02c6', '\u02d1'), - ('\u02e0', '\u02e4'), ('\u02ec', '\u02ec'), - ('\u02ee', '\u02ee'), ('\u0345', '\u0345'), - ('\u0370', '\u0373'), ('\u0374', '\u0374'), - ('\u0376', '\u0377'), ('\u037a', '\u037a'), - ('\u037b', '\u037d'), ('\u0386', '\u0386'), - ('\u0388', '\u038a'), ('\u038c', '\u038c'), - ('\u038e', '\u03a1'), ('\u03a3', '\u03f5'), - ('\u03f7', '\u0481'), ('\u048a', '\u0527'), - ('\u0531', '\u0556'), ('\u0559', '\u0559'), - ('\u0561', '\u0587'), ('\u05b0', '\u05bd'), - ('\u05bf', '\u05bf'), ('\u05c1', '\u05c2'), - ('\u05c4', '\u05c5'), ('\u05c7', '\u05c7'), - ('\u05d0', '\u05ea'), ('\u05f0', '\u05f2'), - ('\u0610', '\u061a'), ('\u0620', '\u063f'), - ('\u0640', '\u0640'), ('\u0641', '\u064a'), - ('\u064b', '\u0657'), ('\u0659', '\u065f'), - ('\u066e', '\u066f'), ('\u0670', '\u0670'), - ('\u0671', '\u06d3'), ('\u06d5', '\u06d5'), - ('\u06d6', '\u06dc'), ('\u06e1', '\u06e4'), - ('\u06e5', '\u06e6'), ('\u06e7', '\u06e8'), - ('\u06ed', '\u06ed'), ('\u06ee', '\u06ef'), - ('\u06fa', '\u06fc'), ('\u06ff', '\u06ff'), - ('\u0710', '\u0710'), ('\u0711', '\u0711'), - ('\u0712', '\u072f'), ('\u0730', '\u073f'), - ('\u074d', '\u07a5'), ('\u07a6', '\u07b0'), - ('\u07b1', '\u07b1'), ('\u07ca', '\u07ea'), - ('\u07f4', '\u07f5'), ('\u07fa', '\u07fa'), - ('\u0800', '\u0815'), ('\u0816', '\u0817'), - ('\u081a', '\u081a'), ('\u081b', '\u0823'), - ('\u0824', '\u0824'), ('\u0825', '\u0827'), - ('\u0828', '\u0828'), ('\u0829', '\u082c'), - ('\u0840', '\u0858'), ('\u08a0', '\u08a0'), - ('\u08a2', '\u08ac'), ('\u08e4', '\u08e9'), - ('\u08f0', '\u08fe'), ('\u0900', '\u0902'), - ('\u0903', '\u0903'), ('\u0904', '\u0939'), - ('\u093a', '\u093a'), ('\u093b', '\u093b'), - ('\u093d', '\u093d'), ('\u093e', '\u0940'), - ('\u0941', '\u0948'), ('\u0949', '\u094c'), - ('\u094e', '\u094f'), ('\u0950', '\u0950'), - ('\u0955', '\u0957'), ('\u0958', '\u0961'), - ('\u0962', '\u0963'), ('\u0971', '\u0971'), - ('\u0972', '\u0977'), ('\u0979', '\u097f'), - ('\u0981', '\u0981'), ('\u0982', '\u0983'), - ('\u0985', '\u098c'), ('\u098f', '\u0990'), - ('\u0993', '\u09a8'), ('\u09aa', '\u09b0'), - ('\u09b2', '\u09b2'), ('\u09b6', '\u09b9'), - ('\u09bd', '\u09bd'), ('\u09be', '\u09c0'), - ('\u09c1', '\u09c4'), ('\u09c7', '\u09c8'), - ('\u09cb', '\u09cc'), ('\u09ce', '\u09ce'), - ('\u09d7', '\u09d7'), ('\u09dc', '\u09dd'), - ('\u09df', '\u09e1'), ('\u09e2', '\u09e3'), - ('\u09f0', '\u09f1'), ('\u0a01', '\u0a02'), - ('\u0a03', '\u0a03'), ('\u0a05', '\u0a0a'), - ('\u0a0f', '\u0a10'), ('\u0a13', '\u0a28'), - ('\u0a2a', '\u0a30'), ('\u0a32', '\u0a33'), - ('\u0a35', '\u0a36'), ('\u0a38', '\u0a39'), - ('\u0a3e', '\u0a40'), ('\u0a41', '\u0a42'), - ('\u0a47', '\u0a48'), ('\u0a4b', '\u0a4c'), - ('\u0a51', '\u0a51'), ('\u0a59', '\u0a5c'), - ('\u0a5e', '\u0a5e'), ('\u0a70', '\u0a71'), - ('\u0a72', '\u0a74'), ('\u0a75', '\u0a75'), - ('\u0a81', '\u0a82'), ('\u0a83', '\u0a83'), - ('\u0a85', '\u0a8d'), ('\u0a8f', '\u0a91'), - ('\u0a93', '\u0aa8'), ('\u0aaa', '\u0ab0'), - ('\u0ab2', '\u0ab3'), ('\u0ab5', '\u0ab9'), - ('\u0abd', '\u0abd'), ('\u0abe', '\u0ac0'), - ('\u0ac1', '\u0ac5'), ('\u0ac7', '\u0ac8'), - ('\u0ac9', '\u0ac9'), ('\u0acb', '\u0acc'), - ('\u0ad0', '\u0ad0'), ('\u0ae0', '\u0ae1'), - ('\u0ae2', '\u0ae3'), ('\u0b01', '\u0b01'), - ('\u0b02', '\u0b03'), ('\u0b05', '\u0b0c'), - ('\u0b0f', '\u0b10'), ('\u0b13', '\u0b28'), - ('\u0b2a', '\u0b30'), ('\u0b32', '\u0b33'), - ('\u0b35', '\u0b39'), ('\u0b3d', '\u0b3d'), - ('\u0b3e', '\u0b3e'), ('\u0b3f', '\u0b3f'), - ('\u0b40', '\u0b40'), ('\u0b41', '\u0b44'), - ('\u0b47', '\u0b48'), ('\u0b4b', '\u0b4c'), - ('\u0b56', '\u0b56'), ('\u0b57', '\u0b57'), - ('\u0b5c', '\u0b5d'), ('\u0b5f', '\u0b61'), - ('\u0b62', '\u0b63'), ('\u0b71', '\u0b71'), - ('\u0b82', '\u0b82'), ('\u0b83', '\u0b83'), - ('\u0b85', '\u0b8a'), ('\u0b8e', '\u0b90'), - ('\u0b92', '\u0b95'), ('\u0b99', '\u0b9a'), - ('\u0b9c', '\u0b9c'), ('\u0b9e', '\u0b9f'), - ('\u0ba3', '\u0ba4'), ('\u0ba8', '\u0baa'), - ('\u0bae', '\u0bb9'), ('\u0bbe', '\u0bbf'), - ('\u0bc0', '\u0bc0'), ('\u0bc1', '\u0bc2'), - ('\u0bc6', '\u0bc8'), ('\u0bca', '\u0bcc'), - ('\u0bd0', '\u0bd0'), ('\u0bd7', '\u0bd7'), - ('\u0c01', '\u0c03'), ('\u0c05', '\u0c0c'), - ('\u0c0e', '\u0c10'), ('\u0c12', '\u0c28'), - ('\u0c2a', '\u0c33'), ('\u0c35', '\u0c39'), - ('\u0c3d', '\u0c3d'), ('\u0c3e', '\u0c40'), - ('\u0c41', '\u0c44'), ('\u0c46', '\u0c48'), - ('\u0c4a', '\u0c4c'), ('\u0c55', '\u0c56'), - ('\u0c58', '\u0c59'), ('\u0c60', '\u0c61'), - ('\u0c62', '\u0c63'), ('\u0c82', '\u0c83'), - ('\u0c85', '\u0c8c'), ('\u0c8e', '\u0c90'), - ('\u0c92', '\u0ca8'), ('\u0caa', '\u0cb3'), - ('\u0cb5', '\u0cb9'), ('\u0cbd', '\u0cbd'), - ('\u0cbe', '\u0cbe'), ('\u0cbf', '\u0cbf'), - ('\u0cc0', '\u0cc4'), ('\u0cc6', '\u0cc6'), - ('\u0cc7', '\u0cc8'), ('\u0cca', '\u0ccb'), - ('\u0ccc', '\u0ccc'), ('\u0cd5', '\u0cd6'), - ('\u0cde', '\u0cde'), ('\u0ce0', '\u0ce1'), - ('\u0ce2', '\u0ce3'), ('\u0cf1', '\u0cf2'), - ('\u0d02', '\u0d03'), ('\u0d05', '\u0d0c'), - ('\u0d0e', '\u0d10'), ('\u0d12', '\u0d3a'), - ('\u0d3d', '\u0d3d'), ('\u0d3e', '\u0d40'), - ('\u0d41', '\u0d44'), ('\u0d46', '\u0d48'), - ('\u0d4a', '\u0d4c'), ('\u0d4e', '\u0d4e'), - ('\u0d57', '\u0d57'), ('\u0d60', '\u0d61'), - ('\u0d62', '\u0d63'), ('\u0d7a', '\u0d7f'), - ('\u0d82', '\u0d83'), ('\u0d85', '\u0d96'), - ('\u0d9a', '\u0db1'), ('\u0db3', '\u0dbb'), - ('\u0dbd', '\u0dbd'), ('\u0dc0', '\u0dc6'), - ('\u0dcf', '\u0dd1'), ('\u0dd2', '\u0dd4'), - ('\u0dd6', '\u0dd6'), ('\u0dd8', '\u0ddf'), - ('\u0df2', '\u0df3'), ('\u0e01', '\u0e30'), - ('\u0e31', '\u0e31'), ('\u0e32', '\u0e33'), - ('\u0e34', '\u0e3a'), ('\u0e40', '\u0e45'), - ('\u0e46', '\u0e46'), ('\u0e4d', '\u0e4d'), - ('\u0e81', '\u0e82'), ('\u0e84', '\u0e84'), - ('\u0e87', '\u0e88'), ('\u0e8a', '\u0e8a'), - ('\u0e8d', '\u0e8d'), ('\u0e94', '\u0e97'), - ('\u0e99', '\u0e9f'), ('\u0ea1', '\u0ea3'), - ('\u0ea5', '\u0ea5'), ('\u0ea7', '\u0ea7'), - ('\u0eaa', '\u0eab'), ('\u0ead', '\u0eb0'), - ('\u0eb1', '\u0eb1'), ('\u0eb2', '\u0eb3'), - ('\u0eb4', '\u0eb9'), ('\u0ebb', '\u0ebc'), - ('\u0ebd', '\u0ebd'), ('\u0ec0', '\u0ec4'), - ('\u0ec6', '\u0ec6'), ('\u0ecd', '\u0ecd'), - ('\u0edc', '\u0edf'), ('\u0f00', '\u0f00'), - ('\u0f40', '\u0f47'), ('\u0f49', '\u0f6c'), - ('\u0f71', '\u0f7e'), ('\u0f7f', '\u0f7f'), - ('\u0f80', '\u0f81'), ('\u0f88', '\u0f8c'), - ('\u0f8d', '\u0f97'), ('\u0f99', '\u0fbc'), - ('\u1000', '\u102a'), ('\u102b', '\u102c'), - ('\u102d', '\u1030'), ('\u1031', '\u1031'), - ('\u1032', '\u1036'), ('\u1038', '\u1038'), - ('\u103b', '\u103c'), ('\u103d', '\u103e'), - ('\u103f', '\u103f'), ('\u1050', '\u1055'), - ('\u1056', '\u1057'), ('\u1058', '\u1059'), - ('\u105a', '\u105d'), ('\u105e', '\u1060'), - ('\u1061', '\u1061'), ('\u1062', '\u1062'), - ('\u1065', '\u1066'), ('\u1067', '\u1068'), - ('\u106e', '\u1070'), ('\u1071', '\u1074'), - ('\u1075', '\u1081'), ('\u1082', '\u1082'), - ('\u1083', '\u1084'), ('\u1085', '\u1086'), - ('\u108e', '\u108e'), ('\u109c', '\u109c'), - ('\u109d', '\u109d'), ('\u10a0', '\u10c5'), - ('\u10c7', '\u10c7'), ('\u10cd', '\u10cd'), - ('\u10d0', '\u10fa'), ('\u10fc', '\u10fc'), - ('\u10fd', '\u1248'), ('\u124a', '\u124d'), - ('\u1250', '\u1256'), ('\u1258', '\u1258'), - ('\u125a', '\u125d'), ('\u1260', '\u1288'), - ('\u128a', '\u128d'), ('\u1290', '\u12b0'), - ('\u12b2', '\u12b5'), ('\u12b8', '\u12be'), - ('\u12c0', '\u12c0'), ('\u12c2', '\u12c5'), - ('\u12c8', '\u12d6'), ('\u12d8', '\u1310'), - ('\u1312', '\u1315'), ('\u1318', '\u135a'), - ('\u135f', '\u135f'), ('\u1380', '\u138f'), - ('\u13a0', '\u13f4'), ('\u1401', '\u166c'), - ('\u166f', '\u167f'), ('\u1681', '\u169a'), - ('\u16a0', '\u16ea'), ('\u16ee', '\u16f0'), - ('\u1700', '\u170c'), ('\u170e', '\u1711'), - ('\u1712', '\u1713'), ('\u1720', '\u1731'), - ('\u1732', '\u1733'), ('\u1740', '\u1751'), - ('\u1752', '\u1753'), ('\u1760', '\u176c'), - ('\u176e', '\u1770'), ('\u1772', '\u1773'), - ('\u1780', '\u17b3'), ('\u17b6', '\u17b6'), - ('\u17b7', '\u17bd'), ('\u17be', '\u17c5'), - ('\u17c6', '\u17c6'), ('\u17c7', '\u17c8'), - ('\u17d7', '\u17d7'), ('\u17dc', '\u17dc'), - ('\u1820', '\u1842'), ('\u1843', '\u1843'), - ('\u1844', '\u1877'), ('\u1880', '\u18a8'), - ('\u18a9', '\u18a9'), ('\u18aa', '\u18aa'), - ('\u18b0', '\u18f5'), ('\u1900', '\u191c'), - ('\u1920', '\u1922'), ('\u1923', '\u1926'), - ('\u1927', '\u1928'), ('\u1929', '\u192b'), - ('\u1930', '\u1931'), ('\u1932', '\u1932'), - ('\u1933', '\u1938'), ('\u1950', '\u196d'), - ('\u1970', '\u1974'), ('\u1980', '\u19ab'), - ('\u19b0', '\u19c0'), ('\u19c1', '\u19c7'), - ('\u19c8', '\u19c9'), ('\u1a00', '\u1a16'), - ('\u1a17', '\u1a18'), ('\u1a19', '\u1a1b'), - ('\u1a20', '\u1a54'), ('\u1a55', '\u1a55'), - ('\u1a56', '\u1a56'), ('\u1a57', '\u1a57'), - ('\u1a58', '\u1a5e'), ('\u1a61', '\u1a61'), - ('\u1a62', '\u1a62'), ('\u1a63', '\u1a64'), - ('\u1a65', '\u1a6c'), ('\u1a6d', '\u1a72'), - ('\u1a73', '\u1a74'), ('\u1aa7', '\u1aa7'), - ('\u1b00', '\u1b03'), ('\u1b04', '\u1b04'), - ('\u1b05', '\u1b33'), ('\u1b35', '\u1b35'), - ('\u1b36', '\u1b3a'), ('\u1b3b', '\u1b3b'), - ('\u1b3c', '\u1b3c'), ('\u1b3d', '\u1b41'), - ('\u1b42', '\u1b42'), ('\u1b43', '\u1b43'), - ('\u1b45', '\u1b4b'), ('\u1b80', '\u1b81'), - ('\u1b82', '\u1b82'), ('\u1b83', '\u1ba0'), - ('\u1ba1', '\u1ba1'), ('\u1ba2', '\u1ba5'), - ('\u1ba6', '\u1ba7'), ('\u1ba8', '\u1ba9'), - ('\u1bac', '\u1bad'), ('\u1bae', '\u1baf'), - ('\u1bba', '\u1be5'), ('\u1be7', '\u1be7'), - ('\u1be8', '\u1be9'), ('\u1bea', '\u1bec'), - ('\u1bed', '\u1bed'), ('\u1bee', '\u1bee'), - ('\u1bef', '\u1bf1'), ('\u1c00', '\u1c23'), - ('\u1c24', '\u1c2b'), ('\u1c2c', '\u1c33'), - ('\u1c34', '\u1c35'), ('\u1c4d', '\u1c4f'), - ('\u1c5a', '\u1c77'), ('\u1c78', '\u1c7d'), - ('\u1ce9', '\u1cec'), ('\u1cee', '\u1cf1'), - ('\u1cf2', '\u1cf3'), ('\u1cf5', '\u1cf6'), - ('\u1d00', '\u1d2b'), ('\u1d2c', '\u1d6a'), - ('\u1d6b', '\u1d77'), ('\u1d78', '\u1d78'), - ('\u1d79', '\u1d9a'), ('\u1d9b', '\u1dbf'), - ('\u1e00', '\u1f15'), ('\u1f18', '\u1f1d'), - ('\u1f20', '\u1f45'), ('\u1f48', '\u1f4d'), - ('\u1f50', '\u1f57'), ('\u1f59', '\u1f59'), - ('\u1f5b', '\u1f5b'), ('\u1f5d', '\u1f5d'), - ('\u1f5f', '\u1f7d'), ('\u1f80', '\u1fb4'), - ('\u1fb6', '\u1fbc'), ('\u1fbe', '\u1fbe'), - ('\u1fc2', '\u1fc4'), ('\u1fc6', '\u1fcc'), - ('\u1fd0', '\u1fd3'), ('\u1fd6', '\u1fdb'), - ('\u1fe0', '\u1fec'), ('\u1ff2', '\u1ff4'), - ('\u1ff6', '\u1ffc'), ('\u2071', '\u2071'), - ('\u207f', '\u207f'), ('\u2090', '\u209c'), - ('\u2102', '\u2102'), ('\u2107', '\u2107'), - ('\u210a', '\u2113'), ('\u2115', '\u2115'), - ('\u2119', '\u211d'), ('\u2124', '\u2124'), - ('\u2126', '\u2126'), ('\u2128', '\u2128'), - ('\u212a', '\u212d'), ('\u212f', '\u2134'), - ('\u2135', '\u2138'), ('\u2139', '\u2139'), - ('\u213c', '\u213f'), ('\u2145', '\u2149'), - ('\u214e', '\u214e'), ('\u2160', '\u2182'), - ('\u2183', '\u2184'), ('\u2185', '\u2188'), - ('\u24b6', '\u24e9'), ('\u2c00', '\u2c2e'), - ('\u2c30', '\u2c5e'), ('\u2c60', '\u2c7b'), - ('\u2c7c', '\u2c7d'), ('\u2c7e', '\u2ce4'), - ('\u2ceb', '\u2cee'), ('\u2cf2', '\u2cf3'), - ('\u2d00', '\u2d25'), ('\u2d27', '\u2d27'), - ('\u2d2d', '\u2d2d'), ('\u2d30', '\u2d67'), - ('\u2d6f', '\u2d6f'), ('\u2d80', '\u2d96'), - ('\u2da0', '\u2da6'), ('\u2da8', '\u2dae'), - ('\u2db0', '\u2db6'), ('\u2db8', '\u2dbe'), - ('\u2dc0', '\u2dc6'), ('\u2dc8', '\u2dce'), - ('\u2dd0', '\u2dd6'), ('\u2dd8', '\u2dde'), - ('\u2de0', '\u2dff'), ('\u2e2f', '\u2e2f'), - ('\u3005', '\u3005'), ('\u3006', '\u3006'), - ('\u3007', '\u3007'), ('\u3021', '\u3029'), - ('\u3031', '\u3035'), ('\u3038', '\u303a'), - ('\u303b', '\u303b'), ('\u303c', '\u303c'), - ('\u3041', '\u3096'), ('\u309d', '\u309e'), - ('\u309f', '\u309f'), ('\u30a1', '\u30fa'), - ('\u30fc', '\u30fe'), ('\u30ff', '\u30ff'), - ('\u3105', '\u312d'), ('\u3131', '\u318e'), - ('\u31a0', '\u31ba'), ('\u31f0', '\u31ff'), - ('\u3400', '\u4db5'), ('\u4e00', '\u9fcc'), - ('\ua000', '\ua014'), ('\ua015', '\ua015'), - ('\ua016', '\ua48c'), ('\ua4d0', '\ua4f7'), - ('\ua4f8', '\ua4fd'), ('\ua500', '\ua60b'), - ('\ua60c', '\ua60c'), ('\ua610', '\ua61f'), - ('\ua62a', '\ua62b'), ('\ua640', '\ua66d'), - ('\ua66e', '\ua66e'), ('\ua674', '\ua67b'), - ('\ua67f', '\ua67f'), ('\ua680', '\ua697'), - ('\ua69f', '\ua69f'), ('\ua6a0', '\ua6e5'), - ('\ua6e6', '\ua6ef'), ('\ua717', '\ua71f'), - ('\ua722', '\ua76f'), ('\ua770', '\ua770'), - ('\ua771', '\ua787'), ('\ua788', '\ua788'), - ('\ua78b', '\ua78e'), ('\ua790', '\ua793'), - ('\ua7a0', '\ua7aa'), ('\ua7f8', '\ua7f9'), - ('\ua7fa', '\ua7fa'), ('\ua7fb', '\ua801'), - ('\ua803', '\ua805'), ('\ua807', '\ua80a'), - ('\ua80c', '\ua822'), ('\ua823', '\ua824'), - ('\ua825', '\ua826'), ('\ua827', '\ua827'), - ('\ua840', '\ua873'), ('\ua880', '\ua881'), - ('\ua882', '\ua8b3'), ('\ua8b4', '\ua8c3'), - ('\ua8f2', '\ua8f7'), ('\ua8fb', '\ua8fb'), - ('\ua90a', '\ua925'), ('\ua926', '\ua92a'), - ('\ua930', '\ua946'), ('\ua947', '\ua951'), - ('\ua952', '\ua952'), ('\ua960', '\ua97c'), - ('\ua980', '\ua982'), ('\ua983', '\ua983'), - ('\ua984', '\ua9b2'), ('\ua9b4', '\ua9b5'), - ('\ua9b6', '\ua9b9'), ('\ua9ba', '\ua9bb'), - ('\ua9bc', '\ua9bc'), ('\ua9bd', '\ua9bf'), - ('\ua9cf', '\ua9cf'), ('\uaa00', '\uaa28'), - ('\uaa29', '\uaa2e'), ('\uaa2f', '\uaa30'), - ('\uaa31', '\uaa32'), ('\uaa33', '\uaa34'), - ('\uaa35', '\uaa36'), ('\uaa40', '\uaa42'), - ('\uaa43', '\uaa43'), ('\uaa44', '\uaa4b'), - ('\uaa4c', '\uaa4c'), ('\uaa4d', '\uaa4d'), - ('\uaa60', '\uaa6f'), ('\uaa70', '\uaa70'), - ('\uaa71', '\uaa76'), ('\uaa7a', '\uaa7a'), - ('\uaa80', '\uaaaf'), ('\uaab0', '\uaab0'), - ('\uaab1', '\uaab1'), ('\uaab2', '\uaab4'), - ('\uaab5', '\uaab6'), ('\uaab7', '\uaab8'), - ('\uaab9', '\uaabd'), ('\uaabe', '\uaabe'), - ('\uaac0', '\uaac0'), ('\uaac2', '\uaac2'), - ('\uaadb', '\uaadc'), ('\uaadd', '\uaadd'), - ('\uaae0', '\uaaea'), ('\uaaeb', '\uaaeb'), - ('\uaaec', '\uaaed'), ('\uaaee', '\uaaef'), - ('\uaaf2', '\uaaf2'), ('\uaaf3', '\uaaf4'), - ('\uaaf5', '\uaaf5'), ('\uab01', '\uab06'), - ('\uab09', '\uab0e'), ('\uab11', '\uab16'), - ('\uab20', '\uab26'), ('\uab28', '\uab2e'), - ('\uabc0', '\uabe2'), ('\uabe3', '\uabe4'), - ('\uabe5', '\uabe5'), ('\uabe6', '\uabe7'), - ('\uabe8', '\uabe8'), ('\uabe9', '\uabea'), - ('\uac00', '\ud7a3'), ('\ud7b0', '\ud7c6'), - ('\ud7cb', '\ud7fb'), ('\uf900', '\ufa6d'), - ('\ufa70', '\ufad9'), ('\ufb00', '\ufb06'), - ('\ufb13', '\ufb17'), ('\ufb1d', '\ufb1d'), - ('\ufb1e', '\ufb1e'), ('\ufb1f', '\ufb28'), - ('\ufb2a', '\ufb36'), ('\ufb38', '\ufb3c'), - ('\ufb3e', '\ufb3e'), ('\ufb40', '\ufb41'), - ('\ufb43', '\ufb44'), ('\ufb46', '\ufbb1'), - ('\ufbd3', '\ufd3d'), ('\ufd50', '\ufd8f'), - ('\ufd92', '\ufdc7'), ('\ufdf0', '\ufdfb'), - ('\ufe70', '\ufe74'), ('\ufe76', '\ufefc'), - ('\uff21', '\uff3a'), ('\uff41', '\uff5a'), - ('\uff66', '\uff6f'), ('\uff70', '\uff70'), - ('\uff71', '\uff9d'), ('\uff9e', '\uff9f'), - ('\uffa0', '\uffbe'), ('\uffc2', '\uffc7'), - ('\uffca', '\uffcf'), ('\uffd2', '\uffd7'), - ('\uffda', '\uffdc'), ('\U00010000', '\U0001000b'), - ('\U0001000d', '\U00010026'), ('\U00010028', '\U0001003a'), - ('\U0001003c', '\U0001003d'), ('\U0001003f', '\U0001004d'), - ('\U00010050', '\U0001005d'), ('\U00010080', '\U000100fa'), - ('\U00010140', '\U00010174'), ('\U00010280', '\U0001029c'), - ('\U000102a0', '\U000102d0'), ('\U00010300', '\U0001031e'), - ('\U00010330', '\U00010340'), ('\U00010341', '\U00010341'), - ('\U00010342', '\U00010349'), ('\U0001034a', '\U0001034a'), - ('\U00010380', '\U0001039d'), ('\U000103a0', '\U000103c3'), - ('\U000103c8', '\U000103cf'), ('\U000103d1', '\U000103d5'), - ('\U00010400', '\U0001044f'), ('\U00010450', '\U0001049d'), - ('\U00010800', '\U00010805'), ('\U00010808', '\U00010808'), - ('\U0001080a', '\U00010835'), ('\U00010837', '\U00010838'), - ('\U0001083c', '\U0001083c'), ('\U0001083f', '\U00010855'), - ('\U00010900', '\U00010915'), ('\U00010920', '\U00010939'), - ('\U00010980', '\U000109b7'), ('\U000109be', '\U000109bf'), - ('\U00010a00', '\U00010a00'), ('\U00010a01', '\U00010a03'), - ('\U00010a05', '\U00010a06'), ('\U00010a0c', '\U00010a0f'), - ('\U00010a10', '\U00010a13'), ('\U00010a15', '\U00010a17'), - ('\U00010a19', '\U00010a33'), ('\U00010a60', '\U00010a7c'), - ('\U00010b00', '\U00010b35'), ('\U00010b40', '\U00010b55'), - ('\U00010b60', '\U00010b72'), ('\U00010c00', '\U00010c48'), - ('\U00011000', '\U00011000'), ('\U00011001', '\U00011001'), - ('\U00011002', '\U00011002'), ('\U00011003', '\U00011037'), - ('\U00011038', '\U00011045'), ('\U00011082', '\U00011082'), - ('\U00011083', '\U000110af'), ('\U000110b0', '\U000110b2'), - ('\U000110b3', '\U000110b6'), ('\U000110b7', '\U000110b8'), - ('\U000110d0', '\U000110e8'), ('\U00011100', '\U00011102'), - ('\U00011103', '\U00011126'), ('\U00011127', '\U0001112b'), - ('\U0001112c', '\U0001112c'), ('\U0001112d', '\U00011132'), - ('\U00011180', '\U00011181'), ('\U00011182', '\U00011182'), - ('\U00011183', '\U000111b2'), ('\U000111b3', '\U000111b5'), - ('\U000111b6', '\U000111be'), ('\U000111bf', '\U000111bf'), - ('\U000111c1', '\U000111c4'), ('\U00011680', '\U000116aa'), - ('\U000116ab', '\U000116ab'), ('\U000116ac', '\U000116ac'), - ('\U000116ad', '\U000116ad'), ('\U000116ae', '\U000116af'), - ('\U000116b0', '\U000116b5'), ('\U00012000', '\U0001236e'), - ('\U00012400', '\U00012462'), ('\U00013000', '\U0001342e'), - ('\U00016800', '\U00016a38'), ('\U00016f00', '\U00016f44'), - ('\U00016f50', '\U00016f50'), ('\U00016f51', '\U00016f7e'), - ('\U00016f93', '\U00016f9f'), ('\U0001b000', '\U0001b001'), - ('\U0001d400', '\U0001d454'), ('\U0001d456', '\U0001d49c'), - ('\U0001d49e', '\U0001d49f'), ('\U0001d4a2', '\U0001d4a2'), - ('\U0001d4a5', '\U0001d4a6'), ('\U0001d4a9', '\U0001d4ac'), - ('\U0001d4ae', '\U0001d4b9'), ('\U0001d4bb', '\U0001d4bb'), - ('\U0001d4bd', '\U0001d4c3'), ('\U0001d4c5', '\U0001d505'), - ('\U0001d507', '\U0001d50a'), ('\U0001d50d', '\U0001d514'), - ('\U0001d516', '\U0001d51c'), ('\U0001d51e', '\U0001d539'), - ('\U0001d53b', '\U0001d53e'), ('\U0001d540', '\U0001d544'), - ('\U0001d546', '\U0001d546'), ('\U0001d54a', '\U0001d550'), - ('\U0001d552', '\U0001d6a5'), ('\U0001d6a8', '\U0001d6c0'), - ('\U0001d6c2', '\U0001d6da'), ('\U0001d6dc', '\U0001d6fa'), - ('\U0001d6fc', '\U0001d714'), ('\U0001d716', '\U0001d734'), - ('\U0001d736', '\U0001d74e'), ('\U0001d750', '\U0001d76e'), - ('\U0001d770', '\U0001d788'), ('\U0001d78a', '\U0001d7a8'), - ('\U0001d7aa', '\U0001d7c2'), ('\U0001d7c4', '\U0001d7cb'), - ('\U0001ee00', '\U0001ee03'), ('\U0001ee05', '\U0001ee1f'), - ('\U0001ee21', '\U0001ee22'), ('\U0001ee24', '\U0001ee24'), - ('\U0001ee27', '\U0001ee27'), ('\U0001ee29', '\U0001ee32'), - ('\U0001ee34', '\U0001ee37'), ('\U0001ee39', '\U0001ee39'), - ('\U0001ee3b', '\U0001ee3b'), ('\U0001ee42', '\U0001ee42'), - ('\U0001ee47', '\U0001ee47'), ('\U0001ee49', '\U0001ee49'), - ('\U0001ee4b', '\U0001ee4b'), ('\U0001ee4d', '\U0001ee4f'), - ('\U0001ee51', '\U0001ee52'), ('\U0001ee54', '\U0001ee54'), - ('\U0001ee57', '\U0001ee57'), ('\U0001ee59', '\U0001ee59'), - ('\U0001ee5b', '\U0001ee5b'), ('\U0001ee5d', '\U0001ee5d'), - ('\U0001ee5f', '\U0001ee5f'), ('\U0001ee61', '\U0001ee62'), - ('\U0001ee64', '\U0001ee64'), ('\U0001ee67', '\U0001ee6a'), - ('\U0001ee6c', '\U0001ee72'), ('\U0001ee74', '\U0001ee77'), - ('\U0001ee79', '\U0001ee7c'), ('\U0001ee7e', '\U0001ee7e'), - ('\U0001ee80', '\U0001ee89'), ('\U0001ee8b', '\U0001ee9b'), - ('\U0001eea1', '\U0001eea3'), ('\U0001eea5', '\U0001eea9'), - ('\U0001eeab', '\U0001eebb'), ('\U00020000', '\U0002a6d6'), - ('\U0002a700', '\U0002b734'), ('\U0002b740', '\U0002b81d'), - ('\U0002f800', '\U0002fa1d') - ]; - - pub fn Alphabetic(c: char) -> bool { - bsearch_range_table(c, Alphabetic_table) - } - - static XID_Continue_table : &'static [(char,char)] = &[ - ('\x30', '\x39'), ('\x41', '\x5a'), - ('\x5f', '\x5f'), ('\x61', '\x7a'), - ('\xaa', '\xaa'), ('\xb5', '\xb5'), - ('\xb7', '\xb7'), ('\xba', '\xba'), - ('\xc0', '\xd6'), ('\xd8', '\xf6'), - ('\xf8', '\u01ba'), ('\u01bb', '\u01bb'), - ('\u01bc', '\u01bf'), ('\u01c0', '\u01c3'), - ('\u01c4', '\u0293'), ('\u0294', '\u0294'), - ('\u0295', '\u02af'), ('\u02b0', '\u02c1'), - ('\u02c6', '\u02d1'), ('\u02e0', '\u02e4'), - ('\u02ec', '\u02ec'), ('\u02ee', '\u02ee'), - ('\u0300', '\u036f'), ('\u0370', '\u0373'), - ('\u0374', '\u0374'), ('\u0376', '\u0377'), - ('\u037b', '\u037d'), ('\u0386', '\u0386'), - ('\u0387', '\u0387'), ('\u0388', '\u038a'), - ('\u038c', '\u038c'), ('\u038e', '\u03a1'), - ('\u03a3', '\u03f5'), ('\u03f7', '\u0481'), - ('\u0483', '\u0487'), ('\u048a', '\u0527'), - ('\u0531', '\u0556'), ('\u0559', '\u0559'), - ('\u0561', '\u0587'), ('\u0591', '\u05bd'), - ('\u05bf', '\u05bf'), ('\u05c1', '\u05c2'), - ('\u05c4', '\u05c5'), ('\u05c7', '\u05c7'), - ('\u05d0', '\u05ea'), ('\u05f0', '\u05f2'), - ('\u0610', '\u061a'), ('\u0620', '\u063f'), - ('\u0640', '\u0640'), ('\u0641', '\u064a'), - ('\u064b', '\u065f'), ('\u0660', '\u0669'), - ('\u066e', '\u066f'), ('\u0670', '\u0670'), - ('\u0671', '\u06d3'), ('\u06d5', '\u06d5'), - ('\u06d6', '\u06dc'), ('\u06df', '\u06e4'), - ('\u06e5', '\u06e6'), ('\u06e7', '\u06e8'), - ('\u06ea', '\u06ed'), ('\u06ee', '\u06ef'), - ('\u06f0', '\u06f9'), ('\u06fa', '\u06fc'), - ('\u06ff', '\u06ff'), ('\u0710', '\u0710'), - ('\u0711', '\u0711'), ('\u0712', '\u072f'), - ('\u0730', '\u074a'), ('\u074d', '\u07a5'), - ('\u07a6', '\u07b0'), ('\u07b1', '\u07b1'), - ('\u07c0', '\u07c9'), ('\u07ca', '\u07ea'), - ('\u07eb', '\u07f3'), ('\u07f4', '\u07f5'), - ('\u07fa', '\u07fa'), ('\u0800', '\u0815'), - ('\u0816', '\u0819'), ('\u081a', '\u081a'), - ('\u081b', '\u0823'), ('\u0824', '\u0824'), - ('\u0825', '\u0827'), ('\u0828', '\u0828'), - ('\u0829', '\u082d'), ('\u0840', '\u0858'), - ('\u0859', '\u085b'), ('\u08a0', '\u08a0'), - ('\u08a2', '\u08ac'), ('\u08e4', '\u08fe'), - ('\u0900', '\u0902'), ('\u0903', '\u0903'), - ('\u0904', '\u0939'), ('\u093a', '\u093a'), - ('\u093b', '\u093b'), ('\u093c', '\u093c'), - ('\u093d', '\u093d'), ('\u093e', '\u0940'), - ('\u0941', '\u0948'), ('\u0949', '\u094c'), - ('\u094d', '\u094d'), ('\u094e', '\u094f'), - ('\u0950', '\u0950'), ('\u0951', '\u0957'), - ('\u0958', '\u0961'), ('\u0962', '\u0963'), - ('\u0966', '\u096f'), ('\u0971', '\u0971'), - ('\u0972', '\u0977'), ('\u0979', '\u097f'), - ('\u0981', '\u0981'), ('\u0982', '\u0983'), - ('\u0985', '\u098c'), ('\u098f', '\u0990'), - ('\u0993', '\u09a8'), ('\u09aa', '\u09b0'), - ('\u09b2', '\u09b2'), ('\u09b6', '\u09b9'), - ('\u09bc', '\u09bc'), ('\u09bd', '\u09bd'), - ('\u09be', '\u09c0'), ('\u09c1', '\u09c4'), - ('\u09c7', '\u09c8'), ('\u09cb', '\u09cc'), - ('\u09cd', '\u09cd'), ('\u09ce', '\u09ce'), - ('\u09d7', '\u09d7'), ('\u09dc', '\u09dd'), - ('\u09df', '\u09e1'), ('\u09e2', '\u09e3'), - ('\u09e6', '\u09ef'), ('\u09f0', '\u09f1'), - ('\u0a01', '\u0a02'), ('\u0a03', '\u0a03'), - ('\u0a05', '\u0a0a'), ('\u0a0f', '\u0a10'), - ('\u0a13', '\u0a28'), ('\u0a2a', '\u0a30'), - ('\u0a32', '\u0a33'), ('\u0a35', '\u0a36'), - ('\u0a38', '\u0a39'), ('\u0a3c', '\u0a3c'), - ('\u0a3e', '\u0a40'), ('\u0a41', '\u0a42'), - ('\u0a47', '\u0a48'), ('\u0a4b', '\u0a4d'), - ('\u0a51', '\u0a51'), ('\u0a59', '\u0a5c'), - ('\u0a5e', '\u0a5e'), ('\u0a66', '\u0a6f'), - ('\u0a70', '\u0a71'), ('\u0a72', '\u0a74'), - ('\u0a75', '\u0a75'), ('\u0a81', '\u0a82'), - ('\u0a83', '\u0a83'), ('\u0a85', '\u0a8d'), - ('\u0a8f', '\u0a91'), ('\u0a93', '\u0aa8'), - ('\u0aaa', '\u0ab0'), ('\u0ab2', '\u0ab3'), - ('\u0ab5', '\u0ab9'), ('\u0abc', '\u0abc'), - ('\u0abd', '\u0abd'), ('\u0abe', '\u0ac0'), - ('\u0ac1', '\u0ac5'), ('\u0ac7', '\u0ac8'), - ('\u0ac9', '\u0ac9'), ('\u0acb', '\u0acc'), - ('\u0acd', '\u0acd'), ('\u0ad0', '\u0ad0'), - ('\u0ae0', '\u0ae1'), ('\u0ae2', '\u0ae3'), - ('\u0ae6', '\u0aef'), ('\u0b01', '\u0b01'), - ('\u0b02', '\u0b03'), ('\u0b05', '\u0b0c'), - ('\u0b0f', '\u0b10'), ('\u0b13', '\u0b28'), - ('\u0b2a', '\u0b30'), ('\u0b32', '\u0b33'), - ('\u0b35', '\u0b39'), ('\u0b3c', '\u0b3c'), - ('\u0b3d', '\u0b3d'), ('\u0b3e', '\u0b3e'), - ('\u0b3f', '\u0b3f'), ('\u0b40', '\u0b40'), - ('\u0b41', '\u0b44'), ('\u0b47', '\u0b48'), - ('\u0b4b', '\u0b4c'), ('\u0b4d', '\u0b4d'), - ('\u0b56', '\u0b56'), ('\u0b57', '\u0b57'), - ('\u0b5c', '\u0b5d'), ('\u0b5f', '\u0b61'), - ('\u0b62', '\u0b63'), ('\u0b66', '\u0b6f'), - ('\u0b71', '\u0b71'), ('\u0b82', '\u0b82'), - ('\u0b83', '\u0b83'), ('\u0b85', '\u0b8a'), - ('\u0b8e', '\u0b90'), ('\u0b92', '\u0b95'), - ('\u0b99', '\u0b9a'), ('\u0b9c', '\u0b9c'), - ('\u0b9e', '\u0b9f'), ('\u0ba3', '\u0ba4'), - ('\u0ba8', '\u0baa'), ('\u0bae', '\u0bb9'), - ('\u0bbe', '\u0bbf'), ('\u0bc0', '\u0bc0'), - ('\u0bc1', '\u0bc2'), ('\u0bc6', '\u0bc8'), - ('\u0bca', '\u0bcc'), ('\u0bcd', '\u0bcd'), - ('\u0bd0', '\u0bd0'), ('\u0bd7', '\u0bd7'), - ('\u0be6', '\u0bef'), ('\u0c01', '\u0c03'), - ('\u0c05', '\u0c0c'), ('\u0c0e', '\u0c10'), - ('\u0c12', '\u0c28'), ('\u0c2a', '\u0c33'), - ('\u0c35', '\u0c39'), ('\u0c3d', '\u0c3d'), - ('\u0c3e', '\u0c40'), ('\u0c41', '\u0c44'), - ('\u0c46', '\u0c48'), ('\u0c4a', '\u0c4d'), - ('\u0c55', '\u0c56'), ('\u0c58', '\u0c59'), - ('\u0c60', '\u0c61'), ('\u0c62', '\u0c63'), - ('\u0c66', '\u0c6f'), ('\u0c82', '\u0c83'), - ('\u0c85', '\u0c8c'), ('\u0c8e', '\u0c90'), - ('\u0c92', '\u0ca8'), ('\u0caa', '\u0cb3'), - ('\u0cb5', '\u0cb9'), ('\u0cbc', '\u0cbc'), - ('\u0cbd', '\u0cbd'), ('\u0cbe', '\u0cbe'), - ('\u0cbf', '\u0cbf'), ('\u0cc0', '\u0cc4'), - ('\u0cc6', '\u0cc6'), ('\u0cc7', '\u0cc8'), - ('\u0cca', '\u0ccb'), ('\u0ccc', '\u0ccd'), - ('\u0cd5', '\u0cd6'), ('\u0cde', '\u0cde'), - ('\u0ce0', '\u0ce1'), ('\u0ce2', '\u0ce3'), - ('\u0ce6', '\u0cef'), ('\u0cf1', '\u0cf2'), - ('\u0d02', '\u0d03'), ('\u0d05', '\u0d0c'), - ('\u0d0e', '\u0d10'), ('\u0d12', '\u0d3a'), - ('\u0d3d', '\u0d3d'), ('\u0d3e', '\u0d40'), - ('\u0d41', '\u0d44'), ('\u0d46', '\u0d48'), - ('\u0d4a', '\u0d4c'), ('\u0d4d', '\u0d4d'), - ('\u0d4e', '\u0d4e'), ('\u0d57', '\u0d57'), - ('\u0d60', '\u0d61'), ('\u0d62', '\u0d63'), - ('\u0d66', '\u0d6f'), ('\u0d7a', '\u0d7f'), - ('\u0d82', '\u0d83'), ('\u0d85', '\u0d96'), - ('\u0d9a', '\u0db1'), ('\u0db3', '\u0dbb'), - ('\u0dbd', '\u0dbd'), ('\u0dc0', '\u0dc6'), - ('\u0dca', '\u0dca'), ('\u0dcf', '\u0dd1'), - ('\u0dd2', '\u0dd4'), ('\u0dd6', '\u0dd6'), - ('\u0dd8', '\u0ddf'), ('\u0df2', '\u0df3'), - ('\u0e01', '\u0e30'), ('\u0e31', '\u0e31'), - ('\u0e32', '\u0e33'), ('\u0e34', '\u0e3a'), - ('\u0e40', '\u0e45'), ('\u0e46', '\u0e46'), - ('\u0e47', '\u0e4e'), ('\u0e50', '\u0e59'), - ('\u0e81', '\u0e82'), ('\u0e84', '\u0e84'), - ('\u0e87', '\u0e88'), ('\u0e8a', '\u0e8a'), - ('\u0e8d', '\u0e8d'), ('\u0e94', '\u0e97'), - ('\u0e99', '\u0e9f'), ('\u0ea1', '\u0ea3'), - ('\u0ea5', '\u0ea5'), ('\u0ea7', '\u0ea7'), - ('\u0eaa', '\u0eab'), ('\u0ead', '\u0eb0'), - ('\u0eb1', '\u0eb1'), ('\u0eb2', '\u0eb3'), - ('\u0eb4', '\u0eb9'), ('\u0ebb', '\u0ebc'), - ('\u0ebd', '\u0ebd'), ('\u0ec0', '\u0ec4'), - ('\u0ec6', '\u0ec6'), ('\u0ec8', '\u0ecd'), - ('\u0ed0', '\u0ed9'), ('\u0edc', '\u0edf'), - ('\u0f00', '\u0f00'), ('\u0f18', '\u0f19'), - ('\u0f20', '\u0f29'), ('\u0f35', '\u0f35'), - ('\u0f37', '\u0f37'), ('\u0f39', '\u0f39'), - ('\u0f3e', '\u0f3f'), ('\u0f40', '\u0f47'), - ('\u0f49', '\u0f6c'), ('\u0f71', '\u0f7e'), - ('\u0f7f', '\u0f7f'), ('\u0f80', '\u0f84'), - ('\u0f86', '\u0f87'), ('\u0f88', '\u0f8c'), - ('\u0f8d', '\u0f97'), ('\u0f99', '\u0fbc'), - ('\u0fc6', '\u0fc6'), ('\u1000', '\u102a'), - ('\u102b', '\u102c'), ('\u102d', '\u1030'), - ('\u1031', '\u1031'), ('\u1032', '\u1037'), - ('\u1038', '\u1038'), ('\u1039', '\u103a'), - ('\u103b', '\u103c'), ('\u103d', '\u103e'), - ('\u103f', '\u103f'), ('\u1040', '\u1049'), - ('\u1050', '\u1055'), ('\u1056', '\u1057'), - ('\u1058', '\u1059'), ('\u105a', '\u105d'), - ('\u105e', '\u1060'), ('\u1061', '\u1061'), - ('\u1062', '\u1064'), ('\u1065', '\u1066'), - ('\u1067', '\u106d'), ('\u106e', '\u1070'), - ('\u1071', '\u1074'), ('\u1075', '\u1081'), - ('\u1082', '\u1082'), ('\u1083', '\u1084'), - ('\u1085', '\u1086'), ('\u1087', '\u108c'), - ('\u108d', '\u108d'), ('\u108e', '\u108e'), - ('\u108f', '\u108f'), ('\u1090', '\u1099'), - ('\u109a', '\u109c'), ('\u109d', '\u109d'), - ('\u10a0', '\u10c5'), ('\u10c7', '\u10c7'), - ('\u10cd', '\u10cd'), ('\u10d0', '\u10fa'), - ('\u10fc', '\u10fc'), ('\u10fd', '\u1248'), - ('\u124a', '\u124d'), ('\u1250', '\u1256'), - ('\u1258', '\u1258'), ('\u125a', '\u125d'), - ('\u1260', '\u1288'), ('\u128a', '\u128d'), - ('\u1290', '\u12b0'), ('\u12b2', '\u12b5'), - ('\u12b8', '\u12be'), ('\u12c0', '\u12c0'), - ('\u12c2', '\u12c5'), ('\u12c8', '\u12d6'), - ('\u12d8', '\u1310'), ('\u1312', '\u1315'), - ('\u1318', '\u135a'), ('\u135d', '\u135f'), - ('\u1369', '\u1371'), ('\u1380', '\u138f'), - ('\u13a0', '\u13f4'), ('\u1401', '\u166c'), - ('\u166f', '\u167f'), ('\u1681', '\u169a'), - ('\u16a0', '\u16ea'), ('\u16ee', '\u16f0'), - ('\u1700', '\u170c'), ('\u170e', '\u1711'), - ('\u1712', '\u1714'), ('\u1720', '\u1731'), - ('\u1732', '\u1734'), ('\u1740', '\u1751'), - ('\u1752', '\u1753'), ('\u1760', '\u176c'), - ('\u176e', '\u1770'), ('\u1772', '\u1773'), - ('\u1780', '\u17b3'), ('\u17b4', '\u17b5'), - ('\u17b6', '\u17b6'), ('\u17b7', '\u17bd'), - ('\u17be', '\u17c5'), ('\u17c6', '\u17c6'), - ('\u17c7', '\u17c8'), ('\u17c9', '\u17d3'), - ('\u17d7', '\u17d7'), ('\u17dc', '\u17dc'), - ('\u17dd', '\u17dd'), ('\u17e0', '\u17e9'), - ('\u180b', '\u180d'), ('\u1810', '\u1819'), - ('\u1820', '\u1842'), ('\u1843', '\u1843'), - ('\u1844', '\u1877'), ('\u1880', '\u18a8'), - ('\u18a9', '\u18a9'), ('\u18aa', '\u18aa'), - ('\u18b0', '\u18f5'), ('\u1900', '\u191c'), - ('\u1920', '\u1922'), ('\u1923', '\u1926'), - ('\u1927', '\u1928'), ('\u1929', '\u192b'), - ('\u1930', '\u1931'), ('\u1932', '\u1932'), - ('\u1933', '\u1938'), ('\u1939', '\u193b'), - ('\u1946', '\u194f'), ('\u1950', '\u196d'), - ('\u1970', '\u1974'), ('\u1980', '\u19ab'), - ('\u19b0', '\u19c0'), ('\u19c1', '\u19c7'), - ('\u19c8', '\u19c9'), ('\u19d0', '\u19d9'), - ('\u19da', '\u19da'), ('\u1a00', '\u1a16'), - ('\u1a17', '\u1a18'), ('\u1a19', '\u1a1b'), - ('\u1a20', '\u1a54'), ('\u1a55', '\u1a55'), - ('\u1a56', '\u1a56'), ('\u1a57', '\u1a57'), - ('\u1a58', '\u1a5e'), ('\u1a60', '\u1a60'), - ('\u1a61', '\u1a61'), ('\u1a62', '\u1a62'), - ('\u1a63', '\u1a64'), ('\u1a65', '\u1a6c'), - ('\u1a6d', '\u1a72'), ('\u1a73', '\u1a7c'), - ('\u1a7f', '\u1a7f'), ('\u1a80', '\u1a89'), - ('\u1a90', '\u1a99'), ('\u1aa7', '\u1aa7'), - ('\u1b00', '\u1b03'), ('\u1b04', '\u1b04'), - ('\u1b05', '\u1b33'), ('\u1b34', '\u1b34'), - ('\u1b35', '\u1b35'), ('\u1b36', '\u1b3a'), - ('\u1b3b', '\u1b3b'), ('\u1b3c', '\u1b3c'), - ('\u1b3d', '\u1b41'), ('\u1b42', '\u1b42'), - ('\u1b43', '\u1b44'), ('\u1b45', '\u1b4b'), - ('\u1b50', '\u1b59'), ('\u1b6b', '\u1b73'), - ('\u1b80', '\u1b81'), ('\u1b82', '\u1b82'), - ('\u1b83', '\u1ba0'), ('\u1ba1', '\u1ba1'), - ('\u1ba2', '\u1ba5'), ('\u1ba6', '\u1ba7'), - ('\u1ba8', '\u1ba9'), ('\u1baa', '\u1baa'), - ('\u1bab', '\u1bab'), ('\u1bac', '\u1bad'), - ('\u1bae', '\u1baf'), ('\u1bb0', '\u1bb9'), - ('\u1bba', '\u1be5'), ('\u1be6', '\u1be6'), - ('\u1be7', '\u1be7'), ('\u1be8', '\u1be9'), - ('\u1bea', '\u1bec'), ('\u1bed', '\u1bed'), - ('\u1bee', '\u1bee'), ('\u1bef', '\u1bf1'), - ('\u1bf2', '\u1bf3'), ('\u1c00', '\u1c23'), - ('\u1c24', '\u1c2b'), ('\u1c2c', '\u1c33'), - ('\u1c34', '\u1c35'), ('\u1c36', '\u1c37'), - ('\u1c40', '\u1c49'), ('\u1c4d', '\u1c4f'), - ('\u1c50', '\u1c59'), ('\u1c5a', '\u1c77'), - ('\u1c78', '\u1c7d'), ('\u1cd0', '\u1cd2'), - ('\u1cd4', '\u1ce0'), ('\u1ce1', '\u1ce1'), - ('\u1ce2', '\u1ce8'), ('\u1ce9', '\u1cec'), - ('\u1ced', '\u1ced'), ('\u1cee', '\u1cf1'), - ('\u1cf2', '\u1cf3'), ('\u1cf4', '\u1cf4'), - ('\u1cf5', '\u1cf6'), ('\u1d00', '\u1d2b'), - ('\u1d2c', '\u1d6a'), ('\u1d6b', '\u1d77'), - ('\u1d78', '\u1d78'), ('\u1d79', '\u1d9a'), - ('\u1d9b', '\u1dbf'), ('\u1dc0', '\u1de6'), - ('\u1dfc', '\u1dff'), ('\u1e00', '\u1f15'), - ('\u1f18', '\u1f1d'), ('\u1f20', '\u1f45'), - ('\u1f48', '\u1f4d'), ('\u1f50', '\u1f57'), - ('\u1f59', '\u1f59'), ('\u1f5b', '\u1f5b'), - ('\u1f5d', '\u1f5d'), ('\u1f5f', '\u1f7d'), - ('\u1f80', '\u1fb4'), ('\u1fb6', '\u1fbc'), - ('\u1fbe', '\u1fbe'), ('\u1fc2', '\u1fc4'), - ('\u1fc6', '\u1fcc'), ('\u1fd0', '\u1fd3'), - ('\u1fd6', '\u1fdb'), ('\u1fe0', '\u1fec'), - ('\u1ff2', '\u1ff4'), ('\u1ff6', '\u1ffc'), - ('\u203f', '\u2040'), ('\u2054', '\u2054'), - ('\u2071', '\u2071'), ('\u207f', '\u207f'), - ('\u2090', '\u209c'), ('\u20d0', '\u20dc'), - ('\u20e1', '\u20e1'), ('\u20e5', '\u20f0'), - ('\u2102', '\u2102'), ('\u2107', '\u2107'), - ('\u210a', '\u2113'), ('\u2115', '\u2115'), - ('\u2118', '\u2118'), ('\u2119', '\u211d'), - ('\u2124', '\u2124'), ('\u2126', '\u2126'), - ('\u2128', '\u2128'), ('\u212a', '\u212d'), - ('\u212e', '\u212e'), ('\u212f', '\u2134'), - ('\u2135', '\u2138'), ('\u2139', '\u2139'), - ('\u213c', '\u213f'), ('\u2145', '\u2149'), - ('\u214e', '\u214e'), ('\u2160', '\u2182'), - ('\u2183', '\u2184'), ('\u2185', '\u2188'), - ('\u2c00', '\u2c2e'), ('\u2c30', '\u2c5e'), - ('\u2c60', '\u2c7b'), ('\u2c7c', '\u2c7d'), - ('\u2c7e', '\u2ce4'), ('\u2ceb', '\u2cee'), - ('\u2cef', '\u2cf1'), ('\u2cf2', '\u2cf3'), - ('\u2d00', '\u2d25'), ('\u2d27', '\u2d27'), - ('\u2d2d', '\u2d2d'), ('\u2d30', '\u2d67'), - ('\u2d6f', '\u2d6f'), ('\u2d7f', '\u2d7f'), - ('\u2d80', '\u2d96'), ('\u2da0', '\u2da6'), - ('\u2da8', '\u2dae'), ('\u2db0', '\u2db6'), - ('\u2db8', '\u2dbe'), ('\u2dc0', '\u2dc6'), - ('\u2dc8', '\u2dce'), ('\u2dd0', '\u2dd6'), - ('\u2dd8', '\u2dde'), ('\u2de0', '\u2dff'), - ('\u3005', '\u3005'), ('\u3006', '\u3006'), - ('\u3007', '\u3007'), ('\u3021', '\u3029'), - ('\u302a', '\u302d'), ('\u302e', '\u302f'), - ('\u3031', '\u3035'), ('\u3038', '\u303a'), - ('\u303b', '\u303b'), ('\u303c', '\u303c'), - ('\u3041', '\u3096'), ('\u3099', '\u309a'), - ('\u309d', '\u309e'), ('\u309f', '\u309f'), - ('\u30a1', '\u30fa'), ('\u30fc', '\u30fe'), - ('\u30ff', '\u30ff'), ('\u3105', '\u312d'), - ('\u3131', '\u318e'), ('\u31a0', '\u31ba'), - ('\u31f0', '\u31ff'), ('\u3400', '\u4db5'), - ('\u4e00', '\u9fcc'), ('\ua000', '\ua014'), - ('\ua015', '\ua015'), ('\ua016', '\ua48c'), - ('\ua4d0', '\ua4f7'), ('\ua4f8', '\ua4fd'), - ('\ua500', '\ua60b'), ('\ua60c', '\ua60c'), - ('\ua610', '\ua61f'), ('\ua620', '\ua629'), - ('\ua62a', '\ua62b'), ('\ua640', '\ua66d'), - ('\ua66e', '\ua66e'), ('\ua66f', '\ua66f'), - ('\ua674', '\ua67d'), ('\ua67f', '\ua67f'), - ('\ua680', '\ua697'), ('\ua69f', '\ua69f'), - ('\ua6a0', '\ua6e5'), ('\ua6e6', '\ua6ef'), - ('\ua6f0', '\ua6f1'), ('\ua717', '\ua71f'), - ('\ua722', '\ua76f'), ('\ua770', '\ua770'), - ('\ua771', '\ua787'), ('\ua788', '\ua788'), - ('\ua78b', '\ua78e'), ('\ua790', '\ua793'), - ('\ua7a0', '\ua7aa'), ('\ua7f8', '\ua7f9'), - ('\ua7fa', '\ua7fa'), ('\ua7fb', '\ua801'), - ('\ua802', '\ua802'), ('\ua803', '\ua805'), - ('\ua806', '\ua806'), ('\ua807', '\ua80a'), - ('\ua80b', '\ua80b'), ('\ua80c', '\ua822'), - ('\ua823', '\ua824'), ('\ua825', '\ua826'), - ('\ua827', '\ua827'), ('\ua840', '\ua873'), - ('\ua880', '\ua881'), ('\ua882', '\ua8b3'), - ('\ua8b4', '\ua8c3'), ('\ua8c4', '\ua8c4'), - ('\ua8d0', '\ua8d9'), ('\ua8e0', '\ua8f1'), - ('\ua8f2', '\ua8f7'), ('\ua8fb', '\ua8fb'), - ('\ua900', '\ua909'), ('\ua90a', '\ua925'), - ('\ua926', '\ua92d'), ('\ua930', '\ua946'), - ('\ua947', '\ua951'), ('\ua952', '\ua953'), - ('\ua960', '\ua97c'), ('\ua980', '\ua982'), - ('\ua983', '\ua983'), ('\ua984', '\ua9b2'), - ('\ua9b3', '\ua9b3'), ('\ua9b4', '\ua9b5'), - ('\ua9b6', '\ua9b9'), ('\ua9ba', '\ua9bb'), - ('\ua9bc', '\ua9bc'), ('\ua9bd', '\ua9c0'), - ('\ua9cf', '\ua9cf'), ('\ua9d0', '\ua9d9'), - ('\uaa00', '\uaa28'), ('\uaa29', '\uaa2e'), - ('\uaa2f', '\uaa30'), ('\uaa31', '\uaa32'), - ('\uaa33', '\uaa34'), ('\uaa35', '\uaa36'), - ('\uaa40', '\uaa42'), ('\uaa43', '\uaa43'), - ('\uaa44', '\uaa4b'), ('\uaa4c', '\uaa4c'), - ('\uaa4d', '\uaa4d'), ('\uaa50', '\uaa59'), - ('\uaa60', '\uaa6f'), ('\uaa70', '\uaa70'), - ('\uaa71', '\uaa76'), ('\uaa7a', '\uaa7a'), - ('\uaa7b', '\uaa7b'), ('\uaa80', '\uaaaf'), - ('\uaab0', '\uaab0'), ('\uaab1', '\uaab1'), - ('\uaab2', '\uaab4'), ('\uaab5', '\uaab6'), - ('\uaab7', '\uaab8'), ('\uaab9', '\uaabd'), - ('\uaabe', '\uaabf'), ('\uaac0', '\uaac0'), - ('\uaac1', '\uaac1'), ('\uaac2', '\uaac2'), - ('\uaadb', '\uaadc'), ('\uaadd', '\uaadd'), - ('\uaae0', '\uaaea'), ('\uaaeb', '\uaaeb'), - ('\uaaec', '\uaaed'), ('\uaaee', '\uaaef'), - ('\uaaf2', '\uaaf2'), ('\uaaf3', '\uaaf4'), - ('\uaaf5', '\uaaf5'), ('\uaaf6', '\uaaf6'), - ('\uab01', '\uab06'), ('\uab09', '\uab0e'), - ('\uab11', '\uab16'), ('\uab20', '\uab26'), - ('\uab28', '\uab2e'), ('\uabc0', '\uabe2'), - ('\uabe3', '\uabe4'), ('\uabe5', '\uabe5'), - ('\uabe6', '\uabe7'), ('\uabe8', '\uabe8'), - ('\uabe9', '\uabea'), ('\uabec', '\uabec'), - ('\uabed', '\uabed'), ('\uabf0', '\uabf9'), - ('\uac00', '\ud7a3'), ('\ud7b0', '\ud7c6'), - ('\ud7cb', '\ud7fb'), ('\uf900', '\ufa6d'), - ('\ufa70', '\ufad9'), ('\ufb00', '\ufb06'), - ('\ufb13', '\ufb17'), ('\ufb1d', '\ufb1d'), - ('\ufb1e', '\ufb1e'), ('\ufb1f', '\ufb28'), - ('\ufb2a', '\ufb36'), ('\ufb38', '\ufb3c'), - ('\ufb3e', '\ufb3e'), ('\ufb40', '\ufb41'), - ('\ufb43', '\ufb44'), ('\ufb46', '\ufbb1'), - ('\ufbd3', '\ufc5d'), ('\ufc64', '\ufd3d'), - ('\ufd50', '\ufd8f'), ('\ufd92', '\ufdc7'), - ('\ufdf0', '\ufdf9'), ('\ufe00', '\ufe0f'), - ('\ufe20', '\ufe26'), ('\ufe33', '\ufe34'), - ('\ufe4d', '\ufe4f'), ('\ufe71', '\ufe71'), - ('\ufe73', '\ufe73'), ('\ufe77', '\ufe77'), - ('\ufe79', '\ufe79'), ('\ufe7b', '\ufe7b'), - ('\ufe7d', '\ufe7d'), ('\ufe7f', '\ufefc'), - ('\uff10', '\uff19'), ('\uff21', '\uff3a'), - ('\uff3f', '\uff3f'), ('\uff41', '\uff5a'), - ('\uff66', '\uff6f'), ('\uff70', '\uff70'), - ('\uff71', '\uff9d'), ('\uff9e', '\uff9f'), - ('\uffa0', '\uffbe'), ('\uffc2', '\uffc7'), - ('\uffca', '\uffcf'), ('\uffd2', '\uffd7'), - ('\uffda', '\uffdc'), ('\U00010000', '\U0001000b'), - ('\U0001000d', '\U00010026'), ('\U00010028', '\U0001003a'), - ('\U0001003c', '\U0001003d'), ('\U0001003f', '\U0001004d'), - ('\U00010050', '\U0001005d'), ('\U00010080', '\U000100fa'), - ('\U00010140', '\U00010174'), ('\U000101fd', '\U000101fd'), - ('\U00010280', '\U0001029c'), ('\U000102a0', '\U000102d0'), - ('\U00010300', '\U0001031e'), ('\U00010330', '\U00010340'), - ('\U00010341', '\U00010341'), ('\U00010342', '\U00010349'), - ('\U0001034a', '\U0001034a'), ('\U00010380', '\U0001039d'), - ('\U000103a0', '\U000103c3'), ('\U000103c8', '\U000103cf'), - ('\U000103d1', '\U000103d5'), ('\U00010400', '\U0001044f'), - ('\U00010450', '\U0001049d'), ('\U000104a0', '\U000104a9'), - ('\U00010800', '\U00010805'), ('\U00010808', '\U00010808'), - ('\U0001080a', '\U00010835'), ('\U00010837', '\U00010838'), - ('\U0001083c', '\U0001083c'), ('\U0001083f', '\U00010855'), - ('\U00010900', '\U00010915'), ('\U00010920', '\U00010939'), - ('\U00010980', '\U000109b7'), ('\U000109be', '\U000109bf'), - ('\U00010a00', '\U00010a00'), ('\U00010a01', '\U00010a03'), - ('\U00010a05', '\U00010a06'), ('\U00010a0c', '\U00010a0f'), - ('\U00010a10', '\U00010a13'), ('\U00010a15', '\U00010a17'), - ('\U00010a19', '\U00010a33'), ('\U00010a38', '\U00010a3a'), - ('\U00010a3f', '\U00010a3f'), ('\U00010a60', '\U00010a7c'), - ('\U00010b00', '\U00010b35'), ('\U00010b40', '\U00010b55'), - ('\U00010b60', '\U00010b72'), ('\U00010c00', '\U00010c48'), - ('\U00011000', '\U00011000'), ('\U00011001', '\U00011001'), - ('\U00011002', '\U00011002'), ('\U00011003', '\U00011037'), - ('\U00011038', '\U00011046'), ('\U00011066', '\U0001106f'), - ('\U00011080', '\U00011081'), ('\U00011082', '\U00011082'), - ('\U00011083', '\U000110af'), ('\U000110b0', '\U000110b2'), - ('\U000110b3', '\U000110b6'), ('\U000110b7', '\U000110b8'), - ('\U000110b9', '\U000110ba'), ('\U000110d0', '\U000110e8'), - ('\U000110f0', '\U000110f9'), ('\U00011100', '\U00011102'), - ('\U00011103', '\U00011126'), ('\U00011127', '\U0001112b'), - ('\U0001112c', '\U0001112c'), ('\U0001112d', '\U00011134'), - ('\U00011136', '\U0001113f'), ('\U00011180', '\U00011181'), - ('\U00011182', '\U00011182'), ('\U00011183', '\U000111b2'), - ('\U000111b3', '\U000111b5'), ('\U000111b6', '\U000111be'), - ('\U000111bf', '\U000111c0'), ('\U000111c1', '\U000111c4'), - ('\U000111d0', '\U000111d9'), ('\U00011680', '\U000116aa'), - ('\U000116ab', '\U000116ab'), ('\U000116ac', '\U000116ac'), - ('\U000116ad', '\U000116ad'), ('\U000116ae', '\U000116af'), - ('\U000116b0', '\U000116b5'), ('\U000116b6', '\U000116b6'), - ('\U000116b7', '\U000116b7'), ('\U000116c0', '\U000116c9'), - ('\U00012000', '\U0001236e'), ('\U00012400', '\U00012462'), - ('\U00013000', '\U0001342e'), ('\U00016800', '\U00016a38'), - ('\U00016f00', '\U00016f44'), ('\U00016f50', '\U00016f50'), - ('\U00016f51', '\U00016f7e'), ('\U00016f8f', '\U00016f92'), - ('\U00016f93', '\U00016f9f'), ('\U0001b000', '\U0001b001'), - ('\U0001d165', '\U0001d166'), ('\U0001d167', '\U0001d169'), - ('\U0001d16d', '\U0001d172'), ('\U0001d17b', '\U0001d182'), - ('\U0001d185', '\U0001d18b'), ('\U0001d1aa', '\U0001d1ad'), - ('\U0001d242', '\U0001d244'), ('\U0001d400', '\U0001d454'), - ('\U0001d456', '\U0001d49c'), ('\U0001d49e', '\U0001d49f'), - ('\U0001d4a2', '\U0001d4a2'), ('\U0001d4a5', '\U0001d4a6'), - ('\U0001d4a9', '\U0001d4ac'), ('\U0001d4ae', '\U0001d4b9'), - ('\U0001d4bb', '\U0001d4bb'), ('\U0001d4bd', '\U0001d4c3'), - ('\U0001d4c5', '\U0001d505'), ('\U0001d507', '\U0001d50a'), - ('\U0001d50d', '\U0001d514'), ('\U0001d516', '\U0001d51c'), - ('\U0001d51e', '\U0001d539'), ('\U0001d53b', '\U0001d53e'), - ('\U0001d540', '\U0001d544'), ('\U0001d546', '\U0001d546'), - ('\U0001d54a', '\U0001d550'), ('\U0001d552', '\U0001d6a5'), - ('\U0001d6a8', '\U0001d6c0'), ('\U0001d6c2', '\U0001d6da'), - ('\U0001d6dc', '\U0001d6fa'), ('\U0001d6fc', '\U0001d714'), - ('\U0001d716', '\U0001d734'), ('\U0001d736', '\U0001d74e'), - ('\U0001d750', '\U0001d76e'), ('\U0001d770', '\U0001d788'), - ('\U0001d78a', '\U0001d7a8'), ('\U0001d7aa', '\U0001d7c2'), - ('\U0001d7c4', '\U0001d7cb'), ('\U0001d7ce', '\U0001d7ff'), - ('\U0001ee00', '\U0001ee03'), ('\U0001ee05', '\U0001ee1f'), - ('\U0001ee21', '\U0001ee22'), ('\U0001ee24', '\U0001ee24'), - ('\U0001ee27', '\U0001ee27'), ('\U0001ee29', '\U0001ee32'), - ('\U0001ee34', '\U0001ee37'), ('\U0001ee39', '\U0001ee39'), - ('\U0001ee3b', '\U0001ee3b'), ('\U0001ee42', '\U0001ee42'), - ('\U0001ee47', '\U0001ee47'), ('\U0001ee49', '\U0001ee49'), - ('\U0001ee4b', '\U0001ee4b'), ('\U0001ee4d', '\U0001ee4f'), - ('\U0001ee51', '\U0001ee52'), ('\U0001ee54', '\U0001ee54'), - ('\U0001ee57', '\U0001ee57'), ('\U0001ee59', '\U0001ee59'), - ('\U0001ee5b', '\U0001ee5b'), ('\U0001ee5d', '\U0001ee5d'), - ('\U0001ee5f', '\U0001ee5f'), ('\U0001ee61', '\U0001ee62'), - ('\U0001ee64', '\U0001ee64'), ('\U0001ee67', '\U0001ee6a'), - ('\U0001ee6c', '\U0001ee72'), ('\U0001ee74', '\U0001ee77'), - ('\U0001ee79', '\U0001ee7c'), ('\U0001ee7e', '\U0001ee7e'), - ('\U0001ee80', '\U0001ee89'), ('\U0001ee8b', '\U0001ee9b'), - ('\U0001eea1', '\U0001eea3'), ('\U0001eea5', '\U0001eea9'), - ('\U0001eeab', '\U0001eebb'), ('\U00020000', '\U0002a6d6'), - ('\U0002a700', '\U0002b734'), ('\U0002b740', '\U0002b81d'), - ('\U0002f800', '\U0002fa1d'), ('\U000e0100', '\U000e01ef') - ]; - - pub fn XID_Continue(c: char) -> bool { - bsearch_range_table(c, XID_Continue_table) - } - - static XID_Start_table : &'static [(char,char)] = &[ - ('\x41', '\x5a'), ('\x61', '\x7a'), - ('\xaa', '\xaa'), ('\xb5', '\xb5'), - ('\xba', '\xba'), ('\xc0', '\xd6'), - ('\xd8', '\xf6'), ('\xf8', '\u01ba'), - ('\u01bb', '\u01bb'), ('\u01bc', '\u01bf'), - ('\u01c0', '\u01c3'), ('\u01c4', '\u0293'), - ('\u0294', '\u0294'), ('\u0295', '\u02af'), - ('\u02b0', '\u02c1'), ('\u02c6', '\u02d1'), - ('\u02e0', '\u02e4'), ('\u02ec', '\u02ec'), - ('\u02ee', '\u02ee'), ('\u0370', '\u0373'), - ('\u0374', '\u0374'), ('\u0376', '\u0377'), - ('\u037b', '\u037d'), ('\u0386', '\u0386'), - ('\u0388', '\u038a'), ('\u038c', '\u038c'), - ('\u038e', '\u03a1'), ('\u03a3', '\u03f5'), - ('\u03f7', '\u0481'), ('\u048a', '\u0527'), - ('\u0531', '\u0556'), ('\u0559', '\u0559'), - ('\u0561', '\u0587'), ('\u05d0', '\u05ea'), - ('\u05f0', '\u05f2'), ('\u0620', '\u063f'), - ('\u0640', '\u0640'), ('\u0641', '\u064a'), - ('\u066e', '\u066f'), ('\u0671', '\u06d3'), - ('\u06d5', '\u06d5'), ('\u06e5', '\u06e6'), - ('\u06ee', '\u06ef'), ('\u06fa', '\u06fc'), - ('\u06ff', '\u06ff'), ('\u0710', '\u0710'), - ('\u0712', '\u072f'), ('\u074d', '\u07a5'), - ('\u07b1', '\u07b1'), ('\u07ca', '\u07ea'), - ('\u07f4', '\u07f5'), ('\u07fa', '\u07fa'), - ('\u0800', '\u0815'), ('\u081a', '\u081a'), - ('\u0824', '\u0824'), ('\u0828', '\u0828'), - ('\u0840', '\u0858'), ('\u08a0', '\u08a0'), - ('\u08a2', '\u08ac'), ('\u0904', '\u0939'), - ('\u093d', '\u093d'), ('\u0950', '\u0950'), - ('\u0958', '\u0961'), ('\u0971', '\u0971'), - ('\u0972', '\u0977'), ('\u0979', '\u097f'), - ('\u0985', '\u098c'), ('\u098f', '\u0990'), - ('\u0993', '\u09a8'), ('\u09aa', '\u09b0'), - ('\u09b2', '\u09b2'), ('\u09b6', '\u09b9'), - ('\u09bd', '\u09bd'), ('\u09ce', '\u09ce'), - ('\u09dc', '\u09dd'), ('\u09df', '\u09e1'), - ('\u09f0', '\u09f1'), ('\u0a05', '\u0a0a'), - ('\u0a0f', '\u0a10'), ('\u0a13', '\u0a28'), - ('\u0a2a', '\u0a30'), ('\u0a32', '\u0a33'), - ('\u0a35', '\u0a36'), ('\u0a38', '\u0a39'), - ('\u0a59', '\u0a5c'), ('\u0a5e', '\u0a5e'), - ('\u0a72', '\u0a74'), ('\u0a85', '\u0a8d'), - ('\u0a8f', '\u0a91'), ('\u0a93', '\u0aa8'), - ('\u0aaa', '\u0ab0'), ('\u0ab2', '\u0ab3'), - ('\u0ab5', '\u0ab9'), ('\u0abd', '\u0abd'), - ('\u0ad0', '\u0ad0'), ('\u0ae0', '\u0ae1'), - ('\u0b05', '\u0b0c'), ('\u0b0f', '\u0b10'), - ('\u0b13', '\u0b28'), ('\u0b2a', '\u0b30'), - ('\u0b32', '\u0b33'), ('\u0b35', '\u0b39'), - ('\u0b3d', '\u0b3d'), ('\u0b5c', '\u0b5d'), - ('\u0b5f', '\u0b61'), ('\u0b71', '\u0b71'), - ('\u0b83', '\u0b83'), ('\u0b85', '\u0b8a'), - ('\u0b8e', '\u0b90'), ('\u0b92', '\u0b95'), - ('\u0b99', '\u0b9a'), ('\u0b9c', '\u0b9c'), - ('\u0b9e', '\u0b9f'), ('\u0ba3', '\u0ba4'), - ('\u0ba8', '\u0baa'), ('\u0bae', '\u0bb9'), - ('\u0bd0', '\u0bd0'), ('\u0c05', '\u0c0c'), - ('\u0c0e', '\u0c10'), ('\u0c12', '\u0c28'), - ('\u0c2a', '\u0c33'), ('\u0c35', '\u0c39'), - ('\u0c3d', '\u0c3d'), ('\u0c58', '\u0c59'), - ('\u0c60', '\u0c61'), ('\u0c85', '\u0c8c'), - ('\u0c8e', '\u0c90'), ('\u0c92', '\u0ca8'), - ('\u0caa', '\u0cb3'), ('\u0cb5', '\u0cb9'), - ('\u0cbd', '\u0cbd'), ('\u0cde', '\u0cde'), - ('\u0ce0', '\u0ce1'), ('\u0cf1', '\u0cf2'), - ('\u0d05', '\u0d0c'), ('\u0d0e', '\u0d10'), - ('\u0d12', '\u0d3a'), ('\u0d3d', '\u0d3d'), - ('\u0d4e', '\u0d4e'), ('\u0d60', '\u0d61'), - ('\u0d7a', '\u0d7f'), ('\u0d85', '\u0d96'), - ('\u0d9a', '\u0db1'), ('\u0db3', '\u0dbb'), - ('\u0dbd', '\u0dbd'), ('\u0dc0', '\u0dc6'), - ('\u0e01', '\u0e30'), ('\u0e32', '\u0e32'), - ('\u0e40', '\u0e45'), ('\u0e46', '\u0e46'), - ('\u0e81', '\u0e82'), ('\u0e84', '\u0e84'), - ('\u0e87', '\u0e88'), ('\u0e8a', '\u0e8a'), - ('\u0e8d', '\u0e8d'), ('\u0e94', '\u0e97'), - ('\u0e99', '\u0e9f'), ('\u0ea1', '\u0ea3'), - ('\u0ea5', '\u0ea5'), ('\u0ea7', '\u0ea7'), - ('\u0eaa', '\u0eab'), ('\u0ead', '\u0eb0'), - ('\u0eb2', '\u0eb2'), ('\u0ebd', '\u0ebd'), - ('\u0ec0', '\u0ec4'), ('\u0ec6', '\u0ec6'), - ('\u0edc', '\u0edf'), ('\u0f00', '\u0f00'), - ('\u0f40', '\u0f47'), ('\u0f49', '\u0f6c'), - ('\u0f88', '\u0f8c'), ('\u1000', '\u102a'), - ('\u103f', '\u103f'), ('\u1050', '\u1055'), - ('\u105a', '\u105d'), ('\u1061', '\u1061'), - ('\u1065', '\u1066'), ('\u106e', '\u1070'), - ('\u1075', '\u1081'), ('\u108e', '\u108e'), - ('\u10a0', '\u10c5'), ('\u10c7', '\u10c7'), - ('\u10cd', '\u10cd'), ('\u10d0', '\u10fa'), - ('\u10fc', '\u10fc'), ('\u10fd', '\u1248'), - ('\u124a', '\u124d'), ('\u1250', '\u1256'), - ('\u1258', '\u1258'), ('\u125a', '\u125d'), - ('\u1260', '\u1288'), ('\u128a', '\u128d'), - ('\u1290', '\u12b0'), ('\u12b2', '\u12b5'), - ('\u12b8', '\u12be'), ('\u12c0', '\u12c0'), - ('\u12c2', '\u12c5'), ('\u12c8', '\u12d6'), - ('\u12d8', '\u1310'), ('\u1312', '\u1315'), - ('\u1318', '\u135a'), ('\u1380', '\u138f'), - ('\u13a0', '\u13f4'), ('\u1401', '\u166c'), - ('\u166f', '\u167f'), ('\u1681', '\u169a'), - ('\u16a0', '\u16ea'), ('\u16ee', '\u16f0'), - ('\u1700', '\u170c'), ('\u170e', '\u1711'), - ('\u1720', '\u1731'), ('\u1740', '\u1751'), - ('\u1760', '\u176c'), ('\u176e', '\u1770'), - ('\u1780', '\u17b3'), ('\u17d7', '\u17d7'), - ('\u17dc', '\u17dc'), ('\u1820', '\u1842'), - ('\u1843', '\u1843'), ('\u1844', '\u1877'), - ('\u1880', '\u18a8'), ('\u18aa', '\u18aa'), - ('\u18b0', '\u18f5'), ('\u1900', '\u191c'), - ('\u1950', '\u196d'), ('\u1970', '\u1974'), - ('\u1980', '\u19ab'), ('\u19c1', '\u19c7'), - ('\u1a00', '\u1a16'), ('\u1a20', '\u1a54'), - ('\u1aa7', '\u1aa7'), ('\u1b05', '\u1b33'), - ('\u1b45', '\u1b4b'), ('\u1b83', '\u1ba0'), - ('\u1bae', '\u1baf'), ('\u1bba', '\u1be5'), - ('\u1c00', '\u1c23'), ('\u1c4d', '\u1c4f'), - ('\u1c5a', '\u1c77'), ('\u1c78', '\u1c7d'), - ('\u1ce9', '\u1cec'), ('\u1cee', '\u1cf1'), - ('\u1cf5', '\u1cf6'), ('\u1d00', '\u1d2b'), - ('\u1d2c', '\u1d6a'), ('\u1d6b', '\u1d77'), - ('\u1d78', '\u1d78'), ('\u1d79', '\u1d9a'), - ('\u1d9b', '\u1dbf'), ('\u1e00', '\u1f15'), - ('\u1f18', '\u1f1d'), ('\u1f20', '\u1f45'), - ('\u1f48', '\u1f4d'), ('\u1f50', '\u1f57'), - ('\u1f59', '\u1f59'), ('\u1f5b', '\u1f5b'), - ('\u1f5d', '\u1f5d'), ('\u1f5f', '\u1f7d'), - ('\u1f80', '\u1fb4'), ('\u1fb6', '\u1fbc'), - ('\u1fbe', '\u1fbe'), ('\u1fc2', '\u1fc4'), - ('\u1fc6', '\u1fcc'), ('\u1fd0', '\u1fd3'), - ('\u1fd6', '\u1fdb'), ('\u1fe0', '\u1fec'), - ('\u1ff2', '\u1ff4'), ('\u1ff6', '\u1ffc'), - ('\u2071', '\u2071'), ('\u207f', '\u207f'), - ('\u2090', '\u209c'), ('\u2102', '\u2102'), - ('\u2107', '\u2107'), ('\u210a', '\u2113'), - ('\u2115', '\u2115'), ('\u2118', '\u2118'), - ('\u2119', '\u211d'), ('\u2124', '\u2124'), - ('\u2126', '\u2126'), ('\u2128', '\u2128'), - ('\u212a', '\u212d'), ('\u212e', '\u212e'), - ('\u212f', '\u2134'), ('\u2135', '\u2138'), - ('\u2139', '\u2139'), ('\u213c', '\u213f'), - ('\u2145', '\u2149'), ('\u214e', '\u214e'), - ('\u2160', '\u2182'), ('\u2183', '\u2184'), - ('\u2185', '\u2188'), ('\u2c00', '\u2c2e'), - ('\u2c30', '\u2c5e'), ('\u2c60', '\u2c7b'), - ('\u2c7c', '\u2c7d'), ('\u2c7e', '\u2ce4'), - ('\u2ceb', '\u2cee'), ('\u2cf2', '\u2cf3'), - ('\u2d00', '\u2d25'), ('\u2d27', '\u2d27'), - ('\u2d2d', '\u2d2d'), ('\u2d30', '\u2d67'), - ('\u2d6f', '\u2d6f'), ('\u2d80', '\u2d96'), - ('\u2da0', '\u2da6'), ('\u2da8', '\u2dae'), - ('\u2db0', '\u2db6'), ('\u2db8', '\u2dbe'), - ('\u2dc0', '\u2dc6'), ('\u2dc8', '\u2dce'), - ('\u2dd0', '\u2dd6'), ('\u2dd8', '\u2dde'), - ('\u3005', '\u3005'), ('\u3006', '\u3006'), - ('\u3007', '\u3007'), ('\u3021', '\u3029'), - ('\u3031', '\u3035'), ('\u3038', '\u303a'), - ('\u303b', '\u303b'), ('\u303c', '\u303c'), - ('\u3041', '\u3096'), ('\u309d', '\u309e'), - ('\u309f', '\u309f'), ('\u30a1', '\u30fa'), - ('\u30fc', '\u30fe'), ('\u30ff', '\u30ff'), - ('\u3105', '\u312d'), ('\u3131', '\u318e'), - ('\u31a0', '\u31ba'), ('\u31f0', '\u31ff'), - ('\u3400', '\u4db5'), ('\u4e00', '\u9fcc'), - ('\ua000', '\ua014'), ('\ua015', '\ua015'), - ('\ua016', '\ua48c'), ('\ua4d0', '\ua4f7'), - ('\ua4f8', '\ua4fd'), ('\ua500', '\ua60b'), - ('\ua60c', '\ua60c'), ('\ua610', '\ua61f'), - ('\ua62a', '\ua62b'), ('\ua640', '\ua66d'), - ('\ua66e', '\ua66e'), ('\ua67f', '\ua67f'), - ('\ua680', '\ua697'), ('\ua6a0', '\ua6e5'), - ('\ua6e6', '\ua6ef'), ('\ua717', '\ua71f'), - ('\ua722', '\ua76f'), ('\ua770', '\ua770'), - ('\ua771', '\ua787'), ('\ua788', '\ua788'), - ('\ua78b', '\ua78e'), ('\ua790', '\ua793'), - ('\ua7a0', '\ua7aa'), ('\ua7f8', '\ua7f9'), - ('\ua7fa', '\ua7fa'), ('\ua7fb', '\ua801'), - ('\ua803', '\ua805'), ('\ua807', '\ua80a'), - ('\ua80c', '\ua822'), ('\ua840', '\ua873'), - ('\ua882', '\ua8b3'), ('\ua8f2', '\ua8f7'), - ('\ua8fb', '\ua8fb'), ('\ua90a', '\ua925'), - ('\ua930', '\ua946'), ('\ua960', '\ua97c'), - ('\ua984', '\ua9b2'), ('\ua9cf', '\ua9cf'), - ('\uaa00', '\uaa28'), ('\uaa40', '\uaa42'), - ('\uaa44', '\uaa4b'), ('\uaa60', '\uaa6f'), - ('\uaa70', '\uaa70'), ('\uaa71', '\uaa76'), - ('\uaa7a', '\uaa7a'), ('\uaa80', '\uaaaf'), - ('\uaab1', '\uaab1'), ('\uaab5', '\uaab6'), - ('\uaab9', '\uaabd'), ('\uaac0', '\uaac0'), - ('\uaac2', '\uaac2'), ('\uaadb', '\uaadc'), - ('\uaadd', '\uaadd'), ('\uaae0', '\uaaea'), - ('\uaaf2', '\uaaf2'), ('\uaaf3', '\uaaf4'), - ('\uab01', '\uab06'), ('\uab09', '\uab0e'), - ('\uab11', '\uab16'), ('\uab20', '\uab26'), - ('\uab28', '\uab2e'), ('\uabc0', '\uabe2'), - ('\uac00', '\ud7a3'), ('\ud7b0', '\ud7c6'), - ('\ud7cb', '\ud7fb'), ('\uf900', '\ufa6d'), - ('\ufa70', '\ufad9'), ('\ufb00', '\ufb06'), - ('\ufb13', '\ufb17'), ('\ufb1d', '\ufb1d'), - ('\ufb1f', '\ufb28'), ('\ufb2a', '\ufb36'), - ('\ufb38', '\ufb3c'), ('\ufb3e', '\ufb3e'), - ('\ufb40', '\ufb41'), ('\ufb43', '\ufb44'), - ('\ufb46', '\ufbb1'), ('\ufbd3', '\ufc5d'), - ('\ufc64', '\ufd3d'), ('\ufd50', '\ufd8f'), - ('\ufd92', '\ufdc7'), ('\ufdf0', '\ufdf9'), - ('\ufe71', '\ufe71'), ('\ufe73', '\ufe73'), - ('\ufe77', '\ufe77'), ('\ufe79', '\ufe79'), - ('\ufe7b', '\ufe7b'), ('\ufe7d', '\ufe7d'), - ('\ufe7f', '\ufefc'), ('\uff21', '\uff3a'), - ('\uff41', '\uff5a'), ('\uff66', '\uff6f'), - ('\uff70', '\uff70'), ('\uff71', '\uff9d'), - ('\uffa0', '\uffbe'), ('\uffc2', '\uffc7'), - ('\uffca', '\uffcf'), ('\uffd2', '\uffd7'), - ('\uffda', '\uffdc'), ('\U00010000', '\U0001000b'), - ('\U0001000d', '\U00010026'), ('\U00010028', '\U0001003a'), - ('\U0001003c', '\U0001003d'), ('\U0001003f', '\U0001004d'), - ('\U00010050', '\U0001005d'), ('\U00010080', '\U000100fa'), - ('\U00010140', '\U00010174'), ('\U00010280', '\U0001029c'), - ('\U000102a0', '\U000102d0'), ('\U00010300', '\U0001031e'), - ('\U00010330', '\U00010340'), ('\U00010341', '\U00010341'), - ('\U00010342', '\U00010349'), ('\U0001034a', '\U0001034a'), - ('\U00010380', '\U0001039d'), ('\U000103a0', '\U000103c3'), - ('\U000103c8', '\U000103cf'), ('\U000103d1', '\U000103d5'), - ('\U00010400', '\U0001044f'), ('\U00010450', '\U0001049d'), - ('\U00010800', '\U00010805'), ('\U00010808', '\U00010808'), - ('\U0001080a', '\U00010835'), ('\U00010837', '\U00010838'), - ('\U0001083c', '\U0001083c'), ('\U0001083f', '\U00010855'), - ('\U00010900', '\U00010915'), ('\U00010920', '\U00010939'), - ('\U00010980', '\U000109b7'), ('\U000109be', '\U000109bf'), - ('\U00010a00', '\U00010a00'), ('\U00010a10', '\U00010a13'), - ('\U00010a15', '\U00010a17'), ('\U00010a19', '\U00010a33'), - ('\U00010a60', '\U00010a7c'), ('\U00010b00', '\U00010b35'), - ('\U00010b40', '\U00010b55'), ('\U00010b60', '\U00010b72'), - ('\U00010c00', '\U00010c48'), ('\U00011003', '\U00011037'), - ('\U00011083', '\U000110af'), ('\U000110d0', '\U000110e8'), - ('\U00011103', '\U00011126'), ('\U00011183', '\U000111b2'), - ('\U000111c1', '\U000111c4'), ('\U00011680', '\U000116aa'), - ('\U00012000', '\U0001236e'), ('\U00012400', '\U00012462'), - ('\U00013000', '\U0001342e'), ('\U00016800', '\U00016a38'), - ('\U00016f00', '\U00016f44'), ('\U00016f50', '\U00016f50'), - ('\U00016f93', '\U00016f9f'), ('\U0001b000', '\U0001b001'), - ('\U0001d400', '\U0001d454'), ('\U0001d456', '\U0001d49c'), - ('\U0001d49e', '\U0001d49f'), ('\U0001d4a2', '\U0001d4a2'), - ('\U0001d4a5', '\U0001d4a6'), ('\U0001d4a9', '\U0001d4ac'), - ('\U0001d4ae', '\U0001d4b9'), ('\U0001d4bb', '\U0001d4bb'), - ('\U0001d4bd', '\U0001d4c3'), ('\U0001d4c5', '\U0001d505'), - ('\U0001d507', '\U0001d50a'), ('\U0001d50d', '\U0001d514'), - ('\U0001d516', '\U0001d51c'), ('\U0001d51e', '\U0001d539'), - ('\U0001d53b', '\U0001d53e'), ('\U0001d540', '\U0001d544'), - ('\U0001d546', '\U0001d546'), ('\U0001d54a', '\U0001d550'), - ('\U0001d552', '\U0001d6a5'), ('\U0001d6a8', '\U0001d6c0'), - ('\U0001d6c2', '\U0001d6da'), ('\U0001d6dc', '\U0001d6fa'), - ('\U0001d6fc', '\U0001d714'), ('\U0001d716', '\U0001d734'), - ('\U0001d736', '\U0001d74e'), ('\U0001d750', '\U0001d76e'), - ('\U0001d770', '\U0001d788'), ('\U0001d78a', '\U0001d7a8'), - ('\U0001d7aa', '\U0001d7c2'), ('\U0001d7c4', '\U0001d7cb'), - ('\U0001ee00', '\U0001ee03'), ('\U0001ee05', '\U0001ee1f'), - ('\U0001ee21', '\U0001ee22'), ('\U0001ee24', '\U0001ee24'), - ('\U0001ee27', '\U0001ee27'), ('\U0001ee29', '\U0001ee32'), - ('\U0001ee34', '\U0001ee37'), ('\U0001ee39', '\U0001ee39'), - ('\U0001ee3b', '\U0001ee3b'), ('\U0001ee42', '\U0001ee42'), - ('\U0001ee47', '\U0001ee47'), ('\U0001ee49', '\U0001ee49'), - ('\U0001ee4b', '\U0001ee4b'), ('\U0001ee4d', '\U0001ee4f'), - ('\U0001ee51', '\U0001ee52'), ('\U0001ee54', '\U0001ee54'), - ('\U0001ee57', '\U0001ee57'), ('\U0001ee59', '\U0001ee59'), - ('\U0001ee5b', '\U0001ee5b'), ('\U0001ee5d', '\U0001ee5d'), - ('\U0001ee5f', '\U0001ee5f'), ('\U0001ee61', '\U0001ee62'), - ('\U0001ee64', '\U0001ee64'), ('\U0001ee67', '\U0001ee6a'), - ('\U0001ee6c', '\U0001ee72'), ('\U0001ee74', '\U0001ee77'), - ('\U0001ee79', '\U0001ee7c'), ('\U0001ee7e', '\U0001ee7e'), - ('\U0001ee80', '\U0001ee89'), ('\U0001ee8b', '\U0001ee9b'), - ('\U0001eea1', '\U0001eea3'), ('\U0001eea5', '\U0001eea9'), - ('\U0001eeab', '\U0001eebb'), ('\U00020000', '\U0002a6d6'), - ('\U0002a700', '\U0002b734'), ('\U0002b740', '\U0002b81d'), - ('\U0002f800', '\U0002fa1d') - ]; - - pub fn XID_Start(c: char) -> bool { - bsearch_range_table(c, XID_Start_table) - } -} diff --git a/src/libstd/arc.rs b/src/libextra/arc.rs similarity index 77% rename from src/libstd/arc.rs rename to src/libextra/arc.rs index df49771258e29..15c24052563b4 100644 --- a/src/libstd/arc.rs +++ b/src/libextra/arc.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,11 +8,39 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/** +/*! * Concurrency-enabled mechanisms for sharing mutable and/or immutable state * between tasks. + * + * # Example + * + * In this example, a large vector of floats is shared between several tasks. + * With simple pipes, without ARC, a copy would have to be made for each task. + * + * ~~~ {.rust} + * extern mod std; + * use std::arc; + * let numbers=vec::from_fn(100, |ind| (ind as float)*rand::random()); + * let shared_numbers=arc::ARC(numbers); + * + * for 10.times { + * let (port, chan) = stream(); + * chan.send(shared_numbers.clone()); + * + * do spawn { + * let shared_numbers=port.recv(); + * let local_numbers=shared_numbers.get(); + * + * // Work with the local numbers + * } + * } + * ~~~ */ +#[allow(missing_doc)]; + +use core::prelude::*; + use sync; use sync::{Mutex, mutex_with_condvars, RWlock, rwlock_with_condvars}; @@ -20,18 +48,19 @@ use core::cast; use core::unstable::sync::UnsafeAtomicRcBox; use core::ptr; use core::task; +use core::borrow; -/// As sync::condvar, a mechanism for unlock-and-descheduling and signalling. +/// As sync::condvar, a mechanism for unlock-and-descheduling and signaling. pub struct Condvar<'self> { is_mutex: bool, failed: &'self mut bool, cond: &'self sync::Condvar<'self> } -pub impl<'self> Condvar<'self> { +impl<'self> Condvar<'self> { /// Atomically exit the associated ARC and block until a signal is sent. #[inline(always)] - fn wait(&self) { self.wait_on(0) } + pub fn wait(&self) { self.wait_on(0) } /** * Atomically exit the associated ARC and block on a specified condvar @@ -40,7 +69,7 @@ pub impl<'self> Condvar<'self> { * wait() is equivalent to wait_on(0). */ #[inline(always)] - fn wait_on(&self, condvar_id: uint) { + pub fn wait_on(&self, condvar_id: uint) { assert!(!*self.failed); self.cond.wait_on(condvar_id); // This is why we need to wrap sync::condvar. @@ -49,28 +78,28 @@ pub impl<'self> Condvar<'self> { /// Wake up a blocked task. Returns false if there was no blocked task. #[inline(always)] - fn signal(&self) -> bool { self.signal_on(0) } + pub fn signal(&self) -> bool { self.signal_on(0) } /** * Wake up a blocked task on a specified condvar (as * sync::cond.signal_on). Returns false if there was no blocked task. */ #[inline(always)] - fn signal_on(&self, condvar_id: uint) -> bool { + pub fn signal_on(&self, condvar_id: uint) -> bool { assert!(!*self.failed); self.cond.signal_on(condvar_id) } /// Wake up all blocked tasks. Returns the number of tasks woken. #[inline(always)] - fn broadcast(&self) -> uint { self.broadcast_on(0) } + pub fn broadcast(&self) -> uint { self.broadcast_on(0) } /** * Wake up all blocked tasks on a specified condvar (as * sync::cond.broadcast_on). Returns Returns the number of tasks woken. */ #[inline(always)] - fn broadcast_on(&self, condvar_id: uint) -> uint { + pub fn broadcast_on(&self, condvar_id: uint) -> uint { assert!(!*self.failed); self.cond.broadcast_on(condvar_id) } @@ -81,7 +110,7 @@ pub impl<'self> Condvar<'self> { ****************************************************************************/ /// An atomically reference counted wrapper for shared immutable state. -struct ARC { x: UnsafeAtomicRcBox } +pub struct ARC { x: UnsafeAtomicRcBox } /// Create an atomically reference counted wrapper. pub fn ARC(data: T) -> ARC { @@ -92,8 +121,10 @@ pub fn ARC(data: T) -> ARC { * Access the underlying data in an atomically reference counted * wrapper. */ -pub fn get<'a, T:Const + Owned>(rc: &'a ARC) -> &'a T { - unsafe { &*rc.x.get_immut() } +impl ARC { + pub fn get<'a>(&'a self) -> &'a T { + unsafe { &*self.x.get_immut() } + } } /** @@ -103,13 +134,9 @@ pub fn get<'a, T:Const + Owned>(rc: &'a ARC) -> &'a T { * object. However, one of the `arc` objects can be sent to another task, * allowing them to share the underlying data. */ -pub fn clone(rc: &ARC) -> ARC { - ARC { x: rc.x.clone() } -} - impl Clone for ARC { fn clone(&self) -> ARC { - clone(self) + ARC { x: self.x.clone() } } } @@ -147,7 +174,7 @@ impl Clone for MutexARC { } } -pub impl MutexARC { +impl MutexARC { /** * Access the underlying mutable data with mutual exclusion from other @@ -173,23 +200,25 @@ pub impl MutexARC { * blocked on the mutex) will also fail immediately. */ #[inline(always)] - unsafe fn access(&self, blk: &fn(x: &mut T) -> U) -> U { - let state = self.x.get(); - // Borrowck would complain about this if the function were - // not already unsafe. See borrow_rwlock, far below. - do (&(*state).lock).lock { - check_poison(true, (*state).failed); - let _z = PoisonOnFail(&mut (*state).failed); - blk(&mut (*state).data) + pub unsafe fn access(&self, blk: &fn(x: &mut T) -> U) -> U { + unsafe { + let state = self.x.get(); + // Borrowck would complain about this if the function were + // not already unsafe. See borrow_rwlock, far below. + do (&(*state).lock).lock { + check_poison(true, (*state).failed); + let _z = PoisonOnFail(&mut (*state).failed); + blk(&mut (*state).data) + } } } /// As access(), but with a condvar, as sync::mutex.lock_cond(). #[inline(always)] - unsafe fn access_cond<'x, 'c, U>( - &self, - blk: &fn(x: &'x mut T, c: &'c Condvar) -> U) -> U - { + pub unsafe fn access_cond<'x, 'c, U>(&self, + blk: &fn(x: &'x mut T, + c: &'c Condvar) -> U) + -> U { let state = self.x.get(); do (&(*state).lock).lock_cond |cond| { check_poison(true, (*state).failed); @@ -274,16 +303,18 @@ pub fn rw_arc_with_condvars( RWARC { x: UnsafeAtomicRcBox::new(data), cant_nest: () } } -pub impl RWARC { +impl RWARC { /// Duplicate a rwlock-protected ARC, as arc::clone. - fn clone(&self) -> RWARC { - RWARC { x: self.x.clone(), - cant_nest: () } + pub fn clone(&self) -> RWARC { + RWARC { + x: self.x.clone(), + cant_nest: (), + } } } -pub impl RWARC { +impl RWARC { /** * Access the underlying data mutably. Locks the rwlock in write mode; * other readers and writers will block. @@ -295,7 +326,7 @@ pub impl RWARC { * poison the ARC, so subsequent readers and writers will both also fail. */ #[inline(always)] - fn write(&self, blk: &fn(x: &mut T) -> U) -> U { + pub fn write(&self, blk: &fn(x: &mut T) -> U) -> U { unsafe { let state = self.x.get(); do (*borrow_rwlock(state)).write { @@ -305,11 +336,12 @@ pub impl RWARC { } } } + /// As write(), but with a condvar, as sync::rwlock.write_cond(). #[inline(always)] - fn write_cond<'x, 'c, U>(&self, - blk: &fn(x: &'x mut T, c: &'c Condvar) -> U) - -> U { + pub fn write_cond<'x, 'c, U>(&self, + blk: &fn(x: &'x mut T, c: &'c Condvar) -> U) + -> U { unsafe { let state = self.x.get(); do (*borrow_rwlock(state)).write_cond |cond| { @@ -322,6 +354,7 @@ pub impl RWARC { } } } + /** * Access the underlying data immutably. May run concurrently with other * reading tasks. @@ -331,9 +364,9 @@ pub impl RWARC { * Failing will unlock the ARC while unwinding. However, unlike all other * access modes, this will not poison the ARC. */ - fn read(&self, blk: &fn(x: &T) -> U) -> U { - let state = self.x.get(); + pub fn read(&self, blk: &fn(x: &T) -> U) -> U { unsafe { + let state = self.x.get(); do (*state).lock.read { check_poison(false, (*state).failed); blk(&(*state).data) @@ -346,7 +379,10 @@ pub impl RWARC { * See sync::rwlock.write_downgrade(). The RWWriteMode token must be used * to obtain the &mut T, and can be transformed into a RWReadMode token by * calling downgrade(), after which a &T can be obtained instead. - * ~~~ + * + * # Example + * + * ~~~ {.rust} * do arc.write_downgrade |write_mode| { * do (&write_mode).write_cond |state, condvar| { * ... exclusive access with mutable state ... @@ -358,7 +394,7 @@ pub impl RWARC { * } * ~~~ */ - fn write_downgrade(&self, blk: &fn(v: RWWriteMode) -> U) -> U { + pub fn write_downgrade(&self, blk: &fn(v: RWWriteMode) -> U) -> U { unsafe { let state = self.x.get(); do (*borrow_rwlock(state)).write_downgrade |write_mode| { @@ -373,7 +409,8 @@ pub impl RWARC { } /// To be called inside of the write_downgrade block. - fn downgrade<'a>(&self, token: RWWriteMode<'a, T>) -> RWReadMode<'a, T> { + pub fn downgrade<'a>(&self, token: RWWriteMode<'a, T>) + -> RWReadMode<'a, T> { unsafe { // The rwlock should assert that the token belongs to us for us. let state = self.x.get(); @@ -389,7 +426,7 @@ pub impl RWARC { // of this cast is removing the mutability.) let new_data = cast::transmute_immut(data); // Downgrade ensured the token belonged to us. Just a sanity check. - assert!(ptr::ref_eq(&(*state).data, new_data)); + assert!(borrow::ref_eq(&(*state).data, new_data)); // Produce new token RWReadMode { data: new_data, @@ -420,9 +457,9 @@ pub struct RWReadMode<'self, T> { token: sync::RWlockReadMode<'self>, } -pub impl<'self, T:Const + Owned> RWWriteMode<'self, T> { +impl<'self, T:Const + Owned> RWWriteMode<'self, T> { /// Access the pre-downgrade RWARC in write mode. - fn write(&mut self, blk: &fn(x: &mut T) -> U) -> U { + pub fn write(&mut self, blk: &fn(x: &mut T) -> U) -> U { match *self { RWWriteMode { data: &ref mut data, @@ -435,10 +472,11 @@ pub impl<'self, T:Const + Owned> RWWriteMode<'self, T> { } } } + /// Access the pre-downgrade RWARC in write mode with a condvar. - fn write_cond<'x, 'c, U>(&mut self, - blk: &fn(x: &'x mut T, c: &'c Condvar) -> U) - -> U { + pub fn write_cond<'x, 'c, U>(&mut self, + blk: &fn(x: &'x mut T, c: &'c Condvar) -> U) + -> U { match *self { RWWriteMode { data: &ref mut data, @@ -460,9 +498,9 @@ pub impl<'self, T:Const + Owned> RWWriteMode<'self, T> { } } -pub impl<'self, T:Const + Owned> RWReadMode<'self, T> { +impl<'self, T:Const + Owned> RWReadMode<'self, T> { /// Access the post-downgrade rwlock in read mode. - fn read(&self, blk: &fn(x: &T) -> U) -> U { + pub fn read(&self, blk: &fn(x: &T) -> U) -> U { match *self { RWReadMode { data: data, @@ -480,17 +518,18 @@ pub impl<'self, T:Const + Owned> RWReadMode<'self, T> { #[cfg(test)] mod tests { + use core::prelude::*; use arc::*; - use arc; use core::cell::Cell; + use core::comm; use core::task; #[test] fn manually_share_arc() { let v = ~[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - let arc_v = arc::ARC(v); + let arc_v = ARC(v); let (p, c) = comm::stream(); @@ -498,75 +537,82 @@ mod tests { let p = comm::PortSet::new(); c.send(p.chan()); - let arc_v = p.recv(); + let arc_v : ARC<~[int]> = p.recv(); - let v = copy *arc::get::<~[int]>(&arc_v); - assert!(v[3] == 4); + let v = copy (*arc_v.get()); + assert_eq!(v[3], 4); }; let c = p.recv(); - c.send(arc::clone(&arc_v)); + c.send(arc_v.clone()); - assert!((*arc::get(&arc_v))[2] == 3); + assert_eq!(arc_v.get()[2], 3); + assert_eq!(arc_v.get()[4], 5); info!(arc_v); } #[test] fn test_mutex_arc_condvar() { - let arc = ~MutexARC(false); - let arc2 = ~arc.clone(); - let (p,c) = comm::oneshot(); - let (c,p) = (Cell(c), Cell(p)); - do task::spawn || { - // wait until parent gets in - comm::recv_one(p.take()); - do arc2.access_cond |state, cond| { - *state = true; - cond.signal(); + unsafe { + let arc = ~MutexARC(false); + let arc2 = ~arc.clone(); + let (p,c) = comm::oneshot(); + let (c,p) = (Cell::new(c), Cell::new(p)); + do task::spawn || { + // wait until parent gets in + comm::recv_one(p.take()); + do arc2.access_cond |state, cond| { + *state = true; + cond.signal(); + } } - } - do arc.access_cond |state, cond| { - comm::send_one(c.take(), ()); - assert!(!*state); - while !*state { - cond.wait(); + do arc.access_cond |state, cond| { + comm::send_one(c.take(), ()); + assert!(!*state); + while !*state { + cond.wait(); + } } } } #[test] #[should_fail] #[ignore(cfg(windows))] fn test_arc_condvar_poison() { - let arc = ~MutexARC(1); - let arc2 = ~arc.clone(); - let (p, c) = comm::stream(); - - do task::spawn_unlinked || { - let _ = p.recv(); - do arc2.access_cond |one, cond| { - cond.signal(); - // Parent should fail when it wakes up. - assert!(*one == 0); + unsafe { + let arc = ~MutexARC(1); + let arc2 = ~arc.clone(); + let (p, c) = comm::stream(); + + do task::spawn_unlinked || { + let _ = p.recv(); + do arc2.access_cond |one, cond| { + cond.signal(); + // Parent should fail when it wakes up. + assert_eq!(*one, 0); + } } - } - do arc.access_cond |one, cond| { - c.send(()); - while *one == 1 { - cond.wait(); + do arc.access_cond |one, cond| { + c.send(()); + while *one == 1 { + cond.wait(); + } } } } #[test] #[should_fail] #[ignore(cfg(windows))] fn test_mutex_arc_poison() { - let arc = ~MutexARC(1); - let arc2 = ~arc.clone(); - do task::try || { - do arc2.access |one| { - assert!(*one == 2); + unsafe { + let arc = ~MutexARC(1); + let arc2 = ~arc.clone(); + do task::try || { + do arc2.access |one| { + assert_eq!(*one, 2); + } + }; + do arc.access |one| { + assert_eq!(*one, 1); } - }; - do arc.access |one| { - assert!(*one == 1); } } #[test] #[should_fail] #[ignore(cfg(windows))] @@ -575,11 +621,11 @@ mod tests { let arc2 = (*arc).clone(); do task::try || { do arc2.write |one| { - assert!(*one == 2); + assert_eq!(*one, 2); } }; do arc.read |one| { - assert!(*one == 1); + assert_eq!(*one, 1); } } #[test] #[should_fail] #[ignore(cfg(windows))] @@ -588,11 +634,11 @@ mod tests { let arc2 = (*arc).clone(); do task::try || { do arc2.write |one| { - assert!(*one == 2); + assert_eq!(*one, 2); } }; do arc.write |one| { - assert!(*one == 1); + assert_eq!(*one, 1); } } #[test] #[should_fail] #[ignore(cfg(windows))] @@ -602,12 +648,12 @@ mod tests { do task::try || { do arc2.write_downgrade |mut write_mode| { do write_mode.write |one| { - assert!(*one == 2); + assert_eq!(*one, 2); } } }; do arc.write |one| { - assert!(*one == 1); + assert_eq!(*one, 1); } } #[test] #[ignore(cfg(windows))] @@ -616,11 +662,11 @@ mod tests { let arc2 = (*arc).clone(); do task::try || { do arc2.read |one| { - assert!(*one == 2); + assert_eq!(*one, 2); } }; do arc.read |one| { - assert!(*one == 1); + assert_eq!(*one, 1); } } #[test] #[ignore(cfg(windows))] @@ -629,11 +675,11 @@ mod tests { let arc2 = (*arc).clone(); do task::try || { do arc2.read |one| { - assert!(*one == 2); + assert_eq!(*one, 2); } }; do arc.write |one| { - assert!(*one == 1); + assert_eq!(*one, 1); } } #[test] #[ignore(cfg(windows))] @@ -644,12 +690,12 @@ mod tests { do arc2.write_downgrade |write_mode| { let read_mode = arc2.downgrade(write_mode); do (&read_mode).read |one| { - assert!(*one == 2); + assert_eq!(*one, 2); } } }; do arc.write |one| { - assert!(*one == 1); + assert_eq!(*one, 1); } } #[test] @@ -691,7 +737,7 @@ mod tests { // Wait for writer to finish p.recv(); do arc.read |num| { - assert!(*num == 10); + assert_eq!(*num, 10); } } #[test] @@ -713,7 +759,7 @@ mod tests { do task::spawn || { rp1.recv(); // wait for downgrader to give go-ahead do arcn.read |state| { - assert!(*state == 31337); + assert_eq!(*state, 31337); rc2.send(()); } } @@ -725,7 +771,7 @@ mod tests { do task::spawn || { wp1.recv(); do arc2.write_cond |state, cond| { - assert!(*state == 0); + assert_eq!(*state, 0); *state = 42; cond.signal(); } @@ -733,7 +779,7 @@ mod tests { do arc2.write |state| { // This shouldn't happen until after the downgrade read // section, and all other readers, finish. - assert!(*state == 31337); + assert_eq!(*state, 31337); *state = 42; } wc2.send(()); @@ -746,7 +792,7 @@ mod tests { while *state == 0 { cond.wait(); } - assert!(*state == 42); + assert_eq!(*state, 42); *state = 31337; // send to other readers for reader_convos.each |x| { @@ -764,7 +810,7 @@ mod tests { } } wc1.send(()); // tell writer to try again - assert!(*state == 31337); + assert_eq!(*state, 31337); } } diff --git a/src/libstd/arena.rs b/src/libextra/arena.rs similarity index 90% rename from src/libstd/arena.rs rename to src/libextra/arena.rs index fd9fba8c1d753..2926d5958f16c 100644 --- a/src/libstd/arena.rs +++ b/src/libextra/arena.rs @@ -32,6 +32,10 @@ // overhead when initializing plain-old-data and means we don't need // to waste time running the destructors of POD. +#[allow(missing_doc)]; + +use core::prelude::*; + use list::{MutList, MutCons, MutNil}; use core::at_vec; @@ -43,14 +47,7 @@ use core::sys::TypeDesc; use core::sys; use core::uint; use core::vec; - -pub mod rusti { - #[abi = "rust-intrinsic"] - pub extern "rust-intrinsic" { - fn move_val_init(dst: &mut T, src: T); - fn needs_drop() -> bool; - } -} +use core::unstable::intrinsics; pub mod rustrt { use core::libc::size_t; @@ -137,7 +134,7 @@ unsafe fn destroy_chunk(chunk: &Chunk) { while idx < fill { let tydesc_data: *uint = transmute(ptr::offset(buf, idx)); let (tydesc, is_done) = un_bitpack_tydesc_ptr(*tydesc_data); - let size = (*tydesc).size, align = (*tydesc).align; + let (size, align) = ((*tydesc).size, (*tydesc).align); let after_tydesc = idx + sys::size_of::<*TypeDesc>(); @@ -169,9 +166,9 @@ unsafe fn un_bitpack_tydesc_ptr(p: uint) -> (*TypeDesc, bool) { (transmute(p & !1), p & 1 == 1) } -pub impl Arena { +impl Arena { // Functions for the POD part of the arena - priv fn alloc_pod_grow(&mut self, n_bytes: uint, align: uint) -> *u8 { + fn alloc_pod_grow(&mut self, n_bytes: uint, align: uint) -> *u8 { // Allocate a new chunk. let chunk_size = at_vec::capacity(self.pod_head.data); let new_min_chunk_size = uint::max(n_bytes, chunk_size); @@ -183,7 +180,7 @@ pub impl Arena { } #[inline(always)] - priv fn alloc_pod_inner(&mut self, n_bytes: uint, align: uint) -> *u8 { + fn alloc_pod_inner(&mut self, n_bytes: uint, align: uint) -> *u8 { unsafe { // XXX: Borrow check let head = transmute_mut_region(&mut self.pod_head); @@ -203,19 +200,19 @@ pub impl Arena { } #[inline(always)] - priv fn alloc_pod<'a, T>(&'a mut self, op: &fn() -> T) -> &'a T { + fn alloc_pod<'a, T>(&'a mut self, op: &fn() -> T) -> &'a T { unsafe { let tydesc = sys::get_type_desc::(); let ptr = self.alloc_pod_inner((*tydesc).size, (*tydesc).align); let ptr: *mut T = transmute(ptr); - rusti::move_val_init(&mut (*ptr), op()); + intrinsics::move_val_init(&mut (*ptr), op()); return transmute(ptr); } } // Functions for the non-POD part of the arena - priv fn alloc_nonpod_grow(&mut self, n_bytes: uint, align: uint) - -> (*u8, *u8) { + fn alloc_nonpod_grow(&mut self, n_bytes: uint, align: uint) + -> (*u8, *u8) { // Allocate a new chunk. let chunk_size = at_vec::capacity(self.head.data); let new_min_chunk_size = uint::max(n_bytes, chunk_size); @@ -227,8 +224,8 @@ pub impl Arena { } #[inline(always)] - priv fn alloc_nonpod_inner(&mut self, n_bytes: uint, align: uint) - -> (*u8, *u8) { + fn alloc_nonpod_inner(&mut self, n_bytes: uint, align: uint) + -> (*u8, *u8) { unsafe { let head = transmute_mut_region(&mut self.head); @@ -250,7 +247,7 @@ pub impl Arena { } #[inline(always)] - priv fn alloc_nonpod<'a, T>(&'a mut self, op: &fn() -> T) -> &'a T { + fn alloc_nonpod<'a, T>(&'a mut self, op: &fn() -> T) -> &'a T { unsafe { let tydesc = sys::get_type_desc::(); let (ty_ptr, ptr) = @@ -261,7 +258,7 @@ pub impl Arena { // has *not* been initialized yet. *ty_ptr = transmute(tydesc); // Actually initialize it - rusti::move_val_init(&mut(*ptr), op()); + intrinsics::move_val_init(&mut(*ptr), op()); // Now that we are done, update the tydesc to indicate that // the object is there. *ty_ptr = bitpack_tydesc_ptr(tydesc, true); @@ -272,11 +269,11 @@ pub impl Arena { // The external interface #[inline(always)] - fn alloc<'a, T>(&'a mut self, op: &fn() -> T) -> &'a T { + pub fn alloc<'a, T>(&'a mut self, op: &fn() -> T) -> &'a T { unsafe { // XXX: Borrow check let this = transmute_mut_region(self); - if !rusti::needs_drop::() { + if !intrinsics::needs_drop::() { return this.alloc_pod(op); } // XXX: Borrow check diff --git a/src/libstd/base64.rs b/src/libextra/base64.rs similarity index 83% rename from src/libstd/base64.rs rename to src/libextra/base64.rs index 68242f88fae5e..b8f3a267d2d24 100644 --- a/src/libstd/base64.rs +++ b/src/libextra/base64.rs @@ -10,11 +10,15 @@ //! Base64 binary-to-text encoding -use core::old_iter; +use core::prelude::*; + use core::str; use core::vec; +/// A trait for converting a value to base64 encoding. pub trait ToBase64 { + /// Converts the value of `self` to a base64 value, returning the owned + /// string fn to_base64(&self) -> ~str; } @@ -30,9 +34,9 @@ impl<'self> ToBase64 for &'self [u8] { /** * Turn a vector of `u8` bytes into a base64 string. * - * *Example*: + * # Example * - * ~~~~ + * ~~~ {.rust} * extern mod std; * use std::base64::ToBase64; * @@ -40,7 +44,7 @@ impl<'self> ToBase64 for &'self [u8] { * let str = [52,32].to_base64(); * println(fmt!("%s", str)); * } - * ~~~~ + * ~~~ */ fn to_base64(&self) -> ~str { let mut s = ~""; @@ -93,9 +97,9 @@ impl<'self> ToBase64 for &'self str { * Convert any string (literal, `@`, `&`, or `~`) to base64 encoding. * * - * *Example*: + * # Example * - * ~~~~ + * ~~~ {.rust} * extern mod std; * use std::base64::ToBase64; * @@ -103,7 +107,7 @@ impl<'self> ToBase64 for &'self str { * let str = "Hello, World".to_base64(); * println(fmt!("%s",str)); * } - * ~~~~ + * ~~~ * */ fn to_base64(&self) -> ~str { @@ -111,18 +115,19 @@ impl<'self> ToBase64 for &'self str { } } +#[allow(missing_doc)] pub trait FromBase64 { fn from_base64(&self) -> ~[u8]; } -impl FromBase64 for ~[u8] { +impl<'self> FromBase64 for &'self [u8] { /** * Convert base64 `u8` vector into u8 byte values. * Every 4 encoded characters is converted into 3 octets, modulo padding. * - * *Example*: + * # Example * - * ~~~~ + * ~~~ {.rust} * extern mod std; * use std::base64::ToBase64; * use std::base64::FromBase64; @@ -133,7 +138,7 @@ impl FromBase64 for ~[u8] { * let bytes = str.from_base64(); * println(fmt!("%?",bytes)); * } - * ~~~~ + * ~~~ */ fn from_base64(&self) -> ~[u8] { if self.len() % 4u != 0u { fail!("invalid base64 length"); } @@ -152,7 +157,7 @@ impl FromBase64 for ~[u8] { while i < len { let mut n = 0u; - for old_iter::repeat(4u) { + for 4u.times { let ch = self[i] as char; n <<= 6u; @@ -190,7 +195,7 @@ impl FromBase64 for ~[u8] { } } -impl FromBase64 for ~str { +impl<'self> FromBase64 for &'self str { /** * Convert any base64 encoded string (literal, `@`, `&`, or `~`) * to the byte values it encodes. @@ -198,11 +203,11 @@ impl FromBase64 for ~str { * You can use the `from_bytes` function in `core::str` * to turn a `[u8]` into a string with characters corresponding to those values. * - * *Example*: + * # Example * * This converts a string literal to base64 and back. * - * ~~~~ + * ~~~ {.rust} * extern mod std; * use std::base64::ToBase64; * use std::base64::FromBase64; @@ -216,7 +221,7 @@ impl FromBase64 for ~str { * let result_str = str::from_bytes(bytes); * println(fmt!("%s",result_str)); * } - * ~~~~ + * ~~~ */ fn from_base64(&self) -> ~[u8] { str::to_bytes(*self).from_base64() @@ -229,23 +234,23 @@ mod tests { #[test] fn test_to_base64() { - assert!((~"").to_base64() == ~""); - assert!((~"f").to_base64() == ~"Zg=="); - assert!((~"fo").to_base64() == ~"Zm8="); - assert!((~"foo").to_base64() == ~"Zm9v"); - assert!((~"foob").to_base64() == ~"Zm9vYg=="); - assert!((~"fooba").to_base64() == ~"Zm9vYmE="); - assert!((~"foobar").to_base64() == ~"Zm9vYmFy"); + assert_eq!("".to_base64(), ~""); + assert_eq!("f".to_base64(), ~"Zg=="); + assert_eq!("fo".to_base64(), ~"Zm8="); + assert_eq!("foo".to_base64(), ~"Zm9v"); + assert_eq!("foob".to_base64(), ~"Zm9vYg=="); + assert_eq!("fooba".to_base64(), ~"Zm9vYmE="); + assert_eq!("foobar".to_base64(), ~"Zm9vYmFy"); } #[test] fn test_from_base64() { - assert!((~"").from_base64() == str::to_bytes(~"")); - assert!((~"Zg==").from_base64() == str::to_bytes(~"f")); - assert!((~"Zm8=").from_base64() == str::to_bytes(~"fo")); - assert!((~"Zm9v").from_base64() == str::to_bytes(~"foo")); - assert!((~"Zm9vYg==").from_base64() == str::to_bytes(~"foob")); - assert!((~"Zm9vYmE=").from_base64() == str::to_bytes(~"fooba")); - assert!((~"Zm9vYmFy").from_base64() == str::to_bytes(~"foobar")); + assert_eq!("".from_base64(), str::to_bytes("")); + assert_eq!("Zg==".from_base64(), str::to_bytes("f")); + assert_eq!("Zm8=".from_base64(), str::to_bytes("fo")); + assert_eq!("Zm9v".from_base64(), str::to_bytes("foo")); + assert_eq!("Zm9vYg==".from_base64(), str::to_bytes("foob")); + assert_eq!("Zm9vYmE=".from_base64(), str::to_bytes("fooba")) + assert_eq!("Zm9vYmFy".from_base64(), str::to_bytes("foobar")); } } diff --git a/src/libstd/bitv.rs b/src/libextra/bitv.rs similarity index 87% rename from src/libstd/bitv.rs rename to src/libextra/bitv.rs index e31818ecc1c16..e3a15f76c786b 100644 --- a/src/libstd/bitv.rs +++ b/src/libextra/bitv.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,7 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::vec::from_elem; +#[allow(missing_doc)]; + +use core::prelude::*; + +use core::cmp; +use core::ops; +use core::uint; +use core::vec; struct SmallBitv { /// only the lowest nbits of this value are used. the rest is undefined. @@ -21,14 +28,17 @@ fn small_mask(nbits: uint) -> uint { (1 << nbits) - 1 } -pub impl SmallBitv { - fn new(bits: uint) -> SmallBitv { +impl SmallBitv { + pub fn new(bits: uint) -> SmallBitv { SmallBitv {bits: bits} } #[inline(always)] - fn bits_op(&mut self, right_bits: uint, nbits: uint, - f: &fn(uint, uint) -> uint) -> bool { + pub fn bits_op(&mut self, + right_bits: uint, + nbits: uint, + f: &fn(uint, uint) -> uint) + -> bool { let mask = small_mask(nbits); let old_b: uint = self.bits; let new_b = f(old_b, right_bits); @@ -37,32 +47,32 @@ pub impl SmallBitv { } #[inline(always)] - fn union(&mut self, s: &SmallBitv, nbits: uint) -> bool { + pub fn union(&mut self, s: &SmallBitv, nbits: uint) -> bool { self.bits_op(s.bits, nbits, |u1, u2| u1 | u2) } #[inline(always)] - fn intersect(&mut self, s: &SmallBitv, nbits: uint) -> bool { + pub fn intersect(&mut self, s: &SmallBitv, nbits: uint) -> bool { self.bits_op(s.bits, nbits, |u1, u2| u1 & u2) } #[inline(always)] - fn become(&mut self, s: &SmallBitv, nbits: uint) -> bool { + pub fn become(&mut self, s: &SmallBitv, nbits: uint) -> bool { self.bits_op(s.bits, nbits, |_u1, u2| u2) } #[inline(always)] - fn difference(&mut self, s: &SmallBitv, nbits: uint) -> bool { + pub fn difference(&mut self, s: &SmallBitv, nbits: uint) -> bool { self.bits_op(s.bits, nbits, |u1, u2| u1 & !u2) } #[inline(always)] - fn get(&self, i: uint) -> bool { + pub fn get(&self, i: uint) -> bool { (self.bits & (1 << i)) != 0 } #[inline(always)] - fn set(&mut self, i: uint, x: bool) { + pub fn set(&mut self, i: uint, x: bool) { if x { self.bits |= 1< bool { + pub fn equals(&self, b: &SmallBitv, nbits: uint) -> bool { let mask = small_mask(nbits); mask & self.bits == mask & b.bits } #[inline(always)] - fn clear(&mut self) { self.bits = 0; } + pub fn clear(&mut self) { self.bits = 0; } #[inline(always)] - fn set_all(&mut self) { self.bits = !0; } + pub fn set_all(&mut self) { self.bits = !0; } #[inline(always)] - fn is_true(&self, nbits: uint) -> bool { + pub fn is_true(&self, nbits: uint) -> bool { small_mask(nbits) & !self.bits == 0 } #[inline(always)] - fn is_false(&self, nbits: uint) -> bool { + pub fn is_false(&self, nbits: uint) -> bool { small_mask(nbits) & self.bits == 0 } #[inline(always)] - fn invert(&mut self) { self.bits = !self.bits; } - + pub fn invert(&mut self) { self.bits = !self.bits; } } struct BigBitv { @@ -118,16 +127,19 @@ fn big_mask(nbits: uint, elem: uint) -> uint { } } -pub impl BigBitv { - fn new(storage: ~[uint]) -> BigBitv { +impl BigBitv { + pub fn new(storage: ~[uint]) -> BigBitv { BigBitv {storage: storage} } #[inline(always)] - fn process(&mut self, b: &BigBitv, nbits: uint, - op: &fn(uint, uint) -> uint) -> bool { + pub fn process(&mut self, + b: &BigBitv, + nbits: uint, + op: &fn(uint, uint) -> uint) + -> bool { let len = b.storage.len(); - assert!((self.storage.len() == len)); + assert_eq!(self.storage.len(), len); let mut changed = false; for uint::range(0, len) |i| { let mask = big_mask(nbits, i); @@ -143,46 +155,35 @@ pub impl BigBitv { } #[inline(always)] - #[cfg(stage0)] - fn each_storage(&mut self, op: &fn(v: &mut uint) -> bool) { - for uint::range(0, self.storage.len()) |i| { - let mut w = self.storage[i]; - let b = op(&mut w); - self.storage[i] = w; - if !b { break; } - } - } - #[inline(always)] - #[cfg(not(stage0))] - fn each_storage(&mut self, op: &fn(v: &mut uint) -> bool) -> bool { + pub fn each_storage(&mut self, op: &fn(v: &mut uint) -> bool) -> bool { uint::range(0, self.storage.len(), |i| op(&mut self.storage[i])) } #[inline(always)] - fn invert(&mut self) { for self.each_storage |w| { *w = !*w } } + pub fn invert(&mut self) { for self.each_storage |w| { *w = !*w } } #[inline(always)] - fn union(&mut self, b: &BigBitv, nbits: uint) -> bool { + pub fn union(&mut self, b: &BigBitv, nbits: uint) -> bool { self.process(b, nbits, |w1, w2| w1 | w2) } #[inline(always)] - fn intersect(&mut self, b: &BigBitv, nbits: uint) -> bool { + pub fn intersect(&mut self, b: &BigBitv, nbits: uint) -> bool { self.process(b, nbits, |w1, w2| w1 & w2) } #[inline(always)] - fn become(&mut self, b: &BigBitv, nbits: uint) -> bool { + pub fn become(&mut self, b: &BigBitv, nbits: uint) -> bool { self.process(b, nbits, |_, w| w) } #[inline(always)] - fn difference(&mut self, b: &BigBitv, nbits: uint) -> bool { + pub fn difference(&mut self, b: &BigBitv, nbits: uint) -> bool { self.process(b, nbits, |w1, w2| w1 & !w2) } #[inline(always)] - fn get(&self, i: uint) -> bool { + pub fn get(&self, i: uint) -> bool { let w = i / uint::bits; let b = i % uint::bits; let x = 1 & self.storage[w] >> b; @@ -190,7 +191,7 @@ pub impl BigBitv { } #[inline(always)] - fn set(&mut self, i: uint, x: bool) { + pub fn set(&mut self, i: uint, x: bool) { let w = i / uint::bits; let b = i % uint::bits; let flag = 1 << b; @@ -199,20 +200,7 @@ pub impl BigBitv { } #[inline(always)] - #[cfg(stage0)] - fn equals(&self, b: &BigBitv, nbits: uint) -> bool { - let len = b.storage.len(); - for uint::iterate(0, len) |i| { - let mask = big_mask(nbits, i); - if mask & self.storage[i] != mask & b.storage[i] { - return false; - } - } - } - - #[inline(always)] - #[cfg(not(stage0))] - fn equals(&self, b: &BigBitv, nbits: uint) -> bool { + pub fn equals(&self, b: &BigBitv, nbits: uint) -> bool { let len = b.storage.len(); for uint::iterate(0, len) |i| { let mask = big_mask(nbits, i); @@ -222,16 +210,17 @@ pub impl BigBitv { } return true; } - } enum BitvVariant { Big(~BigBitv), Small(~SmallBitv) } enum Op {Union, Intersect, Assign, Difference} -// The bitvector type +/// The bitvector type pub struct Bitv { + /// Internal representation of the bit vector (small or large) rep: BitvVariant, + /// The number of valid bits in the internal representation nbits: uint } @@ -239,8 +228,7 @@ fn die() -> ! { fail!("Tried to do operation on bit vectors with different sizes"); } -priv impl Bitv { - +impl Bitv { #[inline(always)] fn do_op(&mut self, op: Op, other: &Bitv) -> bool { if self.nbits != other.nbits { @@ -270,8 +258,8 @@ priv impl Bitv { } -pub impl Bitv { - fn new(nbits: uint, init: bool) -> Bitv { +impl Bitv { + pub fn new(nbits: uint, init: bool) -> Bitv { let rep = if nbits <= uint::bits { Small(~SmallBitv::new(if init {!0} else {0})) } @@ -279,7 +267,7 @@ pub impl Bitv { let nelems = nbits/uint::bits + if nbits % uint::bits == 0 {0} else {1}; let elem = if init {!0} else {0}; - let s = from_elem(nelems, elem); + let s = vec::from_elem(nelems, elem); Big(~BigBitv::new(s)) }; Bitv {rep: rep, nbits: nbits} @@ -292,7 +280,7 @@ pub impl Bitv { * the same length. Returns 'true' if `self` changed. */ #[inline(always)] - fn union(&mut self, v1: &Bitv) -> bool { self.do_op(Union, v1) } + pub fn union(&mut self, v1: &Bitv) -> bool { self.do_op(Union, v1) } /** * Calculates the intersection of two bitvectors @@ -301,7 +289,9 @@ pub impl Bitv { * must be the same length. Returns 'true' if `self` changed. */ #[inline(always)] - fn intersect(&mut self, v1: &Bitv) -> bool { self.do_op(Intersect, v1) } + pub fn intersect(&mut self, v1: &Bitv) -> bool { + self.do_op(Intersect, v1) + } /** * Assigns the value of `v1` to `self` @@ -310,16 +300,16 @@ pub impl Bitv { * changed */ #[inline(always)] - fn assign(&mut self, v: &Bitv) -> bool { self.do_op(Assign, v) } + pub fn assign(&mut self, v: &Bitv) -> bool { self.do_op(Assign, v) } /// Retrieve the value at index `i` #[inline(always)] - fn get(&self, i: uint) -> bool { - assert!((i < self.nbits)); - match self.rep { - Big(ref b) => b.get(i), - Small(ref s) => s.get(i) - } + pub fn get(&self, i: uint) -> bool { + assert!((i < self.nbits)); + match self.rep { + Big(ref b) => b.get(i), + Small(ref s) => s.get(i) + } } /** @@ -328,7 +318,7 @@ pub impl Bitv { * `i` must be less than the length of the bitvector. */ #[inline(always)] - fn set(&mut self, i: uint, x: bool) { + pub fn set(&mut self, i: uint, x: bool) { assert!((i < self.nbits)); match self.rep { Big(ref mut b) => b.set(i, x), @@ -343,7 +333,7 @@ pub impl Bitv { * bitvectors contain identical elements. */ #[inline(always)] - fn equal(&self, v1: &Bitv) -> bool { + pub fn equal(&self, v1: &Bitv) -> bool { if self.nbits != v1.nbits { return false; } match self.rep { Small(ref b) => match v1.rep { @@ -359,7 +349,7 @@ pub impl Bitv { /// Set all bits to 0 #[inline(always)] - fn clear(&mut self) { + pub fn clear(&mut self) { match self.rep { Small(ref mut b) => b.clear(), Big(ref mut s) => for s.each_storage() |w| { *w = 0u } @@ -368,7 +358,7 @@ pub impl Bitv { /// Set all bits to 1 #[inline(always)] - fn set_all(&mut self) { + pub fn set_all(&mut self) { match self.rep { Small(ref mut b) => b.set_all(), Big(ref mut s) => for s.each_storage() |w| { *w = !0u } } @@ -376,7 +366,7 @@ pub impl Bitv { /// Invert all bits #[inline(always)] - fn invert(&mut self) { + pub fn invert(&mut self) { match self.rep { Small(ref mut b) => b.invert(), Big(ref mut s) => for s.each_storage() |w| { *w = !*w } } @@ -392,11 +382,13 @@ pub impl Bitv { * Returns `true` if `v0` was changed. */ #[inline(always)] - fn difference(&mut self, v: &Bitv) -> bool { self.do_op(Difference, v) } + pub fn difference(&mut self, v: &Bitv) -> bool { + self.do_op(Difference, v) + } /// Returns true if all bits are 1 #[inline(always)] - fn is_true(&self) -> bool { + pub fn is_true(&self) -> bool { match self.rep { Small(ref b) => b.is_true(self.nbits), _ => { @@ -407,17 +399,7 @@ pub impl Bitv { } #[inline(always)] - #[cfg(stage0)] - fn each(&self, f: &fn(bool) -> bool) { - let mut i = 0; - while i < self.nbits { - if !f(self.get(i)) { break; } - i += 1; - } - } - #[inline(always)] - #[cfg(not(stage0))] - fn each(&self, f: &fn(bool) -> bool) -> bool { + pub fn each(&self, f: &fn(bool) -> bool) -> bool { let mut i = 0; while i < self.nbits { if !f(self.get(i)) { return false; } @@ -427,7 +409,7 @@ pub impl Bitv { } /// Returns true if all bits are 0 - fn is_false(&self) -> bool { + pub fn is_false(&self) -> bool { match self.rep { Small(ref b) => b.is_false(self.nbits), Big(_) => { @@ -437,7 +419,7 @@ pub impl Bitv { } } - fn init_to_vec(&self, i: uint) -> uint { + pub fn init_to_vec(&self, i: uint) -> uint { return if self.get(i) { 1 } else { 0 }; } @@ -446,7 +428,7 @@ pub impl Bitv { * * Each uint in the resulting vector has either value 0u or 1u. */ - fn to_vec(&self) -> ~[uint] { + pub fn to_vec(&self) -> ~[uint] { vec::from_fn(self.nbits, |x| self.init_to_vec(x)) } @@ -456,8 +438,7 @@ pub impl Bitv { * size of the bitv is not a multiple of 8 then trailing bits * will be filled-in with false/0 */ - fn to_bytes(&self) -> ~[u8] { - + pub fn to_bytes(&self) -> ~[u8] { fn bit (bitv: &Bitv, byte: uint, bit: uint) -> u8 { let offset = byte * 8 + bit; if offset >= bitv.nbits { @@ -484,7 +465,7 @@ pub impl Bitv { /** * Transform self into a [bool] by turning each bit into a bool */ - fn to_bools(&self) -> ~[bool] { + pub fn to_bools(&self) -> ~[bool] { vec::from_fn(self.nbits, |i| self[i]) } @@ -494,9 +475,9 @@ pub impl Bitv { * The resulting string has the same length as `self`, and each * character is either '0' or '1'. */ - fn to_str(&self) -> ~str { + pub fn to_str(&self) -> ~str { let mut rs = ~""; - for self.each() |i| { if i { rs += ~"1"; } else { rs += ~"0"; } }; + for self.each() |i| { if i { rs += "1"; } else { rs += "0"; } }; rs } @@ -507,8 +488,8 @@ pub impl Bitv { * The uint vector is expected to only contain the values 0u and 1u. Both * the bitvector and vector must have the same length */ - fn eq_vec(&self, v: ~[uint]) -> bool { - assert!(self.nbits == v.len()); + pub fn eq_vec(&self, v: ~[uint]) -> bool { + assert_eq!(self.nbits, v.len()); let mut i = 0; while i < self.nbits { let w0 = self.get(i); @@ -519,16 +500,7 @@ pub impl Bitv { true } - #[cfg(stage0)] - fn ones(&self, f: &fn(uint) -> bool) { - for uint::range(0, self.nbits) |i| { - if self.get(i) { - if !f(i) { break } - } - } - } - #[cfg(not(stage0))] - fn ones(&self, f: &fn(uint) -> bool) -> bool { + pub fn ones(&self, f: &fn(uint) -> bool) -> bool { uint::range(0, self.nbits, |i| !self.get(i) || f(i)) } @@ -543,14 +515,13 @@ impl Clone for Bitv { Bitv{nbits: self.nbits, rep: Small(~SmallBitv{bits: b.bits})} } Big(ref b) => { - let mut st = from_elem(self.nbits / uint::bits + 1, 0); + let mut st = vec::from_elem(self.nbits / uint::bits + 1, 0); let len = st.len(); for uint::range(0, len) |i| { st[i] = b.storage[i]; }; Bitv{nbits: self.nbits, rep: Big(~BigBitv{storage: st})} } } } - } /** @@ -621,14 +592,14 @@ pub struct BitvSet { priv bitv: BigBitv } -pub impl BitvSet { +impl BitvSet { /// Creates a new bit vector set with initially no contents - fn new() -> BitvSet { + pub fn new() -> BitvSet { BitvSet{ size: 0, bitv: BigBitv::new(~[0]) } } /// Creates a new bit vector set from the given bit vector - fn from_bitv(bitv: Bitv) -> BitvSet { + pub fn from_bitv(bitv: Bitv) -> BitvSet { let mut size = 0; for bitv.ones |_| { size += 1; @@ -643,17 +614,17 @@ pub impl BitvSet { /// Returns the capacity in bits for this bit vector. Inserting any /// element less than this amount will not trigger a resizing. - fn capacity(&self) -> uint { self.bitv.storage.len() * uint::bits } + pub fn capacity(&self) -> uint { self.bitv.storage.len() * uint::bits } /// Consumes this set to return the underlying bit vector - fn unwrap(self) -> Bitv { + pub fn unwrap(self) -> Bitv { let cap = self.capacity(); let BitvSet{bitv, _} = self; return Bitv{ nbits:cap, rep: Big(~bitv) }; } #[inline(always)] - priv fn other_op(&mut self, other: &BitvSet, f: &fn(uint, uint) -> uint) { + fn other_op(&mut self, other: &BitvSet, f: &fn(uint, uint) -> uint) { fn nbits(mut w: uint) -> uint { let mut bits = 0; for uint::bits.times { @@ -677,27 +648,26 @@ pub impl BitvSet { } /// Union in-place with the specified other bit vector - fn union_with(&mut self, other: &BitvSet) { + pub fn union_with(&mut self, other: &BitvSet) { self.other_op(other, |w1, w2| w1 | w2); } /// Intersect in-place with the specified other bit vector - fn intersect_with(&mut self, other: &BitvSet) { + pub fn intersect_with(&mut self, other: &BitvSet) { self.other_op(other, |w1, w2| w1 & w2); } /// Difference in-place with the specified other bit vector - fn difference_with(&mut self, other: &BitvSet) { + pub fn difference_with(&mut self, other: &BitvSet) { self.other_op(other, |w1, w2| w1 & !w2); } /// Symmetric difference in-place with the specified other bit vector - fn symmetric_difference_with(&mut self, other: &BitvSet) { + pub fn symmetric_difference_with(&mut self, other: &BitvSet) { self.other_op(other, |w1, w2| w1 ^ w2); } } -#[cfg(not(stage0))] impl BaseIter for BitvSet { fn size_hint(&self) -> Option { Some(self.len()) } @@ -711,7 +681,6 @@ impl BaseIter for BitvSet { } } -#[cfg(not(stage0))] impl cmp::Eq for BitvSet { fn eq(&self, other: &BitvSet) -> bool { if self.size != other.size { @@ -745,7 +714,6 @@ impl Mutable for BitvSet { } } -#[cfg(not(stage0))] impl Set for BitvSet { fn contains(&self, value: &uint) -> bool { *value < self.bitv.storage.len() * uint::bits && self.bitv.get(*value) @@ -849,8 +817,7 @@ impl Set for BitvSet { } } -#[cfg(not(stage0))] -priv impl BitvSet { +impl BitvSet { /// Visits each of the words that the two bit vectors (self and other) /// both have in common. The three yielded arguments are (bit location, /// w1, w2) where the bit location is the number of bits offset so far, @@ -909,25 +876,22 @@ mod tests { #[test] fn test_to_str() { let zerolen = Bitv::new(0u, false); - assert!(zerolen.to_str() == ~""); + assert_eq!(zerolen.to_str(), ~""); let eightbits = Bitv::new(8u, false); - assert!(eightbits.to_str() == ~"00000000"); + assert_eq!(eightbits.to_str(), ~"00000000"); } #[test] fn test_0_elements() { - let mut act; - let exp; - act = Bitv::new(0u, false); - exp = vec::from_elem::(0u, 0u); + let act = Bitv::new(0u, false); + let exp = vec::from_elem::(0u, 0u); assert!(act.eq_vec(exp)); } #[test] fn test_1_element() { - let mut act; - act = Bitv::new(1u, false); + let mut act = Bitv::new(1u, false); assert!(act.eq_vec(~[0u])); act = Bitv::new(1u, true); assert!(act.eq_vec(~[1u])); @@ -938,7 +902,7 @@ mod tests { let mut b = bitv::Bitv::new(2, false); b.set(0, true); b.set(1, false); - assert!(b.to_str() == ~"10"); + assert_eq!(b.to_str(), ~"10"); } #[test] @@ -1247,20 +1211,20 @@ mod tests { #[test] fn test_from_bytes() { let bitv = from_bytes([0b10110110, 0b00000000, 0b11111111]); - let str = ~"10110110" + ~"00000000" + ~"11111111"; - assert!(bitv.to_str() == str); + let str = ~"10110110" + "00000000" + "11111111"; + assert_eq!(bitv.to_str(), str); } #[test] fn test_to_bytes() { let mut bv = Bitv::new(3, true); bv.set(1, false); - assert!(bv.to_bytes() == ~[0b10100000]); + assert_eq!(bv.to_bytes(), ~[0b10100000]); let mut bv = Bitv::new(9, false); bv.set(2, true); bv.set(8, true); - assert!(bv.to_bytes() == ~[0b00100000, 0b10000000]); + assert_eq!(bv.to_bytes(), ~[0b00100000, 0b10000000]); } #[test] @@ -1272,7 +1236,7 @@ mod tests { #[test] fn test_to_bools() { let bools = ~[false, false, true, false, false, true, true, false]; - assert!(from_bytes([0b00100110]).to_bools() == bools); + assert_eq!(from_bytes([0b00100110]).to_bools(), bools); } #[test] @@ -1330,7 +1294,7 @@ mod tests { assert!(b.insert(400)); assert!(!b.insert(400)); assert!(b.contains(&400)); - assert!(b.len() == 2); + assert_eq!(b.len(), 2); } #[test] @@ -1354,10 +1318,10 @@ mod tests { let mut i = 0; let expected = [3, 5, 11, 77]; for a.intersection(&b) |x| { - assert!(*x == expected[i]); + assert_eq!(*x, expected[i]); i += 1 } - assert!(i == expected.len()); + assert_eq!(i, expected.len()); } #[test] @@ -1377,10 +1341,10 @@ mod tests { let mut i = 0; let expected = [1, 5, 500]; for a.difference(&b) |x| { - assert!(*x == expected[i]); + assert_eq!(*x, expected[i]); i += 1 } - assert!(i == expected.len()); + assert_eq!(i, expected.len()); } #[test] @@ -1402,10 +1366,10 @@ mod tests { let mut i = 0; let expected = [1, 5, 11, 14, 220]; for a.symmetric_difference(&b) |x| { - assert!(*x == expected[i]); + assert_eq!(*x, expected[i]); i += 1 } - assert!(i == expected.len()); + assert_eq!(i, expected.len()); } #[test] @@ -1430,10 +1394,10 @@ mod tests { let mut i = 0; let expected = [1, 3, 5, 9, 11, 13, 19, 24, 160]; for a.union(&b) |x| { - assert!(*x == expected[i]); + assert_eq!(*x, expected[i]); i += 1 } - assert!(i == expected.len()); + assert_eq!(i, expected.len()); } #[test] @@ -1448,7 +1412,7 @@ mod tests { assert!(a.insert(1000)); assert!(a.remove(&1000)); - assert!(a.capacity() == uint::bits); + assert_eq!(a.capacity(), uint::bits); } fn rng() -> rand::IsaacRng { @@ -1533,7 +1497,7 @@ mod tests { #[bench] fn bench_bitv_big_union(b: &mut BenchHarness) { let mut b1 = Bitv::new(bench_bits, false); - let mut b2 = Bitv::new(bench_bits, false); + let b2 = Bitv::new(bench_bits, false); do b.iter { b1.union(&b2); } diff --git a/src/libstd/c_vec.rs b/src/libextra/c_vec.rs similarity index 96% rename from src/libstd/c_vec.rs rename to src/libextra/c_vec.rs index 17b7bae6de5df..7cc7b659ed9dd 100644 --- a/src/libstd/c_vec.rs +++ b/src/libextra/c_vec.rs @@ -36,6 +36,11 @@ * still held if needed. */ +use core::prelude::*; + +use core::option; +use core::ptr; + /** * The type representing a foreign chunk of memory * @@ -165,9 +170,9 @@ mod tests { set(cv, 3u, 8u8); set(cv, 4u, 9u8); - assert!(get(cv, 3u) == 8u8); - assert!(get(cv, 4u) == 9u8); - assert!(len(cv) == 16u); + assert_eq!(get(cv, 3u), 8u8); + assert_eq!(get(cv, 4u), 9u8); + assert_eq!(len(cv), 16u); } #[test] @@ -195,7 +200,7 @@ mod tests { set(cv, 0u, 32u8); set(cv, 1u, 33u8); - assert!(unsafe { *p } == 32u8); + assert_eq!(unsafe { *p }, 32u8); set(cv, 2u, 34u8); /* safety */ } diff --git a/src/libextra/comm.rs b/src/libextra/comm.rs new file mode 100644 index 0000000000000..1001d4f6ac9ed --- /dev/null +++ b/src/libextra/comm.rs @@ -0,0 +1,115 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/*! + +Higher level communication abstractions. + +*/ + +#[allow(missing_doc)]; + +use core::prelude::*; + +use core::comm::{GenericChan, GenericSmartChan, GenericPort}; +use core::comm::{Chan, Port, Selectable, Peekable}; +use core::comm; +use core::pipes; + +/// An extension of `pipes::stream` that allows both sending and receiving. +pub struct DuplexStream { + priv chan: Chan, + priv port: Port, +} + +// Allow these methods to be used without import: +impl DuplexStream { + pub fn send(&self, x: T) { + self.chan.send(x) + } + pub fn try_send(&self, x: T) -> bool { + self.chan.try_send(x) + } + pub fn recv(&self, ) -> U { + self.port.recv() + } + pub fn try_recv(&self) -> Option { + self.port.try_recv() + } + pub fn peek(&self) -> bool { + self.port.peek() + } +} + +impl GenericChan for DuplexStream { + fn send(&self, x: T) { + self.chan.send(x) + } +} + +impl GenericSmartChan for DuplexStream { + fn try_send(&self, x: T) -> bool { + self.chan.try_send(x) + } +} + +impl GenericPort for DuplexStream { + fn recv(&self) -> U { + self.port.recv() + } + + fn try_recv(&self) -> Option { + self.port.try_recv() + } +} + +impl Peekable for DuplexStream { + fn peek(&self) -> bool { + self.port.peek() + } +} + +impl Selectable for DuplexStream { + fn header(&mut self) -> *mut pipes::PacketHeader { + self.port.header() + } +} + +/// Creates a bidirectional stream. +pub fn DuplexStream() + -> (DuplexStream, DuplexStream) +{ + let (p1, c2) = comm::stream(); + let (p2, c1) = comm::stream(); + (DuplexStream { + chan: c1, + port: p1 + }, + DuplexStream { + chan: c2, + port: p2 + }) +} + +#[cfg(test)] +mod test { + use comm::DuplexStream; + + #[test] + pub fn DuplexStream1() { + let (left, right) = DuplexStream(); + + left.send(~"abc"); + right.send(123); + + assert!(left.recv() == 123); + assert!(right.recv() == ~"abc"); + } +} diff --git a/src/libstd/dbg.rs b/src/libextra/dbg.rs similarity index 98% rename from src/libstd/dbg.rs rename to src/libextra/dbg.rs index 4b2d2a60a68ef..cbd7cb5e3c08f 100644 --- a/src/libstd/dbg.rs +++ b/src/libextra/dbg.rs @@ -10,6 +10,8 @@ //! Unsafe debugging functions for inspecting values. +#[allow(missing_doc)]; + use core::cast::transmute; use core::sys; diff --git a/src/libstd/deque.rs b/src/libextra/deque.rs similarity index 63% rename from src/libstd/deque.rs rename to src/libextra/deque.rs index c94acaa1f70db..a8accc50eab01 100644 --- a/src/libstd/deque.rs +++ b/src/libextra/deque.rs @@ -10,10 +10,15 @@ //! A double-ended queue implemented as a circular buffer +use core::prelude::*; + +use core::uint; use core::util::replace; +use core::vec; static initial_capacity: uint = 32u; // 2^5 +#[allow(missing_doc)] pub struct Deque { priv nelts: uint, priv lo: uint, @@ -39,9 +44,9 @@ impl Mutable for Deque { } } -pub impl Deque { +impl Deque { /// Create an empty Deque - fn new() -> Deque { + pub fn new() -> Deque { Deque{nelts: 0, lo: 0, hi: 0, elts: vec::from_fn(initial_capacity, |_| None)} } @@ -49,47 +54,35 @@ pub impl Deque { /// Return a reference to the first element in the deque /// /// Fails if the deque is empty - fn peek_front<'a>(&'a self) -> &'a T { get(self.elts, self.lo) } + pub fn peek_front<'a>(&'a self) -> &'a T { get(self.elts, self.lo) } /// Return a reference to the last element in the deque /// /// Fails if the deque is empty - fn peek_back<'a>(&'a self) -> &'a T { get(self.elts, self.hi - 1u) } + pub fn peek_back<'a>(&'a self) -> &'a T { get(self.elts, self.hi - 1u) } /// Retrieve an element in the deque by index /// /// Fails if there is no element with the given index - fn get<'a>(&'a self, i: int) -> &'a T { + pub fn get<'a>(&'a self, i: int) -> &'a T { let idx = (self.lo + (i as uint)) % self.elts.len(); get(self.elts, idx) } /// Iterate over the elements in the deque - #[cfg(stage0)] - fn each(&self, f: &fn(&T) -> bool) { - self.eachi(|_i, e| f(e)) - } - /// Iterate over the elements in the deque - #[cfg(not(stage0))] - fn each(&self, f: &fn(&T) -> bool) -> bool { + pub fn each(&self, f: &fn(&T) -> bool) -> bool { self.eachi(|_i, e| f(e)) } /// Iterate over the elements in the deque by index - #[cfg(stage0)] - fn eachi(&self, f: &fn(uint, &T) -> bool) { - uint::range(0, self.nelts, |i| f(i, self.get(i as int))) - } - /// Iterate over the elements in the deque by index - #[cfg(not(stage0))] - fn eachi(&self, f: &fn(uint, &T) -> bool) -> bool { + pub fn eachi(&self, f: &fn(uint, &T) -> bool) -> bool { uint::range(0, self.nelts, |i| f(i, self.get(i as int))) } /// Remove and return the first element in the deque /// /// Fails if the deque is empty - fn pop_front(&mut self) -> T { + pub fn pop_front(&mut self) -> T { let result = self.elts[self.lo].swap_unwrap(); self.lo = (self.lo + 1u) % self.elts.len(); self.nelts -= 1u; @@ -99,7 +92,7 @@ pub impl Deque { /// Remove and return the last element in the deque /// /// Fails if the deque is empty - fn pop_back(&mut self) -> T { + pub fn pop_back(&mut self) -> T { if self.hi == 0u { self.hi = self.elts.len() - 1u; } else { self.hi -= 1u; } @@ -110,7 +103,7 @@ pub impl Deque { } /// Prepend an element to the deque - fn add_front(&mut self, t: T) { + pub fn add_front(&mut self, t: T) { let oldlo = self.lo; if self.lo == 0u { self.lo = self.elts.len() - 1u; @@ -125,7 +118,7 @@ pub impl Deque { } /// Append an element to the deque - fn add_back(&mut self, t: T) { + pub fn add_back(&mut self, t: T) { if self.lo == self.hi && self.nelts != 0u { self.elts = grow(self.nelts, self.lo, self.elts); self.lo = 0u; @@ -135,12 +128,37 @@ pub impl Deque { self.hi = (self.hi + 1u) % self.elts.len(); self.nelts += 1u; } + + /// Reserve capacity for exactly `n` elements in the given deque, + /// doing nothing if `self`'s capacity is already equal to or greater + /// than the requested capacity + /// + /// # Arguments + /// + /// * n - The number of elements to reserve space for + pub fn reserve(&mut self, n: uint) { + vec::reserve(&mut self.elts, n); + } + + /// Reserve capacity for at least `n` elements in the given deque, + /// over-allocating in case the caller needs to reserve additional + /// space. + /// + /// Do nothing if `self`'s capacity is already equal to or greater + /// than the requested capacity. + /// + /// # Arguments + /// + /// * n - The number of elements to reserve space for + pub fn reserve_at_least(&mut self, n: uint) { + vec::reserve_at_least(&mut self.elts, n); + } } /// Grow is only called on full elts, so nelts is also len(elts), unlike /// elsewhere. fn grow(nelts: uint, lo: uint, elts: &mut [Option]) -> ~[Option] { - assert!(nelts == elts.len()); + assert_eq!(nelts, elts.len()); let mut rv = ~[]; do rv.grow_fn(nelts + 1) |i| { @@ -159,50 +177,51 @@ mod tests { use super::*; use core::cmp::Eq; use core::kinds::Copy; + use core::vec::capacity; #[test] fn test_simple() { let mut d = Deque::new(); - assert!(d.len() == 0u); + assert_eq!(d.len(), 0u); d.add_front(17); d.add_front(42); d.add_back(137); - assert!(d.len() == 3u); + assert_eq!(d.len(), 3u); d.add_back(137); - assert!(d.len() == 4u); + assert_eq!(d.len(), 4u); debug!(d.peek_front()); - assert!(*d.peek_front() == 42); + assert_eq!(*d.peek_front(), 42); debug!(d.peek_back()); - assert!(*d.peek_back() == 137); + assert_eq!(*d.peek_back(), 137); let mut i: int = d.pop_front(); debug!(i); - assert!(i == 42); + assert_eq!(i, 42); i = d.pop_back(); debug!(i); - assert!(i == 137); + assert_eq!(i, 137); i = d.pop_back(); debug!(i); - assert!(i == 137); + assert_eq!(i, 137); i = d.pop_back(); debug!(i); - assert!(i == 17); - assert!(d.len() == 0u); + assert_eq!(i, 17); + assert_eq!(d.len(), 0u); d.add_back(3); - assert!(d.len() == 1u); + assert_eq!(d.len(), 1u); d.add_front(2); - assert!(d.len() == 2u); + assert_eq!(d.len(), 2u); d.add_back(4); - assert!(d.len() == 3u); + assert_eq!(d.len(), 3u); d.add_front(1); - assert!(d.len() == 4u); + assert_eq!(d.len(), 4u); debug!(d.get(0)); debug!(d.get(1)); debug!(d.get(2)); debug!(d.get(3)); - assert!(*d.get(0) == 1); - assert!(*d.get(1) == 2); - assert!(*d.get(2) == 3); - assert!(*d.get(3) == 4); + assert_eq!(*d.get(0), 1); + assert_eq!(*d.get(1), 2); + assert_eq!(*d.get(2), 3); + assert_eq!(*d.get(3), 4); } #[test] @@ -213,63 +232,63 @@ mod tests { let d: @int = @175; let mut deq = Deque::new(); - assert!(deq.len() == 0); + assert_eq!(deq.len(), 0); deq.add_front(a); deq.add_front(b); deq.add_back(c); - assert!(deq.len() == 3); + assert_eq!(deq.len(), 3); deq.add_back(d); - assert!(deq.len() == 4); - assert!(*deq.peek_front() == b); - assert!(*deq.peek_back() == d); - assert!(deq.pop_front() == b); - assert!(deq.pop_back() == d); - assert!(deq.pop_back() == c); - assert!(deq.pop_back() == a); - assert!(deq.len() == 0); + assert_eq!(deq.len(), 4); + assert_eq!(*deq.peek_front(), b); + assert_eq!(*deq.peek_back(), d); + assert_eq!(deq.pop_front(), b); + assert_eq!(deq.pop_back(), d); + assert_eq!(deq.pop_back(), c); + assert_eq!(deq.pop_back(), a); + assert_eq!(deq.len(), 0); deq.add_back(c); - assert!(deq.len() == 1); + assert_eq!(deq.len(), 1); deq.add_front(b); - assert!(deq.len() == 2); + assert_eq!(deq.len(), 2); deq.add_back(d); - assert!(deq.len() == 3); + assert_eq!(deq.len(), 3); deq.add_front(a); - assert!(deq.len() == 4); - assert!(*deq.get(0) == a); - assert!(*deq.get(1) == b); - assert!(*deq.get(2) == c); - assert!(*deq.get(3) == d); + assert_eq!(deq.len(), 4); + assert_eq!(*deq.get(0), a); + assert_eq!(*deq.get(1), b); + assert_eq!(*deq.get(2), c); + assert_eq!(*deq.get(3), d); } #[cfg(test)] fn test_parameterized(a: T, b: T, c: T, d: T) { let mut deq = Deque::new(); - assert!(deq.len() == 0); + assert_eq!(deq.len(), 0); deq.add_front(a); deq.add_front(b); deq.add_back(c); - assert!(deq.len() == 3); + assert_eq!(deq.len(), 3); deq.add_back(d); - assert!(deq.len() == 4); - assert!(*deq.peek_front() == b); - assert!(*deq.peek_back() == d); - assert!(deq.pop_front() == b); - assert!(deq.pop_back() == d); - assert!(deq.pop_back() == c); - assert!(deq.pop_back() == a); - assert!(deq.len() == 0); + assert_eq!(deq.len(), 4); + assert_eq!(*deq.peek_front(), b); + assert_eq!(*deq.peek_back(), d); + assert_eq!(deq.pop_front(), b); + assert_eq!(deq.pop_back(), d); + assert_eq!(deq.pop_back(), c); + assert_eq!(deq.pop_back(), a); + assert_eq!(deq.len(), 0); deq.add_back(c); - assert!(deq.len() == 1); + assert_eq!(deq.len(), 1); deq.add_front(b); - assert!(deq.len() == 2); + assert_eq!(deq.len(), 2); deq.add_back(d); - assert!(deq.len() == 3); + assert_eq!(deq.len(), 3); deq.add_front(a); - assert!(deq.len() == 4); - assert!(*deq.get(0) == a); - assert!(*deq.get(1) == b); - assert!(*deq.get(2) == c); - assert!(*deq.get(3) == d); + assert_eq!(deq.len(), 4); + assert_eq!(*deq.get(0), a); + assert_eq!(*deq.get(1), b); + assert_eq!(*deq.get(2), c); + assert_eq!(*deq.get(3), d); } #[deriving(Eq)] @@ -338,4 +357,29 @@ mod tests { } } + + #[test] + fn test_reserve() { + let mut d = Deque::new(); + d.add_back(0u64); + d.reserve(50); + assert_eq!(capacity(&mut d.elts), 50); + let mut d = Deque::new(); + d.add_back(0u32); + d.reserve(50); + assert_eq!(capacity(&mut d.elts), 50); + } + + #[test] + fn test_reserve_at_least() { + let mut d = Deque::new(); + d.add_back(0u64); + d.reserve_at_least(50); + assert_eq!(capacity(&mut d.elts), 64); + let mut d = Deque::new(); + d.add_back(0u32); + d.reserve_at_least(50); + assert_eq!(capacity(&mut d.elts), 64); + } + } diff --git a/src/libstd/dlist.rs b/src/libextra/dlist.rs similarity index 85% rename from src/libstd/dlist.rs rename to src/libextra/dlist.rs index 84bd803afe7e5..52e2b75d6b6d3 100644 --- a/src/libstd/dlist.rs +++ b/src/libextra/dlist.rs @@ -18,10 +18,15 @@ Do not use ==, !=, <, etc on doubly-linked lists -- it may not terminate. */ +use core::prelude::*; + use core::managed; +use core::old_iter; +use core::vec; pub type DListLink = Option<@mut DListNode>; +#[allow(missing_doc)] pub struct DListNode { data: T, linked: bool, // for assertions @@ -29,13 +34,14 @@ pub struct DListNode { next: DListLink, } +#[allow(missing_doc)] pub struct DList { size: uint, hd: DListLink, tl: DListLink, } -priv impl DListNode { +impl DListNode { fn assert_links(@mut self) { match self.next { Some(neighbour) => match neighbour.prev { @@ -58,26 +64,26 @@ priv impl DListNode { } } -pub impl DListNode { +impl DListNode { /// Get the next node in the list, if there is one. - fn next_link(@mut self) -> DListLink { + pub fn next_link(@mut self) -> DListLink { self.assert_links(); self.next } /// Get the next node in the list, failing if there isn't one. - fn next_node(@mut self) -> @mut DListNode { + pub fn next_node(@mut self) -> @mut DListNode { match self.next_link() { Some(nobe) => nobe, None => fail!("This dlist node has no next neighbour.") } } /// Get the previous node in the list, if there is one. - fn prev_link(@mut self) -> DListLink { + pub fn prev_link(@mut self) -> DListLink { self.assert_links(); self.prev } /// Get the previous node in the list, failing if there isn't one. - fn prev_node(@mut self) -> @mut DListNode { + pub fn prev_node(@mut self) -> @mut DListNode { match self.prev_link() { Some(nobe) => nobe, None => fail!("This dlist node has no previous neighbour.") @@ -102,6 +108,7 @@ pub fn from_elem(data: T) -> @mut DList { list } +/// Creates a new dlist from a vector of elements, maintaining the same order pub fn from_vec(vec: &[T]) -> @mut DList { do vec::foldl(DList(), vec) |list,data| { list.push(*data); // Iterating left-to-right -- add newly to the tail. @@ -119,7 +126,7 @@ pub fn concat(lists: @mut DList<@mut DList>) -> @mut DList { result } -priv impl DList { +impl DList { fn new_link(data: T) -> DListLink { Some(@mut DListNode { data: data, @@ -136,10 +143,10 @@ priv impl DList { } if !nobe.linked { fail!("That node isn't linked to any dlist.") } if !((nobe.prev.is_some() - || managed::mut_ptr_eq(self.hd.expect(~"headless dlist?"), + || managed::mut_ptr_eq(self.hd.expect("headless dlist?"), nobe)) && (nobe.next.is_some() - || managed::mut_ptr_eq(self.tl.expect(~"tailless dlist?"), + || managed::mut_ptr_eq(self.tl.expect("tailless dlist?"), nobe))) { fail!("That node isn't on this dlist.") } @@ -204,34 +211,34 @@ priv impl DList { } } -pub impl DList { +impl DList { /// Get the size of the list. O(1). - fn len(@mut self) -> uint { self.size } + pub fn len(@mut self) -> uint { self.size } /// Returns true if the list is empty. O(1). - fn is_empty(@mut self) -> bool { self.len() == 0 } + pub fn is_empty(@mut self) -> bool { self.len() == 0 } /// Add data to the head of the list. O(1). - fn push_head(@mut self, data: T) { + pub fn push_head(@mut self, data: T) { self.add_head(DList::new_link(data)); } /** * Add data to the head of the list, and get the new containing * node. O(1). */ - fn push_head_n(@mut self, data: T) -> @mut DListNode { + pub fn push_head_n(@mut self, data: T) -> @mut DListNode { let nobe = DList::new_link(data); self.add_head(nobe); nobe.get() } /// Add data to the tail of the list. O(1). - fn push(@mut self, data: T) { + pub fn push(@mut self, data: T) { self.add_tail(DList::new_link(data)); } /** * Add data to the tail of the list, and get the new containing * node. O(1). */ - fn push_n(@mut self, data: T) -> @mut DListNode { + pub fn push_n(@mut self, data: T) -> @mut DListNode { let nobe = DList::new_link(data); self.add_tail(nobe); nobe.get() @@ -240,16 +247,16 @@ pub impl DList { * Insert data into the middle of the list, left of the given node. * O(1). */ - fn insert_before(@mut self, data: T, neighbour: @mut DListNode) { + pub fn insert_before(@mut self, data: T, neighbour: @mut DListNode) { self.insert_left(DList::new_link(data), neighbour); } /** * Insert an existing node in the middle of the list, left of the * given node. O(1). */ - fn insert_n_before(@mut self, - nobe: @mut DListNode, - neighbour: @mut DListNode) { + pub fn insert_n_before(@mut self, + nobe: @mut DListNode, + neighbour: @mut DListNode) { self.make_mine(nobe); self.insert_left(Some(nobe), neighbour); } @@ -257,11 +264,10 @@ pub impl DList { * Insert data in the middle of the list, left of the given node, * and get its containing node. O(1). */ - fn insert_before_n( - @mut self, - data: T, - neighbour: @mut DListNode - ) -> @mut DListNode { + pub fn insert_before_n(@mut self, + data: T, + neighbour: @mut DListNode) + -> @mut DListNode { let nobe = DList::new_link(data); self.insert_left(nobe, neighbour); nobe.get() @@ -270,16 +276,16 @@ pub impl DList { * Insert data into the middle of the list, right of the given node. * O(1). */ - fn insert_after(@mut self, data: T, neighbour: @mut DListNode) { + pub fn insert_after(@mut self, data: T, neighbour: @mut DListNode) { self.insert_right(neighbour, DList::new_link(data)); } /** * Insert an existing node in the middle of the list, right of the * given node. O(1). */ - fn insert_n_after(@mut self, - nobe: @mut DListNode, - neighbour: @mut DListNode) { + pub fn insert_n_after(@mut self, + nobe: @mut DListNode, + neighbour: @mut DListNode) { self.make_mine(nobe); self.insert_right(neighbour, Some(nobe)); } @@ -287,42 +293,41 @@ pub impl DList { * Insert data in the middle of the list, right of the given node, * and get its containing node. O(1). */ - fn insert_after_n( - @mut self, - data: T, - neighbour: @mut DListNode - ) -> @mut DListNode { + pub fn insert_after_n(@mut self, + data: T, + neighbour: @mut DListNode) + -> @mut DListNode { let nobe = DList::new_link(data); self.insert_right(neighbour, nobe); nobe.get() } /// Remove a node from the head of the list. O(1). - fn pop_n(@mut self) -> DListLink { + pub fn pop_n(@mut self) -> DListLink { let hd = self.peek_n(); hd.map(|nobe| self.unlink(*nobe)); hd } /// Remove a node from the tail of the list. O(1). - fn pop_tail_n(@mut self) -> DListLink { + pub fn pop_tail_n(@mut self) -> DListLink { let tl = self.peek_tail_n(); tl.map(|nobe| self.unlink(*nobe)); tl } /// Get the node at the list's head. O(1). - fn peek_n(@mut self) -> DListLink { self.hd } + pub fn peek_n(@mut self) -> DListLink { self.hd } /// Get the node at the list's tail. O(1). - fn peek_tail_n(@mut self) -> DListLink { self.tl } + pub fn peek_tail_n(@mut self) -> DListLink { self.tl } /// Get the node at the list's head, failing if empty. O(1). - fn head_n(@mut self) -> @mut DListNode { + pub fn head_n(@mut self) -> @mut DListNode { match self.hd { Some(nobe) => nobe, None => fail!("Attempted to get the head of an empty dlist.") } } /// Get the node at the list's tail, failing if empty. O(1). - fn tail_n(@mut self) -> @mut DListNode { + pub fn tail_n(@mut self) -> @mut DListNode { match self.tl { Some(nobe) => nobe, None => fail!("Attempted to get the tail of an empty dlist.") @@ -330,13 +335,13 @@ pub impl DList { } /// Remove a node from anywhere in the list. O(1). - fn remove(@mut self, nobe: @mut DListNode) { self.unlink(nobe); } + pub fn remove(@mut self, nobe: @mut DListNode) { self.unlink(nobe); } /** * Empty another list onto the end of this list, joining this list's tail * to the other list's head. O(1). */ - fn append(@mut self, them: @mut DList) { + pub fn append(@mut self, them: @mut DList) { if managed::mut_ptr_eq(self, them) { fail!("Cannot append a dlist to itself!") } @@ -353,7 +358,7 @@ pub impl DList { * Empty another list onto the start of this list, joining the other * list's tail to this list's head. O(1). */ - fn prepend(@mut self, them: @mut DList) { + pub fn prepend(@mut self, them: @mut DList) { if managed::mut_ptr_eq(self, them) { fail!("Cannot prepend a dlist to itself!") } @@ -368,7 +373,7 @@ pub impl DList { } /// Reverse the list's elements in place. O(n). - fn reverse(@mut self) { + pub fn reverse(@mut self) { do self.hd.while_some |nobe| { let next_nobe = nobe.next; self.remove(nobe); @@ -382,7 +387,7 @@ pub impl DList { * Remove everything from the list. This is important because the cyclic * links won't otherwise be automatically refcounted-collected. O(n). */ - fn clear(@mut self) { + pub fn clear(@mut self) { // Cute as it would be to simply detach the list and proclaim "O(1)!", // the GC would still be a hidden O(n). Better to be honest about it. while !self.is_empty() { @@ -391,18 +396,7 @@ pub impl DList { } /// Iterate over nodes. - #[cfg(stage0)] - fn each_node(@mut self, f: &fn(@mut DListNode) -> bool) { - let mut link = self.peek_n(); - while link.is_some() { - let nobe = link.get(); - if !f(nobe) { break; } - link = nobe.next_link(); - } - } - /// Iterate over nodes. - #[cfg(not(stage0))] - fn each_node(@mut self, f: &fn(@mut DListNode) -> bool) -> bool { + pub fn each_node(@mut self, f: &fn(@mut DListNode) -> bool) -> bool { let mut link = self.peek_n(); while link.is_some() { let nobe = link.get(); @@ -413,7 +407,7 @@ pub impl DList { } /// Check data structure integrity. O(n). - fn assert_consistent(@mut self) { + pub fn assert_consistent(@mut self) { if self.hd.is_none() || self.tl.is_none() { assert!(self.hd.is_none() && self.tl.is_none()); } @@ -438,7 +432,7 @@ pub impl DList { link = nobe.next_link(); count += 1; } - assert!(count == self.len()); + assert_eq!(count, self.len()); // iterate backwards - some of this is probably redundant. link = self.peek_tail_n(); rabbit = link; @@ -459,39 +453,39 @@ pub impl DList { link = nobe.prev_link(); count -= 1; } - assert!(count == 0); + assert_eq!(count, 0); } } -pub impl DList { +impl DList { /// Remove data from the head of the list. O(1). - fn pop(@mut self) -> Option { + pub fn pop(@mut self) -> Option { self.pop_n().map(|nobe| nobe.data) } /// Remove data from the tail of the list. O(1). - fn pop_tail(@mut self) -> Option { + pub fn pop_tail(@mut self) -> Option { self.pop_tail_n().map(|nobe| nobe.data) } /// Get data at the list's head. O(1). - fn peek(@mut self) -> Option { + pub fn peek(@mut self) -> Option { self.peek_n().map(|nobe| nobe.data) } /// Get data at the list's tail. O(1). - fn peek_tail(@mut self) -> Option { + pub fn peek_tail(@mut self) -> Option { self.peek_tail_n().map (|nobe| nobe.data) } /// Get data at the list's head, failing if empty. O(1). - fn head(@mut self) -> T { self.head_n().data } + pub fn head(@mut self) -> T { self.head_n().data } /// Get data at the list's tail, failing if empty. O(1). - fn tail(@mut self) -> T { self.tail_n().data } + pub fn tail(@mut self) -> T { self.tail_n().data } /// Get the elements of the list as a vector. O(n). - fn to_vec(@mut self) -> ~[T] { + pub fn to_vec(@mut self) -> ~[T] { let mut v = vec::with_capacity(self.size); for old_iter::eachi(&self) |index,data| { v[index] = *data; @@ -508,42 +502,6 @@ impl BaseIter for @mut DList { * allow for e.g. breadth-first search with in-place enqueues), but * removing the current node is forbidden. */ - #[cfg(stage0)] - fn each(&self, f: &fn(v: &T) -> bool) { - let mut link = self.peek_n(); - while link.is_some() { - let nobe = link.get(); - assert!(nobe.linked); - - { - let frozen_nobe = &*nobe; - if !f(&frozen_nobe.data) { break; } - } - - // Check (weakly) that the user didn't do a remove. - if self.size == 0 { - fail!("The dlist became empty during iteration??") - } - if !nobe.linked || - (!((nobe.prev.is_some() - || managed::mut_ptr_eq(self.hd.expect(~"headless dlist?"), - nobe)) - && (nobe.next.is_some() - || managed::mut_ptr_eq(self.tl.expect(~"tailless dlist?"), - nobe)))) { - fail!("Removing a dlist node during iteration is forbidden!") - } - link = nobe.next_link(); - } - } - /** - * Iterates through the current contents. - * - * Attempts to access this dlist during iteration are allowed (to - * allow for e.g. breadth-first search with in-place enqueues), but - * removing the current node is forbidden. - */ - #[cfg(not(stage0))] fn each(&self, f: &fn(v: &T) -> bool) -> bool { let mut link = self.peek_n(); while link.is_some() { @@ -561,10 +519,10 @@ impl BaseIter for @mut DList { } if !nobe.linked || (!((nobe.prev.is_some() - || managed::mut_ptr_eq(self.hd.expect(~"headless dlist?"), + || managed::mut_ptr_eq(self.hd.expect("headless dlist?"), nobe)) && (nobe.next.is_some() - || managed::mut_ptr_eq(self.tl.expect(~"tailless dlist?"), + || managed::mut_ptr_eq(self.tl.expect("tailless dlist?"), nobe)))) { fail!("Removing a dlist node during iteration is forbidden!") } @@ -579,17 +537,22 @@ impl BaseIter for @mut DList { #[cfg(test)] mod tests { + use core::prelude::*; + use super::*; + use core::old_iter; + use core::vec; + #[test] fn test_dlist_concat() { - let a = from_vec(~[1,2]); - let b = from_vec(~[3,4]); - let c = from_vec(~[5,6]); - let d = from_vec(~[7,8]); - let ab = from_vec(~[a,b]); - let cd = from_vec(~[c,d]); - let abcd = concat(concat(from_vec(~[ab,cd]))); + let a = from_vec([1,2]); + let b = from_vec([3,4]); + let c = from_vec([5,6]); + let d = from_vec([7,8]); + let ab = from_vec([a,b]); + let cd = from_vec([c,d]); + let abcd = concat(concat(from_vec([ab,cd]))); abcd.assert_consistent(); assert_eq!(abcd.len(), 8); abcd.assert_consistent(); assert_eq!(abcd.pop().get(), 1); abcd.assert_consistent(); assert_eq!(abcd.pop().get(), 2); @@ -603,8 +566,8 @@ mod tests { } #[test] fn test_dlist_append() { - let a = from_vec(~[1,2,3]); - let b = from_vec(~[4,5,6]); + let a = from_vec([1,2,3]); + let b = from_vec([4,5,6]); a.append(b); assert_eq!(a.len(), 6); assert_eq!(b.len(), 0); @@ -619,7 +582,7 @@ mod tests { } #[test] fn test_dlist_append_empty() { - let a = from_vec(~[1,2,3]); + let a = from_vec([1,2,3]); let b = DList::(); a.append(b); assert_eq!(a.len(), 3); @@ -633,7 +596,7 @@ mod tests { #[test] fn test_dlist_append_to_empty() { let a = DList::(); - let b = from_vec(~[4,5,6]); + let b = from_vec([4,5,6]); a.append(b); assert_eq!(a.len(), 3); assert_eq!(b.len(), 0); @@ -669,8 +632,8 @@ mod tests { } #[test] fn test_dlist_prepend() { - let a = from_vec(~[1,2,3]); - let b = from_vec(~[4,5,6]); + let a = from_vec([1,2,3]); + let b = from_vec([4,5,6]); b.prepend(a); assert_eq!(a.len(), 0); assert_eq!(b.len(), 6); @@ -685,7 +648,7 @@ mod tests { } #[test] fn test_dlist_reverse() { - let a = from_vec(~[5,4,3,2,1]); + let a = from_vec([5,4,3,2,1]); a.reverse(); assert_eq!(a.len(), 5); a.assert_consistent(); assert_eq!(a.pop().get(), 1); @@ -704,7 +667,7 @@ mod tests { } #[test] fn test_dlist_each_node() { - let a = from_vec(~[1,2,4,5]); + let a = from_vec([1,2,4,5]); for a.each_node |nobe| { if nobe.data > 3 { a.insert_before(3, nobe); @@ -721,7 +684,7 @@ mod tests { } #[test] fn test_dlist_clear() { - let a = from_vec(~[5,4,3,2,1]); + let a = from_vec([5,4,3,2,1]); a.clear(); assert_eq!(a.len(), 0); a.assert_consistent(); @@ -729,20 +692,20 @@ mod tests { #[test] fn test_dlist_is_empty() { let empty = DList::(); - let full1 = from_vec(~[1,2,3]); + let full1 = from_vec([1,2,3]); assert!(empty.is_empty()); assert!(!full1.is_empty()); } #[test] fn test_dlist_head_tail() { - let l = from_vec(~[1,2,3]); + let l = from_vec([1,2,3]); assert_eq!(l.head(), 1); assert_eq!(l.tail(), 3); assert_eq!(l.len(), 3); } #[test] fn test_dlist_pop() { - let l = from_vec(~[1,2,3]); + let l = from_vec([1,2,3]); assert_eq!(l.pop().get(), 1); assert_eq!(l.tail(), 3); assert_eq!(l.head(), 2); @@ -755,7 +718,7 @@ mod tests { } #[test] fn test_dlist_pop_tail() { - let l = from_vec(~[1,2,3]); + let l = from_vec([1,2,3]); assert_eq!(l.pop_tail().get(), 3); assert_eq!(l.tail(), 2); assert_eq!(l.head(), 1); @@ -801,7 +764,7 @@ mod tests { } #[test] fn test_dlist_break_early() { - let l = from_vec(~[1,2,3,4,5]); + let l = from_vec([1,2,3,4,5]); let mut x = 0; for l.each |i| { x += 1; diff --git a/src/libstd/ebml.rs b/src/libextra/ebml.rs similarity index 82% rename from src/libstd/ebml.rs rename to src/libextra/ebml.rs index 64f78d5ab7b2b..47b0b4f6c974b 100644 --- a/src/libstd/ebml.rs +++ b/src/libextra/ebml.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[allow(missing_doc)]; + +use core::prelude::*; + // Simple Extensible Binary Markup Language (ebml) reader and writer on a // cursor model. See the specification here: // http://www.matroska.org/technical/specs/rfc/index.html @@ -47,30 +51,34 @@ pub enum EbmlEncoderTag { EsI16, // 8 EsI8, // 9 EsBool, // 10 - EsStr, // 11 - EsF64, // 12 - EsF32, // 13 - EsFloat, // 14 - EsEnum, // 15 - EsEnumVid, // 16 - EsEnumBody, // 17 - EsVec, // 18 - EsVecLen, // 19 - EsVecElt, // 20 + EsChar, // 11 + EsStr, // 12 + EsF64, // 13 + EsF32, // 14 + EsFloat, // 15 + EsEnum, // 16 + EsEnumVid, // 17 + EsEnumBody, // 18 + EsVec, // 19 + EsVecLen, // 20 + EsVecElt, // 21 + EsMap, // 22 + EsMapLen, // 23 + EsMapKey, // 24 + EsMapVal, // 25 EsOpaque, - EsLabel // Used only when debugging + EsLabel, // Used only when debugging } // -------------------------------------- pub mod reader { - use ebml::{Doc, EbmlEncoderTag, EsBool, EsEnum, EsEnumBody, EsEnumVid}; - use ebml::{EsI16, EsI32, EsI64, EsI8, EsInt}; - use ebml::{EsLabel, EsOpaque, EsStr, EsU16, EsU32, EsU64, EsU8, EsUint}; - use ebml::{EsVec, EsVecElt, EsVecLen, TaggedDoc}; + use super::*; + use serialize; + use core::prelude::*; use core::cast::transmute; use core::int; use core::io; @@ -81,8 +89,8 @@ pub mod reader { // ebml reading - pub impl Doc { - fn get(&self, tag: uint) -> Doc { + impl Doc { + pub fn get(&self, tag: uint) -> Doc { get_doc(*self, tag) } } @@ -200,20 +208,6 @@ pub mod reader { } } - #[cfg(stage0)] - pub fn docs(d: Doc, it: &fn(uint, Doc) -> bool) { - let mut pos = d.start; - while pos < d.end { - let elt_tag = vuint_at(*d.data, pos); - let elt_size = vuint_at(*d.data, elt_tag.next); - pos = elt_size.next + elt_size.val; - let doc = Doc { data: d.data, start: elt_size.next, end: pos }; - if !it(elt_tag.val, doc) { - break; - } - } - } - #[cfg(not(stage0))] pub fn docs(d: Doc, it: &fn(uint, Doc) -> bool) -> bool { let mut pos = d.start; while pos < d.end { @@ -228,23 +222,6 @@ pub mod reader { return true; } - #[cfg(stage0)] - pub fn tagged_docs(d: Doc, tg: uint, it: &fn(Doc) -> bool) { - let mut pos = d.start; - while pos < d.end { - let elt_tag = vuint_at(*d.data, pos); - let elt_size = vuint_at(*d.data, elt_tag.next); - pos = elt_size.next + elt_size.val; - if elt_tag.val == tg { - let doc = Doc { data: d.data, start: elt_size.next, - end: pos }; - if !it(doc) { - break; - } - } - } - } - #[cfg(not(stage0))] pub fn tagged_docs(d: Doc, tg: uint, it: &fn(Doc) -> bool) -> bool { let mut pos = d.start; while pos < d.end { @@ -273,22 +250,22 @@ pub mod reader { pub fn doc_as_str(d: Doc) -> ~str { str::from_bytes(doc_data(d)) } pub fn doc_as_u8(d: Doc) -> u8 { - assert!(d.end == d.start + 1u); + assert_eq!(d.end, d.start + 1u); (*d.data)[d.start] } pub fn doc_as_u16(d: Doc) -> u16 { - assert!(d.end == d.start + 2u); + assert_eq!(d.end, d.start + 2u); io::u64_from_be_bytes(*d.data, d.start, 2u) as u16 } pub fn doc_as_u32(d: Doc) -> u32 { - assert!(d.end == d.start + 4u); + assert_eq!(d.end, d.start + 4u); io::u64_from_be_bytes(*d.data, d.start, 4u) as u32 } pub fn doc_as_u64(d: Doc) -> u64 { - assert!(d.end == d.start + 8u); + assert_eq!(d.end, d.start + 8u); io::u64_from_be_bytes(*d.data, d.start, 8u) } @@ -309,7 +286,7 @@ pub mod reader { } } - priv impl Decoder { + impl Decoder { fn _check_label(&mut self, lbl: &str) { if self.pos < self.parent.end { let TaggedDoc { tag: r_tag, doc: r_doc } = @@ -346,12 +323,14 @@ pub mod reader { r_doc } - fn push_doc(&mut self, d: Doc, f: &fn() -> T) -> T { + fn push_doc(&mut self, exp_tag: EbmlEncoderTag, + f: &fn(&mut Decoder) -> T) -> T { + let d = self.next_doc(exp_tag); let old_parent = self.parent; let old_pos = self.pos; self.parent = d; self.pos = d.start; - let r = f(); + let r = f(self); self.parent = old_parent; self.pos = old_pos; r @@ -364,8 +343,9 @@ pub mod reader { } } - pub impl Decoder { - fn read_opaque(&mut self, op: &fn(&mut Decoder, Doc) -> R) -> R { + impl Decoder { + pub fn read_opaque(&mut self, op: &fn(&mut Decoder, Doc) -> R) + -> R { let doc = self.next_doc(EsOpaque); let (old_parent, old_pos) = (self.parent, self.pos); @@ -420,10 +400,21 @@ pub mod reader { doc_as_u8(self.next_doc(EsBool)) as bool } - fn read_f64(&mut self) -> f64 { fail!("read_f64()"); } - fn read_f32(&mut self) -> f32 { fail!("read_f32()"); } - fn read_float(&mut self) -> float { fail!("read_float()"); } - fn read_char(&mut self) -> char { fail!("read_char()"); } + fn read_f64(&mut self) -> f64 { + let bits = doc_as_u64(self.next_doc(EsF64)); + unsafe { transmute(bits) } + } + fn read_f32(&mut self) -> f32 { + let bits = doc_as_u32(self.next_doc(EsF32)); + unsafe { transmute(bits) } + } + fn read_float(&mut self) -> float { + let bits = doc_as_u64(self.next_doc(EsFloat)); + (unsafe { transmute::(bits) }) as float + } + fn read_char(&mut self) -> char { + doc_as_u32(self.next_doc(EsChar)) as char + } fn read_str(&mut self) -> ~str { doc_as_str(self.next_doc(EsStr)) } // Compound types: @@ -566,66 +557,50 @@ pub mod reader { fn read_seq(&mut self, f: &fn(&mut Decoder, uint) -> T) -> T { debug!("read_seq()"); - let doc = self.next_doc(EsVec); - - let (old_parent, old_pos) = (self.parent, self.pos); - self.parent = doc; - self.pos = self.parent.start; - - let len = self._next_uint(EsVecLen); - debug!(" len=%u", len); - let result = f(self, len); - - self.parent = old_parent; - self.pos = old_pos; - result + do self.push_doc(EsVec) |d| { + let len = d._next_uint(EsVecLen); + debug!(" len=%u", len); + f(d, len) + } } fn read_seq_elt(&mut self, idx: uint, f: &fn(&mut Decoder) -> T) -> T { debug!("read_seq_elt(idx=%u)", idx); - let doc = self.next_doc(EsVecElt); - - let (old_parent, old_pos) = (self.parent, self.pos); - self.parent = doc; - self.pos = self.parent.start; - - let result = f(self); - - self.parent = old_parent; - self.pos = old_pos; - result + self.push_doc(EsVecElt, f) } - fn read_map(&mut self, _: &fn(&mut Decoder, uint) -> T) -> T { + fn read_map(&mut self, f: &fn(&mut Decoder, uint) -> T) -> T { debug!("read_map()"); - fail!("read_map is unimplemented"); + do self.push_doc(EsMap) |d| { + let len = d._next_uint(EsMapLen); + debug!(" len=%u", len); + f(d, len) + } } fn read_map_elt_key(&mut self, idx: uint, - _: &fn(&mut Decoder) -> T) + f: &fn(&mut Decoder) -> T) -> T { debug!("read_map_elt_key(idx=%u)", idx); - fail!("read_map_elt_val is unimplemented"); + self.push_doc(EsMapKey, f) } fn read_map_elt_val(&mut self, idx: uint, - _: &fn(&mut Decoder) -> T) + f: &fn(&mut Decoder) -> T) -> T { debug!("read_map_elt_val(idx=%u)", idx); - fail!("read_map_elt_val is unimplemented"); + self.push_doc(EsMapVal, f) } } } pub mod writer { - use ebml::{EbmlEncoderTag, EsBool, EsEnum, EsEnumBody, EsEnumVid}; - use ebml::{EsI16, EsI32, EsI64, EsI8, EsInt}; - use ebml::{EsLabel, EsOpaque, EsStr, EsU16, EsU32, EsU64, EsU8, EsUint}; - use ebml::{EsVec, EsVecElt, EsVecLen}; + use super::*; + use core::cast; use core::io; use core::str; @@ -655,16 +630,6 @@ pub mod writer { fail!("vint to write too big: %?", n); } - #[cfg(stage0)] - pub fn Encoder(w: @io::Writer) -> Encoder { - let size_positions: ~[uint] = ~[]; - Encoder { - writer: w, - mut size_positions: size_positions - } - } - - #[cfg(not(stage0))] pub fn Encoder(w: @io::Writer) -> Encoder { let size_positions: ~[uint] = ~[]; Encoder { @@ -674,8 +639,8 @@ pub mod writer { } // FIXME (#2741): Provide a function to write the standard ebml header. - pub impl Encoder { - fn start_tag(&mut self, tag_id: uint) { + impl Encoder { + pub fn start_tag(&mut self, tag_id: uint) { debug!("Start tag %u", tag_id); // Write the enum ID: @@ -687,7 +652,7 @@ pub mod writer { self.writer.write(zeroes); } - fn end_tag(&mut self) { + pub fn end_tag(&mut self) { let last_size_pos = self.size_positions.pop(); let cur_pos = self.writer.tell(); self.writer.seek(last_size_pos as int, io::SeekSet); @@ -698,72 +663,72 @@ pub mod writer { debug!("End tag (size = %u)", size); } - fn wr_tag(&mut self, tag_id: uint, blk: &fn()) { + pub fn wr_tag(&mut self, tag_id: uint, blk: &fn()) { self.start_tag(tag_id); blk(); self.end_tag(); } - fn wr_tagged_bytes(&mut self, tag_id: uint, b: &[u8]) { + pub fn wr_tagged_bytes(&mut self, tag_id: uint, b: &[u8]) { write_vuint(self.writer, tag_id); write_vuint(self.writer, b.len()); self.writer.write(b); } - fn wr_tagged_u64(&mut self, tag_id: uint, v: u64) { + pub fn wr_tagged_u64(&mut self, tag_id: uint, v: u64) { do io::u64_to_be_bytes(v, 8u) |v| { self.wr_tagged_bytes(tag_id, v); } } - fn wr_tagged_u32(&mut self, tag_id: uint, v: u32) { + pub fn wr_tagged_u32(&mut self, tag_id: uint, v: u32) { do io::u64_to_be_bytes(v as u64, 4u) |v| { self.wr_tagged_bytes(tag_id, v); } } - fn wr_tagged_u16(&mut self, tag_id: uint, v: u16) { + pub fn wr_tagged_u16(&mut self, tag_id: uint, v: u16) { do io::u64_to_be_bytes(v as u64, 2u) |v| { self.wr_tagged_bytes(tag_id, v); } } - fn wr_tagged_u8(&mut self, tag_id: uint, v: u8) { + pub fn wr_tagged_u8(&mut self, tag_id: uint, v: u8) { self.wr_tagged_bytes(tag_id, &[v]); } - fn wr_tagged_i64(&mut self, tag_id: uint, v: i64) { + pub fn wr_tagged_i64(&mut self, tag_id: uint, v: i64) { do io::u64_to_be_bytes(v as u64, 8u) |v| { self.wr_tagged_bytes(tag_id, v); } } - fn wr_tagged_i32(&mut self, tag_id: uint, v: i32) { + pub fn wr_tagged_i32(&mut self, tag_id: uint, v: i32) { do io::u64_to_be_bytes(v as u64, 4u) |v| { self.wr_tagged_bytes(tag_id, v); } } - fn wr_tagged_i16(&mut self, tag_id: uint, v: i16) { + pub fn wr_tagged_i16(&mut self, tag_id: uint, v: i16) { do io::u64_to_be_bytes(v as u64, 2u) |v| { self.wr_tagged_bytes(tag_id, v); } } - fn wr_tagged_i8(&mut self, tag_id: uint, v: i8) { + pub fn wr_tagged_i8(&mut self, tag_id: uint, v: i8) { self.wr_tagged_bytes(tag_id, &[v as u8]); } - fn wr_tagged_str(&mut self, tag_id: uint, v: &str) { + pub fn wr_tagged_str(&mut self, tag_id: uint, v: &str) { str::byte_slice(v, |b| self.wr_tagged_bytes(tag_id, b)); } - fn wr_bytes(&mut self, b: &[u8]) { + pub fn wr_bytes(&mut self, b: &[u8]) { debug!("Write %u bytes", b.len()); self.writer.write(b); } - fn wr_str(&mut self, s: &str) { + pub fn wr_str(&mut self, s: &str) { debug!("Write str: %?", s); self.writer.write(str::to_bytes(s)); } @@ -776,7 +741,7 @@ pub mod writer { // Totally lame approach. static debug: bool = true; - priv impl Encoder { + impl Encoder { // used internally to emit things like the vector length and so on fn _emit_tagged_uint(&mut self, t: EbmlEncoderTag, v: uint) { assert!(v <= 0xFFFF_FFFF_u); @@ -794,8 +759,8 @@ pub mod writer { } } - pub impl Encoder { - fn emit_opaque(&mut self, f: &fn(&mut Encoder)) { + impl Encoder { + pub fn emit_opaque(&mut self, f: &fn(&mut Encoder)) { self.start_tag(EsOpaque as uint); f(self); self.end_tag(); @@ -841,19 +806,21 @@ pub mod writer { self.wr_tagged_u8(EsBool as uint, v as u8) } - // FIXME (#2742): implement these - fn emit_f64(&mut self, _v: f64) { - fail!("Unimplemented: serializing an f64"); + fn emit_f64(&mut self, v: f64) { + let bits = unsafe { cast::transmute(v) }; + self.wr_tagged_u64(EsF64 as uint, bits); } - fn emit_f32(&mut self, _v: f32) { - fail!("Unimplemented: serializing an f32"); + fn emit_f32(&mut self, v: f32) { + let bits = unsafe { cast::transmute(v) }; + self.wr_tagged_u32(EsF32 as uint, bits); } - fn emit_float(&mut self, _v: float) { - fail!("Unimplemented: serializing a float"); + fn emit_float(&mut self, v: float) { + let bits = unsafe { cast::transmute(v as f64) }; + self.wr_tagged_u64(EsFloat as uint, bits); } - fn emit_char(&mut self, _v: char) { - fail!("Unimplemented: serializing a char"); + fn emit_char(&mut self, v: char) { + self.wr_tagged_u32(EsChar as uint, v as u32); } fn emit_str(&mut self, v: &str) { @@ -949,16 +916,23 @@ pub mod writer { self.end_tag(); } - fn emit_map(&mut self, _len: uint, _f: &fn(&mut Encoder)) { - fail!("emit_map is unimplemented"); + fn emit_map(&mut self, len: uint, f: &fn(&mut Encoder)) { + self.start_tag(EsMap as uint); + self._emit_tagged_uint(EsMapLen, len); + f(self); + self.end_tag(); } - fn emit_map_elt_key(&mut self, _idx: uint, _f: &fn(&mut Encoder)) { - fail!("emit_map_elt_key is unimplemented"); + fn emit_map_elt_key(&mut self, _idx: uint, f: &fn(&mut Encoder)) { + self.start_tag(EsMapKey as uint); + f(self); + self.end_tag(); } - fn emit_map_elt_val(&mut self, _idx: uint, _f: &fn(&mut Encoder)) { - fail!("emit_map_elt_val is unimplemented"); + fn emit_map_elt_val(&mut self, _idx: uint, f: &fn(&mut Encoder)) { + self.start_tag(EsMapVal as uint); + f(self); + self.end_tag(); } } } @@ -988,7 +962,7 @@ mod tests { let mut deser = reader::Decoder(ebml_doc); let v1 = serialize::Decodable::decode(&mut deser); debug!("v1 == %?", v1); - assert!(v == v1); + assert_eq!(v, v1); } test_v(Some(22)); diff --git a/src/libstd/fileinput.rs b/src/libextra/fileinput.rs similarity index 85% rename from src/libstd/fileinput.rs rename to src/libextra/fileinput.rs index a31827f95d1ae..3afa9b51c59a5 100644 --- a/src/libstd/fileinput.rs +++ b/src/libextra/fileinput.rs @@ -94,7 +94,14 @@ total line count). } */ +#[allow(missing_doc)]; + +use core::prelude::*; + use core::io::ReaderUtil; +use core::io; +use core::os; +use core::vec; /** A summary of the internal state of a `FileInput` object. `line_num` @@ -187,8 +194,8 @@ impl FileInput { arguments. `"-"` represents `stdin`. */ pub fn from_args() -> FileInput { - let args = os::args(), - pathed = pathify(args.tail(), true); + let args = os::args(); + let pathed = pathify(args.tail(), true); FileInput::from_vec(pathed) } @@ -210,18 +217,16 @@ impl FileInput { pub fn next_file(&self) -> bool { // No more files - // unsafe block can be removed after the next snapshot - // (next one after 2013-05-03) - if unsafe { self.fi.files.is_empty() } { + if self.fi.files.is_empty() { self.fi.current_reader = None; return false; } - let path_option = self.fi.files.shift(), - file = match path_option { - None => io::stdin(), - Some(ref path) => io::file_reader(path).get() - }; + let path_option = self.fi.files.shift(); + let file = match path_option { + None => io::stdin(), + Some(ref path) => io::file_reader(path).get() + }; self.fi.current_reader = Some(file); self.fi.state.current_path = path_option; @@ -254,17 +259,6 @@ impl FileInput { (line numbers and file names, see documentation for `FileInputState`). Otherwise identical to `lines_each`. */ - #[cfg(stage0)] - pub fn each_line_state(&self, - f: &fn(&str, FileInputState) -> bool) { - self.each_line(|line| f(line, copy self.fi.state)); - } - /** - Apply `f` to each line successively, along with some state - (line numbers and file names, see documentation for - `FileInputState`). Otherwise identical to `lines_each`. - */ - #[cfg(not(stage0))] pub fn each_line_state(&self, f: &fn(&str, FileInputState) -> bool) -> bool { self.each_line(|line| f(line, copy self.fi.state)) @@ -335,9 +329,7 @@ impl io::Reader for FileInput { fn eof(&self) -> bool { // we've run out of files, and current_reader is either None or eof. - // unsafe block can be removed after the next snapshot - // (next one after 2013-05-03) - (unsafe { self.fi.files.is_empty() }) && + self.fi.files.is_empty() && match self.fi.current_reader { None => true, Some(r) => r.eof() } } @@ -377,17 +369,6 @@ reading from `stdin`). Fails when attempting to read from a file that can't be opened. */ -#[cfg(stage0)] -pub fn input(f: &fn(&str) -> bool) { - FileInput::from_args().each_line(f); -} -/** -Iterate directly over the command line arguments (no arguments implies -reading from `stdin`). - -Fails when attempting to read from a file that can't be opened. -*/ -#[cfg(not(stage0))] pub fn input(f: &fn(&str) -> bool) -> bool { let i = FileInput::from_args(); i.each_line(f) @@ -400,18 +381,6 @@ provided at each call. Fails when attempting to read from a file that can't be opened. */ -#[cfg(stage0)] -pub fn input_state(f: &fn(&str, FileInputState) -> bool) { - FileInput::from_args().each_line_state(f); -} -/** -Iterate directly over the command line arguments (no arguments -implies reading from `stdin`) with the current state of the iteration -provided at each call. - -Fails when attempting to read from a file that can't be opened. -*/ -#[cfg(not(stage0))] pub fn input_state(f: &fn(&str, FileInputState) -> bool) -> bool { let i = FileInput::from_args(); i.each_line_state(f) @@ -422,16 +391,6 @@ Iterate over a vector of files (an empty vector implies just `stdin`). Fails when attempting to read from a file that can't be opened. */ -#[cfg(stage0)] -pub fn input_vec(files: ~[Option], f: &fn(&str) -> bool) { - FileInput::from_vec(files).each_line(f); -} -/** -Iterate over a vector of files (an empty vector implies just `stdin`). - -Fails when attempting to read from a file that can't be opened. -*/ -#[cfg(not(stage0))] pub fn input_vec(files: ~[Option], f: &fn(&str) -> bool) -> bool { let i = FileInput::from_vec(files); i.each_line(f) @@ -443,18 +402,6 @@ with the current state of the iteration provided at each call. Fails when attempting to read from a file that can't be opened. */ -#[cfg(stage0)] -pub fn input_vec_state(files: ~[Option], - f: &fn(&str, FileInputState) -> bool) { - FileInput::from_vec(files).each_line_state(f); -} -/** -Iterate over a vector of files (an empty vector implies just `stdin`) -with the current state of the iteration provided at each call. - -Fails when attempting to read from a file that can't be opened. -*/ -#[cfg(not(stage0))] pub fn input_vec_state(files: ~[Option], f: &fn(&str, FileInputState) -> bool) -> bool { let i = FileInput::from_vec(files); @@ -463,9 +410,15 @@ pub fn input_vec_state(files: ~[Option], #[cfg(test)] mod test { - use core::io::WriterUtil; + use core::prelude::*; + use super::{FileInput, pathify, input_vec, input_vec_state}; + use core::io; + use core::str; + use core::uint; + use core::vec; + fn make_file(path : &Path, contents: &[~str]) { let file = io::file_writer(path, [io::Create, io::Truncate]).get(); @@ -478,8 +431,8 @@ mod test { #[test] fn test_pathify() { let strs = [~"some/path", - ~"some/other/path"], - paths = ~[Some(Path("some/path")), + ~"some/other/path"]; + let paths = ~[Some(Path("some/path")), Some(Path("some/other/path"))]; assert_eq!(pathify(strs, true), copy paths); @@ -497,7 +450,7 @@ mod test { // 3 files containing 0\n, 1\n, and 2\n respectively for filenames.eachi |i, &filename| { - make_file(filename.get_ref(), ~[fmt!("%u", i)]); + make_file(filename.get_ref(), [fmt!("%u", i)]); } let fi = FileInput::from_vec(copy filenames); @@ -527,7 +480,7 @@ mod test { // 3 files containing 1\n, 2\n, and 3\n respectively for filenames.eachi |i, &filename| { - make_file(filename.get_ref(), ~[fmt!("%u", i)]); + make_file(filename.get_ref(), [fmt!("%u", i)]); } let fi = FileInput::from_vec(filenames); @@ -589,9 +542,9 @@ mod test { 3, |i| fmt!("tmp/lib-fileinput-test-empty-files-%u.tmp", i)),true); - make_file(filenames[0].get_ref(), ~[~"1", ~"2"]); - make_file(filenames[1].get_ref(), ~[]); - make_file(filenames[2].get_ref(), ~[~"3", ~"4"]); + make_file(filenames[0].get_ref(), [~"1", ~"2"]); + make_file(filenames[1].get_ref(), []); + make_file(filenames[2].get_ref(), [~"3", ~"4"]); let mut count = 0; for input_vec_state(copy filenames) |line, state| { @@ -608,8 +561,10 @@ mod test { #[test] fn test_no_trailing_newline() { - let f1 = Some(Path("tmp/lib-fileinput-test-no-trailing-newline-1.tmp")), - f2 = Some(Path("tmp/lib-fileinput-test-no-trailing-newline-2.tmp")); + let f1 = + Some(Path("tmp/lib-fileinput-test-no-trailing-newline-1.tmp")); + let f2 = + Some(Path("tmp/lib-fileinput-test-no-trailing-newline-2.tmp")); let wr = io::file_writer(f1.get_ref(), [io::Create, io::Truncate]).get(); wr.write_str("1\n2"); @@ -636,7 +591,7 @@ mod test { make_file(&filename.get(), contents); } - let mut in = FileInput::from_vec(filenames); + let in = FileInput::from_vec(filenames); // read once from 0 assert_eq!(in.read_line(), ~"0 1"); diff --git a/src/libstd/flate.rs b/src/libextra/flate.rs similarity index 74% rename from src/libstd/flate.rs rename to src/libextra/flate.rs index 7485f2645bdf2..076126e04329c 100644 --- a/src/libstd/flate.rs +++ b/src/libextra/flate.rs @@ -14,12 +14,13 @@ Simple compression */ -use libc; -use core::libc::{c_void, size_t, c_int}; -use vec; +#[allow(missing_doc)]; + +use core::prelude::*; -#[cfg(test)] use core::rand; -#[cfg(test)] use core::rand::RngUtil; +use core::libc::{c_void, size_t, c_int}; +use core::libc; +use core::vec; pub mod rustrt { use core::libc::{c_int, c_void, size_t}; @@ -81,27 +82,34 @@ pub fn inflate_bytes(bytes: &const [u8]) -> ~[u8] { } } -#[test] -#[allow(non_implicitly_copyable_typarams)] -fn test_flate_round_trip() { - let mut r = rand::rng(); - let mut words = ~[]; - for 20.times { - let range = r.gen_uint_range(1, 10); - words.push(r.gen_bytes(range)); - } - for 20.times { - let mut in = ~[]; - for 2000.times { - in.push_all(r.choose(words)); +#[cfg(test)] +mod tests { + use super::*; + use core::rand; + use core::rand::RngUtil; + + #[test] + #[allow(non_implicitly_copyable_typarams)] + fn test_flate_round_trip() { + let mut r = rand::rng(); + let mut words = ~[]; + for 20.times { + let range = r.gen_uint_range(1, 10); + words.push(r.gen_bytes(range)); + } + for 20.times { + let mut in = ~[]; + for 2000.times { + in.push_all(r.choose(words)); + } + debug!("de/inflate of %u bytes of random word-sequences", + in.len()); + let cmp = deflate_bytes(in); + let out = inflate_bytes(cmp); + debug!("%u bytes deflated to %u (%.1f%% size)", + in.len(), cmp.len(), + 100.0 * ((cmp.len() as float) / (in.len() as float))); + assert_eq!(in, out); } - debug!("de/inflate of %u bytes of random word-sequences", - in.len()); - let cmp = deflate_bytes(in); - let out = inflate_bytes(cmp); - debug!("%u bytes deflated to %u (%.1f%% size)", - in.len(), cmp.len(), - 100.0 * ((cmp.len() as float) / (in.len() as float))); - assert!((in == out)); } } diff --git a/src/libstd/flatpipes.rs b/src/libextra/flatpipes.rs similarity index 93% rename from src/libstd/flatpipes.rs rename to src/libextra/flatpipes.rs index f4b581f84fc0d..e8239b9f7fd75 100644 --- a/src/libstd/flatpipes.rs +++ b/src/libextra/flatpipes.rs @@ -25,7 +25,7 @@ ports and channels. This example sends boxed integers across tasks using serialization. -~~~ +~~~ {.rust} let (port, chan) = serial::pipe_stream(); do task::spawn || { @@ -47,6 +47,10 @@ block the scheduler thread, so will their pipes. */ +#[allow(missing_doc)]; + +use core::prelude::*; + // The basic send/recv interface FlatChan and PortChan will implement use core::io; use core::comm::GenericChan; @@ -168,6 +172,8 @@ POD are not equivelant. */ pub mod pod { + use core::prelude::*; + use flatpipes::flatteners::{PodUnflattener, PodFlattener}; use flatpipes::bytepipes::{ReaderBytePort, WriterByteChan}; use flatpipes::bytepipes::{PipeBytePort, PipeByteChan}; @@ -311,8 +317,8 @@ impl,C:ByteChan> GenericChan for FlatChan { } } -pub impl,P:BytePort> FlatPort { - fn new(u: U, p: P) -> FlatPort { +impl,P:BytePort> FlatPort { + pub fn new(u: U, p: P) -> FlatPort { FlatPort { unflattener: u, byte_port: p @@ -320,8 +326,8 @@ pub impl,P:BytePort> FlatPort { } } -pub impl,C:ByteChan> FlatChan { - fn new(f: F, c: C) -> FlatChan { +impl,C:ByteChan> FlatChan { + pub fn new(f: F, c: C) -> FlatChan { FlatChan { flattener: f, byte_chan: c @@ -331,6 +337,8 @@ pub impl,C:ByteChan> FlatChan { pub mod flatteners { + use core::prelude::*; + use ebml; use flatpipes::{Flattener, Unflattener}; use io_util::BufReader; @@ -339,11 +347,11 @@ pub mod flatteners { use core::cast; use core::io::{Writer, Reader, ReaderUtil}; + use core::io; use core::ptr; use core::sys::size_of; use core::vec; - // FIXME #4074: Copy + Owned != POD pub struct PodUnflattener { bogus: () @@ -356,7 +364,7 @@ pub mod flatteners { impl Unflattener for PodUnflattener { fn unflatten(&self, buf: ~[u8]) -> T { assert!(size_of::() != 0); - assert!(size_of::() == buf.len()); + assert_eq!(size_of::(), buf.len()); let addr_of_init: &u8 = unsafe { &*vec::raw::to_ptr(buf) }; let addr_of_value: &T = unsafe { cast::transmute(addr_of_init) }; copy *addr_of_value @@ -372,16 +380,16 @@ pub mod flatteners { } } - pub impl PodUnflattener { - fn new() -> PodUnflattener { + impl PodUnflattener { + pub fn new() -> PodUnflattener { PodUnflattener { bogus: () } } } - pub impl PodFlattener { - fn new() -> PodFlattener { + impl PodFlattener { + pub fn new() -> PodFlattener { PodFlattener { bogus: () } @@ -415,8 +423,8 @@ pub mod flatteners { } } - pub impl> DeserializingUnflattener { - fn new(deserialize_buffer: DeserializeBuffer) + impl> DeserializingUnflattener { + pub fn new(deserialize_buffer: DeserializeBuffer) -> DeserializingUnflattener { DeserializingUnflattener { deserialize_buffer: deserialize_buffer @@ -424,8 +432,8 @@ pub mod flatteners { } } - pub impl> SerializingFlattener { - fn new(serialize_value: SerializeValue) + impl> SerializingFlattener { + pub fn new(serialize_value: SerializeValue) -> SerializingFlattener { SerializingFlattener { serialize_value: serialize_value @@ -501,10 +509,14 @@ pub mod flatteners { } pub mod bytepipes { + use core::prelude::*; + use flatpipes::{ByteChan, BytePort}; - use core::io::{Writer, Reader, ReaderUtil}; use core::comm::{Port, Chan}; + use core::comm; + use core::io::{Writer, Reader, ReaderUtil}; + use core::vec; pub struct ReaderBytePort { reader: R @@ -542,16 +554,16 @@ pub mod bytepipes { } } - pub impl ReaderBytePort { - fn new(r: R) -> ReaderBytePort { + impl ReaderBytePort { + pub fn new(r: R) -> ReaderBytePort { ReaderBytePort { reader: r } } } - pub impl WriterByteChan { - fn new(w: W) -> WriterByteChan { + impl WriterByteChan { + pub fn new(w: W) -> WriterByteChan { WriterByteChan { writer: w } @@ -607,8 +619,8 @@ pub mod bytepipes { } } - pub impl PipeBytePort { - fn new(p: Port<~[u8]>) -> PipeBytePort { + impl PipeBytePort { + pub fn new(p: Port<~[u8]>) -> PipeBytePort { PipeBytePort { port: p, buf: @mut ~[] @@ -616,8 +628,8 @@ pub mod bytepipes { } } - pub impl PipeByteChan { - fn new(c: Chan<~[u8]>) -> PipeByteChan { + impl PipeByteChan { + pub fn new(c: Chan<~[u8]>) -> PipeByteChan { PipeByteChan { chan: c } @@ -628,6 +640,8 @@ pub mod bytepipes { #[cfg(test)] mod test { + use core::prelude::*; + use flatpipes::{Flattener, Unflattener}; use flatpipes::bytepipes::*; use flatpipes::pod; @@ -636,12 +650,17 @@ mod test { use flatpipes::{BytePort, FlatChan, FlatPort}; use net::tcp::TcpSocketBuf; + use core::comm; + use core::int; use core::io::BytesWriter; + use core::result; + use core::sys; + use core::task; #[test] #[ignore(reason = "ebml failure")] fn test_serializing_memory_stream() { - let writer = BytesWriter(); + let writer = BytesWriter::new(); let chan = serial::writer_chan(writer); chan.send(10); @@ -652,7 +671,7 @@ mod test { let port = serial::reader_port(reader); let res: int = port.recv(); - assert!(res == 10i); + assert_eq!(res, 10i); } #[test] @@ -689,7 +708,7 @@ mod test { #[test] fn test_pod_memory_stream() { - let writer = BytesWriter(); + let writer = BytesWriter::new(); let chan = pod::writer_chan(writer); chan.send(10); @@ -700,7 +719,7 @@ mod test { let port = pod::reader_port(reader); let res: int = port.recv(); - assert!(res == 10); + assert_eq!(res, 10); } #[test] @@ -772,8 +791,8 @@ mod test { let addr0 = ip::v4::parse_addr("127.0.0.1"); - let begin_connect_chan = Cell(begin_connect_chan); - let accept_chan = Cell(accept_chan); + let begin_connect_chan = Cell::new(begin_connect_chan); + let accept_chan = Cell::new(accept_chan); // The server task let addr = copy addr0; @@ -843,7 +862,7 @@ mod test { for int::range(0, 10) |i| { let j = port.recv(); debug!("received %?", j); - assert!(i == j); + assert_eq!(i, j); } // The test is over! @@ -856,11 +875,18 @@ mod test { // Tests that the different backends behave the same when the // binary streaming protocol is broken mod broken_protocol { + use core::prelude::*; + use flatpipes::{BytePort, FlatPort}; use flatpipes::flatteners::PodUnflattener; use flatpipes::pod; use io_util::BufReader; + use core::comm; + use core::io; + use core::sys; + use core::task; + type PortLoader

= ~fn(~[u8]) -> FlatPort, P>; @@ -915,7 +941,7 @@ mod test { fn test_try_recv_none3(loader: PortLoader

", "DIR"), @@ -790,7 +846,7 @@ pub fn optgroups() -> ~[getopts::groups::OptGroup] { for detail)", "FEATURE"), optopt("", "android-cross-path", "The path to the Android NDK", "PATH"), - optmulti("W", "warn", + optflagopt("W", "warn", "Set lint warnings", "OPT"), optmulti("A", "allow", "Set lint allowed", "OPT"), @@ -812,6 +868,7 @@ pub struct OutputFilenames { pub fn build_output_filenames(input: &input, odir: &Option, ofile: &Option, + attrs: &[ast::attribute], sess: Session) -> @OutputFilenames { let obj_path; @@ -821,7 +878,6 @@ pub fn build_output_filenames(input: &input, sopts.output_type != link::output_type_exe || sopts.is_static && *sess.building_library; - let obj_suffix = match sopts.output_type { link::output_type_none => ~"none", @@ -834,29 +890,44 @@ pub fn build_output_filenames(input: &input, match *ofile { None => { - // "-" as input file will cause the parser to read from stdin so we - // have to make up a name - // We want to toss everything after the final '.' - let dirpath = match *odir { - Some(ref d) => (/*bad*/copy *d), - None => match *input { - str_input(_) => os::getcwd(), - file_input(ref ifile) => (*ifile).dir_path() + // "-" as input file will cause the parser to read from stdin so we + // have to make up a name + // We want to toss everything after the final '.' + let dirpath = match *odir { + Some(ref d) => (/*bad*/copy *d), + None => match *input { + str_input(_) => os::getcwd(), + file_input(ref ifile) => (*ifile).dir_path() + } + }; + + let mut stem = match *input { + file_input(ref ifile) => (*ifile).filestem().get(), + str_input(_) => ~"rust_out" + }; + + // If a linkage name meta is present, we use it as the link name + let linkage_metas = attr::find_linkage_metas(attrs); + if !linkage_metas.is_empty() { + // But if a linkage meta is present, that overrides + let maybe_matches = attr::find_meta_items_by_name(linkage_metas, "name"); + if !maybe_matches.is_empty() { + match attr::get_meta_item_value_str(maybe_matches[0]) { + Some(s) => stem = copy *s, + _ => () + } + } + // If the name is missing, we just default to the filename + // version } - }; - - let stem = match *input { - file_input(ref ifile) => (*ifile).filestem().get(), - str_input(_) => ~"rust_out" - }; - if *sess.building_library { - out_path = dirpath.push(os::dll_filename(stem)); - obj_path = dirpath.push(stem).with_filetype(obj_suffix); - } else { - out_path = dirpath.push(stem); - obj_path = dirpath.push(stem).with_filetype(obj_suffix); - } + if *sess.building_library { + out_path = dirpath.push(os::dll_filename(stem)); + obj_path = dirpath.push(stem).with_filetype(obj_suffix); + } else { + out_path = dirpath.push(stem); + obj_path = dirpath.push(stem).with_filetype(obj_suffix); + } } Some(ref out_file) => { @@ -875,7 +946,7 @@ pub fn build_output_filenames(input: &input, } if *odir != None { - sess.warn(~"ignoring --out-dir flag due to -o flag."); + sess.warn("ignoring --out-dir flag due to -o flag."); } } } @@ -893,17 +964,19 @@ pub fn early_error(emitter: diagnostic::Emitter, msg: ~str) -> ! { pub fn list_metadata(sess: Session, path: &Path, out: @io::Writer) { metadata::loader::list_file_metadata( - sess.parse_sess.interner, + token::get_ident_interner(), session::sess_os_to_meta_os(sess.targ_cfg.os), path, out); } #[cfg(test)] mod test { + use core::prelude::*; + use driver::driver::{build_configuration, build_session}; use driver::driver::{build_session_options, optgroups, str_input}; - use std::getopts::groups::getopts; - use std::getopts; + use extra::getopts::groups::getopts; + use extra::getopts; use syntax::attr; use syntax::diagnostic; @@ -911,15 +984,15 @@ mod test { #[test] fn test_switch_implies_cfg_test() { let matches = - &match getopts(~[~"--test"], optgroups()) { - Ok(copy m) => m, - Err(copy f) => fail!("test_switch_implies_cfg_test: %s", getopts::fail_str(f)) + &match getopts([~"--test"], optgroups()) { + Ok(m) => m, + Err(f) => fail!("test_switch_implies_cfg_test: %s", getopts::fail_str(f)) }; let sessopts = build_session_options( @~"rustc", matches, diagnostic::emit); let sess = build_session(sessopts, diagnostic::emit); let cfg = build_configuration(sess, @~"whatever", &str_input(~"")); - assert!((attr::contains_name(cfg, ~"test"))); + assert!((attr::contains_name(cfg, "test"))); } // When the user supplies --test and --cfg test, don't implicitly add @@ -927,9 +1000,9 @@ mod test { #[test] fn test_switch_implies_cfg_test_unless_cfg_test() { let matches = - &match getopts(~[~"--test", ~"--cfg=test"], optgroups()) { - Ok(copy m) => m, - Err(copy f) => { + &match getopts([~"--test", ~"--cfg=test"], optgroups()) { + Ok(m) => m, + Err(f) => { fail!("test_switch_implies_cfg_test_unless_cfg_test: %s", getopts::fail_str(f)); } }; @@ -937,7 +1010,7 @@ mod test { @~"rustc", matches, diagnostic::emit); let sess = build_session(sessopts, diagnostic::emit); let cfg = build_configuration(sess, @~"whatever", &str_input(~"")); - let test_items = attr::find_meta_items_by_name(cfg, ~"test"); - assert!(test_items.len() == 1u); + let test_items = attr::find_meta_items_by_name(cfg, "test"); + assert_eq!(test_items.len(), 1u); } } diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs index 6fba5ec8d3a82..211665942a88d 100644 --- a/src/librustc/driver/session.rs +++ b/src/librustc/driver/session.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use back::link; use back::target_strs; use back; @@ -24,6 +26,7 @@ use syntax::diagnostic; use syntax::parse::ParseSess; use syntax::{ast, codemap}; use syntax::abi; +use syntax::parse::token; use syntax; use core::hashmap::HashMap; @@ -66,6 +69,8 @@ pub static debug_info: uint = 1 << 20; pub static extra_debug_info: uint = 1 << 21; pub static statik: uint = 1 << 22; pub static print_link_args: uint = 1 << 23; +pub static no_debug_borrows: uint = 1 << 24; +pub static lint_llvm : uint = 1 << 25; pub fn debugging_opts_map() -> ~[(~str, ~str, uint)] { ~[(~"verbose", ~"in general, enable more debug printouts", verbose), @@ -100,7 +105,13 @@ pub fn debugging_opts_map() -> ~[(~str, ~str, uint)] { extra_debug_info), (~"debug-info", ~"Produce debug info (experimental)", debug_info), (~"static", ~"Use or produce static libraries or binaries " + - "(experimental)", statik) + "(experimental)", statik), + (~"no-debug-borrows", + ~"do not show where borrow checks fail", + no_debug_borrows), + (~"lint-llvm", + ~"Run the LLVM lint pass on the pre-optimization IR", + lint_llvm), ] } @@ -119,13 +130,16 @@ pub struct options { is_static: bool, gc: bool, optimize: OptLevel, + custom_passes: ~[~str], debuginfo: bool, extra_debuginfo: bool, lint_opts: ~[(lint::lint, lint::level)], save_temps: bool, jit: bool, output_type: back::link::output_type, - addl_lib_search_paths: ~[Path], + addl_lib_search_paths: @mut ~[Path], // This is mutable for rustpkg, which + // updates search paths based on the + // parsed code linker: Option<~str>, linker_args: ~[~str], maybe_sysroot: Option<@Path>, @@ -141,7 +155,7 @@ pub struct options { parse_only: bool, no_trans: bool, debugging_opts: uint, - android_cross_path: Option<~str> + android_cross_path: Option<~str>, } pub struct crate_metadata { @@ -177,109 +191,122 @@ pub struct Session_ { pub type Session = @Session_; -pub impl Session_ { - fn span_fatal(@self, sp: span, msg: &str) -> ! { +impl Session_ { + pub fn span_fatal(@self, sp: span, msg: &str) -> ! { self.span_diagnostic.span_fatal(sp, msg) } - fn fatal(@self, msg: &str) -> ! { + pub fn fatal(@self, msg: &str) -> ! { self.span_diagnostic.handler().fatal(msg) } - fn span_err(@self, sp: span, msg: &str) { + pub fn span_err(@self, sp: span, msg: &str) { self.span_diagnostic.span_err(sp, msg) } - fn err(@self, msg: &str) { + pub fn err(@self, msg: &str) { self.span_diagnostic.handler().err(msg) } - fn err_count(@self) -> uint { + pub fn err_count(@self) -> uint { self.span_diagnostic.handler().err_count() } - fn has_errors(@self) -> bool { + pub fn has_errors(@self) -> bool { self.span_diagnostic.handler().has_errors() } - fn abort_if_errors(@self) { + pub fn abort_if_errors(@self) { self.span_diagnostic.handler().abort_if_errors() } - fn span_warn(@self, sp: span, msg: &str) { + pub fn span_warn(@self, sp: span, msg: &str) { self.span_diagnostic.span_warn(sp, msg) } - fn warn(@self, msg: &str) { + pub fn warn(@self, msg: &str) { self.span_diagnostic.handler().warn(msg) } - fn span_note(@self, sp: span, msg: &str) { + pub fn span_note(@self, sp: span, msg: &str) { self.span_diagnostic.span_note(sp, msg) } - fn note(@self, msg: &str) { + pub fn note(@self, msg: &str) { self.span_diagnostic.handler().note(msg) } - fn span_bug(@self, sp: span, msg: &str) -> ! { + pub fn span_bug(@self, sp: span, msg: &str) -> ! { self.span_diagnostic.span_bug(sp, msg) } - fn bug(@self, msg: &str) -> ! { + pub fn bug(@self, msg: &str) -> ! { self.span_diagnostic.handler().bug(msg) } - fn span_unimpl(@self, sp: span, msg: &str) -> ! { + pub fn span_unimpl(@self, sp: span, msg: &str) -> ! { self.span_diagnostic.span_unimpl(sp, msg) } - fn unimpl(@self, msg: &str) -> ! { + pub fn unimpl(@self, msg: &str) -> ! { self.span_diagnostic.handler().unimpl(msg) } - fn add_lint(@self, lint: lint::lint, id: ast::node_id, sp: span, msg: ~str) { + pub fn add_lint(@self, + lint: lint::lint, + id: ast::node_id, + sp: span, + msg: ~str) { match self.lints.find_mut(&id) { Some(arr) => { arr.push((lint, sp, msg)); return; } None => {} } self.lints.insert(id, ~[(lint, sp, msg)]); } - fn next_node_id(@self) -> ast::node_id { + pub fn next_node_id(@self) -> ast::node_id { return syntax::parse::next_node_id(self.parse_sess); } - fn diagnostic(@self) -> @diagnostic::span_handler { + pub fn diagnostic(@self) -> @diagnostic::span_handler { self.span_diagnostic } - fn debugging_opt(@self, opt: uint) -> bool { + pub fn debugging_opt(@self, opt: uint) -> bool { (self.opts.debugging_opts & opt) != 0u } // This exists to help with refactoring to eliminate impossible // cases later on - fn impossible_case(@self, sp: span, msg: &str) -> ! { + pub fn impossible_case(@self, sp: span, msg: &str) -> ! { self.span_bug(sp, fmt!("Impossible case reached: %s", msg)); } - fn verbose(@self) -> bool { self.debugging_opt(verbose) } - fn time_passes(@self) -> bool { self.debugging_opt(time_passes) } - fn count_llvm_insns(@self) -> bool { + pub fn verbose(@self) -> bool { self.debugging_opt(verbose) } + pub fn time_passes(@self) -> bool { self.debugging_opt(time_passes) } + pub fn count_llvm_insns(@self) -> bool { self.debugging_opt(count_llvm_insns) } - fn count_type_sizes(@self) -> bool { + pub fn count_type_sizes(@self) -> bool { self.debugging_opt(count_type_sizes) } - fn time_llvm_passes(@self) -> bool { + pub fn time_llvm_passes(@self) -> bool { self.debugging_opt(time_llvm_passes) } - fn trans_stats(@self) -> bool { self.debugging_opt(trans_stats) } - fn meta_stats(@self) -> bool { self.debugging_opt(meta_stats) } - fn asm_comments(@self) -> bool { self.debugging_opt(asm_comments) } - fn no_verify(@self) -> bool { self.debugging_opt(no_verify) } - fn trace(@self) -> bool { self.debugging_opt(trace) } - fn coherence(@self) -> bool { self.debugging_opt(coherence) } - fn borrowck_stats(@self) -> bool { self.debugging_opt(borrowck_stats) } - fn borrowck_note_pure(@self) -> bool { + pub fn trans_stats(@self) -> bool { self.debugging_opt(trans_stats) } + pub fn meta_stats(@self) -> bool { self.debugging_opt(meta_stats) } + pub fn asm_comments(@self) -> bool { self.debugging_opt(asm_comments) } + pub fn no_verify(@self) -> bool { self.debugging_opt(no_verify) } + pub fn lint_llvm(@self) -> bool { self.debugging_opt(lint_llvm) } + pub fn trace(@self) -> bool { self.debugging_opt(trace) } + pub fn coherence(@self) -> bool { self.debugging_opt(coherence) } + pub fn borrowck_stats(@self) -> bool { self.debugging_opt(borrowck_stats) } + pub fn borrowck_note_pure(@self) -> bool { self.debugging_opt(borrowck_note_pure) } - fn borrowck_note_loan(@self) -> bool { + pub fn borrowck_note_loan(@self) -> bool { self.debugging_opt(borrowck_note_loan) } - fn no_monomorphic_collapse(@self) -> bool { + pub fn no_monomorphic_collapse(@self) -> bool { self.debugging_opt(no_monomorphic_collapse) } + pub fn debug_borrows(@self) -> bool { + self.opts.optimize == No && !self.debugging_opt(no_debug_borrows) + } - fn str_of(@self, id: ast::ident) -> @~str { - self.parse_sess.interner.get(id) + // pointless function, now... + pub fn str_of(@self, id: ast::ident) -> @~str { + token::ident_to_str(&id) } - fn ident_of(@self, st: &str) -> ast::ident { - self.parse_sess.interner.intern(st) + + // pointless function, now... + pub fn ident_of(@self, st: &str) -> ast::ident { + token::str_to_ident(st) } - fn intr(@self) -> @syntax::parse::token::ident_interner { - self.parse_sess.interner + + // pointless function, now... + pub fn intr(@self) -> @syntax::parse::token::ident_interner { + token::get_ident_interner() } } @@ -290,13 +317,14 @@ pub fn basic_options() -> @options { is_static: false, gc: false, optimize: No, + custom_passes: ~[], debuginfo: false, extra_debuginfo: false, lint_opts: ~[], save_temps: false, jit: false, output_type: link::output_type_exe, - addl_lib_search_paths: ~[], + addl_lib_search_paths: @mut ~[], linker: None, linker_args: ~[], maybe_sysroot: None, @@ -308,7 +336,7 @@ pub fn basic_options() -> @options { parse_only: false, no_trans: false, debugging_opts: 0u, - android_cross_path: None + android_cross_path: None, } } @@ -332,7 +360,7 @@ pub fn building_library(req_crate_type: crate_type, } else { match syntax::attr::first_attr_value_str_by_name( crate.node.attrs, - ~"crate_type") { + "crate_type") { Some(@~"lib") => true, _ => false } @@ -375,8 +403,8 @@ mod test { fn make_crate(with_bin: bool, with_lib: bool) -> @ast::crate { let mut attrs = ~[]; - if with_bin { attrs += ~[make_crate_type_attr(~"bin")]; } - if with_lib { attrs += ~[make_crate_type_attr(~"lib")]; } + if with_bin { attrs += [make_crate_type_attr(~"bin")]; } + if with_lib { attrs += [make_crate_type_attr(~"lib")]; } @codemap::respan(codemap::dummy_sp(), ast::crate_ { module: ast::_mod { view_items: ~[], items: ~[] }, attrs: attrs, diff --git a/src/librustc/front/config.rs b/src/librustc/front/config.rs index 2246dd9d2f0aa..b942bcf4b952c 100644 --- a/src/librustc/front/config.rs +++ b/src/librustc/front/config.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + +use core::option; +use core::vec; use syntax::{ast, fold, attr}; type in_cfg_pred = @fn(attrs: ~[ast::attribute]) -> bool; @@ -134,9 +138,20 @@ fn fold_block( ) -> ast::blk_ { let filtered_stmts = b.stmts.filter_mapped(|a| filter_stmt(cx, *a)); + let filtered_view_items = + b.view_items.filter_mapped(|a| filter_view_item(cx, *a)); + let filtered_view_items = + filtered_view_items.map(|x| fld.fold_view_item(*x)); + let mut resulting_stmts = ~[]; + for filtered_stmts.each |stmt| { + match fld.fold_stmt(*stmt) { + None => {} + Some(stmt) => resulting_stmts.push(stmt), + } + } ast::blk_ { - view_items: /*bad*/copy b.view_items, - stmts: vec::map(filtered_stmts, |x| fld.fold_stmt(*x)), + view_items: filtered_view_items, + stmts: resulting_stmts, expr: b.expr.map(|x| fld.fold_expr(*x)), id: b.id, rules: b.rules, @@ -175,7 +190,7 @@ fn in_cfg(cfg: ast::crate_cfg, attrs: ~[ast::attribute]) -> bool { pub fn metas_in_cfg(cfg: ast::crate_cfg, metas: ~[@ast::meta_item]) -> bool { // The "cfg" attributes on the item - let cfg_metas = attr::find_meta_items_by_name(metas, ~"cfg"); + let cfg_metas = attr::find_meta_items_by_name(metas, "cfg"); // Pull the inner meta_items from the #[cfg(meta_item, ...)] attributes, // so we can match against them. This is the list of configurations for diff --git a/src/librustc/front/intrinsic.rs b/src/librustc/front/intrinsic.rs index ece53451ccf80..fcb08180a5ea2 100644 --- a/src/librustc/front/intrinsic.rs +++ b/src/librustc/front/intrinsic.rs @@ -12,6 +12,8 @@ // and injected into each crate the compiler builds. Keep it small. pub mod intrinsic { + #[allow(missing_doc)]; + pub use intrinsic::rusti::visit_tydesc; // FIXME (#3727): remove this when the interface has settled and the diff --git a/src/librustc/front/intrinsic_inject.rs b/src/librustc/front/intrinsic_inject.rs index 54dbea27bacc9..2cdfd17c169a0 100644 --- a/src/librustc/front/intrinsic_inject.rs +++ b/src/librustc/front/intrinsic_inject.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + +use core::vec; use driver::session::Session; use syntax::parse; use syntax::ast; @@ -25,7 +28,7 @@ pub fn inject_intrinsic(sess: Session, crate: @ast::crate) -> @ast::crate { match item { Some(i) => i, None => { - sess.fatal(~"no item found in intrinsic module"); + sess.fatal("no item found in intrinsic module"); } }; diff --git a/src/librustc/front/core_inject.rs b/src/librustc/front/std_inject.rs similarity index 82% rename from src/librustc/front/core_inject.rs rename to src/librustc/front/std_inject.rs index 5862dd00b3ce5..a05dfc446ec42 100644 --- a/src/librustc/front/core_inject.rs +++ b/src/librustc/front/std_inject.rs @@ -8,31 +8,33 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use driver::session::Session; +use core::vec; use syntax::ast; use syntax::attr; -use syntax::codemap; use syntax::codemap::dummy_sp; +use syntax::codemap; use syntax::fold; -static CORE_VERSION: &'static str = "0.7-pre"; +static STD_VERSION: &'static str = "0.7-pre"; -pub fn maybe_inject_libcore_ref(sess: Session, - crate: @ast::crate) -> @ast::crate { - if use_core(crate) { - inject_libcore_ref(sess, crate) +pub fn maybe_inject_libstd_ref(sess: Session, crate: @ast::crate) + -> @ast::crate { + if use_std(crate) { + inject_libstd_ref(sess, crate) } else { crate } } -fn use_core(crate: @ast::crate) -> bool { - !attr::attrs_contains_name(crate.node.attrs, ~"no_core") +fn use_std(crate: @ast::crate) -> bool { + !attr::attrs_contains_name(crate.node.attrs, "no_std") } -fn inject_libcore_ref(sess: Session, - crate: @ast::crate) -> @ast::crate { +fn inject_libstd_ref(sess: Session, crate: @ast::crate) -> @ast::crate { fn spanned(x: T) -> codemap::spanned { codemap::spanned { node: x, span: dummy_sp() } } @@ -42,13 +44,13 @@ fn inject_libcore_ref(sess: Session, let n1 = sess.next_node_id(); let vi1 = @ast::view_item { node: ast::view_item_extern_mod( - sess.ident_of("core"), ~[], n1), + sess.ident_of("std"), ~[], n1), attrs: ~[ spanned(ast::attribute_ { style: ast::attr_inner, value: @spanned(ast::meta_name_value( @~"vers", - spanned(ast::lit_str(@CORE_VERSION.to_str())) + spanned(ast::lit_str(@STD_VERSION.to_str())) )), is_sugared_doc: false }) @@ -78,7 +80,7 @@ fn inject_libcore_ref(sess: Session, span: dummy_sp(), global: false, idents: ~[ - sess.ident_of("core"), + sess.ident_of("std"), sess.ident_of("prelude") ], rp: None, diff --git a/src/librustc/front/test.rs b/src/librustc/front/test.rs index be03ed99ad77b..cda7d1fa93702 100644 --- a/src/librustc/front/test.rs +++ b/src/librustc/front/test.rs @@ -10,15 +10,19 @@ // Code that generates a test runner to run all the tests in a crate +use core::prelude::*; + use driver::session; use front::config; +use core::vec; use syntax::ast_util::*; use syntax::attr; use syntax::codemap::{dummy_sp, span, ExpandedFrom, CallInfo, NameAndSpan}; use syntax::codemap; -use syntax::ext::base::{mk_ctxt, ext_ctxt}; +use syntax::ext::base::ExtCtxt; use syntax::fold; +use syntax::parse::token; use syntax::print::pprust; use syntax::{ast, ast_util}; @@ -36,7 +40,7 @@ struct TestCtxt { sess: session::Session, crate: @ast::crate, path: ~[ast::ident], - ext_cx: @ext_ctxt, + ext_cx: @ExtCtxt, testfns: ~[Test] } @@ -64,7 +68,7 @@ fn generate_test_harness(sess: session::Session, let cx: @mut TestCtxt = @mut TestCtxt { sess: sess, crate: crate, - ext_cx: mk_ctxt(sess.parse_sess, copy sess.opts.cfg), + ext_cx: ExtCtxt::new(sess.parse_sess, copy sess.opts.cfg), path: ~[], testfns: ~[] }; @@ -93,8 +97,8 @@ fn strip_test_functions(crate: @ast::crate) -> @ast::crate { // When not compiling with --test we should not compile the // #[test] functions do config::strip_items(crate) |attrs| { - !attr::contains_name(attr::attr_metas(attrs), ~"test") && - !attr::contains_name(attr::attr_metas(attrs), ~"bench") + !attr::contains_name(attr::attr_metas(attrs), "test") && + !attr::contains_name(attr::attr_metas(attrs), "bench") } } @@ -140,7 +144,7 @@ fn fold_item(cx: @mut TestCtxt, i: @ast::item, fld: @fold::ast_fold) -> Option<@ast::item> { cx.path.push(i.ident); debug!("current path: %s", - ast_util::path_name_i(copy cx.path, cx.sess.parse_sess.interner)); + ast_util::path_name_i(copy cx.path)); if is_test_fn(cx, i) || is_bench_fn(i) { match i.node { @@ -148,7 +152,7 @@ fn fold_item(cx: @mut TestCtxt, i: @ast::item, fld: @fold::ast_fold) let sess = cx.sess; sess.span_fatal( i.span, - ~"unsafe functions cannot be used for tests"); + "unsafe functions cannot be used for tests"); } _ => { debug!("this is a test function"); @@ -172,7 +176,7 @@ fn fold_item(cx: @mut TestCtxt, i: @ast::item, fld: @fold::ast_fold) fn is_test_fn(cx: @mut TestCtxt, i: @ast::item) -> bool { let has_test_attr = !attr::find_attrs_by_name(i.attrs, - ~"test").is_empty(); + "test").is_empty(); fn has_test_signature(i: @ast::item) -> bool { match &i.node { @@ -193,7 +197,7 @@ fn is_test_fn(cx: @mut TestCtxt, i: @ast::item) -> bool { let sess = cx.sess; sess.span_err( i.span, - ~"functions used as tests must have signature fn() -> ()." + "functions used as tests must have signature fn() -> ()." ); } return has_test_attr && has_test_signature(i); @@ -201,7 +205,7 @@ fn is_test_fn(cx: @mut TestCtxt, i: @ast::item) -> bool { fn is_bench_fn(i: @ast::item) -> bool { let has_bench_attr = - vec::len(attr::find_attrs_by_name(i.attrs, ~"bench")) > 0u; + vec::len(attr::find_attrs_by_name(i.attrs, "bench")) > 0u; fn has_test_signature(i: @ast::item) -> bool { match i.node { @@ -239,7 +243,7 @@ fn is_ignored(cx: @mut TestCtxt, i: @ast::item) -> bool { } fn should_fail(i: @ast::item) -> bool { - vec::len(attr::find_attrs_by_name(i.attrs, ~"should_fail")) > 0u + vec::len(attr::find_attrs_by_name(i.attrs, "should_fail")) > 0u } fn add_test_module(cx: &TestCtxt, m: &ast::_mod) -> ast::_mod { @@ -256,13 +260,13 @@ We're going to be building a module that looks more or less like: mod __test { #[!resolve_unexported] - extern mod std (name = "std", vers = "..."); + extern mod extra (name = "extra", vers = "..."); fn main() { #[main]; - std::test::test_main_static(::os::args(), tests) + extra::test::test_main_static(::os::args(), tests) } - static tests : &'static [std::test::TestDescAndFn] = &[ + static tests : &'static [extra::test::TestDescAndFn] = &[ ... the list of tests in the crate ... ]; } @@ -274,7 +278,7 @@ fn mk_std(cx: &TestCtxt) -> @ast::view_item { let vers = nospan(vers); let mi = ast::meta_name_value(@~"vers", vers); let mi = nospan(mi); - let id_std = cx.sess.ident_of("std"); + let id_std = cx.sess.ident_of("extra"); let vi = if is_std(cx) { ast::view_item_use( ~[@nospan(ast::view_path_simple(id_std, @@ -295,7 +299,7 @@ fn mk_std(cx: &TestCtxt) -> @ast::view_item { fn mk_test_module(cx: &TestCtxt) -> @ast::item { - // Link to std + // Link to extra let view_items = ~[mk_std(cx)]; // A constant vector of test descriptors. @@ -307,7 +311,7 @@ fn mk_test_module(cx: &TestCtxt) -> @ast::item { let mainfn = (quote_item!( pub fn main() { #[main]; - std::test::test_main_static(::os::args(), tests); + extra::test::test_main_static(::std::os::args(), tests); } )).get(); @@ -364,7 +368,7 @@ fn mk_tests(cx: &TestCtxt) -> @ast::item { let test_descs = mk_test_descs(cx); (quote_item!( - pub static tests : &'static [self::std::test::TestDescAndFn] = + pub static tests : &'static [self::extra::test::TestDescAndFn] = $test_descs ; )).get() @@ -373,8 +377,8 @@ fn mk_tests(cx: &TestCtxt) -> @ast::item { fn is_std(cx: &TestCtxt) -> bool { let is_std = { let items = attr::find_linkage_metas(cx.crate.node.attrs); - match attr::last_meta_item_value_str_by_name(items, ~"name") { - Some(@~"std") => true, + match attr::last_meta_item_value_str_by_name(items, "name") { + Some(@~"extra") => true, _ => false } }; @@ -391,14 +395,12 @@ fn mk_test_descs(cx: &TestCtxt) -> @ast::expr { let sess = cx.sess; let inner_expr = @ast::expr { id: sess.next_node_id(), - callee_id: sess.next_node_id(), node: ast::expr_vec(descs, ast::m_imm), span: dummy_sp(), }; @ast::expr { id: sess.next_node_id(), - callee_id: sess.next_node_id(), node: ast::expr_vstore(inner_expr, ast::expr_vstore_slice), span: dummy_sp(), } @@ -410,17 +412,13 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> @ast::expr { let ext_cx = cx.ext_cx; - debug!("encoding %s", ast_util::path_name_i(path, - cx.sess.parse_sess.interner)); + debug!("encoding %s", ast_util::path_name_i(path)); let name_lit: ast::lit = - nospan(ast::lit_str(@ast_util::path_name_i( - path, - cx.sess.parse_sess.interner))); + nospan(ast::lit_str(@ast_util::path_name_i(path))); let name_expr = @ast::expr { id: cx.sess.next_node_id(), - callee_id: cx.sess.next_node_id(), node: ast::expr_lit(@name_lit), span: span }; @@ -429,15 +427,14 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> @ast::expr { let fn_expr = @ast::expr { id: cx.sess.next_node_id(), - callee_id: cx.sess.next_node_id(), node: ast::expr_path(fn_path), span: span, }; let t_expr = if test.bench { - quote_expr!( self::std::test::StaticBenchFn($fn_expr) ) + quote_expr!( self::extra::test::StaticBenchFn($fn_expr) ) } else { - quote_expr!( self::std::test::StaticTestFn($fn_expr) ) + quote_expr!( self::extra::test::StaticTestFn($fn_expr) ) }; let ignore_expr = if test.ignore { @@ -453,9 +450,9 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> @ast::expr { }; let e = quote_expr!( - self::std::test::TestDescAndFn { - desc: self::std::test::TestDesc { - name: self::std::test::StaticTestName($name_expr), + self::extra::test::TestDescAndFn { + desc: self::extra::test::TestDesc { + name: self::extra::test::StaticTestName($name_expr), ignore: $ignore_expr, should_fail: $fail_expr }, diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index d06bf1480c989..b664abef34353 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -8,8 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use core::hashmap::HashMap; -use core::libc::c_uint; +use core::libc::{c_uint, c_ushort}; +use core::option; +use core::ptr; +use core::str; +use core::vec; pub type Opcode = u32; pub type Bool = c_uint; @@ -213,15 +219,17 @@ pub enum ObjectFile_opaque {} pub type ObjectFileRef = *ObjectFile_opaque; pub enum SectionIterator_opaque {} pub type SectionIteratorRef = *SectionIterator_opaque; +pub enum Pass_opaque {} +pub type PassRef = *Pass_opaque; pub mod llvm { use super::{AtomicBinOp, AtomicOrdering, BasicBlockRef}; use super::{Bool, BuilderRef, ContextRef, MemoryBufferRef, ModuleRef}; use super::{ObjectFileRef, Opcode, PassManagerRef, PassManagerBuilderRef}; use super::{SectionIteratorRef, TargetDataRef, TypeKind, TypeRef, UseRef}; - use super::{ValueRef}; + use super::{ValueRef,PassRef}; - use core::libc::{c_char, c_int, c_longlong, c_uint, c_ulonglong}; + use core::libc::{c_char, c_int, c_longlong, c_ushort, c_uint, c_ulonglong}; #[link_args = "-Lrustllvm -lrustllvm"] #[link_name = "rustllvm"] @@ -451,6 +459,10 @@ pub mod llvm { /* all zeroes */ #[fast_ffi] pub unsafe fn LLVMConstAllOnes(Ty: TypeRef) -> ValueRef; + #[fast_ffi] + pub unsafe fn LLVMConstICmp(Pred: c_ushort, V1: ValueRef, V2: ValueRef) -> ValueRef; + #[fast_ffi] + pub unsafe fn LLVMConstFCmp(Pred: c_ushort, V1: ValueRef, V2: ValueRef) -> ValueRef; /* only for int/vector */ #[fast_ffi] pub unsafe fn LLVMGetUndef(Ty: TypeRef) -> ValueRef; @@ -1567,13 +1579,15 @@ pub mod llvm { pub unsafe fn LLVMBuildAtomicLoad(B: BuilderRef, PointerVal: ValueRef, Name: *c_char, - Order: AtomicOrdering) + Order: AtomicOrdering, + Alignment: c_uint) -> ValueRef; pub unsafe fn LLVMBuildAtomicStore(B: BuilderRef, Val: ValueRef, Ptr: ValueRef, - Order: AtomicOrdering) + Order: AtomicOrdering, + Alignment: c_uint) -> ValueRef; pub unsafe fn LLVMBuildAtomicCmpXchg(B: BuilderRef, @@ -1646,14 +1660,40 @@ pub mod llvm { /** Creates a pass manager. */ #[fast_ffi] pub unsafe fn LLVMCreatePassManager() -> PassManagerRef; + /** Creates a function-by-function pass manager */ + #[fast_ffi] + pub unsafe fn LLVMCreateFunctionPassManagerForModule(M:ModuleRef) -> PassManagerRef; + /** Disposes a pass manager. */ #[fast_ffi] pub unsafe fn LLVMDisposePassManager(PM: PassManagerRef); + /** Runs a pass manager on a module. */ #[fast_ffi] pub unsafe fn LLVMRunPassManager(PM: PassManagerRef, M: ModuleRef) -> Bool; + /** Runs the function passes on the provided function. */ + #[fast_ffi] + pub unsafe fn LLVMRunFunctionPassManager(FPM:PassManagerRef, F:ValueRef) -> Bool; + + /** Initializes all the function passes scheduled in the manager */ + #[fast_ffi] + pub unsafe fn LLVMInitializeFunctionPassManager(FPM:PassManagerRef) -> Bool; + + /** Finalizes all the function passes scheduled in the manager */ + #[fast_ffi] + pub unsafe fn LLVMFinalizeFunctionPassManager(FPM:PassManagerRef) -> Bool; + + #[fast_ffi] + pub unsafe fn LLVMInitializePasses(); + + #[fast_ffi] + pub unsafe fn LLVMAddPass(PM:PassManagerRef,P:PassRef); + + #[fast_ffi] + pub unsafe fn LLVMCreatePass(PassName:*c_char) -> PassRef; + /** Adds a verification pass. */ #[fast_ffi] pub unsafe fn LLVMAddVerifierPass(PM: PassManagerRef); @@ -1895,6 +1935,7 @@ pub mod llvm { Constraints: *c_char, SideEffects: Bool, AlignStack: Bool, Dialect: c_uint) -> ValueRef; + } } @@ -1914,6 +1955,16 @@ pub fn SetLinkage(Global: ValueRef, Link: Linkage) { } } +pub fn ConstICmp(Pred: IntPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef { + unsafe { + llvm::LLVMConstICmp(Pred as c_ushort, V1, V2) + } +} +pub fn ConstFCmp(Pred: RealPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef { + unsafe { + llvm::LLVMConstFCmp(Pred as c_ushort, V1, V2) + } +} /* Memory-managed object interface to type handles. */ pub struct TypeNames { @@ -1962,8 +2013,8 @@ pub fn type_to_str_inner(names: @TypeNames, outer0: &[TypeRef], ty: TypeRef) let mut s = ~""; let mut first: bool = true; for tys.each |t| { - if first { first = false; } else { s += ~", "; } - s += type_to_str_inner(names, outer, *t).to_owned(); + if first { first = false; } else { s += ", "; } + s += type_to_str_inner(names, outer, *t); } // [Note at-str] FIXME #2543: Could rewrite this without the copy, // but need better @str support. diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index da7a2c15f30be..546c516c287ca 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -8,18 +8,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //! Validates all used crates and extern libraries and loads their metadata +use core::prelude::*; + use metadata::cstore; use metadata::decoder; use metadata::filesearch::FileSearch; use metadata::loader; use core::hashmap::HashMap; +use core::vec; use syntax::attr; use syntax::codemap::{span, dummy_sp}; use syntax::diagnostic::span_handler; +use syntax::parse::token; use syntax::parse::token::ident_interner; use syntax::visit; use syntax::ast; @@ -99,7 +102,7 @@ fn warn_if_multiple_versions(e: @mut Env, diag.handler().warn( fmt!("using multiple versions of crate `%s`", *name)); for matches.each |match_| { - diag.span_note(match_.span, ~"used here"); + diag.span_note(match_.span, "used here"); let attrs = ~[ attr::mk_attr(attr::mk_list_item( @~"link", /*bad*/copy *match_.metas)) @@ -139,10 +142,10 @@ fn visit_crate(e: @mut Env, c: &ast::crate) { fn visit_view_item(e: @mut Env, i: @ast::view_item) { match i.node { - ast::view_item_extern_mod(ident, /*bad*/copy meta_items, id) => { + ast::view_item_extern_mod(ident, ref meta_items, id) => { debug!("resolving extern mod stmt. ident: %?, meta: %?", - ident, meta_items); - let cnum = resolve_crate(e, ident, meta_items, @~"", i.span); + ident, *meta_items); + let cnum = resolve_crate(e, ident, copy *meta_items, @~"", i.span); cstore::add_extern_mod_stmt_cnum(e.cstore, id, cnum); } _ => () @@ -164,25 +167,25 @@ fn visit_item(e: @mut Env, i: @ast::item) { ast::named => { let foreign_name = match attr::first_attr_value_str_by_name(i.attrs, - ~"link_name") { + "link_name") { Some(nn) => { if *nn == ~"" { e.diag.span_fatal( i.span, - ~"empty #[link_name] not allowed; use " + - ~"#[nolink]."); + "empty #[link_name] not allowed; use \ + #[nolink]."); } nn } - None => e.intr.get(i.ident) + None => token::ident_to_str(&i.ident) }; - if attr::find_attrs_by_name(i.attrs, ~"nolink").is_empty() { + if attr::find_attrs_by_name(i.attrs, "nolink").is_empty() { already_added = !cstore::add_used_library(cstore, foreign_name); } if !link_args.is_empty() && already_added { e.diag.span_fatal(i.span, ~"library '" + *foreign_name + - ~"' already added: can't specify link_args."); + "' already added: can't specify link_args."); } } ast::anonymous => { /* do nothing */ } @@ -233,7 +236,7 @@ fn resolve_crate(e: @mut Env, hash: @~str, span: span) -> ast::crate_num { - let metas = metas_with_ident(@/*bad*/copy *e.intr.get(ident), metas); + let metas = metas_with_ident(token::ident_to_str(&ident), metas); match existing_match(e, metas, hash) { None => { @@ -272,9 +275,9 @@ fn resolve_crate(e: @mut Env, let cname = match attr::last_meta_item_value_str_by_name(load_ctxt.metas, - ~"name") { + "name") { Some(v) => v, - None => e.intr.get(ident), + None => token::ident_to_str(&ident), }; let cmeta = @cstore::crate_metadata { name: cname, @@ -303,10 +306,11 @@ fn resolve_crate_deps(e: @mut Env, cdata: @~[u8]) -> cstore::cnum_map { for decoder::get_crate_deps(e.intr, cdata).each |dep| { let extrn_cnum = dep.cnum; let cname = dep.name; + let cname_str = token::ident_to_str(&dep.name); let cmetas = metas_with(dep.vers, @~"vers", ~[]); debug!("resolving dep crate %s ver: %s hash: %s", - *e.intr.get(dep.name), *dep.vers, *dep.hash); - match existing_match(e, metas_with_ident(e.intr.get(cname), + *cname_str, *dep.vers, *dep.hash); + match existing_match(e, metas_with_ident(cname_str, copy cmetas), dep.hash) { Some(local_cnum) => { diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index 5a0820202a99a..2a2419b0e30d7 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -10,13 +10,16 @@ // Searching for information from the cstore +use core::prelude::*; + use metadata::common::*; use metadata::cstore; use metadata::decoder; use metadata; use middle::{ty, resolve}; -use reader = std::ebml::reader; +use core::vec; +use reader = extra::ebml::reader; use syntax::ast; use syntax::ast_map; use syntax::diagnostic::expect; @@ -44,15 +47,6 @@ pub fn get_type_param_count(cstore: @mut cstore::CStore, def: ast::def_id) } /// Iterates over all the language items in the given crate. -#[cfg(stage0)] -pub fn each_lang_item(cstore: @mut cstore::CStore, - cnum: ast::crate_num, - f: &fn(ast::node_id, uint) -> bool) { - let crate_data = cstore::get_crate_data(cstore, cnum); - decoder::each_lang_item(crate_data, f) -} -/// Iterates over all the language items in the given crate. -#[cfg(not(stage0))] pub fn each_lang_item(cstore: @mut cstore::CStore, cnum: ast::crate_num, f: &fn(ast::node_id, uint) -> bool) -> bool { @@ -61,21 +55,10 @@ pub fn each_lang_item(cstore: @mut cstore::CStore, } /// Iterates over all the paths in the given crate. -#[cfg(stage0)] -pub fn each_path(cstore: @mut cstore::CStore, - cnum: ast::crate_num, - f: &fn(&str, decoder::def_like) -> bool) { - let crate_data = cstore::get_crate_data(cstore, cnum); - let get_crate_data: decoder::GetCrateDataCb = |cnum| { - cstore::get_crate_data(cstore, cnum) - }; - decoder::each_path(cstore.intr, crate_data, get_crate_data, f); -} -/// Iterates over all the paths in the given crate. -#[cfg(not(stage0))] pub fn each_path(cstore: @mut cstore::CStore, cnum: ast::crate_num, - f: &fn(&str, decoder::def_like) -> bool) -> bool { + f: &fn(&str, decoder::def_like, ast::visibility) -> bool) + -> bool { let crate_data = cstore::get_crate_data(cstore, cnum); let get_crate_data: decoder::GetCrateDataCb = |cnum| { cstore::get_crate_data(cstore, cnum) diff --git a/src/librustc/metadata/cstore.rs b/src/librustc/metadata/cstore.rs index 21815a9ed4718..6cc01cb90b8be 100644 --- a/src/librustc/metadata/cstore.rs +++ b/src/librustc/metadata/cstore.rs @@ -12,11 +12,14 @@ // The crate store - a central repo for information collected about external // crates and libraries +use core::prelude::*; + use metadata::cstore; use metadata::decoder; use core::hashmap::HashMap; -use std; +use core::vec; +use extra; use syntax::ast; use syntax::parse::token::ident_interner; @@ -150,7 +153,7 @@ pub fn get_dep_hashes(cstore: &CStore) -> ~[~str] { }); } - let sorted = do std::sort::merge_sort(result) |a, b| { + let sorted = do extra::sort::merge_sort(result) |a, b| { (a.name, a.vers, a.hash) <= (b.name, b.vers, b.hash) }; diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 43073728e8351..baf93416379a8 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -10,6 +10,8 @@ // Decoding metadata from a single crate's metadata +use core::prelude::*; + use metadata::cstore::crate_metadata; use metadata::common::*; use metadata::csearch::{ProvidedTraitMethodInfo, StaticMethodInfo}; @@ -28,9 +30,9 @@ use core::io; use core::option; use core::str; use core::vec; -use std::ebml::reader; -use std::ebml; -use std::serialize::Decodable; +use extra::ebml::reader; +use extra::ebml; +use extra::serialize::Decodable; use syntax::ast_map; use syntax::attr; use syntax::diagnostic::span_handler; @@ -38,6 +40,7 @@ use syntax::parse::token::{StringRef, ident_interner, special_idents}; use syntax::print::pprust; use syntax::{ast, ast_util}; use syntax::codemap; +use syntax::parse::token; type cmd = @crate_metadata; @@ -186,7 +189,7 @@ fn translated_parent_item_opt(cnum: ast::crate_num, d: ebml::Doc) -> fn item_reqd_and_translated_parent_item(cnum: ast::crate_num, d: ebml::Doc) -> ast::def_id { - let trait_did = item_parent_item(d).expect(~"item without parent"); + let trait_did = item_parent_item(d).expect("item without parent"); ast::def_id { crate: cnum, node: trait_did.node } } @@ -196,15 +199,6 @@ fn item_def_id(d: ebml::Doc, cdata: cmd) -> ast::def_id { |d| parse_def_id(d))); } -#[cfg(stage0)] -fn each_reexport(d: ebml::Doc, f: &fn(ebml::Doc) -> bool) { - for reader::tagged_docs(d, tag_items_data_item_reexport) |reexport_doc| { - if !f(reexport_doc) { - return; - } - } -} -#[cfg(not(stage0))] fn each_reexport(d: ebml::Doc, f: &fn(ebml::Doc) -> bool) -> bool { for reader::tagged_docs(d, tag_items_data_item_reexport) |reexport_doc| { if !f(reexport_doc) { @@ -304,10 +298,10 @@ fn item_path(intr: @ident_interner, item_doc: ebml::Doc) -> ast_map::path { for reader::docs(path_doc) |tag, elt_doc| { if tag == tag_path_elt_mod { let str = reader::doc_as_str(elt_doc); - result.push(ast_map::path_mod(intr.intern(str))); + result.push(ast_map::path_mod(token::str_to_ident(str))); } else if tag == tag_path_elt_name { let str = reader::doc_as_str(elt_doc); - result.push(ast_map::path_name(intr.intern(str))); + result.push(ast_map::path_name(token::str_to_ident(str))); } else { // ignore tag_path_len element } @@ -321,15 +315,14 @@ fn item_name(intr: @ident_interner, item: ebml::Doc) -> ast::ident { do reader::with_doc_data(name) |data| { let string = str::from_bytes_slice(data); match intr.find_equiv(&StringRef(string)) { - None => intr.intern(string), - Some(val) => val, + None => token::str_to_ident(string), + Some(val) => ast::new_ident(val), } } } fn item_to_def_like(item: ebml::Doc, did: ast::def_id, cnum: ast::crate_num) - -> def_like -{ + -> def_like { let fam = item_family(item); match fam { Const => dl_def(ast::def_const(did)), @@ -465,24 +458,6 @@ fn def_like_to_def(def_like: def_like) -> ast::def { } /// Iterates over the language items in the given crate. -#[cfg(stage0)] -pub fn each_lang_item(cdata: cmd, f: &fn(ast::node_id, uint) -> bool) { - let root = reader::Doc(cdata.data); - let lang_items = reader::get_doc(root, tag_lang_items); - for reader::tagged_docs(lang_items, tag_lang_items_item) |item_doc| { - let id_doc = reader::get_doc(item_doc, tag_lang_items_item_id); - let id = reader::doc_as_u32(id_doc) as uint; - let node_id_doc = reader::get_doc(item_doc, - tag_lang_items_item_node_id); - let node_id = reader::doc_as_u32(node_id_doc) as ast::node_id; - - if !f(node_id, id) { - break; - } - } -} -/// Iterates over the language items in the given crate. -#[cfg(not(stage0))] pub fn each_lang_item(cdata: cmd, f: &fn(ast::node_id, uint) -> bool) -> bool { let root = reader::Doc(cdata.data); let lang_items = reader::get_doc(root, tag_lang_items); @@ -501,9 +476,11 @@ pub fn each_lang_item(cdata: cmd, f: &fn(ast::node_id, uint) -> bool) -> bool { } /// Iterates over all the paths in the given crate. -pub fn _each_path(intr: @ident_interner, cdata: cmd, +pub fn _each_path(intr: @ident_interner, + cdata: cmd, get_crate_data: GetCrateDataCb, - f: &fn(&str, def_like) -> bool) -> bool { + f: &fn(&str, def_like, ast::visibility) -> bool) + -> bool { let root = reader::Doc(cdata.data); let items = reader::get_doc(root, tag_items); let items_data = reader::get_doc(items, tag_items_data); @@ -524,8 +501,10 @@ pub fn _each_path(intr: @ident_interner, cdata: cmd, debug!("(each_path) yielding explicit item: %s", path); let def_like = item_to_def_like(item_doc, def_id, cdata.cnum); + let vis = item_visibility(item_doc); + // Hand the information off to the iteratee. - if !f(path, def_like) { + if !f(path, def_like, vis) { broken = true; // FIXME #4572: This is awful. } } @@ -550,7 +529,7 @@ pub fn _each_path(intr: @ident_interner, cdata: cmd, if path_is_empty { reexport_path = reexport_name; } else { - reexport_path = path + ~"::" + reexport_name; + reexport_path = path + "::" + reexport_name; } // This reexport may be in yet another crate @@ -575,7 +554,7 @@ pub fn _each_path(intr: @ident_interner, cdata: cmd, debug!("(each_path) yielding reexported \ item: %s", reexport_path); - if (!f(reexport_path, def_like)) { + if (!f(reexport_path, def_like, ast::public)) { broken = true; // FIXME #4572: This is awful. } } @@ -588,16 +567,11 @@ pub fn _each_path(intr: @ident_interner, cdata: cmd, return broken; } -#[cfg(stage0)] -pub fn each_path(intr: @ident_interner, cdata: cmd, - get_crate_data: GetCrateDataCb, - f: &fn(&str, def_like) -> bool) { - _each_path(intr, cdata, get_crate_data, f); -} -#[cfg(not(stage0))] -pub fn each_path(intr: @ident_interner, cdata: cmd, +pub fn each_path(intr: @ident_interner, + cdata: cmd, get_crate_data: GetCrateDataCb, - f: &fn(&str, def_like) -> bool) -> bool { + f: &fn(&str, def_like, ast::visibility) -> bool) + -> bool { _each_path(intr, cdata, get_crate_data, f) } @@ -819,8 +793,8 @@ pub fn get_provided_trait_methods(intr: @ident_interner, cdata: cmd, let fty = match ty::get(ty).sty { ty::ty_bare_fn(ref f) => copy *f, _ => { - tcx.diag.handler().bug(~"get_provided_trait_methods(): id \ - has non-function type"); + tcx.diag.handler().bug("get_provided_trait_methods(): id \ + has non-function type"); } }; @@ -870,7 +844,7 @@ pub fn get_type_name_if_impl(intr: @ident_interner, } for reader::tagged_docs(item, tag_item_impl_type_basename) |doc| { - return Some(intr.intern(str::from_bytes(reader::doc_data(doc)))); + return Some(token::str_to_ident(str::from_bytes(reader::doc_data(doc)))); } return None; @@ -1064,7 +1038,7 @@ fn get_attributes(md: ebml::Doc) -> ~[ast::attribute] { let meta_items = get_meta_items(attr_doc); // Currently it's only possible to have a single meta item on // an attribute - assert!(meta_items.len() == 1u); + assert_eq!(meta_items.len(), 1u); let meta_item = meta_items[0]; attrs.push( codemap::spanned { @@ -1098,7 +1072,7 @@ fn list_crate_attributes(intr: @ident_interner, md: ebml::Doc, hash: &str, out.write_str(fmt!("%s\n", pprust::attribute_to_str(*attr, intr))); } - out.write_str(~"\n\n"); + out.write_str("\n\n"); } pub fn get_crate_attributes(data: @~[u8]) -> ~[ast::attribute] { @@ -1122,7 +1096,7 @@ pub fn get_crate_deps(intr: @ident_interner, data: @~[u8]) -> ~[crate_dep] { } for reader::tagged_docs(depsdoc, tag_crate_dep) |depdoc| { deps.push(crate_dep {cnum: crate_num, - name: intr.intern(docstr(depdoc, tag_crate_dep_name)), + name: token::str_to_ident(docstr(depdoc, tag_crate_dep_name)), vers: @docstr(depdoc, tag_crate_dep_vers), hash: @docstr(depdoc, tag_crate_dep_hash)}); crate_num += 1; @@ -1131,15 +1105,15 @@ pub fn get_crate_deps(intr: @ident_interner, data: @~[u8]) -> ~[crate_dep] { } fn list_crate_deps(intr: @ident_interner, data: @~[u8], out: @io::Writer) { - out.write_str(~"=External Dependencies=\n"); + out.write_str("=External Dependencies=\n"); for get_crate_deps(intr, data).each |dep| { out.write_str( fmt!("%d %s-%s-%s\n", - dep.cnum, *intr.get(dep.name), *dep.hash, *dep.vers)); + dep.cnum, *token::ident_to_str(&dep.name), *dep.hash, *dep.vers)); } - out.write_str(~"\n"); + out.write_str("\n"); } pub fn get_crate_hash(data: @~[u8]) -> @~str { @@ -1152,7 +1126,7 @@ pub fn get_crate_vers(data: @~[u8]) -> @~str { let attrs = decoder::get_crate_attributes(data); let linkage_attrs = attr::find_linkage_metas(attrs); - match attr::last_meta_item_value_str_by_name(linkage_attrs, ~"vers") { + match attr::last_meta_item_value_str_by_name(linkage_attrs, "vers") { Some(ver) => ver, None => @~"0.0" } @@ -1161,7 +1135,7 @@ pub fn get_crate_vers(data: @~[u8]) -> @~str { fn iter_crate_items(intr: @ident_interner, cdata: cmd, get_crate_data: GetCrateDataCb, proc: &fn(path: &str, ast::def_id)) { - for each_path(intr, cdata, get_crate_data) |path_string, def_like| { + for each_path(intr, cdata, get_crate_data) |path_string, def_like, _| { match def_like { dl_impl(*) | dl_field => {} dl_def(def) => { diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index d27bfd081bc65..2365897c4d7c9 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -10,6 +10,8 @@ // Metadata encoding +use core::prelude::*; + use metadata::common::*; use metadata::cstore; use metadata::decoder; @@ -20,11 +22,16 @@ use middle::ty; use middle; use util::ppaux::ty_to_str; -use std::flate; use core::hash::HashUtil; use core::hashmap::HashMap; -use std::serialize::Encodable; -use std; +use core::int; +use core::io; +use core::str; +use core::uint; +use core::vec; +use extra::flate; +use extra::serialize::Encodable; +use extra; use syntax::abi::AbiSet; use syntax::ast::*; use syntax::ast; @@ -32,12 +39,13 @@ use syntax::ast_map; use syntax::ast_util::*; use syntax::attr; use syntax::diagnostic::span_handler; -use syntax::parse::token::special_idents; -use syntax::{ast_util, visit}; use syntax::opt_vec::OptVec; use syntax::opt_vec; +use syntax::parse::token::special_idents; +use syntax::{ast_util, visit}; +use syntax::parse::token; use syntax; -use writer = std::ebml::writer; +use writer = extra::ebml::writer; // used by astencode: type abbrev_map = @mut HashMap; @@ -134,8 +142,7 @@ fn add_to_index(ecx: @EncodeContext, full_path.push(name); index.push( entry { - val: ast_util::path_name_i(full_path, - ecx.tcx.sess.parse_sess.interner), + val: ast_util::path_name_i(full_path), pos: ebml_w.writer.tell() }); } @@ -316,6 +323,7 @@ fn encode_enum_variant_info(ecx: @EncodeContext, encode_family(ebml_w, 'v'); encode_name(ecx, ebml_w, variant.node.name); encode_parent_item(ebml_w, local_def(id)); + encode_visibility(ebml_w, variant.node.vis); encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, variant.node.id)); match variant.node.kind { @@ -366,38 +374,90 @@ fn encode_path(ecx: @EncodeContext, fn encode_reexported_static_method(ecx: @EncodeContext, ebml_w: &mut writer::Encoder, exp: &middle::resolve::Export2, - m: @ty::Method) { - debug!("(encode static trait method) reexport '%s::%s'", - *exp.name, *ecx.tcx.sess.str_of(m.ident)); + method_def_id: def_id, + method_ident: ident) { + debug!("(encode reexported static method) %s::%s", + *exp.name, *ecx.tcx.sess.str_of(method_ident)); ebml_w.start_tag(tag_items_data_item_reexport); ebml_w.start_tag(tag_items_data_item_reexport_def_id); - ebml_w.wr_str(def_to_str(m.def_id)); + ebml_w.wr_str(def_to_str(method_def_id)); ebml_w.end_tag(); ebml_w.start_tag(tag_items_data_item_reexport_name); - ebml_w.wr_str(*exp.name + "::" + *ecx.tcx.sess.str_of(m.ident)); + ebml_w.wr_str(*exp.name + "::" + *ecx.tcx.sess.str_of(method_ident)); ebml_w.end_tag(); ebml_w.end_tag(); } +fn encode_reexported_static_base_methods(ecx: @EncodeContext, + ebml_w: &mut writer::Encoder, + exp: &middle::resolve::Export2) + -> bool { + match ecx.tcx.base_impls.find(&exp.def_id) { + Some(implementations) => { + for implementations.each |&base_impl| { + for base_impl.methods.each |&m| { + if m.explicit_self == ast::sty_static { + encode_reexported_static_method(ecx, ebml_w, exp, + m.did, m.ident); + } + } + } + + true + } + None => { false } + } +} + +fn encode_reexported_static_trait_methods(ecx: @EncodeContext, + ebml_w: &mut writer::Encoder, + exp: &middle::resolve::Export2) + -> bool { + match ecx.tcx.trait_methods_cache.find(&exp.def_id) { + Some(methods) => { + for methods.each |&m| { + if m.explicit_self == ast::sty_static { + encode_reexported_static_method(ecx, ebml_w, exp, + m.def_id, m.ident); + } + } + + true + } + None => { false } + } +} + fn encode_reexported_static_methods(ecx: @EncodeContext, ebml_w: &mut writer::Encoder, mod_path: &[ast_map::path_elt], exp: &middle::resolve::Export2) { - match ecx.tcx.trait_methods_cache.find(&exp.def_id) { - Some(methods) => { - match ecx.tcx.items.find(&exp.def_id.node) { - Some(&ast_map::node_item(_, path)) => { - if mod_path != *path { - for methods.each |&m| { - if m.explicit_self == ast::sty_static { - encode_reexported_static_method(ecx, - ebml_w, - exp, m); - } - } + match ecx.tcx.items.find(&exp.def_id.node) { + Some(&ast_map::node_item(item, path)) => { + let original_name = ecx.tcx.sess.str_of(item.ident); + + // + // We don't need to reexport static methods on items + // declared in the same module as our `pub use ...` since + // that's done when we encode the item itself. + // + // The only exception is when the reexport *changes* the + // name e.g. `pub use Foo = self::Bar` -- we have + // encoded metadata for static methods relative to Bar, + // but not yet for Foo. + // + if mod_path != *path || *exp.name != *original_name { + if !encode_reexported_static_base_methods(ecx, ebml_w, exp) { + if encode_reexported_static_trait_methods(ecx, ebml_w, exp) { + debug!(fmt!("(encode reexported static methods) %s \ + [trait]", + *original_name)); } } - _ => {} + else { + debug!(fmt!("(encode reexported static methods) %s [base]", + *original_name)); + } } } _ => {} @@ -425,8 +485,7 @@ fn encode_info_for_mod(ecx: @EncodeContext, (%?/%?)", *ecx.tcx.sess.str_of(ident), did, - ast_map::node_id_to_str(ecx.tcx.items, did, ecx.tcx - .sess.parse_sess.interner)); + ast_map::node_id_to_str(ecx.tcx.items, did, token::get_ident_interner())); ebml_w.start_tag(tag_mod_impl); ebml_w.wr_str(def_to_str(local_def(did))); @@ -834,7 +893,7 @@ fn encode_info_for_item(ecx: @EncodeContext, struct_def.fields[0].node.kind == ast::unnamed_field { let ctor_id = match struct_def.ctor_id { Some(ctor_id) => ctor_id, - None => ecx.tcx.sess.bug(~"struct def didn't have ctor id"), + None => ecx.tcx.sess.bug("struct def didn't have ctor id"), }; encode_info_for_struct_ctor(ecx, @@ -907,7 +966,7 @@ fn encode_info_for_item(ecx: @EncodeContext, // >:-< let mut impl_path = vec::append(~[], path); - impl_path += ~[ast_map::path_name(item.ident)]; + impl_path += [ast_map::path_name(item.ident)]; for methods.each |m| { index.push(entry {val: m.id, pos: ebml_w.writer.tell()}); @@ -946,7 +1005,7 @@ fn encode_info_for_item(ecx: @EncodeContext, // Now output the method info for each method. for ty::trait_method_def_ids(tcx, local_def(item.id)).eachi |i, &method_def_id| { - assert!(method_def_id.crate == ast::local_crate); + assert_eq!(method_def_id.crate, ast::local_crate); let method_ty = ty::method(tcx, method_def_id); @@ -995,7 +1054,7 @@ fn encode_info_for_item(ecx: @EncodeContext, tcx.sess.span_unimpl( item.span, fmt!("Method %s is both provided and static", - *tcx.sess.intr().get(method_ty.ident))); + *token::ident_to_str(&method_ty.ident))); } encode_type_param_bounds(ebml_w, ecx, &m.generics.ty_params); @@ -1055,7 +1114,7 @@ fn encode_info_for_items(ecx: @EncodeContext, ebml_w.start_tag(tag_items_data); index.push(entry { val: crate_node_id, pos: ebml_w.writer.tell() }); encode_info_for_mod(ecx, ebml_w, &crate.node.module, - crate_node_id, ~[], + crate_node_id, [], syntax::parse::token::special_idents::invalid); visit::visit_crate(crate, (), visit::mk_vt(@visit::Visitor { visit_expr: |_e, _cx, _v| { }, @@ -1223,8 +1282,8 @@ fn synthesize_crate_attrs(ecx: @EncodeContext, let other_items = { - let tmp = attr::remove_meta_items_by_name(items, ~"name"); - attr::remove_meta_items_by_name(tmp, ~"vers") + let tmp = attr::remove_meta_items_by_name(items, "name"); + attr::remove_meta_items_by_name(tmp, "vers") }; let meta_items = vec::append(~[name_item, vers_item], other_items); @@ -1273,12 +1332,12 @@ fn encode_crate_deps(ecx: @EncodeContext, }; // Sort by cnum - std::sort::quick_sort(deps, |kv1, kv2| kv1.cnum <= kv2.cnum); + extra::sort::quick_sort(deps, |kv1, kv2| kv1.cnum <= kv2.cnum); // Sanity-check the crate numbers let mut expected_cnum = 1; for deps.each |n| { - assert!((n.cnum == expected_cnum)); + assert_eq!(n.cnum, expected_cnum); expected_cnum += 1; } @@ -1365,7 +1424,7 @@ pub static metadata_encoding_version : &'static [u8] = 0, 0, 0, 1 ]; pub fn encode_metadata(parms: EncodeParams, crate: &crate) -> ~[u8] { - let wr = @io::BytesWriter(); + let wr = @io::BytesWriter::new(); let stats = Stats { inline_bytes: 0, attr_bytes: 0, @@ -1455,19 +1514,10 @@ pub fn encode_metadata(parms: EncodeParams, crate: &crate) -> ~[u8] { // remaining % 4 bytes. wr.write(&[0u8, 0u8, 0u8, 0u8]); - // FIXME #3396: weird bug here, for reasons unclear this emits random - // looking bytes (mostly 0x1) if we use the version byte-array constant - // above; so we use a string constant inline instead. - // - // Should be: - // - // vec::to_owned(metadata_encoding_version) + - let writer_bytes: &mut ~[u8] = wr.bytes; - (do str::as_bytes(&~"rust\x00\x00\x00\x01") |bytes| { - vec::slice(*bytes, 0, 8).to_vec() - }) + flate::deflate_bytes(*writer_bytes) + vec::to_owned(metadata_encoding_version) + + flate::deflate_bytes(*writer_bytes) } // Get the encoded string for a type diff --git a/src/librustc/metadata/filesearch.rs b/src/librustc/metadata/filesearch.rs index 82d46c03101e4..f83d33dcb3c06 100644 --- a/src/librustc/metadata/filesearch.rs +++ b/src/librustc/metadata/filesearch.rs @@ -8,6 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + +use core::option; +use core::os; +use core::result; +use core::str; + // A module for searching for libraries // FIXME (#2658): I'm not happy how this module turned out. Should // probably just be folded into cstore. @@ -21,9 +28,6 @@ pub fn pick_file(file: Path, path: &Path) -> Option { pub trait FileSearch { fn sysroot(&self) -> @Path; - #[cfg(stage0)] - fn for_each_lib_search_path(&self, f: &fn(&Path) -> bool); - #[cfg(not(stage0))] fn for_each_lib_search_path(&self, f: &fn(&Path) -> bool) -> bool; fn get_target_lib_path(&self) -> Path; fn get_target_lib_file_path(&self, file: &Path) -> Path; @@ -31,42 +35,18 @@ pub trait FileSearch { pub fn mk_filesearch(maybe_sysroot: &Option<@Path>, target_triple: &str, - addl_lib_search_paths: ~[Path]) + addl_lib_search_paths: @mut ~[Path]) -> @FileSearch { struct FileSearchImpl { sysroot: @Path, - addl_lib_search_paths: ~[Path], + addl_lib_search_paths: @mut ~[Path], target_triple: ~str } impl FileSearch for FileSearchImpl { fn sysroot(&self) -> @Path { self.sysroot } - #[cfg(stage0)] - fn for_each_lib_search_path(&self, f: &fn(&Path) -> bool) { - debug!("filesearch: searching additional lib search paths"); - // a little weird - self.addl_lib_search_paths.each(f); - - debug!("filesearch: searching target lib path"); - if !f(&make_target_lib_path(self.sysroot, - self.target_triple)) { - return; - } - debug!("filesearch: searching rustpkg lib path nearest"); - if match get_rustpkg_lib_path_nearest() { - result::Ok(ref p) => f(p), - result::Err(_) => true - } { - return; - } - debug!("filesearch: searching rustpkg lib path"); - match get_rustpkg_lib_path() { - result::Ok(ref p) => f(p), - result::Err(_) => true - }; - } - #[cfg(not(stage0))] fn for_each_lib_search_path(&self, f: &fn(&Path) -> bool) -> bool { - debug!("filesearch: searching additional lib search paths"); + debug!("filesearch: searching additional lib search paths [%?]", + self.addl_lib_search_paths.len()); // a little weird self.addl_lib_search_paths.each(f); @@ -155,7 +135,7 @@ pub fn get_rustpkg_sysroot() -> Result { } pub fn get_rustpkg_root() -> Result { - match os::getenv(~"RUSTPKG_ROOT") { + match os::getenv("RUSTPKG_ROOT") { Some(ref _p) => result::Ok(Path((*_p))), None => match os::homedir() { Some(ref _q) => result::Ok((*_q).push(".rustpkg")), @@ -209,5 +189,5 @@ pub fn libdir() -> ~str { if str::is_empty(libdir) { fail!("rustc compiled without CFG_LIBDIR environment variable"); } - libdir + libdir.to_owned() } diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index cfb2bd4b837fa..1ebf8f2e9f471 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -8,9 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //! Finds crate binaries and loads their metadata +use core::prelude::*; + use lib::llvm::{False, llvm, mk_object_file, mk_section_iter}; use metadata::decoder; use metadata::encoder; @@ -18,12 +19,20 @@ use metadata::filesearch::FileSearch; use metadata::filesearch; use syntax::codemap::span; use syntax::diagnostic::span_handler; +use syntax::parse::token; use syntax::parse::token::ident_interner; use syntax::print::pprust; use syntax::{ast, attr}; -use std::flate; +use core::cast; +use core::io; +use core::option; use core::os::consts::{macos, freebsd, linux, android, win32}; +use core::ptr; +use core::str; +use core::uint; +use core::vec; +use extra::flate; pub enum os { os_macos, @@ -51,7 +60,7 @@ pub fn load_library_crate(cx: &Context) -> (~str, @~[u8]) { None => { cx.diag.span_fatal( cx.span, fmt!("can't find crate for `%s`", - *cx.intr.get(cx.ident))); + *token::ident_to_str(&cx.ident))); } } } @@ -80,7 +89,7 @@ fn find_library_crate_aux( filesearch: @filesearch::FileSearch ) -> Option<(~str, @~[u8])> { let crate_name = crate_name_from_metas(cx.metas); - let prefix: ~str = prefix + *crate_name + ~"-"; + let prefix: ~str = prefix + *crate_name + "-"; let suffix: ~str = /*bad*/copy suffix; let mut matches = ~[]; @@ -120,7 +129,7 @@ fn find_library_crate_aux( } else { cx.diag.span_err( cx.span, fmt!("multiple matching crates for `%s`", *crate_name)); - cx.diag.handler().note(~"candidates:"); + cx.diag.handler().note("candidates:"); for matches.each |&(ident, data)| { cx.diag.handler().note(fmt!("path: %s", ident)); let attrs = decoder::get_crate_attributes(data); @@ -132,7 +141,7 @@ fn find_library_crate_aux( } pub fn crate_name_from_metas(metas: &[@ast::meta_item]) -> @~str { - let name_items = attr::find_meta_items_by_name(metas, ~"name"); + let name_items = attr::find_meta_items_by_name(metas, "name"); match name_items.last_opt() { Some(i) => { match attr::get_meta_item_value_str(*i) { @@ -260,8 +269,7 @@ pub fn list_file_metadata(intr: @ident_interner, match get_metadata_section(os, path) { option::Some(bytes) => decoder::list_crate_metadata(intr, bytes, out), option::None => { - out.write_str(~"could not find metadata in " - + path.to_str() + ~".\n"); + out.write_str(fmt!("could not find metadata in %s.\n", path.to_str())) } } } diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 55a0755f5e3f9..33e033ace4835 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -14,8 +14,13 @@ // tjc note: Would be great to have a `match check` macro equivalent // for some of these +use core::prelude::*; + use middle::ty; +use core::str; +use core::uint; +use core::vec; use syntax::abi::AbiSet; use syntax::abi; use syntax::ast; @@ -156,12 +161,12 @@ fn parse_sigil(st: @mut PState) -> ast::Sigil { } fn parse_vstore(st: @mut PState) -> ty::vstore { - assert!(next(st) == '/'); + assert_eq!(next(st), '/'); let c = peek(st); if '0' <= c && c <= '9' { let n = parse_uint(st); - assert!(next(st) == '|'); + assert_eq!(next(st), '|'); return ty::vstore_fixed(n); } @@ -187,7 +192,7 @@ fn parse_substs(st: @mut PState, conv: conv_did) -> ty::substs { let self_ty = parse_opt(st, || parse_ty(st, conv) ); - assert!(next(st) == '['); + assert_eq!(next(st), '['); let mut params: ~[ty::t] = ~[]; while peek(st) != ']' { params.push(parse_ty(st, conv)); } st.pos = st.pos + 1u; @@ -204,13 +209,13 @@ fn parse_bound_region(st: @mut PState) -> ty::bound_region { 's' => ty::br_self, 'a' => { let id = parse_uint(st); - assert!(next(st) == '|'); + assert_eq!(next(st), '|'); ty::br_anon(id) } '[' => ty::br_named(st.tcx.sess.ident_of(parse_str(st, ']'))), 'c' => { let id = parse_uint(st) as int; - assert!(next(st) == '|'); + assert_eq!(next(st), '|'); ty::br_cap_avoid(id, @parse_bound_region(st)) }, _ => fail!("parse_bound_region: bad input") @@ -223,17 +228,17 @@ fn parse_region(st: @mut PState) -> ty::Region { ty::re_bound(parse_bound_region(st)) } 'f' => { - assert!(next(st) == '['); + assert_eq!(next(st), '['); let id = parse_uint(st) as int; - assert!(next(st) == '|'); + assert_eq!(next(st), '|'); let br = parse_bound_region(st); - assert!(next(st) == ']'); + assert_eq!(next(st), ']'); ty::re_free(ty::FreeRegion {scope_id: id, bound_region: br}) } 's' => { let id = parse_uint(st) as int; - assert!(next(st) == '|'); + assert_eq!(next(st), '|'); ty::re_scope(id) } 't' => { @@ -294,19 +299,19 @@ fn parse_ty(st: @mut PState, conv: conv_did) -> ty::t { } 'c' => return ty::mk_char(), 't' => { - assert!((next(st) == '[')); + assert_eq!(next(st), '['); let def = parse_def(st, NominalType, conv); let substs = parse_substs(st, conv); - assert!(next(st) == ']'); + assert_eq!(next(st), ']'); return ty::mk_enum(st.tcx, def, substs); } 'x' => { - assert!(next(st) == '['); + assert_eq!(next(st), '['); let def = parse_def(st, NominalType, conv); let substs = parse_substs(st, conv); let store = parse_trait_store(st); let mt = parse_mutability(st); - assert!(next(st) == ']'); + assert_eq!(next(st), ']'); return ty::mk_trait(st.tcx, def, substs, store, mt); } 'p' => { @@ -337,7 +342,7 @@ fn parse_ty(st: @mut PState, conv: conv_did) -> ty::t { return ty::mk_estr(st.tcx, v); } 'T' => { - assert!((next(st) == '[')); + assert_eq!(next(st), '['); let mut params = ~[]; while peek(st) != ']' { params.push(parse_ty(st, conv)); } st.pos = st.pos + 1u; @@ -356,9 +361,9 @@ fn parse_ty(st: @mut PState, conv: conv_did) -> ty::t { } '#' => { let pos = parse_hex(st); - assert!((next(st) == ':')); + assert_eq!(next(st), ':'); let len = parse_hex(st); - assert!((next(st) == '#')); + assert_eq!(next(st), '#'); let key = ty::creader_cache_key {cnum: st.crate, pos: pos, len: len }; @@ -379,10 +384,10 @@ fn parse_ty(st: @mut PState, conv: conv_did) -> ty::t { } 'B' => ty::mk_opaque_box(st.tcx), 'a' => { - assert!((next(st) == '[')); + assert_eq!(next(st), '['); let did = parse_def(st, NominalType, conv); let substs = parse_substs(st, conv); - assert!((next(st) == ']')); + assert_eq!(next(st), ']'); return ty::mk_struct(st.tcx, did, substs); } c => { error!("unexpected char in type string: %c", c); fail!();} @@ -445,7 +450,7 @@ fn parse_purity(c: char) -> purity { } fn parse_abi_set(st: @mut PState) -> AbiSet { - assert!(next(st) == '['); + assert_eq!(next(st), '['); let mut abis = AbiSet::empty(); while peek(st) != ']' { // FIXME(#5422) str API should not force this copy @@ -453,7 +458,7 @@ fn parse_abi_set(st: @mut PState) -> AbiSet { let abi = abi::lookup(abi_str).expect(abi_str); abis.add(abi); } - assert!(next(st) == ']'); + assert_eq!(next(st), ']'); return abis; } @@ -494,7 +499,7 @@ fn parse_bare_fn_ty(st: @mut PState, conv: conv_did) -> ty::BareFnTy { } fn parse_sig(st: @mut PState, conv: conv_did) -> ty::FnSig { - assert!((next(st) == '[')); + assert_eq!(next(st), '['); let mut inputs = ~[]; while peek(st) != ']' { inputs.push(parse_ty(st, conv)); @@ -564,6 +569,9 @@ fn parse_bounds(st: @mut PState, conv: conv_did) -> ty::ParamBounds { 'O' => { param_bounds.builtin_bounds.add(ty::BoundStatic); } + 'Z' => { + param_bounds.builtin_bounds.add(ty::BoundSized); + } 'I' => { param_bounds.trait_bounds.push(@parse_trait_ref(st, conv)); } diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index 5f799f4994677..947c68634148e 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -10,6 +10,8 @@ // Type encoding +use core::prelude::*; + use middle::ty::param_ty; use middle::ty; @@ -87,8 +89,7 @@ pub fn enc_ty(w: @io::Writer, cx: @ctxt, t: ty::t) { let abbrev_len = 3u + estimate_sz(pos) + estimate_sz(len); if abbrev_len < len { // I.e. it's actually an abbreviation. - let s = ~"#" + uint::to_str_radix(pos, 16u) + ~":" + - uint::to_str_radix(len, 16u) + ~"#"; + let s = fmt!("#%x:%x#", pos, len); let a = ty_abbrev { pos: pos, len: len, s: @s }; abbrevs.insert(t, a); } @@ -155,7 +156,7 @@ fn enc_region(w: @io::Writer, cx: @ctxt, r: ty::Region) { } ty::re_infer(_) => { // these should not crop up after typeck - cx.diag.handler().bug(~"Cannot encode region variables"); + cx.diag.handler().bug("Cannot encode region variables"); } } } @@ -301,7 +302,7 @@ fn enc_sty(w: @io::Writer, cx: @ctxt, st: ty::sty) { enc_bare_fn_ty(w, cx, f); } ty::ty_infer(_) => { - cx.diag.handler().bug(~"Cannot encode inference variable types"); + cx.diag.handler().bug("Cannot encode inference variable types"); } ty::ty_param(param_ty {idx: id, def_id: did}) => { w.write_char('p'); @@ -321,15 +322,15 @@ fn enc_sty(w: @io::Writer, cx: @ctxt, st: ty::sty) { } ty::ty_opaque_box => w.write_char('B'), ty::ty_struct(def, ref substs) => { - debug!("~~~~ %s", ~"a["); + debug!("~~~~ %s", "a["); w.write_str(&"a["); let s = (cx.ds)(def); debug!("~~~~ %s", s); w.write_str(s); - debug!("~~~~ %s", ~"|"); + debug!("~~~~ %s", "|"); w.write_char('|'); enc_substs(w, cx, substs); - debug!("~~~~ %s", ~"]"); + debug!("~~~~ %s", "]"); w.write_char(']'); } ty::ty_err => fail!("Shouldn't encode error type") @@ -402,6 +403,7 @@ fn enc_bounds(w: @io::Writer, cx: @ctxt, bs: &ty::ParamBounds) { ty::BoundCopy => w.write_char('C'), ty::BoundConst => w.write_char('K'), ty::BoundStatic => w.write_char('O'), + ty::BoundSized => w.write_char('Z'), } } diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 209a14942e9a7..8bde4e37d54d8 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use c = metadata::common; use cstore = metadata::cstore; use driver::session::Session; @@ -23,11 +25,14 @@ use middle::{ty, typeck, moves}; use middle; use util::ppaux::ty_to_str; -use std::ebml::reader; -use std::ebml; -use std::serialize; -use std::serialize::{Encoder, Encodable, EncoderHelpers, DecoderHelpers}; -use std::serialize::{Decoder, Decodable}; +use core::at_vec; +use core::str; +use core::uint; +use extra::ebml::reader; +use extra::ebml; +use extra::serialize; +use extra::serialize::{Encoder, Encodable, EncoderHelpers, DecoderHelpers}; +use extra::serialize::{Decoder, Decodable}; use syntax::ast; use syntax::ast_map; use syntax::ast_util::inlined_item_utils; @@ -36,8 +41,9 @@ use syntax::codemap::span; use syntax::codemap; use syntax::fold::*; use syntax::fold; +use syntax::parse::token; use syntax; -use writer = std::ebml::writer; +use writer = extra::ebml::writer; #[cfg(test)] use syntax::parse; #[cfg(test)] use syntax::print::pprust; @@ -81,7 +87,7 @@ pub fn encode_inlined_item(ecx: @e::EncodeContext, ii: ast::inlined_item, maps: Maps) { debug!("> Encoding inlined item: %s::%s (%u)", - ast_map::path_to_str(path, ecx.tcx.sess.parse_sess.interner), + ast_map::path_to_str(path, token::get_ident_interner()), *ecx.tcx.sess.str_of(ii.ident()), ebml_w.writer.tell()); @@ -94,7 +100,7 @@ pub fn encode_inlined_item(ecx: @e::EncodeContext, ebml_w.end_tag(); debug!("< Encoded inlined fn: %s::%s (%u)", - ast_map::path_to_str(path, ecx.tcx.sess.parse_sess.interner), + ast_map::path_to_str(path, token::get_ident_interner()), *ecx.tcx.sess.str_of(ii.ident()), ebml_w.writer.tell()); } @@ -114,7 +120,7 @@ pub fn decode_inlined_item(cdata: @cstore::crate_metadata, None => None, Some(ast_doc) => { debug!("> Decoding inlined fn: %s::?", - ast_map::path_to_str(path, tcx.sess.parse_sess.interner)); + ast_map::path_to_str(path, token::get_ident_interner())); let mut ast_dsr = reader::Decoder(ast_doc); let from_id_range = Decodable::decode(&mut ast_dsr); let to_id_range = reserve_id_range(dcx.tcx.sess, from_id_range); @@ -127,7 +133,7 @@ pub fn decode_inlined_item(cdata: @cstore::crate_metadata, let ii = renumber_ast(xcx, raw_ii); debug!("Fn named: %s", *tcx.sess.str_of(ii.ident())); debug!("< Decoded inlined fn: %s::%s", - ast_map::path_to_str(path, tcx.sess.parse_sess.interner), + ast_map::path_to_str(path, token::get_ident_interner()), *tcx.sess.str_of(ii.ident())); ast_map::map_decoded_item(tcx.sess.diagnostic(), dcx.tcx.items, path, &ii); @@ -158,8 +164,8 @@ fn reserve_id_range(sess: Session, ast_util::id_range { min: to_id_min, max: to_id_min } } -pub impl ExtendedDecodeContext { - fn tr_id(&self, id: ast::node_id) -> ast::node_id { +impl ExtendedDecodeContext { + pub fn tr_id(&self, id: ast::node_id) -> ast::node_id { /*! * Translates an internal id, meaning a node id that is known * to refer to some part of the item currently being inlined, @@ -174,7 +180,7 @@ pub impl ExtendedDecodeContext { assert!(!self.from_id_range.empty()); (id - self.from_id_range.min + self.to_id_range.min) } - fn tr_def_id(&self, did: ast::def_id) -> ast::def_id { + pub fn tr_def_id(&self, did: ast::def_id) -> ast::def_id { /*! * Translates an EXTERNAL def-id, converting the crate number * from the one used in the encoded data to the current crate @@ -198,7 +204,7 @@ pub impl ExtendedDecodeContext { decoder::translate_def_id(self.dcx.cdata, did) } - fn tr_intern_def_id(&self, did: ast::def_id) -> ast::def_id { + pub fn tr_intern_def_id(&self, did: ast::def_id) -> ast::def_id { /*! * Translates an INTERNAL def-id, meaning a def-id that is * known to refer to some part of the item currently being @@ -206,10 +212,10 @@ pub impl ExtendedDecodeContext { * refer to the current crate and to the new, inlined node-id. */ - assert!(did.crate == ast::local_crate); + assert_eq!(did.crate, ast::local_crate); ast::def_id { crate: ast::local_crate, node: self.tr_id(did.node) } } - fn tr_span(&self, _span: span) -> span { + pub fn tr_span(&self, _span: span) -> span { codemap::dummy_sp() // FIXME (#1972): handle span properly } } @@ -614,10 +620,10 @@ fn encode_vtable_res(ecx: @e::EncodeContext, fn encode_vtable_origin(ecx: @e::EncodeContext, ebml_w: &mut writer::Encoder, vtable_origin: &typeck::vtable_origin) { - do ebml_w.emit_enum(~"vtable_origin") |ebml_w| { + do ebml_w.emit_enum("vtable_origin") |ebml_w| { match *vtable_origin { typeck::vtable_static(def_id, ref tys, vtable_res) => { - do ebml_w.emit_enum_variant(~"vtable_static", 0u, 3u) |ebml_w| { + do ebml_w.emit_enum_variant("vtable_static", 0u, 3u) |ebml_w| { do ebml_w.emit_enum_variant_arg(0u) |ebml_w| { ebml_w.emit_def_id(def_id) } @@ -630,7 +636,7 @@ fn encode_vtable_origin(ecx: @e::EncodeContext, } } typeck::vtable_param(pn, bn) => { - do ebml_w.emit_enum_variant(~"vtable_param", 1u, 2u) |ebml_w| { + do ebml_w.emit_enum_variant("vtable_param", 1u, 2u) |ebml_w| { do ebml_w.emit_enum_variant_arg(0u) |ebml_w| { ebml_w.emit_uint(pn); } @@ -756,20 +762,20 @@ impl ebml_writer_helpers for writer::Encoder { ecx: @e::EncodeContext, tpbt: ty::ty_param_bounds_and_ty) { do self.emit_struct("ty_param_bounds_and_ty", 2) |this| { - do this.emit_struct_field(~"generics", 0) |this| { + do this.emit_struct_field("generics", 0) |this| { do this.emit_struct("Generics", 2) |this| { - do this.emit_struct_field(~"type_param_defs", 0) |this| { + do this.emit_struct_field("type_param_defs", 0) |this| { do this.emit_from_vec(*tpbt.generics.type_param_defs) |this, type_param_def| { this.emit_type_param_def(ecx, type_param_def); } } - do this.emit_struct_field(~"region_param", 1) |this| { + do this.emit_struct_field("region_param", 1) |this| { tpbt.generics.region_param.encode(this); } } } - do this.emit_struct_field(~"ty", 1) |this| { + do this.emit_struct_field("ty", 1) |this| { this.emit_ty(ecx, tpbt.ty); } } @@ -1162,7 +1168,7 @@ impl fake_ext_ctxt for fake_session { } } fn ident_of(&self, st: &str) -> ast::ident { - self.interner.intern(st) + token::str_to_ident(st) } } @@ -1231,9 +1237,9 @@ fn test_simplification() { match (item_out, item_exp) { (ast::ii_item(item_out), ast::ii_item(item_exp)) => { assert!(pprust::item_to_str(item_out, - ext_cx.parse_sess().interner) + token::get_ident_interner()) == pprust::item_to_str(item_exp, - ext_cx.parse_sess().interner)); + token::get_ident_interner())); } _ => fail!() } diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index 2f24a8ceb2465..7890e1b9f35bb 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -17,34 +17,40 @@ // 3. assignments do not affect things loaned out as immutable // 4. moves do not affect things loaned out in any way -use middle::moves; -use middle::borrowck::*; +use core::prelude::*; + +use core::hashmap::HashSet; +use core::uint; use mc = middle::mem_categorization; +use middle::borrowck::*; +use middle::moves; use middle::ty; -use util::ppaux::Repr; -use core::hashmap::HashSet; use syntax::ast::{m_mutbl, m_imm, m_const}; use syntax::ast; use syntax::ast_util; -use syntax::visit; use syntax::codemap::span; +use syntax::visit; +use util::ppaux::Repr; struct CheckLoanCtxt<'self> { bccx: @BorrowckCtxt, - dfcx: &'self LoanDataFlow, + dfcx_loans: &'self LoanDataFlow, + move_data: move_data::FlowedMoveData, all_loans: &'self [Loan], reported: @mut HashSet, } pub fn check_loans(bccx: @BorrowckCtxt, - dfcx: &LoanDataFlow, + dfcx_loans: &LoanDataFlow, + move_data: move_data::FlowedMoveData, all_loans: &[Loan], body: &ast::blk) { debug!("check_loans(body id=%?)", body.node.id); let clcx = @mut CheckLoanCtxt { bccx: bccx, - dfcx: dfcx, + dfcx_loans: dfcx_loans, + move_data: move_data, all_loans: all_loans, reported: @mut HashSet::new(), }; @@ -60,43 +66,23 @@ pub fn check_loans(bccx: @BorrowckCtxt, enum MoveError { MoveOk, - MoveFromIllegalCmt(mc::cmt), - MoveWhileBorrowed(/*loan*/@LoanPath, /*loan*/span) + MoveWhileBorrowed(/*move*/@LoanPath, /*loan*/@LoanPath, /*loan*/span) } -pub impl<'self> CheckLoanCtxt<'self> { - fn tcx(&self) -> ty::ctxt { self.bccx.tcx } +impl<'self> CheckLoanCtxt<'self> { + pub fn tcx(&self) -> ty::ctxt { self.bccx.tcx } - #[cfg(stage0)] - fn each_issued_loan(&self, - scope_id: ast::node_id, - op: &fn(&Loan) -> bool) - { - //! Iterates over each loan that that has been issued - //! on entrance to `scope_id`, regardless of whether it is - //! actually *in scope* at that point. Sometimes loans - //! are issued for future scopes and thus they may have been - //! *issued* but not yet be in effect. - - for self.dfcx.each_bit_on_entry(scope_id) |loan_index| { - let loan = &self.all_loans[loan_index]; - if !op(loan) { - return; - } - } - } - #[cfg(not(stage0))] - fn each_issued_loan(&self, - scope_id: ast::node_id, - op: &fn(&Loan) -> bool) -> bool - { + pub fn each_issued_loan(&self, + scope_id: ast::node_id, + op: &fn(&Loan) -> bool) + -> bool { //! Iterates over each loan that that has been issued //! on entrance to `scope_id`, regardless of whether it is //! actually *in scope* at that point. Sometimes loans //! are issued for future scopes and thus they may have been //! *issued* but not yet be in effect. - for self.dfcx.each_bit_on_entry(scope_id) |loan_index| { + for self.dfcx_loans.each_bit_on_entry(scope_id) |loan_index| { let loan = &self.all_loans[loan_index]; if !op(loan) { return false; @@ -105,28 +91,10 @@ pub impl<'self> CheckLoanCtxt<'self> { return true; } - #[cfg(stage0)] - fn each_in_scope_loan(&self, - scope_id: ast::node_id, - op: &fn(&Loan) -> bool) - { - //! Like `each_issued_loan()`, but only considers loans that are - //! currently in scope. - - let region_maps = self.tcx().region_maps; - for self.each_issued_loan(scope_id) |loan| { - if region_maps.is_subscope_of(scope_id, loan.kill_scope) { - if !op(loan) { - return; - } - } - } - } - #[cfg(not(stage0))] - fn each_in_scope_loan(&self, - scope_id: ast::node_id, - op: &fn(&Loan) -> bool) -> bool - { + pub fn each_in_scope_loan(&self, + scope_id: ast::node_id, + op: &fn(&Loan) -> bool) + -> bool { //! Like `each_issued_loan()`, but only considers loans that are //! currently in scope. @@ -141,31 +109,11 @@ pub impl<'self> CheckLoanCtxt<'self> { return true; } - #[cfg(stage0)] - fn each_in_scope_restriction(&self, - scope_id: ast::node_id, - loan_path: @LoanPath, - op: &fn(&Loan, &Restriction) -> bool) - { - //! Iterates through all the in-scope restrictions for the - //! given `loan_path` - - for self.each_in_scope_loan(scope_id) |loan| { - for loan.restrictions.each |restr| { - if restr.loan_path == loan_path { - if !op(loan, restr) { - return; - } - } - } - } - } - #[cfg(not(stage0))] - fn each_in_scope_restriction(&self, - scope_id: ast::node_id, - loan_path: @LoanPath, - op: &fn(&Loan, &Restriction) -> bool) -> bool - { + pub fn each_in_scope_restriction(&self, + scope_id: ast::node_id, + loan_path: @LoanPath, + op: &fn(&Loan, &Restriction) -> bool) + -> bool { //! Iterates through all the in-scope restrictions for the //! given `loan_path` @@ -181,18 +129,18 @@ pub impl<'self> CheckLoanCtxt<'self> { return true; } - fn loans_generated_by(&self, scope_id: ast::node_id) -> ~[uint] { + pub fn loans_generated_by(&self, scope_id: ast::node_id) -> ~[uint] { //! Returns a vector of the loans that are generated as //! we encounter `scope_id`. let mut result = ~[]; - for self.dfcx.each_gen_bit(scope_id) |loan_index| { + for self.dfcx_loans.each_gen_bit(scope_id) |loan_index| { result.push(loan_index); } return result; } - fn check_for_conflicting_loans(&mut self, scope_id: ast::node_id) { + pub fn check_for_conflicting_loans(&mut self, scope_id: ast::node_id) { //! Checks to see whether any of the loans that are issued //! by `scope_id` conflict with loans that have already been //! issued when we enter `scope_id` (for example, we do not @@ -219,9 +167,9 @@ pub impl<'self> CheckLoanCtxt<'self> { } } - fn report_error_if_loans_conflict(&self, - old_loan: &Loan, - new_loan: &Loan) { + pub fn report_error_if_loans_conflict(&self, + old_loan: &Loan, + new_loan: &Loan) { //! Checks whether `old_loan` and `new_loan` can safely be issued //! simultaneously. @@ -240,11 +188,12 @@ pub impl<'self> CheckLoanCtxt<'self> { new_loan, old_loan, old_loan, new_loan); } - fn report_error_if_loan_conflicts_with_restriction(&self, - loan1: &Loan, - loan2: &Loan, - old_loan: &Loan, - new_loan: &Loan) -> bool { + pub fn report_error_if_loan_conflicts_with_restriction(&self, + loan1: &Loan, + loan2: &Loan, + old_loan: &Loan, + new_loan: &Loan) + -> bool { //! Checks whether the restrictions introduced by `loan1` would //! prohibit `loan2`. Returns false if an error is reported. @@ -253,9 +202,9 @@ pub impl<'self> CheckLoanCtxt<'self> { loan1.repr(self.tcx()), loan2.repr(self.tcx())); - // Restrictions that would cause the new loan to be immutable: + // Restrictions that would cause the new loan to be illegal: let illegal_if = match loan2.mutbl { - m_mutbl => RESTR_ALIAS | RESTR_FREEZE | RESTR_MUTATE, + m_mutbl => RESTR_ALIAS | RESTR_FREEZE | RESTR_CLAIM, m_imm => RESTR_ALIAS | RESTR_FREEZE, m_const => RESTR_ALIAS, }; @@ -299,14 +248,37 @@ pub impl<'self> CheckLoanCtxt<'self> { true } - fn is_local_variable(&self, cmt: mc::cmt) -> bool { + pub fn is_local_variable(&self, cmt: mc::cmt) -> bool { match cmt.cat { mc::cat_local(_) => true, _ => false } } - fn check_assignment(&self, expr: @ast::expr) { + pub fn check_if_path_is_moved(&self, + id: ast::node_id, + span: span, + use_kind: MovedValueUseKind, + lp: @LoanPath) { + /*! + * Reports an error if `expr` (which should be a path) + * is using a moved/uninitialized value + */ + + debug!("check_if_path_is_moved(id=%?, use_kind=%?, lp=%s)", + id, use_kind, lp.repr(self.bccx.tcx)); + for self.move_data.each_move_of(id, lp) |move, moved_lp| { + self.bccx.report_use_of_moved_value( + span, + use_kind, + lp, + move, + moved_lp); + return; + } + } + + pub fn check_assignment(&self, expr: @ast::expr) { // We don't use cat_expr() here because we don't want to treat // auto-ref'd parameters in overloaded operators as rvalues. let cmt = match self.bccx.tcx.adjustments.find(&expr.id) { @@ -316,48 +288,42 @@ pub impl<'self> CheckLoanCtxt<'self> { debug!("check_assignment(cmt=%s)", cmt.repr(self.tcx())); - // check that the value being assigned is declared as mutable - // and report an error otherwise. - match cmt.mutbl { - mc::McDeclared => { - // OK, but we have to mark arguments as requiring mut - // if they are assigned (other cases are handled by liveness, - // since we need to distinguish local variables assigned - // once vs those assigned multiple times) - match cmt.cat { - mc::cat_self(*) | - mc::cat_arg(*) => { - mark_variable_as_used_mut(self, cmt); - } - _ => {} + // Mutable values can be assigned, as long as they obey loans + // and aliasing restrictions: + if cmt.mutbl.is_mutable() { + if check_for_aliasable_mutable_writes(self, expr, cmt) { + if check_for_assignment_to_restricted_or_frozen_location( + self, expr, cmt) + { + // Safe, but record for lint pass later: + mark_variable_as_used_mut(self, cmt); } } - mc::McInherited => { - // OK, but we may have to add an entry to `used_mut_nodes` - mark_variable_as_used_mut(self, cmt); - } - mc::McReadOnly | mc::McImmutable => { - // Subtle: liveness guarantees that immutable local - // variables are only assigned once, so no need to - // report an error for an assignment to a local - // variable (note also that it is not legal to borrow - // for a local variable before it has been assigned - // for the first time). - if !self.is_local_variable(cmt) { - self.bccx.span_err( - expr.span, - fmt!("cannot assign to %s %s" - cmt.mutbl.to_user_str(), - self.bccx.cmt_to_str(cmt))); - } + return; + } + + // For immutable local variables, assignments are legal + // if they cannot already have been assigned + if self.is_local_variable(cmt) { + assert!(cmt.mutbl.is_immutable()); // no "const" locals + let lp = opt_loan_path(cmt).get(); + for self.move_data.each_assignment_of(expr.id, lp) |assign| { + self.bccx.report_reassigned_immutable_variable( + expr.span, + lp, + assign); return; } + return; } - if check_for_aliasable_mutable_writes(self, expr, cmt) { - check_for_assignment_to_restricted_or_frozen_location( - self, expr, cmt); - } + // Otherwise, just a plain error. + self.bccx.span_err( + expr.span, + fmt!("cannot assign to %s %s" + cmt.mutbl.to_user_str(), + self.bccx.cmt_to_str(cmt))); + return; fn mark_variable_as_used_mut(this: &CheckLoanCtxt, cmt: mc::cmt) { @@ -400,6 +366,7 @@ pub impl<'self> CheckLoanCtxt<'self> { cmt = b; } + mc::cat_downcast(b) | mc::cat_interior(b, _) => { if cmt.mutbl == mc::McInherited { cmt = b; @@ -567,10 +534,10 @@ pub impl<'self> CheckLoanCtxt<'self> { } } - fn report_illegal_mutation(&self, - expr: @ast::expr, - loan_path: &LoanPath, - loan: &Loan) { + pub fn report_illegal_mutation(&self, + expr: @ast::expr, + loan_path: &LoanPath, + loan: &Loan) { self.bccx.span_err( expr.span, fmt!("cannot assign to `%s` because it is borrowed", @@ -581,7 +548,7 @@ pub impl<'self> CheckLoanCtxt<'self> { self.bccx.loan_path_to_str(loan_path))); } - fn check_move_out_from_expr(&self, ex: @ast::expr) { + pub fn check_move_out_from_expr(&self, ex: @ast::expr) { match ex.node { ast::expr_paren(*) => { /* In the case of an expr_paren(), the expression inside @@ -592,18 +559,12 @@ pub impl<'self> CheckLoanCtxt<'self> { let cmt = self.bccx.cat_expr(ex); match self.analyze_move_out_from_cmt(cmt) { MoveOk => {} - MoveFromIllegalCmt(_) => { - self.bccx.span_err( - cmt.span, - fmt!("cannot move out of %s", - self.bccx.cmt_to_str(cmt))); - } - MoveWhileBorrowed(loan_path, loan_span) => { + MoveWhileBorrowed(move_path, loan_path, loan_span) => { self.bccx.span_err( cmt.span, fmt!("cannot move out of `%s` \ because it is borrowed", - self.bccx.loan_path_to_str(loan_path))); + self.bccx.loan_path_to_str(move_path))); self.bccx.span_note( loan_span, fmt!("borrow of `%s` occurs here", @@ -614,30 +575,8 @@ pub impl<'self> CheckLoanCtxt<'self> { } } - fn analyze_move_out_from_cmt(&self, cmt: mc::cmt) -> MoveError { - debug!("check_move_out_from_cmt(cmt=%s)", cmt.repr(self.tcx())); - - match cmt.cat { - // Rvalues, locals, and arguments can be moved: - mc::cat_rvalue | mc::cat_local(_) | - mc::cat_arg(_) | mc::cat_self(_) => {} - - // It seems strange to allow a move out of a static item, - // but what happens in practice is that you have a - // reference to a constant with a type that should be - // moved, like `None::<~int>`. The type of this constant - // is technically `Option<~int>`, which moves, but we know - // that the content of static items will never actually - // contain allocated pointers, so we can just memcpy it. - mc::cat_static_item => {} - - mc::cat_deref(_, _, mc::unsafe_ptr(*)) => {} - - // Nothing else. - _ => { - return MoveFromIllegalCmt(cmt); - } - } + pub fn analyze_move_out_from_cmt(&self, cmt: mc::cmt) -> MoveError { + debug!("analyze_move_out_from_cmt(cmt=%s)", cmt.repr(self.tcx())); // FIXME(#4384) inadequare if/when we permit `move a.b` @@ -645,20 +584,19 @@ pub impl<'self> CheckLoanCtxt<'self> { for opt_loan_path(cmt).each |&lp| { for self.each_in_scope_restriction(cmt.id, lp) |loan, _| { // Any restriction prevents moves. - return MoveWhileBorrowed(loan.loan_path, loan.span); + return MoveWhileBorrowed(lp, loan.loan_path, loan.span); } } return MoveOk; } - fn check_call(&mut self, - _expr: @ast::expr, - _callee: Option<@ast::expr>, - _callee_id: ast::node_id, - _callee_span: span, - _args: &[@ast::expr]) - { + pub fn check_call(&mut self, + _expr: @ast::expr, + _callee: Option<@ast::expr>, + _callee_id: ast::node_id, + _callee_span: span, + _args: &[@ast::expr]) { // NB: This call to check for conflicting loans is not truly // necessary, because the callee_id never issues new loans. // However, I added it for consistency and lest the system @@ -685,54 +623,53 @@ fn check_loans_in_fn<'a>(fk: &visit::fn_kind, visit::fk_anon(*) | visit::fk_fn_block(*) => { - let fty = ty::node_id_to_type(this.tcx(), id); - let fty_sigil = ty::ty_closure_sigil(fty); - check_moves_from_captured_variables(this, id, fty_sigil); + check_captured_variables(this, id, sp); } } visit::visit_fn(fk, decl, body, sp, id, this, visitor); - fn check_moves_from_captured_variables(this: @mut CheckLoanCtxt, - id: ast::node_id, - fty_sigil: ast::Sigil) { - match fty_sigil { - ast::ManagedSigil | ast::OwnedSigil => { - let cap_vars = this.bccx.capture_map.get(&id); - for cap_vars.each |cap_var| { - match cap_var.mode { - moves::CapRef | moves::CapCopy => { loop; } - moves::CapMove => { } - } - let def_id = ast_util::def_id_of_def(cap_var.def).node; - let ty = ty::node_id_to_type(this.tcx(), def_id); - let cmt = this.bccx.cat_def(id, cap_var.span, - ty, cap_var.def); - let move_err = this.analyze_move_out_from_cmt(cmt); - match move_err { - MoveOk => {} - MoveFromIllegalCmt(move_cmt) => { - this.bccx.span_err( - cap_var.span, - fmt!("illegal by-move capture of %s", - this.bccx.cmt_to_str(move_cmt))); - } - MoveWhileBorrowed(loan_path, loan_span) => { - this.bccx.span_err( - cap_var.span, - fmt!("cannot move `%s` into closure \ - because it is borrowed", - this.bccx.loan_path_to_str(loan_path))); - this.bccx.span_note( - loan_span, - fmt!("borrow of `%s` occurs here", - this.bccx.loan_path_to_str(loan_path))); - } - } + fn check_captured_variables(this: @mut CheckLoanCtxt, + closure_id: ast::node_id, + span: span) { + let cap_vars = this.bccx.capture_map.get(&closure_id); + for cap_vars.each |cap_var| { + match cap_var.mode { + moves::CapRef | moves::CapCopy => { + let var_id = ast_util::def_id_of_def(cap_var.def).node; + let lp = @LpVar(var_id); + this.check_if_path_is_moved(closure_id, span, + MovedInCapture, lp); + } + moves::CapMove => { + check_by_move_capture(this, closure_id, cap_var); + } + } + } + return; + + fn check_by_move_capture(this: @mut CheckLoanCtxt, + closure_id: ast::node_id, + cap_var: &moves::CaptureVar) { + let var_id = ast_util::def_id_of_def(cap_var.def).node; + let ty = ty::node_id_to_type(this.tcx(), var_id); + let cmt = this.bccx.cat_def(closure_id, cap_var.span, + ty, cap_var.def); + let move_err = this.analyze_move_out_from_cmt(cmt); + match move_err { + MoveOk => {} + MoveWhileBorrowed(move_path, loan_path, loan_span) => { + this.bccx.span_err( + cap_var.span, + fmt!("cannot move `%s` into closure \ + because it is borrowed", + this.bccx.loan_path_to_str(move_path))); + this.bccx.span_note( + loan_span, + fmt!("borrow of `%s` occurs here", + this.bccx.loan_path_to_str(loan_path))); } } - - ast::BorrowedSigil => {} } } } @@ -746,11 +683,11 @@ fn check_loans_in_local<'a>(local: @ast::local, fn check_loans_in_expr<'a>(expr: @ast::expr, this: @mut CheckLoanCtxt<'a>, vt: visit::vt<@mut CheckLoanCtxt<'a>>) { + visit::visit_expr(expr, this, vt); + debug!("check_loans_in_expr(expr=%s)", expr.repr(this.tcx())); - visit::visit_expr(expr, this, vt); - this.check_for_conflicting_loans(expr.id); if this.bccx.moves_map.contains(&expr.id) { @@ -758,32 +695,43 @@ fn check_loans_in_expr<'a>(expr: @ast::expr, } match expr.node { + ast::expr_self | + ast::expr_path(*) => { + if !this.move_data.is_assignee(expr.id) { + let cmt = this.bccx.cat_expr_unadjusted(expr); + debug!("path cmt=%s", cmt.repr(this.tcx())); + for opt_loan_path(cmt).each |&lp| { + this.check_if_path_is_moved(expr.id, expr.span, + MovedInUse, lp); + } + } + } ast::expr_assign(dest, _) | - ast::expr_assign_op(_, dest, _) => { + ast::expr_assign_op(_, _, dest, _) => { this.check_assignment(dest); } ast::expr_call(f, ref args, _) => { this.check_call(expr, Some(f), f.id, f.span, *args); } - ast::expr_method_call(_, _, _, ref args, _) => { - this.check_call(expr, None, expr.callee_id, expr.span, *args); + ast::expr_method_call(callee_id, _, _, _, ref args, _) => { + this.check_call(expr, None, callee_id, expr.span, *args); } - ast::expr_index(_, rval) | - ast::expr_binary(_, _, rval) + ast::expr_index(callee_id, _, rval) | + ast::expr_binary(callee_id, _, _, rval) if this.bccx.method_map.contains_key(&expr.id) => { this.check_call(expr, None, - expr.callee_id, + callee_id, expr.span, - ~[rval]); + [rval]); } - ast::expr_unary(*) | ast::expr_index(*) + ast::expr_unary(callee_id, _, _) | ast::expr_index(callee_id, _, _) if this.bccx.method_map.contains_key(&expr.id) => { this.check_call(expr, None, - expr.callee_id, + callee_id, expr.span, - ~[]); + []); } _ => { } } @@ -816,4 +764,3 @@ fn check_loans_in_block<'a>(blk: &ast::blk, visit::visit_block(blk, this, vt); this.check_for_conflicting_loans(blk.node.id); } - diff --git a/src/librustc/middle/borrowck/doc.rs b/src/librustc/middle/borrowck/doc.rs index 1e09fbe71843c..cb3983117e97c 100644 --- a/src/librustc/middle/borrowck/doc.rs +++ b/src/librustc/middle/borrowck/doc.rs @@ -13,13 +13,48 @@ # The Borrow Checker This pass has the job of enforcing memory safety. This is a subtle -topic. The only way I know how to explain it is terms of a formal -model, so that's what I'll do. +topic. This docs aim to explain both the practice and the theory +behind the borrow checker. They start with a high-level overview of +how it works, and then proceed to dive into the theoretical +background. Finally, they go into detail on some of the more subtle +aspects. + +# Table of contents + +These docs are long. Search for the section you are interested in. + +- Overview +- Formal model +- Borrowing and loans +- Moves and initialization +- Future work + +# Overview + +The borrow checker checks one function at a time. It operates in two +passes. The first pass, called `gather_loans`, walks over the function +and identifies all of the places where borrows (e.g., `&` expressions +and `ref` bindings) and moves (copies or captures of a linear value) +occur. It also tracks initialization sites. For each borrow and move, +it checks various basic safety conditions at this time (for example, +that the lifetime of the borrow doesn't exceed the lifetime of the +value being borrowed, or that there is no move out of an `&T` +pointee). + +It then uses the dataflow module to propagate which of those borrows +may be in scope at each point in the procedure. A loan is considered +to come into scope at the expression that caused it and to go out of +scope when the lifetime of the resulting borrowed pointer expires. + +Once the in-scope loans are known for each point in the program, the +borrow checker walks the IR again in a second pass called +`check_loans`. This pass examines each statement and makes sure that +it is safe with respect to the in-scope loans. # Formal model -Let's consider a simple subset of Rust in which you can only borrow -from lvalues like so: +Throughout the docs we'll consider a simple subset of Rust in which +you can only borrow from lvalues, defined like so: LV = x | LV.f | *LV @@ -42,9 +77,11 @@ struct name and we assume structs are declared like so: SD = struct S<'LT...> { (f: TY)... } -# An intuitive explanation +# Borrowing and loans -## Issuing loans +## An intuitive explanation + +### Issuing loans Now, imagine we had a program like this: @@ -60,691 +97,766 @@ This is of course dangerous because mutating `x` will free the old value and hence invalidate `y`. The borrow checker aims to prevent this sort of thing. -### Loans +#### Loans and restrictions The way the borrow checker works is that it analyzes each borrow expression (in our simple model, that's stuff like `&LV`, though in real life there are a few other cases to consider). For each borrow -expression, it computes a vector of loans: - - LOAN = (LV, LT, PT, LK) - PT = Partial | Total - LK = MQ | RESERVE - -Each `LOAN` tuple indicates some sort of restriction on what can be -done to the lvalue `LV`; `LV` will always be a path owned by the -current stack frame. These restrictions are called "loans" because -they are always the result of a borrow expression. - -Every loan has a lifetime `LT` during which those restrictions are in -effect. The indicator `PT` distinguishes between *total* loans, in -which the LV itself was borrowed, and *partial* loans, which means -that some content ownwed by LV was borrowed. - -The final element in the loan tuple is the *loan kind* `LK`. There -are four kinds: mutable, immutable, const, and reserve: - -- A "mutable" loan means that LV may be written to through an alias, and - thus LV cannot be written to directly or immutably aliased (remember - that we preserve the invariant that any given value can only be - written to through one path at a time; hence if there is a mutable - alias to LV, then LV cannot be written directly until this alias is - out of scope). - -- An "immutable" loan means that LV must remain immutable. Hence it - cannot be written, but other immutable aliases are permitted. - -- A "const" loan means that an alias to LV exists. LV may still be - written or frozen. - -- A "reserve" loan is the strongest case. It prevents both mutation - and aliasing of any kind, including `&const` loans. Reserve loans - are a side-effect of borrowing an `&mut` loan. - -In addition to affecting mutability, a loan of any kind implies that -LV cannot be moved. - -### Example - -To give you a better feeling for what a loan is, let's look at three -loans that would be issued as a result of the borrow `&(*x).f` in the -example above: - - ((*x).f, Total, mut, 'a) - (*x, Partial, mut, 'a) - (x, Partial, mut, 'a) - -The first loan states that the expression `(*x).f` has been loaned -totally as mutable for the lifetime `'a`. This first loan would -prevent an assignment `(*x).f = ...` from occurring during the -lifetime `'a`. - -Now let's look at the second loan. You may have expected that each -borrow would result in only one loan. But this is not the case. -Instead, there will be loans for every path where mutation might -affect the validity of the borrowed pointer that is created (in some -cases, there can even be multiple loans per path, see the section on -"Borrowing in Calls" below for the gory details). The reason for this -is to prevent actions that would indirectly affect the borrowed path. -In this case, we wish to ensure that `(*x).f` is not mutated except -through the mutable alias `y`. Therefore, we must not only prevent an -assignment to `(*x).f` but also an assignment like `*x = Foo {...}`, -as this would also mutate the field `f`. To do so, we issue a -*partial* mutable loan for `*x` (the loan is partial because `*x` -itself was not borrowed). This partial loan will cause any attempt to -assign to `*x` to be flagged as an error. - -Because both partial and total loans prevent assignments, you may -wonder why we bother to distinguish between them. The reason for this -distinction has to do with preventing double borrows. In particular, -it is legal to borrow both `&mut x.f` and `&mut x.g` simultaneously, -but it is not legal to borrow `&mut x.f` twice. In the borrow checker, -the first case would result in two *partial* mutable loans of `x` -(along with one total mutable loan of `x.f` and one of `x.g) whereas -the second would result in two *total* mutable loans of `x.f` (along -with two partial mutable loans of `x`). Multiple *total mutable* loan -for the same path are not permitted, but multiple *partial* loans (of -any mutability) are permitted. - -Finally, we come to the third loan. This loan is a partial mutable -loan of `x`. This loan prevents us from reassigning `x`, which would -be bad for two reasons. First, it would change the value of `(*x).f` -but, even worse, it would cause the pointer `y` to become a dangling -pointer. Bad all around. - -## Checking for illegal assignments, moves, and reborrows +expression, it computes a `Loan`, which is a data structure that +records (1) the value being borrowed, (2) the mutability and scope of +the borrow, and (3) a set of restrictions. In the code, `Loan` is a +struct defined in `middle::borrowck`. Formally, we define `LOAN` as +follows: + + LOAN = (LV, LT, MQ, RESTRICTION*) + RESTRICTION = (LV, ACTION*) + ACTION = MUTATE | CLAIM | FREEZE | ALIAS + +Here the `LOAN` tuple defines the lvalue `LV` being borrowed; the +lifetime `LT` of that borrow; the mutability `MQ` of the borrow; and a +list of restrictions. The restrictions indicate actions which, if +taken, could invalidate the loan and lead to type safety violations. + +Each `RESTRICTION` is a pair of a restrictive lvalue `LV` (which will +either be the path that was borrowed or some prefix of the path that +was borrowed) and a set of restricted actions. There are three kinds +of actions that may be restricted for the path `LV`: + +- `MUTATE` means that `LV` cannot be assigned to; +- `CLAIM` means that the `LV` cannot be borrowed mutably; +- `FREEZE` means that the `LV` cannot be borrowed immutably; +- `ALIAS` means that `LV` cannot be aliased in any way (not even `&const`). + +Finally, it is never possible to move from an lvalue that appears in a +restriction. This implies that the "empty restriction" `(LV, [])`, +which contains an empty set of actions, still has a purpose---it +prevents moves from `LV`. I chose not to make `MOVE` a fourth kind of +action because that would imply that sometimes moves are permitted +from restrictived values, which is not the case. + +#### Example + +To give you a better feeling for what kind of restrictions derived +from a loan, let's look at the loan `L` that would be issued as a +result of the borrow `&mut (*x).f` in the example above: + + L = ((*x).f, 'a, mut, RS) where + RS = [((*x).f, [MUTATE, CLAIM, FREEZE]), + (*x, [MUTATE, CLAIM, FREEZE]), + (x, [MUTATE, CLAIM, FREEZE])] + +The loan states that the expression `(*x).f` has been loaned as +mutable for the lifetime `'a`. Because the loan is mutable, that means +that the value `(*x).f` may be mutated via the newly created borrowed +pointer (and *only* via that pointer). This is reflected in the +restrictions `RS` that accompany the loan. + +The first restriction `((*x).f, [MUTATE, CLAIM, FREEZE])` states that +the lender may not mutate nor freeze `(*x).f`. Mutation is illegal +because `(*x).f` is only supposed to be mutated via the new borrowed +pointer, not by mutating the original path `(*x).f`. Freezing is +illegal because the path now has an `&mut` alias; so even if we the +lender were to consider `(*x).f` to be immutable, it might be mutated +via this alias. Both of these restrictions are temporary. They will be +enforced for the lifetime `'a` of the loan. After the loan expires, +the restrictions no longer apply. + +The second restriction on `*x` is interesting because it does not +apply to the path that was lent (`(*x).f`) but rather to a prefix of +the borrowed path. This is due to the rules of inherited mutability: +if the user were to assign to (or freeze) `*x`, they would indirectly +overwrite (or freeze) `(*x).f`, and thus invalidate the borrowed +pointer that was created. In general it holds that when a path is +lent, restrictions are issued for all the owning prefixes of that +path. In this case, the path `*x` owns the path `(*x).f` and, +because `x` is an owned pointer, the path `x` owns the path `*x`. +Therefore, borrowing `(*x).f` yields restrictions on both +`*x` and `x`. + +### Checking for illegal assignments, moves, and reborrows Once we have computed the loans introduced by each borrow, the borrow -checker will determine the full set of loans in scope at each -expression and use that to decide whether that expression is legal. -Remember that the scope of loan is defined by its lifetime LT. We -sometimes say that a loan which is in-scope at a particular point is -an "outstanding loan". - -The kinds of expressions which in-scope loans can render illegal are -*assignments*, *moves*, and *borrows*. - -An assignments to an lvalue LV is illegal if there is in-scope mutable -or immutable loan for LV. Assignment with an outstanding mutable loan -is illegal because then the `&mut` pointer is supposed to be the only -way to mutate the value. Assignment with an outstanding immutable -loan is illegal because the value is supposed to be immutable at that -point. - -A move from an lvalue LV is illegal if there is any sort of -outstanding loan. - -A borrow expression may be illegal if any of the loans which it -produces conflict with other outstanding loans. Two loans are -considered compatible if one of the following conditions holds: - -- At least one loan is a const loan. -- Both loans are partial loans. -- Both loans are immutable. - -Any other combination of loans is illegal. - -# The set of loans that results from a borrow expression - -Here we'll define four functions---MUTATE, FREEZE, ALIAS, and -TAKE---which are all used to compute the set of LOANs that result -from a borrow expression. The first three functions each have -a similar type signature: - - MUTATE(LV, LT, PT) -> LOANS - FREEZE(LV, LT, PT) -> LOANS - ALIAS(LV, LT, PT) -> LOANS - -MUTATE, FREEZE, and ALIAS are used when computing the loans result -from mutable, immutable, and const loans respectively. For example, -the loans resulting from an expression like `&mut (*x).f` would be -computed by `MUTATE((*x).f, LT, Total)`, where `LT` is the lifetime of -the resulting pointer. Similarly the loans for `&(*x).f` and `&const -(*x).f` would be computed by `FREEZE((*x).f, LT, Total)` and -`ALIAS((*x).f, LT, Total)` respectively. (Actually this is a slight -simplification; see the section below on Borrows in Calls for the full -gory details) - -The names MUTATE, FREEZE, and ALIAS are intended to suggest the -semantics of `&mut`, `&`, and `&const` borrows respectively. `&mut`, -for example, creates a mutable alias of LV. `&` causes the borrowed -value to be frozen (immutable). `&const` does neither but does -introduce an alias to be the borrowed value. - -Each of these three functions is only defined for some inputs. That -is, it may occur that some particular borrow is not legal. For -example, it is illegal to make an `&mut` loan of immutable data. In -that case, the MUTATE() function is simply not defined (in the code, -it returns a Result<> condition to indicate when a loan would be -illegal). - -The final function, RESERVE, is used as part of borrowing an `&mut` -pointer. Due to the fact that it is used for one very particular -purpose, it has a rather simpler signature than the others: - - RESERVE(LV, LT) -> LOANS - -It is explained when we come to that case. - -## The function MUTATE() - -Here we use [inference rules][ir] to define the MUTATE() function. -We will go case by case for the various kinds of lvalues that -can be borrowed. - -[ir]: http://en.wikipedia.org/wiki/Rule_of_inference - -### Mutating local variables - -The rule for mutating local variables is as follows: - - Mutate-Variable: - LT <= Scope(x) - Mut(x) = Mut - -------------------------------------------------- - MUTATE(x, LT, PT) = (x, LT, PT, mut) - -Here `Scope(x)` is the lifetime of the block in which `x` was declared -and `Mut(x)` indicates the mutability with which `x` was declared. -This rule simply states that you can only create a mutable alias -to a variable if it is mutable, and that alias cannot outlive the -stack frame in which the variable is declared. - -### Mutating fields and owned pointers - -As it turns out, the rules for mutating fields and mutating owned -pointers turn out to be quite similar. The reason is that the -expressions `LV.f` and `*LV` are both owned by their base expression -`LV`. So basically the result of mutating `LV.f` or `*LV` is computed -by adding a loan for `LV.f` or `*LV` and then the loans for a partial -take of `LV`: - - Mutate-Field: - MUTATE(LV, LT, Partial) = LOANS - ------------------------------------------------------------ - MUTATE(LV.f, LT, PT) = LOANS, (LV.F, LT, PT, mut) - - Mutate-Owned-Ptr: - Type(LV) = ~Ty - MUTATE(LV, LT, Partial) = LOANS - ------------------------------------------------------------ - MUTATE(*LV, LT, PT) = LOANS, (*LV, LT, PT, mut) - -Note that while our micro-language only has fields, the slight -variations on the `Mutate-Field` rule are used for any interior content -that appears in the full Rust language, such as the contents of a -tuple, fields in a struct, or elements of a fixed-length vector. - -### Mutating dereferenced borrowed pointers - -The rule for borrowed pointers is by far the most complicated: - - Mutate-Mut-Borrowed-Ptr: - Type(LV) = <_P mut Ty // (1) - LT <= LT_P // (2) - RESERVE(LV, LT) = LOANS // (3) - ------------------------------------------------------------ - MUTATE(*LV, LT, PT) = LOANS, (*LV, LT, PT, Mut) - -Condition (1) states that only a mutable borrowed pointer can be -taken. Condition (2) states that the lifetime of the alias must be -less than the lifetime of the borrowed pointer being taken. - -Conditions (3) and (4) are where things get interesting. The intended -semantics of the borrow is that the new `&mut` pointer is the only one -which has the right to modify the data; the original `&mut` pointer -must not be used for mutation. Because borrowed pointers do not own -their content nor inherit mutability, we must be particularly cautious -of aliases, which could permit the original borrowed pointer to be -reached from another path and thus circumvent our loans. - -Here is one example of what could go wrong if we ignore clause (4): - - let x: &mut T; - ... - let y = &mut *x; // Only *y should be able to mutate... - let z = &const x; - **z = ...; // ...but here **z is still able to mutate! +checker uses a data flow propagation to compute the full set of loans +in scope at each expression and then uses that set to decide whether +that expression is legal. Remember that the scope of loan is defined +by its lifetime LT. We sometimes say that a loan which is in-scope at +a particular point is an "outstanding loan", aand the set of +restrictions included in those loans as the "outstanding +restrictions". + +The kinds of expressions which in-scope loans can render illegal are: +- *assignments* (`lv = v`): illegal if there is an in-scope restriction + against mutating `lv`; +- *moves*: illegal if there is any in-scope restriction on `lv` at all; +- *mutable borrows* (`&mut lv`): illegal there is an in-scope restriction + against mutating `lv` or aliasing `lv`; +- *immutable borrows* (`&lv`): illegal there is an in-scope restriction + against freezing `lv` or aliasing `lv`; +- *read-only borrows* (`&const lv`): illegal there is an in-scope restriction + against aliasing `lv`. -Another possible error could occur with moves: +## Formal rules - let x: &mut T; - ... - let y = &mut *x; // Issues loan: (*x, LT, Total, Mut) - let z = x; // moves from x - *z = ...; // Mutates *y indirectly! Bad. - -In both of these cases, the problem is that when creating the alias -`y` we would only issue a loan preventing assignment through `*x`. -But this loan can be easily circumvented by moving from `x` or -aliasing it. Note that, in the first example, the alias of `x` was -created using `&const`, which is a particularly weak form of alias. - -The danger of aliases can also occur when the `&mut` pointer itself -is already located in an alias location, as here: - - let x: @mut &mut T; // or &mut &mut T, &&mut T, - ... // &const &mut T, @&mut T, etc - let y = &mut **x; // Only *y should be able to mutate... - let z = x; - **z = ...; // ...but here **z is still able to mutate! - -When we cover the rules for RESERVE, we will see that it would -disallow this case, because MUTATE can only be applied to canonical -lvalues which are owned by the current stack frame. - -It might be the case that if `&const` and `@const` pointers were -removed, we could do away with RESERVE and simply use MUTATE instead. -But we have to be careful about the final example in particular, since -dynamic freezing would not be sufficient to prevent this example. -Perhaps a combination of MUTATE with a predicate OWNED(LV). - -One final detail: unlike every other case, when we calculate the loans -using RESERVE we do not use the original lifetime `LT` but rather -`GLB(Scope(LV), LT)`. What this says is: - -### Mutating dereferenced managed pointers - -Because the correctness of managed pointer loans is checked dynamically, -the rule is quite simple: - - Mutate-Mut-Managed-Ptr: - Type(LV) = @mut Ty - Add ROOT-FREEZE annotation for *LV with lifetime LT - ------------------------------------------------------------ - MUTATE(*LV, LT, Total) = [] - -No loans are issued. Instead, we add a side annotation that causes -`*LV` to be rooted and frozen on entry to LV. You could rephrase -these rules as having multiple returns values, or rephrase this as a -kind of loan, but whatever. - -One interesting point is that *partial takes* of `@mut` are forbidden. -This is not for any soundness reason but just because it is clearer -for users when `@mut` values are either lent completely or not at all. - -## The function FREEZE - -The rules for FREEZE are pretty similar to MUTATE. The first four -cases I'll just present without discussion, as the reasoning is -quite analogous to the MUTATE case: - - Freeze-Variable: - LT <= Scope(x) - -------------------------------------------------- - FREEZE(x, LT, PT) = (x, LT, PT, imm) - - Freeze-Field: - FREEZE(LV, LT, Partial) = LOANS - ------------------------------------------------------------ - FREEZE(LV.f, LT, PT) = LOANS, (LV.F, LT, PT, imm) - - Freeze-Owned-Ptr: - Type(LV) = ~Ty - FREEZE(LV, LT, Partial) = LOANS - ------------------------------------------------------------ - FREEZE(*LV, LT, PT) = LOANS, (*LV, LT, PT, imm) - - Freeze-Mut-Borrowed-Ptr: - Type(LV) = <_P mut Ty - LT <= LT_P - RESERVE(LV, LT) = LOANS - ------------------------------------------------------------ - FREEZE(*LV, LT, PT) = LOANS, (*LV, LT, PT, Imm) - - Freeze-Mut-Managed-Ptr: - Type(LV) = @mut Ty - Add ROOT-FREEZE annotation for *LV with lifetime LT - ------------------------------------------------------------ - Freeze(*LV, LT, Total) = [] - -The rule to "freeze" an immutable borrowed pointer is quite -simple, since the content is already immutable: - - Freeze-Imm-Borrowed-Ptr: - Type(LV) = <_P Ty // (1) - LT <= LT_P // (2) - ------------------------------------------------------------ - FREEZE(*LV, LT, PT) = LOANS, (*LV, LT, PT, Mut) - -The final two rules pertain to borrows of `@Ty`. There is a bit of -subtlety here. The main problem is that we must guarantee that the -managed box remains live for the entire borrow. We can either do this -dynamically, by rooting it, or (better) statically, and hence there -are two rules: - - Freeze-Imm-Managed-Ptr-1: - Type(LV) = @Ty - Add ROOT annotation for *LV - ------------------------------------------------------------ - FREEZE(*LV, LT, PT) = [] - - Freeze-Imm-Managed-Ptr-2: - Type(LV) = @Ty - LT <= Scope(LV) - Mut(LV) = imm - LV is not moved - ------------------------------------------------------------ - FREEZE(*LV, LT, PT) = [] - -The intention of the second rule is to avoid an extra root if LV -serves as a root. In that case, LV must (1) outlive the borrow; (2) -be immutable; and (3) not be moved. - -## The ALIAS function - -The function ALIAS is used for `&const` loans but also to handle one -corner case concerning function arguments (covered in the section -"Borrows in Calls" below). It computes the loans that result from -observing that there is a pointer to `LV` and thus that pointer must -remain valid. - -The first two rules are simple: - - Alias-Variable: - LT <= Scope(x) - -------------------------------------------------- - ALIAS(x, LT, PT) = (x, LT, PT, Const) - - Alias-Field: - ALIAS(LV, LT, Partial) = LOANS - ------------------------------------------------------------ - ALIAS(LV.f, LT, PT) = LOANS, (LV.F, LT, PT, Const) - -### Aliasing owned pointers - -The rule for owned pointers is somewhat interesting: - - Alias-Owned-Ptr: - Type(LV) = ~Ty - FREEZE(LV, LT, Partial) = LOANS - ------------------------------------------------------------ - ALIAS(*LV, LT, PT) = LOANS, (*LV, LT, PT, Const) - -Here we *freeze* the base `LV`. The reason is that if an owned -pointer is mutated it frees its content, which means that the alias to -`*LV` would become a dangling pointer. - -### Aliasing borrowed pointers - -The rule for borrowed pointers is quite simple, because borrowed -pointers do not own their content and thus do not play a role in -keeping it live: - - Alias-Borrowed-Ptr: - Type(LV) = <_P MQ Ty - LT <= LT_P - ------------------------------------------------------------ - ALIAS(*LV, LT, PT) = [] - -Basically, the existence of a borrowed pointer to some memory with -lifetime LT_P is proof that the memory can safely be aliased for any -lifetime LT <= LT_P. - -### Aliasing managed pointers - -The rules for aliasing managed pointers are similar to those -used with FREEZE, except that they apply to all manager pointers -regardles of mutability: - - Alias-Managed-Ptr-1: - Type(LV) = @MQ Ty - Add ROOT annotation for *LV - ------------------------------------------------------------ - ALIAS(*LV, LT, PT) = [] - - Alias-Managed-Ptr-2: - Type(LV) = @MQ Ty - LT <= Scope(LV) - Mut(LV) = imm - LV is not moved - ------------------------------------------------------------ - ALIAS(*LV, LT, PT) = [] - -## The RESERVE function - -The final function, RESERVE, is used for loans of `&mut` pointers. As -discussed in the section on the function MUTATE, we must be quite -careful when "re-borrowing" an `&mut` pointer to ensure that the original -`&mut` pointer can no longer be used to mutate. - -There are a couple of dangers to be aware of: - -- `&mut` pointers do not inherit mutability. Therefore, if you have - an lvalue LV with type `&mut T` and you freeze `LV`, you do *not* - freeze `*LV`. This is quite different from an `LV` with type `~T`. - -- Also, because they do not inherit mutability, if the `&mut` pointer - lives in an aliased location, then *any alias* can be used to write! - -As a consequence of these two rules, RESERVE can only be successfully -invoked on an lvalue LV that is *owned by the current stack frame*. -This ensures that there are no aliases that are not visible from the -outside. Moreover, Reserve loans are incompatible with all other -loans, even Const loans. This prevents any aliases from being created -within the current function. +Now that we hopefully have some kind of intuitive feeling for how the +borrow checker works, let's look a bit more closely now at the precise +conditions that it uses. For simplicity I will ignore const loans. -### Reserving local variables +I will present the rules in a modified form of standard inference +rules, which looks as as follows: -The rule for reserving a variable is generally straightforward but -with one interesting twist: + PREDICATE(X, Y, Z) // Rule-Name + Condition 1 + Condition 2 + Condition 3 + +The initial line states the predicate that is to be satisfied. The +indented lines indicate the conditions that must be met for the +predicate to be satisfied. The right-justified comment states the name +of this rule: there are comments in the borrowck source referencing +these names, so that you can cross reference to find the actual code +that corresponds to the formal rule. + +### The `gather_loans` pass - Reserve-Variable: - -------------------------------------------------- - RESERVE(x, LT) = (x, LT, Total, Reserve) +We start with the `gather_loans` pass, which walks the AST looking for +borrows. For each borrow, there are three bits of information: the +lvalue `LV` being borrowed and the mutability `MQ` and lifetime `LT` +of the resulting pointer. Given those, `gather_loans` applies three +validity tests: -The twist here is that the incoming lifetime is not required to -be a subset of the incoming variable, unlike every other case. To -see the reason for this, imagine the following function: +1. `MUTABILITY(LV, MQ)`: The mutability of the borrowed pointer is +compatible with the mutability of `LV` (i.e., not borrowing immutable +data as mutable). - struct Foo { count: uint } - fn count_field(x: &'a mut Foo) -> &'a mut count { - &mut (*x).count - } +2. `LIFETIME(LV, LT, MQ)`: The lifetime of the borrow does not exceed +the lifetime of the value being borrowed. This pass is also +responsible for inserting root annotations to keep managed values +alive and for dynamically freezing `@mut` boxes. -This function consumes one `&mut` pointer and returns another with the -same lifetime pointing at a particular field. The borrow for the -`&mut` expression will result in a call to `RESERVE(x, 'a)`, which is -intended to guarantee that `*x` is not later aliased or used to -mutate. But the lifetime of `x` is limited to the current function, -which is a sublifetime of the parameter `'a`, so the rules used for -MUTATE, FREEZE, and ALIAS (which require that the lifetime of the loan -not exceed the lifetime of the variable) would result in an error. +3. `RESTRICTIONS(LV, ACTIONS) = RS`: This pass checks and computes the +restrictions to maintain memory safety. These are the restrictions +that will go into the final loan. We'll discuss in more detail below. -Nonetheless this function is perfectly legitimate. After all, the -caller has moved in an `&mut` pointer with lifetime `'a`, and thus has -given up their right to mutate the value for the remainder of `'a`. -So it is fine for us to return a pointer with the same lifetime. +## Checking mutability -The reason that RESERVE differs from the other functions is that -RESERVE is not responsible for guaranteeing that the pointed-to data -will outlive the borrowed pointer being created. After all, `&mut` -values do not own the data they point at. +Checking mutability is fairly straightforward. We just want to prevent +immutable data from being borrowed as mutable. Note that it is ok to +borrow mutable data as immutable, since that is simply a +freeze. Formally we define a predicate `MUTABLE(LV, MQ)` which, if +defined, means that "borrowing `LV` with mutability `MQ` is ok. The +Rust code corresponding to this predicate is the function +`check_mutability` in `middle::borrowck::gather_loans`. -### Reserving owned content +### Checking mutability of variables -The rules for fields and owned pointers are very straightforward: +*Code pointer:* Function `check_mutability()` in `gather_loans/mod.rs`, +but also the code in `mem_categorization`. - Reserve-Field: - RESERVE(LV, LT) = LOANS - ------------------------------------------------------------ - RESERVE(LV.f, LT) = LOANS, (LV.F, LT, Total, Reserve) +Let's begin with the rules for variables, which state that if a +variable is declared as mutable, it may be borrowed any which way, but +otherwise the variable must be borrowed as immutable or const: - Reserve-Owned-Ptr: - Type(LV) = ~Ty - RESERVE(LV, LT) = LOANS - ------------------------------------------------------------ - RESERVE(*LV, LT) = LOANS, (*LV, LT, Total, Reserve) + MUTABILITY(X, MQ) // M-Var-Mut + DECL(X) = mut -### Reserving `&mut` borrowed pointers + MUTABILITY(X, MQ) // M-Var-Imm + DECL(X) = imm + MQ = imm | const -Unlike other borrowed pointers, `&mut` pointers are unaliasable, -so we can reserve them like everything else: +### Checking mutability of owned content - Reserve-Mut-Borrowed-Ptr: - Type(LV) = <_P mut Ty - RESERVE(LV, LT) = LOANS - ------------------------------------------------------------ - RESERVE(*LV, LT) = LOANS, (*LV, LT, Total, Reserve) +Fields and owned pointers inherit their mutability from +their base expressions, so both of their rules basically +delegate the check to the base expression `LV`: -## Borrows in calls + MUTABILITY(LV.f, MQ) // M-Field + MUTABILITY(LV, MQ) -Earlier we said that the MUTATE, FREEZE, and ALIAS functions were used -to compute the loans resulting from a borrow expression. But this is -not strictly correct, there is a slight complication that occurs with -calls by which additional loans may be necessary. We will explain -that here and give the full details. + MUTABILITY(*LV, MQ) // M-Deref-Unique + TYPE(LV) = ~Ty + MUTABILITY(LV, MQ) -Imagine a call expression `'a: E1(E2, E3)`, where `Ei` are some -expressions. If we break this down to something a bit lower-level, it -is kind of short for: +### Checking mutability of immutable pointer types - 'a: { - 'a_arg1: let temp1: ... = E1; - 'a_arg2: let temp2: ... = E2; - 'a_arg3: let temp3: ... = E3; - 'a_call: temp1(temp2, temp3) - } +Immutable pointer types like `&T` and `@T` can only +be borrowed if MQ is immutable or const: -Here the lifetime labels indicate the various lifetimes. As you can -see there are in fact four relevant lifetimes (only one of which was -named by the user): `'a` corresponds to the expression `E1(E2, E3)` as -a whole. `'a_arg1`, `'a_arg2`, and `'a_arg3` correspond to the -evaluations of `E1`, `E2`, and `E3` respectively. Finally, `'a_call` -corresponds to the *actual call*, which is the point where the values -of the parameters will be used. + MUTABILITY(*LV, MQ) // M-Deref-Borrowed-Imm + TYPE(LV) = &Ty + MQ == imm | const -Now, let's look at a (contrived, but representative) example to see -why all this matters: + MUTABILITY(*LV, MQ) // M-Deref-Managed-Imm + TYPE(LV) = @Ty + MQ == imm | const - struct Foo { f: uint, g: uint } - ... - fn add(p: &mut uint, v: uint) { - *p += v; - } - ... - fn inc(p: &mut uint) -> uint { - *p += 1; *p - } - fn weird() { - let mut x: ~Foo = ~Foo { ... }; - 'a: add(&mut (*x).f, - 'b: inc(&mut (*x).f)) // (*) - } +### Checking mutability of mutable pointer types -The important part is the line marked `(*)` which contains a call to -`add()`. The first argument is a mutable borrow of the field `f`. -The second argument *always borrows* the field `f`. Now, if these two -borrows overlapped in time, this would be illegal, because there would -be two `&mut` pointers pointing at `f`. And, in a way, they *do* -overlap in time, since the first argument will be evaluated first, -meaning that the pointer will exist when the second argument executes. -But in another important way they do not overlap in time. Let's -expand out that final call to `add()` as we did before: +`&mut T` and `@mut T` can be frozen, so it is acceptable to borrow +them as either imm or mut: - 'a: { - 'a_arg1: let a_temp1: ... = add; - 'a_arg2: let a_temp2: &'a_call mut uint = &'a_call mut (*x).f; - 'a_arg3_: let a_temp3: uint = { - let b_temp1: ... = inc; - let b_temp2: &'b_call = &'b_call mut (*x).f; - 'b_call: b_temp1(b_temp2) - }; - 'a_call: a_temp1(a_temp2, a_temp3) - } + MUTABILITY(*LV, MQ) // M-Deref-Borrowed-Mut + TYPE(LV) = &mut Ty -When it's written this way, we can see that although there are two -borrows, the first has lifetime `'a_call` and the second has lifetime -`'b_call` and in fact these lifetimes do not overlap. So everything -is fine. + MUTABILITY(*LV, MQ) // M-Deref-Managed-Mut + TYPE(LV) = @mut Ty -But this does not mean that there isn't reason for caution! Imagine a -devious program like *this* one: +## Checking lifetime - struct Foo { f: uint, g: uint } - ... - fn add(p: &mut uint, v: uint) { - *p += v; +These rules aim to ensure that no data is borrowed for a scope that +exceeds its lifetime. In addition, these rules manage the rooting and +dynamic freezing of `@` and `@mut` values. These two computations wind +up being intimately related. Formally, we define a predicate +`LIFETIME(LV, LT, MQ)`, which states that "the lvalue `LV` can be +safely borrowed for the lifetime `LT` with mutability `MQ`". The Rust +code corresponding to this predicate is the module +`middle::borrowck::gather_loans::lifetime`. + +### The Scope function + +Several of the rules refer to a helper function `SCOPE(LV)=LT`. The +`SCOPE(LV)` yields the lifetime `LT` for which the lvalue `LV` is +guaranteed to exist, presuming that no mutations occur. + +The scope of a local variable is the block where it is declared: + + SCOPE(X) = block where X is declared + +The scope of a field is the scope of the struct: + + SCOPE(LV.f) = SCOPE(LV) + +The scope of a unique pointee is the scope of the pointer, since +(barring mutation or moves) the pointer will not be freed until +the pointer itself `LV` goes out of scope: + + SCOPE(*LV) = SCOPE(LV) if LV has type ~T + +The scope of a managed pointee is also the scope of the pointer. This +is a conservative approximation, since there may be other aliases fo +that same managed box that would cause it to live longer: + + SCOPE(*LV) = SCOPE(LV) if LV has type @T or @mut T + +The scope of a borrowed pointee is the scope associated with the +pointer. This is a conservative approximation, since the data that +the pointer points at may actually live longer: + + SCOPE(*LV) = LT if LV has type &'LT T or &'LT mut T + +### Checking lifetime of variables + +The rule for variables states that a variable can only be borrowed a +lifetime `LT` that is a subregion of the variable's scope: + + LIFETIME(X, LT, MQ) // L-Local + LT <= SCOPE(X) + +### Checking lifetime for owned content + +The lifetime of a field or owned pointer is the same as the lifetime +of its owner: + + LIFETIME(LV.f, LT, MQ) // L-Field + LIFETIME(LV, LT, MQ) + + LIFETIME(*LV, LT, MQ) // L-Deref-Owned + TYPE(LV) = ~Ty + LIFETIME(LV, LT, MQ) + +### Checking lifetime for derefs of borrowed pointers + +Borrowed pointers have a lifetime `LT'` associated with them. The +data they point at has been guaranteed to be valid for at least this +lifetime. Therefore, the borrow is valid so long as the lifetime `LT` +of the borrow is shorter than the lifetime `LT'` of the pointer +itself: + + LIFETIME(*LV, LT, MQ) // L-Deref-Borrowed + TYPE(LV) = <' Ty OR <' mut Ty + LT <= LT' + +### Checking lifetime for derefs of managed, immutable pointers + +Managed pointers are valid so long as the data within them is +*rooted*. There are two ways that this can be achieved. The first is +when the user guarantees such a root will exist. For this to be true, +three conditions must be met: + + LIFETIME(*LV, LT, MQ) // L-Deref-Managed-Imm-User-Root + TYPE(LV) = @Ty + LT <= SCOPE(LV) // (1) + LV is immutable // (2) + LV is not moved or not movable // (3) + +Condition (1) guarantees that the managed box will be rooted for at +least the lifetime `LT` of the borrow, presuming that no mutation or +moves occur. Conditions (2) and (3) then serve to guarantee that the +value is not mutated or moved. Note that lvalues are either +(ultimately) owned by a local variable, in which case we can check +whether that local variable is ever moved in its scope, or they are +owned by the pointee of an (immutable, due to condition 2) managed or +borrowed pointer, in which case moves are not permitted because the +location is aliasable. + +If the conditions of `L-Deref-Managed-Imm-User-Root` are not met, then +there is a second alternative. The compiler can attempt to root the +managed pointer itself. This permits great flexibility, because the +location `LV` where the managed pointer is found does not matter, but +there are some limitations. The lifetime of the borrow can only extend +to the innermost enclosing loop or function body. This guarantees that +the compiler never requires an unbounded amount of stack space to +perform the rooting; if this condition were violated, the compiler +might have to accumulate a list of rooted objects, for example if the +borrow occurred inside the body of a loop but the scope of the borrow +extended outside the loop. More formally, the requirement is that +there is no path starting from the borrow that leads back to the +borrow without crossing the exit from the scope `LT`. + +The rule for compiler rooting is as follows: + + LIFETIME(*LV, LT, MQ) // L-Deref-Managed-Imm-Compiler-Root + TYPE(LV) = @Ty + LT <= innermost enclosing loop/func + ROOT LV at *LV for LT + +Here I have written `ROOT LV at *LV FOR LT` to indicate that the code +makes a note in a side-table that the box `LV` must be rooted into the +stack when `*LV` is evaluated, and that this root can be released when +the scope `LT` exits. + +### Checking lifetime for derefs of managed, mutable pointers + +Loans of the contents of mutable managed pointers are simpler in some +ways that loans of immutable managed pointers, because we can never +rely on the user to root them (since the contents are, after all, +mutable). This means that the burden always falls to the compiler, so +there is only one rule: + + LIFETIME(*LV, LT, MQ) // L-Deref-Managed-Mut-Compiler-Root + TYPE(LV) = @mut Ty + LT <= innermost enclosing loop/func + ROOT LV at *LV for LT + LOCK LV at *LV as MQ for LT + +Note that there is an additional clause this time `LOCK LV at *LV as +MQ for LT`. This clause states that in addition to rooting `LV`, the +compiler should also "lock" the box dynamically, meaning that we +register that the box has been borrowed as mutable or immutable, +depending on `MQ`. This lock will fail if the box has already been +borrowed and either the old loan or the new loan is a mutable loan +(multiple immutable loans are okay). The lock is released as we exit +the scope `LT`. + +## Computing the restrictions + +The final rules govern the computation of *restrictions*, meaning that +we compute the set of actions that will be illegal for the life of the +loan. The predicate is written `RESTRICTIONS(LV, ACTIONS) = +RESTRICTION*`, which can be read "in order to prevent `ACTIONS` from +occuring on `LV`, the restrictions `RESTRICTION*` must be respected +for the lifetime of the loan". + +Note that there is an initial set of restrictions: these restrictions +are computed based on the kind of borrow: + + &mut LV => RESTRICTIONS(LV, MUTATE|CLAIM|FREEZE) + &LV => RESTRICTIONS(LV, MUTATE|CLAIM) + &const LV => RESTRICTIONS(LV, []) + +The reasoning here is that a mutable borrow must be the only writer, +therefore it prevents other writes (`MUTATE`), mutable borrows +(`CLAIM`), and immutable borrows (`FREEZE`). An immutable borrow +permits other immutable borows but forbids writes and mutable borows. +Finally, a const borrow just wants to be sure that the value is not +moved out from under it, so no actions are forbidden. + +### Restrictions for loans of a local variable + +The simplest case is a borrow of a local variable `X`: + + RESTRICTIONS(X, ACTIONS) = (X, ACTIONS) // R-Variable + +In such cases we just record the actions that are not permitted. + +### Restrictions for loans of fields + +Restricting a field is the same as restricting the owner of that +field: + + RESTRICTIONS(LV.f, ACTIONS) = RS, (LV.f, ACTIONS) // R-Field + RESTRICTIONS(LV, ACTIONS) = RS + +The reasoning here is as follows. If the field must not be mutated, +then you must not mutate the owner of the field either, since that +would indirectly modify the field. Similarly, if the field cannot be +frozen or aliased, we cannot allow the owner to be frozen or aliased, +since doing so indirectly freezes/aliases the field. This is the +origin of inherited mutability. + +### Restrictions for loans of owned pointees + +Because the mutability of owned pointees is inherited, restricting an +owned pointee is similar to restricting a field, in that it implies +restrictions on the pointer. However, owned pointers have an important +twist: if the owner `LV` is mutated, that causes the owned pointee +`*LV` to be freed! So whenever an owned pointee `*LV` is borrowed, we +must prevent the owned pointer `LV` from being mutated, which means +that we always add `MUTATE` and `CLAIM` to the restriction set imposed +on `LV`: + + RESTRICTIONS(*LV, ACTIONS) = RS, (*LV, ACTIONS) // R-Deref-Owned-Pointer + TYPE(LV) = ~Ty + RESTRICTIONS(LV, ACTIONS|MUTATE|CLAIM) = RS + +### Restrictions for loans of immutable managed/borrowed pointees + +Immutable managed/borrowed pointees are freely aliasable, meaning that +the compiler does not prevent you from copying the pointer. This +implies that issuing restrictions is useless. We might prevent the +user from acting on `*LV` itself, but there could be another path +`*LV1` that refers to the exact same memory, and we would not be +restricting that path. Therefore, the rule for `&Ty` and `@Ty` +pointers always returns an empty set of restrictions, and it only +permits restricting `MUTATE` and `CLAIM` actions: + + RESTRICTIONS(*LV, ACTIONS) = [] // R-Deref-Imm-Borrowed + TYPE(LV) = &Ty or @Ty + ACTIONS subset of [MUTATE, CLAIM] + +The reason that we can restrict `MUTATE` and `CLAIM` actions even +without a restrictions list is that it is never legal to mutate nor to +borrow mutably the contents of a `&Ty` or `@Ty` pointer. In other +words, those restrictions are already inherent in the type. + +Typically, this limitation is not an issue, because restrictions other +than `MUTATE` or `CLAIM` typically arise due to `&mut` borrow, and as +we said, that is already illegal for `*LV`. However, there is one case +where we can be asked to enforce an `ALIAS` restriction on `*LV`, +which is when you have a type like `&&mut T`. In such cases we will +report an error because we cannot enforce a lack of aliases on a `&Ty` +or `@Ty` type. That case is described in more detail in the section on +mutable borrowed pointers. + +### Restrictions for loans of const aliasable pointees + +Const pointers are read-only. There may be `&mut` or `&` aliases, and +we can not prevent *anything* but moves in that case. So the +`RESTRICTIONS` function is only defined if `ACTIONS` is the empty set. +Because moves from a `&const` or `@const` lvalue are never legal, it +is not necessary to add any restrictions at all to the final +result. + + RESTRICTIONS(*LV, []) = [] // R-Deref-Const-Borrowed + TYPE(LV) = &const Ty or @const Ty + +### Restrictions for loans of mutable borrowed pointees + +Borrowing mutable borrowed pointees is a bit subtle because we permit +users to freeze or claim `&mut` pointees. To see what I mean, consider this +(perfectly safe) code example: + + fn foo(t0: &mut T, op: fn(&T)) { + let t1: &T = &*t0; // (1) + op(t1); } - ... - fn consume(x: ~Foo) -> uint { - x.f + x.g + +In the borrow marked `(1)`, the data at `*t0` is *frozen* as part of a +re-borrow. Therefore, for the lifetime of `t1`, `*t0` must not be +mutated. This is the same basic idea as when we freeze a mutable local +variable, but unlike in that case `t0` is a *pointer* to the data, and +thus we must enforce some subtle restrictions in order to guarantee +soundness. + +Intuitively, we must ensure that `*t0` is the only *mutable* path to +reach the memory that was frozen. The reason that we are so concerned +with *mutable* paths is that those are the paths through which the +user could mutate the data that was frozen and hence invalidate the +`t1` pointer. Note that const aliases to `*t0` are acceptable (and in +fact we can't prevent them without unacceptable performance cost, more +on that later) because + +There are two rules governing `&mut` pointers, but we'll begin with +the first. This rule governs cases where we are attempting to prevent +an `&mut` pointee from being mutated, claimed, or frozen, as occurs +whenever the `&mut` pointee `*LV` is reborrowed as mutable or +immutable: + + RESTRICTIONS(*LV, ACTIONS) = RS, (*LV, ACTIONS) // R-Deref-Mut-Borrowed-1 + TYPE(LV) = &mut Ty + RESTRICTIONS(LV, MUTATE|CLAIM|ALIAS) = RS + +The main interesting part of the rule is the final line, which +requires that the `&mut` *pointer* `LV` be restricted from being +mutated, claimed, or aliased. The goal of these restrictions is to +ensure that, not considering the pointer that will result from this +borrow, `LV` remains the *sole pointer with mutable access* to `*LV`. + +Restrictions against mutations and claims are necessary because if the +pointer in `LV` were to be somehow copied or moved to a different +location, then the restriction issued for `*LV` would not apply to the +new location. Note that because `&mut` values are non-copyable, a +simple attempt to move the base pointer will fail due to the +(implicit) restriction against moves: + + // src/test/compile-fail/borrowck-move-mut-base-ptr.rs + fn foo(t0: &mut int) { + let p: &int = &*t0; // Freezes `*t0` + let t1 = t0; //~ ERROR cannot move out of `t0` + *t1 = 22; } - fn weird() { - let mut x: ~Foo = ~Foo { ... }; - 'a: add(&mut (*x).f, consume(x)) // (*) + +However, the additional restrictions against mutation mean that even a +clever attempt to use a swap to circumvent the type system will +encounter an error: + + // src/test/compile-fail/borrowck-swap-mut-base-ptr.rs + fn foo<'a>(mut t0: &'a mut int, + mut t1: &'a mut int) { + let p: &int = &*t0; // Freezes `*t0` + swap(&mut t0, &mut t1); //~ ERROR cannot borrow `t0` + *t1 = 22; } -In this case, there is only one borrow, but the second argument is -`consume(x)` instead of a second borrow. Because `consume()` is -declared to take a `~Foo`, it will in fact free the pointer `x` when -it has finished executing. If it is not obvious why this is -troublesome, consider this expanded version of that call: +The restriction against *aliasing* (and, in turn, freezing) is +necessary because, if an alias were of `LV` were to be produced, then +`LV` would no longer be the sole path to access the `&mut` +pointee. Since we are only issuing restrictions against `*LV`, these +other aliases would be unrestricted, and the result would be +unsound. For example: + + // src/test/compile-fail/borrowck-alias-mut-base-ptr.rs + fn foo(t0: &mut int) { + let p: &int = &*t0; // Freezes `*t0` + let q: &const &mut int = &const t0; //~ ERROR cannot borrow `t0` + **q = 22; // (*) + } - 'a: { - 'a_arg1: let a_temp1: ... = add; - 'a_arg2: let a_temp2: &'a_call mut uint = &'a_call mut (*x).f; - 'a_arg3_: let a_temp3: uint = { - let b_temp1: ... = consume; - let b_temp2: ~Foo = x; - 'b_call: b_temp1(x) - }; - 'a_call: a_temp1(a_temp2, a_temp3) +Note that the current rules also report an error at the assignment in +`(*)`, because we only permit `&mut` poiners to be assigned if they +are located in a non-aliasable location. However, I do not believe +this restriction is strictly necessary. It was added, I believe, to +discourage `&mut` from being placed in aliasable locations in the +first place. One (desirable) side-effect of restricting aliasing on +`LV` is that borrowing an `&mut` pointee found inside an aliasable +pointee yields an error: + + // src/test/compile-fail/borrowck-borrow-mut-base-ptr-in-aliasable-loc: + fn foo(t0: & &mut int) { + let t1 = t0; + let p: &int = &**t0; //~ ERROR cannot borrow an `&mut` in a `&` pointer + **t1 = 22; // (*) } -In this example, we will have borrowed the first argument before `x` -is freed and then free `x` during evaluation of the second -argument. This causes `a_temp2` to be invalidated. +Here at the line `(*)` you will also see the error I referred to +above, which I do not believe is strictly necessary. + +The second rule for `&mut` handles the case where we are not adding +any restrictions (beyond the default of "no move"): -Of course the loans computed from the borrow expression are supposed -to prevent this situation. But if we just considered the loans from -`MUTATE((*x).f, 'a_call, Total)`, the resulting loans would be: + RESTRICTIONS(*LV, []) = [] // R-Deref-Mut-Borrowed-2 + TYPE(LV) = &mut Ty - ((*x).f, 'a_call, Total, Mut) - (*x, 'a_call, Partial, Mut) - (x, 'a_call, Partial, Mut) +Moving from an `&mut` pointee is never legal, so no special +restrictions are needed. -Because these loans are only in scope for `'a_call`, they do nothing -to prevent the move that occurs evaluating the second argument. +### Restrictions for loans of mutable managed pointees -The way that we solve this is to say that if you have a borrow -expression `&'LT_P mut LV` which itself occurs in the lifetime -`'LT_B`, then the resulting loans are: +With `@mut` pointees, we don't make any static guarantees. But as a +convenience, we still register a restriction against `*LV`, because +that way if we *can* find a simple static error, we will: - MUTATE(LV, LT_P, Total) + ALIAS(LV, LUB(LT_P, LT_B), Total) + RESTRICTIONS(*LV, ACTIONS) = [*LV, ACTIONS] // R-Deref-Managed-Borrowed + TYPE(LV) = @mut Ty -The call to MUTATE is what we've seen so far. The second part -expresses the idea that the expression LV will be evaluated starting -at LT_B until the end of LT_P. Now, in the normal case, LT_P >= LT_B, -and so the second set of loans that result from a ALIAS are basically -a no-op. However, in the case of an argument where the evaluation of -the borrow occurs before the interval where the resulting pointer will -be used, this ALIAS is important. +# Moves and initialization -In the case of our example, it would produce a set of loans like: +The borrow checker is also in charge of ensuring that: - ((*x).f, 'a, Total, Const) - (*x, 'a, Total, Const) - (x, 'a, Total, Imm) +- all memory which is accessed is initialized +- immutable local variables are assigned at most once. -The scope of these loans is `'a = LUB('a_arg2, 'a_call)`, and so they -encompass all subsequent arguments. The first set of loans are Const -loans, which basically just prevent moves. However, when we cross -over the dereference of the owned pointer `x`, the rule for ALIAS -specifies that `x` must be frozen, and hence the final loan is an Imm -loan. In any case the troublesome second argument would be flagged -as an error. +These are two separate dataflow analyses built on the same +framework. Let's look at checking that memory is initialized first; +the checking of immutable local variabe assignments works in a very +similar way. -# Maps that are created +To track the initialization of memory, we actually track all the +points in the program that *create uninitialized memory*, meaning +moves and the declaration of uninitialized variables. For each of +these points, we create a bit in the dataflow set. Assignments to a +variable `x` or path `a.b.c` kill the move/uninitialization bits for +those paths and any subpaths (e.g., `x`, `x.y`, `a.b.c`, `*a.b.c`). +The bits are also killed when the root variables (`x`, `a`) go out of +scope. Bits are unioned when two control-flow paths join. Thus, the +presence of a bit indicates that the move may have occurred without an +intervening assignment to the same memory. At each use of a variable, +we examine the bits in scope, and check that none of them are +moves/uninitializations of the variable that is being used. -Borrowck results in two maps. +Let's look at a simple example: + + fn foo(a: ~int) { + let b: ~int; // Gen bit 0. + + if cond { // Bits: 0 + use(&*a); + b = a; // Gen bit 1, kill bit 0. + use(&*b); + } else { + // Bits: 0 + } + // Bits: 0,1 + use(&*a); // Error. + use(&*b); // Error. + } -- `root_map`: identifies those expressions or patterns whose result - needs to be rooted. Conceptually the root_map maps from an - expression or pattern node to a `node_id` identifying the scope for - which the expression must be rooted (this `node_id` should identify - a block or call). The actual key to the map is not an expression id, - however, but a `root_map_key`, which combines an expression id with a - deref count and is used to cope with auto-deref. + fn use(a: &int) { } + +In this example, the variable `b` is created uninitialized. In one +branch of an `if`, we then move the variable `a` into `b`. Once we +exit the `if`, therefore, it is an error to use `a` or `b` since both +are only conditionally initialized. I have annotated the dataflow +state using comments. There are two dataflow bits, with bit 0 +corresponding to the creation of `b` without an initializer, and bit 1 +corresponding to the move of `a`. The assignment `b = a` both +generates bit 1, because it is a move of `a`, and kills bit 0, because +`b` is now initialized. On the else branch, though, `b` is never +initialized, and so bit 0 remains untouched. When the two flows of +control join, we union the bits from both sides, resulting in both +bits 0 and 1 being set. Thus any attempt to use `a` uncovers the bit 1 +from the "then" branch, showing that `a` may be moved, and any attempt +to use `b` uncovers bit 0, from the "else" branch, showing that `b` +may not be initialized. + +## Initialization of immutable variables + +Initialization of immutable variables works in a very similar way, +except that: + +1. we generate bits for each assignment to a variable; +2. the bits are never killed except when the variable goes out of scope. + +Thus the presence of an assignment bit indicates that the assignment +may have occurred. Note that assignments are only killed when the +variable goes out of scope, as it is not relevant whether or not there +has been a move in the meantime. Using these bits, we can declare that +an assignment to an immutable variable is legal iff there is no other +assignment bit to that same variable in scope. + +## Why is the design made this way? + +It may seem surprising that we assign dataflow bits to *each move* +rather than *each path being moved*. This is somewhat less efficient, +since on each use, we must iterate through all moves and check whether +any of them correspond to the path in question. Similar concerns apply +to the analysis for double assignments to immutable variables. The +main reason to do it this way is that it allows us to print better +error messages, because when a use occurs, we can print out the +precise move that may be in scope, rather than simply having to say +"the variable may not be initialized". + +## Data structures used in the move analysis + +The move analysis maintains several data structures that enable it to +cross-reference moves and assignments to determine when they may be +moving/assigning the same memory. These are all collected into the +`MoveData` and `FlowedMoveData` structs. The former represents the set +of move paths, moves, and assignments, and the latter adds in the +results of a dataflow computation. + +### Move paths + +The `MovePath` tree tracks every path that is moved or assigned to. +These paths have the same form as the `LoanPath` data structure, which +in turn is the "real world version of the lvalues `LV` that we +introduced earlier. The difference between a `MovePath` and a `LoanPath` +is that move paths are: + +1. Canonicalized, so that we have exactly one copy of each, and + we can refer to move paths by index; +2. Cross-referenced with other paths into a tree, so that given a move + path we can efficiently find all parent move paths and all + extensions (e.g., given the `a.b` move path, we can easily find the + move path `a` and also the move paths `a.b.c`) +3. Cross-referenced with moves and assignments, so that we can + easily find all moves and assignments to a given path. + +The mechanism that we use is to create a `MovePath` record for each +move path. These are arranged in an array and are referenced using +`MovePathIndex` values, which are newtype'd indices. The `MovePath` +structs are arranged into a tree, representing using the standard +Knuth representation where each node has a child 'pointer' and a "next +sibling" 'pointer'. In addition, each `MovePath` has a parent +'pointer'. In this case, the 'pointers' are just `MovePathIndex` +values. + +In this way, if we want to find all base paths of a given move path, +we can just iterate up the parent pointers (see `each_base_path()` in +the `move_data` module). If we want to find all extensions, we can +iterate through the subtree (see `each_extending_path()`). + +### Moves and assignments + +There are structs to represent moves (`Move`) and assignments +(`Assignment`), and these are also placed into arrays and referenced +by index. All moves of a particular path are arranged into a linked +lists, beginning with `MovePath.first_move` and continuing through +`Move.next_move`. + +We distinguish between "var" assignments, which are assignments to a +variable like `x = foo`, and "path" assignments (`x.f = foo`). This +is because we need to assign dataflows to the former, but not the +latter, so as to check for double initialization of immutable +variables. + +### Gathering and checking moves + +Like loans, we distinguish two phases. The first, gathering, is where +we uncover all the moves and assignments. As with loans, we do some +basic sanity checking in this phase, so we'll report errors if you +attempt to move out of a borrowed pointer etc. Then we do the dataflow +(see `FlowedMoveData::new`). Finally, in the `check_loans.rs` code, we +walk back over, identify all uses, assignments, and captures, and +check that they are legal given the set of dataflow bits we have +computed for that program point. + +# Future work + +While writing up these docs, I encountered some rules I believe to be +stricter than necessary: + +- I think the restriction against mutating `&mut` pointers found in an + aliasable location is unnecessary. They cannot be reborrowed, to be sure, + so it should be safe to mutate them. Lifting this might cause some common + cases (`&mut int`) to work just fine, but might lead to further confusion + in other cases, so maybe it's best to leave it as is. +- I think restricting the `&mut` LV against moves and `ALIAS` is sufficient, + `MUTATE` and `CLAIM` are overkill. `MUTATE` was necessary when swap was + a built-in operator, but as it is not, it is implied by `CLAIM`, + and `CLAIM` is implied by `ALIAS`. The only net effect of this is an + extra error message in some cases, though. +- I have not described how closures interact. Current code is unsound. + I am working on describing and implementing the fix. +- If we wish, we can easily extend the move checking to allow finer-grained + tracking of what is initialized and what is not, enabling code like + this: + + a = x.f.g; // x.f.g is now uninitialized + // here, x and x.f are not usable, but x.f.h *is* + x.f.g = b; // x.f.g is not initialized + // now x, x.f, x.f.g, x.f.h are all usable + + What needs to change here, most likely, is that the `moves` module + should record not only what paths are moved, but what expressions + are actual *uses*. For example, the reference to `x` in `x.f.g = b` + is not a true *use* in the sense that it requires `x` to be fully + initialized. This is in fact why the above code produces an error + today: the reference to `x` in `x.f.g = b` is considered illegal + because `x` is not fully initialized. + +There are also some possible refactorings: + +- It might be nice to replace all loan paths with the MovePath mechanism, + since they allow lightweight comparison using an integer. */ diff --git a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs new file mode 100644 index 0000000000000..d32c1873ba053 --- /dev/null +++ b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs @@ -0,0 +1,164 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/*! + * Computes moves. + */ + +use core::prelude::*; +use mc = middle::mem_categorization; +use middle::borrowck::*; +use middle::borrowck::move_data::*; +use middle::moves; +use middle::ty; +use syntax::ast; +use syntax::ast_util; +use syntax::codemap::span; +use util::ppaux::{UserString}; + +pub fn gather_decl(bccx: @BorrowckCtxt, + move_data: &mut MoveData, + decl_id: ast::node_id, + _decl_span: span, + var_id: ast::node_id) { + let loan_path = @LpVar(var_id); + move_data.add_move(bccx.tcx, loan_path, decl_id, Declared); +} + +pub fn gather_move_from_expr(bccx: @BorrowckCtxt, + move_data: &mut MoveData, + move_expr: @ast::expr, + cmt: mc::cmt) { + gather_move_from_expr_or_pat(bccx, move_data, move_expr.id, + MoveExpr(move_expr), cmt); +} + +pub fn gather_move_from_pat(bccx: @BorrowckCtxt, + move_data: &mut MoveData, + move_pat: @ast::pat, + cmt: mc::cmt) { + gather_move_from_expr_or_pat(bccx, move_data, move_pat.id, + MovePat(move_pat), cmt); +} + +fn gather_move_from_expr_or_pat(bccx: @BorrowckCtxt, + move_data: &mut MoveData, + move_id: ast::node_id, + move_kind: MoveKind, + cmt: mc::cmt) { + if !check_is_legal_to_move_from(bccx, cmt, cmt) { + return; + } + + match opt_loan_path(cmt) { + Some(loan_path) => { + move_data.add_move(bccx.tcx, loan_path, move_id, move_kind); + } + None => { + // move from rvalue or unsafe pointer, hence ok + } + } +} + +pub fn gather_captures(bccx: @BorrowckCtxt, + move_data: &mut MoveData, + closure_expr: @ast::expr) { + let captured_vars = bccx.capture_map.get(&closure_expr.id); + for captured_vars.each |captured_var| { + match captured_var.mode { + moves::CapMove => { + let fvar_id = ast_util::def_id_of_def(captured_var.def).node; + let loan_path = @LpVar(fvar_id); + move_data.add_move(bccx.tcx, loan_path, closure_expr.id, + Captured(closure_expr)); + } + moves::CapCopy | moves::CapRef => {} + } + } +} + +pub fn gather_assignment(bccx: @BorrowckCtxt, + move_data: &mut MoveData, + assignment_id: ast::node_id, + assignment_span: span, + assignee_loan_path: @LoanPath, + assignee_id: ast::node_id) { + move_data.add_assignment(bccx.tcx, + assignee_loan_path, + assignment_id, + assignment_span, + assignee_id); +} + +fn check_is_legal_to_move_from(bccx: @BorrowckCtxt, + cmt0: mc::cmt, + cmt: mc::cmt) -> bool { + match cmt.cat { + mc::cat_stack_upvar(*) | + mc::cat_implicit_self(*) | + mc::cat_copied_upvar(*) | + mc::cat_deref(_, _, mc::region_ptr(*)) | + mc::cat_deref(_, _, mc::gc_ptr(*)) => { + bccx.span_err( + cmt0.span, + fmt!("cannot move out of %s", + bccx.cmt_to_str(cmt))); + false + } + + // It seems strange to allow a move out of a static item, + // but what happens in practice is that you have a + // reference to a constant with a type that should be + // moved, like `None::<~int>`. The type of this constant + // is technically `Option<~int>`, which moves, but we know + // that the content of static items will never actually + // contain allocated pointers, so we can just memcpy it. + // Since static items can never have allocated memory, + // this is ok. For now anyhow. + mc::cat_static_item => { + true + } + + mc::cat_rvalue(*) | + mc::cat_local(*) | + mc::cat_arg(*) | + mc::cat_self(*) | + mc::cat_deref(_, _, mc::unsafe_ptr(*)) => { + true + } + + mc::cat_downcast(b) | + mc::cat_interior(b, _) => { + match ty::get(b.ty).sty { + ty::ty_struct(did, _) | ty::ty_enum(did, _) => { + if ty::has_dtor(bccx.tcx, did) { + bccx.span_err( + cmt0.span, + fmt!("cannot move out of type `%s`, \ + which defines the `Drop` trait", + b.ty.user_string(bccx.tcx))); + false + } else { + check_is_legal_to_move_from(bccx, cmt0, b) + } + } + _ => { + check_is_legal_to_move_from(bccx, cmt0, b) + } + } + } + + mc::cat_deref(b, _, mc::uniq_ptr(*)) | + mc::cat_discr(b, _) => { + check_is_legal_to_move_from(bccx, cmt0, b) + } + } +} + diff --git a/src/librustc/middle/borrowck/gather_loans/lifetime.rs b/src/librustc/middle/borrowck/gather_loans/lifetime.rs index e377bebcc2697..9455340268eff 100644 --- a/src/librustc/middle/borrowck/gather_loans/lifetime.rs +++ b/src/librustc/middle/borrowck/gather_loans/lifetime.rs @@ -12,6 +12,7 @@ //! does not exceed the lifetime of the value being borrowed. use core::prelude::*; + use middle::borrowck::*; use mc = middle::mem_categorization; use middle::ty; @@ -69,11 +70,11 @@ impl GuaranteeLifetimeContext { match cmt.cat { mc::cat_rvalue | mc::cat_implicit_self | - mc::cat_copied_upvar(*) | - mc::cat_local(*) | - mc::cat_arg(*) | - mc::cat_self(*) | - mc::cat_deref(_, _, mc::region_ptr(*)) | + mc::cat_copied_upvar(*) | // L-Local + mc::cat_local(*) | // L-Local + mc::cat_arg(*) | // L-Local + mc::cat_self(*) | // L-Local + mc::cat_deref(_, _, mc::region_ptr(*)) | // L-Deref-Borrowed mc::cat_deref(_, _, mc::unsafe_ptr) => { let scope = self.scope(cmt); self.check_scope(scope) @@ -89,7 +90,7 @@ impl GuaranteeLifetimeContext { mc::cat_deref(base, derefs, mc::gc_ptr(ptr_mutbl)) => { let base_scope = self.scope(base); - // See rule Freeze-Imm-Managed-Ptr-2 in doc.rs + // L-Deref-Managed-Imm-User-Root let omit_root = ( ptr_mutbl == m_imm && self.bccx.is_subregion_of(self.loan_region, base_scope) && @@ -98,6 +99,8 @@ impl GuaranteeLifetimeContext { ); if !omit_root { + // L-Deref-Managed-Imm-Compiler-Root + // L-Deref-Managed-Mut-Compiler-Root self.check_root(cmt, base, derefs, ptr_mutbl, discr_scope); } else { debug!("omitting root, base=%s, base_scope=%?", @@ -105,8 +108,9 @@ impl GuaranteeLifetimeContext { } } - mc::cat_deref(base, _, mc::uniq_ptr(*)) | - mc::cat_interior(base, _) => { + mc::cat_downcast(base) | + mc::cat_deref(base, _, mc::uniq_ptr(*)) | // L-Deref-Owned + mc::cat_interior(base, _) => { // L-Field self.check(base, discr_scope) } @@ -303,6 +307,7 @@ impl GuaranteeLifetimeContext { mc::cat_deref(*) => { false } + r @ mc::cat_downcast(*) | r @ mc::cat_interior(*) | r @ mc::cat_stack_upvar(*) | r @ mc::cat_discr(*) => { @@ -318,6 +323,8 @@ impl GuaranteeLifetimeContext { //! lvalue `cmt` is guaranteed to be valid without any //! rooting etc, and presuming `cmt` is not mutated. + // See the SCOPE(LV) function in doc.rs + match cmt.cat { mc::cat_rvalue => { ty::re_scope(self.bccx.tcx.region_maps.cleanup_scope(cmt.id)) @@ -340,6 +347,7 @@ impl GuaranteeLifetimeContext { mc::cat_deref(_, _, mc::region_ptr(_, r)) => { r } + mc::cat_downcast(cmt) | mc::cat_deref(cmt, _, mc::uniq_ptr(*)) | mc::cat_deref(cmt, _, mc::gc_ptr(*)) | mc::cat_interior(cmt, _) | diff --git a/src/librustc/middle/borrowck/gather_loans/mod.rs b/src/librustc/middle/borrowck/gather_loans/mod.rs index 64d32d713d0da..448f35faa469a 100644 --- a/src/librustc/middle/borrowck/gather_loans/mod.rs +++ b/src/librustc/middle/borrowck/gather_loans/mod.rs @@ -19,6 +19,7 @@ use core::prelude::*; use middle::borrowck::*; +use middle::borrowck::move_data::MoveData; use mc = middle::mem_categorization; use middle::pat_util; use middle::ty::{ty_region}; @@ -35,6 +36,7 @@ use syntax::visit; mod lifetime; mod restrictions; +mod gather_moves; /// Context used while gathering loans: /// @@ -65,28 +67,32 @@ mod restrictions; struct GatherLoanCtxt { bccx: @BorrowckCtxt, id_range: id_range, + move_data: @mut move_data::MoveData, all_loans: @mut ~[Loan], item_ub: ast::node_id, repeating_ids: ~[ast::node_id] } pub fn gather_loans(bccx: @BorrowckCtxt, - body: &ast::blk) -> (id_range, @mut ~[Loan]) { + body: &ast::blk) + -> (id_range, @mut ~[Loan], @mut move_data::MoveData) { let glcx = @mut GatherLoanCtxt { bccx: bccx, id_range: id_range::max(), all_loans: @mut ~[], item_ub: body.node.id, - repeating_ids: ~[body.node.id] + repeating_ids: ~[body.node.id], + move_data: @mut MoveData::new() }; let v = visit::mk_vt(@visit::Visitor {visit_expr: gather_loans_in_expr, visit_block: gather_loans_in_block, visit_fn: gather_loans_in_fn, visit_stmt: add_stmt_to_map, visit_pat: add_pat_to_id_range, + visit_local: gather_loans_in_local, .. *visit::default_visitor()}); (v.visit_block)(body, glcx, v); - return (glcx.id_range, glcx.all_loans); + return (glcx.id_range, glcx.all_loans, glcx.move_data); } fn add_pat_to_id_range(p: @ast::pat, @@ -130,6 +136,35 @@ fn gather_loans_in_block(blk: &ast::blk, visit::visit_block(blk, this, vt); } +fn gather_loans_in_local(local: @ast::local, + this: @mut GatherLoanCtxt, + vt: visit::vt<@mut GatherLoanCtxt>) { + if local.node.init.is_none() { + // Variable declarations without initializers are considered "moves": + let tcx = this.bccx.tcx; + do pat_util::pat_bindings(tcx.def_map, local.node.pat) |_, id, span, _| { + gather_moves::gather_decl(this.bccx, + this.move_data, + id, + span, + id); + } + } else { + // Variable declarations with initializers are considered "assigns": + let tcx = this.bccx.tcx; + do pat_util::pat_bindings(tcx.def_map, local.node.pat) |_, id, span, _| { + gather_moves::gather_assignment(this.bccx, + this.move_data, + id, + span, + @LpVar(id), + id); + } + } + + visit::visit_local(local, this, vt); +} + fn gather_loans_in_expr(ex: @ast::expr, this: @mut GatherLoanCtxt, vt: visit::vt<@mut GatherLoanCtxt>) { @@ -140,13 +175,23 @@ fn gather_loans_in_expr(ex: @ast::expr, ex.id, pprust::expr_to_str(ex, tcx.sess.intr())); this.id_range.add(ex.id); - this.id_range.add(ex.callee_id); + + for ex.get_callee_id().each |callee_id| { + this.id_range.add(*callee_id); + } // If this expression is borrowed, have to ensure it remains valid: for tcx.adjustments.find(&ex.id).each |&adjustments| { this.guarantee_adjustments(ex, *adjustments); } + // If this expression is a move, gather it: + if this.bccx.is_move(ex.id) { + let cmt = this.bccx.cat_expr(ex); + gather_moves::gather_move_from_expr( + this.bccx, this.move_data, ex, cmt); + } + // Special checks for various kinds of expressions: match ex.node { ast::expr_addr_of(mutbl, base) => { @@ -159,6 +204,23 @@ fn gather_loans_in_expr(ex: @ast::expr, visit::visit_expr(ex, this, vt); } + ast::expr_assign(l, _) | ast::expr_assign_op(_, _, l, _) => { + let l_cmt = this.bccx.cat_expr(l); + match opt_loan_path(l_cmt) { + Some(l_lp) => { + gather_moves::gather_assignment(this.bccx, this.move_data, + ex.id, ex.span, + l_lp, l.id); + } + None => { + // This can occur with e.g. `*foo() = 5`. In such + // cases, there is no need to check for conflicts + // with moves etc, just ignore. + } + } + visit::visit_expr(ex, this, vt); + } + ast::expr_match(ex_v, ref arms) => { let cmt = this.bccx.cat_expr(ex_v); for arms.each |arm| { @@ -169,8 +231,8 @@ fn gather_loans_in_expr(ex: @ast::expr, visit::visit_expr(ex, this, vt); } - ast::expr_index(_, arg) | - ast::expr_binary(_, _, arg) + ast::expr_index(_, _, arg) | + ast::expr_binary(_, _, _, arg) if this.bccx.method_map.contains_key(&ex.id) => { // Arguments in method calls are always passed by ref. // @@ -203,27 +265,32 @@ fn gather_loans_in_expr(ex: @ast::expr, this.pop_repeating_id(body.node.id); } + ast::expr_fn_block(*) => { + gather_moves::gather_captures(this.bccx, this.move_data, ex); + visit::visit_expr(ex, this, vt); + } + _ => { visit::visit_expr(ex, this, vt); } } } -pub impl GatherLoanCtxt { - fn tcx(&self) -> ty::ctxt { self.bccx.tcx } +impl GatherLoanCtxt { + pub fn tcx(&self) -> ty::ctxt { self.bccx.tcx } - fn push_repeating_id(&mut self, id: ast::node_id) { + pub fn push_repeating_id(&mut self, id: ast::node_id) { self.repeating_ids.push(id); } - fn pop_repeating_id(&mut self, id: ast::node_id) { + pub fn pop_repeating_id(&mut self, id: ast::node_id) { let popped = self.repeating_ids.pop(); - assert!(id == popped); + assert_eq!(id, popped); } - fn guarantee_adjustments(&mut self, - expr: @ast::expr, - adjustment: &ty::AutoAdjustment) { + pub fn guarantee_adjustments(&mut self, + expr: @ast::expr, + adjustment: &ty::AutoAdjustment) { debug!("guarantee_adjustments(expr=%s, adjustment=%?)", expr.repr(self.tcx()), adjustment); let _i = indenter(); @@ -286,13 +353,12 @@ pub impl GatherLoanCtxt { // out loans, which will be added to the `req_loan_map`. This can // also entail "rooting" GC'd pointers, which means ensuring // dynamically that they are not freed. - fn guarantee_valid(&mut self, - borrow_id: ast::node_id, - borrow_span: span, - cmt: mc::cmt, - req_mutbl: ast::mutability, - loan_region: ty::Region) - { + pub fn guarantee_valid(&mut self, + borrow_id: ast::node_id, + borrow_span: span, + cmt: mc::cmt, + req_mutbl: ast::mutability, + loan_region: ty::Region) { debug!("guarantee_valid(borrow_id=%?, cmt=%s, \ req_mutbl=%?, loan_region=%?)", borrow_id, @@ -417,6 +483,8 @@ pub impl GatherLoanCtxt { borrow_span: span, cmt: mc::cmt, req_mutbl: ast::mutability) { + //! Implements the M-* rules in doc.rs. + match req_mutbl { m_const => { // Data of any mutability can be lent as const. @@ -448,15 +516,16 @@ pub impl GatherLoanCtxt { } } - fn restriction_set(&self, req_mutbl: ast::mutability) -> RestrictionSet { + pub fn restriction_set(&self, req_mutbl: ast::mutability) + -> RestrictionSet { match req_mutbl { m_const => RESTR_EMPTY, - m_imm => RESTR_EMPTY | RESTR_MUTATE, - m_mutbl => RESTR_EMPTY | RESTR_MUTATE | RESTR_FREEZE + m_imm => RESTR_EMPTY | RESTR_MUTATE | RESTR_CLAIM, + m_mutbl => RESTR_EMPTY | RESTR_MUTATE | RESTR_CLAIM | RESTR_FREEZE } } - fn mark_loan_path_as_mutated(&self, loan_path: @LoanPath) { + pub fn mark_loan_path_as_mutated(&self, loan_path: @LoanPath) { //! For mutable loans of content whose mutability derives //! from a local variable, mark the mutability decl as necessary. @@ -474,9 +543,10 @@ pub impl GatherLoanCtxt { } } - fn compute_gen_scope(&self, - borrow_id: ast::node_id, - loan_scope: ast::node_id) -> ast::node_id { + pub fn compute_gen_scope(&self, + borrow_id: ast::node_id, + loan_scope: ast::node_id) + -> ast::node_id { //! Determine when to introduce the loan. Typically the loan //! is introduced at the point of the borrow, but in some cases, //! notably method arguments, the loan may be introduced only @@ -490,9 +560,8 @@ pub impl GatherLoanCtxt { } } - fn compute_kill_scope(&self, - loan_scope: ast::node_id, - lp: @LoanPath) -> ast::node_id { + pub fn compute_kill_scope(&self, loan_scope: ast::node_id, lp: @LoanPath) + -> ast::node_id { //! Determine when the loan restrictions go out of scope. //! This is either when the lifetime expires or when the //! local variable which roots the loan-path goes out of scope, @@ -522,11 +591,11 @@ pub impl GatherLoanCtxt { } } - fn gather_pat(&mut self, - discr_cmt: mc::cmt, - root_pat: @ast::pat, - arm_body_id: ast::node_id, - match_id: ast::node_id) { + pub fn gather_pat(&mut self, + discr_cmt: mc::cmt, + root_pat: @ast::pat, + arm_body_id: ast::node_id, + match_id: ast::node_id) { do self.bccx.cat_pattern(discr_cmt, root_pat) |cmt, pat| { match pat.node { ast::pat_ident(bm, _, _) if self.pat_is_binding(pat) => { @@ -557,9 +626,12 @@ pub impl GatherLoanCtxt { cmt, mutbl, scope_r); } } - ast::bind_by_copy | ast::bind_infer => { - // Nothing to do here; neither copies nor moves induce - // borrows. + ast::bind_infer => { + // No borrows here, but there may be moves + if self.bccx.is_move(pat.id) { + gather_moves::gather_move_from_pat( + self.bccx, self.move_data, pat, cmt); + } } } } @@ -584,9 +656,8 @@ pub impl GatherLoanCtxt { } } - fn vec_slice_info(&self, - pat: @ast::pat, - slice_ty: ty::t) -> (ast::mutability, ty::Region) { + pub fn vec_slice_info(&self, pat: @ast::pat, slice_ty: ty::t) + -> (ast::mutability, ty::Region) { /*! * * In a pattern like [a, b, ..c], normally `c` has slice type, @@ -612,11 +683,11 @@ pub impl GatherLoanCtxt { } } - fn pat_is_variant_or_struct(&self, pat: @ast::pat) -> bool { + pub fn pat_is_variant_or_struct(&self, pat: @ast::pat) -> bool { pat_util::pat_is_variant_or_struct(self.bccx.tcx.def_map, pat) } - fn pat_is_binding(&self, pat: @ast::pat) -> bool { + pub fn pat_is_binding(&self, pat: @ast::pat) -> bool { pat_util::pat_is_binding(self.bccx.tcx.def_map, pat) } } @@ -634,4 +705,3 @@ fn add_stmt_to_map(stmt: @ast::stmt, } visit::visit_stmt(stmt, this, vt); } - diff --git a/src/librustc/middle/borrowck/gather_loans/restrictions.rs b/src/librustc/middle/borrowck/gather_loans/restrictions.rs index 0be4c67a9bc91..6bd32f04ce5b9 100644 --- a/src/librustc/middle/borrowck/gather_loans/restrictions.rs +++ b/src/librustc/middle/borrowck/gather_loans/restrictions.rs @@ -11,6 +11,8 @@ //! Computes the restrictions that result from a borrow. use core::prelude::*; + +use core::vec; use middle::borrowck::*; use mc = middle::mem_categorization; use middle::ty; @@ -32,7 +34,7 @@ pub fn compute_restrictions(bccx: @BorrowckCtxt, cmt_original: cmt }; - ctxt.compute(cmt, restr) + ctxt.restrict(cmt, restr) } /////////////////////////////////////////////////////////////////////////// @@ -49,9 +51,9 @@ impl RestrictionsContext { self.bccx.tcx } - fn compute(&self, - cmt: mc::cmt, - restrictions: RestrictionSet) -> RestrictionResult { + fn restrict(&self, + cmt: mc::cmt, + restrictions: RestrictionSet) -> RestrictionResult { // Check for those cases where we cannot control the aliasing // and make sure that we are not being asked to. @@ -75,38 +77,40 @@ impl RestrictionsContext { mc::cat_local(local_id) | mc::cat_arg(local_id) | mc::cat_self(local_id) => { + // R-Variable let lp = @LpVar(local_id); SafeIf(lp, ~[Restriction {loan_path: lp, set: restrictions}]) } - mc::cat_interior(cmt_base, i @ mc::interior_variant(_)) => { + mc::cat_downcast(cmt_base) => { // When we borrow the interior of an enum, we have to // ensure the enum itself is not mutated, because that // could cause the type of the memory to change. - let result = self.compute(cmt_base, restrictions | RESTR_MUTATE); - self.extend(result, cmt.mutbl, LpInterior(i), restrictions) + self.restrict( + cmt_base, + restrictions | RESTR_MUTATE | RESTR_CLAIM) } - mc::cat_interior(cmt_base, i @ mc::interior_tuple) | - mc::cat_interior(cmt_base, i @ mc::interior_anon_field) | - mc::cat_interior(cmt_base, i @ mc::interior_field(*)) | - mc::cat_interior(cmt_base, i @ mc::interior_index(*)) => { - // For all of these cases, overwriting the base would - // not change the type of the memory, so no additional - // restrictions are needed. + mc::cat_interior(cmt_base, i) => { + // R-Field // - // FIXME(#5397) --- Mut fields are not treated soundly - // (hopefully they will just get phased out) - let result = self.compute(cmt_base, restrictions); + // Overwriting the base would not change the type of + // the memory, so no additional restrictions are + // needed. + let result = self.restrict(cmt_base, restrictions); self.extend(result, cmt.mutbl, LpInterior(i), restrictions) } mc::cat_deref(cmt_base, _, mc::uniq_ptr(*)) => { + // R-Deref-Owned-Pointer + // // When we borrow the interior of an owned pointer, we // cannot permit the base to be mutated, because that // would cause the unique pointer to be freed. - let result = self.compute(cmt_base, restrictions | RESTR_MUTATE); + let result = self.restrict( + cmt_base, + restrictions | RESTR_MUTATE | RESTR_CLAIM); self.extend(result, cmt.mutbl, LpDeref, restrictions) } @@ -115,16 +119,20 @@ impl RestrictionsContext { mc::cat_implicit_self(*) | mc::cat_deref(_, _, mc::region_ptr(m_imm, _)) | mc::cat_deref(_, _, mc::gc_ptr(m_imm)) => { + // R-Deref-Imm-Borrowed Safe } mc::cat_deref(_, _, mc::region_ptr(m_const, _)) | mc::cat_deref(_, _, mc::gc_ptr(m_const)) => { + // R-Deref-Const-Borrowed self.check_no_mutability_control(cmt, restrictions); Safe } mc::cat_deref(cmt_base, _, mc::gc_ptr(m_mutbl)) => { + // R-Deref-Managed-Borrowed + // // Technically, no restrictions are *necessary* here. // The validity of the borrow is guaranteed // dynamically. However, nonetheless we add a @@ -175,12 +183,15 @@ impl RestrictionsContext { // mutability, we can only prevent mutation or prevent // freezing if it is not aliased. Therefore, in such // cases we restrict aliasing on `cmt_base`. - if restrictions.intersects(RESTR_MUTATE | RESTR_FREEZE) { - let result = self.compute(cmt_base, restrictions | RESTR_ALIAS); + if restrictions != RESTR_EMPTY { + // R-Deref-Mut-Borrowed-1 + let result = self.restrict( + cmt_base, + RESTR_ALIAS | RESTR_MUTATE | RESTR_CLAIM); self.extend(result, cmt.mutbl, LpDeref, restrictions) } else { - let result = self.compute(cmt_base, restrictions); - self.extend(result, cmt.mutbl, LpDeref, restrictions) + // R-Deref-Mut-Borrowed-2 + Safe } } @@ -191,7 +202,7 @@ impl RestrictionsContext { mc::cat_stack_upvar(cmt_base) | mc::cat_discr(cmt_base, _) => { - self.compute(cmt_base, restrictions) + self.restrict(cmt_base, restrictions) } } } @@ -239,11 +250,10 @@ impl RestrictionsContext { fn check_no_mutability_control(&self, cmt: mc::cmt, restrictions: RestrictionSet) { - if restrictions.intersects(RESTR_MUTATE | RESTR_FREEZE) { + if restrictions.intersects(RESTR_MUTATE | RESTR_FREEZE | RESTR_CLAIM) { self.bccx.report(BckError {span: self.span, cmt: cmt, code: err_freeze_aliasable_const}); } } } - diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs index 0f01b2b1e418e..fa3bae3f5ac92 100644 --- a/src/librustc/middle/borrowck/mod.rs +++ b/src/librustc/middle/borrowck/mod.rs @@ -19,18 +19,18 @@ use middle::moves; use middle::dataflow::DataFlowContext; use middle::dataflow::DataFlowOperator; use util::common::stmt_set; -use util::ppaux::{note_and_explain_region, Repr}; +use util::ppaux::{note_and_explain_region, Repr, UserString}; -#[cfg(stage0)] -use core; // NOTE: this can be removed after the next snapshot use core::hashmap::{HashSet, HashMap}; use core::io; -use core::result::{Result}; use core::ops::{BitOr, BitAnd}; +use core::result::{Result}; +use core::str; use syntax::ast; use syntax::ast_map; use syntax::visit; use syntax::codemap::span; +use syntax::parse::token; macro_rules! if_ok( ($inp: expr) => ( @@ -48,6 +48,8 @@ pub mod check_loans; #[path="gather_loans/mod.rs"] pub mod gather_loans; +pub mod move_data; + pub struct LoanDataFlowOperator; pub type LoanDataFlow = DataFlowContext; @@ -83,7 +85,7 @@ pub fn check_crate( visit::visit_crate(crate, bccx, v); if tcx.sess.borrowck_stats() { - io::println(~"--- borrowck stats ---"); + io::println("--- borrowck stats ---"); io::println(fmt!("paths requiring guarantees: %u", bccx.stats.guaranteed_paths)); io::println(fmt!("paths requiring loans : %s", @@ -123,21 +125,28 @@ fn borrowck_fn(fk: &visit::fn_kind, debug!("borrowck_fn(id=%?)", id); // Check the body of fn items. - let (id_range, all_loans) = + let (id_range, all_loans, move_data) = gather_loans::gather_loans(this, body); - let all_loans: &~[Loan] = &*all_loans; // FIXME(#5074) - let mut dfcx = + let mut loan_dfcx = DataFlowContext::new(this.tcx, this.method_map, LoanDataFlowOperator, id_range, all_loans.len()); for all_loans.eachi |loan_idx, loan| { - dfcx.add_gen(loan.gen_scope, loan_idx); - dfcx.add_kill(loan.kill_scope, loan_idx); + loan_dfcx.add_gen(loan.gen_scope, loan_idx); + loan_dfcx.add_kill(loan.kill_scope, loan_idx); } - dfcx.propagate(body); - check_loans::check_loans(this, &dfcx, *all_loans, body); + loan_dfcx.propagate(body); + + let flowed_moves = move_data::FlowedMoveData::new(move_data, + this.tcx, + this.method_map, + id_range, + body); + + check_loans::check_loans(this, &loan_dfcx, flowed_moves, + *all_loans, body); } } @@ -228,20 +237,20 @@ pub struct Loan { span: span, } -#[deriving(Eq)] +#[deriving(Eq, IterBytes)] pub enum LoanPath { LpVar(ast::node_id), // `x` in doc.rs LpExtend(@LoanPath, mc::MutabilityCategory, LoanPathElem) } -#[deriving(Eq)] +#[deriving(Eq, IterBytes)] pub enum LoanPathElem { - LpDeref, // `*LV` in doc.rs - LpInterior(mc::interior_kind) // `LV.f` in doc.rs + LpDeref, // `*LV` in doc.rs + LpInterior(mc::InteriorKind) // `LV.f` in doc.rs } -pub impl LoanPath { - fn node_id(&self) -> ast::node_id { +impl LoanPath { + pub fn node_id(&self) -> ast::node_id { match *self { LpVar(local_id) => local_id, LpExtend(base, _, _) => base.node_id() @@ -280,6 +289,7 @@ pub fn opt_loan_path(cmt: mc::cmt) -> Option<@LoanPath> { |&lp| @LpExtend(lp, cmt.mutbl, LpInterior(ik))) } + mc::cat_downcast(cmt_base) | mc::cat_stack_upvar(cmt_base) | mc::cat_discr(cmt_base, _) => { opt_loan_path(cmt_base) @@ -293,10 +303,10 @@ pub fn opt_loan_path(cmt: mc::cmt) -> Option<@LoanPath> { // Borrowing an lvalue often results in *restrictions* that limit what // can be done with this lvalue during the scope of the loan: // -// - `RESTR_MUTATE`: The lvalue may not be modified and mutable pointers to -// the value cannot be created. -// - `RESTR_FREEZE`: Immutable pointers to the value cannot be created. -// - `RESTR_ALIAS`: The lvalue may not be aliased in any way. +// - `RESTR_MUTATE`: The lvalue may not be modified. +// - `RESTR_CLAIM`: `&mut` borrows of the lvalue are forbidden. +// - `RESTR_FREEZE`: `&` borrows of the lvalue are forbidden. +// - `RESTR_ALIAS`: All borrows of the lvalue are forbidden. // // In addition, no value which is restricted may be moved. Therefore, // restrictions are meaningful even if the RestrictionSet is empty, @@ -307,21 +317,23 @@ pub struct Restriction { set: RestrictionSet } +#[deriving(Eq)] pub struct RestrictionSet { bits: u32 } -pub static RESTR_EMPTY: RestrictionSet = RestrictionSet {bits: 0b000}; -pub static RESTR_MUTATE: RestrictionSet = RestrictionSet {bits: 0b001}; -pub static RESTR_FREEZE: RestrictionSet = RestrictionSet {bits: 0b010}; -pub static RESTR_ALIAS: RestrictionSet = RestrictionSet {bits: 0b100}; +pub static RESTR_EMPTY: RestrictionSet = RestrictionSet {bits: 0b0000}; +pub static RESTR_MUTATE: RestrictionSet = RestrictionSet {bits: 0b0001}; +pub static RESTR_CLAIM: RestrictionSet = RestrictionSet {bits: 0b0010}; +pub static RESTR_FREEZE: RestrictionSet = RestrictionSet {bits: 0b0100}; +pub static RESTR_ALIAS: RestrictionSet = RestrictionSet {bits: 0b1000}; -pub impl RestrictionSet { - fn intersects(&self, restr: RestrictionSet) -> bool { +impl RestrictionSet { + pub fn intersects(&self, restr: RestrictionSet) -> bool { (self.bits & restr.bits) != 0 } - fn contains_all(&self, restr: RestrictionSet) -> bool { + pub fn contains_all(&self, restr: RestrictionSet) -> bool { (self.bits & restr.bits) == restr.bits } } @@ -408,28 +420,41 @@ pub enum AliasableViolationKind { BorrowViolation } +pub enum MovedValueUseKind { + MovedInUse, + MovedInCapture, +} + /////////////////////////////////////////////////////////////////////////// // Misc -pub impl BorrowckCtxt { - fn is_subregion_of(&self, r_sub: ty::Region, r_sup: ty::Region) -> bool { +impl BorrowckCtxt { + pub fn is_subregion_of(&self, r_sub: ty::Region, r_sup: ty::Region) + -> bool { self.tcx.region_maps.is_subregion_of(r_sub, r_sup) } - fn is_subscope_of(&self, r_sub: ast::node_id, r_sup: ast::node_id) -> bool { + pub fn is_subscope_of(&self, r_sub: ast::node_id, r_sup: ast::node_id) + -> bool { self.tcx.region_maps.is_subscope_of(r_sub, r_sup) } - fn cat_expr(&self, expr: @ast::expr) -> mc::cmt { + pub fn is_move(&self, id: ast::node_id) -> bool { + self.moves_map.contains(&id) + } + + pub fn cat_expr(&self, expr: @ast::expr) -> mc::cmt { mc::cat_expr(self.tcx, self.method_map, expr) } - fn cat_expr_unadjusted(&self, expr: @ast::expr) -> mc::cmt { + pub fn cat_expr_unadjusted(&self, expr: @ast::expr) -> mc::cmt { mc::cat_expr_unadjusted(self.tcx, self.method_map, expr) } - fn cat_expr_autoderefd(&self, expr: @ast::expr, - adj: @ty::AutoAdjustment) -> mc::cmt { + pub fn cat_expr_autoderefd(&self, + expr: @ast::expr, + adj: @ty::AutoAdjustment) + -> mc::cmt { match *adj { ty::AutoAddEnv(*) => { // no autoderefs @@ -445,49 +470,128 @@ pub impl BorrowckCtxt { } } - fn cat_def(&self, - id: ast::node_id, - span: span, - ty: ty::t, - def: ast::def) -> mc::cmt { + pub fn cat_def(&self, + id: ast::node_id, + span: span, + ty: ty::t, + def: ast::def) + -> mc::cmt { mc::cat_def(self.tcx, self.method_map, id, span, ty, def) } - fn cat_discr(&self, cmt: mc::cmt, match_id: ast::node_id) -> mc::cmt { + pub fn cat_discr(&self, cmt: mc::cmt, match_id: ast::node_id) -> mc::cmt { @mc::cmt_ {cat:mc::cat_discr(cmt, match_id), mutbl:cmt.mutbl.inherit(), ..*cmt} } - fn mc_ctxt(&self) -> mc::mem_categorization_ctxt { + pub fn mc_ctxt(&self) -> mc::mem_categorization_ctxt { mc::mem_categorization_ctxt {tcx: self.tcx, method_map: self.method_map} } - fn cat_pattern(&self, - cmt: mc::cmt, - pat: @ast::pat, - op: &fn(mc::cmt, @ast::pat)) { + pub fn cat_pattern(&self, + cmt: mc::cmt, + pat: @ast::pat, + op: &fn(mc::cmt, @ast::pat)) { let mc = self.mc_ctxt(); mc.cat_pattern(cmt, pat, op); } - fn report(&self, err: BckError) { + pub fn report(&self, err: BckError) { self.span_err( err.span, self.bckerr_to_str(err)); self.note_and_explain_bckerr(err); } - fn span_err(&self, s: span, m: &str) { + pub fn report_use_of_moved_value(&self, + use_span: span, + use_kind: MovedValueUseKind, + lp: @LoanPath, + move: &move_data::Move, + moved_lp: @LoanPath) { + let verb = match use_kind { + MovedInUse => "use", + MovedInCapture => "capture", + }; + + match move.kind { + move_data::Declared => { + self.tcx.sess.span_err( + use_span, + fmt!("%s of possibly uninitialized value: `%s`", + verb, + self.loan_path_to_str(lp))); + } + _ => { + let partially = if lp == moved_lp {""} else {"partially "}; + self.tcx.sess.span_err( + use_span, + fmt!("%s of %smoved value: `%s`", + verb, + partially, + self.loan_path_to_str(lp))); + } + } + + match move.kind { + move_data::Declared => {} + + move_data::MoveExpr(expr) => { + let expr_ty = ty::expr_ty_adjusted(self.tcx, expr); + self.tcx.sess.span_note( + expr.span, + fmt!("`%s` moved here because it has type `%s`, \ + which is moved by default (use `copy` to override)", + self.loan_path_to_str(moved_lp), + expr_ty.user_string(self.tcx))); + } + + move_data::MovePat(pat) => { + let pat_ty = ty::node_id_to_type(self.tcx, pat.id); + self.tcx.sess.span_note( + pat.span, + fmt!("`%s` moved here because it has type `%s`, \ + which is moved by default (use `ref` to override)", + self.loan_path_to_str(moved_lp), + pat_ty.user_string(self.tcx))); + } + + move_data::Captured(expr) => { + self.tcx.sess.span_note( + expr.span, + fmt!("`%s` moved into closure environment here \ + because its type is moved by default \ + (make a copy and capture that instead to override)", + self.loan_path_to_str(moved_lp))); + } + } + } + + pub fn report_reassigned_immutable_variable(&self, + span: span, + lp: @LoanPath, + assign: + &move_data::Assignment) { + self.tcx.sess.span_err( + span, + fmt!("re-assignment of immutable variable `%s`", + self.loan_path_to_str(lp))); + self.tcx.sess.span_note( + assign.span, + fmt!("prior assignment occurs here")); + } + + pub fn span_err(&self, s: span, m: &str) { self.tcx.sess.span_err(s, m); } - fn span_note(&self, s: span, m: &str) { + pub fn span_note(&self, s: span, m: &str) { self.tcx.sess.span_note(s, m); } - fn bckerr_to_str(&self, err: BckError) -> ~str { + pub fn bckerr_to_str(&self, err: BckError) -> ~str { match err.code { err_mutbl(lk) => { fmt!("cannot borrow %s %s as %s", @@ -511,10 +615,10 @@ pub impl BorrowckCtxt { } } - fn report_aliasability_violation(&self, - span: span, - kind: AliasableViolationKind, - cause: mc::AliasableReason) { + pub fn report_aliasability_violation(&self, + span: span, + kind: AliasableViolationKind, + cause: mc::AliasableReason) { let prefix = match kind { MutabilityViolation => "cannot assign to an `&mut`", BorrowViolation => "cannot borrow an `&mut`" @@ -552,7 +656,7 @@ pub impl BorrowckCtxt { } } - fn note_and_explain_bckerr(&self, err: BckError) { + pub fn note_and_explain_bckerr(&self, err: BckError) { let code = err.code; match code { err_mutbl(*) | err_freeze_aliasable_const(*) => {} @@ -560,34 +664,34 @@ pub impl BorrowckCtxt { err_out_of_root_scope(super_scope, sub_scope) => { note_and_explain_region( self.tcx, - ~"managed value would have to be rooted for ", + "managed value would have to be rooted for ", sub_scope, - ~"..."); + "..."); note_and_explain_region( self.tcx, - ~"...but can only be rooted for ", + "...but can only be rooted for ", super_scope, - ~""); + ""); } err_out_of_scope(super_scope, sub_scope) => { note_and_explain_region( self.tcx, - ~"borrowed pointer must be valid for ", + "borrowed pointer must be valid for ", sub_scope, - ~"..."); + "..."); note_and_explain_region( self.tcx, - ~"...but borrowed value is only valid for ", + "...but borrowed value is only valid for ", super_scope, - ~""); + ""); } } } - fn append_loan_path_to_str_from_interior(&self, - loan_path: &LoanPath, - out: &mut ~str) { + pub fn append_loan_path_to_str_from_interior(&self, + loan_path: &LoanPath, + out: &mut ~str) { match *loan_path { LpExtend(_, _, LpDeref) => { str::push_char(out, '('); @@ -601,12 +705,14 @@ pub impl BorrowckCtxt { } } - fn append_loan_path_to_str(&self, loan_path: &LoanPath, out: &mut ~str) { + pub fn append_loan_path_to_str(&self, + loan_path: &LoanPath, + out: &mut ~str) { match *loan_path { LpVar(id) => { match self.tcx.items.find(&id) { - Some(&ast_map::node_local(ident)) => { - str::push_str(out, *self.tcx.sess.intr().get(ident)); + Some(&ast_map::node_local(ref ident)) => { + str::push_str(out, *token::ident_to_str(ident)); } r => { self.tcx.sess.bug( @@ -616,24 +722,25 @@ pub impl BorrowckCtxt { } } - LpExtend(lp_base, _, LpInterior(mc::interior_field(fld))) => { + LpExtend(lp_base, _, LpInterior(mc::InteriorField(fname))) => { self.append_loan_path_to_str_from_interior(lp_base, out); - str::push_char(out, '.'); - str::push_str(out, *self.tcx.sess.intr().get(fld)); + match fname { + mc::NamedField(ref fname) => { + str::push_char(out, '.'); + str::push_str(out, *token::ident_to_str(fname)); + } + mc::PositionalField(idx) => { + str::push_char(out, '#'); // invent a notation here + str::push_str(out, idx.to_str()); + } + } } - LpExtend(lp_base, _, LpInterior(mc::interior_index(*))) => { + LpExtend(lp_base, _, LpInterior(mc::InteriorElement(_))) => { self.append_loan_path_to_str_from_interior(lp_base, out); str::push_str(out, "[]"); } - LpExtend(lp_base, _, LpInterior(mc::interior_tuple)) | - LpExtend(lp_base, _, LpInterior(mc::interior_anon_field)) | - LpExtend(lp_base, _, LpInterior(mc::interior_variant(_))) => { - self.append_loan_path_to_str_from_interior(lp_base, out); - str::push_str(out, ".(tuple)"); - } - LpExtend(lp_base, _, LpDeref) => { str::push_char(out, '*'); self.append_loan_path_to_str(lp_base, out); @@ -641,25 +748,25 @@ pub impl BorrowckCtxt { } } - fn loan_path_to_str(&self, loan_path: &LoanPath) -> ~str { + pub fn loan_path_to_str(&self, loan_path: &LoanPath) -> ~str { let mut result = ~""; self.append_loan_path_to_str(loan_path, &mut result); result } - fn cmt_to_str(&self, cmt: mc::cmt) -> ~str { + pub fn cmt_to_str(&self, cmt: mc::cmt) -> ~str { let mc = &mc::mem_categorization_ctxt {tcx: self.tcx, method_map: self.method_map}; mc.cmt_to_str(cmt) } - fn mut_to_str(&self, mutbl: ast::mutability) -> ~str { + pub fn mut_to_str(&self, mutbl: ast::mutability) -> ~str { let mc = &mc::mem_categorization_ctxt {tcx: self.tcx, method_map: self.method_map}; mc.mut_to_str(mutbl) } - fn mut_to_keyword(&self, mutbl: ast::mutability) -> &'static str { + pub fn mut_to_keyword(&self, mutbl: ast::mutability) -> &'static str { match mutbl { ast::m_imm => "", ast::m_const => "const", diff --git a/src/librustc/middle/borrowck/move_data.rs b/src/librustc/middle/borrowck/move_data.rs new file mode 100644 index 0000000000000..2443c19ac97c5 --- /dev/null +++ b/src/librustc/middle/borrowck/move_data.rs @@ -0,0 +1,605 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/*! + +Data structures used for tracking moves. Please see the extensive +comments in the section "Moves and initialization" and in `doc.rs`. + +*/ + +use core::prelude::*; + +use core::hashmap::{HashMap, HashSet}; +use core::uint; +use middle::borrowck::*; +use middle::dataflow::DataFlowContext; +use middle::dataflow::DataFlowOperator; +use middle::ty; +use middle::typeck; +use syntax::ast; +use syntax::ast_util; +use syntax::codemap::span; +use syntax::opt_vec::OptVec; +use syntax::opt_vec; +use util::ppaux::Repr; + +pub struct MoveData { + /// Move paths. See section "Move paths" in `doc.rs`. + paths: ~[MovePath], + + /// Cache of loan path to move path index, for easy lookup. + path_map: HashMap<@LoanPath, MovePathIndex>, + + /// Each move or uninitialized variable gets an entry here. + moves: ~[Move], + + /// Assignments to a variable, like `x = foo`. These are assigned + /// bits for dataflow, since we must track them to ensure that + /// immutable variables are assigned at most once along each path. + var_assignments: ~[Assignment], + + /// Assignments to a path, like `x.f = foo`. These are not + /// assigned dataflow bits, but we track them because they still + /// kill move bits. + path_assignments: ~[Assignment], + assignee_ids: HashSet, +} + +pub struct FlowedMoveData { + move_data: @mut MoveData, + // ^~~~~~~~~~~~~ + // It makes me sad to use @mut here, except that due to + // the visitor design, this is what gather_loans + // must produce. + + dfcx_moves: MoveDataFlow, + + // We could (and maybe should, for efficiency) combine both move + // and assign data flow into one, but this way it's easier to + // distinguish the bits that correspond to moves and assignments. + dfcx_assign: AssignDataFlow +} + +/// Index into `MoveData.paths`, used like a pointer +#[deriving(Eq)] +pub struct MovePathIndex(uint); + +static InvalidMovePathIndex: MovePathIndex = + MovePathIndex(uint::max_value); + +/// Index into `MoveData.moves`, used like a pointer +#[deriving(Eq)] +pub struct MoveIndex(uint); + +static InvalidMoveIndex: MoveIndex = + MoveIndex(uint::max_value); + +pub struct MovePath { + /// Loan path corresponding to this move path + loan_path: @LoanPath, + + /// Parent pointer, `InvalidMovePathIndex` if root + parent: MovePathIndex, + + /// Head of linked list of moves to this path, + /// `InvalidMoveIndex` if not moved + first_move: MoveIndex, + + /// First node in linked list of children, `InvalidMovePathIndex` if leaf + first_child: MovePathIndex, + + /// Next node in linked list of parent's children (siblings), + /// `InvalidMovePathIndex` if none. + next_sibling: MovePathIndex, +} + +pub enum MoveKind { + Declared, // When declared, variables start out "moved". + MoveExpr(@ast::expr), // Expression or binding that moves a variable + MovePat(@ast::pat), // By-move binding + Captured(@ast::expr), // Closure creation that moves a value +} + +pub struct Move { + /// Path being moved. + path: MovePathIndex, + + /// id of node that is doing the move. + id: ast::node_id, + + /// Kind of move, for error messages. + kind: MoveKind, + + /// Next node in linked list of moves from `path`, or `InvalidMoveIndex` + next_move: MoveIndex, +} + +pub struct Assignment { + /// Path being assigned. + path: MovePathIndex, + + /// id where assignment occurs + id: ast::node_id, + + /// span of node where assignment occurs + span: span, +} + +pub struct MoveDataFlowOperator; +pub type MoveDataFlow = DataFlowContext; + +pub struct AssignDataFlowOperator; +pub type AssignDataFlow = DataFlowContext; + +impl MoveData { + pub fn new() -> MoveData { + MoveData { + paths: ~[], + path_map: HashMap::new(), + moves: ~[], + path_assignments: ~[], + var_assignments: ~[], + assignee_ids: HashSet::new(), + } + } + + fn path<'a>(&'a self, index: MovePathIndex) -> &'a MovePath { + //! Type safe indexing operator + &self.paths[*index] + } + + fn mut_path<'a>(&'a mut self, index: MovePathIndex) -> &'a mut MovePath { + //! Type safe indexing operator + &mut self.paths[*index] + } + + fn move<'a>(&'a self, index: MoveIndex) -> &'a Move { + //! Type safe indexing operator + &self.moves[*index] + } + + fn is_var_path(&self, index: MovePathIndex) -> bool { + //! True if `index` refers to a variable + self.path(index).parent == InvalidMovePathIndex + } + + pub fn move_path(&mut self, + tcx: ty::ctxt, + lp: @LoanPath) -> MovePathIndex { + /*! + * Returns the existing move path index for `lp`, if any, + * and otherwise adds a new index for `lp` and any of its + * base paths that do not yet have an index. + */ + + match self.path_map.find(&lp) { + Some(&index) => { + return index; + } + None => {} + } + + let index = match *lp { + LpVar(*) => { + let index = MovePathIndex(self.paths.len()); + + self.paths.push(MovePath { + loan_path: lp, + parent: InvalidMovePathIndex, + first_move: InvalidMoveIndex, + first_child: InvalidMovePathIndex, + next_sibling: InvalidMovePathIndex, + }); + + index + } + + LpExtend(base, _, _) => { + let parent_index = self.move_path(tcx, base); + let index = MovePathIndex(self.paths.len()); + + let next_sibling = self.path(parent_index).first_child; + self.mut_path(parent_index).first_child = index; + + self.paths.push(MovePath { + loan_path: lp, + parent: parent_index, + first_move: InvalidMoveIndex, + first_child: InvalidMovePathIndex, + next_sibling: next_sibling, + }); + + index + } + }; + + debug!("move_path(lp=%s, index=%?)", + lp.repr(tcx), + index); + + assert_eq!(*index, self.paths.len() - 1); + self.path_map.insert(lp, index); + return index; + } + + fn existing_move_path(&self, + lp: @LoanPath) + -> Option { + self.path_map.find_copy(&lp) + } + + fn existing_base_paths(&self, + lp: @LoanPath) + -> OptVec { + let mut result = opt_vec::Empty; + self.add_existing_base_paths(lp, &mut result); + result + } + + fn add_existing_base_paths(&self, + lp: @LoanPath, + result: &mut OptVec) { + /*! + * Adds any existing move path indices for `lp` and any base + * paths of `lp` to `result`, but does not add new move paths + */ + + match self.path_map.find_copy(&lp) { + Some(index) => { + for self.each_base_path(index) |p| { + result.push(p); + } + } + None => { + match *lp { + LpVar(*) => { } + LpExtend(b, _, _) => { + self.add_existing_base_paths(b, result); + } + } + } + } + + } + + pub fn add_move(&mut self, + tcx: ty::ctxt, + lp: @LoanPath, + id: ast::node_id, + kind: MoveKind) { + /*! + * Adds a new move entry for a move of `lp` that occurs at + * location `id` with kind `kind`. + */ + + debug!("add_move(lp=%s, id=%?, kind=%?)", + lp.repr(tcx), + id, + kind); + + let path_index = self.move_path(tcx, lp); + let move_index = MoveIndex(self.moves.len()); + + let next_move = self.path(path_index).first_move; + self.mut_path(path_index).first_move = move_index; + + self.moves.push(Move { + path: path_index, + id: id, + kind: kind, + next_move: next_move + }); + } + + pub fn add_assignment(&mut self, + tcx: ty::ctxt, + lp: @LoanPath, + assign_id: ast::node_id, + span: span, + assignee_id: ast::node_id) { + /*! + * Adds a new record for an assignment to `lp` that occurs at + * location `id` with the given `span`. + */ + + debug!("add_assignment(lp=%s, assign_id=%?, assignee_id=%?", + lp.repr(tcx), assign_id, assignee_id); + + let path_index = self.move_path(tcx, lp); + + self.assignee_ids.insert(assignee_id); + + let assignment = Assignment { + path: path_index, + id: assign_id, + span: span, + }; + + if self.is_var_path(path_index) { + debug!("add_assignment[var](lp=%s, assignment=%u, path_index=%?)", + lp.repr(tcx), self.var_assignments.len(), path_index); + + self.var_assignments.push(assignment); + } else { + debug!("add_assignment[path](lp=%s, path_index=%?)", + lp.repr(tcx), path_index); + + self.path_assignments.push(assignment); + } + } + + fn add_gen_kills(&self, + tcx: ty::ctxt, + dfcx_moves: &mut MoveDataFlow, + dfcx_assign: &mut AssignDataFlow) { + /*! + * Adds the gen/kills for the various moves and + * assignments into the provided data flow contexts. + * Moves are generated by moves and killed by assignments and + * scoping. Assignments are generated by assignment to variables and + * killed by scoping. See `doc.rs` for more details. + */ + + for self.moves.eachi |i, move| { + dfcx_moves.add_gen(move.id, i); + } + + for self.var_assignments.eachi |i, assignment| { + dfcx_assign.add_gen(assignment.id, i); + self.kill_moves(assignment.path, assignment.id, dfcx_moves); + } + + for self.path_assignments.each |assignment| { + self.kill_moves(assignment.path, assignment.id, dfcx_moves); + } + + // Kill all moves related to a variable `x` when it goes out + // of scope: + for self.paths.each |path| { + match *path.loan_path { + LpVar(id) => { + let kill_id = tcx.region_maps.encl_scope(id); + let path = *self.path_map.get(&path.loan_path); + self.kill_moves(path, kill_id, dfcx_moves); + } + LpExtend(*) => {} + } + } + + // Kill all assignments when the variable goes out of scope: + for self.var_assignments.eachi |assignment_index, assignment| { + match *self.path(assignment.path).loan_path { + LpVar(id) => { + let kill_id = tcx.region_maps.encl_scope(id); + dfcx_assign.add_kill(kill_id, assignment_index); + } + LpExtend(*) => { + tcx.sess.bug("Var assignment for non var path"); + } + } + } + } + + fn each_base_path(&self, + index: MovePathIndex, + f: &fn(MovePathIndex) -> bool) + -> bool { + let mut p = index; + while p != InvalidMovePathIndex { + if !f(p) { + return false; + } + p = self.path(p).parent; + } + return true; + } + + fn each_extending_path(&self, + index: MovePathIndex, + f: &fn(MovePathIndex) -> bool) -> bool { + if !f(index) { + return false; + } + + let mut p = self.path(index).first_child; + while p != InvalidMovePathIndex { + if !self.each_extending_path(p, f) { + return false; + } + p = self.path(p).next_sibling; + } + + return true; + } + + fn each_applicable_move(&self, + index0: MovePathIndex, + f: &fn(MoveIndex) -> bool) -> bool { + for self.each_extending_path(index0) |index| { + let mut p = self.path(index).first_move; + while p != InvalidMoveIndex { + if !f(p) { + return false; + } + p = self.move(p).next_move; + } + } + return true; + } + + fn kill_moves(&self, + path: MovePathIndex, + kill_id: ast::node_id, + dfcx_moves: &mut MoveDataFlow) { + for self.each_applicable_move(path) |move_index| { + dfcx_moves.add_kill(kill_id, *move_index); + } + } +} + +impl FlowedMoveData { + pub fn new(move_data: @mut MoveData, + tcx: ty::ctxt, + method_map: typeck::method_map, + id_range: ast_util::id_range, + body: &ast::blk) + -> FlowedMoveData + { + let mut dfcx_moves = + DataFlowContext::new(tcx, + method_map, + MoveDataFlowOperator, + id_range, + move_data.moves.len()); + let mut dfcx_assign = + DataFlowContext::new(tcx, + method_map, + AssignDataFlowOperator, + id_range, + move_data.var_assignments.len()); + move_data.add_gen_kills(tcx, &mut dfcx_moves, &mut dfcx_assign); + dfcx_moves.propagate(body); + dfcx_assign.propagate(body); + FlowedMoveData { + move_data: move_data, + dfcx_moves: dfcx_moves, + dfcx_assign: dfcx_assign, + } + } + + pub fn each_move_of(&self, + id: ast::node_id, + loan_path: @LoanPath, + f: &fn(&Move, @LoanPath) -> bool) + -> bool { + /*! + * Iterates through each move of `loan_path` (or some base path + * of `loan_path`) that *may* have occurred on entry to `id` without + * an intervening assignment. In other words, any moves that + * would invalidate a reference to `loan_path` at location `id`. + */ + + // Bad scenarios: + // + // 1. Move of `a.b.c`, use of `a.b.c` + // 2. Move of `a.b.c`, use of `a.b.c.d` + // 3. Move of `a.b.c`, use of `a` or `a.b` + // + // OK scenario: + // + // 4. move of `a.b.c`, use of `a.b.d` + + let base_indices = self.move_data.existing_base_paths(loan_path); + if base_indices.is_empty() { + return true; + } + + let opt_loan_path_index = self.move_data.existing_move_path(loan_path); + + for self.dfcx_moves.each_bit_on_entry(id) |index| { + let move = &self.move_data.moves[index]; + let moved_path = move.path; + if base_indices.contains(&moved_path) { + // Scenario 1 or 2: `loan_path` or some base path of + // `loan_path` was moved. + if !f(move, self.move_data.path(moved_path).loan_path) { + return false; + } + loop; + } + + for opt_loan_path_index.each |&loan_path_index| { + for self.move_data.each_base_path(moved_path) |p| { + if p == loan_path_index { + // Scenario 3: some extension of `loan_path` + // was moved + if !f(move, self.move_data.path(moved_path).loan_path) { + return false; + } + } + } + } + } + return true; + } + + pub fn is_assignee(&self, + id: ast::node_id) + -> bool { + //! True if `id` is the id of the LHS of an assignment + + self.move_data.assignee_ids.contains(&id) + } + + pub fn each_assignment_of(&self, + id: ast::node_id, + loan_path: @LoanPath, + f: &fn(&Assignment) -> bool) + -> bool { + /*! + * Iterates through every assignment to `loan_path` that + * may have occurred on entry to `id`. `loan_path` must be + * a single variable. + */ + + let loan_path_index = { + match self.move_data.existing_move_path(loan_path) { + Some(i) => i, + None => { + // if there were any assignments, it'd have an index + return true; + } + } + }; + + for self.dfcx_assign.each_bit_on_entry(id) |index| { + let assignment = &self.move_data.var_assignments[index]; + if assignment.path == loan_path_index && !f(assignment) { + return false; + } + } + return true; + } +} + +impl DataFlowOperator for MoveDataFlowOperator { + #[inline(always)] + fn initial_value(&self) -> bool { + false // no loans in scope by default + } + + #[inline(always)] + fn join(&self, succ: uint, pred: uint) -> uint { + succ | pred // moves from both preds are in scope + } + + #[inline(always)] + fn walk_closures(&self) -> bool { + true + } +} + +impl DataFlowOperator for AssignDataFlowOperator { + #[inline(always)] + fn initial_value(&self) -> bool { + false // no assignments in scope by default + } + + #[inline(always)] + fn join(&self, succ: uint, pred: uint) -> uint { + succ | pred // moves from both preds are in scope + } + + #[inline(always)] + fn walk_closures(&self) -> bool { + true + } +} diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs index faa489e5763f6..0cffc9c52c22b 100644 --- a/src/librustc/middle/check_const.rs +++ b/src/librustc/middle/check_const.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use driver::session::Session; use middle::resolve; use middle::ty; @@ -89,14 +91,14 @@ pub fn check_expr(sess: Session, v: visit::vt) { if is_const { match e.node { - expr_unary(deref, _) => { } - expr_unary(box(_), _) | expr_unary(uniq(_), _) => { + expr_unary(_, deref, _) => { } + expr_unary(_, box(_), _) | expr_unary(_, uniq(_), _) => { sess.span_err(e.span, "disallowed operator in constant expression"); return; } expr_lit(@codemap::spanned {node: lit_str(_), _}) => { } - expr_binary(_, _, _) | expr_unary(_, _) => { + expr_binary(*) | expr_unary(*) => { if method_map.contains_key(&e.id) { sess.span_err(e.span, "user-defined operators are not \ allowed in constant expressions"); @@ -108,7 +110,7 @@ pub fn check_expr(sess: Session, if !ty::type_is_numeric(ety) && !ty::type_is_unsafe_ptr(ety) { sess.span_err(e.span, ~"can not cast to `" + ppaux::ty_to_str(tcx, ety) + - ~"` in a constant expression"); + "` in a constant expression"); } } expr_path(pth) => { diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index d859e03811f7f..b50c158f37a1c 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use middle::const_eval::{compare_const_vals, lookup_const_by_id}; use middle::const_eval::{eval_const_expr, const_val, const_bool}; use middle::pat_util::*; @@ -17,7 +19,9 @@ use middle::typeck::method_map; use middle::moves; use util::ppaux::ty_to_str; -use std::sort; +use core::uint; +use core::vec; +use extra::sort; use syntax::ast::*; use syntax::ast_util::{unguarded_pat, walk_pat}; use syntax::codemap::{span, dummy_sp, spanned}; @@ -129,7 +133,7 @@ pub fn raw_pat(p: @pat) -> @pat { pub fn check_exhaustive(cx: @MatchCheckCtxt, sp: span, pats: ~[@pat]) { assert!((!pats.is_empty())); - let ext = match is_useful(cx, &pats.map(|p| ~[*p]), ~[wild()]) { + let ext = match is_useful(cx, &pats.map(|p| ~[*p]), [wild()]) { not_useful => { // This is good, wildcard pattern isn't reachable return; @@ -169,7 +173,7 @@ pub fn check_exhaustive(cx: @MatchCheckCtxt, sp: span, pats: ~[@pat]) { } }; let msg = ~"non-exhaustive patterns" + match ext { - Some(ref s) => ~": " + **s + ~" not covered", + Some(ref s) => ~": " + **s + " not covered", None => ~"" }; cx.tcx.sess.span_err(sp, msg); @@ -376,7 +380,8 @@ pub fn missing_ctor(cx: @MatchCheckCtxt, } ty::ty_nil => None, ty::ty_bool => { - let mut true_found = false, false_found = false; + let mut true_found = false; + let mut false_found = false; for m.each |r| { match pat_ctor_id(cx, r[0]) { None => (), @@ -498,10 +503,29 @@ pub fn specialize(cx: @MatchCheckCtxt, lookup_const_by_id(cx.tcx, did).get(); let e_v = eval_const_expr(cx.tcx, const_expr); let match_ = match *ctor_id { - val(ref v) => compare_const_vals(&e_v, v) == 0, + val(ref v) => { + match compare_const_vals(&e_v, v) { + Some(val1) => (val1 == 0), + None => { + cx.tcx.sess.span_err(pat_span, + "mismatched types between arms"); + false + } + } + }, range(ref c_lo, ref c_hi) => { - compare_const_vals(c_lo, &e_v) >= 0 && - compare_const_vals(c_hi, &e_v) <= 0 + let m1 = compare_const_vals(c_lo, &e_v); + let m2 = compare_const_vals(c_hi, &e_v); + match (m1, m2) { + (Some(val1), Some(val2)) => { + (val1 >= 0 && val2 <= 0) + } + _ => { + cx.tcx.sess.span_err(pat_span, + "mismatched types between ranges"); + false + } + } } single => true, _ => fail!("type error") @@ -529,10 +553,26 @@ pub fn specialize(cx: @MatchCheckCtxt, lookup_const_by_id(cx.tcx, did).get(); let e_v = eval_const_expr(cx.tcx, const_expr); let match_ = match *ctor_id { - val(ref v) => compare_const_vals(&e_v, v) == 0, + val(ref v) => + match compare_const_vals(&e_v, v) { + Some(val1) => (val1 == 0), + None => { + cx.tcx.sess.span_err(pat_span, + "mismatched types between arms"); + false + } + }, range(ref c_lo, ref c_hi) => { - compare_const_vals(c_lo, &e_v) >= 0 && - compare_const_vals(c_hi, &e_v) <= 0 + let m1 = compare_const_vals(c_lo, &e_v); + let m2 = compare_const_vals(c_hi, &e_v); + match (m1, m2) { + (Some(val1), Some(val2)) => (val1 >= 0 && val2 <= 0), + _ => { + cx.tcx.sess.span_err(pat_span, + "mismatched types between ranges"); + false + } + } } single => true, _ => fail!("type error") @@ -585,7 +625,8 @@ pub fn specialize(cx: @MatchCheckCtxt, } _ => { // Grab the class data that we care about. - let class_fields, class_id; + let class_fields; + let class_id; match ty::get(left_ty).sty { ty::ty_struct(cid, _) => { class_id = cid; @@ -619,10 +660,27 @@ pub fn specialize(cx: @MatchCheckCtxt, pat_lit(expr) => { let e_v = eval_const_expr(cx.tcx, expr); let match_ = match *ctor_id { - val(ref v) => compare_const_vals(&e_v, v) == 0, + val(ref v) => { + match compare_const_vals(&e_v, v) { + Some(val1) => val1 == 0, + None => { + cx.tcx.sess.span_err(pat_span, + "mismatched types between arms"); + false + } + } + }, range(ref c_lo, ref c_hi) => { - compare_const_vals(c_lo, &e_v) >= 0 && - compare_const_vals(c_hi, &e_v) <= 0 + let m1 = compare_const_vals(c_lo, &e_v); + let m2 = compare_const_vals(c_hi, &e_v); + match (m1, m2) { + (Some(val1), Some(val2)) => (val1 >= 0 && val2 <= 0), + _ => { + cx.tcx.sess.span_err(pat_span, + "mismatched types between ranges"); + false + } + } } single => true, _ => fail!("type error") @@ -637,12 +695,23 @@ pub fn specialize(cx: @MatchCheckCtxt, single => return Some(vec::to_owned(r.tail())), _ => fail!("type error") }; - let v_lo = eval_const_expr(cx.tcx, lo), - v_hi = eval_const_expr(cx.tcx, hi); - let match_ = compare_const_vals(&c_lo, &v_lo) >= 0 && - compare_const_vals(&c_hi, &v_hi) <= 0; - if match_ { Some(vec::to_owned(r.tail())) } else { None } - } + let v_lo = eval_const_expr(cx.tcx, lo); + let v_hi = eval_const_expr(cx.tcx, hi); + + let m1 = compare_const_vals(&c_lo, &v_lo); + let m2 = compare_const_vals(&c_hi, &v_hi); + match (m1, m2) { + (Some(val1), Some(val2)) if val1 >= 0 && val2 <= 0 => { + Some(vec::to_owned(r.tail())) + }, + (Some(_), Some(_)) => None, + _ => { + cx.tcx.sess.span_err(pat_span, + "mismatched types between ranges"); + None + } + } + } pat_vec(before, slice, after) => { match *ctor_id { vec(_) => { @@ -762,7 +831,6 @@ pub fn check_legality_of_move_bindings(cx: @MatchCheckCtxt, for pats.each |pat| { do pat_bindings(def_map, *pat) |bm, id, span, _path| { match bm { - bind_by_copy => {} bind_by_ref(_) => { by_ref_span = Some(span); } @@ -803,7 +871,7 @@ pub fn check_legality_of_move_bindings(cx: @MatchCheckCtxt, if !any_by_move { return; } // pointless micro-optimization for pats.each |pat| { - do walk_pat(*pat) |p| { + for walk_pat(*pat) |p| { if pat_is_binding(def_map, p) { match p.node { pat_ident(_, _, sub) => { @@ -821,66 +889,5 @@ pub fn check_legality_of_move_bindings(cx: @MatchCheckCtxt, } } } - - // Now check to ensure that any move binding is not behind an - // @ or &, or within a struct with a destructor. This is - // always illegal. - let vt = visit::mk_vt(@visit::Visitor { - visit_pat: |pat, (behind_bad_pointer, behind_dtor_struct): (bool, bool), v| { - match pat.node { - pat_ident(_, _, sub) => { - debug!("(check legality of move) checking pat \ - ident with behind_bad_pointer %? and behind_dtor_struct %?", - behind_bad_pointer, behind_dtor_struct); - - if behind_bad_pointer || behind_dtor_struct && - cx.moves_map.contains(&pat.id) - { - let msg = if behind_bad_pointer { - "by-move pattern bindings may not occur behind @ or & bindings" - } else { - "cannot bind by-move within struct (it has a destructor)" - }; - cx.tcx.sess.span_err(pat.span, msg); - } - - match sub { - None => {} - Some(subpat) => { - (v.visit_pat)(subpat, - (behind_bad_pointer, behind_dtor_struct), - v); - } - } - } - - pat_box(subpat) | pat_region(subpat) => { - (v.visit_pat)(subpat, (true, behind_dtor_struct), v); - } - - pat_struct(_, ref fields, _) => { - let behind_dtor_struct = behind_dtor_struct || - (match cx.tcx.def_map.find(&pat.id) { - Some(&def_struct(id)) => { - ty::has_dtor(cx.tcx, id) - } - _ => false - }); - debug!("(check legality of move) checking pat \ - struct with behind_bad_pointer %? and behind_dtor_struct %?", - behind_bad_pointer, behind_dtor_struct); - - for fields.each |fld| { - (v.visit_pat)(fld.pat, (behind_bad_pointer, - behind_dtor_struct), v) - } - } - - _ => visit::visit_pat(pat, (behind_bad_pointer, behind_dtor_struct), v) - } - }, - .. *visit::default_visitor::<(bool, bool)>() - }); - (vt.visit_pat)(*pat, (false, false), vt); } } diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index 6cc4409aee660..7e8e5bffb5705 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use metadata::csearch; use middle::astencode; use middle::ty; @@ -16,7 +18,9 @@ use middle; use syntax::{ast, ast_map, ast_util, visit}; use syntax::ast::*; +use core::float; use core::hashmap::{HashMap, HashSet}; +use core::vec; // // This pass classifies expressions by their constant-ness. @@ -89,12 +93,12 @@ pub fn classify(e: @expr, } ast::expr_copy(inner) | - ast::expr_unary(_, inner) | + ast::expr_unary(_, _, inner) | ast::expr_paren(inner) => { classify(inner, tcx) } - ast::expr_binary(_, a, b) => { + ast::expr_binary(_, _, a, b) => { join(classify(a, tcx), classify(b, tcx)) } @@ -116,11 +120,7 @@ pub fn classify(e: @expr, ast::expr_struct(_, ref fs, None) => { let cs = do vec::map((*fs)) |f| { - if f.node.mutbl == ast::m_imm { - classify(f.node.expr, tcx) - } else { - non_const - } + classify(f.node.expr, tcx) }; join_all(cs) } @@ -141,7 +141,7 @@ pub fn classify(e: @expr, classify(base, tcx) } - ast::expr_index(base, idx) => { + ast::expr_index(_, base, idx) => { join(classify(base, tcx), classify(idx, tcx)) } @@ -251,7 +251,7 @@ pub fn eval_const_expr_partial(tcx: middle::ty::ctxt, e: @expr) use middle::ty; fn fromb(b: bool) -> Result { Ok(const_int(b as i64)) } match e.node { - expr_unary(neg, inner) => { + expr_unary(_, neg, inner) => { match eval_const_expr_partial(tcx, inner) { Ok(const_float(f)) => Ok(const_float(-f)), Ok(const_int(i)) => Ok(const_int(-i)), @@ -261,7 +261,7 @@ pub fn eval_const_expr_partial(tcx: middle::ty::ctxt, e: @expr) ref err => (/*bad*/copy *err) } } - expr_unary(not, inner) => { + expr_unary(_, not, inner) => { match eval_const_expr_partial(tcx, inner) { Ok(const_int(i)) => Ok(const_int(!i)), Ok(const_uint(i)) => Ok(const_uint(!i)), @@ -269,7 +269,7 @@ pub fn eval_const_expr_partial(tcx: middle::ty::ctxt, e: @expr) _ => Err(~"Not on float or string") } } - expr_binary(op, a, b) => { + expr_binary(_, op, a, b) => { match (eval_const_expr_partial(tcx, a), eval_const_expr_partial(tcx, b)) { (Ok(const_float(a)), Ok(const_float(b))) => { @@ -420,65 +420,73 @@ pub fn lit_to_const(lit: @lit) -> const_val { } } -pub fn compare_const_vals(a: &const_val, b: &const_val) -> int { +pub fn compare_const_vals(a: &const_val, b: &const_val) -> Option { match (a, b) { (&const_int(a), &const_int(b)) => { if a == b { - 0 + Some(0) } else if a < b { - -1 + Some(-1) } else { - 1 + Some(1) } } (&const_uint(a), &const_uint(b)) => { if a == b { - 0 + Some(0) } else if a < b { - -1 + Some(-1) } else { - 1 + Some(1) } } (&const_float(a), &const_float(b)) => { if a == b { - 0 + Some(0) } else if a < b { - -1 + Some(-1) } else { - 1 + Some(1) } } (&const_str(ref a), &const_str(ref b)) => { if (*a) == (*b) { - 0 + Some(0) } else if (*a) < (*b) { - -1 + Some(-1) } else { - 1 + Some(1) } } (&const_bool(a), &const_bool(b)) => { if a == b { - 0 + Some(0) } else if a < b { - -1 + Some(-1) } else { - 1 + Some(1) } } - _ => fail!("compare_const_vals: ill-typed comparison") + _ => { + None + } } } -pub fn compare_lit_exprs(tcx: middle::ty::ctxt, a: @expr, b: @expr) -> int { - compare_const_vals(&eval_const_expr(tcx, a), &eval_const_expr(tcx, b)) +pub fn compare_lit_exprs(tcx: middle::ty::ctxt, a: @expr, b: @expr) -> Option { + compare_const_vals(&eval_const_expr(tcx, a), &eval_const_expr(tcx, b)) } -pub fn lit_expr_eq(tcx: middle::ty::ctxt, a: @expr, b: @expr) -> bool { - compare_lit_exprs(tcx, a, b) == 0 +pub fn lit_expr_eq(tcx: middle::ty::ctxt, a: @expr, b: @expr) -> Option { + match compare_lit_exprs(tcx, a, b) { + Some(val) => Some(val == 0), + None => None, + } } -pub fn lit_eq(a: @lit, b: @lit) -> bool { - compare_const_vals(&lit_to_const(a), &lit_to_const(b)) == 0 +pub fn lit_eq(a: @lit, b: @lit) -> Option { + match compare_const_vals(&lit_to_const(a), &lit_to_const(b)) { + Some(val) => Some(val == 0), + None => None, + } } diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs index 31d22b76800c1..349deef2998c6 100644 --- a/src/librustc/middle/dataflow.rs +++ b/src/librustc/middle/dataflow.rs @@ -17,8 +17,12 @@ */ use core::prelude::*; + use core::cast; +use core::io; +use core::str; use core::uint; +use core::vec; use syntax::ast; use syntax::ast_util; use syntax::ast_util::id_range; @@ -182,20 +186,6 @@ impl DataFlowContext { } - #[cfg(stage0)] - pub fn each_bit_on_entry(&self, - id: ast::node_id, - f: &fn(uint) -> bool) { - //! Iterates through each bit that is set on entry to `id`. - //! Only useful after `propagate()` has been called. - - let (start, end) = self.compute_id_range(id); - let on_entry = vec::slice(self.on_entry, start, end); - debug!("each_bit_on_entry(id=%?, on_entry=%s)", - id, bits_to_str(on_entry)); - self.each_bit(on_entry, f); - } - #[cfg(not(stage0))] pub fn each_bit_on_entry(&self, id: ast::node_id, f: &fn(uint) -> bool) -> bool { @@ -209,19 +199,6 @@ impl DataFlowContext { self.each_bit(on_entry, f) } - #[cfg(stage0)] - pub fn each_gen_bit(&self, - id: ast::node_id, - f: &fn(uint) -> bool) { - //! Iterates through each bit in the gen set for `id`. - - let (start, end) = self.compute_id_range(id); - let gens = vec::slice(self.gens, start, end); - debug!("each_gen_bit(id=%?, gens=%s)", - id, bits_to_str(gens)); - self.each_bit(gens, f) - } - #[cfg(not(stage0))] pub fn each_gen_bit(&self, id: ast::node_id, f: &fn(uint) -> bool) -> bool { @@ -234,37 +211,6 @@ impl DataFlowContext { self.each_bit(gens, f) } - #[cfg(stage0)] - fn each_bit(&self, - words: &[uint], - f: &fn(uint) -> bool) { - //! Helper for iterating over the bits in a bit set. - - for words.eachi |word_index, &word| { - if word != 0 { - let base_index = word_index * uint::bits; - for uint::range(0, uint::bits) |offset| { - let bit = 1 << offset; - if (word & bit) != 0 { - // NB: we round up the total number of bits - // that we store in any given bit set so that - // it is an even multiple of uint::bits. This - // means that there may be some stray bits at - // the end that do not correspond to any - // actual value. So before we callback, check - // whether the bit_index is greater than the - // actual value the user specified and stop - // iterating if so. - let bit_index = base_index + offset; - if bit_index >= self.bits_per_id || !f(bit_index) { - return; - } - } - } - } - } - } - #[cfg(not(stage0))] fn each_bit(&self, words: &[uint], f: &fn(uint) -> bool) -> bool { @@ -416,7 +362,7 @@ impl<'self, O:DataFlowOperator> PropagationContext<'self, O> { } ast::stmt_mac(*) => { - self.tcx().sess.span_bug(stmt.span, ~"unexpanded macro"); + self.tcx().sess.span_bug(stmt.span, "unexpanded macro"); } } } @@ -426,11 +372,9 @@ impl<'self, O:DataFlowOperator> PropagationContext<'self, O> { in_out: &mut [uint], loop_scopes: &mut ~[LoopScope]) { match decl.node { - ast::decl_local(ref locals) => { - for locals.each |local| { - self.walk_pat(local.node.pat, in_out, loop_scopes); - self.walk_opt_expr(local.node.init, in_out, loop_scopes); - } + ast::decl_local(local) => { + self.walk_pat(local.node.pat, in_out, loop_scopes); + self.walk_opt_expr(local.node.init, in_out, loop_scopes); } ast::decl_item(_) => {} @@ -693,7 +637,7 @@ impl<'self, O:DataFlowOperator> PropagationContext<'self, O> { } ast::expr_assign(l, r) | - ast::expr_assign_op(_, l, r) => { + ast::expr_assign_op(_, _, l, r) => { self.walk_expr(r, in_out, loop_scopes); self.walk_expr(l, in_out, loop_scopes); } @@ -708,30 +652,30 @@ impl<'self, O:DataFlowOperator> PropagationContext<'self, O> { } ast::expr_struct(_, ref fields, with_expr) => { - self.walk_opt_expr(with_expr, in_out, loop_scopes); for fields.each |field| { self.walk_expr(field.node.expr, in_out, loop_scopes); } + self.walk_opt_expr(with_expr, in_out, loop_scopes); } ast::expr_call(f, ref args, _) => { - self.walk_call(expr.callee_id, expr.id, + self.walk_call(f.id, expr.id, f, *args, in_out, loop_scopes); } - ast::expr_method_call(rcvr, _, _, ref args, _) => { - self.walk_call(expr.callee_id, expr.id, + ast::expr_method_call(callee_id, rcvr, _, _, ref args, _) => { + self.walk_call(callee_id, expr.id, rcvr, *args, in_out, loop_scopes); } - ast::expr_index(l, r) | - ast::expr_binary(_, l, r) if self.is_method_call(expr) => { - self.walk_call(expr.callee_id, expr.id, + ast::expr_index(callee_id, l, r) | + ast::expr_binary(callee_id, _, l, r) if self.is_method_call(expr) => { + self.walk_call(callee_id, expr.id, l, [r], in_out, loop_scopes); } - ast::expr_unary(_, e) if self.is_method_call(expr) => { - self.walk_call(expr.callee_id, expr.id, + ast::expr_unary(callee_id, _, e) if self.is_method_call(expr) => { + self.walk_call(callee_id, expr.id, e, [], in_out, loop_scopes); } @@ -739,7 +683,7 @@ impl<'self, O:DataFlowOperator> PropagationContext<'self, O> { self.walk_exprs(*exprs, in_out, loop_scopes); } - ast::expr_binary(op, l, r) if ast_util::lazy_binop(op) => { + ast::expr_binary(_, op, l, r) if ast_util::lazy_binop(op) => { self.walk_expr(l, in_out, loop_scopes); let temp = reslice(in_out).to_vec(); self.walk_expr(r, in_out, loop_scopes); @@ -747,8 +691,8 @@ impl<'self, O:DataFlowOperator> PropagationContext<'self, O> { } ast::expr_log(l, r) | - ast::expr_index(l, r) | - ast::expr_binary(_, l, r) => { + ast::expr_index(_, l, r) | + ast::expr_binary(_, _, l, r) => { self.walk_exprs([l, r], in_out, loop_scopes); } @@ -762,7 +706,7 @@ impl<'self, O:DataFlowOperator> PropagationContext<'self, O> { ast::expr_loop_body(e) | ast::expr_do_body(e) | ast::expr_cast(e, _) | - ast::expr_unary(_, e) | + ast::expr_unary(_, _, e) | ast::expr_paren(e) | ast::expr_vstore(e, _) | ast::expr_field(e, _, _) => { @@ -783,7 +727,7 @@ impl<'self, O:DataFlowOperator> PropagationContext<'self, O> { } ast::expr_mac(*) => { - self.tcx().sess.span_bug(expr.span, ~"unexpanded macro"); + self.tcx().sess.span_bug(expr.span, "unexpanded macro"); } } @@ -883,7 +827,7 @@ impl<'self, O:DataFlowOperator> PropagationContext<'self, O> { debug!("DataFlowContext::walk_pat(pat=%s, in_out=%s)", pat.repr(self.dfcx.tcx), bits_to_str(reslice(in_out))); - do ast_util::walk_pat(pat) |p| { + for ast_util::walk_pat(pat) |p| { debug!(" p.id=%? in_out=%s", p.id, bits_to_str(reslice(in_out))); self.merge_with_entry_set(p.id, in_out); self.dfcx.apply_gen_kill(p.id, in_out); @@ -1062,4 +1006,3 @@ fn reslice<'a>(v: &'a mut [uint]) -> &'a [uint] { cast::transmute(v) } } - diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs new file mode 100644 index 0000000000000..895c6cc477f93 --- /dev/null +++ b/src/librustc/middle/effect.rs @@ -0,0 +1,157 @@ +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Enforces the Rust effect system. Currently there is just one effect, +/// `unsafe`. + +use middle::ty::{ty_bare_fn, ty_closure, ty_ptr}; +use middle::ty; +use middle::typeck::method_map; +use util::ppaux; + +use syntax::ast::{deref, expr_call, expr_inline_asm, expr_method_call}; +use syntax::ast::{expr_unary, node_id, unsafe_blk, unsafe_fn}; +use syntax::ast; +use syntax::codemap::span; +use syntax::visit::{fk_item_fn, fk_method}; +use syntax::visit; + +#[deriving(Eq)] +enum UnsafeContext { + SafeContext, + UnsafeFn, + UnsafeBlock(node_id), +} + +struct Context { + /// The method map. + method_map: method_map, + /// Whether we're in an unsafe context. + unsafe_context: UnsafeContext, +} + +fn type_is_unsafe_function(ty: ty::t) -> bool { + match ty::get(ty).sty { + ty_bare_fn(ref f) => f.purity == unsafe_fn, + ty_closure(ref f) => f.purity == unsafe_fn, + _ => false, + } +} + +pub fn check_crate(tcx: ty::ctxt, + method_map: method_map, + crate: @ast::crate) { + let context = @mut Context { + method_map: method_map, + unsafe_context: SafeContext, + }; + + let require_unsafe: @fn(span: span, + description: &str) = |span, description| { + match context.unsafe_context { + SafeContext => { + // Report an error. + tcx.sess.span_err(span, + fmt!("%s requires unsafe function or block", + description)) + } + UnsafeBlock(block_id) => { + // OK, but record this. + debug!("effect: recording unsafe block as used: %?", block_id); + let _ = tcx.used_unsafe.insert(block_id); + } + UnsafeFn => {} + } + }; + + let visitor = visit::mk_vt(@visit::Visitor { + visit_fn: |fn_kind, fn_decl, block, span, node_id, _, visitor| { + let (is_item_fn, is_unsafe_fn) = match *fn_kind { + fk_item_fn(_, _, purity, _) => (true, purity == unsafe_fn), + fk_method(_, _, method) => (true, method.purity == unsafe_fn), + _ => (false, false), + }; + + let old_unsafe_context = context.unsafe_context; + if is_unsafe_fn { + context.unsafe_context = UnsafeFn + } else if is_item_fn { + context.unsafe_context = SafeContext + } + + visit::visit_fn(fn_kind, + fn_decl, + block, + span, + node_id, + (), + visitor); + + context.unsafe_context = old_unsafe_context + }, + + visit_block: |block, _, visitor| { + let old_unsafe_context = context.unsafe_context; + if block.node.rules == unsafe_blk && + context.unsafe_context == SafeContext { + context.unsafe_context = UnsafeBlock(block.node.id) + } + + visit::visit_block(block, (), visitor); + + context.unsafe_context = old_unsafe_context + }, + + visit_expr: |expr, _, visitor| { + match expr.node { + expr_method_call(callee_id, _, _, _, _, _) => { + let base_type = ty::node_id_to_type(tcx, callee_id); + debug!("effect: method call case, base type is %s", + ppaux::ty_to_str(tcx, base_type)); + if type_is_unsafe_function(base_type) { + require_unsafe(expr.span, + "invocation of unsafe method") + } + } + expr_call(base, _, _) => { + let base_type = ty::node_id_to_type(tcx, base.id); + debug!("effect: call case, base type is %s", + ppaux::ty_to_str(tcx, base_type)); + if type_is_unsafe_function(base_type) { + require_unsafe(expr.span, "call to unsafe function") + } + } + expr_unary(_, deref, base) => { + let base_type = ty::node_id_to_type(tcx, base.id); + debug!("effect: unary case, base type is %s", + ppaux::ty_to_str(tcx, base_type)); + match ty::get(base_type).sty { + ty_ptr(_) => { + require_unsafe(expr.span, + "dereference of unsafe pointer") + } + _ => {} + } + } + expr_inline_asm(*) => { + require_unsafe(expr.span, "use of inline assembly") + } + _ => {} + } + + visit::visit_expr(expr, (), visitor) + }, + + .. *visit::default_visitor() + }); + + visit::visit_crate(crate, (), visitor) +} + diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs index 9ffd0e6f22c3c..b35ec2579d1d9 100644 --- a/src/librustc/middle/entry.rs +++ b/src/librustc/middle/entry.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use driver::session; use driver::session::Session; use syntax::parse::token::special_idents; @@ -78,7 +80,7 @@ fn find_item(item: @item, ctxt: @mut EntryContext, visitor: EntryVisitor) { } else { ctxt.session.span_err( item.span, - ~"multiple 'main' functions"); + "multiple 'main' functions"); } } else { // This isn't main @@ -89,23 +91,23 @@ fn find_item(item: @item, ctxt: @mut EntryContext, visitor: EntryVisitor) { } } - if attrs_contains_name(item.attrs, ~"main") { + if attrs_contains_name(item.attrs, "main") { if ctxt.attr_main_fn.is_none() { ctxt.attr_main_fn = Some((item.id, item.span)); } else { ctxt.session.span_err( item.span, - ~"multiple 'main' functions"); + "multiple 'main' functions"); } } - if attrs_contains_name(item.attrs, ~"start") { + if attrs_contains_name(item.attrs, "start") { if ctxt.start_fn.is_none() { ctxt.start_fn = Some((item.id, item.span)); } else { ctxt.session.span_err( item.span, - ~"multiple 'start' functions"); + "multiple 'start' functions"); } } } @@ -129,22 +131,22 @@ fn configure_main(ctxt: @mut EntryContext) { } else { if !*this.session.building_library { // No main function - this.session.err(~"main function not found"); + this.session.err("main function not found"); if !this.non_main_fns.is_empty() { // There were some functions named 'main' though. Try to give the user a hint. - this.session.note(~"the main function must be defined at the crate level \ - but you have one or more functions named 'main' that are not \ - defined at the crate level. Either move the definition or \ - attach the `#[main]` attribute to override this behavior."); + this.session.note("the main function must be defined at the crate level \ + but you have one or more functions named 'main' that are not \ + defined at the crate level. Either move the definition or \ + attach the `#[main]` attribute to override this behavior."); for this.non_main_fns.each |&(_, span)| { - this.session.span_note(span, ~"here is a function named 'main'"); + this.session.span_note(span, "here is a function named 'main'"); } } this.session.abort_if_errors(); } else { // If we *are* building a library, then we're on android where we still might // optionally want to translate main $4404 - assert!(this.session.targ_cfg.os == session::os_android); + assert_eq!(this.session.targ_cfg.os, session::os_android); } } } diff --git a/src/librustc/middle/freevars.rs b/src/librustc/middle/freevars.rs index 872ad83b7391c..7a57f78d60bb9 100644 --- a/src/librustc/middle/freevars.rs +++ b/src/librustc/middle/freevars.rs @@ -11,10 +11,13 @@ // A pass that annotates for each loops and functions with the free // variables that they contain. +use core::prelude::*; + use middle::resolve; use middle::ty; use core::hashmap::HashMap; +use core::vec; use syntax::codemap::span; use syntax::{ast, ast_util, visit}; diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs index a891e8d3b7f83..48983dcadc8b4 100644 --- a/src/librustc/middle/kind.rs +++ b/src/librustc/middle/kind.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use middle::freevars::freevar_entry; use middle::freevars; use middle::pat_util; @@ -16,6 +18,7 @@ use middle::typeck; use util::ppaux::{Repr, ty_to_str}; use util::ppaux::UserString; +use core::vec; use syntax::ast::*; use syntax::attr::attrs_contains_name; use syntax::codemap::span; @@ -68,7 +71,6 @@ pub fn check_crate(tcx: ty::ctxt, current_item: -1 }; let visit = visit::mk_vt(@visit::Visitor { - visit_arm: check_arm, visit_expr: check_expr, visit_fn: check_fn, visit_ty: check_ty, @@ -122,7 +124,7 @@ fn check_item(item: @item, cx: Context, visitor: visit::vt) { match item.node { item_impl(_, Some(trait_ref), self_type, _) => { match cx.tcx.def_map.find(&trait_ref.ref_id) { - None => cx.tcx.sess.bug(~"trait ref not in def map!"), + None => cx.tcx.sess.bug("trait ref not in def map!"), Some(&trait_def) => { let trait_def_id = ast_util::def_id_of_def(trait_def); if cx.tcx.lang_items.drop_trait() == trait_def_id { @@ -235,27 +237,13 @@ fn check_fn( visit::visit_fn(fk, decl, body, sp, fn_id, cx, v); } -fn check_arm(a: &arm, cx: Context, v: visit::vt) { - for a.pats.each |p| { - do pat_util::pat_bindings(cx.tcx.def_map, *p) |mode, id, span, _pth| { - if mode == bind_by_copy { - let t = ty::node_id_to_type(cx.tcx, id); - let reason = "consider binding with `ref` or `move` instead"; - check_copy(cx, t, span, reason); - } - } - } - visit::visit_arm(a, cx, v); -} - pub fn check_expr(e: @expr, cx: Context, v: visit::vt) { debug!("kind::check_expr(%s)", expr_to_str(e, cx.tcx.sess.intr())); // Handle any kind bounds on type parameters - let type_parameter_id = match e.node { - expr_index(*)|expr_assign_op(*)| - expr_unary(*)|expr_binary(*)|expr_method_call(*) => e.callee_id, - _ => e.id + let type_parameter_id = match e.get_callee_id() { + Some(callee_id) => callee_id, + None => e.id, }; for cx.tcx.node_type_substs.find(&type_parameter_id).each |ts| { let type_param_defs = match e.node { @@ -270,7 +258,7 @@ pub fn check_expr(e: @expr, cx: Context, v: visit::vt) { // Even though the callee_id may have been the id with // node_type_substs, e.id is correct here. ty::method_call_type_param_defs(cx.tcx, cx.method_map, e.id).expect( - ~"non path/method call expr has type substs??") + "non path/method call expr has type substs??") } }; if ts.len() != type_param_defs.len() { @@ -418,7 +406,7 @@ pub fn check_durable(tcx: ty::ctxt, ty: ty::t, sp: span) -> bool { match ty::get(ty).sty { ty::ty_param(*) => { tcx.sess.span_err(sp, "value may contain borrowed \ - pointers; use `'static` bound"); + pointers; add `'static` bound"); } _ => { tcx.sess.span_err(sp, "value may contain borrowed \ diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index e2b4684696a90..798cba236297b 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -19,6 +19,8 @@ // // * Functions called by the compiler itself. +use core::prelude::*; + use driver::session::Session; use metadata::csearch::each_lang_item; use metadata::cstore::iter_crate_data; @@ -34,68 +36,60 @@ pub enum LangItem { ConstTraitLangItem, // 0 CopyTraitLangItem, // 1 OwnedTraitLangItem, // 2 + SizedTraitLangItem, // 3 - DropTraitLangItem, // 3 + DropTraitLangItem, // 4 - AddTraitLangItem, // 4 - SubTraitLangItem, // 5 - MulTraitLangItem, // 6 - DivTraitLangItem, // 7 - RemTraitLangItem, // 8 - NegTraitLangItem, // 9 - NotTraitLangItem, // 10 + AddTraitLangItem, // 5 + SubTraitLangItem, // 6 + MulTraitLangItem, // 7 + DivTraitLangItem, // 8 + RemTraitLangItem, // 9 + NegTraitLangItem, // 10 + NotTraitLangItem, // 11 BitXorTraitLangItem, // 11 - BitAndTraitLangItem, // 12 - BitOrTraitLangItem, // 13 - ShlTraitLangItem, // 14 - ShrTraitLangItem, // 15 - IndexTraitLangItem, // 16 - - EqTraitLangItem, // 17 - OrdTraitLangItem, // 18 - - StrEqFnLangItem, // 19 - UniqStrEqFnLangItem, // 20 - AnnihilateFnLangItem, // 21 - LogTypeFnLangItem, // 22 - FailFnLangItem, // 23 - FailBoundsCheckFnLangItem, // 24 - ExchangeMallocFnLangItem, // 25 - ExchangeFreeFnLangItem, // 26 - MallocFnLangItem, // 27 - FreeFnLangItem, // 28 - BorrowAsImmFnLangItem, // 29 - BorrowAsMutFnLangItem, // 30 - ReturnToMutFnLangItem, // 31 - CheckNotBorrowedFnLangItem, // 32 - StrDupUniqFnLangItem, // 33 - RecordBorrowFnLangItem, // 34 - UnrecordBorrowFnLangItem, // 35 - - StartFnLangItem, // 36 + BitAndTraitLangItem, // 13 + BitOrTraitLangItem, // 14 + ShlTraitLangItem, // 15 + ShrTraitLangItem, // 16 + IndexTraitLangItem, // 17 + + EqTraitLangItem, // 18 + OrdTraitLangItem, // 19 + + StrEqFnLangItem, // 20 + UniqStrEqFnLangItem, // 21 + AnnihilateFnLangItem, // 22 + LogTypeFnLangItem, // 23 + FailFnLangItem, // 24 + FailBoundsCheckFnLangItem, // 25 + ExchangeMallocFnLangItem, // 26 + ExchangeFreeFnLangItem, // 27 + MallocFnLangItem, // 28 + FreeFnLangItem, // 29 + BorrowAsImmFnLangItem, // 30 + BorrowAsMutFnLangItem, // 31 + ReturnToMutFnLangItem, // 32 + CheckNotBorrowedFnLangItem, // 33 + StrDupUniqFnLangItem, // 34 + RecordBorrowFnLangItem, // 35 + UnrecordBorrowFnLangItem, // 36 + + StartFnLangItem, // 37 } pub struct LanguageItems { - items: [Option, ..37] + items: [Option, ..38] } -pub impl LanguageItems { +impl LanguageItems { pub fn new() -> LanguageItems { LanguageItems { - items: [ None, ..37 ] + items: [ None, ..38 ] } } - #[cfg(stage0)] - fn each_item(&self, f: &fn(def_id: def_id, i: uint) -> bool) { - for self.items.eachi |i, &item| { - if !f(item.get(), i) { - break; - } - } - } - #[cfg(not(stage0))] - fn each_item(&self, f: &fn(def_id: def_id, i: uint) -> bool) -> bool { + pub fn each_item(&self, f: &fn(def_id: def_id, i: uint) -> bool) -> bool { self.items.eachi(|i, &item| f(item.get(), i)) } @@ -104,44 +98,45 @@ pub impl LanguageItems { 0 => "const", 1 => "copy", 2 => "owned", - - 3 => "drop", - - 4 => "add", - 5 => "sub", - 6 => "mul", - 7 => "div", - 8 => "rem", - 9 => "neg", - 10 => "not", - 11 => "bitxor", - 12 => "bitand", - 13 => "bitor", - 14 => "shl", - 15 => "shr", - 16 => "index", - 17 => "eq", - 18 => "ord", - - 19 => "str_eq", - 20 => "uniq_str_eq", - 21 => "annihilate", - 22 => "log_type", - 23 => "fail_", - 24 => "fail_bounds_check", - 25 => "exchange_malloc", - 26 => "exchange_free", - 27 => "malloc", - 28 => "free", - 29 => "borrow_as_imm", - 30 => "borrow_as_mut", - 31 => "return_to_mut", - 32 => "check_not_borrowed", - 33 => "strdup_uniq", - 34 => "record_borrow", - 35 => "unrecord_borrow", - - 36 => "start", + 3 => "sized", + + 4 => "drop", + + 5 => "add", + 6 => "sub", + 7 => "mul", + 8 => "div", + 9 => "rem", + 10 => "neg", + 11 => "not", + 12 => "bitxor", + 13 => "bitand", + 14 => "bitor", + 15 => "shl", + 16 => "shr", + 17 => "index", + 18 => "eq", + 19 => "ord", + + 20 => "str_eq", + 21 => "uniq_str_eq", + 22 => "annihilate", + 23 => "log_type", + 24 => "fail_", + 25 => "fail_bounds_check", + 26 => "exchange_malloc", + 27 => "exchange_free", + 28 => "malloc", + 29 => "free", + 30 => "borrow_as_imm", + 31 => "borrow_as_mut", + 32 => "return_to_mut", + 33 => "check_not_borrowed", + 34 => "strdup_uniq", + 35 => "record_borrow", + 36 => "unrecord_borrow", + + 37 => "start", _ => "???" } @@ -158,6 +153,9 @@ pub impl LanguageItems { pub fn owned_trait(&const self) -> def_id { self.items[OwnedTraitLangItem as uint].get() } + pub fn sized_trait(&const self) -> def_id { + self.items[SizedTraitLangItem as uint].get() + } pub fn drop_trait(&const self) -> def_id { self.items[DropTraitLangItem as uint].get() @@ -274,6 +272,7 @@ fn LanguageItemCollector(crate: @crate, item_refs.insert(@~"const", ConstTraitLangItem as uint); item_refs.insert(@~"copy", CopyTraitLangItem as uint); item_refs.insert(@~"owned", OwnedTraitLangItem as uint); + item_refs.insert(@~"sized", SizedTraitLangItem as uint); item_refs.insert(@~"drop", DropTraitLangItem as uint); @@ -332,9 +331,10 @@ struct LanguageItemCollector { item_refs: HashMap<@~str, uint>, } -pub impl LanguageItemCollector { - fn match_and_collect_meta_item(&mut self, item_def_id: def_id, - meta_item: @meta_item) { +impl LanguageItemCollector { + pub fn match_and_collect_meta_item(&mut self, + item_def_id: def_id, + meta_item: @meta_item) { match meta_item.node { meta_name_value(key, literal) => { match literal.node { @@ -348,7 +348,7 @@ pub impl LanguageItemCollector { } } - fn collect_item(&mut self, item_index: uint, item_def_id: def_id) { + pub fn collect_item(&mut self, item_index: uint, item_def_id: def_id) { // Check for duplicates. match self.items.items[item_index] { Some(original_def_id) if original_def_id != item_def_id => { @@ -364,8 +364,10 @@ pub impl LanguageItemCollector { self.items.items[item_index] = Some(item_def_id); } - fn match_and_collect_item(&mut self, - item_def_id: def_id, key: @~str, value: @~str) { + pub fn match_and_collect_item(&mut self, + item_def_id: def_id, + key: @~str, + value: @~str) { if *key != ~"lang" { return; // Didn't match. } @@ -385,7 +387,7 @@ pub impl LanguageItemCollector { } } - fn collect_local_language_items(&mut self) { + pub fn collect_local_language_items(&mut self) { let this: *mut LanguageItemCollector = &mut *self; visit_crate(self.crate, (), mk_simple_visitor(@SimpleVisitor { visit_item: |item| { @@ -402,7 +404,7 @@ pub impl LanguageItemCollector { })); } - fn collect_external_language_items(&mut self) { + pub fn collect_external_language_items(&mut self) { let crate_store = self.session.cstore; do iter_crate_data(crate_store) |crate_number, _crate_metadata| { for each_lang_item(crate_store, crate_number) @@ -413,7 +415,7 @@ pub impl LanguageItemCollector { } } - fn check_completeness(&self) { + pub fn check_completeness(&self) { for self.item_refs.each |&key, &item_ref| { match self.items.items[item_ref] { None => { @@ -426,7 +428,7 @@ pub impl LanguageItemCollector { } } - fn collect(&mut self) { + pub fn collect(&mut self) { self.collect_local_language_items(); self.collect_external_language_items(); self.check_completeness(); diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index 591b196bd6fc7..703516251dcdc 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -8,13 +8,27 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use driver::session; use middle::ty; use middle::pat_util; use util::ppaux::{ty_to_str}; +use core::char; +use core::cmp; use core::hashmap::HashMap; -use std::smallintmap::SmallIntMap; +use core::i16; +use core::i32; +use core::i64; +use core::i8; +use core::str; +use core::u16; +use core::u32; +use core::u64; +use core::u8; +use core::vec; +use extra::smallintmap::SmallIntMap; use syntax::attr; use syntax::codemap::span; use syntax::codemap; @@ -79,6 +93,10 @@ pub enum lint { unused_variable, dead_assignment, unused_mut, + unnecessary_allocation, + + missing_doc, + unreachable_code, } pub fn level_to_str(lv: level) -> &'static str { @@ -242,6 +260,27 @@ static lint_table: &'static [(&'static str, LintSpec)] = &[ desc: "detect mut variables which don't need to be mutable", default: warn }), + + ("unnecessary_allocation", + LintSpec { + lint: unnecessary_allocation, + desc: "detects unnecessary allocations that can be eliminated", + default: warn + }), + + ("missing_doc", + LintSpec { + lint: missing_doc, + desc: "detects missing documentation for public members", + default: allow + }), + + ("unreachable_code", + LintSpec { + lint: unreachable_code, + desc: "detects unreachable code", + default: warn + }), ]; /* @@ -263,6 +302,13 @@ struct Context { curr: SmallIntMap<(level, LintSource)>, // context we're checking in (used to access fields like sess) tcx: ty::ctxt, + // Just a simple flag if we're currently recursing into a trait + // implementation. This is only used by the lint_missing_doc() pass + in_trait_impl: bool, + // Another flag for doc lint emissions. Does some parent of the current node + // have the doc(hidden) attribute? Treating this as allow(missing_doc) would + // play badly with forbid(missing_doc) when it shouldn't. + doc_hidden: bool, // When recursing into an attributed node of the ast which modifies lint // levels, this stack keeps track of the previous lint levels of whatever // was modified. @@ -272,7 +318,15 @@ struct Context { // Others operate directly on @ast::item structures (or similar). Finally, // others still are added to the Session object via `add_lint`, and these // are all passed with the lint_session visitor. - visitors: ~[visit::vt<()>], + // + // This is a pair so every visitor can visit every node. When a lint pass is + // registered, another visitor is created which stops at all items which can + // alter the attributes of the ast. This "item stopping visitor" is the + // second element of the pair, while the original visitor is the first + // element. This means that when visiting a node, the original recursive + // call can used the original visitor's method, although the recursing + // visitor supplied to the method is the item stopping visitor. + visitors: ~[(visit::vt<@mut Context>, visit::vt<@mut Context>)], } impl Context { @@ -380,29 +434,52 @@ impl Context { } } + // detect doc(hidden) + let mut doc_hidden = false; + for attr::find_attrs_by_name(attrs, "doc").each |attr| { + match attr::get_meta_item_list(attr.node.value) { + Some(s) => { + if attr::find_meta_items_by_name(s, "hidden").len() > 0 { + doc_hidden = true; + } + } + None => {} + } + } + if doc_hidden && !self.doc_hidden { + self.doc_hidden = true; + } else { + doc_hidden = false; + } + f(); // rollback + if doc_hidden && self.doc_hidden { + self.doc_hidden = false; + } for pushed.times { let (lint, lvl, src) = self.lint_stack.pop(); self.set_level(lint, lvl, src); } } - fn add_lint(&mut self, v: visit::vt<()>) { - self.visitors.push(item_stopping_visitor(v)); + fn add_lint(&mut self, v: visit::vt<@mut Context>) { + self.visitors.push((v, item_stopping_visitor(v))); } - fn process(&self, n: AttributedNode) { + fn process(@mut self, n: AttributedNode) { + // see comment of the `visitors` field in the struct for why there's a + // pair instead of just one visitor. match n { Item(it) => { - for self.visitors.each |v| { - visit::visit_item(it, (), *v); + for self.visitors.each |&(orig, stopping)| { + (orig.visit_item)(it, self, stopping); } } Crate(c) => { - for self.visitors.each |v| { - visit::visit_crate(c, (), *v); + for self.visitors.each |&(_, stopping)| { + visit::visit_crate(c, self, stopping); } } // Can't use visit::visit_method_helper because the @@ -410,48 +487,15 @@ impl Context { // to be a no-op, so manually invoke visit_fn. Method(m) => { let fk = visit::fk_method(copy m.ident, &m.generics, m); - for self.visitors.each |v| { - visit::visit_fn(&fk, &m.decl, &m.body, m.span, m.id, - (), *v); + for self.visitors.each |&(orig, stopping)| { + (orig.visit_fn)(&fk, &m.decl, &m.body, m.span, m.id, + self, stopping); } } } } } -#[cfg(stage0)] -pub fn each_lint(sess: session::Session, - attrs: &[ast::attribute], - f: &fn(@ast::meta_item, level, &~str) -> bool) -{ - for [allow, warn, deny, forbid].each |&level| { - let level_name = level_to_str(level); - let attrs = attr::find_attrs_by_name(attrs, level_name); - for attrs.each |attr| { - let meta = attr.node.value; - let metas = match meta.node { - ast::meta_list(_, ref metas) => metas, - _ => { - sess.span_err(meta.span, ~"malformed lint attribute"); - loop; - } - }; - for metas.each |meta| { - match meta.node { - ast::meta_word(lintname) => { - if !f(*meta, level, lintname) { - return; - } - } - _ => { - sess.span_err(meta.span, ~"malformed lint attribute"); - } - } - } - } - } -} -#[cfg(not(stage0))] pub fn each_lint(sess: session::Session, attrs: &[ast::attribute], f: &fn(@ast::meta_item, level, &~str) -> bool) -> bool @@ -464,7 +508,7 @@ pub fn each_lint(sess: session::Session, let metas = match meta.node { ast::meta_list(_, ref metas) => metas, _ => { - sess.span_err(meta.span, ~"malformed lint attribute"); + sess.span_err(meta.span, "malformed lint attribute"); loop; } }; @@ -476,7 +520,7 @@ pub fn each_lint(sess: session::Session, } } _ => { - sess.span_err(meta.span, ~"malformed lint attribute"); + sess.span_err(meta.span, "malformed lint attribute"); } } } @@ -489,25 +533,25 @@ pub fn each_lint(sess: session::Session, // This is used to make the simple visitors used for the lint passes // not traverse into subitems, since that is handled by the outer // lint visitor. -fn item_stopping_visitor(v: visit::vt) -> visit::vt { +fn item_stopping_visitor(outer: visit::vt) -> visit::vt { visit::mk_vt(@visit::Visitor { visit_item: |_i, _e, _v| { }, visit_fn: |fk, fd, b, s, id, e, v| { match *fk { visit::fk_method(*) => {} - _ => visit::visit_fn(fk, fd, b, s, id, e, v) + _ => (outer.visit_fn)(fk, fd, b, s, id, e, v) } }, - .. **(ty_stopping_visitor(v))}) + .. **(ty_stopping_visitor(outer))}) } fn ty_stopping_visitor(v: visit::vt) -> visit::vt { visit::mk_vt(@visit::Visitor {visit_ty: |_t, _e, _v| { },.. **v}) } -fn lint_while_true(cx: @mut Context) -> visit::vt<()> { - visit::mk_simple_visitor(@visit::SimpleVisitor { - visit_expr: |e: @ast::expr| { +fn lint_while_true() -> visit::vt<@mut Context> { + visit::mk_vt(@visit::Visitor { + visit_expr: |e, cx: @mut Context, vt| { match e.node { ast::expr_while(cond, _) => { match cond.node { @@ -523,12 +567,13 @@ fn lint_while_true(cx: @mut Context) -> visit::vt<()> { } _ => () } + visit::visit_expr(e, cx, vt); }, - .. *visit::default_simple_visitor() + .. *visit::default_visitor() }) } -fn lint_type_limits(cx: @mut Context) -> visit::vt<()> { +fn lint_type_limits() -> visit::vt<@mut Context> { fn is_valid(binop: ast::binop, v: T, min: T, max: T) -> bool { match binop { @@ -574,7 +619,7 @@ fn lint_type_limits(cx: @mut Context) -> visit::vt<()> { } } - fn check_limits(cx: @mut Context, binop: ast::binop, l: &ast::expr, + fn check_limits(cx: &Context, binop: ast::binop, l: &ast::expr, r: &ast::expr) -> bool { let (lit, expr, swap) = match (&l.node, &r.node) { (&ast::expr_lit(_), _) => (l, r, true), @@ -627,26 +672,26 @@ fn lint_type_limits(cx: @mut Context) -> visit::vt<()> { } } - let visit_expr: @fn(@ast::expr) = |e| { - match e.node { - ast::expr_binary(ref binop, @ref l, @ref r) => { - if is_comparison(*binop) - && !check_limits(cx, *binop, l, r) { - cx.span_lint(type_limits, e.span, - "comparison is useless due to type limits"); + visit::mk_vt(@visit::Visitor { + visit_expr: |e, cx: @mut Context, vt| { + match e.node { + ast::expr_binary(_, ref binop, @ref l, @ref r) => { + if is_comparison(*binop) + && !check_limits(cx, *binop, l, r) { + cx.span_lint(type_limits, e.span, + "comparison is useless due to type limits"); + } } + _ => () } - _ => () - } - }; + visit::visit_expr(e, cx, vt); + }, - visit::mk_simple_visitor(@visit::SimpleVisitor { - visit_expr: visit_expr, - .. *visit::default_simple_visitor() + .. *visit::default_visitor() }) } -fn check_item_default_methods(cx: @mut Context, item: @ast::item) { +fn check_item_default_methods(cx: &Context, item: @ast::item) { match item.node { ast::item_trait(_, _, ref methods) => { for methods.each |method| { @@ -663,9 +708,9 @@ fn check_item_default_methods(cx: @mut Context, item: @ast::item) { } } -fn check_item_ctypes(cx: @mut Context, it: @ast::item) { +fn check_item_ctypes(cx: &Context, it: @ast::item) { - fn check_foreign_fn(cx: @mut Context, decl: &ast::fn_decl) { + fn check_foreign_fn(cx: &Context, decl: &ast::fn_decl) { let tys = vec::map(decl.inputs, |a| a.ty ); for vec::each(vec::append_one(tys, decl.output)) |ty| { match ty.node { @@ -705,7 +750,7 @@ fn check_item_ctypes(cx: @mut Context, it: @ast::item) { } } -fn check_type_for_lint(cx: @mut Context, lint: lint, span: span, ty: ty::t) { +fn check_type_for_lint(cx: &Context, lint: lint, span: span, ty: ty::t) { if cx.get_level(lint) == allow { return } let mut n_box = 0; @@ -732,13 +777,13 @@ fn check_type_for_lint(cx: @mut Context, lint: lint, span: span, ty: ty::t) { } } -fn check_type(cx: @mut Context, span: span, ty: ty::t) { +fn check_type(cx: &Context, span: span, ty: ty::t) { for [managed_heap_memory, owned_heap_memory, heap_memory].each |lint| { check_type_for_lint(cx, *lint, span, ty); } } -fn check_item_heap(cx: @mut Context, it: @ast::item) { +fn check_item_heap(cx: &Context, it: @ast::item) { match it.node { ast::item_fn(*) | ast::item_ty(*) | @@ -762,19 +807,20 @@ fn check_item_heap(cx: @mut Context, it: @ast::item) { } } -fn lint_heap(cx: @mut Context) -> visit::vt<()> { - visit::mk_simple_visitor(@visit::SimpleVisitor { - visit_expr: |e| { +fn lint_heap() -> visit::vt<@mut Context> { + visit::mk_vt(@visit::Visitor { + visit_expr: |e, cx: @mut Context, vt| { let ty = ty::expr_ty(cx.tcx, e); check_type(cx, e.span, ty); + visit::visit_expr(e, cx, vt); }, - .. *visit::default_simple_visitor() + .. *visit::default_visitor() }) } -fn lint_path_statement(cx: @mut Context) -> visit::vt<()> { - visit::mk_simple_visitor(@visit::SimpleVisitor { - visit_stmt: |s| { +fn lint_path_statement() -> visit::vt<@mut Context> { + visit::mk_vt(@visit::Visitor { + visit_stmt: |s, cx: @mut Context, vt| { match s.node { ast::stmt_semi( @ast::expr { node: ast::expr_path(_), _ }, @@ -785,12 +831,13 @@ fn lint_path_statement(cx: @mut Context) -> visit::vt<()> { } _ => () } + visit::visit_stmt(s, cx, vt); }, - .. *visit::default_simple_visitor() + .. *visit::default_visitor() }) } -fn check_item_non_camel_case_types(cx: @mut Context, it: @ast::item) { +fn check_item_non_camel_case_types(cx: &Context, it: @ast::item) { fn is_camel_case(cx: ty::ctxt, ident: ast::ident) -> bool { let ident = cx.sess.str_of(ident); assert!(!ident.is_empty()); @@ -814,7 +861,7 @@ fn check_item_non_camel_case_types(cx: @mut Context, it: @ast::item) { } } - fn check_case(cx: @mut Context, ident: ast::ident, span: span) { + fn check_case(cx: &Context, ident: ast::ident, span: span) { if !is_camel_case(cx.tcx, ident) { cx.span_lint(non_camel_case_types, span, "type, variant, or trait should have \ @@ -837,27 +884,26 @@ fn check_item_non_camel_case_types(cx: @mut Context, it: @ast::item) { } } -fn lint_unused_unsafe(cx: @mut Context) -> visit::vt<()> { - let visit_expr: @fn(@ast::expr) = |e| { - match e.node { - ast::expr_block(ref blk) if blk.node.rules == ast::unsafe_blk => { - if !cx.tcx.used_unsafe.contains(&blk.node.id) { - cx.span_lint(unused_unsafe, blk.span, - "unnecessary `unsafe` block"); +fn lint_unused_unsafe() -> visit::vt<@mut Context> { + visit::mk_vt(@visit::Visitor { + visit_expr: |e, cx: @mut Context, vt| { + match e.node { + ast::expr_block(ref blk) if blk.node.rules == ast::unsafe_blk => { + if !cx.tcx.used_unsafe.contains(&blk.node.id) { + cx.span_lint(unused_unsafe, blk.span, + "unnecessary `unsafe` block"); + } } + _ => () } - _ => () - } - }; - - visit::mk_simple_visitor(@visit::SimpleVisitor { - visit_expr: visit_expr, - .. *visit::default_simple_visitor() + visit::visit_expr(e, cx, vt); + }, + .. *visit::default_visitor() }) } -fn lint_unused_mut(cx: @mut Context) -> visit::vt<()> { - let check_pat: @fn(@ast::pat) = |p| { +fn lint_unused_mut() -> visit::vt<@mut Context> { + fn check_pat(cx: &Context, p: @ast::pat) { let mut used = false; let mut bindings = 0; do pat_util::pat_bindings(cx.tcx.def_map, p) |_, id, _, _| { @@ -872,37 +918,48 @@ fn lint_unused_mut(cx: @mut Context) -> visit::vt<()> { }; cx.span_lint(unused_mut, p.span, msg); } - }; + } - let visit_fn_decl: @fn(&ast::fn_decl) = |fd| { + fn visit_fn_decl(cx: &Context, fd: &ast::fn_decl) { for fd.inputs.each |arg| { if arg.is_mutbl { - check_pat(arg.pat); + check_pat(cx, arg.pat); } } - }; + } - visit::mk_simple_visitor(@visit::SimpleVisitor { - visit_local: |l| { + visit::mk_vt(@visit::Visitor { + visit_local: |l, cx: @mut Context, vt| { if l.node.is_mutbl { - check_pat(l.node.pat); + check_pat(cx, l.node.pat); } + visit::visit_local(l, cx, vt); }, - visit_fn: |_, fd, _, _, _| visit_fn_decl(fd), - visit_ty_method: |tm| visit_fn_decl(&tm.decl), - visit_struct_method: |sm| visit_fn_decl(&sm.decl), - visit_trait_method: |tm| { + visit_fn: |a, fd, b, c, d, cx, vt| { + visit_fn_decl(cx, fd); + visit::visit_fn(a, fd, b, c, d, cx, vt); + }, + visit_ty_method: |tm, cx, vt| { + visit_fn_decl(cx, &tm.decl); + visit::visit_ty_method(tm, cx, vt); + }, + visit_struct_method: |sm, cx, vt| { + visit_fn_decl(cx, &sm.decl); + visit::visit_struct_method(sm, cx, vt); + }, + visit_trait_method: |tm, cx, vt| { match *tm { - ast::required(ref tm) => visit_fn_decl(&tm.decl), - ast::provided(m) => visit_fn_decl(&m.decl), + ast::required(ref tm) => visit_fn_decl(cx, &tm.decl), + ast::provided(m) => visit_fn_decl(cx, &m.decl) } + visit::visit_trait_method(tm, cx, vt); }, - .. *visit::default_simple_visitor() + .. *visit::default_visitor() }) } -fn lint_session(cx: @mut Context) -> visit::vt<()> { - ast_util::id_visitor(|id| { +fn lint_session() -> visit::vt<@mut Context> { + ast_util::id_visitor(|id, cx: @mut Context| { match cx.tcx.sess.lints.pop(&id) { None => {}, Some(l) => { @@ -914,6 +971,134 @@ fn lint_session(cx: @mut Context) -> visit::vt<()> { }) } +fn lint_unnecessary_allocations() -> visit::vt<@mut Context> { + // Warn if string and vector literals with sigils are immediately borrowed. + // Those can have the sigil removed. + fn check(cx: &Context, e: @ast::expr) { + match e.node { + ast::expr_vstore(e2, ast::expr_vstore_uniq) | + ast::expr_vstore(e2, ast::expr_vstore_box) => { + match e2.node { + ast::expr_lit(@codemap::spanned{ + node: ast::lit_str(*), _}) | + ast::expr_vec(*) => {} + _ => return + } + } + + _ => return + } + + match cx.tcx.adjustments.find_copy(&e.id) { + Some(@ty::AutoDerefRef(ty::AutoDerefRef { + autoref: Some(ty::AutoBorrowVec(*)), _ })) => { + cx.span_lint(unnecessary_allocation, + e.span, "unnecessary allocation, the sigil can be \ + removed"); + } + + _ => () + } + } + + visit::mk_vt(@visit::Visitor { + visit_expr: |e, cx: @mut Context, vt| { + check(cx, e); + visit::visit_expr(e, cx, vt); + }, + .. *visit::default_visitor() + }) +} + +fn lint_missing_doc() -> visit::vt<@mut Context> { + fn check_attrs(cx: @mut Context, attrs: &[ast::attribute], + sp: span, msg: &str) { + // If we're building a test harness, then warning about documentation is + // probably not really relevant right now + if cx.tcx.sess.opts.test { return } + // If we have doc(hidden), nothing to do + if cx.doc_hidden { return } + // If we're documented, nothing to do + if attrs.any(|a| a.node.is_sugared_doc) { return } + + // otherwise, warn! + cx.span_lint(missing_doc, sp, msg); + } + + visit::mk_vt(@visit::Visitor { + visit_struct_method: |m, cx, vt| { + if m.vis == ast::public { + check_attrs(cx, m.attrs, m.span, + "missing documentation for a method"); + } + visit::visit_struct_method(m, cx, vt); + }, + + visit_ty_method: |m, cx, vt| { + // All ty_method objects are linted about because they're part of a + // trait (no visibility) + check_attrs(cx, m.attrs, m.span, + "missing documentation for a method"); + visit::visit_ty_method(m, cx, vt); + }, + + visit_fn: |fk, d, b, sp, id, cx, vt| { + // Only warn about explicitly public methods. Soon implicit + // public-ness will hopefully be going away. + match *fk { + visit::fk_method(_, _, m) if m.vis == ast::public => { + // If we're in a trait implementation, no need to duplicate + // documentation + if !cx.in_trait_impl { + check_attrs(cx, m.attrs, sp, + "missing documentation for a method"); + } + } + + _ => {} + } + visit::visit_fn(fk, d, b, sp, id, cx, vt); + }, + + visit_item: |it, cx, vt| { + match it.node { + // Go ahead and match the fields here instead of using + // visit_struct_field while we have access to the enclosing + // struct's visibility + ast::item_struct(sdef, _) if it.vis == ast::public => { + check_attrs(cx, it.attrs, it.span, + "missing documentation for a struct"); + for sdef.fields.each |field| { + match field.node.kind { + ast::named_field(_, vis) if vis != ast::private => { + check_attrs(cx, field.node.attrs, field.span, + "missing documentation for a field"); + } + ast::unnamed_field | ast::named_field(*) => {} + } + } + } + + ast::item_trait(*) if it.vis == ast::public => { + check_attrs(cx, it.attrs, it.span, + "missing documentation for a trait"); + } + + ast::item_fn(*) if it.vis == ast::public => { + check_attrs(cx, it.attrs, it.span, + "missing documentation for a function"); + } + + _ => {} + }; + + visit::visit_item(it, cx, vt); + }, + + .. *visit::default_visitor() + }) +} + pub fn check_crate(tcx: ty::ctxt, crate: @ast::crate) { let cx = @mut Context { dict: @get_lint_dict(), @@ -921,6 +1106,8 @@ pub fn check_crate(tcx: ty::ctxt, crate: @ast::crate) { tcx: tcx, lint_stack: ~[], visitors: ~[], + in_trait_impl: false, + doc_hidden: false, }; // Install defaults. @@ -934,36 +1121,39 @@ pub fn check_crate(tcx: ty::ctxt, crate: @ast::crate) { } // Register each of the lint passes with the context - cx.add_lint(lint_while_true(cx)); - cx.add_lint(lint_path_statement(cx)); - cx.add_lint(lint_heap(cx)); - cx.add_lint(lint_type_limits(cx)); - cx.add_lint(lint_unused_unsafe(cx)); - cx.add_lint(lint_unused_mut(cx)); - cx.add_lint(lint_session(cx)); - - // type inference doesn't like this being declared below, we need to tell it - // what the type of this first function is... - let visit_item: - @fn(@ast::item, @mut Context, visit::vt<@mut Context>) = - |it, cx, vt| { - do cx.with_lint_attrs(it.attrs) { - check_item_ctypes(cx, it); - check_item_non_camel_case_types(cx, it); - check_item_default_methods(cx, it); - check_item_heap(cx, it); - - cx.process(Item(it)); - visit::visit_item(it, cx, vt); - } - }; + cx.add_lint(lint_while_true()); + cx.add_lint(lint_path_statement()); + cx.add_lint(lint_heap()); + cx.add_lint(lint_type_limits()); + cx.add_lint(lint_unused_unsafe()); + cx.add_lint(lint_unused_mut()); + cx.add_lint(lint_session()); + cx.add_lint(lint_unnecessary_allocations()); + cx.add_lint(lint_missing_doc()); // Actually perform the lint checks (iterating the ast) do cx.with_lint_attrs(crate.node.attrs) { cx.process(Crate(crate)); visit::visit_crate(crate, cx, visit::mk_vt(@visit::Visitor { - visit_item: visit_item, + visit_item: |it, cx: @mut Context, vt| { + do cx.with_lint_attrs(it.attrs) { + match it.node { + ast::item_impl(_, Some(*), _, _) => { + cx.in_trait_impl = true; + } + _ => {} + } + check_item_ctypes(cx, it); + check_item_non_camel_case_types(cx, it); + check_item_default_methods(cx, it); + check_item_heap(cx, it); + + cx.process(Item(it)); + visit::visit_item(it, cx, vt); + cx.in_trait_impl = false; + } + }, visit_fn: |fk, decl, body, span, id, cx, vt| { match *fk { visit::fk_method(_, _, m) => { diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 711e391527755..d3a563ca31204 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -102,16 +102,21 @@ * to return explicitly. */ +use core::prelude::*; use middle::lint::{unused_variable, dead_assignment}; use middle::pat_util; use middle::ty; use middle::typeck; use middle::moves; -use util::ppaux::ty_to_str; use core::cast::transmute; use core::hashmap::HashMap; +use core::io; +use core::old_iter; +use core::to_str; +use core::uint; +use core::vec; use syntax::ast::*; use syntax::codemap::span; use syntax::parse::token::special_idents; @@ -145,7 +150,6 @@ fn live_node_kind_to_str(lnk: LiveNodeKind, cx: ty::ctxt) -> ~str { pub fn check_crate(tcx: ty::ctxt, method_map: typeck::method_map, - variable_moves_map: moves::VariableMovesMap, capture_map: moves::CaptureMap, crate: @crate) { let visitor = visit::mk_vt(@visit::Visitor { @@ -158,7 +162,6 @@ pub fn check_crate(tcx: ty::ctxt, let initial_maps = @mut IrMaps(tcx, method_map, - variable_moves_map, capture_map); visit::visit_crate(crate, initial_maps, visitor); tcx.sess.abort_if_errors(); @@ -194,8 +197,10 @@ impl to_str::ToStr for Variable { // variable must not be assigned if there is some successor // assignment. And so forth. -pub impl LiveNode { - fn is_valid(&self) -> bool { **self != uint::max_value } +impl LiveNode { + pub fn is_valid(&self) -> bool { + **self != uint::max_value + } } fn invalid_node() -> LiveNode { LiveNode(uint::max_value) } @@ -228,7 +233,6 @@ enum VarKind { struct IrMaps { tcx: ty::ctxt, method_map: typeck::method_map, - variable_moves_map: moves::VariableMovesMap, capture_map: moves::CaptureMap, num_live_nodes: uint, @@ -242,13 +246,11 @@ struct IrMaps { fn IrMaps(tcx: ty::ctxt, method_map: typeck::method_map, - variable_moves_map: moves::VariableMovesMap, capture_map: moves::CaptureMap) -> IrMaps { IrMaps { tcx: tcx, method_map: method_map, - variable_moves_map: variable_moves_map, capture_map: capture_map, num_live_nodes: 0, num_vars: 0, @@ -260,8 +262,8 @@ fn IrMaps(tcx: ty::ctxt, } } -pub impl IrMaps { - fn add_live_node(&mut self, lnk: LiveNodeKind) -> LiveNode { +impl IrMaps { + pub fn add_live_node(&mut self, lnk: LiveNodeKind) -> LiveNode { let ln = LiveNode(self.num_live_nodes); self.lnks.push(lnk); self.num_live_nodes += 1; @@ -272,16 +274,16 @@ pub impl IrMaps { ln } - fn add_live_node_for_node(&mut self, - node_id: node_id, - lnk: LiveNodeKind) { + pub fn add_live_node_for_node(&mut self, + node_id: node_id, + lnk: LiveNodeKind) { let ln = self.add_live_node(lnk); self.live_node_map.insert(node_id, ln); debug!("%s is node %d", ln.to_str(), node_id); } - fn add_variable(&mut self, vk: VarKind) -> Variable { + pub fn add_variable(&mut self, vk: VarKind) -> Variable { let v = Variable(self.num_vars); self.var_kinds.push(vk); self.num_vars += 1; @@ -298,7 +300,7 @@ pub impl IrMaps { v } - fn variable(&mut self, node_id: node_id, span: span) -> Variable { + pub fn variable(&mut self, node_id: node_id, span: span) -> Variable { match self.variable_map.find(&node_id) { Some(&var) => var, None => { @@ -308,7 +310,7 @@ pub impl IrMaps { } } - fn variable_name(&mut self, var: Variable) -> @~str { + pub fn variable_name(&mut self, var: Variable) -> @~str { match self.var_kinds[*var] { Local(LocalInfo { ident: nm, _ }) | Arg(_, nm) => { self.tcx.sess.str_of(nm) @@ -317,11 +319,11 @@ pub impl IrMaps { } } - fn set_captures(&mut self, node_id: node_id, cs: ~[CaptureInfo]) { + pub fn set_captures(&mut self, node_id: node_id, cs: ~[CaptureInfo]) { self.capture_info_map.insert(node_id, @cs); } - fn captures(&mut self, expr: @expr) -> @~[CaptureInfo] { + pub fn captures(&mut self, expr: @expr) -> @~[CaptureInfo] { match self.capture_info_map.find(&expr.id) { Some(&caps) => caps, None => { @@ -330,7 +332,7 @@ pub impl IrMaps { } } - fn lnk(&mut self, ln: LiveNode) -> LiveNodeKind { + pub fn lnk(&mut self, ln: LiveNode) -> LiveNodeKind { self.lnks[*ln] } } @@ -348,7 +350,6 @@ fn visit_fn(fk: &visit::fn_kind, // swap in a new set of IR maps for this function body: let fn_maps = @mut IrMaps(this.tcx, this.method_map, - this.variable_moves_map, this.capture_map); unsafe { @@ -498,7 +499,7 @@ fn visit_expr(expr: @expr, this: @mut IrMaps, vt: vt<@mut IrMaps>) { this.add_live_node_for_node(expr.id, ExprNode(expr.span)); visit::visit_expr(expr, this, vt); } - expr_binary(op, _, _) if ast_util::lazy_binop(op) => { + expr_binary(_, op, _, _) if ast_util::lazy_binop(op) => { this.add_live_node_for_node(expr.id, ExprNode(expr.span)); visit::visit_expr(expr, this, vt); } @@ -579,8 +580,8 @@ fn Liveness(ir: @mut IrMaps, specials: Specials) -> Liveness { } } -pub impl Liveness { - fn live_node(&self, node_id: node_id, span: span) -> LiveNode { +impl Liveness { + pub fn live_node(&self, node_id: node_id, span: span) -> LiveNode { let ir: &mut IrMaps = self.ir; match ir.live_node_map.find(&node_id) { Some(&ln) => ln, @@ -596,7 +597,7 @@ pub impl Liveness { } } - fn variable_from_path(&self, expr: @expr) -> Option { + pub fn variable_from_path(&self, expr: @expr) -> Option { match expr.node { expr_path(_) => { let def = self.tcx.def_map.get_copy(&expr.id); @@ -608,12 +609,12 @@ pub impl Liveness { } } - fn variable(&self, node_id: node_id, span: span) -> Variable { + pub fn variable(&self, node_id: node_id, span: span) -> Variable { self.ir.variable(node_id, span) } - fn variable_from_def_map(&self, node_id: node_id, - span: span) -> Option { + pub fn variable_from_def_map(&self, node_id: node_id, span: span) + -> Option { match self.tcx.def_map.find(&node_id) { Some(&def) => { moves::moved_variable_node_id_from_def(def).map( @@ -627,8 +628,9 @@ pub impl Liveness { } } - fn pat_bindings(&self, pat: @pat, - f: &fn(LiveNode, Variable, span, node_id)) { + pub fn pat_bindings(&self, + pat: @pat, + f: &fn(LiveNode, Variable, span, node_id)) { let def_map = self.tcx.def_map; do pat_util::pat_bindings(def_map, pat) |_bm, p_id, sp, _n| { let ln = self.live_node(p_id, sp); @@ -637,9 +639,9 @@ pub impl Liveness { } } - fn arm_pats_bindings(&self, - pats: &[@pat], - f: &fn(LiveNode, Variable, span, node_id)) { + pub fn arm_pats_bindings(&self, + pats: &[@pat], + f: &fn(LiveNode, Variable, span, node_id)) { // only consider the first pattern; any later patterns must have // the same bindings, and we also consider the first pattern to be // the "authoratative" set of ids @@ -648,12 +650,13 @@ pub impl Liveness { } } - fn define_bindings_in_pat(&self, pat: @pat, succ: LiveNode) -> LiveNode { + pub fn define_bindings_in_pat(&self, pat: @pat, succ: LiveNode) + -> LiveNode { self.define_bindings_in_arm_pats([pat], succ) } - fn define_bindings_in_arm_pats(&self, pats: &[@pat], - succ: LiveNode) -> LiveNode { + pub fn define_bindings_in_arm_pats(&self, pats: &[@pat], succ: LiveNode) + -> LiveNode { let mut succ = succ; do self.arm_pats_bindings(pats) |ln, var, _sp, _id| { self.init_from_succ(ln, succ); @@ -663,13 +666,12 @@ pub impl Liveness { succ } - fn idx(&self, ln: LiveNode, var: Variable) -> uint { + pub fn idx(&self, ln: LiveNode, var: Variable) -> uint { *ln * self.ir.num_vars + *var } - fn live_on_entry(&self, ln: LiveNode, var: Variable) - -> Option { - + pub fn live_on_entry(&self, ln: LiveNode, var: Variable) + -> Option { assert!(ln.is_valid()); let reader = self.users[self.idx(ln, var)].reader; if reader.is_valid() {Some(self.ir.lnk(reader))} else {None} @@ -678,39 +680,39 @@ pub impl Liveness { /* Is this variable live on entry to any of its successor nodes? */ - fn live_on_exit(&self, ln: LiveNode, var: Variable) - -> Option { - + pub fn live_on_exit(&self, ln: LiveNode, var: Variable) + -> Option { self.live_on_entry(copy self.successors[*ln], var) } - fn used_on_entry(&self, ln: LiveNode, var: Variable) -> bool { + pub fn used_on_entry(&self, ln: LiveNode, var: Variable) -> bool { assert!(ln.is_valid()); self.users[self.idx(ln, var)].used } - fn assigned_on_entry(&self, ln: LiveNode, var: Variable) - -> Option { - + pub fn assigned_on_entry(&self, ln: LiveNode, var: Variable) + -> Option { assert!(ln.is_valid()); let writer = self.users[self.idx(ln, var)].writer; if writer.is_valid() {Some(self.ir.lnk(writer))} else {None} } - fn assigned_on_exit(&self, ln: LiveNode, var: Variable) - -> Option { - + pub fn assigned_on_exit(&self, ln: LiveNode, var: Variable) + -> Option { self.assigned_on_entry(copy self.successors[*ln], var) } - fn indices(&self, ln: LiveNode, op: &fn(uint)) { + pub fn indices(&self, ln: LiveNode, op: &fn(uint)) { let node_base_idx = self.idx(ln, Variable(0)); for uint::range(0, self.ir.num_vars) |var_idx| { op(node_base_idx + var_idx) } } - fn indices2(&self, ln: LiveNode, succ_ln: LiveNode, op: &fn(uint, uint)) { + pub fn indices2(&self, + ln: LiveNode, + succ_ln: LiveNode, + op: &fn(uint, uint)) { let node_base_idx = self.idx(ln, Variable(0u)); let succ_base_idx = self.idx(succ_ln, Variable(0u)); for uint::range(0u, self.ir.num_vars) |var_idx| { @@ -718,22 +720,25 @@ pub impl Liveness { } } - fn write_vars(&self, - wr: @io::Writer, - ln: LiveNode, - test: &fn(uint) -> LiveNode) { + pub fn write_vars(&self, + wr: @io::Writer, + ln: LiveNode, + test: &fn(uint) -> LiveNode) { let node_base_idx = self.idx(ln, Variable(0)); for uint::range(0, self.ir.num_vars) |var_idx| { let idx = node_base_idx + var_idx; if test(idx).is_valid() { - wr.write_str(~" "); + wr.write_str(" "); wr.write_str(Variable(var_idx).to_str()); } } } - fn find_loop_scope(&self, opt_label: Option, id: node_id, sp: span) - -> node_id { + pub fn find_loop_scope(&self, + opt_label: Option, + id: node_id, + sp: span) + -> node_id { match opt_label { Some(_) => // Refers to a labeled loop. Use the results of resolve // to find with one @@ -750,7 +755,7 @@ pub impl Liveness { loop_scope.len() }; if len == 0 { - self.tcx.sess.span_bug(sp, ~"break outside loop"); + self.tcx.sess.span_bug(sp, "break outside loop"); } else { // FIXME(#5275): this shouldn't have to be a method... self.last_loop_scope() @@ -759,29 +764,29 @@ pub impl Liveness { } } - fn last_loop_scope(&self) -> node_id { + pub fn last_loop_scope(&self) -> node_id { let loop_scope = &mut *self.loop_scope; *loop_scope.last() } - fn ln_str(&self, ln: LiveNode) -> ~str { + pub fn ln_str(&self, ln: LiveNode) -> ~str { do io::with_str_writer |wr| { - wr.write_str(~"[ln("); + wr.write_str("[ln("); wr.write_uint(*ln); - wr.write_str(~") of kind "); + wr.write_str(") of kind "); wr.write_str(fmt!("%?", copy self.ir.lnks[*ln])); - wr.write_str(~" reads"); + wr.write_str(" reads"); self.write_vars(wr, ln, |idx| self.users[idx].reader ); - wr.write_str(~" writes"); + wr.write_str(" writes"); self.write_vars(wr, ln, |idx| self.users[idx].writer ); - wr.write_str(~" "); - wr.write_str(~" precedes "); + wr.write_str(" "); + wr.write_str(" precedes "); wr.write_str((copy self.successors[*ln]).to_str()); - wr.write_str(~"]"); + wr.write_str("]"); } } - fn init_empty(&self, ln: LiveNode, succ_ln: LiveNode) { + pub fn init_empty(&self, ln: LiveNode, succ_ln: LiveNode) { self.successors[*ln] = succ_ln; // It is not necessary to initialize the @@ -794,7 +799,7 @@ pub impl Liveness { // } } - fn init_from_succ(&self, ln: LiveNode, succ_ln: LiveNode) { + pub fn init_from_succ(&self, ln: LiveNode, succ_ln: LiveNode) { // more efficient version of init_empty() / merge_from_succ() self.successors[*ln] = succ_ln; self.indices2(ln, succ_ln, |idx, succ_idx| { @@ -804,8 +809,11 @@ pub impl Liveness { self.ln_str(ln), self.ln_str(succ_ln)); } - fn merge_from_succ(&self, ln: LiveNode, succ_ln: LiveNode, - first_merge: bool) -> bool { + pub fn merge_from_succ(&self, + ln: LiveNode, + succ_ln: LiveNode, + first_merge: bool) + -> bool { if ln == succ_ln { return false; } let mut changed = false; @@ -839,7 +847,7 @@ pub impl Liveness { // Indicates that a local variable was *defined*; we know that no // uses of the variable can precede the definition (resolve checks // this) so we just clear out all the data. - fn define(&self, writer: LiveNode, var: Variable) { + pub fn define(&self, writer: LiveNode, var: Variable) { let idx = self.idx(writer, var); self.users[idx].reader = invalid_node(); self.users[idx].writer = invalid_node(); @@ -849,7 +857,7 @@ pub impl Liveness { } // Either read, write, or both depending on the acc bitset - fn acc(&self, ln: LiveNode, var: Variable, acc: uint) { + pub fn acc(&self, ln: LiveNode, var: Variable, acc: uint) { let idx = self.idx(ln, var); let users = &mut *self.users; let user = &mut users[idx]; @@ -875,7 +883,7 @@ pub impl Liveness { // _______________________________________________________________________ - fn compute(&self, decl: &fn_decl, body: &blk) -> LiveNode { + pub fn compute(&self, decl: &fn_decl, body: &blk) -> LiveNode { // if there is a `break` or `again` at the top level, then it's // effectively a return---this only occurs in `for` loops, // where the body is really a closure. @@ -900,8 +908,8 @@ pub impl Liveness { entry_ln } - fn propagate_through_fn_block(&self, _: &fn_decl, blk: &blk) - -> LiveNode { + pub fn propagate_through_fn_block(&self, _: &fn_decl, blk: &blk) + -> LiveNode { // the fallthrough exit is only for those cases where we do not // explicitly return: self.init_from_succ(self.s.fallthrough_ln, self.s.exit_ln); @@ -912,15 +920,16 @@ pub impl Liveness { self.propagate_through_block(blk, self.s.fallthrough_ln) } - fn propagate_through_block(&self, blk: &blk, succ: LiveNode) -> LiveNode { + pub fn propagate_through_block(&self, blk: &blk, succ: LiveNode) + -> LiveNode { let succ = self.propagate_through_opt_expr(blk.node.expr, succ); do blk.node.stmts.foldr(succ) |stmt, succ| { self.propagate_through_stmt(*stmt, succ) } } - fn propagate_through_stmt(&self, stmt: @stmt, succ: LiveNode) - -> LiveNode { + pub fn propagate_through_stmt(&self, stmt: @stmt, succ: LiveNode) + -> LiveNode { match stmt.node { stmt_decl(decl, _) => { return self.propagate_through_decl(decl, succ); @@ -936,22 +945,18 @@ pub impl Liveness { } } - fn propagate_through_decl(&self, decl: @decl, succ: LiveNode) - -> LiveNode { + pub fn propagate_through_decl(&self, decl: @decl, succ: LiveNode) + -> LiveNode { match decl.node { - decl_local(ref locals) => { - do locals.foldr(succ) |local, succ| { + decl_local(ref local) => { self.propagate_through_local(*local, succ) } - } - decl_item(_) => { - succ - } + decl_item(_) => succ, } } - fn propagate_through_local(&self, local: @local, succ: LiveNode) - -> LiveNode { + pub fn propagate_through_local(&self, local: @local, succ: LiveNode) + -> LiveNode { // Note: we mark the variable as defined regardless of whether // there is an initializer. Initially I had thought to only mark // the live variable as defined if it was initialized, and then we @@ -970,22 +975,24 @@ pub impl Liveness { self.define_bindings_in_pat(local.node.pat, succ) } - fn propagate_through_exprs(&self, exprs: &[@expr], - succ: LiveNode) -> LiveNode { + pub fn propagate_through_exprs(&self, exprs: &[@expr], succ: LiveNode) + -> LiveNode { do exprs.foldr(succ) |expr, succ| { self.propagate_through_expr(*expr, succ) } } - fn propagate_through_opt_expr(&self, opt_expr: Option<@expr>, - succ: LiveNode) -> LiveNode { + pub fn propagate_through_opt_expr(&self, + opt_expr: Option<@expr>, + succ: LiveNode) + -> LiveNode { do old_iter::foldl(&opt_expr, succ) |succ, expr| { self.propagate_through_expr(*expr, *succ) } } - fn propagate_through_expr(&self, expr: @expr, succ: LiveNode) - -> LiveNode { + pub fn propagate_through_expr(&self, expr: @expr, succ: LiveNode) + -> LiveNode { debug!("propagate_through_expr: %s", expr_to_str(expr, self.tcx.sess.intr())); @@ -1127,7 +1134,7 @@ pub impl Liveness { self.propagate_through_expr(r, succ) } - expr_assign_op(_, l, r) => { + expr_assign_op(_, _, l, r) => { // see comment on lvalues in // propagate_through_lvalue_components() let succ = self.write_lvalue(l, succ, ACC_WRITE|ACC_READ); @@ -1167,11 +1174,10 @@ pub impl Liveness { self.propagate_through_expr(f, succ) } - expr_method_call(rcvr, _, _, ref args, _) => { + expr_method_call(callee_id, rcvr, _, _, ref args, _) => { // calling a method with bot return type means that the method // will fail, and hence the successors can be ignored - let t_ret = ty::ty_fn_ret(ty::node_id_to_type(self.tcx, - expr.callee_id)); + let t_ret = ty::ty_fn_ret(ty::node_id_to_type(self.tcx, callee_id)); let succ = if ty::type_is_bot(t_ret) {self.s.exit_ln} else {succ}; let succ = self.propagate_through_exprs(*args, succ); @@ -1182,7 +1188,7 @@ pub impl Liveness { self.propagate_through_exprs(*exprs, succ) } - expr_binary(op, l, r) if ast_util::lazy_binop(op) => { + expr_binary(_, op, l, r) if ast_util::lazy_binop(op) => { let r_succ = self.propagate_through_expr(r, succ); let ln = self.live_node(expr.id, expr.span); @@ -1193,9 +1199,9 @@ pub impl Liveness { } expr_log(l, r) | - expr_index(l, r) | - expr_binary(_, l, r) => { - self.propagate_through_exprs(~[l, r], succ) + expr_index(_, l, r) | + expr_binary(_, _, l, r) => { + self.propagate_through_exprs([l, r], succ) } expr_addr_of(_, e) | @@ -1203,7 +1209,7 @@ pub impl Liveness { expr_loop_body(e) | expr_do_body(e) | expr_cast(e, _) | - expr_unary(_, e) | + expr_unary(_, _, e) | expr_paren(e) => { self.propagate_through_expr(e, succ) } @@ -1231,8 +1237,10 @@ pub impl Liveness { } } - fn propagate_through_lvalue_components(&self, expr: @expr, - succ: LiveNode) -> LiveNode { + pub fn propagate_through_lvalue_components(&self, + expr: @expr, + succ: LiveNode) + -> LiveNode { // # Lvalues // // In general, the full flow graph structure for an @@ -1290,9 +1298,8 @@ pub impl Liveness { } // see comment on propagate_through_lvalue() - fn write_lvalue(&self, expr: @expr, - succ: LiveNode, - acc: uint) -> LiveNode { + pub fn write_lvalue(&self, expr: @expr, succ: LiveNode, acc: uint) + -> LiveNode { match expr.node { expr_path(_) => self.access_path(expr, succ, acc), @@ -1304,8 +1311,8 @@ pub impl Liveness { } } - fn access_path(&self, expr: @expr, succ: LiveNode, acc: uint) - -> LiveNode { + pub fn access_path(&self, expr: @expr, succ: LiveNode, acc: uint) + -> LiveNode { let def = self.tcx.def_map.get_copy(&expr.id); match moves::moved_variable_node_id_from_def(def) { Some(nid) => { @@ -1321,10 +1328,12 @@ pub impl Liveness { } } - fn propagate_through_loop(&self, expr: @expr, - cond: Option<@expr>, - body: &blk, - succ: LiveNode) -> LiveNode { + pub fn propagate_through_loop(&self, + expr: @expr, + cond: Option<@expr>, + body: &blk, + succ: LiveNode) + -> LiveNode { /* @@ -1378,10 +1387,12 @@ pub impl Liveness { cond_ln } - fn with_loop_nodes(&self, loop_node_id: node_id, - break_ln: LiveNode, - cont_ln: LiveNode, - f: &fn() -> R) -> R { + pub fn with_loop_nodes(&self, + loop_node_id: node_id, + break_ln: LiveNode, + cont_ln: LiveNode, + f: &fn() -> R) + -> R { debug!("with_loop_nodes: %d %u", loop_node_id, *break_ln); self.loop_scope.push(loop_node_id); self.break_ln.insert(loop_node_id, break_ln); @@ -1398,11 +1409,7 @@ pub impl Liveness { fn check_local(local: @local, this: @Liveness, vt: vt<@Liveness>) { match local.node.init { Some(_) => { - - // Initializer: this.warn_about_unused_or_dead_vars_in_pat(local.node.pat); - this.check_for_reassignments_in_pat(local.node.pat, - local.node.is_mutbl); } None => { @@ -1437,35 +1444,6 @@ fn check_arm(arm: &arm, this: @Liveness, vt: vt<@Liveness>) { fn check_expr(expr: @expr, this: @Liveness, vt: vt<@Liveness>) { match expr.node { - expr_path(_) | expr_self => { - for this.variable_from_def_map(expr.id, expr.span).each |var| { - let ln = this.live_node(expr.id, expr.span); - - match this.ir.variable_moves_map.find(&expr.id) { - None => {} - Some(&entire_expr) => { - debug!("(checking expr) is a move: `%s`", - expr_to_str(expr, this.tcx.sess.intr())); - this.check_move_from_var(ln, *var, entire_expr); - } - } - } - - visit::visit_expr(expr, this, vt); - } - - expr_fn_block(*) => { - let caps = this.ir.captures(expr); - for caps.each |cap| { - let var = this.variable(cap.var_nid, expr.span); - if cap.is_move { - this.check_move_from_var(cap.ln, var, expr); - } - } - - visit::visit_expr(expr, this, vt); - } - expr_assign(l, r) => { this.check_lvalue(l, vt); (vt.visit_expr)(r, this, vt); @@ -1473,7 +1451,7 @@ fn check_expr(expr: @expr, this: @Liveness, vt: vt<@Liveness>) { visit::visit_expr(expr, this, vt); } - expr_assign_op(_, l, _) => { + expr_assign_op(_, _, l, _) => { this.check_lvalue(l, vt); visit::visit_expr(expr, this, vt); @@ -1506,7 +1484,7 @@ fn check_expr(expr: @expr, this: @Liveness, vt: vt<@Liveness>) { expr_cast(*) | expr_unary(*) | expr_ret(*) | expr_break(*) | expr_again(*) | expr_lit(_) | expr_block(*) | expr_mac(*) | expr_addr_of(*) | expr_struct(*) | expr_repeat(*) | - expr_paren(*) => { + expr_paren(*) | expr_fn_block(*) | expr_path(*) | expr_self(*) => { visit::visit_expr(expr, this, vt); } } @@ -1525,9 +1503,12 @@ enum ReadKind { PartiallyMovedValue } -pub impl Liveness { - fn check_ret(&self, id: node_id, sp: span, _fk: &visit::fn_kind, - entry_ln: LiveNode) { +impl Liveness { + pub fn check_ret(&self, + id: node_id, + sp: span, + _fk: &visit::fn_kind, + entry_ln: LiveNode) { if self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() { // if no_ret_var is live, then we fall off the end of the // function without any kind of return expression: @@ -1546,43 +1527,17 @@ pub impl Liveness { } } - fn check_move_from_var(&self, - ln: LiveNode, - var: Variable, - move_expr: @expr) { - /*! - * Checks whether `var` is live on entry to any of the - * successors of `ln`. If it is, report an error. - * `move_expr` is the expression which caused the variable - * to be moved. - * - * Note that `move_expr` is not necessarily a reference to the - * variable. It might be an expression like `x.f` which could - * cause a move of the variable `x`, or a closure creation. - */ - - debug!("check_move_from_var(%s, %s)", - ln.to_str(), var.to_str()); - - match self.live_on_exit(ln, var) { - None => {} - Some(lnk) => self.report_illegal_move(lnk, var, move_expr) - } - } - - fn check_lvalue(@self, expr: @expr, vt: vt<@Liveness>) { + pub fn check_lvalue(@self, expr: @expr, vt: vt<@Liveness>) { match expr.node { expr_path(_) => { match self.tcx.def_map.get_copy(&expr.id) { - def_local(nid, mutbl) => { + def_local(nid, _) => { // Assignment to an immutable variable or argument: only legal // if there is no later assignment. If this local is actually // mutable, then check for a reassignment to flag the mutability // as being used. let ln = self.live_node(expr.id, expr.span); let var = self.variable(nid, expr.span); - self.check_for_reassignment(ln, var, expr.span, - if mutbl {Some(nid)} else {None}); self.warn_about_dead_assign(expr.span, expr.id, ln, var); } def => { @@ -1606,123 +1561,11 @@ pub impl Liveness { } } - fn check_for_reassignments_in_pat(&self, pat: @pat, mutbl: bool) { - do self.pat_bindings(pat) |ln, var, sp, id| { - self.check_for_reassignment(ln, var, sp, - if mutbl {Some(id)} else {None}); - } - } - - fn check_for_reassignment(&self, ln: LiveNode, var: Variable, - orig_span: span, mutbl: Option) { - match self.assigned_on_exit(ln, var) { - Some(ExprNode(span)) => { - match mutbl { - Some(id) => { self.tcx.used_mut_nodes.insert(id); } - None => { - self.tcx.sess.span_err( - span, - "re-assignment of immutable variable"); - self.tcx.sess.span_note( - orig_span, - "prior assignment occurs here"); - } - } - } - Some(lnk) => { - self.tcx.sess.span_bug( - orig_span, - fmt!("illegal writer: %?", lnk)); - } - None => {} - } - } - - fn report_illegal_move(&self, lnk: LiveNodeKind, - var: Variable, - move_expr: @expr) { - // the only time that it is possible to have a moved variable - // used by ExitNode would be arguments or fields in a ctor. - // we give a slightly different error message in those cases. - if lnk == ExitNode { - // FIXME #4715: this seems like it should be reported in the - // borrow checker - let vk = self.ir.var_kinds[*var]; - match vk { - Arg(_, name) => { - self.tcx.sess.span_err( - move_expr.span, - fmt!("illegal move from argument `%s`, which is not \ - copy or move mode", *self.tcx.sess.str_of(name))); - return; - } - Local(*) | ImplicitRet => { - self.tcx.sess.span_bug( - move_expr.span, - fmt!("illegal reader (%?) for `%?`", - lnk, vk)); - } - } - } - - match move_expr.node { - expr_fn_block(*) => { - self.report_illegal_read( - move_expr.span, lnk, var, MovedValue); - let name = self.ir.variable_name(var); - self.tcx.sess.span_note( - move_expr.span, - fmt!("`%s` moved into closure environment here \ - because its type is moved by default", - *name)); - } - expr_path(*) => { - self.report_illegal_read( - move_expr.span, lnk, var, MovedValue); - self.report_move_location( - move_expr, var, "", "it"); - } - expr_field(*) => { - self.report_illegal_read( - move_expr.span, lnk, var, PartiallyMovedValue); - self.report_move_location( - move_expr, var, "field of ", "the field"); - } - expr_index(*) => { - self.report_illegal_read( - move_expr.span, lnk, var, PartiallyMovedValue); - self.report_move_location( - move_expr, var, "element of ", "the element"); - } - _ => { - self.report_illegal_read( - move_expr.span, lnk, var, PartiallyMovedValue); - self.report_move_location( - move_expr, var, "subcomponent of ", "the subcomponent"); - } - }; - } - - fn report_move_location(&self, - move_expr: @expr, - var: Variable, - expr_descr: &str, - pronoun: &str) { - let move_expr_ty = ty::expr_ty(self.tcx, move_expr); - let name = self.ir.variable_name(var); - self.tcx.sess.span_note( - move_expr.span, - fmt!("%s`%s` moved here because %s has type %s, \ - which is moved by default (use `copy` to override)", - expr_descr, *name, pronoun, - ty_to_str(self.tcx, move_expr_ty))); - } - - fn report_illegal_read(&self, - chk_span: span, - lnk: LiveNodeKind, - var: Variable, - rk: ReadKind) { + pub fn report_illegal_read(&self, + chk_span: span, + lnk: LiveNodeKind, + var: Variable, + rk: ReadKind) { let msg = match rk { PossiblyUninitializedVariable => "possibly uninitialized \ variable", @@ -1750,12 +1593,12 @@ pub impl Liveness { } } - fn should_warn(&self, var: Variable) -> Option<@~str> { + pub fn should_warn(&self, var: Variable) -> Option<@~str> { let name = self.ir.variable_name(var); if name[0] == ('_' as u8) { None } else { Some(name) } } - fn warn_about_unused_args(&self, decl: &fn_decl, entry_ln: LiveNode) { + pub fn warn_about_unused_args(&self, decl: &fn_decl, entry_ln: LiveNode) { for decl.inputs.each |arg| { do pat_util::pat_bindings(self.tcx.def_map, arg.pat) |_bm, p_id, sp, _n| { @@ -1765,7 +1608,7 @@ pub impl Liveness { } } - fn warn_about_unused_or_dead_vars_in_pat(&self, pat: @pat) { + pub fn warn_about_unused_or_dead_vars_in_pat(&self, pat: @pat) { do self.pat_bindings(pat) |ln, var, sp, id| { if !self.warn_about_unused(sp, id, ln, var) { self.warn_about_dead_assign(sp, id, ln, var); @@ -1773,8 +1616,12 @@ pub impl Liveness { } } - fn warn_about_unused(&self, sp: span, id: node_id, - ln: LiveNode, var: Variable) -> bool { + pub fn warn_about_unused(&self, + sp: span, + id: node_id, + ln: LiveNode, + var: Variable) + -> bool { if !self.used_on_entry(ln, var) { for self.should_warn(var).each |name| { @@ -1801,8 +1648,11 @@ pub impl Liveness { return false; } - fn warn_about_dead_assign(&self, sp: span, id: node_id, - ln: LiveNode, var: Variable) { + pub fn warn_about_dead_assign(&self, + sp: span, + id: node_id, + ln: LiveNode, + var: Variable) { if self.live_on_exit(ln, var).is_none() { for self.should_warn(var).each |name| { self.tcx.sess.add_lint(dead_assignment, id, sp, diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 91c0b8e61cc7b..f54e1e623ecd9 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -46,11 +46,14 @@ * then an index to jump forward to the relevant item. */ +use core::prelude::*; + use middle::ty; use middle::typeck; use util::ppaux::{ty_to_str, region_to_str, Repr}; use util::common::indenter; +use core::uint; use syntax::ast::{m_imm, m_const, m_mutbl}; use syntax::ast; use syntax::codemap::span; @@ -66,9 +69,12 @@ pub enum categorization { cat_local(ast::node_id), // local variable cat_arg(ast::node_id), // formal argument cat_deref(cmt, uint, ptr_kind), // deref of a ptr - cat_interior(cmt, interior_kind), // something interior + cat_interior(cmt, InteriorKind), // something interior: field, tuple, etc + cat_downcast(cmt), // selects a particular enum variant (*) cat_discr(cmt, ast::node_id), // match discriminant (see preserve()) cat_self(ast::node_id), // explicit `self` + + // (*) downcast is only required if the enum has more than one variant } #[deriving(Eq)] @@ -88,18 +94,26 @@ pub enum ptr_kind { // We use the term "interior" to mean "something reachable from the // base without a pointer dereference", e.g. a field -#[deriving(Eq)] -pub enum interior_kind { - interior_tuple, // elt in a tuple - interior_anon_field, // anonymous field (in e.g. - // struct Foo(int, int); - interior_variant(ast::def_id), // internals to a variant of given enum - interior_field(ast::ident), // name of field - interior_index(ty::t, // type of vec/str/etc being deref'd - ast::mutability) // mutability of vec content +#[deriving(Eq, IterBytes)] +pub enum InteriorKind { + InteriorField(FieldName), + InteriorElement(ElementKind), } -#[deriving(Eq)] +#[deriving(Eq, IterBytes)] +pub enum FieldName { + NamedField(ast::ident), + PositionalField(uint) +} + +#[deriving(Eq, IterBytes)] +pub enum ElementKind { + VecElement, + StrElement, + OtherElement, +} + +#[deriving(Eq, IterBytes)] pub enum MutabilityCategory { McImmutable, // Immutable. McReadOnly, // Read-only (`const`) @@ -134,7 +148,10 @@ pub type cmt = @cmt_; // We pun on *T to mean both actual deref of a ptr as well // as accessing of components: -pub enum deref_kind {deref_ptr(ptr_kind), deref_interior(interior_kind)} +pub enum deref_kind { + deref_ptr(ptr_kind), + deref_interior(InteriorKind), +} // Categorizes a derefable type. Note that we include vectors and strings as // derefable (we model an index as the combination of a deref and then a @@ -176,20 +193,14 @@ pub fn opt_deref_kind(t: ty::t) -> Option { Some(deref_ptr(unsafe_ptr)) } - ty::ty_enum(did, _) => { - Some(deref_interior(interior_variant(did))) - } - - ty::ty_struct(_, _) => { - Some(deref_interior(interior_anon_field)) - } - - ty::ty_evec(mt, ty::vstore_fixed(_)) => { - Some(deref_interior(interior_index(t, mt.mutbl))) + ty::ty_enum(*) | + ty::ty_struct(*) => { // newtype + Some(deref_interior(InteriorField(PositionalField(0)))) } + ty::ty_evec(_, ty::vstore_fixed(_)) | ty::ty_estr(ty::vstore_fixed(_)) => { - Some(deref_interior(interior_index(t, m_imm))) + Some(deref_interior(InteriorElement(element_kind(t)))) } _ => None @@ -279,8 +290,8 @@ impl ToStr for MutabilityCategory { } } -pub impl MutabilityCategory { - fn from_mutbl(m: ast::mutability) -> MutabilityCategory { +impl MutabilityCategory { + pub fn from_mutbl(m: ast::mutability) -> MutabilityCategory { match m { m_imm => McImmutable, m_const => McReadOnly, @@ -288,7 +299,7 @@ pub impl MutabilityCategory { } } - fn inherit(&self) -> MutabilityCategory { + pub fn inherit(&self) -> MutabilityCategory { match *self { McImmutable => McImmutable, McReadOnly => McReadOnly, @@ -297,21 +308,21 @@ pub impl MutabilityCategory { } } - fn is_mutable(&self) -> bool { + pub fn is_mutable(&self) -> bool { match *self { McImmutable | McReadOnly => false, McDeclared | McInherited => true } } - fn is_immutable(&self) -> bool { + pub fn is_immutable(&self) -> bool { match *self { McImmutable => true, McReadOnly | McDeclared | McInherited => false } } - fn to_user_str(&self) -> &'static str { + pub fn to_user_str(&self) -> &'static str { match *self { McDeclared | McInherited => "mutable", McImmutable => "immutable", @@ -320,16 +331,16 @@ pub impl MutabilityCategory { } } -pub impl mem_categorization_ctxt { - fn expr_ty(&self, expr: @ast::expr) -> ty::t { +impl mem_categorization_ctxt { + pub fn expr_ty(&self, expr: @ast::expr) -> ty::t { ty::expr_ty(self.tcx, expr) } - fn pat_ty(&self, pat: @ast::pat) -> ty::t { + pub fn pat_ty(&self, pat: @ast::pat) -> ty::t { ty::node_id_to_type(self.tcx, pat.id) } - fn cat_expr(&self, expr: @ast::expr) -> cmt { + pub fn cat_expr(&self, expr: @ast::expr) -> cmt { match self.tcx.adjustments.find(&expr.id) { None => { // No adjustments. @@ -363,9 +374,8 @@ pub impl mem_categorization_ctxt { } } - fn cat_expr_autoderefd(&self, - expr: @ast::expr, - autoderefs: uint) -> cmt { + pub fn cat_expr_autoderefd(&self, expr: @ast::expr, autoderefs: uint) + -> cmt { let mut cmt = self.cat_expr_unadjusted(expr); for uint::range(1, autoderefs+1) |deref| { cmt = self.cat_deref(expr, cmt, deref); @@ -373,13 +383,13 @@ pub impl mem_categorization_ctxt { return cmt; } - fn cat_expr_unadjusted(&self, expr: @ast::expr) -> cmt { + pub fn cat_expr_unadjusted(&self, expr: @ast::expr) -> cmt { debug!("cat_expr: id=%d expr=%s", expr.id, pprust::expr_to_str(expr, self.tcx.sess.intr())); let expr_ty = self.expr_ty(expr); match expr.node { - ast::expr_unary(ast::deref, e_base) => { + ast::expr_unary(_, ast::deref, e_base) => { if self.method_map.contains_key(&expr.id) { return self.cat_rvalue(expr, expr_ty); } @@ -397,7 +407,7 @@ pub impl mem_categorization_ctxt { self.cat_field(expr, base_cmt, f_name, self.expr_ty(expr)) } - ast::expr_index(base, _) => { + ast::expr_index(_, base, _) => { if self.method_map.contains_key(&expr.id) { return self.cat_rvalue(expr, expr_ty); } @@ -429,11 +439,12 @@ pub impl mem_categorization_ctxt { } } - fn cat_def(&self, - id: ast::node_id, - span: span, - expr_ty: ty::t, - def: ast::def) -> cmt { + pub fn cat_def(&self, + id: ast::node_id, + span: span, + expr_ty: ty::t, + def: ast::def) + -> cmt { match def { ast::def_fn(*) | ast::def_static_method(*) | ast::def_mod(_) | ast::def_foreign_mod(_) | ast::def_const(_) | @@ -546,7 +557,7 @@ pub impl mem_categorization_ctxt { } } - fn cat_rvalue(&self, elt: N, expr_ty: ty::t) -> cmt { + pub fn cat_rvalue(&self, elt: N, expr_ty: ty::t) -> cmt { @cmt_ { id:elt.id(), span:elt.span(), @@ -560,10 +571,10 @@ pub impl mem_categorization_ctxt { /// component is inherited from the base it is a part of. For /// example, a record field is mutable if it is declared mutable /// or if the container is mutable. - fn inherited_mutability(&self, - base_m: MutabilityCategory, - interior_m: ast::mutability) -> MutabilityCategory - { + pub fn inherited_mutability(&self, + base_m: MutabilityCategory, + interior_m: ast::mutability) + -> MutabilityCategory { match interior_m { m_imm => base_m.inherit(), m_const => McReadOnly, @@ -571,25 +582,26 @@ pub impl mem_categorization_ctxt { } } - fn cat_field(&self, - node: N, - base_cmt: cmt, - f_name: ast::ident, - f_ty: ty::t) -> cmt { + pub fn cat_field(&self, + node: N, + base_cmt: cmt, + f_name: ast::ident, + f_ty: ty::t) + -> cmt { @cmt_ { id: node.id(), span: node.span(), - cat: cat_interior(base_cmt, interior_field(f_name)), + cat: cat_interior(base_cmt, InteriorField(NamedField(f_name))), mutbl: base_cmt.mutbl.inherit(), ty: f_ty } } - fn cat_deref_fn(&self, - node: N, - base_cmt: cmt, - deref_cnt: uint) -> cmt - { + pub fn cat_deref_fn(&self, + node: N, + base_cmt: cmt, + deref_cnt: uint) + -> cmt { // Bit of a hack: the "dereference" of a function pointer like // `@fn()` is a mere logical concept. We interpret it as // dereferencing the environment pointer; of course, we don't @@ -601,11 +613,11 @@ pub impl mem_categorization_ctxt { return self.cat_deref_common(node, base_cmt, deref_cnt, mt); } - fn cat_deref(&self, - node: N, - base_cmt: cmt, - deref_cnt: uint) -> cmt - { + pub fn cat_deref(&self, + node: N, + base_cmt: cmt, + deref_cnt: uint) + -> cmt { let mt = match ty::deref(self.tcx, base_cmt.ty, true) { Some(mt) => mt, None => { @@ -619,12 +631,12 @@ pub impl mem_categorization_ctxt { return self.cat_deref_common(node, base_cmt, deref_cnt, mt); } - fn cat_deref_common(&self, - node: N, - base_cmt: cmt, - deref_cnt: uint, - mt: ty::mt) -> cmt - { + pub fn cat_deref_common(&self, + node: N, + base_cmt: cmt, + deref_cnt: uint, + mt: ty::mt) + -> cmt { match deref_kind(self.tcx, base_cmt.ty) { deref_ptr(ptr) => { // for unique ptrs, we inherit mutability from the @@ -660,10 +672,11 @@ pub impl mem_categorization_ctxt { } } - fn cat_index(&self, - elt: N, - base_cmt: cmt, - derefs: uint) -> cmt { + pub fn cat_index(&self, + elt: N, + base_cmt: cmt, + derefs: uint) + -> cmt { //! Creates a cmt for an indexing operation (`[]`); this //! indexing operation may occurs as part of an //! AutoBorrowVec, which when converting a `~[]` to an `&[]` @@ -737,26 +750,28 @@ pub impl mem_categorization_ctxt { } }; - fn interior(elt: N, of_cmt: cmt, - vect: ty::t, mutbl: MutabilityCategory, + fn interior(elt: N, + of_cmt: cmt, + vec_ty: ty::t, + mutbl: MutabilityCategory, mt: ty::mt) -> cmt { - let interior = interior_index(vect, mt.mutbl); @cmt_ { id:elt.id(), span:elt.span(), - cat:cat_interior(of_cmt, interior), + cat:cat_interior(of_cmt, InteriorElement(element_kind(vec_ty))), mutbl:mutbl, ty:mt.ty } } } - fn cat_imm_interior(&self, - node: N, - base_cmt: cmt, - interior_ty: ty::t, - interior: interior_kind) -> cmt { + pub fn cat_imm_interior(&self, + node: N, + base_cmt: cmt, + interior_ty: ty::t, + interior: InteriorKind) + -> cmt { @cmt_ { id: node.id(), span: node.span(), @@ -766,11 +781,24 @@ pub impl mem_categorization_ctxt { } } - fn cat_pattern(&self, - cmt: cmt, - pat: @ast::pat, - op: &fn(cmt, @ast::pat)) - { + pub fn cat_downcast(&self, + node: N, + base_cmt: cmt, + downcast_ty: ty::t) + -> cmt { + @cmt_ { + id: node.id(), + span: node.span(), + cat: cat_downcast(base_cmt), + mutbl: base_cmt.mutbl.inherit(), + ty: downcast_ty + } + } + + pub fn cat_pattern(&self, + cmt: cmt, + pat: @ast::pat, + op: &fn(cmt, @ast::pat)) { // Here, `cmt` is the categorization for the value being // matched and pat is the pattern it is being matched against. // @@ -835,21 +863,34 @@ pub impl mem_categorization_ctxt { match self.tcx.def_map.find(&pat.id) { Some(&ast::def_variant(enum_did, _)) => { // variant(x, y, z) - for subpats.each |&subpat| { + + let downcast_cmt = { + if ty::enum_is_univariant(tcx, enum_did) { + cmt // univariant, no downcast needed + } else { + self.cat_downcast(pat, cmt, cmt.ty) + } + }; + + for subpats.eachi |i, &subpat| { let subpat_ty = self.pat_ty(subpat); // see (*) + let subcmt = - self.cat_imm_interior(pat, cmt, subpat_ty, - interior_variant(enum_did)); + self.cat_imm_interior( + pat, downcast_cmt, subpat_ty, + InteriorField(PositionalField(i))); + self.cat_pattern(subcmt, subpat, op); } } Some(&ast::def_fn(*)) | Some(&ast::def_struct(*)) => { - for subpats.each |&subpat| { + for subpats.eachi |i, &subpat| { let subpat_ty = self.pat_ty(subpat); // see (*) let cmt_field = - self.cat_imm_interior(pat, cmt, subpat_ty, - interior_anon_field); + self.cat_imm_interior( + pat, cmt, subpat_ty, + InteriorField(PositionalField(i))); self.cat_pattern(cmt_field, subpat, op); } } @@ -885,10 +926,12 @@ pub impl mem_categorization_ctxt { ast::pat_tup(ref subpats) => { // (p1, ..., pN) - for subpats.each |&subpat| { + for subpats.eachi |i, &subpat| { let subpat_ty = self.pat_ty(subpat); // see (*) - let subcmt = self.cat_imm_interior(pat, cmt, subpat_ty, - interior_tuple); + let subcmt = + self.cat_imm_interior( + pat, cmt, subpat_ty, + InteriorField(PositionalField(i))); self.cat_pattern(subcmt, subpat, op); } } @@ -921,7 +964,7 @@ pub impl mem_categorization_ctxt { } } - fn mut_to_str(&self, mutbl: ast::mutability) -> ~str { + pub fn mut_to_str(&self, mutbl: ast::mutability) -> ~str { match mutbl { m_mutbl => ~"mutable", m_const => ~"const", @@ -929,29 +972,46 @@ pub impl mem_categorization_ctxt { } } - fn cmt_to_str(&self, cmt: cmt) -> ~str { + pub fn cmt_to_str(&self, cmt: cmt) -> ~str { match cmt.cat { - cat_static_item => ~"static item", - cat_implicit_self => ~"self reference", + cat_static_item => { + ~"static item" + } + cat_implicit_self => { + ~"self reference" + } cat_copied_upvar(_) => { ~"captured outer variable in a heap closure" } - cat_rvalue => ~"non-lvalue", - cat_local(_) => ~"local variable", - cat_self(_) => ~"self value", - cat_arg(*) => ~"argument", - cat_deref(_, _, pk) => fmt!("dereference of %s pointer", - ptr_sigil(pk)), - cat_interior(_, interior_field(*)) => ~"field", - cat_interior(_, interior_tuple) => ~"tuple content", - cat_interior(_, interior_anon_field) => ~"anonymous field", - cat_interior(_, interior_variant(_)) => ~"enum content", - cat_interior(_, interior_index(t, _)) => { - match ty::get(t).sty { - ty::ty_evec(*) => ~"vec content", - ty::ty_estr(*) => ~"str content", - _ => ~"indexed content" - } + cat_rvalue => { + ~"non-lvalue" + } + cat_local(_) => { + ~"local variable" + } + cat_self(_) => { + ~"self value" + } + cat_arg(*) => { + ~"argument" + } + cat_deref(_, _, pk) => { + fmt!("dereference of %s pointer", ptr_sigil(pk)) + } + cat_interior(_, InteriorField(NamedField(_))) => { + ~"field" + } + cat_interior(_, InteriorField(PositionalField(_))) => { + ~"anonymous field" + } + cat_interior(_, InteriorElement(VecElement)) => { + ~"vec content" + } + cat_interior(_, InteriorElement(StrElement)) => { + ~"str content" + } + cat_interior(_, InteriorElement(OtherElement)) => { + ~"indexed content" } cat_stack_upvar(_) => { ~"captured outer variable" @@ -959,10 +1019,13 @@ pub impl mem_categorization_ctxt { cat_discr(cmt, _) => { self.cmt_to_str(cmt) } + cat_downcast(cmt) => { + self.cmt_to_str(cmt) + } } } - fn region_to_str(&self, r: ty::Region) -> ~str { + pub fn region_to_str(&self, r: ty::Region) -> ~str { region_to_str(self.tcx, r) } } @@ -1008,8 +1071,8 @@ pub enum AliasableReason { AliasableOther } -pub impl cmt_ { - fn guarantor(@self) -> cmt { +impl cmt_ { + pub fn guarantor(@self) -> cmt { //! Returns `self` after stripping away any owned pointer derefs or //! interior content. The return value is basically the `cmt` which //! determines how long the value in `self` remains live. @@ -1027,6 +1090,7 @@ pub impl cmt_ { cat_deref(_, _, region_ptr(*)) => { self } + cat_downcast(b) | cat_stack_upvar(b) | cat_discr(b, _) | cat_interior(b, _) | @@ -1036,11 +1100,11 @@ pub impl cmt_ { } } - fn is_freely_aliasable(&self) -> bool { + pub fn is_freely_aliasable(&self) -> bool { self.freely_aliasable().is_some() } - fn freely_aliasable(&self) -> Option { + pub fn freely_aliasable(&self) -> Option { //! True if this lvalue resides in an area that is //! freely aliasable, meaning that rustc cannot track //! the alias//es with precision. @@ -1075,6 +1139,7 @@ pub impl cmt_ { Some(AliasableBorrowed(m)) } + cat_downcast(b) | cat_stack_upvar(b) | cat_deref(b, _, uniq_ptr(*)) | cat_interior(b, _) | @@ -1114,6 +1179,9 @@ impl Repr for categorization { cmt.cat.repr(tcx), interior.repr(tcx)) } + cat_downcast(cmt) => { + fmt!("%s->(enum)", cmt.cat.repr(tcx)) + } cat_stack_upvar(cmt) | cat_discr(cmt, _) => cmt.cat.repr(tcx) } @@ -1129,14 +1197,20 @@ pub fn ptr_sigil(ptr: ptr_kind) -> ~str { } } -impl Repr for interior_kind { +impl Repr for InteriorKind { fn repr(&self, tcx: ty::ctxt) -> ~str { match *self { - interior_field(fld) => copy *tcx.sess.str_of(fld), - interior_index(*) => ~"[]", - interior_tuple => ~"()", - interior_anon_field => ~"", - interior_variant(_) => ~"" + InteriorField(NamedField(fld)) => copy *tcx.sess.str_of(fld), + InteriorField(PositionalField(i)) => fmt!("#%?", i), + InteriorElement(_) => ~"[]", } } } + +fn element_kind(t: ty::t) -> ElementKind { + match ty::get(t).sty { + ty::ty_evec(*) => VecElement, + ty::ty_estr(*) => StrElement, + _ => OtherElement + } +} diff --git a/src/librustc/middle/moves.rs b/src/librustc/middle/moves.rs index e81a9d6b78fcd..caa18b2834fe5 100644 --- a/src/librustc/middle/moves.rs +++ b/src/librustc/middle/moves.rs @@ -88,112 +88,32 @@ Similar reasoning can be applied to `let` expressions: ## Output -The pass results in the struct `MoveMaps` which contains two sets, -`moves_map` and `variable_moves_map`, and one map, `capture_map`. - -`moves_map` is a set containing the id of every *outermost -expression* or *binding* that is moved. Note that `moves_map` only -contains the *outermost expressions* that are moved. Therefore, if -you have a use of `x.b`, as in the example `y` above, the -expression `x.b` would be in the `moves_map` but not `x`. The -reason for this is that, for most purposes, it's only the outermost -expression that is needed. The borrow checker and trans, for -example, only care about the outermost expressions that are moved. -It is more efficient therefore just to store those entries. - -In the case of the liveness pass, however, we need to know which -*variable references* are moved (see the Enforcement of Moves -section below for more details). That is, for the `x.b` -expression, liveness only cares about the `x`. For this purpose, -we have a second map, `variable_moves_map`, that contains the ids -of all variable references which is moved. - -The `capture_map` maps from the node_id of a closure expression to an -array of `CaptureVar` structs detailing which variables are captured -and how (by ref, by copy, by move). +The pass results in the struct `MoveMaps` which contains several +maps: + +`moves_map` is a set containing the id of every *outermost expression* or +*binding* that causes a move. Note that `moves_map` only contains the *outermost +expressions* that are moved. Therefore, if you have a use of `x.b`, +as in the example `y` above, the expression `x.b` would be in the +`moves_map` but not `x`. The reason for this is that, for most +purposes, it's only the outermost expression that is needed. The +borrow checker and trans, for example, only care about the outermost +expressions that are moved. It is more efficient therefore just to +store those entries. + +Sometimes though we want to know the variables that are moved (in +particular in the borrow checker). For these cases, the set +`moved_variables_set` just collects the ids of variables that are +moved. + +Finally, the `capture_map` maps from the node_id of a closure +expression to an array of `CaptureVar` structs detailing which +variables are captured and how (by ref, by copy, by move). ## Enforcement of Moves -The enforcement of moves is somewhat complicated because it is divided -amongst the liveness and borrowck modules. In general, the borrow -checker is responsible for guaranteeing that *only owned data is -moved*. The liveness checker, in contrast, is responsible for -checking that *no variable is used after it is moved*. - -To see the difference, let's look at a few examples. Here is a -program fragment where the error would be caught by liveness: - - struct Foo { a: int, b: ~int } - let x: Foo = ...; - let y = x.b; // (1) - let z = x; // (2) //~ ERROR use of moved value `x` - -Here the liveness checker will see the assignment to `y` moves -invalidates the variable `x` because it moves the expression `x.b`. -An error is resported because `x` is not dead at the point where it is -invalidated. - -In more concrete terms, the `moves_map` generated from this example -would contain both the expression `x.b` (1) and the expression `x` -(2). Note that it would not contain `x` (1), because `moves_map` only -contains the outermost expressions that are moved. However, -`moves_map` is not used by liveness. It uses the -`variable_moves_map`, which would contain both references to `x`: (1) -and (2). Therefore, after computing which variables are live where, -liveness will see that the reference (1) to `x` is both present in -`variable_moves_map` and that `x` is live and report an error. - -Now let's look at another illegal example, but one where liveness would -not catch the error: - - struct Foo { a: int, b: ~int } - let x: @Foo = ...; - let y = x.b; //~ ERROR move from managed (@) box - -This is an interesting example because the only change I've made is -to make `x` have type `@Foo` and not `Foo`. Thanks to auto-deref, -the expression `x.b` still works, but now it is short for `{x).b`, -and hence the move is actually moving out of the contents of a -managed box, which is illegal. However, liveness knows nothing of -this. It only tracks what variables are used where. The moves -pass (that is, this pass) is also ignorant of such details. From -the perspective of the moves pass, the `let y = x.b` line above -will be categorized as follows: - - let y = {(x{Move}) {Move}).b; {Move} - -Therefore, the reference to `x` will be present in -`variable_moves_map`, but liveness will not report an error because -there is no subsequent use. - -This is where the borrow checker comes in. When the borrow checker -runs, it will see that `x.b` is present in the `moves_map`. It will -use the `mem_categorization` module to determine where the result of -this expression resides in memory and see that it is owned by managed -data, and report an error. - -In principle, liveness could use the `mem_categorization` module -itself and check that moves always originate from owned data -(historically, of course, this was not the case; `mem_categorization` -used to be private to the borrow checker). However, there is another -kind of error which liveness could not possibly detect. Sometimes a -move is an error due to an outstanding loan, and it is borrow -checker's job to compute those loans. That is, consider *this* -example: - - struct Foo { a: int, b: ~int } - let x: Foo = ...; - let y = &x.b; //~ NOTE loan issued here - let z = x.b; //~ ERROR move with outstanding loan - -In this case, `y` is a pointer into `x`, so when `z` tries to move out -of `x`, we get an error. There is no way that liveness could compute -this information without redoing the efforts of the borrow checker. - -### Closures - -Liveness is somewhat complicated by having to deal with stack -closures. More information to come! +The enforcement of moves is done by the borrow checker. Please see +the section "Moves and initialization" in `middle/borrowck/doc.rs`. ## Distributive property @@ -206,19 +126,22 @@ and so on. */ +use core::prelude::*; + use middle::pat_util::{pat_bindings}; use middle::freevars; use middle::ty; use middle::typeck::{method_map}; use util::ppaux; +use util::ppaux::Repr; use util::common::indenter; +use core::at_vec; use core::hashmap::{HashSet, HashMap}; use syntax::ast::*; use syntax::ast_util; use syntax::visit; use syntax::visit::vt; -use syntax::print::pprust; use syntax::codemap::span; #[deriving(Encodable, Decodable)] @@ -239,11 +162,6 @@ pub type CaptureMap = @mut HashMap; pub type MovesMap = @mut HashSet; -/** - * For each variable which will be moved, links to the - * expression */ -pub type VariableMovesMap = @mut HashMap; - /** * Set of variable node-ids that are moved. * @@ -255,7 +173,6 @@ pub type MovedVariablesSet = @mut HashSet; /** See the section Output on the module comment for explanation. */ pub struct MoveMaps { moves_map: MovesMap, - variable_moves_map: VariableMovesMap, moved_variables_set: MovedVariablesSet, capture_map: CaptureMap } @@ -267,9 +184,8 @@ struct VisitContext { } enum UseMode { - MoveInWhole, // Move the entire value. - MoveInPart(@expr), // Some subcomponent will be moved - Read // Read no matter what the type. + Move, // This value or something owned by it is moved. + Read // Read no matter what the type. } pub fn compute_moves(tcx: ty::ctxt, @@ -285,7 +201,6 @@ pub fn compute_moves(tcx: ty::ctxt, method_map: method_map, move_maps: MoveMaps { moves_map: @mut HashSet::new(), - variable_moves_map: @mut HashMap::new(), capture_map: @mut HashMap::new(), moved_variables_set: @mut HashSet::new() } @@ -315,56 +230,33 @@ fn compute_modes_for_expr(expr: @expr, cx.consume_expr(expr, v); } -pub impl UseMode { - fn component_mode(&self, expr: @expr) -> UseMode { - /*! - * - * Assuming that `self` is the mode for an expression E, - * returns the appropriate mode to use for a subexpression of E. - */ - - match *self { - Read | MoveInPart(_) => *self, - MoveInWhole => MoveInPart(expr) - } - } -} - -pub impl VisitContext { - fn consume_exprs(&self, - exprs: &[@expr], - visitor: vt) - { +impl VisitContext { + pub fn consume_exprs(&self, exprs: &[@expr], visitor: vt) { for exprs.each |expr| { self.consume_expr(*expr, visitor); } } - fn consume_expr(&self, - expr: @expr, - visitor: vt) - { + pub fn consume_expr(&self, expr: @expr, visitor: vt) { /*! - * * Indicates that the value of `expr` will be consumed, * meaning either copied or moved depending on its type. */ - debug!("consume_expr(expr=%?/%s)", - expr.id, - pprust::expr_to_str(expr, self.tcx.sess.intr())); + debug!("consume_expr(expr=%s)", + expr.repr(self.tcx)); let expr_ty = ty::expr_ty_adjusted(self.tcx, expr); - let mode = self.consume_mode_for_ty(expr_ty); - self.use_expr(expr, mode, visitor); + if ty::type_moves_by_default(self.tcx, expr_ty) { + self.move_maps.moves_map.insert(expr.id); + self.use_expr(expr, Move, visitor); + } else { + self.use_expr(expr, Read, visitor); + }; } - fn consume_block(&self, - blk: &blk, - visitor: vt) - { + pub fn consume_block(&self, blk: &blk, visitor: vt) { /*! - * * Indicates that the value of `blk` will be consumed, * meaning either copied or moved depending on its type. */ @@ -380,46 +272,19 @@ pub impl VisitContext { } } - fn consume_mode_for_ty(&self, ty: ty::t) -> UseMode { - /*! - * - * Selects the appropriate `UseMode` to consume a value with - * the type `ty`. This will be `MoveEntireMode` if `ty` is - * not implicitly copyable. - */ - - let result = if ty::type_moves_by_default(self.tcx, ty) { - MoveInWhole - } else { - Read - }; - - debug!("consume_mode_for_ty(ty=%s) = %?", - ppaux::ty_to_str(self.tcx, ty), result); - - return result; - } - - fn use_expr(&self, - expr: @expr, - expr_mode: UseMode, - visitor: vt) - { + pub fn use_expr(&self, + expr: @expr, + expr_mode: UseMode, + visitor: vt) { /*! - * * Indicates that `expr` is used with a given mode. This will * in turn trigger calls to the subcomponents of `expr`. */ - debug!("use_expr(expr=%?/%s, mode=%?)", - expr.id, pprust::expr_to_str(expr, self.tcx.sess.intr()), + debug!("use_expr(expr=%s, mode=%?)", + expr.repr(self.tcx), expr_mode); - match expr_mode { - MoveInWhole => { self.move_maps.moves_map.insert(expr.id); } - MoveInPart(_) | Read => {} - } - // `expr_mode` refers to the post-adjustment value. If one of // those adjustments is to take a reference, then it's only // reading the underlying expression, not moving it. @@ -427,7 +292,7 @@ pub impl VisitContext { Some(&@ty::AutoDerefRef( ty::AutoDerefRef { autoref: Some(_), _})) => Read, - _ => expr_mode.component_mode(expr) + _ => expr_mode }; debug!("comp_mode = %?", comp_mode); @@ -435,25 +300,17 @@ pub impl VisitContext { match expr.node { expr_path(*) | expr_self => { match comp_mode { - MoveInPart(entire_expr) => { - self.move_maps.variable_moves_map.insert( - expr.id, entire_expr); - + Move => { let def = self.tcx.def_map.get_copy(&expr.id); for moved_variable_node_id_from_def(def).each |&id| { self.move_maps.moved_variables_set.insert(id); } } Read => {} - MoveInWhole => { - self.tcx.sess.span_bug( - expr.span, - "Component mode can never be MoveInWhole"); - } } } - expr_unary(deref, base) => { // *base + expr_unary(_, deref, base) => { // *base if !self.use_overloaded_operator( expr, base, [], visitor) { @@ -467,7 +324,7 @@ pub impl VisitContext { self.use_expr(base, comp_mode, visitor); } - expr_index(lhs, rhs) => { // lhs[rhs] + expr_index(_, lhs, rhs) => { // lhs[rhs] if !self.use_overloaded_operator( expr, lhs, [rhs], visitor) { @@ -481,11 +338,11 @@ pub impl VisitContext { self.use_fn_args(callee.id, *args, visitor); } - expr_method_call(callee, _, _, ref args, _) => { // callee.m(args) + expr_method_call(callee_id, rcvr, _, _, ref args, _) => { // callee.m(args) // Implicit self is equivalent to & mode, but every // other kind should be + mode. - self.use_receiver(callee, visitor); - self.use_fn_args(expr.callee_id, *args, visitor); + self.use_receiver(rcvr, visitor); + self.use_fn_args(callee_id, *args, visitor); } expr_struct(_, ref fields, opt_with) => { @@ -544,19 +401,10 @@ pub impl VisitContext { self.consume_arm(arm, visitor); } - let by_move_bindings_present = - self.arms_have_by_move_bindings( - self.move_maps.moves_map, *arms); - - if by_move_bindings_present { - // If one of the arms moves a value out of the - // discriminant, then the discriminant itself is - // moved. - self.consume_expr(discr, visitor); - } else { - // Otherwise, the discriminant is merely read. - self.use_expr(discr, Read, visitor); - } + // The discriminant may, in fact, be partially moved + // if there are by-move bindings, but borrowck deals + // with that itself. + self.use_expr(discr, Read, visitor); } expr_copy(base) => { @@ -596,7 +444,7 @@ pub impl VisitContext { self.consume_block(blk, visitor); } - expr_unary(_, lhs) => { + expr_unary(_, _, lhs) => { if !self.use_overloaded_operator( expr, lhs, [], visitor) { @@ -604,7 +452,7 @@ pub impl VisitContext { } } - expr_binary(_, lhs, rhs) => { + expr_binary(_, _, lhs, rhs) => { if !self.use_overloaded_operator( expr, lhs, [rhs], visitor) { @@ -632,7 +480,7 @@ pub impl VisitContext { self.consume_expr(base, visitor); } - expr_assign_op(_, lhs, rhs) => { + expr_assign_op(_, _, lhs, rhs) => { // FIXME(#4712) --- Overloaded operators? // // if !self.use_overloaded_operator( @@ -671,12 +519,12 @@ pub impl VisitContext { } } - fn use_overloaded_operator(&self, - expr: @expr, - receiver_expr: @expr, - arg_exprs: &[@expr], - visitor: vt) -> bool - { + pub fn use_overloaded_operator(&self, + expr: @expr, + receiver_expr: @expr, + arg_exprs: &[@expr], + visitor: vt) + -> bool { if !self.method_map.contains_key(&expr.id) { return false; } @@ -692,10 +540,7 @@ pub impl VisitContext { return true; } - fn consume_arm(&self, - arm: &arm, - visitor: vt) - { + pub fn consume_arm(&self, arm: &arm, visitor: vt) { for arm.pats.each |pat| { self.use_pat(*pat); } @@ -707,9 +552,7 @@ pub impl VisitContext { self.consume_block(&arm.body, visitor); } - fn use_pat(&self, - pat: @pat) - { + pub fn use_pat(&self, pat: @pat) { /*! * * Decides whether each binding in a pattern moves the value @@ -717,63 +560,63 @@ pub impl VisitContext { */ do pat_bindings(self.tcx.def_map, pat) |bm, id, _span, _path| { - let mode = match bm { - bind_by_copy => Read, - bind_by_ref(_) => Read, + let binding_moves = match bm { + bind_by_ref(_) => false, bind_infer => { let pat_ty = ty::node_id_to_type(self.tcx, id); - self.consume_mode_for_ty(pat_ty) + debug!("pattern %? type is %s", + id, pat_ty.repr(self.tcx)); + ty::type_moves_by_default(self.tcx, pat_ty) } }; - match mode { - MoveInWhole => { self.move_maps.moves_map.insert(id); } - MoveInPart(_) | Read => {} + debug!("pattern binding %?: bm=%?, binding_moves=%b", + id, bm, binding_moves); + + if binding_moves { + self.move_maps.moves_map.insert(id); } } } - fn use_receiver(&self, - receiver_expr: @expr, - visitor: vt) - { + pub fn use_receiver(&self, + receiver_expr: @expr, + visitor: vt) { self.use_fn_arg(receiver_expr, visitor); } - fn use_fn_args(&self, - _: node_id, - arg_exprs: &[@expr], - visitor: vt) { + pub fn use_fn_args(&self, + _: node_id, + arg_exprs: &[@expr], + visitor: vt) { //! Uses the argument expressions. for arg_exprs.each |arg_expr| { self.use_fn_arg(*arg_expr, visitor); } } - fn use_fn_arg(&self, arg_expr: @expr, visitor: vt) { + pub fn use_fn_arg(&self, arg_expr: @expr, visitor: vt) { //! Uses the argument. self.consume_expr(arg_expr, visitor) } - fn arms_have_by_move_bindings(&self, - moves_map: MovesMap, - arms: &[arm]) -> bool - { + pub fn arms_have_by_move_bindings(&self, + moves_map: MovesMap, + arms: &[arm]) + -> Option<@pat> { for arms.each |arm| { - for arm.pats.each |pat| { - let mut found = false; - do pat_bindings(self.tcx.def_map, *pat) |_, node_id, _, _| { - if moves_map.contains(&node_id) { - found = true; + for arm.pats.each |&pat| { + for ast_util::walk_pat(pat) |p| { + if moves_map.contains(&p.id) { + return Some(p); } } - if found { return true; } } } - return false; + return None; } - fn compute_captures(&self, fn_expr_id: node_id) -> @[CaptureVar] { + pub fn compute_captures(&self, fn_expr_id: node_id) -> @[CaptureVar] { debug!("compute_capture_vars(fn_expr_id=%?)", fn_expr_id); let _indenter = indenter(); diff --git a/src/librustc/middle/pat_util.rs b/src/librustc/middle/pat_util.rs index b87adb75bc37a..1237e9fb4a26a 100644 --- a/src/librustc/middle/pat_util.rs +++ b/src/librustc/middle/pat_util.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use middle::resolve; use core::hashmap::HashMap; @@ -70,8 +72,8 @@ pub fn pat_is_binding_or_wild(dm: resolve::DefMap, pat: @pat) -> bool { } pub fn pat_bindings(dm: resolve::DefMap, pat: @pat, - it: &fn(binding_mode, node_id, span, @Path)) { - do walk_pat(pat) |p| { + it: &fn(binding_mode, node_id, span, @Path)) { + for walk_pat(pat) |p| { match p.node { pat_ident(binding_mode, pth, _) if pat_is_binding(dm, p) => { it(binding_mode, p.id, p.span, pth); diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index ce0f124da74c9..fe30b9c4fd721 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -11,6 +11,8 @@ // A pass that checks to make sure private fields and methods aren't used // outside their scopes. +use core::prelude::*; + use metadata::csearch; use middle::ty::{ty_struct, ty_enum}; use middle::ty; @@ -33,6 +35,7 @@ use syntax::ast_util::{Private, Public, is_local}; use syntax::ast_util::{variant_visibility_to_privacy, visibility_to_privacy}; use syntax::attr; use syntax::codemap::span; +use syntax::parse::token; use syntax::visit; pub fn check_crate(tcx: ty::ctxt, @@ -118,7 +121,7 @@ pub fn check_crate(tcx: ty::ctxt, ast_map::node_id_to_str( tcx.items, method_id, - tcx.sess.parse_sess.interner))); + token::get_ident_interner()))); } None => { tcx.sess.span_bug(span, "method not found in \ @@ -182,7 +185,7 @@ pub fn check_crate(tcx: ty::ctxt, ast_map::node_id_to_str( tcx.items, method_id, - tcx.sess.parse_sess.interner))); + token::get_ident_interner()))); } None => { tcx.sess.span_bug(span, "method not found in \ @@ -198,7 +201,7 @@ pub fn check_crate(tcx: ty::ctxt, f = |item_id| { match tcx.items.find(&item_id) { Some(&node_item(item, _)) => item.vis != public, - Some(&node_foreign_item(_, _, vis, _)) => vis != public, + Some(&node_foreign_item(*)) => false, Some(&node_method(method, impl_did, _)) => { match method.vis { private => true, @@ -214,9 +217,7 @@ pub fn check_crate(tcx: ty::ctxt, ast_map::node_id_to_str( tcx.items, item_id, - tcx.sess - .parse_sess - .interner))); + token::get_ident_interner()))); } None => { tcx.sess.span_bug(span, "item not found in AST map?!"); @@ -234,8 +235,7 @@ pub fn check_crate(tcx: ty::ctxt, if field.ident != ident { loop; } if field.vis == private { tcx.sess.span_err(span, fmt!("field `%s` is private", - *tcx.sess.parse_sess.interner - .get(ident))); + *token::ident_to_str(&ident))); } break; } @@ -255,10 +255,7 @@ pub fn check_crate(tcx: ty::ctxt, !privileged_items.contains(&(container_id.node))) { tcx.sess.span_err(span, fmt!("method `%s` is private", - *tcx.sess - .parse_sess - .interner - .get(*name))); + *token::ident_to_str(name))); } } else { let visibility = @@ -266,8 +263,7 @@ pub fn check_crate(tcx: ty::ctxt, if visibility != public { tcx.sess.span_err(span, fmt!("method `%s` is private", - *tcx.sess.parse_sess.interner - .get(*name))); + *token::ident_to_str(name))); } } }; @@ -287,23 +283,13 @@ pub fn check_crate(tcx: ty::ctxt, !privileged_items.contains(&def_id.node) { tcx.sess.span_err(span, fmt!("function `%s` is private", - *tcx.sess - .parse_sess - .interner - .get(copy *path - .idents - .last()))); + *token::ident_to_str(path.idents.last()))); } } else if csearch::get_item_visibility(tcx.sess.cstore, def_id) != public { tcx.sess.span_err(span, fmt!("function `%s` is private", - *tcx.sess - .parse_sess - .interner - .get(copy *path - .idents - .last()))); + *token::ident_to_str(path.idents.last()))); } } _ => {} @@ -333,10 +319,7 @@ pub fn check_crate(tcx: ty::ctxt, match item.node { item_trait(_, _, ref methods) => { if method_num >= (*methods).len() { - tcx.sess.span_bug(span, "method \ - number \ - out of \ - range?!"); + tcx.sess.span_bug(span, "method number out of range?!"); } match (*methods)[method_num] { provided(method) @@ -344,17 +327,9 @@ pub fn check_crate(tcx: ty::ctxt, !privileged_items .contains(&(trait_id.node)) => { tcx.sess.span_err(span, - fmt!("method - `%s` \ - is \ - private", - *tcx - .sess - .parse_sess - .interner - .get - (method - .ident))); + fmt!("method `%s` is private", + *token::ident_to_str(&method + .ident))); } provided(_) | required(_) => { // Required methods can't be @@ -363,20 +338,15 @@ pub fn check_crate(tcx: ty::ctxt, } } _ => { - tcx.sess.span_bug(span, "trait wasn't \ - actually a \ - trait?!"); + tcx.sess.span_bug(span, "trait wasn't actually a trait?!"); } } } Some(_) => { - tcx.sess.span_bug(span, "trait wasn't an \ - item?!"); + tcx.sess.span_bug(span, "trait wasn't an item?!"); } None => { - tcx.sess.span_bug(span, "trait item wasn't \ - found in the AST \ - map?!"); + tcx.sess.span_bug(span, "trait item wasn't found in the AST map?!"); } } } else { @@ -400,7 +370,7 @@ pub fn check_crate(tcx: ty::ctxt, // Do not check privacy inside items with the resolve_unexported // attribute. This is used for the test runner. if !attr::contains_name(attr::attr_metas(/*bad*/copy item.attrs), - ~"!resolve_unexported") { + "!resolve_unexported") { visit::visit_item(item, method_map, visitor); } }, @@ -430,32 +400,23 @@ pub fn check_crate(tcx: ty::ctxt, visit_expr: |expr, method_map: &method_map, visitor| { match expr.node { expr_field(base, ident, _) => { + // Method calls are now a special syntactic form, + // so `a.b` should always be a field. + assert!(!method_map.contains_key(&expr.id)); + // With type_autoderef, make sure we don't // allow pointers to violate privacy match ty::get(ty::type_autoderef(tcx, ty::expr_ty(tcx, base))).sty { ty_struct(id, _) - if id.crate != local_crate || - !privileged_items.contains(&(id.node)) => { - match method_map.find(&expr.id) { - None => { - debug!("(privacy checking) checking \ - field access"); - check_field(expr.span, id, ident); - } - Some(ref entry) => { - debug!("(privacy checking) checking \ - impl method"); - check_method(expr.span, - &entry.origin, - ident); - } - } + if id.crate != local_crate || !privileged_items.contains(&(id.node)) => { + debug!("(privacy checking) checking field access"); + check_field(expr.span, id, ident); } _ => {} } } - expr_method_call(base, ident, _, _, _) => { + expr_method_call(_, base, ident, _, _, _) => { // Ditto match ty::get(ty::type_autoderef(tcx, ty::expr_ty(tcx, base))).sty { @@ -527,7 +488,7 @@ pub fn check_crate(tcx: ty::ctxt, } } } - expr_unary(ast::deref, operand) => { + expr_unary(_, ast::deref, operand) => { // In *e, we need to check that if e's type is an // enum type t, then t's first variant is public or // privileged. (We can assume it has only one variant diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 27b6273879399..5ccb38b960d58 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -17,6 +17,8 @@ region parameterized. */ +use core::prelude::*; + use driver::session::Session; use metadata::csearch; use middle::resolve; @@ -28,6 +30,7 @@ use core::hashmap::{HashMap, HashSet}; use syntax::ast_map; use syntax::codemap::span; use syntax::print::pprust; +use syntax::parse::token; use syntax::parse::token::special_idents; use syntax::{ast, visit}; @@ -71,11 +74,8 @@ pub struct Context { parent: parent, } -pub impl RegionMaps { - fn relate_free_regions(&mut self, - sub: FreeRegion, - sup: FreeRegion) - { +impl RegionMaps { + pub fn relate_free_regions(&mut self, sub: FreeRegion, sup: FreeRegion) { match self.free_region_map.find_mut(&sub) { Some(sups) => { if !sups.contains(&sup) { @@ -91,19 +91,14 @@ pub impl RegionMaps { self.free_region_map.insert(sub, ~[sup]); } - fn record_parent(&mut self, - sub: ast::node_id, - sup: ast::node_id) - { + pub fn record_parent(&mut self, sub: ast::node_id, sup: ast::node_id) { debug!("record_parent(sub=%?, sup=%?)", sub, sup); assert!(sub != sup); self.scope_map.insert(sub, sup); } - pub fn record_cleanup_scope(&mut self, - scope_id: ast::node_id) - { + pub fn record_cleanup_scope(&mut self, scope_id: ast::node_id) { //! Records that a scope is a CLEANUP SCOPE. This is invoked //! from within regionck. We wait until regionck because we do //! not know which operators are overloaded until that point, @@ -112,17 +107,13 @@ pub impl RegionMaps { self.cleanup_scopes.insert(scope_id); } - fn opt_encl_scope(&self, - id: ast::node_id) -> Option - { + pub fn opt_encl_scope(&self, id: ast::node_id) -> Option { //! Returns the narrowest scope that encloses `id`, if any. self.scope_map.find(&id).map(|&x| *x) } - fn encl_scope(&self, - id: ast::node_id) -> ast::node_id - { + pub fn encl_scope(&self, id: ast::node_id) -> ast::node_id { //! Returns the narrowest scope that encloses `id`, if any. match self.scope_map.find(&id) { @@ -131,13 +122,11 @@ pub impl RegionMaps { } } - fn is_cleanup_scope(&self, scope_id: ast::node_id) -> bool { + pub fn is_cleanup_scope(&self, scope_id: ast::node_id) -> bool { self.cleanup_scopes.contains(&scope_id) } - fn cleanup_scope(&self, - expr_id: ast::node_id) -> ast::node_id - { + pub fn cleanup_scope(&self, expr_id: ast::node_id) -> ast::node_id { //! Returns the scope when temps in expr will be cleaned up let mut id = self.encl_scope(expr_id); @@ -147,25 +136,22 @@ pub impl RegionMaps { return id; } - fn encl_region(&self, - id: ast::node_id) -> ty::Region - { + pub fn encl_region(&self, id: ast::node_id) -> ty::Region { //! Returns the narrowest scope region that encloses `id`, if any. ty::re_scope(self.encl_scope(id)) } - pub fn scopes_intersect(&self, - scope1: ast::node_id, - scope2: ast::node_id) -> bool - { - self.is_subscope_of(scope1, scope2) || self.is_subscope_of(scope2, scope1) + pub fn scopes_intersect(&self, scope1: ast::node_id, scope2: ast::node_id) + -> bool { + self.is_subscope_of(scope1, scope2) || + self.is_subscope_of(scope2, scope1) } - fn is_subscope_of(&self, - subscope: ast::node_id, - superscope: ast::node_id) -> bool - { + pub fn is_subscope_of(&self, + subscope: ast::node_id, + superscope: ast::node_id) + -> bool { /*! * Returns true if `subscope` is equal to or is lexically * nested inside `superscope` and false otherwise. @@ -190,10 +176,7 @@ pub impl RegionMaps { return true; } - fn sub_free_region(&self, - sub: FreeRegion, - sup: FreeRegion) -> bool - { + pub fn sub_free_region(&self, sub: FreeRegion, sup: FreeRegion) -> bool { /*! * Determines whether two free regions have a subregion relationship * by walking the graph encoded in `free_region_map`. Note that @@ -231,10 +214,10 @@ pub impl RegionMaps { return false; } - fn is_subregion_of(&self, - sub_region: ty::Region, - super_region: ty::Region) -> bool - { + pub fn is_subregion_of(&self, + sub_region: ty::Region, + super_region: ty::Region) + -> bool { /*! * Determines whether one region is a subregion of another. This is * intended to run *after inference* and sadly the logic is somewhat @@ -269,10 +252,10 @@ pub impl RegionMaps { } } - fn nearest_common_ancestor(&self, - scope_a: ast::node_id, - scope_b: ast::node_id) -> Option - { + pub fn nearest_common_ancestor(&self, + scope_a: ast::node_id, + scope_b: ast::node_id) + -> Option { /*! * Finds the nearest common ancestor (if any) of two scopes. That * is, finds the smallest scope which is greater than or equal to @@ -343,7 +326,9 @@ pub fn parent_id(cx: Context, span: span) -> ast::node_id { } /// Records the current parent (if any) as the parent of `child_id`. -pub fn parent_to_expr(cx: Context, child_id: ast::node_id) { +pub fn parent_to_expr(cx: Context, child_id: ast::node_id, sp: span) { + debug!("region::parent_to_expr(span=%?)", + cx.sess.codemap.span_to_str(sp)); for cx.parent.each |parent_id| { cx.region_maps.record_parent(child_id, *parent_id); } @@ -351,7 +336,7 @@ pub fn parent_to_expr(cx: Context, child_id: ast::node_id) { pub fn resolve_block(blk: &ast::blk, cx: Context, visitor: visit::vt) { // Record the parent of this block. - parent_to_expr(cx, blk.node.id); + parent_to_expr(cx, blk.node.id, blk.span); // Descend. let new_cx = Context {var_parent: Some(blk.node.id), @@ -365,8 +350,8 @@ pub fn resolve_arm(arm: &ast::arm, cx: Context, visitor: visit::vt) { } pub fn resolve_pat(pat: @ast::pat, cx: Context, visitor: visit::vt) { - assert!(cx.var_parent == cx.parent); - parent_to_expr(cx, pat.id); + assert_eq!(cx.var_parent, cx.parent); + parent_to_expr(cx, pat.id, pat.span); visit::visit_pat(pat, cx, visitor); } @@ -377,16 +362,16 @@ pub fn resolve_stmt(stmt: @ast::stmt, cx: Context, visitor: visit::vt) } ast::stmt_expr(_, stmt_id) | ast::stmt_semi(_, stmt_id) => { - parent_to_expr(cx, stmt_id); + parent_to_expr(cx, stmt_id, stmt.span); let expr_cx = Context {parent: Some(stmt_id), ..cx}; visit::visit_stmt(stmt, expr_cx, visitor); } - ast::stmt_mac(*) => cx.sess.bug(~"unexpanded macro") + ast::stmt_mac(*) => cx.sess.bug("unexpanded macro") } } pub fn resolve_expr(expr: @ast::expr, cx: Context, visitor: visit::vt) { - parent_to_expr(cx, expr.id); + parent_to_expr(cx, expr.id, expr.span); let mut new_cx = cx; new_cx.parent = Some(expr.id); @@ -427,8 +412,8 @@ pub fn resolve_expr(expr: @ast::expr, cx: Context, visitor: visit::vt) pub fn resolve_local(local: @ast::local, cx: Context, visitor: visit::vt) { - assert!(cx.var_parent == cx.parent); - parent_to_expr(cx, local.node.id); + assert_eq!(cx.var_parent, cx.parent); + parent_to_expr(cx, local.node.id, local.span); visit::visit_local(local, cx, visitor); } @@ -441,12 +426,18 @@ pub fn resolve_item(item: @ast::item, cx: Context, visitor: visit::vt) pub fn resolve_fn(fk: &visit::fn_kind, decl: &ast::fn_decl, body: &ast::blk, - _sp: span, + sp: span, id: ast::node_id, cx: Context, visitor: visit::vt) { - debug!("region::resolve_fn(id=%?, body.node.id=%?, cx.parent=%?)", - id, body.node.id, cx.parent); + debug!("region::resolve_fn(id=%?, \ + span=%?, \ + body.node.id=%?, \ + cx.parent=%?)", + id, + cx.sess.codemap.span_to_str(sp), + body.node.id, + cx.parent); // The arguments and `self` are parented to the body of the fn. let decl_cx = Context {parent: Some(body.node.id), @@ -586,15 +577,15 @@ pub fn add_variance(ambient_variance: region_variance, } } -pub impl DetermineRpCtxt { - fn add_variance(&self, variance: region_variance) -> region_variance { +impl DetermineRpCtxt { + pub fn add_variance(&self, variance: region_variance) -> region_variance { add_variance(self.ambient_variance, variance) } /// Records that item `id` is region-parameterized with the /// variance `variance`. If `id` was already parameterized, then /// the new variance is joined with the old variance. - fn add_rp(&mut self, id: ast::node_id, variance: region_variance) { + pub fn add_rp(&mut self, id: ast::node_id, variance: region_variance) { assert!(id != 0); let old_variance = self.region_paramd_items.find(&id). map_consume(|x| *x); @@ -605,7 +596,7 @@ pub impl DetermineRpCtxt { debug!("add_rp() variance for %s: %? == %? ^ %?", ast_map::node_id_to_str(self.ast_map, id, - self.sess.parse_sess.interner), + token::get_ident_interner()), joined_variance, old_variance, variance); if Some(joined_variance) != old_variance { @@ -620,13 +611,13 @@ pub impl DetermineRpCtxt { /// `from`. Put another way, it indicates that the current item /// contains a value of type `from`, so if `from` is /// region-parameterized, so is the current item. - fn add_dep(&mut self, from: ast::node_id) { + pub fn add_dep(&mut self, from: ast::node_id) { debug!("add dependency from %d -> %d (%s -> %s) with variance %?", from, self.item_id, ast_map::node_id_to_str(self.ast_map, from, - self.sess.parse_sess.interner), + token::get_ident_interner()), ast_map::node_id_to_str(self.ast_map, self.item_id, - self.sess.parse_sess.interner), + token::get_ident_interner()), copy self.ambient_variance); let vec = match self.dep_map.find(&from) { Some(&vec) => vec, @@ -680,7 +671,7 @@ pub impl DetermineRpCtxt { // with &self type, &self is also bound. We detect those last two // cases via flags (anon_implies_rp and self_implies_rp) that are // true when the anon or self region implies RP. - fn region_is_relevant(&self, r: Option<@ast::Lifetime>) -> bool { + pub fn region_is_relevant(&self, r: Option<@ast::Lifetime>) -> bool { match r { None => { self.anon_implies_rp @@ -697,10 +688,10 @@ pub impl DetermineRpCtxt { } } - fn with(@mut self, - item_id: ast::node_id, - anon_implies_rp: bool, - f: &fn()) { + pub fn with(@mut self, + item_id: ast::node_id, + anon_implies_rp: bool, + f: &fn()) { let old_item_id = self.item_id; let old_anon_implies_rp = self.anon_implies_rp; self.item_id = item_id; @@ -714,7 +705,9 @@ pub impl DetermineRpCtxt { self.anon_implies_rp = old_anon_implies_rp; } - fn with_ambient_variance(@mut self, variance: region_variance, f: &fn()) { + pub fn with_ambient_variance(@mut self, + variance: region_variance, + f: &fn()) { let old_ambient_variance = self.ambient_variance; self.ambient_variance = self.add_variance(variance); f(); @@ -959,7 +952,7 @@ pub fn determine_rp_in_crate(sess: Session, debug!("item %? (%s) is parameterized with variance %?", key, ast_map::node_id_to_str(ast_map, key, - sess.parse_sess.interner), + token::get_ident_interner()), value); } "----" diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index a7e590e359c4d..c23932b14b51c 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use driver::session::Session; use metadata::csearch::{each_path, get_trait_method_def_ids}; use metadata::csearch::get_method_name_and_explicit_self; @@ -20,11 +22,13 @@ use middle::lint::unused_imports; use middle::pat_util::pat_bindings; use syntax::ast::*; +use syntax::ast; use syntax::ast_util::{def_id_of_def, local_def}; use syntax::ast_util::{path_to_ident, walk_pat, trait_method_to_ty_method}; use syntax::ast_util::{Privacy, Public, Private}; use syntax::ast_util::{variant_visibility_to_privacy, visibility_to_privacy}; use syntax::attr::{attr_metas, contains_name}; +use syntax::parse::token; use syntax::parse::token::ident_interner; use syntax::parse::token::special_idents; use syntax::print::pprust::path_to_str; @@ -36,8 +40,10 @@ use syntax::visit::{visit_foreign_item, visit_item}; use syntax::visit::{visit_mod, visit_ty, vt}; use syntax::opt_vec::OptVec; -use core::option::Some; use core::str::each_split_str; +use core::str; +use core::uint; +use core::vec; use core::hashmap::{HashMap, HashSet}; use core::util; @@ -112,8 +118,8 @@ pub enum NamespaceResult { BoundResult(@mut Module, @mut NameBindings) } -pub impl NamespaceResult { - fn is_unknown(&self) -> bool { +impl NamespaceResult { + pub fn is_unknown(&self) -> bool { match *self { UnknownResult => true, _ => false @@ -157,11 +163,11 @@ pub enum ResolveResult { Success(T) // Successfully resolved the import. } -pub impl ResolveResult { - fn failed(&self) -> bool { +impl ResolveResult { + pub fn failed(&self) -> bool { match *self { Failed => true, _ => false } } - fn indeterminate(&self) -> bool { + pub fn indeterminate(&self) -> bool { match *self { Indeterminate => true, _ => false } } } @@ -255,8 +261,20 @@ pub enum AllowCapturingSelfFlag { #[deriving(Eq)] enum NameSearchType { - SearchItemsAndPublicImports, //< Search items and public imports. - SearchItemsAndAllImports, //< Search items and all imports. + /// We're doing a name search in order to resolve a `use` directive. + ImportSearch, + + /// We're doing a name search in order to resolve a path type, a path + /// expression, or a path pattern. We can select public or private + /// names. + /// + /// XXX: This should be ripped out of resolve and handled later, in + /// the privacy checking phase. + PathPublicOrPrivateSearch, + + /// We're doing a name search in order to resolve a path type, a path + /// expression, or a path pattern. Allow only public names to be selected. + PathPublicOnlySearch, } pub enum BareIdentifierPatternResolution { @@ -373,8 +391,9 @@ pub fn ImportResolution(privacy: Privacy, } } -pub impl ImportResolution { - fn target_for_namespace(&self, namespace: Namespace) -> Option { +impl ImportResolution { + pub fn target_for_namespace(&self, namespace: Namespace) + -> Option { match namespace { TypeNS => return copy self.type_target, ValueNS => return copy self.value_target @@ -394,6 +413,7 @@ pub enum ModuleKind { NormalModuleKind, ExternModuleKind, TraitModuleKind, + ImplModuleKind, AnonymousModuleKind, } @@ -424,7 +444,6 @@ pub struct Module { // // There will be an anonymous module created around `g` with the ID of the // entry block for `f`. - anonymous_children: @mut HashMap, // The status of resolving each import in this module. @@ -455,8 +474,8 @@ pub fn Module(parent_link: ParentLink, } } -pub impl Module { - fn all_imports_resolved(&self) -> bool { +impl Module { + pub fn all_imports_resolved(&self) -> bool { let imports = &mut *self.imports; return imports.len() == self.resolved_import_count; } @@ -484,14 +503,14 @@ pub struct NameBindings { value_def: Option, //< Meaning in value namespace. } -pub impl NameBindings { +impl NameBindings { /// Creates a new module in this set of name bindings. - fn define_module(@mut self, - privacy: Privacy, - parent_link: ParentLink, - def_id: Option, - kind: ModuleKind, - sp: span) { + pub fn define_module(@mut self, + privacy: Privacy, + parent_link: ParentLink, + def_id: Option, + kind: ModuleKind, + sp: span) { // Merges the module with the existing type def or creates a new one. let module_ = @mut Module(parent_link, def_id, kind); match self.type_def { @@ -503,19 +522,53 @@ pub impl NameBindings { type_span: Some(sp) }); } - Some(copy type_def) => { + Some(type_def) => { self.type_def = Some(TypeNsDef { privacy: privacy, module_def: Some(module_), type_span: Some(sp), - .. type_def + type_def: type_def.type_def }); } } } + /// Sets the kind of the module, creating a new one if necessary. + pub fn set_module_kind(@mut self, + privacy: Privacy, + parent_link: ParentLink, + def_id: Option, + kind: ModuleKind, + _sp: span) { + match self.type_def { + None => { + let module = @mut Module(parent_link, def_id, kind); + self.type_def = Some(TypeNsDef { + privacy: privacy, + module_def: Some(module), + type_def: None, + type_span: None, + }) + } + Some(type_def) => { + match type_def.module_def { + None => { + let module = @mut Module(parent_link, def_id, kind); + self.type_def = Some(TypeNsDef { + privacy: privacy, + module_def: Some(module), + type_def: type_def.type_def, + type_span: None, + }) + } + Some(module_def) => module_def.kind = kind, + } + } + } + } + /// Records a type definition. - fn define_type(@mut self, privacy: Privacy, def: def, sp: span) { + pub fn define_type(@mut self, privacy: Privacy, def: def, sp: span) { // Merges the type with the existing type def or creates a new one. match self.type_def { None => { @@ -526,24 +579,24 @@ pub impl NameBindings { type_span: Some(sp) }); } - Some(copy type_def) => { + Some(type_def) => { self.type_def = Some(TypeNsDef { privacy: privacy, type_def: Some(def), type_span: Some(sp), - .. type_def + module_def: type_def.module_def }); } } } /// Records a value definition. - fn define_value(@mut self, privacy: Privacy, def: def, sp: span) { + pub fn define_value(@mut self, privacy: Privacy, def: def, sp: span) { self.value_def = Some(ValueNsDef { privacy: privacy, def: def, value_span: Some(sp) }); } /// Returns the module node if applicable. - fn get_module_if_available(&self) -> Option<@mut Module> { + pub fn get_module_if_available(&self) -> Option<@mut Module> { match self.type_def { Some(ref type_def) => (*type_def).module_def, None => None @@ -554,7 +607,7 @@ pub impl NameBindings { * Returns the module node. Fails if this node does not have a module * definition. */ - fn get_module(@mut self) -> @mut Module { + pub fn get_module(@mut self) -> @mut Module { match self.get_module_if_available() { None => { fail!("get_module called on a node with no module \ @@ -564,14 +617,14 @@ pub impl NameBindings { } } - fn defined_in_namespace(&self, namespace: Namespace) -> bool { + pub fn defined_in_namespace(&self, namespace: Namespace) -> bool { match namespace { TypeNS => return self.type_def.is_some(), ValueNS => return self.value_def.is_some() } } - fn defined_in_public_namespace(&self, namespace: Namespace) -> bool { + pub fn defined_in_public_namespace(&self, namespace: Namespace) -> bool { match namespace { TypeNS => match self.type_def { Some(def) => def.privacy != Private, @@ -584,7 +637,7 @@ pub impl NameBindings { } } - fn def_for_namespace(&self, namespace: Namespace) -> Option { + pub fn def_for_namespace(&self, namespace: Namespace) -> Option { match namespace { TypeNS => { match self.type_def { @@ -618,7 +671,8 @@ pub impl NameBindings { } } - fn privacy_for_namespace(&self, namespace: Namespace) -> Option { + pub fn privacy_for_namespace(&self, namespace: Namespace) + -> Option { match namespace { TypeNS => { match self.type_def { @@ -635,7 +689,7 @@ pub impl NameBindings { } } - fn span_for_namespace(&self, namespace: Namespace) -> Option { + pub fn span_for_namespace(&self, namespace: Namespace) -> Option { if self.defined_in_namespace(namespace) { match namespace { TypeNS => { @@ -669,10 +723,12 @@ pub struct PrimitiveTypeTable { primitive_types: HashMap, } -pub impl PrimitiveTypeTable { - fn intern(&mut self, intr: @ident_interner, string: &str, - primitive_type: prim_ty) { - let ident = intr.intern(string); +impl PrimitiveTypeTable { + pub fn intern(&mut self, + intr: @ident_interner, + string: &str, + primitive_type: prim_ty) { + let ident = token::str_to_ident(string); self.primitive_types.insert(ident, primitive_type); } } @@ -734,7 +790,7 @@ pub fn Resolver(session: Session, graph_root: graph_root, - trait_info: HashMap::new(), + method_map: @mut HashMap::new(), structs: HashSet::new(), unresolved_imports: 0, @@ -750,8 +806,7 @@ pub fn Resolver(session: Session, self_ident: special_idents::self_, type_self_ident: special_idents::type_self, - primitive_type_table: @PrimitiveTypeTable(session. - parse_sess.interner), + primitive_type_table: @PrimitiveTypeTable(token::get_ident_interner()), namespaces: ~[ TypeNS, ValueNS ], @@ -776,7 +831,7 @@ pub struct Resolver { graph_root: @mut NameBindings, - trait_info: HashMap>, + method_map: @mut HashMap>, structs: HashSet, // The number of imports that are currently unresolved. @@ -820,9 +875,9 @@ pub struct Resolver { used_imports: HashSet, } -pub impl Resolver { +impl Resolver { /// The main name resolution procedure. - fn resolve(@mut self) { + pub fn resolve(@mut self) { self.build_reduced_graph(); self.session.abort_if_errors(); @@ -846,7 +901,7 @@ pub impl Resolver { // /// Constructs the reduced graph for the entire crate. - fn build_reduced_graph(@mut self) { + pub fn build_reduced_graph(@mut self) { let initial_parent = ModuleReducedGraphParent(self.graph_root.get_module()); visit_crate(self.crate, initial_parent, mk_vt(@Visitor { @@ -873,9 +928,9 @@ pub impl Resolver { } /// Returns the current module tracked by the reduced graph parent. - fn get_module_from_parent(@mut self, - reduced_graph_parent: ReducedGraphParent) - -> @mut Module { + pub fn get_module_from_parent(@mut self, + reduced_graph_parent: ReducedGraphParent) + -> @mut Module { match reduced_graph_parent { ModuleReducedGraphParent(module_) => { return module_; @@ -893,14 +948,13 @@ pub impl Resolver { * If this node does not have a module definition and we are not inside * a block, fails. */ - fn add_child(@mut self, - name: ident, - reduced_graph_parent: ReducedGraphParent, - duplicate_checking_mode: DuplicateCheckingMode, - // For printing errors - sp: span) - -> (@mut NameBindings, ReducedGraphParent) { - + pub fn add_child(@mut self, + name: ident, + reduced_graph_parent: ReducedGraphParent, + duplicate_checking_mode: DuplicateCheckingMode, + // For printing errors + sp: span) + -> (@mut NameBindings, ReducedGraphParent) { // If this is the immediate descendant of a module, then we add the // child name directly. Otherwise, we create or reuse an anonymous // module and add the child to that. @@ -987,7 +1041,7 @@ pub impl Resolver { } } - fn block_needs_anonymous_module(@mut self, block: &blk) -> bool { + pub fn block_needs_anonymous_module(@mut self, block: &blk) -> bool { // If the block has view items, we need an anonymous module. if block.node.view_items.len() > 0 { return true; @@ -1018,10 +1072,8 @@ pub impl Resolver { return false; } - fn get_parent_link(@mut self, - parent: ReducedGraphParent, - name: ident) - -> ParentLink { + pub fn get_parent_link(@mut self, parent: ReducedGraphParent, name: ident) + -> ParentLink { match parent { ModuleReducedGraphParent(module_) => { return ModuleParentLink(module_, name); @@ -1030,10 +1082,10 @@ pub impl Resolver { } /// Constructs the reduced graph for one item. - fn build_reduced_graph_for_item(@mut self, - item: @item, - parent: ReducedGraphParent, - visitor: vt) { + pub fn build_reduced_graph_for_item(@mut self, + item: @item, + parent: ReducedGraphParent, + visitor: vt) { let ident = item.ident; let sp = item.span; let privacy = visibility_to_privacy(item.vis); @@ -1191,7 +1243,7 @@ pub impl Resolver { name_bindings.define_module(Public, parent_link, Some(def_id), - TraitModuleKind, + ImplModuleKind, sp); let new_parent = ModuleReducedGraphParent( @@ -1292,7 +1344,15 @@ pub impl Resolver { } let def_id = local_def(item.id); - self.trait_info.insert(def_id, method_names); + for method_names.each |name| { + if !self.method_map.contains_key(name) { + self.method_map.insert(*name, HashSet::new()); + } + match self.method_map.find_mut(name) { + Some(s) => { s.insert(def_id); }, + _ => fail!("Can't happen"), + } + } name_bindings.define_type(privacy, def_trait(def_id), sp); visit_item(item, new_parent, visitor); @@ -1306,12 +1366,12 @@ pub impl Resolver { // Constructs the reduced graph for one variant. Variants exist in the // type and/or value namespaces. - fn build_reduced_graph_for_variant(@mut self, - variant: &variant, - item_id: def_id, - parent_privacy: Privacy, - parent: ReducedGraphParent, - _visitor: vt) { + pub fn build_reduced_graph_for_variant(@mut self, + variant: &variant, + item_id: def_id, + parent_privacy: Privacy, + parent: ReducedGraphParent, + _visitor: vt) { let ident = variant.node.name; let (child, _) = self.add_child(ident, parent, ForbidDuplicateValues, variant.span); @@ -1340,14 +1400,12 @@ pub impl Resolver { } } - /** - * Constructs the reduced graph for one 'view item'. View items consist - * of imports and use directives. - */ - fn build_reduced_graph_for_view_item(@mut self, - view_item: @view_item, - parent: ReducedGraphParent, - _visitor: vt) { + /// Constructs the reduced graph for one 'view item'. View items consist + /// of imports and use directives. + pub fn build_reduced_graph_for_view_item(@mut self, + view_item: @view_item, + parent: ReducedGraphParent, + _: vt) { let privacy = visibility_to_privacy(view_item.vis); match view_item.node { view_item_use(ref view_paths) => { @@ -1440,10 +1498,10 @@ pub impl Resolver { } /// Constructs the reduced graph for one foreign item. - fn build_reduced_graph_for_foreign_item(@mut self, - foreign_item: @foreign_item, - parent: ReducedGraphParent, - visitor: + pub fn build_reduced_graph_for_foreign_item(@mut self, + foreign_item: @foreign_item, + parent: ReducedGraphParent, + visitor: vt) { let name = foreign_item.ident; let (name_bindings, new_parent) = @@ -1471,10 +1529,10 @@ pub impl Resolver { } } - fn build_reduced_graph_for_block(@mut self, - block: &blk, - parent: ReducedGraphParent, - visitor: vt) { + pub fn build_reduced_graph_for_block(@mut self, + block: &blk, + parent: ReducedGraphParent, + visitor: vt) { let new_parent; if self.block_needs_anonymous_module(block) { let block_id = block.node.id; @@ -1497,17 +1555,19 @@ pub impl Resolver { visit_block(block, new_parent, visitor); } - fn handle_external_def(@mut self, - def: def, - modules: &mut HashMap, - child_name_bindings: @mut NameBindings, - final_ident: &str, - ident: ident, - new_parent: ReducedGraphParent) { + pub fn handle_external_def(@mut self, + def: def, + visibility: ast::visibility, + modules: &mut HashMap, + child_name_bindings: @mut NameBindings, + final_ident: &str, + ident: ident, + new_parent: ReducedGraphParent) { + let privacy = visibility_to_privacy(visibility); match def { def_mod(def_id) | def_foreign_mod(def_id) => { match child_name_bindings.type_def { - Some(TypeNsDef { module_def: Some(copy module_def), _ }) => { + Some(TypeNsDef { module_def: Some(module_def), _ }) => { debug!("(building reduced graph for external crate) \ already created module"); module_def.def_id = Some(def_id); @@ -1521,7 +1581,7 @@ pub impl Resolver { // FIXME (#5074): this should be a match on find if !modules.contains_key(&def_id) { - child_name_bindings.define_module(Public, + child_name_bindings.define_module(privacy, parent_link, Some(def_id), NormalModuleKind, @@ -1530,9 +1590,9 @@ pub impl Resolver { child_name_bindings.get_module()); } else { let existing_module = *modules.get(&def_id); - // Create an import resolution to - // avoid creating cycles in the - // module graph. + + // Create an import resolution to avoid creating cycles in + // the module graph. let resolution = @mut ImportResolution(Public, 0); resolution.outstanding_references = 0; @@ -1558,11 +1618,19 @@ pub impl Resolver { } } } - def_fn(*) | def_static_method(*) | def_const(*) | def_variant(*) => { + debug!("(building reduced graph for external crate) building \ + variant %s", + final_ident); + // We assume the parent is visible, or else we wouldn't have seen + // it. + let privacy = variant_visibility_to_privacy(visibility, true); + child_name_bindings.define_value(privacy, def, dummy_sp()); + } + def_fn(*) | def_static_method(*) | def_const(*) => { debug!("(building reduced graph for external \ crate) building value %s", final_ident); - child_name_bindings.define_value(Public, def, dummy_sp()); + child_name_bindings.define_value(privacy, def, dummy_sp()); } def_trait(def_id) => { debug!("(building reduced graph for external \ @@ -1571,8 +1639,8 @@ pub impl Resolver { // If this is a trait, add all the method names // to the trait info. - let method_def_ids = get_trait_method_def_ids(self.session.cstore, - def_id); + let method_def_ids = + get_trait_method_def_ids(self.session.cstore, def_id); let mut interned_method_names = HashSet::new(); for method_def_ids.each |&method_def_id| { let (method_name, explicit_self) = @@ -1589,21 +1657,37 @@ pub impl Resolver { interned_method_names.insert(method_name); } } - self.trait_info.insert(def_id, interned_method_names); + for interned_method_names.each |name| { + if !self.method_map.contains_key(name) { + self.method_map.insert(*name, HashSet::new()); + } + match self.method_map.find_mut(name) { + Some(s) => { s.insert(def_id); }, + _ => fail!("Can't happen"), + } + } + + child_name_bindings.define_type(privacy, def, dummy_sp()); - child_name_bindings.define_type(Public, def, dummy_sp()); + // Define a module if necessary. + let parent_link = self.get_parent_link(new_parent, ident); + child_name_bindings.set_module_kind(privacy, + parent_link, + Some(def_id), + TraitModuleKind, + dummy_sp()) } def_ty(_) => { debug!("(building reduced graph for external \ crate) building type %s", final_ident); - child_name_bindings.define_type(Public, def, dummy_sp()); + child_name_bindings.define_type(privacy, def, dummy_sp()); } def_struct(def_id) => { debug!("(building reduced graph for external \ crate) building type %s", final_ident); - child_name_bindings.define_type(Public, def, dummy_sp()); + child_name_bindings.define_type(privacy, def, dummy_sp()); self.structs.insert(def_id); } def_self(*) | def_arg(*) | def_local(*) | @@ -1619,12 +1703,13 @@ pub impl Resolver { * Builds the reduced graph rooted at the 'use' directive for an external * crate. */ - fn build_reduced_graph_for_external_crate(@mut self, root: @mut Module) { + pub fn build_reduced_graph_for_external_crate(@mut self, + root: @mut Module) { let mut modules = HashMap::new(); // Create all the items reachable by paths. for each_path(self.session.cstore, root.def_id.get().crate) - |path_string, def_like| { + |path_string, def_like, visibility| { debug!("(building reduced graph for external crate) found path \ entry: %s (%?)", @@ -1662,7 +1747,7 @@ pub impl Resolver { NormalModuleKind, dummy_sp()); } - Some(copy type_ns_def) + Some(type_ns_def) if type_ns_def.module_def.is_none() => { debug!("(building reduced graph for external crate) \ autovivifying missing module def %s", @@ -1692,6 +1777,7 @@ pub impl Resolver { dummy_sp()); self.handle_external_def(def, + visibility, &mut modules, child_name_bindings, *self.session.str_of( @@ -1728,12 +1814,16 @@ pub impl Resolver { let type_module; match child_name_bindings.type_def { Some(TypeNsDef { - module_def: Some(copy module_def), + module_def: Some(module_def), _ }) => { // We already have a module. This // is OK. type_module = module_def; + + // Mark it as an impl module if + // necessary. + type_module.kind = ImplModuleKind; } Some(_) | None => { let parent_link = @@ -1743,7 +1833,7 @@ pub impl Resolver { Public, parent_link, Some(def), - NormalModuleKind, + ImplModuleKind, dummy_sp()); type_module = child_name_bindings. @@ -1791,13 +1881,13 @@ pub impl Resolver { } /// Creates and adds an import directive to the given module. - fn build_import_directive(@mut self, - privacy: Privacy, - module_: @mut Module, - module_path: ~[ident], - subclass: @ImportDirectiveSubclass, - span: span, - id: node_id) { + pub fn build_import_directive(@mut self, + privacy: Privacy, + module_: @mut Module, + module_path: ~[ident], + subclass: @ImportDirectiveSubclass, + span: span, + id: node_id) { let directive = @ImportDirective(privacy, module_path, subclass, span, id); module_.imports.push(directive); @@ -1818,6 +1908,10 @@ pub impl Resolver { debug!("(building import directive) bumping \ reference"); resolution.outstanding_references += 1; + + // the source of this name is different now + resolution.privacy = privacy; + resolution.id = id; } None => { debug!("(building import directive) creating new"); @@ -1846,11 +1940,9 @@ pub impl Resolver { // remain or unsuccessfully when no forward progress in resolving imports // is made. - /** - * Resolves all imports for the crate. This method performs the fixed- - * point iteration. - */ - fn resolve_imports(@mut self) { + /// Resolves all imports for the crate. This method performs the fixed- + /// point iteration. + pub fn resolve_imports(@mut self) { let mut i = 0; let mut prev_unresolved_imports = 0; loop { @@ -1877,7 +1969,8 @@ pub impl Resolver { /// Attempts to resolve imports for the given module and all of its /// submodules. - fn resolve_imports_for_module_subtree(@mut self, module_: @mut Module) { + pub fn resolve_imports_for_module_subtree(@mut self, + module_: @mut Module) { debug!("(resolving imports for module subtree) resolving %s", self.module_to_str(module_)); self.resolve_imports_for_module(module_); @@ -1899,7 +1992,7 @@ pub impl Resolver { } /// Attempts to resolve imports for the given module only. - fn resolve_imports_for_module(@mut self, module: @mut Module) { + pub fn resolve_imports_for_module(@mut self, module: @mut Module) { if module.all_imports_resolved() { debug!("(resolving imports for module) all imports resolved for \ %s", @@ -1934,7 +2027,7 @@ pub impl Resolver { } } - fn idents_to_str(@mut self, idents: &[ident]) -> ~str { + pub fn idents_to_str(@mut self, idents: &[ident]) -> ~str { let mut first = true; let mut result = ~""; for idents.each |ident| { @@ -1944,19 +2037,19 @@ pub impl Resolver { return result; } - fn import_directive_subclass_to_str(@mut self, - subclass: ImportDirectiveSubclass) - -> @~str { + pub fn import_directive_subclass_to_str(@mut self, + subclass: ImportDirectiveSubclass) + -> @~str { match subclass { SingleImport(_target, source) => self.session.str_of(source), GlobImport => @~"*" } } - fn import_path_to_str(@mut self, - idents: &[ident], - subclass: ImportDirectiveSubclass) - -> @~str { + pub fn import_path_to_str(@mut self, + idents: &[ident], + subclass: ImportDirectiveSubclass) + -> @~str { if idents.is_empty() { self.import_directive_subclass_to_str(subclass) } else { @@ -1971,9 +2064,10 @@ pub impl Resolver { /// don't know whether the name exists at the moment due to other /// currently-unresolved imports, or success if we know the name exists. /// If successful, the resolved bindings are written into the module. - fn resolve_import_for_module(@mut self, module_: @mut Module, - import_directive: @ImportDirective) - -> ResolveResult<()> { + pub fn resolve_import_for_module(@mut self, + module_: @mut Module, + import_directive: @ImportDirective) + -> ResolveResult<()> { let mut resolution_result = Failed; let module_path = &import_directive.module_path; @@ -1987,10 +2081,11 @@ pub impl Resolver { // Use the crate root. Some(self.graph_root.get_module()) } else { - match self.resolve_module_path_for_import(module_, - *module_path, - DontUseLexicalScope, - import_directive.span) { + match self.resolve_module_path(module_, + *module_path, + DontUseLexicalScope, + import_directive.span, + ImportSearch) { Failed => None, Indeterminate => { @@ -2059,7 +2154,8 @@ pub impl Resolver { return resolution_result; } - fn create_name_bindings_from_module(module: @mut Module) -> NameBindings { + pub fn create_name_bindings_from_module(module: @mut Module) + -> NameBindings { NameBindings { type_def: Some(TypeNsDef { privacy: Public, @@ -2071,13 +2167,13 @@ pub impl Resolver { } } - fn resolve_single_import(@mut self, - module_: @mut Module, - containing_module: @mut Module, - target: ident, - source: ident, - span: span) - -> ResolveResult<()> { + pub fn resolve_single_import(@mut self, + module_: @mut Module, + containing_module: @mut Module, + target: ident, + source: ident, + span: span) + -> ResolveResult<()> { debug!("(resolving single import) resolving `%s` = `%s::%s` from \ `%s`", *self.session.str_of(target), @@ -2114,9 +2210,7 @@ pub impl Resolver { // Unless we managed to find a result in both namespaces (unlikely), // search imports as well. match (value_result, type_result) { - (BoundResult(*), BoundResult(*)) => { - // Continue. - } + (BoundResult(*), BoundResult(*)) => {} // Continue. _ => { // If there is an unresolved glob at this point in the // containing module, bail out. We don't know enough to be @@ -2302,12 +2396,12 @@ pub impl Resolver { // Resolves a glob import. Note that this function cannot fail; it either // succeeds or bails out (as importing * from an empty module or a module // that exports nothing is valid). - fn resolve_glob_import(@mut self, - privacy: Privacy, - module_: @mut Module, - containing_module: @mut Module, - id: node_id) - -> ResolveResult<()> { + pub fn resolve_glob_import(@mut self, + privacy: Privacy, + module_: @mut Module, + containing_module: @mut Module, + id: node_id) + -> ResolveResult<()> { // This function works in a highly imperative manner; it eagerly adds // everything it can to the list of import resolutions of the module // node. @@ -2321,7 +2415,7 @@ pub impl Resolver { return Indeterminate; } - assert!(containing_module.glob_count == 0); + assert_eq!(containing_module.glob_count, 0); // Add all resolved imports from the containing module. for containing_module.import_resolutions.each @@ -2355,7 +2449,7 @@ pub impl Resolver { None => { // Continue. } - Some(copy value_target) => { + Some(value_target) => { dest_import_resolution.value_target = Some(value_target); } @@ -2364,7 +2458,7 @@ pub impl Resolver { None => { // Continue. } - Some(copy type_target) => { + Some(type_target) => { dest_import_resolution.type_target = Some(type_target); } @@ -2426,13 +2520,13 @@ pub impl Resolver { } /// Resolves the given module path from the given root `module_`. - fn resolve_module_path_from_root(@mut self, - module_: @mut Module, - module_path: &[ident], - index: uint, - span: span, - mut name_search_type: NameSearchType) - -> ResolveResult<@mut Module> { + pub fn resolve_module_path_from_root(@mut self, + module_: @mut Module, + module_path: &[ident], + index: uint, + span: span, + mut name_search_type: NameSearchType) + -> ResolveResult<@mut Module> { let mut search_module = module_; let mut index = index; let module_path_len = module_path.len(); @@ -2440,7 +2534,6 @@ pub impl Resolver { // Resolve the module part of the path. This does not involve looking // upward though scope chains; we simply resolve names directly in // modules as we go. - while index < module_path_len { let name = module_path[index]; match self.resolve_name_in_module(search_module, @@ -2450,12 +2543,17 @@ pub impl Resolver { Failed => { let segment_name = self.session.str_of(name); let module_name = self.module_to_str(search_module); - if module_name == ~"???" { - self.session.span_err(span {lo: span.lo, hi: span.lo + - BytePos(str::len(*segment_name)), expn_info: - span.expn_info}, fmt!("unresolved import. maybe \ - a missing `extern mod %s`?", - *segment_name)); + if "???" == module_name { + let span = span { + lo: span.lo, + hi: span.lo + BytePos(str::len(*segment_name)), + expn_info: span.expn_info, + }; + self.session.span_err(span, + fmt!("unresolved import. maybe \ + a missing `extern mod \ + %s`?", + *segment_name)); return Failed; } self.session.span_err(span, fmt!("unresolved import: could not find `%s` in \ @@ -2472,7 +2570,7 @@ pub impl Resolver { // Check to see whether there are type bindings, and, if // so, whether there is a module within. match target.bindings.type_def { - Some(copy type_def) => { + Some(type_def) => { match type_def.module_def { None => { // Not a module. @@ -2484,8 +2582,22 @@ pub impl Resolver { name))); return Failed; } - Some(copy module_def) => { - search_module = module_def; + Some(module_def) => { + // If we're doing the search for an + // import, do not allow traits and impls + // to be selected. + match (name_search_type, + module_def.kind) { + (ImportSearch, TraitModuleKind) | + (ImportSearch, ImplModuleKind) => { + self.session.span_err( + span, + "cannot import from a trait \ + or type implementation"); + return Failed; + } + (_, _) => search_module = module_def, + } } } } @@ -2503,18 +2615,13 @@ pub impl Resolver { index += 1; - // After the first element of the path, allow searching through - // items and imports unconditionally. This allows things like: - // - // pub mod core { - // pub use vec; - // } + // After the first element of the path, allow searching only + // through public identifiers. // - // pub mod something_else { - // use core::vec; - // } - - name_search_type = SearchItemsAndPublicImports; + // XXX: Rip this out and move it to the privacy checker. + if name_search_type == PathPublicOrPrivateSearch { + name_search_type = PathPublicOnlySearch + } } return Success(search_module); @@ -2522,12 +2629,13 @@ pub impl Resolver { /// Attempts to resolve the module part of an import directive or path /// rooted at the given module. - fn resolve_module_path_for_import(@mut self, - module_: @mut Module, - module_path: &[ident], - use_lexical_scope: UseLexicalScopeFlag, - span: span) - -> ResolveResult<@mut Module> { + pub fn resolve_module_path(@mut self, + module_: @mut Module, + module_path: &[ident], + use_lexical_scope: UseLexicalScopeFlag, + span: span, + name_search_type: NameSearchType) + -> ResolveResult<@mut Module> { let module_path_len = module_path.len(); assert!(module_path_len > 0); @@ -2584,7 +2692,7 @@ pub impl Resolver { match result { Failed => { self.session.span_err(span, - ~"unresolved name"); + "unresolved name"); return Failed; } Indeterminate => { @@ -2610,18 +2718,18 @@ pub impl Resolver { module_path, start_index, span, - SearchItemsAndPublicImports) + name_search_type) } /// Invariant: This must only be called during main resolution, not during /// import resolution. - fn resolve_item_in_lexical_scope(@mut self, - module_: @mut Module, - name: ident, - namespace: Namespace, - search_through_modules: - SearchThroughModulesFlag) - -> ResolveResult { + pub fn resolve_item_in_lexical_scope(@mut self, + module_: @mut Module, + name: ident, + namespace: Namespace, + search_through_modules: + SearchThroughModulesFlag) + -> ResolveResult { debug!("(resolving item in lexical scope) resolving `%s` in \ namespace %? in `%s`", *self.session.str_of(name), @@ -2702,6 +2810,7 @@ pub impl Resolver { } ExternModuleKind | TraitModuleKind | + ImplModuleKind | AnonymousModuleKind => { search_module = parent_module_node; } @@ -2721,7 +2830,7 @@ pub impl Resolver { match self.resolve_name_in_module(search_module, name, namespace, - SearchItemsAndAllImports) { + PathPublicOrPrivateSearch) { Failed => { // Continue up the search chain. } @@ -2741,11 +2850,11 @@ pub impl Resolver { } } - /** Resolves a module name in the current lexical scope. */ - fn resolve_module_in_lexical_scope(@mut self, - module_: @mut Module, - name: ident) - -> ResolveResult<@mut Module> { + /// Resolves a module name in the current lexical scope. + pub fn resolve_module_in_lexical_scope(@mut self, + module_: @mut Module, + name: ident) + -> ResolveResult<@mut Module> { // If this module is an anonymous module, resolve the item in the // lexical scope. Otherwise, resolve the item from the crate root. let resolve_result = self.resolve_item_in_lexical_scope( @@ -2787,11 +2896,9 @@ pub impl Resolver { } } - /** - * Returns the nearest normal module parent of the given module. - */ - fn get_nearest_normal_module_parent(@mut self, module_: @mut Module) - -> Option<@mut Module> { + /// Returns the nearest normal module parent of the given module. + pub fn get_nearest_normal_module_parent(@mut self, module_: @mut Module) + -> Option<@mut Module> { let mut module_ = module_; loop { match module_.parent_link { @@ -2802,6 +2909,7 @@ pub impl Resolver { NormalModuleKind => return Some(new_module), ExternModuleKind | TraitModuleKind | + ImplModuleKind | AnonymousModuleKind => module_ = new_module, } } @@ -2809,16 +2917,17 @@ pub impl Resolver { } } - /** - * Returns the nearest normal module parent of the given module, or the - * module itself if it is a normal module. - */ - fn get_nearest_normal_module_parent_or_self(@mut self, - module_: @mut Module) - -> @mut Module { + /// Returns the nearest normal module parent of the given module, or the + /// module itself if it is a normal module. + pub fn get_nearest_normal_module_parent_or_self(@mut self, + module_: @mut Module) + -> @mut Module { match module_.kind { NormalModuleKind => return module_, - ExternModuleKind | TraitModuleKind | AnonymousModuleKind => { + ExternModuleKind | + TraitModuleKind | + ImplModuleKind | + AnonymousModuleKind => { match self.get_nearest_normal_module_parent(module_) { None => module_, Some(new_module) => new_module @@ -2827,25 +2936,23 @@ pub impl Resolver { } } - /** - * Resolves a "module prefix". A module prefix is one of (a) `self::`; - * (b) some chain of `super::`. - */ - fn resolve_module_prefix(@mut self, - module_: @mut Module, - module_path: &[ident]) - -> ResolveResult { - let interner = self.session.parse_sess.interner; + /// Resolves a "module prefix". A module prefix is one of (a) `self::`; + /// (b) some chain of `super::`. + pub fn resolve_module_prefix(@mut self, + module_: @mut Module, + module_path: &[ident]) + -> ResolveResult { + let interner = token::get_ident_interner(); // Start at the current module if we see `self` or `super`, or at the // top of the crate otherwise. let mut containing_module; let mut i; - if *interner.get(module_path[0]) == ~"self" { + if *token::ident_to_str(&module_path[0]) == ~"self" { containing_module = self.get_nearest_normal_module_parent_or_self(module_); i = 1; - } else if *interner.get(module_path[0]) == ~"super" { + } else if *token::ident_to_str(&module_path[0]) == ~"super" { containing_module = self.get_nearest_normal_module_parent_or_self(module_); i = 0; // We'll handle `super` below. @@ -2855,7 +2962,7 @@ pub impl Resolver { // Now loop through all the `super`s we find. while i < module_path.len() && - *interner.get(module_path[i]) == ~"super" { + *token::ident_to_str(&module_path[i]) == ~"super" { debug!("(resolving module prefix) resolving `super` at %s", self.module_to_str(containing_module)); match self.get_nearest_normal_module_parent(containing_module) { @@ -2876,12 +2983,12 @@ pub impl Resolver { /// Attempts to resolve the supplied name in the given module for the /// given namespace. If successful, returns the target corresponding to /// the name. - fn resolve_name_in_module(@mut self, - module_: @mut Module, - name: ident, - namespace: Namespace, - name_search_type: NameSearchType) - -> ResolveResult { + pub fn resolve_name_in_module(@mut self, + module_: @mut Module, + name: ident, + namespace: Namespace, + name_search_type: NameSearchType) + -> ResolveResult { debug!("(resolving name in module) resolving `%s` in `%s`", *self.session.str_of(name), self.module_to_str(module_)); @@ -2902,8 +3009,9 @@ pub impl Resolver { // If this is a search of all imports, we should be done with glob // resolution at this point. - if name_search_type == SearchItemsAndAllImports { - assert!(module_.glob_count == 0); + if name_search_type == PathPublicOrPrivateSearch || + name_search_type == PathPublicOnlySearch { + assert_eq!(module_.glob_count, 0); } // Check the list of resolved imports. @@ -2924,7 +3032,7 @@ pub impl Resolver { } Some(target) if name_search_type == - SearchItemsAndAllImports || + PathPublicOrPrivateSearch || import_resolution.privacy == Public => { debug!("(resolving name in module) resolved to \ import"); @@ -2959,17 +3067,17 @@ pub impl Resolver { return Failed; } - fn report_unresolved_imports(@mut self, module_: @mut Module) { + pub fn report_unresolved_imports(@mut self, module_: @mut Module) { let index = module_.resolved_import_count; let imports: &mut ~[@ImportDirective] = &mut *module_.imports; let import_count = imports.len(); if index != import_count { let sn = self.session.codemap.span_to_snippet(imports[index].span); if str::contains(sn, "::") { - self.session.span_err(imports[index].span, ~"unresolved import"); + self.session.span_err(imports[index].span, "unresolved import"); } else { let err = fmt!("unresolved import (maybe you meant `%s::*`?)", - sn.slice(0, sn.len() - 1)); // -1 to adjust for semicolon + sn.slice(0, sn.len())); self.session.span_err(imports[index].span, err); } } @@ -3000,12 +3108,13 @@ pub impl Resolver { // Then this operation can simply be performed as part of item (or import) // processing. - fn record_exports(@mut self) { + pub fn record_exports(@mut self) { let root_module = self.graph_root.get_module(); self.record_exports_for_module_subtree(root_module); } - fn record_exports_for_module_subtree(@mut self, module_: @mut Module) { + pub fn record_exports_for_module_subtree(@mut self, + module_: @mut Module) { // If this isn't a local crate, then bail out. We don't need to record // exports for nonlocal crates. @@ -3047,7 +3156,7 @@ pub impl Resolver { } } - fn record_exports_for_module(@mut self, module_: @mut Module) { + pub fn record_exports_for_module(@mut self, module_: @mut Module) { let mut exports2 = ~[]; self.add_exports_for_module(&mut exports2, module_); @@ -3061,12 +3170,12 @@ pub impl Resolver { } } - fn add_exports_of_namebindings(@mut self, - exports2: &mut ~[Export2], - ident: ident, - namebindings: @mut NameBindings, - ns: Namespace, - reexport: bool) { + pub fn add_exports_of_namebindings(@mut self, + exports2: &mut ~[Export2], + ident: ident, + namebindings: @mut NameBindings, + ns: Namespace, + reexport: bool) { match (namebindings.def_for_namespace(ns), namebindings.privacy_for_namespace(ns)) { (Some(d), Some(Public)) => { @@ -3089,9 +3198,9 @@ pub impl Resolver { } } - fn add_exports_for_module(@mut self, - exports2: &mut ~[Export2], - module_: @mut Module) { + pub fn add_exports_for_module(@mut self, + exports2: &mut ~[Export2], + module_: @mut Module) { for module_.children.each |ident, namebindings| { debug!("(computing exports) maybe export '%s'", *self.session.str_of(*ident)); @@ -3148,7 +3257,7 @@ pub impl Resolver { // generate a fake "implementation scope" containing all the // implementations thus found, for compatibility with old resolve pass. - fn with_scope(@mut self, name: Option, f: &fn()) { + pub fn with_scope(@mut self, name: Option, f: &fn()) { let orig_module = self.current_module; // Move down in the graph. @@ -3185,16 +3294,15 @@ pub impl Resolver { self.current_module = orig_module; } - // Wraps the given definition in the appropriate number of `def_upvar` - // wrappers. - - fn upvarify(@mut self, - ribs: &mut ~[@Rib], - rib_index: uint, - def_like: def_like, - span: span, - allow_capturing_self: AllowCapturingSelfFlag) - -> Option { + /// Wraps the given definition in the appropriate number of `def_upvar` + /// wrappers. + pub fn upvarify(@mut self, + ribs: &mut ~[@Rib], + rib_index: uint, + def_like: def_like, + span: span, + allow_capturing_self: AllowCapturingSelfFlag) + -> Option { let mut def; let is_ty_param; @@ -3249,14 +3357,14 @@ pub impl Resolver { self.session.span_err( span, - ~"attempted dynamic environment-capture"); + "attempted dynamic environment-capture"); } else { // This was an attempt to use a type parameter outside // its scope. self.session.span_err(span, - ~"attempt to use a type \ - argument out of scope"); + "attempt to use a type \ + argument out of scope"); } return None; @@ -3271,14 +3379,14 @@ pub impl Resolver { self.session.span_err( span, - ~"attempted dynamic environment-capture"); + "attempted dynamic environment-capture"); } else { // This was an attempt to use a type parameter outside // its scope. self.session.span_err(span, - ~"attempt to use a type \ - argument out of scope"); + "attempt to use a type \ + argument out of scope"); } return None; @@ -3286,8 +3394,8 @@ pub impl Resolver { ConstantItemRibKind => { // Still doesn't deal with upvars self.session.span_err(span, - ~"attempt to use a non-constant \ - value in a constant"); + "attempt to use a non-constant \ + value in a constant"); } } @@ -3298,12 +3406,12 @@ pub impl Resolver { return Some(dl_def(def)); } - fn search_ribs(@mut self, - ribs: &mut ~[@Rib], - name: ident, - span: span, - allow_capturing_self: AllowCapturingSelfFlag) - -> Option { + pub fn search_ribs(@mut self, + ribs: &mut ~[@Rib], + name: ident, + span: span, + allow_capturing_self: AllowCapturingSelfFlag) + -> Option { // FIXME #4950: This should not use a while loop. // FIXME #4950: Try caching? @@ -3324,7 +3432,7 @@ pub impl Resolver { return None; } - fn resolve_crate(@mut self) { + pub fn resolve_crate(@mut self) { debug!("(resolving crate) starting"); visit_crate(self.crate, (), mk_vt(@Visitor { @@ -3344,7 +3452,7 @@ pub impl Resolver { })); } - fn resolve_item(@mut self, item: @item, visitor: ResolveVisitor) { + pub fn resolve_item(@mut self, item: @item, visitor: ResolveVisitor) { debug!("(resolving item) resolving %s", *self.session.str_of(item.ident)); @@ -3352,7 +3460,7 @@ pub impl Resolver { // This is used to allow the test runner to run unexported tests. let orig_xray_flag = self.xray_context; if contains_name(attr_metas(item.attrs), - ~"!resolve_unexported") { + "!resolve_unexported") { self.xray_context = Xray; } @@ -3424,8 +3532,8 @@ pub impl Resolver { visitor) { None => self.session.span_err(trt.path.span, - ~"attempt to derive a \ - nonexistent trait"), + "attempt to derive a \ + nonexistent trait"), Some(def) => { // Write a mapping from the trait ID to the // definition of the trait into the definition @@ -3542,9 +3650,9 @@ pub impl Resolver { self.xray_context = orig_xray_flag; } - fn with_type_parameter_rib(@mut self, - type_parameters: TypeParameters, - f: &fn()) { + pub fn with_type_parameter_rib(@mut self, + type_parameters: TypeParameters, + f: &fn()) { match type_parameters { HasTypeParameters(generics, node_id, initial_index, rib_kind) => { @@ -3585,25 +3693,25 @@ pub impl Resolver { } } - fn with_label_rib(@mut self, f: &fn()) { + pub fn with_label_rib(@mut self, f: &fn()) { self.label_ribs.push(@Rib(NormalRibKind)); f(); self.label_ribs.pop(); } - fn with_constant_rib(@mut self, f: &fn()) { + pub fn with_constant_rib(@mut self, f: &fn()) { self.value_ribs.push(@Rib(ConstantItemRibKind)); f(); self.value_ribs.pop(); } - fn resolve_function(@mut self, - rib_kind: RibKind, - optional_declaration: Option<&fn_decl>, - type_parameters: TypeParameters, - block: &blk, - self_binding: SelfBinding, - visitor: ResolveVisitor) { + pub fn resolve_function(@mut self, + rib_kind: RibKind, + optional_declaration: Option<&fn_decl>, + type_parameters: TypeParameters, + block: &blk, + self_binding: SelfBinding, + visitor: ResolveVisitor) { // Create a value rib for the function. let function_value_rib = @Rib(rib_kind); self.value_ribs.push(function_value_rib); @@ -3672,9 +3780,9 @@ pub impl Resolver { self.value_ribs.pop(); } - fn resolve_type_parameters(@mut self, - type_parameters: &OptVec, - visitor: ResolveVisitor) { + pub fn resolve_type_parameters(@mut self, + type_parameters: &OptVec, + visitor: ResolveVisitor) { for type_parameters.each |type_parameter| { for type_parameter.bounds.each |bound| { self.resolve_type_parameter_bound(bound, visitor); @@ -3682,9 +3790,9 @@ pub impl Resolver { } } - fn resolve_type_parameter_bound(@mut self, - type_parameter_bound: &TyParamBound, - visitor: ResolveVisitor) { + pub fn resolve_type_parameter_bound(@mut self, + type_parameter_bound: &TyParamBound, + visitor: ResolveVisitor) { match *type_parameter_bound { TraitTyParamBound(tref) => { self.resolve_trait_reference(tref, visitor) @@ -3693,14 +3801,14 @@ pub impl Resolver { } } - fn resolve_trait_reference(@mut self, - trait_reference: &trait_ref, - visitor: ResolveVisitor) { + pub fn resolve_trait_reference(@mut self, + trait_reference: &trait_ref, + visitor: ResolveVisitor) { match self.resolve_path(trait_reference.path, TypeNS, true, visitor) { None => { self.session.span_err(trait_reference.path.span, - ~"attempt to implement an \ - unknown trait"); + "attempt to implement an \ + unknown trait"); } Some(def) => { self.record_def(trait_reference.ref_id, def); @@ -3708,11 +3816,11 @@ pub impl Resolver { } } - fn resolve_struct(@mut self, - id: node_id, - generics: &Generics, - fields: &[@struct_field], - visitor: ResolveVisitor) { + pub fn resolve_struct(@mut self, + id: node_id, + generics: &Generics, + fields: &[@struct_field], + visitor: ResolveVisitor) { // If applicable, create a rib for the type parameters. do self.with_type_parameter_rib(HasTypeParameters (generics, id, 0, @@ -3730,11 +3838,11 @@ pub impl Resolver { // Does this really need to take a RibKind or is it always going // to be NormalRibKind? - fn resolve_method(@mut self, - rib_kind: RibKind, - method: @method, - outer_type_parameter_count: uint, - visitor: ResolveVisitor) { + pub fn resolve_method(@mut self, + rib_kind: RibKind, + method: @method, + outer_type_parameter_count: uint, + visitor: ResolveVisitor) { let method_generics = &method.generics; let type_parameters = HasTypeParameters(method_generics, @@ -3755,13 +3863,13 @@ pub impl Resolver { visitor); } - fn resolve_implementation(@mut self, - id: node_id, - generics: &Generics, - opt_trait_reference: Option<@trait_ref>, - self_type: @Ty, - methods: &[@method], - visitor: ResolveVisitor) { + pub fn resolve_implementation(@mut self, + id: node_id, + generics: &Generics, + opt_trait_reference: Option<@trait_ref>, + self_type: @Ty, + methods: &[@method], + visitor: ResolveVisitor) { // If applicable, create a rib for the type parameters. let outer_type_parameter_count = generics.ty_params.len(); do self.with_type_parameter_rib(HasTypeParameters @@ -3828,18 +3936,18 @@ pub impl Resolver { } } - fn resolve_module(@mut self, - module_: &_mod, - span: span, - _name: ident, - id: node_id, - visitor: ResolveVisitor) { + pub fn resolve_module(@mut self, + module_: &_mod, + span: span, + _name: ident, + id: node_id, + visitor: ResolveVisitor) { // Write the implementations in scope into the module metadata. debug!("(resolving module) resolving module ID %d", id); visit_mod(module_, span, id, (), visitor); } - fn resolve_local(@mut self, local: @local, visitor: ResolveVisitor) { + pub fn resolve_local(@mut self, local: @local, visitor: ResolveVisitor) { let mutability = if local.node.is_mutbl {Mutable} else {Immutable}; // Resolve the type. @@ -3860,7 +3968,7 @@ pub impl Resolver { None, visitor); } - fn binding_mode_map(@mut self, pat: @pat) -> BindingMap { + pub fn binding_mode_map(@mut self, pat: @pat) -> BindingMap { let mut result = HashMap::new(); do pat_bindings(self.def_map, pat) |binding_mode, _id, sp, path| { let ident = path_to_ident(path); @@ -3871,7 +3979,7 @@ pub impl Resolver { return result; } - fn check_consistent_bindings(@mut self, arm: &arm) { + pub fn check_consistent_bindings(@mut self, arm: &arm) { if arm.pats.len() == 0 { return; } let map_0 = self.binding_mode_map(arm.pats[0]); for arm.pats.eachi() |i, p| { @@ -3910,7 +4018,7 @@ pub impl Resolver { } } - fn resolve_arm(@mut self, arm: &arm, visitor: ResolveVisitor) { + pub fn resolve_arm(@mut self, arm: &arm, visitor: ResolveVisitor) { self.value_ribs.push(@Rib(NormalRibKind)); let bindings_list = @mut HashMap::new(); @@ -3929,7 +4037,7 @@ pub impl Resolver { self.value_ribs.pop(); } - fn resolve_block(@mut self, block: &blk, visitor: ResolveVisitor) { + pub fn resolve_block(@mut self, block: &blk, visitor: ResolveVisitor) { debug!("(resolving block) entering block"); self.value_ribs.push(@Rib(NormalRibKind)); @@ -3954,7 +4062,7 @@ pub impl Resolver { debug!("(resolving block) leaving block"); } - fn resolve_type(@mut self, ty: @Ty, visitor: ResolveVisitor) { + pub fn resolve_type(@mut self, ty: @Ty, visitor: ResolveVisitor) { match ty.node { // Like path expressions, the interpretation of path types depends // on whether the path has multiple elements in it or not. @@ -4034,16 +4142,16 @@ pub impl Resolver { } } - fn resolve_pattern(@mut self, - pattern: @pat, - mode: PatternBindingMode, - mutability: Mutability, - // Maps idents to the node ID for the (outermost) - // pattern that binds them - bindings_list: Option<@mut HashMap>, - visitor: ResolveVisitor) { + pub fn resolve_pattern(@mut self, + pattern: @pat, + mode: PatternBindingMode, + mutability: Mutability, + // Maps idents to the node ID for the (outermost) + // pattern that binds them + bindings_list: Option<@mut HashMap>, + visitor: ResolveVisitor) { let pat_id = pattern.id; - do walk_pat(pattern) |pattern| { + for walk_pat(pattern) |pattern| { match pattern.node { pat_ident(binding_mode, path, _) if !path.global && path.idents.len() == 1 => { @@ -4094,8 +4202,8 @@ pub impl Resolver { } FoundConst(_) => { self.session.span_err(pattern.span, - ~"only refutable patterns \ - allowed here"); + "only refutable patterns \ + allowed here"); } BareIdentifierPatternUnresolved => { debug!("(resolving pattern) binding `%s`", @@ -4195,7 +4303,7 @@ pub impl Resolver { } None => { self.session.span_err(path.span, - ~"unresolved enum variant"); + "unresolved enum variant"); } } @@ -4223,8 +4331,8 @@ pub impl Resolver { } None => { self.session.span_err(path.span, - ~"unresolved enum variant, \ - struct or const"); + "unresolved enum variant, \ + struct or const"); } } @@ -4276,8 +4384,9 @@ pub impl Resolver { } } - fn resolve_bare_identifier_pattern(@mut self, name: ident) - -> BareIdentifierPatternResolution { + pub fn resolve_bare_identifier_pattern(@mut self, name: ident) + -> + BareIdentifierPatternResolution { match self.resolve_item_in_lexical_scope(self.current_module, name, ValueNS, @@ -4316,12 +4425,12 @@ pub impl Resolver { /// If `check_ribs` is true, checks the local definitions first; i.e. /// doesn't skip straight to the containing module. - fn resolve_path(@mut self, - path: @Path, - namespace: Namespace, - check_ribs: bool, - visitor: ResolveVisitor) - -> Option { + pub fn resolve_path(@mut self, + path: @Path, + namespace: Namespace, + check_ribs: bool, + visitor: ResolveVisitor) + -> Option { // First, resolve the types. for path.types.each |ty| { self.resolve_type(*ty, visitor); @@ -4345,12 +4454,12 @@ pub impl Resolver { path.span); } - fn resolve_identifier(@mut self, - identifier: ident, - namespace: Namespace, - check_ribs: bool, - span: span) - -> Option { + pub fn resolve_identifier(@mut self, + identifier: ident, + namespace: Namespace, + check_ribs: bool, + span: span) + -> Option { if check_ribs { match self.resolve_identifier_in_local_ribs(identifier, namespace, @@ -4369,12 +4478,12 @@ pub impl Resolver { } // FIXME #4952: Merge me with resolve_name_in_module? - fn resolve_definition_of_name_in_module(@mut self, - containing_module: @mut Module, - name: ident, - namespace: Namespace, - xray: XrayFlag) - -> NameDefinition { + pub fn resolve_definition_of_name_in_module(@mut self, + containing_module: @mut Module, + name: ident, + namespace: Namespace, + xray: XrayFlag) + -> NameDefinition { // First, search children. match containing_module.children.find(&name) { Some(child_name_bindings) => { @@ -4442,7 +4551,7 @@ pub impl Resolver { return NoNameDefinition; } - fn intern_module_part_of_path(@mut self, path: @Path) -> ~[ident] { + pub fn intern_module_part_of_path(@mut self, path: @Path) -> ~[ident] { let mut module_path_idents = ~[]; for path.idents.eachi |index, ident| { if index == path.idents.len() - 1 { @@ -4455,18 +4564,19 @@ pub impl Resolver { return module_path_idents; } - fn resolve_module_relative_path(@mut self, - path: @Path, - xray: XrayFlag, - namespace: Namespace) - -> Option { + pub fn resolve_module_relative_path(@mut self, + path: @Path, + xray: XrayFlag, + namespace: Namespace) + -> Option { let module_path_idents = self.intern_module_part_of_path(path); let containing_module; - match self.resolve_module_path_for_import(self.current_module, - module_path_idents, - UseLexicalScope, - path.span) { + match self.resolve_module_path(self.current_module, + module_path_idents, + UseLexicalScope, + path.span, + PathPublicOnlySearch) { Failed => { self.session.span_err(path.span, fmt!("use of undeclared module `%s`", @@ -4485,7 +4595,7 @@ pub impl Resolver { } let name = *path.idents.last(); - match self.resolve_definition_of_name_in_module(containing_module, + let def = match self.resolve_definition_of_name_in_module(containing_module, name, namespace, xray) { @@ -4494,18 +4604,37 @@ pub impl Resolver { return None; } ChildNameDefinition(def) | ImportNameDefinition(def) => { - return Some(def); + def } - } + }; + match containing_module.kind { + TraitModuleKind | ImplModuleKind => { + match self.method_map.find(&name) { + Some(s) => { + match containing_module.def_id { + Some(def_id) if s.contains(&def_id) => { + debug!("containing module was a trait or impl \ + and name was a method -> not resolved"); + return None; + }, + _ => (), + } + }, + None => (), + } + }, + _ => (), + }; + return Some(def); } /// Invariant: This must be called only during main resolution, not during /// import resolution. - fn resolve_crate_relative_path(@mut self, - path: @Path, - xray: XrayFlag, - namespace: Namespace) - -> Option { + pub fn resolve_crate_relative_path(@mut self, + path: @Path, + xray: XrayFlag, + namespace: Namespace) + -> Option { let module_path_idents = self.intern_module_part_of_path(path); let root_module = self.graph_root.get_module(); @@ -4515,7 +4644,7 @@ pub impl Resolver { module_path_idents, 0, path.span, - SearchItemsAndAllImports) { + PathPublicOrPrivateSearch) { Failed => { self.session.span_err(path.span, fmt!("use of undeclared module `::%s`", @@ -4548,11 +4677,11 @@ pub impl Resolver { } } - fn resolve_identifier_in_local_ribs(@mut self, - ident: ident, - namespace: Namespace, - span: span) - -> Option { + pub fn resolve_identifier_in_local_ribs(@mut self, + ident: ident, + namespace: Namespace, + span: span) + -> Option { // Check the local set of ribs. let search_result; match namespace { @@ -4581,8 +4710,8 @@ pub impl Resolver { } } - fn resolve_self_value_in_local_ribs(@mut self, span: span) - -> Option { + pub fn resolve_self_value_in_local_ribs(@mut self, span: span) + -> Option { // FIXME #4950: This should not use a while loop. let ribs = &mut self.value_ribs; let mut i = ribs.len(); @@ -4598,8 +4727,8 @@ pub impl Resolver { Some(dl_def(def)) => return Some(def), _ => { self.session.span_bug(span, - ~"self wasn't mapped to a \ - def?!") + "self wasn't mapped to a \ + def?!") } } } @@ -4610,10 +4739,10 @@ pub impl Resolver { None } - fn resolve_item_by_identifier_in_lexical_scope(@mut self, - ident: ident, - namespace: Namespace) - -> Option { + pub fn resolve_item_by_identifier_in_lexical_scope(@mut self, + ident: ident, + namespace: Namespace) + -> Option { // Check the items. match self.resolve_item_in_lexical_scope(self.current_module, ident, @@ -4643,7 +4772,10 @@ pub impl Resolver { } } - fn find_best_match_for_name(@mut self, name: &str, max_distance: uint) -> Option<~str> { + pub fn find_best_match_for_name(@mut self, + name: &str, + max_distance: uint) + -> Option<~str> { let this = &mut *self; let mut maybes: ~[~str] = ~[]; @@ -4681,7 +4813,7 @@ pub impl Resolver { } } - fn name_exists_in_scope_struct(@mut self, name: &str) -> bool { + pub fn name_exists_in_scope_struct(@mut self, name: &str) -> bool { let this = &mut *self; let mut i = this.type_ribs.len(); @@ -4715,7 +4847,7 @@ pub impl Resolver { return false; } - fn resolve_expr(@mut self, expr: @expr, visitor: ResolveVisitor) { + pub fn resolve_expr(@mut self, expr: @expr, visitor: ResolveVisitor) { // First, record candidate traits for this expression if it could // result in the invocation of a method call. @@ -4829,8 +4961,8 @@ pub impl Resolver { } Some(_) => { self.session.span_bug(expr.span, - ~"label wasn't mapped to a \ - label def!") + "label wasn't mapped to a \ + label def!") } } } @@ -4839,8 +4971,8 @@ pub impl Resolver { match self.resolve_self_value_in_local_ribs(expr.span) { None => { self.session.span_err(expr.span, - ~"`self` is not allowed in \ - this context") + "`self` is not allowed in \ + this context") } Some(def) => self.record_def(expr.id, def), } @@ -4852,70 +4984,75 @@ pub impl Resolver { } } - fn record_candidate_traits_for_expr_if_necessary(@mut self, expr: @expr) { + pub fn record_candidate_traits_for_expr_if_necessary(@mut self, + expr: @expr) { match expr.node { expr_field(_, ident, _) => { + // FIXME(#6890): Even though you can't treat a method like a + // field, we need to add any trait methods we find that match + // the field name so that we can do some nice error reporting + // later on in typeck. let traits = self.search_for_traits_containing_method(ident); self.trait_map.insert(expr.id, @mut traits); } - expr_method_call(_, ident, _, _, _) => { + expr_method_call(_, _, ident, _, _, _) => { let traits = self.search_for_traits_containing_method(ident); self.trait_map.insert(expr.id, @mut traits); } - expr_binary(add, _, _) | expr_assign_op(add, _, _) => { + expr_binary(_, add, _, _) | expr_assign_op(_, add, _, _) => { self.add_fixed_trait_for_expr(expr.id, self.lang_items.add_trait()); } - expr_binary(subtract, _, _) | expr_assign_op(subtract, _, _) => { + expr_binary(_, subtract, _, _) | expr_assign_op(_, subtract, _, _) => { self.add_fixed_trait_for_expr(expr.id, self.lang_items.sub_trait()); } - expr_binary(mul, _, _) | expr_assign_op(mul, _, _) => { + expr_binary(_, mul, _, _) | expr_assign_op(_, mul, _, _) => { self.add_fixed_trait_for_expr(expr.id, self.lang_items.mul_trait()); } - expr_binary(div, _, _) | expr_assign_op(div, _, _) => { + expr_binary(_, div, _, _) | expr_assign_op(_, div, _, _) => { self.add_fixed_trait_for_expr(expr.id, self.lang_items.div_trait()); } - expr_binary(rem, _, _) | expr_assign_op(rem, _, _) => { + expr_binary(_, rem, _, _) | expr_assign_op(_, rem, _, _) => { self.add_fixed_trait_for_expr(expr.id, self.lang_items.rem_trait()); } - expr_binary(bitxor, _, _) | expr_assign_op(bitxor, _, _) => { + expr_binary(_, bitxor, _, _) | expr_assign_op(_, bitxor, _, _) => { self.add_fixed_trait_for_expr(expr.id, self.lang_items.bitxor_trait()); } - expr_binary(bitand, _, _) | expr_assign_op(bitand, _, _) => { + expr_binary(_, bitand, _, _) | expr_assign_op(_, bitand, _, _) => { self.add_fixed_trait_for_expr(expr.id, self.lang_items.bitand_trait()); } - expr_binary(bitor, _, _) | expr_assign_op(bitor, _, _) => { + expr_binary(_, bitor, _, _) | expr_assign_op(_, bitor, _, _) => { self.add_fixed_trait_for_expr(expr.id, self.lang_items.bitor_trait()); } - expr_binary(shl, _, _) | expr_assign_op(shl, _, _) => { + expr_binary(_, shl, _, _) | expr_assign_op(_, shl, _, _) => { self.add_fixed_trait_for_expr(expr.id, self.lang_items.shl_trait()); } - expr_binary(shr, _, _) | expr_assign_op(shr, _, _) => { + expr_binary(_, shr, _, _) | expr_assign_op(_, shr, _, _) => { self.add_fixed_trait_for_expr(expr.id, self.lang_items.shr_trait()); } - expr_binary(lt, _, _) | expr_binary(le, _, _) | - expr_binary(ge, _, _) | expr_binary(gt, _, _) => { + expr_binary(_, lt, _, _) | expr_binary(_, le, _, _) | + expr_binary(_, ge, _, _) | expr_binary(_, gt, _, _) => { self.add_fixed_trait_for_expr(expr.id, self.lang_items.ord_trait()); } - expr_binary(eq, _, _) | expr_binary(ne, _, _) => { + expr_binary(_, eq, _, _) | expr_binary(_, ne, _, _) => { self.add_fixed_trait_for_expr(expr.id, self.lang_items.eq_trait()); } - expr_unary(neg, _) => { + expr_unary(_, neg, _) => { self.add_fixed_trait_for_expr(expr.id, self.lang_items.neg_trait()); } - expr_unary(not, _) => { + expr_unary(_, not, _) => { self.add_fixed_trait_for_expr(expr.id, self.lang_items.not_trait()); } @@ -4929,149 +5066,135 @@ pub impl Resolver { } } - fn search_for_traits_containing_method(@mut self, - name: ident) - -> ~[def_id] { + pub fn search_for_traits_containing_method(@mut self, name: ident) + -> ~[def_id] { debug!("(searching for traits containing method) looking for '%s'", *self.session.str_of(name)); + let mut found_traits = ~[]; let mut search_module = self.current_module; - loop { - // Look for the current trait. - match /*bad*/copy self.current_trait_refs { - Some(trait_def_ids) => { - for trait_def_ids.each |trait_def_id| { - self.add_trait_info_if_containing_method( - &mut found_traits, *trait_def_id, name); - } - } - None => { - // Nothing to do. - } - } - - // Look for trait children. - for search_module.children.each_value |&child_name_bindings| { - match child_name_bindings.def_for_namespace(TypeNS) { - Some(def) => { - match def { - def_trait(trait_def_id) => { - self.add_trait_info_if_containing_method( - &mut found_traits, trait_def_id, name); - } - _ => { - // Continue. + match self.method_map.find(&name) { + Some(candidate_traits) => loop { + // Look for the current trait. + match /*bad*/copy self.current_trait_refs { + Some(trait_def_ids) => { + for trait_def_ids.each |trait_def_id| { + if candidate_traits.contains(trait_def_id) { + self.add_trait_info( + &mut found_traits, + *trait_def_id, name); } } } None => { - // Continue. + // Nothing to do. } } - } - // Look for imports. - for search_module.import_resolutions.each_value - |&import_resolution| { - - match import_resolution.target_for_namespace(TypeNS) { - None => { - // Continue. - } - Some(target) => { - match target.bindings.def_for_namespace(TypeNS) { - Some(def) => { - match def { - def_trait(trait_def_id) => { - let added = self. - add_trait_info_if_containing_method( + // Look for trait children. + for search_module.children.each_value |&child_name_bindings| { + match child_name_bindings.def_for_namespace(TypeNS) { + Some(def) => { + match def { + def_trait(trait_def_id) => { + if candidate_traits.contains(&trait_def_id) { + self.add_trait_info( &mut found_traits, trait_def_id, name); - if added { - self.used_imports.insert( - import_resolution.id); - } - } - _ => { - // Continue. } } - } - None => { - // Continue. + _ => { + // Continue. + } } } + None => { + // Continue. + } } } - } - // Move to the next parent. - match search_module.parent_link { - NoParentLink => { - // Done. - break; + // Look for imports. + for search_module.import_resolutions.each_value + |&import_resolution| { + + match import_resolution.target_for_namespace(TypeNS) { + None => { + // Continue. + } + Some(target) => { + match target.bindings.def_for_namespace(TypeNS) { + Some(def) => { + match def { + def_trait(trait_def_id) => { + if candidate_traits.contains(&trait_def_id) { + self.add_trait_info( + &mut found_traits, + trait_def_id, name); + self.used_imports.insert( + import_resolution.id); + } + } + _ => { + // Continue. + } + } + } + None => { + // Continue. + } + } + } + } } - ModuleParentLink(parent_module, _) | - BlockParentLink(parent_module, _) => { - search_module = parent_module; + + // Move to the next parent. + match search_module.parent_link { + NoParentLink => { + // Done. + break; + } + ModuleParentLink(parent_module, _) | + BlockParentLink(parent_module, _) => { + search_module = parent_module; + } } - } + }, + _ => () } return found_traits; } - fn add_trait_info_if_containing_method(&self, - found_traits: &mut ~[def_id], - trait_def_id: def_id, - name: ident) - -> bool { - debug!("(adding trait info if containing method) trying trait %d:%d \ - for method '%s'", + pub fn add_trait_info(&self, + found_traits: &mut ~[def_id], + trait_def_id: def_id, + name: ident) { + debug!("(adding trait info) found trait %d:%d for method '%s'", trait_def_id.crate, trait_def_id.node, *self.session.str_of(name)); - - match self.trait_info.find(&trait_def_id) { - Some(trait_info) if trait_info.contains(&name) => { - debug!("(adding trait info if containing method) found trait \ - %d:%d for method '%s'", - trait_def_id.crate, - trait_def_id.node, - *self.session.str_of(name)); - found_traits.push(trait_def_id); - true - } - Some(_) | None => { - false - } - } + found_traits.push(trait_def_id); } - fn add_fixed_trait_for_expr(@mut self, - expr_id: node_id, - trait_id: def_id) { + pub fn add_fixed_trait_for_expr(@mut self, + expr_id: node_id, + trait_id: def_id) { self.trait_map.insert(expr_id, @mut ~[trait_id]); } - fn record_def(@mut self, node_id: node_id, def: def) { + pub fn record_def(@mut self, node_id: node_id, def: def) { debug!("(recording def) recording %? for %?", def, node_id); self.def_map.insert(node_id, def); } - fn enforce_default_binding_mode(@mut self, - pat: @pat, - pat_binding_mode: binding_mode, - descr: &str) { + pub fn enforce_default_binding_mode(@mut self, + pat: @pat, + pat_binding_mode: binding_mode, + descr: &str) { match pat_binding_mode { bind_infer => {} - bind_by_copy => { - self.session.span_err( - pat.span, - fmt!("cannot use `copy` binding mode with %s", - descr)); - } bind_by_ref(*) => { self.session.span_err( pat.span, @@ -5088,7 +5211,7 @@ pub impl Resolver { // resolve data structures. // - fn check_for_unused_imports(@mut self) { + pub fn check_for_unused_imports(@mut self) { let vt = mk_simple_visitor(@SimpleVisitor { visit_view_item: |vi| self.check_for_item_unused_imports(vi), .. *default_simple_visitor() @@ -5096,7 +5219,7 @@ pub impl Resolver { visit_crate(self.crate, (), vt); } - fn check_for_item_unused_imports(&mut self, vi: @view_item) { + pub fn check_for_item_unused_imports(&mut self, vi: @view_item) { // Ignore public import statements because there's no way to be sure // whether they're used or not. Also ignore imports with a dummy span // because this means that they were generated in some fashion by the @@ -5112,7 +5235,7 @@ pub impl Resolver { view_path_simple(_, _, id) | view_path_glob(_, id) => { if !self.used_imports.contains(&id) { self.session.add_lint(unused_imports, - id, vi.span, + id, p.span, ~"unused import"); } } @@ -5140,7 +5263,7 @@ pub impl Resolver { // /// A somewhat inefficient routine to obtain the name of a module. - fn module_to_str(@mut self, module_: @mut Module) -> ~str { + pub fn module_to_str(@mut self, module_: @mut Module) -> ~str { let mut idents = ~[]; let mut current_module = module_; loop { @@ -5165,7 +5288,7 @@ pub impl Resolver { return self.idents_to_str(vec::reversed(idents)); } - fn dump_module(@mut self, module_: @mut Module) { + pub fn dump_module(@mut self, module_: @mut Module) { debug!("Dump of module `%s`:", self.module_to_str(module_)); debug!("Children:"); @@ -5212,7 +5335,7 @@ pub fn resolve_crate(session: Session, -> CrateMap { let resolver = @mut Resolver(session, lang_items, crate); resolver.resolve(); - let @Resolver{def_map, export_map2, trait_map, _} = resolver; + let Resolver{def_map, export_map2, trait_map, _} = copy *resolver; CrateMap { def_map: def_map, exp_map2: export_map2, diff --git a/src/librustc/middle/resolve_stage0.rs b/src/librustc/middle/resolve_stage0.rs deleted file mode 100644 index 713132b12fc19..0000000000000 --- a/src/librustc/middle/resolve_stage0.rs +++ /dev/null @@ -1,5324 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use driver::session; -use driver::session::Session; -use metadata::csearch::{each_path, get_trait_method_def_ids}; -use metadata::csearch::get_method_name_and_explicit_self; -use metadata::csearch::get_static_methods_if_impl; -use metadata::csearch::get_type_name_if_impl; -use metadata::cstore::find_extern_mod_stmt_cnum; -use metadata::decoder::{def_like, dl_def, dl_field, dl_impl}; -use middle::lang_items::LanguageItems; -use middle::lint::{allow, level, warn}; -use middle::pat_util::pat_bindings; - -use syntax::ast::{RegionTyParamBound, TraitTyParamBound, _mod, add, arm}; -use syntax::ast::{binding_mode, bitand, bitor, bitxor, blk}; -use syntax::ast::{bind_infer, bind_by_ref, bind_by_copy}; -use syntax::ast::{crate, decl_item, def, def_arg, def_binding}; -use syntax::ast::{def_const, def_foreign_mod, def_fn, def_id, def_label}; -use syntax::ast::{def_local, def_mod, def_prim_ty, def_region, def_self}; -use syntax::ast::{def_self_ty, def_static_method, def_struct, def_ty}; -use syntax::ast::{def_ty_param, def_typaram_binder, def_trait}; -use syntax::ast::{def_upvar, def_use, def_variant, expr, expr_assign_op}; -use syntax::ast::{expr_binary, expr_break, expr_field}; -use syntax::ast::{expr_fn_block, expr_index, expr_method_call, expr_path}; -use syntax::ast::{def_prim_ty, def_region, def_self, def_ty, def_ty_param}; -use syntax::ast::{def_upvar, def_use, def_variant, div, eq}; -use syntax::ast::{expr, expr_again, expr_assign_op}; -use syntax::ast::{expr_index, expr_loop}; -use syntax::ast::{expr_path, expr_self, expr_struct, expr_unary, fn_decl}; -use syntax::ast::{foreign_item, foreign_item_const, foreign_item_fn, ge}; -use syntax::ast::Generics; -use syntax::ast::{gt, ident, inherited, item, item_struct}; -use syntax::ast::{item_const, item_enum, item_fn, item_foreign_mod}; -use syntax::ast::{item_impl, item_mac, item_mod, item_trait, item_ty, le}; -use syntax::ast::{local, local_crate, lt, method, mul}; -use syntax::ast::{named_field, ne, neg, node_id, pat, pat_enum, pat_ident}; -use syntax::ast::{Path, pat_lit, pat_range, pat_struct}; -use syntax::ast::{prim_ty, private, provided}; -use syntax::ast::{public, required, rem, explicit_self_, shl, shr, stmt_decl}; -use syntax::ast::{struct_field, struct_variant_kind}; -use syntax::ast::{sty_static, subtract, trait_ref, tuple_variant_kind, Ty}; -use syntax::ast::{ty_bool, ty_char, ty_f, ty_f32, ty_f64, ty_float, ty_i}; -use syntax::ast::{ty_i16, ty_i32, ty_i64, ty_i8, ty_int, TyParam, ty_path}; -use syntax::ast::{ty_str, ty_u, ty_u16, ty_u32, ty_u64, ty_u8, ty_uint}; -use syntax::ast::unnamed_field; -use syntax::ast::{variant, view_item, view_item_extern_mod}; -use syntax::ast::{view_item_use, view_path_glob, view_path_list}; -use syntax::ast::{view_path_simple, anonymous, named, not}; -use syntax::ast::{unsafe_fn}; -use syntax::ast_util::{def_id_of_def, local_def}; -use syntax::ast_util::{path_to_ident, walk_pat, trait_method_to_ty_method}; -use syntax::ast_util::{Privacy, Public, Private}; -use syntax::ast_util::{variant_visibility_to_privacy, visibility_to_privacy}; -use syntax::attr::{attr_metas, contains_name, attrs_contains_name}; -use syntax::parse::token::ident_interner; -use syntax::parse::token::special_idents; -use syntax::print::pprust::path_to_str; -use syntax::codemap::{span, dummy_sp}; -use syntax::visit::{default_visitor, mk_vt, Visitor, visit_block}; -use syntax::visit::{visit_crate, visit_expr, visit_expr_opt}; -use syntax::visit::{visit_foreign_item, visit_item}; -use syntax::visit::{visit_mod, visit_ty, vt}; -use syntax::opt_vec::OptVec; - -use core::option::Some; -use core::str::each_split_str; -use core::hashmap::{HashMap, HashSet}; -use core::util; - -// Definition mapping -pub type DefMap = @mut HashMap; - -pub struct binding_info { - span: span, - binding_mode: binding_mode, -} - -// Map from the name in a pattern to its binding mode. -pub type BindingMap = HashMap; - -// Implementation resolution -// -// FIXME #4946: This kind of duplicates information kept in -// ty::method. Maybe it should go away. - -pub struct MethodInfo { - did: def_id, - n_tps: uint, - ident: ident, - explicit_self: explicit_self_ -} - -pub struct Impl { - did: def_id, - ident: ident, - methods: ~[@MethodInfo] -} - -// Trait method resolution -pub type TraitMap = HashMap; - -// This is the replacement export map. It maps a module to all of the exports -// within. -pub type ExportMap2 = @mut HashMap; - -pub struct Export2 { - name: @~str, // The name of the target. - def_id: def_id, // The definition of the target. - reexport: bool, // Whether this is a reexport. -} - -#[deriving(Eq)] -pub enum PatternBindingMode { - RefutableMode, - LocalIrrefutableMode, - ArgumentIrrefutableMode, -} - -#[deriving(Eq)] -pub enum Namespace { - TypeNS, - ValueNS -} - -/// A NamespaceResult represents the result of resolving an import in -/// a particular namespace. The result is either definitely-resolved, -/// definitely- unresolved, or unknown. -pub enum NamespaceResult { - /// Means that resolve hasn't gathered enough information yet to determine - /// whether the name is bound in this namespace. (That is, it hasn't - /// resolved all `use` directives yet.) - UnknownResult, - /// Means that resolve has determined that the name is definitely - /// not bound in the namespace. - UnboundResult, - /// Means that resolve has determined that the name is bound in the Module - /// argument, and specified by the NameBindings argument. - BoundResult(@mut Module, @mut NameBindings) -} - -pub impl NamespaceResult { - fn is_unknown(&self) -> bool { - match *self { - UnknownResult => true, - _ => false - } - } -} - -pub enum NameDefinition { - NoNameDefinition, //< The name was unbound. - ChildNameDefinition(def), //< The name identifies an immediate child. - ImportNameDefinition(def) //< The name identifies an import. -} - -#[deriving(Eq)] -pub enum Mutability { - Mutable, - Immutable -} - -pub enum SelfBinding { - NoSelfBinding, - HasSelfBinding(node_id, bool /* is implicit */) -} - -pub type ResolveVisitor = vt<()>; - -/// Contains data for specific types of import directives. -pub enum ImportDirectiveSubclass { - SingleImport(ident /* target */, ident /* source */), - GlobImport -} - -/// The context that we thread through while building the reduced graph. -pub enum ReducedGraphParent { - ModuleReducedGraphParent(@mut Module) -} - -pub enum ResolveResult { - Failed, // Failed to resolve the name. - Indeterminate, // Couldn't determine due to unresolved globs. - Success(T) // Successfully resolved the import. -} - -pub impl ResolveResult { - fn failed(&self) -> bool { - match *self { Failed => true, _ => false } - } - fn indeterminate(&self) -> bool { - match *self { Indeterminate => true, _ => false } - } -} - -pub enum TypeParameters<'self> { - NoTypeParameters, //< No type parameters. - HasTypeParameters(&'self Generics, //< Type parameters. - node_id, //< ID of the enclosing item - - // The index to start numbering the type parameters at. - // This is zero if this is the outermost set of type - // parameters, or equal to the number of outer type - // parameters. For example, if we have: - // - // impl I { - // fn method() { ... } - // } - // - // The index at the method site will be 1, because the - // outer T had index 0. - uint, - - // The kind of the rib used for type parameters. - RibKind) -} - -// The rib kind controls the translation of argument or local definitions -// (`def_arg` or `def_local`) to upvars (`def_upvar`). - -pub enum RibKind { - // No translation needs to be applied. - NormalRibKind, - - // We passed through a function scope at the given node ID. Translate - // upvars as appropriate. - FunctionRibKind(node_id /* func id */, node_id /* body id */), - - // We passed through an impl or trait and are now in one of its - // methods. Allow references to ty params that that impl or trait - // binds. Disallow any other upvars (including other ty params that are - // upvars). - // parent; method itself - MethodRibKind(node_id, MethodSort), - - // We passed through a function *item* scope. Disallow upvars. - OpaqueFunctionRibKind, - - // We're in a constant item. Can't refer to dynamic stuff. - ConstantItemRibKind -} - -// Methods can be required or provided. Required methods only occur in traits. -pub enum MethodSort { - Required, - Provided(node_id) -} - -// The X-ray flag indicates that a context has the X-ray privilege, which -// allows it to reference private names. Currently, this is used for the test -// runner. -// -// FIXME #4947: The X-ray flag is kind of questionable in the first -// place. It might be better to introduce an expr_xray_path instead. - -#[deriving(Eq)] -pub enum XrayFlag { - NoXray, //< Private items cannot be accessed. - Xray //< Private items can be accessed. -} - -pub enum UseLexicalScopeFlag { - DontUseLexicalScope, - UseLexicalScope -} - -pub enum SearchThroughModulesFlag { - DontSearchThroughModules, - SearchThroughModules -} - -pub enum ModulePrefixResult { - NoPrefixFound, - PrefixFound(@mut Module, uint) -} - -#[deriving(Eq)] -pub enum AllowCapturingSelfFlag { - AllowCapturingSelf, //< The "self" definition can be captured. - DontAllowCapturingSelf, //< The "self" definition cannot be captured. -} - -#[deriving(Eq)] -enum NameSearchType { - SearchItemsAndPublicImports, //< Search items and public imports. - SearchItemsAndAllImports, //< Search items and all imports. -} - -pub enum BareIdentifierPatternResolution { - FoundStructOrEnumVariant(def), - FoundConst(def), - BareIdentifierPatternUnresolved -} - -// Specifies how duplicates should be handled when adding a child item if -// another item exists with the same name in some namespace. -#[deriving(Eq)] -pub enum DuplicateCheckingMode { - ForbidDuplicateModules, - ForbidDuplicateTypes, - ForbidDuplicateValues, - ForbidDuplicateTypesAndValues, - OverwriteDuplicates -} - -// Returns the namespace associated with the given duplicate checking mode, -// or fails for OverwriteDuplicates. This is used for error messages. -pub fn namespace_for_duplicate_checking_mode(mode: DuplicateCheckingMode) - -> Namespace { - match mode { - ForbidDuplicateModules | ForbidDuplicateTypes | - ForbidDuplicateTypesAndValues => TypeNS, - ForbidDuplicateValues => ValueNS, - OverwriteDuplicates => fail!("OverwriteDuplicates has no namespace") - } -} - -/// One local scope. -pub struct Rib { - bindings: @mut HashMap, - self_binding: @mut Option, - kind: RibKind, -} - -pub fn Rib(kind: RibKind) -> Rib { - Rib { - bindings: @mut HashMap::new(), - self_binding: @mut None, - kind: kind - } -} - - -/// One import directive. -pub struct ImportDirective { - privacy: Privacy, - module_path: ~[ident], - subclass: @ImportDirectiveSubclass, - span: span, -} - -pub fn ImportDirective(privacy: Privacy, - module_path: ~[ident], - subclass: @ImportDirectiveSubclass, - span: span) - -> ImportDirective { - ImportDirective { - privacy: privacy, - module_path: module_path, - subclass: subclass, - span: span - } -} - -/// The item that an import resolves to. -pub struct Target { - target_module: @mut Module, - bindings: @mut NameBindings, -} - -pub fn Target(target_module: @mut Module, - bindings: @mut NameBindings) - -> Target { - Target { - target_module: target_module, - bindings: bindings - } -} - -/// An ImportResolution represents a particular `use` directive. -pub struct ImportResolution { - /// The privacy of this `use` directive (whether it's `use` or - /// `pub use`. - privacy: Privacy, - span: span, - - // The number of outstanding references to this name. When this reaches - // zero, outside modules can count on the targets being correct. Before - // then, all bets are off; future imports could override this name. - - outstanding_references: uint, - - /// The value that this `use` directive names, if there is one. - value_target: Option, - /// The type that this `use` directive names, if there is one. - type_target: Option, - - /// There exists one state per import statement - state: @mut ImportState, -} - -pub fn ImportResolution(privacy: Privacy, - span: span, - state: @mut ImportState) -> ImportResolution { - ImportResolution { - privacy: privacy, - span: span, - outstanding_references: 0, - value_target: None, - type_target: None, - state: state, - } -} - -pub impl ImportResolution { - fn target_for_namespace(&self, namespace: Namespace) -> Option { - match namespace { - TypeNS => return copy self.type_target, - ValueNS => return copy self.value_target - } - } -} - -pub struct ImportState { - used: bool, - warned: bool -} - -pub fn ImportState() -> ImportState { - ImportState{ used: false, warned: false } -} - -/// The link from a module up to its nearest parent node. -pub enum ParentLink { - NoParentLink, - ModuleParentLink(@mut Module, ident), - BlockParentLink(@mut Module, node_id) -} - -/// The type of module this is. -pub enum ModuleKind { - NormalModuleKind, - ExternModuleKind, - TraitModuleKind, - AnonymousModuleKind, -} - -/// One node in the tree of modules. -pub struct Module { - parent_link: ParentLink, - def_id: Option, - kind: ModuleKind, - - children: @mut HashMap, - imports: @mut ~[@ImportDirective], - - // The external module children of this node that were declared with - // `extern mod`. - external_module_children: @mut HashMap, - - // The anonymous children of this node. Anonymous children are pseudo- - // modules that are implicitly created around items contained within - // blocks. - // - // For example, if we have this: - // - // fn f() { - // fn g() { - // ... - // } - // } - // - // There will be an anonymous module created around `g` with the ID of the - // entry block for `f`. - - anonymous_children: @mut HashMap, - - // The status of resolving each import in this module. - import_resolutions: @mut HashMap, - - // The number of unresolved globs that this module exports. - glob_count: uint, - - // The index of the import we're resolving. - resolved_import_count: uint, -} - -pub fn Module(parent_link: ParentLink, - def_id: Option, - kind: ModuleKind) - -> Module { - Module { - parent_link: parent_link, - def_id: def_id, - kind: kind, - children: @mut HashMap::new(), - imports: @mut ~[], - external_module_children: @mut HashMap::new(), - anonymous_children: @mut HashMap::new(), - import_resolutions: @mut HashMap::new(), - glob_count: 0, - resolved_import_count: 0 - } -} - -pub impl Module { - fn all_imports_resolved(&self) -> bool { - let imports = &mut *self.imports; - return imports.len() == self.resolved_import_count; - } -} - -// Records a possibly-private type definition. -pub struct TypeNsDef { - privacy: Privacy, - module_def: Option<@mut Module>, - type_def: Option -} - -// Records a possibly-private value definition. -pub struct ValueNsDef { - privacy: Privacy, - def: def, -} - -// Records the definitions (at most one for each namespace) that a name is -// bound to. -pub struct NameBindings { - type_def: Option, //< Meaning in type namespace. - value_def: Option, //< Meaning in value namespace. - - // For error reporting - // FIXME (#3783): Merge me into TypeNsDef and ValueNsDef. - type_span: Option, - value_span: Option, -} - -pub impl NameBindings { - /// Creates a new module in this set of name bindings. - fn define_module(@mut self, - privacy: Privacy, - parent_link: ParentLink, - def_id: Option, - kind: ModuleKind, - sp: span) { - // Merges the module with the existing type def or creates a new one. - let module_ = @mut Module(parent_link, def_id, kind); - match self.type_def { - None => { - self.type_def = Some(TypeNsDef { - privacy: privacy, - module_def: Some(module_), - type_def: None - }); - } - Some(copy type_def) => { - self.type_def = Some(TypeNsDef { - privacy: privacy, - module_def: Some(module_), - .. type_def - }); - } - } - self.type_span = Some(sp); - } - - /// Records a type definition. - fn define_type(@mut self, privacy: Privacy, def: def, sp: span) { - // Merges the type with the existing type def or creates a new one. - match self.type_def { - None => { - self.type_def = Some(TypeNsDef { - privacy: privacy, - module_def: None, - type_def: Some(def) - }); - } - Some(copy type_def) => { - self.type_def = Some(TypeNsDef { - privacy: privacy, - type_def: Some(def), - .. type_def - }); - } - } - self.type_span = Some(sp); - } - - /// Records a value definition. - fn define_value(@mut self, privacy: Privacy, def: def, sp: span) { - self.value_def = Some(ValueNsDef { privacy: privacy, def: def }); - self.value_span = Some(sp); - } - - /// Returns the module node if applicable. - fn get_module_if_available(&self) -> Option<@mut Module> { - match self.type_def { - Some(ref type_def) => (*type_def).module_def, - None => None - } - } - - /** - * Returns the module node. Fails if this node does not have a module - * definition. - */ - fn get_module(@mut self) -> @mut Module { - match self.get_module_if_available() { - None => { - fail!("get_module called on a node with no module \ - definition!") - } - Some(module_def) => module_def - } - } - - fn defined_in_namespace(&self, namespace: Namespace) -> bool { - match namespace { - TypeNS => return self.type_def.is_some(), - ValueNS => return self.value_def.is_some() - } - } - - fn defined_in_public_namespace(&self, namespace: Namespace) -> bool { - match namespace { - TypeNS => match self.type_def { - Some(def) => def.privacy != Private, - None => false - }, - ValueNS => match self.value_def { - Some(def) => def.privacy != Private, - None => false - } - } - } - - fn def_for_namespace(&self, namespace: Namespace) -> Option { - match namespace { - TypeNS => { - match self.type_def { - None => None, - Some(ref type_def) => { - // FIXME (#3784): This is reallllly questionable. - // Perhaps the right thing to do is to merge def_mod - // and def_ty. - match (*type_def).type_def { - Some(type_def) => Some(type_def), - None => { - match (*type_def).module_def { - Some(module_def) => { - let module_def = &mut *module_def; - module_def.def_id.map(|def_id| - def_mod(*def_id)) - } - None => None - } - } - } - } - } - } - ValueNS => { - match self.value_def { - None => None, - Some(value_def) => Some(value_def.def) - } - } - } - } - - fn privacy_for_namespace(&self, namespace: Namespace) -> Option { - match namespace { - TypeNS => { - match self.type_def { - None => None, - Some(ref type_def) => Some((*type_def).privacy) - } - } - ValueNS => { - match self.value_def { - None => None, - Some(value_def) => Some(value_def.privacy) - } - } - } - } - - fn span_for_namespace(&self, namespace: Namespace) -> Option { - if self.defined_in_namespace(namespace) { - match namespace { - TypeNS => self.type_span, - ValueNS => self.value_span, - } - } else { - None - } - } -} - -pub fn NameBindings() -> NameBindings { - NameBindings { - type_def: None, - value_def: None, - type_span: None, - value_span: None - } -} - -/// Interns the names of the primitive types. -pub struct PrimitiveTypeTable { - primitive_types: HashMap, -} - -pub impl PrimitiveTypeTable { - fn intern(&mut self, intr: @ident_interner, string: &str, - primitive_type: prim_ty) { - let ident = intr.intern(string); - self.primitive_types.insert(ident, primitive_type); - } -} - -pub fn PrimitiveTypeTable(intr: @ident_interner) -> PrimitiveTypeTable { - let mut table = PrimitiveTypeTable { - primitive_types: HashMap::new() - }; - - table.intern(intr, "bool", ty_bool); - table.intern(intr, "char", ty_int(ty_char)); - table.intern(intr, "float", ty_float(ty_f)); - table.intern(intr, "f32", ty_float(ty_f32)); - table.intern(intr, "f64", ty_float(ty_f64)); - table.intern(intr, "int", ty_int(ty_i)); - table.intern(intr, "i8", ty_int(ty_i8)); - table.intern(intr, "i16", ty_int(ty_i16)); - table.intern(intr, "i32", ty_int(ty_i32)); - table.intern(intr, "i64", ty_int(ty_i64)); - table.intern(intr, "str", ty_str); - table.intern(intr, "uint", ty_uint(ty_u)); - table.intern(intr, "u8", ty_uint(ty_u8)); - table.intern(intr, "u16", ty_uint(ty_u16)); - table.intern(intr, "u32", ty_uint(ty_u32)); - table.intern(intr, "u64", ty_uint(ty_u64)); - - return table; -} - - -pub fn namespace_to_str(ns: Namespace) -> ~str { - match ns { - TypeNS => ~"type", - ValueNS => ~"value", - } -} - -pub fn Resolver(session: Session, - lang_items: LanguageItems, - crate: @crate) - -> Resolver { - let graph_root = @mut NameBindings(); - - graph_root.define_module(Public, - NoParentLink, - Some(def_id { crate: 0, node: 0 }), - NormalModuleKind, - crate.span); - - let current_module = graph_root.get_module(); - - let this = Resolver { - session: @session, - lang_items: copy lang_items, - crate: crate, - - // The outermost module has def ID 0; this is not reflected in the - // AST. - - graph_root: graph_root, - - trait_info: HashMap::new(), - structs: HashSet::new(), - - unresolved_imports: 0, - - current_module: current_module, - value_ribs: ~[], - type_ribs: ~[], - label_ribs: ~[], - - xray_context: NoXray, - current_trait_refs: None, - - self_ident: special_idents::self_, - type_self_ident: special_idents::type_self, - - primitive_type_table: @PrimitiveTypeTable(session. - parse_sess.interner), - - namespaces: ~[ TypeNS, ValueNS ], - - attr_main_fn: None, - main_fns: ~[], - - start_fn: None, - - def_map: @mut HashMap::new(), - export_map2: @mut HashMap::new(), - trait_map: HashMap::new(), - - intr: session.intr() - }; - - this -} - -/// The main resolver class. -pub struct Resolver { - session: @Session, - lang_items: LanguageItems, - crate: @crate, - - intr: @ident_interner, - - graph_root: @mut NameBindings, - - trait_info: HashMap>, - structs: HashSet, - - // The number of imports that are currently unresolved. - unresolved_imports: uint, - - // The module that represents the current item scope. - current_module: @mut Module, - - // The current set of local scopes, for values. - // FIXME #4948: Reuse ribs to avoid allocation. - value_ribs: ~[@Rib], - - // The current set of local scopes, for types. - type_ribs: ~[@Rib], - - // The current set of local scopes, for labels. - label_ribs: ~[@Rib], - - // Whether the current context is an X-ray context. An X-ray context is - // allowed to access private names of any module. - xray_context: XrayFlag, - - // The trait that the current context can refer to. - current_trait_refs: Option<~[def_id]>, - - // The ident for the keyword "self". - self_ident: ident, - // The ident for the non-keyword "Self". - type_self_ident: ident, - - // The idents for the primitive types. - primitive_type_table: @PrimitiveTypeTable, - - // The four namespaces. - namespaces: ~[Namespace], - - // The function that has attribute named 'main' - attr_main_fn: Option<(node_id, span)>, - - // The functions that could be main functions - main_fns: ~[Option<(node_id, span)>], - - // The function that has the attribute 'start' on it - start_fn: Option<(node_id, span)>, - - def_map: DefMap, - export_map2: ExportMap2, - trait_map: TraitMap, -} - -pub impl Resolver { - /// The main name resolution procedure. - fn resolve(@mut self) { - self.build_reduced_graph(); - self.session.abort_if_errors(); - - self.resolve_imports(); - self.session.abort_if_errors(); - - self.record_exports(); - self.session.abort_if_errors(); - - self.resolve_crate(); - self.session.abort_if_errors(); - - self.check_duplicate_main(); - self.check_for_unused_imports_if_necessary(); - } - - // - // Reduced graph building - // - // Here we build the "reduced graph": the graph of the module tree without - // any imports resolved. - // - - /// Constructs the reduced graph for the entire crate. - fn build_reduced_graph(@mut self) { - let initial_parent = - ModuleReducedGraphParent(self.graph_root.get_module()); - visit_crate(self.crate, initial_parent, mk_vt(@Visitor { - visit_item: |item, context, visitor| - self.build_reduced_graph_for_item(item, context, visitor), - - visit_foreign_item: |foreign_item, context, visitor| - self.build_reduced_graph_for_foreign_item(foreign_item, - context, - visitor), - - visit_view_item: |view_item, context, visitor| - self.build_reduced_graph_for_view_item(view_item, - context, - visitor), - - visit_block: |block, context, visitor| - self.build_reduced_graph_for_block(block, - context, - visitor), - - .. *default_visitor() - })); - } - - /// Returns the current module tracked by the reduced graph parent. - fn get_module_from_parent(@mut self, - reduced_graph_parent: ReducedGraphParent) - -> @mut Module { - match reduced_graph_parent { - ModuleReducedGraphParent(module_) => { - return module_; - } - } - } - - /** - * Adds a new child item to the module definition of the parent node and - * returns its corresponding name bindings as well as the current parent. - * Or, if we're inside a block, creates (or reuses) an anonymous module - * corresponding to the innermost block ID and returns the name bindings - * as well as the newly-created parent. - * - * If this node does not have a module definition and we are not inside - * a block, fails. - */ - fn add_child(@mut self, - name: ident, - reduced_graph_parent: ReducedGraphParent, - duplicate_checking_mode: DuplicateCheckingMode, - // For printing errors - sp: span) - -> (@mut NameBindings, ReducedGraphParent) { - - // If this is the immediate descendant of a module, then we add the - // child name directly. Otherwise, we create or reuse an anonymous - // module and add the child to that. - - let module_; - match reduced_graph_parent { - ModuleReducedGraphParent(parent_module) => { - module_ = parent_module; - } - } - - // Add or reuse the child. - let new_parent = ModuleReducedGraphParent(module_); - match module_.children.find(&name) { - None => { - let child = @mut NameBindings(); - module_.children.insert(name, child); - return (child, new_parent); - } - Some(child) => { - // Enforce the duplicate checking mode: - // - // * If we're requesting duplicate module checking, check that - // there isn't a module in the module with the same name. - // - // * If we're requesting duplicate type checking, check that - // there isn't a type in the module with the same name. - // - // * If we're requesting duplicate value checking, check that - // there isn't a value in the module with the same name. - // - // * If we're requesting duplicate type checking and duplicate - // value checking, check that there isn't a duplicate type - // and a duplicate value with the same name. - // - // * If no duplicate checking was requested at all, do - // nothing. - - let mut is_duplicate = false; - match duplicate_checking_mode { - ForbidDuplicateModules => { - is_duplicate = - child.get_module_if_available().is_some(); - } - ForbidDuplicateTypes => { - match child.def_for_namespace(TypeNS) { - Some(def_mod(_)) | None => {} - Some(_) => is_duplicate = true - } - } - ForbidDuplicateValues => { - is_duplicate = child.defined_in_namespace(ValueNS); - } - ForbidDuplicateTypesAndValues => { - match child.def_for_namespace(TypeNS) { - Some(def_mod(_)) | None => {} - Some(_) => is_duplicate = true - }; - if child.defined_in_namespace(ValueNS) { - is_duplicate = true; - } - } - OverwriteDuplicates => {} - } - if duplicate_checking_mode != OverwriteDuplicates && - is_duplicate { - // Return an error here by looking up the namespace that - // had the duplicate. - let ns = namespace_for_duplicate_checking_mode( - duplicate_checking_mode); - self.session.span_err(sp, - fmt!("duplicate definition of %s %s", - namespace_to_str(ns), - *self.session.str_of(name))); - for child.span_for_namespace(ns).each |sp| { - self.session.span_note(*sp, - fmt!("first definition of %s %s here:", - namespace_to_str(ns), - *self.session.str_of(name))); - } - } - return (*child, new_parent); - } - } - } - - fn block_needs_anonymous_module(@mut self, block: &blk) -> bool { - // If the block has view items, we need an anonymous module. - if block.node.view_items.len() > 0 { - return true; - } - - // Check each statement. - for block.node.stmts.each |statement| { - match statement.node { - stmt_decl(declaration, _) => { - match declaration.node { - decl_item(_) => { - return true; - } - _ => { - // Keep searching. - } - } - } - _ => { - // Keep searching. - } - } - } - - // If we found neither view items nor items, we don't need to create - // an anonymous module. - - return false; - } - - fn get_parent_link(@mut self, - parent: ReducedGraphParent, - name: ident) - -> ParentLink { - match parent { - ModuleReducedGraphParent(module_) => { - return ModuleParentLink(module_, name); - } - } - } - - /// Constructs the reduced graph for one item. - fn build_reduced_graph_for_item(@mut self, - item: @item, - parent: ReducedGraphParent, - visitor: vt) { - let ident = item.ident; - let sp = item.span; - let privacy = visibility_to_privacy(item.vis); - - match item.node { - item_mod(ref module_) => { - let (name_bindings, new_parent) = - self.add_child(ident, parent, ForbidDuplicateModules, sp); - - let parent_link = self.get_parent_link(new_parent, ident); - let def_id = def_id { crate: 0, node: item.id }; - name_bindings.define_module(privacy, - parent_link, - Some(def_id), - NormalModuleKind, - sp); - - let new_parent = - ModuleReducedGraphParent(name_bindings.get_module()); - - visit_mod(module_, sp, item.id, new_parent, visitor); - } - - item_foreign_mod(ref fm) => { - let new_parent = match fm.sort { - named => { - let (name_bindings, new_parent) = - self.add_child(ident, parent, - ForbidDuplicateModules, sp); - - let parent_link = self.get_parent_link(new_parent, - ident); - let def_id = def_id { crate: 0, node: item.id }; - name_bindings.define_module(privacy, - parent_link, - Some(def_id), - ExternModuleKind, - sp); - - ModuleReducedGraphParent(name_bindings.get_module()) - } - - // For anon foreign mods, the contents just go in the - // current scope - anonymous => parent - }; - - visit_item(item, new_parent, visitor); - } - - // These items live in the value namespace. - item_const(*) => { - let (name_bindings, _) = - self.add_child(ident, parent, ForbidDuplicateValues, sp); - - name_bindings.define_value - (privacy, def_const(local_def(item.id)), sp); - } - item_fn(_, purity, _, _, _) => { - let (name_bindings, new_parent) = - self.add_child(ident, parent, ForbidDuplicateValues, sp); - - let def = def_fn(local_def(item.id), purity); - name_bindings.define_value(privacy, def, sp); - visit_item(item, new_parent, visitor); - } - - // These items live in the type namespace. - item_ty(*) => { - let (name_bindings, _) = - self.add_child(ident, parent, ForbidDuplicateTypes, sp); - - name_bindings.define_type - (privacy, def_ty(local_def(item.id)), sp); - } - - item_enum(ref enum_definition, _) => { - let (name_bindings, new_parent) = - self.add_child(ident, parent, ForbidDuplicateTypes, sp); - - name_bindings.define_type - (privacy, def_ty(local_def(item.id)), sp); - - for (*enum_definition).variants.each |variant| { - self.build_reduced_graph_for_variant(variant, - local_def(item.id), - // inherited => privacy of the enum item - variant_visibility_to_privacy(variant.node.vis, - privacy == Public), - new_parent, - visitor); - } - } - - // These items live in both the type and value namespaces. - item_struct(struct_def, _) => { - let (name_bindings, new_parent) = - self.add_child(ident, parent, ForbidDuplicateTypes, sp); - - name_bindings.define_type( - privacy, def_ty(local_def(item.id)), sp); - - // If this struct is tuple-like or enum-like, define a name - // in the value namespace. - match struct_def.ctor_id { - None => {} - Some(ctor_id) => { - name_bindings.define_value( - privacy, - def_struct(local_def(ctor_id)), - sp); - } - } - - // Record the def ID of this struct. - self.structs.insert(local_def(item.id)); - - visit_item(item, new_parent, visitor); - } - - item_impl(_, trait_ref_opt, ty, ref methods) => { - // If this implements an anonymous trait and it has static - // methods, then add all the static methods within to a new - // module, if the type was defined within this module. - // - // FIXME (#3785): This is quite unsatisfactory. Perhaps we - // should modify anonymous traits to only be implementable in - // the same module that declared the type. - - // Bail out early if there are no static methods. - let mut has_static_methods = false; - for methods.each |method| { - match method.explicit_self.node { - sty_static => has_static_methods = true, - _ => {} - } - } - - // If there are static methods, then create the module - // and add them. - match (trait_ref_opt, ty) { - (None, @Ty { node: ty_path(path, _), _ }) if - has_static_methods && path.idents.len() == 1 => { - // Create the module. - let name = path_to_ident(path); - let (name_bindings, new_parent) = - self.add_child(name, - parent, - ForbidDuplicateModules, - sp); - - let parent_link = self.get_parent_link(new_parent, - ident); - let def_id = local_def(item.id); - name_bindings.define_module(Public, - parent_link, - Some(def_id), - TraitModuleKind, - sp); - - let new_parent = ModuleReducedGraphParent( - name_bindings.get_module()); - - // For each static method... - for methods.each |method| { - match method.explicit_self.node { - sty_static => { - // Add the static method to the - // module. - let ident = method.ident; - let (method_name_bindings, _) = - self.add_child( - ident, - new_parent, - ForbidDuplicateValues, - method.span); - let def = def_fn(local_def(method.id), - method.purity); - method_name_bindings.define_value( - Public, def, method.span); - } - _ => {} - } - } - } - _ => {} - } - - visit_item(item, parent, visitor); - } - - item_trait(_, _, ref methods) => { - let (name_bindings, new_parent) = - self.add_child(ident, parent, ForbidDuplicateTypes, sp); - - // If the trait has static methods, then add all the static - // methods within to a new module. - // - // We only need to create the module if the trait has static - // methods, so check that first. - let mut has_static_methods = false; - for (*methods).each |method| { - let ty_m = trait_method_to_ty_method(method); - match ty_m.explicit_self.node { - sty_static => { - has_static_methods = true; - break; - } - _ => {} - } - } - - // Create the module if necessary. - let module_parent_opt; - if has_static_methods { - let parent_link = self.get_parent_link(parent, ident); - name_bindings.define_module(privacy, - parent_link, - Some(local_def(item.id)), - TraitModuleKind, - sp); - module_parent_opt = Some(ModuleReducedGraphParent( - name_bindings.get_module())); - } else { - module_parent_opt = None; - } - - // Add the names of all the methods to the trait info. - let mut method_names = HashSet::new(); - for methods.each |method| { - let ty_m = trait_method_to_ty_method(method); - - let ident = ty_m.ident; - // Add it to the trait info if not static, - // add it as a name in the trait module otherwise. - match ty_m.explicit_self.node { - sty_static => { - let def = def_static_method( - local_def(ty_m.id), - Some(local_def(item.id)), - ty_m.purity); - - let (method_name_bindings, _) = - self.add_child(ident, - module_parent_opt.get(), - ForbidDuplicateValues, - ty_m.span); - method_name_bindings.define_value(Public, - def, - ty_m.span); - } - _ => { - method_names.insert(ident); - } - } - } - - let def_id = local_def(item.id); - self.trait_info.insert(def_id, method_names); - - name_bindings.define_type(privacy, def_trait(def_id), sp); - visit_item(item, new_parent, visitor); - } - - item_mac(*) => { - fail!("item macros unimplemented") - } - } - } - - // Constructs the reduced graph for one variant. Variants exist in the - // type and/or value namespaces. - fn build_reduced_graph_for_variant(@mut self, - variant: &variant, - item_id: def_id, - parent_privacy: Privacy, - parent: ReducedGraphParent, - _visitor: vt) { - let ident = variant.node.name; - let (child, _) = self.add_child(ident, parent, ForbidDuplicateValues, - variant.span); - - let privacy; - match variant.node.vis { - public => privacy = Public, - private => privacy = Private, - inherited => privacy = parent_privacy - } - - match variant.node.kind { - tuple_variant_kind(_) => { - child.define_value(privacy, - def_variant(item_id, - local_def(variant.node.id)), - variant.span); - } - struct_variant_kind(_) => { - child.define_type(privacy, - def_variant(item_id, - local_def(variant.node.id)), - variant.span); - self.structs.insert(local_def(variant.node.id)); - } - } - } - - /** - * Constructs the reduced graph for one 'view item'. View items consist - * of imports and use directives. - */ - fn build_reduced_graph_for_view_item(@mut self, - view_item: @view_item, - parent: ReducedGraphParent, - _visitor: vt) { - let privacy = visibility_to_privacy(view_item.vis); - match view_item.node { - view_item_use(ref view_paths) => { - for view_paths.each |view_path| { - // Extract and intern the module part of the path. For - // globs and lists, the path is found directly in the AST; - // for simple paths we have to munge the path a little. - - let mut module_path = ~[]; - match view_path.node { - view_path_simple(_, full_path, _) => { - let path_len = full_path.idents.len(); - assert!(path_len != 0); - - for full_path.idents.eachi |i, ident| { - if i != path_len - 1 { - module_path.push(*ident); - } - } - } - - view_path_glob(module_ident_path, _) | - view_path_list(module_ident_path, _, _) => { - for module_ident_path.idents.each |ident| { - module_path.push(*ident); - } - } - } - - // Build up the import directives. - let module_ = self.get_module_from_parent(parent); - match view_path.node { - view_path_simple(binding, full_path, _) => { - let source_ident = *full_path.idents.last(); - let subclass = @SingleImport(binding, - source_ident); - self.build_import_directive(privacy, - module_, - module_path, - subclass, - view_path.span); - } - view_path_list(_, ref source_idents, _) => { - for source_idents.each |source_ident| { - let name = source_ident.node.name; - let subclass = @SingleImport(name, name); - self.build_import_directive(privacy, - module_, - copy module_path, - subclass, - source_ident.span); - } - } - view_path_glob(_, _) => { - self.build_import_directive(privacy, - module_, - module_path, - @GlobImport, - view_path.span); - } - } - } - } - - view_item_extern_mod(name, _, node_id) => { - match find_extern_mod_stmt_cnum(self.session.cstore, - node_id) { - Some(crate_id) => { - let def_id = def_id { crate: crate_id, node: 0 }; - let parent_link = ModuleParentLink - (self.get_module_from_parent(parent), name); - let external_module = @mut Module(parent_link, - Some(def_id), - NormalModuleKind); - - parent.external_module_children.insert( - name, - external_module); - - self.build_reduced_graph_for_external_crate( - external_module); - } - None => {} // Ignore. - } - } - } - } - - /// Constructs the reduced graph for one foreign item. - fn build_reduced_graph_for_foreign_item(@mut self, - foreign_item: @foreign_item, - parent: ReducedGraphParent, - visitor: - vt) { - let name = foreign_item.ident; - let (name_bindings, new_parent) = - self.add_child(name, parent, ForbidDuplicateValues, - foreign_item.span); - - match foreign_item.node { - foreign_item_fn(_, _, ref generics) => { - let def = def_fn(local_def(foreign_item.id), unsafe_fn); - name_bindings.define_value(Public, def, foreign_item.span); - - do self.with_type_parameter_rib( - HasTypeParameters( - generics, foreign_item.id, 0, NormalRibKind)) - { - visit_foreign_item(foreign_item, new_parent, visitor); - } - } - foreign_item_const(*) => { - let def = def_const(local_def(foreign_item.id)); - name_bindings.define_value(Public, def, foreign_item.span); - - visit_foreign_item(foreign_item, new_parent, visitor); - } - } - } - - fn build_reduced_graph_for_block(@mut self, - block: &blk, - parent: ReducedGraphParent, - visitor: vt) { - let new_parent; - if self.block_needs_anonymous_module(block) { - let block_id = block.node.id; - - debug!("(building reduced graph for block) creating a new \ - anonymous module for block %d", - block_id); - - let parent_module = self.get_module_from_parent(parent); - let new_module = @mut Module( - BlockParentLink(parent_module, block_id), - None, - AnonymousModuleKind); - parent_module.anonymous_children.insert(block_id, new_module); - new_parent = ModuleReducedGraphParent(new_module); - } else { - new_parent = parent; - } - - visit_block(block, new_parent, visitor); - } - - fn handle_external_def(@mut self, - def: def, - modules: &mut HashMap, - child_name_bindings: @mut NameBindings, - final_ident: &str, - ident: ident, - new_parent: ReducedGraphParent) { - match def { - def_mod(def_id) | def_foreign_mod(def_id) => { - match child_name_bindings.type_def { - Some(TypeNsDef { module_def: Some(copy module_def), _ }) => { - debug!("(building reduced graph for external crate) \ - already created module"); - module_def.def_id = Some(def_id); - modules.insert(def_id, module_def); - } - Some(_) | None => { - debug!("(building reduced graph for \ - external crate) building module \ - %s", final_ident); - let parent_link = self.get_parent_link(new_parent, ident); - - // FIXME (#5074): this should be a match on find - if !modules.contains_key(&def_id) { - child_name_bindings.define_module(Public, - parent_link, - Some(def_id), - NormalModuleKind, - dummy_sp()); - modules.insert(def_id, - child_name_bindings.get_module()); - } else { - let existing_module = *modules.get(&def_id); - // Create an import resolution to - // avoid creating cycles in the - // module graph. - - let resolution = - @mut ImportResolution(Public, - dummy_sp(), - @mut ImportState()); - resolution.outstanding_references = 0; - - match existing_module.parent_link { - NoParentLink | - BlockParentLink(*) => { - fail!("can't happen"); - } - ModuleParentLink(parent_module, ident) => { - let name_bindings = parent_module.children.get( - &ident); - resolution.type_target = - Some(Target(parent_module, *name_bindings)); - } - } - - debug!("(building reduced graph for external crate) \ - ... creating import resolution"); - - new_parent.import_resolutions.insert(ident, resolution); - } - } - } - } - def_fn(*) | def_static_method(*) | def_const(*) | - def_variant(*) => { - debug!("(building reduced graph for external \ - crate) building value %s", final_ident); - child_name_bindings.define_value(Public, def, dummy_sp()); - } - def_trait(def_id) => { - debug!("(building reduced graph for external \ - crate) building type %s", final_ident); - - // If this is a trait, add all the method names - // to the trait info. - - let method_def_ids = get_trait_method_def_ids(self.session.cstore, - def_id); - let mut interned_method_names = HashSet::new(); - for method_def_ids.each |&method_def_id| { - let (method_name, explicit_self) = - get_method_name_and_explicit_self(self.session.cstore, - method_def_id); - - debug!("(building reduced graph for \ - external crate) ... adding \ - trait method '%s'", - *self.session.str_of(method_name)); - - // Add it to the trait info if not static. - if explicit_self != sty_static { - interned_method_names.insert(method_name); - } - } - self.trait_info.insert(def_id, interned_method_names); - - child_name_bindings.define_type(Public, def, dummy_sp()); - } - def_ty(_) => { - debug!("(building reduced graph for external \ - crate) building type %s", final_ident); - - child_name_bindings.define_type(Public, def, dummy_sp()); - } - def_struct(def_id) => { - debug!("(building reduced graph for external \ - crate) building type %s", - final_ident); - child_name_bindings.define_type(Public, def, dummy_sp()); - self.structs.insert(def_id); - } - def_self(*) | def_arg(*) | def_local(*) | - def_prim_ty(*) | def_ty_param(*) | def_binding(*) | - def_use(*) | def_upvar(*) | def_region(*) | - def_typaram_binder(*) | def_label(*) | def_self_ty(*) => { - fail!("didn't expect `%?`", def); - } - } - } - - /** - * Builds the reduced graph rooted at the 'use' directive for an external - * crate. - */ - fn build_reduced_graph_for_external_crate(@mut self, root: @mut Module) { - let mut modules = HashMap::new(); - - // Create all the items reachable by paths. - for each_path(self.session.cstore, root.def_id.get().crate) - |path_string, def_like| { - - debug!("(building reduced graph for external crate) found path \ - entry: %s (%?)", - path_string, def_like); - - let mut pieces = ~[]; - for each_split_str(path_string, "::") |s| { pieces.push(s.to_owned()) } - let final_ident_str = pieces.pop(); - let final_ident = self.session.ident_of(final_ident_str); - - // Find the module we need, creating modules along the way if we - // need to. - - let mut current_module = root; - for pieces.each |ident_str| { - let ident = self.session.ident_of(/*bad*/copy *ident_str); - // Create or reuse a graph node for the child. - let (child_name_bindings, new_parent) = - self.add_child(ident, - ModuleReducedGraphParent(current_module), - OverwriteDuplicates, - dummy_sp()); - - // Define or reuse the module node. - match child_name_bindings.type_def { - None => { - debug!("(building reduced graph for external crate) \ - autovivifying missing type def %s", - *ident_str); - let parent_link = self.get_parent_link(new_parent, - ident); - child_name_bindings.define_module(Public, - parent_link, - None, - NormalModuleKind, - dummy_sp()); - } - Some(copy type_ns_def) - if type_ns_def.module_def.is_none() => { - debug!("(building reduced graph for external crate) \ - autovivifying missing module def %s", - *ident_str); - let parent_link = self.get_parent_link(new_parent, - ident); - child_name_bindings.define_module(Public, - parent_link, - None, - NormalModuleKind, - dummy_sp()); - } - _ => {} // Fall through. - } - - current_module = child_name_bindings.get_module(); - } - - match def_like { - dl_def(def) => { - // Add the new child item. - let (child_name_bindings, new_parent) = - self.add_child(final_ident, - ModuleReducedGraphParent( - current_module), - OverwriteDuplicates, - dummy_sp()); - - self.handle_external_def(def, - &mut modules, - child_name_bindings, - *self.session.str_of( - final_ident), - final_ident, - new_parent); - } - dl_impl(def) => { - // We only process static methods of impls here. - match get_type_name_if_impl(self.session.cstore, def) { - None => {} - Some(final_ident) => { - let static_methods_opt = - get_static_methods_if_impl( - self.session.cstore, def); - match static_methods_opt { - Some(ref static_methods) if - static_methods.len() >= 1 => { - debug!("(building reduced graph for \ - external crate) processing \ - static methods for type name %s", - *self.session.str_of( - final_ident)); - - let (child_name_bindings, new_parent) = - self.add_child(final_ident, - ModuleReducedGraphParent( - current_module), - OverwriteDuplicates, - dummy_sp()); - - // Process the static methods. First, - // create the module. - let type_module; - match child_name_bindings.type_def { - Some(TypeNsDef { - module_def: Some(copy module_def), - _ - }) => { - // We already have a module. This - // is OK. - type_module = module_def; - } - Some(_) | None => { - let parent_link = - self.get_parent_link( - new_parent, final_ident); - child_name_bindings.define_module( - Public, - parent_link, - Some(def), - NormalModuleKind, - dummy_sp()); - type_module = - child_name_bindings. - get_module(); - } - } - - // Add each static method to the module. - let new_parent = ModuleReducedGraphParent( - type_module); - for static_methods.each - |static_method_info| { - let ident = static_method_info.ident; - debug!("(building reduced graph for \ - external crate) creating \ - static method '%s'", - *self.session.str_of(ident)); - - let (method_name_bindings, _) = - self.add_child( - ident, - new_parent, - OverwriteDuplicates, - dummy_sp()); - let def = def_fn( - static_method_info.def_id, - static_method_info.purity); - method_name_bindings.define_value( - Public, def, dummy_sp()); - } - } - - // Otherwise, do nothing. - Some(_) | None => {} - } - } - } - } - dl_field => { - debug!("(building reduced graph for external crate) \ - ignoring field"); - } - } - } - } - - /// Creates and adds an import directive to the given module. - fn build_import_directive(@mut self, - privacy: Privacy, - module_: @mut Module, - module_path: ~[ident], - subclass: @ImportDirectiveSubclass, - span: span) { - let directive = @ImportDirective(privacy, module_path, - subclass, span); - module_.imports.push(directive); - - // Bump the reference count on the name. Or, if this is a glob, set - // the appropriate flag. - - match *subclass { - SingleImport(target, _) => { - debug!("(building import directive) building import \ - directive: privacy %? %s::%s", - privacy, - self.idents_to_str(directive.module_path), - *self.session.str_of(target)); - - match module_.import_resolutions.find(&target) { - Some(resolution) => { - debug!("(building import directive) bumping \ - reference"); - resolution.outstanding_references += 1; - } - None => { - debug!("(building import directive) creating new"); - let state = @mut ImportState(); - let resolution = @mut ImportResolution(privacy, - span, - state); - let name = self.idents_to_str(directive.module_path); - // Don't warn about unused intrinsics because they're - // automatically appended to all files - if name == ~"intrinsic::rusti" { - resolution.state.warned = true; - } - resolution.outstanding_references = 1; - module_.import_resolutions.insert(target, resolution); - } - } - } - GlobImport => { - // Set the glob flag. This tells us that we don't know the - // module's exports ahead of time. - - module_.glob_count += 1; - } - } - - self.unresolved_imports += 1; - } - - // Import resolution - // - // This is a fixed-point algorithm. We resolve imports until our efforts - // are stymied by an unresolved import; then we bail out of the current - // module and continue. We terminate successfully once no more imports - // remain or unsuccessfully when no forward progress in resolving imports - // is made. - - /** - * Resolves all imports for the crate. This method performs the fixed- - * point iteration. - */ - fn resolve_imports(@mut self) { - let mut i = 0; - let mut prev_unresolved_imports = 0; - loop { - debug!("(resolving imports) iteration %u, %u imports left", - i, self.unresolved_imports); - - let module_root = self.graph_root.get_module(); - self.resolve_imports_for_module_subtree(module_root); - - if self.unresolved_imports == 0 { - debug!("(resolving imports) success"); - break; - } - - if self.unresolved_imports == prev_unresolved_imports { - self.session.err(~"failed to resolve imports"); - self.report_unresolved_imports(module_root); - break; - } - - i += 1; - prev_unresolved_imports = self.unresolved_imports; - } - } - - /// Attempts to resolve imports for the given module and all of its - /// submodules. - fn resolve_imports_for_module_subtree(@mut self, module_: @mut Module) { - debug!("(resolving imports for module subtree) resolving %s", - self.module_to_str(module_)); - self.resolve_imports_for_module(module_); - - for module_.children.each_value |&child_node| { - match child_node.get_module_if_available() { - None => { - // Nothing to do. - } - Some(child_module) => { - self.resolve_imports_for_module_subtree(child_module); - } - } - } - - for module_.anonymous_children.each_value |&child_module| { - self.resolve_imports_for_module_subtree(child_module); - } - } - - /// Attempts to resolve imports for the given module only. - fn resolve_imports_for_module(@mut self, module: @mut Module) { - if module.all_imports_resolved() { - debug!("(resolving imports for module) all imports resolved for \ - %s", - self.module_to_str(module)); - return; - } - - let imports = &mut *module.imports; - let import_count = imports.len(); - while module.resolved_import_count < import_count { - let import_index = module.resolved_import_count; - let import_directive = imports[import_index]; - match self.resolve_import_for_module(module, import_directive) { - Failed => { - // We presumably emitted an error. Continue. - let msg = fmt!("failed to resolve import: %s", - *self.import_path_to_str( - import_directive.module_path, - *import_directive.subclass)); - self.session.span_err(import_directive.span, msg); - } - Indeterminate => { - // Bail out. We'll come around next time. - break; - } - Success(()) => { - // Good. Continue. - } - } - - module.resolved_import_count += 1; - } - } - - fn idents_to_str(@mut self, idents: &[ident]) -> ~str { - let mut first = true; - let mut result = ~""; - for idents.each |ident| { - if first { first = false; } else { result += "::" }; - result += *self.session.str_of(*ident); - }; - return result; - } - - fn import_directive_subclass_to_str(@mut self, - subclass: ImportDirectiveSubclass) - -> @~str { - match subclass { - SingleImport(_target, source) => self.session.str_of(source), - GlobImport => @~"*" - } - } - - fn import_path_to_str(@mut self, - idents: &[ident], - subclass: ImportDirectiveSubclass) - -> @~str { - if idents.is_empty() { - self.import_directive_subclass_to_str(subclass) - } else { - @fmt!("%s::%s", - self.idents_to_str(idents), - *self.import_directive_subclass_to_str(subclass)) - } - } - - /// Attempts to resolve the given import. The return value indicates - /// failure if we're certain the name does not exist, indeterminate if we - /// don't know whether the name exists at the moment due to other - /// currently-unresolved imports, or success if we know the name exists. - /// If successful, the resolved bindings are written into the module. - fn resolve_import_for_module(@mut self, module_: @mut Module, - import_directive: @ImportDirective) - -> ResolveResult<()> { - let mut resolution_result = Failed; - let module_path = &import_directive.module_path; - - debug!("(resolving import for module) resolving import `%s::...` in \ - `%s`", - self.idents_to_str(*module_path), - self.module_to_str(module_)); - - // First, resolve the module path for the directive, if necessary. - let containing_module = if module_path.len() == 0 { - // Use the crate root. - Some(self.graph_root.get_module()) - } else { - match self.resolve_module_path_for_import(module_, - *module_path, - DontUseLexicalScope, - import_directive.span) { - - Failed => None, - Indeterminate => { - resolution_result = Indeterminate; - None - } - Success(containing_module) => Some(containing_module), - } - }; - - match containing_module { - None => {} - Some(containing_module) => { - // We found the module that the target is contained - // within. Attempt to resolve the import within it. - - match *import_directive.subclass { - SingleImport(target, source) => { - resolution_result = - self.resolve_single_import(module_, - containing_module, - target, - source); - } - GlobImport => { - let span = import_directive.span; - let privacy = import_directive.privacy; - resolution_result = - self.resolve_glob_import(privacy, - module_, - containing_module, - span); - } - } - } - } - - // Decrement the count of unresolved imports. - match resolution_result { - Success(()) => { - assert!(self.unresolved_imports >= 1); - self.unresolved_imports -= 1; - } - _ => { - // Nothing to do here; just return the error. - } - } - - // Decrement the count of unresolved globs if necessary. But only if - // the resolution result is indeterminate -- otherwise we'll stop - // processing imports here. (See the loop in - // resolve_imports_for_module.) - - if !resolution_result.indeterminate() { - match *import_directive.subclass { - GlobImport => { - assert!(module_.glob_count >= 1); - module_.glob_count -= 1; - } - SingleImport(*) => { - // Ignore. - } - } - } - - return resolution_result; - } - - fn create_name_bindings_from_module(module: @mut Module) -> NameBindings { - NameBindings { - type_def: Some(TypeNsDef { - privacy: Public, - module_def: Some(module), - type_def: None, - }), - value_def: None, - type_span: None, - value_span: None, - } - } - - fn resolve_single_import(@mut self, - module_: @mut Module, - containing_module: @mut Module, - target: ident, - source: ident) - -> ResolveResult<()> { - debug!("(resolving single import) resolving `%s` = `%s::%s` from \ - `%s`", - *self.session.str_of(target), - self.module_to_str(containing_module), - *self.session.str_of(source), - self.module_to_str(module_)); - - // We need to resolve both namespaces for this to succeed. - // - // FIXME #4949: See if there's some way of handling namespaces in - // a more generic way. We have two of them; it seems worth - // doing... - - let mut value_result = UnknownResult; - let mut type_result = UnknownResult; - - // Search for direct children of the containing module. - match containing_module.children.find(&source) { - None => { - // Continue. - } - Some(child_name_bindings) => { - if child_name_bindings.defined_in_namespace(ValueNS) { - value_result = BoundResult(containing_module, - *child_name_bindings); - } - if child_name_bindings.defined_in_namespace(TypeNS) { - type_result = BoundResult(containing_module, - *child_name_bindings); - } - } - } - - // Unless we managed to find a result in both namespaces (unlikely), - // search imports as well. - match (value_result, type_result) { - (BoundResult(*), BoundResult(*)) => { - // Continue. - } - _ => { - // If there is an unresolved glob at this point in the - // containing module, bail out. We don't know enough to be - // able to resolve this import. - - if containing_module.glob_count > 0 { - debug!("(resolving single import) unresolved glob; \ - bailing out"); - return Indeterminate; - } - - // Now search the exported imports within the containing - // module. - - match containing_module.import_resolutions.find(&source) { - None => { - // The containing module definitely doesn't have an - // exported import with the name in question. We can - // therefore accurately report that the names are - // unbound. - - if value_result.is_unknown() { - value_result = UnboundResult; - } - if type_result.is_unknown() { - type_result = UnboundResult; - } - } - Some(import_resolution) - if import_resolution.outstanding_references - == 0 => { - - fn get_binding(import_resolution: - @mut ImportResolution, - namespace: Namespace) - -> NamespaceResult { - - // Import resolutions must be declared with "pub" - // in order to be exported. - if import_resolution.privacy == Private { - return UnboundResult; - } - - match (*import_resolution). - target_for_namespace(namespace) { - None => { - return UnboundResult; - } - Some(target) => { - import_resolution.state.used = true; - return BoundResult(target.target_module, - target.bindings); - } - } - } - - // The name is an import which has been fully - // resolved. We can, therefore, just follow it. - if value_result.is_unknown() { - value_result = get_binding(*import_resolution, - ValueNS); - } - if type_result.is_unknown() { - type_result = get_binding(*import_resolution, - TypeNS); - } - } - Some(_) => { - // The import is unresolved. Bail out. - debug!("(resolving single import) unresolved import; \ - bailing out"); - return Indeterminate; - } - } - } - } - - // If we didn't find a result in the type namespace, search the - // external modules. - match type_result { - BoundResult(*) => {} - _ => { - match containing_module.external_module_children - .find(&source) { - None => {} // Continue. - Some(module) => { - let name_bindings = - @mut Resolver::create_name_bindings_from_module( - *module); - type_result = BoundResult(containing_module, - name_bindings); - } - } - } - } - - // We've successfully resolved the import. Write the results in. - assert!(module_.import_resolutions.contains_key(&target)); - let import_resolution = module_.import_resolutions.get(&target); - - match value_result { - BoundResult(target_module, name_bindings) => { - import_resolution.value_target = - Some(Target(target_module, name_bindings)); - } - UnboundResult => { /* Continue. */ } - UnknownResult => { - fail!("value result should be known at this point"); - } - } - match type_result { - BoundResult(target_module, name_bindings) => { - import_resolution.type_target = - Some(Target(target_module, name_bindings)); - } - UnboundResult => { /* Continue. */ } - UnknownResult => { - fail!("type result should be known at this point"); - } - } - - let i = import_resolution; - match (i.value_target, i.type_target) { - // If this name wasn't found in either namespace, it's definitely - // unresolved. - (None, None) => { return Failed; } - // If it's private, it's also unresolved. - (Some(t), None) | (None, Some(t)) => { - let bindings = &mut *t.bindings; - match bindings.type_def { - Some(ref type_def) => { - if type_def.privacy == Private { - return Failed; - } - } - _ => () - } - match bindings.value_def { - Some(ref value_def) => { - if value_def.privacy == Private { - return Failed; - } - } - _ => () - } - } - // It's also an error if there's both a type and a value with this - // name, but both are private - (Some(val), Some(ty)) => { - match (val.bindings.value_def, ty.bindings.value_def) { - (Some(ref value_def), Some(ref type_def)) => - if value_def.privacy == Private - && type_def.privacy == Private { - return Failed; - }, - _ => () - } - } - } - - assert!(import_resolution.outstanding_references >= 1); - import_resolution.outstanding_references -= 1; - - debug!("(resolving single import) successfully resolved import"); - return Success(()); - } - - // Resolves a glob import. Note that this function cannot fail; it either - // succeeds or bails out (as importing * from an empty module or a module - // that exports nothing is valid). - fn resolve_glob_import(@mut self, - privacy: Privacy, - module_: @mut Module, - containing_module: @mut Module, - span: span) - -> ResolveResult<()> { - // This function works in a highly imperative manner; it eagerly adds - // everything it can to the list of import resolutions of the module - // node. - debug!("(resolving glob import) resolving %? glob import", privacy); - let state = @mut ImportState(); - - // We must bail out if the node has unresolved imports of any kind - // (including globs). - if !(*containing_module).all_imports_resolved() { - debug!("(resolving glob import) target module has unresolved \ - imports; bailing out"); - return Indeterminate; - } - - assert!(containing_module.glob_count == 0); - - // Add all resolved imports from the containing module. - for containing_module.import_resolutions.each - |ident, target_import_resolution| { - - debug!("(resolving glob import) writing module resolution \ - %? into `%s`", - target_import_resolution.type_target.is_none(), - self.module_to_str(module_)); - - // Here we merge two import resolutions. - match module_.import_resolutions.find(ident) { - None if target_import_resolution.privacy == Public => { - // Simple: just copy the old import resolution. - let new_import_resolution = - @mut ImportResolution(privacy, - target_import_resolution.span, - state); - new_import_resolution.value_target = - copy target_import_resolution.value_target; - new_import_resolution.type_target = - copy target_import_resolution.type_target; - - module_.import_resolutions.insert - (*ident, new_import_resolution); - } - None => { /* continue ... */ } - Some(dest_import_resolution) => { - // Merge the two import resolutions at a finer-grained - // level. - - match target_import_resolution.value_target { - None => { - // Continue. - } - Some(copy value_target) => { - dest_import_resolution.value_target = - Some(value_target); - } - } - match target_import_resolution.type_target { - None => { - // Continue. - } - Some(copy type_target) => { - dest_import_resolution.type_target = - Some(type_target); - } - } - } - } - } - - let merge_import_resolution = |ident, - name_bindings: @mut NameBindings| { - let dest_import_resolution; - match module_.import_resolutions.find(&ident) { - None => { - // Create a new import resolution from this child. - dest_import_resolution = @mut ImportResolution(privacy, - span, - state); - module_.import_resolutions.insert - (ident, dest_import_resolution); - } - Some(existing_import_resolution) => { - dest_import_resolution = *existing_import_resolution; - } - } - - debug!("(resolving glob import) writing resolution `%s` in `%s` \ - to `%s`, privacy=%?", - *self.session.str_of(ident), - self.module_to_str(containing_module), - self.module_to_str(module_), - copy dest_import_resolution.privacy); - - // Merge the child item into the import resolution. - if name_bindings.defined_in_public_namespace(ValueNS) { - debug!("(resolving glob import) ... for value target"); - dest_import_resolution.value_target = - Some(Target(containing_module, name_bindings)); - } - if name_bindings.defined_in_public_namespace(TypeNS) { - debug!("(resolving glob import) ... for type target"); - dest_import_resolution.type_target = - Some(Target(containing_module, name_bindings)); - } - }; - - // Add all children from the containing module. - for containing_module.children.each |&ident, name_bindings| { - merge_import_resolution(ident, *name_bindings); - } - - // Add external module children from the containing module. - for containing_module.external_module_children.each - |&ident, module| { - let name_bindings = - @mut Resolver::create_name_bindings_from_module(*module); - merge_import_resolution(ident, name_bindings); - } - - debug!("(resolving glob import) successfully resolved import"); - return Success(()); - } - - /// Resolves the given module path from the given root `module_`. - fn resolve_module_path_from_root(@mut self, - module_: @mut Module, - module_path: &[ident], - index: uint, - span: span, - mut name_search_type: NameSearchType) - -> ResolveResult<@mut Module> { - let mut search_module = module_; - let mut index = index; - let module_path_len = module_path.len(); - - // Resolve the module part of the path. This does not involve looking - // upward though scope chains; we simply resolve names directly in - // modules as we go. - - while index < module_path_len { - let name = module_path[index]; - match self.resolve_name_in_module(search_module, - name, - TypeNS, - name_search_type) { - Failed => { - self.session.span_err(span, ~"unresolved name"); - return Failed; - } - Indeterminate => { - debug!("(resolving module path for import) module \ - resolution is indeterminate: %s", - *self.session.str_of(name)); - return Indeterminate; - } - Success(target) => { - // Check to see whether there are type bindings, and, if - // so, whether there is a module within. - match target.bindings.type_def { - Some(copy type_def) => { - match type_def.module_def { - None => { - // Not a module. - self.session.span_err(span, - fmt!("not a \ - module: %s", - *self.session. - str_of( - name))); - return Failed; - } - Some(copy module_def) => { - search_module = module_def; - } - } - } - None => { - // There are no type bindings at all. - self.session.span_err(span, - fmt!("not a module: %s", - *self.session.str_of( - name))); - return Failed; - } - } - } - } - - index += 1; - - // After the first element of the path, allow searching through - // items and imports unconditionally. This allows things like: - // - // pub mod core { - // pub use vec; - // } - // - // pub mod something_else { - // use core::vec; - // } - - name_search_type = SearchItemsAndPublicImports; - } - - return Success(search_module); - } - - /// Attempts to resolve the module part of an import directive or path - /// rooted at the given module. - fn resolve_module_path_for_import(@mut self, - module_: @mut Module, - module_path: &[ident], - use_lexical_scope: UseLexicalScopeFlag, - span: span) - -> ResolveResult<@mut Module> { - let module_path_len = module_path.len(); - assert!(module_path_len > 0); - - debug!("(resolving module path for import) processing `%s` rooted at \ - `%s`", - self.idents_to_str(module_path), - self.module_to_str(module_)); - - // Resolve the module prefix, if any. - let module_prefix_result = self.resolve_module_prefix(module_, - module_path); - - let search_module; - let start_index; - match module_prefix_result { - Failed => { - self.session.span_err(span, ~"unresolved name"); - return Failed; - } - Indeterminate => { - debug!("(resolving module path for import) indeterminate; \ - bailing"); - return Indeterminate; - } - Success(NoPrefixFound) => { - // There was no prefix, so we're considering the first element - // of the path. How we handle this depends on whether we were - // instructed to use lexical scope or not. - match use_lexical_scope { - DontUseLexicalScope => { - // This is a crate-relative path. We will start the - // resolution process at index zero. - search_module = self.graph_root.get_module(); - start_index = 0; - } - UseLexicalScope => { - // This is not a crate-relative path. We resolve the - // first component of the path in the current lexical - // scope and then proceed to resolve below that. - let result = self.resolve_module_in_lexical_scope( - module_, - module_path[0]); - match result { - Failed => { - self.session.span_err(span, - ~"unresolved name"); - return Failed; - } - Indeterminate => { - debug!("(resolving module path for import) \ - indeterminate; bailing"); - return Indeterminate; - } - Success(containing_module) => { - search_module = containing_module; - start_index = 1; - } - } - } - } - } - Success(PrefixFound(containing_module, index)) => { - search_module = containing_module; - start_index = index; - } - } - - self.resolve_module_path_from_root(search_module, - module_path, - start_index, - span, - SearchItemsAndPublicImports) - } - - /// Invariant: This must only be called during main resolution, not during - /// import resolution. - fn resolve_item_in_lexical_scope(@mut self, - module_: @mut Module, - name: ident, - namespace: Namespace, - search_through_modules: - SearchThroughModulesFlag) - -> ResolveResult { - debug!("(resolving item in lexical scope) resolving `%s` in \ - namespace %? in `%s`", - *self.session.str_of(name), - namespace, - self.module_to_str(module_)); - - // The current module node is handled specially. First, check for - // its immediate children. - match module_.children.find(&name) { - Some(name_bindings) - if name_bindings.defined_in_namespace(namespace) => { - return Success(Target(module_, *name_bindings)); - } - Some(_) | None => { /* Not found; continue. */ } - } - - // Now check for its import directives. We don't have to have resolved - // all its imports in the usual way; this is because chains of - // adjacent import statements are processed as though they mutated the - // current scope. - match module_.import_resolutions.find(&name) { - None => { - // Not found; continue. - } - Some(import_resolution) => { - match (*import_resolution).target_for_namespace(namespace) { - None => { - // Not found; continue. - debug!("(resolving item in lexical scope) found \ - import resolution, but not in namespace %?", - namespace); - } - Some(target) => { - debug!("(resolving item in lexical scope) using \ - import resolution"); - import_resolution.state.used = true; - return Success(copy target); - } - } - } - } - - // Search for external modules. - if namespace == TypeNS { - match module_.external_module_children.find(&name) { - None => {} - Some(module) => { - let name_bindings = - @mut Resolver::create_name_bindings_from_module( - *module); - return Success(Target(module_, name_bindings)); - } - } - } - - // Finally, proceed up the scope chain looking for parent modules. - let mut search_module = module_; - loop { - // Go to the next parent. - match search_module.parent_link { - NoParentLink => { - // No more parents. This module was unresolved. - debug!("(resolving item in lexical scope) unresolved \ - module"); - return Failed; - } - ModuleParentLink(parent_module_node, _) => { - match search_through_modules { - DontSearchThroughModules => { - match search_module.kind { - NormalModuleKind => { - // We stop the search here. - debug!("(resolving item in lexical \ - scope) unresolved module: not \ - searching through module \ - parents"); - return Failed; - } - ExternModuleKind | - TraitModuleKind | - AnonymousModuleKind => { - search_module = parent_module_node; - } - } - } - SearchThroughModules => { - search_module = parent_module_node; - } - } - } - BlockParentLink(parent_module_node, _) => { - search_module = parent_module_node; - } - } - - // Resolve the name in the parent module. - match self.resolve_name_in_module(search_module, - name, - namespace, - SearchItemsAndAllImports) { - Failed => { - // Continue up the search chain. - } - Indeterminate => { - // We couldn't see through the higher scope because of an - // unresolved import higher up. Bail. - - debug!("(resolving item in lexical scope) indeterminate \ - higher scope; bailing"); - return Indeterminate; - } - Success(target) => { - // We found the module. - return Success(copy target); - } - } - } - } - - /** Resolves a module name in the current lexical scope. */ - fn resolve_module_in_lexical_scope(@mut self, - module_: @mut Module, - name: ident) - -> ResolveResult<@mut Module> { - // If this module is an anonymous module, resolve the item in the - // lexical scope. Otherwise, resolve the item from the crate root. - let resolve_result = self.resolve_item_in_lexical_scope( - module_, name, TypeNS, DontSearchThroughModules); - match resolve_result { - Success(target) => { - let bindings = &mut *target.bindings; - match bindings.type_def { - Some(ref type_def) => { - match (*type_def).module_def { - None => { - error!("!!! (resolving module in lexical \ - scope) module wasn't actually a \ - module!"); - return Failed; - } - Some(module_def) => { - return Success(module_def); - } - } - } - None => { - error!("!!! (resolving module in lexical scope) module - wasn't actually a module!"); - return Failed; - } - } - } - Indeterminate => { - debug!("(resolving module in lexical scope) indeterminate; \ - bailing"); - return Indeterminate; - } - Failed => { - debug!("(resolving module in lexical scope) failed to \ - resolve"); - return Failed; - } - } - } - - /** - * Returns the nearest normal module parent of the given module. - */ - fn get_nearest_normal_module_parent(@mut self, module_: @mut Module) - -> Option<@mut Module> { - let mut module_ = module_; - loop { - match module_.parent_link { - NoParentLink => return None, - ModuleParentLink(new_module, _) | - BlockParentLink(new_module, _) => { - match new_module.kind { - NormalModuleKind => return Some(new_module), - ExternModuleKind | - TraitModuleKind | - AnonymousModuleKind => module_ = new_module, - } - } - } - } - } - - /** - * Returns the nearest normal module parent of the given module, or the - * module itself if it is a normal module. - */ - fn get_nearest_normal_module_parent_or_self(@mut self, - module_: @mut Module) - -> @mut Module { - match module_.kind { - NormalModuleKind => return module_, - ExternModuleKind | TraitModuleKind | AnonymousModuleKind => { - match self.get_nearest_normal_module_parent(module_) { - None => module_, - Some(new_module) => new_module - } - } - } - } - - /** - * Resolves a "module prefix". A module prefix is one of (a) `self::`; - * (b) some chain of `super::`. - */ - fn resolve_module_prefix(@mut self, - module_: @mut Module, - module_path: &[ident]) - -> ResolveResult { - let interner = self.session.parse_sess.interner; - - // Start at the current module if we see `self` or `super`, or at the - // top of the crate otherwise. - let mut containing_module; - let mut i; - if *interner.get(module_path[0]) == ~"self" { - containing_module = - self.get_nearest_normal_module_parent_or_self(module_); - i = 1; - } else if *interner.get(module_path[0]) == ~"super" { - containing_module = - self.get_nearest_normal_module_parent_or_self(module_); - i = 0; // We'll handle `super` below. - } else { - return Success(NoPrefixFound); - } - - // Now loop through all the `super`s we find. - while i < module_path.len() && - *interner.get(module_path[i]) == ~"super" { - debug!("(resolving module prefix) resolving `super` at %s", - self.module_to_str(containing_module)); - match self.get_nearest_normal_module_parent(containing_module) { - None => return Failed, - Some(new_module) => { - containing_module = new_module; - i += 1; - } - } - } - - debug!("(resolving module prefix) finished resolving prefix at %s", - self.module_to_str(containing_module)); - - return Success(PrefixFound(containing_module, i)); - } - - /// Attempts to resolve the supplied name in the given module for the - /// given namespace. If successful, returns the target corresponding to - /// the name. - fn resolve_name_in_module(@mut self, - module_: @mut Module, - name: ident, - namespace: Namespace, - name_search_type: NameSearchType) - -> ResolveResult { - debug!("(resolving name in module) resolving `%s` in `%s`", - *self.session.str_of(name), - self.module_to_str(module_)); - - // First, check the direct children of the module. - match module_.children.find(&name) { - Some(name_bindings) - if name_bindings.defined_in_namespace(namespace) => { - debug!("(resolving name in module) found node as child"); - return Success(Target(module_, *name_bindings)); - } - Some(_) | None => { - // Continue. - } - } - - // Next, check the module's imports if necessary. - - // If this is a search of all imports, we should be done with glob - // resolution at this point. - if name_search_type == SearchItemsAndAllImports { - assert!(module_.glob_count == 0); - } - - // Check the list of resolved imports. - match module_.import_resolutions.find(&name) { - Some(import_resolution) => { - if import_resolution.privacy == Public && - import_resolution.outstanding_references != 0 { - debug!("(resolving name in module) import \ - unresolved; bailing out"); - return Indeterminate; - } - - match import_resolution.target_for_namespace(namespace) { - None => { - debug!("(resolving name in module) name found, \ - but not in namespace %?", - namespace); - } - Some(target) - if name_search_type == - SearchItemsAndAllImports || - import_resolution.privacy == Public => { - debug!("(resolving name in module) resolved to \ - import"); - import_resolution.state.used = true; - return Success(copy target); - } - Some(_) => { - debug!("(resolving name in module) name found, \ - but not public"); - } - } - } - None => {} // Continue. - } - - // Finally, search through external children. - if namespace == TypeNS { - match module_.external_module_children.find(&name) { - None => {} - Some(module) => { - let name_bindings = - @mut Resolver::create_name_bindings_from_module( - *module); - return Success(Target(module_, name_bindings)); - } - } - } - - // We're out of luck. - debug!("(resolving name in module) failed to resolve %s", - *self.session.str_of(name)); - return Failed; - } - - fn report_unresolved_imports(@mut self, module_: @mut Module) { - let index = module_.resolved_import_count; - let imports: &mut ~[@ImportDirective] = &mut *module_.imports; - let import_count = imports.len(); - if index != import_count { - let sn = self.session.codemap.span_to_snippet(imports[index].span); - if str::contains(sn, "::") { - self.session.span_err(imports[index].span, ~"unresolved import"); - } else { - let err = fmt!("unresolved import (maybe you meant `%s::*`?)", - sn.slice(0, sn.len() - 1)); // -1 to adjust for semicolon - self.session.span_err(imports[index].span, err); - } - } - - // Descend into children and anonymous children. - for module_.children.each_value |&child_node| { - match child_node.get_module_if_available() { - None => { - // Continue. - } - Some(child_module) => { - self.report_unresolved_imports(child_module); - } - } - } - - for module_.anonymous_children.each_value |&module_| { - self.report_unresolved_imports(module_); - } - } - - // Export recording - // - // This pass simply determines what all "export" keywords refer to and - // writes the results into the export map. - // - // FIXME #4953 This pass will be removed once exports change to per-item. - // Then this operation can simply be performed as part of item (or import) - // processing. - - fn record_exports(@mut self) { - let root_module = self.graph_root.get_module(); - self.record_exports_for_module_subtree(root_module); - } - - fn record_exports_for_module_subtree(@mut self, module_: @mut Module) { - // If this isn't a local crate, then bail out. We don't need to record - // exports for nonlocal crates. - - match module_.def_id { - Some(def_id) if def_id.crate == local_crate => { - // OK. Continue. - debug!("(recording exports for module subtree) recording \ - exports for local module"); - } - None => { - // Record exports for the root module. - debug!("(recording exports for module subtree) recording \ - exports for root module"); - } - Some(_) => { - // Bail out. - debug!("(recording exports for module subtree) not recording \ - exports for `%s`", - self.module_to_str(module_)); - return; - } - } - - self.record_exports_for_module(module_); - - for module_.children.each_value |&child_name_bindings| { - match child_name_bindings.get_module_if_available() { - None => { - // Nothing to do. - } - Some(child_module) => { - self.record_exports_for_module_subtree(child_module); - } - } - } - - for module_.anonymous_children.each_value |&child_module| { - self.record_exports_for_module_subtree(child_module); - } - } - - fn record_exports_for_module(@mut self, module_: @mut Module) { - let mut exports2 = ~[]; - - self.add_exports_for_module(&mut exports2, module_); - match /*bad*/copy module_.def_id { - Some(def_id) => { - self.export_map2.insert(def_id.node, exports2); - debug!("(computing exports) writing exports for %d (some)", - def_id.node); - } - None => {} - } - } - - fn add_exports_of_namebindings(@mut self, - exports2: &mut ~[Export2], - ident: ident, - namebindings: @mut NameBindings, - ns: Namespace, - reexport: bool) { - match (namebindings.def_for_namespace(ns), - namebindings.privacy_for_namespace(ns)) { - (Some(d), Some(Public)) => { - debug!("(computing exports) YES: %s '%s' => %?", - if reexport { ~"reexport" } else { ~"export"}, - *self.session.str_of(ident), - def_id_of_def(d)); - exports2.push(Export2 { - reexport: reexport, - name: self.session.str_of(ident), - def_id: def_id_of_def(d) - }); - } - (Some(_), Some(privacy)) => { - debug!("(computing reexports) NO: privacy %?", privacy); - } - (d_opt, p_opt) => { - debug!("(computing reexports) NO: %?, %?", d_opt, p_opt); - } - } - } - - fn add_exports_for_module(@mut self, - exports2: &mut ~[Export2], - module_: @mut Module) { - for module_.children.each |ident, namebindings| { - debug!("(computing exports) maybe export '%s'", - *self.session.str_of(*ident)); - self.add_exports_of_namebindings(&mut *exports2, - *ident, - *namebindings, - TypeNS, - false); - self.add_exports_of_namebindings(&mut *exports2, - *ident, - *namebindings, - ValueNS, - false); - } - - for module_.import_resolutions.each |ident, importresolution| { - if importresolution.privacy != Public { - debug!("(computing exports) not reexporting private `%s`", - *self.session.str_of(*ident)); - loop; - } - for [ TypeNS, ValueNS ].each |ns| { - match importresolution.target_for_namespace(*ns) { - Some(target) => { - debug!("(computing exports) maybe reexport '%s'", - *self.session.str_of(*ident)); - self.add_exports_of_namebindings(&mut *exports2, - *ident, - target.bindings, - *ns, - true) - } - _ => () - } - } - } - } - - // AST resolution - // - // We maintain a list of value ribs and type ribs. - // - // Simultaneously, we keep track of the current position in the module - // graph in the `current_module` pointer. When we go to resolve a name in - // the value or type namespaces, we first look through all the ribs and - // then query the module graph. When we resolve a name in the module - // namespace, we can skip all the ribs (since nested modules are not - // allowed within blocks in Rust) and jump straight to the current module - // graph node. - // - // Named implementations are handled separately. When we find a method - // call, we consult the module node to find all of the implementations in - // scope. This information is lazily cached in the module node. We then - // generate a fake "implementation scope" containing all the - // implementations thus found, for compatibility with old resolve pass. - - fn with_scope(@mut self, name: Option, f: &fn()) { - let orig_module = self.current_module; - - // Move down in the graph. - match name { - None => { - // Nothing to do. - } - Some(name) => { - match orig_module.children.find(&name) { - None => { - debug!("!!! (with scope) didn't find `%s` in `%s`", - *self.session.str_of(name), - self.module_to_str(orig_module)); - } - Some(name_bindings) => { - match (*name_bindings).get_module_if_available() { - None => { - debug!("!!! (with scope) didn't find module \ - for `%s` in `%s`", - *self.session.str_of(name), - self.module_to_str(orig_module)); - } - Some(module_) => { - self.current_module = module_; - } - } - } - } - } - } - - f(); - - self.current_module = orig_module; - } - - // Wraps the given definition in the appropriate number of `def_upvar` - // wrappers. - - fn upvarify(@mut self, - ribs: &mut ~[@Rib], - rib_index: uint, - def_like: def_like, - span: span, - allow_capturing_self: AllowCapturingSelfFlag) - -> Option { - let mut def; - let is_ty_param; - - match def_like { - dl_def(d @ def_local(*)) | dl_def(d @ def_upvar(*)) | - dl_def(d @ def_arg(*)) | dl_def(d @ def_binding(*)) => { - def = d; - is_ty_param = false; - } - dl_def(d @ def_ty_param(*)) => { - def = d; - is_ty_param = true; - } - dl_def(d @ def_self(*)) - if allow_capturing_self == DontAllowCapturingSelf => { - def = d; - is_ty_param = false; - } - _ => { - return Some(def_like); - } - } - - let mut rib_index = rib_index + 1; - while rib_index < ribs.len() { - match ribs[rib_index].kind { - NormalRibKind => { - // Nothing to do. Continue. - } - FunctionRibKind(function_id, body_id) => { - if !is_ty_param { - def = def_upvar(def_id_of_def(def).node, - @def, - function_id, - body_id); - } - } - MethodRibKind(item_id, _) => { - // If the def is a ty param, and came from the parent - // item, it's ok - match def { - def_ty_param(did, _) - if self.def_map.find(&did.node).map_consume(|x| *x) - == Some(def_typaram_binder(item_id)) => { - // ok - } - _ => { - if !is_ty_param { - // This was an attempt to access an upvar inside a - // named function item. This is not allowed, so we - // report an error. - - self.session.span_err( - span, - ~"attempted dynamic environment-capture"); - } else { - // This was an attempt to use a type parameter outside - // its scope. - - self.session.span_err(span, - ~"attempt to use a type \ - argument out of scope"); - } - - return None; - } - } - } - OpaqueFunctionRibKind => { - if !is_ty_param { - // This was an attempt to access an upvar inside a - // named function item. This is not allowed, so we - // report an error. - - self.session.span_err( - span, - ~"attempted dynamic environment-capture"); - } else { - // This was an attempt to use a type parameter outside - // its scope. - - self.session.span_err(span, - ~"attempt to use a type \ - argument out of scope"); - } - - return None; - } - ConstantItemRibKind => { - // Still doesn't deal with upvars - self.session.span_err(span, - ~"attempt to use a non-constant \ - value in a constant"); - - } - } - - rib_index += 1; - } - - return Some(dl_def(def)); - } - - fn search_ribs(@mut self, - ribs: &mut ~[@Rib], - name: ident, - span: span, - allow_capturing_self: AllowCapturingSelfFlag) - -> Option { - // FIXME #4950: This should not use a while loop. - // FIXME #4950: Try caching? - - let mut i = ribs.len(); - while i != 0 { - i -= 1; - match ribs[i].bindings.find(&name) { - Some(&def_like) => { - return self.upvarify(ribs, i, def_like, span, - allow_capturing_self); - } - None => { - // Continue. - } - } - } - - return None; - } - - fn resolve_crate(@mut self) { - debug!("(resolving crate) starting"); - - visit_crate(self.crate, (), mk_vt(@Visitor { - visit_item: |item, _context, visitor| - self.resolve_item(item, visitor), - visit_arm: |arm, _context, visitor| - self.resolve_arm(arm, visitor), - visit_block: |block, _context, visitor| - self.resolve_block(block, visitor), - visit_expr: |expr, _context, visitor| - self.resolve_expr(expr, visitor), - visit_local: |local, _context, visitor| - self.resolve_local(local, visitor), - visit_ty: |ty, _context, visitor| - self.resolve_type(ty, visitor), - .. *default_visitor() - })); - } - - fn resolve_item(@mut self, item: @item, visitor: ResolveVisitor) { - debug!("(resolving item) resolving %s", - *self.session.str_of(item.ident)); - - // Items with the !resolve_unexported attribute are X-ray contexts. - // This is used to allow the test runner to run unexported tests. - let orig_xray_flag = self.xray_context; - if contains_name(attr_metas(item.attrs), - ~"!resolve_unexported") { - self.xray_context = Xray; - } - - match item.node { - - // enum item: resolve all the variants' discrs, - // then resolve the ty params - item_enum(ref enum_def, ref generics) => { - for (*enum_def).variants.each() |variant| { - for variant.node.disr_expr.each |dis_expr| { - // resolve the discriminator expr - // as a constant - self.with_constant_rib(|| { - self.resolve_expr(*dis_expr, visitor); - }); - } - } - - // n.b. the discr expr gets visted twice. - // but maybe it's okay since the first time will signal an - // error if there is one? -- tjc - do self.with_type_parameter_rib( - HasTypeParameters( - generics, item.id, 0, NormalRibKind)) { - visit_item(item, (), visitor); - } - } - - item_ty(_, ref generics) => { - do self.with_type_parameter_rib - (HasTypeParameters(generics, item.id, 0, - NormalRibKind)) - || { - - visit_item(item, (), visitor); - } - } - - item_impl(ref generics, - implemented_traits, - self_type, - ref methods) => { - self.resolve_implementation(item.id, - generics, - implemented_traits, - self_type, - *methods, - visitor); - } - - item_trait(ref generics, ref traits, ref methods) => { - // Create a new rib for the self type. - let self_type_rib = @Rib(NormalRibKind); - self.type_ribs.push(self_type_rib); - self_type_rib.bindings.insert(self.type_self_ident, - dl_def(def_self_ty(item.id))); - - // Create a new rib for the trait-wide type parameters. - do self.with_type_parameter_rib - (HasTypeParameters(generics, item.id, 0, - NormalRibKind)) { - - self.resolve_type_parameters(&generics.ty_params, - visitor); - - // Resolve derived traits. - for traits.each |trt| { - match self.resolve_path(trt.path, TypeNS, true, - visitor) { - None => - self.session.span_err(trt.path.span, - ~"attempt to derive a \ - nonexistent trait"), - Some(def) => { - // Write a mapping from the trait ID to the - // definition of the trait into the definition - // map. - - debug!("(resolving trait) found trait def: \ - %?", def); - - self.record_def(trt.ref_id, def); - } - } - } - - for (*methods).each |method| { - // Create a new rib for the method-specific type - // parameters. - // - // FIXME #4951: Do we need a node ID here? - - match *method { - required(ref ty_m) => { - do self.with_type_parameter_rib - (HasTypeParameters(&ty_m.generics, - item.id, - generics.ty_params.len(), - MethodRibKind(item.id, Required))) { - - // Resolve the method-specific type - // parameters. - self.resolve_type_parameters( - &ty_m.generics.ty_params, - visitor); - - for ty_m.decl.inputs.each |argument| { - self.resolve_type(argument.ty, visitor); - } - - self.resolve_type(ty_m.decl.output, visitor); - } - } - provided(m) => { - self.resolve_method(MethodRibKind(item.id, - Provided(m.id)), - m, - generics.ty_params.len(), - visitor) - } - } - } - } - - self.type_ribs.pop(); - } - - item_struct(ref struct_def, ref generics) => { - self.resolve_struct(item.id, - generics, - struct_def.fields, - visitor); - } - - item_mod(ref module_) => { - do self.with_scope(Some(item.ident)) { - self.resolve_module(module_, item.span, item.ident, - item.id, visitor); - } - } - - item_foreign_mod(ref foreign_module) => { - do self.with_scope(Some(item.ident)) { - for foreign_module.items.each |foreign_item| { - match foreign_item.node { - foreign_item_fn(_, _, ref generics) => { - self.with_type_parameter_rib( - HasTypeParameters( - generics, foreign_item.id, 0, - NormalRibKind), - || visit_foreign_item(*foreign_item, (), - visitor)); - } - foreign_item_const(_) => { - visit_foreign_item(*foreign_item, (), - visitor); - } - } - } - } - } - - item_fn(ref fn_decl, _, _, ref generics, ref block) => { - // If this is the main function, we must record it in the - // session. - - // FIXME #4404 android JNI hacks - if !*self.session.building_library || - self.session.targ_cfg.os == session::os_android { - - if self.attr_main_fn.is_none() && - item.ident == special_idents::main { - - self.main_fns.push(Some((item.id, item.span))); - } - - if attrs_contains_name(item.attrs, ~"main") { - if self.attr_main_fn.is_none() { - self.attr_main_fn = Some((item.id, item.span)); - } else { - self.session.span_err( - item.span, - ~"multiple 'main' functions"); - } - } - - if attrs_contains_name(item.attrs, ~"start") { - if self.start_fn.is_none() { - self.start_fn = Some((item.id, item.span)); - } else { - self.session.span_err( - item.span, - ~"multiple 'start' functions"); - } - } - } - - self.resolve_function(OpaqueFunctionRibKind, - Some(fn_decl), - HasTypeParameters - (generics, - item.id, - 0, - OpaqueFunctionRibKind), - block, - NoSelfBinding, - visitor); - } - - item_const(*) => { - self.with_constant_rib(|| { - visit_item(item, (), visitor); - }); - } - - item_mac(*) => { - fail!("item macros unimplemented") - } - } - - self.xray_context = orig_xray_flag; - } - - fn with_type_parameter_rib(@mut self, - type_parameters: TypeParameters, - f: &fn()) { - match type_parameters { - HasTypeParameters(generics, node_id, initial_index, - rib_kind) => { - - let function_type_rib = @Rib(rib_kind); - self.type_ribs.push(function_type_rib); - - for generics.ty_params.eachi |index, type_parameter| { - let name = type_parameter.ident; - debug!("with_type_parameter_rib: %d %d", node_id, - type_parameter.id); - let def_like = dl_def(def_ty_param - (local_def(type_parameter.id), - index + initial_index)); - // Associate this type parameter with - // the item that bound it - self.record_def(type_parameter.id, - def_typaram_binder(node_id)); - function_type_rib.bindings.insert(name, def_like); - } - } - - NoTypeParameters => { - // Nothing to do. - } - } - - f(); - - match type_parameters { - HasTypeParameters(*) => { - self.type_ribs.pop(); - } - - NoTypeParameters => { - // Nothing to do. - } - } - } - - fn with_label_rib(@mut self, f: &fn()) { - self.label_ribs.push(@Rib(NormalRibKind)); - f(); - self.label_ribs.pop(); - } - - fn with_constant_rib(@mut self, f: &fn()) { - self.value_ribs.push(@Rib(ConstantItemRibKind)); - f(); - self.value_ribs.pop(); - } - - fn resolve_function(@mut self, - rib_kind: RibKind, - optional_declaration: Option<&fn_decl>, - type_parameters: TypeParameters, - block: &blk, - self_binding: SelfBinding, - visitor: ResolveVisitor) { - // Create a value rib for the function. - let function_value_rib = @Rib(rib_kind); - self.value_ribs.push(function_value_rib); - - // Create a label rib for the function. - let function_label_rib = @Rib(rib_kind); - self.label_ribs.push(function_label_rib); - - // If this function has type parameters, add them now. - do self.with_type_parameter_rib(type_parameters) { - // Resolve the type parameters. - match type_parameters { - NoTypeParameters => { - // Continue. - } - HasTypeParameters(ref generics, _, _, _) => { - self.resolve_type_parameters(&generics.ty_params, - visitor); - } - } - - // Add self to the rib, if necessary. - match self_binding { - NoSelfBinding => { - // Nothing to do. - } - HasSelfBinding(self_node_id, is_implicit) => { - let def_like = dl_def(def_self(self_node_id, - is_implicit)); - *function_value_rib.self_binding = Some(def_like); - } - } - - // Add each argument to the rib. - match optional_declaration { - None => { - // Nothing to do. - } - Some(declaration) => { - for declaration.inputs.each |argument| { - let binding_mode = ArgumentIrrefutableMode; - let mutability = - if argument.is_mutbl {Mutable} else {Immutable}; - self.resolve_pattern(argument.pat, - binding_mode, - mutability, - None, - visitor); - - self.resolve_type(argument.ty, visitor); - - debug!("(resolving function) recorded argument"); - } - - self.resolve_type(declaration.output, visitor); - } - } - - // Resolve the function body. - self.resolve_block(block, visitor); - - debug!("(resolving function) leaving function"); - } - - self.label_ribs.pop(); - self.value_ribs.pop(); - } - - fn resolve_type_parameters(@mut self, - type_parameters: &OptVec, - visitor: ResolveVisitor) { - for type_parameters.each |type_parameter| { - for type_parameter.bounds.each |&bound| { - match bound { - TraitTyParamBound(tref) => { - self.resolve_trait_reference(tref, visitor) - } - RegionTyParamBound => {} - } - } - } - } - - fn resolve_trait_reference(@mut self, - trait_reference: &trait_ref, - visitor: ResolveVisitor) { - match self.resolve_path(trait_reference.path, TypeNS, true, visitor) { - None => { - self.session.span_err(trait_reference.path.span, - ~"attempt to implement an \ - unknown trait"); - } - Some(def) => { - self.record_def(trait_reference.ref_id, def); - } - } - } - - fn resolve_struct(@mut self, - id: node_id, - generics: &Generics, - fields: &[@struct_field], - visitor: ResolveVisitor) { - // If applicable, create a rib for the type parameters. - do self.with_type_parameter_rib(HasTypeParameters - (generics, id, 0, - OpaqueFunctionRibKind)) { - - // Resolve the type parameters. - self.resolve_type_parameters(&generics.ty_params, visitor); - - // Resolve fields. - for fields.each |field| { - self.resolve_type(field.node.ty, visitor); - } - } - } - - // Does this really need to take a RibKind or is it always going - // to be NormalRibKind? - fn resolve_method(@mut self, - rib_kind: RibKind, - method: @method, - outer_type_parameter_count: uint, - visitor: ResolveVisitor) { - let method_generics = &method.generics; - let type_parameters = - HasTypeParameters(method_generics, - method.id, - outer_type_parameter_count, - rib_kind); - // we only have self ty if it is a non static method - let self_binding = match method.explicit_self.node { - sty_static => { NoSelfBinding } - _ => { HasSelfBinding(method.self_id, false) } - }; - - self.resolve_function(rib_kind, - Some(&method.decl), - type_parameters, - &method.body, - self_binding, - visitor); - } - - fn resolve_implementation(@mut self, - id: node_id, - generics: &Generics, - opt_trait_reference: Option<@trait_ref>, - self_type: @Ty, - methods: &[@method], - visitor: ResolveVisitor) { - // If applicable, create a rib for the type parameters. - let outer_type_parameter_count = generics.ty_params.len(); - do self.with_type_parameter_rib(HasTypeParameters - (generics, id, 0, - NormalRibKind)) { - // Resolve the type parameters. - self.resolve_type_parameters(&generics.ty_params, - visitor); - - // Resolve the trait reference, if necessary. - let original_trait_refs; - match opt_trait_reference { - Some(trait_reference) => { - self.resolve_trait_reference(trait_reference, visitor); - - // Record the current set of trait references. - let mut new_trait_refs = ~[]; - for self.def_map.find(&trait_reference.ref_id).each |&def| { - new_trait_refs.push(def_id_of_def(*def)); - } - original_trait_refs = Some(util::replace( - &mut self.current_trait_refs, - Some(new_trait_refs))); - } - None => { - original_trait_refs = None; - } - } - - // Resolve the self type. - self.resolve_type(self_type, visitor); - - for methods.each |method| { - // We also need a new scope for the method-specific - // type parameters. - self.resolve_method(MethodRibKind( - id, - Provided(method.id)), - *method, - outer_type_parameter_count, - visitor); -/* - let borrowed_type_parameters = &method.tps; - self.resolve_function(MethodRibKind( - id, - Provided(method.id)), - Some(@method.decl), - HasTypeParameters - (borrowed_type_parameters, - method.id, - outer_type_parameter_count, - NormalRibKind), - method.body, - HasSelfBinding(method.self_id), - visitor); -*/ - } - - // Restore the original trait references. - match original_trait_refs { - Some(r) => { self.current_trait_refs = r; } - None => () - } - } - } - - fn resolve_module(@mut self, - module_: &_mod, - span: span, - _name: ident, - id: node_id, - visitor: ResolveVisitor) { - // Write the implementations in scope into the module metadata. - debug!("(resolving module) resolving module ID %d", id); - visit_mod(module_, span, id, (), visitor); - } - - fn resolve_local(@mut self, local: @local, visitor: ResolveVisitor) { - let mutability = if local.node.is_mutbl {Mutable} else {Immutable}; - - // Resolve the type. - self.resolve_type(local.node.ty, visitor); - - // Resolve the initializer, if necessary. - match local.node.init { - None => { - // Nothing to do. - } - Some(initializer) => { - self.resolve_expr(initializer, visitor); - } - } - - // Resolve the pattern. - self.resolve_pattern(local.node.pat, LocalIrrefutableMode, mutability, - None, visitor); - } - - fn binding_mode_map(@mut self, pat: @pat) -> BindingMap { - let mut result = HashMap::new(); - do pat_bindings(self.def_map, pat) |binding_mode, _id, sp, path| { - let ident = path_to_ident(path); - result.insert(ident, - binding_info {span: sp, - binding_mode: binding_mode}); - } - return result; - } - - fn check_consistent_bindings(@mut self, arm: &arm) { - if arm.pats.len() == 0 { return; } - let map_0 = self.binding_mode_map(arm.pats[0]); - for arm.pats.eachi() |i, p| { - let map_i = self.binding_mode_map(*p); - - for map_0.each |&key, &binding_0| { - match map_i.find(&key) { - None => { - self.session.span_err( - p.span, - fmt!("variable `%s` from pattern #1 is \ - not bound in pattern #%u", - *self.session.str_of(key), i + 1)); - } - Some(binding_i) => { - if binding_0.binding_mode != binding_i.binding_mode { - self.session.span_err( - binding_i.span, - fmt!("variable `%s` is bound with different \ - mode in pattern #%u than in pattern #1", - *self.session.str_of(key), i + 1)); - } - } - } - } - - for map_i.each |&key, &binding| { - if !map_0.contains_key(&key) { - self.session.span_err( - binding.span, - fmt!("variable `%s` from pattern #%u is \ - not bound in pattern #1", - *self.session.str_of(key), i + 1)); - } - } - } - } - - fn resolve_arm(@mut self, arm: &arm, visitor: ResolveVisitor) { - self.value_ribs.push(@Rib(NormalRibKind)); - - let bindings_list = @mut HashMap::new(); - for arm.pats.each |pattern| { - self.resolve_pattern(*pattern, RefutableMode, Immutable, - Some(bindings_list), visitor); - } - - // This has to happen *after* we determine which - // pat_idents are variants - self.check_consistent_bindings(arm); - - visit_expr_opt(arm.guard, (), visitor); - self.resolve_block(&arm.body, visitor); - - self.value_ribs.pop(); - } - - fn resolve_block(@mut self, block: &blk, visitor: ResolveVisitor) { - debug!("(resolving block) entering block"); - self.value_ribs.push(@Rib(NormalRibKind)); - - // Move down in the graph, if there's an anonymous module rooted here. - let orig_module = self.current_module; - match self.current_module.anonymous_children.find(&block.node.id) { - None => { /* Nothing to do. */ } - Some(&anonymous_module) => { - debug!("(resolving block) found anonymous module, moving \ - down"); - self.current_module = anonymous_module; - } - } - - // Descend into the block. - visit_block(block, (), visitor); - - // Move back up. - self.current_module = orig_module; - - self.value_ribs.pop(); - debug!("(resolving block) leaving block"); - } - - fn resolve_type(@mut self, ty: @Ty, visitor: ResolveVisitor) { - match ty.node { - // Like path expressions, the interpretation of path types depends - // on whether the path has multiple elements in it or not. - - ty_path(path, path_id) => { - // This is a path in the type namespace. Walk through scopes - // scopes looking for it. - let mut result_def = None; - - // First, check to see whether the name is a primitive type. - if path.idents.len() == 1 { - let name = *path.idents.last(); - - match self.primitive_type_table - .primitive_types - .find(&name) { - - Some(&primitive_type) => { - result_def = - Some(def_prim_ty(primitive_type)); - } - None => { - // Continue. - } - } - } - - match result_def { - None => { - match self.resolve_path(path, TypeNS, true, visitor) { - Some(def) => { - debug!("(resolving type) resolved `%s` to \ - type %?", - *self.session.str_of( - *path.idents.last()), - def); - result_def = Some(def); - } - None => { - result_def = None; - } - } - } - Some(_) => { - // Continue. - } - } - - match result_def { - Some(def) => { - // Write the result into the def map. - debug!("(resolving type) writing resolution for `%s` \ - (id %d)", - self.idents_to_str(path.idents), - path_id); - self.record_def(path_id, def); - } - None => { - self.session.span_err - (ty.span, fmt!("use of undeclared type name `%s`", - self.idents_to_str(path.idents))); - } - } - } - - _ => { - // Just resolve embedded types. - visit_ty(ty, (), visitor); - } - } - } - - fn resolve_pattern(@mut self, - pattern: @pat, - mode: PatternBindingMode, - mutability: Mutability, - // Maps idents to the node ID for the (outermost) - // pattern that binds them - bindings_list: Option<@mut HashMap>, - visitor: ResolveVisitor) { - let pat_id = pattern.id; - do walk_pat(pattern) |pattern| { - match pattern.node { - pat_ident(binding_mode, path, _) - if !path.global && path.idents.len() == 1 => { - - // The meaning of pat_ident with no type parameters - // depends on whether an enum variant or unit-like struct - // with that name is in scope. The probing lookup has to - // be careful not to emit spurious errors. Only matching - // patterns (match) can match nullary variants or - // unit-like structs. For binding patterns (let), matching - // such a value is simply disallowed (since it's rarely - // what you want). - - let ident = path.idents[0]; - - match self.resolve_bare_identifier_pattern(ident) { - FoundStructOrEnumVariant(def) - if mode == RefutableMode => { - debug!("(resolving pattern) resolving `%s` to \ - struct or enum variant", - *self.session.str_of(ident)); - - self.enforce_default_binding_mode( - pattern, - binding_mode, - "an enum variant"); - self.record_def(pattern.id, def); - } - FoundStructOrEnumVariant(_) => { - self.session.span_err(pattern.span, - fmt!("declaration of `%s` \ - shadows an enum \ - variant or unit-like \ - struct in scope", - *self.session - .str_of(ident))); - } - FoundConst(def) if mode == RefutableMode => { - debug!("(resolving pattern) resolving `%s` to \ - constant", - *self.session.str_of(ident)); - - self.enforce_default_binding_mode( - pattern, - binding_mode, - "a constant"); - self.record_def(pattern.id, def); - } - FoundConst(_) => { - self.session.span_err(pattern.span, - ~"only refutable patterns \ - allowed here"); - } - BareIdentifierPatternUnresolved => { - debug!("(resolving pattern) binding `%s`", - *self.session.str_of(ident)); - - let is_mutable = mutability == Mutable; - - let def = match mode { - RefutableMode => { - // For pattern arms, we must use - // `def_binding` definitions. - - def_binding(pattern.id, binding_mode) - } - LocalIrrefutableMode => { - // But for locals, we use `def_local`. - def_local(pattern.id, is_mutable) - } - ArgumentIrrefutableMode => { - // And for function arguments, `def_arg`. - def_arg(pattern.id, is_mutable) - } - }; - - // Record the definition so that later passes - // will be able to distinguish variants from - // locals in patterns. - - self.record_def(pattern.id, def); - - // Add the binding to the local ribs, if it - // doesn't already exist in the bindings list. (We - // must not add it if it's in the bindings list - // because that breaks the assumptions later - // passes make about or-patterns.) - - match bindings_list { - Some(bindings_list) - if !bindings_list.contains_key(&ident) => { - let this = &mut *self; - let last_rib = this.value_ribs[ - this.value_ribs.len() - 1]; - last_rib.bindings.insert(ident, - dl_def(def)); - bindings_list.insert(ident, pat_id); - } - Some(b) => { - if b.find(&ident) == Some(&pat_id) { - // Then this is a duplicate variable - // in the same disjunct, which is an - // error - self.session.span_err(pattern.span, - fmt!("Identifier %s is bound more \ - than once in the same pattern", - path_to_str(path, self.session - .intr()))); - } - // Not bound in the same pattern: do nothing - } - None => { - let this = &mut *self; - let last_rib = this.value_ribs[ - this.value_ribs.len() - 1]; - last_rib.bindings.insert(ident, - dl_def(def)); - } - } - } - } - - // Check the types in the path pattern. - for path.types.each |ty| { - self.resolve_type(*ty, visitor); - } - } - - pat_ident(binding_mode, path, _) => { - // This must be an enum variant, struct, or constant. - match self.resolve_path(path, ValueNS, false, visitor) { - Some(def @ def_variant(*)) | - Some(def @ def_struct(*)) => { - self.record_def(pattern.id, def); - } - Some(def @ def_const(*)) => { - self.enforce_default_binding_mode( - pattern, - binding_mode, - "a constant"); - self.record_def(pattern.id, def); - } - Some(_) => { - self.session.span_err( - path.span, - fmt!("not an enum variant or constant: %s", - *self.session.str_of( - *path.idents.last()))); - } - None => { - self.session.span_err(path.span, - ~"unresolved enum variant"); - } - } - - // Check the types in the path pattern. - for path.types.each |ty| { - self.resolve_type(*ty, visitor); - } - } - - pat_enum(path, _) => { - // This must be an enum variant, struct or const. - match self.resolve_path(path, ValueNS, false, visitor) { - Some(def @ def_fn(*)) | - Some(def @ def_variant(*)) | - Some(def @ def_struct(*)) | - Some(def @ def_const(*)) => { - self.record_def(pattern.id, def); - } - Some(_) => { - self.session.span_err( - path.span, - fmt!("not an enum variant, struct or const: %s", - *self.session.str_of( - *path.idents.last()))); - } - None => { - self.session.span_err(path.span, - ~"unresolved enum variant, \ - struct or const"); - } - } - - // Check the types in the path pattern. - for path.types.each |ty| { - self.resolve_type(*ty, visitor); - } - } - - pat_lit(expr) => { - self.resolve_expr(expr, visitor); - } - - pat_range(first_expr, last_expr) => { - self.resolve_expr(first_expr, visitor); - self.resolve_expr(last_expr, visitor); - } - - pat_struct(path, _, _) => { - let structs: &mut HashSet = &mut self.structs; - match self.resolve_path(path, TypeNS, false, visitor) { - Some(def_ty(class_id)) - if structs.contains(&class_id) => { - let class_def = def_struct(class_id); - self.record_def(pattern.id, class_def); - } - Some(definition @ def_struct(class_id)) - if structs.contains(&class_id) => { - self.record_def(pattern.id, definition); - } - Some(definition @ def_variant(_, variant_id)) - if structs.contains(&variant_id) => { - self.record_def(pattern.id, definition); - } - result => { - debug!("(resolving pattern) didn't find struct \ - def: %?", result); - self.session.span_err( - path.span, - fmt!("`%s` does not name a structure", - self.idents_to_str(path.idents))); - } - } - } - - _ => { - // Nothing to do. - } - } - } - } - - fn resolve_bare_identifier_pattern(@mut self, name: ident) - -> BareIdentifierPatternResolution { - match self.resolve_item_in_lexical_scope(self.current_module, - name, - ValueNS, - SearchThroughModules) { - Success(target) => { - match target.bindings.value_def { - None => { - fail!("resolved name in the value namespace to a \ - set of name bindings with no def?!"); - } - Some(def) => { - match def.def { - def @ def_variant(*) | def @ def_struct(*) => { - return FoundStructOrEnumVariant(def); - } - def @ def_const(*) => { - return FoundConst(def); - } - _ => { - return BareIdentifierPatternUnresolved; - } - } - } - } - } - - Indeterminate => { - fail!("unexpected indeterminate result"); - } - - Failed => { - return BareIdentifierPatternUnresolved; - } - } - } - - /// If `check_ribs` is true, checks the local definitions first; i.e. - /// doesn't skip straight to the containing module. - fn resolve_path(@mut self, - path: @Path, - namespace: Namespace, - check_ribs: bool, - visitor: ResolveVisitor) - -> Option { - // First, resolve the types. - for path.types.each |ty| { - self.resolve_type(*ty, visitor); - } - - if path.global { - return self.resolve_crate_relative_path(path, - self.xray_context, - namespace); - } - - if path.idents.len() > 1 { - return self.resolve_module_relative_path(path, - self.xray_context, - namespace); - } - - return self.resolve_identifier(*path.idents.last(), - namespace, - check_ribs, - path.span); - } - - fn resolve_identifier(@mut self, - identifier: ident, - namespace: Namespace, - check_ribs: bool, - span: span) - -> Option { - if check_ribs { - match self.resolve_identifier_in_local_ribs(identifier, - namespace, - span) { - Some(def) => { - return Some(def); - } - None => { - // Continue. - } - } - } - - return self.resolve_item_by_identifier_in_lexical_scope(identifier, - namespace); - } - - // FIXME #4952: Merge me with resolve_name_in_module? - fn resolve_definition_of_name_in_module(@mut self, - containing_module: @mut Module, - name: ident, - namespace: Namespace, - xray: XrayFlag) - -> NameDefinition { - // First, search children. - match containing_module.children.find(&name) { - Some(child_name_bindings) => { - match (child_name_bindings.def_for_namespace(namespace), - child_name_bindings.privacy_for_namespace(namespace)) { - (Some(def), Some(Public)) => { - // Found it. Stop the search here. - return ChildNameDefinition(def); - } - (Some(def), _) if xray == Xray => { - // Found it. Stop the search here. - return ChildNameDefinition(def); - } - (Some(_), _) | (None, _) => { - // Continue. - } - } - } - None => { - // Continue. - } - } - - // Next, search import resolutions. - match containing_module.import_resolutions.find(&name) { - Some(import_resolution) if import_resolution.privacy == Public || - xray == Xray => { - match (*import_resolution).target_for_namespace(namespace) { - Some(target) => { - match (target.bindings.def_for_namespace(namespace), - target.bindings.privacy_for_namespace( - namespace)) { - (Some(def), Some(Public)) => { - // Found it. - import_resolution.state.used = true; - return ImportNameDefinition(def); - } - (Some(_), _) | (None, _) => { - // This can happen with external impls, due to - // the imperfect way we read the metadata. - } - } - } - None => {} - } - } - Some(_) | None => {} // Continue. - } - - // Finally, search through external children. - if namespace == TypeNS { - match containing_module.external_module_children.find(&name) { - None => {} - Some(module) => { - match module.def_id { - None => {} // Continue. - Some(def_id) => { - return ChildNameDefinition(def_mod(def_id)); - } - } - } - } - } - - return NoNameDefinition; - } - - fn intern_module_part_of_path(@mut self, path: @Path) -> ~[ident] { - let mut module_path_idents = ~[]; - for path.idents.eachi |index, ident| { - if index == path.idents.len() - 1 { - break; - } - - module_path_idents.push(*ident); - } - - return module_path_idents; - } - - fn resolve_module_relative_path(@mut self, - path: @Path, - xray: XrayFlag, - namespace: Namespace) - -> Option { - let module_path_idents = self.intern_module_part_of_path(path); - - let containing_module; - match self.resolve_module_path_for_import(self.current_module, - module_path_idents, - UseLexicalScope, - path.span) { - Failed => { - self.session.span_err(path.span, - fmt!("use of undeclared module `%s`", - self.idents_to_str( - module_path_idents))); - return None; - } - - Indeterminate => { - fail!("indeterminate unexpected"); - } - - Success(resulting_module) => { - containing_module = resulting_module; - } - } - - let name = *path.idents.last(); - match self.resolve_definition_of_name_in_module(containing_module, - name, - namespace, - xray) { - NoNameDefinition => { - // We failed to resolve the name. Report an error. - return None; - } - ChildNameDefinition(def) | ImportNameDefinition(def) => { - return Some(def); - } - } - } - - /// Invariant: This must be called only during main resolution, not during - /// import resolution. - fn resolve_crate_relative_path(@mut self, - path: @Path, - xray: XrayFlag, - namespace: Namespace) - -> Option { - let module_path_idents = self.intern_module_part_of_path(path); - - let root_module = self.graph_root.get_module(); - - let containing_module; - match self.resolve_module_path_from_root(root_module, - module_path_idents, - 0, - path.span, - SearchItemsAndAllImports) { - Failed => { - self.session.span_err(path.span, - fmt!("use of undeclared module `::%s`", - self.idents_to_str( - module_path_idents))); - return None; - } - - Indeterminate => { - fail!("indeterminate unexpected"); - } - - Success(resulting_module) => { - containing_module = resulting_module; - } - } - - let name = *path.idents.last(); - match self.resolve_definition_of_name_in_module(containing_module, - name, - namespace, - xray) { - NoNameDefinition => { - // We failed to resolve the name. Report an error. - return None; - } - ChildNameDefinition(def) | ImportNameDefinition(def) => { - return Some(def); - } - } - } - - fn resolve_identifier_in_local_ribs(@mut self, - ident: ident, - namespace: Namespace, - span: span) - -> Option { - // Check the local set of ribs. - let search_result; - match namespace { - ValueNS => { - search_result = self.search_ribs(&mut self.value_ribs, ident, - span, - DontAllowCapturingSelf); - } - TypeNS => { - search_result = self.search_ribs(&mut self.type_ribs, ident, - span, AllowCapturingSelf); - } - } - - match search_result { - Some(dl_def(def)) => { - debug!("(resolving path in local ribs) resolved `%s` to \ - local: %?", - *self.session.str_of(ident), - def); - return Some(def); - } - Some(dl_field) | Some(dl_impl(_)) | None => { - return None; - } - } - } - - fn resolve_self_value_in_local_ribs(@mut self, span: span) - -> Option { - // FIXME #4950: This should not use a while loop. - let ribs = &mut self.value_ribs; - let mut i = ribs.len(); - while i != 0 { - i -= 1; - match *ribs[i].self_binding { - Some(def_like) => { - match self.upvarify(ribs, - i, - def_like, - span, - DontAllowCapturingSelf) { - Some(dl_def(def)) => return Some(def), - _ => { - self.session.span_bug(span, - ~"self wasn't mapped to a \ - def?!") - } - } - } - None => {} - } - } - - None - } - - fn resolve_item_by_identifier_in_lexical_scope(@mut self, - ident: ident, - namespace: Namespace) - -> Option { - // Check the items. - match self.resolve_item_in_lexical_scope(self.current_module, - ident, - namespace, - DontSearchThroughModules) { - Success(target) => { - match (*target.bindings).def_for_namespace(namespace) { - None => { - // This can happen if we were looking for a type and - // found a module instead. Modules don't have defs. - return None; - } - Some(def) => { - debug!("(resolving item path in lexical scope) \ - resolved `%s` to item", - *self.session.str_of(ident)); - return Some(def); - } - } - } - Indeterminate => { - fail!("unexpected indeterminate result"); - } - Failed => { - return None; - } - } - } - - fn find_best_match_for_name(@mut self, name: &str, max_distance: uint) -> Option<~str> { - let this = &mut *self; - - let mut maybes: ~[~str] = ~[]; - let mut values: ~[uint] = ~[]; - - let mut j = this.value_ribs.len(); - while j != 0 { - j -= 1; - for this.value_ribs[j].bindings.each_key |&k| { - vec::push(&mut maybes, copy *this.session.str_of(k)); - vec::push(&mut values, uint::max_value); - } - } - - let mut smallest = 0; - for maybes.eachi |i, &other| { - - values[i] = str::levdistance(name, other); - - if values[i] <= values[smallest] { - smallest = i; - } - } - - if values.len() > 0 && - values[smallest] != uint::max_value && - values[smallest] < str::len(name) + 2 && - values[smallest] <= max_distance && - maybes[smallest] != name.to_owned() { - - Some(vec::swap_remove(&mut maybes, smallest)) - - } else { - None - } - } - - fn name_exists_in_scope_struct(@mut self, name: &str) -> bool { - let this = &mut *self; - - let mut i = this.type_ribs.len(); - while i != 0 { - i -= 1; - match this.type_ribs[i].kind { - MethodRibKind(node_id, _) => - for this.crate.node.module.items.each |item| { - if item.id == node_id { - match item.node { - item_struct(class_def, _) => { - for class_def.fields.each |field| { - match field.node.kind { - unnamed_field => {}, - named_field(ident, _) => { - if str::eq_slice(*this.session.str_of(ident), - name) { - return true - } - } - } - } - } - _ => {} - } - } - }, - _ => {} - } - } - return false; - } - - fn resolve_expr(@mut self, expr: @expr, visitor: ResolveVisitor) { - // First, record candidate traits for this expression if it could - // result in the invocation of a method call. - - self.record_candidate_traits_for_expr_if_necessary(expr); - - // Next, resolve the node. - match expr.node { - // The interpretation of paths depends on whether the path has - // multiple elements in it or not. - - expr_path(path) => { - // This is a local path in the value namespace. Walk through - // scopes looking for it. - - match self.resolve_path(path, ValueNS, true, visitor) { - Some(def) => { - // Write the result into the def map. - debug!("(resolving expr) resolved `%s`", - self.idents_to_str(path.idents)); - self.record_def(expr.id, def); - } - None => { - let wrong_name = self.idents_to_str( - path.idents); - if self.name_exists_in_scope_struct(wrong_name) { - self.session.span_err(expr.span, - fmt!("unresolved name: `%s`. \ - Did you mean: `self.%s`?", - wrong_name, - wrong_name)); - } - else { - // limit search to 5 to reduce the number - // of stupid suggestions - match self.find_best_match_for_name(wrong_name, 5) { - Some(m) => { - self.session.span_err(expr.span, - fmt!("unresolved name: `%s`. \ - Did you mean: `%s`?", - wrong_name, m)); - } - None => { - self.session.span_err(expr.span, - fmt!("unresolved name: `%s`.", - wrong_name)); - } - } - } - } - } - - visit_expr(expr, (), visitor); - } - - expr_fn_block(ref fn_decl, ref block) => { - self.resolve_function(FunctionRibKind(expr.id, block.node.id), - Some(fn_decl), - NoTypeParameters, - block, - NoSelfBinding, - visitor); - } - - expr_struct(path, _, _) => { - // Resolve the path to the structure it goes to. - let structs: &mut HashSet = &mut self.structs; - match self.resolve_path(path, TypeNS, false, visitor) { - Some(def_ty(class_id)) | Some(def_struct(class_id)) - if structs.contains(&class_id) => { - let class_def = def_struct(class_id); - self.record_def(expr.id, class_def); - } - Some(definition @ def_variant(_, class_id)) - if structs.contains(&class_id) => { - self.record_def(expr.id, definition); - } - _ => { - self.session.span_err( - path.span, - fmt!("`%s` does not name a structure", - self.idents_to_str(path.idents))); - } - } - - visit_expr(expr, (), visitor); - } - - expr_loop(_, Some(label)) => { - do self.with_label_rib { - let this = &mut *self; - let def_like = dl_def(def_label(expr.id)); - let rib = this.label_ribs[this.label_ribs.len() - 1]; - rib.bindings.insert(label, def_like); - - visit_expr(expr, (), visitor); - } - } - - expr_break(Some(label)) | expr_again(Some(label)) => { - match self.search_ribs(&mut self.label_ribs, label, expr.span, - DontAllowCapturingSelf) { - None => - self.session.span_err(expr.span, - fmt!("use of undeclared label \ - `%s`", - *self.session.str_of( - label))), - Some(dl_def(def @ def_label(_))) => { - self.record_def(expr.id, def) - } - Some(_) => { - self.session.span_bug(expr.span, - ~"label wasn't mapped to a \ - label def!") - } - } - } - - expr_self => { - match self.resolve_self_value_in_local_ribs(expr.span) { - None => { - self.session.span_err(expr.span, - ~"`self` is not allowed in \ - this context") - } - Some(def) => self.record_def(expr.id, def), - } - } - - _ => { - visit_expr(expr, (), visitor); - } - } - } - - fn record_candidate_traits_for_expr_if_necessary(@mut self, expr: @expr) { - match expr.node { - expr_field(_, ident, _) => { - let traits = self.search_for_traits_containing_method(ident); - self.trait_map.insert(expr.id, @mut traits); - } - expr_method_call(_, ident, _, _, _) => { - let traits = self.search_for_traits_containing_method(ident); - self.trait_map.insert(expr.id, @mut traits); - } - expr_binary(add, _, _) | expr_assign_op(add, _, _) => { - self.add_fixed_trait_for_expr(expr.id, - self.lang_items.add_trait()); - } - expr_binary(subtract, _, _) | expr_assign_op(subtract, _, _) => { - self.add_fixed_trait_for_expr(expr.id, - self.lang_items.sub_trait()); - } - expr_binary(mul, _, _) | expr_assign_op(mul, _, _) => { - self.add_fixed_trait_for_expr(expr.id, - self.lang_items.mul_trait()); - } - expr_binary(div, _, _) | expr_assign_op(div, _, _) => { - self.add_fixed_trait_for_expr(expr.id, - self.lang_items.div_trait()); - } - expr_binary(rem, _, _) | expr_assign_op(rem, _, _) => { - self.add_fixed_trait_for_expr(expr.id, - self.lang_items.rem_trait()); - } - expr_binary(bitxor, _, _) | expr_assign_op(bitxor, _, _) => { - self.add_fixed_trait_for_expr(expr.id, - self.lang_items.bitxor_trait()); - } - expr_binary(bitand, _, _) | expr_assign_op(bitand, _, _) => { - self.add_fixed_trait_for_expr(expr.id, - self.lang_items.bitand_trait()); - } - expr_binary(bitor, _, _) | expr_assign_op(bitor, _, _) => { - self.add_fixed_trait_for_expr(expr.id, - self.lang_items.bitor_trait()); - } - expr_binary(shl, _, _) | expr_assign_op(shl, _, _) => { - self.add_fixed_trait_for_expr(expr.id, - self.lang_items.shl_trait()); - } - expr_binary(shr, _, _) | expr_assign_op(shr, _, _) => { - self.add_fixed_trait_for_expr(expr.id, - self.lang_items.shr_trait()); - } - expr_binary(lt, _, _) | expr_binary(le, _, _) | - expr_binary(ge, _, _) | expr_binary(gt, _, _) => { - self.add_fixed_trait_for_expr(expr.id, - self.lang_items.ord_trait()); - } - expr_binary(eq, _, _) | expr_binary(ne, _, _) => { - self.add_fixed_trait_for_expr(expr.id, - self.lang_items.eq_trait()); - } - expr_unary(neg, _) => { - self.add_fixed_trait_for_expr(expr.id, - self.lang_items.neg_trait()); - } - expr_unary(not, _) => { - self.add_fixed_trait_for_expr(expr.id, - self.lang_items.not_trait()); - } - expr_index(*) => { - self.add_fixed_trait_for_expr(expr.id, - self.lang_items.index_trait()); - } - _ => { - // Nothing to do. - } - } - } - - fn search_for_traits_containing_method(@mut self, - name: ident) - -> ~[def_id] { - debug!("(searching for traits containing method) looking for '%s'", - *self.session.str_of(name)); - - let mut found_traits = ~[]; - let mut search_module = self.current_module; - loop { - // Look for the current trait. - match /*bad*/copy self.current_trait_refs { - Some(trait_def_ids) => { - for trait_def_ids.each |trait_def_id| { - self.add_trait_info_if_containing_method( - &mut found_traits, *trait_def_id, name); - } - } - None => { - // Nothing to do. - } - } - - // Look for trait children. - for search_module.children.each_value |&child_name_bindings| { - match child_name_bindings.def_for_namespace(TypeNS) { - Some(def) => { - match def { - def_trait(trait_def_id) => { - self.add_trait_info_if_containing_method( - &mut found_traits, trait_def_id, name); - } - _ => { - // Continue. - } - } - } - None => { - // Continue. - } - } - } - - // Look for imports. - for search_module.import_resolutions.each_value - |&import_resolution| { - - match import_resolution.target_for_namespace(TypeNS) { - None => { - // Continue. - } - Some(target) => { - match target.bindings.def_for_namespace(TypeNS) { - Some(def) => { - match def { - def_trait(trait_def_id) => { - let added = self. - add_trait_info_if_containing_method( - &mut found_traits, - trait_def_id, name); - if added { - import_resolution.state.used = - true; - } - } - _ => { - // Continue. - } - } - } - None => { - // Continue. - } - } - } - } - } - - // Move to the next parent. - match search_module.parent_link { - NoParentLink => { - // Done. - break; - } - ModuleParentLink(parent_module, _) | - BlockParentLink(parent_module, _) => { - search_module = parent_module; - } - } - } - - return found_traits; - } - - fn add_trait_info_if_containing_method(&self, - found_traits: &mut ~[def_id], - trait_def_id: def_id, - name: ident) - -> bool { - debug!("(adding trait info if containing method) trying trait %d:%d \ - for method '%s'", - trait_def_id.crate, - trait_def_id.node, - *self.session.str_of(name)); - - match self.trait_info.find(&trait_def_id) { - Some(trait_info) if trait_info.contains(&name) => { - debug!("(adding trait info if containing method) found trait \ - %d:%d for method '%s'", - trait_def_id.crate, - trait_def_id.node, - *self.session.str_of(name)); - found_traits.push(trait_def_id); - true - } - Some(_) | None => { - false - } - } - } - - fn add_fixed_trait_for_expr(@mut self, - expr_id: node_id, - trait_id: def_id) { - self.trait_map.insert(expr_id, @mut ~[trait_id]); - } - - fn record_def(@mut self, node_id: node_id, def: def) { - debug!("(recording def) recording %? for %?", def, node_id); - self.def_map.insert(node_id, def); - } - - fn enforce_default_binding_mode(@mut self, - pat: @pat, - pat_binding_mode: binding_mode, - descr: &str) { - match pat_binding_mode { - bind_infer => {} - bind_by_copy => { - self.session.span_err( - pat.span, - fmt!("cannot use `copy` binding mode with %s", - descr)); - } - bind_by_ref(*) => { - self.session.span_err( - pat.span, - fmt!("cannot use `ref` binding mode with %s", - descr)); - } - } - } - - // - // main function checking - // - // be sure that there is only one main function - // - fn check_duplicate_main(@mut self) { - let this = &mut *self; - if this.attr_main_fn.is_none() && this.start_fn.is_none() { - if this.main_fns.len() >= 1u { - let mut i = 1u; - while i < this.main_fns.len() { - let (_, dup_main_span) = this.main_fns[i].unwrap(); - this.session.span_err( - dup_main_span, - ~"multiple 'main' functions"); - i += 1; - } - *this.session.entry_fn = this.main_fns[0]; - *this.session.entry_type = Some(session::EntryMain); - } - } else if !this.start_fn.is_none() { - *this.session.entry_fn = this.start_fn; - *this.session.entry_type = Some(session::EntryStart); - } else { - *this.session.entry_fn = this.attr_main_fn; - *this.session.entry_type = Some(session::EntryMain); - } - } - - // - // Unused import checking - // - // Although this is a lint pass, it lives in here because it depends on - // resolve data structures. - // - - fn unused_import_lint_level(@mut self, _: @mut Module) -> level { warn } - - fn check_for_unused_imports_if_necessary(@mut self) { - if self.unused_import_lint_level(self.current_module) == allow { - return; - } - - let root_module = self.graph_root.get_module(); - self.check_for_unused_imports_in_module_subtree(root_module); - } - - fn check_for_unused_imports_in_module_subtree(@mut self, - module_: @mut Module) { - // If this isn't a local crate, then bail out. We don't need to check - // for unused imports in external crates. - - match module_.def_id { - Some(def_id) if def_id.crate == local_crate => { - // OK. Continue. - } - None => { - // Check for unused imports in the root module. - } - Some(_) => { - // Bail out. - debug!("(checking for unused imports in module subtree) not \ - checking for unused imports for `%s`", - self.module_to_str(module_)); - return; - } - } - - self.check_for_unused_imports_in_module(module_); - - for module_.children.each_value |&child_name_bindings| { - match (*child_name_bindings).get_module_if_available() { - None => { - // Nothing to do. - } - Some(child_module) => { - self.check_for_unused_imports_in_module_subtree - (child_module); - } - } - } - - for module_.anonymous_children.each_value |&child_module| { - self.check_for_unused_imports_in_module_subtree(child_module); - } - } - - fn check_for_unused_imports_in_module(@mut self, module_: @mut Module) { - for module_.import_resolutions.each_value |&import_resolution| { - // Ignore dummy spans for things like automatically injected - // imports for the prelude, and also don't warn about the same - // import statement being unused more than once. Furthermore, if - // the import is public, then we can't be sure whether it's unused - // or not so don't warn about it. - if !import_resolution.state.used && - !import_resolution.state.warned && - import_resolution.span != dummy_sp() && - import_resolution.privacy != Public { - // I swear I work in not(stage0)! - } - } - } - - - // - // Diagnostics - // - // Diagnostics are not particularly efficient, because they're rarely - // hit. - // - - /// A somewhat inefficient routine to obtain the name of a module. - fn module_to_str(@mut self, module_: @mut Module) -> ~str { - let mut idents = ~[]; - let mut current_module = module_; - loop { - match current_module.parent_link { - NoParentLink => { - break; - } - ModuleParentLink(module_, name) => { - idents.push(name); - current_module = module_; - } - BlockParentLink(module_, _) => { - idents.push(special_idents::opaque); - current_module = module_; - } - } - } - - if idents.len() == 0 { - return ~"???"; - } - return self.idents_to_str(vec::reversed(idents)); - } - - fn dump_module(@mut self, module_: @mut Module) { - debug!("Dump of module `%s`:", self.module_to_str(module_)); - - debug!("Children:"); - for module_.children.each_key |&name| { - debug!("* %s", *self.session.str_of(name)); - } - - debug!("Import resolutions:"); - for module_.import_resolutions.each |name, import_resolution| { - let mut value_repr; - match import_resolution.target_for_namespace(ValueNS) { - None => { value_repr = ~""; } - Some(_) => { - value_repr = ~" value:?"; - // FIXME #4954 - } - } - - let mut type_repr; - match import_resolution.target_for_namespace(TypeNS) { - None => { type_repr = ~""; } - Some(_) => { - type_repr = ~" type:?"; - // FIXME #4954 - } - } - - debug!("* %s:%s%s", *self.session.str_of(*name), - value_repr, type_repr); - } - } -} - -pub struct CrateMap { - def_map: DefMap, - exp_map2: ExportMap2, - trait_map: TraitMap -} - -/// Entry point to crate resolution. -pub fn resolve_crate(session: Session, - lang_items: LanguageItems, - crate: @crate) - -> CrateMap { - let resolver = @mut Resolver(session, lang_items, crate); - resolver.resolve(); - let @Resolver{def_map, export_map2, trait_map, _} = resolver; - CrateMap { - def_map: def_map, - exp_map2: export_map2, - trait_map: trait_map - } -} diff --git a/src/librustc/middle/subst.rs b/src/librustc/middle/subst.rs index 5c7c33d35b238..fba174c68405d 100644 --- a/src/librustc/middle/subst.rs +++ b/src/librustc/middle/subst.rs @@ -10,6 +10,8 @@ // Type substitutions. +use core::prelude::*; + use middle::ty; use util::ppaux::Repr; diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index d2834a095aa9c..a42e1cd064792 100644 --- a/src/librustc/middle/trans/_match.rs +++ b/src/librustc/middle/trans/_match.rs @@ -140,8 +140,15 @@ * the various values we copied explicitly. Note that guards and moves are * just plain incompatible. * + * Some relevant helper functions that manage bindings: + * - `create_bindings_map()` + * - `store_non_ref_bindings()` + * - `insert_lllocals()` + * */ +use core::prelude::*; + use back::abi; use lib::llvm::{llvm, ValueRef, BasicBlockRef}; use middle::const_eval; @@ -166,6 +173,7 @@ use middle::ty; use util::common::indenter; use core::hashmap::HashMap; +use core::vec; use syntax::ast; use syntax::ast::ident; use syntax::ast_util::path_to_ident; @@ -193,48 +201,55 @@ pub enum Opt { pub fn opt_eq(tcx: ty::ctxt, a: &Opt, b: &Opt) -> bool { match (a, b) { - (&lit(a), &lit(b)) => { - match (a, b) { - (UnitLikeStructLit(a), UnitLikeStructLit(b)) => a == b, - _ => { - let a_expr; - match a { - ExprLit(existing_a_expr) => a_expr = existing_a_expr, - ConstLit(a_const) => { - let e = const_eval::lookup_const_by_id(tcx, a_const); - a_expr = e.get(); - } - UnitLikeStructLit(_) => { - fail!("UnitLikeStructLit should have been handled \ - above") + (&lit(a), &lit(b)) => { + match (a, b) { + (UnitLikeStructLit(a), UnitLikeStructLit(b)) => a == b, + _ => { + let a_expr; + match a { + ExprLit(existing_a_expr) => a_expr = existing_a_expr, + ConstLit(a_const) => { + let e = const_eval::lookup_const_by_id(tcx, a_const); + a_expr = e.get(); + } + UnitLikeStructLit(_) => { + fail!("UnitLikeStructLit should have been handled \ + above") + } } - } - let b_expr; - match b { - ExprLit(existing_b_expr) => b_expr = existing_b_expr, - ConstLit(b_const) => { - let e = const_eval::lookup_const_by_id(tcx, b_const); - b_expr = e.get(); + let b_expr; + match b { + ExprLit(existing_b_expr) => b_expr = existing_b_expr, + ConstLit(b_const) => { + let e = const_eval::lookup_const_by_id(tcx, b_const); + b_expr = e.get(); + } + UnitLikeStructLit(_) => { + fail!("UnitLikeStructLit should have been handled \ + above") + } } - UnitLikeStructLit(_) => { - fail!("UnitLikeStructLit should have been handled \ - above") + + match const_eval::compare_lit_exprs(tcx, a_expr, b_expr) { + Some(val1) => val1 == 0, + None => fail!("compare_list_exprs: type mismatch"), } } - - const_eval::compare_lit_exprs(tcx, a_expr, b_expr) == 0 } } - } - (&range(a1, a2), &range(b1, b2)) => { - const_eval::compare_lit_exprs(tcx, a1, b1) == 0 && - const_eval::compare_lit_exprs(tcx, a2, b2) == 0 - } - (&var(a, _), &var(b, _)) => a == b, - (&vec_len_eq(a), &vec_len_eq(b)) => a == b, - (&vec_len_ge(a, _), &vec_len_ge(b, _)) => a == b, - _ => false + (&range(a1, a2), &range(b1, b2)) => { + let m1 = const_eval::compare_lit_exprs(tcx, a1, b1); + let m2 = const_eval::compare_lit_exprs(tcx, a2, b2); + match (m1, m2) { + (Some(val1), Some(val2)) => (val1 == 0 && val2 == 0), + _ => fail!("compare_list_exprs: type mismatch"), + } + } + (&var(a, _), &var(b, _)) => a == b, + (&vec_len_eq(a), &vec_len_eq(b)) => a == b, + (&vec_len_ge(a, _), &vec_len_ge(b, _)) => a == b, + _ => false } } @@ -296,7 +311,7 @@ pub fn variant_opt(bcx: block, pat_id: ast::node_id) return lit(UnitLikeStructLit(pat_id)); } _ => { - ccx.sess.bug(~"non-variant or struct in variant_opt()"); + ccx.sess.bug("non-variant or struct in variant_opt()"); } } } @@ -304,7 +319,6 @@ pub fn variant_opt(bcx: block, pat_id: ast::node_id) pub enum TransBindingMode { TrByValue(/*ismove:*/ bool, /*llbinding:*/ ValueRef), TrByRef, - TrByImplicitRef } /** @@ -660,8 +674,8 @@ pub fn enter_tup<'r>(bcx: block, let dummy = @ast::pat {id: 0, node: ast::pat_wild, span: dummy_sp()}; do enter_match(bcx, dm, m, col, val) |p| { match p.node { - ast::pat_tup(/*bad*/copy elts) => { - Some(elts) + ast::pat_tup(ref elts) => { + Some(copy *elts) } _ => { assert_is_binding_or_wild(bcx, p); @@ -688,7 +702,7 @@ pub fn enter_tuple_struct<'r>(bcx: block, let dummy = @ast::pat {id: 0, node: ast::pat_wild, span: dummy_sp()}; do enter_match(bcx, dm, m, col, val) |p| { match p.node { - ast::pat_enum(_, Some(/*bad*/copy elts)) => Some(elts), + ast::pat_enum(_, Some(ref elts)) => Some(copy *elts), _ => { assert_is_binding_or_wild(bcx, p); Some(vec::from_elem(n_elts, dummy)) @@ -871,7 +885,7 @@ fn match_datum(bcx: block, val: ValueRef, pat_id: ast::node_id) -> Datum { //! we should just pass around a Datum and be done with it. let ty = node_id_type(bcx, pat_id); - Datum {val: val, ty: ty, mode: datum::ByRef, source: RevokeClean} + Datum {val: val, ty: ty, mode: datum::ByRef(RevokeClean)} } @@ -891,10 +905,10 @@ pub fn extract_vec_elems(bcx: block, let mut elems = do vec::from_fn(elem_count) |i| { match slice { - None => GEPi(bcx, base, ~[i]), - Some(n) if i < n => GEPi(bcx, base, ~[i]), + None => GEPi(bcx, base, [i]), + Some(n) if i < n => GEPi(bcx, base, [i]), Some(n) if i > n => { - InBoundsGEP(bcx, base, ~[ + InBoundsGEP(bcx, base, [ Sub(bcx, count, C_int(bcx.ccx(), (elem_count - i) as int))]) } @@ -978,7 +992,7 @@ pub fn root_pats_as_necessary(mut bcx: block, let pat_id = br.pats[col].id; if pat_id != 0 { let datum = Datum {val: val, ty: node_id_type(bcx, pat_id), - mode: ByRef, source: ZeroMem}; + mode: ByRef(ZeroMem)}; bcx = datum.root_and_write_guard(bcx, br.pats[col].span, pat_id, 0); } } @@ -1089,11 +1103,8 @@ pub fn compare_values(cx: block, let scratch_rhs = alloca(cx, val_ty(rhs)); Store(cx, rhs, scratch_rhs); let did = cx.tcx().lang_items.uniq_str_eq_fn(); - let bcx = callee::trans_lang_call(cx, did, - ~[scratch_lhs, - scratch_rhs], - expr::SaveIn( - scratch_result.val)); + let bcx = callee::trans_lang_call(cx, did, [scratch_lhs, scratch_rhs], + expr::SaveIn(scratch_result.val)); let result = scratch_result.to_result(bcx); Result { bcx: result.bcx, @@ -1103,10 +1114,8 @@ pub fn compare_values(cx: block, ty::ty_estr(_) => { let scratch_result = scratch_datum(cx, ty::mk_bool(), false); let did = cx.tcx().lang_items.str_eq_fn(); - let bcx = callee::trans_lang_call(cx, did, - ~[lhs, rhs], - expr::SaveIn( - scratch_result.val)); + let bcx = callee::trans_lang_call(cx, did, [lhs, rhs], + expr::SaveIn(scratch_result.val)); let result = scratch_result.to_result(bcx); Result { bcx: result.bcx, @@ -1114,16 +1123,16 @@ pub fn compare_values(cx: block, } } _ => { - cx.tcx().sess.bug(~"only scalars and strings supported in \ + cx.tcx().sess.bug("only scalars and strings supported in \ compare_values"); } } } -pub fn store_non_ref_bindings(bcx: block, - data: &ArmData, - opt_temp_cleanups: Option<&mut ~[ValueRef]>) - -> block +fn store_non_ref_bindings(bcx: block, + bindings_map: &BindingsMap, + mut opt_temp_cleanups: Option<&mut ~[ValueRef]>) + -> block { /*! * @@ -1135,13 +1144,12 @@ pub fn store_non_ref_bindings(bcx: block, */ let mut bcx = bcx; - let mut opt_temp_cleanups = opt_temp_cleanups; - for data.bindings_map.each_value |&binding_info| { + for bindings_map.each_value |&binding_info| { match binding_info.trmode { TrByValue(is_move, lldest) => { let llval = Load(bcx, binding_info.llmatch); // get a T* let datum = Datum {val: llval, ty: binding_info.ty, - mode: ByRef, source: ZeroMem}; + mode: ByRef(ZeroMem)}; bcx = { if is_move { datum.move_to(bcx, INIT, lldest) @@ -1156,22 +1164,28 @@ pub fn store_non_ref_bindings(bcx: block, temp_cleanups } } - TrByRef | TrByImplicitRef => {} + TrByRef => {} } } return bcx; } -pub fn insert_lllocals(bcx: block, - data: &ArmData, - add_cleans: bool) -> block { +fn insert_lllocals(bcx: block, + bindings_map: &BindingsMap, + binding_mode: IrrefutablePatternBindingMode, + add_cleans: bool) -> block { /*! - * * For each binding in `data.bindings_map`, adds an appropriate entry into * the `fcx.lllocals` map. If add_cleans is true, then adds cleanups for - * the bindings. */ + * the bindings. + */ + + let llmap = match binding_mode { + BindLocal => bcx.fcx.lllocals, + BindArgument => bcx.fcx.llargs + }; - for data.bindings_map.each_value |&binding_info| { + for bindings_map.each_value |&binding_info| { let llval = match binding_info.trmode { // By value bindings: use the stack slot that we // copied/moved the value into @@ -1187,17 +1201,12 @@ pub fn insert_lllocals(bcx: block, TrByRef => { binding_info.llmatch } - - // Ugly: for implicit ref, we actually want a T*, but - // we have a T**, so we had to load. This will go away - // once implicit refs go away. - TrByImplicitRef => { - Load(bcx, binding_info.llmatch) - } }; - bcx.fcx.lllocals.insert(binding_info.id, - local_mem(llval)); + debug!("binding %? to %s", + binding_info.id, + val_str(bcx.ccx().tn, llval)); + llmap.insert(binding_info.id, llval); } return bcx; } @@ -1218,8 +1227,8 @@ pub fn compile_guard(bcx: block, let mut bcx = bcx; let mut temp_cleanups = ~[]; - bcx = store_non_ref_bindings(bcx, data, Some(&mut temp_cleanups)); - bcx = insert_lllocals(bcx, data, false); + bcx = store_non_ref_bindings(bcx, &data.bindings_map, Some(&mut temp_cleanups)); + bcx = insert_lllocals(bcx, &data.bindings_map, BindLocal, false); let val = unpack_result!(bcx, { do with_scope_result(bcx, guard_expr.info(), @@ -1249,7 +1258,7 @@ pub fn compile_guard(bcx: block, TrByValue(_, llval) => { bcx = glue::drop_ty(bcx, llval, binding_info.ty); } - TrByRef | TrByImplicitRef => {} + TrByRef => {} } bcx.fcx.lllocals.remove(&binding_info.id); } @@ -1273,7 +1282,8 @@ pub fn compile_submatch(bcx: block, assert!((m.len() > 0u || chk.is_some())); let _icx = bcx.insn_ctxt("match::compile_submatch"); let mut bcx = bcx; - let tcx = bcx.tcx(), dm = tcx.def_map; + let tcx = bcx.tcx(); + let dm = tcx.def_map; if m.len() == 0u { Br(bcx, chk.get()()); return; @@ -1343,7 +1353,7 @@ pub fn compile_submatch(bcx: block, let tup_repr = adt::represent_type(bcx.ccx(), tup_ty); let n_tup_elts = match ty::get(tup_ty).sty { ty::ty_tup(ref elts) => elts.len(), - _ => ccx.sess.bug(~"non-tuple type in tuple pattern") + _ => ccx.sess.bug("non-tuple type in tuple pattern") }; let tup_vals = do vec::from_fn(n_tup_elts) |i| { adt::trans_field_ptr(bcx, tup_repr, val, 0, i) @@ -1362,7 +1372,7 @@ pub fn compile_submatch(bcx: block, ty::lookup_struct_fields(tcx, struct_id).len(); } _ => { - ccx.sess.bug(~"non-struct type in tuple struct pattern"); + ccx.sess.bug("non-struct type in tuple struct pattern"); } } @@ -1478,8 +1488,8 @@ pub fn compile_submatch(bcx: block, } _ => { bcx.sess().bug( - ~"in compile_submatch, expected \ - trans_opt to return a single_result") + "in compile_submatch, expected \ + trans_opt to return a single_result") } } } @@ -1616,6 +1626,43 @@ pub fn trans_match(bcx: block, } } +fn create_bindings_map(bcx: block, pat: @ast::pat) -> BindingsMap { + // Create the bindings map, which is a mapping from each binding name + // to an alloca() that will be the value for that local variable. + // Note that we use the names because each binding will have many ids + // from the various alternatives. + let ccx = bcx.ccx(); + let tcx = bcx.tcx(); + let mut bindings_map = HashMap::new(); + do pat_bindings(tcx.def_map, pat) |bm, p_id, _s, path| { + let ident = path_to_ident(path); + let variable_ty = node_id_type(bcx, p_id); + let llvariable_ty = type_of::type_of(ccx, variable_ty); + + let llmatch; + let trmode; + match bm { + ast::bind_infer => { + // in this case, the final type of the variable will be T, + // but during matching we need to store a *T as explained + // above + let is_move = ccx.maps.moves_map.contains(&p_id); + llmatch = alloca(bcx, T_ptr(llvariable_ty)); + trmode = TrByValue(is_move, alloca(bcx, llvariable_ty)); + } + ast::bind_by_ref(_) => { + llmatch = alloca(bcx, llvariable_ty); + trmode = TrByRef; + } + }; + bindings_map.insert(ident, BindingInfo { + llmatch: llmatch, trmode: trmode, + id: p_id, ty: variable_ty + }); + } + return bindings_map; +} + pub fn trans_match_inner(scope_cx: block, discr_expr: @ast::expr, arms: &[ast::arm], @@ -1631,42 +1678,11 @@ pub fn trans_match_inner(scope_cx: block, return bcx; } - let mut arm_datas = ~[], matches = ~[]; - for arms.each |arm| { + let mut arm_datas = ~[]; + let mut matches = ~[]; + for vec::each(arms) |arm| { let body = scope_block(bcx, arm.body.info(), "case_body"); - - // Create the bindings map, which is a mapping from each binding name - // to an alloca() that will be the value for that local variable. - // Note that we use the names because each binding will have many ids - // from the various alternatives. - let mut bindings_map = HashMap::new(); - do pat_bindings(tcx.def_map, arm.pats[0]) |bm, p_id, _s, path| { - let ident = path_to_ident(path); - let variable_ty = node_id_type(bcx, p_id); - let llvariable_ty = type_of::type_of(bcx.ccx(), variable_ty); - - let llmatch, trmode; - match bm { - ast::bind_by_copy | ast::bind_infer => { - // in this case, the final type of the variable will be T, - // but during matching we need to store a *T as explained - // above - let is_move = - scope_cx.ccx().maps.moves_map.contains(&p_id); - llmatch = alloca(bcx, T_ptr(llvariable_ty)); - trmode = TrByValue(is_move, alloca(bcx, llvariable_ty)); - } - ast::bind_by_ref(_) => { - llmatch = alloca(bcx, llvariable_ty); - trmode = TrByRef; - } - }; - bindings_map.insert(ident, BindingInfo { - llmatch: llmatch, trmode: trmode, - id: p_id, ty: variable_ty - }); - } - + let bindings_map = create_bindings_map(bcx, arm.pats[0]); let arm_data = @ArmData {bodycx: body, arm: arm, bindings_map: bindings_map}; @@ -1688,8 +1704,8 @@ pub fn trans_match_inner(scope_cx: block, None } }; - let lldiscr = discr_datum.to_ref_llval(bcx); - compile_submatch(bcx, matches, ~[lldiscr], chk); + let lldiscr = discr_datum.to_zeroable_ref_llval(bcx); + compile_submatch(bcx, matches, [lldiscr], chk); let mut arm_cxs = ~[]; for arm_datas.each |arm_data| { @@ -1700,11 +1716,11 @@ pub fn trans_match_inner(scope_cx: block, // is just to reduce code space. See extensive comment at the start // of the file for more details. if arm_data.arm.guard.is_none() { - bcx = store_non_ref_bindings(bcx, *arm_data, None); + bcx = store_non_ref_bindings(bcx, &arm_data.bindings_map, None); } // insert bindings into the lllocals map and add cleanups - bcx = insert_lllocals(bcx, *arm_data, true); + bcx = insert_lllocals(bcx, &arm_data.bindings_map, BindLocal, true); bcx = controlflow::trans_block(bcx, &arm_data.arm.body, dest); bcx = trans_block_cleanups(bcx, block_cleanups(arm_data.bodycx)); @@ -1752,27 +1768,25 @@ pub fn bind_irrefutable_pat(bcx: block, if make_copy { let binding_ty = node_id_type(bcx, pat.id); let datum = Datum {val: val, ty: binding_ty, - mode: ByRef, source: RevokeClean}; + mode: ByRef(RevokeClean)}; let scratch = scratch_datum(bcx, binding_ty, false); datum.copy_to_datum(bcx, INIT, scratch); match binding_mode { BindLocal => { - bcx.fcx.lllocals.insert(pat.id, - local_mem(scratch.val)); + bcx.fcx.lllocals.insert(pat.id, scratch.val); } BindArgument => { - bcx.fcx.llargs.insert(pat.id, - local_mem(scratch.val)); + bcx.fcx.llargs.insert(pat.id, scratch.val); } } add_clean(bcx, scratch.val, binding_ty); } else { match binding_mode { BindLocal => { - bcx.fcx.lllocals.insert(pat.id, local_mem(val)); + bcx.fcx.lllocals.insert(pat.id, val); } BindArgument => { - bcx.fcx.llargs.insert(pat.id, local_mem(val)); + bcx.fcx.llargs.insert(pat.id, val); } } } diff --git a/src/librustc/middle/trans/adt.rs b/src/librustc/middle/trans/adt.rs index 21452a736fba8..b26f80fc355b1 100644 --- a/src/librustc/middle/trans/adt.rs +++ b/src/librustc/middle/trans/adt.rs @@ -158,7 +158,7 @@ fn represent_type_uncached(cx: @CrateContext, t: ty::t) -> Repr { if cases.len() == 0 { // Uninhabitable; represent as unit - return Univariant(mk_struct(cx, ~[], false), false); + return Univariant(mk_struct(cx, [], false), false); } if cases.all(|c| c.tys.len() == 0) { @@ -169,7 +169,7 @@ fn represent_type_uncached(cx: @CrateContext, t: ty::t) -> Repr { if cases.len() == 1 { // Equivalent to a struct/tuple/newtype. - assert!(cases[0].discr == 0); + assert_eq!(cases[0].discr, 0); return Univariant(mk_struct(cx, cases[0].tys, false), false) } @@ -206,7 +206,7 @@ fn represent_type_uncached(cx: @CrateContext, t: ty::t) -> Repr { let discr = ~[ty::mk_int()]; return General(cases.map(|c| mk_struct(cx, discr + c.tys, false))) } - _ => cx.sess.bug(~"adt::represent_type called on non-ADT type") + _ => cx.sess.bug("adt::represent_type called on non-ADT type") } } @@ -353,7 +353,7 @@ pub fn trans_case(bcx: block, r: &Repr, discr: int) -> _match::opt_result { _match::single_result(rslt(bcx, C_int(bcx.ccx(), discr))) } Univariant(*) => { - bcx.ccx().sess.bug(~"no cases for univariants or structs") + bcx.ccx().sess.bug("no cases for univariants or structs") } General(*) => { _match::single_result(rslt(bcx, C_int(bcx.ccx(), discr))) @@ -377,12 +377,12 @@ pub fn trans_start_init(bcx: block, r: &Repr, val: ValueRef, discr: int) { Store(bcx, C_int(bcx.ccx(), discr), GEPi(bcx, val, [0, 0])) } Univariant(ref st, true) => { - assert!(discr == 0); + assert_eq!(discr, 0); Store(bcx, C_bool(true), GEPi(bcx, val, [0, st.fields.len() - 1])) } Univariant(*) => { - assert!(discr == 0); + assert_eq!(discr, 0); } General(*) => { Store(bcx, C_int(bcx.ccx(), discr), GEPi(bcx, val, [0, 0])) @@ -405,7 +405,7 @@ pub fn num_args(r: &Repr, discr: int) -> uint { match *r { CEnum(*) => 0, Univariant(ref st, dtor) => { - assert!(discr == 0); + assert_eq!(discr, 0); st.fields.len() - (if dtor { 1 } else { 0 }) } General(ref cases) => cases[discr as uint].fields.len() - 1, @@ -423,10 +423,10 @@ pub fn trans_field_ptr(bcx: block, r: &Repr, val: ValueRef, discr: int, // someday), it will need to return a possibly-new bcx as well. match *r { CEnum(*) => { - bcx.ccx().sess.bug(~"element access in C-like enum") + bcx.ccx().sess.bug("element access in C-like enum") } Univariant(ref st, _dtor) => { - assert!(discr == 0); + assert_eq!(discr, 0); struct_field_ptr(bcx, st, val, ix, false) } General(ref cases) => { @@ -439,7 +439,7 @@ pub fn trans_field_ptr(bcx: block, r: &Repr, val: ValueRef, discr: int, // The unit-like case might have a nonzero number of unit-like fields. // (e.g., Result or Either with () as one side.) let llty = type_of::type_of(bcx.ccx(), nullfields[ix]); - assert!(machine::llsize_of_alloc(bcx.ccx(), llty) == 0); + assert_eq!(machine::llsize_of_alloc(bcx.ccx(), llty), 0); // The contents of memory at this pointer can't matter, but use // the value that's "reasonable" in case of pointer comparison. PointerCast(bcx, val, T_ptr(llty)) @@ -468,8 +468,7 @@ fn struct_field_ptr(bcx: block, st: &Struct, val: ValueRef, ix: uint, pub fn trans_drop_flag_ptr(bcx: block, r: &Repr, val: ValueRef) -> ValueRef { match *r { Univariant(ref st, true) => GEPi(bcx, val, [0, st.fields.len() - 1]), - _ => bcx.ccx().sess.bug(~"tried to get drop flag of non-droppable \ - type") + _ => bcx.ccx().sess.bug("tried to get drop flag of non-droppable type") } } @@ -498,12 +497,12 @@ pub fn trans_const(ccx: @CrateContext, r: &Repr, discr: int, vals: &[ValueRef]) -> ValueRef { match *r { CEnum(min, max) => { - assert!(vals.len() == 0); + assert_eq!(vals.len(), 0); assert!(min <= discr && discr <= max); C_int(ccx, discr) } Univariant(ref st, _dro) => { - assert!(discr == 0); + assert_eq!(discr, 0); C_struct(build_const_struct(ccx, st, vals)) } General(ref cases) => { @@ -517,7 +516,7 @@ pub fn trans_const(ccx: @CrateContext, r: &Repr, discr: int, if discr == nndiscr { C_struct(build_const_struct(ccx, nonnull, vals)) } else { - assert!(vals.len() == 0); + assert_eq!(vals.len(), 0); let vals = do nonnull.fields.mapi |i, &ty| { let llty = type_of::sizing_type_of(ccx, ty); if i == ptrfield { C_null(llty) } else { C_undef(llty) } @@ -540,7 +539,7 @@ pub fn trans_const(ccx: @CrateContext, r: &Repr, discr: int, */ fn build_const_struct(ccx: @CrateContext, st: &Struct, vals: &[ValueRef]) -> ~[ValueRef] { - assert!(vals.len() == st.fields.len()); + assert_eq!(vals.len(), st.fields.len()); let mut offset = 0; let mut cfields = ~[]; @@ -564,6 +563,7 @@ fn build_const_struct(ccx: @CrateContext, st: &Struct, vals: &[ValueRef]) vals[i] }; cfields.push(val); + offset += machine::llsize_of_alloc(ccx, llty) as u64 } return cfields; @@ -600,7 +600,7 @@ pub fn const_get_discrim(ccx: @CrateContext, r: &Repr, val: ValueRef) pub fn const_get_field(ccx: @CrateContext, r: &Repr, val: ValueRef, _discr: int, ix: uint) -> ValueRef { match *r { - CEnum(*) => ccx.sess.bug(~"element access in C-like enum const"), + CEnum(*) => ccx.sess.bug("element access in C-like enum const"), Univariant(*) => const_struct_field(ccx, val, ix), General(*) => const_struct_field(ccx, val, ix + 1), NullablePointer{ _ } => const_struct_field(ccx, val, ix) diff --git a/src/librustc/middle/trans/asm.rs b/src/librustc/middle/trans/asm.rs index 9211939cd2af7..ac92ea7596399 100644 --- a/src/librustc/middle/trans/asm.rs +++ b/src/librustc/middle/trans/asm.rs @@ -12,12 +12,15 @@ # Translation of inline assembly. */ +use core::prelude::*; + use lib; use middle::trans::build::*; use middle::trans::callee; use middle::trans::common::*; use middle::ty; +use core::str; use syntax::ast; // Take an inline assembly expression and splat it out via LLVM @@ -88,14 +91,15 @@ pub fn trans_inline_asm(bcx: block, ia: &ast::inline_asm) -> block { let mut clobbers = getClobbers(); if *ia.clobbers != ~"" && clobbers != ~"" { - clobbers = *ia.clobbers + ~"," + clobbers; + clobbers = *ia.clobbers + "," + clobbers; } else { clobbers += *ia.clobbers; }; // Add the clobbers to our constraints list if clobbers != ~"" && constraints != ~"" { - constraints += ~"," + clobbers; + constraints += ","; + constraints += clobbers; } else { constraints += clobbers; } diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index b5cca20d8eccb..ba88fe09e70ab 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -23,6 +23,8 @@ // but many TypeRefs correspond to one ty::t; for instance, tup(int, int, // int) and rec(x=int, y=int, z=int) will have the same TypeRef. +use core::prelude::*; + use back::link::{mangle_exported_name}; use back::{link, abi, upcall}; use driver::session; @@ -50,7 +52,7 @@ use middle::trans::foreign; use middle::trans::glue; use middle::trans::inline; use middle::trans::machine; -use middle::trans::machine::llsize_of; +use middle::trans::machine::{llalign_of_min, llsize_of}; use middle::trans::meth; use middle::trans::monomorphize; use middle::trans::reachable; @@ -64,14 +66,20 @@ use util::ppaux::{Repr, ty_to_str}; use core::hash; use core::hashmap::{HashMap, HashSet}; +use core::int; +use core::io; use core::libc::c_uint; -use std::time; +use core::str; +use core::uint; +use core::vec; +use extra::time; use syntax::ast::ident; use syntax::ast_map::{path, path_elt_to_str, path_name}; use syntax::ast_util::{local_def, path_to_ident}; use syntax::attr; use syntax::codemap::span; -use syntax::parse::token::special_idents; +use syntax::parse::token; +use syntax::parse::token::{special_idents}; use syntax::print::pprust::stmt_to_str; use syntax::visit; use syntax::{ast, ast_util, codemap, ast_map}; @@ -235,7 +243,7 @@ pub fn umin(cx: block, a: ValueRef, b: ValueRef) -> ValueRef { pub fn ptr_offs(bcx: block, base: ValueRef, sz: ValueRef) -> ValueRef { let _icx = bcx.insn_ctxt("ptr_offs"); let raw = PointerCast(bcx, base, T_ptr(T_i8())); - InBoundsGEP(bcx, raw, ~[sz]) + InBoundsGEP(bcx, raw, [sz]) } // Increment a pointer by a given amount and then cast it to be a pointer @@ -296,7 +304,7 @@ pub fn malloc_raw_dyn(bcx: block, let bcx = callee::trans_lang_call( bcx, langcall, - ~[tydesc, size], + [tydesc, size], expr::SaveIn(rval)); let r = rslt(bcx, PointerCast(bcx, Load(bcx, rval), llty)); maybe_set_managed_unique_rc(r.bcx, r.val, heap); @@ -314,7 +322,7 @@ pub fn malloc_raw_dyn(bcx: block, pub fn non_gc_box_cast(bcx: block, val: ValueRef) -> ValueRef { unsafe { debug!("non_gc_box_cast"); - add_comment(bcx, ~"non_gc_box_cast"); + add_comment(bcx, "non_gc_box_cast"); assert!(llvm::LLVMGetPointerAddressSpace(val_ty(val)) == gc_box_addrspace || bcx.unreachable); let non_gc_t = T_ptr(llvm::LLVMGetElementType(val_ty(val))); @@ -496,7 +504,7 @@ pub fn get_res_dtor(ccx: @CrateContext, } else { did }; - assert!(did.crate == ast::local_crate); + assert_eq!(did.crate, ast::local_crate); let (val, _) = monomorphize::monomorphic_fn(ccx, did, substs, @@ -563,8 +571,8 @@ pub fn compare_scalar_types(cx: block, } _ => { // Should never get here, because t is scalar. - cx.sess().bug(~"non-scalar type passed to \ - compare_scalar_types") + cx.sess().bug("non-scalar type passed to \ + compare_scalar_types") } } } @@ -579,8 +587,8 @@ pub fn compare_scalar_values(cx: block, -> ValueRef { let _icx = cx.insn_ctxt("compare_scalar_values"); fn die(cx: block) -> ! { - cx.tcx().sess.bug(~"compare_scalar_values: must be a\ - comparison operator"); + cx.tcx().sess.bug("compare_scalar_values: must be a\ + comparison operator"); } match nt { nil_type => { @@ -720,18 +728,18 @@ pub fn iter_structural_ty(cx: block, av: ValueRef, t: ty::t, _match::single_result(r) => { AddCase(llswitch, r.val, variant_cx.llbb) } - _ => ccx.sess.unimpl(~"value from adt::trans_case \ - in iter_structural_ty") + _ => ccx.sess.unimpl("value from adt::trans_case \ + in iter_structural_ty") } Br(variant_cx, next_cx.llbb); } cx = next_cx; } - _ => ccx.sess.unimpl(~"value from adt::trans_switch \ - in iter_structural_ty") + _ => ccx.sess.unimpl("value from adt::trans_switch \ + in iter_structural_ty") } } - _ => cx.sess().unimpl(~"type in iter_structural_ty") + _ => cx.sess().unimpl("type in iter_structural_ty") } return cx; } @@ -943,7 +951,8 @@ pub fn in_lpad_scope_cx(bcx: block, f: &fn(si: &mut scope_info)) { pub fn get_landing_pad(bcx: block) -> BasicBlockRef { let _icx = bcx.insn_ctxt("get_landing_pad"); - let mut cached = None, pad_bcx = bcx; // Guaranteed to be set below + let mut cached = None; + let mut pad_bcx = bcx; // Guaranteed to be set below do in_lpad_scope_cx(bcx) |inf| { // If there is a valid landing pad still around, use it match inf.landing_pad { @@ -959,7 +968,7 @@ pub fn get_landing_pad(bcx: block) -> BasicBlockRef { // The landing pad return type (the type being propagated). Not sure what // this represents but it's determined by the personality function and // this is what the EH proposal example uses. - let llretty = T_struct(~[T_ptr(T_i8()), T_i32()], false); + let llretty = T_struct([T_ptr(T_i8()), T_i32()], false); // The exception handling personality function. This is the C++ // personality function __gxx_personality_v0, wrapped in our naming // convention. @@ -972,7 +981,7 @@ pub fn get_landing_pad(bcx: block) -> BasicBlockRef { // Because we may have unwound across a stack boundary, we must call into // the runtime to figure out which stack segment we are on and place the // stack limit back into the TLS. - Call(pad_bcx, bcx.ccx().upcalls.reset_stack_limit, ~[]); + Call(pad_bcx, bcx.ccx().upcalls.reset_stack_limit, []); // We store the retval in a function-central alloca, so that calls to // Resume can find it. @@ -1098,8 +1107,8 @@ pub fn init_local(bcx: block, local: @ast::local) -> block { } } - let llptr = match bcx.fcx.lllocals.find(&local.node.id) { - Some(&local_mem(v)) => v, + let llptr = match bcx.fcx.lllocals.find_copy(&local.node.id) { + Some(v) => v, _ => { bcx.tcx().sess.span_bug(local.span, "init_local: Someone forgot to document why it's\ @@ -1147,19 +1156,17 @@ pub fn trans_stmt(cx: block, s: &ast::stmt) -> block { } ast::stmt_decl(d, _) => { match d.node { - ast::decl_local(ref locals) => { - for locals.each |local| { - bcx = init_local(bcx, *local); - if cx.sess().opts.extra_debuginfo - && fcx_has_nonzero_span(bcx.fcx) { - debuginfo::create_local_var(bcx, *local); - } + ast::decl_local(ref local) => { + bcx = init_local(bcx, *local); + if cx.sess().opts.extra_debuginfo + && fcx_has_nonzero_span(bcx.fcx) { + debuginfo::create_local_var(bcx, *local); } } ast::decl_item(i) => trans_item(*cx.fcx.ccx, i) } } - ast::stmt_mac(*) => cx.tcx().sess.bug(~"unexpanded macro") + ast::stmt_mac(*) => cx.tcx().sess.bug("unexpanded macro") } return bcx; @@ -1289,7 +1296,8 @@ pub fn cleanup_and_leave(bcx: block, upto: Option, leave: Option) { let _icx = bcx.insn_ctxt("cleanup_and_leave"); - let mut cur = bcx, bcx = bcx; + let mut cur = bcx; + let mut bcx = bcx; let is_lpad = leave == None; loop { debug!("cleanup_and_leave: leaving %s", cur.to_str()); @@ -1395,15 +1403,11 @@ pub fn block_locals(b: &ast::blk, it: &fn(@ast::local)) { match s.node { ast::stmt_decl(d, _) => { match d.node { - ast::decl_local(ref locals) => { - for locals.each |local| { - it(*local); - } - } - _ => {/* fall through */ } + ast::decl_local(ref local) => it(*local), + _ => {} /* fall through */ } } - _ => {/* fall through */ } + _ => {} /* fall through */ } } } @@ -1425,7 +1429,7 @@ pub fn alloc_local(cx: block, local: @ast::local) -> block { }); } } - cx.fcx.lllocals.insert(local.node.id, local_mem(val)); + cx.fcx.lllocals.insert(local.node.id, val); cx } @@ -1440,12 +1444,7 @@ pub fn with_cond(bcx: block, val: ValueRef, f: &fn(block) -> block) -> block { next_cx } -pub fn call_memcpy(cx: block, dst: ValueRef, src: ValueRef, - n_bytes: ValueRef) { - // FIXME (Related to #1645, I think?): Provide LLVM with better - // alignment information when the alignment is statically known (it must - // be nothing more than a constant int, or LLVM complains -- not even a - // constant element of a tydesc works). +pub fn call_memcpy(cx: block, dst: ValueRef, src: ValueRef, n_bytes: ValueRef, align: u32) { let _icx = cx.insn_ctxt("call_memcpy"); let ccx = cx.ccx(); let key = match ccx.sess.targ_cfg.arch { @@ -1460,17 +1459,19 @@ pub fn call_memcpy(cx: block, dst: ValueRef, src: ValueRef, let src_ptr = PointerCast(cx, src, T_ptr(T_i8())); let dst_ptr = PointerCast(cx, dst, T_ptr(T_i8())); let size = IntCast(cx, n_bytes, ccx.int_type); - let align = C_i32(1i32); + let align = C_i32(align as i32); let volatile = C_i1(false); - Call(cx, memcpy, ~[dst_ptr, src_ptr, size, align, volatile]); + Call(cx, memcpy, [dst_ptr, src_ptr, size, align, volatile]); } pub fn memcpy_ty(bcx: block, dst: ValueRef, src: ValueRef, t: ty::t) { let _icx = bcx.insn_ctxt("memcpy_ty"); let ccx = bcx.ccx(); if ty::type_is_structural(t) { - let llsz = llsize_of(ccx, type_of::type_of(ccx, t)); - call_memcpy(bcx, dst, src, llsz); + let llty = type_of::type_of(ccx, t); + let llsz = llsize_of(ccx, llty); + let llalign = llalign_of_min(ccx, llty); + call_memcpy(bcx, dst, src, llsz, llalign as u32); } else { Store(bcx, Load(bcx, src), dst); } @@ -1507,9 +1508,9 @@ pub fn memzero(cx: block, llptr: ValueRef, llty: TypeRef) { let llptr = PointerCast(cx, llptr, T_ptr(T_i8())); let llzeroval = C_u8(0); let size = IntCast(cx, machine::llsize_of(ccx, llty), ccx.int_type); - let align = C_i32(1i32); + let align = C_i32(llalign_of_min(ccx, llty) as i32); let volatile = C_i1(false); - Call(cx, llintrinsicfn, ~[llptr, llzeroval, size, align, volatile]); + Call(cx, llintrinsicfn, [llptr, llzeroval, size, align, volatile]); } pub fn alloc_ty(bcx: block, t: ty::t) -> ValueRef { @@ -1559,9 +1560,9 @@ pub struct BasicBlocks { pub fn mk_standard_basic_blocks(llfn: ValueRef) -> BasicBlocks { unsafe { BasicBlocks { - sa: str::as_c_str(~"static_allocas", + sa: str::as_c_str("static_allocas", |buf| llvm::LLVMAppendBasicBlock(llfn, buf)), - rt: str::as_c_str(~"return", + rt: str::as_c_str("return", |buf| llvm::LLVMAppendBasicBlock(llfn, buf)) } } @@ -1613,10 +1614,11 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext, } }; let is_immediate = ty::type_is_immediate(substd_output_type); - let fcx = @mut fn_ctxt_ { llfn: llfndecl, - llenv: unsafe { llvm::LLVMGetParam(llfndecl, 1u as c_uint) }, + llenv: unsafe { + llvm::LLVMGetUndef(T_ptr(T_i8())) + }, llretptr: None, llstaticallocas: llbbs.sa, llloadenv: None, @@ -1635,7 +1637,9 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext, path: path, ccx: @ccx }; - + fcx.llenv = unsafe { + llvm::LLVMGetParam(llfndecl, fcx.env_arg_pos() as c_uint) + }; fcx.llretptr = Some(make_return_pointer(fcx, substd_output_type)); fcx } @@ -1691,8 +1695,21 @@ pub fn create_llargs_for_fn_args(cx: fn_ctxt, // llvm::LLVMGetParam for each argument. vec::from_fn(args.len(), |i| { unsafe { - let arg_n = first_real_arg + i; - llvm::LLVMGetParam(cx.llfn, arg_n as c_uint) + let arg_n = cx.arg_pos(i); + let arg = &args[i]; + let llarg = llvm::LLVMGetParam(cx.llfn, arg_n as c_uint); + + match arg.ty.node { + // `~` pointers never alias other parameters, because ownership was transferred + ast::ty_uniq(_) => { + llvm::LLVMAddAttribute(llarg, lib::llvm::NoAliasAttribute as c_uint); + } + // FIXME: #6785: `&mut` can only alias `&const` and `@mut`, we should check for + // those in the other parameters and then mark it as `noalias` if there aren't any + _ => {} + } + + llarg } }) } @@ -1706,12 +1723,19 @@ pub fn copy_args_to_allocas(fcx: fn_ctxt, let mut bcx = bcx; match fcx.llself { - Some(copy slf) => { + Some(slf) => { // We really should do this regardless of whether self is owned, but // it doesn't work right with default method impls yet. (FIXME: #2794) if slf.is_owned { - let self_val = PointerCast(bcx, slf.v, - T_ptr(type_of(bcx.ccx(), slf.t))); + let self_val = if datum::appropriate_mode(slf.t).is_by_value() { + let tmp = BitCast(bcx, slf.v, type_of(bcx.ccx(), slf.t)); + let alloc = alloc_ty(bcx, slf.t); + Store(bcx, tmp, alloc); + alloc + } else { + PointerCast(bcx, slf.v, T_ptr(type_of(bcx.ccx(), slf.t))) + }; + fcx.llself = Some(ValSelfData {v: self_val, ..slf}); add_clean(bcx, self_val, slf.t); } @@ -1748,7 +1772,7 @@ pub fn copy_args_to_allocas(fcx: fn_ctxt, false, _match::BindArgument); - fcx.llargs.insert(arg_id, local_mem(llarg)); + fcx.llargs.insert(arg_id, llarg); if fcx.ccx.sess.opts.extra_debuginfo && fcx_has_nonzero_span(fcx) { debuginfo::create_arg(bcx, args[arg_n], args[arg_n].ty.span); @@ -1781,7 +1805,7 @@ pub fn build_return_block(fcx: fn_ctxt) { pub fn tie_up_header_blocks(fcx: fn_ctxt, lltop: BasicBlockRef) { let _icx = fcx.insn_ctxt("tie_up_header_blocks"); match fcx.llloadenv { - Some(copy ll) => { + Some(ll) => { Br(raw_block(fcx, false, fcx.llstaticallocas), ll); Br(raw_block(fcx, false, ll), lltop); } @@ -1960,7 +1984,8 @@ pub fn trans_enum_variant(ccx: @CrateContext, None); let raw_llargs = create_llargs_for_fn_args(fcx, no_self, fn_args); - let bcx = top_scope_block(fcx, None), lltop = bcx.llbb; + let bcx = top_scope_block(fcx, None); + let lltop = bcx.llbb; let arg_tys = ty::ty_fn_args(node_id_type(bcx, variant.node.id)); let bcx = copy_args_to_allocas(fcx, bcx, fn_args, raw_llargs, arg_tys); @@ -1969,7 +1994,7 @@ pub fn trans_enum_variant(ccx: @CrateContext, debug!("trans_enum_variant: name=%s tps=%s repr=%? enum_ty=%s", unsafe { str::raw::from_c_str(llvm::LLVMGetValueName(llfndecl)) }, - ~"[" + str::connect(ty_param_substs.map(|&t| ty_to_str(ccx.tcx, t)), ", ") + ~"]", + ~"[" + str::connect(ty_param_substs.map(|&t| ty_to_str(ccx.tcx, t)), ", ") + "]", repr, ty_to_str(ccx.tcx, enum_ty)); adt::trans_start_init(bcx, repr, fcx.llretptr.get(), disr); @@ -1984,7 +2009,7 @@ pub fn trans_enum_variant(ccx: @CrateContext, // this function as an opaque blob due to the way that type_of() // works. So we have to cast to the destination's view of the type. let llarg = match fcx.llargs.find(&va.id) { - Some(&local_mem(x)) => x, + Some(&x) => x, _ => fail!("trans_enum_variant: how do we know this works?"), }; let arg_ty = arg_tys[i]; @@ -2054,13 +2079,7 @@ pub fn trans_tuple_struct(ccx: @CrateContext, fcx.llretptr.get(), 0, i); - let llarg = match fcx.llargs.get_copy(&field.node.id) { - local_mem(x) => x, - _ => { - ccx.tcx.sess.bug(~"trans_tuple_struct: llarg wasn't \ - local_mem") - } - }; + let llarg = fcx.llargs.get_copy(&field.node.id); let arg_ty = arg_tys[i]; memcpy_ty(bcx, lldestptr, llarg, arg_ty); } @@ -2105,7 +2124,7 @@ pub fn trans_item(ccx: @CrateContext, item: &ast::item) { let llfndecl = get_item_val(ccx, item.id); foreign::trans_foreign_fn(ccx, vec::append(/*bad*/copy *path, - ~[path_name(item.ident)]), + [path_name(item.ident)]), decl, body, llfndecl, @@ -2113,7 +2132,7 @@ pub fn trans_item(ccx: @CrateContext, item: &ast::item) { } else if !generics.is_type_parameterized() { let llfndecl = get_item_val(ccx, item.id); trans_fn(ccx, - vec::append(/*bad*/copy *path, ~[path_name(item.ident)]), + vec::append(/*bad*/copy *path, [path_name(item.ident)]), decl, body, llfndecl, @@ -2148,7 +2167,26 @@ pub fn trans_item(ccx: @CrateContext, item: &ast::item) { trans_enum_def(ccx, enum_definition, item.id, vi, &mut i); } } - ast::item_const(_, expr) => consts::trans_const(ccx, expr, item.id), + ast::item_const(_, expr) => { + consts::trans_const(ccx, expr, item.id); + // Do static_assert checking. It can't really be done much earlier because we need to get + // the value of the bool out of LLVM + for item.attrs.each |attr| { + match attr.node.value.node { + ast::meta_word(x) => { + if x.slice(0, x.len()) == "static_assert" { + let v = ccx.const_values.get_copy(&item.id); + unsafe { + if !(llvm::LLVMConstIntGetZExtValue(v) as bool) { + ccx.sess.span_fatal(expr.span, "static assertion failed"); + } + } + } + }, + _ => () + } + } + }, ast::item_foreign_mod(ref foreign_mod) => { foreign::trans_foreign_mod(ccx, path, foreign_mod); } @@ -2220,10 +2258,10 @@ pub fn register_fn_fuller(ccx: @CrateContext, -> ValueRef { debug!("register_fn_fuller creating fn for item %d with path %s", node_id, - ast_map::path_to_str(path, ccx.sess.parse_sess.interner)); + ast_map::path_to_str(path, token::get_ident_interner())); let ps = if attr::attrs_contains_name(attrs, "no_mangle") { - path_elt_to_str(*path.last(), ccx.sess.parse_sess.interner) + path_elt_to_str(*path.last(), token::get_ident_interner()) } else { mangle_exported_name(ccx, /*bad*/copy path, node_type) }; @@ -2263,19 +2301,26 @@ pub fn create_entry_wrapper(ccx: @CrateContext, fn create_main(ccx: @CrateContext, main_llfn: ValueRef) -> ValueRef { let nt = ty::mk_nil(); - let llfty = type_of_fn(ccx, ~[], nt); - let llfdecl = decl_fn(ccx.llmod, ~"_rust_main", + + let llfty = type_of_fn(ccx, [], nt); + let llfdecl = decl_fn(ccx.llmod, "_rust_main", lib::llvm::CCallConv, llfty); let fcx = new_fn_ctxt(ccx, ~[], llfdecl, nt, None); + // the args vector built in create_entry_fn will need + // be updated if this assertion starts to fail. + assert!(fcx.has_immediate_return_value); + let bcx = top_scope_block(fcx, None); let lltop = bcx.llbb; // Call main. - let lloutputarg = C_null(T_ptr(T_i8())); - let llenvarg = unsafe { llvm::LLVMGetParam(llfdecl, 1 as c_uint) }; - let args = ~[lloutputarg, llenvarg]; + let llenvarg = unsafe { + let env_arg = fcx.env_arg_pos(); + llvm::LLVMGetParam(llfdecl, env_arg as c_uint) + }; + let args = ~[llenvarg]; let llresult = Call(bcx, main_llfn, args); Store(bcx, llresult, fcx.llretptr.get()); @@ -2287,11 +2332,11 @@ pub fn create_entry_wrapper(ccx: @CrateContext, fn create_entry_fn(ccx: @CrateContext, rust_main: ValueRef, use_start_lang_item: bool) { - let llfty = T_fn(~[ccx.int_type, T_ptr(T_ptr(T_i8()))], ccx.int_type); + let llfty = T_fn([ccx.int_type, T_ptr(T_ptr(T_i8()))], ccx.int_type); // FIXME #4404 android JNI hacks let llfn = if *ccx.sess.building_library { - decl_cdecl_fn(ccx.llmod, ~"amain", llfty) + decl_cdecl_fn(ccx.llmod, "amain", llfty) } else { let main_name = match ccx.sess.targ_cfg.os { session::os_win32 => ~"WinMain@16", @@ -2299,7 +2344,7 @@ pub fn create_entry_wrapper(ccx: @CrateContext, }; decl_cdecl_fn(ccx.llmod, main_name, llfty) }; - let llbb = str::as_c_str(~"top", |buf| { + let llbb = str::as_c_str("top", |buf| { unsafe { llvm::LLVMAppendBasicBlock(llfn, buf) } @@ -2309,16 +2354,12 @@ pub fn create_entry_wrapper(ccx: @CrateContext, llvm::LLVMPositionBuilderAtEnd(bld, llbb); let start_def_id = ccx.tcx.lang_items.start_fn(); - if start_def_id.crate == ast::local_crate { - ccx.sess.bug(~"start lang item is never in the local crate") - } else { + if start_def_id.crate != ast::local_crate { let start_fn_type = csearch::get_type(ccx.tcx, start_def_id).ty; trans_external_path(ccx, start_def_id, start_fn_type); } - let retptr = llvm::LLVMBuildAlloca(bld, T_i8(), noname()); - let crate_map = ccx.crate_map; let opaque_crate_map = llvm::LLVMBuildPointerCast(bld, crate_map, @@ -2328,8 +2369,7 @@ pub fn create_entry_wrapper(ccx: @CrateContext, let (start_fn, args) = if use_start_lang_item { let start_def_id = ccx.tcx.lang_items.start_fn(); let start_fn = if start_def_id.crate == ast::local_crate { - ccx.sess.bug(~"start lang item is never in the local \ - crate") + get_item_val(ccx, start_def_id.node) } else { let start_fn_type = csearch::get_type(ccx.tcx, start_def_id).ty; @@ -2341,7 +2381,6 @@ pub fn create_entry_wrapper(ccx: @CrateContext, bld, rust_main, T_ptr(T_i8()), noname()); ~[ - retptr, C_null(T_opaque_box_ptr(ccx)), opaque_rust_main, llvm::LLVMGetParam(llfn, 0), @@ -2354,7 +2393,6 @@ pub fn create_entry_wrapper(ccx: @CrateContext, debug!("using user-defined start fn"); let args = { ~[ - retptr, C_null(T_opaque_box_ptr(ccx)), llvm::LLVMGetParam(llfn, 0 as c_uint), llvm::LLVMGetParam(llfn, 1 as c_uint), @@ -2391,7 +2429,7 @@ pub fn item_path(ccx: @CrateContext, i: @ast::item) -> path { // separate map for paths? _ => fail!("item_path") }; - vec::append(/*bad*/copy *base, ~[path_name(i.ident)]) + vec::append(/*bad*/copy *base, [path_name(i.ident)]) } pub fn get_item_val(ccx: @CrateContext, id: ast::node_id) -> ValueRef { @@ -2404,7 +2442,7 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::node_id) -> ValueRef { let val = match tcx.items.get_copy(&id) { ast_map::node_item(i, pth) => { let my_path = vec::append(/*bad*/copy *pth, - ~[path_name(i.ident)]); + [path_name(i.ident)]); match i.node { ast::item_const(_, expr) => { let typ = ty::node_id_to_type(tcx, i.id); @@ -2442,8 +2480,8 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::node_id) -> ValueRef { debug!("get_item_val(): processing a node_trait_method"); match *trait_method { ast::required(_) => { - ccx.sess.bug(~"unexpected variant: required trait method in \ - get_item_val()"); + ccx.sess.bug("unexpected variant: required trait method in \ + get_item_val()"); } ast::provided(m) => { exprt = true; @@ -2461,13 +2499,13 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::node_id) -> ValueRef { ast::foreign_item_fn(*) => { register_fn(ccx, ni.span, vec::append(/*bad*/copy *pth, - ~[path_name(ni.ident)]), + [path_name(ni.ident)]), ni.id, ni.attrs) } ast::foreign_item_const(*) => { let typ = ty::node_id_to_type(tcx, ni.id); - let ident = ccx.sess.parse_sess.interner.get(ni.ident); + let ident = token::ident_to_str(&ni.ident); let g = do str::as_c_str(*ident) |buf| { unsafe { llvm::LLVMAddGlobal(ccx.llmod, @@ -2486,8 +2524,8 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::node_id) -> ValueRef { ast::tuple_variant_kind(ref args) => { assert!(args.len() != 0u); let pth = vec::append(/*bad*/copy *pth, - ~[path_name(enm.ident), - path_name((*v).node.name)]); + [path_name(enm.ident), + path_name((*v).node.name)]); llfn = match enm.node { ast::item_enum(_, _) => { register_fn(ccx, (*v).span, pth, id, enm.attrs) @@ -2507,8 +2545,8 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::node_id) -> ValueRef { // Only register the constructor if this is a tuple-like struct. match struct_def.ctor_id { None => { - tcx.sess.bug(~"attempt to register a constructor of \ - a non-tuple-like struct") + tcx.sess.bug("attempt to register a constructor of \ + a non-tuple-like struct") } Some(ctor_id) => { let llfn = register_fn(ccx, @@ -2541,7 +2579,7 @@ pub fn register_method(ccx: @CrateContext, pth: @ast_map::path, m: @ast::method) -> ValueRef { let mty = ty::node_id_to_type(ccx.tcx, id); - let pth = vec::append(/*bad*/copy *pth, ~[path_name((ccx.names)("meth")), + let pth = vec::append(/*bad*/copy *pth, [path_name((ccx.names)("meth")), path_name(m.ident)]); let llfn = register_fn_full(ccx, m.span, pth, id, m.attrs, mty); set_inline_hint_if_appr(m.attrs, llfn); @@ -2559,7 +2597,7 @@ pub fn trans_constant(ccx: @CrateContext, it: @ast::item) { let mut i = 0; let path = item_path(ccx, it); for (*enum_definition).variants.each |variant| { - let p = vec::append(/*bad*/copy path, ~[ + let p = vec::append(/*bad*/copy path, [ path_name(variant.node.name), path_name(special_idents::descrim) ]); @@ -2617,126 +2655,126 @@ pub fn declare_intrinsics(llmod: ModuleRef) -> HashMap<~str, ValueRef> { let T_trap_args: ~[TypeRef] = ~[]; let T_frameaddress_args: ~[TypeRef] = ~[T_i32()]; let gcroot = - decl_cdecl_fn(llmod, ~"llvm.gcroot", - T_fn(~[T_ptr(T_ptr(T_i8())), T_ptr(T_i8())], + decl_cdecl_fn(llmod, "llvm.gcroot", + T_fn([T_ptr(T_ptr(T_i8())), T_ptr(T_i8())], T_void())); let gcread = - decl_cdecl_fn(llmod, ~"llvm.gcread", - T_fn(~[T_ptr(T_i8()), T_ptr(T_ptr(T_i8()))], + decl_cdecl_fn(llmod, "llvm.gcread", + T_fn([T_ptr(T_i8()), T_ptr(T_ptr(T_i8()))], T_void())); let memcpy32 = - decl_cdecl_fn(llmod, ~"llvm.memcpy.p0i8.p0i8.i32", + decl_cdecl_fn(llmod, "llvm.memcpy.p0i8.p0i8.i32", T_fn(copy T_memcpy32_args, T_void())); let memcpy64 = - decl_cdecl_fn(llmod, ~"llvm.memcpy.p0i8.p0i8.i64", + decl_cdecl_fn(llmod, "llvm.memcpy.p0i8.p0i8.i64", T_fn(copy T_memcpy64_args, T_void())); let memmove32 = - decl_cdecl_fn(llmod, ~"llvm.memmove.p0i8.p0i8.i32", + decl_cdecl_fn(llmod, "llvm.memmove.p0i8.p0i8.i32", T_fn(T_memcpy32_args, T_void())); let memmove64 = - decl_cdecl_fn(llmod, ~"llvm.memmove.p0i8.p0i8.i64", + decl_cdecl_fn(llmod, "llvm.memmove.p0i8.p0i8.i64", T_fn(T_memcpy64_args, T_void())); let memset32 = - decl_cdecl_fn(llmod, ~"llvm.memset.p0i8.i32", + decl_cdecl_fn(llmod, "llvm.memset.p0i8.i32", T_fn(T_memset32_args, T_void())); let memset64 = - decl_cdecl_fn(llmod, ~"llvm.memset.p0i8.i64", + decl_cdecl_fn(llmod, "llvm.memset.p0i8.i64", T_fn(T_memset64_args, T_void())); - let trap = decl_cdecl_fn(llmod, ~"llvm.trap", T_fn(T_trap_args, + let trap = decl_cdecl_fn(llmod, "llvm.trap", T_fn(T_trap_args, T_void())); - let frameaddress = decl_cdecl_fn(llmod, ~"llvm.frameaddress", + let frameaddress = decl_cdecl_fn(llmod, "llvm.frameaddress", T_fn(T_frameaddress_args, T_ptr(T_i8()))); - let sqrtf32 = decl_cdecl_fn(llmod, ~"llvm.sqrt.f32", - T_fn(~[T_f32()], T_f32())); - let sqrtf64 = decl_cdecl_fn(llmod, ~"llvm.sqrt.f64", - T_fn(~[T_f64()], T_f64())); - let powif32 = decl_cdecl_fn(llmod, ~"llvm.powi.f32", - T_fn(~[T_f32(), T_i32()], T_f32())); - let powif64 = decl_cdecl_fn(llmod, ~"llvm.powi.f64", - T_fn(~[T_f64(), T_i32()], T_f64())); - let sinf32 = decl_cdecl_fn(llmod, ~"llvm.sin.f32", - T_fn(~[T_f32()], T_f32())); - let sinf64 = decl_cdecl_fn(llmod, ~"llvm.sin.f64", - T_fn(~[T_f64()], T_f64())); - let cosf32 = decl_cdecl_fn(llmod, ~"llvm.cos.f32", - T_fn(~[T_f32()], T_f32())); - let cosf64 = decl_cdecl_fn(llmod, ~"llvm.cos.f64", - T_fn(~[T_f64()], T_f64())); - let powf32 = decl_cdecl_fn(llmod, ~"llvm.pow.f32", - T_fn(~[T_f32(), T_f32()], T_f32())); - let powf64 = decl_cdecl_fn(llmod, ~"llvm.pow.f64", - T_fn(~[T_f64(), T_f64()], T_f64())); - let expf32 = decl_cdecl_fn(llmod, ~"llvm.exp.f32", - T_fn(~[T_f32()], T_f32())); - let expf64 = decl_cdecl_fn(llmod, ~"llvm.exp.f64", - T_fn(~[T_f64()], T_f64())); - let exp2f32 = decl_cdecl_fn(llmod, ~"llvm.exp2.f32", - T_fn(~[T_f32()], T_f32())); - let exp2f64 = decl_cdecl_fn(llmod, ~"llvm.exp2.f64", - T_fn(~[T_f64()], T_f64())); - let logf32 = decl_cdecl_fn(llmod, ~"llvm.log.f32", - T_fn(~[T_f32()], T_f32())); - let logf64 = decl_cdecl_fn(llmod, ~"llvm.log.f64", - T_fn(~[T_f64()], T_f64())); - let log10f32 = decl_cdecl_fn(llmod, ~"llvm.log10.f32", - T_fn(~[T_f32()], T_f32())); - let log10f64 = decl_cdecl_fn(llmod, ~"llvm.log10.f64", - T_fn(~[T_f64()], T_f64())); - let log2f32 = decl_cdecl_fn(llmod, ~"llvm.log2.f32", - T_fn(~[T_f32()], T_f32())); - let log2f64 = decl_cdecl_fn(llmod, ~"llvm.log2.f64", - T_fn(~[T_f64()], T_f64())); - let fmaf32 = decl_cdecl_fn(llmod, ~"llvm.fma.f32", - T_fn(~[T_f32(), T_f32(), T_f32()], T_f32())); - let fmaf64 = decl_cdecl_fn(llmod, ~"llvm.fma.f64", - T_fn(~[T_f64(), T_f64(), T_f64()], T_f64())); - let fabsf32 = decl_cdecl_fn(llmod, ~"llvm.fabs.f32", - T_fn(~[T_f32()], T_f32())); - let fabsf64 = decl_cdecl_fn(llmod, ~"llvm.fabs.f64", - T_fn(~[T_f64()], T_f64())); - let floorf32 = decl_cdecl_fn(llmod, ~"llvm.floor.f32", - T_fn(~[T_f32()], T_f32())); - let floorf64 = decl_cdecl_fn(llmod, ~"llvm.floor.f64", - T_fn(~[T_f64()], T_f64())); - let ceilf32 = decl_cdecl_fn(llmod, ~"llvm.ceil.f32", - T_fn(~[T_f32()], T_f32())); - let ceilf64 = decl_cdecl_fn(llmod, ~"llvm.ceil.f64", - T_fn(~[T_f64()], T_f64())); - let truncf32 = decl_cdecl_fn(llmod, ~"llvm.trunc.f32", - T_fn(~[T_f32()], T_f32())); - let truncf64 = decl_cdecl_fn(llmod, ~"llvm.trunc.f64", - T_fn(~[T_f64()], T_f64())); - let ctpop8 = decl_cdecl_fn(llmod, ~"llvm.ctpop.i8", - T_fn(~[T_i8()], T_i8())); - let ctpop16 = decl_cdecl_fn(llmod, ~"llvm.ctpop.i16", - T_fn(~[T_i16()], T_i16())); - let ctpop32 = decl_cdecl_fn(llmod, ~"llvm.ctpop.i32", - T_fn(~[T_i32()], T_i32())); - let ctpop64 = decl_cdecl_fn(llmod, ~"llvm.ctpop.i64", - T_fn(~[T_i64()], T_i64())); - let ctlz8 = decl_cdecl_fn(llmod, ~"llvm.ctlz.i8", - T_fn(~[T_i8(), T_i1()], T_i8())); - let ctlz16 = decl_cdecl_fn(llmod, ~"llvm.ctlz.i16", - T_fn(~[T_i16(), T_i1()], T_i16())); - let ctlz32 = decl_cdecl_fn(llmod, ~"llvm.ctlz.i32", - T_fn(~[T_i32(), T_i1()], T_i32())); - let ctlz64 = decl_cdecl_fn(llmod, ~"llvm.ctlz.i64", - T_fn(~[T_i64(), T_i1()], T_i64())); - let cttz8 = decl_cdecl_fn(llmod, ~"llvm.cttz.i8", - T_fn(~[T_i8(), T_i1()], T_i8())); - let cttz16 = decl_cdecl_fn(llmod, ~"llvm.cttz.i16", - T_fn(~[T_i16(), T_i1()], T_i16())); - let cttz32 = decl_cdecl_fn(llmod, ~"llvm.cttz.i32", - T_fn(~[T_i32(), T_i1()], T_i32())); - let cttz64 = decl_cdecl_fn(llmod, ~"llvm.cttz.i64", - T_fn(~[T_i64(), T_i1()], T_i64())); - let bswap16 = decl_cdecl_fn(llmod, ~"llvm.bswap.i16", - T_fn(~[T_i16()], T_i16())); - let bswap32 = decl_cdecl_fn(llmod, ~"llvm.bswap.i32", - T_fn(~[T_i32()], T_i32())); - let bswap64 = decl_cdecl_fn(llmod, ~"llvm.bswap.i64", - T_fn(~[T_i64()], T_i64())); + let sqrtf32 = decl_cdecl_fn(llmod, "llvm.sqrt.f32", + T_fn([T_f32()], T_f32())); + let sqrtf64 = decl_cdecl_fn(llmod, "llvm.sqrt.f64", + T_fn([T_f64()], T_f64())); + let powif32 = decl_cdecl_fn(llmod, "llvm.powi.f32", + T_fn([T_f32(), T_i32()], T_f32())); + let powif64 = decl_cdecl_fn(llmod, "llvm.powi.f64", + T_fn([T_f64(), T_i32()], T_f64())); + let sinf32 = decl_cdecl_fn(llmod, "llvm.sin.f32", + T_fn([T_f32()], T_f32())); + let sinf64 = decl_cdecl_fn(llmod, "llvm.sin.f64", + T_fn([T_f64()], T_f64())); + let cosf32 = decl_cdecl_fn(llmod, "llvm.cos.f32", + T_fn([T_f32()], T_f32())); + let cosf64 = decl_cdecl_fn(llmod, "llvm.cos.f64", + T_fn([T_f64()], T_f64())); + let powf32 = decl_cdecl_fn(llmod, "llvm.pow.f32", + T_fn([T_f32(), T_f32()], T_f32())); + let powf64 = decl_cdecl_fn(llmod, "llvm.pow.f64", + T_fn([T_f64(), T_f64()], T_f64())); + let expf32 = decl_cdecl_fn(llmod, "llvm.exp.f32", + T_fn([T_f32()], T_f32())); + let expf64 = decl_cdecl_fn(llmod, "llvm.exp.f64", + T_fn([T_f64()], T_f64())); + let exp2f32 = decl_cdecl_fn(llmod, "llvm.exp2.f32", + T_fn([T_f32()], T_f32())); + let exp2f64 = decl_cdecl_fn(llmod, "llvm.exp2.f64", + T_fn([T_f64()], T_f64())); + let logf32 = decl_cdecl_fn(llmod, "llvm.log.f32", + T_fn([T_f32()], T_f32())); + let logf64 = decl_cdecl_fn(llmod, "llvm.log.f64", + T_fn([T_f64()], T_f64())); + let log10f32 = decl_cdecl_fn(llmod, "llvm.log10.f32", + T_fn([T_f32()], T_f32())); + let log10f64 = decl_cdecl_fn(llmod, "llvm.log10.f64", + T_fn([T_f64()], T_f64())); + let log2f32 = decl_cdecl_fn(llmod, "llvm.log2.f32", + T_fn([T_f32()], T_f32())); + let log2f64 = decl_cdecl_fn(llmod, "llvm.log2.f64", + T_fn([T_f64()], T_f64())); + let fmaf32 = decl_cdecl_fn(llmod, "llvm.fma.f32", + T_fn([T_f32(), T_f32(), T_f32()], T_f32())); + let fmaf64 = decl_cdecl_fn(llmod, "llvm.fma.f64", + T_fn([T_f64(), T_f64(), T_f64()], T_f64())); + let fabsf32 = decl_cdecl_fn(llmod, "llvm.fabs.f32", + T_fn([T_f32()], T_f32())); + let fabsf64 = decl_cdecl_fn(llmod, "llvm.fabs.f64", + T_fn([T_f64()], T_f64())); + let floorf32 = decl_cdecl_fn(llmod, "llvm.floor.f32", + T_fn([T_f32()], T_f32())); + let floorf64 = decl_cdecl_fn(llmod, "llvm.floor.f64", + T_fn([T_f64()], T_f64())); + let ceilf32 = decl_cdecl_fn(llmod, "llvm.ceil.f32", + T_fn([T_f32()], T_f32())); + let ceilf64 = decl_cdecl_fn(llmod, "llvm.ceil.f64", + T_fn([T_f64()], T_f64())); + let truncf32 = decl_cdecl_fn(llmod, "llvm.trunc.f32", + T_fn([T_f32()], T_f32())); + let truncf64 = decl_cdecl_fn(llmod, "llvm.trunc.f64", + T_fn([T_f64()], T_f64())); + let ctpop8 = decl_cdecl_fn(llmod, "llvm.ctpop.i8", + T_fn([T_i8()], T_i8())); + let ctpop16 = decl_cdecl_fn(llmod, "llvm.ctpop.i16", + T_fn([T_i16()], T_i16())); + let ctpop32 = decl_cdecl_fn(llmod, "llvm.ctpop.i32", + T_fn([T_i32()], T_i32())); + let ctpop64 = decl_cdecl_fn(llmod, "llvm.ctpop.i64", + T_fn([T_i64()], T_i64())); + let ctlz8 = decl_cdecl_fn(llmod, "llvm.ctlz.i8", + T_fn([T_i8(), T_i1()], T_i8())); + let ctlz16 = decl_cdecl_fn(llmod, "llvm.ctlz.i16", + T_fn([T_i16(), T_i1()], T_i16())); + let ctlz32 = decl_cdecl_fn(llmod, "llvm.ctlz.i32", + T_fn([T_i32(), T_i1()], T_i32())); + let ctlz64 = decl_cdecl_fn(llmod, "llvm.ctlz.i64", + T_fn([T_i64(), T_i1()], T_i64())); + let cttz8 = decl_cdecl_fn(llmod, "llvm.cttz.i8", + T_fn([T_i8(), T_i1()], T_i8())); + let cttz16 = decl_cdecl_fn(llmod, "llvm.cttz.i16", + T_fn([T_i16(), T_i1()], T_i16())); + let cttz32 = decl_cdecl_fn(llmod, "llvm.cttz.i32", + T_fn([T_i32(), T_i1()], T_i32())); + let cttz64 = decl_cdecl_fn(llmod, "llvm.cttz.i64", + T_fn([T_i64(), T_i1()], T_i64())); + let bswap16 = decl_cdecl_fn(llmod, "llvm.bswap.i16", + T_fn([T_i16()], T_i16())); + let bswap32 = decl_cdecl_fn(llmod, "llvm.bswap.i32", + T_fn([T_i32()], T_i32())); + let bswap64 = decl_cdecl_fn(llmod, "llvm.bswap.i64", + T_fn([T_i64()], T_i64())); let mut intrinsics = HashMap::new(); intrinsics.insert(~"llvm.gcroot", gcroot); @@ -2801,12 +2839,11 @@ pub fn declare_intrinsics(llmod: ModuleRef) -> HashMap<~str, ValueRef> { pub fn declare_dbg_intrinsics(llmod: ModuleRef, intrinsics: &mut HashMap<~str, ValueRef>) { let declare = - decl_cdecl_fn(llmod, ~"llvm.dbg.declare", - T_fn(~[T_metadata(), T_metadata()], T_void())); + decl_cdecl_fn(llmod, "llvm.dbg.declare", + T_fn([T_metadata(), T_metadata()], T_void())); let value = - decl_cdecl_fn(llmod, ~"llvm.dbg.value", - T_fn(~[T_metadata(), T_i64(), T_metadata()], - T_void())); + decl_cdecl_fn(llmod, "llvm.dbg.value", + T_fn([T_metadata(), T_i64(), T_metadata()], T_void())); intrinsics.insert(~"llvm.dbg.declare", declare); intrinsics.insert(~"llvm.dbg.value", value); } @@ -2815,7 +2852,7 @@ pub fn trap(bcx: block) { let v: ~[ValueRef] = ~[]; match bcx.ccx().intrinsics.find(&~"llvm.trap") { Some(&x) => { Call(bcx, x, v); }, - _ => bcx.sess().bug(~"unbound llvm.trap in trap") + _ => bcx.sess().bug("unbound llvm.trap in trap") } } @@ -2838,9 +2875,9 @@ pub fn decl_gc_metadata(ccx: @CrateContext, llmod_id: &str) { } pub fn create_module_map(ccx: @CrateContext) -> ValueRef { - let elttype = T_struct(~[ccx.int_type, ccx.int_type], false); + let elttype = T_struct([ccx.int_type, ccx.int_type], false); let maptype = T_array(elttype, ccx.module_data.len() + 1); - let map = str::as_c_str(~"_rust_mod_map", |buf| { + let map = str::as_c_str("_rust_mod_map", |buf| { unsafe { llvm::LLVMAddGlobal(ccx.llmod, maptype, buf) } @@ -2848,11 +2885,11 @@ pub fn create_module_map(ccx: @CrateContext) -> ValueRef { lib::llvm::SetLinkage(map, lib::llvm::InternalLinkage); let mut elts: ~[ValueRef] = ~[]; for ccx.module_data.each |key, &val| { - let elt = C_struct(~[p2i(ccx, C_cstr(ccx, @/*bad*/ copy *key)), + let elt = C_struct([p2i(ccx, C_cstr(ccx, @/*bad*/ copy *key)), p2i(ccx, val)]); elts.push(elt); } - let term = C_struct(~[C_int(ccx, 0), C_int(ccx, 0)]); + let term = C_struct([C_int(ccx, 0), C_int(ccx, 0)]); elts.push(term); unsafe { llvm::LLVMSetInitializer(map, C_array(elttype, elts)); @@ -2869,14 +2906,13 @@ pub fn decl_crate_map(sess: session::Session, mapmeta: LinkMeta, let cstore = sess.cstore; while cstore::have_crate_data(cstore, n_subcrates) { n_subcrates += 1; } let mapname = if *sess.building_library { - mapmeta.name.to_owned() + ~"_" + mapmeta.vers.to_owned() + ~"_" - + mapmeta.extras_hash.to_owned() + fmt!("%s_%s_%s", mapmeta.name, mapmeta.vers, mapmeta.extras_hash) } else { ~"toplevel" }; let sym_name = ~"_rust_crate_map_" + mapname; let arrtype = T_array(int_type, n_subcrates as uint); - let maptype = T_struct(~[T_i32(), T_ptr(T_i8()), int_type, arrtype], false); + let maptype = T_struct([T_i32(), T_ptr(T_i8()), int_type, arrtype], false); let map = str::as_c_str(sym_name, |buf| { unsafe { llvm::LLVMAddGlobal(llmod, maptype, buf) @@ -2893,8 +2929,8 @@ pub fn fill_crate_map(ccx: @CrateContext, map: ValueRef) { while cstore::have_crate_data(cstore, i) { let cdata = cstore::get_crate_data(cstore, i); let nm = ~"_rust_crate_map_" + *cdata.name + - ~"_" + *cstore::get_crate_vers(cstore, i) + - ~"_" + *cstore::get_crate_hash(cstore, i); + "_" + *cstore::get_crate_vers(cstore, i) + + "_" + *cstore::get_crate_hash(cstore, i); let cr = str::as_c_str(nm, |buf| { unsafe { llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type, buf) @@ -2919,11 +2955,11 @@ pub fn fill_crate_map(ccx: @CrateContext, map: ValueRef) { unsafe { llvm::LLVMSetInitializer(map, C_struct( - ~[C_i32(1), - lib::llvm::llvm::LLVMConstPointerCast(llannihilatefn, - T_ptr(T_i8())), - p2i(ccx, create_module_map(ccx)), - C_array(ccx.int_type, subcrates)])); + [C_i32(1), + lib::llvm::llvm::LLVMConstPointerCast(llannihilatefn, + T_ptr(T_i8())), + p2i(ccx, create_module_map(ccx)), + C_array(ccx.int_type, subcrates)])); } } @@ -2950,8 +2986,8 @@ pub fn write_metadata(cx: @CrateContext, crate: &ast::crate) { if !*cx.sess.building_library { return; } let encode_parms = crate_ctxt_to_encode_parms(cx); let llmeta = C_bytes(encoder::encode_metadata(encode_parms, crate)); - let llconst = C_struct(~[llmeta]); - let mut llglobal = str::as_c_str(~"rust_metadata", |buf| { + let llconst = C_struct([llmeta]); + let mut llglobal = str::as_c_str("rust_metadata", |buf| { unsafe { llvm::LLVMAddGlobal(cx.llmod, val_ty(llconst), buf) } @@ -2965,11 +3001,11 @@ pub fn write_metadata(cx: @CrateContext, crate: &ast::crate) { let t_ptr_i8 = T_ptr(T_i8()); llglobal = llvm::LLVMConstBitCast(llglobal, t_ptr_i8); - let llvm_used = str::as_c_str(~"llvm.used", |buf| { + let llvm_used = str::as_c_str("llvm.used", |buf| { llvm::LLVMAddGlobal(cx.llmod, T_array(t_ptr_i8, 1u), buf) }); lib::llvm::SetLinkage(llvm_used, lib::llvm::AppendingLinkage); - llvm::LLVMSetInitializer(llvm_used, C_array(t_ptr_i8, ~[llglobal])); + llvm::LLVMSetInitializer(llvm_used, C_array(t_ptr_i8, [llglobal])); } } @@ -3003,7 +3039,7 @@ pub fn trans_crate(sess: session::Session, // crashes if the module identifer is same as other symbols // such as a function name in the module. // 1. http://llvm.org/bugs/show_bug.cgi?id=11479 - let llmod_id = link_meta.name.to_owned() + ~".rc"; + let llmod_id = link_meta.name.to_owned() + ".rc"; unsafe { let llmod = str::as_c_str(llmod_id, |buf| { @@ -3034,7 +3070,7 @@ pub fn trans_crate(sess: session::Session, lib::llvm::associate_type(tn, @"tydesc", tydesc_type); let crate_map = decl_crate_map(sess, link_meta, llmod); let dbg_cx = if sess.opts.debuginfo { - Some(debuginfo::mk_ctxt(copy llmod_id, sess.parse_sess.interner)) + Some(debuginfo::mk_ctxt(copy llmod_id, token::get_ident_interner())) } else { None }; @@ -3069,7 +3105,7 @@ pub fn trans_crate(sess: session::Session, lltypes: @mut HashMap::new(), llsizingtypes: @mut HashMap::new(), adt_reprs: @mut HashMap::new(), - names: new_namegen(sess.parse_sess.interner), + names: new_namegen(token::get_ident_interner()), next_addrspace: new_addrspace_gen(), symbol_hasher: symbol_hasher, type_hashcodes: @mut HashMap::new(), @@ -3122,7 +3158,7 @@ pub fn trans_crate(sess: session::Session, // Translate the metadata. write_metadata(ccx, crate); if ccx.sess.trans_stats() { - io::println(~"--- trans stats ---"); + io::println("--- trans stats ---"); io::println(fmt!("n_static_tydescs: %u", ccx.stats.n_static_tydescs)); io::println(fmt!("n_glues_created: %u", diff --git a/src/librustc/middle/trans/build.rs b/src/librustc/middle/trans/build.rs index e8853fd20e98b..a77e27bf0fe41 100644 --- a/src/librustc/middle/trans/build.rs +++ b/src/librustc/middle/trans/build.rs @@ -8,16 +8,22 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use lib::llvm::llvm; use lib::llvm::{CallConv, AtomicBinOp, AtomicOrdering, AsmDialect}; use lib::llvm::{Opcode, IntPredicate, RealPredicate, False}; use lib::llvm::{ValueRef, TypeRef, BasicBlockRef, BuilderRef, ModuleRef}; use lib; use middle::trans::common::*; +use middle::trans::machine::llalign_of_min; use syntax::codemap::span; +use core::cast; use core::hashmap::HashMap; use core::libc::{c_uint, c_ulonglong, c_char}; +use core::str; +use core::vec; pub fn terminate(cx: block, _: &str) { cx.terminated = true; @@ -62,12 +68,12 @@ pub fn count_insn(cx: block, category: &str) { i = 0u; while i < len { i = *mm.get(&v[i]); - s += ~"/"; + s += "/"; s += v[i]; i += 1u; } - s += ~"/"; + s += "/"; s += category; let n = match h.find(&s) { @@ -189,7 +195,7 @@ pub fn Invoke(cx: block, val_str(cx.ccx().tn, Fn), str::connect(vec::map(Args, |a| val_str(cx.ccx().tn, *a).to_owned()), - ~", ")); + ", ")); unsafe { count_insn(cx, "invoke"); llvm::LLVMBuildInvoke(B(cx), @@ -544,7 +550,8 @@ pub fn AtomicLoad(cx: block, PointerVal: ValueRef, order: AtomicOrdering) -> Val return llvm::LLVMGetUndef(ccx.int_type); } count_insn(cx, "load.atomic"); - return llvm::LLVMBuildAtomicLoad(B(cx), PointerVal, noname(), order); + let align = llalign_of_min(*ccx, ccx.int_type); + return llvm::LLVMBuildAtomicLoad(B(cx), PointerVal, noname(), order, align as c_uint); } } @@ -558,7 +565,6 @@ pub fn LoadRangeAssert(cx: block, PointerVal: ValueRef, lo: c_ulonglong, let min = llvm::LLVMConstInt(t, lo, signed); let max = llvm::LLVMConstInt(t, hi, signed); - do vec::as_imm_buf([min, max]) |ptr, len| { llvm::LLVMSetMetadata(value, lib::llvm::MD_range as c_uint, llvm::LLVMMDNode(ptr, len as c_uint)); @@ -586,7 +592,8 @@ pub fn AtomicStore(cx: block, Val: ValueRef, Ptr: ValueRef, order: AtomicOrderin val_str(cx.ccx().tn, Val), val_str(cx.ccx().tn, Ptr)); count_insn(cx, "store.atomic"); - llvm::LLVMBuildAtomicStore(B(cx), Val, Ptr, order); + let align = llalign_of_min(cx.ccx(), cx.ccx().int_type); + llvm::LLVMBuildAtomicStore(B(cx), Val, Ptr, order, align as c_uint); } } @@ -602,7 +609,7 @@ pub fn GEP(cx: block, Pointer: ValueRef, Indices: &[ValueRef]) -> ValueRef { // Simple wrapper around GEP that takes an array of ints and wraps them // in C_i32() // -// XXX: Use a small-vector optimization to avoid allocations here. +// FIXME #6571: Use a small-vector optimization to avoid allocations here. pub fn GEPi(cx: block, base: ValueRef, ixs: &[uint]) -> ValueRef { let v = do vec::map(ixs) |i| { C_i32(*i as i32) }; count_insn(cx, "gepi"); @@ -837,7 +844,7 @@ pub fn Phi(cx: block, Ty: TypeRef, vals: &[ValueRef], bbs: &[BasicBlockRef]) -> ValueRef { unsafe { if cx.unreachable { return llvm::LLVMGetUndef(Ty); } - assert!(vals.len() == bbs.len()); + assert_eq!(vals.len(), bbs.len()); let phi = EmptyPhi(cx, Ty); count_insn(cx, "addincoming"); llvm::LLVMAddIncoming(phi, vec::raw::to_ptr(vals), @@ -862,7 +869,7 @@ pub fn _UndefReturn(cx: block, Fn: ValueRef) -> ValueRef { let ty = val_ty(Fn); let retty = if llvm::LLVMGetTypeKind(ty) == lib::llvm::Integer { llvm::LLVMGetReturnType(ty) } else { ccx.int_type }; - count_insn(cx, ~""); + count_insn(cx, ""); return llvm::LLVMGetUndef(retty); } } @@ -880,17 +887,17 @@ pub fn add_comment(bcx: block, text: &str) { unsafe { let ccx = bcx.ccx(); if ccx.sess.asm_comments() { - let sanitized = str::replace(text, ~"$", ~""); + let sanitized = str::replace(text, "$", ""); let comment_text = ~"# " + - str::replace(sanitized, ~"\n", ~"\n\t# "); + str::replace(sanitized, "\n", "\n\t# "); let asm = str::as_c_str(comment_text, |c| { - str::as_c_str(~"", |e| { - count_insn(bcx, ~"inlineasm"); - llvm::LLVMConstInlineAsm(T_fn(~[], T_void()), c, e, + str::as_c_str("", |e| { + count_insn(bcx, "inlineasm"); + llvm::LLVMConstInlineAsm(T_fn([], T_void()), c, e, False, False) }) }); - Call(bcx, asm, ~[]); + Call(bcx, asm, []); } } } @@ -1062,7 +1069,7 @@ pub fn Trap(cx: block) { let BB: BasicBlockRef = llvm::LLVMGetInsertBlock(b); let FN: ValueRef = llvm::LLVMGetBasicBlockParent(BB); let M: ModuleRef = llvm::LLVMGetGlobalParent(FN); - let T: ValueRef = str::as_c_str(~"llvm.trap", |buf| { + let T: ValueRef = str::as_c_str("llvm.trap", |buf| { llvm::LLVMGetNamedFunction(M, buf) }); assert!((T as int != 0)); diff --git a/src/librustc/middle/trans/cabi.rs b/src/librustc/middle/trans/cabi.rs index e103bbc5de7a8..acc3293f26783 100644 --- a/src/librustc/middle/trans/cabi.rs +++ b/src/librustc/middle/trans/cabi.rs @@ -36,8 +36,8 @@ pub struct FnType { sret: bool } -pub impl FnType { - fn decl_fn(&self, decl: &fn(fnty: TypeRef) -> ValueRef) -> ValueRef { +impl FnType { + pub fn decl_fn(&self, decl: &fn(fnty: TypeRef) -> ValueRef) -> ValueRef { let atys = vec::map(self.arg_tys, |t| t.ty); let rty = self.ret_ty.ty; let fnty = T_fn(atys, rty); @@ -57,11 +57,13 @@ pub impl FnType { return llfn; } - fn build_shim_args(&self, bcx: block, - arg_tys: &[TypeRef], - llargbundle: ValueRef) -> ~[ValueRef] { - let mut atys = /*bad*/copy self.arg_tys; - let mut attrs = /*bad*/copy self.attrs; + pub fn build_shim_args(&self, + bcx: block, + arg_tys: &[TypeRef], + llargbundle: ValueRef) + -> ~[ValueRef] { + let mut atys: &[LLVMType] = self.arg_tys; + let mut attrs: &[option::Option] = self.attrs; let mut llargvals = ~[]; let mut i = 0u; @@ -71,8 +73,8 @@ pub impl FnType { let llretptr = GEPi(bcx, llargbundle, [0u, n]); let llretloc = Load(bcx, llretptr); llargvals = ~[llretloc]; - atys = vec::to_owned(atys.tail()); - attrs = vec::to_owned(attrs.tail()); + atys = atys.tail(); + attrs = attrs.tail(); } while i < n { @@ -92,12 +94,12 @@ pub impl FnType { return llargvals; } - fn build_shim_ret(&self, - bcx: block, - arg_tys: &[TypeRef], - ret_def: bool, - llargbundle: ValueRef, - llretval: ValueRef) { + pub fn build_shim_ret(&self, + bcx: block, + arg_tys: &[TypeRef], + ret_def: bool, + llargbundle: ValueRef, + llretval: ValueRef) { for vec::eachi(self.attrs) |i, a| { match *a { option::Some(attr) => { @@ -128,17 +130,17 @@ pub impl FnType { }; } - fn build_wrap_args(&self, - bcx: block, - ret_ty: TypeRef, - llwrapfn: ValueRef, - llargbundle: ValueRef) { - let mut atys = /*bad*/copy self.arg_tys; - let mut attrs = /*bad*/copy self.attrs; + pub fn build_wrap_args(&self, + bcx: block, + ret_ty: TypeRef, + llwrapfn: ValueRef, + llargbundle: ValueRef) { + let mut atys: &[LLVMType] = self.arg_tys; + let mut attrs: &[option::Option] = self.attrs; let mut j = 0u; let llretptr = if self.sret { - atys = vec::to_owned(atys.tail()); - attrs = vec::to_owned(attrs.tail()); + atys = atys.tail(); + attrs = attrs.tail(); j = 1u; get_param(llwrapfn, 0u) } else if self.ret_ty.cast { @@ -167,17 +169,17 @@ pub impl FnType { store_inbounds(bcx, llretptr, llargbundle, [0u, n]); } - fn build_wrap_ret(&self, - bcx: block, - arg_tys: &[TypeRef], - llargbundle: ValueRef) { + pub fn build_wrap_ret(&self, + bcx: block, + arg_tys: &[TypeRef], + llargbundle: ValueRef) { unsafe { if llvm::LLVMGetTypeKind(self.ret_ty.ty) == Void { return; } } - let llretval = load_inbounds(bcx, llargbundle, ~[ 0, arg_tys.len() ]); + let llretval = load_inbounds(bcx, llargbundle, [ 0, arg_tys.len() ]); let llretval = if self.ret_ty.cast { let retptr = BitCast(bcx, llretval, T_ptr(self.ret_ty.ty)); Load(bcx, retptr) diff --git a/src/librustc/middle/trans/cabi_mips.rs b/src/librustc/middle/trans/cabi_mips.rs index a1f54c2d1827f..c9fb01905fb2f 100644 --- a/src/librustc/middle/trans/cabi_mips.rs +++ b/src/librustc/middle/trans/cabi_mips.rs @@ -8,7 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use core::libc::c_uint; +use core::ptr; +use core::uint; +use core::vec; use lib::llvm::{llvm, TypeRef, Integer, Pointer, Float, Double}; use lib::llvm::{Struct, Array, Attribute}; use lib::llvm::{StructRetAttribute}; diff --git a/src/librustc/middle/trans/cabi_x86.rs b/src/librustc/middle/trans/cabi_x86.rs index 3a45b281543cf..fbb605330245c 100644 --- a/src/librustc/middle/trans/cabi_x86.rs +++ b/src/librustc/middle/trans/cabi_x86.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use driver::session::{os_win32, os_macos}; use lib::llvm::*; use lib::llvm::llvm::*; diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index dc81a9805887b..767b02d13e2ef 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -16,6 +16,8 @@ // and methods are represented as just a fn ptr and not a full // closure. +use core::prelude::*; + use back::abi; use driver::session; use lib; @@ -41,6 +43,7 @@ use middle::ty; use middle::typeck; use util::ppaux::Repr; +use core::vec; use syntax::ast; use syntax::ast_map; use syntax::visit; @@ -272,7 +275,7 @@ pub fn trans_fn_ref_with_vtables( // Create a monomorphic verison of generic functions if must_monomorphise { // Should be either intra-crate or inlined. - assert!(def_id.crate == ast::local_crate); + assert_eq!(def_id.crate, ast::local_crate); let mut (val, must_cast) = monomorphize::monomorphic_fn(ccx, def_id, type_params, @@ -325,6 +328,7 @@ pub fn trans_call(in_cx: block, pub fn trans_method_call(in_cx: block, call_ex: @ast::expr, + callee_id: ast::node_id, rcvr: @ast::expr, args: CallArgs, dest: expr::Dest) @@ -336,7 +340,7 @@ pub fn trans_method_call(in_cx: block, trans_call_inner( in_cx, call_ex.info(), - node_id_type(in_cx, call_ex.callee_id), + node_id_type(in_cx, callee_id), expr_ty(in_cx, call_ex), |cx| { match cx.ccx().maps.method_map.find_copy(&call_ex.id) { @@ -346,7 +350,7 @@ pub fn trans_method_call(in_cx: block, origin.repr(in_cx.tcx())); meth::trans_method_callee(cx, - call_ex.callee_id, + callee_id, rcvr, origin) } @@ -379,7 +383,7 @@ pub fn trans_lang_call(bcx: block, trans_fn_ref_with_vtables_to_callee(bcx, did, 0, - ~[], + [], None) }, ArgVals(args), @@ -508,11 +512,7 @@ pub fn trans_call_inner(in_cx: block, let mut llargs = ~[]; - if ty::type_is_immediate(ret_ty) { - unsafe { - llargs.push(llvm::LLVMGetUndef(T_ptr(T_i8()))); - } - } else { + if !ty::type_is_immediate(ret_ty) { llargs.push(llretslot); } @@ -712,13 +712,11 @@ pub fn trans_arg_expr(bcx: block, DatumBlock {bcx: bcx, datum: Datum {val: scratch, ty: scratch_ty, - mode: ByRef, - source: RevokeClean}} + mode: ByRef(RevokeClean)}} } _ => { bcx.sess().impossible_case( - arg_expr.span, ~"ret_flag with non-loop-\ - body expr"); + arg_expr.span, "ret_flag with non-loop-body expr"); } } } @@ -777,7 +775,7 @@ pub fn trans_arg_expr(bcx: block, match arg_datum.appropriate_mode() { ByValue => val = Load(bcx, scratch.val), - ByRef => val = scratch.val, + ByRef(_) => val = scratch.val, } } } diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs index 0651d3443b56a..c8405c929cb58 100644 --- a/src/librustc/middle/trans/closure.rs +++ b/src/librustc/middle/trans/closure.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use back::abi; use back::link::{mangle_internal_name_by_path_and_seq}; use lib::llvm::{llvm, ValueRef}; @@ -24,6 +26,8 @@ use middle::trans::type_of::*; use middle::ty; use util::ppaux::ty_to_str; +use core::str; +use core::vec; use syntax::ast; use syntax::ast_map::path_name; use syntax::ast_util; @@ -114,8 +118,8 @@ pub struct EnvValue { datum: Datum } -pub impl EnvAction { - fn to_str(&self) -> ~str { +impl EnvAction { + pub fn to_str(&self) -> ~str { match *self { EnvCopy => ~"EnvCopy", EnvMove => ~"EnvMove", @@ -124,8 +128,8 @@ pub impl EnvAction { } } -pub impl EnvValue { - fn to_str(&self, ccx: @CrateContext) -> ~str { +impl EnvValue { + pub fn to_str(&self, ccx: @CrateContext) -> ~str { fmt!("%s(%s)", self.action.to_str(), self.datum.to_str(ccx)) } } @@ -137,7 +141,7 @@ pub fn mk_tuplified_uniq_cbox_ty(tcx: ty::ctxt, cdata_ty: ty::t) -> ty::t { // Given a closure ty, emits a corresponding tuple ty pub fn mk_closure_tys(tcx: ty::ctxt, - bound_values: ~[EnvValue]) + bound_values: &[EnvValue]) -> ty::t { // determine the types of the values in the env. Note that this // is the actual types that will be stored in the map, not the @@ -157,7 +161,8 @@ pub fn mk_closure_tys(tcx: ty::ctxt, pub fn allocate_cbox(bcx: block, sigil: ast::Sigil, cdata_ty: ty::t) -> Result { let _icx = bcx.insn_ctxt("closure::allocate_cbox"); - let ccx = bcx.ccx(), tcx = ccx.tcx; + let ccx = bcx.ccx(); + let tcx = ccx.tcx; fn nuke_ref_count(bcx: block, llbox: ValueRef) { let _icx = bcx.insn_ctxt("closure::nuke_ref_count"); @@ -200,11 +205,11 @@ pub fn store_environment(bcx: block, bound_values: ~[EnvValue], sigil: ast::Sigil) -> ClosureResult { let _icx = bcx.insn_ctxt("closure::store_environment"); - let ccx = bcx.ccx(), tcx = ccx.tcx; + let ccx = bcx.ccx(); + let tcx = ccx.tcx; // compute the shape of the closure - // XXX: Bad copy. - let cdata_ty = mk_closure_tys(tcx, copy bound_values); + let cdata_ty = mk_closure_tys(tcx, bound_values); // allocate closure in the heap let Result {bcx: bcx, val: llbox} = allocate_cbox(bcx, sigil, cdata_ty); @@ -264,7 +269,7 @@ pub fn build_closure(bcx0: block, let datum = expr::trans_local_var(bcx, cap_var.def); match cap_var.mode { moves::CapRef => { - assert!(sigil == ast::BorrowedSigil); + assert_eq!(sigil, ast::BorrowedSigil); env_vals.push(EnvValue {action: EnvRef, datum: datum}); } @@ -284,7 +289,7 @@ pub fn build_closure(bcx0: block, for include_ret_handle.each |flagptr| { // Flag indicating we have returned (a by-ref bool): let flag_datum = Datum {val: *flagptr, ty: ty::mk_bool(), - mode: ByRef, source: ZeroMem}; + mode: ByRef(ZeroMem)}; env_vals.push(EnvValue {action: EnvRef, datum: flag_datum}); @@ -296,7 +301,7 @@ pub fn build_closure(bcx0: block, }; let ret_casted = PointerCast(bcx, ret_true, T_ptr(T_nil())); let ret_datum = Datum {val: ret_casted, ty: ty::mk_nil(), - mode: ByRef, source: ZeroMem}; + mode: ByRef(ZeroMem)}; env_vals.push(EnvValue {action: EnvRef, datum: ret_datum}); } @@ -318,7 +323,7 @@ pub fn load_environment(fcx: fn_ctxt, Some(ll) => ll, None => { let ll = - str::as_c_str(~"load_env", + str::as_c_str("load_env", |buf| unsafe { llvm::LLVMAppendBasicBlock(fcx.llfn, buf) @@ -497,7 +502,8 @@ pub fn make_opaque_cbox_take_glue( } // ~fn requires a deep copy. - let ccx = bcx.ccx(), tcx = ccx.tcx; + let ccx = bcx.ccx(); + let tcx = ccx.tcx; let llopaquecboxty = T_opaque_box_ptr(ccx); let cbox_in = Load(bcx, cboxptr); do with_cond(bcx, IsNotNull(bcx, cbox_in)) |bcx| { @@ -517,10 +523,10 @@ pub fn make_opaque_cbox_take_glue( let bcx = callee::trans_lang_call( bcx, bcx.tcx().lang_items.exchange_malloc_fn(), - ~[opaque_tydesc, sz], + [opaque_tydesc, sz], expr::SaveIn(rval)); let cbox_out = PointerCast(bcx, Load(bcx, rval), llopaquecboxty); - call_memcpy(bcx, cbox_out, cbox_in, sz); + call_memcpy(bcx, cbox_out, cbox_in, sz, 1); Store(bcx, cbox_out, cboxptr); // Take the (deeply cloned) type descriptor @@ -590,7 +596,7 @@ pub fn make_opaque_cbox_free_glue( ast::ManagedSigil => glue::trans_free(bcx, cbox), ast::OwnedSigil => glue::trans_exchange_free(bcx, cbox), ast::BorrowedSigil => { - bcx.sess().bug(~"impossible") + bcx.sess().bug("impossible") } } } diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 8000484c0550f..8831cde110541 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -8,11 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//! Code that is useful in various trans modules. -/** - Code that is useful in various trans modules. - -*/ +use core::prelude::*; use back::{abi, upcall}; use driver::session; @@ -42,24 +40,31 @@ use middle::borrowck::root_map_key; use util::ppaux::{Repr}; use core::cast::transmute; +use core::cast; use core::hash; use core::hashmap::{HashMap, HashSet}; use core::libc::{c_uint, c_longlong, c_ulonglong}; +use core::ptr; +use core::str; use core::to_bytes; use core::vec::raw::to_ptr; +use core::vec; use syntax::ast::ident; use syntax::ast_map::{path, path_elt}; use syntax::codemap::span; +use syntax::parse::token; use syntax::parse::token::ident_interner; use syntax::{ast, ast_map}; use syntax::abi::{X86, X86_64, Arm, Mips}; +// NOTE: this thunk is totally pointless now that we're not passing +// interners around... pub type namegen = @fn(s: &str) -> ident; pub fn new_namegen(intr: @ident_interner) -> namegen { let f: @fn(s: &str) -> ident = |prefix| { - intr.gensym(fmt!("%s_%u", - prefix, - intr.gensym(prefix).repr)) + token::str_to_ident(fmt!("%s_%u", + prefix, + token::gensym(prefix))) }; f } @@ -238,8 +243,6 @@ pub struct ValSelfData { is_owned: bool } -pub enum local_val { local_mem(ValueRef), local_imm(ValueRef), } - // Here `self_ty` is the real type of the self parameter to this method. It // will only be set in the case of default methods. pub struct param_substs { @@ -249,8 +252,8 @@ pub struct param_substs { self_ty: Option } -pub impl param_substs { - fn validate(&self) { +impl param_substs { + pub fn validate(&self) { for self.tys.each |t| { assert!(!ty::type_needs_infer(*t)); } for self.self_ty.each |t| { assert!(!ty::type_needs_infer(*t)); } } @@ -326,10 +329,10 @@ pub struct fn_ctxt_ { has_immediate_return_value: bool, // Maps arguments to allocas created for them in llallocas. - llargs: @mut HashMap, + llargs: @mut HashMap, // Maps the def_ids for local variables to the allocas created for // them in llallocas. - lllocals: @mut HashMap, + lllocals: @mut HashMap, // Same as above, but for closure upvars llupvars: @mut HashMap, @@ -353,12 +356,36 @@ pub struct fn_ctxt_ { ccx: @@CrateContext } +impl fn_ctxt_ { + pub fn arg_pos(&self, arg: uint) -> uint { + if self.has_immediate_return_value { + arg + 1u + } else { + arg + 2u + } + } + + pub fn out_arg_pos(&self) -> uint { + assert!(self.has_immediate_return_value); + 0u + } + + pub fn env_arg_pos(&self) -> uint { + if !self.has_immediate_return_value { + 1u + } else { + 0u + } + } + +} + pub type fn_ctxt = @mut fn_ctxt_; pub fn warn_not_to_commit(ccx: @CrateContext, msg: &str) { if !*ccx.do_not_commit_warning_issued { *ccx.do_not_commit_warning_issued = true; - ccx.sess.warn(msg.to_str() + ~" -- do not commit like this!"); + ccx.sess.warn(msg.to_str() + " -- do not commit like this!"); } } @@ -574,8 +601,8 @@ pub struct scope_info { landing_pad: Option, } -pub impl scope_info { - fn empty_cleanups(&mut self) -> bool { +impl scope_info { + pub fn empty_cleanups(&mut self) -> bool { self.cleanups.is_empty() } } @@ -587,7 +614,7 @@ pub trait get_node_info { impl get_node_info for @ast::expr { fn info(&self) -> Option { Some(NodeInfo {id: self.id, - callee_id: Some(self.callee_id), + callee_id: self.get_callee_id(), span: self.span}) } } @@ -662,9 +689,6 @@ pub fn mk_block(llbb: BasicBlockRef, parent: Option, kind: block_kind, @mut block_(llbb, parent, kind, is_lpad, node_info, fcx) } -// First two args are retptr, env -pub static first_real_arg: uint = 2u; - pub struct Result { bcx: block, val: ValueRef @@ -674,8 +698,8 @@ pub fn rslt(bcx: block, val: ValueRef) -> Result { Result {bcx: bcx, val: val} } -pub impl Result { - fn unpack(&self, bcx: &mut block) -> ValueRef { +impl Result { + pub fn unpack(&self, bcx: &mut block) -> ValueRef { *bcx = self.bcx; return self.val; } @@ -721,28 +745,28 @@ pub fn block_parent(cx: block) -> block { // Accessors -pub impl block_ { - fn ccx(@mut self) -> @CrateContext { *self.fcx.ccx } - fn tcx(@mut self) -> ty::ctxt { self.fcx.ccx.tcx } - fn sess(@mut self) -> Session { self.fcx.ccx.sess } +impl block_ { + pub fn ccx(@mut self) -> @CrateContext { *self.fcx.ccx } + pub fn tcx(@mut self) -> ty::ctxt { self.fcx.ccx.tcx } + pub fn sess(@mut self) -> Session { self.fcx.ccx.sess } - fn node_id_to_str(@mut self, id: ast::node_id) -> ~str { + pub fn node_id_to_str(@mut self, id: ast::node_id) -> ~str { ast_map::node_id_to_str(self.tcx().items, id, self.sess().intr()) } - fn expr_to_str(@mut self, e: @ast::expr) -> ~str { + pub fn expr_to_str(@mut self, e: @ast::expr) -> ~str { e.repr(self.tcx()) } - fn expr_is_lval(@mut self, e: @ast::expr) -> bool { + pub fn expr_is_lval(@mut self, e: @ast::expr) -> bool { ty::expr_is_lval(self.tcx(), self.ccx().maps.method_map, e) } - fn expr_kind(@mut self, e: @ast::expr) -> ty::ExprKind { + pub fn expr_kind(@mut self, e: @ast::expr) -> ty::ExprKind { ty::expr_kind(self.tcx(), self.ccx().maps.method_map, e) } - fn def(@mut self, nid: ast::node_id) -> ast::def { + pub fn def(@mut self, nid: ast::node_id) -> ast::def { match self.tcx().def_map.find(&nid) { Some(&v) => v, None => { @@ -752,18 +776,19 @@ pub impl block_ { } } - fn val_str(@mut self, val: ValueRef) -> @str { + pub fn val_str(@mut self, val: ValueRef) -> @str { val_str(self.ccx().tn, val) } - fn llty_str(@mut self, llty: TypeRef) -> @str { + pub fn llty_str(@mut self, llty: TypeRef) -> @str { ty_str(self.ccx().tn, llty) } - fn ty_to_str(@mut self, t: ty::t) -> ~str { + pub fn ty_to_str(@mut self, t: ty::t) -> ~str { t.repr(self.tcx()) } - fn to_str(@mut self) -> ~str { + + pub fn to_str(@mut self) -> ~str { unsafe { match self.node_info { Some(node_info) => fmt!("[block %d]", node_info.id), @@ -781,7 +806,7 @@ pub fn T_void() -> TypeRef { } pub fn T_nil() -> TypeRef { - return T_struct(~[], false) + return T_struct([], false) } pub fn T_metadata() -> TypeRef { unsafe { return llvm::LLVMMetadataType(); } } @@ -864,7 +889,7 @@ pub fn T_fn(inputs: &[TypeRef], output: TypeRef) -> TypeRef { } pub fn T_fn_pair(cx: @CrateContext, tfn: TypeRef) -> TypeRef { - return T_struct(~[T_ptr(tfn), T_opaque_cbox_ptr(cx)], false); + return T_struct([T_ptr(tfn), T_opaque_cbox_ptr(cx)], false); } pub fn T_ptr(t: TypeRef) -> TypeRef { @@ -903,7 +928,7 @@ pub fn set_struct_body(t: TypeRef, elts: &[TypeRef], packed: bool) { } } -pub fn T_empty_struct() -> TypeRef { return T_struct(~[], false); } +pub fn T_empty_struct() -> TypeRef { return T_struct([], false); } // A vtable is, in reality, a vtable pointer followed by zero or more pointers // to tydescs and other vtables that it closes over. But the types and number @@ -912,7 +937,7 @@ pub fn T_empty_struct() -> TypeRef { return T_struct(~[], false); } pub fn T_vtable() -> TypeRef { T_array(T_ptr(T_i8()), 1u) } pub fn T_task(targ_cfg: @session::config) -> TypeRef { - let t = T_named_struct(~"task"); + let t = T_named_struct("task"); // Refcount // Delegate pointer @@ -960,12 +985,11 @@ pub fn T_generic_glue_fn(cx: @CrateContext) -> TypeRef { } pub fn T_tydesc(targ_cfg: @session::config) -> TypeRef { - let tydesc = T_named_struct(~"tydesc"); + let tydesc = T_named_struct("tydesc"); let tydescpp = T_ptr(T_ptr(tydesc)); let pvoid = T_ptr(T_i8()); let glue_fn_ty = - T_ptr(T_fn(~[T_ptr(T_nil()), T_ptr(T_nil()), tydescpp, - pvoid], T_void())); + T_ptr(T_fn([T_ptr(T_nil()), tydescpp, pvoid], T_void())); let int_type = T_int(targ_cfg); let elems = @@ -990,9 +1014,9 @@ pub fn T_vector(t: TypeRef, n: uint) -> TypeRef { // Interior vector. pub fn T_vec2(targ_cfg: @session::config, t: TypeRef) -> TypeRef { - return T_struct(~[T_int(targ_cfg), // fill - T_int(targ_cfg), // alloc - T_array(t, 0u)], // elements + return T_struct([T_int(targ_cfg), // fill + T_int(targ_cfg), // alloc + T_array(t, 0u)], // elements false); } @@ -1028,7 +1052,7 @@ pub fn T_box_header(cx: @CrateContext) -> TypeRef { } pub fn T_box(cx: @CrateContext, t: TypeRef) -> TypeRef { - return T_struct(vec::append(T_box_header_fields(cx), ~[t]), false); + return T_struct(vec::append(T_box_header_fields(cx), [t]), false); } pub fn T_box_ptr(t: TypeRef) -> TypeRef { @@ -1046,7 +1070,7 @@ pub fn T_opaque_box_ptr(cx: @CrateContext) -> TypeRef { } pub fn T_unique(cx: @CrateContext, t: TypeRef) -> TypeRef { - return T_struct(vec::append(T_box_header_fields(cx), ~[t]), false); + return T_struct(vec::append(T_box_header_fields(cx), [t]), false); } pub fn T_unique_ptr(t: TypeRef) -> TypeRef { @@ -1056,12 +1080,12 @@ pub fn T_unique_ptr(t: TypeRef) -> TypeRef { } pub fn T_port(cx: @CrateContext, _t: TypeRef) -> TypeRef { - return T_struct(~[cx.int_type], false); // Refcount + return T_struct([cx.int_type], false); // Refcount } pub fn T_chan(cx: @CrateContext, _t: TypeRef) -> TypeRef { - return T_struct(~[cx.int_type], false); // Refcount + return T_struct([cx.int_type], false); // Refcount } @@ -1085,16 +1109,15 @@ pub fn T_captured_tydescs(cx: @CrateContext, n: uint) -> TypeRef { pub fn T_opaque_trait(cx: @CrateContext, store: ty::TraitStore) -> TypeRef { match store { ty::BoxTraitStore => { - T_struct(~[T_ptr(cx.tydesc_type), T_opaque_box_ptr(cx)], false) + T_struct([T_ptr(cx.tydesc_type), T_opaque_box_ptr(cx)], false) } ty::UniqTraitStore => { - T_struct(~[T_ptr(cx.tydesc_type), - T_unique_ptr(T_unique(cx, T_i8())), - T_ptr(cx.tydesc_type)], + T_struct([T_ptr(cx.tydesc_type), + T_unique_ptr(T_unique(cx, T_i8()))], false) } ty::RegionTraitStore(_) => { - T_struct(~[T_ptr(cx.tydesc_type), T_ptr(T_i8())], false) + T_struct([T_ptr(cx.tydesc_type), T_ptr(T_i8())], false) } } } @@ -1130,7 +1153,7 @@ pub fn C_floating(s: &str, t: TypeRef) -> ValueRef { } pub fn C_nil() -> ValueRef { - return C_struct(~[]); + return C_struct([]); } pub fn C_bool(b: bool) -> ValueRef { @@ -1175,7 +1198,7 @@ pub fn C_cstr(cx: @CrateContext, s: @~str) -> ValueRef { llvm::LLVMConstString(buf, s.len() as c_uint, False) }; let g = - str::as_c_str(fmt!("str%u", (cx.names)("str").repr), + str::as_c_str(fmt!("str%u", (cx.names)("str").name), |buf| llvm::LLVMAddGlobal(cx.llmod, val_ty(sc), buf)); llvm::LLVMSetInitializer(g, sc); llvm::LLVMSetGlobalConstant(g, True); @@ -1193,7 +1216,7 @@ pub fn C_estr_slice(cx: @CrateContext, s: @~str) -> ValueRef { unsafe { let len = s.len(); let cs = llvm::LLVMConstPointerCast(C_cstr(cx, s), T_ptr(T_i8())); - C_struct(~[cs, C_uint(cx, len + 1u /* +1 for null */)]) + C_struct([cs, C_uint(cx, len + 1u /* +1 for null */)]) } } @@ -1267,7 +1290,7 @@ pub fn C_bytes_plus_null(bytes: &[u8]) -> ValueRef { pub fn C_shape(ccx: @CrateContext, bytes: ~[u8]) -> ValueRef { unsafe { let llshape = C_bytes_plus_null(bytes); - let name = fmt!("shape%u", (ccx.names)("shape").repr); + let name = fmt!("shape%u", (ccx.names)("shape").name); let llglobal = str::as_c_str(name, |buf| { llvm::LLVMAddGlobal(ccx.llmod, val_ty(llshape), buf) }); @@ -1325,7 +1348,7 @@ pub fn is_null(val: ValueRef) -> bool { // Used to identify cached monomorphized functions and vtables #[deriving(Eq)] pub enum mono_param_id { - mono_precise(ty::t, Option<~[mono_id]>), + mono_precise(ty::t, Option<@~[mono_id]>), mono_any, mono_repr(uint /* size */, uint /* align */, @@ -1367,58 +1390,37 @@ pub struct mono_id_ { pub type mono_id = @mono_id_; -#[cfg(stage0)] -impl to_bytes::IterBytes for mono_param_id { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - match *self { - mono_precise(t, ref mids) => - to_bytes::iter_bytes_3(&0u8, &ty::type_id(t), mids, lsb0, f), - - mono_any => 1u8.iter_bytes(lsb0, f), - - mono_repr(ref a, ref b, ref c, ref d) => - to_bytes::iter_bytes_5(&2u8, a, b, c, d, lsb0, f) - } - } -} -#[cfg(not(stage0))] impl to_bytes::IterBytes for mono_param_id { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { match *self { - mono_precise(t, ref mids) => - to_bytes::iter_bytes_3(&0u8, &ty::type_id(t), mids, lsb0, f), + mono_precise(t, ref mids) => { + 0u8.iter_bytes(lsb0, f) && + ty::type_id(t).iter_bytes(lsb0, f) && + mids.iter_bytes(lsb0, f) + } mono_any => 1u8.iter_bytes(lsb0, f), - mono_repr(ref a, ref b, ref c, ref d) => - to_bytes::iter_bytes_5(&2u8, a, b, c, d, lsb0, f) + mono_repr(ref a, ref b, ref c, ref d) => { + 2u8.iter_bytes(lsb0, f) && + a.iter_bytes(lsb0, f) && + b.iter_bytes(lsb0, f) && + c.iter_bytes(lsb0, f) && + d.iter_bytes(lsb0, f) + } } } } -#[cfg(stage0)] -impl to_bytes::IterBytes for MonoDataClass { - fn iter_bytes(&self, lsb0: bool, f:to_bytes::Cb) { - (*self as u8).iter_bytes(lsb0, f) - } -} -#[cfg(not(stage0))] impl to_bytes::IterBytes for MonoDataClass { fn iter_bytes(&self, lsb0: bool, f:to_bytes::Cb) -> bool { (*self as u8).iter_bytes(lsb0, f) } } -#[cfg(stage0)] -impl to_bytes::IterBytes for mono_id_ { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - to_bytes::iter_bytes_2(&self.def, &self.params, lsb0, f); - } -} -#[cfg(not(stage0))] impl to_bytes::IterBytes for mono_id_ { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { - to_bytes::iter_bytes_2(&self.def, &self.params, lsb0, f) + self.def.iter_bytes(lsb0, f) && self.params.iter_bytes(lsb0, f) } } @@ -1439,12 +1441,13 @@ pub fn align_to(cx: block, off: ValueRef, align: ValueRef) -> ValueRef { } pub fn path_str(sess: session::Session, p: &[path_elt]) -> ~str { - let mut r = ~"", first = true; + let mut r = ~""; + let mut first = true; for p.each |e| { match *e { ast_map::path_name(s) | ast_map::path_mod(s) => { if first { first = false; } - else { r += ~"::"; } + else { r += "::"; } r += *sess.str_of(s); } } diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs index 48c5a96c8e7b2..62704fd1eb06e 100644 --- a/src/librustc/middle/trans/consts.rs +++ b/src/librustc/middle/trans/consts.rs @@ -8,9 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use back::abi; -use lib::llvm::{llvm, SetLinkage, PrivateLinkage, - ValueRef, TypeRef, Bool, True, False}; +use lib::llvm::{llvm, ConstFCmp, ConstICmp, SetLinkage, PrivateLinkage, ValueRef, TypeRef, Bool, + True, False}; +use lib::llvm::{IntEQ, IntNE, IntUGT, IntUGE, IntULT, IntULE, IntSGT, IntSGE, IntSLT, IntSLE, + RealOEQ, RealOGT, RealOGE, RealOLT, RealOLE, RealONE}; + use metadata::csearch; use middle::const_eval; use middle::trans::adt; @@ -26,8 +31,8 @@ use middle::ty; use util::ppaux::{Repr, ty_to_str}; use core::libc::c_uint; +use core::str; use syntax::{ast, ast_util, ast_map}; -use util::ppaux::ty_to_str; pub fn const_lit(cx: @CrateContext, e: @ast::expr, lit: ast::lit) -> ValueRef { @@ -113,7 +118,7 @@ fn const_deref_ptr(cx: @CrateContext, v: ValueRef) -> ValueRef { None => v }; unsafe { - assert!(llvm::LLVMIsGlobalConstant(v) == True); + assert_eq!(llvm::LLVMIsGlobalConstant(v), True); llvm::LLVMGetInitializer(v) } } @@ -163,7 +168,7 @@ pub fn get_const_val(cx: @CrateContext, def_id: ast::def_id) -> ValueRef { }, _) => { trans_const(cx, subexpr, def_id.node); } - _ => cx.tcx.sess.bug(~"expected a const to be an item") + _ => cx.tcx.sess.bug("expected a const to be an item") } } cx.const_values.get_copy(&def_id.node) @@ -175,7 +180,7 @@ pub fn const_expr(cx: @CrateContext, e: @ast::expr) -> ValueRef { match cx.tcx.adjustments.find(&e.id) { None => { } Some(&@ty::AutoAddEnv(ty::re_static, ast::BorrowedSigil)) => { - llconst = C_struct(~[llconst, C_null(T_opaque_box_ptr(cx))]) + llconst = C_struct([llconst, C_null(T_opaque_box_ptr(cx))]) } Some(&@ty::AutoAddEnv(ref r, ref s)) => { cx.sess.span_bug(e.span, fmt!("unexpected static function: \ @@ -209,9 +214,9 @@ pub fn const_expr(cx: @CrateContext, e: @ast::expr) -> ValueRef { assert!(m != ast::m_mutbl); let size = machine::llsize_of(cx, val_ty(llconst)); - assert!(abi::slice_elt_base == 0); - assert!(abi::slice_elt_len == 1); - llconst = C_struct(~[llptr, size]); + assert_eq!(abi::slice_elt_base, 0); + assert_eq!(abi::slice_elt_len, 1); + llconst = C_struct([llptr, size]); } _ => { cx.sess.span_bug(e.span, @@ -246,7 +251,7 @@ fn const_expr_unadjusted(cx: @CrateContext, e: @ast::expr) -> ValueRef { let _icx = cx.insn_ctxt("const_expr"); return match e.node { ast::expr_lit(lit) => consts::const_lit(cx, e, *lit), - ast::expr_binary(b, e1, e2) => { + ast::expr_binary(_, b, e1, e2) => { let te1 = const_expr(cx, e1); let te2 = const_expr(cx, e2); @@ -280,8 +285,8 @@ fn const_expr_unadjusted(cx: @CrateContext, e: @ast::expr) -> ValueRef { else if signed { llvm::LLVMConstSRem(te1, te2) } else { llvm::LLVMConstURem(te1, te2) } } - ast::and | - ast::or => cx.sess.span_unimpl(e.span, "binop logic"), + ast::and => llvm::LLVMConstAnd(te1, te2), + ast::or => llvm::LLVMConstOr(te1, te2), ast::bitxor => llvm::LLVMConstXor(te1, te2), ast::bitand => llvm::LLVMConstAnd(te1, te2), ast::bitor => llvm::LLVMConstOr(te1, te2), @@ -290,15 +295,45 @@ fn const_expr_unadjusted(cx: @CrateContext, e: @ast::expr) -> ValueRef { if signed { llvm::LLVMConstAShr(te1, te2) } else { llvm::LLVMConstLShr(te1, te2) } } - ast::eq | - ast::lt | - ast::le | - ast::ne | - ast::ge | - ast::gt => cx.sess.span_unimpl(e.span, "binop comparator") - } - } - ast::expr_unary(u, e) => { + ast::eq => { + if is_float { ConstFCmp(RealOEQ, te1, te2) } + else { ConstICmp(IntEQ, te1, te2) } + }, + ast::lt => { + if is_float { ConstFCmp(RealOLT, te1, te2) } + else { + if signed { ConstICmp(IntSLT, te1, te2) } + else { ConstICmp(IntULT, te1, te2) } + } + }, + ast::le => { + if is_float { ConstFCmp(RealOLE, te1, te2) } + else { + if signed { ConstICmp(IntSLE, te1, te2) } + else { ConstICmp(IntULE, te1, te2) } + } + }, + ast::ne => { + if is_float { ConstFCmp(RealONE, te1, te2) } + else { ConstICmp(IntNE, te1, te2) } + }, + ast::ge => { + if is_float { ConstFCmp(RealOGE, te1, te2) } + else { + if signed { ConstICmp(IntSGE, te1, te2) } + else { ConstICmp(IntUGE, te1, te2) } + } + }, + ast::gt => { + if is_float { ConstFCmp(RealOGT, te1, te2) } + else { + if signed { ConstICmp(IntSGT, te1, te2) } + else { ConstICmp(IntUGT, te1, te2) } + } + }, + }; + }, + ast::expr_unary(_, u, e) => { let te = const_expr(cx, e); let ty = ty::expr_ty(cx.tcx, e); let is_float = ty::type_is_fp(ty); @@ -337,7 +372,7 @@ fn const_expr_unadjusted(cx: @CrateContext, e: @ast::expr) -> ValueRef { } } - ast::expr_index(base, index) => { + ast::expr_index(_, base, index) => { let bt = ty::expr_ty_adjusted(cx.tcx, base); let bv = const_expr(cx, base); let iv = match const_eval::eval_const_expr(cx.tcx, index) { @@ -418,8 +453,8 @@ fn const_expr_unadjusted(cx: @CrateContext, e: @ast::expr) -> ValueRef { llvm::LLVMConstIntCast(iv, llty, s) } expr::cast_float => llvm::LLVMConstUIToFP(iv, llty), - _ => cx.sess.bug(~"enum cast destination is not \ - integral or float") + _ => cx.sess.bug("enum cast destination is not \ + integral or float") } } (expr::cast_pointer, expr::cast_pointer) => { @@ -430,7 +465,7 @@ fn const_expr_unadjusted(cx: @CrateContext, e: @ast::expr) -> ValueRef { } _ => { cx.sess.impossible_case(e.span, - ~"bad combination of types for cast") + "bad combination of types for cast") } } } @@ -480,13 +515,13 @@ fn const_expr_unadjusted(cx: @CrateContext, e: @ast::expr) -> ValueRef { llvm::LLVMSetGlobalConstant(gv, True); SetLinkage(gv, PrivateLinkage); let p = const_ptrcast(cx, gv, llunitty); - C_struct(~[p, sz]) + C_struct([p, sz]) } _ => cx.sess.span_bug(e.span, "bad const-slice expr") } } ast::expr_path(pth) => { - assert!(pth.types.len() == 0); + assert_eq!(pth.types.len(), 0); match cx.tcx.def_map.find(&e.id) { Some(&ast::def_fn(def_id, _purity)) => { if !ast_util::is_local(def_id) { diff --git a/src/librustc/middle/trans/controlflow.rs b/src/librustc/middle/trans/controlflow.rs index ac512bc4bf95d..8c6dbb009f556 100644 --- a/src/librustc/middle/trans/controlflow.rs +++ b/src/librustc/middle/trans/controlflow.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use back::link; use lib; use lib::llvm::*; @@ -22,6 +24,8 @@ use middle::ty; use util::common::indenter; use util::ppaux; +use core::str; +use core::vec; use syntax::ast; use syntax::ast::ident; use syntax::ast_map::path_mod; @@ -93,14 +97,14 @@ pub fn trans_if(bcx: block, trans_block(else_bcx_in, blk, dest) } // would be nice to have a constraint on ifs - _ => bcx.tcx().sess.bug(~"strange alternative in if") + _ => bcx.tcx().sess.bug("strange alternative in if") } } _ => else_bcx_in }; let else_bcx_out = trans_block_cleanups(else_bcx_out, block_cleanups(else_bcx_in)); - return join_blocks(bcx, ~[then_bcx_out, else_bcx_out]); + return join_blocks(bcx, [then_bcx_out, else_bcx_out]); } @@ -228,7 +232,7 @@ pub fn trans_log(log_ex: @ast::expr, let val = val_datum.to_ref_llval(bcx); let did = bcx.tcx().lang_items.log_type_fn(); let bcx = callee::trans_lang_call_with_type_params( - bcx, did, ~[level, val], ~[val_datum.ty], expr::Ignore); + bcx, did, [level, val], [val_datum.ty], expr::Ignore); bcx } } @@ -328,7 +332,8 @@ pub fn trans_fail_expr(bcx: block, let mut bcx = bcx; match fail_expr { Some(arg_expr) => { - let ccx = bcx.ccx(), tcx = ccx.tcx; + let ccx = bcx.ccx(); + let tcx = ccx.tcx; let arg_datum = unpack_datum!( bcx, expr::trans_to_datum(bcx, arg_expr)); diff --git a/src/librustc/middle/trans/datum.rs b/src/librustc/middle/trans/datum.rs index 8055d919ffd9a..1c94d16b15834 100644 --- a/src/librustc/middle/trans/datum.rs +++ b/src/librustc/middle/trans/datum.rs @@ -44,15 +44,17 @@ * # Datum cleanup styles * * Each datum carries with it an idea of how its value will be cleaned - * up. This is important after a move, because we need to know how to - * cancel the cleanup (since the value has been moved and therefore does - * not need to be freed). There are two options: - * - * 1. `RevokeClean`: To cancel the cleanup, we invoke `revoke_clean()`. - * This is used for temporary rvalues. - * - * 2. `ZeroMem`: To cancel the cleanup, we zero out the memory where - * the value resides. This is used for lvalues. + * up. This is primarily determined by the mode: a `ByValue` datum + * will always be cleaned up by revoking cleanup using + * `revoke_clean()`, because there is no other option. By ref datums + * can sometimes be cleaned up via `revoke_clean` (in particular, + * by-ref datums that originated from rvalues), but sometimes they + * must be zeroed. This is indicated by the `DatumCleanup` + * parameter. Note that zeroing a by-ref datum *always works* to + * cancel the cleanup, but using `revoke_clean` is preferable since + * there is no runtime cost. Some older parts of the code (notably + * `match_`, at least at the time of this writing) rely on this and + * only use zeroing. * * # Copying, moving, and storing * @@ -85,6 +87,8 @@ * methods themselves. Most are only suitable for some types of * values. */ +use core::prelude::*; + use lib; use lib::llvm::ValueRef; use middle::trans::adt; @@ -101,7 +105,7 @@ use middle::ty; use util::common::indenter; use util::ppaux::ty_to_str; -use core::to_bytes; +use core::uint; use syntax::ast; use syntax::codemap::span; use syntax::parse::token::special_idents; @@ -122,12 +126,6 @@ pub struct Datum { /// Indicates whether this is by-ref or by-value. mode: DatumMode, - - /// How did this value originate? This is particularly important - /// if the value is MOVED or prematurely DROPPED, because it - /// describes how to cancel the cleanup that was scheduled before. - /// See the def'n of the `DatumCleanup` type. - source: DatumCleanup } pub struct DatumBlock { @@ -135,48 +133,37 @@ pub struct DatumBlock { datum: Datum, } -#[deriving(Eq)] +#[deriving(Eq, IterBytes)] pub enum DatumMode { - /// `val` is a pointer to the actual value (and thus has type *T) - ByRef, + /// `val` is a pointer to the actual value (and thus has type *T). + /// The argument indicates how to cancel cleanup of this datum if + /// the value is moved elsewhere, which can either be by zeroing + /// the memory or by canceling a registered cleanup. + ByRef(DatumCleanup), /// `val` is the actual value (*only used for immediates* like ints, ptrs) ByValue, } -pub impl DatumMode { - fn is_by_ref(&self) -> bool { - match *self { ByRef => true, ByValue => false } +impl DatumMode { + pub fn is_by_ref(&self) -> bool { + match *self { ByRef(_) => true, ByValue => false } } - fn is_by_value(&self) -> bool { - match *self { ByRef => false, ByValue => true } - } -} - -#[cfg(stage0)] -impl to_bytes::IterBytes for DatumMode { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - (*self as uint).iter_bytes(lsb0, f) - } -} -#[cfg(not(stage0))] -impl to_bytes::IterBytes for DatumMode { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { - (*self as uint).iter_bytes(lsb0, f) + pub fn is_by_value(&self) -> bool { + match *self { ByRef(_) => false, ByValue => true } } } /// See `Datum cleanup styles` section at the head of this module. -#[deriving(Eq)] +#[deriving(Eq, IterBytes)] pub enum DatumCleanup { RevokeClean, ZeroMem } pub fn immediate_rvalue(val: ValueRef, ty: ty::t) -> Datum { - return Datum {val: val, ty: ty, - mode: ByValue, source: RevokeClean}; + return Datum {val: val, ty: ty, mode: ByValue}; } pub fn immediate_rvalue_bcx(bcx: block, @@ -199,7 +186,7 @@ pub fn scratch_datum(bcx: block, ty: ty::t, zero: bool) -> Datum { let llty = type_of::type_of(bcx.ccx(), ty); let scratch = alloca_maybe_zeroed(bcx, llty, zero); - Datum { val: scratch, ty: ty, mode: ByRef, source: RevokeClean } + Datum { val: scratch, ty: ty, mode: ByRef(RevokeClean) } } pub fn appropriate_mode(ty: ty::t) -> DatumMode { @@ -214,13 +201,17 @@ pub fn appropriate_mode(ty: ty::t) -> DatumMode { } else if ty::type_is_immediate(ty) { ByValue } else { - ByRef + ByRef(RevokeClean) } } -pub impl Datum { - fn store_to(&self, bcx: block, id: ast::node_id, - action: CopyAction, dst: ValueRef) -> block { +impl Datum { + pub fn store_to(&self, + bcx: block, + id: ast::node_id, + action: CopyAction, + dst: ValueRef) + -> block { /*! * * Stores this value into its final home. This moves if @@ -234,8 +225,11 @@ pub impl Datum { } } - fn store_to_dest(&self, bcx: block, id: ast::node_id, - dest: expr::Dest) -> block { + pub fn store_to_dest(&self, + bcx: block, + id: ast::node_id, + dest: expr::Dest) + -> block { match dest { expr::Ignore => { return bcx; @@ -246,28 +240,32 @@ pub impl Datum { } } - fn store_to_datum(&self, bcx: block, id: ast::node_id, - action: CopyAction, datum: Datum) -> block { + pub fn store_to_datum(&self, + bcx: block, + id: ast::node_id, + action: CopyAction, + datum: Datum) + -> block { debug!("store_to_datum(self=%s, action=%?, datum=%s)", self.to_str(bcx.ccx()), action, datum.to_str(bcx.ccx())); assert!(datum.mode.is_by_ref()); self.store_to(bcx, id, action, datum.val) } - fn move_to_datum(&self, bcx: block, action: CopyAction, datum: Datum) - -> block { + pub fn move_to_datum(&self, bcx: block, action: CopyAction, datum: Datum) + -> block { assert!(datum.mode.is_by_ref()); self.move_to(bcx, action, datum.val) } - fn copy_to_datum(&self, bcx: block, action: CopyAction, datum: Datum) - -> block { + pub fn copy_to_datum(&self, bcx: block, action: CopyAction, datum: Datum) + -> block { assert!(datum.mode.is_by_ref()); self.copy_to(bcx, action, datum.val) } - fn copy_to(&self, bcx: block, action: CopyAction, dst: ValueRef) - -> block { + pub fn copy_to(&self, bcx: block, action: CopyAction, dst: ValueRef) + -> block { /*! * * Copies the value into `dst`, which should be a pointer to a @@ -293,7 +291,7 @@ pub impl Datum { ty::type_needs_drop(bcx.tcx(), self.ty) { match self.mode { - ByRef => { + ByRef(_) => { let cast = PointerCast(bcx, dst, val_ty(self.val)); let cmp = ICmp(bcx, lib::llvm::IntNE, cast, self.val); do with_cond(bcx, cmp) |bcx| { @@ -309,9 +307,11 @@ pub impl Datum { } } - fn copy_to_no_check(&self, bcx: block, action: CopyAction, - dst: ValueRef) -> block - { + pub fn copy_to_no_check(&self, + bcx: block, + action: CopyAction, + dst: ValueRef) + -> block { /*! * * A helper for `copy_to()` which does not check to see if we @@ -328,7 +328,7 @@ pub impl Datum { ByValue => { Store(bcx, self.val, dst); } - ByRef => { + ByRef(_) => { memcpy_ty(bcx, dst, self.val, self.ty); } } @@ -339,8 +339,8 @@ pub impl Datum { // This works like copy_val, except that it deinitializes the source. // Since it needs to zero out the source, src also needs to be an lval. // - fn move_to(&self, bcx: block, action: CopyAction, dst: ValueRef) - -> block { + pub fn move_to(&self, bcx: block, action: CopyAction, dst: ValueRef) + -> block { let _icx = bcx.insn_ctxt("move_to"); let mut bcx = bcx; @@ -356,7 +356,7 @@ pub impl Datum { } match self.mode { - ByRef => { + ByRef(_) => { memcpy_ty(bcx, dst, self.val, self.ty); } ByValue => { @@ -369,30 +369,34 @@ pub impl Datum { return bcx; } - fn add_clean(&self, bcx: block) { + pub fn add_clean(&self, bcx: block) { /*! - * * Schedules this datum for cleanup in `bcx`. The datum - * must be an rvalue. */ + * must be an rvalue. + */ - assert!(self.source == RevokeClean); match self.mode { ByValue => { add_clean_temp_immediate(bcx, self.val, self.ty); } - ByRef => { + ByRef(RevokeClean) => { add_clean_temp_mem(bcx, self.val, self.ty); } + ByRef(ZeroMem) => { + bcx.tcx().sess.bug( + fmt!("Cannot add clean to a 'zero-mem' datum")); + } } } - fn cancel_clean(&self, bcx: block) { + pub fn cancel_clean(&self, bcx: block) { if ty::type_needs_drop(bcx.tcx(), self.ty) { - match self.source { - RevokeClean => { + match self.mode { + ByValue | + ByRef(RevokeClean) => { revoke_clean(bcx, self.val); } - ZeroMem => { + ByRef(ZeroMem) => { // Lvalues which potentially need to be dropped // must be passed by ref, so that we can zero them // out. @@ -403,15 +407,14 @@ pub impl Datum { } } - fn to_str(&self, ccx: &CrateContext) -> ~str { - fmt!("Datum { val=%s, ty=%s, mode=%?, source=%? }", + pub fn to_str(&self, ccx: &CrateContext) -> ~str { + fmt!("Datum { val=%s, ty=%s, mode=%? }", val_str(ccx.tn, self.val), ty_to_str(ccx.tcx, self.ty), - self.mode, - self.source) + self.mode) } - fn to_value_datum(&self, bcx: block) -> Datum { + pub fn to_value_datum(&self, bcx: block) -> Datum { /*! * * Yields a by-ref form of this datum. This may involve @@ -421,14 +424,14 @@ pub impl Datum { match self.mode { ByValue => *self, - ByRef => { + ByRef(_) => { Datum {val: self.to_value_llval(bcx), mode: ByValue, - ty: self.ty, source: RevokeClean} + ty: self.ty} } } } - fn to_value_llval(&self, bcx: block) -> ValueRef { + pub fn to_value_llval(&self, bcx: block) -> ValueRef { /*! * * Yields the value itself. */ @@ -438,7 +441,7 @@ pub impl Datum { } else { match self.mode { ByValue => self.val, - ByRef => { + ByRef(_) => { if ty::type_is_bool(self.ty) { LoadRangeAssert(bcx, self.val, 0, 2, lib::llvm::True) } else { @@ -449,26 +452,26 @@ pub impl Datum { } } - fn to_ref_datum(&self, bcx: block) -> Datum { + pub fn to_ref_datum(&self, bcx: block) -> Datum { /*! - * * Yields a by-ref form of this datum. This may involve * creation of a temporary stack slot. The value returned by * this function is not separately rooted from this datum, so - * it will not live longer than the current datum. */ + * it will not live longer than the current datum. + */ match self.mode { - ByRef => *self, + ByRef(_) => *self, ByValue => { - Datum {val: self.to_ref_llval(bcx), mode: ByRef, - ty: self.ty, source: RevokeClean} + Datum {val: self.to_ref_llval(bcx), mode: ByRef(RevokeClean), + ty: self.ty} } } } - fn to_ref_llval(&self, bcx: block) -> ValueRef { + pub fn to_ref_llval(&self, bcx: block) -> ValueRef { match self.mode { - ByRef => self.val, + ByRef(_) => self.val, ByValue => { if ty::type_is_nil(self.ty) || ty::type_is_bot(self.ty) { C_null(T_ptr(type_of::type_of(bcx.ccx(), self.ty))) @@ -481,59 +484,85 @@ pub impl Datum { } } - fn appropriate_mode(&self) -> DatumMode { + pub fn to_zeroable_ref_llval(&self, bcx: block) -> ValueRef { + /*! + * Returns a by-ref llvalue that can be zeroed in order to + * cancel cleanup. This is a kind of hokey bridge used + * to adapt to the match code. Please don't use it for new code. + */ + + match self.mode { + // All by-ref datums are zeroable, even if we *could* just + // cancel the cleanup. + ByRef(_) => self.val, + + // By value datums can't be zeroed (where would you store + // the zero?) so we have to spill them. Add a temp cleanup + // for this spilled value and cancel the cleanup on this + // current value. + ByValue => { + let slot = self.to_ref_llval(bcx); + self.cancel_clean(bcx); + add_clean_temp_mem(bcx, slot, self.ty); + slot + } + } + } + + pub fn appropriate_mode(&self) -> DatumMode { /*! See the `appropriate_mode()` function */ appropriate_mode(self.ty) } - fn to_appropriate_llval(&self, bcx: block) -> ValueRef { + pub fn to_appropriate_llval(&self, bcx: block) -> ValueRef { /*! * * Yields an llvalue with the `appropriate_mode()`. */ match self.appropriate_mode() { ByValue => self.to_value_llval(bcx), - ByRef => self.to_ref_llval(bcx) + ByRef(_) => self.to_ref_llval(bcx) } } - fn to_appropriate_datum(&self, bcx: block) -> Datum { + pub fn to_appropriate_datum(&self, bcx: block) -> Datum { /*! * * Yields a datum with the `appropriate_mode()`. */ match self.appropriate_mode() { ByValue => self.to_value_datum(bcx), - ByRef => self.to_ref_datum(bcx) + ByRef(_) => self.to_ref_datum(bcx) } } - fn get_element(&self, bcx: block, - ty: ty::t, - source: DatumCleanup, - gep: &fn(ValueRef) -> ValueRef) -> Datum { + pub fn get_element(&self, + bcx: block, + ty: ty::t, + source: DatumCleanup, + gep: &fn(ValueRef) -> ValueRef) + -> Datum { let base_val = self.to_ref_llval(bcx); Datum { val: gep(base_val), - mode: ByRef, + mode: ByRef(source), ty: ty, - source: source } } - fn drop_val(&self, bcx: block) -> block { + pub fn drop_val(&self, bcx: block) -> block { if !ty::type_needs_drop(bcx.tcx(), self.ty) { return bcx; } return match self.mode { - ByRef => glue::drop_ty(bcx, self.val, self.ty), + ByRef(_) => glue::drop_ty(bcx, self.val, self.ty), ByValue => glue::drop_ty_immediate(bcx, self.val, self.ty) }; } - fn box_body(&self, bcx: block) -> Datum { + pub fn box_body(&self, bcx: block) -> Datum { /*! * * This datum must represent an @T or ~T box. Returns a new @@ -550,10 +579,10 @@ pub impl Datum { let ptr = self.to_value_llval(bcx); let body = opaque_box_body(bcx, content_ty, ptr); - Datum {val: body, ty: content_ty, mode: ByRef, source: ZeroMem} + Datum {val: body, ty: content_ty, mode: ByRef(ZeroMem)} } - fn to_rptr(&self, bcx: block) -> Datum { + pub fn to_rptr(&self, bcx: block) -> Datum { //! Returns a new datum of region-pointer type containing the //! the same ptr as this datum (after converting to by-ref //! using `to_ref_llval()`). @@ -565,18 +594,21 @@ pub impl Datum { let llval = self.to_ref_llval(bcx); let rptr_ty = ty::mk_imm_rptr(bcx.tcx(), ty::re_static, self.ty); - Datum {val: llval, ty: rptr_ty, - mode: ByValue, source: RevokeClean} - } - - fn try_deref(&self, - bcx: block, // block wherein to generate insn's - span: span, // location where deref occurs - expr_id: ast::node_id, // id of deref expr - derefs: uint, // number of times deref'd already - is_auto: bool) // if true, only deref if auto-derefable - -> (Option, block) - { + Datum {val: llval, ty: rptr_ty, mode: ByValue} + } + + /// bcx: Block wherein to generate insns. + /// span: Location where deref occurs. + /// expr_id: ID of deref expr. + /// derefs: Number of times deref'd already. + /// is_auto: If true, only deref if auto-derefable. + pub fn try_deref(&self, + bcx: block, + span: span, + expr_id: ast::node_id, + derefs: uint, + is_auto: bool) + -> (Option, block) { let ccx = bcx.ccx(); debug!("try_deref(expr_id=%?, derefs=%?, is_auto=%b, self=%?)", @@ -610,7 +642,7 @@ pub impl Datum { let repr = adt::represent_type(ccx, self.ty); let ty = ty::subst(ccx.tcx, substs, variants[0].args[0]); return match self.mode { - ByRef => { + ByRef(_) => { // Recast lv.val as a pointer to the newtype // rather than a ptr to the enum type. ( @@ -618,8 +650,7 @@ pub impl Datum { val: adt::trans_field_ptr(bcx, repr, self.val, 0, 0), ty: ty, - mode: ByRef, - source: ZeroMem + mode: ByRef(ZeroMem) }), bcx ) @@ -649,18 +680,17 @@ pub impl Datum { let repr = adt::represent_type(ccx, self.ty); let ty = fields[0].mt.ty; return match self.mode { - ByRef => { + ByRef(_) => { // Recast lv.val as a pointer to the newtype rather // than a pointer to the struct type. - // XXX: This isn't correct for structs with + // FIXME #6572: This isn't correct for structs with // destructors. ( Some(Datum { val: adt::trans_field_ptr(bcx, repr, self.val, 0, 0), ty: ty, - mode: ByRef, - source: ZeroMem + mode: ByRef(ZeroMem) }), bcx ) @@ -687,16 +717,14 @@ pub impl Datum { Datum { val: lv.to_value_llval(bcx), ty: ty, - mode: ByRef, - source: ZeroMem // *p is an lvalue + mode: ByRef(ZeroMem) } } } - fn deref(&self, bcx: block, - expr: @ast::expr, // the deref expression - derefs: uint) - -> DatumBlock { + /// expr: The deref expression. + pub fn deref(&self, bcx: block, expr: @ast::expr, derefs: uint) + -> DatumBlock { match self.try_deref(bcx, expr.span, expr.id, derefs, false) { (Some(lvres), bcx) => DatumBlock { bcx: bcx, datum: lvres }, (None, _) => { @@ -706,11 +734,12 @@ pub impl Datum { } } - fn autoderef(&self, bcx: block, - span: span, - expr_id: ast::node_id, - max: uint) - -> DatumBlock { + pub fn autoderef(&self, + bcx: block, + span: span, + expr_id: ast::node_id, + max: uint) + -> DatumBlock { let _icx = bcx.insn_ctxt("autoderef"); debug!("autoderef(expr_id=%d, max=%?, self=%?)", @@ -738,12 +767,12 @@ pub impl Datum { DatumBlock { bcx: bcx, datum: datum } } - fn get_vec_base_and_len(&self, - mut bcx: block, - span: span, - expr_id: ast::node_id, - derefs: uint) - -> (block, ValueRef, ValueRef) { + pub fn get_vec_base_and_len(&self, + mut bcx: block, + span: span, + expr_id: ast::node_id, + derefs: uint) + -> (block, ValueRef, ValueRef) { //! Converts a vector into the slice pair. Performs rooting //! and write guards checks. @@ -753,7 +782,8 @@ pub impl Datum { (bcx, base, len) } - fn get_vec_base_and_len_no_root(&self, bcx: block) -> (ValueRef, ValueRef) { + pub fn get_vec_base_and_len_no_root(&self, bcx: block) + -> (ValueRef, ValueRef) { //! Converts a vector into the slice pair. Des not root //! nor perform write guard checks. @@ -761,64 +791,68 @@ pub impl Datum { tvec::get_base_and_len(bcx, llval, self.ty) } - fn root_and_write_guard(&self, - bcx: block, - span: span, - expr_id: ast::node_id, - derefs: uint) -> block { + pub fn root_and_write_guard(&self, + bcx: block, + span: span, + expr_id: ast::node_id, + derefs: uint) + -> block { write_guard::root_and_write_guard(self, bcx, span, expr_id, derefs) } - fn to_result(&self, bcx: block) -> common::Result { + pub fn to_result(&self, bcx: block) -> common::Result { rslt(bcx, self.to_appropriate_llval(bcx)) } } -pub impl DatumBlock { - fn unpack(&self, bcx: &mut block) -> Datum { +impl DatumBlock { + pub fn unpack(&self, bcx: &mut block) -> Datum { *bcx = self.bcx; return self.datum; } - fn assert_by_ref(&self) -> DatumBlock { + pub fn assert_by_ref(&self) -> DatumBlock { assert!(self.datum.mode.is_by_ref()); *self } - fn drop_val(&self) -> block { + pub fn drop_val(&self) -> block { self.datum.drop_val(self.bcx) } - fn store_to(&self, id: ast::node_id, action: CopyAction, - dst: ValueRef) -> block { + pub fn store_to(&self, + id: ast::node_id, + action: CopyAction, + dst: ValueRef) + -> block { self.datum.store_to(self.bcx, id, action, dst) } - fn copy_to(&self, action: CopyAction, dst: ValueRef) -> block { + pub fn copy_to(&self, action: CopyAction, dst: ValueRef) -> block { self.datum.copy_to(self.bcx, action, dst) } - fn move_to(&self, action: CopyAction, dst: ValueRef) -> block { + pub fn move_to(&self, action: CopyAction, dst: ValueRef) -> block { self.datum.move_to(self.bcx, action, dst) } - fn to_value_llval(&self) -> ValueRef { + pub fn to_value_llval(&self) -> ValueRef { self.datum.to_value_llval(self.bcx) } - fn to_result(&self) -> common::Result { + pub fn to_result(&self) -> common::Result { rslt(self.bcx, self.datum.to_appropriate_llval(self.bcx)) } - fn ccx(&self) -> @CrateContext { + pub fn ccx(&self) -> @CrateContext { self.bcx.ccx() } - fn tcx(&self) -> ty::ctxt { + pub fn tcx(&self) -> ty::ctxt { self.bcx.tcx() } - fn to_str(&self) -> ~str { + pub fn to_str(&self) -> ~str { self.datum.to_str(self.ccx()) } } diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index d8252a449ba0d..88b7f7e70de74 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; use driver::session; use lib::llvm::ValueRef; @@ -19,8 +20,14 @@ use middle::trans; use middle::ty; use util::ppaux::ty_to_str; +use core::cast; use core::hashmap::HashMap; use core::libc; +use core::option; +use core::ptr; +use core::str; +use core::sys; +use core::vec; use syntax::codemap::span; use syntax::parse::token::ident_interner; use syntax::{ast, codemap, ast_util, ast_map}; @@ -217,7 +224,7 @@ fn create_compile_unit(cx: @CrateContext) -> @Metadata { llstr(env!("CFG_VERSION")), lli1(true), // deprecated: main compile unit lli1(cx.sess.opts.optimize != session::No), - llstr(~""), // flags (???) + llstr(""), // flags (???) lli32(0) // runtime version (???) ]; let unit_node = llmdnode(unit_metadata); @@ -368,7 +375,7 @@ fn create_basic_type(cx: @CrateContext, t: ty::t, span: span) ast::ty_f32 => (~"f32", DW_ATE_float), ast::ty_f64 => (~"f64", DW_ATE_float) }, - _ => cx.sess.bug(~"debuginfo::create_basic_type - t is invalid type") + _ => cx.sess.bug("debuginfo::create_basic_type - t is invalid type") }; let fname = filename_from_span(cx, span); @@ -522,7 +529,7 @@ fn create_tuple(cx: @CrateContext, t: ty::t, elements: &[ty::t], span: span) for elements.each |element| { let ty_md = create_ty(cx, *element, span); let (size, align) = size_and_align_of(cx, *element); - add_member(scx, ~"", line_from_span(cx.sess.codemap, span) as int, + add_member(scx, "", line_from_span(cx.sess.codemap, span) as int, size as int, align as int, ty_md.node); } let mdval = @Metadata { @@ -539,7 +546,7 @@ fn voidptr() -> (ValueRef, int, int) { let null = ptr::null(); let size = sys::size_of::() as int; let align = sys::min_align_of::() as int; - let vp = create_derived_type(PointerTypeTag, null, ~"", 0, + let vp = create_derived_type(PointerTypeTag, null, "", 0, size, align, 0, null); return (vp, size, align); } @@ -561,16 +568,16 @@ fn create_boxed_type(cx: @CrateContext, contents: ty::t, let refcount_type = create_basic_type(cx, int_t, span); let name = ty_to_str(cx.tcx, contents); let scx = create_structure(file_node, @fmt!("box<%s>", name), 0); - add_member(scx, ~"refcnt", 0, sys::size_of::() as int, + add_member(scx, "refcnt", 0, sys::size_of::() as int, sys::min_align_of::() as int, refcount_type.node); // the tydesc and other pointers should be irrelevant to the // debugger, so treat them as void* types let (vp, vpsize, vpalign) = voidptr(); - add_member(scx, ~"tydesc", 0, vpsize, vpalign, vp); - add_member(scx, ~"prev", 0, vpsize, vpalign, vp); - add_member(scx, ~"next", 0, vpsize, vpalign, vp); + add_member(scx, "tydesc", 0, vpsize, vpalign, vp); + add_member(scx, "prev", 0, vpsize, vpalign, vp); + add_member(scx, "next", 0, vpsize, vpalign, vp); let (size, align) = size_and_align_of(cx, contents); - add_member(scx, ~"boxed", 0, size, align, boxed.node); + add_member(scx, "boxed", 0, size, align, boxed.node); let llnode = finish_structure(scx); let mdval = @Metadata { node: llnode, @@ -619,7 +626,7 @@ fn create_fixed_vec(cx: @CrateContext, vec_t: ty::t, elem_t: ty::t, let fname = filename_from_span(cx, span); let file_node = create_file(cx, fname); let (size, align) = size_and_align_of(cx, elem_t); - let subrange = llmdnode(~[lltag(SubrangeTag), lli64(0), lli64(len - 1)]); + let subrange = llmdnode([lltag(SubrangeTag), lli64(0), lli64(len - 1)]); let name = fmt!("[%s]", ty_to_str(cx.tcx, elem_t)); let array = create_composite_type(ArrayTypeTag, name, file_node.node, 0, size * len, align, 0, Some(t_md.node), @@ -641,18 +648,18 @@ fn create_boxed_vec(cx: @CrateContext, vec_t: ty::t, elem_t: ty::t, let vec_scx = create_structure(file_node, @/*bad*/ copy ty_to_str(cx.tcx, vec_t), 0); let size_t_type = create_basic_type(cx, ty::mk_uint(), vec_ty_span); - add_member(vec_scx, ~"fill", 0, sys::size_of::() as int, + add_member(vec_scx, "fill", 0, sys::size_of::() as int, sys::min_align_of::() as int, size_t_type.node); - add_member(vec_scx, ~"alloc", 0, sys::size_of::() as int, + add_member(vec_scx, "alloc", 0, sys::size_of::() as int, sys::min_align_of::() as int, size_t_type.node); - let subrange = llmdnode(~[lltag(SubrangeTag), lli64(0), lli64(0)]); + let subrange = llmdnode([lltag(SubrangeTag), lli64(0), lli64(0)]); let (arr_size, arr_align) = size_and_align_of(cx, elem_t); let name = fmt!("[%s]", ty_to_str(cx.tcx, elem_t)); let data_ptr = create_composite_type(ArrayTypeTag, name, file_node.node, 0, arr_size, arr_align, 0, Some(elem_ty_md.node), Some(~[subrange])); - add_member(vec_scx, ~"data", 0, 0, // clang says the size should be 0 + add_member(vec_scx, "data", 0, 0, // clang says the size should be 0 sys::min_align_of::() as int, data_ptr); let llnode = finish_structure(vec_scx); let vec_md = @Metadata { @@ -665,15 +672,15 @@ fn create_boxed_vec(cx: @CrateContext, vec_t: ty::t, elem_t: ty::t, let box_scx = create_structure(file_node, @fmt!("box<%s>", name), 0); let int_t = ty::mk_int(); let refcount_type = create_basic_type(cx, int_t, vec_ty_span); - add_member(box_scx, ~"refcnt", 0, sys::size_of::() as int, + add_member(box_scx, "refcnt", 0, sys::size_of::() as int, sys::min_align_of::() as int, refcount_type.node); let (vp, vpsize, vpalign) = voidptr(); - add_member(box_scx, ~"tydesc", 0, vpsize, vpalign, vp); - add_member(box_scx, ~"prev", 0, vpsize, vpalign, vp); - add_member(box_scx, ~"next", 0, vpsize, vpalign, vp); + add_member(box_scx, "tydesc", 0, vpsize, vpalign, vp); + add_member(box_scx, "prev", 0, vpsize, vpalign, vp); + add_member(box_scx, "next", 0, vpsize, vpalign, vp); let size = 2 * sys::size_of::() as int; let align = sys::min_align_of::() as int; - add_member(box_scx, ~"boxed", 0, size, align, vec_md.node); + add_member(box_scx, "boxed", 0, size, align, vec_md.node); let llnode = finish_structure(box_scx); let mdval = @Metadata { node: llnode, @@ -693,8 +700,8 @@ fn create_vec_slice(cx: @CrateContext, vec_t: ty::t, elem_t: ty::t, span: span) let elem_ptr = create_pointer_type(cx, elem_t, span, elem_ty_md); let scx = create_structure(file_node, @ty_to_str(cx.tcx, vec_t), 0); let (_, ptr_size, ptr_align) = voidptr(); - add_member(scx, ~"vec", 0, ptr_size, ptr_align, elem_ptr.node); - add_member(scx, ~"length", 0, sys::size_of::() as int, + add_member(scx, "vec", 0, ptr_size, ptr_align, elem_ptr.node); + add_member(scx, "length", 0, sys::size_of::() as int, sys::min_align_of::() as int, uint_type.node); let llnode = finish_structure(scx); let mdval = @Metadata { @@ -715,7 +722,7 @@ fn create_fn_ty(cx: @CrateContext, fn_ty: ty::t, inputs: ~[ty::t], output: ty::t let output_ptr_md = create_pointer_type(cx, output, span, output_md); let inputs_vals = do inputs.map |arg| { create_ty(cx, *arg, span).node }; let members = ~[output_ptr_md.node, vp] + inputs_vals; - let llnode = create_composite_type(SubroutineTag, ~"", file_node.node, + let llnode = create_composite_type(SubroutineTag, "", file_node.node, 0, 0, 0, 0, None, Some(members)); let mdval = @Metadata { node: llnode, @@ -802,7 +809,7 @@ fn create_ty(cx: @CrateContext, t: ty::t, span: span) ty::ty_tup(ref elements) => { create_tuple(cx, t, *elements, span) }, - _ => cx.sess.bug(~"debuginfo: unexpected type in create_ty") + _ => cx.sess.bug("debuginfo: unexpected type in create_ty") } } @@ -857,19 +864,16 @@ pub fn create_local_var(bcx: block, local: @ast::local) }; update_cache(cache, AutoVariableTag, local_var_metadata(mdval)); - let llptr = match bcx.fcx.lllocals.find(&local.node.id) { - option::Some(&local_mem(v)) => v, - option::Some(_) => { - bcx.tcx().sess.span_bug(local.span, "local is bound to something weird"); - } - option::None => { - match bcx.fcx.lllocals.get_copy(&local.node.pat.id) { - local_imm(v) => v, - _ => bcx.tcx().sess.span_bug(local.span, "local is bound to something weird") + // FIXME(#6814) Should use `pat_util::pat_bindings` for pats like (a, b) etc + let llptr = match bcx.fcx.lllocals.find_copy(&local.node.pat.id) { + Some(v) => v, + None => { + bcx.tcx().sess.span_bug( + local.span, + fmt!("No entry in lllocals table for %?", local.node.id)); } - } }; - let declargs = ~[llmdnode(~[llptr]), mdnode]; + let declargs = ~[llmdnode([llptr]), mdnode]; trans::build::Call(bcx, *cx.intrinsics.get(&~"llvm.dbg.declare"), declargs); return mdval; @@ -877,7 +881,8 @@ pub fn create_local_var(bcx: block, local: @ast::local) pub fn create_arg(bcx: block, arg: ast::arg, sp: span) -> Option<@Metadata> { - let fcx = bcx.fcx, cx = *fcx.ccx; + let fcx = bcx.fcx; + let cx = *fcx.ccx; let cache = get_cache(cx); let tg = ArgVariableTag; match cached_metadata::<@Metadata>( @@ -915,10 +920,8 @@ pub fn create_arg(bcx: block, arg: ast::arg, sp: span) }; update_cache(cache, tg, argument_metadata(mdval)); - let llptr = match fcx.llargs.get_copy(&arg.id) { - local_mem(v) | local_imm(v) => v, - }; - let declargs = ~[llmdnode(~[llptr]), mdnode]; + let llptr = fcx.llargs.get_copy(&arg.id); + let declargs = ~[llmdnode([llptr]), mdnode]; trans::build::Call(bcx, *cx.intrinsics.get(&~"llvm.dbg.declare"), declargs); @@ -1003,7 +1006,7 @@ pub fn create_function(fcx: fn_ctxt) -> @Metadata { } else { llnull() }; - let sub_node = create_composite_type(SubroutineTag, ~"", file_node, 0, 0, + let sub_node = create_composite_type(SubroutineTag, "", file_node, 0, 0, 0, 0, option::None, option::Some(~[ty_node])); @@ -1013,7 +1016,7 @@ pub fn create_function(fcx: fn_ctxt) -> @Metadata { llstr(*cx.sess.str_of(ident)), //XXX fully-qualified C++ name: llstr(*cx.sess.str_of(ident)), - llstr(~""), //XXX MIPS name????? + llstr(""), //XXX MIPS name????? file_node, lli32(loc.line as int), sub_node, diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index 59526ffbe498d..65afafcd60d8f 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -119,6 +119,8 @@ lvalues are *never* stored by value. */ +use core::prelude::*; + use back::abi; use lib::llvm::{ValueRef, TypeRef, llvm}; use lib; @@ -145,13 +147,14 @@ use middle::trans::type_of; use middle::ty::struct_fields; use middle::ty::{AutoDerefRef, AutoAddEnv}; use middle::ty::{AutoPtr, AutoBorrowVec, AutoBorrowVecRef, AutoBorrowFn, - AutoDerefRef, AutoAddEnv, AutoUnsafe}; + AutoUnsafe}; use middle::ty; use util::common::indenter; use util::ppaux::Repr; use core::cast::transmute; use core::hashmap::HashMap; +use core::vec; use syntax::print::pprust::{expr_to_str}; use syntax::ast; use syntax::codemap; @@ -167,8 +170,8 @@ pub enum Dest { Ignore, } -pub impl Dest { - fn to_str(&self, ccx: @CrateContext) -> ~str { +impl Dest { + pub fn to_str(&self, ccx: @CrateContext) -> ~str { match *self { SaveIn(v) => fmt!("SaveIn(%s)", val_str(ccx.tn, v)), Ignore => ~"Ignore" @@ -244,7 +247,7 @@ pub fn trans_to_datum(bcx: block, expr: @ast::expr) -> DatumBlock { // must patchup the type. DatumBlock {bcx: bcx, datum: Datum {val: datum.val, ty: adjusted_ty, - mode: datum.mode, source: datum.source}} + mode: datum.mode}} } fn auto_slice(bcx: block, @@ -287,7 +290,7 @@ pub fn trans_to_datum(bcx: block, expr: @ast::expr) -> DatumBlock { debug!("add_env(closure_ty=%s)", closure_ty.repr(tcx)); let scratch = scratch_datum(bcx, closure_ty, false); let llfn = GEPi(bcx, scratch.val, [0u, abi::fn_field_code]); - assert!(datum.appropriate_mode() == ByValue); + assert_eq!(datum.appropriate_mode(), ByValue); Store(bcx, datum.to_appropriate_llval(bcx), llfn); let llenv = GEPi(bcx, scratch.val, [0u, abi::fn_field_box]); Store(bcx, base::null_env_ptr(bcx), llenv); @@ -467,13 +470,13 @@ fn trans_rvalue_datum_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock { ast::expr_lit(lit) => { return trans_immediate_lit(bcx, expr, *lit); } - ast::expr_binary(op, lhs, rhs) => { + ast::expr_binary(_, op, lhs, rhs) => { // if overloaded, would be RvalueDpsExpr assert!(!bcx.ccx().maps.method_map.contains_key(&expr.id)); return trans_binary(bcx, expr, op, lhs, rhs); } - ast::expr_unary(op, x) => { + ast::expr_unary(_, op, x) => { return trans_unary_datum(bcx, expr, op, x); } ast::expr_addr_of(_, x) => { @@ -499,6 +502,10 @@ fn trans_rvalue_stmt_unadjusted(bcx: block, expr: @ast::expr) -> block { let mut bcx = bcx; let _icx = bcx.insn_ctxt("trans_rvalue_stmt"); + if bcx.unreachable { + return bcx; + } + trace_span!(bcx, expr.span, @shorten(bcx.expr_to_str(expr))); match expr.node { @@ -528,8 +535,8 @@ fn trans_rvalue_stmt_unadjusted(bcx: block, expr: @ast::expr) -> block { return src_datum.store_to_datum( bcx, src.id, DROP_EXISTING, dst_datum); } - ast::expr_assign_op(op, dst, src) => { - return trans_assign_op(bcx, expr, op, dst, src); + ast::expr_assign_op(callee_id, op, dst, src) => { + return trans_assign_op(bcx, expr, callee_id, op, dst, src); } ast::expr_paren(a) => { return trans_rvalue_stmt_unadjusted(bcx, a); @@ -576,7 +583,7 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr, }; } ast::expr_struct(_, ref fields, base) => { - return trans_rec_or_struct(bcx, (*fields), base, expr.id, dest); + return trans_rec_or_struct(bcx, (*fields), base, expr.span, expr.id, dest); } ast::expr_tup(ref args) => { let repr = adt::represent_type(bcx.ccx(), expr_ty(bcx, expr)); @@ -634,35 +641,39 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr, return callee::trans_call( bcx, expr, f, callee::ArgExprs(*args), expr.id, dest); } - ast::expr_method_call(rcvr, _, _, ref args, _) => { + ast::expr_method_call(callee_id, rcvr, _, _, ref args, _) => { return callee::trans_method_call(bcx, expr, + callee_id, rcvr, callee::ArgExprs(*args), dest); } - ast::expr_binary(_, lhs, rhs) => { + ast::expr_binary(callee_id, _, lhs, rhs) => { // if not overloaded, would be RvalueDatumExpr return trans_overloaded_op(bcx, expr, + callee_id, lhs, ~[rhs], expr_ty(bcx, expr), dest); } - ast::expr_unary(_, subexpr) => { + ast::expr_unary(callee_id, _, subexpr) => { // if not overloaded, would be RvalueDatumExpr return trans_overloaded_op(bcx, expr, + callee_id, subexpr, ~[], expr_ty(bcx, expr), dest); } - ast::expr_index(base, idx) => { + ast::expr_index(callee_id, base, idx) => { // if not overloaded, would be RvalueDatumExpr return trans_overloaded_op(bcx, expr, + callee_id, base, ~[idx], expr_ty(bcx, expr), @@ -680,8 +691,8 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr, } } } - ast::expr_assign_op(op, dst, src) => { - return trans_assign_op(bcx, expr, op, dst, src); + ast::expr_assign_op(callee_id, op, dst, src) => { + return trans_assign_op(bcx, expr, callee_id, op, dst, src); } _ => { bcx.tcx().sess.span_bug( @@ -720,8 +731,14 @@ fn trans_def_dps_unadjusted(bcx: block, ref_expr: @ast::expr, } } ast::def_struct(*) => { - // Nothing to do here. - // XXX: May not be true in the case of classes with destructors. + let ty = expr_ty(bcx, ref_expr); + match ty::get(ty).sty { + ty::ty_struct(did, _) if ty::has_dtor(ccx.tcx, did) => { + let repr = adt::represent_type(ccx, ty); + adt::trans_start_init(bcx, repr, lldest, 0); + } + _ => {} + } return bcx; } _ => { @@ -786,8 +803,7 @@ fn trans_def_datum_unadjusted(bcx: block, bcx: bcx, datum: Datum {val: llval, ty: rust_ty, - mode: ByValue, - source: RevokeClean} + mode: ByValue} }; } } @@ -816,10 +832,10 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock { ast::expr_field(base, ident, _) => { trans_rec_field(bcx, base, ident) } - ast::expr_index(base, idx) => { + ast::expr_index(_, base, idx) => { trans_index(bcx, expr, base, idx) } - ast::expr_unary(ast::deref, base) => { + ast::expr_unary(_, ast::deref, base) => { let basedatum = unpack_datum!(bcx, trans_to_datum(bcx, base)); basedatum.deref(bcx, expr, 0) } @@ -885,9 +901,9 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock { }; let vt = tvec::vec_types(bcx, base_datum.ty); - base::maybe_name_value(bcx.ccx(), vt.llunit_size, ~"unit_sz"); + base::maybe_name_value(bcx.ccx(), vt.llunit_size, "unit_sz"); let scaled_ix = Mul(bcx, ix_val, vt.llunit_size); - base::maybe_name_value(bcx.ccx(), scaled_ix, ~"scaled_ix"); + base::maybe_name_value(bcx.ccx(), scaled_ix, "scaled_ix"); let mut (bcx, base, len) = base_datum.get_vec_base_and_len(bcx, index_expr.span, @@ -907,14 +923,13 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock { controlflow::trans_fail_bounds_check(bcx, index_expr.span, ix_val, unscaled_len) }; - let elt = InBoundsGEP(bcx, base, ~[ix_val]); + let elt = InBoundsGEP(bcx, base, [ix_val]); let elt = PointerCast(bcx, elt, T_ptr(vt.llunit_ty)); return DatumBlock { bcx: bcx, datum: Datum {val: elt, ty: vt.unit_ty, - mode: ByRef, - source: ZeroMem} + mode: ByRef(ZeroMem)} }; } @@ -981,8 +996,7 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock { bcx: bcx, datum: Datum {val: val, ty: const_ty, - mode: ByRef, - source: ZeroMem} + mode: ByRef(ZeroMem)} } } _ => { @@ -1007,8 +1021,7 @@ pub fn trans_local_var(bcx: block, def: ast::def) -> Datum { Datum { val: val, ty: local_ty, - mode: ByRef, - source: ZeroMem + mode: ByRef(ZeroMem) } } None => { @@ -1045,8 +1058,7 @@ pub fn trans_local_var(bcx: block, def: ast::def) -> Datum { Datum { val: casted_val, ty: self_info.t, - mode: ByRef, - source: ZeroMem + mode: ByRef(ZeroMem) } } _ => { @@ -1056,26 +1068,22 @@ pub fn trans_local_var(bcx: block, def: ast::def) -> Datum { }; fn take_local(bcx: block, - table: &HashMap, + table: &HashMap, nid: ast::node_id) -> Datum { - let (v, mode) = match table.find(&nid) { - Some(&local_mem(v)) => (v, ByRef), - Some(&local_imm(v)) => (v, ByValue), + let v = match table.find(&nid) { + Some(&v) => v, None => { bcx.sess().bug(fmt!( "trans_local_var: no llval for local/arg %? found", nid)); } }; let ty = node_id_type(bcx, nid); - - debug!("take_local(nid=%?, v=%s, mode=%?, ty=%s)", - nid, bcx.val_str(v), mode, bcx.ty_to_str(ty)); - + debug!("take_local(nid=%?, v=%s, ty=%s)", + nid, bcx.val_str(v), bcx.ty_to_str(ty)); Datum { val: v, ty: ty, - mode: mode, - source: ZeroMem + mode: ByRef(ZeroMem) } } } @@ -1110,8 +1118,8 @@ pub fn with_field_tys(tcx: ty::ctxt, struct_fields(tcx, variant_id, substs)) } _ => { - tcx.sess.bug(~"resolve didn't map this expr to a \ - variant ID") + tcx.sess.bug("resolve didn't map this expr to a \ + variant ID") } } } @@ -1129,6 +1137,7 @@ pub fn with_field_tys(tcx: ty::ctxt, fn trans_rec_or_struct(bcx: block, fields: &[ast::field], base: Option<@ast::expr>, + expr_span: codemap::span, id: ast::node_id, dest: Dest) -> block { @@ -1167,8 +1176,7 @@ fn trans_rec_or_struct(bcx: block, } None => { if need_base.any(|b| *b) { - // XXX should be span bug - tcx.sess.bug(~"missing fields and no base expr") + tcx.sess.span_bug(expr_span, "missing fields and no base expr") } None } @@ -1232,8 +1240,8 @@ fn trans_adt(bcx: block, repr: &adt::Repr, discr: int, temp_cleanups.push(dest); } for optbase.each |base| { - // XXX is it sound to use the destination's repr on the base? - // XXX would it ever be reasonable to be here with discr != 0? + // FIXME #6573: is it sound to use the destination's repr on the base? + // And, would it ever be reasonable to be here with discr != 0? let base_datum = unpack_datum!(bcx, trans_to_datum(bcx, base.expr)); for base.fields.each |&(i, t)| { let datum = do base_datum.get_element(bcx, t, ZeroMem) |srcval| { @@ -1313,9 +1321,9 @@ fn trans_unary_datum(bcx: block, trans_boxed_expr(bcx, un_ty, sub_expr, sub_ty, heap) } ast::deref => { - bcx.sess().bug(~"deref expressions should have been \ - translated using trans_lvalue(), not \ - trans_unary_datum()") + bcx.sess().bug("deref expressions should have been \ + translated using trans_lvalue(), not \ + trans_unary_datum()") } }; @@ -1482,8 +1490,8 @@ fn trans_lazy_binop(bcx: block, } Br(past_rhs, join.llbb); - let phi = Phi(join, T_bool(), ~[lhs, rhs], ~[past_lhs.llbb, - past_rhs.llbb]); + let phi = Phi(join, T_bool(), [lhs, rhs], [past_lhs.llbb, + past_rhs.llbb]); return immediate_rvalue_bcx(join, phi, binop_ty); } @@ -1516,20 +1524,21 @@ fn trans_binary(bcx: block, fn trans_overloaded_op(bcx: block, expr: @ast::expr, + callee_id: ast::node_id, rcvr: @ast::expr, args: ~[@ast::expr], ret_ty: ty::t, dest: Dest) -> block { let origin = bcx.ccx().maps.method_map.get_copy(&expr.id); - let fty = node_id_type(bcx, expr.callee_id); + let fty = node_id_type(bcx, callee_id); callee::trans_call_inner(bcx, expr.info(), fty, ret_ty, |bcx| { meth::trans_method_callee(bcx, - expr.callee_id, + callee_id, rcvr, origin) }, @@ -1644,16 +1653,17 @@ fn trans_imm_cast(bcx: block, expr: @ast::expr, val_ty(lldiscrim_a), lldiscrim_a, true), cast_float => SIToFP(bcx, lldiscrim_a, ll_t_out), - _ => ccx.sess.bug(~"translating unsupported cast.") + _ => ccx.sess.bug("translating unsupported cast.") } } - _ => ccx.sess.bug(~"translating unsupported cast.") + _ => ccx.sess.bug("translating unsupported cast.") }; return immediate_rvalue_bcx(bcx, newval, t_out); } fn trans_assign_op(bcx: block, expr: @ast::expr, + callee_id: ast::node_id, op: ast::binop, dst: @ast::expr, src: @ast::expr) -> block @@ -1672,6 +1682,7 @@ fn trans_assign_op(bcx: block, let scratch = scratch_datum(bcx, dst_datum.ty, false); let bcx = trans_overloaded_op(bcx, expr, + callee_id, dst, ~[src], dst_datum.ty, diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index fd545ca2c6ea8..dfcf364233be2 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use back::{link, abi}; use lib::llvm::{SequentiallyConsistent, Acquire, Release, Xchg}; use lib::llvm::{TypeRef, ValueRef}; @@ -32,11 +34,14 @@ use middle::ty; use middle::ty::FnSig; use util::ppaux::ty_to_str; +use core::uint; +use core::vec; use syntax::codemap::span; use syntax::{ast, ast_util}; use syntax::{attr, ast_map}; use syntax::opt_vec; use syntax::parse::token::special_idents; +use syntax::parse::token; use syntax::abi::{X86, X86_64, Arm, Mips}; use syntax::abi::{RustIntrinsic, Rust, Stdcall, Fastcall, Cdecl, Aapcs, C}; @@ -51,7 +56,7 @@ fn abi_info(ccx: @CrateContext) -> @cabi::ABIInfo { } pub fn link_name(ccx: @CrateContext, i: @ast::foreign_item) -> @~str { - match attr::first_attr_value_str_by_name(i.attrs, ~"link_name") { + match attr::first_attr_value_str_by_name(i.attrs, "link_name") { None => ccx.sess.str_of(i.ident), Some(ln) => ln, } @@ -106,7 +111,7 @@ fn foreign_signature(ccx: @CrateContext, fn_sig: &ty::FnSig) fn shim_types(ccx: @CrateContext, id: ast::node_id) -> ShimTypes { let fn_sig = match ty::get(ty::node_id_to_type(ccx.tcx, id)).sty { ty::ty_bare_fn(ref fn_ty) => copy fn_ty.sig, - _ => ccx.sess.bug(~"c_arg_and_ret_lltys called on non-function type") + _ => ccx.sess.bug("c_arg_and_ret_lltys called on non-function type") }; let llsig = foreign_signature(ccx, &fn_sig); let bundle_ty = T_struct(vec::append_one(copy llsig.llarg_tys, @@ -122,7 +127,7 @@ fn shim_types(ccx: @CrateContext, id: ast::node_id) -> ShimTypes { llsig: llsig, ret_def: ret_def, bundle_ty: bundle_ty, - shim_fn_ty: T_fn(~[T_ptr(bundle_ty)], T_nil()), + shim_fn_ty: T_fn([T_ptr(bundle_ty)], T_nil()), fn_ty: fn_ty } } @@ -151,6 +156,7 @@ fn build_shim_fn_(ccx: @CrateContext, let fcx = new_fn_ctxt(ccx, ~[], llshimfn, tys.fn_sig.output, None); let bcx = top_scope_block(fcx, None); let lltop = bcx.llbb; + let llargbundle = get_param(llshimfn, 0u); let llargvals = arg_builder(bcx, tys, llargbundle); @@ -207,7 +213,7 @@ fn build_wrap_fn_(ccx: @CrateContext, // Create call itself. let llshimfnptr = PointerCast(bcx, llshimfn, T_ptr(T_i8())); let llrawargbundle = PointerCast(bcx, llargbundle, T_ptr(T_i8())); - Call(bcx, shim_upcall, ~[llrawargbundle, llshimfnptr]); + Call(bcx, shim_upcall, [llrawargbundle, llshimfnptr]); ret_builder(bcx, tys, llargbundle); // Perform a custom version of `finish_fn`. First, tie up the header @@ -338,8 +344,7 @@ pub fn trans_foreign_mod(ccx: @CrateContext, } } ast::foreign_item_const(*) => { - let ident = ccx.sess.parse_sess.interner.get( - foreign_item.ident); + let ident = token::ident_to_str(&foreign_item.ident); ccx.item_symbols.insert(foreign_item.id, copy *ident); } } @@ -400,7 +405,7 @@ pub fn trans_foreign_mod(ccx: @CrateContext, let lname = link_name(ccx, foreign_item); let llbasefn = base_fn(ccx, *lname, tys, cc); // Name the shim function - let shim_name = *lname + ~"__c_stack_shim"; + let shim_name = *lname + "__c_stack_shim"; build_shim_fn_(ccx, shim_name, llbasefn, @@ -431,15 +436,16 @@ pub fn trans_foreign_mod(ccx: @CrateContext, debug!("build_direct_fn(%s)", *link_name(ccx, item)); let fcx = new_fn_ctxt(ccx, ~[], decl, tys.fn_sig.output, None); - let bcx = top_scope_block(fcx, None), lltop = bcx.llbb; + let bcx = top_scope_block(fcx, None); + let lltop = bcx.llbb; let llbasefn = base_fn(ccx, *link_name(ccx, item), tys, cc); let ty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(item.id)).ty; + let ret_ty = ty::ty_fn_ret(ty); let args = vec::from_fn(ty::ty_fn_args(ty).len(), |i| { - get_param(decl, i + first_real_arg) + get_param(decl, fcx.arg_pos(i)) }); let retval = Call(bcx, llbasefn, args); - let ret_ty = ty::ty_fn_ret(ty); if !ty::type_is_nil(ret_ty) && !ty::type_is_bot(ret_ty) { Store(bcx, retval, fcx.llretptr.get()); } @@ -457,17 +463,18 @@ pub fn trans_foreign_mod(ccx: @CrateContext, debug!("build_fast_ffi_fn(%s)", *link_name(ccx, item)); let fcx = new_fn_ctxt(ccx, ~[], decl, tys.fn_sig.output, None); - let bcx = top_scope_block(fcx, None), lltop = bcx.llbb; + let bcx = top_scope_block(fcx, None); + let lltop = bcx.llbb; let llbasefn = base_fn(ccx, *link_name(ccx, item), tys, cc); set_no_inline(fcx.llfn); set_fixed_stack_segment(fcx.llfn); let ty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(item.id)).ty; + let ret_ty = ty::ty_fn_ret(ty); let args = vec::from_fn(ty::ty_fn_args(ty).len(), |i| { - get_param(decl, i + first_real_arg) + get_param(decl, fcx.arg_pos(i)) }); let retval = Call(bcx, llbasefn, args); - let ret_ty = ty::ty_fn_ret(ty); if !ty::type_is_nil(ret_ty) && !ty::type_is_bot(ret_ty) { Store(bcx, retval, fcx.llretptr.get()); } @@ -510,9 +517,9 @@ pub fn trans_foreign_mod(ccx: @CrateContext, let _icx = bcx.insn_ctxt("foreign::wrap::build_args"); let ccx = bcx.ccx(); let n = tys.llsig.llarg_tys.len(); - let implicit_args = first_real_arg; // return + env for uint::range(0, n) |i| { - let mut llargval = get_param(llwrapfn, i + implicit_args); + let arg_i = bcx.fcx.arg_pos(i); + let mut llargval = get_param(llwrapfn, arg_i); // In some cases, Rust will pass a pointer which the // native C type doesn't have. In that case, just @@ -521,10 +528,10 @@ pub fn trans_foreign_mod(ccx: @CrateContext, llargval = Load(bcx, llargval); } - store_inbounds(bcx, llargval, llargbundle, ~[0u, i]); + store_inbounds(bcx, llargval, llargbundle, [0u, i]); } let llretptr = bcx.fcx.llretptr.get(); - store_inbounds(bcx, llretptr, llargbundle, ~[0u, n]); + store_inbounds(bcx, llretptr, llargbundle, [0u, n]); } fn build_ret(bcx: block, @@ -532,7 +539,7 @@ pub fn trans_foreign_mod(ccx: @CrateContext, llargbundle: ValueRef) { let _icx = bcx.insn_ctxt("foreign::wrap::build_ret"); let arg_count = shim_types.fn_sig.inputs.len(); - let llretptr = load_inbounds(bcx, llargbundle, ~[0, arg_count]); + let llretptr = load_inbounds(bcx, llargbundle, [0, arg_count]); Store(bcx, Load(bcx, llretptr), bcx.fcx.llretptr.get()); build_return(bcx); } @@ -550,14 +557,13 @@ pub fn trans_intrinsic(ccx: @CrateContext, let output_type = ty::ty_fn_ret(ty::node_id_to_type(ccx.tcx, item.id)); - // XXX: Bad copy. let fcx = new_fn_ctxt_w_id(ccx, path, decl, item.id, output_type, None, - Some(copy substs), + Some(substs), Some(item.span)); // Set the fixed stack segment flag if necessary. @@ -567,6 +573,7 @@ pub fn trans_intrinsic(ccx: @CrateContext, let mut bcx = top_scope_block(fcx, None); let lltop = bcx.llbb; + let first_real_arg = fcx.arg_pos(0u); match *ccx.sess.str_of(item.ident) { ~"atomic_cxchg" => { let old = AtomicCmpXchg(bcx, @@ -686,19 +693,15 @@ pub fn trans_intrinsic(ccx: @CrateContext, fcx.llretptr.get()); } ~"move_val" => { - // Create a datum reflecting the value being moved: - // - // - the datum will be by ref if the value is non-immediate; - // - // - the datum has a RevokeClean source because, that way, - // the `move_to()` method does not feel compelled to - // zero out the memory where the datum resides. Zeroing - // is not necessary since, for intrinsics, there is no - // cleanup to concern ourselves with. + // Create a datum reflecting the value being moved. + // Use `appropriate_mode` so that the datum is by ref + // if the value is non-immediate. Note that, with + // intrinsics, there are no argument cleanups to + // concern ourselves with. let tp_ty = substs.tys[0]; let mode = appropriate_mode(tp_ty); let src = Datum {val: get_param(decl, first_real_arg + 1u), - ty: tp_ty, mode: mode, source: RevokeClean}; + ty: tp_ty, mode: mode}; bcx = src.move_to(bcx, DROP_EXISTING, get_param(decl, first_real_arg)); } @@ -707,7 +710,7 @@ pub fn trans_intrinsic(ccx: @CrateContext, let tp_ty = substs.tys[0]; let mode = appropriate_mode(tp_ty); let src = Datum {val: get_param(decl, first_real_arg + 1u), - ty: tp_ty, mode: mode, source: RevokeClean}; + ty: tp_ty, mode: mode}; bcx = src.move_to(bcx, INIT, get_param(decl, first_real_arg)); } ~"min_align_of" => { @@ -786,7 +789,7 @@ pub fn trans_intrinsic(ccx: @CrateContext, let llsrcptr = PointerCast(bcx, llsrcptr, T_ptr(T_i8())); let llsize = llsize_of(ccx, llintype); - call_memcpy(bcx, lldestptr, llsrcptr, llsize); + call_memcpy(bcx, lldestptr, llsrcptr, llsize, 1); } } ~"needs_drop" => { @@ -809,7 +812,7 @@ pub fn trans_intrinsic(ccx: @CrateContext, } ~"frame_address" => { let frameaddress = *ccx.intrinsics.get(&~"llvm.frameaddress"); - let frameaddress_val = Call(bcx, frameaddress, ~[C_i32(0i32)]); + let frameaddress_val = Call(bcx, frameaddress, [C_i32(0i32)]); let star_u8 = ty::mk_imm_ptr( bcx.tcx(), ty::mk_mach_uint(ast::ty_u8)); @@ -826,7 +829,7 @@ pub fn trans_intrinsic(ccx: @CrateContext, } }); let datum = Datum {val: get_param(decl, first_real_arg), - mode: ByRef, ty: fty, source: ZeroMem}; + mode: ByRef(ZeroMem), ty: fty}; let arg_vals = ~[frameaddress_val]; bcx = trans_call_inner( bcx, None, fty, ty::mk_nil(), @@ -837,273 +840,331 @@ pub fn trans_intrinsic(ccx: @CrateContext, // XXX This is a hack to grab the address of this particular // native function. There should be a general in-language // way to do this - let llfty = type_of_fn(bcx.ccx(), ~[], ty::mk_nil()); + let llfty = type_of_fn(bcx.ccx(), [], ty::mk_nil()); let morestack_addr = decl_cdecl_fn( - bcx.ccx().llmod, ~"__morestack", llfty); + bcx.ccx().llmod, "__morestack", llfty); let morestack_addr = PointerCast(bcx, morestack_addr, T_ptr(T_nil())); Store(bcx, morestack_addr, fcx.llretptr.get()); } + ~"memcpy32" => { + let tp_ty = substs.tys[0]; + let lltp_ty = type_of::type_of(ccx, tp_ty); + let align = C_i32(machine::llalign_of_min(ccx, lltp_ty) as i32); + let size = C_i32(machine::llsize_of_real(ccx, lltp_ty) as i32); + + let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), T_ptr(T_i8())); + let src_ptr = PointerCast(bcx, get_param(decl, first_real_arg + 1), T_ptr(T_i8())); + let count = get_param(decl, first_real_arg + 2); + let volatile = C_i1(false); + let llfn = *bcx.ccx().intrinsics.get(&~"llvm.memcpy.p0i8.p0i8.i32"); + Call(bcx, llfn, [dst_ptr, src_ptr, Mul(bcx, size, count), align, volatile]); + } + ~"memcpy64" => { + let tp_ty = substs.tys[0]; + let lltp_ty = type_of::type_of(ccx, tp_ty); + let align = C_i32(machine::llalign_of_min(ccx, lltp_ty) as i32); + let size = C_i64(machine::llsize_of_real(ccx, lltp_ty) as i64); + + let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), T_ptr(T_i8())); + let src_ptr = PointerCast(bcx, get_param(decl, first_real_arg + 1), T_ptr(T_i8())); + let count = get_param(decl, first_real_arg + 2); + let volatile = C_i1(false); + let llfn = *bcx.ccx().intrinsics.get(&~"llvm.memcpy.p0i8.p0i8.i64"); + Call(bcx, llfn, [dst_ptr, src_ptr, Mul(bcx, size, count), align, volatile]); + } ~"memmove32" => { - let dst_ptr = get_param(decl, first_real_arg); - let src_ptr = get_param(decl, first_real_arg + 1); - let size = get_param(decl, first_real_arg + 2); - let align = C_i32(1); + let tp_ty = substs.tys[0]; + let lltp_ty = type_of::type_of(ccx, tp_ty); + let align = C_i32(machine::llalign_of_min(ccx, lltp_ty) as i32); + let size = C_i32(machine::llsize_of_real(ccx, lltp_ty) as i32); + + let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), T_ptr(T_i8())); + let src_ptr = PointerCast(bcx, get_param(decl, first_real_arg + 1), T_ptr(T_i8())); + let count = get_param(decl, first_real_arg + 2); let volatile = C_i1(false); - let llfn = *bcx.ccx().intrinsics.get( - &~"llvm.memmove.p0i8.p0i8.i32"); - Call(bcx, llfn, ~[dst_ptr, src_ptr, size, align, volatile]); + let llfn = *bcx.ccx().intrinsics.get(&~"llvm.memmove.p0i8.p0i8.i32"); + Call(bcx, llfn, [dst_ptr, src_ptr, Mul(bcx, size, count), align, volatile]); } ~"memmove64" => { - let dst_ptr = get_param(decl, first_real_arg); - let src_ptr = get_param(decl, first_real_arg + 1); - let size = get_param(decl, first_real_arg + 2); - let align = C_i32(1); + let tp_ty = substs.tys[0]; + let lltp_ty = type_of::type_of(ccx, tp_ty); + let align = C_i32(machine::llalign_of_min(ccx, lltp_ty) as i32); + let size = C_i64(machine::llsize_of_real(ccx, lltp_ty) as i64); + + let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), T_ptr(T_i8())); + let src_ptr = PointerCast(bcx, get_param(decl, first_real_arg + 1), T_ptr(T_i8())); + let count = get_param(decl, first_real_arg + 2); let volatile = C_i1(false); - let llfn = *bcx.ccx().intrinsics.get( - &~"llvm.memmove.p0i8.p0i8.i64"); - Call(bcx, llfn, ~[dst_ptr, src_ptr, size, align, volatile]); + let llfn = *bcx.ccx().intrinsics.get(&~"llvm.memmove.p0i8.p0i8.i64"); + Call(bcx, llfn, [dst_ptr, src_ptr, Mul(bcx, size, count), align, volatile]); + } + ~"memset32" => { + let tp_ty = substs.tys[0]; + let lltp_ty = type_of::type_of(ccx, tp_ty); + let align = C_i32(machine::llalign_of_min(ccx, lltp_ty) as i32); + let size = C_i32(machine::llsize_of_real(ccx, lltp_ty) as i32); + + let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), T_ptr(T_i8())); + let val = get_param(decl, first_real_arg + 1); + let count = get_param(decl, first_real_arg + 2); + let volatile = C_i1(false); + let llfn = *bcx.ccx().intrinsics.get(&~"llvm.memset.p0i8.i32"); + Call(bcx, llfn, [dst_ptr, val, Mul(bcx, size, count), align, volatile]); + } + ~"memset64" => { + let tp_ty = substs.tys[0]; + let lltp_ty = type_of::type_of(ccx, tp_ty); + let align = C_i32(machine::llalign_of_min(ccx, lltp_ty) as i32); + let size = C_i64(machine::llsize_of_real(ccx, lltp_ty) as i64); + + let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), T_ptr(T_i8())); + let val = get_param(decl, first_real_arg + 1); + let count = get_param(decl, first_real_arg + 2); + let volatile = C_i1(false); + let llfn = *bcx.ccx().intrinsics.get(&~"llvm.memset.p0i8.i64"); + Call(bcx, llfn, [dst_ptr, val, Mul(bcx, size, count), align, volatile]); } ~"sqrtf32" => { let x = get_param(decl, first_real_arg); let sqrtf = *ccx.intrinsics.get(&~"llvm.sqrt.f32"); - Store(bcx, Call(bcx, sqrtf, ~[x]), fcx.llretptr.get()); + Store(bcx, Call(bcx, sqrtf, [x]), fcx.llretptr.get()); } ~"sqrtf64" => { let x = get_param(decl, first_real_arg); let sqrtf = *ccx.intrinsics.get(&~"llvm.sqrt.f64"); - Store(bcx, Call(bcx, sqrtf, ~[x]), fcx.llretptr.get()); + Store(bcx, Call(bcx, sqrtf, [x]), fcx.llretptr.get()); } ~"powif32" => { let a = get_param(decl, first_real_arg); let x = get_param(decl, first_real_arg + 1u); let powif = *ccx.intrinsics.get(&~"llvm.powi.f32"); - Store(bcx, Call(bcx, powif, ~[a, x]), fcx.llretptr.get()); + Store(bcx, Call(bcx, powif, [a, x]), fcx.llretptr.get()); } ~"powif64" => { let a = get_param(decl, first_real_arg); let x = get_param(decl, first_real_arg + 1u); let powif = *ccx.intrinsics.get(&~"llvm.powi.f64"); - Store(bcx, Call(bcx, powif, ~[a, x]), fcx.llretptr.get()); + Store(bcx, Call(bcx, powif, [a, x]), fcx.llretptr.get()); } ~"sinf32" => { let x = get_param(decl, first_real_arg); let sinf = *ccx.intrinsics.get(&~"llvm.sin.f32"); - Store(bcx, Call(bcx, sinf, ~[x]), fcx.llretptr.get()); + Store(bcx, Call(bcx, sinf, [x]), fcx.llretptr.get()); } ~"sinf64" => { let x = get_param(decl, first_real_arg); let sinf = *ccx.intrinsics.get(&~"llvm.sin.f64"); - Store(bcx, Call(bcx, sinf, ~[x]), fcx.llretptr.get()); + Store(bcx, Call(bcx, sinf, [x]), fcx.llretptr.get()); } ~"cosf32" => { let x = get_param(decl, first_real_arg); let cosf = *ccx.intrinsics.get(&~"llvm.cos.f32"); - Store(bcx, Call(bcx, cosf, ~[x]), fcx.llretptr.get()); + Store(bcx, Call(bcx, cosf, [x]), fcx.llretptr.get()); } ~"cosf64" => { let x = get_param(decl, first_real_arg); let cosf = *ccx.intrinsics.get(&~"llvm.cos.f64"); - Store(bcx, Call(bcx, cosf, ~[x]), fcx.llretptr.get()); + Store(bcx, Call(bcx, cosf, [x]), fcx.llretptr.get()); } ~"powf32" => { let a = get_param(decl, first_real_arg); let x = get_param(decl, first_real_arg + 1u); let powf = *ccx.intrinsics.get(&~"llvm.pow.f32"); - Store(bcx, Call(bcx, powf, ~[a, x]), fcx.llretptr.get()); + Store(bcx, Call(bcx, powf, [a, x]), fcx.llretptr.get()); } ~"powf64" => { let a = get_param(decl, first_real_arg); let x = get_param(decl, first_real_arg + 1u); let powf = *ccx.intrinsics.get(&~"llvm.pow.f64"); - Store(bcx, Call(bcx, powf, ~[a, x]), fcx.llretptr.get()); + Store(bcx, Call(bcx, powf, [a, x]), fcx.llretptr.get()); } ~"expf32" => { let x = get_param(decl, first_real_arg); let expf = *ccx.intrinsics.get(&~"llvm.exp.f32"); - Store(bcx, Call(bcx, expf, ~[x]), fcx.llretptr.get()); + Store(bcx, Call(bcx, expf, [x]), fcx.llretptr.get()); } ~"expf64" => { let x = get_param(decl, first_real_arg); let expf = *ccx.intrinsics.get(&~"llvm.exp.f64"); - Store(bcx, Call(bcx, expf, ~[x]), fcx.llretptr.get()); + Store(bcx, Call(bcx, expf, [x]), fcx.llretptr.get()); } ~"exp2f32" => { let x = get_param(decl, first_real_arg); let exp2f = *ccx.intrinsics.get(&~"llvm.exp2.f32"); - Store(bcx, Call(bcx, exp2f, ~[x]), fcx.llretptr.get()); + Store(bcx, Call(bcx, exp2f, [x]), fcx.llretptr.get()); } ~"exp2f64" => { let x = get_param(decl, first_real_arg); let exp2f = *ccx.intrinsics.get(&~"llvm.exp2.f64"); - Store(bcx, Call(bcx, exp2f, ~[x]), fcx.llretptr.get()); + Store(bcx, Call(bcx, exp2f, [x]), fcx.llretptr.get()); } ~"logf32" => { let x = get_param(decl, first_real_arg); let logf = *ccx.intrinsics.get(&~"llvm.log.f32"); - Store(bcx, Call(bcx, logf, ~[x]), fcx.llretptr.get()); + Store(bcx, Call(bcx, logf, [x]), fcx.llretptr.get()); } ~"logf64" => { let x = get_param(decl, first_real_arg); let logf = *ccx.intrinsics.get(&~"llvm.log.f64"); - Store(bcx, Call(bcx, logf, ~[x]), fcx.llretptr.get()); + Store(bcx, Call(bcx, logf, [x]), fcx.llretptr.get()); } ~"log10f32" => { let x = get_param(decl, first_real_arg); let log10f = *ccx.intrinsics.get(&~"llvm.log10.f32"); - Store(bcx, Call(bcx, log10f, ~[x]), fcx.llretptr.get()); + Store(bcx, Call(bcx, log10f, [x]), fcx.llretptr.get()); } ~"log10f64" => { let x = get_param(decl, first_real_arg); let log10f = *ccx.intrinsics.get(&~"llvm.log10.f64"); - Store(bcx, Call(bcx, log10f, ~[x]), fcx.llretptr.get()); + Store(bcx, Call(bcx, log10f, [x]), fcx.llretptr.get()); } ~"log2f32" => { let x = get_param(decl, first_real_arg); let log2f = *ccx.intrinsics.get(&~"llvm.log2.f32"); - Store(bcx, Call(bcx, log2f, ~[x]), fcx.llretptr.get()); + Store(bcx, Call(bcx, log2f, [x]), fcx.llretptr.get()); } ~"log2f64" => { let x = get_param(decl, first_real_arg); let log2f = *ccx.intrinsics.get(&~"llvm.log2.f64"); - Store(bcx, Call(bcx, log2f, ~[x]), fcx.llretptr.get()); + Store(bcx, Call(bcx, log2f, [x]), fcx.llretptr.get()); } ~"fmaf32" => { let a = get_param(decl, first_real_arg); let b = get_param(decl, first_real_arg + 1u); let c = get_param(decl, first_real_arg + 2u); let fmaf = *ccx.intrinsics.get(&~"llvm.fma.f32"); - Store(bcx, Call(bcx, fmaf, ~[a, b, c]), fcx.llretptr.get()); + Store(bcx, Call(bcx, fmaf, [a, b, c]), fcx.llretptr.get()); } ~"fmaf64" => { let a = get_param(decl, first_real_arg); let b = get_param(decl, first_real_arg + 1u); let c = get_param(decl, first_real_arg + 2u); let fmaf = *ccx.intrinsics.get(&~"llvm.fma.f64"); - Store(bcx, Call(bcx, fmaf, ~[a, b, c]), fcx.llretptr.get()); + Store(bcx, Call(bcx, fmaf, [a, b, c]), fcx.llretptr.get()); } ~"fabsf32" => { let x = get_param(decl, first_real_arg); let fabsf = *ccx.intrinsics.get(&~"llvm.fabs.f32"); - Store(bcx, Call(bcx, fabsf, ~[x]), fcx.llretptr.get()); + Store(bcx, Call(bcx, fabsf, [x]), fcx.llretptr.get()); } ~"fabsf64" => { let x = get_param(decl, first_real_arg); let fabsf = *ccx.intrinsics.get(&~"llvm.fabs.f64"); - Store(bcx, Call(bcx, fabsf, ~[x]), fcx.llretptr.get()); + Store(bcx, Call(bcx, fabsf, [x]), fcx.llretptr.get()); } ~"floorf32" => { let x = get_param(decl, first_real_arg); let floorf = *ccx.intrinsics.get(&~"llvm.floor.f32"); - Store(bcx, Call(bcx, floorf, ~[x]), fcx.llretptr.get()); + Store(bcx, Call(bcx, floorf, [x]), fcx.llretptr.get()); } ~"floorf64" => { let x = get_param(decl, first_real_arg); let floorf = *ccx.intrinsics.get(&~"llvm.floor.f64"); - Store(bcx, Call(bcx, floorf, ~[x]), fcx.llretptr.get()); + Store(bcx, Call(bcx, floorf, [x]), fcx.llretptr.get()); } ~"ceilf32" => { let x = get_param(decl, first_real_arg); let ceilf = *ccx.intrinsics.get(&~"llvm.ceil.f32"); - Store(bcx, Call(bcx, ceilf, ~[x]), fcx.llretptr.get()); + Store(bcx, Call(bcx, ceilf, [x]), fcx.llretptr.get()); } ~"ceilf64" => { let x = get_param(decl, first_real_arg); let ceilf = *ccx.intrinsics.get(&~"llvm.ceil.f64"); - Store(bcx, Call(bcx, ceilf, ~[x]), fcx.llretptr.get()); + Store(bcx, Call(bcx, ceilf, [x]), fcx.llretptr.get()); } ~"truncf32" => { let x = get_param(decl, first_real_arg); let truncf = *ccx.intrinsics.get(&~"llvm.trunc.f32"); - Store(bcx, Call(bcx, truncf, ~[x]), fcx.llretptr.get()); + Store(bcx, Call(bcx, truncf, [x]), fcx.llretptr.get()); } ~"truncf64" => { let x = get_param(decl, first_real_arg); let truncf = *ccx.intrinsics.get(&~"llvm.trunc.f64"); - Store(bcx, Call(bcx, truncf, ~[x]), fcx.llretptr.get()); + Store(bcx, Call(bcx, truncf, [x]), fcx.llretptr.get()); } ~"ctpop8" => { let x = get_param(decl, first_real_arg); let ctpop = *ccx.intrinsics.get(&~"llvm.ctpop.i8"); - Store(bcx, Call(bcx, ctpop, ~[x]), fcx.llretptr.get()) + Store(bcx, Call(bcx, ctpop, [x]), fcx.llretptr.get()) } ~"ctpop16" => { let x = get_param(decl, first_real_arg); let ctpop = *ccx.intrinsics.get(&~"llvm.ctpop.i16"); - Store(bcx, Call(bcx, ctpop, ~[x]), fcx.llretptr.get()) + Store(bcx, Call(bcx, ctpop, [x]), fcx.llretptr.get()) } ~"ctpop32" => { let x = get_param(decl, first_real_arg); let ctpop = *ccx.intrinsics.get(&~"llvm.ctpop.i32"); - Store(bcx, Call(bcx, ctpop, ~[x]), fcx.llretptr.get()) + Store(bcx, Call(bcx, ctpop, [x]), fcx.llretptr.get()) } ~"ctpop64" => { let x = get_param(decl, first_real_arg); let ctpop = *ccx.intrinsics.get(&~"llvm.ctpop.i64"); - Store(bcx, Call(bcx, ctpop, ~[x]), fcx.llretptr.get()) + Store(bcx, Call(bcx, ctpop, [x]), fcx.llretptr.get()) } ~"ctlz8" => { let x = get_param(decl, first_real_arg); let y = C_i1(false); let ctlz = *ccx.intrinsics.get(&~"llvm.ctlz.i8"); - Store(bcx, Call(bcx, ctlz, ~[x, y]), fcx.llretptr.get()) + Store(bcx, Call(bcx, ctlz, [x, y]), fcx.llretptr.get()) } ~"ctlz16" => { let x = get_param(decl, first_real_arg); let y = C_i1(false); let ctlz = *ccx.intrinsics.get(&~"llvm.ctlz.i16"); - Store(bcx, Call(bcx, ctlz, ~[x, y]), fcx.llretptr.get()) + Store(bcx, Call(bcx, ctlz, [x, y]), fcx.llretptr.get()) } ~"ctlz32" => { let x = get_param(decl, first_real_arg); let y = C_i1(false); let ctlz = *ccx.intrinsics.get(&~"llvm.ctlz.i32"); - Store(bcx, Call(bcx, ctlz, ~[x, y]), fcx.llretptr.get()) + Store(bcx, Call(bcx, ctlz, [x, y]), fcx.llretptr.get()) } ~"ctlz64" => { let x = get_param(decl, first_real_arg); let y = C_i1(false); let ctlz = *ccx.intrinsics.get(&~"llvm.ctlz.i64"); - Store(bcx, Call(bcx, ctlz, ~[x, y]), fcx.llretptr.get()) + Store(bcx, Call(bcx, ctlz, [x, y]), fcx.llretptr.get()) } ~"cttz8" => { let x = get_param(decl, first_real_arg); let y = C_i1(false); let cttz = *ccx.intrinsics.get(&~"llvm.cttz.i8"); - Store(bcx, Call(bcx, cttz, ~[x, y]), fcx.llretptr.get()) + Store(bcx, Call(bcx, cttz, [x, y]), fcx.llretptr.get()) } ~"cttz16" => { let x = get_param(decl, first_real_arg); let y = C_i1(false); let cttz = *ccx.intrinsics.get(&~"llvm.cttz.i16"); - Store(bcx, Call(bcx, cttz, ~[x, y]), fcx.llretptr.get()) + Store(bcx, Call(bcx, cttz, [x, y]), fcx.llretptr.get()) } ~"cttz32" => { let x = get_param(decl, first_real_arg); let y = C_i1(false); let cttz = *ccx.intrinsics.get(&~"llvm.cttz.i32"); - Store(bcx, Call(bcx, cttz, ~[x, y]), fcx.llretptr.get()) + Store(bcx, Call(bcx, cttz, [x, y]), fcx.llretptr.get()) } ~"cttz64" => { let x = get_param(decl, first_real_arg); let y = C_i1(false); let cttz = *ccx.intrinsics.get(&~"llvm.cttz.i64"); - Store(bcx, Call(bcx, cttz, ~[x, y]), fcx.llretptr.get()) + Store(bcx, Call(bcx, cttz, [x, y]), fcx.llretptr.get()) } ~"bswap16" => { let x = get_param(decl, first_real_arg); let cttz = *ccx.intrinsics.get(&~"llvm.bswap.i16"); - Store(bcx, Call(bcx, cttz, ~[x]), fcx.llretptr.get()) + Store(bcx, Call(bcx, cttz, [x]), fcx.llretptr.get()) } ~"bswap32" => { let x = get_param(decl, first_real_arg); let cttz = *ccx.intrinsics.get(&~"llvm.bswap.i32"); - Store(bcx, Call(bcx, cttz, ~[x]), fcx.llretptr.get()) + Store(bcx, Call(bcx, cttz, [x]), fcx.llretptr.get()) } ~"bswap64" => { let x = get_param(decl, first_real_arg); let cttz = *ccx.intrinsics.get(&~"llvm.bswap.i64"); - Store(bcx, Call(bcx, cttz, ~[x]), fcx.llretptr.get()) + Store(bcx, Call(bcx, cttz, [x]), fcx.llretptr.get()) } _ => { // Could we make this an enum rather than a string? does it get @@ -1208,10 +1269,8 @@ pub fn trans_foreign_fn(ccx: @CrateContext, let n = tys.fn_sig.inputs.len(); if !ty::type_is_immediate(tys.fn_sig.output) { - let llretptr = load_inbounds(bcx, llargbundle, ~[0u, n]); + let llretptr = load_inbounds(bcx, llargbundle, [0u, n]); llargvals.push(llretptr); - } else { - llargvals.push(C_null(T_ptr(T_i8()))); } let llenvptr = C_null(T_opaque_box_ptr(bcx.ccx())); @@ -1240,7 +1299,7 @@ pub fn trans_foreign_fn(ccx: @CrateContext, let arg_count = shim_types.fn_sig.inputs.len(); let llretptr = load_inbounds(bcx, llargbundle, - ~[0, arg_count]); + [0, arg_count]); Store(bcx, llretval, llretptr); } else { // NB: The return pointer in the Rust ABI function is wired diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index 585d9d8420cd7..e2f7dc086d0fb 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -12,6 +12,8 @@ // // Code relating to taking, dropping, etc as well as type descriptors. +use core::prelude::*; + use back::abi; use back::link::*; use driver::session; @@ -33,8 +35,11 @@ use middle::ty; use util::ppaux; use util::ppaux::ty_to_short_str; +use core::io; use core::libc::c_uint; -use std::time; +use core::str; +use core::vec; +use extra::time; use syntax::ast; pub fn trans_free(cx: block, v: ValueRef) -> block { @@ -42,7 +47,7 @@ pub fn trans_free(cx: block, v: ValueRef) -> block { callee::trans_lang_call( cx, cx.tcx().lang_items.free_fn(), - ~[PointerCast(cx, v, T_ptr(T_i8()))], + [PointerCast(cx, v, T_ptr(T_i8()))], expr::Ignore) } @@ -51,7 +56,7 @@ pub fn trans_exchange_free(cx: block, v: ValueRef) -> block { callee::trans_lang_call( cx, cx.tcx().lang_items.exchange_free_fn(), - ~[PointerCast(cx, v, T_ptr(T_i8()))], + [PointerCast(cx, v, T_ptr(T_i8()))], expr::Ignore) } @@ -100,7 +105,7 @@ pub fn drop_ty_immediate(bcx: block, v: ValueRef, t: ty::t) -> block { ty::ty_estr(ty::vstore_box) => { decr_refcnt_maybe_free(bcx, v, t) } - _ => bcx.tcx().sess.bug(~"drop_ty_immediate: non-box ty") + _ => bcx.tcx().sess.bug("drop_ty_immediate: non-box ty") } } @@ -147,7 +152,7 @@ pub fn free_ty_immediate(bcx: block, v: ValueRef, t: ty::t) -> block { Store(bcx, v, vp); free_ty(bcx, vp, t) } - _ => bcx.tcx().sess.bug(~"free_ty_immediate: non-box ty") + _ => bcx.tcx().sess.bug("free_ty_immediate: non-box ty") } } @@ -269,7 +274,7 @@ pub fn lazily_emit_tydesc_glue(ccx: @CrateContext, ppaux::ty_to_str(ccx.tcx, ti.ty)); let glue_fn = declare_generic_glue(ccx, ti.ty, llfnty, ~"take"); ti.take_glue = Some(glue_fn); - make_generic_glue(ccx, ti.ty, glue_fn, make_take_glue, ~"take"); + make_generic_glue(ccx, ti.ty, glue_fn, make_take_glue, "take"); debug!("--- lazily_emit_tydesc_glue TAKE %s", ppaux::ty_to_str(ccx.tcx, ti.ty)); } @@ -282,7 +287,7 @@ pub fn lazily_emit_tydesc_glue(ccx: @CrateContext, ppaux::ty_to_str(ccx.tcx, ti.ty)); let glue_fn = declare_generic_glue(ccx, ti.ty, llfnty, ~"drop"); ti.drop_glue = Some(glue_fn); - make_generic_glue(ccx, ti.ty, glue_fn, make_drop_glue, ~"drop"); + make_generic_glue(ccx, ti.ty, glue_fn, make_drop_glue, "drop"); debug!("--- lazily_emit_tydesc_glue DROP %s", ppaux::ty_to_str(ccx.tcx, ti.ty)); } @@ -295,7 +300,7 @@ pub fn lazily_emit_tydesc_glue(ccx: @CrateContext, ppaux::ty_to_str(ccx.tcx, ti.ty)); let glue_fn = declare_generic_glue(ccx, ti.ty, llfnty, ~"free"); ti.free_glue = Some(glue_fn); - make_generic_glue(ccx, ti.ty, glue_fn, make_free_glue, ~"free"); + make_generic_glue(ccx, ti.ty, glue_fn, make_free_glue, "free"); debug!("--- lazily_emit_tydesc_glue FREE %s", ppaux::ty_to_str(ccx.tcx, ti.ty)); } @@ -308,7 +313,7 @@ pub fn lazily_emit_tydesc_glue(ccx: @CrateContext, ppaux::ty_to_str(ccx.tcx, ti.ty)); let glue_fn = declare_generic_glue(ccx, ti.ty, llfnty, ~"visit"); ti.visit_glue = Some(glue_fn); - make_generic_glue(ccx, ti.ty, glue_fn, make_visit_glue, ~"visit"); + make_generic_glue(ccx, ti.ty, glue_fn, make_visit_glue, "visit"); debug!("--- lazily_emit_tydesc_glue VISIT %s", ppaux::ty_to_str(ccx.tcx, ti.ty)); } @@ -379,8 +384,9 @@ pub fn call_tydesc_glue_full(bcx: block, } }; - Call(bcx, llfn, ~[C_null(T_ptr(T_nil())), C_null(T_ptr(T_nil())), - C_null(T_ptr(T_ptr(bcx.ccx().tydesc_type))), llrawptr]); + Call(bcx, llfn, [C_null(T_ptr(T_nil())), + C_null(T_ptr(T_ptr(bcx.ccx().tydesc_type))), + llrawptr]); } // See [Note-arg-mode] @@ -394,7 +400,7 @@ pub fn call_tydesc_glue(cx: block, v: ValueRef, t: ty::t, field: uint) pub fn make_visit_glue(bcx: block, v: ValueRef, t: ty::t) { let _icx = bcx.insn_ctxt("make_visit_glue"); - let bcx = do with_scope(bcx, None, ~"visitor cleanup") |bcx| { + let bcx = do with_scope(bcx, None, "visitor cleanup") |bcx| { let mut bcx = bcx; let (visitor_trait, object_ty) = ty::visitor_object_ty(bcx.tcx()); let v = PointerCast(bcx, v, T_ptr(type_of::type_of(bcx.ccx(), object_ty))); @@ -481,17 +487,16 @@ pub fn trans_struct_drop(bcx: block, }; // Class dtors have no explicit args, so the params should - // just consist of the output pointer and the environment - // (self) - assert!((params.len() == 2)); + // just consist of the environment (self) + assert_eq!(params.len(), 1); // Take a reference to the class (because it's using the Drop trait), // do so now. let llval = alloca(bcx, val_ty(v0)); Store(bcx, v0, llval); - let self_arg = PointerCast(bcx, llval, params[1]); - let args = ~[C_null(T_ptr(T_i8())), self_arg]; + let self_arg = PointerCast(bcx, llval, params[0]); + let args = ~[self_arg]; Call(bcx, dtor_addr, args); @@ -544,11 +549,23 @@ pub fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) { decr_refcnt_maybe_free(bcx, llbox, ty::mk_opaque_box(ccx.tcx)) } ty::ty_trait(_, _, ty::UniqTraitStore, _) => { - let lluniquevalue = GEPi(bcx, v0, [0, abi::trt_field_box]); - let lltydesc = Load(bcx, GEPi(bcx, v0, [0, abi::trt_field_tydesc])); - call_tydesc_glue_full(bcx, lluniquevalue, lltydesc, - abi::tydesc_field_free_glue, None); - bcx + let lluniquevalue = GEPi(bcx, v0, [0, abi::trt_field_box]); + // Only drop the value when it is non-null + do with_cond(bcx, IsNotNull(bcx, Load(bcx, lluniquevalue))) |bcx| { + let llvtable = Load(bcx, GEPi(bcx, v0, [0, abi::trt_field_vtable])); + + // Cast the vtable to a pointer to a pointer to a tydesc. + let llvtable = PointerCast(bcx, + llvtable, + T_ptr(T_ptr(ccx.tydesc_type))); + let lltydesc = Load(bcx, llvtable); + call_tydesc_glue_full(bcx, + lluniquevalue, + lltydesc, + abi::tydesc_field_free_glue, + None); + bcx + } } ty::ty_opaque_closure_ptr(ck) => { closure::make_opaque_cbox_drop_glue(bcx, ck, v0) @@ -669,12 +686,7 @@ pub fn declare_tydesc(ccx: @CrateContext, t: ty::t) -> @mut tydesc_info { let llsize = llsize_of(ccx, llty); let llalign = llalign_of(ccx, llty); let addrspace = declare_tydesc_addrspace(ccx, t); - //XXX this triggers duplicate LLVM symbols - let name = @(if false /*ccx.sess.opts.debuginfo*/ { - mangle_internal_name_by_type_only(ccx, t, "tydesc") - } else { - mangle_internal_name_by_seq(ccx, "tydesc") - }); + let name = @mangle_internal_name_by_type_and_seq(ccx, t, "tydesc"); note_unique_llvm_symbol(ccx, name); debug!("+++ declare_tydesc %s %s", ppaux::ty_to_str(ccx.tcx, t), *name); let gvar = str::as_c_str(*name, |buf| { @@ -703,14 +715,8 @@ pub fn declare_generic_glue(ccx: @CrateContext, t: ty::t, llfnty: TypeRef, name: ~str) -> ValueRef { let _icx = ccx.insn_ctxt("declare_generic_glue"); let name = name; - //XXX this triggers duplicate LLVM symbols - let fn_nm = @(if false /*ccx.sess.opts.debuginfo*/ { - mangle_internal_name_by_type_only(ccx, t, (~"glue_" + name)) - } else { - mangle_internal_name_by_seq(ccx, (~"glue_" + name)) - }); + let fn_nm = @mangle_internal_name_by_type_and_seq(ccx, t, (~"glue_" + name)); debug!("%s is for type %s", *fn_nm, ppaux::ty_to_str(ccx.tcx, t)); - // XXX: Bad copy. note_unique_llvm_symbol(ccx, fn_nm); let llfn = decl_cdecl_fn(ccx.llmod, *fn_nm, llfnty); set_glue_inlining(llfn, t); @@ -736,7 +742,8 @@ pub fn make_generic_glue_inner(ccx: @CrateContext, let bcx = top_scope_block(fcx, None); let lltop = bcx.llbb; - let llrawptr0 = unsafe { llvm::LLVMGetParam(llfn, 3u as c_uint) }; + let rawptr0_arg = fcx.arg_pos(1u); + let llrawptr0 = unsafe { llvm::LLVMGetParam(llfn, rawptr0_arg as c_uint) }; helper(bcx, llrawptr0, t); finish_fn(fcx, lltop); return llfn; @@ -821,14 +828,14 @@ pub fn emit_tydescs(ccx: @CrateContext) { let tydesc = C_named_struct(ccx.tydesc_type, - ~[ti.size, // size - ti.align, // align - take_glue, // take_glue - drop_glue, // drop_glue - free_glue, // free_glue - visit_glue, // visit_glue - shape, // shape - shape_tables]); // shape_tables + [ti.size, // size + ti.align, // align + take_glue, // take_glue + drop_glue, // drop_glue + free_glue, // free_glue + visit_glue, // visit_glue + shape, // shape + shape_tables]); // shape_tables unsafe { let gvar = ti.tydesc; diff --git a/src/librustc/middle/trans/inline.rs b/src/librustc/middle/trans/inline.rs index 10e019b2a376c..1f9bdcb5abb21 100644 --- a/src/librustc/middle/trans/inline.rs +++ b/src/librustc/middle/trans/inline.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use metadata::csearch; use middle::astencode; use middle::trans::base::{get_insn_ctxt}; @@ -17,6 +19,7 @@ use middle::trans::common::*; use middle::ty; use util::ppaux::ty_to_str; +use core::vec; use syntax::ast; use syntax::ast_map::path_name; use syntax::ast_util::local_def; @@ -77,14 +80,14 @@ pub fn maybe_instantiate_inline(ccx: @CrateContext, fn_id: ast::def_id, ccx.external.insert(there.id, Some(here.id.node)); } } - _ => ccx.sess.bug(~"maybe_instantiate_inline: item has a \ - non-enum parent") + _ => ccx.sess.bug("maybe_instantiate_inline: item has a \ + non-enum parent") } if translate { trans_item(ccx, item); } local_def(my_id) } csearch::found_parent(_, _) => { - ccx.sess.bug(~"maybe_get_item_ast returned a found_parent \ + ccx.sess.bug("maybe_get_item_ast returned a found_parent \ with a non-item parent"); } csearch::found(ast::ii_method(impl_did, mth)) => { @@ -98,7 +101,7 @@ pub fn maybe_instantiate_inline(ccx: @CrateContext, fn_id: ast::def_id, let llfn = get_item_val(ccx, mth.id); let path = vec::append( ty::item_path(ccx.tcx, impl_did), - ~[path_name(mth.ident)]); + [path_name(mth.ident)]); let self_kind = match mth.explicit_self.node { ast::sty_static => no_self, _ => { diff --git a/src/librustc/middle/trans/machine.rs b/src/librustc/middle/trans/machine.rs index 038c5e0369b8c..bd3c630fbb7b0 100644 --- a/src/librustc/middle/trans/machine.rs +++ b/src/librustc/middle/trans/machine.rs @@ -150,6 +150,6 @@ pub fn static_size_of_enum(cx: @CrateContext, t: ty::t) -> uint { cx.enum_sizes.insert(t, max_size); return max_size; } - _ => cx.sess.bug(~"static_size_of_enum called on non-enum") + _ => cx.sess.bug("static_size_of_enum called on non-enum") } } diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs index 6eb2540f1df65..f05165fe25610 100644 --- a/src/librustc/middle/trans/meth.rs +++ b/src/librustc/middle/trans/meth.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use back::abi; use lib::llvm::llvm; use lib::llvm::ValueRef; @@ -29,6 +31,8 @@ use middle::typeck; use util::common::indenter; use util::ppaux::Repr; +use core::str; +use core::vec; use syntax::ast_map::{path, path_mod, path_name}; use syntax::ast_util; use syntax::{ast, ast_map}; @@ -39,9 +43,13 @@ for non-monomorphized methods only. Other methods will be generated once they are invoked with specific type parameters, see `trans::base::lval_static_fn()` or `trans::base::monomorphic_fn()`. */ -pub fn trans_impl(ccx: @CrateContext, path: path, name: ast::ident, - methods: &[@ast::method], generics: &ast::Generics, - self_ty: Option, id: ast::node_id) { +pub fn trans_impl(ccx: @CrateContext, + path: path, + name: ast::ident, + methods: &[@ast::method], + generics: &ast::Generics, + self_ty: Option, + id: ast::node_id) { let _icx = ccx.insn_ctxt("impl::trans_impl"); let tcx = ccx.tcx; @@ -189,7 +197,7 @@ pub fn trans_method_callee(bcx: block, // Replace method_self with method_static here. let mut origin = mentry.origin; match origin { - typeck::method_self(copy trait_id, copy method_index) => { + typeck::method_self(trait_id, method_index) => { // Get the ID of the impl we're inside. let impl_def_id = bcx.fcx.impl_id.get(); @@ -213,8 +221,8 @@ pub fn trans_method_callee(bcx: block, // Make sure to fail with a readable error message if // there's some internal error here if !(method_index < supertrait_method_def_ids.len()) { - tcx.sess.bug(~"trans_method_callee: supertrait method \ - index is out of bounds"); + tcx.sess.bug("trans_method_callee: supertrait method \ + index is out of bounds"); } // Get the method name using the method index in the origin let method_name = @@ -401,7 +409,7 @@ pub fn method_with_name_or_default(ccx: @CrateContext, Some(pmis) => { for pmis.each |pmi| { if pmi.method_info.ident == name { - debug!("XXX %?", pmi.method_info.did); + debug!("pmi.method_info.did = %?", pmi.method_info.did); return pmi.method_info.did; } } @@ -437,7 +445,7 @@ pub fn method_ty_param_count(ccx: @CrateContext, m_id: ast::def_id, _, _)) => { m.generics.ty_params.len() } - copy e => fail!("method_ty_param_count %?", e) + ref e => fail!("method_ty_param_count %?", *e) } } else { csearch::get_type_param_count(ccx.sess.cstore, m_id) - @@ -558,7 +566,8 @@ pub fn combine_impl_and_methods_origins(bcx: block, // Find the bounds for the method, which are the tail of the // bounds found in the item type, as the item type combines the // rcvr + method bounds. - let ccx = bcx.ccx(), tcx = bcx.tcx(); + let ccx = bcx.ccx(); + let tcx = bcx.tcx(); let n_m_tps = method_ty_param_count(ccx, mth_did, impl_did); let ty::ty_param_bounds_and_ty { generics: r_m_generics, @@ -657,11 +666,11 @@ pub fn trans_trait_callee_from_llval(bcx: block, let self_mode; match explicit_self { ast::sty_static => { - bcx.tcx().sess.bug(~"shouldn't see static method here"); + bcx.tcx().sess.bug("shouldn't see static method here"); } ast::sty_value => { - bcx.tcx().sess.bug(~"methods with by-value self should not be \ - called on objects"); + bcx.tcx().sess.bug("methods with by-value self should not be \ + called on objects"); } ast::sty_region(*) => { // As before, we need to pass a pointer to a pointer to the @@ -691,7 +700,7 @@ pub fn trans_trait_callee_from_llval(bcx: block, // Pass a pointer to the box. match store { ty::BoxTraitStore => llself = llbox, - _ => bcx.tcx().sess.bug(~"@self receiver with non-@Trait") + _ => bcx.tcx().sess.bug("@self receiver with non-@Trait") } let llscratch = alloca(bcx, val_ty(llself)); @@ -704,7 +713,7 @@ pub fn trans_trait_callee_from_llval(bcx: block, // Pass the unique pointer. match store { ty::UniqTraitStore => llself = llbox, - _ => bcx.tcx().sess.bug(~"~self receiver with non-~Trait") + _ => bcx.tcx().sess.bug("~self receiver with non-~Trait") } let llscratch = alloca(bcx, val_ty(llself)); @@ -718,7 +727,10 @@ pub fn trans_trait_callee_from_llval(bcx: block, // Load the function from the vtable and cast it to the expected type. debug!("(translating trait callee) loading method"); let llcallee_ty = type_of_fn_from_ty(ccx, callee_ty); - let mptr = Load(bcx, GEPi(bcx, llvtable, [0u, n_method])); + + // Plus one in order to skip past the type descriptor. + let mptr = Load(bcx, GEPi(bcx, llvtable, [0u, n_method + 1])); + let mptr = PointerCast(bcx, mptr, T_ptr(llcallee_ty)); return Callee { @@ -734,15 +746,15 @@ pub fn trans_trait_callee_from_llval(bcx: block, } pub fn vtable_id(ccx: @CrateContext, - origin: typeck::vtable_origin) + origin: &typeck::vtable_origin) -> mono_id { match origin { - typeck::vtable_static(impl_id, substs, sub_vtables) => { + &typeck::vtable_static(impl_id, ref substs, sub_vtables) => { monomorphize::make_mono_id( ccx, impl_id, - substs, - if (*sub_vtables).len() == 0u { + *substs, + if sub_vtables.is_empty() { None } else { Some(sub_vtables) @@ -756,26 +768,40 @@ pub fn vtable_id(ccx: @CrateContext, } } +/// Creates a returns a dynamic vtable for the given type and vtable origin. +/// This is used only for objects. pub fn get_vtable(ccx: @CrateContext, + self_ty: ty::t, origin: typeck::vtable_origin) - -> ValueRef { - // XXX: Bad copy. - let hash_id = vtable_id(ccx, copy origin); + -> ValueRef { + let hash_id = vtable_id(ccx, &origin); match ccx.vtables.find(&hash_id) { - Some(&val) => val, - None => match origin { - typeck::vtable_static(id, substs, sub_vtables) => { - make_impl_vtable(ccx, id, substs, sub_vtables) + Some(&val) => val, + None => { + match origin { + typeck::vtable_static(id, substs, sub_vtables) => { + make_impl_vtable(ccx, id, self_ty, substs, sub_vtables) + } + _ => fail!("get_vtable: expected a static origin"), + } } - _ => fail!("get_vtable: expected a static origin") - } } } -pub fn make_vtable(ccx: @CrateContext, ptrs: ~[ValueRef]) -> ValueRef { +/// Helper function to declare and initialize the vtable. +pub fn make_vtable(ccx: @CrateContext, + tydesc: @mut tydesc_info, + ptrs: &[ValueRef]) + -> ValueRef { unsafe { let _icx = ccx.insn_ctxt("impl::make_vtable"); - let tbl = C_struct(ptrs); + + let mut components = ~[ tydesc.tydesc ]; + for ptrs.each |&ptr| { + components.push(ptr) + } + + let tbl = C_struct(components); let vtable = ccx.sess.str_of((ccx.names)("vtable")); let vt_gvar = do str::as_c_str(*vtable) |buf| { llvm::LLVMAddGlobal(ccx.llmod, val_ty(tbl), buf) @@ -787,11 +813,13 @@ pub fn make_vtable(ccx: @CrateContext, ptrs: ~[ValueRef]) -> ValueRef { } } +/// Generates a dynamic vtable for objects. pub fn make_impl_vtable(ccx: @CrateContext, impl_id: ast::def_id, + self_ty: ty::t, substs: ~[ty::t], vtables: typeck::vtable_res) - -> ValueRef { + -> ValueRef { let _icx = ccx.insn_ctxt("impl::make_impl_vtable"); let tcx = ccx.tcx; @@ -803,9 +831,13 @@ pub fn make_impl_vtable(ccx: @CrateContext, let has_tps = !ty::lookup_item_type(ccx.tcx, impl_id).generics.type_param_defs.is_empty(); - make_vtable(ccx, ty::trait_method_def_ids(tcx, trt_id).map(|method_def_id| { + + let trait_method_def_ids = ty::trait_method_def_ids(tcx, trt_id); + let methods = do trait_method_def_ids.map |method_def_id| { let im = ty::method(tcx, *method_def_id); - let fty = ty::subst_tps(tcx, substs, None, + let fty = ty::subst_tps(tcx, + substs, + None, ty::mk_bare_fn(tcx, copy im.fty)); if im.generics.has_type_params() || ty::type_has_self(fty) { debug!("(making impl vtable) method has self or type params: %s", @@ -831,14 +863,20 @@ pub fn make_impl_vtable(ccx: @CrateContext, trans_external_path(ccx, m_id, fty) } } - })) + }; + + // Generate a type descriptor for the vtable. + let tydesc = get_tydesc(ccx, self_ty); + glue::lazily_emit_all_tydesc_glue(ccx, tydesc); + + make_vtable(ccx, tydesc, methods) } pub fn trans_trait_cast(bcx: block, val: @ast::expr, id: ast::node_id, dest: expr::Dest, - store: ty::TraitStore) + _store: ty::TraitStore) -> block { let mut bcx = bcx; let _icx = bcx.insn_ctxt("impl::trans_cast"); @@ -853,40 +891,19 @@ pub fn trans_trait_cast(bcx: block, let ccx = bcx.ccx(); let v_ty = expr_ty(bcx, val); - match store { - ty::RegionTraitStore(_) | ty::BoxTraitStore => { - let mut llboxdest = GEPi(bcx, lldest, [0u, abi::trt_field_box]); - // Just store the pointer into the pair. (Region/borrowed - // and boxed trait objects are represented as pairs, and - // have no type descriptor field.) - llboxdest = PointerCast(bcx, - llboxdest, - T_ptr(type_of(bcx.ccx(), v_ty))); - bcx = expr::trans_into(bcx, val, SaveIn(llboxdest)); - } - ty::UniqTraitStore => { - // Translate the uniquely-owned value in the - // triple. (Unique trait objects are represented as - // triples.) - let mut llvaldest = GEPi(bcx, lldest, [0, abi::trt_field_box]); - llvaldest = PointerCast(bcx, - llvaldest, - T_ptr(type_of(bcx.ccx(), v_ty))); - bcx = expr::trans_into(bcx, val, SaveIn(llvaldest)); - - // Get the type descriptor of the wrapped value and store - // it in the triple as well. - let tydesc = get_tydesc(bcx.ccx(), v_ty); - glue::lazily_emit_all_tydesc_glue(bcx.ccx(), tydesc); - let lltydescdest = GEPi(bcx, lldest, [0, abi::trt_field_tydesc]); - Store(bcx, tydesc.tydesc, lltydescdest); - } - } + let mut llboxdest = GEPi(bcx, lldest, [0u, abi::trt_field_box]); + // Just store the pointer into the pair. (Region/borrowed + // and boxed trait objects are represented as pairs, and + // have no type descriptor field.) + llboxdest = PointerCast(bcx, + llboxdest, + T_ptr(type_of(bcx.ccx(), v_ty))); + bcx = expr::trans_into(bcx, val, SaveIn(llboxdest)); // Store the vtable into the pair or triple. let orig = /*bad*/copy ccx.maps.vtable_map.get(&id)[0]; let orig = resolve_vtable_in_fn_ctxt(bcx.fcx, orig); - let vtable = get_vtable(bcx.ccx(), orig); + let vtable = get_vtable(bcx.ccx(), v_ty, orig); Store(bcx, vtable, PointerCast(bcx, GEPi(bcx, lldest, [0u, abi::trt_field_vtable]), T_ptr(val_ty(vtable)))); diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs index ccc906f2ee8af..062f72b6feba6 100644 --- a/src/librustc/middle/trans/monomorphize.rs +++ b/src/librustc/middle/trans/monomorphize.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use back::link::mangle_exported_name; use driver::session; use lib::llvm::ValueRef; @@ -28,8 +30,9 @@ use middle::trans::type_use; use middle::ty; use middle::ty::{FnSig}; use middle::typeck; -use util::ppaux::Repr; +use util::ppaux::{Repr,ty_to_str}; +use core::vec; use syntax::ast; use syntax::ast_map; use syntax::ast_map::path_name; @@ -70,8 +73,7 @@ pub fn monomorphic_fn(ccx: @CrateContext, for real_substs.each() |s| { assert!(!ty::type_has_params(*s)); } for substs.each() |s| { assert!(!ty::type_has_params(*s)); } let param_uses = type_use::type_uses_for(ccx, fn_id, substs.len()); - // XXX: Bad copy. - let hash_id = make_mono_id(ccx, fn_id, copy substs, vtables, impl_did_opt, + let hash_id = make_mono_id(ccx, fn_id, substs, vtables, impl_did_opt, Some(param_uses)); if vec::any(hash_id.params, |p| match *p { mono_precise(_, _) => false, _ => true }) { @@ -121,23 +123,23 @@ pub fn monomorphic_fn(ccx: @CrateContext, (pt, m.ident, m.span) } ast_map::node_trait_method(@ast::required(_), _, _) => { - ccx.tcx.sess.bug(~"Can't monomorphize a required trait method") + ccx.tcx.sess.bug("Can't monomorphize a required trait method") } ast_map::node_expr(*) => { - ccx.tcx.sess.bug(~"Can't monomorphize an expr") + ccx.tcx.sess.bug("Can't monomorphize an expr") } ast_map::node_stmt(*) => { - ccx.tcx.sess.bug(~"Can't monomorphize a stmt") + ccx.tcx.sess.bug("Can't monomorphize a stmt") } - ast_map::node_arg(*) => ccx.tcx.sess.bug(~"Can't monomorphize an arg"), + ast_map::node_arg(*) => ccx.tcx.sess.bug("Can't monomorphize an arg"), ast_map::node_block(*) => { - ccx.tcx.sess.bug(~"Can't monomorphize a block") + ccx.tcx.sess.bug("Can't monomorphize a block") } ast_map::node_local(*) => { - ccx.tcx.sess.bug(~"Can't monomorphize a local") + ccx.tcx.sess.bug("Can't monomorphize a local") } ast_map::node_callee_scope(*) => { - ccx.tcx.sess.bug(~"Can't monomorphize a callee-scope") + ccx.tcx.sess.bug("Can't monomorphize a callee-scope") } ast_map::node_struct_ctor(_, i, pt) => (pt, i.ident, i.span) }; @@ -170,8 +172,7 @@ pub fn monomorphic_fn(ccx: @CrateContext, ccx.monomorphizing.insert(fn_id, depth + 1); let pt = vec::append(/*bad*/copy *pt, - ~[path_name((ccx.names)( - *ccx.sess.str_of(name)))]); + [path_name((ccx.names)(*ccx.sess.str_of(name)))]); let s = mangle_exported_name(ccx, /*bad*/copy pt, mono_ty); let mk_lldecl = || { @@ -207,7 +208,7 @@ pub fn monomorphic_fn(ccx: @CrateContext, d } ast_map::node_item(*) => { - ccx.tcx.sess.bug(~"Can't monomorphize this kind of item") + ccx.tcx.sess.bug("Can't monomorphize this kind of item") } ast_map::node_foreign_item(i, _, _, _) => { let d = mk_lldecl(); @@ -226,7 +227,7 @@ pub fn monomorphic_fn(ccx: @CrateContext, this_tv.disr_val, psubsts, d); } ast::struct_variant_kind(_) => - ccx.tcx.sess.bug(~"can't monomorphize struct variants"), + ccx.tcx.sess.bug("can't monomorphize struct variants"), } d } @@ -258,8 +259,8 @@ pub fn monomorphic_fn(ccx: @CrateContext, set_inline_hint(d); base::trans_tuple_struct(ccx, /*bad*/copy struct_def.fields, - struct_def.ctor_id.expect(~"ast-mapped tuple struct \ - didn't have a ctor id"), + struct_def.ctor_id.expect("ast-mapped tuple struct \ + didn't have a ctor id"), psubsts, d); d @@ -350,10 +351,10 @@ pub fn make_mono_id(ccx: @CrateContext, vec::map_zip(*item_ty.generics.type_param_defs, substs, |type_param_def, subst| { let mut v = ~[]; for type_param_def.bounds.trait_bounds.each |_bound| { - v.push(meth::vtable_id(ccx, /*bad*/copy vts[i])); + v.push(meth::vtable_id(ccx, &vts[i])); i += 1; } - (*subst, if !v.is_empty() { Some(v) } else { None }) + (*subst, if !v.is_empty() { Some(@v) } else { None }) }) } None => { @@ -369,8 +370,7 @@ pub fn make_mono_id(ccx: @CrateContext, } } else { match *id { - // XXX: Bad copy. - (a, copy b@Some(_)) => mono_precise(a, b), + (a, b@Some(_)) => mono_precise(a, b), (subst, None) => { if *uses == 0 { mono_any @@ -379,10 +379,14 @@ pub fn make_mono_id(ccx: @CrateContext, { let llty = type_of::type_of(ccx, subst); let size = machine::llbitsize_of_real(ccx, llty); - let align = machine::llalign_of_pref(ccx, llty); + let align = machine::llalign_of_min(ccx, llty); let mode = datum::appropriate_mode(subst); let data_class = mono_data_classify(subst); + debug!("make_mono_id: type %s -> size %u align %u mode %? class %?", + ty_to_str(ccx.tcx, subst), + size, align, mode, data_class); + // Special value for nil to prevent problems // with undef return pointers. if size <= 8u && ty::type_is_nil(subst) { diff --git a/src/librustc/middle/trans/reachable.rs b/src/librustc/middle/trans/reachable.rs index dfae7ca0e889b..237ba1f49bbc5 100644 --- a/src/librustc/middle/trans/reachable.rs +++ b/src/librustc/middle/trans/reachable.rs @@ -15,6 +15,7 @@ // makes all other generics or inline functions that it references // reachable as well. +use core::prelude::*; use middle::resolve; use middle::ty; @@ -191,17 +192,6 @@ fn traverse_inline_body(cx: @mut ctx, body: &blk) { expr_to_str(e, cx.tcx.sess.intr()))) } } - expr_field(_, _, _) => { - match cx.method_map.find(&e.id) { - Some(&typeck::method_map_entry { - origin: typeck::method_static(did), - _ - }) => { - traverse_def_id(cx, did); - } - _ => () - } - } expr_method_call(*) => { match cx.method_map.find(&e.id) { Some(&typeck::method_map_entry { @@ -212,8 +202,8 @@ fn traverse_inline_body(cx: @mut ctx, body: &blk) { } Some(_) => {} None => { - cx.tcx.sess.span_bug(e.span, ~"expr_method_call not in \ - method map"); + cx.tcx.sess.span_bug(e.span, "expr_method_call not in \ + method map"); } } } diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs index 1141e0c007fee..38cc9ba69de92 100644 --- a/src/librustc/middle/trans/reflect.rs +++ b/src/librustc/middle/trans/reflect.rs @@ -41,16 +41,16 @@ pub struct Reflector { bcx: block } -pub impl Reflector { - fn c_uint(&mut self, u: uint) -> ValueRef { +impl Reflector { + pub fn c_uint(&mut self, u: uint) -> ValueRef { C_uint(self.bcx.ccx(), u) } - fn c_int(&mut self, i: int) -> ValueRef { + pub fn c_int(&mut self, i: int) -> ValueRef { C_int(self.bcx.ccx(), i) } - fn c_slice(&mut self, s: @~str) -> ValueRef { + pub fn c_slice(&mut self, s: @~str) -> ValueRef { // We're careful to not use first class aggregates here because that // will kick us off fast isel. (Issue #4352.) let bcx = self.bcx; @@ -64,7 +64,7 @@ pub impl Reflector { scratch.val } - fn c_size_and_align(&mut self, t: ty::t) -> ~[ValueRef] { + pub fn c_size_and_align(&mut self, t: ty::t) -> ~[ValueRef] { let tr = type_of(self.bcx.ccx(), t); let s = machine::llsize_of_real(self.bcx.ccx(), tr); let a = machine::llalign_of_min(self.bcx.ccx(), tr); @@ -72,19 +72,19 @@ pub impl Reflector { self.c_uint(a)]; } - fn c_tydesc(&mut self, t: ty::t) -> ValueRef { + pub fn c_tydesc(&mut self, t: ty::t) -> ValueRef { let bcx = self.bcx; let static_ti = get_tydesc(bcx.ccx(), t); glue::lazily_emit_all_tydesc_glue(bcx.ccx(), static_ti); PointerCast(bcx, static_ti.tydesc, T_ptr(self.tydesc_ty)) } - fn c_mt(&mut self, mt: &ty::mt) -> ~[ValueRef] { + pub fn c_mt(&mut self, mt: &ty::mt) -> ~[ValueRef] { ~[self.c_uint(mt.mutbl as uint), self.c_tydesc(mt.ty)] } - fn visit(&mut self, ty_name: ~str, args: ~[ValueRef]) { + pub fn visit(&mut self, ty_name: ~str, args: &[ValueRef]) { let tcx = self.bcx.tcx(); let mth_idx = ty::method_idx( tcx.sess.ident_of(~"visit_" + ty_name), @@ -119,20 +119,19 @@ pub impl Reflector { self.bcx = next_bcx } - fn bracketed(&mut self, - bracket_name: ~str, - extra: ~[ValueRef], - inner: &fn(&mut Reflector)) { - // XXX: Bad copy. - self.visit(~"enter_" + bracket_name, copy extra); + pub fn bracketed(&mut self, + bracket_name: ~str, + extra: &[ValueRef], + inner: &fn(&mut Reflector)) { + self.visit(~"enter_" + bracket_name, extra); inner(self); self.visit(~"leave_" + bracket_name, extra); } - fn vstore_name_and_extra(&mut self, - t: ty::t, - vstore: ty::vstore) -> (~str, ~[ValueRef]) - { + pub fn vstore_name_and_extra(&mut self, + t: ty::t, + vstore: ty::vstore) + -> (~str, ~[ValueRef]) { match vstore { ty::vstore_fixed(n) => { let extra = vec::append(~[self.c_uint(n)], @@ -145,12 +144,12 @@ pub impl Reflector { } } - fn leaf(&mut self, name: ~str) { - self.visit(name, ~[]); + pub fn leaf(&mut self, name: ~str) { + self.visit(name, []); } // Entrypoint - fn visit_ty(&mut self, t: ty::t) { + pub fn visit_ty(&mut self, t: ty::t) { let bcx = self.bcx; debug!("reflect::visit_ty %s", ty_to_str(bcx.ccx().tcx, t)); @@ -226,7 +225,7 @@ pub impl Reflector { self.c_uint(sigilval), self.c_uint(fty.sig.inputs.len()), self.c_uint(retval)]; - self.visit(~"enter_fn", copy extra); // XXX: Bad copy. + self.visit(~"enter_fn", extra); self.visit_sig(retval, &fty.sig); self.visit(~"leave_fn", extra); } @@ -241,7 +240,7 @@ pub impl Reflector { self.c_uint(sigilval), self.c_uint(fty.sig.inputs.len()), self.c_uint(retval)]; - self.visit(~"enter_fn", copy extra); // XXX: Bad copy. + self.visit(~"enter_fn", extra); self.visit_sig(retval, &fty.sig); self.visit(~"leave_fn", extra); } @@ -280,21 +279,26 @@ pub impl Reflector { let opaqueptrty = ty::mk_ptr(ccx.tcx, ty::mt { ty: opaquety, mutbl: ast::m_imm }); let make_get_disr = || { - let sub_path = bcx.fcx.path + ~[path_name(special_idents::anon)]; + let sub_path = bcx.fcx.path + [path_name(special_idents::anon)]; let sym = mangle_internal_name_by_path_and_seq(ccx, sub_path, "get_disr"); let llfty = type_of_fn(ccx, [opaqueptrty], ty::mk_int()); let llfdecl = decl_internal_cdecl_fn(ccx.llmod, sym, llfty); - let arg = unsafe { - llvm::LLVMGetParam(llfdecl, first_real_arg as c_uint) - }; let fcx = new_fn_ctxt(ccx, ~[], llfdecl, ty::mk_uint(), None); + let arg = unsafe { + // + // we know the return type of llfdecl is an int here, so + // no need for a special check to see if the return type + // is immediate. + // + llvm::LLVMGetParam(llfdecl, fcx.arg_pos(0u) as c_uint) + }; let bcx = top_scope_block(fcx, None); let arg = BitCast(bcx, arg, llptrty); let ret = adt::trans_get_discr(bcx, repr, arg); @@ -347,7 +351,7 @@ pub impl Reflector { } } - fn visit_sig(&mut self, retval: uint, sig: &ty::FnSig) { + pub fn visit_sig(&mut self, retval: uint, sig: &ty::FnSig) { for sig.inputs.eachi |i, arg| { let modeval = 5u; // "by copy" let extra = ~[self.c_uint(i), diff --git a/src/librustc/middle/trans/shape.rs b/src/librustc/middle/trans/shape.rs index 31de128074110..6612122fd3e34 100644 --- a/src/librustc/middle/trans/shape.rs +++ b/src/librustc/middle/trans/shape.rs @@ -48,8 +48,8 @@ pub fn mk_global(ccx: @CrateContext, pub fn mk_ctxt(llmod: ModuleRef) -> Ctxt { unsafe { - let llshapetablesty = trans::common::T_named_struct(~"shapes"); - let _llshapetables = str::as_c_str(~"shapes", |buf| { + let llshapetablesty = trans::common::T_named_struct("shapes"); + let _llshapetables = str::as_c_str("shapes", |buf| { llvm::LLVMAddGlobal(llmod, llshapetablesty, buf) }); @@ -66,7 +66,7 @@ Although these two functions are never called, they are here for a VERY GOOD REASON. See #3670 */ pub fn add_u16(dest: &mut ~[u8], val: u16) { - *dest += ~[(val & 0xffu16) as u8, (val >> 8u16) as u8]; + *dest += [(val & 0xffu16) as u8, (val >> 8u16) as u8]; } pub fn add_substr(dest: &mut ~[u8], src: ~[u8]) { diff --git a/src/librustc/middle/trans/tvec.rs b/src/librustc/middle/trans/tvec.rs index 7a85e93584e25..c009b03e5c245 100644 --- a/src/librustc/middle/trans/tvec.rs +++ b/src/librustc/middle/trans/tvec.rs @@ -45,8 +45,8 @@ pub fn expand_boxed_vec_ty(tcx: ty::ctxt, t: ty::t) -> ty::t { ty::ty_estr(ty::vstore_box) | ty::ty_evec(_, ty::vstore_box) => { ty::mk_imm_box(tcx, unboxed_vec_ty) } - _ => tcx.sess.bug(~"non boxed-vec type \ - in tvec::expand_boxed_vec_ty") + _ => tcx.sess.bug("non boxed-vec type \ + in tvec::expand_boxed_vec_ty") } } @@ -74,7 +74,7 @@ pub fn pointer_add(bcx: block, ptr: ValueRef, bytes: ValueRef) -> ValueRef { let _icx = bcx.insn_ctxt("tvec::pointer_add"); let old_ty = val_ty(ptr); let bptr = PointerCast(bcx, ptr, T_ptr(T_i8())); - return PointerCast(bcx, InBoundsGEP(bcx, bptr, ~[bytes]), old_ty); + return PointerCast(bcx, InBoundsGEP(bcx, bptr, [bytes]), old_ty); } pub fn alloc_raw(bcx: block, unit_ty: ty::t, @@ -125,7 +125,7 @@ pub fn duplicate_uniq(bcx: block, vptr: ValueRef, vec_ty: ty::t) -> Result { let data_ptr = get_dataptr(bcx, get_bodyptr(bcx, vptr)); let new_data_ptr = get_dataptr(bcx, get_bodyptr(bcx, newptr)); - base::call_memcpy(bcx, new_data_ptr, data_ptr, fill); + base::call_memcpy(bcx, new_data_ptr, data_ptr, fill, 1); let bcx = if ty::type_needs_drop(bcx.tcx(), unit_ty) { iter_vec_raw(bcx, new_data_ptr, vec_ty, fill, glue::take_ty) @@ -136,7 +136,8 @@ pub fn duplicate_uniq(bcx: block, vptr: ValueRef, vec_ty: ty::t) -> Result { pub fn make_drop_glue_unboxed(bcx: block, vptr: ValueRef, vec_ty: ty::t) -> block { let _icx = bcx.insn_ctxt("tvec::make_drop_glue_unboxed"); - let tcx = bcx.tcx(), unit_ty = ty::sequence_element_type(tcx, vec_ty); + let tcx = bcx.tcx(); + let unit_ty = ty::sequence_element_type(tcx, vec_ty); if ty::type_needs_drop(tcx, unit_ty) { iter_vec_unboxed(bcx, vptr, vec_ty, glue::drop_ty) } else { bcx } @@ -149,8 +150,8 @@ pub struct VecTypes { llunit_size: ValueRef } -pub impl VecTypes { - fn to_str(&self, ccx: @CrateContext) -> ~str { +impl VecTypes { + pub fn to_str(&self, ccx: @CrateContext) -> ~str { fmt!("VecTypes {vec_ty=%s, unit_ty=%s, llunit_ty=%s, llunit_size=%s}", ty_to_str(ccx.tcx, self.vec_ty), ty_to_str(ccx.tcx, self.unit_ty), @@ -313,7 +314,7 @@ pub fn trans_uniq_or_managed_vstore(bcx: block, let bcx = callee::trans_lang_call( bcx, bcx.tcx().lang_items.strdup_uniq_fn(), - ~[ llptrval, llsizeval ], + [ llptrval, llsizeval ], expr::SaveIn(lldestval.to_ref_llval(bcx))); return DatumBlock { bcx: bcx, @@ -370,7 +371,7 @@ pub fn write_content(bcx: block, let bytes = s.len() + 1; // copy null-terminator too let llbytes = C_uint(bcx.ccx(), bytes); let llcstr = C_cstr(bcx.ccx(), s); - base::call_memcpy(bcx, lldest, llcstr, llbytes); + base::call_memcpy(bcx, lldest, llcstr, llbytes, 1); return bcx; } } @@ -564,7 +565,7 @@ pub fn iter_vec_raw(bcx: block, data_ptr: ValueRef, vec_ty: ty::t, let header_bcx = base::sub_block(bcx, "iter_vec_loop_header"); Br(bcx, header_bcx.llbb); let data_ptr = - Phi(header_bcx, val_ty(data_ptr), ~[data_ptr], ~[bcx.llbb]); + Phi(header_bcx, val_ty(data_ptr), [data_ptr], [bcx.llbb]); let not_yet_at_end = ICmp(header_bcx, lib::llvm::IntULT, data_ptr, data_end_ptr); let body_bcx = base::sub_block(header_bcx, "iter_vec_loop_body"); @@ -572,7 +573,7 @@ pub fn iter_vec_raw(bcx: block, data_ptr: ValueRef, vec_ty: ty::t, CondBr(header_bcx, not_yet_at_end, body_bcx.llbb, next_bcx.llbb); let body_bcx = f(body_bcx, data_ptr, unit_ty); AddIncomingToPhi(data_ptr, InBoundsGEP(body_bcx, data_ptr, - ~[C_int(bcx.ccx(), 1)]), + [C_int(bcx.ccx(), 1)]), body_bcx.llbb); Br(body_bcx, header_bcx.llbb); return next_bcx; diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs index dfbebd90c298b..e3c424f8e7ecf 100644 --- a/src/librustc/middle/trans/type_of.rs +++ b/src/librustc/middle/trans/type_of.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use lib::llvm::llvm; use lib::llvm::{TypeRef}; use middle::trans::adt; @@ -44,9 +46,6 @@ pub fn type_of_fn(cx: @CrateContext, inputs: &[ty::t], output: ty::t) let lloutputtype = type_of(cx, output); if !output_is_immediate { atys.push(T_ptr(lloutputtype)); - } else { - // XXX: Eliminate this. - atys.push(T_ptr(T_i8())); } // Arg 1: Environment @@ -70,7 +69,7 @@ pub fn type_of_fn_from_ty(cx: @CrateContext, fty: ty::t) -> TypeRef { ty::ty_closure(ref f) => type_of_fn(cx, f.sig.inputs, f.sig.output), ty::ty_bare_fn(ref f) => type_of_fn(cx, f.sig.inputs, f.sig.output), _ => { - cx.sess.bug(~"type_of_fn_from_ty given non-closure, non-bare-fn") + cx.sess.bug("type_of_fn_from_ty given non-closure, non-bare-fn") } } } @@ -90,7 +89,7 @@ pub fn type_of_non_gc_box(cx: @CrateContext, t: ty::t) -> TypeRef { T_ptr(T_unique(cx, type_of(cx, mt.ty))) } _ => { - cx.sess.bug(~"non-box in type_of_non_gc_box"); + cx.sess.bug("non-box in type_of_non_gc_box"); } } } @@ -135,11 +134,11 @@ pub fn sizing_type_of(cx: @CrateContext, t: ty::t) -> TypeRef { ty::ty_estr(ty::vstore_slice(*)) | ty::ty_evec(_, ty::vstore_slice(*)) => { - T_struct(~[T_ptr(T_i8()), T_ptr(T_i8())], false) + T_struct([T_ptr(T_i8()), T_ptr(T_i8())], false) } ty::ty_bare_fn(*) => T_ptr(T_i8()), - ty::ty_closure(*) => T_struct(~[T_ptr(T_i8()), T_ptr(T_i8())], false), + ty::ty_closure(*) => T_struct([T_ptr(T_i8()), T_ptr(T_i8())], false), ty::ty_trait(_, _, store, _) => T_opaque_trait(cx, store), ty::ty_estr(ty::vstore_fixed(size)) => T_array(T_i8(), size), @@ -200,7 +199,6 @@ pub fn type_of(cx: @CrateContext, t: ty::t) -> TypeRef { return llty; } - // XXX: This is a terrible terrible copy. let llty = match ty::get(t).sty { ty::ty_nil | ty::ty_bot => T_nil(), ty::ty_bool => T_bool(), @@ -219,7 +217,7 @@ pub fn type_of(cx: @CrateContext, t: ty::t) -> TypeRef { common::T_named_struct(llvm_type_name(cx, an_enum, did, - /*bad*/copy substs.tps)) + substs.tps)) } ty::ty_estr(ty::vstore_box) => { T_box_ptr(T_box(cx, T_vec(cx, T_i8()))) @@ -240,15 +238,11 @@ pub fn type_of(cx: @CrateContext, t: ty::t) -> TypeRef { ty::ty_rptr(_, ref mt) => T_ptr(type_of(cx, mt.ty)), ty::ty_evec(ref mt, ty::vstore_slice(_)) => { - T_struct(~[T_ptr(type_of(cx, mt.ty)), - T_uint_ty(cx, ast::ty_u)], - false) + T_struct([T_ptr(type_of(cx, mt.ty)), T_uint_ty(cx, ast::ty_u)], false) } ty::ty_estr(ty::vstore_slice(_)) => { - T_struct(~[T_ptr(T_i8()), - T_uint_ty(cx, ast::ty_u)], - false) + T_struct([T_ptr(T_i8()), T_uint_ty(cx, ast::ty_u)], false) } ty::ty_estr(ty::vstore_fixed(n)) => { @@ -280,13 +274,13 @@ pub fn type_of(cx: @CrateContext, t: ty::t) -> TypeRef { T_named_struct(llvm_type_name(cx, a_struct, did, - /*bad*/ copy substs.tps)) + substs.tps)) } } - ty::ty_self(*) => cx.tcx.sess.unimpl(~"type_of: ty_self"), - ty::ty_infer(*) => cx.tcx.sess.bug(~"type_of with ty_infer"), - ty::ty_param(*) => cx.tcx.sess.bug(~"type_of with ty_param"), - ty::ty_err(*) => cx.tcx.sess.bug(~"type_of with ty_err") + ty::ty_self(*) => cx.tcx.sess.unimpl("type_of: ty_self"), + ty::ty_infer(*) => cx.tcx.sess.bug("type_of with ty_infer"), + ty::ty_param(*) => cx.tcx.sess.bug("type_of with ty_param"), + ty::ty_err(*) => cx.tcx.sess.bug("type_of with ty_err") }; cx.lltypes.insert(t, llty); @@ -337,9 +331,7 @@ pub fn llvm_type_name(cx: @CrateContext, } pub fn type_of_dtor(ccx: @CrateContext, self_ty: ty::t) -> TypeRef { - T_fn(~[T_ptr(T_i8()), // output pointer - T_ptr(type_of(ccx, self_ty))], // self arg - T_nil()) + T_fn([T_ptr(type_of(ccx, self_ty))] /* self */, T_nil()) } pub fn type_of_rooted(ccx: @CrateContext, t: ty::t) -> TypeRef { @@ -352,6 +344,5 @@ pub fn type_of_rooted(ccx: @CrateContext, t: ty::t) -> TypeRef { pub fn type_of_glue_fn(ccx: @CrateContext, t: ty::t) -> TypeRef { let tydescpp = T_ptr(T_ptr(ccx.tydesc_type)); let llty = T_ptr(type_of(ccx, t)); - return T_fn(~[T_ptr(T_nil()), T_ptr(T_nil()), tydescpp, llty], - T_nil()); + return T_fn([T_ptr(T_nil()), tydescpp, llty], T_nil()); } diff --git a/src/librustc/middle/trans/type_use.rs b/src/librustc/middle/trans/type_use.rs index 4a8adfba11c31..9c84b4ffa997f 100644 --- a/src/librustc/middle/trans/type_use.rs +++ b/src/librustc/middle/trans/type_use.rs @@ -36,12 +36,13 @@ use middle::typeck; use core::option::{Some, None}; use core::uint; use core::vec; -use std::list::{List, Cons, Nil}; -use std::list; +use extra::list::{List, Cons, Nil}; +use extra::list; use syntax::ast; use syntax::ast::*; use syntax::ast_map; use syntax::ast_util; +use syntax::parse::token; use syntax::visit; pub type type_uses = uint; // Bitmask @@ -85,8 +86,8 @@ pub fn type_uses_for(ccx: @CrateContext, fn_id: def_id, n_tps: uint) } if fn_id_loc.crate != local_crate { - let Context { uses: @uses, _ } = cx; - let uses = @uses; // mutability + let Context { uses, _ } = cx; + let uses = @copy *uses; // freeze ccx.type_use_cache.insert(fn_id, uses); return uses; } @@ -135,7 +136,8 @@ pub fn type_uses_for(ccx: @CrateContext, fn_id: def_id, n_tps: uint) ~"visit_tydesc" | ~"forget" | ~"frame_address" | ~"morestack_addr" => 0, - ~"memmove32" | ~"memmove64" => 0, + ~"memcpy32" | ~"memcpy64" | ~"memmove32" | ~"memmove64" | + ~"memset32" | ~"memset64" => use_repr, ~"sqrtf32" | ~"sqrtf64" | ~"powif32" | ~"powif64" | ~"sinf32" | ~"sinf64" | ~"cosf32" | ~"cosf64" | @@ -169,11 +171,11 @@ pub fn type_uses_for(ccx: @CrateContext, fn_id: def_id, n_tps: uint) ast_map::node_id_to_str( ccx.tcx.items, fn_id_loc.node, - ccx.tcx.sess.parse_sess.interner))); + token::get_ident_interner()))); } } - let Context { uses: @uses, _ } = cx; - let uses = @uses; // mutability + let Context { uses, _ } = cx; + let uses = @copy *uses; // freeze ccx.type_use_cache.insert(fn_id, uses); uses } @@ -272,8 +274,8 @@ pub fn mark_for_method_call(cx: Context, e_id: node_id, callee_id: node_id) { pub fn mark_for_expr(cx: Context, e: @expr) { match e.node { expr_vstore(_, _) | expr_vec(_, _) | expr_struct(*) | expr_tup(_) | - expr_unary(box(_), _) | expr_unary(uniq(_), _) | - expr_binary(add, _, _) | expr_copy(_) | expr_repeat(*) => { + expr_unary(_, box(_), _) | expr_unary(_, uniq(_), _) | + expr_binary(_, add, _, _) | expr_copy(_) | expr_repeat(*) => { node_type_needs(cx, use_repr, e.id); } expr_cast(base, _) => { @@ -287,7 +289,7 @@ pub fn mark_for_expr(cx: Context, e: @expr) { _ => () } } - expr_binary(op, lhs, _) => { + expr_binary(_, op, lhs, _) => { match op { eq | lt | le | ne | ge | gt => { node_type_needs(cx, use_tydesc, lhs.id) @@ -316,16 +318,24 @@ pub fn mark_for_expr(cx: Context, e: @expr) { } } } - expr_assign(val, _) | expr_assign_op(_, val, _) | + expr_assign(val, _) | expr_assign_op(_, _, val, _) | expr_ret(Some(val)) => { node_type_needs(cx, use_repr, val.id); } - expr_index(base, _) | expr_field(base, _, _) => { + expr_index(callee_id, base, _) => { // FIXME (#2537): could be more careful and not count fields after // the chosen field. let base_ty = ty::node_id_to_type(cx.ccx.tcx, base.id); type_needs(cx, use_repr, ty::type_autoderef(cx.ccx.tcx, base_ty)); - mark_for_method_call(cx, e.id, e.callee_id); + mark_for_method_call(cx, e.id, callee_id); + } + expr_field(base, _, _) => { + // Method calls are now a special syntactic form, + // so `a.b` should always be a field. + assert!(!cx.ccx.maps.method_map.contains_key(&e.id)); + + let base_ty = ty::node_id_to_type(cx.ccx.tcx, base.id); + type_needs(cx, use_repr, ty::type_autoderef(cx.ccx.tcx, base_ty)); } expr_log(_, val) => { node_type_needs(cx, use_tydesc, val.id); @@ -335,14 +345,14 @@ pub fn mark_for_expr(cx: Context, e: @expr) { type_needs(cx, use_repr, *a); } } - expr_method_call(rcvr, _, _, _, _) => { + expr_method_call(callee_id, rcvr, _, _, _, _) => { let base_ty = ty::node_id_to_type(cx.ccx.tcx, rcvr.id); type_needs(cx, use_repr, ty::type_autoderef(cx.ccx.tcx, base_ty)); - for ty::ty_fn_args(ty::node_id_to_type(cx.ccx.tcx, e.callee_id)).each |a| { + for ty::ty_fn_args(ty::node_id_to_type(cx.ccx.tcx, callee_id)).each |a| { type_needs(cx, use_repr, *a); } - mark_for_method_call(cx, e.id, e.callee_id); + mark_for_method_call(cx, e.id, callee_id); } expr_inline_asm(ref ia) => { @@ -357,8 +367,8 @@ pub fn mark_for_expr(cx: Context, e: @expr) { expr_paren(e) => mark_for_expr(cx, e), expr_match(*) | expr_block(_) | expr_if(*) | expr_while(*) | - expr_break(_) | expr_again(_) | expr_unary(_, _) | expr_lit(_) | - expr_mac(_) | expr_addr_of(_, _) | expr_ret(_) | expr_loop(_, _) | + expr_break(_) | expr_again(_) | expr_unary(*) | expr_lit(_) | + expr_mac(_) | expr_addr_of(*) | expr_ret(_) | expr_loop(*) | expr_loop_body(_) | expr_do_body(_) => () } } diff --git a/src/librustc/middle/trans/write_guard.rs b/src/librustc/middle/trans/write_guard.rs index 18f21b489b0b8..ffcef3ae78c1b 100644 --- a/src/librustc/middle/trans/write_guard.rs +++ b/src/librustc/middle/trans/write_guard.rs @@ -14,6 +14,8 @@ //! and for each in debugging (e.g., so you can use //! `RUST_LOG=rustc::middle::trans::write_guard`). +use core::prelude::*; + use lib::llvm::ValueRef; use middle::borrowck::{RootInfo, root_map_key, DynaImm, DynaMut}; use middle::trans::base::*; @@ -23,7 +25,6 @@ use middle::trans::common::*; use middle::trans::datum::*; use middle::trans::expr; use middle::ty; -use driver::session; use syntax::codemap::span; use syntax::ast; @@ -74,11 +75,11 @@ pub fn return_to_mut(mut bcx: block, let bits_val = Load(bcx, bits_val_ref); - if bcx.tcx().sess.opts.optimize == session::No { + if bcx.tcx().sess.debug_borrows() { bcx = callee::trans_lang_call( bcx, bcx.tcx().lang_items.unrecord_borrow_fn(), - ~[ + [ box_ptr, bits_val, filename_val, @@ -90,7 +91,7 @@ pub fn return_to_mut(mut bcx: block, callee::trans_lang_call( bcx, bcx.tcx().lang_items.return_to_mut_fn(), - ~[ + [ box_ptr, bits_val, filename_val, @@ -153,18 +154,18 @@ fn root(datum: &Datum, bcx = callee::trans_lang_call( bcx, freeze_did, - ~[ + [ box_ptr, filename, line ], expr::SaveIn(scratch_bits.val)); - if bcx.tcx().sess.opts.optimize == session::No { + if bcx.tcx().sess.debug_borrows() { bcx = callee::trans_lang_call( bcx, bcx.tcx().lang_items.record_borrow_fn(), - ~[ + [ box_ptr, Load(bcx, scratch_bits.val), filename, @@ -193,9 +194,6 @@ fn perform_write_guard(datum: &Datum, callee::trans_lang_call( bcx, bcx.tcx().lang_items.check_not_borrowed_fn(), - ~[PointerCast(bcx, llval, T_ptr(T_i8())), - filename, - line], + [PointerCast(bcx, llval, T_ptr(T_i8())), filename, line], expr::Ignore) } - diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index c51fba8a62b71..363af7c9e56ca 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; use driver::session; use metadata::csearch; @@ -26,18 +27,23 @@ use util::ppaux::{Repr, UserString}; use util::common::{indenter}; use util::enum_set::{EnumSet, CLike}; -#[cfg(stage0)] -use core; // NOTE: this can be removed after the next snapshot +use core::cast; +use core::cmp; +use core::hashmap::{HashMap, HashSet}; +use core::iter; +use core::ops; use core::ptr::to_unsafe_ptr; use core::to_bytes; -use core::hashmap::{HashMap, HashSet}; -use std::smallintmap::SmallIntMap; +use core::u32; +use core::uint; +use core::vec; use syntax::ast::*; use syntax::ast_util::is_local; use syntax::ast_util; use syntax::attr; use syntax::codemap::span; use syntax::codemap; +use syntax::parse::token; use syntax::parse::token::special_idents; use syntax::{ast, ast_map}; use syntax::opt_vec::OptVec; @@ -63,14 +69,15 @@ pub struct Method { def_id: ast::def_id } -pub impl Method { - fn new(ident: ast::ident, - generics: ty::Generics, - transformed_self_ty: Option, - fty: BareFnTy, - explicit_self: ast::explicit_self_, - vis: ast::visibility, - def_id: ast::def_id) -> Method { +impl Method { + pub fn new(ident: ast::ident, + generics: ty::Generics, + transformed_self_ty: Option, + fty: BareFnTy, + explicit_self: ast::explicit_self_, + vis: ast::visibility, + def_id: ast::def_id) + -> Method { // Check the invariants. if explicit_self == ast::sty_static { assert!(transformed_self_ty.is_none()); @@ -136,16 +143,11 @@ pub struct creader_cache_key { type creader_cache = @mut HashMap; -#[cfg(stage0)] -impl to_bytes::IterBytes for creader_cache_key { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - to_bytes::iter_bytes_3(&self.cnum, &self.pos, &self.len, lsb0, f); - } -} -#[cfg(not(stage0))] impl to_bytes::IterBytes for creader_cache_key { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { - to_bytes::iter_bytes_3(&self.cnum, &self.pos, &self.len, lsb0, f) + self.cnum.iter_bytes(lsb0, f) && + self.pos.iter_bytes(lsb0, f) && + self.len.iter_bytes(lsb0, f) } } @@ -167,15 +169,6 @@ impl cmp::Eq for intern_key { } } -#[cfg(stage0)] -impl to_bytes::IterBytes for intern_key { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - unsafe { - (*self.sty).iter_bytes(lsb0, f); - } - } -} -#[cfg(not(stage0))] impl to_bytes::IterBytes for intern_key { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { unsafe { @@ -250,7 +243,6 @@ struct ctxt_ { diag: @syntax::diagnostic::span_handler, interner: @mut HashMap, next_id: @mut uint, - legacy_modes: bool, cstore: @mut metadata::cstore::CStore, sess: session::Session, def_map: resolve::DefMap, @@ -316,6 +308,9 @@ struct ctxt_ { // Maps a trait onto a mapping from self-ty to impl trait_impls: @mut HashMap>, + // Maps a base type to its impl + base_impls: @mut HashMap, + // Set of used unsafe nodes (functions or blocks). Unsafe nodes not // present in this set can be warned about. used_unsafe: @mut HashSet, @@ -408,31 +403,21 @@ pub struct FnSig { output: t } -#[cfg(stage0)] -impl to_bytes::IterBytes for BareFnTy { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - to_bytes::iter_bytes_3(&self.purity, &self.abis, &self.sig, lsb0, f) - } -} -#[cfg(not(stage0))] impl to_bytes::IterBytes for BareFnTy { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { - to_bytes::iter_bytes_3(&self.purity, &self.abis, &self.sig, lsb0, f) + self.purity.iter_bytes(lsb0, f) && + self.abis.iter_bytes(lsb0, f) && + self.sig.iter_bytes(lsb0, f) } } -#[cfg(stage0)] -impl to_bytes::IterBytes for ClosureTy { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - to_bytes::iter_bytes_5(&self.purity, &self.sigil, &self.onceness, - &self.region, &self.sig, lsb0, f) - } -} -#[cfg(not(stage0))] impl to_bytes::IterBytes for ClosureTy { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { - to_bytes::iter_bytes_5(&self.purity, &self.sigil, &self.onceness, - &self.region, &self.sig, lsb0, f) + self.purity.iter_bytes(lsb0, f) && + self.sigil.iter_bytes(lsb0, f) && + self.onceness.iter_bytes(lsb0, f) && + self.region.iter_bytes(lsb0, f) && + self.sig.iter_bytes(lsb0, f) } } @@ -480,8 +465,8 @@ pub enum Region { re_empty, } -pub impl Region { - fn is_bound(&self) -> bool { +impl Region { + pub fn is_bound(&self) -> bool { match self { &re_bound(*) => true, _ => false @@ -681,7 +666,6 @@ pub enum type_err { terr_trait_stores_differ(terr_vstore_kind, expected_found), terr_in_field(@type_err, ast::ident), terr_sorts(expected_found), - terr_self_substs, terr_integer_as_char, terr_int_mismatch(expected_found), terr_float_mismatch(expected_found), @@ -703,6 +687,7 @@ pub enum BuiltinBound { BoundStatic, BoundOwned, BoundConst, + BoundSized, } pub fn EmptyBuiltinBounds() -> BuiltinBounds { @@ -715,6 +700,7 @@ pub fn AllBuiltinBounds() -> BuiltinBounds { set.add(BoundStatic); set.add(BoundOwned); set.add(BoundConst); + set.add(BoundSized); set } @@ -748,23 +734,18 @@ pub enum InferTy { FloatVar(FloatVid) } -#[cfg(stage0)] -impl to_bytes::IterBytes for InferTy { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - match *self { - TyVar(ref tv) => to_bytes::iter_bytes_2(&0u8, tv, lsb0, f), - IntVar(ref iv) => to_bytes::iter_bytes_2(&1u8, iv, lsb0, f), - FloatVar(ref fv) => to_bytes::iter_bytes_2(&2u8, fv, lsb0, f), - } - } -} -#[cfg(not(stage0))] impl to_bytes::IterBytes for InferTy { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { match *self { - TyVar(ref tv) => to_bytes::iter_bytes_2(&0u8, tv, lsb0, f), - IntVar(ref iv) => to_bytes::iter_bytes_2(&1u8, iv, lsb0, f), - FloatVar(ref fv) => to_bytes::iter_bytes_2(&2u8, fv, lsb0, f), + TyVar(ref tv) => { + 0u8.iter_bytes(lsb0, f) && tv.iter_bytes(lsb0, f) + } + IntVar(ref iv) => { + 1u8.iter_bytes(lsb0, f) && iv.iter_bytes(lsb0, f) + } + FloatVar(ref fv) => { + 2u8.iter_bytes(lsb0, f) && fv.iter_bytes(lsb0, f) + } } } } @@ -775,21 +756,15 @@ pub enum InferRegion { ReSkolemized(uint, bound_region) } -#[cfg(stage0)] -impl to_bytes::IterBytes for InferRegion { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - match *self { - ReVar(ref rv) => to_bytes::iter_bytes_2(&0u8, rv, lsb0, f), - ReSkolemized(ref v, _) => to_bytes::iter_bytes_2(&1u8, v, lsb0, f) - } - } -} -#[cfg(not(stage0))] impl to_bytes::IterBytes for InferRegion { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { match *self { - ReVar(ref rv) => to_bytes::iter_bytes_2(&0u8, rv, lsb0, f), - ReSkolemized(ref v, _) => to_bytes::iter_bytes_2(&1u8, v, lsb0, f) + ReVar(ref rv) => { + 0u8.iter_bytes(lsb0, f) && rv.iter_bytes(lsb0, f) + } + ReSkolemized(ref v, _) => { + 1u8.iter_bytes(lsb0, f) && v.iter_bytes(lsb0, f) + } } } } @@ -873,52 +848,24 @@ impl ToStr for IntVarValue { } } -#[cfg(stage0)] -impl to_bytes::IterBytes for TyVid { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - self.to_uint().iter_bytes(lsb0, f) - } -} -#[cfg(not(stage0))] impl to_bytes::IterBytes for TyVid { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { self.to_uint().iter_bytes(lsb0, f) } } -#[cfg(stage0)] -impl to_bytes::IterBytes for IntVid { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - self.to_uint().iter_bytes(lsb0, f) - } -} -#[cfg(not(stage0))] impl to_bytes::IterBytes for IntVid { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { self.to_uint().iter_bytes(lsb0, f) } } -#[cfg(stage0)] -impl to_bytes::IterBytes for FloatVid { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - self.to_uint().iter_bytes(lsb0, f) - } -} -#[cfg(not(stage0))] impl to_bytes::IterBytes for FloatVid { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { self.to_uint().iter_bytes(lsb0, f) } } -#[cfg(stage0)] -impl to_bytes::IterBytes for RegionVid { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - self.to_uint().iter_bytes(lsb0, f) - } -} -#[cfg(not(stage0))] impl to_bytes::IterBytes for RegionVid { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { self.to_uint().iter_bytes(lsb0, f) @@ -937,8 +884,8 @@ pub struct Generics { region_param: Option, } -pub impl Generics { - fn has_type_params(&self) -> bool { +impl Generics { + pub fn has_type_params(&self) -> bool { !self.type_param_defs.is_empty() } } @@ -973,7 +920,7 @@ type type_cache = @mut HashMap; type constness_cache = @mut HashMap; -pub type node_type_table = @mut SmallIntMap; +pub type node_type_table = @mut HashMap; fn mk_rcache() -> creader_cache { return @mut HashMap::new(); @@ -989,30 +936,18 @@ pub fn mk_ctxt(s: session::Session, freevars: freevars::freevar_map, region_maps: @mut middle::region::RegionMaps, region_paramd_items: middle::region::region_paramd_items, - lang_items: middle::lang_items::LanguageItems, - crate: @ast::crate) + lang_items: middle::lang_items::LanguageItems) -> ctxt { - let mut legacy_modes = false; - for crate.node.attrs.each |attribute| { - match attribute.node.value.node { - ast::meta_word(w) if *w == ~"legacy_modes" => { - legacy_modes = true; - } - _ => {} - } - } - @ctxt_ { diag: s.diagnostic(), interner: @mut HashMap::new(), next_id: @mut primitives::LAST_PRIMITIVE_ID, - legacy_modes: legacy_modes, cstore: s.cstore, sess: s, def_map: dm, region_maps: region_maps, region_paramd_items: region_paramd_items, - node_types: @mut SmallIntMap::new(), + node_types: @mut HashMap::new(), node_type_substs: @mut HashMap::new(), trait_refs: @mut HashMap::new(), trait_defs: @mut HashMap::new(), @@ -1041,6 +976,7 @@ pub fn mk_ctxt(s: session::Session, destructor_for_type: @mut HashMap::new(), destructors: @mut HashSet::new(), trait_impls: @mut HashMap::new(), + base_impls: @mut HashMap::new(), used_unsafe: @mut HashSet::new(), used_mut_nodes: @mut HashSet::new(), } @@ -1577,7 +1513,7 @@ pub fn subst_tps(cx: ctxt, tps: &[t], self_ty_opt: Option, typ: t) -> t { ty_param(p) => tps[p.idx], ty_self(_) => { match self_ty_opt { - None => cx.sess.bug(~"ty_self unexpected here"), + None => cx.sess.bug("ty_self unexpected here"), Some(self_ty) => { subst_tps(cx, tps, self_ty_opt, self_ty) } @@ -1678,8 +1614,7 @@ pub fn sequence_element_type(cx: ctxt, ty: t) -> t { match get(ty).sty { ty_estr(_) => return mk_mach_uint(ast::ty_u8), ty_evec(mt, _) | ty_unboxed_vec(mt) => return mt.ty, - _ => cx.sess.bug( - ~"sequence_element_type called on non-sequence value"), + _ => cx.sess.bug("sequence_element_type called on non-sequence value"), } } @@ -1888,75 +1823,84 @@ pub struct TypeContents { bits: u32 } -pub impl TypeContents { - fn meets_bounds(&self, cx: ctxt, bbs: BuiltinBounds) -> bool { +impl TypeContents { + pub fn meets_bounds(&self, cx: ctxt, bbs: BuiltinBounds) -> bool { iter::all(|bb| self.meets_bound(cx, bb), |f| bbs.each(f)) } - fn meets_bound(&self, cx: ctxt, bb: BuiltinBound) -> bool { + pub fn meets_bound(&self, cx: ctxt, bb: BuiltinBound) -> bool { match bb { BoundCopy => self.is_copy(cx), BoundStatic => self.is_static(cx), BoundConst => self.is_const(cx), - BoundOwned => self.is_owned(cx) + BoundOwned => self.is_owned(cx), + BoundSized => self.is_sized(cx), } } - fn intersects(&self, tc: TypeContents) -> bool { + pub fn intersects(&self, tc: TypeContents) -> bool { (self.bits & tc.bits) != 0 } - fn is_copy(&self, cx: ctxt) -> bool { + pub fn is_copy(&self, cx: ctxt) -> bool { !self.intersects(TypeContents::noncopyable(cx)) } - fn noncopyable(_cx: ctxt) -> TypeContents { + pub fn noncopyable(_cx: ctxt) -> TypeContents { TC_DTOR + TC_BORROWED_MUT + TC_ONCE_CLOSURE + TC_OWNED_CLOSURE + TC_EMPTY_ENUM } - fn is_static(&self, cx: ctxt) -> bool { + pub fn is_static(&self, cx: ctxt) -> bool { !self.intersects(TypeContents::nonstatic(cx)) } - fn nonstatic(_cx: ctxt) -> TypeContents { + pub fn nonstatic(_cx: ctxt) -> TypeContents { TC_BORROWED_POINTER } - fn is_owned(&self, cx: ctxt) -> bool { + pub fn is_owned(&self, cx: ctxt) -> bool { !self.intersects(TypeContents::nonowned(cx)) } - fn nonowned(_cx: ctxt) -> TypeContents { + pub fn nonowned(_cx: ctxt) -> TypeContents { TC_MANAGED + TC_BORROWED_POINTER + TC_NON_OWNED } - fn contains_managed(&self) -> bool { + pub fn contains_managed(&self) -> bool { self.intersects(TC_MANAGED) } - fn is_const(&self, cx: ctxt) -> bool { + pub fn is_const(&self, cx: ctxt) -> bool { !self.intersects(TypeContents::nonconst(cx)) } - fn nonconst(_cx: ctxt) -> TypeContents { + pub fn nonconst(_cx: ctxt) -> TypeContents { TC_MUTABLE } - fn moves_by_default(&self, cx: ctxt) -> bool { + pub fn is_sized(&self, cx: ctxt) -> bool { + !self.intersects(TypeContents::dynamically_sized(cx)) + } + + pub fn dynamically_sized(_cx: ctxt) -> TypeContents { + TC_DYNAMIC_SIZE + } + + pub fn moves_by_default(&self, cx: ctxt) -> bool { self.intersects(TypeContents::nonimplicitly_copyable(cx)) } - fn nonimplicitly_copyable(cx: ctxt) -> TypeContents { + pub fn nonimplicitly_copyable(cx: ctxt) -> TypeContents { TypeContents::noncopyable(cx) + TC_OWNED_POINTER + TC_OWNED_VEC } - fn needs_drop(&self, cx: ctxt) -> bool { + pub fn needs_drop(&self, cx: ctxt) -> bool { let tc = TC_MANAGED + TC_DTOR + TypeContents::owned(cx); self.intersects(tc) } - fn owned(_cx: ctxt) -> TypeContents { + pub fn owned(_cx: ctxt) -> TypeContents { //! Any kind of owned contents. TC_OWNED_CLOSURE + TC_OWNED_POINTER + TC_OWNED_VEC } @@ -2016,8 +1960,11 @@ static TC_EMPTY_ENUM: TypeContents = TypeContents{bits: 0b0010_0000_0000}; /// Contains a type marked with `#[non_owned]` static TC_NON_OWNED: TypeContents = TypeContents{bits: 0b0100_0000_0000}; +/// Is a bare vector, str, function, trait, etc (only relevant at top level). +static TC_DYNAMIC_SIZE: TypeContents = TypeContents{bits: 0b1000_0000_0000}; + /// All possible contents. -static TC_ALL: TypeContents = TypeContents{bits: 0b0111_1111_1111}; +static TC_ALL: TypeContents = TypeContents{bits: 0b1111_1111_1111}; pub fn type_is_copyable(cx: ctxt, t: ty::t) -> bool { type_contents(cx, t).is_copy(cx) @@ -2101,7 +2048,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { } ty_box(mt) => { - TC_MANAGED + nonowned(tc_mt(cx, mt, cache)) + TC_MANAGED + statically_sized(nonowned(tc_mt(cx, mt, cache))) } ty_trait(_, _, UniqTraitStore, _) => { @@ -2121,28 +2068,35 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { ty_rptr(r, mt) => { borrowed_contents(r, mt.mutbl) + - nonowned(tc_mt(cx, mt, cache)) + statically_sized(nonowned(tc_mt(cx, mt, cache))) } ty_uniq(mt) => { - TC_OWNED_POINTER + tc_mt(cx, mt, cache) + TC_OWNED_POINTER + statically_sized(tc_mt(cx, mt, cache)) } ty_evec(mt, vstore_uniq) => { - TC_OWNED_VEC + tc_mt(cx, mt, cache) + TC_OWNED_VEC + statically_sized(tc_mt(cx, mt, cache)) } ty_evec(mt, vstore_box) => { - TC_MANAGED + nonowned(tc_mt(cx, mt, cache)) + TC_MANAGED + statically_sized(nonowned(tc_mt(cx, mt, cache))) } ty_evec(mt, vstore_slice(r)) => { borrowed_contents(r, mt.mutbl) + - nonowned(tc_mt(cx, mt, cache)) + statically_sized(nonowned(tc_mt(cx, mt, cache))) } ty_evec(mt, vstore_fixed(_)) => { - tc_mt(cx, mt, cache) + let contents = tc_mt(cx, mt, cache); + // FIXME(#6308) Uncomment this when construction of such + // vectors is prevented earlier in compilation. + // if !contents.is_sized(cx) { + // cx.sess.bug("Fixed-length vector of unsized type \ + // should be impossible"); + // } + contents } ty_estr(vstore_box) => { @@ -2195,7 +2149,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { // If this assertion failures, it is likely because of a // failure in the cross-crate inlining code to translate a // def-id. - assert!(p.def_id.crate == ast::local_crate); + assert_eq!(p.def_id.crate, ast::local_crate); type_param_def_to_contents( cx, cx.ty_param_defs.get(&p.def_id.node)) @@ -2217,7 +2171,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { } ty_opaque_box => TC_MANAGED, - ty_unboxed_vec(mt) => tc_mt(cx, mt, cache), + ty_unboxed_vec(mt) => TC_DYNAMIC_SIZE + tc_mt(cx, mt, cache), ty_opaque_closure_ptr(sigil) => { match sigil { ast::BorrowedSigil => TC_BORROWED_POINTER, @@ -2229,7 +2183,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { ty_type => TC_NONE, ty_err => { - cx.sess.bug(~"Asked to compute contents of fictitious type"); + cx.sess.bug("Asked to compute contents of fictitious type"); } }; @@ -2284,6 +2238,14 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { TypeContents {bits: pointee.bits & mask} } + fn statically_sized(pointee: TypeContents) -> TypeContents { + /*! + * If a dynamically-sized type is found behind a pointer, we should + * restore the 'Sized' kind to the pointer and things that contain it. + */ + TypeContents {bits: pointee.bits & !TC_DYNAMIC_SIZE.bits} + } + fn closure_contents(cty: &ClosureTy) -> TypeContents { let st = match cty.sigil { ast::BorrowedSigil => TC_BORROWED_POINTER, @@ -2312,6 +2274,8 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents { BoundStatic => TypeContents::nonstatic(cx), BoundOwned => TypeContents::nonowned(cx), BoundConst => TypeContents::nonconst(cx), + // The dynamic-size bit can be removed at pointer-level, etc. + BoundSized => TypeContents::dynamically_sized(cx), }; } @@ -2555,7 +2519,7 @@ pub fn type_is_pod(cx: ctxt, ty: t) -> bool { ty_param(_) => result = false, ty_opaque_closure_ptr(_) => result = true, ty_struct(did, ref substs) => { - result = vec::any(lookup_struct_fields(cx, did), |f| { + result = vec::all(lookup_struct_fields(cx, did), |f| { let fty = ty::lookup_item_type(cx, f.id); let sty = subst(cx, substs, fty.ty); type_is_pod(cx, sty) @@ -2567,7 +2531,7 @@ pub fn type_is_pod(cx: ctxt, ty: t) -> bool { } ty_infer(*) | ty_self(*) | ty_err => { - cx.sess.bug(~"non concrete type in type_is_pod"); + cx.sess.bug("non concrete type in type_is_pod"); } } @@ -2581,6 +2545,21 @@ pub fn type_is_enum(ty: t) -> bool { } } +// Is the type's representation size known at compile time? +pub fn type_is_sized(cx: ctxt, ty: ty::t) -> bool { + match get(ty).sty { + // FIXME(#6308) add trait, vec, str, etc here. + ty_param(p) => { + let param_def = cx.ty_param_defs.get(&p.def_id.node); + if param_def.bounds.builtin_bounds.contains_elem(BoundSized) { + return true; + } + return false; + }, + _ => return true, + } +} + // Whether a type is enum like, that is a enum type with only nullary // constructors pub fn type_is_c_like_enum(cx: ctxt, ty: t) -> bool { @@ -2700,7 +2679,7 @@ impl cmp::TotalOrd for bound_region { (&ty::br_anon(ref a1), &ty::br_anon(ref a2)) => a1.cmp(a2), (&ty::br_anon(*), _) => cmp::Less, - (&ty::br_named(ref a1), &ty::br_named(ref a2)) => a1.repr.cmp(&a2.repr), + (&ty::br_named(ref a1), &ty::br_named(ref a2)) => a1.name.cmp(&a2.name), (&ty::br_named(*), _) => cmp::Less, (&ty::br_cap_avoid(ref a1, @ref b1), @@ -2719,248 +2698,118 @@ impl cmp::TotalEq for bound_region { } } -#[cfg(stage0)] -impl to_bytes::IterBytes for vstore { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - match *self { - vstore_fixed(ref u) => - to_bytes::iter_bytes_2(&0u8, u, lsb0, f), - - vstore_uniq => 1u8.iter_bytes(lsb0, f), - vstore_box => 2u8.iter_bytes(lsb0, f), - - vstore_slice(ref r) => - to_bytes::iter_bytes_2(&3u8, r, lsb0, f), - } - } -} -#[cfg(not(stage0))] impl to_bytes::IterBytes for vstore { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { match *self { - vstore_fixed(ref u) => - to_bytes::iter_bytes_2(&0u8, u, lsb0, f), - - vstore_uniq => 1u8.iter_bytes(lsb0, f), - vstore_box => 2u8.iter_bytes(lsb0, f), + vstore_fixed(ref u) => { + 0u8.iter_bytes(lsb0, f) && u.iter_bytes(lsb0, f) + } + vstore_uniq => 1u8.iter_bytes(lsb0, f), + vstore_box => 2u8.iter_bytes(lsb0, f), - vstore_slice(ref r) => - to_bytes::iter_bytes_2(&3u8, r, lsb0, f), + vstore_slice(ref r) => { + 3u8.iter_bytes(lsb0, f) && r.iter_bytes(lsb0, f) + } } } } -#[cfg(stage0)] -impl to_bytes::IterBytes for substs { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - to_bytes::iter_bytes_3(&self.self_r, - &self.self_ty, - &self.tps, lsb0, f) - } -} -#[cfg(not(stage0))] impl to_bytes::IterBytes for substs { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { - to_bytes::iter_bytes_3(&self.self_r, - &self.self_ty, - &self.tps, lsb0, f) + self.self_r.iter_bytes(lsb0, f) && + self.self_ty.iter_bytes(lsb0, f) && + self.tps.iter_bytes(lsb0, f) } } -#[cfg(stage0)] -impl to_bytes::IterBytes for mt { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - to_bytes::iter_bytes_2(&self.ty, - &self.mutbl, lsb0, f) - } -} -#[cfg(not(stage0))] impl to_bytes::IterBytes for mt { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { - to_bytes::iter_bytes_2(&self.ty, - &self.mutbl, lsb0, f) + self.ty.iter_bytes(lsb0, f) && self.mutbl.iter_bytes(lsb0, f) } } -#[cfg(stage0)] -impl to_bytes::IterBytes for field { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - to_bytes::iter_bytes_2(&self.ident, - &self.mt, lsb0, f) - } -} -#[cfg(not(stage0))] impl to_bytes::IterBytes for field { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { - to_bytes::iter_bytes_2(&self.ident, - &self.mt, lsb0, f) + self.ident.iter_bytes(lsb0, f) && self.mt.iter_bytes(lsb0, f) } } -#[cfg(stage0)] -impl to_bytes::IterBytes for FnSig { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - to_bytes::iter_bytes_2(&self.inputs, - &self.output, - lsb0, f); - } -} -#[cfg(not(stage0))] impl to_bytes::IterBytes for FnSig { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { - to_bytes::iter_bytes_2(&self.inputs, - &self.output, - lsb0, f) + self.inputs.iter_bytes(lsb0, f) && self.output.iter_bytes(lsb0, f) } } -#[cfg(stage0)] -impl to_bytes::IterBytes for sty { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - match *self { - ty_nil => 0u8.iter_bytes(lsb0, f), - ty_bool => 1u8.iter_bytes(lsb0, f), - - ty_int(ref t) => - to_bytes::iter_bytes_2(&2u8, t, lsb0, f), - - ty_uint(ref t) => - to_bytes::iter_bytes_2(&3u8, t, lsb0, f), - - ty_float(ref t) => - to_bytes::iter_bytes_2(&4u8, t, lsb0, f), - - ty_estr(ref v) => - to_bytes::iter_bytes_2(&5u8, v, lsb0, f), - - ty_enum(ref did, ref substs) => - to_bytes::iter_bytes_3(&6u8, did, substs, lsb0, f), - - ty_box(ref mt) => - to_bytes::iter_bytes_2(&7u8, mt, lsb0, f), - - ty_evec(ref mt, ref v) => - to_bytes::iter_bytes_3(&8u8, mt, v, lsb0, f), - - ty_unboxed_vec(ref mt) => - to_bytes::iter_bytes_2(&9u8, mt, lsb0, f), - - ty_tup(ref ts) => - to_bytes::iter_bytes_2(&10u8, ts, lsb0, f), - - ty_bare_fn(ref ft) => - to_bytes::iter_bytes_2(&12u8, ft, lsb0, f), - - ty_self(ref did) => to_bytes::iter_bytes_2(&13u8, did, lsb0, f), - - ty_infer(ref v) => - to_bytes::iter_bytes_2(&14u8, v, lsb0, f), - - ty_param(ref p) => - to_bytes::iter_bytes_2(&15u8, p, lsb0, f), - - ty_type => 16u8.iter_bytes(lsb0, f), - ty_bot => 17u8.iter_bytes(lsb0, f), - - ty_ptr(ref mt) => - to_bytes::iter_bytes_2(&18u8, mt, lsb0, f), - - ty_uniq(ref mt) => - to_bytes::iter_bytes_2(&19u8, mt, lsb0, f), - - ty_trait(ref did, ref substs, ref v, ref mutbl) => - to_bytes::iter_bytes_5(&20u8, did, substs, v, mutbl, lsb0, f), - - ty_opaque_closure_ptr(ref ck) => - to_bytes::iter_bytes_2(&21u8, ck, lsb0, f), - - ty_opaque_box => 22u8.iter_bytes(lsb0, f), - - ty_struct(ref did, ref substs) => - to_bytes::iter_bytes_3(&23u8, did, substs, lsb0, f), - - ty_rptr(ref r, ref mt) => - to_bytes::iter_bytes_3(&24u8, r, mt, lsb0, f), - - ty_err => 25u8.iter_bytes(lsb0, f), - - ty_closure(ref ct) => - to_bytes::iter_bytes_2(&26u8, ct, lsb0, f), - } - } -} -#[cfg(not(stage0))] impl to_bytes::IterBytes for sty { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { match *self { - ty_nil => 0u8.iter_bytes(lsb0, f), - ty_bool => 1u8.iter_bytes(lsb0, f), + ty_nil => 0u8.iter_bytes(lsb0, f), + ty_bool => 1u8.iter_bytes(lsb0, f), - ty_int(ref t) => - to_bytes::iter_bytes_2(&2u8, t, lsb0, f), + ty_int(ref t) => 2u8.iter_bytes(lsb0, f) && t.iter_bytes(lsb0, f), - ty_uint(ref t) => - to_bytes::iter_bytes_2(&3u8, t, lsb0, f), + ty_uint(ref t) => 3u8.iter_bytes(lsb0, f) && t.iter_bytes(lsb0, f), - ty_float(ref t) => - to_bytes::iter_bytes_2(&4u8, t, lsb0, f), + ty_float(ref t) => 4u8.iter_bytes(lsb0, f) && t.iter_bytes(lsb0, f), - ty_estr(ref v) => - to_bytes::iter_bytes_2(&5u8, v, lsb0, f), + ty_estr(ref v) => 5u8.iter_bytes(lsb0, f) && v.iter_bytes(lsb0, f), - ty_enum(ref did, ref substs) => - to_bytes::iter_bytes_3(&6u8, did, substs, lsb0, f), + ty_enum(ref did, ref substs) => { + 6u8.iter_bytes(lsb0, f) && + did.iter_bytes(lsb0, f) && + substs.iter_bytes(lsb0, f) + } - ty_box(ref mt) => - to_bytes::iter_bytes_2(&7u8, mt, lsb0, f), + ty_box(ref mt) => 7u8.iter_bytes(lsb0, f) && mt.iter_bytes(lsb0, f), - ty_evec(ref mt, ref v) => - to_bytes::iter_bytes_3(&8u8, mt, v, lsb0, f), + ty_evec(ref mt, ref v) => { + 8u8.iter_bytes(lsb0, f) && + mt.iter_bytes(lsb0, f) && + v.iter_bytes(lsb0, f) + } - ty_unboxed_vec(ref mt) => - to_bytes::iter_bytes_2(&9u8, mt, lsb0, f), + ty_unboxed_vec(ref mt) => 9u8.iter_bytes(lsb0, f) && mt.iter_bytes(lsb0, f), - ty_tup(ref ts) => - to_bytes::iter_bytes_2(&10u8, ts, lsb0, f), + ty_tup(ref ts) => 10u8.iter_bytes(lsb0, f) && ts.iter_bytes(lsb0, f), - ty_bare_fn(ref ft) => - to_bytes::iter_bytes_2(&12u8, ft, lsb0, f), + ty_bare_fn(ref ft) => 12u8.iter_bytes(lsb0, f) && ft.iter_bytes(lsb0, f), - ty_self(ref did) => to_bytes::iter_bytes_2(&13u8, did, lsb0, f), + ty_self(ref did) => 13u8.iter_bytes(lsb0, f) && did.iter_bytes(lsb0, f), - ty_infer(ref v) => - to_bytes::iter_bytes_2(&14u8, v, lsb0, f), + ty_infer(ref v) => 14u8.iter_bytes(lsb0, f) && v.iter_bytes(lsb0, f), - ty_param(ref p) => - to_bytes::iter_bytes_2(&15u8, p, lsb0, f), + ty_param(ref p) => 15u8.iter_bytes(lsb0, f) && p.iter_bytes(lsb0, f), - ty_type => 16u8.iter_bytes(lsb0, f), - ty_bot => 17u8.iter_bytes(lsb0, f), + ty_type => 16u8.iter_bytes(lsb0, f), + ty_bot => 17u8.iter_bytes(lsb0, f), - ty_ptr(ref mt) => - to_bytes::iter_bytes_2(&18u8, mt, lsb0, f), + ty_ptr(ref mt) => 18u8.iter_bytes(lsb0, f) && mt.iter_bytes(lsb0, f), - ty_uniq(ref mt) => - to_bytes::iter_bytes_2(&19u8, mt, lsb0, f), + ty_uniq(ref mt) => 19u8.iter_bytes(lsb0, f) && mt.iter_bytes(lsb0, f), - ty_trait(ref did, ref substs, ref v, ref mutbl) => - to_bytes::iter_bytes_5(&20u8, did, substs, v, mutbl, lsb0, f), + ty_trait(ref did, ref substs, ref v, ref mutbl) => { + 20u8.iter_bytes(lsb0, f) && + did.iter_bytes(lsb0, f) && + substs.iter_bytes(lsb0, f) && + v.iter_bytes(lsb0, f) && + mutbl.iter_bytes(lsb0, f) + } - ty_opaque_closure_ptr(ref ck) => - to_bytes::iter_bytes_2(&21u8, ck, lsb0, f), + ty_opaque_closure_ptr(ref ck) => 21u8.iter_bytes(lsb0, f) && ck.iter_bytes(lsb0, f), - ty_opaque_box => 22u8.iter_bytes(lsb0, f), + ty_opaque_box => 22u8.iter_bytes(lsb0, f), - ty_struct(ref did, ref substs) => - to_bytes::iter_bytes_3(&23u8, did, substs, lsb0, f), + ty_struct(ref did, ref substs) => { + 23u8.iter_bytes(lsb0, f) && did.iter_bytes(lsb0, f) && substs.iter_bytes(lsb0, f) + } - ty_rptr(ref r, ref mt) => - to_bytes::iter_bytes_3(&24u8, r, mt, lsb0, f), + ty_rptr(ref r, ref mt) => { + 24u8.iter_bytes(lsb0, f) && r.iter_bytes(lsb0, f) && mt.iter_bytes(lsb0, f) + } - ty_err => 25u8.iter_bytes(lsb0, f), + ty_err => 25u8.iter_bytes(lsb0, f), - ty_closure(ref ct) => - to_bytes::iter_bytes_2(&26u8, ct, lsb0, f), + ty_closure(ref ct) => 26u8.iter_bytes(lsb0, f) && ct.iter_bytes(lsb0, f), } } } @@ -2971,7 +2820,7 @@ pub fn node_id_to_trait_ref(cx: ctxt, id: ast::node_id) -> @ty::TraitRef { None => cx.sess.bug( fmt!("node_id_to_trait_ref: no trait ref for node `%s`", ast_map::node_id_to_str(cx.items, id, - cx.sess.parse_sess.interner))) + token::get_ident_interner()))) } } @@ -2982,7 +2831,7 @@ pub fn node_id_to_type(cx: ctxt, id: ast::node_id) -> t { None => cx.sess.bug( fmt!("node_id_to_type: no type for node `%s`", ast_map::node_id_to_str(cx.items, id, - cx.sess.parse_sess.interner))) + token::get_ident_interner()))) } } @@ -3277,8 +3126,8 @@ pub fn adjust_ty(cx: ctxt, } } -pub impl AutoRef { - fn map_region(&self, f: &fn(Region) -> Region) -> AutoRef { +impl AutoRef { + pub fn map_region(&self, f: &fn(Region) -> Region) -> AutoRef { match *self { ty::AutoPtr(r, m) => ty::AutoPtr(f(r), m), ty::AutoBorrowVec(r, m) => ty::AutoBorrowVec(f(r), m), @@ -3409,7 +3258,7 @@ pub fn expr_kind(tcx: ctxt, } } - ast::expr_unary(ast::deref, _) | + ast::expr_unary(_, ast::deref, _) | ast::expr_field(*) | ast::expr_index(*) => { LvalueExpr @@ -3563,8 +3412,8 @@ pub fn occurs_check(tcx: ctxt, sp: span, vid: TyVid, rt: t) { (sp, ~"type inference failed because I \ could not find a type\n that's both of the form " + ::util::ppaux::ty_to_str(tcx, mk_var(tcx, vid)) + - ~" and of the form " + ::util::ppaux::ty_to_str(tcx, rt) + - ~" - such a type would have to be infinitely large."); + " and of the form " + ::util::ppaux::ty_to_str(tcx, rt) + + " - such a type would have to be infinitely large."); } } @@ -3722,9 +3571,6 @@ pub fn type_err_to_str(cx: ctxt, err: &type_err) -> ~str { values.found.user_string(cx)) } } - terr_self_substs => { - ~"inconsistent self substitution" // XXX this is more of a bug - } terr_integer_as_char => { fmt!("expected an integral type but found char") } @@ -3744,29 +3590,29 @@ pub fn type_err_to_str(cx: ctxt, err: &type_err) -> ~str { pub fn note_and_explain_type_err(cx: ctxt, err: &type_err) { match *err { terr_regions_does_not_outlive(subregion, superregion) => { - note_and_explain_region(cx, ~"", subregion, ~"..."); - note_and_explain_region(cx, ~"...does not necessarily outlive ", - superregion, ~""); + note_and_explain_region(cx, "", subregion, "..."); + note_and_explain_region(cx, "...does not necessarily outlive ", + superregion, ""); } terr_regions_not_same(region1, region2) => { - note_and_explain_region(cx, ~"", region1, ~"..."); - note_and_explain_region(cx, ~"...is not the same lifetime as ", - region2, ~""); + note_and_explain_region(cx, "", region1, "..."); + note_and_explain_region(cx, "...is not the same lifetime as ", + region2, ""); } terr_regions_no_overlap(region1, region2) => { - note_and_explain_region(cx, ~"", region1, ~"..."); - note_and_explain_region(cx, ~"...does not overlap ", - region2, ~""); + note_and_explain_region(cx, "", region1, "..."); + note_and_explain_region(cx, "...does not overlap ", + region2, ""); } terr_regions_insufficiently_polymorphic(_, conc_region) => { note_and_explain_region(cx, - ~"concrete lifetime that was found is ", - conc_region, ~""); + "concrete lifetime that was found is ", + conc_region, ""); } terr_regions_overly_polymorphic(_, conc_region) => { note_and_explain_region(cx, - ~"expected concrete lifetime is ", - conc_region, ~""); + "expected concrete lifetime is ", + conc_region, ""); } _ => {} } @@ -3859,6 +3705,21 @@ pub fn trait_method(cx: ctxt, trait_did: ast::def_id, idx: uint) -> @Method { ty::method(cx, method_def_id) } + +pub fn add_base_impl(cx: ctxt, base_def_id: def_id, implementation: @Impl) { + let implementations; + match cx.base_impls.find(&base_def_id) { + None => { + implementations = @mut ~[]; + cx.base_impls.insert(base_def_id, implementations); + } + Some(&existing) => { + implementations = existing; + } + } + implementations.push(implementation); +} + pub fn trait_methods(cx: ctxt, trait_did: ast::def_id) -> @~[@Method] { match cx.trait_methods_cache.find(&trait_did) { Some(&methods) => methods, @@ -3916,7 +3777,7 @@ pub fn ty_to_def_id(ty: t) -> Option { fn struct_ctor_id(cx: ctxt, struct_did: ast::def_id) -> Option { if struct_did.crate != ast::local_crate { // XXX: Cross-crate functionality. - cx.sess.unimpl(~"constructor ID of cross-crate tuple structs"); + cx.sess.unimpl("constructor ID of cross-crate tuple structs"); } match cx.items.find(&struct_did.node) { @@ -3926,10 +3787,10 @@ fn struct_ctor_id(cx: ctxt, struct_did: ast::def_id) -> Option { struct_def.ctor_id.map(|ctor_id| ast_util::local_def(*ctor_id)) } - _ => cx.sess.bug(~"called struct_ctor_id on non-struct") + _ => cx.sess.bug("called struct_ctor_id on non-struct") } } - _ => cx.sess.bug(~"called struct_ctor_id on non-struct") + _ => cx.sess.bug("called struct_ctor_id on non-struct") } } @@ -3961,7 +3822,7 @@ pub fn substd_enum_variants(cx: ctxt, } pub fn item_path_str(cx: ctxt, id: ast::def_id) -> ~str { - ast_map::path_to_str(item_path(cx, id), cx.sess.parse_sess.interner) + ast_map::path_to_str(item_path(cx, id), token::get_ident_interner()) } pub enum DtorKind { @@ -3969,14 +3830,15 @@ pub enum DtorKind { TraitDtor(def_id) } -pub impl DtorKind { - fn is_not_present(&const self) -> bool { +impl DtorKind { + pub fn is_not_present(&const self) -> bool { match *self { NoDtor => true, _ => false } } - fn is_present(&const self) -> bool { + + pub fn is_present(&const self) -> bool { !self.is_not_present() } } @@ -4094,7 +3956,7 @@ pub fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[VariantInfo] { disr_val = match const_eval::eval_const_expr(cx, ex) { const_eval::const_int(val) => val as int, - _ => cx.sess.bug(~"tag_variants: bad disr expr") + _ => cx.sess.bug("tag_variants: bad disr expr") } } _ => disr_val += 1 @@ -4113,7 +3975,7 @@ pub fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[VariantInfo] { } }) } - _ => cx.sess.bug(~"tag_variants: id not bound to an enum") + _ => cx.sess.bug("tag_variants: id not bound to an enum") } }; cx.enum_var_cache.insert(id, result); @@ -4133,7 +3995,7 @@ pub fn enum_variant_with_id(cx: ctxt, if variant.id == variant_id { return variant; } i += 1; } - cx.sess.bug(~"enum_variant_with_id(): no variant exists with that ID"); + cx.sess.bug("enum_variant_with_id(): no variant exists with that ID"); } @@ -4228,7 +4090,7 @@ pub fn lookup_struct_fields(cx: ctxt, did: ast::def_id) -> ~[field_ty] { ast::item_struct(struct_def, _) => { struct_field_tys(struct_def.fields) } - _ => cx.sess.bug(~"struct ID bound to non-struct") + _ => cx.sess.bug("struct ID bound to non-struct") } } Some(&ast_map::node_variant(ref variant, _, _)) => { @@ -4237,8 +4099,8 @@ pub fn lookup_struct_fields(cx: ctxt, did: ast::def_id) -> ~[field_ty] { struct_field_tys(struct_def.fields) } _ => { - cx.sess.bug(~"struct ID bound to enum variant that isn't \ - struct-like") + cx.sess.bug("struct ID bound to enum variant that isn't \ + struct-like") } } } @@ -4246,7 +4108,7 @@ pub fn lookup_struct_fields(cx: ctxt, did: ast::def_id) -> ~[field_ty] { cx.sess.bug( fmt!("struct ID not bound to an item: %s", ast_map::node_id_to_str(cx.items, did.node, - cx.sess.parse_sess.interner))); + token::get_ident_interner()))); } } } @@ -4262,7 +4124,7 @@ pub fn lookup_struct_field(cx: ctxt, match vec::find(lookup_struct_fields(cx, parent), |f| f.id.node == field_id.node) { Some(t) => t, - None => cx.sess.bug(~"struct ID not found in parent's fields") + None => cx.sess.bug("struct ID not found in parent's fields") } } @@ -4503,52 +4365,6 @@ pub fn determine_inherited_purity(parent: (ast::purity, ast::node_id), // Here, the supertraits are the transitive closure of the supertrait // relation on the supertraits from each bounded trait's constraint // list. -#[cfg(stage0)] -pub fn each_bound_trait_and_supertraits(tcx: ctxt, - bounds: &ParamBounds, - f: &fn(@TraitRef) -> bool) { - for bounds.trait_bounds.each |&bound_trait_ref| { - let mut supertrait_set = HashMap::new(); - let mut trait_refs = ~[]; - let mut i = 0; - - // Seed the worklist with the trait from the bound - supertrait_set.insert(bound_trait_ref.def_id, ()); - trait_refs.push(bound_trait_ref); - - // Add the given trait ty to the hash map - while i < trait_refs.len() { - debug!("each_bound_trait_and_supertraits(i=%?, trait_ref=%s)", - i, trait_refs[i].repr(tcx)); - - if !f(trait_refs[i]) { - return; - } - - // Add supertraits to supertrait_set - let supertrait_refs = trait_ref_supertraits(tcx, trait_refs[i]); - for supertrait_refs.each |&supertrait_ref| { - debug!("each_bound_trait_and_supertraits(supertrait_ref=%s)", - supertrait_ref.repr(tcx)); - - let d_id = supertrait_ref.def_id; - if !supertrait_set.contains_key(&d_id) { - // FIXME(#5527) Could have same trait multiple times - supertrait_set.insert(d_id, ()); - trait_refs.push(supertrait_ref); - } - } - - i += 1; - } - } -} -// Iterate over a type parameter's bounded traits and any supertraits -// of those traits, ignoring kinds. -// Here, the supertraits are the transitive closure of the supertrait -// relation on the supertraits from each bounded trait's constraint -// list. -#[cfg(not(stage0))] pub fn each_bound_trait_and_supertraits(tcx: ctxt, bounds: &ParamBounds, f: &fn(@TraitRef) -> bool) -> bool { @@ -4609,11 +4425,11 @@ pub fn get_impl_id(tcx: ctxt, trait_id: def_id, self_ty: t) -> def_id { None => // try autoderef! match deref(tcx, self_ty, false) { Some(some_ty) => get_impl_id(tcx, trait_id, some_ty.ty), - None => tcx.sess.bug(~"get_impl_id: no impl of trait for \ - this type") + None => tcx.sess.bug("get_impl_id: no impl of trait for \ + this type") } }, - None => tcx.sess.bug(~"get_impl_id: trait isn't in trait_impls") + None => tcx.sess.bug("get_impl_id: trait isn't in trait_impls") } } diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index 222493b056456..4b5f416cdd172 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -52,6 +52,8 @@ * an rptr (`&r.T`) use the region `r` that appears in the rptr. */ +use core::prelude::*; + use middle::const_eval; use middle::ty::{substs}; use middle::ty::{ty_param_substs_and_ty}; @@ -61,6 +63,8 @@ use middle::typeck::rscope::{region_scope, RegionError}; use middle::typeck::rscope::RegionParamNames; use middle::typeck::lookup_def_tcx; +use core::result; +use core::vec; use syntax::abi::AbiSet; use syntax::{ast, ast_util}; use syntax::codemap::span; @@ -451,7 +455,7 @@ pub fn ast_ty_to_ty( } _ => { tcx.sess.span_fatal(ast_ty.span, - "found type name used as a variable"); + fmt!("found value name used as a type: %?", a_def)); } } } @@ -778,6 +782,9 @@ pub fn try_add_builtin_trait(tcx: ty::ctxt, } else if trait_def_id == li.const_trait() { builtin_bounds.add(ty::BoundConst); true + } else if trait_def_id == li.sized_trait() { + builtin_bounds.add(ty::BoundSized); + true } else { false } diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs index 07083459020b1..03803a64fc36e 100644 --- a/src/librustc/middle/typeck/check/_match.rs +++ b/src/librustc/middle/typeck/check/_match.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use middle::pat_util::{PatIdMap, pat_id_map, pat_is_binding, pat_is_const}; use middle::ty; use middle::typeck::check::demand; @@ -17,6 +19,7 @@ use middle::typeck::check::{structure_of, valid_range_bounds}; use middle::typeck::require_same_types; use core::hashmap::{HashMap, HashSet}; +use core::vec; use syntax::ast; use syntax::ast_util; use syntax::codemap::span; @@ -103,7 +106,8 @@ pub fn check_pat_variant(pcx: &pat_ctxt, pat: @ast::pat, path: @ast::Path, let fcx = pcx.fcx; let tcx = pcx.fcx.ccx.tcx; - let arg_types, kind_name; + let arg_types; + let kind_name; // structure_of requires type variables to be resolved. // So when we pass in , it's an error if it @@ -155,8 +159,8 @@ pub fn check_pat_variant(pcx: &pat_ctxt, pat: @ast::pat, path: @ast::Path, None); fcx.write_error(pat.id); kind_name = "[error]"; - arg_types = (copy subpats).get_or_default(~[]).map(|_| - ty::mk_err()); + arg_types = (copy *subpats).get_or_default(~[]).map(|_| + ty::mk_err()); } } } @@ -197,8 +201,8 @@ pub fn check_pat_variant(pcx: &pat_ctxt, pat: @ast::pat, path: @ast::Path, None); fcx.write_error(pat.id); kind_name = "[error]"; - arg_types = (copy subpats).get_or_default(~[]).map(|_| - ty::mk_err()); + arg_types = (copy *subpats).get_or_default(~[]).map(|_| + ty::mk_err()); } } @@ -408,8 +412,18 @@ pub fn check_pat(pcx: &pat_ctxt, pat: @ast::pat, expected: ty::t) { // no-op } else if !ty::type_is_numeric(b_ty) { tcx.sess.span_err(pat.span, "non-numeric type used in range"); - } else if !valid_range_bounds(fcx.ccx, begin, end) { - tcx.sess.span_err(begin.span, "lower range bound must be less than upper"); + } else { + match valid_range_bounds(fcx.ccx, begin, end) { + Some(false) => { + tcx.sess.span_err(begin.span, + "lower range bound must be less than upper"); + }, + None => { + tcx.sess.span_err(begin.span, + "mismatched types in range"); + }, + _ => { }, + } } fcx.write_ty(pat.id, b_ty); } @@ -437,7 +451,7 @@ pub fn check_pat(pcx: &pat_ctxt, pat: @ast::pat, expected: ty::t) { demand::eqtype(fcx, pat.span, region_ty, typ); } // otherwise the type of x is the expected type T - ast::bind_by_copy | ast::bind_infer => { + ast::bind_infer => { demand::eqtype(fcx, pat.span, expected, typ); } } diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index 9e8103f4527f6..9b8393a7464bf 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -79,6 +79,8 @@ obtained the type `Foo`, we would never match this method. */ +use core::prelude::*; + use middle::resolve; use middle::ty::*; use middle::ty; @@ -94,7 +96,10 @@ use middle::typeck::check::regionmanip::replace_bound_regions_in_fn_sig; use util::common::indenter; use core::hashmap::HashSet; -use std::list::Nil; +use core::result; +use core::uint; +use core::vec; +use extra::list::Nil; use syntax::ast::{def_id, sty_value, sty_region, sty_box}; use syntax::ast::{sty_uniq, sty_static, node_id}; use syntax::ast::{m_const, m_mutbl, m_imm}; @@ -174,8 +179,8 @@ pub struct Candidate { origin: method_origin, } -pub impl<'self> LookupContext<'self> { - fn do_lookup(&self, self_ty: ty::t) -> Option { +impl<'self> LookupContext<'self> { + pub fn do_lookup(&self, self_ty: ty::t) -> Option { let self_ty = structurally_resolved_type(self.fcx, self.self_expr.span, self_ty); @@ -243,8 +248,8 @@ pub impl<'self> LookupContext<'self> { self.search_for_autosliced_method(self_ty, autoderefs) } - fn deref(&self, ty: ty::t, enum_dids: &mut ~[ast::def_id]) - -> Option { + pub fn deref(&self, ty: ty::t, enum_dids: &mut ~[ast::def_id]) + -> Option { match ty::get(ty).sty { ty_enum(did, _) => { // Watch out for newtype'd enums like "enum t = @T". @@ -270,7 +275,7 @@ pub impl<'self> LookupContext<'self> { // ______________________________________________________________________ // Candidate collection (see comment at start of file) - fn push_inherent_candidates(&self, self_ty: ty::t) { + pub fn push_inherent_candidates(&self, self_ty: ty::t) { /*! * Collect all inherent candidates into * `self.inherent_candidates`. See comment at the start of @@ -321,7 +326,7 @@ pub impl<'self> LookupContext<'self> { } } - fn push_extension_candidates(&self, self_ty: ty::t) { + pub fn push_extension_candidates(&self, self_ty: ty::t) { // If the method being called is associated with a trait, then // find all the impls of that trait. Each of those are // candidates. @@ -354,9 +359,9 @@ pub impl<'self> LookupContext<'self> { } } - fn push_inherent_candidates_from_param(&self, - rcvr_ty: ty::t, - param_ty: param_ty) { + pub fn push_inherent_candidates_from_param(&self, + rcvr_ty: ty::t, + param_ty: param_ty) { debug!("push_inherent_candidates_from_param(param_ty=%?)", param_ty); let _indenter = indenter(); @@ -412,11 +417,11 @@ pub impl<'self> LookupContext<'self> { } } - fn push_inherent_candidates_from_trait(&self, - self_ty: ty::t, - did: def_id, - substs: &ty::substs, - store: ty::TraitStore) { + pub fn push_inherent_candidates_from_trait(&self, + self_ty: ty::t, + did: def_id, + substs: &ty::substs, + store: ty::TraitStore) { debug!("push_inherent_candidates_from_trait(did=%s, substs=%s)", self.did_to_str(did), substs_to_str(self.tcx(), substs)); @@ -438,7 +443,7 @@ pub impl<'self> LookupContext<'self> { return; // inapplicable } ast::sty_region(_) => vstore_slice(r) - ast::sty_box(_) => vstore_box, // XXX NDM mutability + ast::sty_box(_) => vstore_box, // NDM mutability, as per #5762 ast::sty_uniq(_) => vstore_uniq } */ @@ -464,10 +469,10 @@ pub impl<'self> LookupContext<'self> { }); } - fn push_inherent_candidates_from_self(&self, - self_ty: ty::t, - did: def_id, - substs: &ty::substs) { + pub fn push_inherent_candidates_from_self(&self, + self_ty: ty::t, + did: def_id, + substs: &ty::substs) { struct MethodInfo { method_ty: @ty::Method, trait_def_id: ast::def_id, @@ -528,7 +533,7 @@ pub impl<'self> LookupContext<'self> { } } - fn push_inherent_impl_candidates_for_type(&self, did: def_id) { + pub fn push_inherent_impl_candidates_for_type(&self, did: def_id) { let opt_impl_infos = self.fcx.ccx.coherence_info.inherent_methods.find(&did); for opt_impl_infos.each |impl_infos| { @@ -539,8 +544,9 @@ pub impl<'self> LookupContext<'self> { } } - fn push_candidates_from_impl(&self, candidates: &mut ~[Candidate], - impl_info: &resolve::Impl) { + pub fn push_candidates_from_impl(&self, + candidates: &mut ~[Candidate], + impl_info: &resolve::Impl) { if !self.impl_dups.insert(impl_info.did) { return; // already visited } @@ -574,12 +580,14 @@ pub impl<'self> LookupContext<'self> { }); } - fn push_candidates_from_provided_methods( - &self, - candidates: &mut ~[Candidate], - self_ty: ty::t, - trait_def_id: def_id, - methods: &mut ~[@ProvidedMethodInfo]) { + pub fn push_candidates_from_provided_methods(&self, + candidates: + &mut ~[Candidate], + self_ty: ty::t, + trait_def_id: def_id, + methods: + &mut ~[@ProvidedMethodInfo]) + { debug!("(pushing candidates from provided methods) considering trait \ id %d:%d", trait_def_id.crate, @@ -594,7 +602,7 @@ pub impl<'self> LookupContext<'self> { let method = ty::method(self.tcx(), provided_method_info.method_info.did); - // XXX: Needs to support generics. + // FIXME #4099 (?) Needs to support generics. let dummy_substs = substs { self_r: None, self_ty: None, @@ -613,12 +621,10 @@ pub impl<'self> LookupContext<'self> { // ______________________________________________________________________ // Candidate selection (see comment at start of file) - fn search_for_autoderefd_method( - &self, - self_ty: ty::t, - autoderefs: uint) - -> Option - { + pub fn search_for_autoderefd_method(&self, + self_ty: ty::t, + autoderefs: uint) + -> Option { let (self_ty, autoadjust) = self.consider_reborrow(self_ty, autoderefs); match self.search_for_method(self_ty) { @@ -634,10 +640,10 @@ pub impl<'self> LookupContext<'self> { } } - fn consider_reborrow(&self, - self_ty: ty::t, - autoderefs: uint) -> (ty::t, ty::AutoAdjustment) - { + pub fn consider_reborrow(&self, + self_ty: ty::t, + autoderefs: uint) + -> (ty::t, ty::AutoAdjustment) { /*! * * In the event that we are invoking a method with a receiver @@ -697,12 +703,10 @@ pub impl<'self> LookupContext<'self> { } } - fn search_for_autosliced_method( - &self, - self_ty: ty::t, - autoderefs: uint) - -> Option - { + pub fn search_for_autosliced_method(&self, + self_ty: ty::t, + autoderefs: uint) + -> Option { /*! * * Searches for a candidate by converting things like @@ -765,12 +769,8 @@ pub impl<'self> LookupContext<'self> { } } - fn search_for_autoptrd_method( - &self, - self_ty: ty::t, - autoderefs: uint) - -> Option - { + pub fn search_for_autoptrd_method(&self, self_ty: ty::t, autoderefs: uint) + -> Option { /*! * * Converts any type `T` to `&M T` where `M` is an @@ -801,14 +801,13 @@ pub impl<'self> LookupContext<'self> { } } - fn search_for_some_kind_of_autorefd_method( + pub fn search_for_some_kind_of_autorefd_method( &self, kind: &fn(Region, ast::mutability) -> ty::AutoRef, autoderefs: uint, mutbls: &[ast::mutability], mk_autoref_ty: &fn(ast::mutability, ty::Region) -> ty::t) - -> Option - { + -> Option { // This is hokey. We should have mutability inference as a // variable. But for now, try &const, then &, then &mut: let region = self.infcx().next_region_var_nb(self.expr.span); @@ -829,10 +828,8 @@ pub impl<'self> LookupContext<'self> { return None; } - fn search_for_method(&self, - rcvr_ty: ty::t) - -> Option - { + pub fn search_for_method(&self, rcvr_ty: ty::t) + -> Option { debug!("search_for_method(rcvr_ty=%s)", self.ty_to_str(rcvr_ty)); let _indenter = indenter(); @@ -859,11 +856,10 @@ pub impl<'self> LookupContext<'self> { } } - fn consider_candidates(&self, - rcvr_ty: ty::t, - candidates: &mut ~[Candidate]) - -> Option - { + pub fn consider_candidates(&self, + rcvr_ty: ty::t, + candidates: &mut ~[Candidate]) + -> Option { let relevant_candidates = candidates.filter_to_vec(|c| self.is_relevant(rcvr_ty, c)); @@ -885,7 +881,7 @@ pub impl<'self> LookupContext<'self> { Some(self.confirm_candidate(rcvr_ty, &relevant_candidates[0])) } - fn merge_candidates(&self, candidates: &[Candidate]) -> ~[Candidate] { + pub fn merge_candidates(&self, candidates: &[Candidate]) -> ~[Candidate] { let mut merged = ~[]; let mut i = 0; while i < candidates.len() { @@ -931,11 +927,8 @@ pub impl<'self> LookupContext<'self> { return merged; } - fn confirm_candidate(&self, - rcvr_ty: ty::t, - candidate: &Candidate) - -> method_map_entry - { + pub fn confirm_candidate(&self, rcvr_ty: ty::t, candidate: &Candidate) + -> method_map_entry { let tcx = self.tcx(); let fty = self.fn_ty_from_origin(&candidate.origin); @@ -1060,10 +1053,9 @@ pub impl<'self> LookupContext<'self> { } } - fn enforce_trait_instance_limitations(&self, - method_fty: ty::t, - candidate: &Candidate) - { + pub fn enforce_trait_instance_limitations(&self, + method_fty: ty::t, + candidate: &Candidate) { /*! * * There are some limitations to calling functions through a @@ -1094,7 +1086,7 @@ pub impl<'self> LookupContext<'self> { } } - fn enforce_drop_trait_limitations(&self, candidate: &Candidate) { + pub fn enforce_drop_trait_limitations(&self, candidate: &Candidate) { // No code can call the finalize method explicitly. let bad; match candidate.origin { @@ -1116,7 +1108,7 @@ pub impl<'self> LookupContext<'self> { // `rcvr_ty` is the type of the expression. It may be a subtype of a // candidate method's `self_ty`. - fn is_relevant(&self, rcvr_ty: ty::t, candidate: &Candidate) -> bool { + pub fn is_relevant(&self, rcvr_ty: ty::t, candidate: &Candidate) -> bool { debug!("is_relevant(rcvr_ty=%s, candidate=%s)", self.ty_to_str(rcvr_ty), self.cand_to_str(candidate)); @@ -1203,7 +1195,7 @@ pub impl<'self> LookupContext<'self> { } } - fn fn_ty_from_origin(&self, origin: &method_origin) -> ty::t { + pub fn fn_ty_from_origin(&self, origin: &method_origin) -> ty::t { return match *origin { method_static(did) => { ty::lookup_item_type(self.tcx(), did).ty @@ -1225,7 +1217,7 @@ pub impl<'self> LookupContext<'self> { } } - fn report_candidate(&self, idx: uint, origin: &method_origin) { + pub fn report_candidate(&self, idx: uint, origin: &method_origin) { match *origin { method_static(impl_did) => { self.report_static_candidate(idx, impl_did) @@ -1240,7 +1232,7 @@ pub impl<'self> LookupContext<'self> { } } - fn report_static_candidate(&self, idx: uint, did: def_id) { + pub fn report_static_candidate(&self, idx: uint, did: def_id) { let span = if did.crate == ast::local_crate { match self.tcx().items.find(&did.node) { Some(&ast_map::node_method(m, _, _)) => m.span, @@ -1256,7 +1248,7 @@ pub impl<'self> LookupContext<'self> { ty::item_path_str(self.tcx(), did))); } - fn report_param_candidate(&self, idx: uint, did: def_id) { + pub fn report_param_candidate(&self, idx: uint, did: def_id) { self.tcx().sess.span_note( self.expr.span, fmt!("candidate #%u derives from the bound `%s`", @@ -1264,7 +1256,7 @@ pub impl<'self> LookupContext<'self> { ty::item_path_str(self.tcx(), did))); } - fn report_trait_candidate(&self, idx: uint, did: def_id) { + pub fn report_trait_candidate(&self, idx: uint, did: def_id) { self.tcx().sess.span_note( self.expr.span, fmt!("candidate #%u derives from the type of the receiver, \ @@ -1273,30 +1265,30 @@ pub impl<'self> LookupContext<'self> { ty::item_path_str(self.tcx(), did))); } - fn infcx(&self) -> @mut infer::InferCtxt { + pub fn infcx(&self) -> @mut infer::InferCtxt { self.fcx.inh.infcx } - fn tcx(&self) -> ty::ctxt { + pub fn tcx(&self) -> ty::ctxt { self.fcx.tcx() } - fn ty_to_str(&self, t: ty::t) -> ~str { + pub fn ty_to_str(&self, t: ty::t) -> ~str { self.fcx.infcx().ty_to_str(t) } - fn cand_to_str(&self, cand: &Candidate) -> ~str { + pub fn cand_to_str(&self, cand: &Candidate) -> ~str { fmt!("Candidate(rcvr_ty=%s, rcvr_substs=%s, origin=%?)", self.ty_to_str(cand.rcvr_ty), ty::substs_to_str(self.tcx(), &cand.rcvr_substs), cand.origin) } - fn did_to_str(&self, did: def_id) -> ~str { + pub fn did_to_str(&self, did: def_id) -> ~str { ty::item_path_str(self.tcx(), did) } - fn bug(&self, s: ~str) -> ! { + pub fn bug(&self, s: ~str) -> ! { self.tcx().sess.bug(s) } } diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 8d32bb7f67756..c69aeeb4aa8b8 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -76,9 +76,12 @@ type parameter). */ +use core::prelude::*; + use middle::const_eval; use middle::pat_util::pat_id_map; use middle::pat_util; +use middle::lint::unreachable_code; use middle::ty::{FnSig, VariantInfo_}; use middle::ty::{ty_param_bounds_and_ty, ty_param_substs_and_ty}; use middle::ty::{substs, param_ty}; @@ -109,8 +112,11 @@ use util::ppaux; use core::cast::transmute; use core::hashmap::HashMap; +use core::result; +use core::str; use core::util::replace; -use std::list::Nil; +use core::vec; +use extra::list::Nil; use syntax::abi::AbiSet; use syntax::ast::{provided, required}; use syntax::ast; @@ -121,6 +127,7 @@ use syntax::codemap::span; use syntax::codemap; use syntax::opt_vec::OptVec; use syntax::opt_vec; +use syntax::parse::token; use syntax::parse::token::special_idents; use syntax::print::pprust; use syntax::visit; @@ -180,7 +187,7 @@ pub struct PurityState { priv from_fn: bool } -pub impl PurityState { +impl PurityState { pub fn function(purity: ast::purity, def: ast::node_id) -> PurityState { PurityState { def: def, purity: purity, from_fn: true } } @@ -652,18 +659,17 @@ impl AstConv for FnCtxt { } } -pub impl FnCtxt { - fn infcx(&self) -> @mut infer::InferCtxt { +impl FnCtxt { + pub fn infcx(&self) -> @mut infer::InferCtxt { self.inh.infcx } - fn err_count_since_creation(&self) -> uint { + pub fn err_count_since_creation(&self) -> uint { self.ccx.tcx.sess.err_count() - self.err_count_on_creation } - fn search_in_scope_regions( - &self, - span: span, - br: ty::bound_region) -> Result - { + pub fn search_in_scope_regions(&self, + span: span, + br: ty::bound_region) + -> Result { let in_scope_regions = self.in_scope_regions; match in_scope_regions.find(br) { Some(r) => result::Ok(r), @@ -697,14 +703,14 @@ impl region_scope for FnCtxt { } } -pub impl FnCtxt { - fn tag(&self) -> ~str { +impl FnCtxt { + pub fn tag(&self) -> ~str { unsafe { fmt!("%x", transmute(self)) } } - fn local_ty(&self, span: span, nid: ast::node_id) -> ty::t { + pub fn local_ty(&self, span: span, nid: ast::node_id) -> ty::t { match self.inh.locals.find(&nid) { Some(&t) => t, None => { @@ -715,23 +721,23 @@ pub impl FnCtxt { } } - fn expr_to_str(&self, expr: @ast::expr) -> ~str { + pub fn expr_to_str(&self, expr: @ast::expr) -> ~str { fmt!("expr(%?:%s)", expr.id, pprust::expr_to_str(expr, self.tcx().sess.intr())) } - fn block_region(&self) -> ty::Region { + pub fn block_region(&self) -> ty::Region { ty::re_scope(self.region_lb) } #[inline(always)] - fn write_ty(&self, node_id: ast::node_id, ty: ty::t) { + pub fn write_ty(&self, node_id: ast::node_id, ty: ty::t) { debug!("write_ty(%d, %s) in fcx %s", node_id, ppaux::ty_to_str(self.tcx(), ty), self.tag()); self.inh.node_types.insert(node_id, ty); } - fn write_substs(&self, node_id: ast::node_id, substs: ty::substs) { + pub fn write_substs(&self, node_id: ast::node_id, substs: ty::substs) { if !ty::substs_is_noop(&substs) { debug!("write_substs(%d, %s) in fcx %s", node_id, @@ -741,18 +747,18 @@ pub impl FnCtxt { } } - fn write_ty_substs(&self, - node_id: ast::node_id, - ty: ty::t, - substs: ty::substs) { + pub fn write_ty_substs(&self, + node_id: ast::node_id, + ty: ty::t, + substs: ty::substs) { let ty = ty::subst(self.tcx(), &substs, ty); self.write_ty(node_id, ty); self.write_substs(node_id, substs); } - fn write_autoderef_adjustment(&self, - node_id: ast::node_id, - derefs: uint) { + pub fn write_autoderef_adjustment(&self, + node_id: ast::node_id, + derefs: uint) { if derefs == 0 { return; } self.write_adjustment( node_id, @@ -762,36 +768,36 @@ pub impl FnCtxt { ); } - fn write_adjustment(&self, - node_id: ast::node_id, - adj: @ty::AutoAdjustment) { + pub fn write_adjustment(&self, + node_id: ast::node_id, + adj: @ty::AutoAdjustment) { debug!("write_adjustment(node_id=%?, adj=%?)", node_id, adj); self.inh.adjustments.insert(node_id, adj); } - fn write_nil(&self, node_id: ast::node_id) { + pub fn write_nil(&self, node_id: ast::node_id) { self.write_ty(node_id, ty::mk_nil()); } - fn write_bot(&self, node_id: ast::node_id) { + pub fn write_bot(&self, node_id: ast::node_id) { self.write_ty(node_id, ty::mk_bot()); } - fn write_error(@mut self, node_id: ast::node_id) { + pub fn write_error(@mut self, node_id: ast::node_id) { self.write_ty(node_id, ty::mk_err()); } - fn to_ty(&self, ast_t: @ast::Ty) -> ty::t { + pub fn to_ty(&self, ast_t: @ast::Ty) -> ty::t { ast_ty_to_ty(self, self, ast_t) } - fn expr_to_str(&self, expr: @ast::expr) -> ~str { + pub fn expr_to_str(&self, expr: @ast::expr) -> ~str { expr.repr(self.tcx()) } - fn pat_to_str(&self, pat: @ast::pat) -> ~str { + pub fn pat_to_str(&self, pat: @ast::pat) -> ~str { pat.repr(self.tcx()) } - fn expr_ty(&self, ex: @ast::expr) -> ty::t { + pub fn expr_ty(&self, ex: @ast::expr) -> ty::t { match self.inh.node_types.find(&ex.id) { Some(&t) => t, None => { @@ -801,7 +807,8 @@ pub impl FnCtxt { } } } - fn node_ty(&self, id: ast::node_id) -> ty::t { + + pub fn node_ty(&self, id: ast::node_id) -> ty::t { match self.inh.node_types.find(&id) { Some(&t) => t, None => { @@ -809,12 +816,13 @@ pub impl FnCtxt { fmt!("no type for node %d: %s in fcx %s", id, ast_map::node_id_to_str( self.tcx().items, id, - self.tcx().sess.parse_sess.interner), + token::get_ident_interner()), self.tag())); } } } - fn node_ty_substs(&self, id: ast::node_id) -> ty::substs { + + pub fn node_ty_substs(&self, id: ast::node_id) -> ty::substs { match self.inh.node_type_substs.find(&id) { Some(ts) => (/*bad*/copy *ts), None => { @@ -822,47 +830,38 @@ pub impl FnCtxt { fmt!("no type substs for node %d: %s in fcx %s", id, ast_map::node_id_to_str( self.tcx().items, id, - self.tcx().sess.parse_sess.interner), + token::get_ident_interner()), self.tag())); } } } - #[cfg(stage0)] - fn opt_node_ty_substs(&self, id: ast::node_id, - f: &fn(&ty::substs) -> bool) { - match self.inh.node_type_substs.find(&id) { - Some(s) => { f(s); } - None => () - } - } - #[cfg(not(stage0))] - fn opt_node_ty_substs(&self, id: ast::node_id, - f: &fn(&ty::substs) -> bool) -> bool { + pub fn opt_node_ty_substs(&self, + id: ast::node_id, + f: &fn(&ty::substs) -> bool) + -> bool { match self.inh.node_type_substs.find(&id) { Some(s) => f(s), None => true } } - fn mk_subty(&self, - a_is_expected: bool, - span: span, - sub: ty::t, - sup: ty::t) - -> Result<(), ty::type_err> { + pub fn mk_subty(&self, + a_is_expected: bool, + span: span, + sub: ty::t, + sup: ty::t) + -> Result<(), ty::type_err> { infer::mk_subty(self.infcx(), a_is_expected, span, sub, sup) } - fn can_mk_subty(&self, - sub: ty::t, - sup: ty::t) - -> Result<(), ty::type_err> { + pub fn can_mk_subty(&self, sub: ty::t, sup: ty::t) + -> Result<(), ty::type_err> { infer::can_mk_subty(self.infcx(), sub, sup) } - fn mk_assignty(&self, expr: @ast::expr, sub: ty::t, sup: ty::t) - -> Result<(), ty::type_err> { + pub fn mk_assignty(&self, expr: @ast::expr, sub: ty::t, sup: ty::t) + -> Result<(), ty::type_err> { match infer::mk_coercety(self.infcx(), false, expr.span, sub, sup) { Ok(None) => result::Ok(()), Err(ref e) => result::Err((*e)), @@ -873,47 +872,31 @@ pub impl FnCtxt { } } - fn can_mk_assignty(&self, - sub: ty::t, - sup: ty::t) - -> Result<(), ty::type_err> { + pub fn can_mk_assignty(&self, sub: ty::t, sup: ty::t) + -> Result<(), ty::type_err> { infer::can_mk_coercety(self.infcx(), sub, sup) } - fn mk_eqty(&self, - a_is_expected: bool, - span: span, - sub: ty::t, - sup: ty::t) - -> Result<(), ty::type_err> { + pub fn mk_eqty(&self, + a_is_expected: bool, + span: span, + sub: ty::t, + sup: ty::t) + -> Result<(), ty::type_err> { infer::mk_eqty(self.infcx(), a_is_expected, span, sub, sup) } - fn mk_subr(&self, - a_is_expected: bool, - span: span, - sub: ty::Region, - sup: ty::Region) - -> Result<(), ty::type_err> { + pub fn mk_subr(&self, + a_is_expected: bool, + span: span, + sub: ty::Region, + sup: ty::Region) + -> Result<(), ty::type_err> { infer::mk_subr(self.infcx(), a_is_expected, span, sub, sup) } - fn require_unsafe(&self, sp: span, op: ~str) { - match self.ps.purity { - ast::unsafe_fn => { - // ok, but flag that we used the source of unsafeness - debug!("flagging %? as a used unsafe source", self.ps); - self.tcx().used_unsafe.insert(self.ps.def); - } - _ => { - self.ccx.tcx.sess.span_err( - sp, - fmt!("%s requires unsafe function or block", op)); - } - } - } - - fn with_region_lb(@mut self, lb: ast::node_id, f: &fn() -> R) -> R { + pub fn with_region_lb(@mut self, lb: ast::node_id, f: &fn() -> R) + -> R { let old_region_lb = self.region_lb; self.region_lb = lb; let v = f(); @@ -921,26 +904,26 @@ pub impl FnCtxt { v } - fn region_var_if_parameterized(&self, - rp: Option, - span: span) - -> Option { + pub fn region_var_if_parameterized(&self, + rp: Option, + span: span) + -> Option { rp.map(|_rp| self.infcx().next_region_var_nb(span)) } - fn type_error_message(&self, - sp: span, - mk_msg: &fn(~str) -> ~str, - actual_ty: ty::t, - err: Option<&ty::type_err>) { + pub fn type_error_message(&self, + sp: span, + mk_msg: &fn(~str) -> ~str, + actual_ty: ty::t, + err: Option<&ty::type_err>) { self.infcx().type_error_message(sp, mk_msg, actual_ty, err); } - fn report_mismatched_return_types(&self, - sp: span, - e: ty::t, - a: ty::t, - err: &ty::type_err) { + pub fn report_mismatched_return_types(&self, + sp: span, + e: ty::t, + a: ty::t, + err: &ty::type_err) { // Derived error if ty::type_is_error(e) || ty::type_is_error(a) { return; @@ -961,11 +944,11 @@ pub impl FnCtxt { } } - fn report_mismatched_types(&self, - sp: span, - e: ty::t, - a: ty::t, - err: &ty::type_err) { + pub fn report_mismatched_types(&self, + sp: span, + e: ty::t, + a: ty::t, + err: &ty::type_err) { self.infcx().report_mismatched_types(sp, e, a, err) } } @@ -1053,8 +1036,11 @@ pub fn check_lit(fcx: @mut FnCtxt, lit: @ast::lit) -> ty::t { pub fn valid_range_bounds(ccx: @mut CrateCtxt, from: @ast::expr, to: @ast::expr) - -> bool { - const_eval::compare_lit_exprs(ccx.tcx, from, to) <= 0 + -> Option { + match const_eval::compare_lit_exprs(ccx.tcx, from, to) { + Some(val) => Some(val <= 0), + None => None + } } pub fn check_expr_has_type( @@ -1325,6 +1311,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, // A generic function for doing all of the checking for call expressions fn check_call(fcx: @mut FnCtxt, + callee_id: ast::node_id, call_expr: @ast::expr, f: @ast::expr, args: &[@ast::expr], @@ -1341,7 +1328,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, // now. Best thing would I think be to just have a separate // "callee table" that contains the FnSig and not a general // purpose ty::t - fcx.write_ty(call_expr.callee_id, fn_ty); + fcx.write_ty(callee_id, fn_ty); // Extract the function signature from `in_fty`. let fn_sty = structure_of(fcx, f.span, fn_ty); @@ -1378,6 +1365,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, // Checks a method call. fn check_method_call(fcx: @mut FnCtxt, + callee_id: ast::node_id, expr: @ast::expr, rcvr: @ast::expr, method_name: ast::ident, @@ -1395,7 +1383,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, match method::lookup(fcx, expr, rcvr, - expr.callee_id, + callee_id, method_name, expr_t, tps, @@ -1419,12 +1407,12 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, // Add error type for the result fcx.write_error(expr.id); - fcx.write_error(expr.callee_id); + fcx.write_error(callee_id); } } // Call the generic checker. - let fn_ty = fcx.node_ty(expr.callee_id); + let fn_ty = fcx.node_ty(callee_id); let ret_ty = check_method_argument_types(fcx, expr.span, fn_ty, expr, args, sugar, DontDerefArgs); @@ -1459,6 +1447,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } fn lookup_op_method(fcx: @mut FnCtxt, + callee_id: ast::node_id, op_ex: @ast::expr, self_ex: @ast::expr, self_t: ty::t, @@ -1471,10 +1460,10 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, ) -> ty::t { match method::lookup(fcx, op_ex, self_ex, - op_ex.callee_id, opname, self_t, ~[], + callee_id, opname, self_t, [], deref_args, CheckTraitsOnly, autoderef_receiver) { Some(ref origin) => { - let method_ty = fcx.node_ty(op_ex.callee_id); + let method_ty = fcx.node_ty(callee_id); let method_map = fcx.inh.method_map; method_map.insert(op_ex.id, *origin); check_method_argument_types(fcx, op_ex.span, @@ -1496,6 +1485,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, // could be either a expr_binop or an expr_assign_binop fn check_binop(fcx: @mut FnCtxt, + callee_id: ast::node_id, expr: @ast::expr, op: ast::binop, lhs: @ast::expr, @@ -1551,7 +1541,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } - let result_t = check_user_binop(fcx, expr, lhs, lhs_t, op, rhs, + let result_t = check_user_binop(fcx, callee_id, expr, lhs, lhs_t, op, rhs, expected_result); fcx.write_ty(expr.id, result_t); if ty::type_is_error(result_t) { @@ -1560,6 +1550,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } fn check_user_binop(fcx: @mut FnCtxt, + callee_id: ast::node_id, ex: @ast::expr, lhs_expr: @ast::expr, lhs_resolved_t: ty::t, @@ -1576,7 +1567,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, ast_util::binop_to_str(op), actual)}, lhs_resolved_t, None) }; - return lookup_op_method(fcx, ex, lhs_expr, lhs_resolved_t, + return lookup_op_method(fcx, callee_id, ex, lhs_expr, lhs_resolved_t, fcx.tcx().sess.ident_of(*name), ~[rhs], DoDerefArgs, DontAutoderefReceiver, if_op_unbound, expected_result); @@ -1601,6 +1592,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } fn check_user_unop(fcx: @mut FnCtxt, + callee_id: ast::node_id, op_str: &str, mname: &str, ex: @ast::expr, @@ -1609,7 +1601,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, expected_t: Option) -> ty::t { lookup_op_method( - fcx, ex, rhs_expr, rhs_t, + fcx, callee_id, ex, rhs_expr, rhs_t, fcx.tcx().sess.ident_of(mname), ~[], DoDerefArgs, DontAutoderefReceiver, || { @@ -1817,7 +1809,6 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, let mut class_field_map = HashMap::new(); let mut fields_found = 0; for field_types.each |field| { - // XXX: Check visibility here. class_field_map.insert(field.ident, (field.id, false)); } @@ -1875,7 +1866,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, let (_, seen) = *class_field_map.get(&name); if !seen { missing_fields.push( - ~"`" + *tcx.sess.str_of(name) + ~"`"); + ~"`" + *tcx.sess.str_of(name) + "`"); } } @@ -1886,7 +1877,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } else { "s" }, - str::connect(missing_fields, ~", "))); + str::connect(missing_fields, ", "))); } } @@ -1906,7 +1897,9 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, // Look up the number of type parameters and the raw type, and // determine whether the class is region-parameterized. - let type_parameter_count, region_parameterized, raw_type; + let type_parameter_count; + let region_parameterized; + let raw_type; if class_id.crate == ast::local_crate { region_parameterized = tcx.region_paramd_items.find(&class_id.node). @@ -1993,7 +1986,9 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, // Look up the number of type parameters and the raw type, and // determine whether the enum is region-parameterized. - let type_parameter_count, region_parameterized, raw_type; + let type_parameter_count; + let region_parameterized; + let raw_type; if enum_id.crate == ast::local_crate { region_parameterized = tcx.region_paramd_items.find(&enum_id.node).map_consume(|x| *x); @@ -2121,7 +2116,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } None => fcx.tcx().sess.impossible_case( expr.span, - ~"loop body must have an expected type") + "loop body must have an expected type") } } }; @@ -2237,8 +2232,8 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, let typ = check_lit(fcx, lit); fcx.write_ty(id, typ); } - ast::expr_binary(op, lhs, rhs) => { - check_binop(fcx, expr, op, lhs, rhs, expected); + ast::expr_binary(callee_id, op, lhs, rhs) => { + check_binop(fcx, callee_id, expr, op, lhs, rhs, expected); let lhs_ty = fcx.expr_ty(lhs); let rhs_ty = fcx.expr_ty(rhs); if ty::type_is_error(lhs_ty) || @@ -2250,8 +2245,8 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, fcx.write_bot(id); } } - ast::expr_assign_op(op, lhs, rhs) => { - check_binop(fcx, expr, op, lhs, rhs, expected); + ast::expr_assign_op(callee_id, op, lhs, rhs) => { + check_binop(fcx, callee_id, expr, op, lhs, rhs, expected); let lhs_t = fcx.expr_ty(lhs); let result_t = fcx.expr_ty(expr); demand::suptype(fcx, expr.span, result_t, lhs_t); @@ -2264,7 +2259,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, fcx.write_nil(expr.id); } } - ast::expr_unary(unop, oprnd) => { + ast::expr_unary(callee_id, unop, oprnd) => { let exp_inner = do unpack_expected(fcx, expected) |sty| { match unop { ast::box(_) | ast::uniq(_) => match *sty { @@ -2290,16 +2285,6 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } ast::deref => { let sty = structure_of(fcx, expr.span, oprnd_t); - match sty { - // deref'ing an unsafe pointer requires that we be in - // an unsafe context - ty::ty_ptr(*) => { - fcx.require_unsafe( - expr.span, - ~"dereference of unsafe pointer"); - } - _ => { /*ok*/ } - } let operand_ty = ty::deref_sty(tcx, &sty, true); match operand_ty { Some(mt) => { @@ -2333,7 +2318,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, oprnd_t); if !(ty::type_is_integral(oprnd_t) || ty::get(oprnd_t).sty == ty::ty_bool) { - oprnd_t = check_user_unop(fcx, + oprnd_t = check_user_unop(fcx, callee_id, "!", "not", expr, oprnd, oprnd_t, expected); } @@ -2343,7 +2328,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, oprnd_t); if !(ty::type_is_integral(oprnd_t) || ty::type_is_fp(oprnd_t)) { - oprnd_t = check_user_unop(fcx, + oprnd_t = check_user_unop(fcx, callee_id, "-", "neg", expr, oprnd, oprnd_t, expected); } } @@ -2397,8 +2382,6 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, fcx.write_ty(id, ty_param_bounds_and_ty.ty); } ast::expr_inline_asm(ref ia) => { - fcx.require_unsafe(expr.span, ~"use of inline assembly"); - for ia.inputs.each |&(_, in)| { check_expr(fcx, in); } @@ -2407,7 +2390,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, } fcx.write_nil(id); } - ast::expr_mac(_) => tcx.sess.bug(~"unexpanded macro"), + ast::expr_mac(_) => tcx.sess.bug("unexpanded macro"), ast::expr_break(_) => { fcx.write_bot(id); } ast::expr_again(_) => { fcx.write_bot(id); } ast::expr_ret(expr_opt) => { @@ -2561,7 +2544,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, None => { fcx.tcx().sess.impossible_case( expr.span, - ~"do body must have expected type") + "do body must have expected type") } } }; @@ -2581,7 +2564,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, fcx.write_ty(id, fcx.node_ty(b.node.id)); } ast::expr_call(f, ref args, sugar) => { - check_call(fcx, expr, f, *args, sugar); + check_call(fcx, expr.id, expr, f, *args, sugar); let f_ty = fcx.expr_ty(f); let (args_bot, args_err) = args.foldl((false, false), |&(rest_bot, rest_err), a| { @@ -2596,8 +2579,8 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, fcx.write_bot(id); } } - ast::expr_method_call(rcvr, ident, ref tps, ref args, sugar) => { - check_method_call(fcx, expr, rcvr, ident, *args, *tps, sugar); + ast::expr_method_call(callee_id, rcvr, ident, ref tps, ref args, sugar) => { + check_method_call(fcx, callee_id, expr, rcvr, ident, *args, *tps, sugar); let f_ty = fcx.expr_ty(rcvr); let arg_tys = args.map(|a| fcx.expr_ty(*a)); let (args_bot, args_err) = arg_tys.foldl((false, false), @@ -2779,7 +2762,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, ast::expr_field(base, field, ref tys) => { check_field(fcx, expr, base, field, *tys); } - ast::expr_index(base, idx) => { + ast::expr_index(callee_id, base, idx) => { check_expr(fcx, base); check_expr(fcx, idx); let raw_base_t = fcx.expr_ty(base); @@ -2813,6 +2796,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, None); }; let ret_ty = lookup_op_method(fcx, + callee_id, expr, base, resolved, @@ -2897,12 +2881,12 @@ pub fn check_stmt(fcx: @mut FnCtxt, stmt: @ast::stmt) { ast::stmt_decl(decl, id) => { node_id = id; match decl.node { - ast::decl_local(ref ls) => for ls.each |l| { + ast::decl_local(ref l) => { check_decl_local(fcx, *l); let l_t = fcx.node_ty(l.node.id); saw_bot = saw_bot || ty::type_is_bot(l_t); saw_err = saw_err || ty::type_is_error(l_t); - }, + } ast::decl_item(_) => {/* ignore for now */ } } } @@ -2921,7 +2905,7 @@ pub fn check_stmt(fcx: @mut FnCtxt, stmt: @ast::stmt) { saw_bot |= ty::type_is_bot(expr_ty); saw_err |= ty::type_is_error(expr_ty); } - ast::stmt_mac(*) => fcx.ccx.tcx.sess.bug(~"unexpanded macro") + ast::stmt_mac(*) => fcx.ccx.tcx.sess.bug("unexpanded macro") } if saw_bot { fcx.write_bot(node_id); @@ -2966,7 +2950,8 @@ pub fn check_block_with_expected(fcx: @mut FnCtxt, let mut any_err = false; for blk.node.stmts.each |s| { check_stmt(fcx, *s); - let s_ty = fcx.node_ty(ast_util::stmt_id(*s)); + let s_id = ast_util::stmt_id(*s); + let s_ty = fcx.node_ty(s_id); if last_was_bot && !warned && match s.node { ast::stmt_decl(@codemap::spanned { node: ast::decl_local(_), _}, _) | @@ -2975,7 +2960,8 @@ pub fn check_block_with_expected(fcx: @mut FnCtxt, } _ => false } { - fcx.ccx.tcx.sess.span_warn(s.span, "unreachable statement"); + fcx.ccx.tcx.sess.add_lint(unreachable_code, s_id, s.span, + ~"unreachable statement"); warned = true; } if ty::type_is_bot(s_ty) { @@ -3228,13 +3214,6 @@ pub fn ty_param_bounds_and_ty_for_def(fcx: @mut FnCtxt, }; } - ast::def_fn(id, ast::unsafe_fn) | - ast::def_static_method(id, _, ast::unsafe_fn) => { - // Unsafe functions can only be touched in an unsafe context - fcx.require_unsafe(sp, ~"access to unsafe function"); - return ty::lookup_item_type(fcx.ccx.tcx, id); - } - ast::def_fn(id, _) | ast::def_static_method(id, _, _) | ast::def_const(id) | ast::def_variant(_, id) | ast::def_struct(id) => { @@ -3456,122 +3435,176 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) { let tcx = ccx.tcx; let (n_tps, inputs, output) = match *ccx.tcx.sess.str_of(it.ident) { - ~"size_of" | - ~"pref_align_of" | ~"min_align_of" => (1u, ~[], ty::mk_uint()), - ~"init" => (1u, ~[], param(ccx, 0u)), - ~"uninit" => (1u, ~[], param(ccx, 0u)), - ~"forget" => (1u, ~[ param(ccx, 0) ], ty::mk_nil()), - ~"transmute" => (2, ~[ param(ccx, 0) ], param(ccx, 1)), - ~"move_val" | ~"move_val_init" => { - (1u, + ~"size_of" | + ~"pref_align_of" | ~"min_align_of" => (1u, ~[], ty::mk_uint()), + ~"init" => (1u, ~[], param(ccx, 0u)), + ~"uninit" => (1u, ~[], param(ccx, 0u)), + ~"forget" => (1u, ~[ param(ccx, 0) ], ty::mk_nil()), + ~"transmute" => (2, ~[ param(ccx, 0) ], param(ccx, 1)), + ~"move_val" | ~"move_val_init" => { + (1u, + ~[ + ty::mk_mut_rptr(tcx, ty::re_bound(ty::br_anon(0)), param(ccx, 0)), + param(ccx, 0u) + ], + ty::mk_nil()) + } + ~"needs_drop" => (1u, ~[], ty::mk_bool()), + + ~"atomic_cxchg" | ~"atomic_cxchg_acq"| ~"atomic_cxchg_rel" => { + (0, ~[ - ty::mk_mut_rptr(tcx, ty::re_bound(ty::br_anon(0)), param(ccx, 0)), - param(ccx, 0u) - ], - ty::mk_nil()) - } - ~"needs_drop" => (1u, ~[], ty::mk_bool()), - - ~"atomic_cxchg" | ~"atomic_cxchg_acq"| ~"atomic_cxchg_rel" => { - (0, - ~[ - ty::mk_mut_rptr(tcx, - ty::re_bound(ty::br_anon(0)), - ty::mk_int()), - ty::mk_int(), - ty::mk_int() - ], - ty::mk_int()) - } - ~"atomic_load" | ~"atomic_load_acq" => { - (0, - ~[ - ty::mk_imm_rptr(tcx, ty::re_bound(ty::br_anon(0)), ty::mk_int()) - ], - ty::mk_int()) - } - ~"atomic_store" | ~"atomic_store_rel" => { - (0, - ~[ - ty::mk_mut_rptr(tcx, ty::re_bound(ty::br_anon(0)), ty::mk_int()), - ty::mk_int() - ], - ty::mk_nil()) - } - ~"atomic_xchg" | ~"atomic_xadd" | ~"atomic_xsub" | - ~"atomic_xchg_acq" | ~"atomic_xadd_acq" | ~"atomic_xsub_acq" | - ~"atomic_xchg_rel" | ~"atomic_xadd_rel" | ~"atomic_xsub_rel" => { - (0, - ~[ - ty::mk_mut_rptr(tcx, ty::re_bound(ty::br_anon(0)), ty::mk_int()), - ty::mk_int() - ], - ty::mk_int()) - } - - ~"get_tydesc" => { - // FIXME (#3730): return *intrinsic::tydesc, not *() - (1u, ~[], ty::mk_nil_ptr(ccx.tcx)) - } - ~"visit_tydesc" => { - let tydesc_name = special_idents::tydesc; - assert!(tcx.intrinsic_defs.contains_key(&tydesc_name)); - let (_, tydesc_ty) = tcx.intrinsic_defs.get_copy(&tydesc_name); - let (_, visitor_object_ty) = ty::visitor_object_ty(tcx); - let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt { - ty: tydesc_ty, - mutbl: ast::m_imm - }); - (0, ~[ td_ptr, visitor_object_ty ], ty::mk_nil()) - } - ~"frame_address" => { - let fty = ty::mk_closure(ccx.tcx, ty::ClosureTy { - purity: ast::impure_fn, - sigil: ast::BorrowedSigil, - onceness: ast::Once, - region: ty::re_bound(ty::br_anon(0)), - bounds: ty::EmptyBuiltinBounds(), - sig: ty::FnSig { - bound_lifetime_names: opt_vec::Empty, - inputs: ~[ty::mk_imm_ptr(ccx.tcx, ty::mk_mach_uint(ast::ty_u8))], - output: ty::mk_nil() - } - }); - (0u, ~[fty], ty::mk_nil()) - } - ~"morestack_addr" => { - (0u, ~[], ty::mk_nil_ptr(ccx.tcx)) - } - ~"memmove32" => { - (0, - ~[ - ty::mk_ptr(tcx, ty::mt { - ty: ty::mk_u8(), - mutbl: ast::m_mutbl - }), - ty::mk_ptr(tcx, ty::mt { - ty: ty::mk_u8(), - mutbl: ast::m_imm - }), - ty::mk_u32() - ], - ty::mk_nil()) - } - ~"memmove64" => { - (0, - ~[ - ty::mk_ptr(tcx, ty::mt { - ty: ty::mk_u8(), - mutbl: ast::m_mutbl - }), - ty::mk_ptr(tcx, ty::mt { - ty: ty::mk_u8(), - mutbl: ast::m_imm - }), - ty::mk_u64() - ], - ty::mk_nil()) - } + ty::mk_mut_rptr(tcx, + ty::re_bound(ty::br_anon(0)), + ty::mk_int()), + ty::mk_int(), + ty::mk_int() + ], + ty::mk_int()) + } + ~"atomic_load" | ~"atomic_load_acq" => { + (0, + ~[ + ty::mk_imm_rptr(tcx, ty::re_bound(ty::br_anon(0)), ty::mk_int()) + ], + ty::mk_int()) + } + ~"atomic_store" | ~"atomic_store_rel" => { + (0, + ~[ + ty::mk_mut_rptr(tcx, ty::re_bound(ty::br_anon(0)), ty::mk_int()), + ty::mk_int() + ], + ty::mk_nil()) + } + ~"atomic_xchg" | ~"atomic_xadd" | ~"atomic_xsub" | + ~"atomic_xchg_acq" | ~"atomic_xadd_acq" | ~"atomic_xsub_acq" | + ~"atomic_xchg_rel" | ~"atomic_xadd_rel" | ~"atomic_xsub_rel" => { + (0, + ~[ + ty::mk_mut_rptr(tcx, ty::re_bound(ty::br_anon(0)), ty::mk_int()), + ty::mk_int() + ], + ty::mk_int()) + } + + ~"get_tydesc" => { + // FIXME (#3730): return *intrinsic::tydesc, not *() + (1u, ~[], ty::mk_nil_ptr(ccx.tcx)) + } + ~"visit_tydesc" => { + let tydesc_name = special_idents::tydesc; + assert!(tcx.intrinsic_defs.contains_key(&tydesc_name)); + let (_, tydesc_ty) = tcx.intrinsic_defs.get_copy(&tydesc_name); + let (_, visitor_object_ty) = ty::visitor_object_ty(tcx); + let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt { + ty: tydesc_ty, + mutbl: ast::m_imm + }); + (0, ~[ td_ptr, visitor_object_ty ], ty::mk_nil()) + } + ~"frame_address" => { + let fty = ty::mk_closure(ccx.tcx, ty::ClosureTy { + purity: ast::impure_fn, + sigil: ast::BorrowedSigil, + onceness: ast::Once, + region: ty::re_bound(ty::br_anon(0)), + bounds: ty::EmptyBuiltinBounds(), + sig: ty::FnSig { + bound_lifetime_names: opt_vec::Empty, + inputs: ~[ty::mk_imm_ptr(ccx.tcx, ty::mk_mach_uint(ast::ty_u8))], + output: ty::mk_nil() + } + }); + (0u, ~[fty], ty::mk_nil()) + } + ~"morestack_addr" => { + (0u, ~[], ty::mk_nil_ptr(ccx.tcx)) + } + ~"memcpy32" => { + (1, + ~[ + ty::mk_ptr(tcx, ty::mt { + ty: param(ccx, 0), + mutbl: ast::m_mutbl + }), + ty::mk_ptr(tcx, ty::mt { + ty: param(ccx, 0), + mutbl: ast::m_imm + }), + ty::mk_u32() + ], + ty::mk_nil()) + } + ~"memcpy64" => { + (1, + ~[ + ty::mk_ptr(tcx, ty::mt { + ty: param(ccx, 0), + mutbl: ast::m_mutbl + }), + ty::mk_ptr(tcx, ty::mt { + ty: param(ccx, 0), + mutbl: ast::m_imm + }), + ty::mk_u64() + ], + ty::mk_nil()) + } + ~"memmove32" => { + (1, + ~[ + ty::mk_ptr(tcx, ty::mt { + ty: param(ccx, 0), + mutbl: ast::m_mutbl + }), + ty::mk_ptr(tcx, ty::mt { + ty: param(ccx, 0), + mutbl: ast::m_imm + }), + ty::mk_u32() + ], + ty::mk_nil()) + } + ~"memmove64" => { + (1, + ~[ + ty::mk_ptr(tcx, ty::mt { + ty: param(ccx, 0), + mutbl: ast::m_mutbl + }), + ty::mk_ptr(tcx, ty::mt { + ty: param(ccx, 0), + mutbl: ast::m_imm + }), + ty::mk_u64() + ], + ty::mk_nil()) + } + ~"memset32" => { + (1, + ~[ + ty::mk_ptr(tcx, ty::mt { + ty: param(ccx, 0), + mutbl: ast::m_mutbl + }), + ty::mk_u8(), + ty::mk_u32() + ], + ty::mk_nil()) + } + ~"memset64" => { + (1, + ~[ + ty::mk_ptr(tcx, ty::mt { + ty: param(ccx, 0), + mutbl: ast::m_mutbl + }), + ty::mk_u8(), + ty::mk_u64() + ], + ty::mk_nil()) + } ~"sqrtf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()), ~"sqrtf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()), ~"powif32" => { @@ -3643,8 +3676,8 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) { ~"bswap64" => (0, ~[ ty::mk_i64() ], ty::mk_i64()), ref other => { tcx.sess.span_err(it.span, - ~"unrecognized intrinsic function: `" + - (*other) + ~"`"); + fmt!("unrecognized intrinsic function: `%s`", + *other)); return; } }; diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs index ecec07ec51287..58749b92ddcd4 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -27,6 +27,8 @@ this point a bit better. */ +use core::prelude::*; + use middle::freevars::get_freevars; use middle::ty::{re_scope}; use middle::ty; @@ -34,10 +36,11 @@ use middle::typeck::check::FnCtxt; use middle::typeck::check::regionmanip::relate_nested_regions; use middle::typeck::infer::resolve_and_force_all_but_regions; use middle::typeck::infer::resolve_type; -use util::ppaux::{note_and_explain_region, ty_to_str, - region_to_str}; +use util::ppaux::{note_and_explain_region, ty_to_str, region_to_str}; use middle::pat_util; +use core::result; +use core::uint; use syntax::ast::{ManagedSigil, OwnedSigil, BorrowedSigil}; use syntax::ast::{def_arg, def_binding, def_local, def_self, def_upvar}; use syntax::ast; @@ -71,12 +74,12 @@ fn encl_region_of_def(fcx: @mut FnCtxt, def: ast::def) -> ty::Region { } } -pub impl Rcx { - fn tcx(&self) -> ty::ctxt { +impl Rcx { + pub fn tcx(&self) -> ty::ctxt { self.fcx.ccx.tcx } - fn resolve_type(&mut self, unresolved_ty: ty::t) -> ty::t { + pub fn resolve_type(&mut self, unresolved_ty: ty::t) -> ty::t { /*! * Try to resolve the type for the given node, returning * t_err if an error results. Note that we never care @@ -113,32 +116,12 @@ pub impl Rcx { } /// Try to resolve the type for the given node. - fn resolve_node_type(@mut self, id: ast::node_id) -> ty::t { + pub fn resolve_node_type(@mut self, id: ast::node_id) -> ty::t { self.resolve_type(self.fcx.node_ty(id)) } /// Try to resolve the type for the given node. - #[config(stage0)] - fn resolve_expr_type_adjusted(@mut self, expr: @ast::expr) -> ty::t { - let ty_unadjusted = self.resolve_node_type(expr.id); - if ty::type_is_error(ty_unadjusted) || ty::type_is_bot(ty_unadjusted) { - ty_unadjusted - } else { - let tcx = self.fcx.tcx(); - let adjustments = self.fcx.inh.adjustments; - match adjustments.find_copy(&expr.id) { - None => ty_unadjusted, - Some(adjustment) => { - ty::adjust_ty(tcx, expr.span, ty_unadjusted, - Some(adjustment)) - } - } - } - } - - /// Try to resolve the type for the given node. - #[config(not(stage0))] - fn resolve_expr_type_adjusted(@mut self, expr: @ast::expr) -> ty::t { + pub fn resolve_expr_type_adjusted(@mut self, expr: @ast::expr) -> ty::t { let ty_unadjusted = self.resolve_node_type(expr.id); if ty::type_is_error(ty_unadjusted) || ty::type_is_bot(ty_unadjusted) { ty_unadjusted @@ -273,8 +256,8 @@ fn visit_expr(expr: @ast::expr, rcx: @mut Rcx, v: rvt) { ast::expr_unary(*) if has_method_map => { tcx.region_maps.record_cleanup_scope(expr.id); } - ast::expr_binary(ast::and, lhs, rhs) | - ast::expr_binary(ast::or, lhs, rhs) => { + ast::expr_binary(_, ast::and, lhs, rhs) | + ast::expr_binary(_, ast::or, lhs, rhs) => { tcx.region_maps.record_cleanup_scope(lhs.id); tcx.region_maps.record_cleanup_scope(rhs.id); } @@ -323,36 +306,36 @@ fn visit_expr(expr: @ast::expr, rcx: @mut Rcx, v: rvt) { match expr.node { ast::expr_call(callee, ref args, _) => { - constrain_callee(rcx, expr, callee); - constrain_call(rcx, expr, None, *args, false); + constrain_callee(rcx, callee.id, expr, callee); + constrain_call(rcx, callee.id, expr, None, *args, false); } - ast::expr_method_call(arg0, _, _, ref args, _) => { - constrain_call(rcx, expr, Some(arg0), *args, false); + ast::expr_method_call(callee_id, arg0, _, _, ref args, _) => { + constrain_call(rcx, callee_id, expr, Some(arg0), *args, false); } - ast::expr_index(lhs, rhs) | - ast::expr_assign_op(_, lhs, rhs) | - ast::expr_binary(_, lhs, rhs) if has_method_map => { + ast::expr_index(callee_id, lhs, rhs) | + ast::expr_assign_op(callee_id, _, lhs, rhs) | + ast::expr_binary(callee_id, _, lhs, rhs) if has_method_map => { // As `expr_method_call`, but the call is via an // overloaded op. Note that we (sadly) currently use an // implicit "by ref" sort of passing style here. This // should be converted to an adjustment! - constrain_call(rcx, expr, Some(lhs), [rhs], true); + constrain_call(rcx, callee_id, expr, Some(lhs), [rhs], true); } - ast::expr_unary(_, lhs) if has_method_map => { + ast::expr_unary(callee_id, _, lhs) if has_method_map => { // As above. - constrain_call(rcx, expr, Some(lhs), [], true); + constrain_call(rcx, callee_id, expr, Some(lhs), [], true); } - ast::expr_unary(ast::deref, base) => { + ast::expr_unary(_, ast::deref, base) => { // For *a, the lifetime of a must enclose the deref let base_ty = rcx.resolve_node_type(base.id); constrain_derefs(rcx, expr, 1, base_ty); } - ast::expr_index(vec_expr, _) => { + ast::expr_index(_, vec_expr, _) => { // For a[b], the lifetime of a must enclose the deref let vec_type = rcx.resolve_expr_type_adjusted(vec_expr); constrain_index(rcx, expr, vec_type); @@ -421,6 +404,7 @@ fn visit_expr(expr: @ast::expr, rcx: @mut Rcx, v: rvt) { } fn constrain_callee(rcx: @mut Rcx, + callee_id: ast::node_id, call_expr: @ast::expr, callee_expr: @ast::expr) { @@ -428,7 +412,7 @@ fn constrain_callee(rcx: @mut Rcx, let call_region = ty::re_scope(call_expr.id); - let callee_ty = rcx.resolve_node_type(call_expr.callee_id); + let callee_ty = rcx.resolve_node_type(callee_id); match ty::get(callee_ty).sty { ty::ty_bare_fn(*) => { } ty::ty_closure(ref closure_ty) => { @@ -461,6 +445,7 @@ fn constrain_callee(rcx: @mut Rcx, fn constrain_call(rcx: @mut Rcx, // might be expr_call, expr_method_call, or an overloaded // operator + callee_id: ast::node_id, call_expr: @ast::expr, receiver: Option<@ast::expr>, arg_exprs: &[@ast::expr], @@ -474,7 +459,7 @@ fn constrain_call(rcx: @mut Rcx, let tcx = rcx.fcx.tcx(); debug!("constrain_call(call_expr=%s, implicitly_ref_args=%?)", call_expr.repr(tcx), implicitly_ref_args); - let callee_ty = rcx.resolve_node_type(call_expr.callee_id); + let callee_ty = rcx.resolve_node_type(callee_id); let fn_sig = ty::ty_fn_sig(callee_ty); // `callee_region` is the scope representing the time in which the @@ -798,6 +783,8 @@ pub mod guarantor { * but more special purpose. */ + use core::prelude::*; + use middle::typeck::check::regionck::{Rcx, infallibly_mk_subr}; use middle::typeck::check::regionck::mk_subregion_due_to_derefence; use middle::ty; @@ -805,6 +792,8 @@ pub mod guarantor { use syntax::codemap::span; use util::ppaux::{ty_to_str}; + use core::uint; + pub fn for_addr_of(rcx: @mut Rcx, expr: @ast::expr, base: @ast::expr) { /*! * Computes the guarantor for an expression `&base` and then @@ -977,14 +966,14 @@ pub mod guarantor { debug!("guarantor(expr=%s)", rcx.fcx.expr_to_str(expr)); match expr.node { - ast::expr_unary(ast::deref, b) => { + ast::expr_unary(_, ast::deref, b) => { let cat = categorize(rcx, b); guarantor_of_deref(&cat) } ast::expr_field(b, _, _) => { categorize(rcx, b).guarantor } - ast::expr_index(b, _) => { + ast::expr_index(_, b, _) => { let cat = categorize(rcx, b); guarantor_of_deref(&cat) } diff --git a/src/librustc/middle/typeck/check/regionmanip.rs b/src/librustc/middle/typeck/check/regionmanip.rs index 87b105e3c7d4d..c1b33d317f1e3 100644 --- a/src/librustc/middle/typeck/check/regionmanip.rs +++ b/src/librustc/middle/typeck/check/regionmanip.rs @@ -10,6 +10,8 @@ // #[warn(deprecated_mode)]; +use core::prelude::*; + use middle::ty; use middle::typeck::isr_alist; @@ -17,7 +19,7 @@ use util::common::indenter; use util::ppaux::region_to_str; use util::ppaux; -use std::list::Cons; +use extra::list::Cons; // Helper functions related to manipulating region types. diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index 2e2b4550f6331..4bf40d1c18eec 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use middle::resolve::Impl; use middle::ty::param_ty; use middle::ty; @@ -24,6 +26,8 @@ use util::ppaux::tys_to_str; use util::ppaux; use core::hashmap::HashSet; +use core::result; +use core::uint; use syntax::ast; use syntax::ast_util; use syntax::codemap::span; @@ -61,8 +65,8 @@ pub struct VtableContext { infcx: @mut infer::InferCtxt } -pub impl VtableContext { - fn tcx(&const self) -> ty::ctxt { self.ccx.tcx } +impl VtableContext { + pub fn tcx(&const self) -> ty::ctxt { self.ccx.tcx } } fn has_trait_bounds(type_param_defs: &[ty::TypeParameterDef]) -> bool { @@ -84,7 +88,8 @@ fn lookup_vtables(vcx: &VtableContext, let _i = indenter(); let tcx = vcx.tcx(); - let mut result = ~[], i = 0u; + let mut result = ~[]; + let mut i = 0u; for substs.tps.each |ty| { // ty is the value supplied for the type parameter A... @@ -508,19 +513,16 @@ pub fn early_resolve_expr(ex: @ast::expr, } // Must resolve bounds on methods with bounded params - ast::expr_binary(*) | - ast::expr_unary(*) | ast::expr_assign_op(*) | - ast::expr_index(*) | ast::expr_method_call(*) => { + ast::expr_binary(callee_id, _, _, _) | + ast::expr_unary(callee_id, _, _) | + ast::expr_assign_op(callee_id, _, _, _) | + ast::expr_index(callee_id, _, _) | + ast::expr_method_call(callee_id, _, _, _, _, _) => { match ty::method_call_type_param_defs(cx.tcx, fcx.inh.method_map, ex.id) { Some(type_param_defs) => { debug!("vtable resolution on parameter bounds for method call %s", ex.repr(fcx.tcx())); if has_trait_bounds(*type_param_defs) { - let callee_id = match ex.node { - ast::expr_field(_, _, _) => ex.id, - _ => ex.callee_id - }; - let substs = fcx.node_ty_substs(callee_id); let vcx = VtableContext { ccx: fcx.ccx, infcx: fcx.infcx() }; let vtbls = lookup_vtables(&vcx, &location_info_for_expr(ex), diff --git a/src/librustc/middle/typeck/check/writeback.rs b/src/librustc/middle/typeck/check/writeback.rs index 394d00bef2d44..68f9a43d6e67b 100644 --- a/src/librustc/middle/typeck/check/writeback.rs +++ b/src/librustc/middle/typeck/check/writeback.rs @@ -12,6 +12,8 @@ // unresolved type variables and replaces "ty_var" types with their // substitutions. +use core::prelude::*; + use middle::pat_util; use middle::ty; use middle::typeck::check::{FnCtxt, SelfInfo}; @@ -105,7 +107,8 @@ fn resolve_vtable_map_entry(fcx: @mut FnCtxt, sp: span, id: ast::node_id) { fn resolve_type_vars_for_node(wbcx: @mut WbCtxt, sp: span, id: ast::node_id) -> Option { - let fcx = wbcx.fcx, tcx = fcx.ccx.tcx; + let fcx = wbcx.fcx; + let tcx = fcx.ccx.tcx; // Resolve any borrowings for the node with id `id` match fcx.inh.adjustments.find(&id) { @@ -215,10 +218,16 @@ fn visit_expr(e: @ast::expr, wbcx: @mut WbCtxt, v: wb_vt) { } resolve_type_vars_for_node(wbcx, e.span, e.id); + resolve_method_map_entry(wbcx.fcx, e.span, e.id); - resolve_method_map_entry(wbcx.fcx, e.span, e.callee_id); + for e.get_callee_id().each |callee_id| { + resolve_method_map_entry(wbcx.fcx, e.span, *callee_id); + } + resolve_vtable_map_entry(wbcx.fcx, e.span, e.id); - resolve_vtable_map_entry(wbcx.fcx, e.span, e.callee_id); + for e.get_callee_id().each |callee_id| { + resolve_vtable_map_entry(wbcx.fcx, e.span, *callee_id); + } match e.node { ast::expr_fn_block(ref decl, _) => { @@ -227,14 +236,16 @@ fn visit_expr(e: @ast::expr, wbcx: @mut WbCtxt, v: wb_vt) { } } - ast::expr_binary(*) | ast::expr_unary(*) | ast::expr_assign_op(*) | - ast::expr_index(*) => { - maybe_resolve_type_vars_for_node(wbcx, e.span, e.callee_id); + ast::expr_binary(callee_id, _, _, _) | + ast::expr_unary(callee_id, _, _) | + ast::expr_assign_op(callee_id, _, _, _) | + ast::expr_index(callee_id, _, _) => { + maybe_resolve_type_vars_for_node(wbcx, e.span, callee_id); } - ast::expr_method_call(*) => { + ast::expr_method_call(callee_id, _, _, _, _, _) => { // We must always have written in a callee ID type for these. - resolve_type_vars_for_node(wbcx, e.span, e.callee_id); + resolve_type_vars_for_node(wbcx, e.span, callee_id); } _ => () diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index 311aa551601dc..9d25430d80b72 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -14,6 +14,7 @@ // has at most one implementation for each type. Then we build a mapping from // each trait in the system to its implementations. +use core::prelude::*; use driver; use metadata::csearch::{each_path, get_impl_trait}; @@ -53,9 +54,11 @@ use syntax::visit::{Visitor, SimpleVisitor}; use syntax::visit::{visit_mod}; use util::ppaux::ty_to_str; -use core::result::Ok; use core::hashmap::{HashMap, HashSet}; +use core::old_iter; +use core::result::Ok; use core::uint; +use core::vec; pub struct UniversalQuantificationResult { monotype: t, @@ -143,7 +146,7 @@ pub fn get_base_type_def_id(inference_context: @mut InferCtxt, } _ => { fail!("get_base_type() returned a type that wasn't an \ - enum, class, or trait"); + enum, struct, or trait"); } } } @@ -196,8 +199,8 @@ pub struct CoherenceChecker { base_type_def_ids: @mut HashMap, } -pub impl CoherenceChecker { - fn check_coherence(self, crate: @crate) { +impl CoherenceChecker { + pub fn check_coherence(self, crate: @crate) { // Check implementations and traits. This populates the tables // containing the inherent methods and extension methods. It also // builds up the trait inheritance table. @@ -236,8 +239,9 @@ pub impl CoherenceChecker { self.populate_destructor_table(); } - fn check_implementation(&self, - item: @item, associated_traits: ~[@trait_ref]) { + pub fn check_implementation(&self, + item: @item, + associated_traits: ~[@trait_ref]) { let tcx = self.crate_context.tcx; let self_type = ty::lookup_item_type(tcx, local_def(item.id)); @@ -305,10 +309,11 @@ pub impl CoherenceChecker { implementation = self.create_impl_from_item(item); } - Some(copy existing_implementation) => { + Some(existing_implementation) => { implementation = existing_implementation; } } + self.add_inherent_method(base_type_def_id, implementation); } @@ -322,9 +327,9 @@ pub impl CoherenceChecker { // Creates default method IDs and performs type substitutions for an impl // and trait pair. Then, for each provided method in the trait, inserts a // `ProvidedMethodInfo` instance into the `provided_method_sources` map. - fn instantiate_default_methods(&self, - impl_id: ast::node_id, - trait_ref: &ty::TraitRef) { + pub fn instantiate_default_methods(&self, + impl_id: ast::node_id, + trait_ref: &ty::TraitRef) { let tcx = self.crate_context.tcx; debug!("instantiate_default_methods(impl_id=%?, trait_ref=%s)", impl_id, trait_ref.repr(tcx)); @@ -413,8 +418,9 @@ pub impl CoherenceChecker { } } - fn add_inherent_method(&self, - base_def_id: def_id, implementation: @Impl) { + pub fn add_inherent_method(&self, + base_def_id: def_id, + implementation: @Impl) { let implementation_list; match self.crate_context.coherence_info.inherent_methods .find(&base_def_id) { @@ -429,9 +435,11 @@ pub impl CoherenceChecker { } implementation_list.push(implementation); + + ty::add_base_impl(self.crate_context.tcx, base_def_id, implementation); } - fn add_trait_method(&self, trait_id: def_id, implementation: @Impl) { + pub fn add_trait_method(&self, trait_id: def_id, implementation: @Impl) { let implementation_list; match self.crate_context.coherence_info.extension_methods .find(&trait_id) { @@ -448,15 +456,14 @@ pub impl CoherenceChecker { implementation_list.push(implementation); } - fn check_implementation_coherence(&self) { + pub fn check_implementation_coherence(&self) { let coherence_info = self.crate_context.coherence_info; for coherence_info.extension_methods.each_key |&trait_id| { self.check_implementation_coherence_of(trait_id); } } - fn check_implementation_coherence_of(&self, trait_def_id: def_id) { - + pub fn check_implementation_coherence_of(&self, trait_def_id: def_id) { // Unify pairs of polytypes. do self.iter_impls_of_trait(trait_def_id) |a| { let implementation_a = a; @@ -489,8 +496,10 @@ pub impl CoherenceChecker { // Adds an impl of trait trait_t for self type self_t; that impl // is the_impl - fn add_impl_for_trait(&self, - trait_t: def_id, self_t: t, the_impl: @Impl) { + pub fn add_impl_for_trait(&self, + trait_t: def_id, + self_t: t, + the_impl: @Impl) { debug!("Adding impl %? of %? for %s", the_impl.did, trait_t, ty_to_str(self.crate_context.tcx, self_t)); @@ -506,7 +515,7 @@ pub impl CoherenceChecker { } } - fn iter_impls_of_trait(&self, trait_def_id: def_id, f: &fn(@Impl)) { + pub fn iter_impls_of_trait(&self, trait_def_id: def_id, f: &fn(@Impl)) { let coherence_info = self.crate_context.coherence_info; let extension_methods = &*coherence_info.extension_methods; @@ -524,30 +533,10 @@ pub impl CoherenceChecker { } } - #[cfg(stage0)] - fn each_provided_trait_method(&self, - trait_did: ast::def_id, - f: &fn(@ty::Method) -> bool) { - // Make a list of all the names of the provided methods. - // XXX: This is horrible. - let mut provided_method_idents = HashSet::new(); - let tcx = self.crate_context.tcx; - for ty::provided_trait_methods(tcx, trait_did).each |ident| { - provided_method_idents.insert(*ident); - } - - for ty::trait_methods(tcx, trait_did).each |&method| { - if provided_method_idents.contains(&method.ident) { - if !f(method) { - break; - } - } - } - } - #[cfg(not(stage0))] - fn each_provided_trait_method(&self, - trait_did: ast::def_id, - f: &fn(x: @ty::Method) -> bool) -> bool { + pub fn each_provided_trait_method(&self, + trait_did: ast::def_id, + f: &fn(x: @ty::Method) -> bool) + -> bool { // Make a list of all the names of the provided methods. // XXX: This is horrible. let mut provided_method_idents = HashSet::new(); @@ -566,9 +555,10 @@ pub impl CoherenceChecker { return true; } - fn polytypes_unify(&self, polytype_a: ty_param_bounds_and_ty, - polytype_b: ty_param_bounds_and_ty) - -> bool { + pub fn polytypes_unify(&self, + polytype_a: ty_param_bounds_and_ty, + polytype_b: ty_param_bounds_and_ty) + -> bool { let universally_quantified_a = self.universally_quantify_polytype(polytype_a); let universally_quantified_b = @@ -582,8 +572,9 @@ pub impl CoherenceChecker { // Converts a polytype to a monotype by replacing all parameters with // type variables. Returns the monotype and the type variables created. - fn universally_quantify_polytype(&self, polytype: ty_param_bounds_and_ty) - -> UniversalQuantificationResult { + pub fn universally_quantify_polytype(&self, + polytype: ty_param_bounds_and_ty) + -> UniversalQuantificationResult { // NDM--this span is bogus. let self_region = polytype.generics.region_param.map( @@ -612,11 +603,12 @@ pub impl CoherenceChecker { } } - fn can_unify_universally_quantified<'a> - (&self, - a: &'a UniversalQuantificationResult, - b: &'a UniversalQuantificationResult) - -> bool { + pub fn can_unify_universally_quantified<'a>(&self, + a: &'a + UniversalQuantificationResult, + b: &'a + UniversalQuantificationResult) + -> bool { let mut might_unify = true; let _ = do self.inference_context.probe { let result = self.inference_context.sub(true, dummy_sp()) @@ -660,13 +652,13 @@ pub impl CoherenceChecker { might_unify } - fn get_self_type_for_implementation(&self, implementation: @Impl) - -> ty_param_bounds_and_ty { + pub fn get_self_type_for_implementation(&self, implementation: @Impl) + -> ty_param_bounds_and_ty { return self.crate_context.tcx.tcache.get_copy(&implementation.did); } // Privileged scope checking - fn check_privileged_scopes(self, crate: @crate) { + pub fn check_privileged_scopes(self, crate: @crate) { visit_crate(crate, (), mk_vt(@Visitor { visit_item: |item, _context, visitor| { match item.node { @@ -716,7 +708,7 @@ pub impl CoherenceChecker { })); } - fn trait_ref_to_trait_def_id(&self, trait_ref: @trait_ref) -> def_id { + pub fn trait_ref_to_trait_def_id(&self, trait_ref: @trait_ref) -> def_id { let def_map = self.crate_context.tcx.def_map; let trait_def = def_map.get_copy(&trait_ref.ref_id); let trait_id = def_id_of_def(trait_def); @@ -725,10 +717,13 @@ pub impl CoherenceChecker { // This check doesn't really have anything to do with coherence. It's // here for historical reasons - fn please_check_that_trait_methods_are_implemented(&self, - all_methods: &mut ~[@MethodInfo], - trait_did: def_id, - trait_ref_span: span) { + pub fn please_check_that_trait_methods_are_implemented(&self, + all_methods: + &mut + ~[@MethodInfo], + trait_did: def_id, + trait_ref_span: + span) { let tcx = self.crate_context.tcx; @@ -792,7 +787,7 @@ pub impl CoherenceChecker { } // Converts an implementation in the AST to an Impl structure. - fn create_impl_from_item(&self, item: @item) -> @Impl { + pub fn create_impl_from_item(&self, item: @item) -> @Impl { fn add_provided_methods(all_methods: &mut ~[@MethodInfo], all_provided_methods: &mut ~[@ProvidedMethodInfo], sess: driver::session::Session) { @@ -862,8 +857,8 @@ pub impl CoherenceChecker { } } - fn span_of_impl(&self, implementation: @Impl) -> span { - assert!(implementation.did.crate == local_crate); + pub fn span_of_impl(&self, implementation: @Impl) -> span { + assert_eq!(implementation.did.crate, local_crate); match self.crate_context.tcx.items.find(&implementation.did.node) { Some(&node_item(item, _)) => { return item.span; @@ -877,9 +872,10 @@ pub impl CoherenceChecker { // External crate handling - fn add_impls_for_module(&self, impls_seen: &mut HashSet, - crate_store: @mut CStore, - module_def_id: def_id) { + pub fn add_impls_for_module(&self, + impls_seen: &mut HashSet, + crate_store: @mut CStore, + module_def_id: def_id) { let implementations = get_impls_for_mod(crate_store, module_def_id, None); @@ -952,8 +948,8 @@ pub impl CoherenceChecker { } } - fn add_default_methods_for_external_trait(&self, - trait_def_id: ast::def_id) { + pub fn add_default_methods_for_external_trait(&self, + trait_def_id: ast::def_id) { let tcx = self.crate_context.tcx; let pmm = tcx.provided_methods; @@ -986,7 +982,7 @@ pub impl CoherenceChecker { // Adds implementations and traits from external crates to the coherence // info. - fn add_external_crates(&self) { + pub fn add_external_crates(&self) { let mut impls_seen = HashSet::new(); let crate_store = self.crate_context.tcx.sess.cstore; @@ -996,7 +992,7 @@ pub impl CoherenceChecker { def_id { crate: crate_number, node: 0 }); - for each_path(crate_store, crate_number) |_p, def_like| { + for each_path(crate_store, crate_number) |_, def_like, _| { match def_like { dl_def(def_mod(def_id)) => { self.add_impls_for_module(&mut impls_seen, @@ -1019,7 +1015,7 @@ pub impl CoherenceChecker { // Destructors // - fn populate_destructor_table(&self) { + pub fn populate_destructor_table(&self) { let coherence_info = self.crate_context.coherence_info; let tcx = self.crate_context.tcx; let drop_trait = tcx.lang_items.drop_trait(); @@ -1068,13 +1064,12 @@ pub impl CoherenceChecker { } } -fn subst_receiver_types_in_method_ty( - tcx: ty::ctxt, - impl_id: ast::node_id, - trait_ref: &ty::TraitRef, - new_def_id: ast::def_id, - method: &ty::Method) -> ty::Method -{ +fn subst_receiver_types_in_method_ty(tcx: ty::ctxt, + impl_id: ast::node_id, + trait_ref: &ty::TraitRef, + new_def_id: ast::def_id, + method: &ty::Method) + -> ty::Method { /*! * Substitutes the values for the receiver's type parameters * that are found in method, leaving the method's type parameters diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index 6c7f73177fadf..a2c1211c5c46e 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -30,6 +30,8 @@ are represented as `ty_param()` instances. */ +use core::prelude::*; + use metadata::csearch; use middle::ty::{substs, ty_param_bounds_and_ty}; use middle::ty; @@ -45,6 +47,8 @@ use util::common::pluralize; use util::ppaux; use util::ppaux::UserString; +use core::result; +use core::vec; use syntax::abi::AbiSet; use syntax::ast::{RegionTyParamBound, TraitTyParamBound}; use syntax::ast; diff --git a/src/librustc/middle/typeck/infer/coercion.rs b/src/librustc/middle/typeck/infer/coercion.rs index 3620b609edf3b..47f49ade336d1 100644 --- a/src/librustc/middle/typeck/infer/coercion.rs +++ b/src/librustc/middle/typeck/infer/coercion.rs @@ -64,6 +64,8 @@ we may want to adjust precisely when coercions occur. */ +use core::prelude::*; + use middle::ty::{AutoPtr, AutoBorrowVec, AutoBorrowFn}; use middle::ty::{AutoDerefRef}; use middle::ty::{vstore_slice, vstore_box, vstore_uniq}; @@ -84,8 +86,8 @@ use syntax::ast; // function. pub struct Coerce(CombineFields); -pub impl Coerce { - fn tys(&self, a: ty::t, b: ty::t) -> CoerceResult { +impl Coerce { + pub fn tys(&self, a: ty::t, b: ty::t) -> CoerceResult { debug!("Coerce.tys(%s => %s)", a.inf_str(self.infcx), b.inf_str(self.infcx)); @@ -147,17 +149,17 @@ pub impl Coerce { } } - fn subtype(&self, a: ty::t, b: ty::t) -> CoerceResult { + pub fn subtype(&self, a: ty::t, b: ty::t) -> CoerceResult { match Sub(**self).tys(a, b) { Ok(_) => Ok(None), // No coercion required. Err(ref e) => Err(*e) } } - fn unpack_actual_value(&self, - a: ty::t, - f: &fn(&ty::sty) -> CoerceResult) -> CoerceResult - { + pub fn unpack_actual_value(&self, + a: ty::t, + f: &fn(&ty::sty) -> CoerceResult) + -> CoerceResult { match resolve_type(self.infcx, a, try_resolve_tvar_shallow) { Ok(t) => { f(&ty::get(t).sty) @@ -171,12 +173,12 @@ pub impl Coerce { } } - fn coerce_borrowed_pointer(&self, - a: ty::t, - sty_a: &ty::sty, - b: ty::t, - mt_b: ty::mt) -> CoerceResult - { + pub fn coerce_borrowed_pointer(&self, + a: ty::t, + sty_a: &ty::sty, + b: ty::t, + mt_b: ty::mt) + -> CoerceResult { debug!("coerce_borrowed_pointer(a=%s, sty_a=%?, b=%s, mt_b=%?)", a.inf_str(self.infcx), sty_a, b.inf_str(self.infcx), mt_b); @@ -209,11 +211,11 @@ pub impl Coerce { }))) } - fn coerce_borrowed_string(&self, - a: ty::t, - sty_a: &ty::sty, - b: ty::t) -> CoerceResult - { + pub fn coerce_borrowed_string(&self, + a: ty::t, + sty_a: &ty::sty, + b: ty::t) + -> CoerceResult { debug!("coerce_borrowed_string(a=%s, sty_a=%?, b=%s)", a.inf_str(self.infcx), sty_a, b.inf_str(self.infcx)); @@ -235,12 +237,12 @@ pub impl Coerce { }))) } - fn coerce_borrowed_vector(&self, - a: ty::t, - sty_a: &ty::sty, - b: ty::t, - mt_b: ty::mt) -> CoerceResult - { + pub fn coerce_borrowed_vector(&self, + a: ty::t, + sty_a: &ty::sty, + b: ty::t, + mt_b: ty::mt) + -> CoerceResult { debug!("coerce_borrowed_vector(a=%s, sty_a=%?, b=%s)", a.inf_str(self.infcx), sty_a, b.inf_str(self.infcx)); @@ -264,11 +266,11 @@ pub impl Coerce { }))) } - fn coerce_borrowed_fn(&self, - a: ty::t, - sty_a: &ty::sty, - b: ty::t) -> CoerceResult - { + pub fn coerce_borrowed_fn(&self, + a: ty::t, + sty_a: &ty::sty, + b: ty::t) + -> CoerceResult { debug!("coerce_borrowed_fn(a=%s, sty_a=%?, b=%s)", a.inf_str(self.infcx), sty_a, b.inf_str(self.infcx)); @@ -300,22 +302,22 @@ pub impl Coerce { }))) } - fn coerce_from_bare_fn(&self, - a: ty::t, - fn_ty_a: &ty::BareFnTy, - b: ty::t) -> CoerceResult - { + pub fn coerce_from_bare_fn(&self, + a: ty::t, + fn_ty_a: &ty::BareFnTy, + b: ty::t) + -> CoerceResult { do self.unpack_actual_value(b) |sty_b| { self.coerce_from_bare_fn_post_unpack(a, fn_ty_a, b, sty_b) } } - fn coerce_from_bare_fn_post_unpack(&self, - a: ty::t, - fn_ty_a: &ty::BareFnTy, - b: ty::t, - sty_b: &ty::sty) -> CoerceResult - { + pub fn coerce_from_bare_fn_post_unpack(&self, + a: ty::t, + fn_ty_a: &ty::BareFnTy, + b: ty::t, + sty_b: &ty::sty) + -> CoerceResult { /*! * * Attempts to coerce from a bare Rust function (`extern @@ -344,12 +346,12 @@ pub impl Coerce { Ok(Some(adj)) } - fn coerce_unsafe_ptr(&self, - a: ty::t, - sty_a: &ty::sty, - b: ty::t, - mt_b: ty::mt) -> CoerceResult - { + pub fn coerce_unsafe_ptr(&self, + a: ty::t, + sty_a: &ty::sty, + b: ty::t, + mt_b: ty::mt) + -> CoerceResult { debug!("coerce_unsafe_ptr(a=%s, sty_a=%?, b=%s)", a.inf_str(self.infcx), sty_a, b.inf_str(self.infcx)); diff --git a/src/librustc/middle/typeck/infer/combine.rs b/src/librustc/middle/typeck/infer/combine.rs index 3c337d17f8684..f0fe48918073e 100644 --- a/src/librustc/middle/typeck/infer/combine.rs +++ b/src/librustc/middle/typeck/infer/combine.rs @@ -54,6 +54,8 @@ // terms of error reporting, although we do not do that properly right // now. +use core::prelude::*; + use middle::ty::{FloatVar, FnSig, IntVar, TyVar}; use middle::ty::{IntType, UintType, substs}; use middle::ty::{BuiltinBounds}; @@ -62,10 +64,11 @@ use middle::typeck::infer::glb::Glb; use middle::typeck::infer::lub::Lub; use middle::typeck::infer::sub::Sub; use middle::typeck::infer::to_str::InferStr; -use middle::typeck::infer::{cres, InferCtxt, ures, IntType, UintType}; +use middle::typeck::infer::{cres, InferCtxt, ures}; use util::common::indent; use core::result::{iter_vec2, map_vec2}; +use core::vec; use syntax::ast::{Onceness, purity}; use syntax::ast; use syntax::opt_vec; @@ -286,7 +289,9 @@ pub fn super_self_tys( // I think it should never happen that we unify two substs and // one of them has a self_ty and one doesn't...? I could be // wrong about this. - Err(ty::terr_self_substs) + this.infcx().tcx.sess.bug( + fmt!("substitution a had a self_ty and substitution b didn't, \ + or vice versa")); } } } diff --git a/src/librustc/middle/typeck/infer/glb.rs b/src/librustc/middle/typeck/infer/glb.rs index 9ade6de6cf4fd..700a78699b1e2 100644 --- a/src/librustc/middle/typeck/infer/glb.rs +++ b/src/librustc/middle/typeck/infer/glb.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use middle::ty::{BuiltinBounds}; use middle::ty::RegionVid; use middle::ty; @@ -28,7 +30,7 @@ use syntax::codemap::span; use util::common::{indent, indenter}; use util::ppaux::mt_to_str; -use std::list; +use extra::list; pub struct Glb(CombineFields); // "greatest lower bound" (common subtype) @@ -218,7 +220,9 @@ impl Combine for Glb { let tainted = this.infcx.region_vars.tainted(snapshot, r0); - let mut a_r = None, b_r = None, only_new_vars = true; + let mut a_r = None; + let mut b_r = None; + let mut only_new_vars = true; for tainted.each |r| { if is_var_in_set(a_vars, *r) { if a_r.is_some() { diff --git a/src/librustc/middle/typeck/infer/lattice.rs b/src/librustc/middle/typeck/infer/lattice.rs index 3c48e09c05747..820bb2f86b04c 100644 --- a/src/librustc/middle/typeck/infer/lattice.rs +++ b/src/librustc/middle/typeck/infer/lattice.rs @@ -32,6 +32,8 @@ * a lattice. */ +use core::prelude::*; + use middle::ty::{RegionVid, TyVar, Vid}; use middle::ty; use middle::typeck::isr_alist; @@ -41,12 +43,10 @@ use middle::typeck::infer::glb::Glb; use middle::typeck::infer::lub::Lub; use middle::typeck::infer::unify::*; use middle::typeck::infer::sub::Sub; -use middle::typeck::infer::lub::Lub; -use middle::typeck::infer::glb::Glb; use middle::typeck::infer::to_str::InferStr; use util::common::indenter; -use std::list; +use extra::list; pub trait LatticeValue { fn sub(cf: &CombineFields, a: &Self, b: &Self) -> ures; @@ -71,13 +71,15 @@ impl LatticeValue for ty::t { } } -pub impl CombineFields { - fn var_sub_var>>( - &self, - a_id: V, - b_id: V) -> ures - { +impl CombineFields { + pub fn var_sub_var>>(&self, + a_id: + V, + b_id: + V) + -> + ures { /*! * * Make one variable a subtype of another variable. This is a @@ -125,12 +127,12 @@ pub impl CombineFields { } /// make variable a subtype of T - fn var_sub_t>>( - &self, - a_id: V, - b: T) -> ures - { + pub fn var_sub_t>>(&self, + a_id: V, + b: T) + -> ures + { /*! * * Make a variable (`a_id`) a subtype of the concrete type `b` */ @@ -149,12 +151,12 @@ pub impl CombineFields { a_id, a_bounds, b_bounds, node_a.rank) } - fn t_sub_var>>( - &self, - a: T, - b_id: V) -> ures - { + pub fn t_sub_var>>(&self, + a: T, + b_id: V) + -> ures + { /*! * * Make a concrete type (`a`) a subtype of the variable `b_id` */ @@ -173,13 +175,12 @@ pub impl CombineFields { b_id, a_bounds, b_bounds, node_b.rank) } - fn merge_bnd( - &self, - a: &Bound, - b: &Bound, - lattice_op: LatticeOp) - -> cres> - { + pub fn merge_bnd(&self, + a: &Bound, + b: &Bound, + lattice_op: + LatticeOp) + -> cres> { /*! * * Combines two bounds into a more general bound. */ @@ -201,14 +202,14 @@ pub impl CombineFields { } } - fn set_var_to_merged_bounds>>( - &self, - v_id: V, - a: &Bounds, - b: &Bounds, - rank: uint) -> ures - { + pub fn set_var_to_merged_bounds>>( + &self, + v_id: V, + a: &Bounds, + b: &Bounds, + rank: uint) + -> ures { /*! * * Updates the bounds for the variable `v_id` to be the intersection @@ -263,11 +264,10 @@ pub impl CombineFields { uok() } - fn bnds( - &self, - a: &Bound, - b: &Bound) -> ures - { + pub fn bnds(&self, + a: &Bound, + b: &Bound) + -> ures { debug!("bnds(%s <: %s)", a.inf_str(self.infcx), b.inf_str(self.infcx)); let _r = indenter(); @@ -422,7 +422,7 @@ pub fn lattice_vars { match this.infcx().try(|| lattice_dir_op(a_ty, b_ty) ) { diff --git a/src/librustc/middle/typeck/infer/lub.rs b/src/librustc/middle/typeck/infer/lub.rs index 82fd4e3ae6dd6..1a73d5bd36bbb 100644 --- a/src/librustc/middle/typeck/infer/lub.rs +++ b/src/librustc/middle/typeck/infer/lub.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use middle::ty::{BuiltinBounds}; use middle::ty::RegionVid; use middle::ty; @@ -22,7 +24,7 @@ use middle::typeck::isr_alist; use util::common::indent; use util::ppaux::mt_to_str; -use std::list; +use extra::list; use syntax::abi::AbiSet; use syntax::ast; use syntax::ast::{Many, Once, extern_fn, m_const, impure_fn}; @@ -32,10 +34,11 @@ use syntax::codemap::span; pub struct Lub(CombineFields); // least-upper-bound: common supertype -pub impl Lub { - fn bot_ty(&self, b: ty::t) -> cres { Ok(b) } - fn ty_bot(&self, b: ty::t) - -> cres { self.bot_ty(b) } // commutative +impl Lub { + pub fn bot_ty(&self, b: ty::t) -> cres { Ok(b) } + pub fn ty_bot(&self, b: ty::t) -> cres { + self.bot_ty(b) // commutative + } } impl Combine for Lub { diff --git a/src/librustc/middle/typeck/infer/mod.rs b/src/librustc/middle/typeck/infer/mod.rs index 2c42914f4b551..00e5415e0414a 100644 --- a/src/librustc/middle/typeck/infer/mod.rs +++ b/src/librustc/middle/typeck/infer/mod.rs @@ -242,6 +242,8 @@ section on "Type Combining" below for details. */ +use core::prelude::*; + pub use middle::ty::IntVarValue; pub use middle::typeck::infer::resolve::resolve_and_force_all_but_regions; pub use middle::typeck::infer::resolve::{force_all, not_regions}; @@ -265,8 +267,10 @@ use middle::typeck::isr_alist; use util::common::indent; use util::ppaux::{bound_region_to_str, ty_to_str, trait_ref_to_str}; -use std::list::Nil; -use std::smallintmap::SmallIntMap; +use core::result; +use core::vec; +use extra::list::Nil; +use extra::smallintmap::SmallIntMap; use syntax::ast::{m_imm, m_mutbl}; use syntax::ast; use syntax::codemap; @@ -531,24 +535,23 @@ struct Snapshot { region_vars_snapshot: uint, } -pub impl InferCtxt { - fn combine_fields(@mut self, - a_is_expected: bool, - span: span) -> CombineFields { +impl InferCtxt { + pub fn combine_fields(@mut self, a_is_expected: bool, span: span) + -> CombineFields { CombineFields {infcx: self, a_is_expected: a_is_expected, span: span} } - fn sub(@mut self, a_is_expected: bool, span: span) -> Sub { + pub fn sub(@mut self, a_is_expected: bool, span: span) -> Sub { Sub(self.combine_fields(a_is_expected, span)) } - fn in_snapshot(&self) -> bool { + pub fn in_snapshot(&self) -> bool { self.region_vars.in_snapshot() } - fn start_snapshot(&mut self) -> Snapshot { + pub fn start_snapshot(&mut self) -> Snapshot { Snapshot { ty_var_bindings_len: self.ty_var_bindings.bindings.len(), @@ -561,7 +564,7 @@ pub impl InferCtxt { } } - fn rollback_to(&mut self, snapshot: &Snapshot) { + pub fn rollback_to(&mut self, snapshot: &Snapshot) { debug!("rollback!"); rollback_to(&mut self.ty_var_bindings, snapshot.ty_var_bindings_len); @@ -574,7 +577,7 @@ pub impl InferCtxt { } /// Execute `f` and commit the bindings if successful - fn commit(@mut self, f: &fn() -> Result) -> Result { + pub fn commit(@mut self, f: &fn() -> Result) -> Result { assert!(!self.in_snapshot()); debug!("commit()"); @@ -589,7 +592,7 @@ pub impl InferCtxt { } /// Execute `f`, unroll bindings on failure - fn try(@mut self, f: &fn() -> Result) -> Result { + pub fn try(@mut self, f: &fn() -> Result) -> Result { debug!("try()"); do indent { let snapshot = self.start_snapshot(); @@ -603,7 +606,7 @@ pub impl InferCtxt { } /// Execute `f` then unroll any bindings it creates - fn probe(@mut self, f: &fn() -> Result) -> Result { + pub fn probe(@mut self, f: &fn() -> Result) -> Result { debug!("probe()"); do indent { let snapshot = self.start_snapshot(); @@ -624,8 +627,8 @@ fn next_simple_var( return id; } -pub impl InferCtxt { - fn next_ty_var_id(&mut self) -> TyVid { +impl InferCtxt { + pub fn next_ty_var_id(&mut self) -> TyVid { let id = self.ty_var_counter; self.ty_var_counter += 1; { @@ -635,38 +638,40 @@ pub impl InferCtxt { return TyVid(id); } - fn next_ty_var(&mut self) -> ty::t { + pub fn next_ty_var(&mut self) -> ty::t { ty::mk_var(self.tcx, self.next_ty_var_id()) } - fn next_ty_vars(&mut self, n: uint) -> ~[ty::t] { + pub fn next_ty_vars(&mut self, n: uint) -> ~[ty::t] { vec::from_fn(n, |_i| self.next_ty_var()) } - fn next_int_var_id(&mut self) -> IntVid { + pub fn next_int_var_id(&mut self) -> IntVid { IntVid(next_simple_var(&mut self.int_var_counter, &mut self.int_var_bindings)) } - fn next_int_var(&mut self) -> ty::t { + pub fn next_int_var(&mut self) -> ty::t { ty::mk_int_var(self.tcx, self.next_int_var_id()) } - fn next_float_var_id(&mut self) -> FloatVid { + pub fn next_float_var_id(&mut self) -> FloatVid { FloatVid(next_simple_var(&mut self.float_var_counter, &mut self.float_var_bindings)) } - fn next_float_var(&mut self) -> ty::t { + pub fn next_float_var(&mut self) -> ty::t { ty::mk_float_var(self.tcx, self.next_float_var_id()) } - fn next_region_var_nb(&mut self, span: span) -> ty::Region { + pub fn next_region_var_nb(&mut self, span: span) -> ty::Region { ty::re_infer(ty::ReVar(self.region_vars.new_region_var(span))) } - fn next_region_var_with_lb(&mut self, span: span, - lb_region: ty::Region) -> ty::Region { + pub fn next_region_var_with_lb(&mut self, + span: span, + lb_region: ty::Region) + -> ty::Region { let region_var = self.next_region_var_nb(span); // add lb_region as a lower bound on the newly built variable @@ -677,35 +682,36 @@ pub impl InferCtxt { return region_var; } - fn next_region_var(&mut self, span: span, scope_id: ast::node_id) - -> ty::Region { + pub fn next_region_var(&mut self, span: span, scope_id: ast::node_id) + -> ty::Region { self.next_region_var_with_lb(span, ty::re_scope(scope_id)) } - fn resolve_regions(&mut self) { + pub fn resolve_regions(&mut self) { self.region_vars.resolve_regions(); } - fn ty_to_str(@mut self, t: ty::t) -> ~str { + pub fn ty_to_str(@mut self, t: ty::t) -> ~str { ty_to_str(self.tcx, self.resolve_type_vars_if_possible(t)) } - fn trait_ref_to_str(@mut self, t: &ty::TraitRef) -> ~str { + pub fn trait_ref_to_str(@mut self, t: &ty::TraitRef) -> ~str { let t = self.resolve_type_vars_in_trait_ref_if_possible(t); trait_ref_to_str(self.tcx, &t) } - fn resolve_type_vars_if_possible(@mut self, typ: ty::t) -> ty::t { + pub fn resolve_type_vars_if_possible(@mut self, typ: ty::t) -> ty::t { match resolve_type(self, typ, resolve_nested_tvar | resolve_ivar) { result::Ok(new_type) => new_type, result::Err(_) => typ } } - fn resolve_type_vars_in_trait_ref_if_possible(@mut self, - trait_ref: &ty::TraitRef) - -> ty::TraitRef - { + + pub fn resolve_type_vars_in_trait_ref_if_possible(@mut self, + trait_ref: + &ty::TraitRef) + -> ty::TraitRef { // make up a dummy type just to reuse/abuse the resolve machinery let dummy0 = ty::mk_trait(self.tcx, trait_ref.def_id, @@ -728,18 +734,22 @@ pub impl InferCtxt { } } - fn type_error_message_str(@mut self, - sp: span, - mk_msg: &fn(Option<~str>, ~str) -> ~str, - actual_ty: ~str, err: Option<&ty::type_err>) { + pub fn type_error_message_str(@mut self, + sp: span, + mk_msg: &fn(Option<~str>, ~str) -> ~str, + actual_ty: ~str, + err: Option<&ty::type_err>) { self.type_error_message_str_with_expected(sp, mk_msg, None, actual_ty, err) } - fn type_error_message_str_with_expected(@mut self, - sp: span, - mk_msg: &fn(Option<~str>, ~str) -> ~str, - expected_ty: Option, actual_ty: ~str, - err: Option<&ty::type_err>) { + pub fn type_error_message_str_with_expected(@mut self, + sp: span, + mk_msg: + &fn(Option<~str>, ~str) -> + ~str, + expected_ty: Option, + actual_ty: ~str, + err: Option<&ty::type_err>) { debug!("hi! expected_ty = %?, actual_ty = %s", expected_ty, actual_ty); let error_str = err.map_default(~"", |t_err| @@ -762,11 +772,11 @@ pub impl InferCtxt { } } - fn type_error_message(@mut self, - sp: span, - mk_msg: &fn(~str) -> ~str, - actual_ty: ty::t, - err: Option<&ty::type_err>) { + pub fn type_error_message(@mut self, + sp: span, + mk_msg: &fn(~str) -> ~str, + actual_ty: ty::t, + err: Option<&ty::type_err>) { let actual_ty = self.resolve_type_vars_if_possible(actual_ty); // Don't report an error if actual type is ty_err. @@ -777,8 +787,11 @@ pub impl InferCtxt { self.type_error_message_str(sp, |_e, a| { mk_msg(a) }, self.ty_to_str(actual_ty), err); } - fn report_mismatched_types(@mut self, sp: span, e: ty::t, a: ty::t, - err: &ty::type_err) { + pub fn report_mismatched_types(@mut self, + sp: span, + e: ty::t, + a: ty::t, + err: &ty::type_err) { let resolved_expected = self.resolve_type_vars_if_possible(e); let mk_msg = match ty::get(resolved_expected).sty { @@ -795,10 +808,11 @@ pub impl InferCtxt { self.type_error_message(sp, mk_msg, a, Some(err)); } - fn replace_bound_regions_with_fresh_regions(&mut self, - span: span, - fsig: &ty::FnSig) - -> (ty::FnSig, isr_alist) { + pub fn replace_bound_regions_with_fresh_regions(&mut self, + span: span, + fsig: &ty::FnSig) + -> (ty::FnSig, + isr_alist) { let(isr, _, fn_sig) = replace_bound_regions_in_fn_sig(self.tcx, @Nil, None, fsig, |br| { // N.B.: The name of the bound region doesn't have anything to diff --git a/src/librustc/middle/typeck/infer/region_inference.rs b/src/librustc/middle/typeck/infer/region_inference.rs index a5e8b42dee5ac..9d6176af0baba 100644 --- a/src/librustc/middle/typeck/infer/region_inference.rs +++ b/src/librustc/middle/typeck/infer/region_inference.rs @@ -536,6 +536,8 @@ more convincing in the future. */ +use core::prelude::*; + use middle::ty; use middle::ty::{FreeRegion, Region, RegionVid}; use middle::ty::{re_empty, re_static, re_infer, re_free, re_bound}; @@ -544,9 +546,7 @@ use middle::typeck::infer::cres; use util::common::indenter; use util::ppaux::note_and_explain_region; -#[cfg(stage0)] -use core; // NOTE: this can be removed after next snapshot -use core::cell::{Cell, empty_cell}; +use core::cell::Cell; use core::hashmap::{HashMap, HashSet}; use core::to_bytes; use core::uint; @@ -561,33 +561,26 @@ enum Constraint { ConstrainVarSubReg(RegionVid, Region) } -#[cfg(stage0)] -impl to_bytes::IterBytes for Constraint { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - match *self { - ConstrainVarSubVar(ref v0, ref v1) => - to_bytes::iter_bytes_3(&0u8, v0, v1, lsb0, f), - - ConstrainRegSubVar(ref ra, ref va) => - to_bytes::iter_bytes_3(&1u8, ra, va, lsb0, f), - - ConstrainVarSubReg(ref va, ref ra) => - to_bytes::iter_bytes_3(&2u8, va, ra, lsb0, f) - } - } -} -#[cfg(not(stage0))] impl to_bytes::IterBytes for Constraint { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { match *self { - ConstrainVarSubVar(ref v0, ref v1) => - to_bytes::iter_bytes_3(&0u8, v0, v1, lsb0, f), + ConstrainVarSubVar(ref v0, ref v1) => { + 0u8.iter_bytes(lsb0, f) && + v0.iter_bytes(lsb0, f) && + v1.iter_bytes(lsb0, f) + } - ConstrainRegSubVar(ref ra, ref va) => - to_bytes::iter_bytes_3(&1u8, ra, va, lsb0, f), + ConstrainRegSubVar(ref ra, ref va) => { + 1u8.iter_bytes(lsb0, f) && + ra.iter_bytes(lsb0, f) && + va.iter_bytes(lsb0, f) + } - ConstrainVarSubReg(ref va, ref ra) => - to_bytes::iter_bytes_3(&2u8, va, ra, lsb0, f) + ConstrainVarSubReg(ref va, ref ra) => { + 2u8.iter_bytes(lsb0, f) && + va.iter_bytes(lsb0, f) && + ra.iter_bytes(lsb0, f) + } } } } @@ -640,7 +633,7 @@ pub fn RegionVarBindings(tcx: ty::ctxt) -> RegionVarBindings { RegionVarBindings { tcx: tcx, var_spans: ~[], - values: empty_cell(), + values: Cell::new_empty(), constraints: HashMap::new(), lubs: HashMap::new(), glbs: HashMap::new(), @@ -650,12 +643,12 @@ pub fn RegionVarBindings(tcx: ty::ctxt) -> RegionVarBindings { } } -pub impl RegionVarBindings { - fn in_snapshot(&self) -> bool { +impl RegionVarBindings { + pub fn in_snapshot(&self) -> bool { self.undo_log.len() > 0 } - fn start_snapshot(&mut self) -> uint { + pub fn start_snapshot(&mut self) -> uint { debug!("RegionVarBindings: snapshot()=%u", self.undo_log.len()); if self.in_snapshot() { self.undo_log.len() @@ -665,14 +658,14 @@ pub impl RegionVarBindings { } } - fn commit(&mut self) { + pub fn commit(&mut self) { debug!("RegionVarBindings: commit()"); while self.undo_log.len() > 0 { self.undo_log.pop(); } } - fn rollback_to(&mut self, snapshot: uint) { + pub fn rollback_to(&mut self, snapshot: uint) { debug!("RegionVarBindings: rollback_to(%u)", snapshot); while self.undo_log.len() > snapshot { let undo_item = self.undo_log.pop(); @@ -680,7 +673,7 @@ pub impl RegionVarBindings { match undo_item { Snapshot => {} AddVar(vid) => { - assert!(self.var_spans.len() == vid.to_uint() + 1); + assert_eq!(self.var_spans.len(), vid.to_uint() + 1); self.var_spans.pop(); } AddConstraint(ref constraint) => { @@ -696,11 +689,11 @@ pub impl RegionVarBindings { } } - fn num_vars(&mut self) -> uint { + pub fn num_vars(&mut self) -> uint { self.var_spans.len() } - fn new_region_var(&mut self, span: span) -> RegionVid { + pub fn new_region_var(&mut self, span: span) -> RegionVid { let id = self.num_vars(); self.var_spans.push(span); let vid = RegionVid { id: id }; @@ -712,13 +705,13 @@ pub impl RegionVarBindings { return vid; } - fn new_skolemized(&mut self, br: ty::bound_region) -> Region { + pub fn new_skolemized(&mut self, br: ty::bound_region) -> Region { let sc = self.skolemization_count; self.skolemization_count += 1; re_infer(ReSkolemized(sc, br)) } - fn new_bound(&mut self) -> Region { + pub fn new_bound(&mut self) -> Region { // Creates a fresh bound variable for use in GLB computations. // See discussion of GLB computation in the large comment at // the top of this file for more details. @@ -738,7 +731,7 @@ pub impl RegionVarBindings { re_bound(br_fresh(sc)) } - fn add_constraint(&mut self, constraint: Constraint, span: span) { + pub fn add_constraint(&mut self, constraint: Constraint, span: span) { // cannot add constraints once regions are resolved assert!(self.values.is_empty()); @@ -751,10 +744,8 @@ pub impl RegionVarBindings { } } - fn make_subregion(&mut self, - span: span, - sub: Region, - sup: Region) -> cres<()> { + pub fn make_subregion(&mut self, span: span, sub: Region, sup: Region) + -> cres<()> { // cannot add constraints once regions are resolved assert!(self.values.is_empty()); @@ -792,11 +783,8 @@ pub impl RegionVarBindings { } } - fn lub_regions(&mut self, - span: span, - a: Region, - b: Region) - -> cres { + pub fn lub_regions(&mut self, span: span, a: Region, b: Region) + -> cres { // cannot add constraints once regions are resolved assert!(self.values.is_empty()); @@ -818,11 +806,8 @@ pub impl RegionVarBindings { } } - fn glb_regions(&mut self, - span: span, - a: Region, - b: Region) - -> cres { + pub fn glb_regions(&mut self, span: span, a: Region, b: Region) + -> cres { // cannot add constraints once regions are resolved assert!(self.values.is_empty()); @@ -845,7 +830,7 @@ pub impl RegionVarBindings { } } - fn resolve_var(&mut self, rid: RegionVid) -> ty::Region { + pub fn resolve_var(&mut self, rid: RegionVid) -> ty::Region { if self.values.is_empty() { self.tcx.sess.span_bug( self.var_spans[rid.to_uint()], @@ -871,15 +856,15 @@ pub impl RegionVarBindings { } } - fn combine_vars(&mut self, - t: CombineMapType, - a: Region, - b: Region, - span: span, - relate: &fn(this: &mut RegionVarBindings, - old_r: Region, - new_r: Region) -> cres<()>) - -> cres { + pub fn combine_vars(&mut self, + t: CombineMapType, + a: Region, + b: Region, + span: span, + relate: &fn(this: &mut RegionVarBindings, + old_r: Region, + new_r: Region) -> cres<()>) + -> cres { let vars = TwoRegions { a: a, b: b }; let c; { @@ -913,9 +898,8 @@ pub impl RegionVarBindings { } } - fn vars_created_since_snapshot(&mut self, - snapshot: uint) - -> ~[RegionVid] { + pub fn vars_created_since_snapshot(&mut self, snapshot: uint) + -> ~[RegionVid] { do vec::build |push| { for uint::range(snapshot, self.undo_log.len()) |i| { match self.undo_log[i] { @@ -926,7 +910,7 @@ pub impl RegionVarBindings { } } - fn tainted(&mut self, snapshot: uint, r0: Region) -> ~[Region] { + pub fn tainted(&mut self, snapshot: uint, r0: Region) -> ~[Region] { /*! * * Computes all regions that have been related to `r0` in any @@ -944,7 +928,8 @@ pub impl RegionVarBindings { // `result_set` acts as a worklist: we explore all outgoing // edges and add any new regions we find to result_set. This // is not a terribly efficient implementation. - let mut result_set = ~[r0], result_index = 0; + let mut result_set = ~[r0]; + let mut result_index = 0; while result_index < result_set.len() { // nb: can't use uint::range() here because result_set grows let r = result_set[result_index]; @@ -1010,14 +995,14 @@ pub impl RegionVarBindings { constraints, assuming such values can be found; if they cannot, errors are reported. */ - fn resolve_regions(&mut self) { + pub fn resolve_regions(&mut self) { debug!("RegionVarBindings: resolve_regions()"); let v = self.infer_variable_values(); self.values.put_back(v); } } -priv impl RegionVarBindings { +impl RegionVarBindings { fn is_subregion_of(&self, sub: Region, sup: Region) -> bool { let rm = self.tcx.region_maps; rm.is_subregion_of(sub, sup) @@ -1273,15 +1258,15 @@ struct SpannedRegion { span: span, } -pub impl RegionVarBindings { - fn infer_variable_values(&mut self) -> ~[GraphNodeValue] { +impl RegionVarBindings { + pub fn infer_variable_values(&mut self) -> ~[GraphNodeValue] { let mut graph = self.construct_graph(); self.expansion(&mut graph); self.contraction(&mut graph); self.extract_values_and_report_conflicts(&graph) } - fn construct_graph(&mut self) -> Graph { + pub fn construct_graph(&mut self) -> Graph { let num_vars = self.num_vars(); let num_edges = self.constraints.len(); @@ -1346,7 +1331,7 @@ pub impl RegionVarBindings { } } - fn expansion(&mut self, graph: &mut Graph) { + pub fn expansion(&mut self, graph: &mut Graph) { do iterate_until_fixed_point(~"Expansion", graph) |nodes, edge| { match edge.constraint { ConstrainRegSubVar(a_region, b_vid) => { @@ -1370,11 +1355,11 @@ pub impl RegionVarBindings { } } - fn expand_node(&mut self, - a_region: Region, - b_vid: RegionVid, - b_node: &mut GraphNode) - -> bool { + pub fn expand_node(&mut self, + a_region: Region, + b_vid: RegionVid, + b_node: &mut GraphNode) + -> bool { debug!("expand_node(%?, %? == %?)", a_region, b_vid, b_node.value); @@ -1406,7 +1391,7 @@ pub impl RegionVarBindings { } } - fn contraction(&mut self, graph: &mut Graph) { + pub fn contraction(&mut self, graph: &mut Graph) { do iterate_until_fixed_point(~"Contraction", graph) |nodes, edge| { match edge.constraint { ConstrainRegSubVar(*) => { @@ -1430,17 +1415,17 @@ pub impl RegionVarBindings { } } - fn contract_node(&mut self, - a_vid: RegionVid, - a_node: &mut GraphNode, - b_region: Region) - -> bool { + pub fn contract_node(&mut self, + a_vid: RegionVid, + a_node: &mut GraphNode, + b_region: Region) + -> bool { debug!("contract_node(%? == %?/%?, %?)", a_vid, a_node.value, a_node.classification, b_region); return match a_node.value { NoValue => { - assert!(a_node.classification == Contracting); + assert_eq!(a_node.classification, Contracting); a_node.value = Value(b_region); true // changed } @@ -1502,10 +1487,8 @@ pub impl RegionVarBindings { } } - fn extract_values_and_report_conflicts( - &mut self, - graph: &Graph) -> ~[GraphNodeValue] - { + pub fn extract_values_and_report_conflicts(&mut self, graph: &Graph) + -> ~[GraphNodeValue] { debug!("extract_values_and_report_conflicts()"); // This is the best way that I have found to suppress @@ -1574,10 +1557,10 @@ pub impl RegionVarBindings { }) } - fn report_error_for_expanding_node(&mut self, - graph: &Graph, - dup_vec: &mut [uint], - node_idx: RegionVid) { + pub fn report_error_for_expanding_node(&mut self, + graph: &Graph, + dup_vec: &mut [uint], + node_idx: RegionVid) { // Errors in expanding nodes result from a lower-bound that is // not contained by an upper-bound. let (lower_bounds, lower_dup) = @@ -1633,10 +1616,10 @@ pub impl RegionVarBindings { upper_bounds.map(|x| x.region).repr(self.tcx))); } - fn report_error_for_contracting_node(&mut self, - graph: &Graph, - dup_vec: &mut [uint], - node_idx: RegionVid) { + pub fn report_error_for_contracting_node(&mut self, + graph: &Graph, + dup_vec: &mut [uint], + node_idx: RegionVid) { // Errors in contracting nodes result from two upper-bounds // that have no intersection. let (upper_bounds, dup_found) = @@ -1660,9 +1643,9 @@ pub impl RegionVarBindings { note_and_explain_region( self.tcx, - ~"first, the lifetime must be contained by ", + "first, the lifetime must be contained by ", upper_bound_1.region, - ~"..."); + "..."); self.tcx.sess.span_note( upper_bound_1.span, @@ -1670,9 +1653,9 @@ pub impl RegionVarBindings { note_and_explain_region( self.tcx, - ~"but, the lifetime must also be contained by ", + "but, the lifetime must also be contained by ", upper_bound_2.region, - ~"..."); + "..."); self.tcx.sess.span_note( upper_bound_2.span, @@ -1692,12 +1675,12 @@ pub impl RegionVarBindings { upper_bounds.map(|x| x.region).repr(self.tcx))); } - fn collect_concrete_regions(&mut self, - graph: &Graph, - orig_node_idx: RegionVid, - dir: Direction, - dup_vec: &mut [uint]) - -> (~[SpannedRegion], bool) { + pub fn collect_concrete_regions(&mut self, + graph: &Graph, + orig_node_idx: RegionVid, + dir: Direction, + dup_vec: &mut [uint]) + -> (~[SpannedRegion], bool) { struct WalkState { set: HashSet, stack: ~[RegionVid], @@ -1773,28 +1756,12 @@ pub impl RegionVarBindings { } } - #[cfg(stage0)] - fn each_edge(&mut self, - graph: &Graph, - node_idx: RegionVid, - dir: Direction, - op: &fn(edge: &GraphEdge) -> bool) { - let mut edge_idx = - graph.nodes[node_idx.to_uint()].head_edge[dir as uint]; - while edge_idx != uint::max_value { - let edge_ptr = &graph.edges[edge_idx]; - if !op(edge_ptr) { - return; - } - edge_idx = edge_ptr.next_edge[dir as uint]; - } - } - #[cfg(not(stage0))] - fn each_edge(&mut self, - graph: &Graph, - node_idx: RegionVid, - dir: Direction, - op: &fn(edge: &GraphEdge) -> bool) -> bool { + pub fn each_edge(&mut self, + graph: &Graph, + node_idx: RegionVid, + dir: Direction, + op: &fn(edge: &GraphEdge) -> bool) + -> bool { let mut edge_idx = graph.nodes[node_idx.to_uint()].head_edge[dir as uint]; while edge_idx != uint::max_value { diff --git a/src/librustc/middle/typeck/infer/resolve.rs b/src/librustc/middle/typeck/infer/resolve.rs index 2b88825c49a69..c2ee7fc2647bd 100644 --- a/src/librustc/middle/typeck/infer/resolve.rs +++ b/src/librustc/middle/typeck/infer/resolve.rs @@ -46,6 +46,8 @@ // future). If you want to resolve everything but one type, you are // probably better off writing `resolve_all - resolve_ivar`. +use core::prelude::*; + use middle::ty::{FloatVar, FloatVid, IntVar, IntVid, RegionVid, TyVar, TyVid}; use middle::ty::{type_is_bot, IntType, UintType}; use middle::ty; @@ -56,6 +58,7 @@ use middle::typeck::infer::unify::Root; use util::common::{indent, indenter}; use util::ppaux::ty_to_str; +use core::vec; use syntax::ast; pub static resolve_nested_tvar: uint = 0b0000000001; @@ -95,12 +98,12 @@ pub fn resolver(infcx: @mut InferCtxt, modes: uint) -> ResolveState { } } -pub impl ResolveState { - fn should(&mut self, mode: uint) -> bool { +impl ResolveState { + pub fn should(&mut self, mode: uint) -> bool { (self.modes & mode) == mode } - fn resolve_type_chk(&mut self, typ: ty::t) -> fres { + pub fn resolve_type_chk(&mut self, typ: ty::t) -> fres { self.err = None; debug!("Resolving %s (modes=%x)", @@ -125,7 +128,8 @@ pub impl ResolveState { } } - fn resolve_region_chk(&mut self, orig: ty::Region) -> fres { + pub fn resolve_region_chk(&mut self, orig: ty::Region) + -> fres { self.err = None; let resolved = indent(|| self.resolve_region(orig) ); match self.err { @@ -134,7 +138,7 @@ pub impl ResolveState { } } - fn resolve_type(&mut self, typ: ty::t) -> ty::t { + pub fn resolve_type(&mut self, typ: ty::t) -> ty::t { debug!("resolve_type(%s)", typ.inf_str(self.infcx)); let _i = indenter(); @@ -176,7 +180,7 @@ pub impl ResolveState { } } - fn resolve_region(&mut self, orig: ty::Region) -> ty::Region { + pub fn resolve_region(&mut self, orig: ty::Region) -> ty::Region { debug!("Resolve_region(%s)", orig.inf_str(self.infcx)); match orig { ty::re_infer(ty::ReVar(rid)) => self.resolve_region_var(rid), @@ -184,14 +188,14 @@ pub impl ResolveState { } } - fn resolve_region_var(&mut self, rid: RegionVid) -> ty::Region { + pub fn resolve_region_var(&mut self, rid: RegionVid) -> ty::Region { if !self.should(resolve_rvar) { return ty::re_infer(ty::ReVar(rid)); } self.infcx.region_vars.resolve_var(rid) } - fn assert_not_rvar(&mut self, rid: RegionVid, r: ty::Region) { + pub fn assert_not_rvar(&mut self, rid: RegionVid, r: ty::Region) { match r { ty::re_infer(ty::ReVar(rid2)) => { self.err = Some(region_var_bound_by_region_var(rid, rid2)); @@ -200,7 +204,7 @@ pub impl ResolveState { } } - fn resolve_ty_var(&mut self, vid: TyVid) -> ty::t { + pub fn resolve_ty_var(&mut self, vid: TyVid) -> ty::t { if vec::contains(self.v_seen, &vid) { self.err = Some(cyclic_ty(vid)); return ty::mk_var(self.infcx.tcx, vid); @@ -234,7 +238,7 @@ pub impl ResolveState { } } - fn resolve_int_var(&mut self, vid: IntVid) -> ty::t { + pub fn resolve_int_var(&mut self, vid: IntVid) -> ty::t { if !self.should(resolve_ivar) { return ty::mk_int_var(self.infcx.tcx, vid); } @@ -257,7 +261,7 @@ pub impl ResolveState { } } - fn resolve_float_var(&mut self, vid: FloatVid) -> ty::t { + pub fn resolve_float_var(&mut self, vid: FloatVid) -> ty::t { if !self.should(resolve_fvar) { return ty::mk_float_var(self.infcx.tcx, vid); } diff --git a/src/librustc/middle/typeck/infer/sub.rs b/src/librustc/middle/typeck/infer/sub.rs index 8da3d7bfa000d..2578f7c855359 100644 --- a/src/librustc/middle/typeck/infer/sub.rs +++ b/src/librustc/middle/typeck/infer/sub.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use middle::ty::{BuiltinBounds}; use middle::ty; use middle::ty::TyVar; @@ -21,8 +23,8 @@ use middle::typeck::infer::to_str::InferStr; use util::common::{indent, indenter}; use util::ppaux::bound_region_to_str; -use std::list::Nil; -use std::list; +use extra::list::Nil; +use extra::list; use syntax::abi::AbiSet; use syntax::ast; use syntax::ast::{Onceness, m_const, purity}; diff --git a/src/librustc/middle/typeck/infer/test.rs b/src/librustc/middle/typeck/infer/test.rs index 1d24a4dbd4f91..e6e6753255e74 100644 --- a/src/librustc/middle/typeck/infer/test.rs +++ b/src/librustc/middle/typeck/infer/test.rs @@ -23,12 +23,12 @@ use middle::lang_items::{LanguageItems, language_items}; use middle::ty::{FnTyBase, FnMeta, FnSig}; use util::ppaux::ty_to_str; -use std::getopts::groups::{optopt, optmulti, optflag, optflagopt, getopts}; -use std::getopts::groups; -use std::getopts::{opt_present}; -use std::getopts; -use std::getopts; -use std::oldmap::HashMap; +use extra::getopts::groups::{optopt, optmulti, optflag, optflagopt, getopts}; +use extra::getopts::groups; +use extra::getopts::{opt_present}; +use extra::getopts; +use extra::getopts; +use extra::oldmap::HashMap; use syntax::codemap::dummy_sp; use syntax::parse::parse_crate_from_source_str; use syntax::{ast, attr, parse}; @@ -67,7 +67,7 @@ fn setup_env(test_name: &str, source_string: &str) -> Env { cfg, parse_sess); let tcx = ty::mk_ctxt(sess, dm, amap, freevars, region_map, - region_paramd_items, lang_items, crate); + region_paramd_items, lang_items); let infcx = infer::new_infer_ctxt(tcx); @@ -77,15 +77,15 @@ fn setup_env(test_name: &str, source_string: &str) -> Env { err_messages: messages}; } -pub impl Env { - fn create_region_hierarchy(&self, rh: &RH) { +impl Env { + pub fn create_region_hierarchy(&self, rh: &RH) { for rh.sub.each |child_rh| { self.create_region_hierarchy(child_rh); self.tcx.region_map.insert(child_rh.id, rh.id); } } - fn create_simple_region_hierarchy(&self) { + pub fn create_simple_region_hierarchy(&self) { // creates a region hierarchy where 1 is root, 10 and 11 are // children of 1, etc self.create_region_hierarchy( @@ -96,7 +96,7 @@ pub impl Env { sub: &[]}]}); } - fn lookup_item(&self, names: &[~str]) -> ast::node_id { + pub fn lookup_item(&self, names: &[~str]) -> ast::node_id { return match search_mod(self, &self.crate.node.module, 0, names) { Some(id) => id, None => { @@ -144,14 +144,14 @@ pub impl Env { } } - fn is_subtype(&self, a: ty::t, b: ty::t) -> bool { + pub fn is_subtype(&self, a: ty::t, b: ty::t) -> bool { match infer::can_mk_subty(self.infcx, a, b) { Ok(_) => true, Err(_) => false } } - fn assert_subtype(&self, a: ty::t, b: ty::t) { + pub fn assert_subtype(&self, a: ty::t, b: ty::t) { if !self.is_subtype(a, b) { fail!("%s is not a subtype of %s, but it should be", self.ty_to_str(a), @@ -159,7 +159,7 @@ pub impl Env { } } - fn assert_not_subtype(&self, a: ty::t, b: ty::t) { + pub fn assert_not_subtype(&self, a: ty::t, b: ty::t) { if self.is_subtype(a, b) { fail!("%s is a subtype of %s, but it shouldn't be", self.ty_to_str(a), @@ -167,21 +167,21 @@ pub impl Env { } } - fn assert_strict_subtype(&self, a: ty::t, b: ty::t) { + pub fn assert_strict_subtype(&self, a: ty::t, b: ty::t) { self.assert_subtype(a, b); self.assert_not_subtype(b, a); } - fn assert_eq(&self, a: ty::t, b: ty::t) { + pub fn assert_eq(&self, a: ty::t, b: ty::t) { self.assert_subtype(a, b); self.assert_subtype(b, a); } - fn ty_to_str(&self, a: ty::t) -> ~str { + pub fn ty_to_str(&self, a: ty::t) -> ~str { ty_to_str(self.tcx, a) } - fn t_fn(&self, input_tys: &[ty::t], output_ty: ty::t) -> ty::t { + pub fn t_fn(&self, input_tys: &[ty::t], output_ty: ty::t) -> ty::t { let inputs = input_tys.map(|t| {mode: ast::expl(ast::by_copy), ty: *t}); ty::mk_fn(self.tcx, FnTyBase { @@ -195,34 +195,34 @@ pub impl Env { }) } - fn t_int(&self) -> ty::t { + pub fn t_int(&self) -> ty::t { ty::mk_int(self.tcx) } - fn t_rptr_bound(&self, id: uint) -> ty::t { + pub fn t_rptr_bound(&self, id: uint) -> ty::t { ty::mk_imm_rptr(self.tcx, ty::re_bound(ty::br_anon(id)), self.t_int()) } - fn t_rptr_scope(&self, id: ast::node_id) -> ty::t { + pub fn t_rptr_scope(&self, id: ast::node_id) -> ty::t { ty::mk_imm_rptr(self.tcx, ty::re_scope(id), self.t_int()) } - fn t_rptr_free(&self, nid: ast::node_id, id: uint) -> ty::t { + pub fn t_rptr_free(&self, nid: ast::node_id, id: uint) -> ty::t { ty::mk_imm_rptr(self.tcx, ty::re_free(ty::FreeRegion {scope_id: nid, bound_region: ty::br_anon(id)}), self.t_int()) } - fn t_rptr_static(&self) -> ty::t { + pub fn t_rptr_static(&self) -> ty::t { ty::mk_imm_rptr(self.tcx, ty::re_static, self.t_int()) } - fn lub() -> Lub { Lub(self.infcx.combine_fields(true, dummy_sp())) } + pub fn lub() -> Lub { Lub(self.infcx.combine_fields(true, dummy_sp())) } - fn glb() -> Glb { Glb(self.infcx.combine_fields(true, dummy_sp())) } + pub fn glb() -> Glb { Glb(self.infcx.combine_fields(true, dummy_sp())) } - fn resolve_regions(exp_count: uint) { + pub fn resolve_regions(exp_count: uint) { debug!("resolve_regions(%u)", exp_count); self.infcx.resolve_regions(); @@ -237,7 +237,7 @@ pub impl Env { } /// Checks that `LUB(t1,t2) == t_lub` - fn check_lub(&self, t1: ty::t, t2: ty::t, t_lub: ty::t) { + pub fn check_lub(&self, t1: ty::t, t2: ty::t, t_lub: ty::t) { match self.lub().tys(t1, t2) { Err(e) => { fail!("Unexpected error computing LUB: %?", e) @@ -255,7 +255,7 @@ pub impl Env { } /// Checks that `GLB(t1,t2) == t_glb` - fn check_glb(&self, t1: ty::t, t2: ty::t, t_glb: ty::t) { + pub fn check_glb(&self, t1: ty::t, t2: ty::t, t_glb: ty::t) { debug!("check_glb(t1=%s, t2=%s, t_glb=%s)", self.ty_to_str(t1), self.ty_to_str(t2), @@ -277,7 +277,7 @@ pub impl Env { } /// Checks that `LUB(t1,t2)` is undefined - fn check_no_lub(&self, t1: ty::t, t2: ty::t) { + pub fn check_no_lub(&self, t1: ty::t, t2: ty::t) { match self.lub().tys(t1, t2) { Err(_) => {} Ok(t) => { @@ -287,7 +287,7 @@ pub impl Env { } /// Checks that `GLB(t1,t2)` is undefined - fn check_no_glb(&self, t1: ty::t, t2: ty::t) { + pub fn check_no_glb(&self, t1: ty::t, t2: ty::t) { match self.glb().tys(t1, t2) { Err(_) => {} Ok(t) => { diff --git a/src/librustc/middle/typeck/infer/to_str.rs b/src/librustc/middle/typeck/infer/to_str.rs index d9088c064939b..ef3b837e98a16 100644 --- a/src/librustc/middle/typeck/infer/to_str.rs +++ b/src/librustc/middle/typeck/infer/to_str.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use middle::ty::{FnSig, Vid}; use middle::ty::IntVarValue; use middle::ty; @@ -16,6 +18,8 @@ use middle::typeck::infer::InferCtxt; use middle::typeck::infer::unify::{Redirect, Root, VarValue}; use util::ppaux::{mt_to_str, ty_to_str, trait_ref_to_str}; +use core::str; +use core::uint; use syntax::ast; pub trait InferStr { diff --git a/src/librustc/middle/typeck/infer/unify.rs b/src/librustc/middle/typeck/infer/unify.rs index 3bcff92346566..c6e4b485d29b5 100644 --- a/src/librustc/middle/typeck/infer/unify.rs +++ b/src/librustc/middle/typeck/infer/unify.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::smallintmap::SmallIntMap; +use core::prelude::*; + +use extra::smallintmap::SmallIntMap; use middle::ty::{Vid, expected_found, IntVarValue}; use middle::ty; @@ -38,11 +40,9 @@ pub trait UnifyVid { -> &'v mut ValsAndBindings; } -pub impl InferCtxt { - fn get>( - &mut self, - vid: V) -> Node - { +impl InferCtxt { + pub fn get>(&mut self, vid: V) + -> Node { /*! * * Find the root node for `vid`. This uses the standard @@ -84,10 +84,10 @@ pub impl InferCtxt { } } - fn set>( - &mut self, - vid: V, - new_v: VarValue) { + pub fn set>(&mut self, + vid: V, + new_v: VarValue) { /*! * * Sets the value for `vid` to `new_v`. `vid` MUST be a root node! @@ -104,11 +104,11 @@ pub impl InferCtxt { } } - fn unify>( - &mut self, - node_a: &Node, - node_b: &Node) -> (V, uint) - { + pub fn unify>(&mut self, + node_a: &Node, + node_b: &Node) + -> (V, uint) { // Rank optimization: if you don't know what it is, check // out @@ -129,7 +129,7 @@ pub impl InferCtxt { } else { // If equal, redirect one to the other and increment the // other's rank. - assert!(node_a.rank == node_b.rank); + assert_eq!(node_a.rank, node_b.rank); self.set(node_b.root, Redirect(node_a.root)); (node_a.root, node_a.rank + 1) } @@ -157,14 +157,14 @@ pub fn mk_err(a_is_expected: bool, } } -pub impl InferCtxt { - fn simple_vars>>( - &mut self, - a_is_expected: bool, - a_id: V, - b_id: V) - -> ures { +impl InferCtxt { + pub fn simple_vars>>(&mut self, + a_is_expected: + bool, + a_id: V, + b_id: V) + -> ures { /*! * * Unifies two simple variables. Because simple variables do @@ -196,13 +196,13 @@ pub impl InferCtxt { return uok(); } - fn simple_var_t>>( - &mut self, - a_is_expected: bool, - a_id: V, - b: T) - -> ures { + pub fn simple_var_t>>(&mut self, + a_is_expected + : bool, + a_id: V, + b: T) + -> ures { /*! * * Sets the value of the variable `a_id` to `b`. Because diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs index dd313c54efb92..dc561f413c710 100644 --- a/src/librustc/middle/typeck/mod.rs +++ b/src/librustc/middle/typeck/mod.rs @@ -48,6 +48,8 @@ independently: */ +use core::prelude::*; + use driver::session; use middle::resolve; @@ -57,8 +59,9 @@ use util::ppaux::Repr; use util::ppaux; use core::hashmap::HashMap; -use std::list::List; -use std::list; +use core::result; +use extra::list::List; +use extra::list; use syntax::codemap::span; use syntax::print::pprust::*; use syntax::{ast, ast_map, abi}; @@ -239,7 +242,8 @@ pub fn require_same_types( t2: ty::t, msg: &fn() -> ~str) -> bool { - let l_tcx, l_infcx; + let l_tcx; + let l_infcx; match maybe_infcx { None => { l_tcx = tcx; @@ -254,7 +258,7 @@ pub fn require_same_types( match infer::mk_eqty(l_infcx, t1_is_expected, span, t1, t2) { result::Ok(()) => true, result::Err(ref terr) => { - l_tcx.sess.span_err(span, msg() + ~": " + + l_tcx.sess.span_err(span, msg() + ": " + ty::type_err_to_str(l_tcx, terr)); ty::note_and_explain_type_err(l_tcx, terr); false @@ -320,8 +324,8 @@ fn check_main_fn_ty(ccx: @mut CrateCtxt, } _ => { tcx.sess.span_bug(main_span, - ~"main has a non-function type: found `" + - ppaux::ty_to_str(tcx, main_t) + ~"`"); + fmt!("main has a non-function type: found `%s`", + ppaux::ty_to_str(tcx, main_t))); } } } @@ -369,8 +373,8 @@ fn check_start_fn_ty(ccx: @mut CrateCtxt, } _ => { tcx.sess.span_bug(start_span, - ~"start has a non-function type: found `" + - ppaux::ty_to_str(tcx, start_t) + ~"`"); + fmt!("start has a non-function type: found `%s`", + ppaux::ty_to_str(tcx, start_t))); } } } @@ -382,9 +386,9 @@ fn check_for_entry_fn(ccx: @mut CrateCtxt) { Some((id, sp)) => match *tcx.sess.entry_type { Some(session::EntryMain) => check_main_fn_ty(ccx, id, sp), Some(session::EntryStart) => check_start_fn_ty(ccx, id, sp), - None => tcx.sess.bug(~"entry function without a type") + None => tcx.sess.bug("entry function without a type") }, - None => tcx.sess.bug(~"type checking without entry function") + None => tcx.sess.bug("type checking without entry function") } } } diff --git a/src/librustc/middle/typeck/rscope.rs b/src/librustc/middle/typeck/rscope.rs index 7c37784b09db9..709d631de117a 100644 --- a/src/librustc/middle/typeck/rscope.rs +++ b/src/librustc/middle/typeck/rscope.rs @@ -8,8 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use middle::ty; +use core::result; use syntax::ast; use syntax::codemap::span; use syntax::opt_vec::OptVec; diff --git a/src/librustc/rustc.rc b/src/librustc/rustc.rc index 6027a04454180..baf920c04acbe 100644 --- a/src/librustc/rustc.rc +++ b/src/librustc/rustc.rc @@ -21,9 +21,26 @@ #[allow(non_camel_case_types)]; #[deny(deprecated_pattern)]; -extern mod std(vers = "0.7-pre"); -extern mod syntax(vers = "0.7-pre"); +#[no_core]; +#[no_std]; +extern mod core(name = "std"); +extern mod extra(name = "extra"); +extern mod syntax; + +// For deriving(Encodable) purposes... +#[cfg(stage0)] +extern mod std(name = "extra", vers = "0.7-pre"); +#[cfg(not(stage0))] +extern mod std(name = "std", vers = "0.7-pre"); + +// For bootstrapping purposes. +#[cfg(stage0)] +pub use core::str; +#[cfg(stage0)] +pub use core::unstable; + +use core::prelude::*; use driver::driver::{host_triple, optgroups, early_error}; use driver::driver::{str_input, file_input, build_session_options}; @@ -33,8 +50,15 @@ use driver::driver::{compile_input}; use driver::session; use middle::lint; -use std::getopts::{groups, opt_present}; -use std::getopts; +use core::io; +use core::os; +use core::result; +use core::str; +use core::task; +use core::uint; +use core::vec; +use extra::getopts::{groups, opt_present}; +use extra::getopts; use syntax::codemap; use syntax::diagnostic; @@ -76,9 +100,6 @@ pub mod middle { } pub mod ty; pub mod subst; - #[cfg(stage0)] #[path = "resolve_stage0.rs"] - pub mod resolve; - #[cfg(not(stage0))] pub mod resolve; #[path = "typeck/mod.rs"] pub mod typeck; @@ -101,12 +122,13 @@ pub mod middle { pub mod privacy; pub mod moves; pub mod entry; + pub mod effect; } pub mod front { pub mod config; pub mod test; - pub mod core_inject; + pub mod std_inject; pub mod intrinsic_inject; } @@ -120,6 +142,7 @@ pub mod back { pub mod x86_64; pub mod rpath; pub mod target_strs; + pub mod passes; } #[path = "metadata/mod.rs"] @@ -138,21 +161,33 @@ pub mod lib { pub mod llvm; } +// A curious inner module that allows ::std::foo to be available in here for +// macros. +mod std { + pub use core::cmp; + pub use core::os; + pub use core::str; + pub use core::sys; + pub use core::to_bytes; + pub use core::unstable; + pub use extra::serialize; +} + pub fn version(argv0: &str) { let mut vers = ~"unknown version"; let env_vers = env!("CFG_VERSION"); - if env_vers.len() != 0 { vers = env_vers; } + if env_vers.len() != 0 { vers = env_vers.to_owned(); } io::println(fmt!("%s %s", argv0, vers)); io::println(fmt!("host: %s", host_triple())); } pub fn usage(argv0: &str) { let message = fmt!("Usage: %s [OPTIONS] INPUT", argv0); - io::println(groups::usage(message, optgroups()) + - ~"Additional help: - -W help Print 'lint' options and default settings - -Z help Print internal options for debugging rustc -"); + io::println(fmt!("%s \ + Additional help: \ + -W help Print 'lint' options and default settings \ + -Z help Print internal options for debugging rustc", + groups::usage(message, optgroups()))); } pub fn describe_warnings() { @@ -172,11 +207,11 @@ Available lint options: } io::println(fmt!("\nAvailable lint checks:\n")); io::println(fmt!(" %s %7.7s %s", - padded(max_key, ~"name"), ~"default", ~"meaning")); + padded(max_key, "name"), "default", "meaning")); io::println(fmt!(" %s %7.7s %s\n", - padded(max_key, ~"----"), ~"-------", ~"-------")); + padded(max_key, "----"), "-------", "-------")); for lint_dict.each |k, v| { - let k = str::replace(*k, ~"_", ~"-"); + let k = str::replace(*k, "_", "-"); io::println(fmt!(" %s %7.7s %s", padded(max_key, k), match v.default { @@ -187,7 +222,7 @@ Available lint options: }, v.desc)); } - io::println(~""); + io::println(""); } pub fn describe_debug_flags() { @@ -215,24 +250,34 @@ pub fn run_compiler(args: &~[~str], demitter: diagnostic::Emitter) { } }; - if opt_present(matches, ~"h") || opt_present(matches, ~"help") { + if opt_present(matches, "h") || opt_present(matches, "help") { usage(*binary); return; } - let lint_flags = vec::append(getopts::opt_strs(matches, ~"W"), - getopts::opt_strs(matches, ~"warn")); - if lint_flags.contains(&~"help") { + // Display the available lint options if "-W help" or only "-W" is given. + let lint_flags = vec::append(getopts::opt_strs(matches, "W"), + getopts::opt_strs(matches, "warn")); + + let show_lint_options = lint_flags.contains(&~"help") || + (opt_present(matches, "W") && lint_flags.is_empty()); + + if show_lint_options { describe_warnings(); return; } - if getopts::opt_strs(matches, ~"Z").contains(&~"help") { + if getopts::opt_strs(matches, "Z").contains(&~"help") { describe_debug_flags(); return; } - if opt_present(matches, ~"v") || opt_present(matches, ~"version") { + if getopts::opt_maybe_str(matches, "passes") == Some(~"list") { + back::passes::list_passes(); + return; + } + + if opt_present(matches, "v") || opt_present(matches, "version") { version(*binary); return; } @@ -252,12 +297,12 @@ pub fn run_compiler(args: &~[~str], demitter: diagnostic::Emitter) { let sopts = build_session_options(binary, matches, demitter); let sess = build_session(sopts, demitter); - let odir = getopts::opt_maybe_str(matches, ~"out-dir"); + let odir = getopts::opt_maybe_str(matches, "out-dir"); let odir = odir.map(|o| Path(*o)); - let ofile = getopts::opt_maybe_str(matches, ~"o"); + let ofile = getopts::opt_maybe_str(matches, "o"); let ofile = ofile.map(|o| Path(*o)); let cfg = build_configuration(sess, binary, &input); - let pretty = getopts::opt_default(matches, ~"pretty", "normal").map( + let pretty = getopts::opt_default(matches, "pretty", "normal").map( |a| parse_pretty(sess, *a)); match pretty { Some::(ppm) => { @@ -266,7 +311,7 @@ pub fn run_compiler(args: &~[~str], demitter: diagnostic::Emitter) { } None:: => {/* continue */ } } - let ls = opt_present(matches, ~"ls"); + let ls = opt_present(matches, "ls"); if ls { match input { file_input(ref ifile) => { @@ -338,7 +383,7 @@ pub fn monitor(f: ~fn(diagnostic::Emitter)) { if p.recv() == done { diagnostic::emit( None, - diagnostic::ice_msg(~"unexpected failure"), + diagnostic::ice_msg("unexpected failure"), diagnostic::error); for [ diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index b4a479fc5970f..a44c409aa33b5 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -8,18 +8,22 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use syntax::ast; use syntax::codemap::{span}; use syntax::visit; use core::hashmap::HashSet; -use std; +use core::io; +use core::str; +use extra; pub fn time(do_it: bool, what: ~str, thunk: &fn() -> T) -> T { if !do_it { return thunk(); } - let start = std::time::precise_time_s(); + let start = extra::time::precise_time_s(); let rv = thunk(); - let end = std::time::precise_time_s(); + let end = extra::time::precise_time_s(); io::println(fmt!("time: %3.3f s\t%s", end - start, what)); rv } diff --git a/src/librustc/util/enum_set.rs b/src/librustc/util/enum_set.rs index 2e6c4ee3eaa8e..85fceabf0ac8f 100644 --- a/src/librustc/util/enum_set.rs +++ b/src/librustc/util/enum_set.rs @@ -8,8 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[cfg(stage0)] -use core; +use core::prelude::*; #[deriving(Eq, IterBytes)] pub struct EnumSet { @@ -27,56 +26,40 @@ fn bit(e: E) -> uint { 1 << e.to_uint() } -pub impl EnumSet { - fn empty() -> EnumSet { +impl EnumSet { + pub fn empty() -> EnumSet { EnumSet {bits: 0} } - fn is_empty(&self) -> bool { + pub fn is_empty(&self) -> bool { self.bits == 0 } - fn intersects(&self, e: EnumSet) -> bool { + pub fn intersects(&self, e: EnumSet) -> bool { (self.bits & e.bits) != 0 } - fn intersection(&self, e: EnumSet) -> EnumSet { + pub fn intersection(&self, e: EnumSet) -> EnumSet { EnumSet {bits: self.bits & e.bits} } - fn contains(&self, e: EnumSet) -> bool { + pub fn contains(&self, e: EnumSet) -> bool { (self.bits & e.bits) == e.bits } - fn union(&self, e: EnumSet) -> EnumSet { + pub fn union(&self, e: EnumSet) -> EnumSet { EnumSet {bits: self.bits | e.bits} } - fn add(&mut self, e: E) { + pub fn add(&mut self, e: E) { self.bits |= bit(e); } - fn contains_elem(&self, e: E) -> bool { + pub fn contains_elem(&self, e: E) -> bool { (self.bits & bit(e)) != 0 } - #[cfg(stage0)] - fn each(&self, f: &fn(E) -> bool) { - let mut bits = self.bits; - let mut index = 0; - while bits != 0 { - if (bits & 1) != 0 { - let e = CLike::from_uint(index); - if !f(e) { - return; - } - } - index += 1; - bits >>= 1; - } - } - #[cfg(not(stage0))] - fn each(&self, f: &fn(E) -> bool) -> bool { + pub fn each(&self, f: &fn(E) -> bool) -> bool { let mut bits = self.bits; let mut index = 0; while bits != 0 { @@ -113,7 +96,11 @@ impl BitAnd, EnumSet> for EnumSet { #[cfg(test)] mod test { + use core::prelude::*; + + use core::cast; use core::iter; + use util::enum_set::*; #[deriving(Eq)] diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 13a2f376c0694..2ec4cc65528f3 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use metadata::encoder; use middle::ty::{ReSkolemized, ReVar}; use middle::ty::{bound_region, br_anon, br_named, br_self, br_cap_avoid}; @@ -26,9 +28,13 @@ use middle::typeck; use syntax::abi::AbiSet; use syntax::ast_map; use syntax::codemap::span; +use syntax::parse::token; use syntax::print::pprust; use syntax::{ast, ast_util}; +use core::str; +use core::vec; + /// Produces a string suitable for debugging output. pub trait Repr { fn repr(&self, tcx: ctxt) -> ~str; @@ -177,7 +183,6 @@ pub fn re_scope_id_to_str(cx: ctxt, node_id: ast::node_id) -> ~str { cx.sess.codemap.span_to_str(expr.span)) } ast::expr_assign_op(*) | - ast::expr_field(*) | ast::expr_unary(*) | ast::expr_binary(*) | ast::expr_index(*) => { @@ -196,7 +201,7 @@ pub fn re_scope_id_to_str(cx: ctxt, node_id: ast::node_id) -> ~str { _ => { cx.sess.bug( fmt!("re_scope refers to %s", ast_map::node_id_to_str(cx.items, node_id, - cx.sess.parse_sess.interner))) } + token::get_ident_interner()))) } } } @@ -380,10 +385,10 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str { m.fty.purity, m.fty.abis, Some(m.ident), - &m.fty.sig) + ~";" + &m.fty.sig) + ";" } fn field_to_str(cx: ctxt, f: field) -> ~str { - return *cx.sess.str_of(f.ident) + ~": " + mt_to_str(cx, &f.mt); + return *cx.sess.str_of(f.ident) + ": " + mt_to_str(cx, &f.mt); } // if there is an id, print that instead of the structural type: @@ -409,13 +414,13 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str { ty_uniq(ref tm) => ~"~" + mt_to_str(cx, tm), ty_ptr(ref tm) => ~"*" + mt_to_str(cx, tm), ty_rptr(r, ref tm) => { - region_to_str_space(cx, ~"&", r) + mt_to_str(cx, tm) + region_to_str_space(cx, "&", r) + mt_to_str(cx, tm) } - ty_unboxed_vec(ref tm) => { ~"unboxed_vec<" + mt_to_str(cx, tm) + ~">" } + ty_unboxed_vec(ref tm) => { fmt!("unboxed_vec<%s>", mt_to_str(cx, tm)) } ty_type => ~"type", ty_tup(ref elems) => { let strs = elems.map(|elem| ty_to_str(cx, *elem)); - ~"(" + str::connect(strs, ~",") + ~")" + ~"(" + str::connect(strs, ",") + ")" } ty_closure(ref f) => { closure_to_str(cx, f) @@ -428,11 +433,11 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str { ty_param(param_ty {idx: id, def_id: did}) => { if cx.sess.verbose() { fmt!("'%s:%?", - str::from_bytes(~[('a' as u8) + (id as u8)]), + str::from_bytes([('a' as u8) + (id as u8)]), did) } else { fmt!("'%s", - str::from_bytes(~[('a' as u8) + (id as u8)])) + str::from_bytes([('a' as u8) + (id as u8)])) } } ty_self(*) => ~"Self", @@ -450,7 +455,7 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str { ty_evec(ref mt, vs) => { vstore_ty_to_str(cx, mt, vs) } - ty_estr(vs) => fmt!("%s%s", vstore_to_str(cx, vs), ~"str"), + ty_estr(vs) => fmt!("%s%s", vstore_to_str(cx, vs), "str"), ty_opaque_box => ~"@?", ty_opaque_closure_ptr(ast::BorrowedSigil) => ~"closure&", ty_opaque_closure_ptr(ast::ManagedSigil) => ~"closure@", @@ -558,6 +563,7 @@ impl Repr for ty::ParamBounds { ty::BoundStatic => ~"'static", ty::BoundOwned => ~"Owned", ty::BoundConst => ~"Const", + ty::BoundSized => ~"Sized", }); } for self.trait_bounds.each |t| { @@ -649,7 +655,7 @@ impl Repr for ty::Method { impl Repr for ast::ident { fn repr(&self, tcx: ctxt) -> ~str { - copy *tcx.sess.intr().get(*self) + copy *token::ident_to_str(self) } } @@ -762,7 +768,8 @@ impl UserString for ty::BuiltinBound { ty::BoundCopy => ~"Copy", ty::BoundStatic => ~"'static", ty::BoundOwned => ~"Owned", - ty::BoundConst => ~"Const" + ty::BoundConst => ~"Const", + ty::BoundSized => ~"Sized", } } } @@ -799,3 +806,9 @@ impl UserString for ty::TraitRef { } } } + +impl UserString for ty::t { + fn user_string(&self, tcx: ctxt) -> ~str { + ty_to_str(tcx, *self) + } +} diff --git a/src/librustdoc/astsrv.rs b/src/librustdoc/astsrv.rs index b8a66eb8f64f0..c4fc377bc8bf7 100644 --- a/src/librustdoc/astsrv.rs +++ b/src/librustdoc/astsrv.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -17,10 +17,13 @@ query AST-related information, shielding the rest of Rustdoc from its non-sendableness. */ +use core::prelude::*; + use parse; use core::cell::Cell; use core::comm::{stream, SharedChan, Port}; +use core::task; use rustc::driver::driver; use rustc::driver::session::Session; use rustc::driver::session::{basic_options, options}; @@ -29,6 +32,8 @@ use syntax::ast; use syntax::ast_map; use syntax; +#[cfg(test)] use core::vec; + pub struct Ctxt { ast: @ast::crate, ast_map: ast_map::map @@ -60,8 +65,8 @@ fn run(owner: SrvOwner, source: ~str, parse: Parser) -> T { let (po, ch) = stream(); - let source = Cell(source); - let parse = Cell(parse); + let source = Cell::new(source); + let parse = Cell::new(parse); do task::spawn { act(&po, source.take(), parse.take()); } @@ -162,6 +167,6 @@ fn srv_should_return_request_result() { let source = ~"fn a() { }"; do from_str(source) |srv| { let result = exec(srv, |_ctxt| 1000 ); - assert!(result == 1000); + assert_eq!(result, 1000); } } diff --git a/src/librustdoc/attr_parser.rs b/src/librustdoc/attr_parser.rs index 433809b9db291..d2d9ec7d79bd8 100644 --- a/src/librustdoc/attr_parser.rs +++ b/src/librustdoc/attr_parser.rs @@ -15,6 +15,9 @@ The attribute parser provides methods for pulling documentation out of an AST's attributes. */ +use core::prelude::*; + +use core::str; use syntax::ast; use syntax::attr; @@ -26,7 +29,7 @@ fn doc_metas( attrs: ~[ast::attribute] ) -> ~[@ast::meta_item] { - let doc_attrs = attr::find_attrs_by_name(attrs, ~"doc"); + let doc_attrs = attr::find_attrs_by_name(attrs, "doc"); let doc_metas = do doc_attrs.map |attr| { attr::attr_meta(attr::desugar_doc_attr(attr)) }; @@ -36,7 +39,7 @@ fn doc_metas( pub fn parse_crate(attrs: ~[ast::attribute]) -> CrateAttrs { let link_metas = attr::find_linkage_metas(attrs); - let name = attr::last_meta_item_value_str_by_name(link_metas, ~"name"); + let name = attr::last_meta_item_value_str_by_name(link_metas, "name"); CrateAttrs { name: name.map(|s| copy **s) @@ -58,7 +61,7 @@ pub fn parse_hidden(attrs: ~[ast::attribute]) -> bool { do doc_metas(attrs).find |meta| { match attr::get_meta_item_list(*meta) { Some(metas) => { - let hiddens = attr::find_meta_items_by_name(metas, ~"hidden"); + let hiddens = attr::find_meta_items_by_name(metas, "hidden"); !hiddens.is_empty() } None => false @@ -68,6 +71,7 @@ pub fn parse_hidden(attrs: ~[ast::attribute]) -> bool { #[cfg(test)] mod test { + use core::prelude::*; use syntax::ast; use syntax; use super::{parse_hidden, parse_crate, parse_desc}; @@ -75,7 +79,6 @@ mod test { fn parse_attributes(source: ~str) -> ~[ast::attribute] { use syntax::parse; use syntax::parse::attr::parser_attr; - use syntax::codemap; let parse_sess = syntax::parse::new_parse_sess(None); let parser = parse::new_parser_from_source_str( diff --git a/src/librustdoc/attr_pass.rs b/src/librustdoc/attr_pass.rs index 35cbe394b86a3..a1dad7d17f8e8 100644 --- a/src/librustdoc/attr_pass.rs +++ b/src/librustdoc/attr_pass.rs @@ -16,6 +16,8 @@ corresponding AST nodes. The information gathered here is the basis of the natural-language documentation for a crate. */ +use core::prelude::*; + use astsrv; use attr_parser; use doc::ItemUtils; @@ -25,6 +27,7 @@ use fold::Fold; use fold; use pass::Pass; +use core::vec; use syntax::ast; use syntax::ast_map; @@ -232,6 +235,8 @@ fn fold_impl( #[cfg(test)] mod test { + use core::prelude::*; + use astsrv; use attr_pass::run; use doc; diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 0644b57a0f45b..691f0dfedc4ca 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -8,12 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; use core::cell::Cell; -use core::run; -use core::run::ProgramOutput; +use core::os; use core::result::Result; -use std::getopts; +use core::result; +use core::run::ProcessOutput; +use core::run; +use core::vec; +use extra::getopts; /// The type of document to output #[deriving(Eq)] @@ -70,12 +74,12 @@ fn opts() -> ~[(getopts::Opt, ~str)] { pub fn usage() { use core::io::println; - println(~"Usage: rustdoc [options] \n"); - println(~"Options:\n"); + println("Usage: rustdoc [options] \n"); + println("Options:\n"); for opts().each |opt| { println(fmt!(" %s", opt.second())); } - println(~""); + println(""); } pub fn default_config(input_crate: &Path) -> Config { @@ -88,27 +92,27 @@ pub fn default_config(input_crate: &Path) -> Config { } } -type Process = ~fn((&str), (&[~str])) -> ProgramOutput; +type Process = ~fn((&str), (&[~str])) -> ProcessOutput; -pub fn mock_program_output(_prog: &str, _args: &[~str]) -> ProgramOutput { - ProgramOutput { +pub fn mock_process_output(_prog: &str, _args: &[~str]) -> ProcessOutput { + ProcessOutput { status: 0, - out: ~"", - err: ~"" + output: ~[], + error: ~[] } } -pub fn program_output(prog: &str, args: &[~str]) -> ProgramOutput { - run::program_output(prog, args) +pub fn process_output(prog: &str, args: &[~str]) -> ProcessOutput { + run::process_output(prog, args) } pub fn parse_config(args: &[~str]) -> Result { - parse_config_(args, program_output) + parse_config_(args, process_output) } pub fn parse_config_( args: &[~str], - program_output: Process + process_output: Process ) -> Result { let args = args.tail(); let opts = vec::unzip(opts()).first(); @@ -116,7 +120,7 @@ pub fn parse_config_( Ok(matches) => { if matches.free.len() == 1 { let input_crate = Path(*matches.free.head()); - config_from_opts(&input_crate, &matches, program_output) + config_from_opts(&input_crate, &matches, process_output) } else if matches.free.is_empty() { Err(~"no crates specified") } else { @@ -132,7 +136,7 @@ pub fn parse_config_( fn config_from_opts( input_crate: &Path, matches: &getopts::Matches, - program_output: Process + process_output: Process ) -> Result { let config = default_config(input_crate); @@ -174,11 +178,11 @@ fn config_from_opts( } } }; - let program_output = Cell(program_output); + let process_output = Cell::new(process_output); let result = do result::chain(result) |config| { let pandoc_cmd = getopts::opt_maybe_str(matches, opt_pandoc_cmd()); let pandoc_cmd = maybe_find_pandoc( - &config, pandoc_cmd, program_output.take()); + &config, pandoc_cmd, process_output.take()); do result::chain(pandoc_cmd) |pandoc_cmd| { result::Ok(Config { pandoc_cmd: pandoc_cmd, @@ -208,7 +212,7 @@ fn parse_output_style(output_style: &str) -> Result { pub fn maybe_find_pandoc( config: &Config, maybe_pandoc_cmd: Option<~str>, - program_output: Process + process_output: Process ) -> Result, ~str> { if config.output_format != PandocHtml { return result::Ok(maybe_pandoc_cmd); @@ -227,7 +231,7 @@ pub fn maybe_find_pandoc( }; let pandoc = do vec::find(possible_pandocs) |pandoc| { - let output = program_output(*pandoc, ~[~"--version"]); + let output = process_output(*pandoc, [~"--version"]); debug!("testing pandoc cmd %s: %?", *pandoc, output); output.status == 0 }; @@ -241,11 +245,14 @@ pub fn maybe_find_pandoc( #[cfg(test)] mod test { + use core::prelude::*; + use config::*; - use core::run::ProgramOutput; + use core::result; + use core::run::ProcessOutput; fn parse_config(args: &[~str]) -> Result { - parse_config_(args, mock_program_output) + parse_config_(args, mock_process_output) } #[test] @@ -254,10 +261,10 @@ mod test { output_format: PandocHtml, .. default_config(&Path("test")) }; - let mock_program_output: ~fn(&str, &[~str]) -> ProgramOutput = |_, _| { - ProgramOutput { status: 0, out: ~"pandoc 1.8.2.1", err: ~"" } + let mock_process_output: ~fn(&str, &[~str]) -> ProcessOutput = |_, _| { + ProcessOutput { status: 0, output: "pandoc 1.8.2.1".to_bytes(), error: ~[] } }; - let result = maybe_find_pandoc(&config, None, mock_program_output); + let result = maybe_find_pandoc(&config, None, mock_process_output); assert!(result == result::Ok(Some(~"pandoc"))); } @@ -267,35 +274,35 @@ mod test { output_format: PandocHtml, .. default_config(&Path("test")) }; - let mock_program_output: ~fn(&str, &[~str]) -> ProgramOutput = |_, _| { - ProgramOutput { status: 1, out: ~"", err: ~"" } + let mock_process_output: ~fn(&str, &[~str]) -> ProcessOutput = |_, _| { + ProcessOutput { status: 1, output: ~[], error: ~[] } }; - let result = maybe_find_pandoc(&config, None, mock_program_output); + let result = maybe_find_pandoc(&config, None, mock_process_output); assert!(result == result::Err(~"couldn't find pandoc")); } #[test] fn should_error_with_no_crates() { - let config = parse_config(~[~"rustdoc"]); + let config = parse_config([~"rustdoc"]); assert!(config.get_err() == ~"no crates specified"); } #[test] fn should_error_with_multiple_crates() { let config = - parse_config(~[~"rustdoc", ~"crate1.rc", ~"crate2.rc"]); + parse_config([~"rustdoc", ~"crate1.rc", ~"crate2.rc"]); assert!(config.get_err() == ~"multiple crates specified"); } #[test] fn should_set_output_dir_to_cwd_if_not_provided() { - let config = parse_config(~[~"rustdoc", ~"crate.rc"]); + let config = parse_config([~"rustdoc", ~"crate.rc"]); assert!(config.get().output_dir == Path(".")); } #[test] fn should_set_output_dir_if_provided() { - let config = parse_config(~[ + let config = parse_config([ ~"rustdoc", ~"crate.rc", ~"--output-dir", ~"snuggles" ]); assert!(config.get().output_dir == Path("snuggles")); @@ -303,13 +310,13 @@ mod test { #[test] fn should_set_output_format_to_pandoc_html_if_not_provided() { - let config = parse_config(~[~"rustdoc", ~"crate.rc"]); + let config = parse_config([~"rustdoc", ~"crate.rc"]); assert!(config.get().output_format == PandocHtml); } #[test] fn should_set_output_format_to_markdown_if_requested() { - let config = parse_config(~[ + let config = parse_config([ ~"rustdoc", ~"crate.rc", ~"--output-format", ~"markdown" ]); assert!(config.get().output_format == Markdown); @@ -317,7 +324,7 @@ mod test { #[test] fn should_set_output_format_to_pandoc_html_if_requested() { - let config = parse_config(~[ + let config = parse_config([ ~"rustdoc", ~"crate.rc", ~"--output-format", ~"html" ]); assert!(config.get().output_format == PandocHtml); @@ -325,7 +332,7 @@ mod test { #[test] fn should_error_on_bogus_format() { - let config = parse_config(~[ + let config = parse_config([ ~"rustdoc", ~"crate.rc", ~"--output-format", ~"bogus" ]); assert!(config.get_err() == ~"unknown output format 'bogus'"); @@ -333,13 +340,13 @@ mod test { #[test] fn should_set_output_style_to_doc_per_mod_by_default() { - let config = parse_config(~[~"rustdoc", ~"crate.rc"]); + let config = parse_config([~"rustdoc", ~"crate.rc"]); assert!(config.get().output_style == DocPerMod); } #[test] fn should_set_output_style_to_one_doc_if_requested() { - let config = parse_config(~[ + let config = parse_config([ ~"rustdoc", ~"crate.rc", ~"--output-style", ~"doc-per-crate" ]); assert!(config.get().output_style == DocPerCrate); @@ -347,7 +354,7 @@ mod test { #[test] fn should_set_output_style_to_doc_per_mod_if_requested() { - let config = parse_config(~[ + let config = parse_config([ ~"rustdoc", ~"crate.rc", ~"--output-style", ~"doc-per-mod" ]); assert!(config.get().output_style == DocPerMod); @@ -355,7 +362,7 @@ mod test { #[test] fn should_error_on_bogus_output_style() { - let config = parse_config(~[ + let config = parse_config([ ~"rustdoc", ~"crate.rc", ~"--output-style", ~"bogus" ]); assert!(config.get_err() == ~"unknown output style 'bogus'"); @@ -363,7 +370,7 @@ mod test { #[test] fn should_set_pandoc_command_if_requested() { - let config = parse_config(~[ + let config = parse_config([ ~"rustdoc", ~"crate.rc", ~"--pandoc-cmd", ~"panda-bear-doc" ]); assert!(config.get().pandoc_cmd == Some(~"panda-bear-doc")); @@ -371,7 +378,7 @@ mod test { #[test] fn should_set_pandoc_command_when_using_pandoc() { - let config = parse_config(~[~"rustdoc", ~"crate.rc"]); + let config = parse_config([~"rustdoc", ~"crate.rc"]); assert!(config.get().pandoc_cmd == Some(~"pandoc")); } } diff --git a/src/librustdoc/demo.rs b/src/librustdoc/demo.rs index 7cbd92292c198..c5fb8f289f65e 100644 --- a/src/librustdoc/demo.rs +++ b/src/librustdoc/demo.rs @@ -21,6 +21,8 @@ * tests on this file */ +use core::prelude::*; + /// The base price of a muffin on a non-holiday static price_of_a_muffin: float = 70f; diff --git a/src/librustdoc/desc_to_brief_pass.rs b/src/librustdoc/desc_to_brief_pass.rs index 278f77135f9f5..7a3ab259b1d97 100644 --- a/src/librustdoc/desc_to_brief_pass.rs +++ b/src/librustdoc/desc_to_brief_pass.rs @@ -15,6 +15,8 @@ If the first paragraph of a long description is short enough then it is interpreted as the brief description. */ +use core::prelude::*; + use astsrv; use doc::ItemUtils; use doc; @@ -22,7 +24,9 @@ use fold::Fold; use fold; use pass::Pass; +use core::str; use core::util; +use core::vec; pub fn mk_pass() -> Pass { Pass { @@ -104,7 +108,7 @@ fn first_sentence(s: ~str) -> Option<~str> { let paras = paragraphs(s); if !paras.is_empty() { let first_para = paras.head(); - Some(str::replace(first_sentence_(*first_para), ~"\n", ~" ")) + Some(str::replace(first_sentence_(*first_para), "\n", " ")) } else { None } @@ -132,7 +136,7 @@ fn first_sentence_(s: &str) -> ~str { str::to_owned(str::slice(s, 0, idx - 1)) } _ => { - if str::ends_with(s, ~".") { + if str::ends_with(s, ".") { str::to_owned(s) } else { str::to_owned(s) @@ -164,7 +168,7 @@ pub fn paragraphs(s: &str) -> ~[~str] { accum = if str::is_empty(accum) { copy *line } else { - accum + ~"\n" + *line + accum + "\n" + *line } } @@ -172,7 +176,7 @@ pub fn paragraphs(s: &str) -> ~[~str] { }; if !accum.is_empty() { - paras + ~[accum] + paras + [accum] } else { paras } @@ -180,6 +184,8 @@ pub fn paragraphs(s: &str) -> ~[~str] { #[cfg(test)] mod test { + use core::prelude::*; + use astsrv; use attr_pass; use super::{extract, paragraphs, run}; @@ -197,7 +203,7 @@ mod test { #[test] fn should_promote_desc() { let doc = mk_doc(~"#[doc = \"desc\"] mod m { }"); - assert!(doc.cratemod().mods()[0].brief() == Some(~"desc")); + assert_eq!(doc.cratemod().mods()[0].brief(), Some(~"desc")); } #[test] @@ -216,21 +222,21 @@ mod test { #[test] fn test_paragraphs_1() { - let paras = paragraphs(~"1\n\n2"); - assert!(paras == ~[~"1", ~"2"]); + let paras = paragraphs("1\n\n2"); + assert_eq!(paras, ~[~"1", ~"2"]); } #[test] fn test_paragraphs_2() { - let paras = paragraphs(~"\n\n1\n1\n\n2\n\n"); - assert!(paras == ~[~"1\n1", ~"2"]); + let paras = paragraphs("\n\n1\n1\n\n2\n\n"); + assert_eq!(paras, ~[~"1\n1", ~"2"]); } #[test] fn should_promote_short_descs() { let desc = Some(~"desc"); let brief = extract(copy desc); - assert!(brief == desc); + assert_eq!(brief, desc); } #[test] @@ -244,7 +250,7 @@ Scotland in the mid 12th century, although it may have been built by King Henry II of England when he took control of England'snorthern counties."); let brief = extract(desc); - assert!(brief == None); + assert_eq!(brief, None); } #[test] diff --git a/src/librustdoc/doc.rs b/src/librustdoc/doc.rs index 1656eb0309812..283763c156471 100644 --- a/src/librustdoc/doc.rs +++ b/src/librustdoc/doc.rs @@ -10,8 +10,12 @@ //! The document model +use core::prelude::*; + use doc; +use core::vec; + pub type AstId = int; #[deriving(Eq)] @@ -168,8 +172,8 @@ pub struct IndexEntry { link: ~str } -pub impl Doc { - fn CrateDoc(&self) -> CrateDoc { +impl Doc { + pub fn CrateDoc(&self) -> CrateDoc { vec::foldl(None, self.pages, |_m, page| { match copy *page { doc::CratePage(doc) => Some(doc), @@ -178,14 +182,14 @@ pub impl Doc { }).get() } - fn cratemod(&self) -> ModDoc { + pub fn cratemod(&self) -> ModDoc { copy self.CrateDoc().topmod } } /// Some helper methods on ModDoc, mostly for testing -pub impl ModDoc { - fn mods(&self) -> ~[ModDoc] { +impl ModDoc { + pub fn mods(&self) -> ~[ModDoc] { do vec::filter_mapped(self.items) |itemtag| { match copy *itemtag { ModTag(ModDoc) => Some(ModDoc), @@ -194,7 +198,7 @@ pub impl ModDoc { } } - fn nmods(&self) -> ~[NmodDoc] { + pub fn nmods(&self) -> ~[NmodDoc] { do vec::filter_mapped(self.items) |itemtag| { match copy *itemtag { NmodTag(nModDoc) => Some(nModDoc), @@ -203,7 +207,7 @@ pub impl ModDoc { } } - fn fns(&self) -> ~[FnDoc] { + pub fn fns(&self) -> ~[FnDoc] { do vec::filter_mapped(self.items) |itemtag| { match copy *itemtag { FnTag(FnDoc) => Some(FnDoc), @@ -212,7 +216,7 @@ pub impl ModDoc { } } - fn consts(&self) -> ~[ConstDoc] { + pub fn consts(&self) -> ~[ConstDoc] { do vec::filter_mapped(self.items) |itemtag| { match copy *itemtag { ConstTag(ConstDoc) => Some(ConstDoc), @@ -221,7 +225,7 @@ pub impl ModDoc { } } - fn enums(&self) -> ~[EnumDoc] { + pub fn enums(&self) -> ~[EnumDoc] { do vec::filter_mapped(self.items) |itemtag| { match copy *itemtag { EnumTag(EnumDoc) => Some(EnumDoc), @@ -230,7 +234,7 @@ pub impl ModDoc { } } - fn traits(&self) -> ~[TraitDoc] { + pub fn traits(&self) -> ~[TraitDoc] { do vec::filter_mapped(self.items) |itemtag| { match copy *itemtag { TraitTag(TraitDoc) => Some(TraitDoc), @@ -239,7 +243,7 @@ pub impl ModDoc { } } - fn impls(&self) -> ~[ImplDoc] { + pub fn impls(&self) -> ~[ImplDoc] { do vec::filter_mapped(self.items) |itemtag| { match copy *itemtag { ImplTag(ImplDoc) => Some(ImplDoc), @@ -248,7 +252,7 @@ pub impl ModDoc { } } - fn types(&self) -> ~[TyDoc] { + pub fn types(&self) -> ~[TyDoc] { do vec::filter_mapped(self.items) |itemtag| { match copy *itemtag { TyTag(TyDoc) => Some(TyDoc), @@ -257,7 +261,7 @@ pub impl ModDoc { } } - fn structs(&self) -> ~[StructDoc] { + pub fn structs(&self) -> ~[StructDoc] { do vec::filter_mapped(self.items) |itemtag| { match copy *itemtag { StructTag(StructDoc) => Some(StructDoc), diff --git a/src/librustdoc/escape_pass.rs b/src/librustdoc/escape_pass.rs index 949573be05ebb..045e916b11006 100644 --- a/src/librustdoc/escape_pass.rs +++ b/src/librustdoc/escape_pass.rs @@ -20,12 +20,12 @@ pub fn mk_pass() -> Pass { } fn escape(s: &str) -> ~str { - str::replace(s, ~"\\", ~"\\\\") + str::replace(s, "\\", "\\\\") } #[test] fn should_escape_backslashes() { let s = ~"\\n"; let r = escape(s); - assert!(r == ~"\\\\n"); + assert_eq!(r, ~"\\\\n"); } diff --git a/src/librustdoc/extract.rs b/src/librustdoc/extract.rs index 0c49d457ad809..1175175c2d6b9 100644 --- a/src/librustdoc/extract.rs +++ b/src/librustdoc/extract.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -10,31 +10,27 @@ //! Converts the Rust AST to the rustdoc document model +use core::prelude::*; + use astsrv; use doc::ItemUtils; use doc; -use core::local_data::local_data_get; +use core::vec; use syntax::ast; -use syntax; - -/* can't import macros yet, so this is copied from token.rs. See its comment - * there. */ -macro_rules! interner_key ( - () => (cast::transmute::<(uint, uint), - &fn(v: @@syntax::parse::token::ident_interner)>((-3 as uint, 0u))) -) +use syntax::parse::token::{ident_interner, ident_to_str}; +use syntax::parse::token; // Hack; rather than thread an interner through everywhere, rely on // thread-local data +// Hack-Becomes-Feature: using thread-local-state everywhere... pub fn to_str(id: ast::ident) -> ~str { - let intr = unsafe{ local_data_get(interner_key!()) }; - - return copy *(*intr.get()).get(id); + return copy *ident_to_str(&id); } -pub fn interner() -> @syntax::parse::token::ident_interner { - return *(unsafe{ local_data_get(interner_key!()) }).get(); +// get rid of this pointless function: +pub fn interner() -> @ident_interner { + return token::get_ident_interner(); } pub fn from_srv( diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index 7c66b4f4d4e93..bd999b637c28b 100644 --- a/src/librustdoc/fold.rs +++ b/src/librustdoc/fold.rs @@ -8,10 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use doc; #[cfg(test)] use extract; #[cfg(test)] use parse; +use core::vec; + pub struct Fold { ctxt: T, fold_doc: FoldDoc, @@ -369,7 +373,7 @@ fn default_fold_should_produce_same_doc() { let doc = extract::extract(ast, ~""); let fld = default_seq_fold(()); let folded = (fld.fold_doc)(&fld, copy doc); - assert!(doc == folded); + assert_eq!(doc, folded); } #[test] @@ -379,7 +383,7 @@ fn default_fold_should_produce_same_consts() { let doc = extract::extract(ast, ~""); let fld = default_seq_fold(()); let folded = (fld.fold_doc)(&fld, copy doc); - assert!(doc == folded); + assert_eq!(doc, folded); } #[test] @@ -389,7 +393,7 @@ fn default_fold_should_produce_same_enums() { let doc = extract::extract(ast, ~""); let fld = default_seq_fold(()); let folded = (fld.fold_doc)(&fld, copy doc); - assert!(doc == folded); + assert_eq!(doc, folded); } #[test] @@ -399,5 +403,5 @@ fn default_parallel_fold_should_produce_same_doc() { let doc = extract::extract(ast, ~""); let fld = default_par_fold(()); let folded = (fld.fold_doc)(&fld, copy doc); - assert!(doc == folded); + assert_eq!(doc, folded); } diff --git a/src/librustdoc/markdown_index_pass.rs b/src/librustdoc/markdown_index_pass.rs index 24bfa62305a94..87a73f5c9d3e0 100644 --- a/src/librustdoc/markdown_index_pass.rs +++ b/src/librustdoc/markdown_index_pass.rs @@ -10,6 +10,8 @@ //! Build indexes as appropriate for the markdown pass +use core::prelude::*; + use astsrv; use config; use doc::ItemUtils; @@ -20,6 +22,8 @@ use markdown_pass; use markdown_writer; use pass::Pass; +use core::str; + pub fn mk_pass(config: config::Config) -> Pass { Pass { name: ~"markdown_index", @@ -72,7 +76,7 @@ fn build_mod_index( ) -> doc::Index { doc::Index { entries: doc.items.map(|doc| { - item_to_entry(copy *doc, copy config) + item_to_entry(copy *doc, &config) }) } } @@ -83,14 +87,14 @@ fn build_nmod_index( ) -> doc::Index { doc::Index { entries: doc.fns.map(|doc| { - item_to_entry(doc::FnTag(copy *doc), copy config) + item_to_entry(doc::FnTag(copy *doc), &config) }) } } fn item_to_entry( doc: doc::ItemTag, - config: config::Config + config: &config::Config ) -> doc::IndexEntry { let link = match doc { doc::ModTag(_) | doc::NmodTag(_) @@ -124,24 +128,24 @@ pub fn pandoc_header_id(header: &str) -> ~str { return header; fn remove_formatting(s: &str) -> ~str { - str::replace(s, ~"`", ~"") + str::replace(s, "`", "") } fn remove_punctuation(s: &str) -> ~str { - let s = str::replace(s, ~"<", ~""); - let s = str::replace(s, ~">", ~""); - let s = str::replace(s, ~"[", ~""); - let s = str::replace(s, ~"]", ~""); - let s = str::replace(s, ~"(", ~""); - let s = str::replace(s, ~")", ~""); - let s = str::replace(s, ~"@~", ~""); - let s = str::replace(s, ~"~", ~""); - let s = str::replace(s, ~"/", ~""); - let s = str::replace(s, ~":", ~""); - let s = str::replace(s, ~"&", ~""); - let s = str::replace(s, ~"^", ~""); - let s = str::replace(s, ~",", ~""); - let s = str::replace(s, ~"'", ~""); - let s = str::replace(s, ~"+", ~""); + let s = str::replace(s, "<", ""); + let s = str::replace(s, ">", ""); + let s = str::replace(s, "[", ""); + let s = str::replace(s, "]", ""); + let s = str::replace(s, "(", ""); + let s = str::replace(s, ")", ""); + let s = str::replace(s, "@~", ""); + let s = str::replace(s, "~", ""); + let s = str::replace(s, "/", ""); + let s = str::replace(s, ":", ""); + let s = str::replace(s, "&", ""); + let s = str::replace(s, "^", ""); + let s = str::replace(s, ",", ""); + let s = str::replace(s, "'", ""); + let s = str::replace(s, "+", ""); return s; } fn replace_with_hyphens(s: &str) -> ~str { @@ -149,8 +153,8 @@ pub fn pandoc_header_id(header: &str) -> ~str { // XXX: Hacky implementation here that only covers // one or two spaces. let s = str::trim(s); - let s = str::replace(s, ~" ", ~"-"); - let s = str::replace(s, ~" ", ~"-"); + let s = str::replace(s, " ", "-"); + let s = str::replace(s, " ", "-"); return s; } // FIXME: #4318 Instead of to_ascii and to_str_ascii, could use @@ -162,6 +166,8 @@ pub fn pandoc_header_id(header: &str) -> ~str { #[cfg(test)] mod test { + use core::prelude::*; + use astsrv; use attr_pass; use config; @@ -189,27 +195,27 @@ mod test { #[test] fn should_remove_punctuation_from_headers() { - assert!(pandoc_header_id(~"impl foo of bar") == + assert!(pandoc_header_id("impl foo of bar") == ~"impl-foo-of-bara"); - assert!(pandoc_header_id(~"impl of num::num for int") + assert!(pandoc_header_id("impl of num::num for int") == ~"impl-of-numnum-for-int"); - assert!(pandoc_header_id(~"impl of num::num for int/&") + assert!(pandoc_header_id("impl of num::num for int/&") == ~"impl-of-numnum-for-int"); - assert!(pandoc_header_id(~"impl of num::num for ^int") + assert!(pandoc_header_id("impl of num::num for ^int") == ~"impl-of-numnum-for-int"); - assert!(pandoc_header_id(~"impl for & condvar") + assert!(pandoc_header_id("impl for & condvar") == ~"impl-for-condvar"); - assert!(pandoc_header_id(~"impl of Select for (Left, Right)") + assert!(pandoc_header_id("impl of Select for (Left, Right)") == ~"impl-of-selectt-u-for-left-right"); - assert!(pandoc_header_id(~"impl of Condition<'self, T, U>") + assert!(pandoc_header_id("impl of Condition<'self, T, U>") == ~"impl-of-conditionself-t-u"); - assert!(pandoc_header_id(~"impl of Condition") + assert!(pandoc_header_id("impl of Condition") == ~"impl-of-conditiont-copy-clone"); } #[test] fn should_trim_whitespace_after_removing_punctuation() { - assert!(pandoc_header_id("impl foo for ()") == ~"impl-foo-for"); + assert_eq!(pandoc_header_id("impl foo for ()"), ~"impl-foo-for"); } #[test] @@ -218,13 +224,13 @@ mod test { config::DocPerCrate, ~"mod a { } fn b() { }" ); - assert!((&doc.cratemod().index).get().entries[0] == doc::IndexEntry { + assert!(doc.cratemod().index.get().entries[0] == doc::IndexEntry { kind: ~"Module", name: ~"a", brief: None, link: ~"#module-a" }); - assert!((&doc.cratemod().index).get().entries[1] == doc::IndexEntry { + assert!(doc.cratemod().index.get().entries[1] == doc::IndexEntry { kind: ~"Function", name: ~"b", brief: None, @@ -238,13 +244,13 @@ mod test { config::DocPerMod, ~"mod a { } fn b() { }" ); - assert!((&doc.cratemod().index).get().entries[0] == doc::IndexEntry { + assert!(doc.cratemod().index.get().entries[0] == doc::IndexEntry { kind: ~"Module", name: ~"a", brief: None, link: ~"a.html" }); - assert!((&doc.cratemod().index).get().entries[1] == doc::IndexEntry { + assert!(doc.cratemod().index.get().entries[1] == doc::IndexEntry { kind: ~"Function", name: ~"b", brief: None, @@ -258,7 +264,7 @@ mod test { config::DocPerMod, ~"#[doc = \"test\"] mod a { }" ); - assert!((&doc.cratemod().index).get().entries[0].brief + assert!(doc.cratemod().index.get().entries[0].brief == Some(~"test")); } @@ -268,7 +274,7 @@ mod test { config::DocPerCrate, ~"extern { fn b(); }" ); - assert!((&doc.cratemod().nmods()[0].index).get().entries[0] + assert!(doc.cratemod().nmods()[0].index.get().entries[0] == doc::IndexEntry { kind: ~"Function", name: ~"b", diff --git a/src/librustdoc/markdown_pass.rs b/src/librustdoc/markdown_pass.rs index a42c4738b2de7..b17816d4e3652 100644 --- a/src/librustdoc/markdown_pass.rs +++ b/src/librustdoc/markdown_pass.rs @@ -10,6 +10,8 @@ //! Generate markdown from a document tree +use core::prelude::*; + use astsrv; use doc::ItemUtils; use doc; @@ -21,10 +23,12 @@ use pass::Pass; use sort_pass; use core::cell::Cell; +use core::str; +use core::vec; use syntax; pub fn mk_pass(writer_factory: WriterFactory) -> Pass { - let writer_factory = Cell(writer_factory); + let writer_factory = Cell::new(writer_factory); Pass { name: ~"markdown", f: |srv, doc| run(srv, doc, writer_factory.take()) @@ -110,7 +114,7 @@ fn make_title(page: doc::Page) -> ~str { } }; let title = markdown_pass::header_text(item); - let title = str::replace(title, ~"`", ~""); + let title = str::replace(title, "`", ""); return title; } @@ -169,7 +173,7 @@ pub fn header_kind(doc: doc::ItemTag) -> ~str { } pub fn header_name(doc: doc::ItemTag) -> ~str { - let fullpath = str::connect(doc.path() + ~[doc.name()], ~"::"); + let fullpath = str::connect(doc.path() + [doc.name()], "::"); match &doc { &doc::ModTag(_) if doc.id() != syntax::ast::crate_node_id => { fullpath @@ -179,22 +183,22 @@ pub fn header_name(doc: doc::ItemTag) -> ~str { } &doc::ImplTag(ref doc) => { assert!(doc.self_ty.is_some()); - let bounds = if (&doc.bounds_str).is_some() { - fmt!(" where %s", (&doc.bounds_str).get()) + let bounds = if doc.bounds_str.is_some() { + fmt!(" where %s", *doc.bounds_str.get_ref()) } else { ~"" }; - let self_ty = (&doc.self_ty).get(); + let self_ty = doc.self_ty.get_ref(); let mut trait_part = ~""; for doc.trait_types.eachi |i, trait_type| { if i == 0 { - trait_part += ~" of "; + trait_part += " of "; } else { - trait_part += ~", "; + trait_part += ", "; } trait_part += *trait_type; } - fmt!("%s for %s%s", trait_part, self_ty, bounds) + fmt!("%s for %s%s", trait_part, *self_ty, bounds) } _ => { doc.name() @@ -206,17 +210,17 @@ pub fn header_text(doc: doc::ItemTag) -> ~str { match &doc { &doc::ImplTag(ref ImplDoc) => { let header_kind = header_kind(copy doc); - let bounds = if (&ImplDoc.bounds_str).is_some() { - fmt!(" where `%s`", (&ImplDoc.bounds_str).get()) + let bounds = if ImplDoc.bounds_str.is_some() { + fmt!(" where `%s`", *ImplDoc.bounds_str.get_ref()) } else { ~"" }; let desc = if ImplDoc.trait_types.is_empty() { - fmt!("for `%s`%s", (&ImplDoc.self_ty).get(), bounds) + fmt!("for `%s`%s", *ImplDoc.self_ty.get_ref(), bounds) } else { fmt!("of `%s` for `%s`%s", ImplDoc.trait_types[0], - (&ImplDoc.self_ty).get(), + *ImplDoc.self_ty.get_ref(), bounds) }; return fmt!("%s %s", header_kind, desc); @@ -293,7 +297,7 @@ fn write_mod_contents( ) { write_common(ctxt, doc.desc(), doc.sections()); if doc.index.is_some() { - write_index(ctxt, (&doc.index).get()); + write_index(ctxt, doc.index.get_ref()); } for doc.items.each |itemTag| { @@ -338,7 +342,7 @@ fn item_header_lvl(doc: &doc::ItemTag) -> Hlvl { } } -fn write_index(ctxt: &Ctxt, index: doc::Index) { +fn write_index(ctxt: &Ctxt, index: &doc::Index) { if vec::is_empty(index.entries) { return; } @@ -351,7 +355,7 @@ fn write_index(ctxt: &Ctxt, index: doc::Index) { let id = copy entry.link; if entry.brief.is_some() { ctxt.w.put_line(fmt!("* [%s](%s) - %s", - header, id, (&entry.brief).get())); + header, id, *entry.brief.get_ref())); } else { ctxt.w.put_line(fmt!("* [%s](%s)", header, id)); } @@ -364,7 +368,7 @@ fn write_index(ctxt: &Ctxt, index: doc::Index) { fn write_nmod(ctxt: &Ctxt, doc: doc::NmodDoc) { write_common(ctxt, doc.desc(), doc.sections()); if doc.index.is_some() { - write_index(ctxt, (&doc.index).get()); + write_index(ctxt, doc.index.get_ref()); } for doc.fns.each |FnDoc| { @@ -448,17 +452,33 @@ fn write_variants( fn write_variant(ctxt: &Ctxt, doc: doc::VariantDoc) { assert!(doc.sig.is_some()); - let sig = (&doc.sig).get(); + let sig = doc.sig.get_ref(); + + // space out list items so they all end up within paragraph elements + ctxt.w.put_line(~""); + match copy doc.desc { Some(desc) => { - ctxt.w.put_line(fmt!("* `%s` - %s", sig, desc)); + ctxt.w.put_line(list_item_indent(fmt!("* `%s` - %s", *sig, desc))); } None => { - ctxt.w.put_line(fmt!("* `%s`", sig)); + ctxt.w.put_line(fmt!("* `%s`", *sig)); } } } +fn list_item_indent(item: &str) -> ~str { + let mut indented = ~[]; + for str::each_line_any(item) |line| { + indented.push(line); + } + + // separate markdown elements within `*` lists must be indented by four + // spaces, or they will escape the list context. indenting everything + // seems fine though. + str::connect_slices(indented, "\n ") +} + fn write_trait(ctxt: &Ctxt, doc: doc::TraitDoc) { write_common(ctxt, doc.desc(), doc.sections()); write_methods(ctxt, doc.methods); @@ -471,7 +491,7 @@ fn write_methods(ctxt: &Ctxt, docs: &[doc::MethodDoc]) { } fn write_method(ctxt: &Ctxt, doc: doc::MethodDoc) { - write_header_(ctxt, H3, header_text_(~"Method", doc.name)); + write_header_(ctxt, H3, header_text_("Method", doc.name)); write_fnlike( ctxt, copy doc.sig, @@ -503,6 +523,8 @@ fn put_struct( #[cfg(test)] mod test { + use core::prelude::*; + use astsrv; use attr_pass; use config; @@ -519,6 +541,8 @@ mod test { use tystr_pass; use unindent_pass; + use core::str; + fn render(source: ~str) -> ~str { let (srv, doc) = create_doc_srv(source); let markdown = write_markdown_str_srv(srv, doc); @@ -583,13 +607,13 @@ mod test { #[test] fn write_markdown_should_write_mod_headers() { let markdown = render(~"mod moo { }"); - assert!(str::contains(markdown, ~"# Module `moo`")); + assert!(str::contains(markdown, "# Module `moo`")); } #[test] fn should_leave_blank_line_after_header() { let markdown = render(~"mod morp { }"); - assert!(str::contains(markdown, ~"Module `morp`\n\n")); + assert!(str::contains(markdown, "Module `morp`\n\n")); } #[test] @@ -609,10 +633,10 @@ mod test { fn d() { }" ); - let idx_a = str::find_str(markdown, ~"# Module `a`").get(); - let idx_b = str::find_str(markdown, ~"## Function `b`").get(); - let idx_c = str::find_str(markdown, ~"# Module `c`").get(); - let idx_d = str::find_str(markdown, ~"## Function `d`").get(); + let idx_a = str::find_str(markdown, "# Module `a`").get(); + let idx_b = str::find_str(markdown, "## Function `b`").get(); + let idx_c = str::find_str(markdown, "# Module `c`").get(); + let idx_d = str::find_str(markdown, "## Function `d`").get(); assert!(idx_b < idx_d); assert!(idx_d < idx_a); @@ -629,7 +653,7 @@ mod test { let doc = (page_pass::mk_pass(config::DocPerMod).f)(srv, doc); write_markdown(doc, writer_factory); // We expect two pages to have been written - for old_iter::repeat(2) { + for 2.times { po.recv(); } } @@ -641,14 +665,14 @@ mod test { ~"#[link(name = \"core\")]; mod a { }"); let doc = (page_pass::mk_pass(config::DocPerMod).f)(srv, doc); write_markdown(doc, writer_factory); - for old_iter::repeat(2) { + for 2.times { let (page, markdown) = po.recv(); match page { doc::CratePage(_) => { - assert!(str::contains(markdown, ~"% Crate core")); + assert!(str::contains(markdown, "% Crate core")); } doc::ItemPage(_) => { - assert!(str::contains(markdown, ~"% Module a")); + assert!(str::contains(markdown, "% Module a")); } } } @@ -657,7 +681,7 @@ mod test { #[test] fn should_write_full_path_to_mod() { let markdown = render(~"mod a { mod b { mod c { } } }"); - assert!(str::contains(markdown, ~"# Module `a::b::c`")); + assert!(str::contains(markdown, "# Module `a::b::c`")); } #[test] @@ -668,13 +692,13 @@ mod test { Body\"]\ mod a { }"); - assert!(str::contains(markdown, ~"#### Header\n\nBody\n\n")); + assert!(str::contains(markdown, "#### Header\n\nBody\n\n")); } #[test] fn should_write_crate_description() { let markdown = render(~"#[doc = \"this is the crate\"];"); - assert!(str::contains(markdown, ~"this is the crate")); + assert!(str::contains(markdown, "this is the crate")); } @@ -683,21 +707,21 @@ mod test { let markdown = render(~"mod a { } mod b { }"); assert!(str::contains( markdown, - ~"\n\n* [Module `a`](#module-a)\n\ - * [Module `b`](#module-b)\n\n" + "\n\n* [Module `a`](#module-a)\n\ + * [Module `b`](#module-b)\n\n" )); } #[test] fn should_write_index_brief() { let markdown = render(~"#[doc = \"test\"] mod a { }"); - assert!(str::contains(markdown, ~"(#module-a) - test\n")); + assert!(str::contains(markdown, "(#module-a) - test\n")); } #[test] fn should_not_write_index_if_no_entries() { let markdown = render(~""); - assert!(!str::contains(markdown, ~"\n\n\n")); + assert!(!str::contains(markdown, "\n\n\n")); } #[test] @@ -705,7 +729,7 @@ mod test { let markdown = render(~"extern { fn a(); }"); assert!(str::contains( markdown, - ~"\n\n* [Function `a`](#function-a)\n\n" + "\n\n* [Function `a`](#function-a)\n\n" )); } @@ -713,32 +737,32 @@ mod test { fn should_write_foreign_fns() { let markdown = render( ~"extern { #[doc = \"test\"] fn a(); }"); - assert!(str::contains(markdown, ~"test")); + assert!(str::contains(markdown, "test")); } #[test] fn should_write_foreign_fn_headers() { let markdown = render( ~"extern { #[doc = \"test\"] fn a(); }"); - assert!(str::contains(markdown, ~"## Function `a`")); + assert!(str::contains(markdown, "## Function `a`")); } #[test] fn write_markdown_should_write_function_header() { let markdown = render(~"fn func() { }"); - assert!(str::contains(markdown, ~"## Function `func`")); + assert!(str::contains(markdown, "## Function `func`")); } #[test] fn should_write_the_function_signature() { let markdown = render(~"#[doc = \"f\"] fn a() { }"); - assert!(str::contains(markdown, ~"\n fn a()\n")); + assert!(str::contains(markdown, "\n fn a()\n")); } #[test] fn should_insert_blank_line_after_fn_signature() { let markdown = render(~"#[doc = \"f\"] fn a() { }"); - assert!(str::contains(markdown, ~"fn a()\n\n")); + assert!(str::contains(markdown, "fn a()\n\n")); } #[test] @@ -759,19 +783,19 @@ mod test { ] }; let markdown = write_markdown_str(doc); - assert!(str::contains(markdown, ~" line 1\n line 2")); + assert!(str::contains(markdown, " line 1\n line 2")); } #[test] fn should_leave_blank_line_between_fn_header_and_sig() { let markdown = render(~"fn a() { }"); - assert!(str::contains(markdown, ~"Function `a`\n\n fn a()")); + assert!(str::contains(markdown, "Function `a`\n\n fn a()")); } #[test] fn should_write_const_header() { let markdown = render(~"static a: bool = true;"); - assert!(str::contains(markdown, ~"## Const `a`\n\n")); + assert!(str::contains(markdown, "## Const `a`\n\n")); } #[test] @@ -779,20 +803,19 @@ mod test { let markdown = render( ~"#[doc = \"b\"]\ static a: bool = true;"); - assert!(str::contains(markdown, ~"\n\nb\n\n")); + assert!(str::contains(markdown, "\n\nb\n\n")); } #[test] fn should_write_enum_header() { let markdown = render(~"enum a { b }"); - assert!(str::contains(markdown, ~"## Enum `a`\n\n")); + assert!(str::contains(markdown, "## Enum `a`\n\n")); } #[test] fn should_write_enum_description() { - let markdown = render( - ~"#[doc = \"b\"] enum a { b }"); - assert!(str::contains(markdown, ~"\n\nb\n\n")); + let markdown = render(~"#[doc = \"b\"] enum a { b }"); + assert!(str::contains(markdown, "\n\nb\n\n")); } #[test] @@ -803,9 +826,11 @@ mod test { #[doc = \"test\"] c }"); assert!(str::contains( markdown, - ~"\n\n#### Variants\n\ - \n* `b` - test\ - \n* `c` - test\n\n")); + "\n\n#### Variants\n\ + \n\ + \n* `b` - test\ + \n\ + \n* `c` - test\n\n")); } #[test] @@ -813,9 +838,26 @@ mod test { let markdown = render(~"enum a { b, c }"); assert!(str::contains( markdown, - ~"\n\n#### Variants\n\ - \n* `b`\ - \n* `c`\n\n")); + "\n\n#### Variants\n\ + \n\ + \n* `b`\ + \n\ + \n* `c`\n\n")); + } + + #[test] + fn should_write_variant_list_with_indent() { + let markdown = render( + ~"enum a { #[doc = \"line 1\\n\\nline 2\"] b, c }"); + assert!(str::contains( + markdown, + "\n\n#### Variants\n\ + \n\ + \n* `b` - line 1\ + \n \ + \n line 2\ + \n\ + \n* `c`\n\n")); } #[test] @@ -823,100 +865,99 @@ mod test { let markdown = render(~"enum a { b(int), #[doc = \"a\"] c(int) }"); assert!(str::contains( markdown, - ~"\n\n#### Variants\n\ - \n* `b(int)`\ - \n* `c(int)` - a\n\n")); + "\n\n#### Variants\n\ + \n\ + \n* `b(int)`\ + \n\ + \n* `c(int)` - a\n\n")); } #[test] fn should_write_trait_header() { let markdown = render(~"trait i { fn a(); }"); - assert!(str::contains(markdown, ~"## Trait `i`")); + assert!(str::contains(markdown, "## Trait `i`")); } #[test] fn should_write_trait_desc() { - let markdown = render( - ~"#[doc = \"desc\"] trait i { fn a(); }"); - assert!(str::contains(markdown, ~"desc")); + let markdown = render(~"#[doc = \"desc\"] trait i { fn a(); }"); + assert!(str::contains(markdown, "desc")); } #[test] fn should_write_trait_method_header() { - let markdown = render( - ~"trait i { fn a(); }"); - assert!(str::contains(markdown, ~"### Method `a`")); + let markdown = render(~"trait i { fn a(); }"); + assert!(str::contains(markdown, "### Method `a`")); } #[test] fn should_write_trait_method_signature() { - let markdown = render( - ~"trait i { fn a(&self); }"); - assert!(str::contains(markdown, ~"\n fn a(&self)")); + let markdown = render(~"trait i { fn a(&self); }"); + assert!(str::contains(markdown, "\n fn a(&self)")); } #[test] fn should_write_impl_header() { let markdown = render(~"impl int { fn a() { } }"); - assert!(str::contains(markdown, ~"## Implementation for `int`")); + assert!(str::contains(markdown, "## Implementation for `int`")); } #[test] fn should_write_impl_header_with_bounds() { let markdown = render(~"impl int { }"); - assert!(str::contains(markdown, ~"## Implementation for `int` where ``")); + assert!(str::contains(markdown, "## Implementation for `int` where ``")); } #[test] fn should_write_impl_header_with_trait() { let markdown = render(~"impl j for int { fn a() { } }"); assert!(str::contains(markdown, - ~"## Implementation of `j` for `int`")); + "## Implementation of `j` for `int`")); } #[test] fn should_write_impl_desc() { let markdown = render( ~"#[doc = \"desc\"] impl int { fn a() { } }"); - assert!(str::contains(markdown, ~"desc")); + assert!(str::contains(markdown, "desc")); } #[test] fn should_write_impl_method_header() { let markdown = render( ~"impl int { fn a() { } }"); - assert!(str::contains(markdown, ~"### Method `a`")); + assert!(str::contains(markdown, "### Method `a`")); } #[test] fn should_write_impl_method_signature() { let markdown = render( ~"impl int { fn a(&mut self) { } }"); - assert!(str::contains(markdown, ~"\n fn a(&mut self)")); + assert!(str::contains(markdown, "\n fn a(&mut self)")); } #[test] fn should_write_type_header() { let markdown = render(~"type t = int;"); - assert!(str::contains(markdown, ~"## Type `t`")); + assert!(str::contains(markdown, "## Type `t`")); } #[test] fn should_write_type_desc() { let markdown = render( ~"#[doc = \"desc\"] type t = int;"); - assert!(str::contains(markdown, ~"\n\ndesc\n\n")); + assert!(str::contains(markdown, "\n\ndesc\n\n")); } #[test] fn should_write_type_signature() { let markdown = render(~"type t = int;"); - assert!(str::contains(markdown, ~"\n\n type t = int\n\n")); + assert!(str::contains(markdown, "\n\n type t = int\n\n")); } #[test] fn should_put_struct_header() { let markdown = render(~"struct S { field: () }"); - assert!(str::contains(markdown, ~"## Struct `S`\n\n")); + assert!(str::contains(markdown, "## Struct `S`\n\n")); } } diff --git a/src/librustdoc/markdown_writer.rs b/src/librustdoc/markdown_writer.rs index 456a5f09a8800..7bcfa1acdfad2 100644 --- a/src/librustdoc/markdown_writer.rs +++ b/src/librustdoc/markdown_writer.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,14 +8,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use config; use doc::ItemUtils; use doc; -use core::libc; -use core::run; use core::comm::*; -use std::future; +use core::comm; +use core::io; +use core::result; +use core::run; +use core::str; +use core::task; +use extra::future; pub enum WriteInstr { Write(~str), @@ -37,7 +43,7 @@ impl WriterUtils for Writer { } fn put_line(&self, str: ~str) { - self.put_str(str + ~"\n"); + self.put_str(str + "\n"); } fn put_done(&self) { @@ -58,20 +64,20 @@ pub fn make_writer_factory(config: config::Config) -> WriterFactory { fn markdown_writer_factory(config: config::Config) -> WriterFactory { let result: ~fn(page: doc::Page) -> Writer = |page| { - markdown_writer(copy config, page) + markdown_writer(&config, page) }; result } fn pandoc_writer_factory(config: config::Config) -> WriterFactory { let result: ~fn(doc::Page) -> Writer = |page| { - pandoc_writer(copy config, page) + pandoc_writer(&config, page) }; result } fn markdown_writer( - config: config::Config, + config: &config::Config, page: doc::Page ) -> Writer { let filename = make_local_filename(config, page); @@ -81,11 +87,11 @@ fn markdown_writer( } fn pandoc_writer( - config: config::Config, + config: &config::Config, page: doc::Page ) -> Writer { assert!(config.pandoc_cmd.is_some()); - let pandoc_cmd = (&config.pandoc_cmd).get(); + let pandoc_cmd = copy *config.pandoc_cmd.get_ref(); let filename = make_local_filename(config, page); let pandoc_args = ~[ @@ -101,62 +107,22 @@ fn pandoc_writer( use core::io::WriterUtil; debug!("pandoc cmd: %s", pandoc_cmd); - debug!("pandoc args: %s", str::connect(pandoc_args, ~" ")); - - let pipe_in = os::pipe(); - let pipe_out = os::pipe(); - let pipe_err = os::pipe(); - let pid = run::spawn_process( - pandoc_cmd, pandoc_args, &None, &None, - pipe_in.in, pipe_out.out, pipe_err.out); - - let writer = io::fd_writer(pipe_in.out, false); - writer.write_str(markdown); - - os::close(pipe_in.in); - os::close(pipe_out.out); - os::close(pipe_err.out); - os::close(pipe_in.out); - - let (stdout_po, stdout_ch) = comm::stream(); - do task::spawn_sched(task::SingleThreaded) || { - stdout_ch.send(readclose(pipe_out.in)); - } + debug!("pandoc args: %s", str::connect(pandoc_args, " ")); - let (stderr_po, stderr_ch) = comm::stream(); - do task::spawn_sched(task::SingleThreaded) || { - stderr_ch.send(readclose(pipe_err.in)); - } - let stdout = stdout_po.recv(); - let stderr = stderr_po.recv(); - - let status = run::waitpid(pid); - debug!("pandoc result: %i", status); - if status != 0 { - error!("pandoc-out: %s", stdout); - error!("pandoc-err: %s", stderr); + let mut proc = run::Process::new(pandoc_cmd, pandoc_args, run::ProcessOptions::new()); + + proc.input().write_str(markdown); + let output = proc.finish_with_output(); + + debug!("pandoc result: %i", output.status); + if output.status != 0 { + error!("pandoc-out: %s", str::from_bytes(output.output)); + error!("pandoc-err: %s", str::from_bytes(output.error)); fail!("pandoc failed"); } } } -fn readclose(fd: libc::c_int) -> ~str { - // Copied from run::program_output - unsafe { - let file = os::fdopen(fd); - let reader = io::FILE_reader(file, false); - let buf = io::with_bytes_writer(|writer| { - let mut bytes = [0, ..4096]; - while !reader.eof() { - let nread = reader.read(bytes, bytes.len()); - writer.write(bytes.slice(0, nread).to_owned()); - } - }); - os::fclose(file); - str::from_bytes(buf) - } -} - fn generic_writer(process: ~fn(markdown: ~str)) -> Writer { let (po, ch) = stream::(); do task::spawn || { @@ -175,15 +141,15 @@ fn generic_writer(process: ~fn(markdown: ~str)) -> Writer { } pub fn make_local_filename( - config: config::Config, + config: &config::Config, page: doc::Page ) -> Path { - let filename = make_filename(copy config, page); + let filename = make_filename(config, page); config.output_dir.push_rel(&filename) } pub fn make_filename( - config: config::Config, + config: &config::Config, page: doc::Page ) -> Path { let filename = { @@ -198,7 +164,7 @@ pub fn make_filename( } } doc::ItemPage(doc) => { - str::connect(doc.path() + ~[doc.name()], ~"_") + str::connect(doc.path() + [doc.name()], "_") } } }; @@ -213,7 +179,7 @@ pub fn make_filename( fn write_file(path: &Path, s: ~str) { use core::io::WriterUtil; - match io::file_writer(path, ~[io::Create, io::Truncate]) { + match io::file_writer(path, [io::Create, io::Truncate]) { result::Ok(writer) => { writer.write_str(s); } @@ -259,6 +225,8 @@ fn future_writer() -> (Writer, future::Future<~str>) { #[cfg(test)] mod test { + use core::prelude::*; + use astsrv; use doc; use extract; @@ -284,8 +252,8 @@ mod test { }; let doc = mk_doc(~"test", ~""); let page = doc::CratePage(doc.CrateDoc()); - let filename = make_local_filename(config, page); - assert!(filename.to_str() == ~"output/dir/test.md"); + let filename = make_local_filename(&config, page); + assert_eq!(filename.to_str(), ~"output/dir/test.md"); } #[test] @@ -298,8 +266,8 @@ mod test { }; let doc = mk_doc(~"", ~""); let page = doc::CratePage(doc.CrateDoc()); - let filename = make_local_filename(config, page); - assert!(filename.to_str() == ~"output/dir/index.html"); + let filename = make_local_filename(&config, page); + assert_eq!(filename.to_str(), ~"output/dir/index.html"); } #[test] @@ -313,7 +281,7 @@ mod test { let doc = mk_doc(~"", ~"mod a { mod b { } }"); let modb = copy doc.cratemod().mods()[0].mods()[0]; let page = doc::ItemPage(doc::ModTag(modb)); - let filename = make_local_filename(config, page); - assert!(filename == Path("output/dir/a_b.html")); + let filename = make_local_filename(&config, page); + assert_eq!(filename, Path("output/dir/a_b.html")); } } diff --git a/src/librustdoc/page_pass.rs b/src/librustdoc/page_pass.rs index 89a3acc6cac71..29a6765f16d53 100644 --- a/src/librustdoc/page_pass.rs +++ b/src/librustdoc/page_pass.rs @@ -15,6 +15,8 @@ Each page corresponds is a logical section. There may be pages for individual modules, pages for the crate, indexes, etc. */ +use core::prelude::*; + use astsrv; use config; use doc::ItemUtils; @@ -25,6 +27,7 @@ use pass::Pass; use util::NominalOp; use core::comm::*; +use core::task; use syntax::ast; #[cfg(test)] use doc::PageUtils; @@ -67,7 +70,7 @@ fn make_doc_from_pages(page_port: &PagePort) -> doc::Doc { loop { let val = page_port.recv(); if val.is_some() { - pages += ~[val.unwrap()]; + pages += [val.unwrap()]; } else { break; } @@ -176,13 +179,13 @@ mod test { config::DocPerCrate, ~"mod a { } mod b { mod c { } }" ); - assert!(doc.pages.len() == 1u); + assert_eq!(doc.pages.len(), 1u); } #[test] fn should_make_a_page_for_every_mod() { let doc = mk_doc(~"mod a { }"); - assert!(doc.pages.mods()[0].name() == ~"a"); + assert_eq!(doc.pages.mods()[0].name(), ~"a"); } #[test] diff --git a/src/librustdoc/parse.rs b/src/librustdoc/parse.rs index 1f4133592f242..455720f47ef90 100644 --- a/src/librustdoc/parse.rs +++ b/src/librustdoc/parse.rs @@ -10,6 +10,8 @@ //! AST-parsing helpers +use core::prelude::*; + use rustc::driver::driver::{file_input, str_input}; use rustc::driver::driver; use rustc::driver::session; diff --git a/src/librustdoc/pass.rs b/src/librustdoc/pass.rs index b80f43a7bbd06..8a51339c89669 100644 --- a/src/librustdoc/pass.rs +++ b/src/librustdoc/pass.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + +use core::vec; + use astsrv; use doc; use time; @@ -46,7 +50,7 @@ fn test_run_passes() { doc::CratePage(doc::CrateDoc{ topmod: doc::ModDoc{ item: doc::ItemDoc { - name: doc.cratemod().name() + ~"two", + name: doc.cratemod().name() + "two", .. copy doc.cratemod().item }, items: ~[], @@ -65,7 +69,7 @@ fn test_run_passes() { doc::CratePage(doc::CrateDoc{ topmod: doc::ModDoc{ item: doc::ItemDoc { - name: doc.cratemod().name() + ~"three", + name: doc.cratemod().name() + "three", .. copy doc.cratemod().item }, items: ~[], @@ -89,6 +93,6 @@ fn test_run_passes() { ]; let doc = extract::from_srv(srv.clone(), ~"one"); let doc = run_passes(srv, doc, passes); - assert!(doc.cratemod().name() == ~"onetwothree"); + assert_eq!(doc.cratemod().name(), ~"onetwothree"); } } diff --git a/src/librustdoc/path_pass.rs b/src/librustdoc/path_pass.rs index 5560f21af61db..a7a36152ace39 100644 --- a/src/librustdoc/path_pass.rs +++ b/src/librustdoc/path_pass.rs @@ -10,6 +10,8 @@ //! Records the full path to items +use core::prelude::*; + use astsrv; use doc::ItemUtils; use doc; @@ -109,6 +111,6 @@ fn should_record_fn_paths() { do astsrv::from_str(source) |srv| { let doc = extract::from_srv(srv.clone(), ~""); let doc = run(srv.clone(), doc); - assert!(doc.cratemod().mods()[0].fns()[0].path() == ~[~"a"]); + assert_eq!(doc.cratemod().mods()[0].fns()[0].path(), ~[~"a"]); } } diff --git a/src/librustdoc/prune_private_pass.rs b/src/librustdoc/prune_private_pass.rs index 086b5f476016c..a2fa80daa3ba2 100644 --- a/src/librustdoc/prune_private_pass.rs +++ b/src/librustdoc/prune_private_pass.rs @@ -10,6 +10,8 @@ //! Prune things that are private +use core::prelude::*; + use extract; use syntax::ast; use syntax::ast_map; @@ -194,7 +196,7 @@ mod test { pub fn bar() { }\ fn baz() { }\ }"); - assert!(doc.cratemod().impls()[0].methods.len() == 1); + assert_eq!(doc.cratemod().impls()[0].methods.len(), 1); } #[test] @@ -204,43 +206,43 @@ mod test { pub fn bar() { }\ priv fn baz() { }\ }"); - assert!(doc.cratemod().impls()[0].methods.len() == 1); + assert_eq!(doc.cratemod().impls()[0].methods.len(), 1); } #[test] fn should_prune_priv_associated_methods_on_pub_impls() { let doc = mk_doc( - ~"pub impl Foo {\ - fn bar() { }\ + ~"impl Foo {\ + pub fn bar() { }\ priv fn baz() { }\ }"); - assert!(doc.cratemod().impls()[0].methods.len() == 1); + assert_eq!(doc.cratemod().impls()[0].methods.len(), 1); } #[test] fn should_prune_associated_methods_without_vis_modifier_on_priv_impls() { let doc = mk_doc( - ~"priv impl Foo {\ + ~"impl Foo {\ pub fn bar() { }\ fn baz() { }\ }"); - assert!(doc.cratemod().impls()[0].methods.len() == 1); + assert_eq!(doc.cratemod().impls()[0].methods.len(), 1); } #[test] fn should_prune_priv_associated_methods_on_priv_impls() { let doc = mk_doc( - ~"priv impl Foo {\ + ~"impl Foo {\ pub fn bar() { }\ priv fn baz() { }\ }"); - assert!(doc.cratemod().impls()[0].methods.len() == 1); + assert_eq!(doc.cratemod().impls()[0].methods.len(), 1); } #[test] fn should_prune_associated_impls_with_no_pub_methods() { let doc = mk_doc( - ~"priv impl Foo {\ + ~"impl Foo {\ fn baz() { }\ }"); assert!(doc.cratemod().impls().is_empty()); diff --git a/src/librustdoc/rustdoc.rc b/src/librustdoc/rustdoc.rc index 333ea5bce2fde..7ed5d5f551630 100644 --- a/src/librustdoc/rustdoc.rc +++ b/src/librustdoc/rustdoc.rc @@ -21,9 +21,15 @@ #[allow(non_implicitly_copyable_typarams)]; -extern mod std(vers = "0.7-pre"); -extern mod rustc(vers = "0.7-pre"); -extern mod syntax(vers = "0.7-pre"); +#[no_std]; + +extern mod core(name = "std"); +extern mod extra(name = "extra"); + +extern mod rustc; +extern mod syntax; + +use core::prelude::*; use config::Config; use doc::Item; @@ -60,6 +66,15 @@ pub mod escape_pass; pub mod prune_private_pass; pub mod util; +mod std { + pub use core::clone; + pub use core::cmp; + pub use core::os; + pub use core::str; + pub use core::sys; + pub use core::unstable; +} + pub fn main() { let args = os::args(); @@ -139,9 +154,9 @@ fn run(config: Config) { } pub fn time(what: ~str, f: &fn() -> T) -> T { - let start = std::time::precise_time_s(); + let start = extra::time::precise_time_s(); let rv = f(); - let end = std::time::precise_time_s(); + let end = extra::time::precise_time_s(); info!("time: %3.3f s %s", end - start, what); rv } diff --git a/src/librustdoc/sectionalize_pass.rs b/src/librustdoc/sectionalize_pass.rs index c69f3b13e26d8..1a475879fc10b 100644 --- a/src/librustdoc/sectionalize_pass.rs +++ b/src/librustdoc/sectionalize_pass.rs @@ -10,6 +10,8 @@ //! Breaks rustdocs into sections according to their headers +use core::prelude::*; + use astsrv; use doc::ItemUtils; use doc; @@ -17,6 +19,8 @@ use fold::Fold; use fold; use pass::Pass; +use core::str; + pub fn mk_pass() -> Pass { Pass { name: ~"sectionalize", @@ -111,7 +115,7 @@ fn sectionalize(desc: Option<~str>) -> (Option<~str>, ~[doc::Section]) { match parse_header(copy *line) { Some(header) => { if current_section.is_some() { - sections += ~[(¤t_section).get()]; + sections += [copy *current_section.get_ref()]; } current_section = Some(doc::Section { header: header, @@ -122,14 +126,14 @@ fn sectionalize(desc: Option<~str>) -> (Option<~str>, ~[doc::Section]) { match copy current_section { Some(section) => { current_section = Some(doc::Section { - body: section.body + ~"\n" + *line, + body: section.body + "\n" + *line, .. section }); } None => { new_desc = match copy new_desc { Some(desc) => { - Some(desc + ~"\n" + *line) + Some(desc + "\n" + *line) } None => { Some(copy *line) @@ -142,14 +146,14 @@ fn sectionalize(desc: Option<~str>) -> (Option<~str>, ~[doc::Section]) { } if current_section.is_some() { - sections += ~[current_section.get()]; + sections += [current_section.get()]; } (new_desc, sections) } fn parse_header(line: ~str) -> Option<~str> { - if str::starts_with(line, ~"# ") { + if str::starts_with(line, "# ") { Some(str::slice(line, 2u, str::len(line)).to_owned()) } else { None @@ -160,12 +164,17 @@ fn parse_header(line: ~str) -> Option<~str> { #[cfg(test)] mod test { + use core::prelude::*; + use astsrv; use attr_pass; use doc; use extract; use sectionalize_pass::run; + use core::str; + use core::vec; + fn mk_doc(source: ~str) -> doc::Doc { do astsrv::from_str(copy source) |srv| { let doc = extract::from_srv(srv.clone(), ~""); @@ -184,7 +193,7 @@ mod test { }"); assert!(str::contains( doc.cratemod().mods()[0].item.sections[0].header, - ~"Header")); + "Header")); } #[test] @@ -197,7 +206,7 @@ mod test { }"); assert!(str::contains( doc.cratemod().mods()[0].item.sections[0].body, - ~"Body")); + "Body")); } #[test] @@ -222,10 +231,10 @@ mod test { }"); assert!(!str::contains( doc.cratemod().mods()[0].desc().get(), - ~"Header")); + "Header")); assert!(!str::contains( doc.cratemod().mods()[0].desc().get(), - ~"Body")); + "Body")); } #[test] @@ -236,7 +245,7 @@ mod test { Body\"]\ mod a { }"); - assert!(doc.cratemod().mods()[0].desc() == None); + assert_eq!(doc.cratemod().mods()[0].desc(), None); } #[test] @@ -247,7 +256,7 @@ mod test { # Header\n\ Body\"]\ fn a(); }"); - assert!(doc.cratemod().traits()[0].methods[0].sections.len() == 1u); + assert_eq!(doc.cratemod().traits()[0].methods[0].sections.len(), 1u); } #[test] @@ -258,6 +267,6 @@ mod test { # Header\n\ Body\"]\ fn a() { } }"); - assert!(doc.cratemod().impls()[0].methods[0].sections.len() == 1u); + assert_eq!(doc.cratemod().impls()[0].methods[0].sections.len(), 1u); } } diff --git a/src/librustdoc/sort_item_name_pass.rs b/src/librustdoc/sort_item_name_pass.rs index 86b2cc634fd04..572cb7db926e3 100644 --- a/src/librustdoc/sort_item_name_pass.rs +++ b/src/librustdoc/sort_item_name_pass.rs @@ -31,7 +31,7 @@ fn test() { do astsrv::from_str(source) |srv| { let doc = extract::from_srv(srv.clone(), ~""); let doc = (mk_pass().f)(srv.clone(), doc); - assert!(doc.cratemod().items[0].name() == ~"y"); - assert!(doc.cratemod().items[1].name() == ~"z"); + assert_eq!(doc.cratemod().items[0].name(), ~"y"); + assert_eq!(doc.cratemod().items[1].name(), ~"z"); } } diff --git a/src/librustdoc/sort_item_type_pass.rs b/src/librustdoc/sort_item_type_pass.rs index 158d407fff64f..bf4c7027ce21b 100644 --- a/src/librustdoc/sort_item_type_pass.rs +++ b/src/librustdoc/sort_item_type_pass.rs @@ -47,19 +47,19 @@ fn test() { fn ifn() { } \ enum ienum { ivar } \ trait itrait { fn a(); } \ - pub impl int { fn a() { } } \ + impl int { fn a() { } } \ type itype = int; \ struct istruct { f: () }"; do astsrv::from_str(source) |srv| { let doc = extract::from_srv(srv.clone(), ~""); let doc = (mk_pass().f)(srv.clone(), doc); - assert!(doc.cratemod().items[0].name() == ~"iconst"); - assert!(doc.cratemod().items[1].name() == ~"itype"); - assert!(doc.cratemod().items[2].name() == ~"ienum"); - assert!(doc.cratemod().items[3].name() == ~"istruct"); - assert!(doc.cratemod().items[4].name() == ~"itrait"); - assert!(doc.cratemod().items[5].name() == ~"__extensions__"); - assert!(doc.cratemod().items[6].name() == ~"ifn"); - assert!(doc.cratemod().items[7].name() == ~"imod"); + assert_eq!(doc.cratemod().items[0].name(), ~"iconst"); + assert_eq!(doc.cratemod().items[1].name(), ~"itype"); + assert_eq!(doc.cratemod().items[2].name(), ~"ienum"); + assert_eq!(doc.cratemod().items[3].name(), ~"istruct"); + assert_eq!(doc.cratemod().items[4].name(), ~"itrait"); + assert_eq!(doc.cratemod().items[5].name(), ~"__extensions__"); + assert_eq!(doc.cratemod().items[6].name(), ~"ifn"); + assert_eq!(doc.cratemod().items[7].name(), ~"imod"); } } diff --git a/src/librustdoc/sort_pass.rs b/src/librustdoc/sort_pass.rs index dc7bc8b9df21f..2c545f7d2be07 100644 --- a/src/librustdoc/sort_pass.rs +++ b/src/librustdoc/sort_pass.rs @@ -19,7 +19,7 @@ use util::NominalOp; #[cfg(test)] use extract; -use std::sort; +use extra::sort; pub type ItemLtEqOp = @fn(v1: &doc::ItemTag, v2: &doc::ItemTag) -> bool; @@ -67,10 +67,10 @@ fn test() { do astsrv::from_str(source) |srv| { let doc = extract::from_srv(srv.clone(), ~""); let doc = (mk_pass(~"", name_lteq).f)(srv.clone(), doc); - assert!(doc.cratemod().mods()[0].name() == ~"w"); - assert!(doc.cratemod().mods()[1].items[0].name() == ~"x"); - assert!(doc.cratemod().mods()[1].items[1].name() == ~"y"); - assert!(doc.cratemod().mods()[1].name() == ~"z"); + assert_eq!(doc.cratemod().mods()[0].name(), ~"w"); + assert_eq!(doc.cratemod().mods()[1].items[0].name(), ~"x"); + assert_eq!(doc.cratemod().mods()[1].items[1].name(), ~"y"); + assert_eq!(doc.cratemod().mods()[1].name(), ~"z"); } } @@ -84,10 +84,10 @@ fn should_be_stable() { do astsrv::from_str(source) |srv| { let doc = extract::from_srv(srv.clone(), ~""); let doc = (mk_pass(~"", always_eq).f)(srv.clone(), doc); - assert!(doc.cratemod().mods()[0].items[0].name() == ~"b"); - assert!(doc.cratemod().mods()[1].items[0].name() == ~"d"); + assert_eq!(doc.cratemod().mods()[0].items[0].name(), ~"b"); + assert_eq!(doc.cratemod().mods()[1].items[0].name(), ~"d"); let doc = (mk_pass(~"", always_eq).f)(srv.clone(), doc); - assert!(doc.cratemod().mods()[0].items[0].name() == ~"b"); - assert!(doc.cratemod().mods()[1].items[0].name() == ~"d"); + assert_eq!(doc.cratemod().mods()[0].items[0].name(), ~"b"); + assert_eq!(doc.cratemod().mods()[1].items[0].name(), ~"d"); } } diff --git a/src/librustdoc/text_pass.rs b/src/librustdoc/text_pass.rs index 61768e37a83ff..96a67ea324356 100644 --- a/src/librustdoc/text_pass.rs +++ b/src/librustdoc/text_pass.rs @@ -10,6 +10,8 @@ //! Generic pass for performing an operation on all descriptions +use core::prelude::*; + use astsrv; use doc::ItemUtils; use doc; @@ -21,7 +23,7 @@ use util::NominalOp; use core::cell::Cell; pub fn mk_pass(name: ~str, op: @fn(&str) -> ~str) -> Pass { - let op = Cell(op); + let op = Cell::new(op); Pass { name: copy name, f: |srv: astsrv::Srv, doc: doc::Doc| -> doc::Doc { @@ -137,6 +139,8 @@ fn fold_impl( #[cfg(test)] mod test { + use core::prelude::*; + use astsrv; use attr_pass; use desc_to_brief_pass; @@ -145,6 +149,8 @@ mod test { use sectionalize_pass; use text_pass::mk_pass; + use core::str; + fn mk_doc(source: ~str) -> doc::Doc { do astsrv::from_str(copy source) |srv| { let doc = extract::from_srv(srv.clone(), ~""); @@ -158,13 +164,13 @@ mod test { #[test] fn should_execute_op_on_enum_brief() { let doc = mk_doc(~"#[doc = \" a \"] enum a { b }"); - assert!(doc.cratemod().enums()[0].brief() == Some(~"a")); + assert_eq!(doc.cratemod().enums()[0].brief(), Some(~"a")); } #[test] fn should_execute_op_on_enum_desc() { let doc = mk_doc(~"#[doc = \" a \"] enum a { b }"); - assert!(doc.cratemod().enums()[0].desc() == Some(~"a")); + assert_eq!(doc.cratemod().enums()[0].desc(), Some(~"a")); } #[test] @@ -177,14 +183,14 @@ mod test { fn should_execute_op_on_trait_brief() { let doc = mk_doc( ~"#[doc = \" a \"] trait i { fn a(); }"); - assert!(doc.cratemod().traits()[0].brief() == Some(~"a")); + assert_eq!(doc.cratemod().traits()[0].brief(), Some(~"a")); } #[test] fn should_execute_op_on_trait_desc() { let doc = mk_doc( ~"#[doc = \" a \"] trait i { fn a(); }"); - assert!(doc.cratemod().traits()[0].desc() == Some(~"a")); + assert_eq!(doc.cratemod().traits()[0].desc(), Some(~"a")); } #[test] @@ -205,14 +211,14 @@ mod test { fn should_execute_op_on_impl_brief() { let doc = mk_doc( ~"#[doc = \" a \"] impl int { fn a() { } }"); - assert!(doc.cratemod().impls()[0].brief() == Some(~"a")); + assert_eq!(doc.cratemod().impls()[0].brief(), Some(~"a")); } #[test] fn should_execute_op_on_impl_desc() { let doc = mk_doc( ~"#[doc = \" a \"] impl int { fn a() { } }"); - assert!(doc.cratemod().impls()[0].desc() == Some(~"a")); + assert_eq!(doc.cratemod().impls()[0].desc(), Some(~"a")); } #[test] @@ -233,14 +239,14 @@ mod test { fn should_execute_op_on_type_brief() { let doc = mk_doc( ~"#[doc = \" a \"] type t = int;"); - assert!(doc.cratemod().types()[0].brief() == Some(~"a")); + assert_eq!(doc.cratemod().types()[0].brief(), Some(~"a")); } #[test] fn should_execute_op_on_type_desc() { let doc = mk_doc( ~"#[doc = \" a \"] type t = int;"); - assert!(doc.cratemod().types()[0].desc() == Some(~"a")); + assert_eq!(doc.cratemod().types()[0].desc(), Some(~"a")); } #[test] diff --git a/src/librustdoc/trim_pass.rs b/src/librustdoc/trim_pass.rs index e56a5f18ac6f7..8bfa12ca0b5c4 100644 --- a/src/librustdoc/trim_pass.rs +++ b/src/librustdoc/trim_pass.rs @@ -45,6 +45,6 @@ mod test { let doc = mk_doc(~"#[doc = \" desc \"] \ mod m { }"); - assert!(doc.cratemod().mods()[0].desc() == Some(~"desc")); + assert_eq!(doc.cratemod().mods()[0].desc(), Some(~"desc")); } } diff --git a/src/librustdoc/tystr_pass.rs b/src/librustdoc/tystr_pass.rs index 12689466c8c32..82336addb62fc 100644 --- a/src/librustdoc/tystr_pass.rs +++ b/src/librustdoc/tystr_pass.rs @@ -10,6 +10,8 @@ //! Pulls type information out of the AST and attaches it to the document +use core::prelude::*; + use astsrv; use doc::ItemUtils; use doc; @@ -19,8 +21,10 @@ use fold::Fold; use fold; use pass::Pass; +use core::vec; use syntax::ast; use syntax::print::pprust; +use syntax::parse::token; use syntax::ast_map; pub fn mk_pass() -> Pass { @@ -73,7 +77,7 @@ fn get_fn_sig(srv: astsrv::Srv, fn_id: doc::AstId) -> Option<~str> { node: ast::foreign_item_fn(ref decl, purity, ref tys), _ }, _, _, _) => { Some(pprust::fun_to_str(decl, purity, ident, None, tys, - extract::interner())) + token::get_ident_interner())) } _ => fail!("get_fn_sig: fn_id not bound to a fn item") } @@ -345,6 +349,8 @@ fn strip_struct_extra_stuff(item: @ast::item) -> @ast::item { #[cfg(test)] mod test { + use core::prelude::*; + use astsrv; use doc; use extract; @@ -430,7 +436,7 @@ mod test { #[test] fn should_add_struct_defs() { let doc = mk_doc(~"struct S { field: () }"); - assert!((&doc.cratemod().structs()[0].sig).get().contains( + assert!(doc.cratemod().structs()[0].sig.get().contains( "struct S {")); } @@ -438,6 +444,6 @@ mod test { fn should_not_serialize_struct_attrs() { // All we care about are the fields let doc = mk_doc(~"#[wut] struct S { field: () }"); - assert!(!(&doc.cratemod().structs()[0].sig).get().contains("wut")); + assert!(!doc.cratemod().structs()[0].sig.get().contains("wut")); } } diff --git a/src/librustdoc/unindent_pass.rs b/src/librustdoc/unindent_pass.rs index 082c4dd1989a6..a7f195a35eec7 100644 --- a/src/librustdoc/unindent_pass.rs +++ b/src/librustdoc/unindent_pass.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -19,6 +19,11 @@ instances where the string containing the doc comment is opened in the middle of a line, and each of the following lines is indented. */ +use core::prelude::*; + +use core::str; +use core::uint; +use core::vec; use pass::Pass; use text_pass; @@ -82,7 +87,7 @@ fn unindent(s: &str) -> ~str { str::slice(*line, min_indent, str::len(*line)).to_owned() } }; - str::connect(unindented, ~"\n") + str::connect(unindented, "\n") } else { s.to_str() } @@ -92,14 +97,14 @@ fn unindent(s: &str) -> ~str { fn should_unindent() { let s = ~" line1\n line2"; let r = unindent(s); - assert!(r == ~"line1\nline2"); + assert_eq!(r, ~"line1\nline2"); } #[test] fn should_unindent_multiple_paragraphs() { let s = ~" line1\n\n line2"; let r = unindent(s); - assert!(r == ~"line1\n\nline2"); + assert_eq!(r, ~"line1\n\nline2"); } #[test] @@ -108,7 +113,7 @@ fn should_leave_multiple_indent_levels() { // base indentation and should be preserved let s = ~" line1\n\n line2"; let r = unindent(s); - assert!(r == ~"line1\n\n line2"); + assert_eq!(r, ~"line1\n\n line2"); } #[test] @@ -120,12 +125,12 @@ fn should_ignore_first_line_indent() { // and continue here"] let s = ~"line1\n line2"; let r = unindent(s); - assert!(r == ~"line1\nline2"); + assert_eq!(r, ~"line1\nline2"); } #[test] fn should_not_ignore_first_line_indent_in_a_single_line_para() { let s = ~"line1\n\n line2"; let r = unindent(s); - assert!(r == ~"line1\n\n line2"); + assert_eq!(r, ~"line1\n\n line2"); } diff --git a/src/librustdoc/util.rs b/src/librustdoc/util.rs index 0368b8a034610..fe39ac6bc505c 100644 --- a/src/librustdoc/util.rs +++ b/src/librustdoc/util.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + // Just a named container for our op, so it can have impls pub struct NominalOp { op: T diff --git a/src/librusti/rusti.rc b/src/librusti/rusti.rc index 4a03d31e5dba1..88482c94336da 100644 --- a/src/librusti/rusti.rc +++ b/src/librusti/rusti.rc @@ -18,11 +18,17 @@ #[license = "MIT/ASL2"]; #[crate_type = "lib"]; -extern mod std(vers = "0.7-pre"); -extern mod rustc(vers = "0.7-pre"); -extern mod syntax(vers = "0.7-pre"); +#[no_std]; +extern mod core(name = "std"); +extern mod std(name = "extra"); + +extern mod rustc; +extern mod syntax; + +use core::prelude::*; use core::*; + use core::cell::Cell; use rustc::driver::{driver, session}; use syntax::{ast, diagnostic}; @@ -74,7 +80,7 @@ fn record(mut repl: Repl, blk: &ast::blk, intr: @token::ident_interner) -> Repl let new_view_items = do with_pp(intr) |pp, writer| { for blk.node.view_items.each |view_item| { pprust::print_view_item(pp, *view_item); - writer.write_line(~""); + writer.write_line(""); } }; @@ -88,7 +94,7 @@ fn record(mut repl: Repl, blk: &ast::blk, intr: @token::ident_interner) -> Repl match stmt.node { ast::stmt_decl(*) | ast::stmt_mac(*) => { pprust::print_stmt(pp, *stmt); - writer.write_line(~""); + writer.write_line(""); } ast::stmt_expr(expr, _) | ast::stmt_semi(expr, _) => { match expr.node { @@ -115,7 +121,7 @@ fn run(repl: Repl, input: ~str) -> Repl { let options = @session::options { crate_type: session::unknown_crate, binary: binary, - addl_lib_search_paths: repl.lib_search_paths.map(|p| Path(*p)), + addl_lib_search_paths: @mut repl.lib_search_paths.map(|p| Path(*p)), jit: true, .. copy *session::basic_options() }; @@ -136,11 +142,13 @@ fn run(repl: Repl, input: ~str) -> Repl { binary, &wrapped); - let outputs = driver::build_output_filenames(&wrapped, &None, &None, sess); + let outputs = driver::build_output_filenames(&wrapped, &None, &None, [], sess); debug!("calling compile_upto"); - let (crate, _) = driver::compile_upto(sess, cfg, &wrapped, - driver::cu_everything, - Some(outputs)); + + let crate = driver::parse_input(sess, copy cfg, &wrapped); + driver::compile_rest(sess, cfg, driver::compile_upto { from: driver::cu_parse, + to: driver::cu_everything }, + Some(outputs), Some(crate)); let mut opt = None; @@ -166,7 +174,7 @@ fn run(repl: Repl, input: ~str) -> Repl { _ => fail!() }; debug!("recording input into repl history"); - record(repl, blk, sess.parse_sess.interner) + record(repl, blk, token::get_ident_interner()) } // Compiles a crate given by the filename as a library if the compiled @@ -181,7 +189,7 @@ fn compile_crate(src_filename: ~str, binary: ~str) -> Option { let binary = @copy binary; let options = @session::options { binary: binary, - addl_lib_search_paths: ~[os::getcwd()], + addl_lib_search_paths: @mut ~[os::getcwd()], .. copy *session::basic_options() }; let input = driver::file_input(copy src_path); @@ -189,7 +197,7 @@ fn compile_crate(src_filename: ~str, binary: ~str) -> Option { *sess.building_library = true; let cfg = driver::build_configuration(sess, binary, &input); let outputs = driver::build_output_filenames( - &input, &None, &None, sess); + &input, &None, &None, [], sess); // If the library already exists and is newer than the source // file, skip compilation and return None. let mut should_compile = true; @@ -216,7 +224,7 @@ fn compile_crate(src_filename: ~str, binary: ~str) -> Option { None => { }, } if (should_compile) { - io::println(fmt!("compiling %s...", src_filename)); + println(fmt!("compiling %s...", src_filename)); driver::compile_upto(sess, cfg, &input, driver::cu_everything, Some(outputs)); true @@ -264,13 +272,12 @@ fn run_cmd(repl: &mut Repl, _in: @io::Reader, _out: @io::Writer, //rl::clear(); } ~"help" => { - io::println( - ~":{\\n ..lines.. \\n:}\\n - execute multiline command\n" + - ~":load ... - \ - loads given crates as dynamic libraries\n" + - ~":clear - clear the bindings\n" + - ~":exit - exit from the repl\n" + - ~":help - show this message"); + println( + ":{\\n ..lines.. \\n:}\\n - execute multiline command\n\ + :load ... - loads given crates as dynamic libraries\n\ + :clear - clear the bindings\n\ + :exit - exit from the repl\n\ + :help - show this message"); } ~"load" => { let mut loaded_crates: ~[~str] = ~[]; @@ -298,9 +305,9 @@ fn run_cmd(repl: &mut Repl, _in: @io::Reader, _out: @io::Writer, } } if loaded_crates.is_empty() { - io::println("no crates loaded"); + println("no crates loaded"); } else { - io::println(fmt!("crates loaded: %s", + println(fmt!("crates loaded: %s", str::connect(loaded_crates, ", "))); } } @@ -311,17 +318,17 @@ fn run_cmd(repl: &mut Repl, _in: @io::Reader, _out: @io::Writer, match get_line(use_rl, "rusti| ") { None => fail!("unterminated multiline command :{ .. :}"), Some(line) => { - if str::trim(line) == ~":}" { + if str::trim(line) == ":}" { end_multiline = true; } else { - multiline_cmd += line + ~"\n"; + multiline_cmd += line + "\n"; } } } } action = action_run_line(multiline_cmd); } - _ => io::println(~"unknown cmd: " + cmd) + _ => println(~"unknown cmd: " + cmd) } return action; } @@ -358,8 +365,8 @@ pub fn run_line(repl: &mut Repl, in: @io::Reader, out: @io::Writer, line: ~str, } } - let line = Cell(line); - let r = Cell(copy *repl); + let line = Cell::new(line); + let r = Cell::new(copy *repl); let result = do task::try { run(r.take(), line.take()) }; @@ -387,9 +394,9 @@ pub fn main() { // only print this stuff if the user is actually typing into rusti if istty { - io::println("WARNING: The Rust REPL is experimental and may be"); - io::println("unstable. If you encounter problems, please use the"); - io::println("compiler instead."); + println("WARNING: The Rust REPL is experimental and may be"); + println("unstable. If you encounter problems, please use the"); + println("compiler instead. Type :help for help."); unsafe { do rl::complete |line, suggest| { @@ -409,7 +416,7 @@ pub fn main() { Some(line) => { if line.is_empty() { if istty { - io::println(~"()"); + println("()"); } loop; } @@ -425,6 +432,7 @@ pub fn main() { #[cfg(test)] mod tests { use super::*; + use core::io; fn repl() -> Repl { Repl { @@ -446,8 +454,9 @@ mod tests { } } - #[test] #[ignore] + #[test] fn run_all() { + // FIXME(#6511): // By default, unit tests are run in parallel. Rusti, on the other hand, // does not enjoy doing this. I suspect that it is because the LLVM // bindings are not thread-safe (when running parallel tests, some tests @@ -460,7 +469,7 @@ mod tests { run_cmds([""]); debug!("regression test for #5937"); - run_cmds(["use core;", ""]); + run_cmds(["use std;", ""]); debug!("regression test for #5784"); run_cmds(["let a = 1;"]); diff --git a/src/librusti/wrapper.rs b/src/librusti/wrapper.rs index 9c3026f0915cd..664e5e3b24639 100644 --- a/src/librusti/wrapper.rs +++ b/src/librusti/wrapper.rs @@ -26,5 +26,5 @@ extern mod std; fn print(result: T) { - io::println(fmt!("%?", result)); + println(fmt!("%?", result)); } diff --git a/src/librustpkg/conditions.rs b/src/librustpkg/conditions.rs index 680e0924d798c..caab16cd2917d 100644 --- a/src/librustpkg/conditions.rs +++ b/src/librustpkg/conditions.rs @@ -11,14 +11,14 @@ // Useful conditions pub use core::path::Path; -pub use util::PkgId; +pub use package_id::PkgId; condition! { bad_path: (super::Path, ~str) -> super::Path; } condition! { - nonexistent_package: (super::PkgId, ~str) -> (); + nonexistent_package: (super::PkgId, ~str) -> super::Path; } condition! { @@ -30,5 +30,5 @@ condition! { } condition! { - bad_pkg_id: (super::Path, ~str) -> ::util::PkgId; + bad_pkg_id: (super::Path, ~str) -> super::PkgId; } diff --git a/src/librustpkg/context.rs b/src/librustpkg/context.rs index 348d828bded2f..4f67118e52059 100644 --- a/src/librustpkg/context.rs +++ b/src/librustpkg/context.rs @@ -10,6 +10,8 @@ // Context data structure used by rustpkg +use core::prelude::*; + use core::hashmap::HashMap; pub struct Ctx { diff --git a/src/librustpkg/package_id.rs b/src/librustpkg/package_id.rs new file mode 100644 index 0000000000000..85c82787f266e --- /dev/null +++ b/src/librustpkg/package_id.rs @@ -0,0 +1,132 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub use package_path::{RemotePath, LocalPath, normalize, hash}; +use extra::semver; +use core::prelude::*; +use core::result; + +/// Placeholder +pub fn default_version() -> Version { ExactRevision(0.1) } + +/// Path-fragment identifier of a package such as +/// 'github.com/graydon/test'; path must be a relative +/// path with >=1 component. +pub struct PkgId { + /// Remote path: for example, github.com/mozilla/quux-whatever + remote_path: RemotePath, + /// Local path: for example, /home/quux/github.com/mozilla/quux_whatever + /// Note that '-' normalizes to '_' when mapping a remote path + /// onto a local path + /// Also, this will change when we implement #6407, though we'll still + /// need to keep track of separate local and remote paths + local_path: LocalPath, + /// Short name. This is the local path's filestem, but we store it + /// redundantly so as to not call get() everywhere (filestem() returns an + /// option) + short_name: ~str, + version: Version +} + +impl PkgId { + pub fn new(s: &str) -> PkgId { + use conditions::bad_pkg_id::cond; + + let p = Path(s); + if p.is_absolute { + return cond.raise((p, ~"absolute pkgid")); + } + if p.components.len() < 1 { + return cond.raise((p, ~"0-length pkgid")); + } + let remote_path = RemotePath(p); + let local_path = normalize(copy remote_path); + let short_name = (copy local_path).filestem().expect(fmt!("Strange path! %s", s)); + PkgId { + local_path: local_path, + remote_path: remote_path, + short_name: short_name, + version: default_version() + } + } + + pub fn hash(&self) -> ~str { + fmt!("%s-%s-%s", self.remote_path.to_str(), + hash(self.remote_path.to_str() + self.version.to_str()), + self.version.to_str()) + } + + pub fn short_name_with_version(&self) -> ~str { + fmt!("%s-%s", self.short_name, self.version.to_str()) + } +} + +impl ToStr for PkgId { + fn to_str(&self) -> ~str { + // should probably use the filestem and not the whole path + fmt!("%s-%s", self.local_path.to_str(), self.version.to_str()) + } +} + +/// A version is either an exact revision, +/// or a semantic version +pub enum Version { + ExactRevision(float), + SemVersion(semver::Version) +} + + +impl Ord for Version { + fn lt(&self, other: &Version) -> bool { + match (self, other) { + (&ExactRevision(f1), &ExactRevision(f2)) => f1 < f2, + (&SemVersion(ref v1), &SemVersion(ref v2)) => v1 < v2, + _ => false // incomparable, really + } + } + fn le(&self, other: &Version) -> bool { + match (self, other) { + (&ExactRevision(f1), &ExactRevision(f2)) => f1 <= f2, + (&SemVersion(ref v1), &SemVersion(ref v2)) => v1 <= v2, + _ => false // incomparable, really + } + } + fn ge(&self, other: &Version) -> bool { + match (self, other) { + (&ExactRevision(f1), &ExactRevision(f2)) => f1 > f2, + (&SemVersion(ref v1), &SemVersion(ref v2)) => v1 > v2, + _ => false // incomparable, really + } + } + fn gt(&self, other: &Version) -> bool { + match (self, other) { + (&ExactRevision(f1), &ExactRevision(f2)) => f1 >= f2, + (&SemVersion(ref v1), &SemVersion(ref v2)) => v1 >= v2, + _ => false // incomparable, really + } + } + +} + +impl ToStr for Version { + fn to_str(&self) -> ~str { + match *self { + ExactRevision(ref n) => n.to_str(), + SemVersion(ref v) => v.to_str() + } + } +} + +pub fn parse_vers(vers: ~str) -> result::Result { + match semver::parse(vers) { + Some(vers) => result::Ok(vers), + None => result::Err(~"could not parse version: invalid") + } +} diff --git a/src/librustpkg/package_path.rs b/src/librustpkg/package_path.rs new file mode 100644 index 0000000000000..a54f9ad152f48 --- /dev/null +++ b/src/librustpkg/package_path.rs @@ -0,0 +1,55 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// rustpkg utilities having to do with local and remote paths + +use core::path::Path; +use core::option::Some; +use core::{hash, str}; +use core::rt::io::Writer; +use core::hash::Streaming; + +/// Wrappers to prevent local and remote paths from getting confused +/// (These will go away after #6407) +pub struct RemotePath (Path); +pub struct LocalPath (Path); + + +// normalize should be the only way to construct a LocalPath +// (though this isn't enforced) +/// Replace all occurrences of '-' in the stem part of path with '_' +/// This is because we treat rust-foo-bar-quux and rust_foo_bar_quux +/// as the same name +pub fn normalize(p_: RemotePath) -> LocalPath { + let RemotePath(p) = p_; + match p.filestem() { + None => LocalPath(p), + Some(st) => { + let replaced = str::replace(st, "-", "_"); + if replaced != st { + LocalPath(p.with_filestem(replaced)) + } + else { + LocalPath(p) + } + } + } +} + +pub fn write(writer: &mut W, string: &str) { + let buffer = str::as_bytes_slice(string); + writer.write(buffer); +} + +pub fn hash(data: ~str) -> ~str { + let hasher = &mut hash::default_state(); + write(hasher, data); + hasher.result_str() +} diff --git a/src/librustpkg/path_util.rs b/src/librustpkg/path_util.rs index bbd8d09235484..7b4a9a63a4ec0 100644 --- a/src/librustpkg/path_util.rs +++ b/src/librustpkg/path_util.rs @@ -10,10 +10,13 @@ // rustpkg utilities having to do with paths and directories -pub use util::{PkgId, RemotePath, LocalPath}; +use core::prelude::*; +pub use package_path::{RemotePath, LocalPath}; +pub use package_id::{PkgId, Version}; +pub use target::{OutputType, Main, Lib, Test, Bench, Target, Build, Install}; use core::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR}; use core::os::mkdir_recursive; -pub use util::{normalize, OutputType, Main, Lib, Bench, Test}; +use core::os; /// Returns the value of RUST_PATH, as a list /// of Paths. In general this should be read from the @@ -29,22 +32,38 @@ pub static u_rwx: i32 = (S_IRUSR | S_IWUSR | S_IXUSR) as i32; /// succeeded. pub fn make_dir_rwx(p: &Path) -> bool { os::make_dir(p, u_rwx) } -// n.b. So far this only handles local workspaces // n.b. The next three functions ignore the package version right // now. Should fix that. /// True if there's a directory in with /// pkgid's short name pub fn workspace_contains_package_id(pkgid: &PkgId, workspace: &Path) -> bool { - let pkgpath = workspace.push("src").push(pkgid.local_path.to_str()); + let pkgpath = workspace.push("src").push(pkgid.remote_path.to_str()); os::path_is_dir(&pkgpath) } -/// Return the directory for 's source files in . -/// Doesn't check that it exists. -pub fn pkgid_src_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path { - let result = workspace.push("src"); - result.push(pkgid.local_path.to_str()) +/// Returns a list of possible directories +/// for 's source files in . +/// Doesn't check that any of them exist. +/// (for example, try both with and without the version) +pub fn pkgid_src_in_workspace(pkgid: &PkgId, workspace: &Path) -> ~[Path] { + let mut results = ~[]; + let result = workspace.push("src").push(fmt!("%s-%s", + pkgid.local_path.to_str(), pkgid.version.to_str())); + results.push(result); + results.push(workspace.push("src").push_rel(&*pkgid.remote_path)); + results +} + +/// Returns a src for pkgid that does exist -- None if none of them do +pub fn first_pkgid_src_in_workspace(pkgid: &PkgId, workspace: &Path) -> Option { + let rs = pkgid_src_in_workspace(pkgid, workspace); + for rs.each |p| { + if os::path_exists(p) { + return Some(copy *p); + } + } + None } /// Figure out what the executable name for in 's build @@ -52,7 +71,7 @@ pub fn pkgid_src_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path { pub fn built_executable_in_workspace(pkgid: &PkgId, workspace: &Path) -> Option { let mut result = workspace.push("build"); // should use a target-specific subdirectory - result = mk_output_path(Main, pkgid, &result); + result = mk_output_path(Main, Build, pkgid, &result); debug!("built_executable_in_workspace: checking whether %s exists", result.to_str()); if os::path_exists(&result) { @@ -80,7 +99,7 @@ pub fn built_bench_in_workspace(pkgid: &PkgId, workspace: &Path) -> Option fn output_in_workspace(pkgid: &PkgId, workspace: &Path, what: OutputType) -> Option { let mut result = workspace.push("build"); // should use a target-specific subdirectory - result = mk_output_path(what, pkgid, &result); + result = mk_output_path(what, Build, pkgid, &result); debug!("output_in_workspace: checking whether %s exists", result.to_str()); if os::path_exists(&result) { @@ -95,17 +114,39 @@ fn output_in_workspace(pkgid: &PkgId, workspace: &Path, what: OutputType) -> Opt /// Figure out what the library name for in 's build /// directory is, and if the file exists, return it. pub fn built_library_in_workspace(pkgid: &PkgId, workspace: &Path) -> Option { - let result = mk_output_path(Lib, pkgid, &workspace.push("build")); - debug!("built_library_in_workspace: checking whether %s exists", - result.to_str()); + // passing in local_path here sounds fishy + library_in_workspace(pkgid.local_path.to_str(), pkgid.short_name, Build, + workspace, "build") +} + +/// Does the actual searching stuff +pub fn installed_library_in_workspace(short_name: &str, workspace: &Path) -> Option { + library_in_workspace(short_name, short_name, Install, workspace, "lib") +} + + +/// This doesn't take a PkgId, so we can use it for `extern mod` inference, where we +/// don't know the entire package ID. +/// `full_name` is used to figure out the directory to search. +/// `short_name` is taken as the link name of the library. +fn library_in_workspace(full_name: &str, short_name: &str, where: Target, + workspace: &Path, prefix: &str) -> Option { + debug!("library_in_workspace: checking whether a library named %s exists", + short_name); // We don't know what the hash is, so we have to search through the directory // contents - let dir_contents = os::list_dir(&result.pop()); + + let dir_to_search = match where { + Build => workspace.push(prefix).push(full_name), + Install => workspace.push(prefix) + }; + debug!("Listing directory %s", dir_to_search.to_str()); + let dir_contents = os::list_dir(&dir_to_search); debug!("dir has %? entries", dir_contents.len()); - let lib_prefix = fmt!("%s%s", os::consts::DLL_PREFIX, pkgid.short_name); - let lib_filetype = fmt!("%s%s", pkgid.version.to_str(), os::consts::DLL_SUFFIX); + let lib_prefix = fmt!("%s%s", os::consts::DLL_PREFIX, short_name); + let lib_filetype = os::consts::DLL_SUFFIX; debug!("lib_prefix = %s and lib_filetype = %s", lib_prefix, lib_filetype); @@ -113,9 +154,19 @@ pub fn built_library_in_workspace(pkgid: &PkgId, workspace: &Path) -> Option (), + _ => loop + } // Find a filename that matches the pattern: (lib_prefix)-hash-(version)(lib_suffix) // and remember what the hash was - for p.each_split_char('-') |piece| { + let f_name = match p_path.filename() { + Some(s) => s, None => loop + }; + for f_name.each_split_char('-') |piece| { debug!("a piece = %s", piece); if which == 0 && piece != lib_prefix { break; @@ -125,13 +176,6 @@ pub fn built_library_in_workspace(pkgid: &PkgId, workspace: &Path) -> Option Option None, Some(result_filename) => { - let result_filename = result.with_filename(result_filename); - debug!("result_filename = %s", result_filename.to_str()); - Some(result_filename) + let absolute_path = dir_to_search.push_rel(&result_filename); + debug!("result_filename = %s", absolute_path.to_str()); + Some(absolute_path) } } } @@ -163,33 +206,36 @@ pub fn built_library_in_workspace(pkgid: &PkgId, workspace: &Path) -> Option /// As a side effect, creates the bin-dir if it doesn't exist pub fn target_executable_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path { - target_file_in_workspace(pkgid, workspace, Main) + target_file_in_workspace(pkgid, workspace, Main, Install) } /// Returns the executable that would be installed for /// in -/// As a side effect, creates the bin-dir if it doesn't exist +/// As a side effect, creates the lib-dir if it doesn't exist pub fn target_library_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path { - target_file_in_workspace(pkgid, workspace, Lib) + target_file_in_workspace(pkgid, workspace, Lib, Install) } /// Returns the test executable that would be installed for /// in /// note that we *don't* install test executables, so this is just for unit testing pub fn target_test_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path { - target_file_in_workspace(pkgid, workspace, Test) + target_file_in_workspace(pkgid, workspace, Test, Install) } /// Returns the bench executable that would be installed for /// in /// note that we *don't* install bench executables, so this is just for unit testing pub fn target_bench_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path { - target_file_in_workspace(pkgid, workspace, Bench) + target_file_in_workspace(pkgid, workspace, Bench, Install) } + +/// Returns the path that pkgid `pkgid` would have if placed `where` +/// in `workspace` fn target_file_in_workspace(pkgid: &PkgId, workspace: &Path, - what: OutputType) -> Path { + what: OutputType, where: Target) -> Path { use conditions::bad_path::cond; let subdir = match what { @@ -199,7 +245,7 @@ fn target_file_in_workspace(pkgid: &PkgId, workspace: &Path, if !os::path_exists(&result) && !mkdir_recursive(&result, u_rwx) { cond.raise((copy result, fmt!("I couldn't create the %s dir", subdir))); } - mk_output_path(what, pkgid, &result) + mk_output_path(what, where, pkgid, &result) } /// Return the directory for 's build artifacts in . @@ -221,15 +267,21 @@ pub fn build_pkg_id_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path { /// Return the output file for a given directory name, /// given whether we're building a library and whether we're building tests -pub fn mk_output_path(what: OutputType, pkg_id: &PkgId, workspace: &Path) -> Path { +pub fn mk_output_path(what: OutputType, where: Target, + pkg_id: &PkgId, workspace: &Path) -> Path { let short_name_with_version = pkg_id.short_name_with_version(); // Not local_path.dir_path()! For package foo/bar/blat/, we want // the executable blat-0.5 to live under blat/ - let dir = workspace.push_rel(&*pkg_id.local_path); - debug!("mk_output_path: short_name = %s, path = %s", + let dir = match where { + // If we're installing, it just goes under ... + Install => copy *workspace, // bad copy, but I just couldn't make the borrow checker happy + // and if we're just building, it goes in a package-specific subdir + Build => workspace.push_rel(&*pkg_id.local_path) + }; + debug!("[%?:%?] mk_output_path: short_name = %s, path = %s", what, where, if what == Lib { copy short_name_with_version } else { copy pkg_id.short_name }, dir.to_str()); - let output_path = match what { + let mut output_path = match what { // this code is duplicated from elsewhere; fix this Lib => dir.push(os::dll_filename(short_name_with_version)), // executable names *aren't* versioned @@ -241,6 +293,9 @@ pub fn mk_output_path(what: OutputType, pkg_id: &PkgId, workspace: &Path) -> Pat } os::EXE_SUFFIX)) }; + if !output_path.is_absolute() { + output_path = os::getcwd().push_rel(&output_path).normalize(); + } debug!("mk_output_path: returning %s", output_path.to_str()); output_path } diff --git a/src/librustpkg/rustpkg.rc b/src/librustpkg/rustpkg.rc index a69613776efdc..005f2de3f4276 100644 --- a/src/librustpkg/rustpkg.rc +++ b/src/librustpkg/rustpkg.rc @@ -18,27 +18,38 @@ #[license = "MIT/ASL2"]; #[crate_type = "lib"]; -extern mod std(vers = "0.7-pre"); -extern mod rustc(vers = "0.7-pre"); -extern mod syntax(vers = "0.7-pre"); +#[no_std]; +extern mod core(name = "std"); +extern mod extra(name = "extra"); + +extern mod rustc; +extern mod syntax; + +use core::prelude::*; use core::*; pub use core::path::Path; use core::hashmap::HashMap; use rustc::driver::{driver, session}; use rustc::metadata::filesearch; -use std::{getopts}; +use extra::{getopts}; use syntax::{ast, diagnostic}; use util::*; -use path_util::{build_pkg_id_in_workspace, pkgid_src_in_workspace, u_rwx}; +use path_util::{build_pkg_id_in_workspace, pkgid_src_in_workspace, first_pkgid_src_in_workspace}; +use path_util::u_rwx; use path_util::{built_executable_in_workspace, built_library_in_workspace}; use path_util::{target_executable_in_workspace, target_library_in_workspace}; use workspace::pkg_parent_workspaces; use context::Ctx; +use package_id::PkgId; mod conditions; mod context; +mod package_id; +mod package_path; mod path_util; +mod search; +mod target; #[cfg(test)] mod tests; mod util; @@ -46,6 +57,15 @@ mod workspace; pub mod usage; +mod std { + pub use core::cmp; + pub use core::condition; + pub use core::os; + pub use core::str; + pub use core::sys; + pub use core::unstable; +} + /// A PkgScript represents user-supplied custom logic for /// special build hooks. This only exists for packages with /// an explicit package script. @@ -85,8 +105,7 @@ impl<'self> PkgScript<'self> { let input = driver::file_input(script); let sess = driver::build_session(options, diagnostic::emit); let cfg = driver::build_configuration(sess, binary, &input); - let (crate, _) = driver::compile_upto(sess, copy cfg, &input, - driver::cu_parse, None); + let (crate, _) = driver::compile_upto(sess, copy cfg, &input, driver::cu_parse, None); let work_dir = build_pkg_id_in_workspace(id, workspace); debug!("Returning package script with id %?", id); @@ -96,7 +115,7 @@ impl<'self> PkgScript<'self> { input: input, sess: sess, cfg: cfg, - crate: crate, + crate: crate.unwrap(), build_dir: work_dir } } @@ -120,23 +139,25 @@ impl<'self> PkgScript<'self> { let root = r.pop().pop().pop().pop(); // :-\ debug!("Root is %s, calling compile_rest", root.to_str()); let exe = self.build_dir.push(~"pkg" + util::exe_suffix()); - util::compile_crate_from_input(&self.input, self.id, - Some(copy self.build_dir), - sess, Some(crate), - &exe, @copy os::args()[0], - driver::cu_everything); + let binary = @copy os::args()[0]; + util::compile_crate_from_input(&self.input, + &self.build_dir, + sess, + crate, + driver::build_configuration(sess, + binary, &self.input)); debug!("Running program: %s %s %s", exe.to_str(), root.to_str(), what); - let status = run::run_program(exe.to_str(), ~[root.to_str(), what]); + let status = run::process_status(exe.to_str(), [root.to_str(), what]); if status != 0 { return (~[], status); } else { debug!("Running program (configs): %s %s %s", - exe.to_str(), root.to_str(), ~"configs"); - let output = run::program_output(exe.to_str(), ~[root.to_str(), ~"configs"]); + exe.to_str(), root.to_str(), "configs"); + let output = run::process_output(exe.to_str(), [root.to_str(), ~"configs"]); // Run the configs() function to get the configs let mut cfgs = ~[]; - for str::each_word(output.out) |w| { + for str::each_word(str::from_bytes(output.output)) |w| { cfgs.push(w.to_owned()); } (cfgs, output.status) @@ -156,9 +177,9 @@ impl<'self> PkgScript<'self> { impl Ctx { - fn run(&self, cmd: ~str, args: ~[~str]) { + fn run(&self, cmd: &str, args: ~[~str]) { match cmd { - ~"build" => { + "build" => { if args.len() < 1 { return usage::build(); } @@ -169,7 +190,7 @@ impl Ctx { self.build(workspace, &pkgid); } } - ~"clean" => { + "clean" => { if args.len() < 1 { return usage::build(); } @@ -179,17 +200,17 @@ impl Ctx { let cwd = os::getcwd(); self.clean(&cwd, &pkgid); // tjc: should use workspace, not cwd } - ~"do" => { + "do" => { if args.len() < 2 { return usage::do_cmd(); } self.do_cmd(copy args[0], copy args[1]); } - ~"info" => { + "info" => { self.info(); } - ~"install" => { + "install" => { if args.len() < 1 { return usage::install(); } @@ -201,24 +222,24 @@ impl Ctx { self.install(workspace, &pkgid); } } - ~"prefer" => { + "prefer" => { if args.len() < 1 { return usage::uninstall(); } self.prefer(args[0], None); } - ~"test" => { + "test" => { self.test(); } - ~"uninstall" => { + "uninstall" => { if args.len() < 1 { return usage::uninstall(); } self.uninstall(args[0], None); } - ~"unprefer" => { + "unprefer" => { if args.len() < 1 { return usage::uninstall(); } @@ -235,7 +256,7 @@ impl Ctx { } fn build(&self, workspace: &Path, pkgid: &PkgId) { - let src_dir = pkgid_src_in_workspace(pkgid, workspace); + let src_dir = first_pkgid_src_in_workspace(pkgid, workspace); let build_dir = build_pkg_id_in_workspace(pkgid, workspace); debug!("Destination dir = %s", build_dir.to_str()); @@ -246,8 +267,8 @@ impl Ctx { // Is there custom build logic? If so, use it let pkg_src_dir = src_dir; let mut custom = false; - debug!("Package source directory = %s", pkg_src_dir.to_str()); - let cfgs = match src.package_script_option(&pkg_src_dir) { + debug!("Package source directory = %?", pkg_src_dir); + let cfgs = match pkg_src_dir.chain_ref(|p| src.package_script_option(p)) { Some(package_script_path) => { let pscript = PkgScript::parse(package_script_path, workspace, @@ -276,7 +297,7 @@ impl Ctx { // Find crates inside the workspace src.find_crates(); // Build it! - src.build(&build_dir, cfgs, self.sysroot_opt); + src.build(self, build_dir, cfgs); } } @@ -338,7 +359,7 @@ impl Ctx { } fn prefer(&self, _id: &str, _vers: Option<~str>) { - fail!(~"prefer not yet implemented"); + fail!("prefer not yet implemented"); } fn test(&self) { @@ -360,9 +381,9 @@ pub fn main() { io::println("WARNING: The Rust package manager is experimental and may be unstable"); let args = os::args(); - let opts = ~[getopts::optflag(~"h"), getopts::optflag(~"help"), - getopts::optflag(~"j"), getopts::optflag(~"json"), - getopts::optmulti(~"c"), getopts::optmulti(~"cfg")]; + let opts = ~[getopts::optflag("h"), getopts::optflag("help"), + getopts::optflag("j"), getopts::optflag("json"), + getopts::optmulti("c"), getopts::optmulti("cfg")]; let matches = &match getopts::getopts(args, opts) { result::Ok(m) => m, result::Err(f) => { @@ -371,10 +392,10 @@ pub fn main() { return; } }; - let help = getopts::opt_present(matches, ~"h") || - getopts::opt_present(matches, ~"help"); - let json = getopts::opt_present(matches, ~"j") || - getopts::opt_present(matches, ~"json"); + let help = getopts::opt_present(matches, "h") || + getopts::opt_present(matches, "help"); + let json = getopts::opt_present(matches, "j") || + getopts::opt_present(matches, "json"); let mut args = copy matches.free; args.shift(); @@ -416,9 +437,8 @@ pub struct Crate { cfgs: ~[~str] } -pub impl Crate { - - fn new(p: &Path) -> Crate { +impl Crate { + pub fn new(p: &Path) -> Crate { Crate { file: copy *p, flags: ~[], @@ -426,28 +446,28 @@ pub impl Crate { } } - fn flag(&self, flag: ~str) -> Crate { + pub fn flag(&self, flag: ~str) -> Crate { Crate { - flags: vec::append(copy self.flags, ~[flag]), + flags: vec::append(copy self.flags, [flag]), .. copy *self } } - fn flags(&self, flags: ~[~str]) -> Crate { + pub fn flags(&self, flags: ~[~str]) -> Crate { Crate { flags: vec::append(copy self.flags, flags), .. copy *self } } - fn cfg(&self, cfg: ~str) -> Crate { + pub fn cfg(&self, cfg: ~str) -> Crate { Crate { - cfgs: vec::append(copy self.cfgs, ~[cfg]), + cfgs: vec::append(copy self.cfgs, [cfg]), .. copy *self } } - fn cfgs(&self, cfgs: ~[~str]) -> Crate { + pub fn cfgs(&self, cfgs: ~[~str]) -> Crate { Crate { cfgs: vec::append(copy self.cfgs, cfgs), .. copy *self @@ -509,21 +529,20 @@ impl PkgSrc { fn check_dir(&self) -> Path { use conditions::nonexistent_package::cond; - debug!("Pushing onto root: %s | %s", self.id.to_str(), + debug!("Pushing onto root: %s | %s", self.id.remote_path.to_str(), self.root.to_str()); - - let mut dir = self.root.push("src"); - dir = dir.push(self.id.to_str()); // ?? Should this use the version number? - - debug!("Checking dir: %s", dir.to_str()); - - if !os::path_exists(&dir) { - if !self.fetch_git() { - cond.raise((copy self.id, ~"supplied path for package dir does not \ - exist, and couldn't interpret it as a URL fragment")); + let dir; + let dirs = pkgid_src_in_workspace(&self.id, &self.root); + debug!("Checking dirs: %?", dirs); + let path = dirs.find(|d| os::path_exists(d)); + match path { + Some(d) => dir = d, + None => dir = match self.fetch_git() { + None => cond.raise((copy self.id, ~"supplied path for package dir does not \ + exist, and couldn't interpret it as a URL fragment")), + Some(d) => d } } - if !os::path_is_dir(&dir) { cond.raise((copy self.id, ~"supplied path for package dir is a \ non-directory")); @@ -533,10 +552,10 @@ impl PkgSrc { } /// Try interpreting self's package id as a remote package, and try - /// fetching it and caching it in a local directory. If that didn't - /// work, return false. + /// fetching it and caching it in a local directory. Return the cached directory + /// if this was successful, None otherwise /// (right now we only support git) - fn fetch_git(&self) -> bool { + fn fetch_git(&self) -> Option { let mut local = self.root.push("src"); local = local.push(self.id.to_str()); @@ -546,11 +565,13 @@ impl PkgSrc { let url = fmt!("https://%s", self.id.remote_path.to_str()); util::note(fmt!("git clone %s %s", url, local.to_str())); - if run::program_output(~"git", ~[~"clone", copy url, local.to_str()]).status != 0 { + if run::process_output("git", [~"clone", copy url, local.to_str()]).status != 0 { util::note(fmt!("fetching %s failed: can't clone repository", url)); - return false; + None + } + else { + Some(local) } - true } @@ -602,7 +623,6 @@ impl PkgSrc { /// Infers crates to build. Called only in the case where there /// is no custom build logic fn find_crates(&mut self) { - use PkgSrc::push_crate; use conditions::missing_pkg_files::cond; let dir = self.check_dir(); @@ -610,14 +630,18 @@ impl PkgSrc { debug!("Matching against %?", self.id.local_path.filestem()); for os::walk_dir(&dir) |pth| { match pth.filename() { - Some(~"lib.rs") => push_crate(&mut self.libs, - prefix, pth), - Some(~"main.rs") => push_crate(&mut self.mains, - prefix, pth), - Some(~"test.rs") => push_crate(&mut self.tests, - prefix, pth), - Some(~"bench.rs") => push_crate(&mut self.benchs, - prefix, pth), + Some(~"lib.rs") => PkgSrc::push_crate(&mut self.libs, + prefix, + pth), + Some(~"main.rs") => PkgSrc::push_crate(&mut self.mains, + prefix, + pth), + Some(~"test.rs") => PkgSrc::push_crate(&mut self.tests, + prefix, + pth), + Some(~"bench.rs") => PkgSrc::push_crate(&mut self.benchs, + prefix, + pth), _ => () } } @@ -639,7 +663,7 @@ impl PkgSrc { } fn build_crates(&self, - maybe_sysroot: Option<@Path>, + ctx: &Ctx, dst_dir: &Path, src_dir: &Path, crates: &[Crate], @@ -650,11 +674,14 @@ impl PkgSrc { util::note(fmt!("build_crates: compiling %s", path.to_str())); util::note(fmt!("build_crates: destination dir is %s", dst_dir.to_str())); - let result = util::compile_crate(maybe_sysroot, &self.id, path, - dst_dir, - crate.flags, - crate.cfgs + cfgs, - false, what); + let result = util::compile_crate(ctx, + &self.id, + path, + dst_dir, + crate.flags, + crate.cfgs + cfgs, + false, + what); if !result { build_err::cond.raise(fmt!("build failure on %s", path.to_str())); @@ -664,16 +691,15 @@ impl PkgSrc { } } - fn build(&self, dst_dir: &Path, cfgs: ~[~str], maybe_sysroot: Option<@Path>) { + fn build(&self, ctx: &Ctx, dst_dir: Path, cfgs: ~[~str]) { let dir = self.check_dir(); debug!("Building libs"); - self.build_crates(maybe_sysroot, dst_dir, &dir, self.libs, cfgs, Lib); + self.build_crates(ctx, &dst_dir, &dir, self.libs, cfgs, Lib); debug!("Building mains"); - self.build_crates(maybe_sysroot, dst_dir, &dir, self.mains, cfgs, Main); + self.build_crates(ctx, &dst_dir, &dir, self.mains, cfgs, Main); debug!("Building tests"); - self.build_crates(maybe_sysroot, dst_dir, &dir, self.tests, cfgs, Test); + self.build_crates(ctx, &dst_dir, &dir, self.tests, cfgs, Test); debug!("Building benches"); - self.build_crates(maybe_sysroot, dst_dir, &dir, self.benchs, cfgs, Bench); + self.build_crates(ctx, &dst_dir, &dir, self.benchs, cfgs, Bench); } } - diff --git a/src/librustpkg/search.rs b/src/librustpkg/search.rs new file mode 100644 index 0000000000000..987e01009fc8b --- /dev/null +++ b/src/librustpkg/search.rs @@ -0,0 +1,25 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use path_util::installed_library_in_workspace; +use core::prelude::*; + +/// If a library with path `p` matching pkg_id's name exists under sroot_opt, +/// return Some(p). Return None if there's no such path or if sroot_opt is None. +pub fn find_library_in_search_path(sroot_opt: Option<@Path>, short_name: &str) -> Option { + match sroot_opt { + Some(sroot) => { + debug!("Will search for a library with short name %s in \ + %s", short_name, (sroot.push("lib")).to_str()); + installed_library_in_workspace(short_name, sroot) + } + None => None + } +} \ No newline at end of file diff --git a/src/librustpkg/target.rs b/src/librustpkg/target.rs new file mode 100644 index 0000000000000..03c2f5a4fe42a --- /dev/null +++ b/src/librustpkg/target.rs @@ -0,0 +1,23 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + +// Data types that express build artifacts + +#[deriving(Eq)] +pub enum OutputType { Main, Lib, Bench, Test } + +#[deriving(Eq)] +pub enum Target { + // In-place build + Build, + // Install to bin/ or lib/ dir + Install +} diff --git a/src/librustpkg/tests.rs b/src/librustpkg/tests.rs index 8eba3f06de387..a96a7a0a5fc9a 100644 --- a/src/librustpkg/tests.rs +++ b/src/librustpkg/tests.rs @@ -12,12 +12,16 @@ use context::Ctx; use core::hashmap::HashMap; -use core::path::Path; -use std::tempfile::mkdtemp; -use util::{PkgId, default_version}; +use core::io; +use core::os; +use core::prelude::*; +use core::result; +use extra::tempfile::mkdtemp; +use package_path::*; +use package_id::{PkgId, default_version}; use path_util::{target_executable_in_workspace, target_library_in_workspace, target_test_in_workspace, target_bench_in_workspace, - make_dir_rwx, u_rwx, RemotePath, LocalPath, normalize, + make_dir_rwx, u_rwx, built_bench_in_workspace, built_test_in_workspace}; fn fake_ctxt(sysroot_opt: Option<@Path>) -> Ctx { @@ -40,7 +44,7 @@ fn fake_pkg() -> PkgId { } fn remote_pkg() -> PkgId { - let remote = RemotePath(Path(~"github.com/catamorphism/test-pkg")); + let remote = RemotePath(Path("github.com/catamorphism/test-pkg")); PkgId { local_path: normalize(copy remote), remote_path: remote, @@ -49,27 +53,29 @@ fn remote_pkg() -> PkgId { } } -fn writeFile(file_path: &Path, contents: ~str) { +fn writeFile(file_path: &Path, contents: &str) { let out: @io::Writer = result::get(&io::file_writer(file_path, - ~[io::Create, io::Truncate])); + [io::Create, io::Truncate])); out.write_line(contents); } fn mk_temp_workspace(short_name: &LocalPath) -> Path { let workspace = mkdtemp(&os::tmpdir(), "test").expect("couldn't create temp dir"); // include version number in directory name - let package_dir = workspace.push(~"src").push(fmt!("%s-0.1", short_name.to_str())); + let package_dir = workspace.push("src").push(fmt!("%s-0.1", short_name.to_str())); assert!(os::mkdir_recursive(&package_dir, u_rwx)); + debug!("Created %s and does it exist? %?", package_dir.to_str(), + os::path_is_dir(&package_dir)); // Create main, lib, test, and bench files - writeFile(&package_dir.push(~"main.rs"), - ~"fn main() { let _x = (); }"); - writeFile(&package_dir.push(~"lib.rs"), - ~"pub fn f() { let _x = (); }"); - writeFile(&package_dir.push(~"test.rs"), - ~"#[test] pub fn f() { (); }"); - writeFile(&package_dir.push(~"bench.rs"), - ~"#[bench] pub fn f() { (); }"); + writeFile(&package_dir.push("main.rs"), + "fn main() { let _x = (); }"); + writeFile(&package_dir.push("lib.rs"), + "pub fn f() { let _x = (); }"); + writeFile(&package_dir.push("test.rs"), + "#[test] pub fn f() { (); }"); + writeFile(&package_dir.push("bench.rs"), + "#[bench] pub fn f() { (); }"); workspace } @@ -93,12 +99,10 @@ fn test_sysroot() -> Path { self_path.pop() } -// Ignored on i686 -- see #6517 #[test] -#[ignore(cfg(target_arch = "x86"))] fn test_make_dir_rwx() { let temp = &os::tmpdir(); - let dir = temp.push(~"quux"); + let dir = temp.push("quux"); assert!(!os::path_exists(&dir) || os::remove_dir_recursive(&dir)); debug!("Trying to make %s", dir.to_str()); @@ -109,8 +113,9 @@ fn test_make_dir_rwx() { } #[test] -#[ignore(cfg(target_arch = "x86"))] fn test_install_valid() { + use path_util::installed_library_in_workspace; + let sysroot = test_sysroot(); debug!("sysroot = %s", sysroot.to_str()); let ctxt = fake_ctxt(Some(@sysroot)); @@ -123,10 +128,12 @@ fn test_install_valid() { debug!("exec = %s", exec.to_str()); assert!(os::path_exists(&exec)); assert!(is_rwx(&exec)); - let lib = target_library_in_workspace(&temp_pkg_id, &temp_workspace); - debug!("lib = %s", lib.to_str()); - assert!(os::path_exists(&lib)); - assert!(is_rwx(&lib)); + + let lib = installed_library_in_workspace(temp_pkg_id.short_name, &temp_workspace); + debug!("lib = %?", lib); + assert!(lib.map_default(false, |l| os::path_exists(l))); + assert!(lib.map_default(false, |l| is_rwx(l))); + // And that the test and bench executables aren't installed assert!(!os::path_exists(&target_test_in_workspace(&temp_pkg_id, &temp_workspace))); let bench = target_bench_in_workspace(&temp_pkg_id, &temp_workspace); @@ -135,7 +142,6 @@ fn test_install_valid() { } #[test] -#[ignore(cfg(target_arch = "x86"))] fn test_install_invalid() { use conditions::nonexistent_package::cond; use cond1 = conditions::missing_pkg_files::cond; @@ -150,6 +156,7 @@ fn test_install_invalid() { }).in { do cond.trap(|_| { error_occurred = true; + copy temp_workspace }).in { ctxt.install(&temp_workspace, &pkgid); } @@ -158,7 +165,6 @@ fn test_install_invalid() { } #[test] -#[ignore(cfg(target_arch = "x86"))] fn test_install_url() { let workspace = mkdtemp(&os::tmpdir(), "test").expect("couldn't create temp dir"); let sysroot = test_sysroot(); @@ -176,10 +182,11 @@ fn test_install_url() { debug!("lib = %s", lib.to_str()); assert!(os::path_exists(&lib)); assert!(is_rwx(&lib)); - let built_test = built_test_in_workspace(&temp_pkg_id, &workspace).expect(~"test_install_url"); + let built_test = built_test_in_workspace(&temp_pkg_id, + &workspace).expect("test_install_url: built test should exist"); assert!(os::path_exists(&built_test)); let built_bench = built_bench_in_workspace(&temp_pkg_id, - &workspace).expect(~"test_install_url"); + &workspace).expect("test_install_url: built bench should exist"); assert!(os::path_exists(&built_bench)); // And that the test and bench executables aren't installed let test = target_test_in_workspace(&temp_pkg_id, &workspace); @@ -212,7 +219,7 @@ fn test_package_ids_must_be_relative_path_like() { let whatever = PkgId::new("foo"); - assert!(addversion("foo") == whatever.to_str()); + assert_eq!(addversion("foo"), whatever.to_str()); assert!(addversion("github.com/mozilla/rust") == PkgId::new("github.com/mozilla/rust").to_str()); @@ -222,16 +229,16 @@ fn test_package_ids_must_be_relative_path_like() { copy whatever }).in { let x = PkgId::new(""); - assert!(addversion("foo") == x.to_str()); + assert_eq!(addversion("foo"), x.to_str()); } do cond.trap(|(p, e)| { - assert!(p.to_str() == os::make_absolute(&Path("foo/bar/quux")).to_str()); + assert_eq!(p.to_str(), os::make_absolute(&Path("foo/bar/quux")).to_str()); assert!("absolute pkgid" == e); copy whatever }).in { let z = PkgId::new(os::make_absolute(&Path("foo/bar/quux")).to_str()); - assert!(addversion("foo") == z.to_str()); + assert_eq!(addversion("foo"), z.to_str()); } } diff --git a/src/librustpkg/testsuite/pass/src/external-crate/main.rs b/src/librustpkg/testsuite/pass/src/external-crate/main.rs index d094bcd6bba62..1e5c1d5e627d1 100644 --- a/src/librustpkg/testsuite/pass/src/external-crate/main.rs +++ b/src/librustpkg/testsuite/pass/src/external-crate/main.rs @@ -13,9 +13,12 @@ The test runner should check that, after `rustpkg install external crate` with RUST_PATH undefined in the environment and with `rustpkg install deeply/nested/path/foo` already executed: - * ./.rust/external_crate exists and is an executable + * ../bin/external_crate exists and is an executable + + tjc: Also want a test like this where foo is an external URL, + which requires the `extern mod` changes */ -extern mod foo; // refers to deeply/nested/path/foo +extern mod foo; fn main() {} diff --git a/src/librustpkg/testsuite/pass/src/fancy-lib/pkg.rs b/src/librustpkg/testsuite/pass/src/fancy-lib/pkg.rs index eeaa0f68ed531..2d3a75d9197bf 100644 --- a/src/librustpkg/testsuite/pass/src/fancy-lib/pkg.rs +++ b/src/librustpkg/testsuite/pass/src/fancy-lib/pkg.rs @@ -23,6 +23,6 @@ pub fn main() { file.write_str("pub fn wheeeee() { for [1, 2, 3].each() |_| { assert!(true); } }"); // now compile the crate itself - run::run_program("rustc", ~[~"src/fancy-lib/fancy-lib.rs", ~"--lib", - ~"-o", out_path.push(~"fancy_lib").to_str()]); + run::process_status("rustc", [~"src/fancy-lib/fancy-lib.rs", ~"--lib", ~"-o", + out_path.push(~"fancy_lib").to_str()]); } \ No newline at end of file diff --git a/src/librustpkg/testsuite/pass/src/foo/lib.rs b/src/librustpkg/testsuite/pass/src/foo/lib.rs new file mode 100644 index 0000000000000..91fc466f8c65b --- /dev/null +++ b/src/librustpkg/testsuite/pass/src/foo/lib.rs @@ -0,0 +1,11 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn f() {} diff --git a/src/librustpkg/testsuite/pass/src/install-paths/test.rs b/src/librustpkg/testsuite/pass/src/install-paths/test.rs index acfae9e04fb59..011a1540e1bca 100644 --- a/src/librustpkg/testsuite/pass/src/install-paths/test.rs +++ b/src/librustpkg/testsuite/pass/src/install-paths/test.rs @@ -10,5 +10,5 @@ #[test] fn test_two_plus_two() { - assert!(2 + 2 == 4); + assert_eq!(2 + 2, 4); } diff --git a/src/librustpkg/usage.rs b/src/librustpkg/usage.rs index cfda56f777ab2..90c87210faaa8 100644 --- a/src/librustpkg/usage.rs +++ b/src/librustpkg/usage.rs @@ -11,7 +11,7 @@ use core::io; pub fn general() { - io::println(~"Usage: rustpkg [options] [args..] + io::println("Usage: rustpkg [options] [args..] Where is one of: build, clean, do, info, install, prefer, test, uninstall, unprefer @@ -23,7 +23,7 @@ Options: } pub fn build() { - io::println(~"rustpkg [options..] build + io::println("rustpkg [options..] build Build all targets described in the package script in the current directory. @@ -33,21 +33,21 @@ Options: } pub fn clean() { - io::println(~"rustpkg clean + io::println("rustpkg clean Remove all build files in the work cache for the package in the current directory."); } pub fn do_cmd() { - io::println(~"rustpkg do + io::println("rustpkg do Runs a command in the package script. You can listen to a command by tagging a function with the attribute `#[pkg_do(cmd)]`."); } pub fn info() { - io::println(~"rustpkg [options..] info + io::println("rustpkg [options..] info Probe the package script in the current directory for information. @@ -56,7 +56,7 @@ Options: } pub fn install() { - io::println(~"rustpkg [options..] install [url] [target] + io::println("rustpkg [options..] install [url] [target] Install a package from a URL by Git or cURL (FTP, HTTP, etc.). If target is provided, Git will checkout the branch or tag before @@ -76,14 +76,14 @@ Options: } pub fn uninstall() { - io::println(~"rustpkg uninstall [@version] + io::println("rustpkg uninstall [@version] Remove a package by id or name and optionally version. If the package(s) is/are depended on by another package then they cannot be removed."); } pub fn prefer() { - io::println(~"rustpkg [options..] prefer [@version] + io::println("rustpkg [options..] prefer [@version] By default all binaries are given a unique name so that multiple versions can coexist. The prefer command will symlink the uniquely named binary to @@ -101,7 +101,7 @@ Example: } pub fn unprefer() { - io::println(~"rustpkg [options..] unprefer [@version] + io::println("rustpkg [options..] unprefer [@version] Remove all symlinks from the store to the binary directory for a package name and optionally version. If version is not supplied, the latest version @@ -110,7 +110,7 @@ information."); } pub fn test() { - io::println(~"rustpkg [options..] test + io::println("rustpkg [options..] test Build all targets described in the package script in the current directory with the test flag. The test bootstraps will be run afterwards and the output diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs index 4a9c276948aa0..33745e85387e5 100644 --- a/src/librustpkg/util.rs +++ b/src/librustpkg/util.rs @@ -8,23 +8,29 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::*; -use core::cmp::Ord; -use core::hash::Streaming; -use core::rt::io::Writer; +use core::prelude::*; +use core::{io, libc, os, result, str}; use rustc::driver::{driver, session}; use rustc::metadata::filesearch; -use std::getopts::groups::getopts; -use std::semver; -use std::{term, getopts}; +use extra::getopts::groups::getopts; +use extra::term; +#[cfg(not(test))] +use extra::getopts; use syntax::ast_util::*; -use syntax::codemap::{dummy_sp, spanned, dummy_spanned}; -use syntax::ext::base::{mk_ctxt, ext_ctxt}; +use syntax::codemap::{dummy_sp, spanned}; +use syntax::codemap::dummy_spanned; +use syntax::ext::base::ExtCtxt; use syntax::{ast, attr, codemap, diagnostic, fold}; use syntax::ast::{meta_name_value, meta_list}; use syntax::attr::{mk_attr}; use rustc::back::link::output_type_exe; +use rustc::driver::driver::compile_upto; use rustc::driver::session::{lib_crate, bin_crate}; +use context::Ctx; +use package_id::PkgId; +use path_util::target_library_in_workspace; +use search::find_library_in_search_path; +pub use target::{OutputType, Main, Lib, Bench, Test}; static Commands: &'static [&'static str] = &["build", "clean", "do", "info", "install", "prefer", "test", "uninstall", @@ -33,119 +39,6 @@ static Commands: &'static [&'static str] = pub type ExitCode = int; // For now -/// A version is either an exact revision, -/// or a semantic version -pub enum Version { - ExactRevision(float), - SemVersion(semver::Version) -} - -impl Ord for Version { - fn lt(&self, other: &Version) -> bool { - match (self, other) { - (&ExactRevision(f1), &ExactRevision(f2)) => f1 < f2, - (&SemVersion(ref v1), &SemVersion(ref v2)) => v1 < v2, - _ => false // incomparable, really - } - } - fn le(&self, other: &Version) -> bool { - match (self, other) { - (&ExactRevision(f1), &ExactRevision(f2)) => f1 <= f2, - (&SemVersion(ref v1), &SemVersion(ref v2)) => v1 <= v2, - _ => false // incomparable, really - } - } - fn ge(&self, other: &Version) -> bool { - match (self, other) { - (&ExactRevision(f1), &ExactRevision(f2)) => f1 > f2, - (&SemVersion(ref v1), &SemVersion(ref v2)) => v1 > v2, - _ => false // incomparable, really - } - } - fn gt(&self, other: &Version) -> bool { - match (self, other) { - (&ExactRevision(f1), &ExactRevision(f2)) => f1 >= f2, - (&SemVersion(ref v1), &SemVersion(ref v2)) => v1 >= v2, - _ => false // incomparable, really - } - } - -} - -impl ToStr for Version { - fn to_str(&self) -> ~str { - match *self { - ExactRevision(ref n) => n.to_str(), - SemVersion(ref v) => v.to_str() - } - } -} - -#[deriving(Eq)] -pub enum OutputType { Main, Lib, Bench, Test } - -/// Placeholder -pub fn default_version() -> Version { ExactRevision(0.1) } - -/// Path-fragment identifier of a package such as -/// 'github.com/graydon/test'; path must be a relative -/// path with >=1 component. -pub struct PkgId { - /// Remote path: for example, github.com/mozilla/quux-whatever - remote_path: RemotePath, - /// Local path: for example, /home/quux/github.com/mozilla/quux_whatever - /// Note that '-' normalizes to '_' when mapping a remote path - /// onto a local path - /// Also, this will change when we implement #6407, though we'll still - /// need to keep track of separate local and remote paths - local_path: LocalPath, - /// Short name. This is the local path's filestem, but we store it - /// redundantly so as to not call get() everywhere (filestem() returns an - /// option) - short_name: ~str, - version: Version -} - -pub impl PkgId { - fn new(s: &str) -> PkgId { - use conditions::bad_pkg_id::cond; - - let p = Path(s); - if p.is_absolute { - return cond.raise((p, ~"absolute pkgid")); - } - if p.components.len() < 1 { - return cond.raise((p, ~"0-length pkgid")); - } - let remote_path = RemotePath(p); - let local_path = normalize(copy remote_path); - let short_name = (copy local_path).filestem().expect(fmt!("Strange path! %s", s)); - PkgId { - local_path: local_path, - remote_path: remote_path, - short_name: short_name, - version: default_version() - } - } - - fn hash(&self) -> ~str { - fmt!("%s-%s-%s", self.remote_path.to_str(), - hash(self.remote_path.to_str() + self.version.to_str()), - self.version.to_str()) - } - - fn short_name_with_version(&self) -> ~str { - fmt!("%s-%s", self.short_name, self.version.to_str()) - } -} - -impl ToStr for PkgId { - fn to_str(&self) -> ~str { - // should probably use the filestem and not the whole path - fmt!("%s-%s", self.local_path.to_str(), self.version.to_str()) - } -} - pub struct Pkg { id: PkgId, bins: ~[~str], @@ -178,7 +71,7 @@ struct ListenerFn { struct ReadyCtx { sess: session::Session, crate: @ast::crate, - ext_cx: @ext_ctxt, + ext_cx: @ExtCtxt, path: ~[ast::ident], fns: ~[ListenerFn] } @@ -208,7 +101,7 @@ fn fold_item(ctx: @mut ReadyCtx, fold: @fold::ast_fold) -> Option<@ast::item> { ctx.path.push(item.ident); - let attrs = attr::find_attrs_by_name(item.attrs, ~"pkg_do"); + let attrs = attr::find_attrs_by_name(item.attrs, "pkg_do"); if attrs.len() > 0 { let mut cmds = ~[]; @@ -247,7 +140,7 @@ pub fn ready_crate(sess: session::Session, let ctx = @mut ReadyCtx { sess: sess, crate: crate, - ext_cx: mk_ctxt(sess.parse_sess, copy sess.opts.cfg), + ext_cx: ExtCtxt::new(sess.parse_sess, copy sess.opts.cfg), path: ~[], fns: ~[] }; @@ -263,67 +156,41 @@ pub fn ready_crate(sess: session::Session, @fold.fold_crate(crate) } -pub fn parse_vers(vers: ~str) -> result::Result { - match semver::parse(vers) { - Some(vers) => result::Ok(vers), - None => result::Err(~"could not parse version: invalid") - } -} - pub fn need_dir(s: &Path) { if !os::path_is_dir(s) && !os::make_dir(s, 493_i32) { fail!("can't create dir: %s", s.to_str()); } } -pub fn note(msg: ~str) { - let out = io::stdout(); - - if term::color_supported() { - term::fg(out, term::color_green); - out.write_str(~"note: "); - term::reset(out); - out.write_line(msg); - } else { - out.write_line(~"note: " + msg); +fn pretty_message<'a>(msg: &'a str, prefix: &'a str, color: u8, out: @io::Writer) { + let term = term::Terminal::new(out); + match term { + Ok(ref t) => { + t.fg(color); + out.write_str(prefix); + t.reset(); + }, + _ => { + out.write_str(prefix); + } } + out.write_line(msg); } -pub fn warn(msg: ~str) { - let out = io::stdout(); - - if term::color_supported() { - term::fg(out, term::color_yellow); - out.write_str(~"warning: "); - term::reset(out); - out.write_line(msg); - } else { - out.write_line(~"warning: " + msg); - } +pub fn note(msg: &str) { + pretty_message(msg, "note: ", term::color_green, io::stdout()) } -pub fn error(msg: ~str) { - let out = io::stdout(); - - if term::color_supported() { - term::fg(out, term::color_red); - out.write_str(~"error: "); - term::reset(out); - out.write_line(msg); - } else { - out.write_line(~"error: " + msg); - } +pub fn warn(msg: &str) { + pretty_message(msg, "warning: ", term::color_yellow, io::stdout()) } -pub fn hash(data: ~str) -> ~str { - let mut hasher = hash::default_state(); - let buffer = str::as_bytes_slice(data); - hasher.write(buffer); - hasher.result_str() +pub fn error(msg: &str) { + pretty_message(msg, "error: ", term::color_red, io::stdout()) } // FIXME (#4432): Use workcache to only compile when needed -pub fn compile_input(sysroot: Option<@Path>, +pub fn compile_input(ctxt: &Ctx, pkg_id: &PkgId, in_file: &Path, out_dir: &Path, @@ -332,6 +199,8 @@ pub fn compile_input(sysroot: Option<@Path>, opt: bool, what: OutputType) -> bool { + let workspace = out_dir.pop().pop(); + assert!(in_file.components.len() > 1); let input = driver::file_input(copy *in_file); debug!("compile_input: %s / %?", in_file.to_str(), what); @@ -339,23 +208,10 @@ pub fn compile_input(sysroot: Option<@Path>, // not sure if we should support anything else let binary = @(copy os::args()[0]); - let building_library = what == Lib; - - let out_file = if building_library { - out_dir.push(os::dll_filename(pkg_id.short_name)) - } - else { - out_dir.push(pkg_id.short_name + match what { - Test => ~"test", Bench => ~"bench", Main | Lib => ~"" - } + os::EXE_SUFFIX) - }; - debug!("compiling %s into %s", - in_file.to_str(), - out_file.to_str()); - debug!("flags: %s", str::connect(flags, ~" ")); - debug!("cfgs: %s", str::connect(cfgs, ~" ")); - debug!("compile_input's sysroot = %?", sysroot); + debug!("flags: %s", str::connect(flags, " ")); + debug!("cfgs: %s", str::connect(cfgs, " ")); + debug!("compile_input's sysroot = %?", ctxt.sysroot_opt); let crate_type = match what { Lib => lib_crate, @@ -371,28 +227,62 @@ pub fn compile_input(sysroot: Option<@Path>, + flags + cfgs.flat_map(|&c| { ~[~"--cfg", c] }), driver::optgroups()).get(); - let mut options = session::options { + let options = @session::options { crate_type: crate_type, optimize: if opt { session::Aggressive } else { session::No }, test: what == Test || what == Bench, - maybe_sysroot: sysroot, - addl_lib_search_paths: ~[copy *out_dir], + maybe_sysroot: ctxt.sysroot_opt, + addl_lib_search_paths: @mut ~[copy *out_dir], // output_type should be conditional output_type: output_type_exe, // Use this to get a library? That's weird .. copy *driver::build_session_options(binary, &matches, diagnostic::emit) }; - for cfgs.each |&cfg| { - options.cfg.push(attr::mk_word_item(@cfg)); - } + let addl_lib_search_paths = @mut options.addl_lib_search_paths; + + let sess = driver::build_session(options, diagnostic::emit); - let sess = driver::build_session(@options, diagnostic::emit); + // Infer dependencies that rustpkg needs to build, by scanning for + // `extern mod` directives. + let cfg = driver::build_configuration(sess, binary, &input); + let (crate_opt, _) = driver::compile_upto(sess, copy cfg, &input, driver::cu_expand, None); + + let mut crate = match crate_opt { + Some(c) => c, + None => fail!("compile_input expected...") + }; + + // Not really right. Should search other workspaces too, and the installed + // database (which doesn't exist yet) + find_and_install_dependencies(ctxt, sess, &workspace, crate, + |p| { + debug!("a dependency: %s", p.to_str()); + // Pass the directory containing a dependency + // as an additional lib search path + addl_lib_search_paths.push(p); + }); + + // Inject the link attributes so we get the right package name and version + if attr::find_linkage_metas(crate.node.attrs).is_empty() { + let short_name_to_use = match what { + Test => fmt!("%stest", pkg_id.short_name), + Bench => fmt!("%sbench", pkg_id.short_name), + _ => copy pkg_id.short_name + }; + debug!("Injecting link name: %s", short_name_to_use); + crate = @codemap::respan(crate.span, ast::crate_ { + attrs: ~[mk_attr(@dummy_spanned( + meta_list(@~"link", + ~[@dummy_spanned(meta_name_value(@~"name", + mk_string_lit(@short_name_to_use))), + @dummy_spanned(meta_name_value(@~"vers", + mk_string_lit(@(copy pkg_id.version.to_str()))))])))], + ..copy crate.node}); + } debug!("calling compile_crate_from_input, out_dir = %s, building_library = %?", out_dir.to_str(), sess.building_library); - let _ = compile_crate_from_input(&input, pkg_id, Some(copy *out_dir), sess, - None, &out_file, binary, - driver::cu_everything); + compile_crate_from_input(&input, out_dir, sess, crate, copy cfg); true } @@ -402,52 +292,31 @@ pub fn compile_input(sysroot: Option<@Path>, // call compile_upto and return the crate // also, too many arguments pub fn compile_crate_from_input(input: &driver::input, - pkg_id: &PkgId, - build_dir_opt: Option, + build_dir: &Path, sess: session::Session, - crate_opt: Option<@ast::crate>, - out_file: &Path, - binary: @~str, - what: driver::compile_upto) -> @ast::crate { - debug!("Calling build_output_filenames with %? and %s", build_dir_opt, out_file.to_str()); - let outputs = driver::build_output_filenames(input, &build_dir_opt, - &Some(copy *out_file), sess); - debug!("Outputs are %? and output type = %?", outputs, sess.opts.output_type); - let cfg = driver::build_configuration(sess, binary, input); - match crate_opt { - Some(c) => { - debug!("Calling compile_rest, outputs = %?", outputs); - assert!(what == driver::cu_everything); - driver::compile_rest(sess, cfg, driver::cu_everything, Some(outputs), Some(c)); - c - } - None => { - debug!("Calling compile_upto, outputs = %?", outputs); - let (crate, _) = driver::compile_upto(sess, copy cfg, input, - driver::cu_parse, Some(outputs)); - let mut crate = crate; - - debug!("About to inject link_meta info..."); - // Inject the inferred link_meta info if it's not already there - // (assumes that name and vers are the only linkage metas) - - debug!("How many attrs? %?", attr::find_linkage_metas(crate.node.attrs).len()); - - if attr::find_linkage_metas(crate.node.attrs).is_empty() { - crate = @codemap::respan(crate.span, ast::crate_ { - attrs: ~[mk_attr(@dummy_spanned( - meta_list(@~"link", - ~[@dummy_spanned(meta_name_value(@~"name", - mk_string_lit(@(copy pkg_id.short_name)))), - @dummy_spanned(meta_name_value(@~"vers", - mk_string_lit(@(copy pkg_id.version.to_str()))))])))], - ..copy crate.node}); - } + crate: @ast::crate, + cfg: ast::crate_cfg) { + debug!("Calling build_output_filenames with %s, building library? %?", + build_dir.to_str(), sess.building_library); - driver::compile_rest(sess, cfg, what, Some(outputs), Some(crate)); - crate - } + // bad copy + let outputs = driver::build_output_filenames(input, &Some(copy *build_dir), &None, + crate.node.attrs, sess); + + debug!("Outputs are %? and output type = %?", outputs, sess.opts.output_type); + debug!("additional libraries:"); + for sess.opts.addl_lib_search_paths.each |lib| { + debug!("an additional library: %s", lib.to_str()); } + + driver::compile_rest(sess, + cfg, + compile_upto { + from: driver::cu_expand, + to: driver::cu_everything + }, + Some(outputs), + Some(crate)); } #[cfg(windows)] @@ -461,7 +330,7 @@ pub fn exe_suffix() -> ~str { ~"" } // Called by build_crates // FIXME (#4432): Use workcache to only compile when needed -pub fn compile_crate(sysroot: Option<@Path>, pkg_id: &PkgId, +pub fn compile_crate(ctxt: &Ctx, pkg_id: &PkgId, crate: &Path, dir: &Path, flags: &[~str], cfgs: &[~str], opt: bool, what: OutputType) -> bool { @@ -470,26 +339,51 @@ pub fn compile_crate(sysroot: Option<@Path>, pkg_id: &PkgId, for flags.each |&fl| { debug!("+++ %s", fl); } - compile_input(sysroot, pkg_id, crate, dir, flags, cfgs, opt, what) + compile_input(ctxt, pkg_id, crate, dir, flags, cfgs, opt, what) } -// normalize should be the only way to construct a LocalPath -// (though this isn't enforced) -/// Replace all occurrences of '-' in the stem part of path with '_' -/// This is because we treat rust-foo-bar-quux and rust_foo_bar_quux -/// as the same name -pub fn normalize(p_: RemotePath) -> LocalPath { - let RemotePath(p) = p_; - match p.filestem() { - None => LocalPath(p), - Some(st) => { - let replaced = str::replace(st, "-", "_"); - if replaced != st { - LocalPath(p.with_filestem(replaced)) - } - else { - LocalPath(p) +/// Collect all `extern mod` directives in `c`, then +/// try to install their targets, failing if any target +/// can't be found. +fn find_and_install_dependencies(ctxt: &Ctx, + sess: session::Session, + workspace: &Path, + c: &ast::crate, + save: @fn(Path) + ) { + // :-( + debug!("In find_and_install_dependencies..."); + let my_workspace = copy *workspace; + let my_ctxt = copy *ctxt; + for c.each_view_item() |vi: @ast::view_item| { + debug!("A view item!"); + match vi.node { + // ignore metadata, I guess + ast::view_item_extern_mod(lib_ident, _, _) => { + match my_ctxt.sysroot_opt { + Some(ref x) => debug!("sysroot: %s", x.to_str()), + None => () + }; + let lib_name = sess.str_of(lib_ident); + match find_library_in_search_path(my_ctxt.sysroot_opt, *lib_name) { + Some(installed_path) => { + debug!("It exists: %s", installed_path.to_str()); + } + None => { + // Try to install it + let pkg_id = PkgId::new(*lib_name); + my_ctxt.install(&my_workspace, &pkg_id); + // Also, add an additional search path + let installed_path = target_library_in_workspace(&pkg_id, + &my_workspace).pop(); + debug!("Great, I installed %s, and it's in %s", + *lib_name, installed_path.to_str()); + save(installed_path); + } + } } + // Ignore `use`s + _ => () } } } @@ -525,25 +419,21 @@ pub fn mk_string_lit(s: @~str) -> ast::lit { } } -/// Wrappers to prevent local and remote paths from getting confused -pub struct RemotePath (Path); -pub struct LocalPath (Path); - #[cfg(test)] mod test { use super::is_cmd; #[test] fn test_is_cmd() { - assert!(is_cmd(~"build")); - assert!(is_cmd(~"clean")); - assert!(is_cmd(~"do")); - assert!(is_cmd(~"info")); - assert!(is_cmd(~"install")); - assert!(is_cmd(~"prefer")); - assert!(is_cmd(~"test")); - assert!(is_cmd(~"uninstall")); - assert!(is_cmd(~"unprefer")); + assert!(is_cmd("build")); + assert!(is_cmd("clean")); + assert!(is_cmd("do")); + assert!(is_cmd("info")); + assert!(is_cmd("install")); + assert!(is_cmd("prefer")); + assert!(is_cmd("test")); + assert!(is_cmd("uninstall")); + assert!(is_cmd("unprefer")); } } diff --git a/src/librustpkg/workspace.rs b/src/librustpkg/workspace.rs index cb9f735bce8d4..3010e27385fa0 100644 --- a/src/librustpkg/workspace.rs +++ b/src/librustpkg/workspace.rs @@ -11,7 +11,7 @@ // rustpkg utilities having to do with workspaces use path_util::{rust_path, workspace_contains_package_id}; -use util::PkgId; +use package_id::PkgId; use core::path::Path; pub fn pkg_parent_workspaces(pkgid: &PkgId, action: &fn(&Path) -> bool) -> bool { diff --git a/src/libcore/at_vec.rs b/src/libstd/at_vec.rs similarity index 88% rename from src/libcore/at_vec.rs rename to src/libstd/at_vec.rs index 93bbf8fb66214..23f901c23ed2d 100644 --- a/src/libcore/at_vec.rs +++ b/src/libstd/at_vec.rs @@ -101,6 +101,9 @@ pub fn build_sized_opt(size: Option, } // Appending + +/// Iterates over the `rhs` vector, copying each element and appending it to the +/// `lhs`. Afterwards, the `lhs` is then returned for use again. #[inline(always)] pub fn append(lhs: @[T], rhs: &const [T]) -> @[T] { do build_sized(lhs.len() + rhs.len()) |push| { @@ -211,6 +214,9 @@ pub mod raw { (**repr).unboxed.fill = new_len * sys::size_of::(); } + /** + * Pushes a new value onto this vector. + */ #[inline(always)] pub unsafe fn push(v: &mut @[T], initval: T) { let repr: **VecRepr = transmute_copy(&v); @@ -223,7 +229,7 @@ pub mod raw { } #[inline(always)] // really pretty please - pub unsafe fn push_fast(v: &mut @[T], initval: T) { + unsafe fn push_fast(v: &mut @[T], initval: T) { let repr: **mut VecRepr = ::cast::transmute(v); let fill = (**repr).unboxed.fill; (**repr).unboxed.fill += sys::size_of::(); @@ -232,7 +238,7 @@ pub mod raw { move_val_init(&mut(*p), initval); } - pub unsafe fn push_slow(v: &mut @[T], initval: T) { + unsafe fn push_slow(v: &mut @[T], initval: T) { reserve_at_least(&mut *v, v.len() + 1u); push_fast(v, initval); } @@ -282,6 +288,8 @@ mod test { use super::*; use prelude::*; + use uint; + #[test] fn test() { // Some code that could use that, then: @@ -294,30 +302,30 @@ mod test { } assert_eq!(seq_range(10, 15), @[10, 11, 12, 13, 14]); - assert!(from_fn(5, |x| x+1) == @[1, 2, 3, 4, 5]); - assert!(from_elem(5, 3.14) == @[3.14, 3.14, 3.14, 3.14, 3.14]); + assert_eq!(from_fn(5, |x| x+1), @[1, 2, 3, 4, 5]); + assert_eq!(from_elem(5, 3.14), @[3.14, 3.14, 3.14, 3.14, 3.14]); } #[test] fn append_test() { - assert!(@[1,2,3] + @[4,5,6] == @[1,2,3,4,5,6]); + assert_eq!(@[1,2,3] + [4,5,6], @[1,2,3,4,5,6]); } #[test] fn test_to_managed_consume() { - assert!(to_managed_consume::(~[]) == @[]); - assert!(to_managed_consume(~[true]) == @[true]); - assert!(to_managed_consume(~[1, 2, 3, 4, 5]) == @[1, 2, 3, 4, 5]); - assert!(to_managed_consume(~[~"abc", ~"123"]) == @[~"abc", ~"123"]); - assert!(to_managed_consume(~[~[42]]) == @[~[42]]); + assert_eq!(to_managed_consume::(~[]), @[]); + assert_eq!(to_managed_consume(~[true]), @[true]); + assert_eq!(to_managed_consume(~[1, 2, 3, 4, 5]), @[1, 2, 3, 4, 5]); + assert_eq!(to_managed_consume(~[~"abc", ~"123"]), @[~"abc", ~"123"]); + assert_eq!(to_managed_consume(~[~[42]]), @[~[42]]); } #[test] fn test_to_managed() { - assert!(to_managed::([]) == @[]); - assert!(to_managed([true]) == @[true]); - assert!(to_managed([1, 2, 3, 4, 5]) == @[1, 2, 3, 4, 5]); - assert!(to_managed([@"abc", @"123"]) == @[@"abc", @"123"]); - assert!(to_managed([@[42]]) == @[@[42]]); + assert_eq!(to_managed::([]), @[]); + assert_eq!(to_managed([true]), @[true]); + assert_eq!(to_managed([1, 2, 3, 4, 5]), @[1, 2, 3, 4, 5]); + assert_eq!(to_managed([@"abc", @"123"]), @[@"abc", @"123"]); + assert_eq!(to_managed([@[42]]), @[@[42]]); } } diff --git a/src/libstd/bool.rs b/src/libstd/bool.rs new file mode 100644 index 0000000000000..66a5bfa944f10 --- /dev/null +++ b/src/libstd/bool.rs @@ -0,0 +1,358 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/*! + +The `bool` module contains useful code to help work with boolean values. + +A quick summary: + +## Trait implementations for `bool` + +Implementations of the following traits: + +* `FromStr` +* `Ord` +* `TotalOrd` +* `Eq` + +## Various functions to compare `bool`s + +All of the standard comparison functions one would expect: `and`, `eq`, `or`, +and more. + +Also, a few conversion functions: `to_bit` and `to_str`. + +Finally, some inquries into the nature of truth: `is_true` and `is_false`. + +*/ + +#[cfg(not(test))] +use cmp::{Eq, Ord, TotalOrd, Ordering}; +use option::{None, Option, Some}; +use from_str::FromStr; +use to_str::ToStr; + +/** +* Negation of a boolean value. +* +* # Examples +* +* ~~~ {.rust} +* rusti> std::bool::not(true) +* false +* ~~~ +* +* ~~~ {.rust} +* rusti> std::bool::not(false) +* true +* ~~~ +*/ +pub fn not(v: bool) -> bool { !v } + +/** +* Conjunction of two boolean values. +* +* # Examples +* +* ~~~ {.rust} +* rusti> std::bool::and(true, false) +* false +* ~~~ +* +* ~~~ {.rust} +* rusti> std::bool::and(true, true) +* true +* ~~~ +*/ +pub fn and(a: bool, b: bool) -> bool { a && b } + +/** +* Disjunction of two boolean values. +* +* # Examples +* +* ~~~ {.rust} +* rusti> std::bool::or(true, false) +* true +* ~~~ +* +* ~~~ {.rust} +* rusti> std::bool::or(false, false) +* false +* ~~~ +*/ +pub fn or(a: bool, b: bool) -> bool { a || b } + +/** +* An 'exclusive or' of two boolean values. +* +* 'exclusive or' is identical to `or(and(a, not(b)), and(not(a), b))`. +* +* # Examples +* +* ~~~ {.rust} +* rusti> std::bool::xor(true, false) +* true +* ~~~ +* +* ~~~ {.rust} +* rusti> std::bool::xor(true, true) +* false +* ~~~ +*/ +pub fn xor(a: bool, b: bool) -> bool { (a && !b) || (!a && b) } + +/** +* Implication between two boolean values. +* +* Implication is often phrased as 'if a then b.' +* +* 'if a then b' is equivalent to `!a || b`. +* +* # Examples +* +* ~~~ {.rust} +* rusti> std::bool::implies(true, true) +* true +* +* ~~~ {.rust} +* rusti> std::bool::implies(true, false) +* false +* ~~~ +*/ +pub fn implies(a: bool, b: bool) -> bool { !a || b } + +/** +* Is a given boolean value true? +* +* # Examples +* +* ~~~ {.rust} +* rusti> std::bool::is_true(true) +* true +* ~~~ +* +* ~~~ {.rust} +* rusti> std::bool::is_true(false) +* false +* ~~~ +*/ +pub fn is_true(v: bool) -> bool { v } + +/** +* Is a given boolean value false? +* +* # Examples +* +* ~~~ {.rust} +* rusti> std::bool::is_false(false) +* true +* ~~~ +* +* ~~~ {.rust} +* rusti> std::bool::is_false(true) +* false +* ~~~ +*/ +pub fn is_false(v: bool) -> bool { !v } + +/** +* Parse a `bool` from a `str`. +* +* Yields an `Option`, because `str` may or may not actually be parseable. +* +* # Examples +* +* ~~~ {.rust} +* rusti> FromStr::from_str::("true") +* Some(true) +* ~~~ +* +* ~~~ {.rust} +* rusti> FromStr::from_str::("false") +* Some(false) +* ~~~ +* +* ~~~ {.rust} +* rusti> FromStr::from_str::("not even a boolean") +* None +* ~~~ +*/ +impl FromStr for bool { + fn from_str(s: &str) -> Option { + match s { + "true" => Some(true), + "false" => Some(false), + _ => None, + } + } +} + +/** +* Convert a `bool` to a `str`. +* +* # Examples +* +* ~~~ {.rust} +* rusti> true.to_str() +* "true" +* ~~~ +* +* ~~~ {.rust} +* rusti> false.to_str() +* "false" +* ~~~ +*/ +impl ToStr for bool { + #[inline(always)] + fn to_str(&self) -> ~str { + if *self { ~"true" } else { ~"false" } + } +} + +/** +* Iterates over all truth values, passing them to the given block. +* +* There are no guarantees about the order values will be given. +* +* # Examples +* ~~~ +* do std::bool::all_values |x: bool| { +* println(x.to_str()) +* } +* ~~~ +*/ +pub fn all_values(blk: &fn(v: bool)) { + blk(true); + blk(false); +} + +/** +* Convert a `bool` to a `u8`. +* +* # Examples +* +* ~~~ {.rust} +* rusti> std::bool::to_bit(true) +* 1 +* ~~~ +* +* ~~~ {.rust} +* rusti> std::bool::to_bit(false) +* 0 +* ~~~ +*/ +#[inline(always)] +pub fn to_bit(v: bool) -> u8 { if v { 1u8 } else { 0u8 } } + +#[cfg(not(test))] +impl Ord for bool { + #[inline(always)] + fn lt(&self, other: &bool) -> bool { to_bit(*self) < to_bit(*other) } + #[inline(always)] + fn le(&self, other: &bool) -> bool { to_bit(*self) <= to_bit(*other) } + #[inline(always)] + fn gt(&self, other: &bool) -> bool { to_bit(*self) > to_bit(*other) } + #[inline(always)] + fn ge(&self, other: &bool) -> bool { to_bit(*self) >= to_bit(*other) } +} + +#[cfg(not(test))] +impl TotalOrd for bool { + #[inline(always)] + fn cmp(&self, other: &bool) -> Ordering { to_bit(*self).cmp(&to_bit(*other)) } +} + +/** +* Equality between two boolean values. +* +* Two booleans are equal if they have the same value. +* +* ~~~ {.rust} +* rusti> false.eq(&true) +* false +* ~~~ +* +* ~~~ {.rust} +* rusti> false == false +* true +* ~~~ +* +* ~~~ {.rust} +* rusti> false != true +* true +* ~~~ +* +* ~~~ {.rust} +* rusti> false.ne(&false) +* false +* ~~~ +*/ +#[cfg(not(test))] +impl Eq for bool { + #[inline(always)] + fn eq(&self, other: &bool) -> bool { (*self) == (*other) } + #[inline(always)] + fn ne(&self, other: &bool) -> bool { (*self) != (*other) } +} + +#[cfg(test)] +mod tests { + use super::*; + use prelude::*; + + #[test] + fn test_bool_from_str() { + do all_values |v| { + assert!(Some(v) == FromStr::from_str(v.to_str())) + } + } + + #[test] + fn test_bool_to_str() { + assert_eq!(false.to_str(), ~"false"); + assert_eq!(true.to_str(), ~"true"); + } + + #[test] + fn test_bool_to_bit() { + do all_values |v| { + assert_eq!(to_bit(v), if is_true(v) { 1u8 } else { 0u8 }); + } + } + + #[test] + fn test_bool_ord() { + assert!(true > false); + assert!(!(false > true)); + + assert!(false < true); + assert!(!(true < false)); + + assert!(false <= false); + assert!(false >= false); + assert!(true <= true); + assert!(true >= true); + + assert!(false <= true); + assert!(!(false >= true)); + assert!(true >= false); + assert!(!(true <= false)); + } + + #[test] + fn test_bool_totalord() { + assert_eq!(true.cmp(&true), Equal); + assert_eq!(false.cmp(&false), Equal); + assert_eq!(true.cmp(&false), Greater); + assert_eq!(false.cmp(&true), Less); + } +} diff --git a/src/libstd/borrow.rs b/src/libstd/borrow.rs new file mode 100644 index 0000000000000..703011aea7f86 --- /dev/null +++ b/src/libstd/borrow.rs @@ -0,0 +1,60 @@ +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Borrowed pointer utilities + +#[cfg(not(test))] +use prelude::*; + +/// Cast a region pointer - &T - to a uint. +#[inline(always)] +pub fn to_uint(thing: &T) -> uint { + thing as *T as uint +} + +/// Determine if two borrowed pointers point to the same thing. +#[inline(always)] +pub fn ref_eq<'a, 'b, T>(thing: &'a T, other: &'b T) -> bool { + to_uint(thing) == to_uint(other) +} + +// Equality for region pointers +#[cfg(not(test))] +impl<'self, T: Eq> Eq for &'self T { + #[inline(always)] + fn eq(&self, other: & &'self T) -> bool { + *(*self) == *(*other) + } + #[inline(always)] + fn ne(&self, other: & &'self T) -> bool { + *(*self) != *(*other) + } +} + +// Comparison for region pointers +#[cfg(not(test))] +impl<'self, T: Ord> Ord for &'self T { + #[inline(always)] + fn lt(&self, other: & &'self T) -> bool { + *(*self) < *(*other) + } + #[inline(always)] + fn le(&self, other: & &'self T) -> bool { + *(*self) <= *(*other) + } + #[inline(always)] + fn ge(&self, other: & &'self T) -> bool { + *(*self) >= *(*other) + } + #[inline(always)] + fn gt(&self, other: & &'self T) -> bool { + *(*self) > *(*other) + } +} diff --git a/src/libcore/cast.rs b/src/libstd/cast.rs similarity index 77% rename from src/libcore/cast.rs rename to src/libstd/cast.rs index 7451353458e28..2109568a0a4e0 100644 --- a/src/libcore/cast.rs +++ b/src/libstd/cast.rs @@ -11,42 +11,41 @@ //! Unsafe casting functions use sys; -use unstable; +use unstable::intrinsics; -pub mod rusti { - #[abi = "rust-intrinsic"] - #[link_name = "rusti"] - pub extern "rust-intrinsic" { - fn forget(x: T); - - fn transmute(e: T) -> U; +/// Casts the value at `src` to U. The two types must have the same length. +#[cfg(stage0)] +pub unsafe fn transmute_copy(src: &T) -> U { + let mut dest: U = intrinsics::uninit(); + { + let dest_ptr: *mut u8 = transmute(&mut dest); + let src_ptr: *u8 = transmute(src); + intrinsics::memmove64(dest_ptr, + src_ptr, + sys::size_of::() as u64); } + dest } /// Casts the value at `src` to U. The two types must have the same length. -#[cfg(not(stage0))] +#[cfg(target_word_size = "32", not(stage0))] +#[inline(always)] pub unsafe fn transmute_copy(src: &T) -> U { - let mut dest: U = unstable::intrinsics::uninit(); - { - let dest_ptr: *mut u8 = rusti::transmute(&mut dest); - let src_ptr: *u8 = rusti::transmute(src); - unstable::intrinsics::memmove64(dest_ptr, - src_ptr, - sys::size_of::() as u64); - } + let mut dest: U = intrinsics::uninit(); + let dest_ptr: *mut u8 = transmute(&mut dest); + let src_ptr: *u8 = transmute(src); + intrinsics::memcpy32(dest_ptr, src_ptr, sys::size_of::() as u32); dest } -#[cfg(stage0)] +/// Casts the value at `src` to U. The two types must have the same length. +#[cfg(target_word_size = "64", not(stage0))] +#[inline(always)] pub unsafe fn transmute_copy(src: &T) -> U { - let mut dest: U = unstable::intrinsics::init(); - { - let dest_ptr: *mut u8 = rusti::transmute(&mut dest); - let src_ptr: *u8 = rusti::transmute(src); - unstable::intrinsics::memmove64(dest_ptr, - src_ptr, - sys::size_of::() as u64); - } + let mut dest: U = intrinsics::uninit(); + let dest_ptr: *mut u8 = transmute(&mut dest); + let src_ptr: *u8 = transmute(src); + intrinsics::memcpy64(dest_ptr, src_ptr, sys::size_of::() as u64); dest } @@ -59,7 +58,7 @@ pub unsafe fn transmute_copy(src: &T) -> U { * reinterpret_cast on pointer types. */ #[inline(always)] -pub unsafe fn forget(thing: T) { rusti::forget(thing); } +pub unsafe fn forget(thing: T) { intrinsics::forget(thing); } /** * Force-increment the reference count on a shared box. If used @@ -67,6 +66,7 @@ pub unsafe fn forget(thing: T) { rusti::forget(thing); } * and/or reinterpret_cast when such calls would otherwise scramble a box's * reference count */ +#[inline(always)] pub unsafe fn bump_box_refcount(t: @T) { forget(t); } /** @@ -79,7 +79,7 @@ pub unsafe fn bump_box_refcount(t: @T) { forget(t); } */ #[inline(always)] pub unsafe fn transmute(thing: L) -> G { - rusti::transmute(thing) + intrinsics::transmute(thing) } /// Coerce an immutable reference to be mutable. @@ -145,7 +145,7 @@ mod tests { #[test] fn test_transmute_copy() { - assert!(1u == unsafe { ::cast::transmute_copy(&1) }); + assert_eq!(1u, unsafe { ::cast::transmute_copy(&1) }); } #[test] @@ -177,7 +177,7 @@ mod tests { #[test] fn test_transmute2() { unsafe { - assert!(~[76u8, 0u8] == transmute(~"L")); + assert_eq!(~[76u8, 0u8], transmute(~"L")); } } } diff --git a/src/libcore/cell.rs b/src/libstd/cell.rs similarity index 66% rename from src/libcore/cell.rs rename to src/libstd/cell.rs index 87e8d0525e5b0..e1d2b246dd370 100644 --- a/src/libcore/cell.rs +++ b/src/libstd/cell.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -10,6 +10,8 @@ //! A mutable, nullable memory location +#[missing_doc]; + use cast::transmute_mut; use prelude::*; use util::replace; @@ -21,36 +23,25 @@ Similar to a mutable option type, but friendlier. */ #[mutable] -#[deriving(Clone)] +#[deriving(Clone, DeepClone, Eq)] +#[allow(missing_doc)] pub struct Cell { priv value: Option } -impl DeepClone for Cell { - fn deep_clone(&self) -> Cell { - Cell{value: self.value.deep_clone()} +impl Cell { + /// Creates a new full cell with the given value. + pub fn new(value: T) -> Cell { + Cell { value: Some(value) } } -} -impl cmp::Eq for Cell { - fn eq(&self, other: &Cell) -> bool { - (self.value) == (other.value) + /// Creates a new empty cell with no value inside. + pub fn new_empty() -> Cell { + Cell { value: None } } - fn ne(&self, other: &Cell) -> bool { !self.eq(other) } -} - -/// Creates a new full cell with the given value. -pub fn Cell(value: T) -> Cell { - Cell { value: Some(value) } -} - -pub fn empty_cell() -> Cell { - Cell { value: None } -} -pub impl Cell { /// Yields the value, failing if the cell is empty. - fn take(&self) -> T { + pub fn take(&self) -> T { let this = unsafe { transmute_mut(self) }; if this.is_empty() { fail!("attempt to take an empty cell"); @@ -60,7 +51,7 @@ pub impl Cell { } /// Returns the value, failing if the cell is full. - fn put_back(&self, value: T) { + pub fn put_back(&self, value: T) { let this = unsafe { transmute_mut(self) }; if !this.is_empty() { fail!("attempt to put a value back into a full cell"); @@ -69,20 +60,20 @@ pub impl Cell { } /// Returns true if the cell is empty and false if the cell is full. - fn is_empty(&self) -> bool { + pub fn is_empty(&self) -> bool { self.value.is_none() } - // Calls a closure with a reference to the value. - fn with_ref(&self, op: &fn(v: &T) -> R) -> R { + /// Calls a closure with a reference to the value. + pub fn with_ref(&self, op: &fn(v: &T) -> R) -> R { let v = self.take(); let r = op(&v); self.put_back(v); r } - // Calls a closure with a mutable reference to the value. - fn with_mut_ref(&self, op: &fn(v: &mut T) -> R) -> R { + /// Calls a closure with a mutable reference to the value. + pub fn with_mut_ref(&self, op: &fn(v: &mut T) -> R) -> R { let mut v = self.take(); let r = op(&mut v); self.put_back(v); @@ -92,7 +83,7 @@ pub impl Cell { #[test] fn test_basic() { - let value_cell = Cell(~10); + let value_cell = Cell::new(~10); assert!(!value_cell.is_empty()); let value = value_cell.take(); assert!(value == ~10); @@ -105,7 +96,7 @@ fn test_basic() { #[should_fail] #[ignore(cfg(windows))] fn test_take_empty() { - let value_cell = empty_cell::<~int>(); + let value_cell = Cell::new_empty::<~int>(); value_cell.take(); } @@ -113,24 +104,24 @@ fn test_take_empty() { #[should_fail] #[ignore(cfg(windows))] fn test_put_back_non_empty() { - let value_cell = Cell(~10); + let value_cell = Cell::new(~10); value_cell.put_back(~20); } #[test] fn test_with_ref() { let good = 6; - let c = Cell(~[1, 2, 3, 4, 5, 6]); + let c = Cell::new(~[1, 2, 3, 4, 5, 6]); let l = do c.with_ref() |v| { v.len() }; - assert!(l == good); + assert_eq!(l, good); } #[test] fn test_with_mut_ref() { let good = ~[1, 2, 3]; let v = ~[1, 2]; - let c = Cell(v); + let c = Cell::new(v); do c.with_mut_ref() |v| { v.push(3); } let v = c.take(); - assert!(v == good); + assert_eq!(v, good); } diff --git a/src/libstd/char.rs b/src/libstd/char.rs new file mode 100644 index 0000000000000..073ced8988ada --- /dev/null +++ b/src/libstd/char.rs @@ -0,0 +1,411 @@ +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Utilities for manipulating the char type + +use option::{None, Option, Some}; +use str; +use str::{StrSlice, OwnedStr}; +use u32; +use uint; +use unicode::{derived_property, general_category}; + +#[cfg(not(test))] +use cmp::{Eq, Ord}; + +/* + Lu Uppercase_Letter an uppercase letter + Ll Lowercase_Letter a lowercase letter + Lt Titlecase_Letter a digraphic character, with first part uppercase + Lm Modifier_Letter a modifier letter + Lo Other_Letter other letters, including syllables and ideographs + Mn Nonspacing_Mark a nonspacing combining mark (zero advance width) + Mc Spacing_Mark a spacing combining mark (positive advance width) + Me Enclosing_Mark an enclosing combining mark + Nd Decimal_Number a decimal digit + Nl Letter_Number a letterlike numeric character + No Other_Number a numeric character of other type + Pc Connector_Punctuation a connecting punctuation mark, like a tie + Pd Dash_Punctuation a dash or hyphen punctuation mark + Ps Open_Punctuation an opening punctuation mark (of a pair) + Pe Close_Punctuation a closing punctuation mark (of a pair) + Pi Initial_Punctuation an initial quotation mark + Pf Final_Punctuation a final quotation mark + Po Other_Punctuation a punctuation mark of other type + Sm Math_Symbol a symbol of primarily mathematical use + Sc Currency_Symbol a currency sign + Sk Modifier_Symbol a non-letterlike modifier symbol + So Other_Symbol a symbol of other type + Zs Space_Separator a space character (of various non-zero widths) + Zl Line_Separator U+2028 LINE SEPARATOR only + Zp Paragraph_Separator U+2029 PARAGRAPH SEPARATOR only + Cc Control a C0 or C1 control code + Cf Format a format control character + Cs Surrogate a surrogate code point + Co Private_Use a private-use character + Cn Unassigned a reserved unassigned code point or a noncharacter +*/ + +/// Returns whether the specified character is considered a unicode alphabetic +/// character +pub fn is_alphabetic(c: char) -> bool { derived_property::Alphabetic(c) } +#[allow(missing_doc)] +pub fn is_XID_start(c: char) -> bool { derived_property::XID_Start(c) } +#[allow(missing_doc)] +pub fn is_XID_continue(c: char) -> bool { derived_property::XID_Continue(c) } + +/// +/// Indicates whether a character is in lower case, defined +/// in terms of the Unicode General Category 'Ll' +/// +#[inline(always)] +pub fn is_lowercase(c: char) -> bool { general_category::Ll(c) } + +/// +/// Indicates whether a character is in upper case, defined +/// in terms of the Unicode General Category 'Lu'. +/// +#[inline(always)] +pub fn is_uppercase(c: char) -> bool { general_category::Lu(c) } + +/// +/// Indicates whether a character is whitespace. Whitespace is defined in +/// terms of the Unicode General Categories 'Zs', 'Zl', 'Zp' +/// additional 'Cc'-category control codes in the range [0x09, 0x0d] +/// +#[inline(always)] +pub fn is_whitespace(c: char) -> bool { + ('\x09' <= c && c <= '\x0d') + || general_category::Zs(c) + || general_category::Zl(c) + || general_category::Zp(c) +} + +/// +/// Indicates whether a character is alphanumeric. Alphanumericness is +/// defined in terms of the Unicode General Categories 'Nd', 'Nl', 'No' +/// and the Derived Core Property 'Alphabetic'. +/// +#[inline(always)] +pub fn is_alphanumeric(c: char) -> bool { + derived_property::Alphabetic(c) + || general_category::Nd(c) + || general_category::Nl(c) + || general_category::No(c) +} + +/// Indicates whether the character is numeric (Nd, Nl, or No) +#[inline(always)] +pub fn is_digit(c: char) -> bool { + general_category::Nd(c) + || general_category::Nl(c) + || general_category::No(c) +} + +/// +/// Checks if a character parses as a numeric digit in the given radix. +/// Compared to `is_digit()`, this function only recognizes the +/// characters `0-9`, `a-z` and `A-Z`. +/// +/// # Return value +/// +/// Returns `true` if `c` is a valid digit under `radix`, and `false` +/// otherwise. +/// +/// # Failure +/// +/// Fails if given a `radix` > 36. +/// +/// # Note +/// +/// This just wraps `to_digit()`. +/// +#[inline(always)] +pub fn is_digit_radix(c: char, radix: uint) -> bool { + match to_digit(c, radix) { + Some(_) => true, + None => false, + } +} + +/// +/// Convert a char to the corresponding digit. +/// +/// # Return value +/// +/// If `c` is between '0' and '9', the corresponding value +/// between 0 and 9. If `c` is 'a' or 'A', 10. If `c` is +/// 'b' or 'B', 11, etc. Returns none if the char does not +/// refer to a digit in the given radix. +/// +/// # Failure +/// +/// Fails if given a `radix` outside the range `[0..36]`. +/// +#[inline] +pub fn to_digit(c: char, radix: uint) -> Option { + if radix > 36 { + fail!("to_digit: radix %? is to high (maximum 36)", radix); + } + let val = match c { + '0' .. '9' => c as uint - ('0' as uint), + 'a' .. 'z' => c as uint + 10u - ('a' as uint), + 'A' .. 'Z' => c as uint + 10u - ('A' as uint), + _ => return None, + }; + if val < radix { Some(val) } + else { None } +} + +/// +/// Converts a number to the character representing it. +/// +/// # Return value +/// +/// Returns `Some(char)` if `num` represents one digit under `radix`, +/// using one character of `0-9` or `a-z`, or `None` if it doesn't. +/// +/// # Failure +/// +/// Fails if given an `radix` > 36. +/// +#[inline] +pub fn from_digit(num: uint, radix: uint) -> Option { + if radix > 36 { + fail!("from_digit: radix %? is to high (maximum 36)", num); + } + if num < radix { + if num < 10 { + Some(('0' as uint + num) as char) + } else { + Some(('a' as uint + num - 10u) as char) + } + } else { + None + } +} + +/// +/// Return the hexadecimal unicode escape of a char. +/// +/// The rules are as follows: +/// +/// - chars in [0,0xff] get 2-digit escapes: `\\xNN` +/// - chars in [0x100,0xffff] get 4-digit escapes: `\\uNNNN` +/// - chars above 0x10000 get 8-digit escapes: `\\UNNNNNNNN` +/// +pub fn escape_unicode(c: char) -> ~str { + let s = u32::to_str_radix(c as u32, 16u); + let (c, pad) = cond!( + (c <= '\xff') { ('x', 2u) } + (c <= '\uffff') { ('u', 4u) } + _ { ('U', 8u) } + ); + assert!(s.len() <= pad); + let mut out = ~"\\"; + out.push_str(str::from_char(c)); + for uint::range(s.len(), pad) |_| { + out.push_str("0"); + } + out.push_str(s); + out +} + +/// +/// Return a 'default' ASCII and C++11-like char-literal escape of a char. +/// +/// The default is chosen with a bias toward producing literals that are +/// legal in a variety of languages, including C++11 and similar C-family +/// languages. The exact rules are: +/// +/// - Tab, CR and LF are escaped as '\t', '\r' and '\n' respectively. +/// - Single-quote, double-quote and backslash chars are backslash-escaped. +/// - Any other chars in the range [0x20,0x7e] are not escaped. +/// - Any other chars are given hex unicode escapes; see `escape_unicode`. +/// +pub fn escape_default(c: char) -> ~str { + match c { + '\t' => ~"\\t", + '\r' => ~"\\r", + '\n' => ~"\\n", + '\\' => ~"\\\\", + '\'' => ~"\\'", + '"' => ~"\\\"", + '\x20' .. '\x7e' => str::from_char(c), + _ => c.escape_unicode(), + } +} + +/// Returns the amount of bytes this character would need if encoded in utf8 +pub fn len_utf8_bytes(c: char) -> uint { + static MAX_ONE_B: uint = 128u; + static MAX_TWO_B: uint = 2048u; + static MAX_THREE_B: uint = 65536u; + static MAX_FOUR_B: uint = 2097152u; + + let code = c as uint; + cond!( + (code < MAX_ONE_B) { 1u } + (code < MAX_TWO_B) { 2u } + (code < MAX_THREE_B) { 3u } + (code < MAX_FOUR_B) { 4u } + _ { fail!("invalid character!") } + ) +} + +#[allow(missing_doc)] +pub trait Char { + fn is_alphabetic(&self) -> bool; + fn is_XID_start(&self) -> bool; + fn is_XID_continue(&self) -> bool; + fn is_lowercase(&self) -> bool; + fn is_uppercase(&self) -> bool; + fn is_whitespace(&self) -> bool; + fn is_alphanumeric(&self) -> bool; + fn is_digit(&self) -> bool; + fn is_digit_radix(&self, radix: uint) -> bool; + fn to_digit(&self, radix: uint) -> Option; + fn from_digit(num: uint, radix: uint) -> Option; + fn escape_unicode(&self) -> ~str; + fn escape_default(&self) -> ~str; + fn len_utf8_bytes(&self) -> uint; +} + +impl Char for char { + fn is_alphabetic(&self) -> bool { is_alphabetic(*self) } + + fn is_XID_start(&self) -> bool { is_XID_start(*self) } + + fn is_XID_continue(&self) -> bool { is_XID_continue(*self) } + + fn is_lowercase(&self) -> bool { is_lowercase(*self) } + + fn is_uppercase(&self) -> bool { is_uppercase(*self) } + + fn is_whitespace(&self) -> bool { is_whitespace(*self) } + + fn is_alphanumeric(&self) -> bool { is_alphanumeric(*self) } + + fn is_digit(&self) -> bool { is_digit(*self) } + + fn is_digit_radix(&self, radix: uint) -> bool { is_digit_radix(*self, radix) } + + fn to_digit(&self, radix: uint) -> Option { to_digit(*self, radix) } + + fn from_digit(num: uint, radix: uint) -> Option { from_digit(num, radix) } + + fn escape_unicode(&self) -> ~str { escape_unicode(*self) } + + fn escape_default(&self) -> ~str { escape_default(*self) } + + fn len_utf8_bytes(&self) -> uint { len_utf8_bytes(*self) } +} + +#[cfg(not(test))] +impl Eq for char { + #[inline(always)] + fn eq(&self, other: &char) -> bool { (*self) == (*other) } + #[inline(always)] + fn ne(&self, other: &char) -> bool { (*self) != (*other) } +} + +#[cfg(not(test))] +impl Ord for char { + #[inline(always)] + fn lt(&self, other: &char) -> bool { *self < *other } + #[inline(always)] + fn le(&self, other: &char) -> bool { *self <= *other } + #[inline(always)] + fn gt(&self, other: &char) -> bool { *self > *other } + #[inline(always)] + fn ge(&self, other: &char) -> bool { *self >= *other } +} + +#[test] +fn test_is_lowercase() { + assert!('a'.is_lowercase()); + assert!('ö'.is_lowercase()); + assert!('ß'.is_lowercase()); + assert!(!'Ü'.is_lowercase()); + assert!(!'P'.is_lowercase()); +} + +#[test] +fn test_is_uppercase() { + assert!(!'h'.is_uppercase()); + assert!(!'ä'.is_uppercase()); + assert!(!'ß'.is_uppercase()); + assert!('Ö'.is_uppercase()); + assert!('T'.is_uppercase()); +} + +#[test] +fn test_is_whitespace() { + assert!(' '.is_whitespace()); + assert!('\u2007'.is_whitespace()); + assert!('\t'.is_whitespace()); + assert!('\n'.is_whitespace()); + assert!(!'a'.is_whitespace()); + assert!(!'_'.is_whitespace()); + assert!(!'\u0000'.is_whitespace()); +} + +#[test] +fn test_to_digit() { + assert_eq!('0'.to_digit(10u), Some(0u)); + assert_eq!('1'.to_digit(2u), Some(1u)); + assert_eq!('2'.to_digit(3u), Some(2u)); + assert_eq!('9'.to_digit(10u), Some(9u)); + assert_eq!('a'.to_digit(16u), Some(10u)); + assert_eq!('A'.to_digit(16u), Some(10u)); + assert_eq!('b'.to_digit(16u), Some(11u)); + assert_eq!('B'.to_digit(16u), Some(11u)); + assert_eq!('z'.to_digit(36u), Some(35u)); + assert_eq!('Z'.to_digit(36u), Some(35u)); + assert_eq!(' '.to_digit(10u), None); + assert_eq!('$'.to_digit(36u), None); +} + +#[test] +fn test_is_digit() { + assert!('2'.is_digit()); + assert!('7'.is_digit()); + assert!(!'c'.is_digit()); + assert!(!'i'.is_digit()); + assert!(!'z'.is_digit()); + assert!(!'Q'.is_digit()); +} + +#[test] +fn test_escape_default() { + assert_eq!('\n'.escape_default(), ~"\\n"); + assert_eq!('\r'.escape_default(), ~"\\r"); + assert_eq!('\''.escape_default(), ~"\\'"); + assert_eq!('"'.escape_default(), ~"\\\""); + assert_eq!(' '.escape_default(), ~" "); + assert_eq!('a'.escape_default(), ~"a"); + assert_eq!('~'.escape_default(), ~"~"); + assert_eq!('\x00'.escape_default(), ~"\\x00"); + assert_eq!('\x1f'.escape_default(), ~"\\x1f"); + assert_eq!('\x7f'.escape_default(), ~"\\x7f"); + assert_eq!('\xff'.escape_default(), ~"\\xff"); + assert_eq!('\u011b'.escape_default(), ~"\\u011b"); + assert_eq!('\U0001d4b6'.escape_default(), ~"\\U0001d4b6"); +} + +#[test] +fn test_escape_unicode() { + assert_eq!('\x00'.escape_unicode(), ~"\\x00"); + assert_eq!('\n'.escape_unicode(), ~"\\x0a"); + assert_eq!(' '.escape_unicode(), ~"\\x20"); + assert_eq!('a'.escape_unicode(), ~"\\x61"); + assert_eq!('\u011b'.escape_unicode(), ~"\\u011b"); + assert_eq!('\U0001d4b6'.escape_unicode(), ~"\\U0001d4b6"); +} diff --git a/src/libcore/cleanup.rs b/src/libstd/cleanup.rs similarity index 89% rename from src/libcore/cleanup.rs rename to src/libstd/cleanup.rs index a5df97e3d574f..d1460b7a3c96b 100644 --- a/src/libcore/cleanup.rs +++ b/src/libstd/cleanup.rs @@ -39,11 +39,11 @@ struct AllocHeader { priv opaque: () } struct MemoryRegion { priv opaque: () } #[cfg(target_arch="x86")] -#[cfg(target_arch="arm")] struct Registers { data: [u32, ..16] } +#[cfg(target_arch="arm")] #[cfg(target_arch="mips")] struct Registers { data: [u32, ..32] @@ -127,33 +127,6 @@ struct AnnihilateStats { n_bytes_freed: uint } -#[cfg(stage0)] -unsafe fn each_live_alloc(read_next_before: bool, - f: &fn(box: *mut BoxRepr, uniq: bool) -> bool) { - //! Walks the internal list of allocations - - use managed; - - let task: *Task = transmute(rustrt::rust_get_task()); - let box = (*task).boxed_region.live_allocs; - let mut box: *mut BoxRepr = transmute(copy box); - while box != mut_null() { - let next_before = transmute(copy (*box).header.next); - let uniq = - (*box).header.ref_count == managed::raw::RC_MANAGED_UNIQUE; - - if !f(box, uniq) { - return; - } - - if read_next_before { - box = next_before; - } else { - box = transmute(copy (*box).header.next); - } - } -} -#[cfg(not(stage0))] unsafe fn each_live_alloc(read_next_before: bool, f: &fn(box: *mut BoxRepr, uniq: bool) -> bool) -> bool { //! Walks the internal list of allocations diff --git a/src/libcore/clone.rs b/src/libstd/clone.rs similarity index 88% rename from src/libcore/clone.rs rename to src/libstd/clone.rs index 4d2b5998b445b..266dd1a35e32c 100644 --- a/src/libcore/clone.rs +++ b/src/libstd/clone.rs @@ -24,9 +24,11 @@ by convention implementing the `Clone` trait and calling the use core::kinds::Const; +/// A common trait for cloning an object. pub trait Clone { - /// Return a deep copy of the owned object tree. Types with shared ownership like managed boxes - /// are cloned with a shallow copy. + /// Returns a copy of the value. The contents of owned pointers + /// are copied to maintain uniqueness, while the contents of + /// managed pointers are not copied. fn clone(&self) -> Self; } @@ -84,9 +86,11 @@ clone_impl!(()) clone_impl!(bool) clone_impl!(char) +/// A trait distinct from `Clone` which represents "deep copies" of things like +/// managed boxes which would otherwise not be copied. pub trait DeepClone { - /// Return a deep copy of the object tree. Types with shared ownership are also copied via a - /// deep copy, unlike `Clone`. + /// Return a deep copy of the value. Unlike `Clone`, the contents of shared pointer types + /// *are* copied. fn deep_clone(&self) -> Self; } @@ -146,14 +150,14 @@ deep_clone_impl!(char) fn test_owned_clone() { let a = ~5i; let b: ~int = a.clone(); - assert!(a == b); + assert_eq!(a, b); } #[test] fn test_managed_clone() { let a = @5i; let b: @int = a.clone(); - assert!(a == b); + assert_eq!(a, b); } #[test] @@ -168,9 +172,9 @@ fn test_managed_mut_deep_clone() { fn test_managed_mut_clone() { let a = @mut 5i; let b: @mut int = a.clone(); - assert!(a == b); + assert_eq!(a, b); *b = 10; - assert!(a == b); + assert_eq!(a, b); } #[test] diff --git a/src/libcore/cmp.rs b/src/libstd/cmp.rs similarity index 98% rename from src/libcore/cmp.rs rename to src/libstd/cmp.rs index 80f1f05961a5d..55530f181a11b 100644 --- a/src/libcore/cmp.rs +++ b/src/libstd/cmp.rs @@ -20,6 +20,8 @@ and `Eq` to overload the `==` and `!=` operators. */ +#[allow(missing_doc)]; + /** * Trait for values that can be compared for equality and inequality. * @@ -127,12 +129,11 @@ totalord_impl!(uint) totalord_impl!(char) +/// Compares (a1, b1) against (a2, b2), where the a values are more significant. pub fn cmp2( a1: &A, b1: &B, a2: &A, b2: &B) -> Ordering { - //! Compares (a1, b1) against (a2, b2), where the a values are more significant. - match a1.cmp(a2) { Less => Less, Greater => Greater, diff --git a/src/libstd/comm.rs b/src/libstd/comm.rs index 20ab2d61ecc07..f0c353c8d62b6 100644 --- a/src/libstd/comm.rs +++ b/src/libstd/comm.rs @@ -9,102 +9,808 @@ // except according to those terms. /*! +Message passing +*/ -Higher level communication abstractions. +#[allow(missing_doc)]; -*/ +use cast::{transmute, transmute_mut}; +use container::Container; +use either::{Either, Left, Right}; +use kinds::Owned; +use option::{Option, Some, None}; +use uint; +use vec; +use vec::OwnedVector; +use util::replace; +use unstable::sync::{Exclusive, exclusive}; +use rtcomm = rt::comm; +use rt; + +use pipes::{wait_many, PacketHeader}; -use core::comm::{GenericChan, GenericSmartChan, GenericPort}; -use core::comm::{Chan, Port, Selectable, Peekable}; -use core::pipes; +// FIXME #5160: Making this public exposes some plumbing from +// pipes. Needs some refactoring +pub use pipes::Selectable; -/// An extension of `pipes::stream` that allows both sending and receiving. -pub struct DuplexStream { - priv chan: Chan, - priv port: Port, +/// A trait for things that can send multiple messages. +pub trait GenericChan { + /// Sends a message. + fn send(&self, x: T); } -// Allow these methods to be used without import: -pub impl DuplexStream { +/// Things that can send multiple messages and can detect when the receiver +/// is closed +pub trait GenericSmartChan { + /// Sends a message, or report if the receiver has closed the connection. + fn try_send(&self, x: T) -> bool; +} + +/// A trait for things that can receive multiple messages. +pub trait GenericPort { + /// Receives a message, or fails if the connection closes. + fn recv(&self) -> T; + + /** Receives a message, or returns `none` if + the connection is closed or closes. + */ + fn try_recv(&self) -> Option; +} + +/// Ports that can `peek` +pub trait Peekable { + /// Returns true if a message is available + fn peek(&self) -> bool; +} + +/// An endpoint that can send many messages. +pub struct Chan { + inner: Either, rtcomm::Chan> +} + +/// An endpoint that can receive many messages. +pub struct Port { + inner: Either, rtcomm::Port> +} + +/** Creates a `(Port, Chan)` pair. + +These allow sending or receiving an unlimited number of messages. + +*/ +pub fn stream() -> (Port, Chan) { + let (port, chan) = match rt::context() { + rt::OldTaskContext => match pipesy::stream() { + (p, c) => (Left(p), Left(c)) + }, + _ => match rtcomm::stream() { + (p, c) => (Right(p), Right(c)) + } + }; + let port = Port { inner: port }; + let chan = Chan { inner: chan }; + return (port, chan); +} + +impl GenericChan for Chan { fn send(&self, x: T) { - self.chan.send(x) + match self.inner { + Left(ref chan) => chan.send(x), + Right(ref chan) => chan.send(x) + } } +} + +impl GenericSmartChan for Chan { fn try_send(&self, x: T) -> bool { - self.chan.try_send(x) + match self.inner { + Left(ref chan) => chan.try_send(x), + Right(ref chan) => chan.try_send(x) + } + } +} + +impl GenericPort for Port { + fn recv(&self) -> T { + match self.inner { + Left(ref port) => port.recv(), + Right(ref port) => port.recv() + } + } + + fn try_recv(&self) -> Option { + match self.inner { + Left(ref port) => port.try_recv(), + Right(ref port) => port.try_recv() + } + } +} + +impl Peekable for Port { + fn peek(&self) -> bool { + match self.inner { + Left(ref port) => port.peek(), + Right(ref port) => port.peek() + } + } +} + +impl Selectable for Port { + fn header(&mut self) -> *mut PacketHeader { + match self.inner { + Left(ref mut port) => port.header(), + Right(_) => fail!("can't select on newsched ports") + } + } +} + +/// Treat many ports as one. +#[unsafe_mut_field(ports)] +pub struct PortSet { + ports: ~[pipesy::Port], +} + +impl PortSet { + pub fn new() -> PortSet { + PortSet { + ports: ~[] + } + } + + pub fn add(&self, port: Port) { + let Port { inner } = port; + let port = match inner { + Left(p) => p, + Right(_) => fail!("PortSet not implemented") + }; + unsafe { + let self_ports = transmute_mut(&self.ports); + self_ports.push(port) + } + } + + pub fn chan(&self) -> Chan { + let (po, ch) = stream(); + self.add(po); + ch } - fn recv(&self, ) -> U { - self.port.recv() +} + +impl GenericPort for PortSet { + fn try_recv(&self) -> Option { + unsafe { + let self_ports = transmute_mut(&self.ports); + let mut result = None; + // we have to swap the ports array so we aren't borrowing + // aliasable mutable memory. + let mut ports = replace(self_ports, ~[]); + while result.is_none() && ports.len() > 0 { + let i = wait_many(ports); + match ports[i].try_recv() { + Some(m) => { + result = Some(m); + } + None => { + // Remove this port. + let _ = ports.swap_remove(i); + } + } + } + *self_ports = ports; + result + } } - fn try_recv(&self) -> Option { - self.port.try_recv() + fn recv(&self) -> T { + self.try_recv().expect("port_set: endpoints closed") } +} + +impl Peekable for PortSet { fn peek(&self) -> bool { - self.port.peek() + // It'd be nice to use self.port.each, but that version isn't + // pure. + for uint::range(0, vec::uniq_len(&const self.ports)) |i| { + let port: &pipesy::Port = &self.ports[i]; + if port.peek() { + return true; + } + } + false } } -impl GenericChan for DuplexStream { +/// A channel that can be shared between many senders. +pub struct SharedChan { + ch: Exclusive> +} + +impl SharedChan { + /// Converts a `chan` into a `shared_chan`. + pub fn new(c: Chan) -> SharedChan { + let Chan { inner } = c; + let c = match inner { + Left(c) => c, + Right(_) => fail!("SharedChan not implemented") + }; + SharedChan { ch: exclusive(c) } + } +} + +impl GenericChan for SharedChan { fn send(&self, x: T) { - self.chan.send(x) + unsafe { + let mut xx = Some(x); + do self.ch.with_imm |chan| { + let x = replace(&mut xx, None); + chan.send(x.unwrap()) + } + } } } -impl GenericSmartChan for DuplexStream { +impl GenericSmartChan for SharedChan { fn try_send(&self, x: T) -> bool { - self.chan.try_send(x) + unsafe { + let mut xx = Some(x); + do self.ch.with_imm |chan| { + let x = replace(&mut xx, None); + chan.try_send(x.unwrap()) + } + } } } -impl GenericPort for DuplexStream { - fn recv(&self) -> U { - self.port.recv() +impl ::clone::Clone for SharedChan { + fn clone(&self) -> SharedChan { + SharedChan { ch: self.ch.clone() } } +} - fn try_recv(&self) -> Option { - self.port.try_recv() +pub struct PortOne { + inner: Either, rtcomm::PortOne> +} + +pub struct ChanOne { + inner: Either, rtcomm::ChanOne> +} + +pub fn oneshot() -> (PortOne, ChanOne) { + let (port, chan) = match rt::context() { + rt::OldTaskContext => match pipesy::oneshot() { + (p, c) => (Left(p), Left(c)), + }, + _ => match rtcomm::oneshot() { + (p, c) => (Right(p), Right(c)) + } + }; + let port = PortOne { inner: port }; + let chan = ChanOne { inner: chan }; + return (port, chan); +} + +impl PortOne { + pub fn recv(self) -> T { + let PortOne { inner } = self; + match inner { + Left(p) => p.recv(), + Right(p) => p.recv() + } + } + + pub fn try_recv(self) -> Option { + let PortOne { inner } = self; + match inner { + Left(p) => p.try_recv(), + Right(p) => p.try_recv() + } } } -impl Peekable for DuplexStream { - fn peek(&self) -> bool { - self.port.peek() +impl ChanOne { + pub fn send(self, data: T) { + let ChanOne { inner } = self; + match inner { + Left(p) => p.send(data), + Right(p) => p.send(data) + } + } + + pub fn try_send(self, data: T) -> bool { + let ChanOne { inner } = self; + match inner { + Left(p) => p.try_send(data), + Right(p) => p.try_send(data) + } + } +} + +pub fn recv_one(port: PortOne) -> T { + let PortOne { inner } = port; + match inner { + Left(p) => pipesy::recv_one(p), + Right(p) => p.recv() + } +} + +pub fn try_recv_one(port: PortOne) -> Option { + let PortOne { inner } = port; + match inner { + Left(p) => pipesy::try_recv_one(p), + Right(p) => p.try_recv() } } -impl Selectable for DuplexStream { - fn header(&mut self) -> *mut pipes::PacketHeader { - self.port.header() +pub fn send_one(chan: ChanOne, data: T) { + let ChanOne { inner } = chan; + match inner { + Left(c) => pipesy::send_one(c, data), + Right(c) => c.send(data) } } -/// Creates a bidirectional stream. -pub fn DuplexStream() - -> (DuplexStream, DuplexStream) -{ - let (p1, c2) = comm::stream(); - let (p2, c1) = comm::stream(); - (DuplexStream { - chan: c1, - port: p1 - }, - DuplexStream { - chan: c2, - port: p2 - }) +pub fn try_send_one(chan: ChanOne, data: T) -> bool { + let ChanOne { inner } = chan; + match inner { + Left(c) => pipesy::try_send_one(c, data), + Right(c) => c.try_send(data) + } +} + +mod pipesy { + + use kinds::Owned; + use option::{Option, Some, None}; + use pipes::{recv, try_recv, peek, PacketHeader}; + use super::{GenericChan, GenericSmartChan, GenericPort, Peekable, Selectable}; + use cast::transmute_mut; + use util::replace; + + /*proto! oneshot ( + Oneshot:send { + send(T) -> ! + } + )*/ + + #[allow(non_camel_case_types)] + pub mod oneshot { + priv use core::kinds::Owned; + use ptr::to_mut_unsafe_ptr; + + pub fn init() -> (server::Oneshot, client::Oneshot) { + pub use core::pipes::HasBuffer; + + let buffer = ~::core::pipes::Buffer { + header: ::core::pipes::BufferHeader(), + data: __Buffer { + Oneshot: ::core::pipes::mk_packet::>() + }, + }; + do ::core::pipes::entangle_buffer(buffer) |buffer, data| { + data.Oneshot.set_buffer(buffer); + to_mut_unsafe_ptr(&mut data.Oneshot) + } + } + #[allow(non_camel_case_types)] + pub enum Oneshot { pub send(T), } + #[allow(non_camel_case_types)] + pub struct __Buffer { + Oneshot: ::core::pipes::Packet>, + } + + #[allow(non_camel_case_types)] + pub mod client { + + priv use core::kinds::Owned; + + #[allow(non_camel_case_types)] + pub fn try_send(pipe: Oneshot, x_0: T) -> + ::core::option::Option<()> { + { + use super::send; + let message = send(x_0); + if ::core::pipes::send(pipe, message) { + ::core::pipes::rt::make_some(()) + } else { ::core::pipes::rt::make_none() } + } + } + + #[allow(non_camel_case_types)] + pub fn send(pipe: Oneshot, x_0: T) { + { + use super::send; + let message = send(x_0); + ::core::pipes::send(pipe, message); + } + } + + #[allow(non_camel_case_types)] + pub type Oneshot = + ::core::pipes::SendPacketBuffered, + super::__Buffer>; + } + + #[allow(non_camel_case_types)] + pub mod server { + #[allow(non_camel_case_types)] + pub type Oneshot = + ::core::pipes::RecvPacketBuffered, + super::__Buffer>; + } + } + + /// The send end of a oneshot pipe. + pub struct ChanOne { + contents: oneshot::client::Oneshot + } + + impl ChanOne { + pub fn new(contents: oneshot::client::Oneshot) -> ChanOne { + ChanOne { + contents: contents + } + } + } + + /// The receive end of a oneshot pipe. + pub struct PortOne { + contents: oneshot::server::Oneshot + } + + impl PortOne { + pub fn new(contents: oneshot::server::Oneshot) -> PortOne { + PortOne { + contents: contents + } + } + } + + /// Initialiase a (send-endpoint, recv-endpoint) oneshot pipe pair. + pub fn oneshot() -> (PortOne, ChanOne) { + let (port, chan) = oneshot::init(); + (PortOne::new(port), ChanOne::new(chan)) + } + + impl PortOne { + pub fn recv(self) -> T { recv_one(self) } + pub fn try_recv(self) -> Option { try_recv_one(self) } + pub fn unwrap(self) -> oneshot::server::Oneshot { + match self { + PortOne { contents: s } => s + } + } + } + + impl ChanOne { + pub fn send(self, data: T) { send_one(self, data) } + pub fn try_send(self, data: T) -> bool { try_send_one(self, data) } + pub fn unwrap(self) -> oneshot::client::Oneshot { + match self { + ChanOne { contents: s } => s + } + } + } + + /** + * Receive a message from a oneshot pipe, failing if the connection was + * closed. + */ + pub fn recv_one(port: PortOne) -> T { + match port { + PortOne { contents: port } => { + let oneshot::send(message) = recv(port); + message + } + } + } + + /// Receive a message from a oneshot pipe unless the connection was closed. + pub fn try_recv_one (port: PortOne) -> Option { + match port { + PortOne { contents: port } => { + let message = try_recv(port); + + if message.is_none() { + None + } else { + let oneshot::send(message) = message.unwrap(); + Some(message) + } + } + } + } + + /// Send a message on a oneshot pipe, failing if the connection was closed. + pub fn send_one(chan: ChanOne, data: T) { + match chan { + ChanOne { contents: chan } => oneshot::client::send(chan, data), + } + } + + /** + * Send a message on a oneshot pipe, or return false if the connection was + * closed. + */ + pub fn try_send_one(chan: ChanOne, data: T) -> bool { + match chan { + ChanOne { contents: chan } => { + oneshot::client::try_send(chan, data).is_some() + } + } + } + + // Streams - Make pipes a little easier in general. + + /*proto! streamp ( + Open:send { + data(T) -> Open + } + )*/ + + #[allow(non_camel_case_types)] + pub mod streamp { + priv use core::kinds::Owned; + + pub fn init() -> (server::Open, client::Open) { + pub use core::pipes::HasBuffer; + ::core::pipes::entangle() + } + + #[allow(non_camel_case_types)] + pub enum Open { pub data(T, server::Open), } + + #[allow(non_camel_case_types)] + pub mod client { + priv use core::kinds::Owned; + + #[allow(non_camel_case_types)] + pub fn try_data(pipe: Open, x_0: T) -> + ::core::option::Option> { + { + use super::data; + let (s, c) = ::core::pipes::entangle(); + let message = data(x_0, s); + if ::core::pipes::send(pipe, message) { + ::core::pipes::rt::make_some(c) + } else { ::core::pipes::rt::make_none() } + } + } + + #[allow(non_camel_case_types)] + pub fn data(pipe: Open, x_0: T) -> Open { + { + use super::data; + let (s, c) = ::core::pipes::entangle(); + let message = data(x_0, s); + ::core::pipes::send(pipe, message); + c + } + } + + #[allow(non_camel_case_types)] + pub type Open = ::core::pipes::SendPacket>; + } + + #[allow(non_camel_case_types)] + pub mod server { + #[allow(non_camel_case_types)] + pub type Open = ::core::pipes::RecvPacket>; + } + } + + /// An endpoint that can send many messages. + #[unsafe_mut_field(endp)] + pub struct Chan { + endp: Option> + } + + /// An endpoint that can receive many messages. + #[unsafe_mut_field(endp)] + pub struct Port { + endp: Option>, + } + + /** Creates a `(Port, Chan)` pair. + + These allow sending or receiving an unlimited number of messages. + + */ + pub fn stream() -> (Port, Chan) { + let (s, c) = streamp::init(); + + (Port { + endp: Some(s) + }, Chan { + endp: Some(c) + }) + } + + impl GenericChan for Chan { + #[inline(always)] + fn send(&self, x: T) { + unsafe { + let self_endp = transmute_mut(&self.endp); + let endp = replace(self_endp, None); + *self_endp = Some(streamp::client::data(endp.unwrap(), x)) + } + } + } + + impl GenericSmartChan for Chan { + #[inline(always)] + fn try_send(&self, x: T) -> bool { + unsafe { + let self_endp = transmute_mut(&self.endp); + let endp = replace(self_endp, None); + match streamp::client::try_data(endp.unwrap(), x) { + Some(next) => { + *self_endp = Some(next); + true + } + None => false + } + } + } + } + + impl GenericPort for Port { + #[inline(always)] + fn recv(&self) -> T { + unsafe { + let self_endp = transmute_mut(&self.endp); + let endp = replace(self_endp, None); + let streamp::data(x, endp) = recv(endp.unwrap()); + *self_endp = Some(endp); + x + } + } + + #[inline(always)] + fn try_recv(&self) -> Option { + unsafe { + let self_endp = transmute_mut(&self.endp); + let endp = replace(self_endp, None); + match try_recv(endp.unwrap()) { + Some(streamp::data(x, endp)) => { + *self_endp = Some(endp); + Some(x) + } + None => None + } + } + } + } + + impl Peekable for Port { + #[inline(always)] + fn peek(&self) -> bool { + unsafe { + let self_endp = transmute_mut(&self.endp); + let mut endp = replace(self_endp, None); + let peek = match endp { + Some(ref mut endp) => peek(endp), + None => fail!("peeking empty stream") + }; + *self_endp = endp; + peek + } + } + } + + impl Selectable for Port { + fn header(&mut self) -> *mut PacketHeader { + match self.endp { + Some(ref mut endp) => endp.header(), + None => fail!("peeking empty stream") + } + } +} + +} + +/// Returns the index of an endpoint that is ready to receive. +pub fn selecti(endpoints: &mut [T]) -> uint { + wait_many(endpoints) +} + +/// Returns 0 or 1 depending on which endpoint is ready to receive +pub fn select2i(a: &mut A, b: &mut B) + -> Either<(), ()> { + let mut endpoints = [ a.header(), b.header() ]; + match wait_many(endpoints) { + 0 => Left(()), + 1 => Right(()), + _ => fail!("wait returned unexpected index"), + } +} + +/// Receive a message from one of two endpoints. +pub trait Select2 { + /// Receive a message or return `None` if a connection closes. + fn try_select(&mut self) -> Either, Option>; + /// Receive a message or fail if a connection closes. + fn select(&mut self) -> Either; +} + +impl, + Right:Selectable + GenericPort> + Select2 + for (Left, Right) { + fn select(&mut self) -> Either { + // XXX: Bad borrow check workaround. + unsafe { + let this: &(Left, Right) = transmute(self); + match *this { + (ref lp, ref rp) => { + let lp: &mut Left = transmute(lp); + let rp: &mut Right = transmute(rp); + match select2i(lp, rp) { + Left(()) => Left(lp.recv()), + Right(()) => Right(rp.recv()), + } + } + } + } + } + + fn try_select(&mut self) -> Either, Option> { + // XXX: Bad borrow check workaround. + unsafe { + let this: &(Left, Right) = transmute(self); + match *this { + (ref lp, ref rp) => { + let lp: &mut Left = transmute(lp); + let rp: &mut Right = transmute(rp); + match select2i(lp, rp) { + Left(()) => Left (lp.try_recv()), + Right(()) => Right(rp.try_recv()), + } + } + } + } + } } #[cfg(test)] mod test { - use comm::DuplexStream; + use either::Right; + use super::{Chan, Port, oneshot, stream}; + + #[test] + fn test_select2() { + let (p1, c1) = stream(); + let (p2, c2) = stream(); + + c1.send(~"abc"); + + let mut tuple = (p1, p2); + match tuple.select() { + Right(_) => fail!(), + _ => (), + } + + c2.send(123); + } + + #[test] + fn test_oneshot() { + let (p, c) = oneshot(); + + c.send(()); + + p.recv() + } #[test] - pub fn DuplexStream1() { - let (left, right) = DuplexStream(); + fn test_peek_terminated() { + let (port, chan): (Port, Chan) = stream(); - left.send(~"abc"); - right.send(123); + { + // Destroy the channel + let _chan = chan; + } - assert!(left.recv() == 123); - assert!(right.recv() == ~"abc"); + assert!(!port.peek()); } } diff --git a/src/libcore/condition.rs b/src/libstd/condition.rs similarity index 94% rename from src/libcore/condition.rs rename to src/libstd/condition.rs index baa6722b1936e..2f150a0d1b283 100644 --- a/src/libcore/condition.rs +++ b/src/libstd/condition.rs @@ -10,8 +10,11 @@ /*! Condition handling */ -use prelude::*; +#[allow(missing_doc)]; + use local_data::{local_data_pop, local_data_set}; +use local_data; +use prelude::*; // helper for transmutation, shown below. type RustClosure = (int, int); @@ -26,8 +29,8 @@ pub struct Condition<'self, T, U> { key: local_data::LocalDataKey<'self, Handler> } -pub impl<'self, T, U> Condition<'self, T, U> { - fn trap(&'self self, h: &'self fn(T) -> U) -> Trap<'self, T, U> { +impl<'self, T, U> Condition<'self, T, U> { + pub fn trap(&'self self, h: &'self fn(T) -> U) -> Trap<'self, T, U> { unsafe { let p : *RustClosure = ::cast::transmute(&h); let prev = local_data::local_data_get(self.key); @@ -36,12 +39,12 @@ pub impl<'self, T, U> Condition<'self, T, U> { } } - fn raise(&self, t: T) -> U { + pub fn raise(&self, t: T) -> U { let msg = fmt!("Unhandled condition: %s: %?", self.name, t); self.raise_default(t, || fail!(copy msg)) } - fn raise_default(&self, t: T, default: &fn() -> U) -> U { + pub fn raise_default(&self, t: T, default: &fn() -> U) -> U { unsafe { match local_data_pop(self.key) { None => { @@ -70,8 +73,8 @@ struct Trap<'self, T, U> { handler: @Handler } -pub impl<'self, T, U> Trap<'self, T, U> { - fn in(&self, inner: &'self fn() -> V) -> V { +impl<'self, T, U> Trap<'self, T, U> { + pub fn in(&self, inner: &'self fn() -> V) -> V { unsafe { let _g = Guard { cond: self.cond }; debug!("Trap: pushing handler to TLS"); diff --git a/src/libcore/container.rs b/src/libstd/container.rs similarity index 66% rename from src/libcore/container.rs rename to src/libstd/container.rs index 1d5d77649549e..065582e2e0d2e 100644 --- a/src/libcore/container.rs +++ b/src/libstd/container.rs @@ -12,6 +12,8 @@ use option::Option; +/// A trait to represent the abstract idea of a container. The only concrete +/// knowledge known is the number of elements contained within. pub trait Container { /// Return the number of elements in the container fn len(&const self) -> uint; @@ -20,41 +22,28 @@ pub trait Container { fn is_empty(&const self) -> bool; } +/// A trait to represent mutable containers pub trait Mutable: Container { /// Clear the container, removing all values. fn clear(&mut self); } +/// A map is a key-value store where values may be looked up by their keys. This +/// trait provides basic operations to operate on these stores. pub trait Map: Mutable { /// Return true if the map contains a value for the specified key fn contains_key(&self, key: &K) -> bool; - // Visits all keys and values - #[cfg(stage0)] - fn each<'a>(&'a self, f: &fn(&K, &'a V) -> bool); - // Visits all keys and values - #[cfg(not(stage0))] + /// Visits all keys and values fn each<'a>(&'a self, f: &fn(&K, &'a V) -> bool) -> bool; /// Visit all keys - #[cfg(stage0)] - fn each_key(&self, f: &fn(&K) -> bool); - /// Visit all keys - #[cfg(not(stage0))] fn each_key(&self, f: &fn(&K) -> bool) -> bool; /// Visit all values - #[cfg(stage0)] - fn each_value<'a>(&'a self, f: &fn(&'a V) -> bool); - /// Visit all values - #[cfg(not(stage0))] fn each_value<'a>(&'a self, f: &fn(&'a V) -> bool) -> bool; /// Iterate over the map and mutate the contained values - #[cfg(stage0)] - fn mutate_values(&mut self, f: &fn(&K, &mut V) -> bool); - /// Iterate over the map and mutate the contained values - #[cfg(not(stage0))] fn mutate_values(&mut self, f: &fn(&K, &mut V) -> bool) -> bool; /// Return a reference to the value corresponding to the key @@ -81,43 +70,9 @@ pub trait Map: Mutable { fn pop(&mut self, k: &K) -> Option; } -#[cfg(stage0)] -pub trait Set: Mutable { - /// Return true if the set contains a value - fn contains(&self, value: &T) -> bool; - - /// Add a value to the set. Return true if the value was not already - /// present in the set. - fn insert(&mut self, value: T) -> bool; - - /// Remove a value from the set. Return true if the value was - /// present in the set. - fn remove(&mut self, value: &T) -> bool; - - /// Return true if the set has no elements in common with `other`. - /// This is equivalent to checking for an empty intersection. - fn is_disjoint(&self, other: &Self) -> bool; - - /// Return true if the set is a subset of another - fn is_subset(&self, other: &Self) -> bool; - - /// Return true if the set is a superset of another - fn is_superset(&self, other: &Self) -> bool; - - /// Visit the values representing the difference - fn difference(&self, other: &Self, f: &fn(&T) -> bool); - - /// Visit the values representing the symmetric difference - fn symmetric_difference(&self, other: &Self, f: &fn(&T) -> bool); - - /// Visit the values representing the intersection - fn intersection(&self, other: &Self, f: &fn(&T) -> bool); - - /// Visit the values representing the union - fn union(&self, other: &Self, f: &fn(&T) -> bool); -} - -#[cfg(not(stage0))] +/// A set is a group of objects which are each distinct from one another. This +/// trait represents actions which can be performed on sets to manipulate and +/// iterate over them. pub trait Set: Mutable { /// Return true if the set contains a value fn contains(&self, value: &T) -> bool; diff --git a/src/libcore/core.rc b/src/libstd/core.rc similarity index 71% rename from src/libcore/core.rc rename to src/libstd/core.rc index 96b5e1b781de4..a6334cc0c4964 100644 --- a/src/libcore/core.rc +++ b/src/libstd/core.rc @@ -33,7 +33,7 @@ if the first line of each crate was extern mod core; -This means that the contents of core can be accessed from from any context +This means that the contents of core can be accessed from any context with the `core::` path prefix, as in `use core::vec`, `use core::task::spawn`, etc. @@ -47,7 +47,7 @@ they contained the following prologue: */ -#[link(name = "core", +#[link(name = "std", vers = "0.7-pre", uuid = "c70c24a7-5551-4f73-8e37-380b11d80be8", url = "https://github.com/mozilla/rust/tree/master/src/libcore")]; @@ -56,17 +56,21 @@ they contained the following prologue: #[license = "MIT/ASL2"]; #[crate_type = "lib"]; +// NOTE: remove these two attributes after the next snapshot +#[no_core]; // for stage0 +#[allow(unrecognized_lint)]; // otherwise stage0 is seriously ugly -// Don't link to core. We are core. -#[no_core]; +// Don't link to std. We are std. +#[no_std]; #[deny(non_camel_case_types)]; +#[deny(missing_doc)]; // Make core testable by not duplicating lang items. See #2912 -#[cfg(test)] extern mod realcore(name = "core", vers = "0.7-pre"); -#[cfg(test)] pub use kinds = realcore::kinds; -#[cfg(test)] pub use ops = realcore::ops; -#[cfg(test)] pub use cmp = realcore::cmp; +#[cfg(test)] extern mod realstd(name = "std"); +#[cfg(test)] pub use kinds = realstd::kinds; +#[cfg(test)] pub use ops = realstd::ops; +#[cfg(test)] pub use cmp = realstd::cmp; // On Linux, link to the runtime with -lrt. #[cfg(target_os = "linux")] @@ -87,34 +91,24 @@ pub mod prelude; /* Primitive types */ -#[path = "num/int-template.rs"] #[merge = "num/int-template/int.rs"] -pub mod int; -#[path = "num/int-template.rs"] #[merge = "num/int-template/i8.rs"] -pub mod i8; -#[path = "num/int-template.rs"] #[merge = "num/int-template/i16.rs"] -pub mod i16; -#[path = "num/int-template.rs"] #[merge = "num/int-template/i32.rs"] -pub mod i32; -#[path = "num/int-template.rs"] #[merge = "num/int-template/i64.rs"] -pub mod i64; -#[path = "num/uint-template.rs"] #[merge = "num/uint-template/uint.rs"] -pub mod uint; - -#[path = "num/uint-template.rs"] #[merge = "num/uint-template/u8.rs"] -pub mod u8; -#[path = "num/uint-template.rs"] #[merge = "num/uint-template/u16.rs"] -pub mod u16; -#[path = "num/uint-template.rs"] #[merge = "num/uint-template/u32.rs"] -pub mod u32; -#[path = "num/uint-template.rs"] #[merge = "num/uint-template/u64.rs"] -pub mod u64; - -#[path = "num/float.rs"] -pub mod float; -#[path = "num/f32.rs"] -pub mod f32; -#[path = "num/f64.rs"] -pub mod f64; +#[path = "num/int_macros.rs"] mod int_macros; +#[path = "num/uint_macros.rs"] mod uint_macros; + +#[path = "num/int.rs"] pub mod int; +#[path = "num/i8.rs"] pub mod i8; +#[path = "num/i16.rs"] pub mod i16; +#[path = "num/i32.rs"] pub mod i32; +#[path = "num/i64.rs"] pub mod i64; + +#[path = "num/uint.rs"] pub mod uint; +#[path = "num/u8.rs"] pub mod u8; +#[path = "num/u16.rs"] pub mod u16; +#[path = "num/u32.rs"] pub mod u32; +#[path = "num/u64.rs"] pub mod u64; + +#[path = "num/float.rs"] pub mod float; +#[path = "num/f32.rs"] pub mod f32; +#[path = "num/f64.rs"] pub mod f64; pub mod nil; pub mod bool; @@ -131,6 +125,7 @@ pub mod ascii; pub mod ptr; pub mod owned; pub mod managed; +pub mod borrow; /* Core language traits */ @@ -205,12 +200,15 @@ mod unicode; #[path = "num/cmath.rs"] mod cmath; mod stackwalk; + +// XXX: This shouldn't be pub, and it should be reexported under 'unstable' +// but name resolution doesn't work without it being pub. #[path = "rt/mod.rs"] -mod rt; +pub mod rt; // A curious inner-module that's not exported that contains the binding -// 'core' so that macro-expanded references to core::error and such -// can be resolved within libcore. +// 'std' so that macro-expanded references to std::error and such +// can be resolved within libstd. #[doc(hidden)] mod core { pub use clone; @@ -221,3 +219,17 @@ mod core { pub use sys; pub use pipes; } +#[doc(hidden)] +mod std { + pub use clone; + pub use cmp; + pub use condition; + pub use option; + pub use kinds; + pub use sys; + pub use pipes; + pub use unstable; + pub use str; + pub use os; +} + diff --git a/src/libcore/either.rs b/src/libstd/either.rs similarity index 70% rename from src/libcore/either.rs rename to src/libstd/either.rs index 8c16f5c64824f..fac0866f17e76 100644 --- a/src/libcore/either.rs +++ b/src/libstd/either.rs @@ -10,6 +10,8 @@ //! A type that represents one of two alternatives +#[allow(missing_doc)]; + use container::Container; use cmp::Eq; use kinds::Copy; @@ -26,26 +28,22 @@ pub enum Either { Right(U) } +/// Applies a function based on the given either value +/// +/// If `value` is left(T) then `f_left` is applied to its contents, if +/// `value` is right(U) then `f_right` is applied to its contents, and the +/// result is returned. #[inline(always)] pub fn either(f_left: &fn(&T) -> V, f_right: &fn(&U) -> V, value: &Either) -> V { - /*! - * Applies a function based on the given either value - * - * If `value` is left(T) then `f_left` is applied to its contents, if - * `value` is right(U) then `f_right` is applied to its contents, and the - * result is returned. - */ - match *value { - Left(ref l) => f_left(l), - Right(ref r) => f_right(r) + Left(ref l) => f_left(l), + Right(ref r) => f_right(r) } } +/// Extracts from a vector of either all the left values pub fn lefts(eithers: &[Either]) -> ~[T] { - //! Extracts from a vector of either all the left values - do vec::build_sized(eithers.len()) |push| { for eithers.each |elt| { match *elt { @@ -56,9 +54,8 @@ pub fn lefts(eithers: &[Either]) -> ~[T] { } } +/// Extracts from a vector of either all the right values pub fn rights(eithers: &[Either]) -> ~[U] { - //! Extracts from a vector of either all the right values - do vec::build_sized(eithers.len()) |push| { for eithers.each |elt| { match *elt { @@ -69,109 +66,102 @@ pub fn rights(eithers: &[Either]) -> ~[U] { } } -pub fn partition(eithers: ~[Either]) - -> (~[T], ~[U]) { - /*! - * Extracts from a vector of either all the left values and right values - * - * Returns a structure containing a vector of left values and a vector of - * right values. - */ - +/// Extracts from a vector of either all the left values and right values +/// +/// Returns a structure containing a vector of left values and a vector of +/// right values. +pub fn partition(eithers: ~[Either]) -> (~[T], ~[U]) { let mut lefts: ~[T] = ~[]; let mut rights: ~[U] = ~[]; do vec::consume(eithers) |_i, elt| { match elt { - Left(l) => lefts.push(l), - Right(r) => rights.push(r) + Left(l) => lefts.push(l), + Right(r) => rights.push(r) } } return (lefts, rights); } +/// Flips between left and right of a given either #[inline(always)] pub fn flip(eith: Either) -> Either { - //! Flips between left and right of a given either - match eith { - Right(r) => Left(r), - Left(l) => Right(l) + Right(r) => Left(r), + Left(l) => Right(l) } } +/// Converts either::t to a result::t +/// +/// Converts an `either` type to a `result` type, making the "right" choice +/// an ok result, and the "left" choice a fail #[inline(always)] -pub fn to_result(eith: Either) - -> Result { - /*! - * Converts either::t to a result::t - * - * Converts an `either` type to a `result` type, making the "right" choice - * an ok result, and the "left" choice a fail - */ - +pub fn to_result(eith: Either) -> Result { match eith { - Right(r) => result::Ok(r), - Left(l) => result::Err(l) + Right(r) => result::Ok(r), + Left(l) => result::Err(l) } } +/// Checks whether the given value is a left #[inline(always)] pub fn is_left(eith: &Either) -> bool { - //! Checks whether the given value is a left - - match *eith { Left(_) => true, _ => false } + match *eith { + Left(_) => true, + _ => false + } } +/// Checks whether the given value is a right #[inline(always)] pub fn is_right(eith: &Either) -> bool { - //! Checks whether the given value is a right - - match *eith { Right(_) => true, _ => false } + match *eith { + Right(_) => true, + _ => false + } } +/// Retrieves the value in the left branch. Fails if the either is Right. #[inline(always)] pub fn unwrap_left(eith: Either) -> T { - //! Retrieves the value in the left branch. Fails if the either is Right. - match eith { Left(x) => x, Right(_) => fail!("either::unwrap_left Right") } } +/// Retrieves the value in the right branch. Fails if the either is Left. #[inline(always)] pub fn unwrap_right(eith: Either) -> U { - //! Retrieves the value in the right branch. Fails if the either is Left. - match eith { Right(x) => x, Left(_) => fail!("either::unwrap_right Left") } } -pub impl Either { +impl Either { #[inline(always)] - fn either(&self, f_left: &fn(&T) -> V, f_right: &fn(&U) -> V) -> V { + pub fn either(&self, f_left: &fn(&T) -> V, f_right: &fn(&U) -> V) -> V { either(f_left, f_right, self) } #[inline(always)] - fn flip(self) -> Either { flip(self) } + pub fn flip(self) -> Either { flip(self) } #[inline(always)] - fn to_result(self) -> Result { to_result(self) } + pub fn to_result(self) -> Result { to_result(self) } #[inline(always)] - fn is_left(&self) -> bool { is_left(self) } + pub fn is_left(&self) -> bool { is_left(self) } #[inline(always)] - fn is_right(&self) -> bool { is_right(self) } + pub fn is_right(&self) -> bool { is_right(self) } #[inline(always)] - fn unwrap_left(self) -> T { unwrap_left(self) } + pub fn unwrap_left(self) -> T { unwrap_left(self) } #[inline(always)] - fn unwrap_right(self) -> U { unwrap_right(self) } + pub fn unwrap_right(self) -> U { unwrap_right(self) } } #[test] diff --git a/src/libstd/from_str.rs b/src/libstd/from_str.rs new file mode 100644 index 0000000000000..d2f1a895e1e2b --- /dev/null +++ b/src/libstd/from_str.rs @@ -0,0 +1,21 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! The trait for types that can be created from strings + +use option::Option; + +/// A trait to abstract the idea of creating a new instance of a type from a +/// string. +pub trait FromStr { + /// Parses a string `s` to return an optional value of this type. If the + /// string is ill-formatted, the None is returned. + fn from_str(s: &str) -> Option; +} diff --git a/src/libcore/gc.rs b/src/libstd/gc.rs similarity index 97% rename from src/libcore/gc.rs rename to src/libstd/gc.rs index 6a427297cc22d..611b95a7745e4 100644 --- a/src/libcore/gc.rs +++ b/src/libstd/gc.rs @@ -171,11 +171,6 @@ unsafe fn _walk_safe_point(fp: *Word, sp: SafePoint, visitor: Visitor) -> bool { return true; } -#[cfg(stage0)] -unsafe fn walk_safe_point(fp: *Word, sp: SafePoint, visitor: Visitor) { - _walk_safe_point(fp, sp, visitor); -} -#[cfg(not(stage0))] unsafe fn walk_safe_point(fp: *Word, sp: SafePoint, visitor: Visitor) -> bool { _walk_safe_point(fp, sp, visitor) } @@ -303,11 +298,6 @@ unsafe fn _walk_gc_roots(mem: Memory, sentinel: **Word, visitor: Visitor) -> boo return true; } -#[cfg(stage0)] -unsafe fn walk_gc_roots(mem: Memory, sentinel: **Word, visitor: Visitor) { - _walk_gc_roots(mem, sentinel, visitor); -} -#[cfg(not(stage0))] unsafe fn walk_gc_roots(mem: Memory, sentinel: **Word, visitor: Visitor) -> bool { _walk_gc_roots(mem, sentinel, visitor) } diff --git a/src/libcore/hash.rs b/src/libstd/hash.rs similarity index 92% rename from src/libcore/hash.rs rename to src/libstd/hash.rs index cb02364d725f8..e902244578634 100644 --- a/src/libcore/hash.rs +++ b/src/libstd/hash.rs @@ -19,8 +19,8 @@ * CPRNG like rand::rng. */ -#[cfg(stage0)] -use cast; +#[allow(missing_doc)]; + use container::Container; use old_iter::BaseIter; use rt::io::Writer; @@ -78,24 +78,12 @@ pub trait Streaming { fn reset(&mut self); } -// XXX: Ugly workaround for bootstrapping. -#[cfg(stage0)] -fn transmute_for_stage0<'a>(bytes: &'a [const u8]) -> &'a [u8] { - unsafe { - cast::transmute(bytes) - } -} -#[cfg(not(stage0))] -fn transmute_for_stage0<'a>(bytes: &'a [u8]) -> &'a [u8] { - bytes -} - impl Hash for A { #[inline(always)] fn hash_keyed(&self, k0: u64, k1: u64) -> u64 { let mut s = State::new(k0, k1); for self.iter_bytes(true) |bytes| { - s.input(transmute_for_stage0(bytes)); + s.input(bytes); } s.result_u64() } @@ -105,10 +93,10 @@ fn hash_keyed_2(a: &A, b: &B, k0: u64, k1: u64) -> u64 { let mut s = State::new(k0, k1); for a.iter_bytes(true) |bytes| { - s.input(transmute_for_stage0(bytes)); + s.input(bytes); } for b.iter_bytes(true) |bytes| { - s.input(transmute_for_stage0(bytes)); + s.input(bytes); } s.result_u64() } @@ -118,13 +106,13 @@ fn hash_keyed_3(a: &A, b: &B, c: &C, k0: u64, k1: u64) -> u64 { let mut s = State::new(k0, k1); for a.iter_bytes(true) |bytes| { - s.input(transmute_for_stage0(bytes)); + s.input(bytes); } for b.iter_bytes(true) |bytes| { - s.input(transmute_for_stage0(bytes)); + s.input(bytes); } for c.iter_bytes(true) |bytes| { - s.input(transmute_for_stage0(bytes)); + s.input(bytes); } s.result_u64() } @@ -142,16 +130,16 @@ fn hash_keyed_4 u64 { let mut s = State::new(k0, k1); for a.iter_bytes(true) |bytes| { - s.input(transmute_for_stage0(bytes)); + s.input(bytes); } for b.iter_bytes(true) |bytes| { - s.input(transmute_for_stage0(bytes)); + s.input(bytes); } for c.iter_bytes(true) |bytes| { - s.input(transmute_for_stage0(bytes)); + s.input(bytes); } for d.iter_bytes(true) |bytes| { - s.input(transmute_for_stage0(bytes)); + s.input(bytes); } s.result_u64() } @@ -171,19 +159,19 @@ fn hash_keyed_5 u64 { let mut s = State::new(k0, k1); for a.iter_bytes(true) |bytes| { - s.input(transmute_for_stage0(bytes)); + s.input(bytes); } for b.iter_bytes(true) |bytes| { - s.input(transmute_for_stage0(bytes)); + s.input(bytes); } for c.iter_bytes(true) |bytes| { - s.input(transmute_for_stage0(bytes)); + s.input(bytes); } for d.iter_bytes(true) |bytes| { - s.input(transmute_for_stage0(bytes)); + s.input(bytes); } for e.iter_bytes(true) |bytes| { - s.input(transmute_for_stage0(bytes)); + s.input(bytes); } s.result_u64() } @@ -401,6 +389,8 @@ mod tests { use super::*; use prelude::*; + use uint; + #[test] fn test_siphash() { let vecs : [[u8, ..8], ..64] = [ @@ -490,7 +480,7 @@ mod tests { let vec = u8to64_le!(vecs[t], 0); let out = buf.hash_keyed(k0, k1); debug!("got %?, expected %?", out, vec); - assert!(vec == out); + assert_eq!(vec, out); stream_full.reset(); stream_full.input(buf); @@ -501,8 +491,8 @@ mod tests { assert!(f == i && f == v); - buf += ~[t as u8]; - stream_inc.input(~[t as u8]); + buf += [t as u8]; + stream_inc.input([t as u8]); t += 1; } @@ -512,19 +502,19 @@ mod tests { fn test_hash_uint() { let val = 0xdeadbeef_deadbeef_u64; assert!((val as u64).hash() != (val as uint).hash()); - assert!((val as u32).hash() == (val as uint).hash()); + assert_eq!((val as u32).hash(), (val as uint).hash()); } #[test] #[cfg(target_arch = "x86_64")] fn test_hash_uint() { let val = 0xdeadbeef_deadbeef_u64; - assert!((val as u64).hash() == (val as uint).hash()); + assert_eq!((val as u64).hash(), (val as uint).hash()); assert!((val as u32).hash() != (val as uint).hash()); } #[test] #[cfg(target_arch = "x86")] fn test_hash_uint() { let val = 0xdeadbeef_deadbeef_u64; assert!((val as u64).hash() != (val as uint).hash()); - assert!((val as u32).hash() == (val as uint).hash()); + assert_eq!((val as u32).hash(), (val as uint).hash()); } #[test] diff --git a/src/libcore/hashmap.rs b/src/libstd/hashmap.rs similarity index 73% rename from src/libcore/hashmap.rs rename to src/libstd/hashmap.rs index d9912813cf930..b1400d1bc76f4 100644 --- a/src/libcore/hashmap.rs +++ b/src/libstd/hashmap.rs @@ -13,6 +13,8 @@ //! The tables use a keyed hash with new random keys generated for each container, so the ordering //! of a set of keys in a hash table is randomized. +#[mutable_doc]; + use container::{Container, Mutable, Map, Set}; use cmp::{Eq, Equiv}; use hash::Hash; @@ -34,6 +36,14 @@ struct Bucket { value: V, } +/// A hash map implementation which uses linear probing along with the SipHash +/// hash function for internal state. This means that the order of all hash maps +/// is randomized by keying each hash map randomly on creation. +/// +/// It is required that the keys implement the `Eq` and `Hash` traits, although +/// this can frequently be achieved by just implementing the `Eq` and +/// `IterBytes` traits as `Hash` is automatically implemented for types that +/// implement `IterBytes`. pub struct HashMap { priv k0: u64, priv k1: u64, @@ -53,6 +63,7 @@ fn resize_at(capacity: uint) -> uint { ((capacity as float) * 3. / 4.) as uint } +/// Creates a new hash map with the specified capacity. pub fn linear_map_with_capacity( initial_capacity: uint) -> HashMap { let mut r = rand::task_rng(); @@ -63,15 +74,16 @@ pub fn linear_map_with_capacity( fn linear_map_with_capacity_and_keys( k0: u64, k1: u64, initial_capacity: uint) -> HashMap { + let cap = uint::max(INITIAL_CAPACITY, initial_capacity); HashMap { k0: k0, k1: k1, - resize_at: resize_at(initial_capacity), + resize_at: resize_at(cap), size: 0, - buckets: vec::from_fn(initial_capacity, |_| None) + buckets: vec::from_fn(cap, |_| None) } } -priv impl HashMap { +impl HashMap { #[inline(always)] fn to_bucket(&self, h: uint) -> uint { // A good hash function with entropy spread over all of the @@ -87,22 +99,6 @@ priv impl HashMap { } #[inline(always)] - #[cfg(stage0)] - fn bucket_sequence(&self, hash: uint, - op: &fn(uint) -> bool) { - let start_idx = self.to_bucket(hash); - let len_buckets = self.buckets.len(); - let mut idx = start_idx; - loop { - if !op(idx) { return; } - idx = self.next_bucket(idx, len_buckets); - if idx == start_idx { - return; - } - } - } - #[inline(always)] - #[cfg(not(stage0))] fn bucket_sequence(&self, hash: uint, op: &fn(uint) -> bool) -> bool { let start_idx = self.to_bucket(hash); @@ -318,23 +314,10 @@ impl Map for HashMap { } /// Visit all key-value pairs - #[cfg(stage0)] - fn each<'a>(&'a self, blk: &fn(&K, &'a V) -> bool) { - for uint::range(0, self.buckets.len()) |i| { - for self.buckets[i].each |bucket| { - if !blk(&bucket.key, &bucket.value) { - return; - } - } - } - } - - /// Visit all key-value pairs - #[cfg(not(stage0))] fn each<'a>(&'a self, blk: &fn(&K, &'a V) -> bool) -> bool { - for uint::range(0, self.buckets.len()) |i| { - for self.buckets[i].each |bucket| { - if !blk(&bucket.key, &bucket.value) { + for self.buckets.each |bucket| { + for bucket.each |pair| { + if !blk(&pair.key, &pair.value) { return false; } } @@ -343,44 +326,16 @@ impl Map for HashMap { } /// Visit all keys - #[cfg(stage0)] - fn each_key(&self, blk: &fn(k: &K) -> bool) { - self.each(|k, _| blk(k)) - } - - /// Visit all keys - #[cfg(not(stage0))] fn each_key(&self, blk: &fn(k: &K) -> bool) -> bool { self.each(|k, _| blk(k)) } /// Visit all values - #[cfg(stage0)] - fn each_value<'a>(&'a self, blk: &fn(v: &'a V) -> bool) { - self.each(|_, v| blk(v)) - } - - /// Visit all values - #[cfg(not(stage0))] fn each_value<'a>(&'a self, blk: &fn(v: &'a V) -> bool) -> bool { self.each(|_, v| blk(v)) } /// Iterate over the map and mutate the contained values - #[cfg(stage0)] - fn mutate_values(&mut self, blk: &fn(&K, &mut V) -> bool) { - for uint::range(0, self.buckets.len()) |i| { - match self.buckets[i] { - Some(Bucket{key: ref key, value: ref mut value, _}) => { - if !blk(key, value) { return } - } - None => () - } - } - } - - /// Iterate over the map and mutate the contained values - #[cfg(not(stage0))] fn mutate_values(&mut self, blk: &fn(&K, &mut V) -> bool) -> bool { for uint::range(0, self.buckets.len()) |i| { match self.buckets[i] { @@ -402,19 +357,6 @@ impl Map for HashMap { } /// Return a mutable reference to the value corresponding to the key - #[cfg(stage0)] - fn find_mut<'a>(&'a mut self, k: &K) -> Option<&'a mut V> { - let idx = match self.bucket_for_key(k) { - FoundEntry(idx) => idx, - TableFull | FoundHole(_) => return None - }; - unsafe { - Some(::cast::transmute_mut_region(self.mut_value_for_bucket(idx))) - } - } - - /// Return a mutable reference to the value corresponding to the key - #[cfg(not(stage0))] fn find_mut<'a>(&'a mut self, k: &K) -> Option<&'a mut V> { let idx = match self.bucket_for_key(k) { FoundEntry(idx) => idx, @@ -463,30 +405,30 @@ impl Map for HashMap { } } -pub impl HashMap { +impl HashMap { /// Create an empty HashMap - fn new() -> HashMap { + pub fn new() -> HashMap { HashMap::with_capacity(INITIAL_CAPACITY) } /// Create an empty HashMap with space for at least `n` elements in /// the hash table. - fn with_capacity(capacity: uint) -> HashMap { + pub fn with_capacity(capacity: uint) -> HashMap { linear_map_with_capacity(capacity) } /// Reserve space for at least `n` elements in the hash table. - fn reserve_at_least(&mut self, n: uint) { + pub fn reserve_at_least(&mut self, n: uint) { if n > self.buckets.len() { let buckets = n * 4 / 3 + 1; self.resize(uint::next_power_of_two(buckets)); } } - /// Return the value corresponding to the key in the map, or insert - /// and return the value if it doesn't exist. - #[cfg(stage0)] - fn find_or_insert<'a>(&'a mut self, k: K, v: V) -> &'a V { + /// Modify and return the value corresponding to the key in the map, or + /// insert and return a new value if it doesn't exist. + pub fn mangle<'a,A>(&'a mut self, k: K, a: A, not_found: &fn(&K, A) -> V, + found: &fn(&K, &mut V, A)) -> &'a mut V { if self.size >= self.resize_at { // n.b.: We could also do this after searching, so // that we do not resize if this call to insert is @@ -500,113 +442,44 @@ pub impl HashMap { let hash = k.hash_keyed(self.k0, self.k1) as uint; let idx = match self.bucket_for_key_with_hash(hash, &k) { TableFull => fail!("Internal logic error"), - FoundEntry(idx) => idx, + FoundEntry(idx) => { found(&k, self.mut_value_for_bucket(idx), a); idx } FoundHole(idx) => { - self.buckets[idx] = Some(Bucket{hash: hash, key: k, - value: v}); + let v = not_found(&k, a); + self.buckets[idx] = Some(Bucket{hash: hash, key: k, value: v}); self.size += 1; idx - }, + } }; - unsafe { - ::cast::transmute_region(self.value_for_bucket(idx)) - } + self.mut_value_for_bucket(idx) } /// Return the value corresponding to the key in the map, or insert /// and return the value if it doesn't exist. - #[cfg(not(stage0))] - fn find_or_insert<'a>(&'a mut self, k: K, v: V) -> &'a V { - if self.size >= self.resize_at { - // n.b.: We could also do this after searching, so - // that we do not resize if this call to insert is - // simply going to update a key in place. My sense - // though is that it's worse to have to search through - // buckets to find the right spot twice than to just - // resize in this corner case. - self.expand(); - } - - let hash = k.hash_keyed(self.k0, self.k1) as uint; - let idx = match self.bucket_for_key_with_hash(hash, &k) { - TableFull => fail!("Internal logic error"), - FoundEntry(idx) => idx, - FoundHole(idx) => { - self.buckets[idx] = Some(Bucket{hash: hash, key: k, - value: v}); - self.size += 1; - idx - }, - }; - - self.value_for_bucket(idx) + pub fn find_or_insert<'a>(&'a mut self, k: K, v: V) -> &'a mut V { + self.mangle(k, v, |_k, a| a, |_k,_v,_a| ()) } /// Return the value corresponding to the key in the map, or create, /// insert, and return a new value if it doesn't exist. - #[cfg(stage0)] - fn find_or_insert_with<'a>(&'a mut self, k: K, f: &fn(&K) -> V) -> &'a V { - if self.size >= self.resize_at { - // n.b.: We could also do this after searching, so - // that we do not resize if this call to insert is - // simply going to update a key in place. My sense - // though is that it's worse to have to search through - // buckets to find the right spot twice than to just - // resize in this corner case. - self.expand(); - } - - let hash = k.hash_keyed(self.k0, self.k1) as uint; - let idx = match self.bucket_for_key_with_hash(hash, &k) { - TableFull => fail!("Internal logic error"), - FoundEntry(idx) => idx, - FoundHole(idx) => { - let v = f(&k); - self.buckets[idx] = Some(Bucket{hash: hash, key: k, - value: v}); - self.size += 1; - idx - }, - }; - - unsafe { - ::cast::transmute_region(self.value_for_bucket(idx)) - } + pub fn find_or_insert_with<'a>(&'a mut self, k: K, f: &fn(&K) -> V) + -> &'a mut V { + self.mangle(k, (), |k,_a| f(k), |_k,_v,_a| ()) } - /// Return the value corresponding to the key in the map, or create, - /// insert, and return a new value if it doesn't exist. - #[cfg(not(stage0))] - fn find_or_insert_with<'a>(&'a mut self, k: K, f: &fn(&K) -> V) -> &'a V { - if self.size >= self.resize_at { - // n.b.: We could also do this after searching, so - // that we do not resize if this call to insert is - // simply going to update a key in place. My sense - // though is that it's worse to have to search through - // buckets to find the right spot twice than to just - // resize in this corner case. - self.expand(); - } - - let hash = k.hash_keyed(self.k0, self.k1) as uint; - let idx = match self.bucket_for_key_with_hash(hash, &k) { - TableFull => fail!("Internal logic error"), - FoundEntry(idx) => idx, - FoundHole(idx) => { - let v = f(&k); - self.buckets[idx] = Some(Bucket{hash: hash, key: k, - value: v}); - self.size += 1; - idx - }, - }; - - self.value_for_bucket(idx) + /// Insert a key-value pair into the map if the key is not already present. + /// Otherwise, modify the existing value for the key. + /// Returns the new or modified value for the key. + pub fn insert_or_update_with<'a>(&'a mut self, k: K, v: V, + f: &fn(&K, &mut V)) -> &'a mut V { + self.mangle(k, v, |_k,a| a, |k,v,_a| f(k,v)) } - fn consume(&mut self, f: &fn(K, V)) { - let buckets = replace(&mut self.buckets, ~[]); + /// Calls a function on each element of a hash map, destroying the hash + /// map in the process. + pub fn consume(&mut self, f: &fn(K, V)) { + let buckets = replace(&mut self.buckets, + vec::from_fn(INITIAL_CAPACITY, |_| None)); self.size = 0; do vec::consume(buckets) |_, bucket| { @@ -619,16 +492,27 @@ pub impl HashMap { } } - fn get<'a>(&'a self, k: &K) -> &'a V { + /// Retrieves a value for the given key, failing if the key is not + /// present. + pub fn get<'a>(&'a self, k: &K) -> &'a V { match self.find(k) { Some(v) => v, None => fail!("No entry found for key: %?", k), } } + /// Retrieves a (mutable) value for the given key, failing if the key + /// is not present. + pub fn get_mut<'a>(&'a mut self, k: &K) -> &'a mut V { + match self.find_mut(k) { + Some(v) => v, + None => fail!("No entry found for key: %?", k), + } + } + /// Return true if the map contains a value for the specified key, /// using equivalence - fn contains_key_equiv>(&self, key: &Q) -> bool { + pub fn contains_key_equiv>(&self, key: &Q) -> bool { match self.bucket_for_key_equiv(key) { FoundEntry(_) => {true} TableFull | FoundHole(_) => {false} @@ -637,7 +521,8 @@ pub impl HashMap { /// Return the value corresponding to the key in the map, using /// equivalence - fn find_equiv<'a, Q:Hash + Equiv>(&'a self, k: &Q) -> Option<&'a V> { + pub fn find_equiv<'a, Q:Hash + Equiv>(&'a self, k: &Q) + -> Option<&'a V> { match self.bucket_for_key_equiv(k) { FoundEntry(idx) => Some(self.value_for_bucket(idx)), TableFull | FoundHole(_) => None, @@ -645,14 +530,14 @@ pub impl HashMap { } } -pub impl HashMap { +impl HashMap { /// Like `find`, but returns a copy of the value. - fn find_copy(&self, k: &K) -> Option { + pub fn find_copy(&self, k: &K) -> Option { self.find(k).map_consume(|v| copy *v) } /// Like `get`, but returns a copy of the value. - fn get_copy(&self, k: &K) -> V { + pub fn get_copy(&self, k: &K) -> V { copy *self.get(k) } } @@ -674,15 +559,15 @@ impl Eq for HashMap { fn ne(&self, other: &HashMap) -> bool { !self.eq(other) } } +/// An implementation of a hash set using the underlying representation of a +/// HashMap where the value is (). As with the `HashMap` type, a `HashSet` +/// requires that the elements implement the `Eq` and `Hash` traits. pub struct HashSet { priv map: HashMap } impl BaseIter for HashSet { /// Visit all values in order - #[cfg(stage0)] - fn each(&self, f: &fn(&T) -> bool) { self.map.each_key(f) } - #[cfg(not(stage0))] fn each(&self, f: &fn(&T) -> bool) -> bool { self.map.each_key(f) } fn size_hint(&self) -> Option { Some(self.len()) } } @@ -734,32 +619,11 @@ impl Set for HashSet { } /// Visit the values representing the difference - #[cfg(stage0)] - fn difference(&self, other: &HashSet, f: &fn(&T) -> bool) { - for self.each |v| { - if !other.contains(v) { - if !f(v) { return } - } - } - } - - /// Visit the values representing the difference - #[cfg(not(stage0))] fn difference(&self, other: &HashSet, f: &fn(&T) -> bool) -> bool { self.each(|v| other.contains(v) || f(v)) } /// Visit the values representing the symmetric difference - #[cfg(stage0)] - fn symmetric_difference(&self, - other: &HashSet, - f: &fn(&T) -> bool) { - self.difference(other, f); - other.difference(self, f); - } - - /// Visit the values representing the symmetric difference - #[cfg(not(stage0))] fn symmetric_difference(&self, other: &HashSet, f: &fn(&T) -> bool) -> bool { @@ -767,65 +631,41 @@ impl Set for HashSet { } /// Visit the values representing the intersection - #[cfg(stage0)] - fn intersection(&self, other: &HashSet, f: &fn(&T) -> bool) { - for self.each |v| { - if other.contains(v) { - if !f(v) { return } - } - } - } - - /// Visit the values representing the intersection - #[cfg(not(stage0))] fn intersection(&self, other: &HashSet, f: &fn(&T) -> bool) -> bool { self.each(|v| !other.contains(v) || f(v)) } /// Visit the values representing the union - #[cfg(stage0)] - fn union(&self, other: &HashSet, f: &fn(&T) -> bool) { - for self.each |v| { - if !f(v) { return } - } - - for other.each |v| { - if !self.contains(v) { - if !f(v) { return } - } - } - } - - /// Visit the values representing the union - #[cfg(not(stage0))] fn union(&self, other: &HashSet, f: &fn(&T) -> bool) -> bool { self.each(f) && other.each(|v| self.contains(v) || f(v)) } } -pub impl HashSet { +impl HashSet { /// Create an empty HashSet - fn new() -> HashSet { + pub fn new() -> HashSet { HashSet::with_capacity(INITIAL_CAPACITY) } /// Create an empty HashSet with space for at least `n` elements in /// the hash table. - fn with_capacity(capacity: uint) -> HashSet { + pub fn with_capacity(capacity: uint) -> HashSet { HashSet { map: HashMap::with_capacity(capacity) } } /// Reserve space for at least `n` elements in the hash table. - fn reserve_at_least(&mut self, n: uint) { + pub fn reserve_at_least(&mut self, n: uint) { self.map.reserve_at_least(n) } /// Consumes all of the elements in the set, emptying it out - fn consume(&mut self, f: &fn(T)) { + pub fn consume(&mut self, f: &fn(T)) { self.map.consume(|k, _| f(k)) } - fn contains_equiv>(&self, value: &Q) -> bool { + /// Returns true if the hash set contains a value equivalent to the + /// given query value. + pub fn contains_equiv>(&self, value: &Q) -> bool { self.map.contains_key_equiv(value) } } @@ -837,13 +677,19 @@ mod test_map { use super::*; use uint; + #[test] + fn test_create_capacity_zero() { + let mut m = HashMap::with_capacity(0); + assert!(m.insert(1, 1)); + } + #[test] fn test_insert() { let mut m = HashMap::new(); assert!(m.insert(1, 2)); assert!(m.insert(2, 4)); - assert!(*m.get(&1) == 2); - assert!(*m.get(&2) == 4); + assert_eq!(*m.get(&1), 2); + assert_eq!(*m.get(&2), 4); } #[test] @@ -863,9 +709,9 @@ mod test_map { fn test_insert_overwrite() { let mut m = HashMap::new(); assert!(m.insert(1, 2)); - assert!(*m.get(&1) == 2); + assert_eq!(*m.get(&1), 2); assert!(!m.insert(1, 3)); - assert!(*m.get(&1) == 3); + assert_eq!(*m.get(&1), 3); } #[test] @@ -874,9 +720,9 @@ mod test_map { assert!(m.insert(1, 2)); assert!(m.insert(5, 3)); assert!(m.insert(9, 4)); - assert!(*m.get(&9) == 4); - assert!(*m.get(&5) == 3); - assert!(*m.get(&1) == 2); + assert_eq!(*m.get(&9), 4); + assert_eq!(*m.get(&5), 3); + assert_eq!(*m.get(&1), 2); } #[test] @@ -886,8 +732,8 @@ mod test_map { assert!(m.insert(5, 3)); assert!(m.insert(9, 4)); assert!(m.remove(&1)); - assert!(*m.get(&9) == 4); - assert!(*m.get(&5) == 3); + assert_eq!(*m.get(&9), 4); + assert_eq!(*m.get(&5), 3); } #[test] @@ -903,30 +749,37 @@ mod test_map { fn test_pop() { let mut m = HashMap::new(); m.insert(1, 2); - assert!(m.pop(&1) == Some(2)); - assert!(m.pop(&1) == None); + assert_eq!(m.pop(&1), Some(2)); + assert_eq!(m.pop(&1), None); } #[test] fn test_swap() { let mut m = HashMap::new(); - assert!(m.swap(1, 2) == None); - assert!(m.swap(1, 3) == Some(2)); - assert!(m.swap(1, 4) == Some(3)); + assert_eq!(m.swap(1, 2), None); + assert_eq!(m.swap(1, 3), Some(2)); + assert_eq!(m.swap(1, 4), Some(3)); } #[test] fn test_find_or_insert() { let mut m = HashMap::new::(); - assert!(m.find_or_insert(1, 2) == &2); - assert!(m.find_or_insert(1, 3) == &2); + assert_eq!(*m.find_or_insert(1, 2), 2); + assert_eq!(*m.find_or_insert(1, 3), 2); } #[test] fn test_find_or_insert_with() { let mut m = HashMap::new::(); - assert!(m.find_or_insert_with(1, |_| 2) == &2); - assert!(m.find_or_insert_with(1, |_| 3) == &2); + assert_eq!(*m.find_or_insert_with(1, |_| 2), 2); + assert_eq!(*m.find_or_insert_with(1, |_| 3), 2); + } + + #[test] + fn test_insert_or_update_with() { + let mut m = HashMap::new::(); + assert_eq!(*m.insert_or_update_with(1, 2, |_,x| *x+=1), 2); + assert_eq!(*m.insert_or_update_with(1, 2, |_,x| *x+=1), 3); } #[test] @@ -938,10 +791,18 @@ mod test_map { do m.consume |k, v| { m2.insert(k, v); } - assert!(m.len() == 0); - assert!(m2.len() == 2); - assert!(m2.get(&1) == &2); - assert!(m2.get(&2) == &3); + assert_eq!(m.len(), 0); + assert_eq!(m2.len(), 2); + assert_eq!(m2.get(&1), &2); + assert_eq!(m2.get(&2), &3); + } + + #[test] + fn test_consume_still_usable() { + let mut m = HashMap::new(); + assert!(m.insert(1, 2)); + do m.consume |_, _| {} + assert!(m.insert(1, 2)); } #[test] @@ -952,10 +813,10 @@ mod test_map { } let mut observed = 0; for m.each |k, v| { - assert!(*v == *k * 2); + assert_eq!(*v, *k * 2); observed |= (1 << *k); } - assert!(observed == 0xFFFF_FFFF); + assert_eq!(observed, 0xFFFF_FFFF); } #[test] @@ -984,14 +845,14 @@ mod test_map { m2.insert(3, 4); - assert!(m1 == m2); + assert_eq!(m1, m2); } #[test] fn test_expand() { let mut m = HashMap::new(); - assert!(m.len() == 0); + assert_eq!(m.len(), 0); assert!(m.is_empty()); let mut i = 0u; @@ -1001,7 +862,7 @@ mod test_map { i += 1; } - assert!(m.len() == i); + assert_eq!(m.len(), i); assert!(!m.is_empty()); } } @@ -1090,7 +951,7 @@ mod test_set { assert!(vec::contains(expected, x)); i += 1 } - assert!(i == expected.len()); + assert_eq!(i, expected.len()); } #[test] @@ -1113,7 +974,7 @@ mod test_set { assert!(vec::contains(expected, x)); i += 1 } - assert!(i == expected.len()); + assert_eq!(i, expected.len()); } #[test] @@ -1139,7 +1000,7 @@ mod test_set { assert!(vec::contains(expected, x)); i += 1 } - assert!(i == expected.len()); + assert_eq!(i, expected.len()); } #[test] @@ -1169,6 +1030,6 @@ mod test_set { assert!(vec::contains(expected, x)); i += 1 } - assert!(i == expected.len()); + assert_eq!(i, expected.len()); } } diff --git a/src/libcore/io.rs b/src/libstd/io.rs similarity index 90% rename from src/libcore/io.rs rename to src/libstd/io.rs index 7b7d278380f1a..e3977ca00674b 100644 --- a/src/libcore/io.rs +++ b/src/libstd/io.rs @@ -10,10 +10,42 @@ /*! -Basic input/output +The `io` module contains basic input and output routines. + +A quick summary: + +## `Reader` and `Writer` traits + +These traits define the minimal set of methods that anything that can do +input and output should implement. + +## `ReaderUtil` and `WriterUtil` traits + +Richer methods that allow you to do more. `Reader` only lets you read a certain +number of bytes into a buffer, while `ReaderUtil` allows you to read a whole +line, for example. + +Generally, these richer methods are probably the ones you want to actually +use in day-to-day Rust. + +Furthermore, because there is an implementation of `ReaderUtil` for +``, when your input or output code implements `Reader`, you get +all of these methods for free. + +## `print` and `println` + +These very useful functions are defined here. You generally don't need to +import them, though, as the prelude already does. + +## `stdin`, `stdout`, and `stderr` + +These functions return references to the classic three file descriptors. They +implement `Reader` and `Writer`, where appropriate. */ +#[allow(missing_doc)]; + use result::Result; use container::Container; @@ -84,14 +116,16 @@ pub trait Reader { // FIXME (#2982): This should probably return an error. /** - * Reads bytes and puts them into `bytes`. Returns the number of - * bytes read. + * Reads bytes and puts them into `bytes`, advancing the cursor. Returns the + * number of bytes read. * * The number of bytes to be read is `len` or the end of the file, * whichever comes first. * * The buffer must be at least `len` bytes long. * + * `read` is conceptually similar to C's `fread` function. + * * # Examples * * None right now. @@ -99,10 +133,12 @@ pub trait Reader { fn read(&self, bytes: &mut [u8], len: uint) -> uint; /** - * Reads a single byte. + * Reads a single byte, advancing the cursor. * * In the case of an EOF or an error, returns a negative value. * + * `read_byte` is conceptually similar to C's `getc` function. + * * # Examples * * None right now. @@ -112,6 +148,8 @@ pub trait Reader { /** * Returns a boolean value: are we currently at EOF? * + * `eof` is conceptually similar to C's `feof` function. + * * # Examples * * None right now. @@ -124,6 +162,8 @@ pub trait Reader { * Takes an optional SeekStyle, which affects how we seek from the * position. See `SeekStyle` docs for more details. * + * `seek` is conceptually similar to C's `fseek` function. + * * # Examples * * None right now. @@ -133,6 +173,8 @@ pub trait Reader { /** * Returns the current position within the stream. * + * `tell` is conceptually similar to C's `ftell` function. + * * # Examples * * None right now. @@ -252,9 +294,6 @@ pub trait ReaderUtil { * * None right now. */ - #[cfg(stage0)] - fn each_byte(&self, it: &fn(int) -> bool); - #[cfg(not(stage0))] fn each_byte(&self, it: &fn(int) -> bool) -> bool; /** @@ -264,9 +303,6 @@ pub trait ReaderUtil { * * None right now. */ - #[cfg(stage0)] - fn each_char(&self, it: &fn(char) -> bool); - #[cfg(not(stage0))] fn each_char(&self, it: &fn(char) -> bool) -> bool; /** @@ -276,9 +312,6 @@ pub trait ReaderUtil { * * None right now. */ - #[cfg(stage0)] - fn each_line(&self, it: &fn(&str) -> bool); - #[cfg(not(stage0))] fn each_line(&self, it: &fn(&str) -> bool) -> bool; /** @@ -635,7 +668,7 @@ impl ReaderUtil for T { let next = bytes[i] as int; i += 1; assert!((next > -1)); - assert!((next & 192 == 128)); + assert_eq!(next & 192, 128); val <<= 6; val += (next & 63) as uint; } @@ -676,7 +709,7 @@ impl ReaderUtil for T { if c.len() == 0 { return -1 as char; // FIXME will this stay valid? // #2004 } - assert!(c.len() == 1); + assert_eq!(c.len(), 1); return c[0]; } @@ -690,13 +723,6 @@ impl ReaderUtil for T { bytes } - #[cfg(stage0)] - fn each_byte(&self, it: &fn(int) -> bool) { - while !self.eof() { - if !it(self.read_byte()) { break; } - } - } - #[cfg(not(stage0))] fn each_byte(&self, it: &fn(int) -> bool) -> bool { while !self.eof() { if !it(self.read_byte()) { return false; } @@ -704,13 +730,6 @@ impl ReaderUtil for T { return true; } - #[cfg(stage0)] - fn each_char(&self, it: &fn(char) -> bool) { - while !self.eof() { - if !it(self.read_char()) { break; } - } - } - #[cfg(not(stage0))] fn each_char(&self, it: &fn(char) -> bool) -> bool { while !self.eof() { if !it(self.read_char()) { return false; } @@ -718,27 +737,6 @@ impl ReaderUtil for T { return true; } - #[cfg(stage0)] - fn each_line(&self, it: &fn(s: &str) -> bool) { - while !self.eof() { - // include the \n, so that we can distinguish an entirely empty - // line read after "...\n", and the trailing empty line in - // "...\n\n". - let mut line = self.read_until('\n' as u8, true); - - // blank line at the end of the reader is ignored - if self.eof() && line.is_empty() { break; } - - // trim the \n, so that each_line is consistent with read_line - let n = str::len(line); - if line[n-1] == '\n' as u8 { - unsafe { str::raw::set_len(&mut line, n-1); } - } - - if !it(line) { break; } - } - } - #[cfg(not(stage0))] fn each_line(&self, it: &fn(s: &str) -> bool) -> bool { while !self.eof() { // include the \n, so that we can distinguish an entirely empty @@ -773,7 +771,7 @@ impl ReaderUtil for T { fn read_le_uint_n(&self, nbytes: uint) -> u64 { assert!(nbytes > 0 && nbytes <= 8); - let mut val = 0u64, pos = 0, i = nbytes; + let mut (val, pos, i) = (0u64, 0, nbytes); while i > 0 { val += (self.read_u8() as u64) << pos; pos += 8; @@ -789,7 +787,7 @@ impl ReaderUtil for T { fn read_be_uint_n(&self, nbytes: uint) -> u64 { assert!(nbytes > 0 && nbytes <= 8); - let mut val = 0u64, i = nbytes; + let mut (val, i) = (0u64, nbytes); while i > 0 { i -= 1; val += (self.read_u8() as u64) << i * 8; @@ -984,6 +982,12 @@ pub struct FILERes { f: *libc::FILE, } +impl FILERes { + pub fn new(f: *libc::FILE) -> FILERes { + FILERes { f: f } + } +} + impl Drop for FILERes { fn finalize(&self) { unsafe { @@ -992,15 +996,9 @@ impl Drop for FILERes { } } -pub fn FILERes(f: *libc::FILE) -> FILERes { - FILERes { - f: f - } -} - pub fn FILE_reader(f: *libc::FILE, cleanup: bool) -> @Reader { if cleanup { - @Wrapper { base: f, cleanup: FILERes(f) } as @Reader + @Wrapper { base: f, cleanup: FILERes::new(f) } as @Reader } else { @f as @Reader } @@ -1010,6 +1008,17 @@ pub fn FILE_reader(f: *libc::FILE, cleanup: bool) -> @Reader { // top-level functions that take a reader, or a set of default methods on // reader (which can then be called reader) +/** +* Gives a `Reader` that allows you to read values from standard input. +* +* # Example +* +* ~~~ {.rust} +* let stdin = core::io::stdin(); +* let line = stdin.read_line(); +* core::io::print(line); +* ~~~ +*/ pub fn stdin() -> @Reader { unsafe { @rustrt::rust_get_stdin() as @Reader @@ -1174,7 +1183,7 @@ impl Writer for *libc::FILE { pub fn FILE_writer(f: *libc::FILE, cleanup: bool) -> @Writer { if cleanup { - @Wrapper { base: f, cleanup: FILERes(f) } as @Writer + @Wrapper { base: f, cleanup: FILERes::new(f) } as @Writer } else { @f as @Writer } @@ -1218,6 +1227,12 @@ pub struct FdRes { fd: fd_t, } +impl FdRes { + pub fn new(fd: fd_t) -> FdRes { + FdRes { fd: fd } + } +} + impl Drop for FdRes { fn finalize(&self) { unsafe { @@ -1226,15 +1241,9 @@ impl Drop for FdRes { } } -pub fn FdRes(fd: fd_t) -> FdRes { - FdRes { - fd: fd - } -} - pub fn fd_writer(fd: fd_t, cleanup: bool) -> @Writer { if cleanup { - @Wrapper { base: fd, cleanup: FdRes(fd) } as @Writer + @Wrapper { base: fd, cleanup: FdRes::new(fd) } as @Writer } else { @fd as @Writer } @@ -1295,7 +1304,9 @@ pub fn u64_to_le_bytes(n: u64, size: uint, (n >> 56) as u8]), _ => { - let mut bytes: ~[u8] = ~[], i = size, n = n; + let mut bytes: ~[u8] = ~[]; + let mut i = size; + let mut n = n; while i > 0u { bytes.push((n & 255_u64) as u8); n >>= 8_u64; @@ -1561,13 +1572,61 @@ pub fn buffered_file_writer(path: &Path) -> Result<@Writer, ~str> { // FIXME (#2004) it would be great if this could be a const // FIXME (#2004) why are these different from the way stdin() is // implemented? + + +/** +* Gives a `Writer` which allows you to write to the standard output. +* +* # Example +* +* ~~~ {.rust} +* let stdout = core::io::stdout(); +* stdout.write_str("hello\n"); +* ~~~ +*/ pub fn stdout() -> @Writer { fd_writer(libc::STDOUT_FILENO as c_int, false) } + +/** +* Gives a `Writer` which allows you to write to standard error. +* +* # Example +* +* ~~~ {.rust} +* let stderr = core::io::stderr(); +* stderr.write_str("hello\n"); +* ~~~ +*/ pub fn stderr() -> @Writer { fd_writer(libc::STDERR_FILENO as c_int, false) } +/** +* Prints a string to standard output. +* +* This string will not have an implicit newline at the end. If you want +* an implicit newline, please see `println`. +* +* # Example +* +* ~~~ {.rust} +* // print is imported into the prelude, and so is always available. +* print("hello"); +* ~~~ +*/ pub fn print(s: &str) { stdout().write_str(s); } +/** +* Prints a string to standard output, followed by a newline. +* +* If you do not want an implicit newline, please see `print`. +* +* # Example +* +* ~~~ {.rust} +* // println is imported into the prelude, and so is always available. +* println("hello"); +* ~~~ +*/ pub fn println(s: &str) { stdout().write_line(s); } @@ -1577,6 +1636,15 @@ pub struct BytesWriter { pos: @mut uint, } +impl BytesWriter { + pub fn new() -> BytesWriter { + BytesWriter { + bytes: @mut ~[], + pos: @mut 0 + } + } +} + impl Writer for BytesWriter { fn write(&self, v: &[u8]) { let v_len = v.len(); @@ -1616,15 +1684,8 @@ impl Writer for BytesWriter { } } -pub fn BytesWriter() -> BytesWriter { - BytesWriter { - bytes: @mut ~[], - pos: @mut 0 - } -} - pub fn with_bytes_writer(f: &fn(@Writer)) -> ~[u8] { - let wr = @BytesWriter(); + let wr = @BytesWriter::new(); f(wr as @Writer); let @BytesWriter { bytes, _ } = wr; copy *bytes @@ -1661,9 +1722,9 @@ pub fn read_whole_file_str(file: &Path) -> Result<~str, ~str> { result::chain(read_whole_file(file), |bytes| { if str::is_utf8(bytes) { result::Ok(str::from_bytes(bytes)) - } else { - result::Err(file.to_str() + ~" is not UTF-8") - } + } else { + result::Err(file.to_str() + " is not UTF-8") + } }) } @@ -1705,6 +1766,12 @@ pub mod fsync { arg: Arg, } + impl Res { + pub fn new(arg: Arg) -> Res { + Res { arg: arg } + } + } + #[unsafe_destructor] impl Drop for Res { fn finalize(&self) { @@ -1719,12 +1786,6 @@ pub mod fsync { } } - pub fn Res(arg: Arg) -> Res{ - Res { - arg: arg - } - } - pub struct Arg { val: t, opt_level: Option, @@ -1736,7 +1797,7 @@ pub mod fsync { // outer res pub fn FILE_res_sync(file: &FILERes, opt_level: Option, blk: &fn(v: Res<*libc::FILE>)) { - blk(Res(Arg { + blk(Res::new(Arg { val: file.f, opt_level: opt_level, fsync_fn: |file, l| { unsafe { @@ -1749,7 +1810,7 @@ pub mod fsync { // fsync fd after executing blk pub fn fd_res_sync(fd: &FdRes, opt_level: Option, blk: &fn(v: Res)) { - blk(Res(Arg { + blk(Res::new(Arg { val: fd.fd, opt_level: opt_level, fsync_fn: |fd, l| os::fsync_fd(fd, l) as int })); @@ -1761,7 +1822,7 @@ pub mod fsync { // Call o.fsync after executing blk pub fn obj_sync(o: @FSyncable, opt_level: Option, blk: &fn(v: Res<@FSyncable>)) { - blk(Res(Arg { + blk(Res::new(Arg { val: o, opt_level: opt_level, fsync_fn: |o, l| o.fsync(l) })); @@ -1789,42 +1850,42 @@ mod tests { { let out: @io::Writer = result::get( - &io::file_writer(tmpfile, ~[io::Create, io::Truncate])); + &io::file_writer(tmpfile, [io::Create, io::Truncate])); out.write_str(frood); } let inp: @io::Reader = result::get(&io::file_reader(tmpfile)); let frood2: ~str = inp.read_c_str(); debug!(copy frood2); - assert!(frood == frood2); + assert_eq!(frood, frood2); } #[test] fn test_readchars_empty() { - do io::with_str_reader(~"") |inp| { + do io::with_str_reader("") |inp| { let res : ~[char] = inp.read_chars(128); - assert!(res.len() == 0); + assert_eq!(res.len(), 0); } } #[test] fn test_read_line_utf8() { - do io::with_str_reader(~"生锈的汤匙切肉汤hello生锈的汤匙切肉汤") |inp| { + do io::with_str_reader("生锈的汤匙切肉汤hello生锈的汤匙切肉汤") |inp| { let line = inp.read_line(); - assert!(line == ~"生锈的汤匙切肉汤hello生锈的汤匙切肉汤"); + assert_eq!(line, ~"生锈的汤匙切肉汤hello生锈的汤匙切肉汤"); } } #[test] fn test_read_lines() { - do io::with_str_reader(~"a\nb\nc\n") |inp| { - assert!(inp.read_lines() == ~[~"a", ~"b", ~"c"]); + do io::with_str_reader("a\nb\nc\n") |inp| { + assert_eq!(inp.read_lines(), ~[~"a", ~"b", ~"c"]); } - do io::with_str_reader(~"a\nb\nc") |inp| { - assert!(inp.read_lines() == ~[~"a", ~"b", ~"c"]); + do io::with_str_reader("a\nb\nc") |inp| { + assert_eq!(inp.read_lines(), ~[~"a", ~"b", ~"c"]); } - do io::with_str_reader(~"") |inp| { + do io::with_str_reader("") |inp| { assert!(inp.read_lines().is_empty()); } } @@ -1842,7 +1903,7 @@ mod tests { do io::with_str_reader(s) |inp| { let res : ~[char] = inp.read_chars(len); if len <= ivals.len() { - assert!(res.len() == len); + assert_eq!(res.len(), len); } assert!(vec::slice(ivals, 0u, res.len()) == vec::map(res, |x| *x as int)); @@ -1859,25 +1920,25 @@ mod tests { #[test] fn test_readchar() { - do io::with_str_reader(~"生") |inp| { + do io::with_str_reader("生") |inp| { let res : char = inp.read_char(); - assert!((res as int == 29983)); + assert_eq!(res as int, 29983); } } #[test] fn test_readchar_empty() { - do io::with_str_reader(~"") |inp| { + do io::with_str_reader("") |inp| { let res : char = inp.read_char(); - assert!((res as int == -1)); + assert_eq!(res as int, -1); } } #[test] fn file_reader_not_exist() { match io::file_reader(&Path("not a file")) { - result::Err(copy e) => { - assert!(e == ~"error opening not a file"); + result::Err(e) => { + assert_eq!(e, ~"error opening not a file"); } result::Ok(_) => fail!() } @@ -1916,8 +1977,8 @@ mod tests { #[test] fn file_writer_bad_name() { - match io::file_writer(&Path("?/?"), ~[]) { - result::Err(copy e) => { + match io::file_writer(&Path("?/?"), []) { + result::Err(e) => { assert!(str::starts_with(e, "error opening")); } result::Ok(_) => fail!() @@ -1927,7 +1988,7 @@ mod tests { #[test] fn buffered_file_writer_bad_name() { match io::buffered_file_writer(&Path("?/?")) { - result::Err(copy e) => { + result::Err(e) => { assert!(str::starts_with(e, "error opening")); } result::Ok(_) => fail!() @@ -1936,16 +1997,16 @@ mod tests { #[test] fn bytes_buffer_overwrite() { - let wr = BytesWriter(); - wr.write(~[0u8, 1u8, 2u8, 3u8]); + let wr = BytesWriter::new(); + wr.write([0u8, 1u8, 2u8, 3u8]); assert!(*wr.bytes == ~[0u8, 1u8, 2u8, 3u8]); wr.seek(-2, SeekCur); - wr.write(~[4u8, 5u8, 6u8, 7u8]); + wr.write([4u8, 5u8, 6u8, 7u8]); assert!(*wr.bytes == ~[0u8, 1u8, 4u8, 5u8, 6u8, 7u8]); wr.seek(-2, SeekEnd); - wr.write(~[8u8]); + wr.write([8u8]); wr.seek(1, SeekSet); - wr.write(~[9u8]); + wr.write([9u8]); assert!(*wr.bytes == ~[0u8, 9u8, 4u8, 5u8, 8u8, 7u8]); } @@ -1966,7 +2027,7 @@ mod tests { { let file = io::file_reader(&path).get(); for uints.each |i| { - assert!(file.read_le_u64() == *i); + assert_eq!(file.read_le_u64(), *i); } } } @@ -1988,7 +2049,7 @@ mod tests { { let file = io::file_reader(&path).get(); for uints.each |i| { - assert!(file.read_be_u64() == *i); + assert_eq!(file.read_be_u64(), *i); } } } @@ -2012,7 +2073,7 @@ mod tests { for ints.each |i| { // this tests that the sign extension is working // (comparing the values as i32 would not test this) - assert!(file.read_be_int_n(4) == *i as i64); + assert_eq!(file.read_be_int_n(4), *i as i64); } } } @@ -2031,11 +2092,11 @@ mod tests { { let file = io::file_reader(&path).get(); let f = file.read_be_f32(); - assert!(f == 8.1250); + assert_eq!(f, 8.1250); } } -#[test] + #[test] fn test_read_write_f32() { let path = Path("tmp/lib-io-test-read-write-f32.tmp"); let f:f32 = 8.1250; @@ -2048,8 +2109,8 @@ mod tests { { let file = io::file_reader(&path).get(); - assert!(file.read_be_f32() == 8.1250); - assert!(file.read_le_f32() == 8.1250); + assert_eq!(file.read_be_f32(), 8.1250); + assert_eq!(file.read_le_f32(), 8.1250); } } } diff --git a/src/libcore/iter.rs b/src/libstd/iter.rs similarity index 86% rename from src/libcore/iter.rs rename to src/libstd/iter.rs index ae4af3812d2d2..e5d79d79fcef3 100644 --- a/src/libcore/iter.rs +++ b/src/libstd/iter.rs @@ -16,14 +16,14 @@ An internal iterator takes `fn(...) -> bool` as a parameter, with returning `fal breaking out of iteration. The adaptors in the module work with any such iterator, not just ones tied to specific traits. For example: -~~~~ +~~~ {.rust} println(iter::to_vec(|f| uint::range(0, 20, f)).to_str()); -~~~~ +~~~ An external iterator object implementing the interface in the `iterator` module can be used as an internal iterator by calling the `advance` method. For example: -~~~~ +~~~ {.rust} use core::iterator::*; let xs = [0u, 1, 2, 3, 4, 5]; @@ -32,7 +32,7 @@ let mut it = xs.iter().chain(ys.iter()); for it.advance |&x: &uint| { println(x.to_str()); } -~~~~ +~~~ Internal iterators provide a subset of the functionality of an external iterator. It's not possible to interleave them to implement algorithms like `zip`, `union` and `merge`. However, they're often @@ -40,17 +40,13 @@ much easier to implement. */ -#[cfg(not(stage0))] use cmp::Ord; -#[cfg(not(stage0))] use option::{Option, Some, None}; -#[cfg(not(stage0))] use vec::OwnedVector; -#[cfg(not(stage0))] use num::{One, Zero}; -#[cfg(not(stage0))] use ops::{Add, Mul}; +use cmp::Ord; +use option::{Option, Some, None}; +use vec::OwnedVector; +use num::{One, Zero}; +use ops::{Add, Mul}; -#[cfg(stage0)] -pub trait Times { - fn times(&self, it: &fn() -> bool); -} -#[cfg(not(stage0))] +#[allow(missing_doc)] pub trait Times { fn times(&self, it: &fn() -> bool) -> bool; } @@ -60,14 +56,13 @@ pub trait Times { * * # Example: * - * ~~~ + * ~~~ {.rust} * let xs = ~[1, 2, 3]; * let ys = do iter::to_vec |f| { xs.each(|x| f(*x)) }; * assert_eq!(xs, ys); * ~~~ */ #[inline(always)] -#[cfg(not(stage0))] pub fn to_vec(iter: &fn(f: &fn(T) -> bool) -> bool) -> ~[T] { let mut v = ~[]; for iter |x| { v.push(x) } @@ -79,14 +74,13 @@ pub fn to_vec(iter: &fn(f: &fn(T) -> bool) -> bool) -> ~[T] { * * Example: * - * ~~~~ + * ~~~ {.rust} * let xs = ~[1u, 2, 3, 4, 5]; * assert!(any(|&x: &uint| x > 2, |f| xs.each(f))); * assert!(!any(|&x: &uint| x > 5, |f| xs.each(f))); - * ~~~~ + * ~~~ */ #[inline(always)] -#[cfg(not(stage0))] pub fn any(predicate: &fn(T) -> bool, iter: &fn(f: &fn(T) -> bool) -> bool) -> bool { for iter |x| { @@ -102,35 +96,12 @@ pub fn any(predicate: &fn(T) -> bool, * * # Example: * - * ~~~~ - * assert!(all(|&x: &uint| x < 6, |f| uint::range(1, 6, f))); - * assert!(!all(|&x: &uint| x < 5, |f| uint::range(1, 6, f))); - * ~~~~ - */ -#[inline(always)] -#[cfg(stage0)] -pub fn all(predicate: &fn(T) -> bool, - iter: &fn(f: &fn(T) -> bool)) -> bool { - for iter |x| { - if !predicate(x) { - return false; - } - } - return true; -} - -/** - * Return true if `predicate` is true for all values yielded by an internal iterator. - * - * # Example: - * - * ~~~~ + * ~~~ {.rust} * assert!(all(|&x: &uint| x < 6, |f| uint::range(1, 6, f))); * assert!(!all(|&x: &uint| x < 5, |f| uint::range(1, 6, f))); - * ~~~~ + * ~~~ */ #[inline(always)] -#[cfg(not(stage0))] pub fn all(predicate: &fn(T) -> bool, iter: &fn(f: &fn(T) -> bool) -> bool) -> bool { // If we ever break, iter will return false, so this will only return true @@ -143,13 +114,12 @@ pub fn all(predicate: &fn(T) -> bool, * * # Example: * - * ~~~~ + * ~~~ {.rust} * let xs = ~[1u, 2, 3, 4, 5, 6]; * assert_eq!(*find(|& &x: & &uint| x > 3, |f| xs.each(f)).unwrap(), 4); - * ~~~~ + * ~~~ */ #[inline(always)] -#[cfg(not(stage0))] pub fn find(predicate: &fn(&T) -> bool, iter: &fn(f: &fn(T) -> bool) -> bool) -> Option { for iter |x| { @@ -165,13 +135,12 @@ pub fn find(predicate: &fn(&T) -> bool, * * # Example: * - * ~~~~ + * ~~~ {.rust} * let xs = ~[8, 2, 3, 1, -5, 9, 11, 15]; * assert_eq!(max(|f| xs.each(f)).unwrap(), &15); - * ~~~~ + * ~~~ */ #[inline] -#[cfg(not(stage0))] pub fn max(iter: &fn(f: &fn(T) -> bool) -> bool) -> Option { let mut result = None; for iter |x| { @@ -192,13 +161,12 @@ pub fn max(iter: &fn(f: &fn(T) -> bool) -> bool) -> Option { * * # Example: * - * ~~~~ + * ~~~ {.rust} * let xs = ~[8, 2, 3, 1, -5, 9, 11, 15]; * assert_eq!(max(|f| xs.each(f)).unwrap(), &-5); - * ~~~~ + * ~~~ */ #[inline] -#[cfg(not(stage0))] pub fn min(iter: &fn(f: &fn(T) -> bool) -> bool) -> Option { let mut result = None; for iter |x| { @@ -219,11 +187,10 @@ pub fn min(iter: &fn(f: &fn(T) -> bool) -> bool) -> Option { * * # Example: * - * ~~~~ + * ~~~ {.rust} * assert_eq!(fold(0i, |f| int::range(1, 5, f), |a, x| *a += x), 10); - * ~~~~ + * ~~~ */ -#[cfg(not(stage0))] #[inline] pub fn fold(start: T, iter: &fn(f: &fn(U) -> bool) -> bool, f: &fn(&mut T, U)) -> T { let mut result = start; @@ -241,13 +208,12 @@ pub fn fold(start: T, iter: &fn(f: &fn(U) -> bool) -> bool, f: &fn(&mut T, * * # Example: * - * ~~~~ + * ~~~ {.rust} * fn product>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T { * fold_ref(One::one::(), iter, |a, x| *a = a.mul(x)) * } - * ~~~~ + * ~~~ */ -#[cfg(not(stage0))] #[inline] pub fn fold_ref(start: T, iter: &fn(f: &fn(&U) -> bool) -> bool, f: &fn(&mut T, &U)) -> T { let mut result = start; @@ -262,12 +228,11 @@ pub fn fold_ref(start: T, iter: &fn(f: &fn(&U) -> bool) -> bool, f: &fn(&m * * # Example: * - * ~~~~ + * ~~~ {.rust} * let xs: ~[int] = ~[1, 2, 3, 4]; * assert_eq!(do sum |f| { xs.each(f) }, 10); - * ~~~~ + * ~~~ */ -#[cfg(not(stage0))] #[inline(always)] pub fn sum>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T { fold_ref(Zero::zero::(), iter, |a, x| *a = a.add(x)) @@ -278,12 +243,11 @@ pub fn sum>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T { * * # Example: * - * ~~~~ + * ~~~ {.rust} * let xs: ~[int] = ~[1, 2, 3, 4]; * assert_eq!(do product |f| { xs.each(f) }, 24); - * ~~~~ + * ~~~ */ -#[cfg(not(stage0))] #[inline(always)] pub fn product>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T { fold_ref(One::one::(), iter, |a, x| *a = a.mul(x)) @@ -294,6 +258,9 @@ mod tests { use super::*; use prelude::*; + use int; + use uint; + #[test] fn test_to_vec() { let xs = ~[1, 2, 3]; diff --git a/src/libstd/iterator.rs b/src/libstd/iterator.rs new file mode 100644 index 0000000000000..7be9e8c354e91 --- /dev/null +++ b/src/libstd/iterator.rs @@ -0,0 +1,1080 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/*! Composable external iterators + +The `Iterator` trait defines an interface for objects which implement iteration as a state machine. + +Algorithms like `zip` are provided as `Iterator` implementations which wrap other objects +implementing the `Iterator` trait. + +*/ + +use cmp; +use iter; +use num::{Zero, One}; +use prelude::*; + +/// An interface for dealing with "external iterators". These types of iterators +/// can be resumed at any time as all state is stored internally as opposed to +/// being located on the call stack. +pub trait Iterator { + /// Advance the iterator and return the next value. Return `None` when the end is reached. + fn next(&mut self) -> Option; +} + +/// Iterator adaptors provided for every `Iterator` implementation. The adaptor objects are also +/// implementations of the `Iterator` trait. +/// +/// In the future these will be default methods instead of a utility trait. +pub trait IteratorUtil { + /// Chan this iterator with another, returning a new iterator which will + /// finish iterating over the current iterator, and then it will iterate + /// over the other specified iterator. + /// + /// # Example + /// + /// ~~~ {.rust} + /// use std::iterator::*; + /// + /// let a = [0]; + /// let b = [1]; + /// let mut it = a.iter().chain(b.iter()); + /// assert_eq!(it.next().get(), &0); + /// assert_eq!(it.next().get(), &1); + /// assert!(it.next().is_none()); + /// ~~~ + fn chain>(self, other: U) -> ChainIterator; + + /// Creates an iterator which iterates over both this and the specified + /// iterators simultaneously, yielding the two elements as pairs. When + /// either iterator returns None, all further invocations of next() will + /// return None. + /// + /// # Example + /// + /// ~~~ {.rust} + /// use std::iterator::*; + /// + /// let a = [0]; + /// let b = [1]; + /// let mut it = a.iter().zip(b.iter()); + /// assert_eq!(it.next().get(), (&0, &1)); + /// assert!(it.next().is_none()); + /// ~~~ + fn zip>(self, other: U) -> ZipIterator; + + // FIXME: #5898: should be called map + /// Creates a new iterator which will apply the specified function to each + /// element returned by the first, yielding the mapped element instead. This + /// similar to the `vec::map` function. + /// + /// # Example + /// + /// ~~~ {.rust} + /// use std::iterator::*; + /// + /// let a = [1, 2]; + /// let mut it = a.iter().transform(|&x| 2 * x); + /// assert_eq!(it.next().get(), 2); + /// assert_eq!(it.next().get(), 4); + /// assert!(it.next().is_none()); + /// ~~~ + fn transform<'r, B>(self, f: &'r fn(A) -> B) -> MapIterator<'r, A, B, Self>; + + /// Creates an iterator which applies the predicate to each element returned + /// by this iterator. Only elements which have the predicate evaluate to + /// `true` will be yielded. + /// + /// # Example + /// + /// ~~~ {.rust} + /// use std::iterator::*; + /// + /// let a = [1, 2]; + /// let mut it = a.iter().filter(|&x| *x > 1); + /// assert_eq!(it.next().get(), &2); + /// assert!(it.next().is_none()); + /// ~~~ + fn filter<'r>(self, predicate: &'r fn(&A) -> bool) -> FilterIterator<'r, A, Self>; + + /// Creates an iterator which both filters and maps elements at the same + /// If the specified function returns None, the element is skipped. + /// Otherwise the option is unwrapped and the new value is yielded. + /// + /// # Example + /// + /// ~~~ {.rust} + /// use std::iterator::*; + /// + /// let a = [1, 2]; + /// let mut it = a.iter().filter_map(|&x| if x > 1 {Some(2 * x)} else {None}); + /// assert_eq!(it.next().get(), 4); + /// assert!(it.next().is_none()); + /// ~~~ + fn filter_map<'r, B>(self, f: &'r fn(A) -> Option) -> FilterMapIterator<'r, A, B, Self>; + + /// Creates an iterator which yields a pair of the value returned by this + /// iterator plus the current index of iteration. + /// + /// # Example + /// + /// ~~~ {.rust} + /// use std::iterator::*; + /// + /// let a = [100, 200]; + /// let mut it = a.iter().enumerate(); + /// assert_eq!(it.next().get(), (0, &100)); + /// assert_eq!(it.next().get(), (1, &200)); + /// assert!(it.next().is_none()); + /// ~~~ + fn enumerate(self) -> EnumerateIterator; + + /// Creates an iterator which invokes the predicate on elements until it + /// returns true. Once the predicate returns true, all further elements are + /// yielded. + /// + /// # Example + /// + /// ~~~ {.rust} + /// use std::iterator::*; + /// + /// let a = [1, 2, 3, 2, 1]; + /// let mut it = a.iter().skip_while(|&a| *a < 3); + /// assert_eq!(it.next().get(), &3); + /// assert_eq!(it.next().get(), &2); + /// assert_eq!(it.next().get(), &1); + /// assert!(it.next().is_none()); + /// ~~~ + fn skip_while<'r>(self, predicate: &'r fn(&A) -> bool) -> SkipWhileIterator<'r, A, Self>; + + /// Creates an iterator which yields elements so long as the predicate + /// returns true. After the predicate returns false for the first time, no + /// further elements will be yielded. + /// + /// # Example + /// + /// ~~~ {.rust} + /// use std::iterator::*; + /// + /// let a = [1, 2, 3, 2, 1]; + /// let mut it = a.iter().take_while(|&a| *a < 3); + /// assert_eq!(it.next().get(), &1); + /// assert_eq!(it.next().get(), &2); + /// assert!(it.next().is_none()); + /// ~~~ + fn take_while<'r>(self, predicate: &'r fn(&A) -> bool) -> TakeWhileIterator<'r, A, Self>; + + /// Creates an iterator which skips the first `n` elements of this iterator, + /// and then it yields all further items. + /// + /// # Example + /// + /// ~~~ {.rust} + /// use std::iterator::*; + /// + /// let a = [1, 2, 3, 4, 5]; + /// let mut it = a.iter().skip(3); + /// assert_eq!(it.next().get(), &4); + /// assert_eq!(it.next().get(), &5); + /// assert!(it.next().is_none()); + /// ~~~ + fn skip(self, n: uint) -> SkipIterator; + + /// Creates an iterator which yields the first `n` elements of this + /// iterator, and then it will always return None. + /// + /// # Example + /// + /// ~~~ {.rust} + /// use std::iterator::*; + /// + /// let a = [1, 2, 3, 4, 5]; + /// let mut it = a.iter().take(3); + /// assert_eq!(it.next().get(), &1); + /// assert_eq!(it.next().get(), &2); + /// assert_eq!(it.next().get(), &3); + /// assert!(it.next().is_none()); + /// ~~~ + fn take(self, n: uint) -> TakeIterator; + + /// Creates a new iterator which behaves in a similar fashion to foldl. + /// There is a state which is passed between each iteration and can be + /// mutated as necessary. The yielded values from the closure are yielded + /// from the ScanIterator instance when not None. + /// + /// # Example + /// + /// ~~~ {.rust} + /// use std::iterator::*; + /// + /// let a = [1, 2, 3, 4, 5]; + /// let mut it = a.iter().scan(1, |fac, &x| { + /// *fac = *fac * x; + /// Some(*fac) + /// }); + /// assert_eq!(it.next().get(), 1); + /// assert_eq!(it.next().get(), 2); + /// assert_eq!(it.next().get(), 6); + /// assert_eq!(it.next().get(), 24); + /// assert_eq!(it.next().get(), 120); + /// assert!(it.next().is_none()); + /// ~~~ + fn scan<'r, St, B>(self, initial_state: St, f: &'r fn(&mut St, A) -> Option) + -> ScanIterator<'r, A, B, Self, St>; + + /// An adaptation of an external iterator to the for-loop protocol of rust. + /// + /// # Example + /// + /// ~~~ {.rust} + /// for Counter::new(0, 10).advance |i| { + /// io::println(fmt!("%d", i)); + /// } + /// ~~~ + fn advance(&mut self, f: &fn(A) -> bool) -> bool; + + /// Loops through the entire iterator, accumulating all of the elements into + /// a vector. + /// + /// # Example + /// + /// ~~~ {.rust} + /// use std::iterator::*; + /// + /// let a = [1, 2, 3, 4, 5]; + /// let b = a.iter().transform(|&x| x).to_vec(); + /// assert!(a == b); + /// ~~~ + fn to_vec(&mut self) -> ~[A]; + + /// Loops through `n` iterations, returning the `n`th element of the + /// iterator. + /// + /// # Example + /// + /// ~~~ {.rust} + /// use std::iterator::*; + /// + /// let a = [1, 2, 3, 4, 5]; + /// let mut it = a.iter(); + /// assert!(it.nth(2).get() == &3); + /// assert!(it.nth(2) == None); + /// ~~~ + fn nth(&mut self, n: uint) -> Option; + + /// Loops through the entire iterator, returning the last element of the + /// iterator. + /// + /// # Example + /// + /// ~~~ {.rust} + /// use std::iterator::*; + /// + /// let a = [1, 2, 3, 4, 5]; + /// assert!(a.iter().last().get() == &5); + /// ~~~ + fn last(&mut self) -> Option; + + /// Performs a fold operation over the entire iterator, returning the + /// eventual state at the end of the iteration. + /// + /// # Example + /// + /// ~~~ {.rust} + /// use std::iterator::*; + /// + /// let a = [1, 2, 3, 4, 5]; + /// assert!(a.iter().fold(0, |a, &b| a + b) == 15); + /// ~~~ + fn fold(&mut self, start: B, f: &fn(B, A) -> B) -> B; + + /// Counts the number of elements in this iterator. + /// + /// # Example + /// + /// ~~~ {.rust} + /// use std::iterator::*; + /// + /// let a = [1, 2, 3, 4, 5]; + /// let mut it = a.iter(); + /// assert!(it.count() == 5); + /// assert!(it.count() == 0); + /// ~~~ + fn count(&mut self) -> uint; + + /// Tests whether the predicate holds true for all elements in the iterator. + /// + /// # Example + /// + /// ~~~ {.rust} + /// use std::iterator::*; + /// + /// let a = [1, 2, 3, 4, 5]; + /// assert!(a.iter().all(|&x| *x > 0)); + /// assert!(!a.iter().all(|&x| *x > 2)); + /// ~~~ + fn all(&mut self, f: &fn(&A) -> bool) -> bool; + + /// Tests whether any element of an iterator satisfies the specified + /// predicate. + /// + /// # Example + /// + /// ~~~ {.rust} + /// use std::iterator::*; + /// + /// let a = [1, 2, 3, 4, 5]; + /// let mut it = a.iter(); + /// assert!(it.any(|&x| *x == 3)); + /// assert!(!it.any(|&x| *x == 3)); + /// ~~~ + fn any(&mut self, f: &fn(&A) -> bool) -> bool; +} + +/// Iterator adaptors provided for every `Iterator` implementation. The adaptor objects are also +/// implementations of the `Iterator` trait. +/// +/// In the future these will be default methods instead of a utility trait. +impl> IteratorUtil for T { + #[inline(always)] + fn chain>(self, other: U) -> ChainIterator { + ChainIterator{a: self, b: other, flag: false} + } + + #[inline(always)] + fn zip>(self, other: U) -> ZipIterator { + ZipIterator{a: self, b: other} + } + + // FIXME: #5898: should be called map + #[inline(always)] + fn transform<'r, B>(self, f: &'r fn(A) -> B) -> MapIterator<'r, A, B, T> { + MapIterator{iter: self, f: f} + } + + #[inline(always)] + fn filter<'r>(self, predicate: &'r fn(&A) -> bool) -> FilterIterator<'r, A, T> { + FilterIterator{iter: self, predicate: predicate} + } + + #[inline(always)] + fn filter_map<'r, B>(self, f: &'r fn(A) -> Option) -> FilterMapIterator<'r, A, B, T> { + FilterMapIterator { iter: self, f: f } + } + + #[inline(always)] + fn enumerate(self) -> EnumerateIterator { + EnumerateIterator{iter: self, count: 0} + } + + #[inline(always)] + fn skip_while<'r>(self, predicate: &'r fn(&A) -> bool) -> SkipWhileIterator<'r, A, T> { + SkipWhileIterator{iter: self, flag: false, predicate: predicate} + } + + #[inline(always)] + fn take_while<'r>(self, predicate: &'r fn(&A) -> bool) -> TakeWhileIterator<'r, A, T> { + TakeWhileIterator{iter: self, flag: false, predicate: predicate} + } + + #[inline(always)] + fn skip(self, n: uint) -> SkipIterator { + SkipIterator{iter: self, n: n} + } + + #[inline(always)] + fn take(self, n: uint) -> TakeIterator { + TakeIterator{iter: self, n: n} + } + + #[inline(always)] + fn scan<'r, St, B>(self, initial_state: St, f: &'r fn(&mut St, A) -> Option) + -> ScanIterator<'r, A, B, T, St> { + ScanIterator{iter: self, f: f, state: initial_state} + } + + /// A shim implementing the `for` loop iteration protocol for iterator objects + #[inline] + fn advance(&mut self, f: &fn(A) -> bool) -> bool { + loop { + match self.next() { + Some(x) => { + if !f(x) { return false; } + } + None => { return true; } + } + } + } + + #[inline(always)] + fn to_vec(&mut self) -> ~[A] { + iter::to_vec::(|f| self.advance(f)) + } + + /// Return the `n`th item yielded by an iterator. + #[inline(always)] + fn nth(&mut self, mut n: uint) -> Option { + loop { + match self.next() { + Some(x) => if n == 0 { return Some(x) }, + None => return None + } + n -= 1; + } + } + + /// Return the last item yielded by an iterator. + #[inline(always)] + fn last(&mut self) -> Option { + let mut last = None; + for self.advance |x| { last = Some(x); } + last + } + + /// Reduce an iterator to an accumulated value + #[inline] + fn fold(&mut self, init: B, f: &fn(B, A) -> B) -> B { + let mut accum = init; + loop { + match self.next() { + Some(x) => { accum = f(accum, x); } + None => { break; } + } + } + return accum; + } + + /// Count the number of items yielded by an iterator + #[inline(always)] + fn count(&mut self) -> uint { self.fold(0, |cnt, _x| cnt + 1) } + + #[inline(always)] + fn all(&mut self, f: &fn(&A) -> bool) -> bool { + for self.advance |x| { if !f(&x) { return false; } } + return true; + } + + #[inline(always)] + fn any(&mut self, f: &fn(&A) -> bool) -> bool { + for self.advance |x| { if f(&x) { return true; } } + return false; + } +} + +/// A trait for iterators over elements which can be added together +pub trait AdditiveIterator { + /// Iterates over the entire iterator, summing up all the elements + /// + /// # Example + /// + /// ~~~ {.rust} + /// use std::iterator::*; + /// + /// let a = [1, 2, 3, 4, 5]; + /// let mut it = a.iter().transform(|&x| x); + /// assert!(it.sum() == 15); + /// ~~~ + fn sum(&mut self) -> A; +} + +impl + Zero, T: Iterator> AdditiveIterator for T { + #[inline(always)] + fn sum(&mut self) -> A { self.fold(Zero::zero::(), |s, x| s + x) } +} + +/// A trait for iterators over elements whose elements can be multiplied +/// together. +pub trait MultiplicativeIterator { + /// Iterates over the entire iterator, multiplying all the elements + /// + /// # Example + /// + /// ~~~ {.rust} + /// use std::iterator::*; + /// + /// fn factorial(n: uint) -> uint { + /// Counter::new(1u, 1).take_while(|&i| i <= n).product() + /// } + /// assert!(factorial(0) == 1); + /// assert!(factorial(1) == 1); + /// assert!(factorial(5) == 120); + /// ~~~ + fn product(&mut self) -> A; +} + +impl + One, T: Iterator> MultiplicativeIterator for T { + #[inline(always)] + fn product(&mut self) -> A { self.fold(One::one::(), |p, x| p * x) } +} + +/// A trait for iterators over elements which can be compared to one another. +/// The type of each element must ascribe to the `Ord` trait. +pub trait OrdIterator { + /// Consumes the entire iterator to return the maximum element. + /// + /// # Example + /// + /// ~~~ {.rust} + /// use std::iterator::*; + /// + /// let a = [1, 2, 3, 4, 5]; + /// assert!(a.iter().max().get() == &5); + /// ~~~ + fn max(&mut self) -> Option; + + /// Consumes the entire iterator to return the minimum element. + /// + /// # Example + /// + /// ~~~ {.rust} + /// use std::iterator::*; + /// + /// let a = [1, 2, 3, 4, 5]; + /// assert!(a.iter().min().get() == &1); + /// ~~~ + fn min(&mut self) -> Option; +} + +impl> OrdIterator for T { + #[inline(always)] + fn max(&mut self) -> Option { + self.fold(None, |max, x| { + match max { + None => Some(x), + Some(y) => Some(cmp::max(x, y)) + } + }) + } + + #[inline(always)] + fn min(&mut self) -> Option { + self.fold(None, |min, x| { + match min { + None => Some(x), + Some(y) => Some(cmp::min(x, y)) + } + }) + } +} + +/// An iterator which strings two iterators together +pub struct ChainIterator { + priv a: T, + priv b: U, + priv flag: bool +} + +impl, U: Iterator> Iterator for ChainIterator { + #[inline] + fn next(&mut self) -> Option { + if self.flag { + self.b.next() + } else { + match self.a.next() { + Some(x) => return Some(x), + _ => () + } + self.flag = true; + self.b.next() + } + } +} + +/// An iterator which iterates two other iterators simultaneously +pub struct ZipIterator { + priv a: T, + priv b: U +} + +impl, U: Iterator> Iterator<(A, B)> for ZipIterator { + #[inline] + fn next(&mut self) -> Option<(A, B)> { + match (self.a.next(), self.b.next()) { + (Some(x), Some(y)) => Some((x, y)), + _ => None + } + } +} + +/// An iterator which maps the values of `iter` with `f` +pub struct MapIterator<'self, A, B, T> { + priv iter: T, + priv f: &'self fn(A) -> B +} + +impl<'self, A, B, T: Iterator> Iterator for MapIterator<'self, A, B, T> { + #[inline] + fn next(&mut self) -> Option { + match self.iter.next() { + Some(a) => Some((self.f)(a)), + _ => None + } + } +} + +/// An iterator which filters the elements of `iter` with `predicate` +pub struct FilterIterator<'self, A, T> { + priv iter: T, + priv predicate: &'self fn(&A) -> bool +} + +impl<'self, A, T: Iterator> Iterator for FilterIterator<'self, A, T> { + #[inline] + fn next(&mut self) -> Option { + for self.iter.advance |x| { + if (self.predicate)(&x) { + return Some(x); + } else { + loop + } + } + None + } +} + +/// An iterator which uses `f` to both filter and map elements from `iter` +pub struct FilterMapIterator<'self, A, B, T> { + priv iter: T, + priv f: &'self fn(A) -> Option +} + +impl<'self, A, B, T: Iterator> Iterator for FilterMapIterator<'self, A, B, T> { + #[inline] + fn next(&mut self) -> Option { + for self.iter.advance |x| { + match (self.f)(x) { + Some(y) => return Some(y), + None => () + } + } + None + } +} + +/// An iterator which yields the current count and the element during iteration +pub struct EnumerateIterator { + priv iter: T, + priv count: uint +} + +impl> Iterator<(uint, A)> for EnumerateIterator { + #[inline] + fn next(&mut self) -> Option<(uint, A)> { + match self.iter.next() { + Some(a) => { + let ret = Some((self.count, a)); + self.count += 1; + ret + } + _ => None + } + } +} + +/// An iterator which rejects elements while `predicate` is true +pub struct SkipWhileIterator<'self, A, T> { + priv iter: T, + priv flag: bool, + priv predicate: &'self fn(&A) -> bool +} + +impl<'self, A, T: Iterator> Iterator for SkipWhileIterator<'self, A, T> { + #[inline] + fn next(&mut self) -> Option { + let mut next = self.iter.next(); + if self.flag { + next + } else { + loop { + match next { + Some(x) => { + if (self.predicate)(&x) { + next = self.iter.next(); + loop + } else { + self.flag = true; + return Some(x) + } + } + None => return None + } + } + } + } +} + +/// An iterator which only accepts elements while `predicate` is true +pub struct TakeWhileIterator<'self, A, T> { + priv iter: T, + priv flag: bool, + priv predicate: &'self fn(&A) -> bool +} + +impl<'self, A, T: Iterator> Iterator for TakeWhileIterator<'self, A, T> { + #[inline] + fn next(&mut self) -> Option { + if self.flag { + None + } else { + match self.iter.next() { + Some(x) => { + if (self.predicate)(&x) { + Some(x) + } else { + self.flag = true; + None + } + } + None => None + } + } + } +} + +/// An iterator which skips over `n` elements of `iter` +pub struct SkipIterator { + priv iter: T, + priv n: uint +} + +impl> Iterator for SkipIterator { + #[inline] + fn next(&mut self) -> Option { + let mut next = self.iter.next(); + if self.n == 0 { + next + } else { + let n = self.n; + for n.times { + match next { + Some(_) => { + next = self.iter.next(); + loop + } + None => { + self.n = 0; + return None + } + } + } + self.n = 0; + next + } + } +} + +/// An iterator which only iterates over the first `n` iterations of `iter`. +pub struct TakeIterator { + priv iter: T, + priv n: uint +} + +impl> Iterator for TakeIterator { + #[inline] + fn next(&mut self) -> Option { + let next = self.iter.next(); + if self.n != 0 { + self.n -= 1; + next + } else { + None + } + } +} + +/// An iterator to maintain state while iterating another iterator +pub struct ScanIterator<'self, A, B, T, St> { + priv iter: T, + priv f: &'self fn(&mut St, A) -> Option, + + /// The current internal state to be passed to the closure next. + state: St +} + +impl<'self, A, B, T: Iterator, St> Iterator for ScanIterator<'self, A, B, T, St> { + #[inline] + fn next(&mut self) -> Option { + self.iter.next().chain(|a| (self.f)(&mut self.state, a)) + } +} + +/// An iterator which just modifies the contained state throughout iteration. +pub struct UnfoldrIterator<'self, A, St> { + priv f: &'self fn(&mut St) -> Option, + /// Internal state that will be yielded on the next iteration + state: St +} + +impl<'self, A, St> UnfoldrIterator<'self, A, St> { + /// Creates a new iterator with the specified closure as the "iterator + /// function" and an initial state to eventually pass to the iterator + #[inline] + pub fn new(f: &'self fn(&mut St) -> Option, initial_state: St) + -> UnfoldrIterator<'self, A, St> { + UnfoldrIterator { + f: f, + state: initial_state + } + } +} + +impl<'self, A, St> Iterator for UnfoldrIterator<'self, A, St> { + #[inline] + fn next(&mut self) -> Option { + (self.f)(&mut self.state) + } +} + +/// An infinite iterator starting at `start` and advancing by `step` with each +/// iteration +pub struct Counter { + /// The current state the counter is at (next value to be yielded) + state: A, + /// The amount that this iterator is stepping by + step: A +} + +impl Counter { + /// Creates a new counter with the specified start/step + #[inline(always)] + pub fn new(start: A, step: A) -> Counter { + Counter{state: start, step: step} + } +} + +impl + Clone> Iterator for Counter { + #[inline(always)] + fn next(&mut self) -> Option { + let result = self.state.clone(); + self.state = self.state.add(&self.step); // FIXME: #6050 + Some(result) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use prelude::*; + + use iter; + use uint; + + #[test] + fn test_counter_to_vec() { + let mut it = Counter::new(0, 5).take(10); + let xs = iter::to_vec(|f| it.advance(f)); + assert_eq!(xs, ~[0, 5, 10, 15, 20, 25, 30, 35, 40, 45]); + } + + #[test] + fn test_iterator_chain() { + let xs = [0u, 1, 2, 3, 4, 5]; + let ys = [30u, 40, 50, 60]; + let expected = [0, 1, 2, 3, 4, 5, 30, 40, 50, 60]; + let mut it = xs.iter().chain(ys.iter()); + let mut i = 0; + for it.advance |&x: &uint| { + assert_eq!(x, expected[i]); + i += 1; + } + assert_eq!(i, expected.len()); + + let ys = Counter::new(30u, 10).take(4); + let mut it = xs.iter().transform(|&x| x).chain(ys); + let mut i = 0; + for it.advance |x: uint| { + assert_eq!(x, expected[i]); + i += 1; + } + assert_eq!(i, expected.len()); + } + + #[test] + fn test_filter_map() { + let mut it = Counter::new(0u, 1u).take(10) + .filter_map(|x: uint| if x.is_even() { Some(x*x) } else { None }); + assert_eq!(it.to_vec(), ~[0*0, 2*2, 4*4, 6*6, 8*8]); + } + + #[test] + fn test_iterator_enumerate() { + let xs = [0u, 1, 2, 3, 4, 5]; + let mut it = xs.iter().enumerate(); + for it.advance |(i, &x): (uint, &uint)| { + assert_eq!(i, x); + } + } + + #[test] + fn test_iterator_take_while() { + let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19]; + let ys = [0u, 1, 2, 3, 5, 13]; + let mut it = xs.iter().take_while(|&x| *x < 15u); + let mut i = 0; + for it.advance |&x: &uint| { + assert_eq!(x, ys[i]); + i += 1; + } + assert_eq!(i, ys.len()); + } + + #[test] + fn test_iterator_skip_while() { + let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19]; + let ys = [15, 16, 17, 19]; + let mut it = xs.iter().skip_while(|&x| *x < 15u); + let mut i = 0; + for it.advance |&x: &uint| { + assert_eq!(x, ys[i]); + i += 1; + } + assert_eq!(i, ys.len()); + } + + #[test] + fn test_iterator_skip() { + let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30]; + let ys = [13, 15, 16, 17, 19, 20, 30]; + let mut it = xs.iter().skip(5); + let mut i = 0; + for it.advance |&x: &uint| { + assert_eq!(x, ys[i]); + i += 1; + } + assert_eq!(i, ys.len()); + } + + #[test] + fn test_iterator_take() { + let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19]; + let ys = [0u, 1, 2, 3, 5]; + let mut it = xs.iter().take(5); + let mut i = 0; + for it.advance |&x: &uint| { + assert_eq!(x, ys[i]); + i += 1; + } + assert_eq!(i, ys.len()); + } + + #[test] + fn test_iterator_scan() { + // test the type inference + fn add(old: &mut int, new: &uint) -> Option { + *old += *new as int; + Some(*old as float) + } + let xs = [0u, 1, 2, 3, 4]; + let ys = [0f, 1f, 3f, 6f, 10f]; + + let mut it = xs.iter().scan(0, add); + let mut i = 0; + for it.advance |x| { + assert_eq!(x, ys[i]); + i += 1; + } + assert_eq!(i, ys.len()); + } + + #[test] + fn test_unfoldr() { + fn count(st: &mut uint) -> Option { + if *st < 10 { + let ret = Some(*st); + *st += 1; + ret + } else { + None + } + } + + let mut it = UnfoldrIterator::new(count, 0); + let mut i = 0; + for it.advance |counted| { + assert_eq!(counted, i); + i += 1; + } + assert_eq!(i, 10); + } + + #[test] + fn test_iterator_nth() { + let v = &[0, 1, 2, 3, 4]; + for uint::range(0, v.len()) |i| { + assert_eq!(v.iter().nth(i).unwrap(), &v[i]); + } + } + + #[test] + fn test_iterator_last() { + let v = &[0, 1, 2, 3, 4]; + assert_eq!(v.iter().last().unwrap(), &4); + assert_eq!(v.slice(0, 1).iter().last().unwrap(), &0); + } + + #[test] + fn test_iterator_count() { + let v = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + assert_eq!(v.slice(0, 4).iter().count(), 4); + assert_eq!(v.slice(0, 10).iter().count(), 10); + assert_eq!(v.slice(0, 0).iter().count(), 0); + } + + #[test] + fn test_iterator_sum() { + let v = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + assert_eq!(v.slice(0, 4).iter().transform(|&x| x).sum(), 6); + assert_eq!(v.iter().transform(|&x| x).sum(), 55); + assert_eq!(v.slice(0, 0).iter().transform(|&x| x).sum(), 0); + } + + #[test] + fn test_iterator_product() { + let v = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + assert_eq!(v.slice(0, 4).iter().transform(|&x| x).product(), 0); + assert_eq!(v.slice(1, 5).iter().transform(|&x| x).product(), 24); + assert_eq!(v.slice(0, 0).iter().transform(|&x| x).product(), 1); + } + + #[test] + fn test_iterator_max() { + let v = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + assert_eq!(v.slice(0, 4).iter().transform(|&x| x).max(), Some(3)); + assert_eq!(v.iter().transform(|&x| x).max(), Some(10)); + assert_eq!(v.slice(0, 0).iter().transform(|&x| x).max(), None); + } + + #[test] + fn test_iterator_min() { + let v = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + assert_eq!(v.slice(0, 4).iter().transform(|&x| x).min(), Some(0)); + assert_eq!(v.iter().transform(|&x| x).min(), Some(0)); + assert_eq!(v.slice(0, 0).iter().transform(|&x| x).min(), None); + } + + #[test] + fn test_all() { + let v = ~&[1, 2, 3, 4, 5]; + assert!(v.iter().all(|&x| *x < 10)); + assert!(!v.iter().all(|&x| x.is_even())); + assert!(!v.iter().all(|&x| *x > 100)); + assert!(v.slice(0, 0).iter().all(|_| fail!())); + } + + #[test] + fn test_any() { + let v = ~&[1, 2, 3, 4, 5]; + assert!(v.iter().any(|&x| *x < 10)); + assert!(v.iter().any(|&x| x.is_even())); + assert!(!v.iter().any(|&x| *x > 100)); + assert!(!v.slice(0, 0).iter().any(|_| fail!())); + } +} diff --git a/src/libcore/kinds.rs b/src/libstd/kinds.rs similarity index 96% rename from src/libcore/kinds.rs rename to src/libstd/kinds.rs index eeafc4cf786a5..05c963a32cc73 100644 --- a/src/libcore/kinds.rs +++ b/src/libstd/kinds.rs @@ -37,6 +37,8 @@ instead implement `Clone`. */ +#[allow(missing_doc)]; + #[lang="copy"] pub trait Copy { // Empty. @@ -52,8 +54,7 @@ pub trait Const { // Empty. } -#[lang="durable"] -#[cfg(stage0)] -pub trait Durable { +#[lang="sized"] +pub trait Sized { // Empty. } diff --git a/src/libcore/libc.rs b/src/libstd/libc.rs similarity index 99% rename from src/libcore/libc.rs rename to src/libstd/libc.rs index 7ae3f0fd2d462..142b2f7d6af58 100644 --- a/src/libcore/libc.rs +++ b/src/libstd/libc.rs @@ -64,6 +64,7 @@ */ #[allow(non_camel_case_types)]; +#[allow(missing_doc)]; // Initial glob-exports mean that all the contents of all the modules // wind up exported, if you're interested in writing platform-specific code. diff --git a/src/libcore/local_data.rs b/src/libstd/local_data.rs similarity index 98% rename from src/libcore/local_data.rs rename to src/libstd/local_data.rs index 2cbf8b9f05ef8..82c01c998cf1e 100644 --- a/src/libcore/local_data.rs +++ b/src/libstd/local_data.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -27,8 +27,11 @@ magic. */ use prelude::*; + use task::local_data_priv::{local_get, local_pop, local_modify, local_set, Handle}; +#[cfg(test)] use task; + /** * Indexes a task-local data slot. The function's code pointer is used for * comparison. Recommended use is to write an empty function for each desired diff --git a/src/libcore/logging.rs b/src/libstd/logging.rs similarity index 59% rename from src/libcore/logging.rs rename to src/libstd/logging.rs index cea827298af06..c2f854179b8dd 100644 --- a/src/libcore/logging.rs +++ b/src/libstd/logging.rs @@ -10,17 +10,9 @@ //! Logging -pub mod rustrt { - use libc; - - pub extern { - unsafe fn rust_log_console_on(); - unsafe fn rust_log_console_off(); - unsafe fn rust_log_str(level: u32, - string: *libc::c_char, - size: libc::size_t); - } -} +use option::*; +use either::*; +use rt::logging::{Logger, StdErrLogger}; /// Turns on logging to stdout globally pub fn console_on() { @@ -44,19 +36,63 @@ pub fn console_off() { #[cfg(not(test))] #[lang="log_type"] +#[allow(missing_doc)] pub fn log_type(level: u32, object: &T) { + use cast; use container::Container; - use cast::transmute; use io; use libc; use repr; + use rt; + use str; use vec; let bytes = do io::with_bytes_writer |writer| { repr::write_repr(writer, object); }; + + match rt::context() { + rt::OldTaskContext => { + unsafe { + let len = bytes.len() as libc::size_t; + rustrt::rust_log_str(level, cast::transmute(vec::raw::to_ptr(bytes)), len); + } + } + _ => { + // XXX: Bad allocation + let msg = str::from_bytes(bytes); + newsched_log_str(msg); + } + } +} + +fn newsched_log_str(msg: ~str) { + use rt::task::Task; + use rt::local::Local; + unsafe { - let len = bytes.len() as libc::size_t; - rustrt::rust_log_str(level, transmute(vec::raw::to_ptr(bytes)), len); + match Local::try_unsafe_borrow::() { + Some(local) => { + // Use the available logger + (*local).logger.log(Left(msg)); + } + None => { + // There is no logger anywhere, just write to stderr + let mut logger = StdErrLogger; + logger.log(Left(msg)); + } + } + } +} + +pub mod rustrt { + use libc; + + pub extern { + unsafe fn rust_log_console_on(); + unsafe fn rust_log_console_off(); + unsafe fn rust_log_str(level: u32, + string: *libc::c_char, + size: libc::size_t); } } diff --git a/src/libcore/macros.rs b/src/libstd/macros.rs similarity index 72% rename from src/libcore/macros.rs rename to src/libstd/macros.rs index b19a753b71577..fda48b6ffb7d9 100644 --- a/src/libcore/macros.rs +++ b/src/libstd/macros.rs @@ -30,10 +30,24 @@ macro_rules! rtdebug ( ($( $arg:expr),+) => ( $(let _ = $arg)*; ) ) +macro_rules! rtassert ( + ( $arg:expr ) => ( { + if !$arg { + abort!("assertion failed: %s", stringify!($arg)); + } + } ) +) + macro_rules! abort( ($( $msg:expr),+) => ( { rtdebug!($($msg),+); - unsafe { ::libc::abort(); } + do_abort(); + + // NB: This is in a fn to avoid putting the `unsafe` block in a macro, + // which causes spurious 'unnecessary unsafe block' warnings. + fn do_abort() -> ! { + unsafe { ::libc::abort(); } + } } ) ) diff --git a/src/libcore/managed.rs b/src/libstd/managed.rs similarity index 88% rename from src/libcore/managed.rs rename to src/libstd/managed.rs index d2bb88ca30202..7d0defea05ace 100644 --- a/src/libcore/managed.rs +++ b/src/libstd/managed.rs @@ -21,6 +21,7 @@ pub mod raw { pub static RC_MANAGED_UNIQUE : uint = (-2) as uint; pub static RC_IMMORTAL : uint = 0x77777777; + #[allow(missing_doc)] pub struct BoxHeaderRepr { ref_count: uint, type_desc: *TyDesc, @@ -28,6 +29,7 @@ pub mod raw { next: *BoxRepr, } + #[allow(missing_doc)] pub struct BoxRepr { header: BoxHeaderRepr, data: u8 @@ -35,17 +37,17 @@ pub mod raw { } +/// Determine if two shared boxes point to the same object #[inline(always)] pub fn ptr_eq(a: @T, b: @T) -> bool { - //! Determine if two shared boxes point to the same object - let a_ptr: *T = to_unsafe_ptr(&*a), b_ptr: *T = to_unsafe_ptr(&*b); + let (a_ptr, b_ptr): (*T, *T) = (to_unsafe_ptr(&*a), to_unsafe_ptr(&*b)); a_ptr == b_ptr } +/// Determine if two mutable shared boxes point to the same object #[inline(always)] pub fn mut_ptr_eq(a: @mut T, b: @mut T) -> bool { - //! Determine if two mutable shared boxes point to the same object - let a_ptr: *T = to_unsafe_ptr(&*a), b_ptr: *T = to_unsafe_ptr(&*b); + let (a_ptr, b_ptr): (*T, *T) = (to_unsafe_ptr(&*a), to_unsafe_ptr(&*b)); a_ptr == b_ptr } diff --git a/src/libcore/nil.rs b/src/libstd/nil.rs similarity index 100% rename from src/libcore/nil.rs rename to src/libstd/nil.rs diff --git a/src/libcore/num/cmath.rs b/src/libstd/num/cmath.rs similarity index 99% rename from src/libcore/num/cmath.rs rename to src/libstd/num/cmath.rs index a80703fafa3d2..96d3b79e33850 100644 --- a/src/libcore/num/cmath.rs +++ b/src/libstd/num/cmath.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[doc(hidden)]; // FIXME #3538 +#[allow(missing_doc)]; // function names are almost identical to C's libmath, a few have been // renamed, grep for "rename:" diff --git a/src/libcore/num/f32.rs b/src/libstd/num/f32.rs similarity index 98% rename from src/libcore/num/f32.rs rename to src/libstd/num/f32.rs index 4a3ec3528f28b..62ce5ed65e10c 100644 --- a/src/libcore/num/f32.rs +++ b/src/libstd/num/f32.rs @@ -9,11 +9,14 @@ // except according to those terms. //! Operations and constants for `f32` +#[allow(missing_doc)]; use libc::c_int; use num::{Zero, One, strconv}; use num::{FPCategory, FPNaN, FPInfinite , FPZero, FPSubnormal, FPNormal}; +use num; use prelude::*; +use to_str; pub use cmath::c_float_targ_consts::*; @@ -86,8 +89,6 @@ delegate!( fn erfc(n: c_float) -> c_float = c_float_utils::erfc, fn exp_m1(n: c_float) -> c_float = c_float_utils::exp_m1, fn abs_sub(a: c_float, b: c_float) -> c_float = c_float_utils::abs_sub, - fn fmax(a: c_float, b: c_float) -> c_float = c_float_utils::fmax, - fn fmin(a: c_float, b: c_float) -> c_float = c_float_utils::fmin, fn next_after(x: c_float, y: c_float) -> c_float = c_float_utils::next_after, fn frexp(n: c_float, value: &mut c_int) -> c_float = c_float_utils::frexp, fn hypot(x: c_float, y: c_float) -> c_float = c_float_utils::hypot, @@ -147,6 +148,16 @@ pub fn ge(x: f32, y: f32) -> bool { return x >= y; } #[inline(always)] pub fn gt(x: f32, y: f32) -> bool { return x > y; } +#[inline(always)] +pub fn fmax(x: f32, y: f32) -> f32 { + if x >= y || y.is_NaN() { x } else { y } +} + +#[inline(always)] +pub fn fmin(x: f32, y: f32) -> f32 { + if x <= y || y.is_NaN() { x } else { y } +} + // FIXME (#1999): replace the predicates below with llvm intrinsics or // calls to the libmath macros in the rust runtime for performance. @@ -252,10 +263,12 @@ impl Orderable for f32 { /// If any of the numbers are `NaN` then `NaN` is returned. #[inline(always)] fn clamp(&self, mn: &f32, mx: &f32) -> f32 { - if self.is_NaN() { *self } - else if !(*self <= *mx) { *mx } - else if !(*self >= *mn) { *mn } - else { *self } + cond!( + (self.is_NaN()) { *self } + (!(*self <= *mx)) { *mx } + (!(*self >= *mn)) { *mn } + _ { *self } + ) } } @@ -362,7 +375,7 @@ impl Round for f32 { /// /// The fractional part of the number, satisfying: /// - /// ~~~ + /// ~~~ {.rust} /// assert!(x == trunc(x) + fract(x)) /// ~~~ /// @@ -948,10 +961,12 @@ impl num::FromStrRadix for f32 { #[cfg(test)] mod tests { use f32::*; - use num::*; - use super::*; use prelude::*; + use num::*; + use num; + use sys; + #[test] fn test_num() { num::test_num(10f32, 2f32); diff --git a/src/libcore/num/f64.rs b/src/libstd/num/f64.rs similarity index 98% rename from src/libcore/num/f64.rs rename to src/libstd/num/f64.rs index e370f43a0037e..de44d861645b3 100644 --- a/src/libcore/num/f64.rs +++ b/src/libstd/num/f64.rs @@ -10,10 +10,14 @@ //! Operations and constants for `f64` +#[allow(missing_doc)]; + use libc::c_int; use num::{Zero, One, strconv}; use num::{FPCategory, FPNaN, FPInfinite , FPZero, FPSubnormal, FPNormal}; +use num; use prelude::*; +use to_str; pub use cmath::c_double_targ_consts::*; pub use cmp::{min, max}; @@ -87,8 +91,6 @@ delegate!( fn erfc(n: c_double) -> c_double = c_double_utils::erfc, fn exp_m1(n: c_double) -> c_double = c_double_utils::exp_m1, fn abs_sub(a: c_double, b: c_double) -> c_double = c_double_utils::abs_sub, - fn fmax(a: c_double, b: c_double) -> c_double = c_double_utils::fmax, - fn fmin(a: c_double, b: c_double) -> c_double = c_double_utils::fmin, fn next_after(x: c_double, y: c_double) -> c_double = c_double_utils::next_after, fn frexp(n: c_double, value: &mut c_int) -> c_double = c_double_utils::frexp, fn hypot(x: c_double, y: c_double) -> c_double = c_double_utils::hypot, @@ -172,6 +174,15 @@ pub fn ge(x: f64, y: f64) -> bool { return x >= y; } #[inline(always)] pub fn gt(x: f64, y: f64) -> bool { return x > y; } +#[inline(always)] +pub fn fmax(x: f64, y: f64) -> f64 { + if x >= y || y.is_NaN() { x } else { y } +} + +#[inline(always)] +pub fn fmin(x: f64, y: f64) -> f64 { + if x <= y || y.is_NaN() { x } else { y } +} // FIXME (#1999): add is_normal, is_subnormal, and fpclassify @@ -274,10 +285,12 @@ impl Orderable for f64 { /// If any of the numbers are `NaN` then `NaN` is returned. #[inline(always)] fn clamp(&self, mn: &f64, mx: &f64) -> f64 { - if self.is_NaN() { *self } - else if !(*self <= *mx) { *mx } - else if !(*self >= *mn) { *mn } - else { *self } + cond!( + (self.is_NaN()) { *self } + (!(*self <= *mx)) { *mx } + (!(*self >= *mn)) { *mn } + _ { *self } + ) } } @@ -374,7 +387,7 @@ impl Round for f64 { /// /// The fractional part of the number, satisfying: /// - /// ~~~ + /// ~~~ {.rust} /// assert!(x == trunc(x) + fract(x)) /// ~~~ /// @@ -990,10 +1003,12 @@ impl num::FromStrRadix for f64 { #[cfg(test)] mod tests { use f64::*; - use num::*; - use super::*; use prelude::*; + use num::*; + use num; + use sys; + #[test] fn test_num() { num::test_num(10f64, 2f64); diff --git a/src/libcore/num/float.rs b/src/libstd/num/float.rs similarity index 91% rename from src/libcore/num/float.rs rename to src/libstd/num/float.rs index 681aafaab8884..97d661d8fe2e7 100644 --- a/src/libcore/num/float.rs +++ b/src/libstd/num/float.rs @@ -20,10 +20,15 @@ // PORT this must match in width according to architecture +#[allow(missing_doc)]; + +use f64; use libc::c_int; use num::{Zero, One, strconv}; use num::FPCategory; +use num; use prelude::*; +use to_str; pub use f64::{add, sub, mul, div, rem, lt, le, eq, ne, ge, gt}; pub use f64::{acos, asin, atan2, cbrt, ceil, copysign, cosh, floor}; @@ -43,7 +48,7 @@ pub static neg_infinity: float = -1.0/0.0; pub mod consts { // FIXME (requires Issue #1433 to fix): replace with mathematical // staticants from cmath. - /// Archimedes' staticant + /// Archimedes' constant pub static pi: float = 3.14159265358979323846264338327950288; /// pi/2.0 @@ -454,7 +459,7 @@ impl Round for float { /// /// The fractional part of the number, satisfying: /// - /// ~~~ + /// ~~~ {.rust} /// assert!(x == trunc(x) + fract(x)) /// ~~~ /// @@ -945,10 +950,13 @@ impl Float for float { #[cfg(test)] mod tests { - use num::*; use super::*; use prelude::*; + use num::*; + use num; + use sys; + #[test] fn test_num() { num::test_num(10f, 2f); @@ -1251,101 +1259,101 @@ mod tests { #[test] pub fn test_from_str() { - assert_eq!(from_str(~"3"), Some(3.)); - assert_eq!(from_str(~"3.14"), Some(3.14)); - assert_eq!(from_str(~"+3.14"), Some(3.14)); - assert_eq!(from_str(~"-3.14"), Some(-3.14)); - assert_eq!(from_str(~"2.5E10"), Some(25000000000.)); - assert_eq!(from_str(~"2.5e10"), Some(25000000000.)); - assert_eq!(from_str(~"25000000000.E-10"), Some(2.5)); - assert_eq!(from_str(~"."), Some(0.)); - assert_eq!(from_str(~".e1"), Some(0.)); - assert_eq!(from_str(~".e-1"), Some(0.)); - assert_eq!(from_str(~"5."), Some(5.)); - assert_eq!(from_str(~".5"), Some(0.5)); - assert_eq!(from_str(~"0.5"), Some(0.5)); - assert_eq!(from_str(~"-.5"), Some(-0.5)); - assert_eq!(from_str(~"-5"), Some(-5.)); - assert_eq!(from_str(~"inf"), Some(infinity)); - assert_eq!(from_str(~"+inf"), Some(infinity)); - assert_eq!(from_str(~"-inf"), Some(neg_infinity)); + assert_eq!(from_str("3"), Some(3.)); + assert_eq!(from_str("3.14"), Some(3.14)); + assert_eq!(from_str("+3.14"), Some(3.14)); + assert_eq!(from_str("-3.14"), Some(-3.14)); + assert_eq!(from_str("2.5E10"), Some(25000000000.)); + assert_eq!(from_str("2.5e10"), Some(25000000000.)); + assert_eq!(from_str("25000000000.E-10"), Some(2.5)); + assert_eq!(from_str("."), Some(0.)); + assert_eq!(from_str(".e1"), Some(0.)); + assert_eq!(from_str(".e-1"), Some(0.)); + assert_eq!(from_str("5."), Some(5.)); + assert_eq!(from_str(".5"), Some(0.5)); + assert_eq!(from_str("0.5"), Some(0.5)); + assert_eq!(from_str("-.5"), Some(-0.5)); + assert_eq!(from_str("-5"), Some(-5.)); + assert_eq!(from_str("inf"), Some(infinity)); + assert_eq!(from_str("+inf"), Some(infinity)); + assert_eq!(from_str("-inf"), Some(neg_infinity)); // note: NaN != NaN, hence this slightly complex test - match from_str(~"NaN") { + match from_str("NaN") { Some(f) => assert!(f.is_NaN()), None => fail!() } // note: -0 == 0, hence these slightly more complex tests - match from_str(~"-0") { + match from_str("-0") { Some(v) if v.is_zero() => assert!(v.is_negative()), _ => fail!() } - match from_str(~"0") { + match from_str("0") { Some(v) if v.is_zero() => assert!(v.is_positive()), _ => fail!() } - assert!(from_str(~"").is_none()); - assert!(from_str(~"x").is_none()); - assert!(from_str(~" ").is_none()); - assert!(from_str(~" ").is_none()); - assert!(from_str(~"e").is_none()); - assert!(from_str(~"E").is_none()); - assert!(from_str(~"E1").is_none()); - assert!(from_str(~"1e1e1").is_none()); - assert!(from_str(~"1e1.1").is_none()); - assert!(from_str(~"1e1-1").is_none()); + assert!(from_str("").is_none()); + assert!(from_str("x").is_none()); + assert!(from_str(" ").is_none()); + assert!(from_str(" ").is_none()); + assert!(from_str("e").is_none()); + assert!(from_str("E").is_none()); + assert!(from_str("E1").is_none()); + assert!(from_str("1e1e1").is_none()); + assert!(from_str("1e1.1").is_none()); + assert!(from_str("1e1-1").is_none()); } #[test] pub fn test_from_str_hex() { - assert_eq!(from_str_hex(~"a4"), Some(164.)); - assert_eq!(from_str_hex(~"a4.fe"), Some(164.9921875)); - assert_eq!(from_str_hex(~"-a4.fe"), Some(-164.9921875)); - assert_eq!(from_str_hex(~"+a4.fe"), Some(164.9921875)); - assert_eq!(from_str_hex(~"ff0P4"), Some(0xff00 as float)); - assert_eq!(from_str_hex(~"ff0p4"), Some(0xff00 as float)); - assert_eq!(from_str_hex(~"ff0p-4"), Some(0xff as float)); - assert_eq!(from_str_hex(~"."), Some(0.)); - assert_eq!(from_str_hex(~".p1"), Some(0.)); - assert_eq!(from_str_hex(~".p-1"), Some(0.)); - assert_eq!(from_str_hex(~"f."), Some(15.)); - assert_eq!(from_str_hex(~".f"), Some(0.9375)); - assert_eq!(from_str_hex(~"0.f"), Some(0.9375)); - assert_eq!(from_str_hex(~"-.f"), Some(-0.9375)); - assert_eq!(from_str_hex(~"-f"), Some(-15.)); - assert_eq!(from_str_hex(~"inf"), Some(infinity)); - assert_eq!(from_str_hex(~"+inf"), Some(infinity)); - assert_eq!(from_str_hex(~"-inf"), Some(neg_infinity)); + assert_eq!(from_str_hex("a4"), Some(164.)); + assert_eq!(from_str_hex("a4.fe"), Some(164.9921875)); + assert_eq!(from_str_hex("-a4.fe"), Some(-164.9921875)); + assert_eq!(from_str_hex("+a4.fe"), Some(164.9921875)); + assert_eq!(from_str_hex("ff0P4"), Some(0xff00 as float)); + assert_eq!(from_str_hex("ff0p4"), Some(0xff00 as float)); + assert_eq!(from_str_hex("ff0p-4"), Some(0xff as float)); + assert_eq!(from_str_hex("."), Some(0.)); + assert_eq!(from_str_hex(".p1"), Some(0.)); + assert_eq!(from_str_hex(".p-1"), Some(0.)); + assert_eq!(from_str_hex("f."), Some(15.)); + assert_eq!(from_str_hex(".f"), Some(0.9375)); + assert_eq!(from_str_hex("0.f"), Some(0.9375)); + assert_eq!(from_str_hex("-.f"), Some(-0.9375)); + assert_eq!(from_str_hex("-f"), Some(-15.)); + assert_eq!(from_str_hex("inf"), Some(infinity)); + assert_eq!(from_str_hex("+inf"), Some(infinity)); + assert_eq!(from_str_hex("-inf"), Some(neg_infinity)); // note: NaN != NaN, hence this slightly complex test - match from_str_hex(~"NaN") { + match from_str_hex("NaN") { Some(f) => assert!(f.is_NaN()), None => fail!() } // note: -0 == 0, hence these slightly more complex tests - match from_str_hex(~"-0") { + match from_str_hex("-0") { Some(v) if v.is_zero() => assert!(v.is_negative()), _ => fail!() } - match from_str_hex(~"0") { + match from_str_hex("0") { Some(v) if v.is_zero() => assert!(v.is_positive()), _ => fail!() } - assert_eq!(from_str_hex(~"e"), Some(14.)); - assert_eq!(from_str_hex(~"E"), Some(14.)); - assert_eq!(from_str_hex(~"E1"), Some(225.)); - assert_eq!(from_str_hex(~"1e1e1"), Some(123361.)); - assert_eq!(from_str_hex(~"1e1.1"), Some(481.0625)); - - assert!(from_str_hex(~"").is_none()); - assert!(from_str_hex(~"x").is_none()); - assert!(from_str_hex(~" ").is_none()); - assert!(from_str_hex(~" ").is_none()); - assert!(from_str_hex(~"p").is_none()); - assert!(from_str_hex(~"P").is_none()); - assert!(from_str_hex(~"P1").is_none()); - assert!(from_str_hex(~"1p1p1").is_none()); - assert!(from_str_hex(~"1p1.1").is_none()); - assert!(from_str_hex(~"1p1-1").is_none()); + assert_eq!(from_str_hex("e"), Some(14.)); + assert_eq!(from_str_hex("E"), Some(14.)); + assert_eq!(from_str_hex("E1"), Some(225.)); + assert_eq!(from_str_hex("1e1e1"), Some(123361.)); + assert_eq!(from_str_hex("1e1.1"), Some(481.0625)); + + assert!(from_str_hex("").is_none()); + assert!(from_str_hex("x").is_none()); + assert!(from_str_hex(" ").is_none()); + assert!(from_str_hex(" ").is_none()); + assert!(from_str_hex("p").is_none()); + assert!(from_str_hex("P").is_none()); + assert!(from_str_hex("P1").is_none()); + assert!(from_str_hex("1p1p1").is_none()); + assert!(from_str_hex("1p1.1").is_none()); + assert!(from_str_hex("1p1-1").is_none()); } #[test] @@ -1375,8 +1383,8 @@ mod tests { #[test] pub fn test_from_str_radix() { - assert_eq!(from_str_radix(~"10", 36u), Some(36.)); - assert_eq!(from_str_radix(~"1000.001", 2u), Some(8.125)); + assert_eq!(from_str_radix("10", 36u), Some(36.)); + assert_eq!(from_str_radix("1000.001", 2u), Some(8.125)); } #[test] diff --git a/src/libstd/num/i16.rs b/src/libstd/num/i16.rs new file mode 100644 index 0000000000000..9977247b249b5 --- /dev/null +++ b/src/libstd/num/i16.rs @@ -0,0 +1,32 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Operations and constants for `i16` + +use num::BitCount; +use unstable::intrinsics; + +pub use self::generated::*; + +int_module!(i16, 16) + +impl BitCount for i16 { + /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic. + #[inline(always)] + fn population_count(&self) -> i16 { unsafe { intrinsics::ctpop16(*self) } } + + /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic. + #[inline(always)] + fn leading_zeros(&self) -> i16 { unsafe { intrinsics::ctlz16(*self) } } + + /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic. + #[inline(always)] + fn trailing_zeros(&self) -> i16 { unsafe { intrinsics::cttz16(*self) } } +} diff --git a/src/libstd/num/i32.rs b/src/libstd/num/i32.rs new file mode 100644 index 0000000000000..0115f306e4e0e --- /dev/null +++ b/src/libstd/num/i32.rs @@ -0,0 +1,32 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Operations and constants for `i32` + +use num::BitCount; +use unstable::intrinsics; + +pub use self::generated::*; + +int_module!(i32, 32) + +impl BitCount for i32 { + /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic. + #[inline(always)] + fn population_count(&self) -> i32 { unsafe { intrinsics::ctpop32(*self) } } + + /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic. + #[inline(always)] + fn leading_zeros(&self) -> i32 { unsafe { intrinsics::ctlz32(*self) } } + + /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic. + #[inline(always)] + fn trailing_zeros(&self) -> i32 { unsafe { intrinsics::cttz32(*self) } } +} diff --git a/src/libstd/num/i64.rs b/src/libstd/num/i64.rs new file mode 100644 index 0000000000000..4e280f01f2720 --- /dev/null +++ b/src/libstd/num/i64.rs @@ -0,0 +1,32 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Operations and constants for `i64` + +use num::BitCount; +use unstable::intrinsics; + +pub use self::generated::*; + +int_module!(i64, 64) + +impl BitCount for i64 { + /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic. + #[inline(always)] + fn population_count(&self) -> i64 { unsafe { intrinsics::ctpop64(*self) } } + + /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic. + #[inline(always)] + fn leading_zeros(&self) -> i64 { unsafe { intrinsics::ctlz64(*self) } } + + /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic. + #[inline(always)] + fn trailing_zeros(&self) -> i64 { unsafe { intrinsics::cttz64(*self) } } +} diff --git a/src/libstd/num/i8.rs b/src/libstd/num/i8.rs new file mode 100644 index 0000000000000..939965b969185 --- /dev/null +++ b/src/libstd/num/i8.rs @@ -0,0 +1,32 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Operations and constants for `i8` + +use num::BitCount; +use unstable::intrinsics; + +pub use self::generated::*; + +int_module!(i8, 8) + +impl BitCount for i8 { + /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic. + #[inline(always)] + fn population_count(&self) -> i8 { unsafe { intrinsics::ctpop8(*self) } } + + /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic. + #[inline(always)] + fn leading_zeros(&self) -> i8 { unsafe { intrinsics::ctlz8(*self) } } + + /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic. + #[inline(always)] + fn trailing_zeros(&self) -> i8 { unsafe { intrinsics::cttz8(*self) } } +} diff --git a/src/libstd/num/int.rs b/src/libstd/num/int.rs new file mode 100644 index 0000000000000..96ef7e9e3412c --- /dev/null +++ b/src/libstd/num/int.rs @@ -0,0 +1,89 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Operations and constants for `int` + +use num::BitCount; + +pub use self::generated::*; + +#[cfg(target_word_size = "32")] pub static bits: uint = 32; +#[cfg(target_word_size = "64")] pub static bits: uint = 64; + +int_module!(int, super::bits) + +#[cfg(target_word_size = "32")] +impl BitCount for int { + /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic. + #[inline(always)] + fn population_count(&self) -> int { (*self as i32).population_count() as int } + + /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic. + #[inline(always)] + fn leading_zeros(&self) -> int { (*self as i32).leading_zeros() as int } + + /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic. + #[inline(always)] + fn trailing_zeros(&self) -> int { (*self as i32).trailing_zeros() as int } +} + +#[cfg(target_word_size = "64")] +impl BitCount for int { + /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic. + #[inline(always)] + fn population_count(&self) -> int { (*self as i64).population_count() as int } + + /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic. + #[inline(always)] + fn leading_zeros(&self) -> int { (*self as i64).leading_zeros() as int } + + /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic. + #[inline(always)] + fn trailing_zeros(&self) -> int { (*self as i64).trailing_zeros() as int } +} + +/// Returns `base` raised to the power of `exponent` +pub fn pow(base: int, exponent: uint) -> int { + if exponent == 0u { + //Not mathemtically true if ~[base == 0] + return 1; + } + if base == 0 { return 0; } + let mut my_pow = exponent; + let mut acc = 1; + let mut multiplier = base; + while(my_pow > 0u) { + if my_pow % 2u == 1u { + acc *= multiplier; + } + my_pow /= 2u; + multiplier *= multiplier; + } + return acc; +} + +#[test] +fn test_pow() { + assert!((pow(0, 0u) == 1)); + assert!((pow(0, 1u) == 0)); + assert!((pow(0, 2u) == 0)); + assert!((pow(-1, 0u) == 1)); + assert!((pow(1, 0u) == 1)); + assert!((pow(-3, 2u) == 9)); + assert!((pow(-3, 3u) == -27)); + assert!((pow(4, 9u) == 262144)); +} + +#[test] +fn test_overflows() { + assert!((::int::max_value > 0)); + assert!((::int::min_value <= 0)); + assert!((::int::min_value + ::int::max_value + 1 == 0)); +} diff --git a/src/libcore/num/int-template.rs b/src/libstd/num/int_macros.rs similarity index 55% rename from src/libcore/num/int-template.rs rename to src/libstd/num/int_macros.rs index 348f72f9f0a74..3583e2f366ff3 100644 --- a/src/libcore/num/int-template.rs +++ b/src/libstd/num/int_macros.rs @@ -8,7 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use T = self::inst::T; +// FIXME(#4375): this shouldn't have to be a nested module named 'generated' + +#[macro_escape]; + +macro_rules! int_module (($T:ty, $bits:expr) => (mod generated { use num::{ToStrRadix, FromStrRadix}; use num::{Zero, One, strconv}; @@ -16,20 +20,25 @@ use prelude::*; pub use cmp::{min, max}; -pub static bits : uint = inst::bits; -pub static bytes : uint = (inst::bits / 8); +pub static bits : uint = $bits; +pub static bytes : uint = ($bits / 8); -pub static min_value: T = (-1 as T) << (bits - 1); -pub static max_value: T = min_value - 1 as T; +pub static min_value: $T = (-1 as $T) << (bits - 1); +pub static max_value: $T = min_value - 1 as $T; +/// Calculates the sum of two numbers #[inline(always)] -pub fn add(x: T, y: T) -> T { x + y } +pub fn add(x: $T, y: $T) -> $T { x + y } +/// Subtracts the second number from the first #[inline(always)] -pub fn sub(x: T, y: T) -> T { x - y } +pub fn sub(x: $T, y: $T) -> $T { x - y } +/// Multiplies two numbers together #[inline(always)] -pub fn mul(x: T, y: T) -> T { x * y } +pub fn mul(x: $T, y: $T) -> $T { x * y } +/// Divides the first argument by the second argument (using integer division) +/// Divides the first argument by the second argument (using integer division) #[inline(always)] -pub fn div(x: T, y: T) -> T { x / y } +pub fn div(x: $T, y: $T) -> $T { x / y } /// /// Returns the remainder of y / x. @@ -52,20 +61,26 @@ pub fn div(x: T, y: T) -> T { x / y } /// /// #[inline(always)] -pub fn rem(x: T, y: T) -> T { x % y } +pub fn rem(x: $T, y: $T) -> $T { x % y } +/// Returns true iff `x < y` #[inline(always)] -pub fn lt(x: T, y: T) -> bool { x < y } +pub fn lt(x: $T, y: $T) -> bool { x < y } +/// Returns true iff `x <= y` #[inline(always)] -pub fn le(x: T, y: T) -> bool { x <= y } +pub fn le(x: $T, y: $T) -> bool { x <= y } +/// Returns true iff `x == y` #[inline(always)] -pub fn eq(x: T, y: T) -> bool { x == y } +pub fn eq(x: $T, y: $T) -> bool { x == y } +/// Returns true iff `x != y` #[inline(always)] -pub fn ne(x: T, y: T) -> bool { x != y } +pub fn ne(x: $T, y: $T) -> bool { x != y } +/// Returns true iff `x >= y` #[inline(always)] -pub fn ge(x: T, y: T) -> bool { x >= y } +pub fn ge(x: $T, y: $T) -> bool { x >= y } +/// Returns true iff `x > y` #[inline(always)] -pub fn gt(x: T, y: T) -> bool { x > y } +pub fn gt(x: $T, y: $T) -> bool { x > y } /// /// Iterate over the range [`lo`..`hi`) @@ -85,11 +100,10 @@ pub fn gt(x: T, y: T) -> bool { x > y } /// ~~~ /// #[inline(always)] -/// Iterate over the range [`start`,`start`+`step`..`stop`) -pub fn _range_step(start: T, stop: T, step: T, it: &fn(T) -> bool) -> bool { +pub fn range_step(start: $T, stop: $T, step: $T, it: &fn($T) -> bool) -> bool { let mut i = start; if step == 0 { - fail!("range_step called with step == 0"); + fail!(~"range_step called with step == 0"); } else if step > 0 { // ascending while i < stop { if !it(i) { return false; } @@ -108,125 +122,101 @@ pub fn _range_step(start: T, stop: T, step: T, it: &fn(T) -> bool) -> bool { return true; } -#[cfg(stage0)] -pub fn range_step(start: T, stop: T, step: T, it: &fn(T) -> bool) { - _range_step(start, stop, step, it); -} -#[cfg(not(stage0))] -pub fn range_step(start: T, stop: T, step: T, it: &fn(T) -> bool) -> bool { - _range_step(start, stop, step, it) -} - #[inline(always)] -#[cfg(stage0)] /// Iterate over the range [`lo`..`hi`) -pub fn range(lo: T, hi: T, it: &fn(T) -> bool) { - range_step(lo, hi, 1 as T, it); +pub fn range(lo: $T, hi: $T, it: &fn($T) -> bool) -> bool { + range_step(lo, hi, 1 as $T, it) } #[inline(always)] -#[cfg(not(stage0))] -/// Iterate over the range [`lo`..`hi`) -pub fn range(lo: T, hi: T, it: &fn(T) -> bool) -> bool { - range_step(lo, hi, 1 as T, it) -} - -#[inline(always)] -#[cfg(stage0)] /// Iterate over the range [`hi`..`lo`) -pub fn range_rev(hi: T, lo: T, it: &fn(T) -> bool) { - range_step(hi, lo, -1 as T, it); -} -#[inline(always)] -#[cfg(not(stage0))] -/// Iterate over the range [`hi`..`lo`) -pub fn range_rev(hi: T, lo: T, it: &fn(T) -> bool) -> bool { - range_step(hi, lo, -1 as T, it) +pub fn range_rev(hi: $T, lo: $T, it: &fn($T) -> bool) -> bool { + range_step(hi, lo, -1 as $T, it) } /// Computes the bitwise complement #[inline(always)] -pub fn compl(i: T) -> T { - -1 as T ^ i +pub fn compl(i: $T) -> $T { + -1 as $T ^ i } /// Computes the absolute value #[inline(always)] -pub fn abs(i: T) -> T { i.abs() } +pub fn abs(i: $T) -> $T { i.abs() } -impl Num for T {} +impl Num for $T {} #[cfg(not(test))] -impl Ord for T { +impl Ord for $T { #[inline(always)] - fn lt(&self, other: &T) -> bool { return (*self) < (*other); } + fn lt(&self, other: &$T) -> bool { return (*self) < (*other); } #[inline(always)] - fn le(&self, other: &T) -> bool { return (*self) <= (*other); } + fn le(&self, other: &$T) -> bool { return (*self) <= (*other); } #[inline(always)] - fn ge(&self, other: &T) -> bool { return (*self) >= (*other); } + fn ge(&self, other: &$T) -> bool { return (*self) >= (*other); } #[inline(always)] - fn gt(&self, other: &T) -> bool { return (*self) > (*other); } + fn gt(&self, other: &$T) -> bool { return (*self) > (*other); } } #[cfg(not(test))] -impl Eq for T { +impl Eq for $T { #[inline(always)] - fn eq(&self, other: &T) -> bool { return (*self) == (*other); } + fn eq(&self, other: &$T) -> bool { return (*self) == (*other); } #[inline(always)] - fn ne(&self, other: &T) -> bool { return (*self) != (*other); } + fn ne(&self, other: &$T) -> bool { return (*self) != (*other); } } -impl Orderable for T { +impl Orderable for $T { #[inline(always)] - fn min(&self, other: &T) -> T { + fn min(&self, other: &$T) -> $T { if *self < *other { *self } else { *other } } #[inline(always)] - fn max(&self, other: &T) -> T { + fn max(&self, other: &$T) -> $T { if *self > *other { *self } else { *other } } #[inline(always)] - fn clamp(&self, mn: &T, mx: &T) -> T { + fn clamp(&self, mn: &$T, mx: &$T) -> $T { if *self > *mx { *mx } else if *self < *mn { *mn } else { *self } } } -impl Zero for T { +impl Zero for $T { #[inline(always)] - fn zero() -> T { 0 } + fn zero() -> $T { 0 } #[inline(always)] fn is_zero(&self) -> bool { *self == 0 } } -impl One for T { +impl One for $T { #[inline(always)] - fn one() -> T { 1 } + fn one() -> $T { 1 } } #[cfg(not(test))] -impl Add for T { +impl Add<$T,$T> for $T { #[inline(always)] - fn add(&self, other: &T) -> T { *self + *other } + fn add(&self, other: &$T) -> $T { *self + *other } } #[cfg(not(test))] -impl Sub for T { +impl Sub<$T,$T> for $T { #[inline(always)] - fn sub(&self, other: &T) -> T { *self - *other } + fn sub(&self, other: &$T) -> $T { *self - *other } } #[cfg(not(test))] -impl Mul for T { +impl Mul<$T,$T> for $T { #[inline(always)] - fn mul(&self, other: &T) -> T { *self * *other } + fn mul(&self, other: &$T) -> $T { *self * *other } } #[cfg(not(test))] -impl Div for T { +impl Div<$T,$T> for $T { /// /// Integer division, truncated towards 0. As this behaviour reflects the underlying /// machine implementation it is more efficient than `Integer::div_floor`. @@ -246,11 +236,11 @@ impl Div for T { /// ~~~ /// #[inline(always)] - fn div(&self, other: &T) -> T { *self / *other } + fn div(&self, other: &$T) -> $T { *self / *other } } #[cfg(not(test))] -impl Rem for T { +impl Rem<$T,$T> for $T { /// /// Returns the integer remainder after division, satisfying: /// @@ -273,19 +263,19 @@ impl Rem for T { /// ~~~ /// #[inline(always)] - fn rem(&self, other: &T) -> T { *self % *other } + fn rem(&self, other: &$T) -> $T { *self % *other } } #[cfg(not(test))] -impl Neg for T { +impl Neg<$T> for $T { #[inline(always)] - fn neg(&self) -> T { -*self } + fn neg(&self) -> $T { -*self } } -impl Signed for T { +impl Signed for $T { /// Computes the absolute value #[inline(always)] - fn abs(&self) -> T { + fn abs(&self) -> $T { if self.is_negative() { -*self } else { *self } } @@ -294,7 +284,7 @@ impl Signed for T { /// equal to `other`, otherwise the difference between`self` and `other` is returned. /// #[inline(always)] - fn abs_sub(&self, other: &T) -> T { + fn abs_sub(&self, other: &$T) -> $T { if *self <= *other { 0 } else { *self - *other } } @@ -306,7 +296,7 @@ impl Signed for T { /// - `-1` if the number is negative /// #[inline(always)] - fn signum(&self) -> T { + fn signum(&self) -> $T { match *self { n if n > 0 => 1, 0 => 0, @@ -323,7 +313,7 @@ impl Signed for T { fn is_negative(&self) -> bool { *self < 0 } } -impl Integer for T { +impl Integer for $T { /// /// Floored integer division /// @@ -342,7 +332,7 @@ impl Integer for T { /// ~~~ /// #[inline(always)] - fn div_floor(&self, other: &T) -> T { + fn div_floor(&self, other: &$T) -> $T { // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_, // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf) match self.div_rem(other) { @@ -374,7 +364,7 @@ impl Integer for T { /// ~~~ /// #[inline(always)] - fn mod_floor(&self, other: &T) -> T { + fn mod_floor(&self, other: &$T) -> $T { // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_, // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf) match *self % *other { @@ -386,7 +376,7 @@ impl Integer for T { /// Calculates `div_floor` and `mod_floor` simultaneously #[inline(always)] - fn div_mod_floor(&self, other: &T) -> (T,T) { + fn div_mod_floor(&self, other: &$T) -> ($T,$T) { // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_, // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf) match self.div_rem(other) { @@ -398,7 +388,7 @@ impl Integer for T { /// Calculates `div` (`\`) and `rem` (`%`) simultaneously #[inline(always)] - fn div_rem(&self, other: &T) -> (T,T) { + fn div_rem(&self, other: &$T) -> ($T,$T) { (*self / *other, *self % *other) } @@ -408,9 +398,9 @@ impl Integer for T { /// The result is always positive /// #[inline(always)] - fn gcd(&self, other: &T) -> T { + fn gcd(&self, other: &$T) -> $T { // Use Euclid's algorithm - let mut m = *self, n = *other; + let mut (m, n) = (*self, *other); while m != 0 { let temp = m; m = n % temp; @@ -423,13 +413,13 @@ impl Integer for T { /// Calculates the Lowest Common Multiple (LCM) of the number and `other` /// #[inline(always)] - fn lcm(&self, other: &T) -> T { + fn lcm(&self, other: &$T) -> $T { ((*self * *other) / self.gcd(other)).abs() // should not have to recaluculate abs } /// Returns `true` if the number can be divided by `other` without leaving a remainder #[inline(always)] - fn is_multiple_of(&self, other: &T) -> bool { *self % *other == 0 } + fn is_multiple_of(&self, other: &$T) -> bool { *self % *other == 0 } /// Returns `true` if the number is divisible by `2` #[inline(always)] @@ -440,87 +430,95 @@ impl Integer for T { fn is_odd(&self) -> bool { !self.is_even() } } -impl Bitwise for T {} +impl Bitwise for $T {} #[cfg(not(test))] -impl BitOr for T { +impl BitOr<$T,$T> for $T { #[inline(always)] - fn bitor(&self, other: &T) -> T { *self | *other } + fn bitor(&self, other: &$T) -> $T { *self | *other } } #[cfg(not(test))] -impl BitAnd for T { +impl BitAnd<$T,$T> for $T { #[inline(always)] - fn bitand(&self, other: &T) -> T { *self & *other } + fn bitand(&self, other: &$T) -> $T { *self & *other } } #[cfg(not(test))] -impl BitXor for T { +impl BitXor<$T,$T> for $T { #[inline(always)] - fn bitxor(&self, other: &T) -> T { *self ^ *other } + fn bitxor(&self, other: &$T) -> $T { *self ^ *other } } #[cfg(not(test))] -impl Shl for T { +impl Shl<$T,$T> for $T { #[inline(always)] - fn shl(&self, other: &T) -> T { *self << *other } + fn shl(&self, other: &$T) -> $T { *self << *other } } #[cfg(not(test))] -impl Shr for T { +impl Shr<$T,$T> for $T { #[inline(always)] - fn shr(&self, other: &T) -> T { *self >> *other } + fn shr(&self, other: &$T) -> $T { *self >> *other } } #[cfg(not(test))] -impl Not for T { +impl Not<$T> for $T { #[inline(always)] - fn not(&self) -> T { !*self } + fn not(&self) -> $T { !*self } } -impl Bounded for T { +impl Bounded for $T { #[inline(always)] - fn min_value() -> T { min_value } + fn min_value() -> $T { min_value } #[inline(always)] - fn max_value() -> T { max_value } + fn max_value() -> $T { max_value } } -impl Int for T {} +impl Int for $T {} + +impl Primitive for $T { + #[inline(always)] + fn bits() -> uint { bits } + + #[inline(always)] + fn bytes() -> uint { bits / 8 } +} // String conversion functions and impl str -> num /// Parse a string as a number in base 10. #[inline(always)] -pub fn from_str(s: &str) -> Option { +pub fn from_str(s: &str) -> Option<$T> { strconv::from_str_common(s, 10u, true, false, false, strconv::ExpNone, false, false) } /// Parse a string as a number in the given base. #[inline(always)] -pub fn from_str_radix(s: &str, radix: uint) -> Option { +pub fn from_str_radix(s: &str, radix: uint) -> Option<$T> { strconv::from_str_common(s, radix, true, false, false, strconv::ExpNone, false, false) } /// Parse a byte slice as a number in the given base. #[inline(always)] -pub fn parse_bytes(buf: &[u8], radix: uint) -> Option { +pub fn parse_bytes(buf: &[u8], radix: uint) -> Option<$T> { strconv::from_str_bytes_common(buf, radix, true, false, false, strconv::ExpNone, false, false) } -impl FromStr for T { +impl FromStr for $T { #[inline(always)] - fn from_str(s: &str) -> Option { + fn from_str(s: &str) -> Option<$T> { from_str(s) } } -impl FromStrRadix for T { +impl FromStrRadix for $T { #[inline(always)] - fn from_str_radix(s: &str, radix: uint) -> Option { + fn from_str_radix(s: &str, radix: uint) -> Option<$T> { from_str_radix(s, radix) } } @@ -529,7 +527,7 @@ impl FromStrRadix for T { /// Convert to a string as a byte slice in a given base. #[inline(always)] -pub fn to_str_bytes(n: T, radix: uint, f: &fn(v: &[u8]) -> U) -> U { +pub fn to_str_bytes(n: $T, radix: uint, f: &fn(v: &[u8]) -> U) -> U { let (buf, _) = strconv::to_str_bytes_common(&n, radix, false, strconv::SignNeg, strconv::DigAll); f(buf) @@ -537,7 +535,7 @@ pub fn to_str_bytes(n: T, radix: uint, f: &fn(v: &[u8]) -> U) -> U { /// Convert to a string in base 10. #[inline(always)] -pub fn to_str(num: T) -> ~str { +pub fn to_str(num: $T) -> ~str { let (buf, _) = strconv::to_str_common(&num, 10u, false, strconv::SignNeg, strconv::DigAll); buf @@ -545,20 +543,20 @@ pub fn to_str(num: T) -> ~str { /// Convert to a string in a given base. #[inline(always)] -pub fn to_str_radix(num: T, radix: uint) -> ~str { +pub fn to_str_radix(num: $T, radix: uint) -> ~str { let (buf, _) = strconv::to_str_common(&num, radix, false, strconv::SignNeg, strconv::DigAll); buf } -impl ToStr for T { +impl ToStr for $T { #[inline(always)] fn to_str(&self) -> ~str { to_str(*self) } } -impl ToStrRadix for T { +impl ToStrRadix for $T { #[inline(always)] fn to_str_radix(&self, radix: uint) -> ~str { to_str_radix(*self, radix) @@ -568,62 +566,68 @@ impl ToStrRadix for T { #[cfg(test)] mod tests { use super::*; - use super::inst::T; use prelude::*; + use i16; + use i32; + use i64; + use i8; + use num; + use sys; + #[test] fn test_num() { - num::test_num(10 as T, 2 as T); + num::test_num(10 as $T, 2 as $T); } #[test] fn test_orderable() { - assert_eq!((1 as T).min(&(2 as T)), 1 as T); - assert_eq!((2 as T).min(&(1 as T)), 1 as T); - assert_eq!((1 as T).max(&(2 as T)), 2 as T); - assert_eq!((2 as T).max(&(1 as T)), 2 as T); - assert_eq!((1 as T).clamp(&(2 as T), &(4 as T)), 2 as T); - assert_eq!((8 as T).clamp(&(2 as T), &(4 as T)), 4 as T); - assert_eq!((3 as T).clamp(&(2 as T), &(4 as T)), 3 as T); + assert_eq!((1 as $T).min(&(2 as $T)), 1 as $T); + assert_eq!((2 as $T).min(&(1 as $T)), 1 as $T); + assert_eq!((1 as $T).max(&(2 as $T)), 2 as $T); + assert_eq!((2 as $T).max(&(1 as $T)), 2 as $T); + assert_eq!((1 as $T).clamp(&(2 as $T), &(4 as $T)), 2 as $T); + assert_eq!((8 as $T).clamp(&(2 as $T), &(4 as $T)), 4 as $T); + assert_eq!((3 as $T).clamp(&(2 as $T), &(4 as $T)), 3 as $T); } #[test] pub fn test_abs() { - assert_eq!((1 as T).abs(), 1 as T); - assert_eq!((0 as T).abs(), 0 as T); - assert_eq!((-1 as T).abs(), 1 as T); + assert_eq!((1 as $T).abs(), 1 as $T); + assert_eq!((0 as $T).abs(), 0 as $T); + assert_eq!((-1 as $T).abs(), 1 as $T); } #[test] fn test_abs_sub() { - assert_eq!((-1 as T).abs_sub(&(1 as T)), 0 as T); - assert_eq!((1 as T).abs_sub(&(1 as T)), 0 as T); - assert_eq!((1 as T).abs_sub(&(0 as T)), 1 as T); - assert_eq!((1 as T).abs_sub(&(-1 as T)), 2 as T); + assert_eq!((-1 as $T).abs_sub(&(1 as $T)), 0 as $T); + assert_eq!((1 as $T).abs_sub(&(1 as $T)), 0 as $T); + assert_eq!((1 as $T).abs_sub(&(0 as $T)), 1 as $T); + assert_eq!((1 as $T).abs_sub(&(-1 as $T)), 2 as $T); } #[test] fn test_signum() { - assert_eq!((1 as T).signum(), 1 as T); - assert_eq!((0 as T).signum(), 0 as T); - assert_eq!((-0 as T).signum(), 0 as T); - assert_eq!((-1 as T).signum(), -1 as T); + assert_eq!((1 as $T).signum(), 1 as $T); + assert_eq!((0 as $T).signum(), 0 as $T); + assert_eq!((-0 as $T).signum(), 0 as $T); + assert_eq!((-1 as $T).signum(), -1 as $T); } #[test] fn test_is_positive() { - assert!((1 as T).is_positive()); - assert!(!(0 as T).is_positive()); - assert!(!(-0 as T).is_positive()); - assert!(!(-1 as T).is_positive()); + assert!((1 as $T).is_positive()); + assert!(!(0 as $T).is_positive()); + assert!(!(-0 as $T).is_positive()); + assert!(!(-1 as $T).is_positive()); } #[test] fn test_is_negative() { - assert!(!(1 as T).is_negative()); - assert!(!(0 as T).is_negative()); - assert!(!(-0 as T).is_negative()); - assert!((-1 as T).is_negative()); + assert!(!(1 as $T).is_negative()); + assert!(!(0 as $T).is_negative()); + assert!(!(-0 as $T).is_negative()); + assert!((-1 as $T).is_negative()); } /// @@ -634,13 +638,13 @@ mod tests { /// - `qr`: quotient and remainder /// #[cfg(test)] - fn test_division_rule((n,d): (T,T), (q,r): (T,T)) { + fn test_division_rule((n,d): ($T,$T), (q,r): ($T,$T)) { assert_eq!(d * q + r, n); } #[test] fn test_div_rem() { - fn test_nd_dr(nd: (T,T), qr: (T,T)) { + fn test_nd_dr(nd: ($T,$T), qr: ($T,$T)) { let (n,d) = nd; let separate_div_rem = (n / d, n % d); let combined_div_rem = n.div_rem(&d); @@ -665,7 +669,7 @@ mod tests { #[test] fn test_div_mod_floor() { - fn test_nd_dm(nd: (T,T), dm: (T,T)) { + fn test_nd_dm(nd: ($T,$T), dm: ($T,$T)) { let (n,d) = nd; let separate_div_mod_floor = (n.div_floor(&d), n.mod_floor(&d)); let combined_div_mod_floor = n.div_mod_floor(&d); @@ -690,135 +694,135 @@ mod tests { #[test] fn test_gcd() { - assert_eq!((10 as T).gcd(&2), 2 as T); - assert_eq!((10 as T).gcd(&3), 1 as T); - assert_eq!((0 as T).gcd(&3), 3 as T); - assert_eq!((3 as T).gcd(&3), 3 as T); - assert_eq!((56 as T).gcd(&42), 14 as T); - assert_eq!((3 as T).gcd(&-3), 3 as T); - assert_eq!((-6 as T).gcd(&3), 3 as T); - assert_eq!((-4 as T).gcd(&-2), 2 as T); + assert_eq!((10 as $T).gcd(&2), 2 as $T); + assert_eq!((10 as $T).gcd(&3), 1 as $T); + assert_eq!((0 as $T).gcd(&3), 3 as $T); + assert_eq!((3 as $T).gcd(&3), 3 as $T); + assert_eq!((56 as $T).gcd(&42), 14 as $T); + assert_eq!((3 as $T).gcd(&-3), 3 as $T); + assert_eq!((-6 as $T).gcd(&3), 3 as $T); + assert_eq!((-4 as $T).gcd(&-2), 2 as $T); } #[test] fn test_lcm() { - assert_eq!((1 as T).lcm(&0), 0 as T); - assert_eq!((0 as T).lcm(&1), 0 as T); - assert_eq!((1 as T).lcm(&1), 1 as T); - assert_eq!((-1 as T).lcm(&1), 1 as T); - assert_eq!((1 as T).lcm(&-1), 1 as T); - assert_eq!((-1 as T).lcm(&-1), 1 as T); - assert_eq!((8 as T).lcm(&9), 72 as T); - assert_eq!((11 as T).lcm(&5), 55 as T); + assert_eq!((1 as $T).lcm(&0), 0 as $T); + assert_eq!((0 as $T).lcm(&1), 0 as $T); + assert_eq!((1 as $T).lcm(&1), 1 as $T); + assert_eq!((-1 as $T).lcm(&1), 1 as $T); + assert_eq!((1 as $T).lcm(&-1), 1 as $T); + assert_eq!((-1 as $T).lcm(&-1), 1 as $T); + assert_eq!((8 as $T).lcm(&9), 72 as $T); + assert_eq!((11 as $T).lcm(&5), 55 as $T); } #[test] fn test_bitwise() { - assert_eq!(0b1110 as T, (0b1100 as T).bitor(&(0b1010 as T))); - assert_eq!(0b1000 as T, (0b1100 as T).bitand(&(0b1010 as T))); - assert_eq!(0b0110 as T, (0b1100 as T).bitxor(&(0b1010 as T))); - assert_eq!(0b1110 as T, (0b0111 as T).shl(&(1 as T))); - assert_eq!(0b0111 as T, (0b1110 as T).shr(&(1 as T))); - assert_eq!(-(0b11 as T) - (1 as T), (0b11 as T).not()); + assert_eq!(0b1110 as $T, (0b1100 as $T).bitor(&(0b1010 as $T))); + assert_eq!(0b1000 as $T, (0b1100 as $T).bitand(&(0b1010 as $T))); + assert_eq!(0b0110 as $T, (0b1100 as $T).bitxor(&(0b1010 as $T))); + assert_eq!(0b1110 as $T, (0b0111 as $T).shl(&(1 as $T))); + assert_eq!(0b0111 as $T, (0b1110 as $T).shr(&(1 as $T))); + assert_eq!(-(0b11 as $T) - (1 as $T), (0b11 as $T).not()); } #[test] fn test_multiple_of() { - assert!((6 as T).is_multiple_of(&(6 as T))); - assert!((6 as T).is_multiple_of(&(3 as T))); - assert!((6 as T).is_multiple_of(&(1 as T))); - assert!((-8 as T).is_multiple_of(&(4 as T))); - assert!((8 as T).is_multiple_of(&(-1 as T))); - assert!((-8 as T).is_multiple_of(&(-2 as T))); + assert!((6 as $T).is_multiple_of(&(6 as $T))); + assert!((6 as $T).is_multiple_of(&(3 as $T))); + assert!((6 as $T).is_multiple_of(&(1 as $T))); + assert!((-8 as $T).is_multiple_of(&(4 as $T))); + assert!((8 as $T).is_multiple_of(&(-1 as $T))); + assert!((-8 as $T).is_multiple_of(&(-2 as $T))); } #[test] fn test_even() { - assert_eq!((-4 as T).is_even(), true); - assert_eq!((-3 as T).is_even(), false); - assert_eq!((-2 as T).is_even(), true); - assert_eq!((-1 as T).is_even(), false); - assert_eq!((0 as T).is_even(), true); - assert_eq!((1 as T).is_even(), false); - assert_eq!((2 as T).is_even(), true); - assert_eq!((3 as T).is_even(), false); - assert_eq!((4 as T).is_even(), true); + assert_eq!((-4 as $T).is_even(), true); + assert_eq!((-3 as $T).is_even(), false); + assert_eq!((-2 as $T).is_even(), true); + assert_eq!((-1 as $T).is_even(), false); + assert_eq!((0 as $T).is_even(), true); + assert_eq!((1 as $T).is_even(), false); + assert_eq!((2 as $T).is_even(), true); + assert_eq!((3 as $T).is_even(), false); + assert_eq!((4 as $T).is_even(), true); } #[test] fn test_odd() { - assert_eq!((-4 as T).is_odd(), false); - assert_eq!((-3 as T).is_odd(), true); - assert_eq!((-2 as T).is_odd(), false); - assert_eq!((-1 as T).is_odd(), true); - assert_eq!((0 as T).is_odd(), false); - assert_eq!((1 as T).is_odd(), true); - assert_eq!((2 as T).is_odd(), false); - assert_eq!((3 as T).is_odd(), true); - assert_eq!((4 as T).is_odd(), false); + assert_eq!((-4 as $T).is_odd(), false); + assert_eq!((-3 as $T).is_odd(), true); + assert_eq!((-2 as $T).is_odd(), false); + assert_eq!((-1 as $T).is_odd(), true); + assert_eq!((0 as $T).is_odd(), false); + assert_eq!((1 as $T).is_odd(), true); + assert_eq!((2 as $T).is_odd(), false); + assert_eq!((3 as $T).is_odd(), true); + assert_eq!((4 as $T).is_odd(), false); } #[test] fn test_bitcount() { - assert_eq!((0b010101 as T).population_count(), 3); + assert_eq!((0b010101 as $T).population_count(), 3); } #[test] fn test_primitive() { - assert_eq!(Primitive::bits::(), sys::size_of::() * 8); - assert_eq!(Primitive::bytes::(), sys::size_of::()); + assert_eq!(Primitive::bits::<$T>(), sys::size_of::<$T>() * 8); + assert_eq!(Primitive::bytes::<$T>(), sys::size_of::<$T>()); } #[test] fn test_from_str() { - assert_eq!(from_str(~"0"), Some(0 as T)); - assert_eq!(from_str(~"3"), Some(3 as T)); - assert_eq!(from_str(~"10"), Some(10 as T)); - assert_eq!(i32::from_str(~"123456789"), Some(123456789 as i32)); - assert_eq!(from_str(~"00100"), Some(100 as T)); + assert_eq!(from_str("0"), Some(0 as $T)); + assert_eq!(from_str("3"), Some(3 as $T)); + assert_eq!(from_str("10"), Some(10 as $T)); + assert_eq!(i32::from_str("123456789"), Some(123456789 as i32)); + assert_eq!(from_str("00100"), Some(100 as $T)); - assert_eq!(from_str(~"-1"), Some(-1 as T)); - assert_eq!(from_str(~"-3"), Some(-3 as T)); - assert_eq!(from_str(~"-10"), Some(-10 as T)); - assert_eq!(i32::from_str(~"-123456789"), Some(-123456789 as i32)); - assert_eq!(from_str(~"-00100"), Some(-100 as T)); + assert_eq!(from_str("-1"), Some(-1 as $T)); + assert_eq!(from_str("-3"), Some(-3 as $T)); + assert_eq!(from_str("-10"), Some(-10 as $T)); + assert_eq!(i32::from_str("-123456789"), Some(-123456789 as i32)); + assert_eq!(from_str("-00100"), Some(-100 as $T)); - assert!(from_str(~" ").is_none()); - assert!(from_str(~"x").is_none()); + assert!(from_str(" ").is_none()); + assert!(from_str("x").is_none()); } #[test] fn test_parse_bytes() { use str::to_bytes; - assert_eq!(parse_bytes(to_bytes(~"123"), 10u), Some(123 as T)); - assert_eq!(parse_bytes(to_bytes(~"1001"), 2u), Some(9 as T)); - assert_eq!(parse_bytes(to_bytes(~"123"), 8u), Some(83 as T)); - assert_eq!(i32::parse_bytes(to_bytes(~"123"), 16u), Some(291 as i32)); - assert_eq!(i32::parse_bytes(to_bytes(~"ffff"), 16u), Some(65535 as i32)); - assert_eq!(i32::parse_bytes(to_bytes(~"FFFF"), 16u), Some(65535 as i32)); - assert_eq!(parse_bytes(to_bytes(~"z"), 36u), Some(35 as T)); - assert_eq!(parse_bytes(to_bytes(~"Z"), 36u), Some(35 as T)); - - assert_eq!(parse_bytes(to_bytes(~"-123"), 10u), Some(-123 as T)); - assert_eq!(parse_bytes(to_bytes(~"-1001"), 2u), Some(-9 as T)); - assert_eq!(parse_bytes(to_bytes(~"-123"), 8u), Some(-83 as T)); - assert_eq!(i32::parse_bytes(to_bytes(~"-123"), 16u), Some(-291 as i32)); - assert_eq!(i32::parse_bytes(to_bytes(~"-ffff"), 16u), Some(-65535 as i32)); - assert_eq!(i32::parse_bytes(to_bytes(~"-FFFF"), 16u), Some(-65535 as i32)); - assert_eq!(parse_bytes(to_bytes(~"-z"), 36u), Some(-35 as T)); - assert_eq!(parse_bytes(to_bytes(~"-Z"), 36u), Some(-35 as T)); - - assert!(parse_bytes(to_bytes(~"Z"), 35u).is_none()); - assert!(parse_bytes(to_bytes(~"-9"), 2u).is_none()); + assert_eq!(parse_bytes(to_bytes("123"), 10u), Some(123 as $T)); + assert_eq!(parse_bytes(to_bytes("1001"), 2u), Some(9 as $T)); + assert_eq!(parse_bytes(to_bytes("123"), 8u), Some(83 as $T)); + assert_eq!(i32::parse_bytes(to_bytes("123"), 16u), Some(291 as i32)); + assert_eq!(i32::parse_bytes(to_bytes("ffff"), 16u), Some(65535 as i32)); + assert_eq!(i32::parse_bytes(to_bytes("FFFF"), 16u), Some(65535 as i32)); + assert_eq!(parse_bytes(to_bytes("z"), 36u), Some(35 as $T)); + assert_eq!(parse_bytes(to_bytes("Z"), 36u), Some(35 as $T)); + + assert_eq!(parse_bytes(to_bytes("-123"), 10u), Some(-123 as $T)); + assert_eq!(parse_bytes(to_bytes("-1001"), 2u), Some(-9 as $T)); + assert_eq!(parse_bytes(to_bytes("-123"), 8u), Some(-83 as $T)); + assert_eq!(i32::parse_bytes(to_bytes("-123"), 16u), Some(-291 as i32)); + assert_eq!(i32::parse_bytes(to_bytes("-ffff"), 16u), Some(-65535 as i32)); + assert_eq!(i32::parse_bytes(to_bytes("-FFFF"), 16u), Some(-65535 as i32)); + assert_eq!(parse_bytes(to_bytes("-z"), 36u), Some(-35 as $T)); + assert_eq!(parse_bytes(to_bytes("-Z"), 36u), Some(-35 as $T)); + + assert!(parse_bytes(to_bytes("Z"), 35u).is_none()); + assert!(parse_bytes(to_bytes("-9"), 2u).is_none()); } #[test] fn test_to_str() { - assert_eq!(to_str_radix(0 as T, 10u), ~"0"); - assert_eq!(to_str_radix(1 as T, 10u), ~"1"); - assert_eq!(to_str_radix(-1 as T, 10u), ~"-1"); - assert_eq!(to_str_radix(127 as T, 16u), ~"7f"); - assert_eq!(to_str_radix(100 as T, 10u), ~"100"); + assert_eq!(to_str_radix(0 as $T, 10u), ~"0"); + assert_eq!(to_str_radix(1 as $T, 10u), ~"1"); + assert_eq!(to_str_radix(-1 as $T, 10u), ~"-1"); + assert_eq!(to_str_radix(127 as $T, 16u), ~"7f"); + assert_eq!(to_str_radix(100 as $T, 10u), ~"100"); } @@ -852,36 +856,36 @@ mod tests { #[test] fn test_int_from_str_overflow() { let mut i8_val: i8 = 127_i8; - assert_eq!(i8::from_str(~"127"), Some(i8_val)); - assert!(i8::from_str(~"128").is_none()); + assert_eq!(i8::from_str("127"), Some(i8_val)); + assert!(i8::from_str("128").is_none()); i8_val += 1 as i8; - assert_eq!(i8::from_str(~"-128"), Some(i8_val)); - assert!(i8::from_str(~"-129").is_none()); + assert_eq!(i8::from_str("-128"), Some(i8_val)); + assert!(i8::from_str("-129").is_none()); let mut i16_val: i16 = 32_767_i16; - assert_eq!(i16::from_str(~"32767"), Some(i16_val)); - assert!(i16::from_str(~"32768").is_none()); + assert_eq!(i16::from_str("32767"), Some(i16_val)); + assert!(i16::from_str("32768").is_none()); i16_val += 1 as i16; - assert_eq!(i16::from_str(~"-32768"), Some(i16_val)); - assert!(i16::from_str(~"-32769").is_none()); + assert_eq!(i16::from_str("-32768"), Some(i16_val)); + assert!(i16::from_str("-32769").is_none()); let mut i32_val: i32 = 2_147_483_647_i32; - assert_eq!(i32::from_str(~"2147483647"), Some(i32_val)); - assert!(i32::from_str(~"2147483648").is_none()); + assert_eq!(i32::from_str("2147483647"), Some(i32_val)); + assert!(i32::from_str("2147483648").is_none()); i32_val += 1 as i32; - assert_eq!(i32::from_str(~"-2147483648"), Some(i32_val)); - assert!(i32::from_str(~"-2147483649").is_none()); + assert_eq!(i32::from_str("-2147483648"), Some(i32_val)); + assert!(i32::from_str("-2147483649").is_none()); let mut i64_val: i64 = 9_223_372_036_854_775_807_i64; - assert_eq!(i64::from_str(~"9223372036854775807"), Some(i64_val)); - assert!(i64::from_str(~"9223372036854775808").is_none()); + assert_eq!(i64::from_str("9223372036854775807"), Some(i64_val)); + assert!(i64::from_str("9223372036854775808").is_none()); i64_val += 1 as i64; - assert_eq!(i64::from_str(~"-9223372036854775808"), Some(i64_val)); - assert!(i64::from_str(~"-9223372036854775809").is_none()); + assert_eq!(i64::from_str("-9223372036854775808"), Some(i64_val)); + assert!(i64::from_str("-9223372036854775809").is_none()); } #[test] @@ -923,16 +927,16 @@ mod tests { // None of the `fail`s should execute. for range(10,0) |_i| { - fail!("unreachable"); + fail!(~"unreachable"); } for range_rev(0,10) |_i| { - fail!("unreachable"); + fail!(~"unreachable"); } for range_step(10,0,1) |_i| { - fail!("unreachable"); + fail!(~"unreachable"); } for range_step(0,10,-1) |_i| { - fail!("unreachable"); + fail!(~"unreachable"); } } @@ -943,3 +947,5 @@ mod tests { for range_step(0,10,0) |_i| {} } } + +})) diff --git a/src/libcore/num/num.rs b/src/libstd/num/num.rs similarity index 99% rename from src/libcore/num/num.rs rename to src/libstd/num/num.rs index 96b302d317499..91631d3c9b904 100644 --- a/src/libcore/num/num.rs +++ b/src/libstd/num/num.rs @@ -9,6 +9,9 @@ // except according to those terms. //! An interface for numeric types + +#[allow(missing_doc)]; + use cmp::{Eq, ApproxEq, Ord}; use ops::{Add, Sub, Mul, Div, Rem, Neg}; use ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr}; diff --git a/src/libcore/num/strconv.rs b/src/libstd/num/strconv.rs similarity index 99% rename from src/libcore/num/strconv.rs rename to src/libstd/num/strconv.rs index 1d65b84b7cec1..30efe9a392233 100644 --- a/src/libcore/num/strconv.rs +++ b/src/libstd/num/strconv.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[allow(missing_doc)]; + use container::Container; use core::cmp::{Ord, Eq}; use ops::{Add, Sub, Mul, Div, Rem, Neg}; diff --git a/src/libstd/num/u16.rs b/src/libstd/num/u16.rs new file mode 100644 index 0000000000000..3a4c2420f9ed5 --- /dev/null +++ b/src/libstd/num/u16.rs @@ -0,0 +1,14 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Operations and constants for `u16` + +pub use self::generated::*; +uint_module!(u16, i16, 16) diff --git a/src/libstd/num/u32.rs b/src/libstd/num/u32.rs new file mode 100644 index 0000000000000..f87fa7fcd426b --- /dev/null +++ b/src/libstd/num/u32.rs @@ -0,0 +1,14 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Operations and constants for `u32` + +pub use self::generated::*; +uint_module!(u32, i32, 32) diff --git a/src/libstd/num/u64.rs b/src/libstd/num/u64.rs new file mode 100644 index 0000000000000..792db1555695a --- /dev/null +++ b/src/libstd/num/u64.rs @@ -0,0 +1,14 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Operations and constants for `u64` + +pub use self::generated::*; +uint_module!(u64, i64, 64) diff --git a/src/libstd/num/u8.rs b/src/libstd/num/u8.rs new file mode 100644 index 0000000000000..e21e80f840678 --- /dev/null +++ b/src/libstd/num/u8.rs @@ -0,0 +1,14 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Operations and constants for `u8` + +pub use self::generated::*; +uint_module!(u8, i8, 8) diff --git a/src/libstd/num/uint.rs b/src/libstd/num/uint.rs new file mode 100644 index 0000000000000..bcb97ff5a07f6 --- /dev/null +++ b/src/libstd/num/uint.rs @@ -0,0 +1,195 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Operations and constants for `uint` + +use iter; +use sys; + +pub use self::generated::*; + +uint_module!(uint, int, ::int::bits) + +/// +/// Divide two numbers, return the result, rounded up. +/// +/// # Arguments +/// +/// * x - an integer +/// * y - an integer distinct from 0u +/// +/// # Return value +/// +/// The smallest integer `q` such that `x/y <= q`. +/// +pub fn div_ceil(x: uint, y: uint) -> uint { + let div = x / y; + if x % y == 0u { div } + else { div + 1u } +} + +/// +/// Divide two numbers, return the result, rounded to the closest integer. +/// +/// # Arguments +/// +/// * x - an integer +/// * y - an integer distinct from 0u +/// +/// # Return value +/// +/// The integer `q` closest to `x/y`. +/// +pub fn div_round(x: uint, y: uint) -> uint { + let div = x / y; + if x % y * 2u < y { div } + else { div + 1u } +} + +/// +/// Divide two numbers, return the result, rounded down. +/// +/// Note: This is the same function as `div`. +/// +/// # Arguments +/// +/// * x - an integer +/// * y - an integer distinct from 0u +/// +/// # Return value +/// +/// The smallest integer `q` such that `x/y <= q`. This +/// is either `x/y` or `x/y + 1`. +/// +pub fn div_floor(x: uint, y: uint) -> uint { return x / y; } + +/// +/// Iterate over the range [`lo`..`hi`), or stop when requested +/// +/// # Arguments +/// +/// * lo - The integer at which to start the loop (included) +/// * hi - The integer at which to stop the loop (excluded) +/// * it - A block to execute with each consecutive integer of the range. +/// Return `true` to continue, `false` to stop. +/// +/// # Return value +/// +/// `true` If execution proceeded correctly, `false` if it was interrupted, +/// that is if `it` returned `false` at any point. +/// +pub fn iterate(lo: uint, hi: uint, it: &fn(uint) -> bool) -> bool { + let mut i = lo; + while i < hi { + if (!it(i)) { return false; } + i += 1u; + } + return true; +} + +impl iter::Times for uint { + #[inline(always)] + /// + /// A convenience form for basic iteration. Given a uint `x`, + /// `for x.times { ... }` executes the given block x times. + /// + /// Equivalent to `for uint::range(0, x) |_| { ... }`. + /// + /// Not defined on all integer types to permit unambiguous + /// use with integer literals of inferred integer-type as + /// the self-value (eg. `for 100.times { ... }`). + /// + fn times(&self, it: &fn() -> bool) -> bool { + let mut i = *self; + while i > 0 { + if !it() { return false; } + i -= 1; + } + return true; + } +} + +/// Returns the smallest power of 2 greater than or equal to `n` +#[inline(always)] +pub fn next_power_of_two(n: uint) -> uint { + let halfbits: uint = sys::size_of::() * 4u; + let mut tmp: uint = n - 1u; + let mut shift: uint = 1u; + while shift <= halfbits { tmp |= tmp >> shift; shift <<= 1u; } + return tmp + 1u; +} + +#[test] +fn test_next_power_of_two() { + assert!((next_power_of_two(0u) == 0u)); + assert!((next_power_of_two(1u) == 1u)); + assert!((next_power_of_two(2u) == 2u)); + assert!((next_power_of_two(3u) == 4u)); + assert!((next_power_of_two(4u) == 4u)); + assert!((next_power_of_two(5u) == 8u)); + assert!((next_power_of_two(6u) == 8u)); + assert!((next_power_of_two(7u) == 8u)); + assert!((next_power_of_two(8u) == 8u)); + assert!((next_power_of_two(9u) == 16u)); + assert!((next_power_of_two(10u) == 16u)); + assert!((next_power_of_two(11u) == 16u)); + assert!((next_power_of_two(12u) == 16u)); + assert!((next_power_of_two(13u) == 16u)); + assert!((next_power_of_two(14u) == 16u)); + assert!((next_power_of_two(15u) == 16u)); + assert!((next_power_of_two(16u) == 16u)); + assert!((next_power_of_two(17u) == 32u)); + assert!((next_power_of_two(18u) == 32u)); + assert!((next_power_of_two(19u) == 32u)); + assert!((next_power_of_two(20u) == 32u)); + assert!((next_power_of_two(21u) == 32u)); + assert!((next_power_of_two(22u) == 32u)); + assert!((next_power_of_two(23u) == 32u)); + assert!((next_power_of_two(24u) == 32u)); + assert!((next_power_of_two(25u) == 32u)); + assert!((next_power_of_two(26u) == 32u)); + assert!((next_power_of_two(27u) == 32u)); + assert!((next_power_of_two(28u) == 32u)); + assert!((next_power_of_two(29u) == 32u)); + assert!((next_power_of_two(30u) == 32u)); + assert!((next_power_of_two(31u) == 32u)); + assert!((next_power_of_two(32u) == 32u)); + assert!((next_power_of_two(33u) == 64u)); + assert!((next_power_of_two(34u) == 64u)); + assert!((next_power_of_two(35u) == 64u)); + assert!((next_power_of_two(36u) == 64u)); + assert!((next_power_of_two(37u) == 64u)); + assert!((next_power_of_two(38u) == 64u)); + assert!((next_power_of_two(39u) == 64u)); +} + +#[test] +fn test_overflows() { + use uint; + assert!((uint::max_value > 0u)); + assert!((uint::min_value <= 0u)); + assert!((uint::min_value + uint::max_value + 1u == 0u)); +} + +#[test] +fn test_div() { + assert!((div_floor(3u, 4u) == 0u)); + assert!((div_ceil(3u, 4u) == 1u)); + assert!((div_round(3u, 4u) == 1u)); +} + +#[test] +pub fn test_times() { + use iter::Times; + let ten = 10 as uint; + let mut accum = 0; + for ten.times { accum += 1; } + assert!((accum == 10)); +} diff --git a/src/libstd/num/uint_macros.rs b/src/libstd/num/uint_macros.rs new file mode 100644 index 0000000000000..a7aebf1f176c2 --- /dev/null +++ b/src/libstd/num/uint_macros.rs @@ -0,0 +1,696 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// FIXME(#4375): this shouldn't have to be a nested module named 'generated' + +#[macro_escape]; + +macro_rules! uint_module (($T:ty, $T_SIGNED:ty, $bits:expr) => (mod generated { + +use num::BitCount; +use num::{ToStrRadix, FromStrRadix}; +use num::{Zero, One, strconv}; +use prelude::*; + +pub use cmp::{min, max}; + +pub static bits : uint = $bits; +pub static bytes : uint = ($bits / 8); + +pub static min_value: $T = 0 as $T; +pub static max_value: $T = 0 as $T - 1 as $T; + +/// Calculates the sum of two numbers +#[inline(always)] +pub fn add(x: $T, y: $T) -> $T { x + y } +/// Subtracts the second number from the first +#[inline(always)] +pub fn sub(x: $T, y: $T) -> $T { x - y } +/// Multiplies two numbers together +#[inline(always)] +pub fn mul(x: $T, y: $T) -> $T { x * y } +/// Divides the first argument by the second argument (using integer division) +#[inline(always)] +pub fn div(x: $T, y: $T) -> $T { x / y } +/// Calculates the integer remainder when x is divided by y (equivalent to the +/// '%' operator) +#[inline(always)] +pub fn rem(x: $T, y: $T) -> $T { x % y } + +/// Returns true iff `x < y` +#[inline(always)] +pub fn lt(x: $T, y: $T) -> bool { x < y } +/// Returns true iff `x <= y` +#[inline(always)] +pub fn le(x: $T, y: $T) -> bool { x <= y } +/// Returns true iff `x == y` +#[inline(always)] +pub fn eq(x: $T, y: $T) -> bool { x == y } +/// Returns true iff `x != y` +#[inline(always)] +pub fn ne(x: $T, y: $T) -> bool { x != y } +/// Returns true iff `x >= y` +#[inline(always)] +pub fn ge(x: $T, y: $T) -> bool { x >= y } +/// Returns true iff `x > y` +#[inline(always)] +pub fn gt(x: $T, y: $T) -> bool { x > y } + +#[inline(always)] +/** + * Iterate through a range with a given step value. + * + * # Examples + * ~~~ {.rust} + * let nums = [1,2,3,4,5,6,7]; + * + * for uint::range_step(0, nums.len() - 1, 2) |i| { + * println(fmt!("%d & %d", nums[i], nums[i+1])); + * } + * ~~~ + */ +pub fn range_step(start: $T, stop: $T, step: $T_SIGNED, it: &fn($T) -> bool) -> bool { + let mut i = start; + if step == 0 { + fail!("range_step called with step == 0"); + } + if step >= 0 { + while i < stop { + if !it(i) { return false; } + // avoiding overflow. break if i + step > max_value + if i > max_value - (step as $T) { return true; } + i += step as $T; + } + } else { + while i > stop { + if !it(i) { return false; } + // avoiding underflow. break if i + step < min_value + if i < min_value + ((-step) as $T) { return true; } + i -= -step as $T; + } + } + return true; +} + +#[inline(always)] +/// Iterate over the range [`lo`..`hi`) +pub fn range(lo: $T, hi: $T, it: &fn($T) -> bool) -> bool { + range_step(lo, hi, 1 as $T_SIGNED, it) +} + +#[inline(always)] +/// Iterate over the range [`hi`..`lo`) +pub fn range_rev(hi: $T, lo: $T, it: &fn($T) -> bool) -> bool { + range_step(hi, lo, -1 as $T_SIGNED, it) +} + +/// Computes the bitwise complement +#[inline(always)] +pub fn compl(i: $T) -> $T { + max_value ^ i +} + +impl Num for $T {} + +#[cfg(not(test))] +impl Ord for $T { + #[inline(always)] + fn lt(&self, other: &$T) -> bool { (*self) < (*other) } + #[inline(always)] + fn le(&self, other: &$T) -> bool { (*self) <= (*other) } + #[inline(always)] + fn ge(&self, other: &$T) -> bool { (*self) >= (*other) } + #[inline(always)] + fn gt(&self, other: &$T) -> bool { (*self) > (*other) } +} + +#[cfg(not(test))] +impl Eq for $T { + #[inline(always)] + fn eq(&self, other: &$T) -> bool { return (*self) == (*other); } + #[inline(always)] + fn ne(&self, other: &$T) -> bool { return (*self) != (*other); } +} + +impl Orderable for $T { + #[inline(always)] + fn min(&self, other: &$T) -> $T { + if *self < *other { *self } else { *other } + } + + #[inline(always)] + fn max(&self, other: &$T) -> $T { + if *self > *other { *self } else { *other } + } + + /// Returns the number constrained within the range `mn <= self <= mx`. + #[inline(always)] + fn clamp(&self, mn: &$T, mx: &$T) -> $T { + cond!( + (*self > *mx) { *mx } + (*self < *mn) { *mn } + _ { *self } + ) + } +} + +impl Zero for $T { + #[inline(always)] + fn zero() -> $T { 0 } + + #[inline(always)] + fn is_zero(&self) -> bool { *self == 0 } +} + +impl One for $T { + #[inline(always)] + fn one() -> $T { 1 } +} + +#[cfg(not(test))] +impl Add<$T,$T> for $T { + #[inline(always)] + fn add(&self, other: &$T) -> $T { *self + *other } +} + +#[cfg(not(test))] +impl Sub<$T,$T> for $T { + #[inline(always)] + fn sub(&self, other: &$T) -> $T { *self - *other } +} + +#[cfg(not(test))] +impl Mul<$T,$T> for $T { + #[inline(always)] + fn mul(&self, other: &$T) -> $T { *self * *other } +} + +#[cfg(not(test))] +impl Div<$T,$T> for $T { + #[inline(always)] + fn div(&self, other: &$T) -> $T { *self / *other } +} + +#[cfg(not(test))] +impl Rem<$T,$T> for $T { + #[inline(always)] + fn rem(&self, other: &$T) -> $T { *self % *other } +} + +#[cfg(not(test))] +impl Neg<$T> for $T { + #[inline(always)] + fn neg(&self) -> $T { -*self } +} + +impl Unsigned for $T {} + +impl Integer for $T { + /// Calculates `div` (`\`) and `rem` (`%`) simultaneously + #[inline(always)] + fn div_rem(&self, other: &$T) -> ($T,$T) { + (*self / *other, *self % *other) + } + + /// Unsigned integer division. Returns the same result as `div` (`/`). + #[inline(always)] + fn div_floor(&self, other: &$T) -> $T { *self / *other } + + /// Unsigned integer modulo operation. Returns the same result as `rem` (`%`). + #[inline(always)] + fn mod_floor(&self, other: &$T) -> $T { *self / *other } + + /// Calculates `div_floor` and `modulo_floor` simultaneously + #[inline(always)] + fn div_mod_floor(&self, other: &$T) -> ($T,$T) { + (*self / *other, *self % *other) + } + + /// Calculates the Greatest Common Divisor (GCD) of the number and `other` + #[inline(always)] + fn gcd(&self, other: &$T) -> $T { + // Use Euclid's algorithm + let mut (m, n) = (*self, *other); + while m != 0 { + let temp = m; + m = n % temp; + n = temp; + } + n + } + + /// Calculates the Lowest Common Multiple (LCM) of the number and `other` + #[inline(always)] + fn lcm(&self, other: &$T) -> $T { + (*self * *other) / self.gcd(other) + } + + /// Returns `true` if the number can be divided by `other` without leaving a remainder + #[inline(always)] + fn is_multiple_of(&self, other: &$T) -> bool { *self % *other == 0 } + + /// Returns `true` if the number is divisible by `2` + #[inline(always)] + fn is_even(&self) -> bool { self.is_multiple_of(&2) } + + /// Returns `true` if the number is not divisible by `2` + #[inline(always)] + fn is_odd(&self) -> bool { !self.is_even() } +} + +impl Bitwise for $T {} + +#[cfg(not(test))] +impl BitOr<$T,$T> for $T { + #[inline(always)] + fn bitor(&self, other: &$T) -> $T { *self | *other } +} + +#[cfg(not(test))] +impl BitAnd<$T,$T> for $T { + #[inline(always)] + fn bitand(&self, other: &$T) -> $T { *self & *other } +} + +#[cfg(not(test))] +impl BitXor<$T,$T> for $T { + #[inline(always)] + fn bitxor(&self, other: &$T) -> $T { *self ^ *other } +} + +#[cfg(not(test))] +impl Shl<$T,$T> for $T { + #[inline(always)] + fn shl(&self, other: &$T) -> $T { *self << *other } +} + +#[cfg(not(test))] +impl Shr<$T,$T> for $T { + #[inline(always)] + fn shr(&self, other: &$T) -> $T { *self >> *other } +} + +#[cfg(not(test))] +impl Not<$T> for $T { + #[inline(always)] + fn not(&self) -> $T { !*self } +} + +impl Bounded for $T { + #[inline(always)] + fn min_value() -> $T { min_value } + + #[inline(always)] + fn max_value() -> $T { max_value } +} + +impl Int for $T {} + +// String conversion functions and impl str -> num + +/// Parse a string as a number in base 10. +#[inline(always)] +pub fn from_str(s: &str) -> Option<$T> { + strconv::from_str_common(s, 10u, false, false, false, + strconv::ExpNone, false, false) +} + +/// Parse a string as a number in the given base. +#[inline(always)] +pub fn from_str_radix(s: &str, radix: uint) -> Option<$T> { + strconv::from_str_common(s, radix, false, false, false, + strconv::ExpNone, false, false) +} + +/// Parse a byte slice as a number in the given base. +#[inline(always)] +pub fn parse_bytes(buf: &[u8], radix: uint) -> Option<$T> { + strconv::from_str_bytes_common(buf, radix, false, false, false, + strconv::ExpNone, false, false) +} + +impl FromStr for $T { + #[inline(always)] + fn from_str(s: &str) -> Option<$T> { + from_str(s) + } +} + +impl FromStrRadix for $T { + #[inline(always)] + fn from_str_radix(s: &str, radix: uint) -> Option<$T> { + from_str_radix(s, radix) + } +} + +// String conversion functions and impl num -> str + +/// Convert to a string as a byte slice in a given base. +#[inline(always)] +pub fn to_str_bytes(n: $T, radix: uint, f: &fn(v: &[u8]) -> U) -> U { + let (buf, _) = strconv::to_str_bytes_common(&n, radix, false, + strconv::SignNeg, strconv::DigAll); + f(buf) +} + +/// Convert to a string in base 10. +#[inline(always)] +pub fn to_str(num: $T) -> ~str { + let (buf, _) = strconv::to_str_common(&num, 10u, false, + strconv::SignNeg, strconv::DigAll); + buf +} + +/// Convert to a string in a given base. +#[inline(always)] +pub fn to_str_radix(num: $T, radix: uint) -> ~str { + let (buf, _) = strconv::to_str_common(&num, radix, false, + strconv::SignNeg, strconv::DigAll); + buf +} + +impl ToStr for $T { + #[inline(always)] + fn to_str(&self) -> ~str { + to_str(*self) + } +} + +impl ToStrRadix for $T { + #[inline(always)] + fn to_str_radix(&self, radix: uint) -> ~str { + to_str_radix(*self, radix) + } +} + +impl Primitive for $T { + #[inline(always)] + fn bits() -> uint { bits } + + #[inline(always)] + fn bytes() -> uint { bits / 8 } +} + +impl BitCount for $T { + /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic. + #[inline(always)] + fn population_count(&self) -> $T { + (*self as $T_SIGNED).population_count() as $T + } + + /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic. + #[inline(always)] + fn leading_zeros(&self) -> $T { + (*self as $T_SIGNED).leading_zeros() as $T + } + + /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic. + #[inline(always)] + fn trailing_zeros(&self) -> $T { + (*self as $T_SIGNED).trailing_zeros() as $T + } +} + +#[cfg(test)] +mod tests { + use super::*; + use prelude::*; + + use num; + use sys; + use u16; + use u32; + use u64; + use u8; + use uint; + + #[test] + fn test_num() { + num::test_num(10 as $T, 2 as $T); + } + + #[test] + fn test_orderable() { + assert_eq!((1 as $T).min(&(2 as $T)), 1 as $T); + assert_eq!((2 as $T).min(&(1 as $T)), 1 as $T); + assert_eq!((1 as $T).max(&(2 as $T)), 2 as $T); + assert_eq!((2 as $T).max(&(1 as $T)), 2 as $T); + assert_eq!((1 as $T).clamp(&(2 as $T), &(4 as $T)), 2 as $T); + assert_eq!((8 as $T).clamp(&(2 as $T), &(4 as $T)), 4 as $T); + assert_eq!((3 as $T).clamp(&(2 as $T), &(4 as $T)), 3 as $T); + } + + #[test] + fn test_gcd() { + assert_eq!((10 as $T).gcd(&2), 2 as $T); + assert_eq!((10 as $T).gcd(&3), 1 as $T); + assert_eq!((0 as $T).gcd(&3), 3 as $T); + assert_eq!((3 as $T).gcd(&3), 3 as $T); + assert_eq!((56 as $T).gcd(&42), 14 as $T); + } + + #[test] + fn test_lcm() { + assert_eq!((1 as $T).lcm(&0), 0 as $T); + assert_eq!((0 as $T).lcm(&1), 0 as $T); + assert_eq!((1 as $T).lcm(&1), 1 as $T); + assert_eq!((8 as $T).lcm(&9), 72 as $T); + assert_eq!((11 as $T).lcm(&5), 55 as $T); + assert_eq!((99 as $T).lcm(&17), 1683 as $T); + } + + #[test] + fn test_multiple_of() { + assert!((6 as $T).is_multiple_of(&(6 as $T))); + assert!((6 as $T).is_multiple_of(&(3 as $T))); + assert!((6 as $T).is_multiple_of(&(1 as $T))); + } + + #[test] + fn test_even() { + assert_eq!((0 as $T).is_even(), true); + assert_eq!((1 as $T).is_even(), false); + assert_eq!((2 as $T).is_even(), true); + assert_eq!((3 as $T).is_even(), false); + assert_eq!((4 as $T).is_even(), true); + } + + #[test] + fn test_odd() { + assert_eq!((0 as $T).is_odd(), false); + assert_eq!((1 as $T).is_odd(), true); + assert_eq!((2 as $T).is_odd(), false); + assert_eq!((3 as $T).is_odd(), true); + assert_eq!((4 as $T).is_odd(), false); + } + + #[test] + fn test_bitwise() { + assert_eq!(0b1110 as $T, (0b1100 as $T).bitor(&(0b1010 as $T))); + assert_eq!(0b1000 as $T, (0b1100 as $T).bitand(&(0b1010 as $T))); + assert_eq!(0b0110 as $T, (0b1100 as $T).bitxor(&(0b1010 as $T))); + assert_eq!(0b1110 as $T, (0b0111 as $T).shl(&(1 as $T))); + assert_eq!(0b0111 as $T, (0b1110 as $T).shr(&(1 as $T))); + assert_eq!(max_value - (0b1011 as $T), (0b1011 as $T).not()); + } + + #[test] + fn test_bitcount() { + assert_eq!((0b010101 as $T).population_count(), 3); + } + + #[test] + fn test_primitive() { + assert_eq!(Primitive::bits::<$T>(), sys::size_of::<$T>() * 8); + assert_eq!(Primitive::bytes::<$T>(), sys::size_of::<$T>()); + } + + #[test] + pub fn test_to_str() { + assert_eq!(to_str_radix(0 as $T, 10u), ~"0"); + assert_eq!(to_str_radix(1 as $T, 10u), ~"1"); + assert_eq!(to_str_radix(2 as $T, 10u), ~"2"); + assert_eq!(to_str_radix(11 as $T, 10u), ~"11"); + assert_eq!(to_str_radix(11 as $T, 16u), ~"b"); + assert_eq!(to_str_radix(255 as $T, 16u), ~"ff"); + assert_eq!(to_str_radix(0xff as $T, 10u), ~"255"); + } + + #[test] + pub fn test_from_str() { + assert_eq!(from_str("0"), Some(0u as $T)); + assert_eq!(from_str("3"), Some(3u as $T)); + assert_eq!(from_str("10"), Some(10u as $T)); + assert_eq!(u32::from_str("123456789"), Some(123456789 as u32)); + assert_eq!(from_str("00100"), Some(100u as $T)); + + assert!(from_str("").is_none()); + assert!(from_str(" ").is_none()); + assert!(from_str("x").is_none()); + } + + #[test] + pub fn test_parse_bytes() { + use str::to_bytes; + assert_eq!(parse_bytes(to_bytes("123"), 10u), Some(123u as $T)); + assert_eq!(parse_bytes(to_bytes("1001"), 2u), Some(9u as $T)); + assert_eq!(parse_bytes(to_bytes("123"), 8u), Some(83u as $T)); + assert_eq!(u16::parse_bytes(to_bytes("123"), 16u), Some(291u as u16)); + assert_eq!(u16::parse_bytes(to_bytes("ffff"), 16u), Some(65535u as u16)); + assert_eq!(parse_bytes(to_bytes("z"), 36u), Some(35u as $T)); + + assert!(parse_bytes(to_bytes("Z"), 10u).is_none()); + assert!(parse_bytes(to_bytes("_"), 2u).is_none()); + } + + #[test] + fn test_uint_to_str_overflow() { + let mut u8_val: u8 = 255_u8; + assert_eq!(u8::to_str(u8_val), ~"255"); + + u8_val += 1 as u8; + assert_eq!(u8::to_str(u8_val), ~"0"); + + let mut u16_val: u16 = 65_535_u16; + assert_eq!(u16::to_str(u16_val), ~"65535"); + + u16_val += 1 as u16; + assert_eq!(u16::to_str(u16_val), ~"0"); + + let mut u32_val: u32 = 4_294_967_295_u32; + assert_eq!(u32::to_str(u32_val), ~"4294967295"); + + u32_val += 1 as u32; + assert_eq!(u32::to_str(u32_val), ~"0"); + + let mut u64_val: u64 = 18_446_744_073_709_551_615_u64; + assert_eq!(u64::to_str(u64_val), ~"18446744073709551615"); + + u64_val += 1 as u64; + assert_eq!(u64::to_str(u64_val), ~"0"); + } + + #[test] + fn test_uint_from_str_overflow() { + let mut u8_val: u8 = 255_u8; + assert_eq!(u8::from_str("255"), Some(u8_val)); + assert!(u8::from_str("256").is_none()); + + u8_val += 1 as u8; + assert_eq!(u8::from_str("0"), Some(u8_val)); + assert!(u8::from_str("-1").is_none()); + + let mut u16_val: u16 = 65_535_u16; + assert_eq!(u16::from_str("65535"), Some(u16_val)); + assert!(u16::from_str("65536").is_none()); + + u16_val += 1 as u16; + assert_eq!(u16::from_str("0"), Some(u16_val)); + assert!(u16::from_str("-1").is_none()); + + let mut u32_val: u32 = 4_294_967_295_u32; + assert_eq!(u32::from_str("4294967295"), Some(u32_val)); + assert!(u32::from_str("4294967296").is_none()); + + u32_val += 1 as u32; + assert_eq!(u32::from_str("0"), Some(u32_val)); + assert!(u32::from_str("-1").is_none()); + + let mut u64_val: u64 = 18_446_744_073_709_551_615_u64; + assert_eq!(u64::from_str("18446744073709551615"), Some(u64_val)); + assert!(u64::from_str("18446744073709551616").is_none()); + + u64_val += 1 as u64; + assert_eq!(u64::from_str("0"), Some(u64_val)); + assert!(u64::from_str("-1").is_none()); + } + + #[test] + #[should_fail] + #[ignore(cfg(windows))] + pub fn to_str_radix1() { + uint::to_str_radix(100u, 1u); + } + + #[test] + #[should_fail] + #[ignore(cfg(windows))] + pub fn to_str_radix37() { + uint::to_str_radix(100u, 37u); + } + + #[test] + pub fn test_ranges() { + let mut l = ~[]; + + for range(0,3) |i| { + l.push(i); + } + for range_rev(13,10) |i| { + l.push(i); + } + for range_step(20,26,2) |i| { + l.push(i); + } + for range_step(36,30,-2) |i| { + l.push(i); + } + for range_step(max_value - 2, max_value, 2) |i| { + l.push(i); + } + for range_step(max_value - 3, max_value, 2) |i| { + l.push(i); + } + for range_step(min_value + 2, min_value, -2) |i| { + l.push(i); + } + for range_step(min_value + 3, min_value, -2) |i| { + l.push(i); + } + + assert_eq!(l, ~[0,1,2, + 13,12,11, + 20,22,24, + 36,34,32, + max_value-2, + max_value-3,max_value-1, + min_value+2, + min_value+3,min_value+1]); + + // None of the `fail`s should execute. + for range(0,0) |_i| { + fail!("unreachable"); + } + for range_rev(0,0) |_i| { + fail!("unreachable"); + } + for range_step(10,0,1) |_i| { + fail!("unreachable"); + } + for range_step(0,1,-10) |_i| { + fail!("unreachable"); + } + } + + #[test] + #[should_fail] + #[ignore(cfg(windows))] + fn test_range_step_zero_step_up() { + for range_step(0,10,0) |_i| {} + } + #[test] + #[should_fail] + #[ignore(cfg(windows))] + fn test_range_step_zero_step_down() { + for range_step(0,-10,0) |_i| {} + } +} + +})) diff --git a/src/libcore/old_iter.rs b/src/libstd/old_iter.rs similarity index 89% rename from src/libcore/old_iter.rs rename to src/libstd/old_iter.rs index 7cffcb10a5321..22ca356fa9b18 100644 --- a/src/libcore/old_iter.rs +++ b/src/libstd/old_iter.rs @@ -14,6 +14,8 @@ */ +#[allow(missing_doc)]; + use cmp::{Eq, Ord}; use kinds::Copy; use option::{None, Option, Some}; @@ -22,39 +24,20 @@ use vec; /// A function used to initialize the elements of a sequence pub type InitOp<'self,T> = &'self fn(uint) -> T; -#[cfg(stage0)] -pub trait BaseIter { - fn each(&self, blk: &fn(v: &A) -> bool); - fn size_hint(&self) -> Option; -} -#[cfg(not(stage0))] pub trait BaseIter { fn each(&self, blk: &fn(v: &A) -> bool) -> bool; fn size_hint(&self) -> Option; } -#[cfg(stage0)] -pub trait ReverseIter: BaseIter { - fn each_reverse(&self, blk: &fn(&A) -> bool); -} -#[cfg(not(stage0))] pub trait ReverseIter: BaseIter { fn each_reverse(&self, blk: &fn(&A) -> bool) -> bool; } -#[cfg(stage0)] -pub trait MutableIter: BaseIter { - fn each_mut(&mut self, blk: &fn(&mut A) -> bool); -} -#[cfg(not(stage0))] pub trait MutableIter: BaseIter { fn each_mut(&mut self, blk: &fn(&mut A) -> bool) -> bool; } pub trait ExtendedIter { - #[cfg(stage0)] - fn eachi(&self, blk: &fn(uint, v: &A) -> bool); - #[cfg(not(stage0))] fn eachi(&self, blk: &fn(uint, v: &A) -> bool) -> bool; fn all(&self, blk: &fn(&A) -> bool) -> bool; fn any(&self, blk: &fn(&A) -> bool) -> bool; @@ -64,11 +47,6 @@ pub trait ExtendedIter { fn flat_map_to_vec>(&self, op: &fn(&A) -> IB) -> ~[B]; } -#[cfg(stage0)] -pub trait ExtendedMutableIter { - fn eachi_mut(&mut self, blk: &fn(uint, &mut A) -> bool); -} -#[cfg(not(stage0))] pub trait ExtendedMutableIter { fn eachi_mut(&mut self, blk: &fn(uint, &mut A) -> bool) -> bool; } @@ -127,11 +105,6 @@ pub fn _eachi>(this: &IA, blk: &fn(uint, &A) -> bool) -> bool { return true; } -#[cfg(stage0)] -pub fn eachi>(this: &IA, blk: &fn(uint, &A) -> bool) { - _eachi(this, blk); -} -#[cfg(not(stage0))] pub fn eachi>(this: &IA, blk: &fn(uint, &A) -> bool) -> bool { _eachi(this, blk) } @@ -238,26 +211,6 @@ pub fn position>(this: &IA, f: &fn(&A) -> bool) // iter interface, such as would provide "reach" in addition to "each". As is, // it would have to be implemented with foldr, which is too inefficient. -#[inline(always)] -#[cfg(stage0)] -pub fn repeat(times: uint, blk: &fn() -> bool) { - let mut i = 0; - while i < times { - if !blk() { break } - i += 1; - } -} -#[inline(always)] -#[cfg(not(stage0))] -pub fn repeat(times: uint, blk: &fn() -> bool) -> bool { - let mut i = 0; - while i < times { - if !blk() { return false; } - i += 1; - } - return true; -} - #[inline(always)] pub fn min>(this: &IA) -> A { match do foldl::,IA>(this, None) |a, b| { diff --git a/src/libcore/ops.rs b/src/libstd/ops.rs similarity index 98% rename from src/libcore/ops.rs rename to src/libstd/ops.rs index 47ff45be68726..77cfe62e49527 100644 --- a/src/libcore/ops.rs +++ b/src/libstd/ops.rs @@ -10,6 +10,8 @@ //! Traits for the built-in operators +#[allow(missing_doc)]; + #[lang="drop"] pub trait Drop { fn finalize(&self); // FIXME(#4332): Rename to "drop"? --pcwalton diff --git a/src/libcore/option.rs b/src/libstd/option.rs similarity index 78% rename from src/libcore/option.rs rename to src/libstd/option.rs index 5aee3077e4866..2386a779235d5 100644 --- a/src/libcore/option.rs +++ b/src/libstd/option.rs @@ -54,21 +54,12 @@ use clone::DeepClone; #[cfg(test)] use str; /// The option type -#[deriving(Clone, Eq)] +#[deriving(Clone, DeepClone, Eq)] pub enum Option { None, Some(T), } -impl DeepClone for Option { - fn deep_clone(&self) -> Option { - match *self { - Some(ref x) => Some(x.deep_clone()), - None => None - } - } -} - impl Ord for Option { fn lt(&self, other: &Option) -> bool { match (self, other) { @@ -89,11 +80,11 @@ impl Ord for Option { } fn ge(&self, other: &Option) -> bool { - ! (self < other) + !(self < other) } fn gt(&self, other: &Option) -> bool { - ! (self <= other) + !(self <= other) } } @@ -112,13 +103,6 @@ impl> Add, Option> for Option { impl BaseIter for Option { /// Performs an operation on the contained value by reference #[inline(always)] - #[cfg(stage0)] - fn each<'a>(&'a self, f: &fn(x: &'a T) -> bool) { - match *self { None => (), Some(ref t) => { f(t); } } - } - /// Performs an operation on the contained value by reference - #[inline(always)] - #[cfg(not(stage0))] fn each<'a>(&'a self, f: &fn(x: &'a T) -> bool) -> bool { match *self { None => true, Some(ref t) => { f(t) } } } @@ -130,12 +114,6 @@ impl BaseIter for Option { } impl MutableIter for Option { - #[cfg(stage0)] - #[inline(always)] - fn each_mut<'a>(&'a mut self, f: &fn(&'a mut T) -> bool) { - match *self { None => (), Some(ref mut t) => { f(t); } } - } - #[cfg(not(stage0))] #[inline(always)] fn each_mut<'a>(&'a mut self, f: &fn(&'a mut T) -> bool) -> bool { match *self { None => true, Some(ref mut t) => { f(t) } } @@ -143,11 +121,6 @@ impl MutableIter for Option { } impl ExtendedIter for Option { - #[cfg(stage0)] - pub fn eachi(&self, blk: &fn(uint, v: &A) -> bool) { - old_iter::eachi(self, blk) - } - #[cfg(not(stage0))] pub fn eachi(&self, blk: &fn(uint, v: &A) -> bool) -> bool { old_iter::eachi(self, blk) } @@ -172,84 +145,81 @@ impl ExtendedIter for Option { } } -pub impl Option { +impl Option { /// Returns true if the option equals `none` - fn is_none(&const self) -> bool { + pub fn is_none(&const self) -> bool { match *self { None => true, Some(_) => false } } /// Returns true if the option contains some value #[inline(always)] - fn is_some(&const self) -> bool { !self.is_none() } + pub fn is_some(&const self) -> bool { !self.is_none() } + /// Update an optional value by optionally running its content through a + /// function that returns an option. #[inline(always)] - fn chain(self, f: &fn(t: T) -> Option) -> Option { - /*! - * Update an optional value by optionally running its content through a - * function that returns an option. - */ - + pub fn chain(self, f: &fn(t: T) -> Option) -> Option { match self { Some(t) => f(t), None => None } } + /// Returns the leftmost Some() value, or None if both are None. #[inline(always)] - fn or(self, optb: Option) -> Option { - /*! - * Returns the leftmost Some() value, or None if both are None. - */ + pub fn or(self, optb: Option) -> Option { match self { Some(opta) => Some(opta), _ => optb } } - /** - * Update an optional value by optionally running its content by reference - * through a function that returns an option. - */ + /// Update an optional value by optionally running its content by reference + /// through a function that returns an option. #[inline(always)] - fn chain_ref<'a, U>(&'a self, f: &fn(x: &'a T) -> Option) -> Option { - match *self { Some(ref x) => f(x), None => None } + pub fn chain_ref<'a, U>(&'a self, f: &fn(x: &'a T) -> Option) + -> Option { + match *self { + Some(ref x) => f(x), + None => None + } } /// Maps a `some` value from one type to another by reference #[inline(always)] - fn map<'a, U>(&self, f: &fn(&'a T) -> U) -> Option { + pub fn map<'a, U>(&self, f: &fn(&'a T) -> U) -> Option { match *self { Some(ref x) => Some(f(x)), None => None } } /// As `map`, but consumes the option and gives `f` ownership to avoid /// copying. #[inline(always)] - fn map_consume(self, f: &fn(v: T) -> U) -> Option { + pub fn map_consume(self, f: &fn(v: T) -> U) -> Option { match self { None => None, Some(v) => Some(f(v)) } } /// Applies a function to the contained value or returns a default #[inline(always)] - fn map_default<'a, U>(&'a self, def: U, f: &fn(&'a T) -> U) -> U { + pub fn map_default<'a, U>(&'a self, def: U, f: &fn(&'a T) -> U) -> U { match *self { None => def, Some(ref t) => f(t) } } /// As `map_default`, but consumes the option and gives `f` /// ownership to avoid copying. #[inline(always)] - fn map_consume_default(self, def: U, f: &fn(v: T) -> U) -> U { + pub fn map_consume_default(self, def: U, f: &fn(v: T) -> U) -> U { match self { None => def, Some(v) => f(v) } } /// Apply a function to the contained value or do nothing - fn mutate(&mut self, f: &fn(T) -> T) { + pub fn mutate(&mut self, f: &fn(T) -> T) { if self.is_some() { *self = Some(f(self.swap_unwrap())); } } /// Apply a function to the contained value or set it to a default - fn mutate_default(&mut self, def: T, f: &fn(T) -> T) { + pub fn mutate_default(&mut self, def: T, f: &fn(T) -> T) { if self.is_some() { *self = Some(f(self.swap_unwrap())); } else { @@ -272,7 +242,7 @@ pub impl Option { case explicitly. */ #[inline(always)] - fn get_ref<'a>(&'a self) -> &'a T { + pub fn get_ref<'a>(&'a self) -> &'a T { match *self { Some(ref x) => x, None => fail!("option::get_ref none") @@ -294,7 +264,7 @@ pub impl Option { case explicitly. */ #[inline(always)] - fn get_mut_ref<'a>(&'a mut self) -> &'a mut T { + pub fn get_mut_ref<'a>(&'a mut self) -> &'a mut T { match *self { Some(ref mut x) => x, None => fail!("option::get_mut_ref none") @@ -302,7 +272,7 @@ pub impl Option { } #[inline(always)] - fn unwrap(self) -> T { + pub fn unwrap(self) -> T { /*! Moves a value out of an option type and returns it. @@ -334,7 +304,7 @@ pub impl Option { * Fails if the value equals `None`. */ #[inline(always)] - fn swap_unwrap(&mut self) -> T { + pub fn swap_unwrap(&mut self) -> T { if self.is_none() { fail!("option::swap_unwrap none") } util::replace(self, None).unwrap() } @@ -348,7 +318,7 @@ pub impl Option { * Fails if the value equals `none` */ #[inline(always)] - fn expect(self, reason: &str) -> T { + pub fn expect(self, reason: &str) -> T { match self { Some(val) => val, None => fail!(reason.to_owned()), @@ -356,7 +326,7 @@ pub impl Option { } } -pub impl Option { +impl Option { /** Gets the value out of an option @@ -372,22 +342,22 @@ pub impl Option { case explicitly. */ #[inline(always)] - fn get(self) -> T { + pub fn get(self) -> T { match self { - Some(copy x) => return x, + Some(x) => return x, None => fail!("option::get none") } } /// Returns the contained value or a default #[inline(always)] - fn get_or_default(self, def: T) -> T { - match self { Some(copy x) => x, None => def } + pub fn get_or_default(self, def: T) -> T { + match self { Some(x) => x, None => def } } /// Applies a function zero or more times until the result is none. #[inline(always)] - fn while_some(self, blk: &fn(v: T) -> Option) { + pub fn while_some(self, blk: &fn(v: T) -> Option) { let mut opt = self; while opt.is_some() { opt = blk(opt.unwrap()); @@ -395,11 +365,14 @@ pub impl Option { } } -pub impl Option { +impl Option { /// Returns the contained value or zero (for this type) #[inline(always)] - fn get_or_zero(self) -> T { - match self { Some(copy x) => x, None => Zero::zero() } + pub fn get_or_zero(self) -> T { + match self { + Some(x) => x, + None => Zero::zero() + } } } @@ -411,7 +384,7 @@ fn test_unwrap_ptr() { let opt = Some(x); let y = opt.unwrap(); let addr_y: *int = ::cast::transmute(&*y); - assert!(addr_x == addr_y); + assert_eq!(addr_x, addr_y); } } @@ -422,7 +395,7 @@ fn test_unwrap_str() { let opt = Some(x); let y = opt.unwrap(); let addr_y = str::as_buf(y, |buf, _len| buf); - assert!(addr_x == addr_y); + assert_eq!(addr_x, addr_y); } #[test] @@ -448,7 +421,7 @@ fn test_unwrap_resource() { let opt = Some(x); let _y = opt.unwrap(); } - assert!(*i == 1); + assert_eq!(*i, 1); } #[test] @@ -459,12 +432,12 @@ fn test_option_dance() { for x.each |_x| { y2 = y.swap_unwrap(); } - assert!(y2 == 5); + assert_eq!(y2, 5); assert!(y.is_none()); } #[test] #[should_fail] #[ignore(cfg(windows))] fn test_option_too_much_dance() { - let mut y = Some(util::NonCopyable()); + let mut y = Some(util::NonCopyable::new()); let _y2 = y.swap_unwrap(); let _y3 = y.swap_unwrap(); } @@ -480,13 +453,13 @@ fn test_option_while_some() { None } } - assert!(i == 11); + assert_eq!(i, 11); } #[test] fn test_get_or_zero() { let some_stuff = Some(42); - assert!(some_stuff.get_or_zero() == 42); + assert_eq!(some_stuff.get_or_zero(), 42); let no_stuff: Option = None; - assert!(no_stuff.get_or_zero() == 0); + assert_eq!(no_stuff.get_or_zero(), 0); } diff --git a/src/libcore/os.rs b/src/libstd/os.rs similarity index 90% rename from src/libcore/os.rs rename to src/libstd/os.rs index b97b32330dec1..446804f7b304d 100644 --- a/src/libcore/os.rs +++ b/src/libstd/os.rs @@ -26,13 +26,17 @@ * to write OS-ignorant code by default. */ +#[allow(missing_doc)]; + use cast; use io; use libc; use libc::{c_char, c_void, c_int, size_t}; use libc::{mode_t, FILE}; +use local_data; use option; use option::{Some, None}; +use os; use prelude::*; use ptr; use str; @@ -43,6 +47,7 @@ use vec; pub use libc::fclose; pub use os::consts::*; +/// Delegates to the libc close() function, returning the same return value. pub fn close(fd: c_int) -> c_int { unsafe { libc::close(fd) @@ -140,33 +145,37 @@ pub mod win32 { pub fn as_utf16_p(s: &str, f: &fn(*u16) -> T) -> T { let mut t = str::to_utf16(s); // Null terminate before passing on. - t += ~[0u16]; + t += [0u16]; vec::as_imm_buf(t, |buf, _len| f(buf)) } } /* Accessing environment variables is not generally threadsafe. -This uses a per-runtime lock to serialize access. -FIXME #4726: It would probably be appropriate to make this a real global +Serialize access through a global lock. */ fn with_env_lock(f: &fn() -> T) -> T { - use unstable::global::global_data_clone_create; - use unstable::sync::{Exclusive, exclusive}; - - struct SharedValue(()); - type ValueMutex = Exclusive; - fn key(_: ValueMutex) { } + use unstable::finally::Finally; unsafe { - let lock: ValueMutex = global_data_clone_create(key, || { - ~exclusive(SharedValue(())) - }); + return do (|| { + rust_take_env_lock(); + f() + }).finally { + rust_drop_env_lock(); + }; + } - lock.with_imm(|_| f() ) + extern { + #[fast_ffi] + fn rust_take_env_lock(); + #[fast_ffi] + fn rust_drop_env_lock(); } } +/// Returns a vector of (variable, value) pairs for all the environment +/// variables of the current process. pub fn env() -> ~[(~str,~str)] { unsafe { #[cfg(windows)] @@ -219,7 +228,7 @@ pub fn env() -> ~[(~str,~str)] { for str::each_splitn_char(*p, '=', 1) |s| { vs.push(s.to_owned()) } debug!("splitting: len: %u", vs.len()); - assert!(vs.len() == 2); + assert_eq!(vs.len(), 2); pairs.push((copy vs[0], copy vs[1])); } pairs @@ -232,6 +241,8 @@ pub fn env() -> ~[(~str,~str)] { } #[cfg(unix)] +/// Fetches the environment variable `n` from the current process, returning +/// None if the variable isn't set. pub fn getenv(n: &str) -> Option<~str> { unsafe { do with_env_lock { @@ -247,6 +258,8 @@ pub fn getenv(n: &str) -> Option<~str> { } #[cfg(windows)] +/// Fetches the environment variable `n` from the current process, returning +/// None if the variable isn't set. pub fn getenv(n: &str) -> Option<~str> { unsafe { do with_env_lock { @@ -262,6 +275,8 @@ pub fn getenv(n: &str) -> Option<~str> { #[cfg(unix)] +/// Sets the environment variable `n` to the value `v` for the currently running +/// process pub fn setenv(n: &str, v: &str) { unsafe { do with_env_lock { @@ -276,6 +291,8 @@ pub fn setenv(n: &str, v: &str) { #[cfg(windows)] +/// Sets the environment variable `n` to the value `v` for the currently running +/// process pub fn setenv(n: &str, v: &str) { unsafe { do with_env_lock { @@ -386,7 +403,7 @@ pub fn pipe() -> Pipe { unsafe { let mut fds = Pipe {in: 0 as c_int, out: 0 as c_int }; - assert!((libc::pipe(&mut fds.in) == (0 as c_int))); + assert_eq!(libc::pipe(&mut fds.in), (0 as c_int)); return Pipe {in: fds.in, out: fds.out}; } } @@ -405,7 +422,7 @@ pub fn pipe() -> Pipe { out: 0 as c_int }; let res = libc::pipe(&mut fds.in, 1024 as ::libc::c_uint, (libc::O_BINARY | libc::O_NOINHERIT) as c_int); - assert!((res == 0 as c_int)); + assert_eq!(res, 0 as c_int); assert!((fds.in != -1 as c_int && fds.in != 0 as c_int)); assert!((fds.out != -1 as c_int && fds.in != 0 as c_int)); return Pipe {in: fds.in, out: fds.out}; @@ -418,13 +435,13 @@ fn dup2(src: c_int, dst: c_int) -> c_int { } } - +/// Returns the proper dll filename for the given basename of a file. pub fn dll_filename(base: &str) -> ~str { - return str::to_owned(DLL_PREFIX) + str::to_owned(base) + - str::to_owned(DLL_SUFFIX) + fmt!("%s%s%s", DLL_PREFIX, base, DLL_SUFFIX) } - +/// Optionally returns the filesystem path to the current executable which is +/// running. If any failure occurs, None is returned. pub fn self_exe_path() -> Option { #[cfg(target_os = "freebsd")] @@ -507,7 +524,7 @@ pub fn self_exe_path() -> Option { * Otherwise, homedir returns option::none. */ pub fn homedir() -> Option { - return match getenv(~"HOME") { + return match getenv("HOME") { Some(ref p) => if !str::is_empty(*p) { Some(Path(*p)) } else { @@ -573,37 +590,8 @@ pub fn tmpdir() -> Path { getenv_nonempty("WINDIR")))).get_or_default(Path("C:\\Windows")) } } -/// Recursively walk a directory structure -#[cfg(stage0)] -pub fn walk_dir(p: &Path, f: &fn(&Path) -> bool) { - - walk_dir_(p, f); - fn walk_dir_(p: &Path, f: &fn(&Path) -> bool) -> bool { - let mut keepgoing = true; - do list_dir(p).each |q| { - let path = &p.push(*q); - if !f(path) { - keepgoing = false; - false - } else { - if path_is_dir(path) { - if !walk_dir_(path, f) { - keepgoing = false; - false - } else { - true - } - } else { - true - } - } - } - return keepgoing; - } -} /// Recursively walk a directory structure -#[cfg(not(stage0))] pub fn walk_dir(p: &Path, f: &fn(&Path) -> bool) -> bool { list_dir(p).each(|q| { let path = &p.push(*q); @@ -702,6 +690,11 @@ pub fn mkdir_recursive(p: &Path, mode: c_int) -> bool { /// Lists the contents of a directory #[allow(non_implicitly_copyable_typarams)] pub fn list_dir(p: &Path) -> ~[~str] { + if p.components.is_empty() && !p.is_absolute() { + // Not sure what the right behavior is here, but this + // prevents a bounds check failure later + return ~[]; + } unsafe { #[cfg(target_os = "linux")] #[cfg(target_os = "android")] @@ -749,7 +742,7 @@ pub fn list_dir(p: &Path) -> ~[~str] { use os::win32::{ as_utf16_p }; - use unstable::exchange_alloc::{malloc_raw, free_raw}; + use rt::global_heap::{malloc_raw, free_raw}; #[nolink] extern { unsafe fn rust_list_dir_wfd_size() -> libc::size_t; @@ -848,6 +841,8 @@ pub fn remove_dir(p: &Path) -> bool { } } +/// Changes the current working directory to the specified path, returning +/// whether the change was completed successfully or not. pub fn change_dir(p: &Path) -> bool { return chdir(p); @@ -883,20 +878,18 @@ pub fn change_dir_locked(p: &Path, action: &fn()) -> bool { fn key(_: Exclusive<()>) { } - let result = unsafe { - global_data_clone_create(key, || { - ~exclusive(()) - }) - }; + unsafe { + let result = global_data_clone_create(key, || { ~exclusive(()) }); - do result.with_imm() |_| { - let old_dir = os::getcwd(); - if change_dir(p) { - action(); - change_dir(&old_dir) - } - else { - false + do result.with_imm() |_| { + let old_dir = os::getcwd(); + if change_dir(p) { + action(); + change_dir(&old_dir) + } + else { + false + } } } } @@ -1003,6 +996,7 @@ pub fn remove_file(p: &Path) -> bool { } #[cfg(unix)] +/// Returns the platform-specific value of errno pub fn errno() -> int { #[cfg(target_os = "macos")] #[cfg(target_os = "freebsd")] @@ -1034,6 +1028,7 @@ pub fn errno() -> int { } #[cfg(windows)] +/// Returns the platform-specific value of errno pub fn errno() -> uint { use libc::types::os::arch::extra::DWORD; @@ -1233,6 +1228,11 @@ struct OverriddenArgs { fn overridden_arg_key(_v: @OverriddenArgs) {} +/// Returns the arguments which this program was started with (normally passed +/// via the command line). +/// +/// The return value of the function can be changed by invoking the +/// `os::set_args` function. pub fn args() -> ~[~str] { unsafe { match local_data::local_data_get(overridden_arg_key) { @@ -1242,6 +1242,9 @@ pub fn args() -> ~[~str] { } } +/// For the current task, overrides the task-local cache of the arguments this +/// program had when it started. These new arguments are only available to the +/// current task via the `os::args` method. pub fn set_args(new_args: ~[~str]) { unsafe { let overridden_args = @OverriddenArgs { val: copy new_args }; @@ -1471,16 +1474,16 @@ mod tests { #[test] fn test_setenv() { let n = make_rand_name(); - setenv(n, ~"VALUE"); - assert!(getenv(n) == option::Some(~"VALUE")); + setenv(n, "VALUE"); + assert_eq!(getenv(n), option::Some(~"VALUE")); } #[test] fn test_unsetenv() { let n = make_rand_name(); - setenv(n, ~"VALUE"); + setenv(n, "VALUE"); unsetenv(n); - assert!(getenv(n) == option::None); + assert_eq!(getenv(n), option::None); } #[test] @@ -1488,11 +1491,11 @@ mod tests { #[ignore] fn test_setenv_overwrite() { let n = make_rand_name(); - setenv(n, ~"1"); - setenv(n, ~"2"); - assert!(getenv(n) == option::Some(~"2")); - setenv(n, ~""); - assert!(getenv(n) == option::Some(~"")); + setenv(n, "1"); + setenv(n, "2"); + assert_eq!(getenv(n), option::Some(~"2")); + setenv(n, ""); + assert_eq!(getenv(n), option::Some(~"")); } // Windows GetEnvironmentVariable requires some extra work to make sure @@ -1503,11 +1506,11 @@ mod tests { fn test_getenv_big() { let mut s = ~""; let mut i = 0; - while i < 100 { s += ~"aaaaaaaaaa"; i += 1; } + while i < 100 { s += "aaaaaaaaaa"; i += 1; } let n = make_rand_name(); setenv(n, s); debug!(copy s); - assert!(getenv(n) == option::Some(s)); + assert_eq!(getenv(n), option::Some(s)); } #[test] @@ -1542,7 +1545,7 @@ mod tests { let n = make_rand_name(); let mut e = env(); - setenv(n, ~"VALUE"); + setenv(n, "VALUE"); assert!(!vec::contains(e, &(copy n, ~"VALUE"))); e = env(); @@ -1553,7 +1556,7 @@ mod tests { fn test() { assert!((!Path("test-path").is_absolute)); - debug!(~"Current working directory: " + getcwd().to_str()); + debug!("Current working directory: %s", getcwd().to_str()); debug!(make_absolute(&Path("test-path"))); debug!(make_absolute(&Path("/usr/bin"))); @@ -1562,43 +1565,43 @@ mod tests { #[test] #[cfg(unix)] fn homedir() { - let oldhome = getenv(~"HOME"); + let oldhome = getenv("HOME"); - setenv(~"HOME", ~"/home/MountainView"); - assert!(os::homedir() == Some(Path("/home/MountainView"))); + setenv("HOME", "/home/MountainView"); + assert_eq!(os::homedir(), Some(Path("/home/MountainView"))); - setenv(~"HOME", ~""); + setenv("HOME", ""); assert!(os::homedir().is_none()); - for oldhome.each |s| { setenv(~"HOME", *s) } + for oldhome.each |s| { setenv("HOME", *s) } } #[test] #[cfg(windows)] fn homedir() { - let oldhome = getenv(~"HOME"); - let olduserprofile = getenv(~"USERPROFILE"); + let oldhome = getenv("HOME"); + let olduserprofile = getenv("USERPROFILE"); - setenv(~"HOME", ~""); - setenv(~"USERPROFILE", ~""); + setenv("HOME", ""); + setenv("USERPROFILE", ""); assert!(os::homedir().is_none()); - setenv(~"HOME", ~"/home/MountainView"); - assert!(os::homedir() == Some(Path("/home/MountainView"))); + setenv("HOME", "/home/MountainView"); + assert_eq!(os::homedir(), Some(Path("/home/MountainView"))); - setenv(~"HOME", ~""); + setenv("HOME", ""); - setenv(~"USERPROFILE", ~"/home/MountainView"); - assert!(os::homedir() == Some(Path("/home/MountainView"))); + setenv("USERPROFILE", "/home/MountainView"); + assert_eq!(os::homedir(), Some(Path("/home/MountainView"))); - setenv(~"HOME", ~"/home/MountainView"); - setenv(~"USERPROFILE", ~"/home/PaloAlto"); - assert!(os::homedir() == Some(Path("/home/MountainView"))); + setenv("HOME", "/home/MountainView"); + setenv("USERPROFILE", "/home/PaloAlto"); + assert_eq!(os::homedir(), Some(Path("/home/MountainView"))); - oldhome.each(|s| {setenv(~"HOME", *s);true}); - olduserprofile.each(|s| {setenv(~"USERPROFILE", *s);true}); + oldhome.each(|s| { setenv("HOME", *s); true }); + olduserprofile.each(|s| { setenv("USERPROFILE", *s); true }); } #[test] @@ -1623,6 +1626,26 @@ mod tests { } } + #[test] + fn list_dir_empty_path() { + let dirs = os::list_dir(&Path("")); + assert!(dirs.is_empty()); + } + + #[test] + #[cfg(not(windows))] + fn list_dir_root() { + let dirs = os::list_dir(&Path("/")); + assert!(dirs.len() > 1); + } + #[test] + #[cfg(windows)] + fn list_dir_root() { + let dirs = os::list_dir(&Path("C:\\")); + assert!(dirs.len() > 1); + } + + #[test] fn path_is_dir() { assert!((os::path_is_dir(&Path(".")))); @@ -1660,22 +1683,22 @@ mod tests { }; assert!((ostream as uint != 0u)); let s = ~"hello"; - let mut buf = str::to_bytes(s) + ~[0 as u8]; + let mut buf = str::to_bytes(s) + [0 as u8]; do vec::as_mut_buf(buf) |b, _len| { assert!((libc::fwrite(b as *c_void, 1u as size_t, (str::len(s) + 1u) as size_t, ostream) == buf.len() as size_t)) } - assert!((libc::fclose(ostream) == (0u as c_int))); + assert_eq!(libc::fclose(ostream), (0u as c_int)); let in_mode = in.get_mode(); let rs = os::copy_file(&in, &out); if (!os::path_exists(&in)) { fail!("%s doesn't exist", in.to_str()); } assert!((rs)); - let rslt = run::run_program(~"diff", ~[in.to_str(), out.to_str()]); - assert!((rslt == 0)); - assert!(out.get_mode() == in_mode); + let rslt = run::process_status("diff", [in.to_str(), out.to_str()]); + assert_eq!(rslt, 0); + assert_eq!(out.get_mode(), in_mode); assert!((remove_file(&in))); assert!((remove_file(&out))); } diff --git a/src/libcore/owned.rs b/src/libstd/owned.rs similarity index 100% rename from src/libcore/owned.rs rename to src/libstd/owned.rs diff --git a/src/libcore/path.rs b/src/libstd/path.rs similarity index 83% rename from src/libcore/path.rs rename to src/libstd/path.rs index 2015c5474be32..a551b9bf3c0b3 100644 --- a/src/libcore/path.rs +++ b/src/libstd/path.rs @@ -14,6 +14,8 @@ Cross-platform file path handling */ +#[allow(missing_doc)]; + use container::Container; use cmp::Eq; use libc; @@ -306,45 +308,47 @@ mod stat { } -pub impl Path { - fn stat(&self) -> Option { +impl Path { + pub fn stat(&self) -> Option { unsafe { do str::as_c_str(self.to_str()) |buf| { let mut st = stat::arch::default_stat(); - let r = libc::stat(buf, &mut st); - - if r == 0 { Some(st) } else { None } + match libc::stat(buf, &mut st) { + 0 => Some(st), + _ => None, + } } } } #[cfg(unix)] - fn lstat(&self) -> Option { + pub fn lstat(&self) -> Option { unsafe { do str::as_c_str(self.to_str()) |buf| { let mut st = stat::arch::default_stat(); - let r = libc::lstat(buf, &mut st); - - if r == 0 { Some(st) } else { None } + match libc::lstat(buf, &mut st) { + 0 => Some(st), + _ => None, + } } } } - fn exists(&self) -> bool { + pub fn exists(&self) -> bool { match self.stat() { None => false, Some(_) => true, } } - fn get_size(&self) -> Option { + pub fn get_size(&self) -> Option { match self.stat() { None => None, Some(ref st) => Some(st.st_size as i64), } } - fn get_mode(&self) -> Option { + pub fn get_mode(&self) -> Option { match self.stat() { None => None, Some(ref st) => Some(st.st_mode as uint), @@ -355,8 +359,8 @@ pub impl Path { #[cfg(target_os = "freebsd")] #[cfg(target_os = "linux")] #[cfg(target_os = "macos")] -pub impl Path { - fn get_atime(&self) -> Option<(i64, int)> { +impl Path { + pub fn get_atime(&self) -> Option<(i64, int)> { match self.stat() { None => None, Some(ref st) => { @@ -366,7 +370,7 @@ pub impl Path { } } - fn get_mtime(&self) -> Option<(i64, int)> { + pub fn get_mtime(&self) -> Option<(i64, int)> { match self.stat() { None => None, Some(ref st) => { @@ -376,7 +380,7 @@ pub impl Path { } } - fn get_ctime(&self) -> Option<(i64, int)> { + pub fn get_ctime(&self) -> Option<(i64, int)> { match self.stat() { None => None, Some(ref st) => { @@ -389,8 +393,8 @@ pub impl Path { #[cfg(target_os = "freebsd")] #[cfg(target_os = "macos")] -pub impl Path { - fn get_birthtime(&self) -> Option<(i64, int)> { +impl Path { + pub fn get_birthtime(&self) -> Option<(i64, int)> { match self.stat() { None => None, Some(ref st) => { @@ -402,8 +406,8 @@ pub impl Path { } #[cfg(target_os = "win32")] -pub impl Path { - fn get_atime(&self) -> Option<(i64, int)> { +impl Path { + pub fn get_atime(&self) -> Option<(i64, int)> { match self.stat() { None => None, Some(ref st) => { @@ -412,7 +416,7 @@ pub impl Path { } } - fn get_mtime(&self) -> Option<(i64, int)> { + pub fn get_mtime(&self) -> Option<(i64, int)> { match self.stat() { None => None, Some(ref st) => { @@ -421,7 +425,7 @@ pub impl Path { } } - fn get_ctime(&self) -> Option<(i64, int)> { + pub fn get_ctime(&self) -> Option<(i64, int)> { match self.stat() { None => None, Some(ref st) => { @@ -450,55 +454,56 @@ impl GenericPath for PosixPath { components.push(s.to_owned()) } let is_absolute = (s.len() != 0 && s[0] == '/' as u8); - return PosixPath { is_absolute: is_absolute, - components: components } + PosixPath { + is_absolute: is_absolute, + components: components, + } } fn dirname(&self) -> ~str { let s = self.dir_path().to_str(); - if s.len() == 0 { - ~"." - } else { - s + match s.len() { + 0 => ~".", + _ => s, } } fn filename(&self) -> Option<~str> { match self.components.len() { - 0 => None, - n => Some(copy self.components[n - 1]) + 0 => None, + n => Some(copy self.components[n - 1]), } } fn filestem(&self) -> Option<~str> { match self.filename() { - None => None, - Some(ref f) => { - match str::rfind_char(*f, '.') { - Some(p) => Some(f.slice(0, p).to_owned()), - None => Some(copy *f) + None => None, + Some(ref f) => { + match str::rfind_char(*f, '.') { + Some(p) => Some(f.slice(0, p).to_owned()), + None => Some(copy *f), + } } - } } } fn filetype(&self) -> Option<~str> { match self.filename() { - None => None, - Some(ref f) => { - match str::rfind_char(*f, '.') { - Some(p) if p < f.len() => Some(f.slice(p, f.len()).to_owned()), - _ => None + None => None, + Some(ref f) => { + match str::rfind_char(*f, '.') { + Some(p) if p < f.len() => Some(f.slice(p, f.len()).to_owned()), + _ => None, + } } - } } } fn with_dirname(&self, d: &str) -> PosixPath { let dpath = PosixPath(d); match self.filename() { - Some(ref f) => dpath.push(*f), - None => dpath + Some(ref f) => dpath.push(*f), + None => dpath, } } @@ -509,31 +514,24 @@ impl GenericPath for PosixPath { fn with_filestem(&self, s: &str) -> PosixPath { match self.filetype() { - None => self.with_filename(s), - Some(ref t) => self.with_filename(str::to_owned(s) + *t) + None => self.with_filename(s), + Some(ref t) => self.with_filename(str::to_owned(s) + *t), } } fn with_filetype(&self, t: &str) -> PosixPath { - if t.len() == 0 { - match self.filestem() { - None => copy *self, - Some(ref s) => self.with_filename(*s) - } - } else { - let t = ~"." + str::to_owned(t); - match self.filestem() { - None => self.with_filename(t), - Some(ref s) => self.with_filename(*s + t) - } + match (t.len(), self.filestem()) { + (0, None) => copy *self, + (0, Some(ref s)) => self.with_filename(*s), + (_, None) => self.with_filename(fmt!(".%s", t)), + (_, Some(ref s)) => self.with_filename(fmt!("%s.%s", *s, t)), } } fn dir_path(&self) -> PosixPath { - if self.components.len() != 0 { - self.pop() - } else { - copy *self + match self.components.len() { + 0 => copy *self, + _ => self.pop(), } } @@ -542,8 +540,10 @@ impl GenericPath for PosixPath { None => ~[], Some(ref f) => ~[copy *f] }; - return PosixPath { is_absolute: false, - components: cs } + PosixPath { + is_absolute: false, + components: cs, + } } fn push_rel(&self, other: &PosixPath) -> PosixPath { @@ -553,8 +553,10 @@ impl GenericPath for PosixPath { fn unsafe_join(&self, other: &PosixPath) -> PosixPath { if other.is_absolute { - PosixPath { is_absolute: true, - components: copy other.components } + PosixPath { + is_absolute: true, + components: copy other.components, + } } else { self.push_rel(other) } @@ -573,8 +575,10 @@ impl GenericPath for PosixPath { } v.push_all_move(ss); } - PosixPath { is_absolute: self.is_absolute, - components: v } + PosixPath { + is_absolute: self.is_absolute, + components: v, + } } fn push(&self, s: &str) -> PosixPath { @@ -592,19 +596,17 @@ impl GenericPath for PosixPath { if cs.len() != 0 { cs.pop(); } - return PosixPath { + PosixPath { is_absolute: self.is_absolute, - components: cs - } - //..self } + components: cs, + } //..self } } fn normalize(&self) -> PosixPath { - return PosixPath { + PosixPath { is_absolute: self.is_absolute, - components: normalize(self.components) - // ..self - } + components: normalize(self.components), + } // ..self } } fn is_absolute(&self) -> bool { @@ -638,26 +640,25 @@ impl GenericPath for WindowsPath { let device; let rest; - match windows::extract_drive_prefix(s) { - Some((ref d, ref r)) => { - host = None; - device = Some(copy *d); - rest = copy *r; - } - None => { - match windows::extract_unc_prefix(s) { - Some((ref h, ref r)) => { + match ( + windows::extract_drive_prefix(s), + windows::extract_unc_prefix(s), + ) { + (Some((ref d, ref r)), _) => { + host = None; + device = Some(copy *d); + rest = copy *r; + } + (None, Some((ref h, ref r))) => { host = Some(copy *h); device = None; rest = copy *r; - } - None => { + } + (None, None) => { host = None; device = None; rest = str::to_owned(s); - } } - } } let mut components = ~[]; @@ -665,37 +666,38 @@ impl GenericPath for WindowsPath { components.push(s.to_owned()) } let is_absolute = (rest.len() != 0 && windows::is_sep(rest[0])); - return WindowsPath { host: host, - device: device, - is_absolute: is_absolute, - components: components } + WindowsPath { + host: host, + device: device, + is_absolute: is_absolute, + components: components, + } } fn dirname(&self) -> ~str { let s = self.dir_path().to_str(); - if s.len() == 0 { - ~"." - } else { - s + match s.len() { + 0 => ~".", + _ => s, } } fn filename(&self) -> Option<~str> { match self.components.len() { - 0 => None, - n => Some(copy self.components[n - 1]) + 0 => None, + n => Some(copy self.components[n - 1]), } } fn filestem(&self) -> Option<~str> { match self.filename() { - None => None, - Some(ref f) => { - match str::rfind_char(*f, '.') { - Some(p) => Some(f.slice(0, p).to_owned()), - None => Some(copy *f) + None => None, + Some(ref f) => { + match str::rfind_char(*f, '.') { + Some(p) => Some(f.slice(0, p).to_owned()), + None => Some(copy *f), + } } - } } } @@ -704,8 +706,8 @@ impl GenericPath for WindowsPath { None => None, Some(ref f) => { match str::rfind_char(*f, '.') { - Some(p) if p < f.len() => Some(f.slice(p, f.len()).to_owned()), - _ => None + Some(p) if p < f.len() => Some(f.slice(p, f.len()).to_owned()), + _ => None, } } } @@ -714,8 +716,8 @@ impl GenericPath for WindowsPath { fn with_dirname(&self, d: &str) -> WindowsPath { let dpath = WindowsPath(d); match self.filename() { - Some(ref f) => dpath.push(*f), - None => dpath + Some(ref f) => dpath.push(*f), + None => dpath, } } @@ -726,44 +728,37 @@ impl GenericPath for WindowsPath { fn with_filestem(&self, s: &str) -> WindowsPath { match self.filetype() { - None => self.with_filename(s), - Some(ref t) => self.with_filename(str::to_owned(s) + *t) + None => self.with_filename(s), + Some(ref t) => self.with_filename(str::to_owned(s) + *t), } } fn with_filetype(&self, t: &str) -> WindowsPath { - if t.len() == 0 { - match self.filestem() { - None => copy *self, - Some(ref s) => self.with_filename(*s) - } - } else { - let t = ~"." + str::to_owned(t); - match self.filestem() { - None => self.with_filename(t), - Some(ref s) => - self.with_filename(*s + t) - } + match (t.len(), self.filestem()) { + (0, None) => copy *self, + (0, Some(ref s)) => self.with_filename(*s), + (_, None) => self.with_filename(fmt!(".%s", t)), + (_, Some(ref s)) => self.with_filename(fmt!("%s.%s", *s, t)), } } fn dir_path(&self) -> WindowsPath { - if self.components.len() != 0 { - self.pop() - } else { - copy *self + match self.components.len() { + 0 => copy *self, + _ => self.pop(), } } fn file_path(&self) -> WindowsPath { - let cs = match self.filename() { - None => ~[], - Some(ref f) => ~[copy *f] - }; - return WindowsPath { host: None, - device: None, - is_absolute: false, - components: cs } + WindowsPath { + host: None, + device: None, + is_absolute: false, + components: match self.filename() { + None => ~[], + Some(ref f) => ~[copy *f], + } + } } fn push_rel(&self, other: &WindowsPath) -> WindowsPath { @@ -779,12 +774,12 @@ impl GenericPath for WindowsPath { /* if rhs has a host set, then the whole thing wins */ match other.host { - Some(copy host) => { + Some(ref host) => { return WindowsPath { - host: Some(host), + host: Some(copy *host), device: copy other.device, is_absolute: true, - components: copy other.components + components: copy other.components, }; } _ => {} @@ -792,12 +787,12 @@ impl GenericPath for WindowsPath { /* if rhs has a device set, then a part wins */ match other.device { - Some(copy device) => { + Some(ref device) => { return WindowsPath { host: None, - device: Some(device), + device: Some(copy *device), is_absolute: true, - components: copy other.components + components: copy other.components, }; } _ => {} @@ -809,7 +804,7 @@ impl GenericPath for WindowsPath { host: copy self.host, device: copy self.device, is_absolute: self.is_absolute || other.is_absolute, - components: copy other.components + components: copy other.components, } } @@ -838,7 +833,7 @@ impl GenericPath for WindowsPath { v.push_all_move(ss); } // tedious, but as-is, we can't use ..self - return WindowsPath { + WindowsPath { host: copy self.host, device: copy self.device, is_absolute: self.is_absolute, @@ -853,7 +848,7 @@ impl GenericPath for WindowsPath { ss.push(s.to_owned()) } v.push_all_move(ss); - return WindowsPath { components: v, ..copy *self } + WindowsPath { components: v, ..copy *self } } fn pop(&self) -> WindowsPath { @@ -861,16 +856,16 @@ impl GenericPath for WindowsPath { if cs.len() != 0 { cs.pop(); } - return WindowsPath { + WindowsPath { host: copy self.host, device: copy self.device, is_absolute: self.is_absolute, - components: cs + components: cs, } } fn normalize(&self) -> WindowsPath { - return WindowsPath { + WindowsPath { host: copy self.host, device: match self.device { None => None, @@ -959,30 +954,30 @@ mod tests { let path = PosixPath("tmp/"); let path = path.push("/hmm"); let path = path.normalize(); - assert!(~"tmp/hmm" == path.to_str()); + assert_eq!(~"tmp/hmm", path.to_str()); let path = WindowsPath("tmp/"); let path = path.push("/hmm"); let path = path.normalize(); - assert!(~"tmp\\hmm" == path.to_str()); + assert_eq!(~"tmp\\hmm", path.to_str()); } #[test] fn test_filetype_foo_bar() { let wp = PosixPath("foo.bar"); - assert!(wp.filetype() == Some(~".bar")); + assert_eq!(wp.filetype(), Some(~".bar")); let wp = WindowsPath("foo.bar"); - assert!(wp.filetype() == Some(~".bar")); + assert_eq!(wp.filetype(), Some(~".bar")); } #[test] fn test_filetype_foo() { let wp = PosixPath("foo"); - assert!(wp.filetype() == None); + assert_eq!(wp.filetype(), None); let wp = WindowsPath("foo"); - assert!(wp.filetype() == None); + assert_eq!(wp.filetype(), None); } #[test] @@ -993,7 +988,7 @@ mod tests { if (ss != sss) { debug!("got %s", ss); debug!("expected %s", sss); - assert!(ss == sss); + assert_eq!(ss, sss); } } @@ -1051,7 +1046,7 @@ mod tests { if (ss != sss) { debug!("got %s", ss); debug!("expected %s", sss); - assert!(ss == sss); + assert_eq!(ss, sss); } } @@ -1114,7 +1109,7 @@ mod tests { if (ss != sss) { debug!("got %s", ss); debug!("expected %s", sss); - assert!(ss == sss); + assert_eq!(ss, sss); } } @@ -1199,9 +1194,9 @@ mod tests { #[test] fn test_windows_path_restrictions() { - assert!(WindowsPath("hi").is_restricted() == false); - assert!(WindowsPath("C:\\NUL").is_restricted() == true); - assert!(WindowsPath("C:\\COM1.TXT").is_restricted() == true); - assert!(WindowsPath("c:\\prn.exe").is_restricted() == true); + assert_eq!(WindowsPath("hi").is_restricted(), false); + assert_eq!(WindowsPath("C:\\NUL").is_restricted(), true); + assert_eq!(WindowsPath("C:\\COM1.TXT").is_restricted(), true); + assert_eq!(WindowsPath("c:\\prn.exe").is_restricted(), true); } } diff --git a/src/libcore/pipes.rs b/src/libstd/pipes.rs similarity index 94% rename from src/libcore/pipes.rs rename to src/libstd/pipes.rs index c0cf4c052c509..fe1b834813e8b 100644 --- a/src/libcore/pipes.rs +++ b/src/libstd/pipes.rs @@ -16,7 +16,7 @@ the other can receive messages. The set of legal messages and which directions they can flow at any given point are determined by a protocol. Below is an example protocol. -~~~ +~~~ {.rust} proto! pingpong ( ping: send { ping -> pong @@ -82,6 +82,8 @@ bounded and unbounded protocols allows for less code duplication. */ +#[allow(missing_doc)]; + use container::Container; use cast::{forget, transmute, transmute_copy}; use either::{Either, Left, Right}; @@ -92,7 +94,7 @@ use option::{None, Option, Some}; use unstable::finally::Finally; use unstable::intrinsics; use ptr; -use ptr::Ptr; +use ptr::RawPtr; use task; use vec; use vec::OwnedVector; @@ -150,16 +152,16 @@ pub fn PacketHeader() -> PacketHeader { } } -pub impl PacketHeader { +impl PacketHeader { // Returns the old state. - unsafe fn mark_blocked(&mut self, this: *rust_task) -> State { + pub unsafe fn mark_blocked(&mut self, this: *rust_task) -> State { rustrt::rust_task_ref(this); let old_task = swap_task(&mut self.blocked_task, this); assert!(old_task.is_null()); swap_state_acq(&mut self.state, Blocked) } - unsafe fn unblock(&mut self) { + pub unsafe fn unblock(&mut self) { let old_task = swap_task(&mut self.blocked_task, ptr::null()); if !old_task.is_null() { rustrt::rust_task_deref(old_task) @@ -174,12 +176,12 @@ pub impl PacketHeader { // unsafe because this can do weird things to the space/time // continuum. It ends making multiple unique pointers to the same // thing. You'll probably want to forget them when you're done. - unsafe fn buf_header(&mut self) -> ~BufferHeader { + pub unsafe fn buf_header(&mut self) -> ~BufferHeader { assert!(self.buffer.is_not_null()); transmute_copy(&self.buffer) } - fn set_buffer(&mut self, b: ~Buffer) { + pub fn set_buffer(&mut self, b: ~Buffer) { unsafe { self.buffer = transmute_copy(&b); } @@ -235,11 +237,11 @@ pub fn packet() -> *mut Packet { pub fn entangle_buffer( mut buffer: ~Buffer, init: &fn(*libc::c_void, x: &mut T) -> *mut Packet) - -> (SendPacketBuffered, RecvPacketBuffered) { + -> (RecvPacketBuffered, SendPacketBuffered) { unsafe { let p = init(transmute_copy(&buffer), &mut buffer.data); forget(buffer); - (SendPacketBuffered(p), RecvPacketBuffered(p)) + (RecvPacketBuffered(p), SendPacketBuffered(p)) } } @@ -353,7 +355,7 @@ pub fn send(mut p: SendPacketBuffered, let header = p.header(); let p_ = p.unwrap(); let p = unsafe { &mut *p_ }; - assert!(ptr::to_unsafe_ptr(&(p.header)) == header); + assert_eq!(ptr::to_unsafe_ptr(&(p.header)), header); assert!(p.payload.is_none()); p.payload = Some(payload); let old_state = swap_state_rel(&mut p.header.state, Full); @@ -494,7 +496,7 @@ fn try_recv_(p: &mut Packet) -> Option { Terminated => { // This assert detects when we've accidentally unsafely // casted too big of a number to a state. - assert!(old_state == Terminated); + assert_eq!(old_state, Terminated); let old_task = swap_task(&mut p.header.blocked_task, ptr::null()); if !old_task.is_null() { @@ -566,7 +568,7 @@ fn receiver_terminate(p: *mut Packet) { if !old_task.is_null() { unsafe { rustrt::rust_task_deref(old_task); - assert!(old_task == rustrt::rust_get_task()); + assert_eq!(old_task, rustrt::rust_get_task()); } } } @@ -692,12 +694,12 @@ pub fn SendPacketBuffered(p: *mut Packet) } } -pub impl SendPacketBuffered { - fn unwrap(&mut self) -> *mut Packet { +impl SendPacketBuffered { + pub fn unwrap(&mut self) -> *mut Packet { replace(&mut self.p, None).unwrap() } - fn header(&mut self) -> *mut PacketHeader { + pub fn header(&mut self) -> *mut PacketHeader { match self.p { Some(packet) => unsafe { let packet = &mut *packet; @@ -708,7 +710,7 @@ pub impl SendPacketBuffered { } } - fn reuse_buffer(&mut self) -> BufferResource { + pub fn reuse_buffer(&mut self) -> BufferResource { //error!("send reuse_buffer"); replace(&mut self.buffer, None).unwrap() } @@ -740,12 +742,12 @@ impl Drop for RecvPacketBuffered { } } -pub impl RecvPacketBuffered { - fn unwrap(&mut self) -> *mut Packet { +impl RecvPacketBuffered { + pub fn unwrap(&mut self) -> *mut Packet { replace(&mut self.p, None).unwrap() } - fn reuse_buffer(&mut self) -> BufferResource { + pub fn reuse_buffer(&mut self) -> BufferResource { replace(&mut self.buffer, None).unwrap() } } @@ -773,9 +775,9 @@ pub fn RecvPacketBuffered(p: *mut Packet) } } -pub fn entangle() -> (SendPacket, RecvPacket) { +pub fn entangle() -> (RecvPacket, SendPacket) { let p = packet(); - (SendPacket(p), RecvPacket(p)) + (RecvPacket(p), SendPacket(p)) } /** Receives a message from one of two endpoints. @@ -785,20 +787,20 @@ or `right` if the second endpoint receives something. In each case, the result includes the other endpoint as well so it can be used again. Below is an example of using `select2`. -~~~ +~~~ {.rust} match select2(a, b) { - left((none, b)) { - // endpoint a was closed. - } - right((a, none)) { - // endpoint b was closed. - } - left((Some(_), b)) { - // endpoint a received a message - } - right(a, Some(_)) { - // endpoint b received a message. - } + left((none, b)) { + // endpoint a was closed. + } + right((a, none)) { + // endpoint b was closed. + } + left((Some(_), b)) { + // endpoint a received a message + } + right(a, Some(_)) { + // endpoint b received a message. + } } ~~~ diff --git a/src/libcore/prelude.rs b/src/libstd/prelude.rs similarity index 60% rename from src/libcore/prelude.rs rename to src/libstd/prelude.rs index 4ed648161fc22..ab8a699a50299 100644 --- a/src/libcore/prelude.rs +++ b/src/libstd/prelude.rs @@ -8,12 +8,28 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! The Rust prelude. Imported into every module by default. +/*! -/* Reexported core operators */ +Many programming languages have a 'prelude': a particular subset of the +libraries that come with the language. Every program imports the prelude by +default. +For example, it would be annoying to add `use io::println;` to every single +program, and the vast majority of Rust programs will wish to print to standard +output. Therefore, it makes sense to import it into every program. + +Rust's prelude has three main parts: + +1. io::print and io::println. +2. Core operators, such as `Add`, `Mul`, and `Not`. +3. Various types and traits, such as `Clone`, `Eq`, and `comm::Chan`. + +*/ + + +// Reexported core operators pub use either::{Either, Left, Right}; -pub use kinds::{Const, Copy, Owned}; +pub use kinds::{Const, Copy, Owned, Sized}; pub use ops::{Add, Sub, Mul, Div, Rem, Neg, Not}; pub use ops::{BitAnd, BitOr, BitXor}; pub use ops::{Drop}; @@ -21,14 +37,13 @@ pub use ops::{Shl, Shr, Index}; pub use option::{Option, Some, None}; pub use result::{Result, Ok, Err}; -/* Reexported functions */ - +// Reexported functions pub use io::{print, println}; -/* Reexported types and traits */ - +// Reexported types and traits pub use clone::{Clone, DeepClone}; pub use cmp::{Eq, ApproxEq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater, Equiv}; +pub use char::Char; pub use container::{Container, Mutable, Map, Set}; pub use hash::Hash; pub use old_iter::{BaseIter, ReverseIter, MutableIter, ExtendedIter, EqIter}; @@ -45,60 +60,25 @@ pub use path::GenericPath; pub use path::Path; pub use path::PosixPath; pub use path::WindowsPath; -pub use ptr::Ptr; +pub use ptr::RawPtr; pub use ascii::{Ascii, AsciiCast, OwnedAsciiCast, AsciiStr}; -pub use str::{StrSlice, OwnedStr}; +pub use str::{StrVector, StrSlice, OwnedStr, StrUtil}; pub use from_str::{FromStr}; pub use to_bytes::IterBytes; pub use to_str::{ToStr, ToStrConsume}; pub use tuple::{CopyableTuple, ImmutableTuple, ExtendedTupleOps}; -pub use vec::{CopyableVector, ImmutableVector}; +pub use tuple::{CloneableTuple2, CloneableTuple3, CloneableTuple4, CloneableTuple5}; +pub use tuple::{CloneableTuple6, CloneableTuple7, CloneableTuple8, CloneableTuple9}; +pub use tuple::{CloneableTuple10, CloneableTuple11, CloneableTuple12}; +pub use tuple::{ImmutableTuple2, ImmutableTuple3, ImmutableTuple4, ImmutableTuple5}; +pub use tuple::{ImmutableTuple6, ImmutableTuple7, ImmutableTuple8, ImmutableTuple9}; +pub use tuple::{ImmutableTuple10, ImmutableTuple11, ImmutableTuple12}; +pub use vec::{VectorVector, CopyableVector, ImmutableVector}; pub use vec::{ImmutableEqVector, ImmutableCopyableVector}; pub use vec::{OwnedVector, OwnedCopyableVector, MutableVector}; pub use io::{Reader, ReaderUtil, Writer, WriterUtil}; -/* Reexported runtime types */ +// Reexported runtime types pub use comm::{stream, Port, Chan, GenericChan, GenericSmartChan, GenericPort, Peekable}; pub use task::spawn; -/* Reexported modules */ - -pub use at_vec; -pub use bool; -pub use cast; -pub use char; -pub use cmp; -pub use either; -pub use f32; -pub use f64; -pub use float; -pub use i16; -pub use i32; -pub use i64; -pub use i8; -pub use int; -pub use io; -pub use iter; -pub use old_iter; -pub use libc; -pub use local_data; -pub use num; -pub use ops; -pub use option; -pub use os; -pub use path; -pub use comm; -pub use unstable; -pub use ptr; -pub use rand; -pub use result; -pub use str; -pub use sys; -pub use task; -pub use to_str; -pub use u16; -pub use u32; -pub use u64; -pub use u8; -pub use uint; -pub use vec; diff --git a/src/libcore/ptr.rs b/src/libstd/ptr.rs similarity index 62% rename from src/libcore/ptr.rs rename to src/libstd/ptr.rs index e116dc0194310..c656a3eef62c3 100644 --- a/src/libcore/ptr.rs +++ b/src/libstd/ptr.rs @@ -11,13 +11,16 @@ //! Unsafe pointer utility functions use cast; -use libc; -use libc::{c_void, size_t}; +#[cfg(stage0)] use libc; +#[cfg(stage0)] use libc::{c_void, size_t}; +use option::{Option, Some, None}; use sys; +use unstable::intrinsics; #[cfg(not(test))] use cmp::{Eq, Ord}; use uint; +#[cfg(stage0)] pub mod libc_ { use libc::c_void; use libc; @@ -25,12 +28,6 @@ pub mod libc_ { #[nolink] #[abi = "cdecl"] pub extern { - #[rust_stack] - unsafe fn memmove(dest: *mut c_void, - src: *const c_void, - n: libc::size_t) - -> *c_void; - #[rust_stack] unsafe fn memset(dest: *mut c_void, c: libc::c_int, @@ -75,11 +72,11 @@ pub unsafe fn position(buf: *T, f: &fn(&T) -> bool) -> uint { /// Create an unsafe null pointer #[inline(always)] -pub fn null() -> *T { unsafe { cast::transmute(0u) } } +pub fn null() -> *T { 0 as *T } /// Create an unsafe mutable null pointer #[inline(always)] -pub fn mut_null() -> *mut T { unsafe { cast::transmute(0u) } } +pub fn mut_null() -> *mut T { 0 as *mut T } /// Returns true if the pointer is equal to the null pointer. #[inline(always)] @@ -96,74 +93,166 @@ pub fn is_not_null(ptr: *const T) -> bool { !is_null(ptr) } * and destination may overlap. */ #[inline(always)] -#[cfg(target_word_size = "32")] +#[cfg(target_word_size = "32", stage0)] pub unsafe fn copy_memory(dst: *mut T, src: *const T, count: uint) { use unstable::intrinsics::memmove32; let n = count * sys::size_of::(); memmove32(dst as *mut u8, src as *u8, n as u32); } + +/** + * Copies data from one location to another + * + * Copies `count` elements (not bytes) from `src` to `dst`. The source + * and destination may overlap. + */ +#[inline(always)] +#[cfg(target_word_size = "32", not(stage0))] +pub unsafe fn copy_memory(dst: *mut T, src: *const T, count: uint) { + use unstable::intrinsics::memmove32; + memmove32(dst, src as *T, count as u32); +} + #[inline(always)] -#[cfg(target_word_size = "64")] +#[cfg(target_word_size = "64", stage0)] pub unsafe fn copy_memory(dst: *mut T, src: *const T, count: uint) { use unstable::intrinsics::memmove64; let n = count * sys::size_of::(); memmove64(dst as *mut u8, src as *u8, n as u64); } +/** + * Copies data from one location to another + * + * Copies `count` elements (not bytes) from `src` to `dst`. The source + * and destination may overlap. + */ #[inline(always)] +#[cfg(target_word_size = "64", not(stage0))] +pub unsafe fn copy_memory(dst: *mut T, src: *const T, count: uint) { + use unstable::intrinsics::memmove64; + memmove64(dst, src as *T, count as u64); +} + +#[inline(always)] +#[cfg(target_word_size = "32", stage0)] +pub unsafe fn copy_nonoverlapping_memory(dst: *mut T, src: *const T, count: uint) { + use unstable::intrinsics::memmove32; + let n = count * sys::size_of::(); + memmove32(dst as *mut u8, src as *u8, n as u32); +} + +/** + * Copies data from one location to another. This uses memcpy instead of memmove + * to take advantage of the knowledge that the memory does not overlap. + * + * Copies `count` elements (not bytes) from `src` to `dst`. The source + * and destination may overlap. + */ +#[inline(always)] +#[cfg(target_word_size = "32", not(stage0))] +pub unsafe fn copy_nonoverlapping_memory(dst: *mut T, src: *const T, count: uint) { + use unstable::intrinsics::memcpy32; + memcpy32(dst, src as *T, count as u32); +} + +#[inline(always)] +#[cfg(target_word_size = "64", stage0)] +pub unsafe fn copy_nonoverlapping_memory(dst: *mut T, src: *const T, count: uint) { + use unstable::intrinsics::memmove64; + let n = count * sys::size_of::(); + memmove64(dst as *mut u8, src as *u8, n as u64); +} + +/** + * Copies data from one location to another. This uses memcpy instead of memmove + * to take advantage of the knowledge that the memory does not overlap. + * + * Copies `count` elements (not bytes) from `src` to `dst`. The source + * and destination may overlap. + */ +#[inline(always)] +#[cfg(target_word_size = "64", not(stage0))] +pub unsafe fn copy_nonoverlapping_memory(dst: *mut T, src: *const T, count: uint) { + use unstable::intrinsics::memcpy64; + memcpy64(dst, src as *T, count as u64); +} + +#[inline(always)] +#[cfg(stage0)] pub unsafe fn set_memory(dst: *mut T, c: int, count: uint) { let n = count * sys::size_of::(); libc_::memset(dst as *mut c_void, c as libc::c_int, n as size_t); } /** - Transform a region pointer - &T - to an unsafe pointer - *T. - This is safe, but is implemented with an unsafe block due to - transmute. -*/ + * Invokes memset on the specified pointer, setting `count` bytes of memory + * starting at `dst` to `c`. + */ #[inline(always)] -pub fn to_unsafe_ptr(thing: &T) -> *T { - unsafe { cast::transmute(thing) } +#[cfg(target_word_size = "32", not(stage0))] +pub unsafe fn set_memory(dst: *mut T, c: u8, count: uint) { + use unstable::intrinsics::memset32; + memset32(dst, c, count as u32); } /** - Transform a const region pointer - &const T - to a const unsafe pointer - - *const T. This is safe, but is implemented with an unsafe block due to - transmute. -*/ + * Invokes memset on the specified pointer, setting `count` bytes of memory + * starting at `dst` to `c`. + */ #[inline(always)] -pub fn to_const_unsafe_ptr(thing: &const T) -> *const T { - unsafe { cast::transmute(thing) } +#[cfg(target_word_size = "64", not(stage0))] +pub unsafe fn set_memory(dst: *mut T, c: u8, count: uint) { + use unstable::intrinsics::memset64; + memset64(dst, c, count as u64); } /** - Transform a mutable region pointer - &mut T - to a mutable unsafe pointer - - *mut T. This is safe, but is implemented with an unsafe block due to - transmute. -*/ -#[inline(always)] -pub fn to_mut_unsafe_ptr(thing: &mut T) -> *mut T { - unsafe { cast::transmute(thing) } + * Swap the values at two mutable locations of the same type, without + * deinitialising or copying either one. + */ +#[inline] +pub unsafe fn swap_ptr(x: *mut T, y: *mut T) { + // Give ourselves some scratch space to work with + let mut tmp: T = intrinsics::uninit(); + let t: *mut T = &mut tmp; + + // Perform the swap + copy_memory(t, x, 1); + copy_memory(x, y, 1); + copy_memory(y, t, 1); + + // y and t now point to the same thing, but we need to completely forget `tmp` + // because it's no longer relevant. + cast::forget(tmp); } /** - Cast a region pointer - &T - to a uint. - This is safe, but is implemented with an unsafe block due to - transmute. + * Replace the value at a mutable location with a new one, returning the old + * value, without deinitialising or copying either one. + */ +#[inline(always)] +pub unsafe fn replace_ptr(dest: *mut T, mut src: T) -> T { + swap_ptr(dest, &mut src); + src +} - (I couldn't think of a cutesy name for this one.) -*/ +/// Transform a region pointer - &T - to an unsafe pointer - *T. #[inline(always)] -pub fn to_uint(thing: &T) -> uint { - unsafe { - cast::transmute(thing) - } +pub fn to_unsafe_ptr(thing: &T) -> *T { + thing as *T } -/// Determine if two borrowed pointers point to the same thing. +/// Transform a const region pointer - &const T - to a const unsafe pointer - *const T. #[inline(always)] -pub fn ref_eq<'a,'b,T>(thing: &'a T, other: &'b T) -> bool { - to_uint(thing) == to_uint(other) +pub fn to_const_unsafe_ptr(thing: &const T) -> *const T { + thing as *const T +} + +/// Transform a mutable region pointer - &mut T - to a mutable unsafe pointer - *mut T. +#[inline(always)] +pub fn to_mut_unsafe_ptr(thing: &mut T) -> *mut T { + thing as *mut T } /** @@ -206,14 +295,16 @@ pub unsafe fn array_each(arr: **T, cb: &fn(*T)) { array_each_with_len(arr, len, cb); } -pub trait Ptr { +#[allow(missing_doc)] +pub trait RawPtr { fn is_null(&const self) -> bool; fn is_not_null(&const self) -> bool; + unsafe fn to_option(&const self) -> Option<&T>; fn offset(&self, count: uint) -> Self; } /// Extension methods for immutable pointers -impl Ptr for *T { +impl RawPtr for *T { /// Returns true if the pointer is equal to the null pointer. #[inline(always)] fn is_null(&const self) -> bool { is_null(*self) } @@ -222,13 +313,30 @@ impl Ptr for *T { #[inline(always)] fn is_not_null(&const self) -> bool { is_not_null(*self) } + /// + /// Returns `None` if the pointer is null, or else returns the value wrapped + /// in `Some`. + /// + /// # Safety Notes + /// + /// While this method is useful for null-safety, it is important to note + /// that this is still an unsafe operation because the returned value could + /// be pointing to invalid memory. + /// + #[inline(always)] + unsafe fn to_option(&const self) -> Option<&T> { + if self.is_null() { None } else { + Some(cast::transmute(*self)) + } + } + /// Calculates the offset from a pointer. #[inline(always)] fn offset(&self, count: uint) -> *T { offset(*self, count) } } /// Extension methods for mutable pointers -impl Ptr for *mut T { +impl RawPtr for *mut T { /// Returns true if the pointer is equal to the null pointer. #[inline(always)] fn is_null(&const self) -> bool { is_null(*self) } @@ -237,6 +345,23 @@ impl Ptr for *mut T { #[inline(always)] fn is_not_null(&const self) -> bool { is_not_null(*self) } + /// + /// Returns `None` if the pointer is null, or else returns the value wrapped + /// in `Some`. + /// + /// # Safety Notes + /// + /// While this method is useful for null-safety, it is important to note + /// that this is still an unsafe operation because the returned value could + /// be pointing to invalid memory. + /// + #[inline(always)] + unsafe fn to_option(&const self) -> Option<&T> { + if self.is_null() { None } else { + Some(cast::transmute(*self)) + } + } + /// Calculates the offset from a mutable pointer. #[inline(always)] fn offset(&self, count: uint) -> *mut T { mut_offset(*self, count) } @@ -247,14 +372,10 @@ impl Ptr for *mut T { impl Eq for *const T { #[inline(always)] fn eq(&self, other: &*const T) -> bool { - unsafe { - let a: uint = cast::transmute(*self); - let b: uint = cast::transmute(*other); - return a == b; - } + (*self as uint) == (*other as uint) } #[inline(always)] - fn ne(&self, other: &*const T) -> bool { !(*self).eq(other) } + fn ne(&self, other: &*const T) -> bool { !self.eq(other) } } // Comparison for pointers @@ -262,69 +383,19 @@ impl Eq for *const T { impl Ord for *const T { #[inline(always)] fn lt(&self, other: &*const T) -> bool { - unsafe { - let a: uint = cast::transmute(*self); - let b: uint = cast::transmute(*other); - return a < b; - } + (*self as uint) < (*other as uint) } #[inline(always)] fn le(&self, other: &*const T) -> bool { - unsafe { - let a: uint = cast::transmute(*self); - let b: uint = cast::transmute(*other); - return a <= b; - } + (*self as uint) <= (*other as uint) } #[inline(always)] fn ge(&self, other: &*const T) -> bool { - unsafe { - let a: uint = cast::transmute(*self); - let b: uint = cast::transmute(*other); - return a >= b; - } + (*self as uint) >= (*other as uint) } #[inline(always)] fn gt(&self, other: &*const T) -> bool { - unsafe { - let a: uint = cast::transmute(*self); - let b: uint = cast::transmute(*other); - return a > b; - } - } -} - -// Equality for region pointers -#[cfg(not(test))] -impl<'self,T:Eq> Eq for &'self T { - #[inline(always)] - fn eq(&self, other: & &'self T) -> bool { - return *(*self) == *(*other); - } - #[inline(always)] - fn ne(&self, other: & &'self T) -> bool { - return *(*self) != *(*other); - } -} - -// Comparison for region pointers -#[cfg(not(test))] -impl<'self,T:Ord> Ord for &'self T { - #[inline(always)] - fn lt(&self, other: & &'self T) -> bool { - *(*self) < *(*other) - } - #[inline(always)] - fn le(&self, other: & &'self T) -> bool { - *(*self) <= *(*other) - } - #[inline(always)] - fn ge(&self, other: & &'self T) -> bool { - *(*self) >= *(*other) - } - #[inline(always)] - fn gt(&self, other: & &'self T) -> bool { - *(*self) > *(*other) + (*self as uint) > (*other as uint) } } @@ -333,6 +404,11 @@ pub mod ptr_tests { use super::*; use prelude::*; + use cast; + use libc; + use str; + use vec; + #[test] fn test() { unsafe { @@ -343,15 +419,15 @@ pub mod ptr_tests { let mut p = Pair {fst: 10, snd: 20}; let pptr: *mut Pair = &mut p; let iptr: *mut int = cast::transmute(pptr); - assert!((*iptr == 10));; + assert_eq!(*iptr, 10); *iptr = 30; - assert!((*iptr == 30)); - assert!((p.fst == 30));; + assert_eq!(*iptr, 30); + assert_eq!(p.fst, 30); *pptr = Pair {fst: 50, snd: 60}; - assert!((*iptr == 50)); - assert!((p.fst == 50)); - assert!((p.snd == 60)); + assert_eq!(*iptr, 50); + assert_eq!(p.fst, 50); + assert_eq!(p.snd, 60); let v0 = ~[32000u16, 32001u16, 32002u16]; let mut v1 = ~[0u16, 0u16, 0u16]; @@ -396,8 +472,8 @@ pub mod ptr_tests { do str::as_c_str(s2) |p2| { let v = ~[p0, p1, p2, null()]; do vec::as_imm_buf(v) |vp, len| { - assert!(unsafe { buf_len(vp) } == 3u); - assert!(len == 4u); + assert_eq!(unsafe { buf_len(vp) }, 3u); + assert_eq!(len, 4u); } } } @@ -423,6 +499,22 @@ pub mod ptr_tests { assert!(mq.is_not_null()); } + #[test] + fn test_to_option() { + unsafe { + let p: *int = null(); + assert_eq!(p.to_option(), None); + + let q: *int = &2; + assert_eq!(q.to_option().unwrap(), &2); + + let p: *mut int = mut_null(); + assert_eq!(p.to_option(), None); + + let q: *mut int = &mut 2; + assert_eq!(q.to_option().unwrap(), &2); + } + } #[test] fn test_ptr_array_each_with_len() { @@ -448,11 +540,11 @@ pub mod ptr_tests { debug!( "test_ptr_array_each e: %s, a: %s", expected, actual); - assert!(actual == expected); + assert_eq!(actual, expected); ctr += 1; iteration_count += 1; }); - assert!(iteration_count == 3u); + assert_eq!(iteration_count, 3u); } } #[test] @@ -480,11 +572,11 @@ pub mod ptr_tests { debug!( "test_ptr_array_each e: %s, a: %s", expected, actual); - assert!(actual == expected); + assert_eq!(actual, expected); ctr += 1; iteration_count += 1; }); - assert!(iteration_count == 3); + assert_eq!(iteration_count, 3); } } #[test] @@ -507,4 +599,12 @@ pub mod ptr_tests { }); } } + + #[test] + fn test_set_memory() { + let mut xs = [0u8, ..20]; + let ptr = vec::raw::to_mut_ptr(xs); + unsafe { set_memory(ptr, 5u8, xs.len()); } + assert_eq!(xs, [5u8, ..20]); + } } diff --git a/src/libcore/rand.rs b/src/libstd/rand.rs similarity index 91% rename from src/libcore/rand.rs rename to src/libstd/rand.rs index daf0b9d094aca..b763c1c2d7617 100644 --- a/src/libcore/rand.rs +++ b/src/libstd/rand.rs @@ -20,18 +20,19 @@ See the `distributions` submodule for sampling random numbers from distributions like normal and exponential. # Examples -~~~ + +~~~ {.rust} use core::rand::RngUtil; fn main() { - let rng = rand::rng(); + let mut rng = rand::rng(); if rng.gen() { // bool println(fmt!("int: %d, uint: %u", rng.gen(), rng.gen())) } } ~~~ -~~~ +~~~ {.rust} fn main () { let tuple_ptr = rand::random::<~(f64, char)>(); println(fmt!("%?", tuple_ptr)) @@ -39,10 +40,13 @@ fn main () { ~~~ */ - +use cast; +use cmp; use int; +use local_data; use prelude::*; use str; +use sys; use u32; use uint; use util; @@ -54,6 +58,8 @@ pub mod distributions; /// A type that can be randomly generated using an Rng pub trait Rand { + /// Generates a random instance of this type using the specified source of + /// randomness fn rand(rng: &mut R) -> Self; } @@ -252,10 +258,13 @@ pub trait Rng { /// A value with a particular weight compared to other values pub struct Weighted { + /// The numerical weight of this item weight: uint, + /// The actual item which is being weighted item: T, } +/// Helper functions attached to the Rng type pub trait RngUtil { /// Return a random value of a Rand type fn gen(&mut self) -> T; @@ -276,9 +285,9 @@ pub trait RngUtil { /** * Return a bool with a 1 in n chance of true * - * *Example* + * # Example * - * ~~~ + * ~~~ {.rust} * * use core::rand::RngUtil; * @@ -292,9 +301,9 @@ pub trait RngUtil { /** * Return a random string of the specified length composed of A-Z,a-z,0-9 * - * *Example* + * # Example * - * ~~~ + * ~~~ {.rust} * * use core::rand::RngUtil; * @@ -308,9 +317,9 @@ pub trait RngUtil { /** * Return a random byte string of the specified length * - * *Example* + * # Example * - * ~~~ + * ~~~ {.rust} * * use core::rand::RngUtil; * @@ -324,9 +333,9 @@ pub trait RngUtil { /** * Choose an item randomly, failing if values is empty * - * *Example* + * # Example * - * ~~~ + * ~~~ {.rust} * * use core::rand::RngUtil; * @@ -343,9 +352,9 @@ pub trait RngUtil { * Choose an item respecting the relative weights, failing if the sum of * the weights is 0 * - * *Example* + * # Example * - * ~~~ + * ~~~ {.rust} * * use core::rand::RngUtil; * @@ -363,9 +372,9 @@ pub trait RngUtil { * Choose Some(item) respecting the relative weights, returning none if * the sum of the weights is 0 * - * *Example* + * # Example * - * ~~~ + * ~~~ {.rust} * * use core::rand::RngUtil; * @@ -384,9 +393,9 @@ pub trait RngUtil { * Return a vec containing copies of the items, in order, where * the weight of the item determines how many copies there are * - * *Example* + * # Example * - * ~~~ + * ~~~ {.rust} * * use core::rand::RngUtil; * @@ -403,9 +412,9 @@ pub trait RngUtil { /** * Shuffle a vec * - * *Example* + * # Example * - * ~~~ + * ~~~ {.rust} * * use core::rand::RngUtil; * @@ -419,9 +428,9 @@ pub trait RngUtil { /** * Shuffle a mutable vec in place * - * *Example* + * # Example * - * ~~~ + * ~~~ {.rust} * * use core::rand::RngUtil; * @@ -603,9 +612,9 @@ pub struct IsaacRng { priv c: u32 } -pub impl IsaacRng { +impl IsaacRng { /// Create an ISAAC random number generator with a random seed. - fn new() -> IsaacRng { + pub fn new() -> IsaacRng { IsaacRng::new_seeded(seed()) } @@ -614,7 +623,7 @@ pub impl IsaacRng { /// will be silently ignored. A generator constructed with a given seed /// will generate the same sequence of values as all other generators /// constructed with the same seed. - fn new_seeded(seed: &[u8]) -> IsaacRng { + pub fn new_seeded(seed: &[u8]) -> IsaacRng { let mut rng = IsaacRng { cnt: 0, rsl: [0, .. RAND_SIZE], @@ -634,7 +643,7 @@ pub impl IsaacRng { /// Create an ISAAC random number generator using the default /// fixed seed. - fn new_unseeded() -> IsaacRng { + pub fn new_unseeded() -> IsaacRng { let mut rng = IsaacRng { cnt: 0, rsl: [0, .. RAND_SIZE], @@ -648,14 +657,15 @@ pub impl IsaacRng { /// Initialises `self`. If `use_rsl` is true, then use the current value /// of `rsl` as a seed, otherwise construct one algorithmically (not /// randomly). - priv fn init(&mut self, use_rsl: bool) { - macro_rules! init_mut_many ( - ($( $var:ident ),* = $val:expr ) => { - let mut $( $var = $val ),*; - } - ); - init_mut_many!(a, b, c, d, e, f, g, h = 0x9e3779b9); - + fn init(&mut self, use_rsl: bool) { + let mut a = 0x9e3779b9; + let mut b = a; + let mut c = a; + let mut d = a; + let mut e = a; + let mut f = a; + let mut g = a; + let mut h = a; macro_rules! mix( () => {{ @@ -706,12 +716,12 @@ pub impl IsaacRng { /// Refills the output buffer (`self.rsl`) #[inline] - priv fn isaac(&mut self) { + fn isaac(&mut self) { self.c += 1; // abbreviations - let mut a = self.a, b = self.b + self.c; + let mut (a, b) = (self.a, self.b + self.c); - static midpoint: uint = RAND_SIZE as uint / 2; + static midpoint: uint = RAND_SIZE as uint / 2; macro_rules! ind (($x:expr) => { self.mem[($x >> 2) & (RAND_SIZE - 1)] @@ -786,9 +796,9 @@ impl Rng for XorShiftRng { } } -pub impl XorShiftRng { +impl XorShiftRng { /// Create an xor shift random number generator with a default seed. - fn new() -> XorShiftRng { + pub fn new() -> XorShiftRng { // constants taken from http://en.wikipedia.org/wiki/Xorshift XorShiftRng::new_seeded(123456789u32, 362436069u32, @@ -798,10 +808,10 @@ pub impl XorShiftRng { /** * Create a random number generator using the specified seed. A generator - * constructed with a given seed will generate the same sequence of values as - * all other generators constructed with the same seed. + * constructed with a given seed will generate the same sequence of values + * as all other generators constructed with the same seed. */ - fn new_seeded(x: u32, y: u32, z: u32, w: u32) -> XorShiftRng { + pub fn new_seeded(x: u32, y: u32, z: u32, w: u32) -> XorShiftRng { XorShiftRng { x: x, y: y, @@ -880,7 +890,7 @@ mod tests { let seed = seed(); let mut ra = IsaacRng::new_seeded(seed); let mut rb = IsaacRng::new_seeded(seed); - assert!(ra.gen_str(100u) == rb.gen_str(100u)); + assert_eq!(ra.gen_str(100u), rb.gen_str(100u)); } #[test] @@ -889,7 +899,7 @@ mod tests { let seed = [2u8, 32u8, 4u8, 32u8, 51u8]; let mut ra = IsaacRng::new_seeded(seed); let mut rb = IsaacRng::new_seeded(seed); - assert!(ra.gen_str(100u) == rb.gen_str(100u)); + assert_eq!(ra.gen_str(100u), rb.gen_str(100u)); } #[test] @@ -908,8 +918,8 @@ mod tests { let mut r = rng(); let a = r.gen_int_range(-3, 42); assert!(a >= -3 && a < 42); - assert!(r.gen_int_range(0, 1) == 0); - assert!(r.gen_int_range(-12, -11) == -12); + assert_eq!(r.gen_int_range(0, 1), 0); + assert_eq!(r.gen_int_range(-12, -11), -12); } #[test] @@ -925,8 +935,8 @@ mod tests { let mut r = rng(); let a = r.gen_uint_range(3u, 42u); assert!(a >= 3u && a < 42u); - assert!(r.gen_uint_range(0u, 1u) == 0u); - assert!(r.gen_uint_range(12u, 13u) == 12u); + assert_eq!(r.gen_uint_range(0u, 1u), 0u); + assert_eq!(r.gen_uint_range(12u, 13u), 12u); } #[test] @@ -948,8 +958,8 @@ mod tests { #[test] fn test_gen_weighted_bool() { let mut r = rng(); - assert!(r.gen_weighted_bool(0u) == true); - assert!(r.gen_weighted_bool(1u) == true); + assert_eq!(r.gen_weighted_bool(0u), true); + assert_eq!(r.gen_weighted_bool(1u), true); } #[test] @@ -958,23 +968,23 @@ mod tests { debug!(r.gen_str(10u)); debug!(r.gen_str(10u)); debug!(r.gen_str(10u)); - assert!(r.gen_str(0u).len() == 0u); - assert!(r.gen_str(10u).len() == 10u); - assert!(r.gen_str(16u).len() == 16u); + assert_eq!(r.gen_str(0u).len(), 0u); + assert_eq!(r.gen_str(10u).len(), 10u); + assert_eq!(r.gen_str(16u).len(), 16u); } #[test] fn test_gen_bytes() { let mut r = rng(); - assert!(r.gen_bytes(0u).len() == 0u); - assert!(r.gen_bytes(10u).len() == 10u); - assert!(r.gen_bytes(16u).len() == 16u); + assert_eq!(r.gen_bytes(0u).len(), 0u); + assert_eq!(r.gen_bytes(10u).len(), 10u); + assert_eq!(r.gen_bytes(16u).len(), 16u); } #[test] fn test_choose() { let mut r = rng(); - assert!(r.choose([1, 1, 1]) == 1); + assert_eq!(r.choose([1, 1, 1]), 1); } #[test] @@ -982,16 +992,16 @@ mod tests { let mut r = rng(); let x: Option = r.choose_option([]); assert!(x.is_none()); - assert!(r.choose_option([1, 1, 1]) == Some(1)); + assert_eq!(r.choose_option([1, 1, 1]), Some(1)); } #[test] fn test_choose_weighted() { let mut r = rng(); - assert!(r.choose_weighted(~[ + assert!(r.choose_weighted([ Weighted { weight: 1u, item: 42 }, ]) == 42); - assert!(r.choose_weighted(~[ + assert!(r.choose_weighted([ Weighted { weight: 0u, item: 42 }, Weighted { weight: 1u, item: 43 }, ]) == 43); @@ -1000,10 +1010,10 @@ mod tests { #[test] fn test_choose_weighted_option() { let mut r = rng(); - assert!(r.choose_weighted_option(~[ + assert!(r.choose_weighted_option([ Weighted { weight: 1u, item: 42 }, ]) == Some(42)); - assert!(r.choose_weighted_option(~[ + assert!(r.choose_weighted_option([ Weighted { weight: 0u, item: 42 }, Weighted { weight: 1u, item: 43 }, ]) == Some(43)); @@ -1015,8 +1025,8 @@ mod tests { fn test_weighted_vec() { let mut r = rng(); let empty: ~[int] = ~[]; - assert!(r.weighted_vec(~[]) == empty); - assert!(r.weighted_vec(~[ + assert_eq!(r.weighted_vec([]), empty); + assert!(r.weighted_vec([ Weighted { weight: 0u, item: 3u }, Weighted { weight: 1u, item: 2u }, Weighted { weight: 2u, item: 1u }, @@ -1027,16 +1037,16 @@ mod tests { fn test_shuffle() { let mut r = rng(); let empty: ~[int] = ~[]; - assert!(r.shuffle(~[]) == empty); - assert!(r.shuffle(~[1, 1, 1]) == ~[1, 1, 1]); + assert_eq!(r.shuffle([]), empty); + assert_eq!(r.shuffle([1, 1, 1]), ~[1, 1, 1]); } #[test] fn test_task_rng() { let mut r = task_rng(); r.gen::(); - assert!(r.shuffle(~[1, 1, 1]) == ~[1, 1, 1]); - assert!(r.gen_uint_range(0u, 1u) == 0u); + assert_eq!(r.shuffle([1, 1, 1]), ~[1, 1, 1]); + assert_eq!(r.gen_uint_range(0u, 1u), 0u); } #[test] diff --git a/src/libcore/rand/distributions.rs b/src/libstd/rand/distributions.rs similarity index 98% rename from src/libcore/rand/distributions.rs rename to src/libstd/rand/distributions.rs index 72cff5111e762..f08d967cbe022 100644 --- a/src/libcore/rand/distributions.rs +++ b/src/libstd/rand/distributions.rs @@ -20,7 +20,7 @@ // Generating Random Variables"], but more robust. If one wanted, one // could implement VIZIGNOR the ZIGNOR paper for more speed. -use prelude::*; +use f64; use rand::{Rng,Rand}; mod ziggurat_tables; @@ -89,7 +89,7 @@ impl Rand for StandardNormal { // do-while, so the condition should be true on the first // run, they get overwritten anyway (0 < 1, so these are // good). - let mut x = 1.0, y = 0.0; + let mut (x, y) = (1.0, 0.0); // XXX infinities? while -2.0*y < x * x { diff --git a/src/libcore/rand/ziggurat_tables.rs b/src/libstd/rand/ziggurat_tables.rs similarity index 100% rename from src/libcore/rand/ziggurat_tables.rs rename to src/libstd/rand/ziggurat_tables.rs diff --git a/src/libcore/reflect.rs b/src/libstd/reflect.rs similarity index 97% rename from src/libcore/reflect.rs rename to src/libstd/reflect.rs index 30f60dce04113..1eb3d3a0daaae 100644 --- a/src/libcore/reflect.rs +++ b/src/libstd/reflect.rs @@ -14,6 +14,8 @@ Runtime type reflection */ +#[allow(missing_doc)]; + use intrinsic::{TyDesc, TyVisitor}; use intrinsic::Opaque; use libc::c_void; @@ -46,28 +48,28 @@ pub fn MovePtrAdaptor(v: V) -> MovePtrAdaptor { MovePtrAdaptor { inner: v } } -pub impl MovePtrAdaptor { +impl MovePtrAdaptor { #[inline(always)] - fn bump(&self, sz: uint) { - do self.inner.move_ptr() |p| { + pub fn bump(&self, sz: uint) { + do self.inner.move_ptr() |p| { ((p as uint) + sz) as *c_void - }; + }; } #[inline(always)] - fn align(&self, a: uint) { - do self.inner.move_ptr() |p| { + pub fn align(&self, a: uint) { + do self.inner.move_ptr() |p| { align(p as uint, a) as *c_void - }; + }; } #[inline(always)] - fn align_to(&self) { + pub fn align_to(&self) { self.align(sys::min_align_of::()); } #[inline(always)] - fn bump_past(&self) { + pub fn bump_past(&self) { self.bump(sys::size_of::()); } } diff --git a/src/libcore/repr.rs b/src/libstd/repr.rs similarity index 95% rename from src/libcore/repr.rs rename to src/libstd/repr.rs index 53f51fe1da2f4..14bec48782ff3 100644 --- a/src/libcore/repr.rs +++ b/src/libstd/repr.rs @@ -14,6 +14,8 @@ More runtime type reflection */ +#[allow(missing_doc)]; + use cast::transmute; use char; use intrinsic; @@ -172,12 +174,11 @@ impl MovePtr for ReprVisitor { } } -pub impl ReprVisitor { - +impl ReprVisitor { // Various helpers for the TyVisitor impl #[inline(always)] - fn get(&self, f: &fn(&T)) -> bool { + pub fn get(&self, f: &fn(&T)) -> bool { unsafe { f(transmute::<*c_void,&T>(*self.ptr)); } @@ -185,12 +186,12 @@ pub impl ReprVisitor { } #[inline(always)] - fn visit_inner(&self, inner: *TyDesc) -> bool { + pub fn visit_inner(&self, inner: *TyDesc) -> bool { self.visit_ptr_inner(*self.ptr, inner) } #[inline(always)] - fn visit_ptr_inner(&self, ptr: *c_void, inner: *TyDesc) -> bool { + pub fn visit_ptr_inner(&self, ptr: *c_void, inner: *TyDesc) -> bool { unsafe { let u = ReprVisitor(ptr, self.writer); let v = reflect::MovePtrAdaptor(u); @@ -200,13 +201,13 @@ pub impl ReprVisitor { } #[inline(always)] - fn write(&self) -> bool { + pub fn write(&self) -> bool { do self.get |v:&T| { v.write_repr(self.writer); } } - fn write_escaped_slice(&self, slice: &str) { + pub fn write_escaped_slice(&self, slice: &str) { self.writer.write_char('"'); for slice.each_char |ch| { self.writer.write_escaped_char(ch); @@ -214,19 +215,23 @@ pub impl ReprVisitor { self.writer.write_char('"'); } - fn write_mut_qualifier(&self, mtbl: uint) { + pub fn write_mut_qualifier(&self, mtbl: uint) { if mtbl == 0 { self.writer.write_str("mut "); } else if mtbl == 1 { // skip, this is ast::m_imm } else { - assert!(mtbl == 2); + assert_eq!(mtbl, 2); self.writer.write_str("const "); } } - fn write_vec_range(&self, mtbl: uint, ptr: *u8, len: uint, - inner: *TyDesc) -> bool { + pub fn write_vec_range(&self, + mtbl: uint, + ptr: *u8, + len: uint, + inner: *TyDesc) + -> bool { let mut p = ptr; let end = ptr::offset(p, len); let (sz, al) = unsafe { ((*inner).size, (*inner).align) }; @@ -246,13 +251,14 @@ pub impl ReprVisitor { true } - fn write_unboxed_vec_repr(&self, mtbl: uint, v: &UnboxedVecRepr, - inner: *TyDesc) -> bool { + pub fn write_unboxed_vec_repr(&self, + mtbl: uint, + v: &UnboxedVecRepr, + inner: *TyDesc) + -> bool { self.write_vec_range(mtbl, ptr::to_unsafe_ptr(&v.data), v.fill, inner) } - - } impl TyVisitor for ReprVisitor { @@ -592,7 +598,7 @@ fn test_repr() { error!("expected '%s', got '%s'", e, s); } - assert!(s == e); + assert_eq!(s, e); } exact_test(&10, "10"); diff --git a/src/libcore/result.rs b/src/libstd/result.rs similarity index 84% rename from src/libcore/result.rs rename to src/libstd/result.rs index 72704a429ed5a..8f7a0015bcf15 100644 --- a/src/libcore/result.rs +++ b/src/libstd/result.rs @@ -10,7 +10,7 @@ //! A type representing either success or failure -// NB: transitionary, de-mode-ing. +#[allow(missing_doc)]; use cmp::Eq; use either; @@ -40,7 +40,7 @@ pub enum Result { #[inline(always)] pub fn get(res: &Result) -> T { match *res { - Ok(copy t) => t, + Ok(ref t) => copy *t, Err(ref the_err) => fail!("get called on error result: %?", *the_err) } @@ -72,7 +72,7 @@ pub fn get_ref<'a, T, U>(res: &'a Result) -> &'a T { #[inline(always)] pub fn get_err(res: &Result) -> U { match *res { - Err(copy u) => u, + Err(ref u) => copy *u, Ok(_) => fail!("get_err called on ok result") } } @@ -102,8 +102,8 @@ pub fn is_err(res: &Result) -> bool { pub fn to_either(res: &Result) -> Either { match *res { - Ok(copy res) => either::Right(res), - Err(copy fail_) => either::Left(fail_) + Ok(ref res) => either::Right(copy *res), + Err(ref fail_) => either::Left(copy *fail_) } } @@ -206,7 +206,7 @@ pub fn map(res: &Result, op: &fn(&T) -> U) -> Result { match *res { Ok(ref t) => Ok(op(t)), - Err(copy e) => Err(e) + Err(ref e) => Err(copy *e) } } @@ -222,60 +222,60 @@ pub fn map(res: &Result, op: &fn(&T) -> U) pub fn map_err(res: &Result, op: &fn(&E) -> F) -> Result { match *res { - Ok(copy t) => Ok(t), + Ok(ref t) => Ok(copy *t), Err(ref e) => Err(op(e)) } } -pub impl Result { +impl Result { #[inline(always)] - fn get_ref<'a>(&'a self) -> &'a T { get_ref(self) } + pub fn get_ref<'a>(&'a self) -> &'a T { get_ref(self) } #[inline(always)] - fn is_ok(&self) -> bool { is_ok(self) } + pub fn is_ok(&self) -> bool { is_ok(self) } #[inline(always)] - fn is_err(&self) -> bool { is_err(self) } + pub fn is_err(&self) -> bool { is_err(self) } #[inline(always)] - fn iter(&self, f: &fn(&T)) { iter(self, f) } + pub fn iter(&self, f: &fn(&T)) { iter(self, f) } #[inline(always)] - fn iter_err(&self, f: &fn(&E)) { iter_err(self, f) } + pub fn iter_err(&self, f: &fn(&E)) { iter_err(self, f) } #[inline(always)] - fn unwrap(self) -> T { unwrap(self) } + pub fn unwrap(self) -> T { unwrap(self) } #[inline(always)] - fn unwrap_err(self) -> E { unwrap_err(self) } + pub fn unwrap_err(self) -> E { unwrap_err(self) } #[inline(always)] - fn chain(self, op: &fn(T) -> Result) -> Result { + pub fn chain(self, op: &fn(T) -> Result) -> Result { chain(self, op) } #[inline(always)] - fn chain_err(self, op: &fn(E) -> Result) -> Result { + pub fn chain_err(self, op: &fn(E) -> Result) -> Result { chain_err(self, op) } } -pub impl Result { +impl Result { #[inline(always)] - fn get(&self) -> T { get(self) } + pub fn get(&self) -> T { get(self) } #[inline(always)] - fn map_err(&self, op: &fn(&E) -> F) -> Result { + pub fn map_err(&self, op: &fn(&E) -> F) -> Result { map_err(self, op) } } -pub impl Result { +impl Result { #[inline(always)] - fn get_err(&self) -> E { get_err(self) } + pub fn get_err(&self) -> E { get_err(self) } #[inline(always)] - fn map(&self, op: &fn(&T) -> U) -> Result { + pub fn map(&self, op: &fn(&T) -> U) -> Result { map(self, op) } } @@ -304,22 +304,23 @@ pub fn map_vec( let mut vs: ~[V] = vec::with_capacity(vec::len(ts)); for ts.each |t| { match op(t) { - Ok(copy v) => vs.push(v), - Err(copy u) => return Err(u) + Ok(v) => vs.push(v), + Err(u) => return Err(u) } } return Ok(vs); } #[inline(always)] +#[allow(missing_doc)] pub fn map_opt( o_t: &Option, op: &fn(&T) -> Result) -> Result,U> { match *o_t { None => Ok(None), Some(ref t) => match op(t) { - Ok(copy v) => Ok(Some(v)), - Err(copy e) => Err(e) + Ok(v) => Ok(Some(v)), + Err(e) => Err(e) } } } @@ -343,8 +344,8 @@ pub fn map_vec2(ss: &[S], ts: &[T], let mut i = 0u; while i < n { match op(&ss[i],&ts[i]) { - Ok(copy v) => vs.push(v), - Err(copy u) => return Err(u) + Ok(v) => vs.push(v), + Err(u) => return Err(u) } i += 1u; } @@ -366,7 +367,7 @@ pub fn iter_vec2(ss: &[S], ts: &[T], while i < n { match op(&ss[i],&ts[i]) { Ok(()) => (), - Err(copy u) => return Err(u) + Err(u) => return Err(u) } i += 1u; } @@ -407,12 +408,12 @@ mod tests { #[test] pub fn chain_success() { - assert!(get(&chain(op1(), op2)) == 667u); + assert_eq!(get(&chain(op1(), op2)), 667u); } #[test] pub fn chain_failure() { - assert!(get_err(&chain(op3(), op2)) == ~"sadface"); + assert_eq!(get_err(&chain(op3(), op2)), ~"sadface"); } #[test] @@ -438,19 +439,19 @@ mod tests { #[test] pub fn test_impl_map() { - assert!(Ok::<~str, ~str>(~"a").map(|_x| ~"b") == Ok(~"b")); - assert!(Err::<~str, ~str>(~"a").map(|_x| ~"b") == Err(~"a")); + assert_eq!(Ok::<~str, ~str>(~"a").map(|_x| ~"b"), Ok(~"b")); + assert_eq!(Err::<~str, ~str>(~"a").map(|_x| ~"b"), Err(~"a")); } #[test] pub fn test_impl_map_err() { - assert!(Ok::<~str, ~str>(~"a").map_err(|_x| ~"b") == Ok(~"a")); - assert!(Err::<~str, ~str>(~"a").map_err(|_x| ~"b") == Err(~"b")); + assert_eq!(Ok::<~str, ~str>(~"a").map_err(|_x| ~"b"), Ok(~"a")); + assert_eq!(Err::<~str, ~str>(~"a").map_err(|_x| ~"b"), Err(~"b")); } #[test] pub fn test_get_ref_method() { let foo: Result = Ok(100); - assert!(*foo.get_ref() == 100); + assert_eq!(*foo.get_ref(), 100); } } diff --git a/src/libstd/rt/comm.rs b/src/libstd/rt/comm.rs new file mode 100644 index 0000000000000..8a8f31bbdfa52 --- /dev/null +++ b/src/libstd/rt/comm.rs @@ -0,0 +1,618 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Ports and channels. +//! +//! XXX: Carefully consider whether the sequentially consistent +//! atomics here can be converted to acq/rel. I'm not sure they can, +//! because there is data being transerred in both directions (the payload +//! goes from sender to receiver and the task pointer goes the other way). + +use option::*; +use cast; +use util; +use ops::Drop; +use kinds::Owned; +use rt::sched::{Scheduler, Coroutine}; +use rt::local::Local; +use unstable::intrinsics::{atomic_xchg, atomic_load}; +use util::Void; +use comm::{GenericChan, GenericSmartChan, GenericPort, Peekable}; +use cell::Cell; + +/// A combined refcount / ~Task pointer. +/// +/// Can be equal to the following values: +/// +/// * 2 - both endpoints are alive +/// * 1 - either the sender or the receiver is dead, determined by context +/// * - A pointer to a blocked Task that can be transmuted to ~Task +type State = int; + +static STATE_BOTH: State = 2; +static STATE_ONE: State = 1; + +/// The heap-allocated structure shared between two endpoints. +struct Packet { + state: State, + payload: Option, +} + +/// A one-shot channel. +pub struct ChanOne { + // XXX: Hack extra allocation to make by-val self work + inner: ~ChanOneHack +} + + +/// A one-shot port. +pub struct PortOne { + // XXX: Hack extra allocation to make by-val self work + inner: ~PortOneHack +} + +pub struct ChanOneHack { + void_packet: *mut Void, + suppress_finalize: bool +} + +pub struct PortOneHack { + void_packet: *mut Void, + suppress_finalize: bool +} + +pub fn oneshot() -> (PortOne, ChanOne) { + let packet: ~Packet = ~Packet { + state: STATE_BOTH, + payload: None + }; + + unsafe { + let packet: *mut Void = cast::transmute(packet); + let port = PortOne { + inner: ~PortOneHack { + void_packet: packet, + suppress_finalize: false + } + }; + let chan = ChanOne { + inner: ~ChanOneHack { + void_packet: packet, + suppress_finalize: false + } + }; + return (port, chan); + } +} + +impl ChanOne { + + pub fn send(self, val: T) { + self.try_send(val); + } + + pub fn try_send(self, val: T) -> bool { + let mut this = self; + let mut recvr_active = true; + let packet = this.inner.packet(); + + unsafe { + + // Install the payload + assert!((*packet).payload.is_none()); + (*packet).payload = Some(val); + + // Atomically swap out the old state to figure out what + // the port's up to, issuing a release barrier to prevent + // reordering of the payload write. This also issues an + // acquire barrier that keeps the subsequent access of the + // ~Task pointer from being reordered. + let oldstate = atomic_xchg(&mut (*packet).state, STATE_ONE); + match oldstate { + STATE_BOTH => { + // Port is not waiting yet. Nothing to do + } + STATE_ONE => { + // Port has closed. Need to clean up. + let _packet: ~Packet = cast::transmute(this.inner.void_packet); + recvr_active = false; + } + task_as_state => { + // Port is blocked. Wake it up. + let recvr: ~Coroutine = cast::transmute(task_as_state); + let sched = Local::take::(); + sched.schedule_task(recvr); + } + } + } + + // Suppress the synchronizing actions in the finalizer. We're done with the packet. + this.inner.suppress_finalize = true; + return recvr_active; + } +} + + +impl PortOne { + pub fn recv(self) -> T { + match self.try_recv() { + Some(val) => val, + None => { + fail!("receiving on closed channel"); + } + } + } + + pub fn try_recv(self) -> Option { + let mut this = self; + let packet = this.inner.packet(); + + // XXX: Optimize this to not require the two context switches when data is available + + // Switch to the scheduler to put the ~Task into the Packet state. + let sched = Local::take::(); + do sched.deschedule_running_task_and_then |task| { + unsafe { + // Atomically swap the task pointer into the Packet state, issuing + // an acquire barrier to prevent reordering of the subsequent read + // of the payload. Also issues a release barrier to prevent reordering + // of any previous writes to the task structure. + let task_as_state: State = cast::transmute(task); + let oldstate = atomic_xchg(&mut (*packet).state, task_as_state); + match oldstate { + STATE_BOTH => { + // Data has not been sent. Now we're blocked. + } + STATE_ONE => { + // Channel is closed. Switch back and check the data. + let task: ~Coroutine = cast::transmute(task_as_state); + let sched = Local::take::(); + sched.resume_task_immediately(task); + } + _ => util::unreachable() + } + } + } + + // Task resumes. + + // No further memory barrier is needed here to access the + // payload. Some scenarios: + // + // 1) We encountered STATE_ONE above - the atomic_xchg was the acq barrier. We're fine. + // 2) We encountered STATE_BOTH above and blocked. The sending task then ran us + // and ran on its thread. The sending task issued a read barrier when taking the + // pointer to the receiving task. + // 3) We encountered STATE_BOTH above and blocked, but the receiving task (this task) + // is pinned to some other scheduler, so the sending task had to give us to + // a different scheduler for resuming. That send synchronized memory. + + unsafe { + let payload = util::replace(&mut (*packet).payload, None); + + // The sender has closed up shop. Drop the packet. + let _packet: ~Packet = cast::transmute(this.inner.void_packet); + // Suppress the synchronizing actions in the finalizer. We're done with the packet. + this.inner.suppress_finalize = true; + return payload; + } + } +} + +impl Peekable for PortOne { + fn peek(&self) -> bool { + unsafe { + let packet: *mut Packet = self.inner.packet(); + let oldstate = atomic_load(&mut (*packet).state); + match oldstate { + STATE_BOTH => false, + STATE_ONE => (*packet).payload.is_some(), + _ => util::unreachable() + } + } + } +} + +#[unsafe_destructor] +impl Drop for ChanOneHack { + fn finalize(&self) { + if self.suppress_finalize { return } + + unsafe { + let this = cast::transmute_mut(self); + let oldstate = atomic_xchg(&mut (*this.packet()).state, STATE_ONE); + match oldstate { + STATE_BOTH => { + // Port still active. It will destroy the Packet. + }, + STATE_ONE => { + let _packet: ~Packet = cast::transmute(this.void_packet); + }, + task_as_state => { + // The port is blocked waiting for a message we will never send. Wake it. + assert!((*this.packet()).payload.is_none()); + let recvr: ~Coroutine = cast::transmute(task_as_state); + let sched = Local::take::(); + sched.schedule_task(recvr); + } + } + } + } +} + +#[unsafe_destructor] +impl Drop for PortOneHack { + fn finalize(&self) { + if self.suppress_finalize { return } + + unsafe { + let this = cast::transmute_mut(self); + let oldstate = atomic_xchg(&mut (*this.packet()).state, STATE_ONE); + match oldstate { + STATE_BOTH => { + // Chan still active. It will destroy the packet. + }, + STATE_ONE => { + let _packet: ~Packet = cast::transmute(this.void_packet); + } + _ => { + util::unreachable() + } + } + } + } +} + +impl ChanOneHack { + fn packet(&self) -> *mut Packet { + unsafe { + let p: *mut ~Packet = cast::transmute(&self.void_packet); + let p: *mut Packet = &mut **p; + return p; + } + } +} + +impl PortOneHack { + fn packet(&self) -> *mut Packet { + unsafe { + let p: *mut ~Packet = cast::transmute(&self.void_packet); + let p: *mut Packet = &mut **p; + return p; + } + } +} + +struct StreamPayload { + val: T, + next: PortOne> +} + +/// A channel with unbounded size. +pub struct Chan { + // FIXME #5372. Using Cell because we don't take &mut self + next: Cell>> +} + +/// An port with unbounded size. +pub struct Port { + // FIXME #5372. Using Cell because we don't take &mut self + next: Cell>> +} + +pub fn stream() -> (Port, Chan) { + let (pone, cone) = oneshot(); + let port = Port { next: Cell::new(pone) }; + let chan = Chan { next: Cell::new(cone) }; + return (port, chan); +} + +impl GenericChan for Chan { + fn send(&self, val: T) { + self.try_send(val); + } +} + +impl GenericSmartChan for Chan { + fn try_send(&self, val: T) -> bool { + let (next_pone, next_cone) = oneshot(); + let cone = self.next.take(); + self.next.put_back(next_cone); + cone.try_send(StreamPayload { val: val, next: next_pone }) + } +} + +impl GenericPort for Port { + fn recv(&self) -> T { + match self.try_recv() { + Some(val) => val, + None => { + fail!("receiving on closed channel"); + } + } + } + + fn try_recv(&self) -> Option { + let pone = self.next.take(); + match pone.try_recv() { + Some(StreamPayload { val, next }) => { + self.next.put_back(next); + Some(val) + } + None => None + } + } +} + +impl Peekable for Port { + fn peek(&self) -> bool { + self.next.with_mut_ref(|p| p.peek()) + } +} + +#[cfg(test)] +mod test { + use super::*; + use option::*; + use rt::test::*; + use cell::Cell; + use iter::Times; + + #[test] + fn oneshot_single_thread_close_port_first() { + // Simple test of closing without sending + do run_in_newsched_task { + let (port, _chan) = oneshot::(); + { let _p = port; } + } + } + + #[test] + fn oneshot_single_thread_close_chan_first() { + // Simple test of closing without sending + do run_in_newsched_task { + let (_port, chan) = oneshot::(); + { let _c = chan; } + } + } + + #[test] + fn oneshot_single_thread_send_port_close() { + // Testing that the sender cleans up the payload if receiver is closed + do run_in_newsched_task { + let (port, chan) = oneshot::<~int>(); + { let _p = port; } + chan.send(~0); + } + } + + #[test] + fn oneshot_single_thread_recv_chan_close() { + // Receiving on a closed chan will fail + do run_in_newsched_task { + let res = do spawntask_try { + let (port, chan) = oneshot::<~int>(); + { let _c = chan; } + port.recv(); + }; + assert!(res.is_err()); + } + } + + #[test] + fn oneshot_single_thread_send_then_recv() { + do run_in_newsched_task { + let (port, chan) = oneshot::<~int>(); + chan.send(~10); + assert!(port.recv() == ~10); + } + } + + #[test] + fn oneshot_single_thread_try_send_open() { + do run_in_newsched_task { + let (port, chan) = oneshot::(); + assert!(chan.try_send(10)); + assert!(port.recv() == 10); + } + } + + #[test] + fn oneshot_single_thread_try_send_closed() { + do run_in_newsched_task { + let (port, chan) = oneshot::(); + { let _p = port; } + assert!(!chan.try_send(10)); + } + } + + #[test] + fn oneshot_single_thread_try_recv_open() { + do run_in_newsched_task { + let (port, chan) = oneshot::(); + chan.send(10); + assert!(port.try_recv() == Some(10)); + } + } + + #[test] + fn oneshot_single_thread_try_recv_closed() { + do run_in_newsched_task { + let (port, chan) = oneshot::(); + { let _c = chan; } + assert!(port.try_recv() == None); + } + } + + #[test] + fn oneshot_single_thread_peek_data() { + do run_in_newsched_task { + let (port, chan) = oneshot::(); + assert!(!port.peek()); + chan.send(10); + assert!(port.peek()); + } + } + + #[test] + fn oneshot_single_thread_peek_close() { + do run_in_newsched_task { + let (port, chan) = oneshot::(); + { let _c = chan; } + assert!(!port.peek()); + assert!(!port.peek()); + } + } + + #[test] + fn oneshot_single_thread_peek_open() { + do run_in_newsched_task { + let (port, _) = oneshot::(); + assert!(!port.peek()); + } + } + + #[test] + fn oneshot_multi_task_recv_then_send() { + do run_in_newsched_task { + let (port, chan) = oneshot::<~int>(); + let port_cell = Cell::new(port); + do spawntask_immediately { + assert!(port_cell.take().recv() == ~10); + } + + chan.send(~10); + } + } + + #[test] + fn oneshot_multi_task_recv_then_close() { + do run_in_newsched_task { + let (port, chan) = oneshot::<~int>(); + let port_cell = Cell::new(port); + let chan_cell = Cell::new(chan); + do spawntask_later { + let _cell = chan_cell.take(); + } + let res = do spawntask_try { + assert!(port_cell.take().recv() == ~10); + }; + assert!(res.is_err()); + } + } + + #[test] + fn oneshot_multi_thread_close_stress() { + for stress_factor().times { + do run_in_newsched_task { + let (port, chan) = oneshot::(); + let port_cell = Cell::new(port); + let _thread = do spawntask_thread { + let _p = port_cell.take(); + }; + let _chan = chan; + } + } + } + + #[test] + fn oneshot_multi_thread_send_close_stress() { + for stress_factor().times { + do run_in_newsched_task { + let (port, chan) = oneshot::(); + let chan_cell = Cell::new(chan); + let port_cell = Cell::new(port); + let _thread1 = do spawntask_thread { + let _p = port_cell.take(); + }; + let _thread2 = do spawntask_thread { + let c = chan_cell.take(); + c.send(1); + }; + } + } + } + + #[test] + fn oneshot_multi_thread_recv_close_stress() { + for stress_factor().times { + do run_in_newsched_task { + let (port, chan) = oneshot::(); + let chan_cell = Cell::new(chan); + let port_cell = Cell::new(port); + let _thread1 = do spawntask_thread { + let port_cell = Cell::new(port_cell.take()); + let res = do spawntask_try { + port_cell.take().recv(); + }; + assert!(res.is_err()); + }; + let _thread2 = do spawntask_thread { + let chan_cell = Cell::new(chan_cell.take()); + do spawntask { + chan_cell.take(); + } + }; + } + } + } + + #[test] + fn oneshot_multi_thread_send_recv_stress() { + for stress_factor().times { + do run_in_newsched_task { + let (port, chan) = oneshot::<~int>(); + let chan_cell = Cell::new(chan); + let port_cell = Cell::new(port); + let _thread1 = do spawntask_thread { + chan_cell.take().send(~10); + }; + let _thread2 = do spawntask_thread { + assert!(port_cell.take().recv() == ~10); + }; + } + } + } + + #[test] + fn stream_send_recv_stress() { + for stress_factor().times { + do run_in_newsched_task { + let (port, chan) = stream::<~int>(); + + send(chan, 0); + recv(port, 0); + + fn send(chan: Chan<~int>, i: int) { + if i == 10 { return } + + let chan_cell = Cell::new(chan); + let _thread = do spawntask_thread { + let chan = chan_cell.take(); + chan.send(~i); + send(chan, i + 1); + }; + } + + fn recv(port: Port<~int>, i: int) { + if i == 10 { return } + + let port_cell = Cell::new(port); + let _thread = do spawntask_thread { + let port = port_cell.take(); + assert!(port.recv() == ~i); + recv(port, i + 1); + }; + } + } + } + } +} + diff --git a/src/libcore/rt/context.rs b/src/libstd/rt/context.rs similarity index 91% rename from src/libcore/rt/context.rs rename to src/libstd/rt/context.rs index 9c1e566f218f6..d5ca8473ceeac 100644 --- a/src/libcore/rt/context.rs +++ b/src/libstd/rt/context.rs @@ -27,8 +27,8 @@ pub struct Context { regs: ~Registers } -pub impl Context { - fn empty() -> Context { +impl Context { + pub fn empty() -> Context { Context { start: None, regs: new_regs() @@ -36,7 +36,7 @@ pub impl Context { } /// Create a new context that will resume execution by running ~fn() - fn new(start: ~fn(), stack: &mut StackSegment) -> Context { + pub fn new(start: ~fn(), stack: &mut StackSegment) -> Context { // XXX: Putting main into a ~ so it's a thin pointer and can // be passed to the spawn function. Another unfortunate // allocation @@ -71,7 +71,7 @@ pub impl Context { saving the registers values of the executing thread to a Context then loading the registers from a previously saved Context. */ - fn swap(out_context: &mut Context, in_context: &Context) { + pub fn swap(out_context: &mut Context, in_context: &Context) { let out_regs: &mut Registers = match out_context { &Context { regs: ~ref mut r, _ } => r }; @@ -84,6 +84,7 @@ pub impl Context { } extern { + #[rust_stack] fn swap_registers(out_regs: *mut Registers, in_regs: *Registers); } @@ -111,9 +112,9 @@ fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp: let sp = align_down(sp); let sp = mut_offset(sp, -4); - unsafe { *sp = arg as uint; } + unsafe { *sp = arg as uint }; let sp = mut_offset(sp, -1); - unsafe { *sp = 0; } // The final return address + unsafe { *sp = 0 }; // The final return address regs.esp = sp as u32; regs.eip = fptr as u32; @@ -164,7 +165,9 @@ fn new_regs() -> ~Registers { ~([0, .. 32]) } #[cfg(target_arch = "arm")] fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp: *mut uint) { - let sp = mut_offset(sp, -1); + let sp = align_down(sp); + // sp of arm eabi is 8-byte aligned + let sp = mut_offset(sp, -2); // The final return address. 0 indicates the bottom of the stack unsafe { *sp = 0; } @@ -182,7 +185,9 @@ fn new_regs() -> ~Registers { ~([0, .. 32]) } #[cfg(target_arch = "mips")] fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp: *mut uint) { - let sp = mut_offset(sp, -1); + let sp = align_down(sp); + // sp of mips o32 is 8-byte aligned + let sp = mut_offset(sp, -2); // The final return address. 0 indicates the bottom of the stack unsafe { *sp = 0; } @@ -195,7 +200,7 @@ fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp: fn align_down(sp: *mut uint) -> *mut uint { unsafe { - let sp = transmute::<*mut uint, uint>(sp); + let sp: uint = transmute(sp); let sp = sp & !(16 - 1); transmute::(sp) } diff --git a/src/libcore/rt/env.rs b/src/libstd/rt/env.rs similarity index 100% rename from src/libcore/rt/env.rs rename to src/libstd/rt/env.rs diff --git a/src/libstd/rt/global_heap.rs b/src/libstd/rt/global_heap.rs new file mode 100644 index 0000000000000..ce7ff87b44580 --- /dev/null +++ b/src/libstd/rt/global_heap.rs @@ -0,0 +1,87 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use sys::{TypeDesc, size_of}; +use libc::{c_void, size_t, uintptr_t}; +use c_malloc = libc::malloc; +use c_free = libc::free; +use managed::raw::{BoxHeaderRepr, BoxRepr}; +use cast::transmute; +use unstable::intrinsics::{atomic_xadd,atomic_xsub}; +use ptr::null; +use intrinsic::TyDesc; + +pub unsafe fn malloc(td: *TypeDesc, size: uint) -> *c_void { + assert!(td.is_not_null()); + + let total_size = get_box_size(size, (*td).align); + let p = c_malloc(total_size as size_t); + assert!(p.is_not_null()); + + // FIXME #3475: Converting between our two different tydesc types + let td: *TyDesc = transmute(td); + + let box: &mut BoxRepr = transmute(p); + box.header.ref_count = -1; // Exchange values not ref counted + box.header.type_desc = td; + box.header.prev = null(); + box.header.next = null(); + + let exchange_count = &mut *exchange_count_ptr(); + atomic_xadd(exchange_count, 1); + + return transmute(box); +} +/** +Thin wrapper around libc::malloc, none of the box header +stuff in exchange_alloc::malloc +*/ +pub unsafe fn malloc_raw(size: uint) -> *c_void { + let p = c_malloc(size as size_t); + if p.is_null() { + fail!("Failure in malloc_raw: result ptr is null"); + } + p +} + +pub unsafe fn free(ptr: *c_void) { + let exchange_count = &mut *exchange_count_ptr(); + atomic_xsub(exchange_count, 1); + + assert!(ptr.is_not_null()); + c_free(ptr); +} +///Thin wrapper around libc::free, as with exchange_alloc::malloc_raw +pub unsafe fn free_raw(ptr: *c_void) { + c_free(ptr); +} + +fn get_box_size(body_size: uint, body_align: uint) -> uint { + let header_size = size_of::(); + // FIXME (#2699): This alignment calculation is suspicious. Is it right? + let total_size = align_to(header_size, body_align) + body_size; + return total_size; +} + +// Rounds |size| to the nearest |alignment|. Invariant: |alignment| is a power +// of two. +fn align_to(size: uint, align: uint) -> uint { + assert!(align != 0); + (size + align - 1) & !(align - 1) +} + +fn exchange_count_ptr() -> *mut int { + // XXX: Need mutable globals + unsafe { transmute(&rust_exchange_count) } +} + +extern { + static rust_exchange_count: uintptr_t; +} diff --git a/src/libcore/rt/io/comm_adapters.rs b/src/libstd/rt/io/comm_adapters.rs similarity index 100% rename from src/libcore/rt/io/comm_adapters.rs rename to src/libstd/rt/io/comm_adapters.rs diff --git a/src/libstd/rt/io/extensions.rs b/src/libstd/rt/io/extensions.rs new file mode 100644 index 0000000000000..727ab13a4f6f7 --- /dev/null +++ b/src/libstd/rt/io/extensions.rs @@ -0,0 +1,901 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Utility mixins that apply to all Readers and Writers + +// XXX: Not sure how this should be structured +// XXX: Iteration should probably be considered separately + +use uint; +use int; +use vec; +use rt::io::{Reader, Writer}; +use rt::io::{read_error, standard_error, EndOfFile, DEFAULT_BUF_SIZE}; +use option::{Option, Some, None}; +use unstable::finally::Finally; +use util; +use cast; +use io::{u64_to_le_bytes, u64_to_be_bytes}; + +pub trait ReaderUtil { + + /// Reads a single byte. Returns `None` on EOF. + /// + /// # Failure + /// + /// Raises the same conditions as the `read` method. Returns + /// `None` if the condition is handled. + fn read_byte(&mut self) -> Option; + + /// Reads `len` bytes and appends them to a vector. + /// + /// May push fewer than the requested number of bytes on error + /// or EOF. Returns true on success, false on EOF or error. + /// + /// # Failure + /// + /// Raises the same conditions as `read`. Additionally raises `read_error` + /// on EOF. If `read_error` is handled then `push_bytes` may push less + /// than the requested number of bytes. + fn push_bytes(&mut self, buf: &mut ~[u8], len: uint); + + /// Reads `len` bytes and gives you back a new vector of length `len` + /// + /// # Failure + /// + /// Raises the same conditions as `read`. Additionally raises `read_error` + /// on EOF. If `read_error` is handled then the returned vector may + /// contain less than the requested number of bytes. + fn read_bytes(&mut self, len: uint) -> ~[u8]; + + /// Reads all remaining bytes from the stream. + /// + /// # Failure + /// + /// Raises the same conditions as the `read` method. + fn read_to_end(&mut self) -> ~[u8]; + +} + +pub trait ReaderByteConversions { + /// Reads `n` little-endian unsigned integer bytes. + /// + /// `n` must be between 1 and 8, inclusive. + fn read_le_uint_n(&mut self, nbytes: uint) -> u64; + + /// Reads `n` little-endian signed integer bytes. + /// + /// `n` must be between 1 and 8, inclusive. + fn read_le_int_n(&mut self, nbytes: uint) -> i64; + + /// Reads `n` big-endian unsigned integer bytes. + /// + /// `n` must be between 1 and 8, inclusive. + fn read_be_uint_n(&mut self, nbytes: uint) -> u64; + + /// Reads `n` big-endian signed integer bytes. + /// + /// `n` must be between 1 and 8, inclusive. + fn read_be_int_n(&mut self, nbytes: uint) -> i64; + + /// Reads a little-endian unsigned integer. + /// + /// The number of bytes returned is system-dependant. + fn read_le_uint(&mut self) -> uint; + + /// Reads a little-endian integer. + /// + /// The number of bytes returned is system-dependant. + fn read_le_int(&mut self) -> int; + + /// Reads a big-endian unsigned integer. + /// + /// The number of bytes returned is system-dependant. + fn read_be_uint(&mut self) -> uint; + + /// Reads a big-endian integer. + /// + /// The number of bytes returned is system-dependant. + fn read_be_int(&mut self) -> int; + + /// Reads a big-endian `u64`. + /// + /// `u64`s are 8 bytes long. + fn read_be_u64(&mut self) -> u64; + + /// Reads a big-endian `u32`. + /// + /// `u32`s are 4 bytes long. + fn read_be_u32(&mut self) -> u32; + + /// Reads a big-endian `u16`. + /// + /// `u16`s are 2 bytes long. + fn read_be_u16(&mut self) -> u16; + + /// Reads a big-endian `i64`. + /// + /// `i64`s are 8 bytes long. + fn read_be_i64(&mut self) -> i64; + + /// Reads a big-endian `i32`. + /// + /// `i32`s are 4 bytes long. + fn read_be_i32(&mut self) -> i32; + + /// Reads a big-endian `i16`. + /// + /// `i16`s are 2 bytes long. + fn read_be_i16(&mut self) -> i16; + + /// Reads a big-endian `f64`. + /// + /// `f64`s are 8 byte, IEEE754 double-precision floating point numbers. + fn read_be_f64(&mut self) -> f64; + + /// Reads a big-endian `f32`. + /// + /// `f32`s are 4 byte, IEEE754 single-precision floating point numbers. + fn read_be_f32(&mut self) -> f32; + + /// Reads a little-endian `u64`. + /// + /// `u64`s are 8 bytes long. + fn read_le_u64(&mut self) -> u64; + + /// Reads a little-endian `u32`. + /// + /// `u32`s are 4 bytes long. + fn read_le_u32(&mut self) -> u32; + + /// Reads a little-endian `u16`. + /// + /// `u16`s are 2 bytes long. + fn read_le_u16(&mut self) -> u16; + + /// Reads a little-endian `i64`. + /// + /// `i64`s are 8 bytes long. + fn read_le_i64(&mut self) -> i64; + + /// Reads a little-endian `i32`. + /// + /// `i32`s are 4 bytes long. + fn read_le_i32(&mut self) -> i32; + + /// Reads a little-endian `i16`. + /// + /// `i16`s are 2 bytes long. + fn read_le_i16(&mut self) -> i16; + + /// Reads a little-endian `f64`. + /// + /// `f64`s are 8 byte, IEEE754 double-precision floating point numbers. + fn read_le_f64(&mut self) -> f64; + + /// Reads a little-endian `f32`. + /// + /// `f32`s are 4 byte, IEEE754 single-precision floating point numbers. + fn read_le_f32(&mut self) -> f32; + + /// Read a u8. + /// + /// `u8`s are 1 byte. + fn read_u8(&mut self) -> u8; + + /// Read an i8. + /// + /// `i8`s are 1 byte. + fn read_i8(&mut self) -> i8; + +} + +pub trait WriterByteConversions { + /// Write the result of passing n through `int::to_str_bytes`. + fn write_int(&mut self, n: int); + + /// Write the result of passing n through `uint::to_str_bytes`. + fn write_uint(&mut self, n: uint); + + /// Write a little-endian uint (number of bytes depends on system). + fn write_le_uint(&mut self, n: uint); + + /// Write a little-endian int (number of bytes depends on system). + fn write_le_int(&mut self, n: int); + + /// Write a big-endian uint (number of bytes depends on system). + fn write_be_uint(&mut self, n: uint); + + /// Write a big-endian int (number of bytes depends on system). + fn write_be_int(&mut self, n: int); + + /// Write a big-endian u64 (8 bytes). + fn write_be_u64_(&mut self, n: u64); + + /// Write a big-endian u32 (4 bytes). + fn write_be_u32(&mut self, n: u32); + + /// Write a big-endian u16 (2 bytes). + fn write_be_u16(&mut self, n: u16); + + /// Write a big-endian i64 (8 bytes). + fn write_be_i64(&mut self, n: i64); + + /// Write a big-endian i32 (4 bytes). + fn write_be_i32(&mut self, n: i32); + + /// Write a big-endian i16 (2 bytes). + fn write_be_i16(&mut self, n: i16); + + /// Write a big-endian IEEE754 double-precision floating-point (8 bytes). + fn write_be_f64(&mut self, f: f64); + + /// Write a big-endian IEEE754 single-precision floating-point (4 bytes). + fn write_be_f32(&mut self, f: f32); + + /// Write a little-endian u64 (8 bytes). + fn write_le_u64_(&mut self, n: u64); + + /// Write a little-endian u32 (4 bytes). + fn write_le_u32(&mut self, n: u32); + + /// Write a little-endian u16 (2 bytes). + fn write_le_u16(&mut self, n: u16); + + /// Write a little-endian i64 (8 bytes). + fn write_le_i64(&mut self, n: i64); + + /// Write a little-endian i32 (4 bytes). + fn write_le_i32(&mut self, n: i32); + + /// Write a little-endian i16 (2 bytes). + fn write_le_i16(&mut self, n: i16); + + /// Write a little-endian IEEE754 double-precision floating-point + /// (8 bytes). + fn write_le_f64(&mut self, f: f64); + + /// Write a litten-endian IEEE754 single-precision floating-point + /// (4 bytes). + fn write_le_f32(&mut self, f: f32); + + /// Write a u8 (1 byte). + fn write_u8(&mut self, n: u8); + + /// Write a i8 (1 byte). + fn write_i8(&mut self, n: i8); +} + +impl ReaderUtil for T { + fn read_byte(&mut self) -> Option { + let mut buf = [0]; + match self.read(buf) { + Some(0) => { + debug!("read 0 bytes. trying again"); + self.read_byte() + } + Some(1) => Some(buf[0]), + Some(_) => util::unreachable(), + None => None + } + } + + fn push_bytes(&mut self, buf: &mut ~[u8], len: uint) { + unsafe { + let start_len = buf.len(); + let mut total_read = 0; + + vec::reserve_at_least(buf, start_len + len); + vec::raw::set_len(buf, start_len + len); + + do (|| { + while total_read < len { + let slice = vec::mut_slice(*buf, start_len + total_read, buf.len()); + match self.read(slice) { + Some(nread) => { + total_read += nread; + } + None => { + read_error::cond.raise(standard_error(EndOfFile)); + break; + } + } + } + }).finally { + vec::raw::set_len(buf, start_len + total_read); + } + } + } + + fn read_bytes(&mut self, len: uint) -> ~[u8] { + let mut buf = vec::with_capacity(len); + self.push_bytes(&mut buf, len); + return buf; + } + + fn read_to_end(&mut self) -> ~[u8] { + let mut buf = vec::with_capacity(DEFAULT_BUF_SIZE); + let mut keep_reading = true; + do read_error::cond.trap(|e| { + if e.kind == EndOfFile { + keep_reading = false; + } else { + read_error::cond.raise(e) + } + }).in { + while keep_reading { + self.push_bytes(&mut buf, DEFAULT_BUF_SIZE) + } + } + return buf; + } +} + +impl ReaderByteConversions for T { + fn read_le_uint_n(&mut self, nbytes: uint) -> u64 { + assert!(nbytes > 0 && nbytes <= 8); + + let mut (val, pos, i) = (0u64, 0, nbytes); + while i > 0 { + val += (self.read_u8() as u64) << pos; + pos += 8; + i -= 1; + } + val + } + + fn read_le_int_n(&mut self, nbytes: uint) -> i64 { + extend_sign(self.read_le_uint_n(nbytes), nbytes) + } + + fn read_be_uint_n(&mut self, nbytes: uint) -> u64 { + assert!(nbytes > 0 && nbytes <= 8); + + let mut (val, i) = (0u64, nbytes); + while i > 0 { + i -= 1; + val += (self.read_u8() as u64) << i * 8; + } + val + } + + fn read_be_int_n(&mut self, nbytes: uint) -> i64 { + extend_sign(self.read_be_uint_n(nbytes), nbytes) + } + + fn read_le_uint(&mut self) -> uint { + self.read_le_uint_n(uint::bytes) as uint + } + + fn read_le_int(&mut self) -> int { + self.read_le_int_n(int::bytes) as int + } + + fn read_be_uint(&mut self) -> uint { + self.read_be_uint_n(uint::bytes) as uint + } + + fn read_be_int(&mut self) -> int { + self.read_be_int_n(int::bytes) as int + } + + fn read_be_u64(&mut self) -> u64 { + self.read_be_uint_n(8) as u64 + } + + fn read_be_u32(&mut self) -> u32 { + self.read_be_uint_n(4) as u32 + } + + fn read_be_u16(&mut self) -> u16 { + self.read_be_uint_n(2) as u16 + } + + fn read_be_i64(&mut self) -> i64 { + self.read_be_int_n(8) as i64 + } + + fn read_be_i32(&mut self) -> i32 { + self.read_be_int_n(4) as i32 + } + + fn read_be_i16(&mut self) -> i16 { + self.read_be_int_n(2) as i16 + } + + fn read_be_f64(&mut self) -> f64 { + unsafe { + cast::transmute::(self.read_be_u64()) + } + } + + fn read_be_f32(&mut self) -> f32 { + unsafe { + cast::transmute::(self.read_be_u32()) + } + } + + fn read_le_u64(&mut self) -> u64 { + self.read_le_uint_n(8) as u64 + } + + fn read_le_u32(&mut self) -> u32 { + self.read_le_uint_n(4) as u32 + } + + fn read_le_u16(&mut self) -> u16 { + self.read_le_uint_n(2) as u16 + } + + fn read_le_i64(&mut self) -> i64 { + self.read_le_int_n(8) as i64 + } + + fn read_le_i32(&mut self) -> i32 { + self.read_le_int_n(4) as i32 + } + + fn read_le_i16(&mut self) -> i16 { + self.read_le_int_n(2) as i16 + } + + fn read_le_f64(&mut self) -> f64 { + unsafe { + cast::transmute::(self.read_le_u64()) + } + } + + fn read_le_f32(&mut self) -> f32 { + unsafe { + cast::transmute::(self.read_le_u32()) + } + } + + fn read_u8(&mut self) -> u8 { + match self.read_byte() { + Some(b) => b as u8, + None => 0 + } + } + + fn read_i8(&mut self) -> i8 { + match self.read_byte() { + Some(b) => b as i8, + None => 0 + } + } + +} + +impl WriterByteConversions for T { + fn write_int(&mut self, n: int) { + int::to_str_bytes(n, 10u, |bytes| self.write(bytes)) + } + + fn write_uint(&mut self, n: uint) { + uint::to_str_bytes(n, 10u, |bytes| self.write(bytes)) + } + + fn write_le_uint(&mut self, n: uint) { + u64_to_le_bytes(n as u64, uint::bytes, |v| self.write(v)) + } + + fn write_le_int(&mut self, n: int) { + u64_to_le_bytes(n as u64, int::bytes, |v| self.write(v)) + } + + fn write_be_uint(&mut self, n: uint) { + u64_to_be_bytes(n as u64, uint::bytes, |v| self.write(v)) + } + + fn write_be_int(&mut self, n: int) { + u64_to_be_bytes(n as u64, int::bytes, |v| self.write(v)) + } + + fn write_be_u64_(&mut self, n: u64) { + u64_to_be_bytes(n, 8u, |v| self.write(v)) + } + + fn write_be_u32(&mut self, n: u32) { + u64_to_be_bytes(n as u64, 4u, |v| self.write(v)) + } + + fn write_be_u16(&mut self, n: u16) { + u64_to_be_bytes(n as u64, 2u, |v| self.write(v)) + } + + fn write_be_i64(&mut self, n: i64) { + u64_to_be_bytes(n as u64, 8u, |v| self.write(v)) + } + + fn write_be_i32(&mut self, n: i32) { + u64_to_be_bytes(n as u64, 4u, |v| self.write(v)) + } + + fn write_be_i16(&mut self, n: i16) { + u64_to_be_bytes(n as u64, 2u, |v| self.write(v)) + } + + fn write_be_f64(&mut self, f: f64) { + unsafe { + self.write_be_u64_(cast::transmute(f)) + } + } + + fn write_be_f32(&mut self, f: f32) { + unsafe { + self.write_be_u32(cast::transmute(f)) + } + } + + fn write_le_u64_(&mut self, n: u64) { + u64_to_le_bytes(n, 8u, |v| self.write(v)) + } + + fn write_le_u32(&mut self, n: u32) { + u64_to_le_bytes(n as u64, 4u, |v| self.write(v)) + } + + fn write_le_u16(&mut self, n: u16) { + u64_to_le_bytes(n as u64, 2u, |v| self.write(v)) + } + + fn write_le_i64(&mut self, n: i64) { + u64_to_le_bytes(n as u64, 8u, |v| self.write(v)) + } + + fn write_le_i32(&mut self, n: i32) { + u64_to_le_bytes(n as u64, 4u, |v| self.write(v)) + } + + fn write_le_i16(&mut self, n: i16) { + u64_to_le_bytes(n as u64, 2u, |v| self.write(v)) + } + + fn write_le_f64(&mut self, f: f64) { + unsafe { + self.write_le_u64_(cast::transmute(f)) + } + } + + fn write_le_f32(&mut self, f: f32) { + unsafe { + self.write_le_u32(cast::transmute(f)) + } + } + + fn write_u8(&mut self, n: u8) { + self.write([n]) + } + + fn write_i8(&mut self, n: i8) { + self.write([n as u8]) + } +} + +fn extend_sign(val: u64, nbytes: uint) -> i64 { + let shift = (8 - nbytes) * 8; + (val << shift) as i64 >> shift +} + +#[cfg(test)] +mod test { + use super::ReaderUtil; + use option::{Some, None}; + use cell::Cell; + use rt::io::mem::MemReader; + use rt::io::mock::MockReader; + use rt::io::{read_error, placeholder_error}; + + #[test] + fn read_byte() { + let mut reader = MemReader::new(~[10]); + let byte = reader.read_byte(); + assert!(byte == Some(10)); + } + + #[test] + fn read_byte_0_bytes() { + let mut reader = MockReader::new(); + let count = Cell::new(0); + reader.read = |buf| { + do count.with_mut_ref |count| { + if *count == 0 { + *count = 1; + Some(0) + } else { + buf[0] = 10; + Some(1) + } + } + }; + let byte = reader.read_byte(); + assert!(byte == Some(10)); + } + + #[test] + fn read_byte_eof() { + let mut reader = MockReader::new(); + reader.read = |_| None; + let byte = reader.read_byte(); + assert!(byte == None); + } + + #[test] + fn read_byte_error() { + let mut reader = MockReader::new(); + reader.read = |_| { + read_error::cond.raise(placeholder_error()); + None + }; + do read_error::cond.trap(|_| { + }).in { + let byte = reader.read_byte(); + assert!(byte == None); + } + } + + #[test] + fn read_bytes() { + let mut reader = MemReader::new(~[10, 11, 12, 13]); + let bytes = reader.read_bytes(4); + assert!(bytes == ~[10, 11, 12, 13]); + } + + #[test] + fn read_bytes_partial() { + let mut reader = MockReader::new(); + let count = Cell::new(0); + reader.read = |buf| { + do count.with_mut_ref |count| { + if *count == 0 { + *count = 1; + buf[0] = 10; + buf[1] = 11; + Some(2) + } else { + buf[0] = 12; + buf[1] = 13; + Some(2) + } + } + }; + let bytes = reader.read_bytes(4); + assert!(bytes == ~[10, 11, 12, 13]); + } + + #[test] + fn read_bytes_eof() { + let mut reader = MemReader::new(~[10, 11]); + do read_error::cond.trap(|_| { + }).in { + assert!(reader.read_bytes(4) == ~[10, 11]); + } + } + + #[test] + fn push_bytes() { + let mut reader = MemReader::new(~[10, 11, 12, 13]); + let mut buf = ~[8, 9]; + reader.push_bytes(&mut buf, 4); + assert!(buf == ~[8, 9, 10, 11, 12, 13]); + } + + #[test] + fn push_bytes_partial() { + let mut reader = MockReader::new(); + let count = Cell::new(0); + reader.read = |buf| { + do count.with_mut_ref |count| { + if *count == 0 { + *count = 1; + buf[0] = 10; + buf[1] = 11; + Some(2) + } else { + buf[0] = 12; + buf[1] = 13; + Some(2) + } + } + }; + let mut buf = ~[8, 9]; + reader.push_bytes(&mut buf, 4); + assert!(buf == ~[8, 9, 10, 11, 12, 13]); + } + + #[test] + fn push_bytes_eof() { + let mut reader = MemReader::new(~[10, 11]); + let mut buf = ~[8, 9]; + do read_error::cond.trap(|_| { + }).in { + reader.push_bytes(&mut buf, 4); + assert!(buf == ~[8, 9, 10, 11]); + } + } + + #[test] + fn push_bytes_error() { + let mut reader = MockReader::new(); + let count = Cell::new(0); + reader.read = |buf| { + do count.with_mut_ref |count| { + if *count == 0 { + *count = 1; + buf[0] = 10; + Some(1) + } else { + read_error::cond.raise(placeholder_error()); + None + } + } + }; + let mut buf = ~[8, 9]; + do read_error::cond.trap(|_| { } ).in { + reader.push_bytes(&mut buf, 4); + } + assert!(buf == ~[8, 9, 10]); + } + + #[test] + #[should_fail] + #[ignore(cfg(windows))] + fn push_bytes_fail_reset_len() { + use unstable::finally::Finally; + + // push_bytes unsafely sets the vector length. This is testing that + // upon failure the length is reset correctly. + let mut reader = MockReader::new(); + let count = Cell::new(0); + reader.read = |buf| { + do count.with_mut_ref |count| { + if *count == 0 { + *count = 1; + buf[0] = 10; + Some(1) + } else { + read_error::cond.raise(placeholder_error()); + None + } + } + }; + let buf = @mut ~[8, 9]; + do (|| { + reader.push_bytes(&mut *buf, 4); + }).finally { + // NB: Using rtassert here to trigger abort on failure since this is a should_fail test + rtassert!(*buf == ~[8, 9, 10]); + } + } + + #[test] + fn read_to_end() { + let mut reader = MockReader::new(); + let count = Cell::new(0); + reader.read = |buf| { + do count.with_mut_ref |count| { + if *count == 0 { + *count = 1; + buf[0] = 10; + buf[1] = 11; + Some(2) + } else if *count == 1 { + *count = 2; + buf[0] = 12; + buf[1] = 13; + Some(2) + } else { + None + } + } + }; + let buf = reader.read_to_end(); + assert!(buf == ~[10, 11, 12, 13]); + } + + #[test] + #[should_fail] + #[ignore(cfg(windows))] + fn read_to_end_error() { + let mut reader = MockReader::new(); + let count = Cell::new(0); + reader.read = |buf| { + do count.with_mut_ref |count| { + if *count == 0 { + *count = 1; + buf[0] = 10; + buf[1] = 11; + Some(2) + } else { + read_error::cond.raise(placeholder_error()); + None + } + } + }; + let buf = reader.read_to_end(); + assert!(buf == ~[10, 11]); + } + + // XXX: Some problem with resolve here + /*#[test] + fn test_read_write_le() { + let uints = [0, 1, 2, 42, 10_123, 100_123_456, u64::max_value]; + + let mut writer = MemWriter::new(); + for uints.each |i| { + writer.write_le_u64(*i); + } + + let mut reader = MemReader::new(writer.inner()); + for uints.each |i| { + assert!(reader.read_le_u64() == *i); + } + } + + #[test] + fn test_read_write_be() { + let uints = [0, 1, 2, 42, 10_123, 100_123_456, u64::max_value]; + + let mut writer = MemWriter::new(); + for uints.each |i| { + writer.write_be_u64(*i); + } + + let mut reader = MemReader::new(writer.inner()); + for uints.each |i| { + assert!(reader.read_be_u64() == *i); + } + } + + #[test] + fn test_read_be_int_n() { + let ints = [i32::min_value, -123456, -42, -5, 0, 1, i32::max_value]; + + let mut writer = MemWriter::new(); + for ints.each |i| { + writer.write_be_i32(*i); + } + + let mut reader = MemReader::new(writer.inner()); + for ints.each |i| { + // this tests that the sign extension is working + // (comparing the values as i32 would not test this) + assert!(reader.read_be_int_n(4) == *i as i64); + } + } + + #[test] + fn test_read_f32() { + //big-endian floating-point 8.1250 + let buf = ~[0x41, 0x02, 0x00, 0x00]; + + let mut writer = MemWriter::new(); + writer.write(buf); + + let mut reader = MemReader::new(writer.inner()); + let f = reader.read_be_f32(); + assert!(f == 8.1250); + } + + #[test] + fn test_read_write_f32() { + let f:f32 = 8.1250; + + let mut writer = MemWriter::new(); + writer.write_be_f32(f); + writer.write_le_f32(f); + + let mut reader = MemReader::new(writer.inner()); + assert!(reader.read_be_f32() == 8.1250); + assert!(reader.read_le_f32() == 8.1250); + }*/ + +} diff --git a/src/libcore/rt/io/file.rs b/src/libstd/rt/io/file.rs similarity index 95% rename from src/libcore/rt/io/file.rs rename to src/libstd/rt/io/file.rs index 85dc180452ffc..1f61cf25fbdd4 100644 --- a/src/libcore/rt/io/file.rs +++ b/src/libstd/rt/io/file.rs @@ -10,7 +10,7 @@ use prelude::*; use super::support::PathLike; -use super::{Reader, Writer, Seek, Close}; +use super::{Reader, Writer, Seek}; use super::SeekStyle; /// # XXX @@ -69,10 +69,6 @@ impl Seek for FileStream { fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() } } -impl Close for FileStream { - fn close(&mut self) { fail!() } -} - #[test] #[ignore] fn super_simple_smoke_test_lets_go_read_some_files_and_have_a_good_time() { diff --git a/src/libcore/rt/io/flate.rs b/src/libstd/rt/io/flate.rs similarity index 98% rename from src/libcore/rt/io/flate.rs rename to src/libstd/rt/io/flate.rs index 24537bef329ab..0a9e0b1e38f23 100644 --- a/src/libcore/rt/io/flate.rs +++ b/src/libstd/rt/io/flate.rs @@ -100,6 +100,8 @@ mod test { use super::super::mem::*; use super::super::Decorator; + use str; + #[test] #[ignore] fn smoke_test() { @@ -114,8 +116,8 @@ mod test { let mut inflate_reader = InflateReader::new(mem_reader); let mut out_bytes = [0, .. 100]; let bytes_read = inflate_reader.read(out_bytes).get(); - assert!(bytes_read == in_bytes.len()); + assert_eq!(bytes_read, in_bytes.len()); let out_msg = str::from_bytes(out_bytes); assert!(in_msg == out_msg); } -} \ No newline at end of file +} diff --git a/src/libcore/rt/io/mem.rs b/src/libstd/rt/io/mem.rs similarity index 86% rename from src/libcore/rt/io/mem.rs rename to src/libstd/rt/io/mem.rs index 06e1466831df0..bd9cff76e5763 100644 --- a/src/libcore/rt/io/mem.rs +++ b/src/libstd/rt/io/mem.rs @@ -15,9 +15,10 @@ //! * Should probably have something like this for strings. //! * Should they implement Closable? Would take extra state. +use cmp::min; use prelude::*; use super::*; -use cmp::min; +use vec; /// Writes to an owned, growable byte vector pub struct MemWriter { @@ -86,7 +87,7 @@ impl Reader for MemReader { { let input = self.buf.slice(self.pos, self.pos + write_len); let output = vec::mut_slice(buf, 0, write_len); - assert!(input.len() == output.len()); + assert_eq!(input.len(), output.len()); vec::bytes::copy_memory(output, input, write_len); } self.pos += write_len; @@ -189,33 +190,33 @@ mod test { #[test] fn test_mem_writer() { let mut writer = MemWriter::new(); - assert!(writer.tell() == 0); + assert_eq!(writer.tell(), 0); writer.write([0]); - assert!(writer.tell() == 1); + assert_eq!(writer.tell(), 1); writer.write([1, 2, 3]); writer.write([4, 5, 6, 7]); - assert!(writer.tell() == 8); - assert!(writer.inner() == ~[0, 1, 2, 3, 4, 5 , 6, 7]); + assert_eq!(writer.tell(), 8); + assert_eq!(writer.inner(), ~[0, 1, 2, 3, 4, 5 , 6, 7]); } #[test] fn test_mem_reader() { let mut reader = MemReader::new(~[0, 1, 2, 3, 4, 5, 6, 7]); let mut buf = []; - assert!(reader.read(buf) == Some(0)); - assert!(reader.tell() == 0); + assert_eq!(reader.read(buf), Some(0)); + assert_eq!(reader.tell(), 0); let mut buf = [0]; - assert!(reader.read(buf) == Some(1)); - assert!(reader.tell() == 1); - assert!(buf == [0]); + assert_eq!(reader.read(buf), Some(1)); + assert_eq!(reader.tell(), 1); + assert_eq!(buf, [0]); let mut buf = [0, ..4]; - assert!(reader.read(buf) == Some(4)); - assert!(reader.tell() == 5); - assert!(buf == [1, 2, 3, 4]); - assert!(reader.read(buf) == Some(3)); - assert!(buf.slice(0, 3) == [5, 6, 7]); + assert_eq!(reader.read(buf), Some(4)); + assert_eq!(reader.tell(), 5); + assert_eq!(buf, [1, 2, 3, 4]); + assert_eq!(reader.read(buf), Some(3)); + assert_eq!(buf.slice(0, 3), [5, 6, 7]); assert!(reader.eof()); - assert!(reader.read(buf) == None); + assert_eq!(reader.read(buf), None); assert!(reader.eof()); } } diff --git a/src/libstd/rt/io/mock.rs b/src/libstd/rt/io/mock.rs new file mode 100644 index 0000000000000..b580b752bd985 --- /dev/null +++ b/src/libstd/rt/io/mock.rs @@ -0,0 +1,50 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use option::{Option, None}; +use rt::io::{Reader, Writer}; + +pub struct MockReader { + read: ~fn(buf: &mut [u8]) -> Option, + eof: ~fn() -> bool +} + +impl MockReader { + pub fn new() -> MockReader { + MockReader { + read: |_| None, + eof: || false + } + } +} + +impl Reader for MockReader { + fn read(&mut self, buf: &mut [u8]) -> Option { (self.read)(buf) } + fn eof(&mut self) -> bool { (self.eof)() } +} + +pub struct MockWriter { + write: ~fn(buf: &[u8]), + flush: ~fn() +} + +impl MockWriter { + pub fn new() -> MockWriter { + MockWriter { + write: |_| (), + flush: || () + } + } +} + +impl Writer for MockWriter { + fn write(&mut self, buf: &[u8]) { (self.write)(buf) } + fn flush(&mut self) { (self.flush)() } +} \ No newline at end of file diff --git a/src/libcore/rt/io/mod.rs b/src/libstd/rt/io/mod.rs similarity index 89% rename from src/libcore/rt/io/mod.rs rename to src/libstd/rt/io/mod.rs index fea32bc5b7509..0ec51a3aa941e 100644 --- a/src/libcore/rt/io/mod.rs +++ b/src/libstd/rt/io/mod.rs @@ -187,7 +187,7 @@ In particular code written to ignore errors and expect conditions to be unhandle will start passing around null or zero objects when wrapped in a condition handler. * XXX: How should we use condition handlers that return values? - +* XXX: Should EOF raise default conditions when EOF is not an error? # Issues withi/o scheduler affinity, work stealing, task pinning @@ -238,6 +238,7 @@ Out of scope * How does I/O relate to the Iterator trait? * std::base64 filters * Using conditions is a big unknown since we don't have much experience with them +* Too many uses of OtherIoError */ @@ -281,7 +282,6 @@ pub mod mem; pub mod stdio; /// Implementations for Option -#[cfg(not(stage0))] // Requires condition! fixes mod option; /// Basic stream compression. XXX: Belongs with other flate code @@ -312,6 +312,12 @@ pub mod native { } } +/// Mock implementations for testing +mod mock; + +/// The default buffer size for various I/O operations +/// XXX: Not pub +pub static DEFAULT_BUF_SIZE: uint = 1024 * 64; /// The type passed to I/O condition handlers to indicate error /// @@ -326,12 +332,16 @@ pub struct IoError { #[deriving(Eq)] pub enum IoErrorKind { + PreviousIoError, + OtherIoError, + EndOfFile, FileNotFound, - FilePermission, + PermissionDenied, ConnectionFailed, Closed, - OtherIoError, - PreviousIoError + ConnectionRefused, + ConnectionReset, + BrokenPipe } // XXX: Can't put doc comments on macros @@ -341,19 +351,36 @@ condition! { /*pub*/ io_error: super::IoError -> (); } +// XXX: Can't put doc comments on macros +// Raised by `read` on error +condition! { + // FIXME (#6009): uncomment `pub` after expansion support lands. + /*pub*/ read_error: super::IoError -> (); +} + pub trait Reader { /// Read bytes, up to the length of `buf` and place them in `buf`. - /// Returns the number of bytes read, or `None` on EOF. + /// Returns the number of bytes read. The number of bytes read my + /// be less than the number requested, even 0. Returns `None` on EOF. /// /// # Failure /// - /// Raises the `io_error` condition on error, then returns `None`. + /// Raises the `read_error` condition on error. If the condition + /// is handled then no guarantee is made about the number of bytes + /// read and the contents of `buf`. If the condition is handled + /// returns `None` (XXX see below). /// /// # XXX /// + /// * Should raise_default error on eof? + /// * If the condition is handled it should still return the bytes read, + /// in which case there's no need to return Option - but then you *have* + /// to install a handler to detect eof. + /// /// This doesn't take a `len` argument like the old `read`. /// Will people often need to slice their vectors to call this /// and will that be annoying? + /// Is it actually possible for 0 bytes to be read successfully? fn read(&mut self, buf: &mut [u8]) -> Option; /// Return whether the Reader has reached the end of the stream. @@ -383,16 +410,7 @@ pub trait Writer { fn flush(&mut self); } -/// I/O types that may be closed -/// -/// Any further operations performed on a closed resource will raise -/// on `io_error` -pub trait Close { - /// Close the I/O resource - fn close(&mut self); -} - -pub trait Stream: Reader + Writer + Close { } +pub trait Stream: Reader + Writer { } pub enum SeekStyle { /// Seek from the beginning of the stream @@ -466,6 +484,21 @@ pub fn standard_error(kind: IoErrorKind) -> IoError { detail: None } } + EndOfFile => { + IoError { + kind: EndOfFile, + desc: "End of file", + detail: None + } + } _ => fail!() } } + +pub fn placeholder_error() -> IoError { + IoError { + kind: OtherIoError, + desc: "Placeholder error. You shouldn't be seeing this", + detail: None + } +} \ No newline at end of file diff --git a/src/libcore/rt/io/native/file.rs b/src/libstd/rt/io/native/file.rs similarity index 93% rename from src/libcore/rt/io/native/file.rs rename to src/libstd/rt/io/native/file.rs index e203df815f2f4..31c90336a24c2 100644 --- a/src/libcore/rt/io/native/file.rs +++ b/src/libstd/rt/io/native/file.rs @@ -40,10 +40,6 @@ impl Writer for FileDesc { fn flush(&mut self) { fail!() } } -impl Close for FileDesc { - fn close(&mut self) { fail!() } -} - impl Seek for FileDesc { fn tell(&self) -> u64 { fail!() } @@ -72,10 +68,6 @@ impl Writer for CFile { fn flush(&mut self) { fail!() } } -impl Close for CFile { - fn close(&mut self) { fail!() } -} - impl Seek for CFile { fn tell(&self) -> u64 { fail!() } fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() } diff --git a/src/libcore/rt/io/net/http.rs b/src/libstd/rt/io/net/http.rs similarity index 100% rename from src/libcore/rt/io/net/http.rs rename to src/libstd/rt/io/net/http.rs diff --git a/src/libcore/rt/io/net/ip.rs b/src/libstd/rt/io/net/ip.rs similarity index 100% rename from src/libcore/rt/io/net/ip.rs rename to src/libstd/rt/io/net/ip.rs diff --git a/src/libstd/rt/io/net/tcp.rs b/src/libstd/rt/io/net/tcp.rs new file mode 100644 index 0000000000000..3607f781da3ff --- /dev/null +++ b/src/libstd/rt/io/net/tcp.rs @@ -0,0 +1,359 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use option::{Option, Some, None}; +use result::{Ok, Err}; +use rt::io::net::ip::IpAddr; +use rt::io::{Reader, Writer, Listener}; +use rt::io::{io_error, read_error, EndOfFile}; +use rt::rtio::{IoFactory, IoFactoryObject, + RtioTcpListener, RtioTcpListenerObject, + RtioTcpStream, RtioTcpStreamObject}; +use rt::local::Local; + +pub struct TcpStream { + rtstream: ~RtioTcpStreamObject +} + +impl TcpStream { + fn new(s: ~RtioTcpStreamObject) -> TcpStream { + TcpStream { + rtstream: s + } + } + + pub fn connect(addr: IpAddr) -> Option { + let stream = unsafe { + rtdebug!("borrowing io to connect"); + let io = Local::unsafe_borrow::(); + rtdebug!("about to connect"); + (*io).tcp_connect(addr) + }; + + match stream { + Ok(s) => { + Some(TcpStream::new(s)) + } + Err(ioerr) => { + rtdebug!("failed to connect: %?", ioerr); + io_error::cond.raise(ioerr); + return None; + } + } + } +} + +impl Reader for TcpStream { + fn read(&mut self, buf: &mut [u8]) -> Option { + let bytes_read = self.rtstream.read(buf); + match bytes_read { + Ok(read) => Some(read), + Err(ioerr) => { + // EOF is indicated by returning None + if ioerr.kind != EndOfFile { + read_error::cond.raise(ioerr); + } + return None; + } + } + } + + fn eof(&mut self) -> bool { fail!() } +} + +impl Writer for TcpStream { + fn write(&mut self, buf: &[u8]) { + let res = self.rtstream.write(buf); + match res { + Ok(_) => (), + Err(ioerr) => { + io_error::cond.raise(ioerr); + } + } + } + + fn flush(&mut self) { fail!() } +} + +pub struct TcpListener { + rtlistener: ~RtioTcpListenerObject, +} + +impl TcpListener { + pub fn bind(addr: IpAddr) -> Option { + let listener = unsafe { + let io = Local::unsafe_borrow::(); + (*io).tcp_bind(addr) + }; + match listener { + Ok(l) => { + Some(TcpListener { + rtlistener: l + }) + } + Err(ioerr) => { + io_error::cond.raise(ioerr); + return None; + } + } + } +} + +impl Listener for TcpListener { + fn accept(&mut self) -> Option { + let rtstream = self.rtlistener.accept(); + match rtstream { + Ok(s) => { + Some(TcpStream::new(s)) + } + Err(ioerr) => { + io_error::cond.raise(ioerr); + return None; + } + } + } +} + +#[cfg(test)] +mod test { + use super::*; + use int; + use cell::Cell; + use rt::test::*; + use rt::io::net::ip::Ipv4; + use rt::io::*; + + #[test] #[ignore] + fn bind_error() { + do run_in_newsched_task { + let mut called = false; + do io_error::cond.trap(|e| { + assert!(e.kind == PermissionDenied); + called = true; + }).in { + let addr = Ipv4(0, 0, 0, 0, 1); + let listener = TcpListener::bind(addr); + assert!(listener.is_none()); + } + assert!(called); + } + } + + #[test] + fn connect_error() { + do run_in_newsched_task { + let mut called = false; + do io_error::cond.trap(|e| { + assert!(e.kind == ConnectionRefused); + called = true; + }).in { + let addr = Ipv4(0, 0, 0, 0, 1); + let stream = TcpStream::connect(addr); + assert!(stream.is_none()); + } + assert!(called); + } + } + + #[test] + fn smoke_test() { + do run_in_newsched_task { + let addr = next_test_ip4(); + + do spawntask_immediately { + let mut listener = TcpListener::bind(addr); + let mut stream = listener.accept(); + let mut buf = [0]; + stream.read(buf); + assert!(buf[0] == 99); + } + + do spawntask_immediately { + let mut stream = TcpStream::connect(addr); + stream.write([99]); + } + } + } + + #[test] + fn read_eof() { + do run_in_newsched_task { + let addr = next_test_ip4(); + + do spawntask_immediately { + let mut listener = TcpListener::bind(addr); + let mut stream = listener.accept(); + let mut buf = [0]; + let nread = stream.read(buf); + assert!(nread.is_none()); + } + + do spawntask_immediately { + let _stream = TcpStream::connect(addr); + // Close + } + } + } + + #[test] + fn read_eof_twice() { + do run_in_newsched_task { + let addr = next_test_ip4(); + + do spawntask_immediately { + let mut listener = TcpListener::bind(addr); + let mut stream = listener.accept(); + let mut buf = [0]; + let nread = stream.read(buf); + assert!(nread.is_none()); + let nread = stream.read(buf); + assert!(nread.is_none()); + } + + do spawntask_immediately { + let _stream = TcpStream::connect(addr); + // Close + } + } + } + + #[test] + fn write_close() { + do run_in_newsched_task { + let addr = next_test_ip4(); + + do spawntask_immediately { + let mut listener = TcpListener::bind(addr); + let mut stream = listener.accept(); + let buf = [0]; + loop { + let mut stop = false; + do io_error::cond.trap(|e| { + // NB: ECONNRESET on linux, EPIPE on mac + assert!(e.kind == ConnectionReset || e.kind == BrokenPipe); + stop = true; + }).in { + stream.write(buf); + } + if stop { break } + } + } + + do spawntask_immediately { + let _stream = TcpStream::connect(addr); + // Close + } + } + } + + #[test] + fn multiple_connect_serial() { + do run_in_newsched_task { + let addr = next_test_ip4(); + let max = 10; + + do spawntask_immediately { + let mut listener = TcpListener::bind(addr); + for max.times { + let mut stream = listener.accept(); + let mut buf = [0]; + stream.read(buf); + assert_eq!(buf[0], 99); + } + } + + do spawntask_immediately { + for max.times { + let mut stream = TcpStream::connect(addr); + stream.write([99]); + } + } + } + } + + #[test] + fn multiple_connect_interleaved_greedy_schedule() { + do run_in_newsched_task { + let addr = next_test_ip4(); + static MAX: int = 10; + + do spawntask_immediately { + let mut listener = TcpListener::bind(addr); + for int::range(0, MAX) |i| { + let stream = Cell::new(listener.accept()); + rtdebug!("accepted"); + // Start another task to handle the connection + do spawntask_immediately { + let mut stream = stream.take(); + let mut buf = [0]; + stream.read(buf); + assert!(buf[0] == i as u8); + rtdebug!("read"); + } + } + } + + connect(0, addr); + + fn connect(i: int, addr: IpAddr) { + if i == MAX { return } + + do spawntask_immediately { + rtdebug!("connecting"); + let mut stream = TcpStream::connect(addr); + // Connect again before writing + connect(i + 1, addr); + rtdebug!("writing"); + stream.write([i as u8]); + } + } + } + } + + #[test] + fn multiple_connect_interleaved_lazy_schedule() { + do run_in_newsched_task { + let addr = next_test_ip4(); + static MAX: int = 10; + + do spawntask_immediately { + let mut listener = TcpListener::bind(addr); + for int::range(0, MAX) |_| { + let stream = Cell::new(listener.accept()); + rtdebug!("accepted"); + // Start another task to handle the connection + do spawntask_later { + let mut stream = stream.take(); + let mut buf = [0]; + stream.read(buf); + assert!(buf[0] == 99); + rtdebug!("read"); + } + } + } + + connect(0, addr); + + fn connect(i: int, addr: IpAddr) { + if i == MAX { return } + + do spawntask_later { + rtdebug!("connecting"); + let mut stream = TcpStream::connect(addr); + // Connect again before writing + connect(i + 1, addr); + rtdebug!("writing"); + stream.write([99]); + } + } + } + } + +} diff --git a/src/libcore/rt/io/net/udp.rs b/src/libstd/rt/io/net/udp.rs similarity index 94% rename from src/libcore/rt/io/net/udp.rs rename to src/libstd/rt/io/net/udp.rs index 1f1254a7029f0..bb5457e334dda 100644 --- a/src/libcore/rt/io/net/udp.rs +++ b/src/libstd/rt/io/net/udp.rs @@ -32,10 +32,6 @@ impl Writer for UdpStream { fn flush(&mut self) { fail!() } } -impl Close for UdpStream { - fn close(&mut self) { fail!() } -} - pub struct UdpListener; impl UdpListener { diff --git a/src/libcore/rt/io/net/unix.rs b/src/libstd/rt/io/net/unix.rs similarity index 94% rename from src/libcore/rt/io/net/unix.rs rename to src/libstd/rt/io/net/unix.rs index f449a857467cc..b85b7dd059d82 100644 --- a/src/libcore/rt/io/net/unix.rs +++ b/src/libstd/rt/io/net/unix.rs @@ -32,10 +32,6 @@ impl Writer for UnixStream { fn flush(&mut self) { fail!() } } -impl Close for UnixStream { - fn close(&mut self) { fail!() } -} - pub struct UnixListener; impl UnixListener { diff --git a/src/libcore/rt/io/option.rs b/src/libstd/rt/io/option.rs similarity index 87% rename from src/libcore/rt/io/option.rs rename to src/libstd/rt/io/option.rs index 95f8711cb5bd5..d71ef55d3ad97 100644 --- a/src/libcore/rt/io/option.rs +++ b/src/libstd/rt/io/option.rs @@ -18,7 +18,7 @@ use option::*; use super::{Reader, Writer, Listener}; -use super::{standard_error, PreviousIoError, io_error, IoError}; +use super::{standard_error, PreviousIoError, io_error, read_error, IoError}; fn prev_io_error() -> IoError { standard_error(PreviousIoError) @@ -45,7 +45,7 @@ impl Reader for Option { match *self { Some(ref mut reader) => reader.read(buf), None => { - io_error::cond.raise(prev_io_error()); + read_error::cond.raise(prev_io_error()); None } } @@ -79,7 +79,7 @@ mod test { use option::*; use super::super::mem::*; use rt::test::*; - use super::super::{PreviousIoError, io_error}; + use super::super::{PreviousIoError, io_error, read_error}; #[test] fn test_option_writer() { @@ -87,7 +87,7 @@ mod test { let mut writer: Option = Some(MemWriter::new()); writer.write([0, 1, 2]); writer.flush(); - assert!(writer.unwrap().inner() == ~[0, 1, 2]); + assert_eq!(writer.unwrap().inner(), ~[0, 1, 2]); } } @@ -98,7 +98,7 @@ mod test { let mut called = false; do io_error::cond.trap(|err| { - assert!(err.kind == PreviousIoError); + assert_eq!(err.kind, PreviousIoError); called = true; }).in { writer.write([0, 0, 0]); @@ -107,7 +107,7 @@ mod test { let mut called = false; do io_error::cond.trap(|err| { - assert!(err.kind == PreviousIoError); + assert_eq!(err.kind, PreviousIoError); called = true; }).in { writer.flush(); @@ -122,7 +122,7 @@ mod test { let mut reader: Option = Some(MemReader::new(~[0, 1, 2, 3])); let mut buf = [0, 0]; reader.read(buf); - assert!(buf == [0, 1]); + assert_eq!(buf, [0, 1]); assert!(!reader.eof()); } } @@ -133,8 +133,8 @@ mod test { let mut buf = []; let mut called = false; - do io_error::cond.trap(|err| { - assert!(err.kind == PreviousIoError); + do read_error::cond.trap(|err| { + assert_eq!(err.kind, PreviousIoError); called = true; }).in { reader.read(buf); @@ -143,7 +143,7 @@ mod test { let mut called = false; do io_error::cond.trap(|err| { - assert!(err.kind == PreviousIoError); + assert_eq!(err.kind, PreviousIoError); called = true; }).in { assert!(reader.eof()); diff --git a/src/libcore/rt/io/stdio.rs b/src/libstd/rt/io/stdio.rs similarity index 87% rename from src/libcore/rt/io/stdio.rs rename to src/libstd/rt/io/stdio.rs index 26950986f7a09..247fe9544088b 100644 --- a/src/libcore/rt/io/stdio.rs +++ b/src/libstd/rt/io/stdio.rs @@ -9,7 +9,7 @@ // except according to those terms. use prelude::*; -use super::{Reader, Writer, Close}; +use super::{Reader, Writer}; pub fn stdin() -> StdReader { fail!() } @@ -39,10 +39,6 @@ impl Reader for StdReader { fn eof(&mut self) -> bool { fail!() } } -impl Close for StdReader { - fn close(&mut self) { fail!() } -} - pub struct StdWriter; impl StdWriter { @@ -55,6 +51,3 @@ impl Writer for StdWriter { fn flush(&mut self) { fail!() } } -impl Close for StdWriter { - fn close(&mut self) { fail!() } -} diff --git a/src/libcore/rt/io/support.rs b/src/libstd/rt/io/support.rs similarity index 100% rename from src/libcore/rt/io/support.rs rename to src/libstd/rt/io/support.rs diff --git a/src/libstd/rt/local.rs b/src/libstd/rt/local.rs new file mode 100644 index 0000000000000..313123c38b58d --- /dev/null +++ b/src/libstd/rt/local.rs @@ -0,0 +1,118 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use option::{Option, Some, None}; +use rt::sched::Scheduler; +use rt::task::Task; +use rt::local_ptr; +use rt::rtio::{EventLoop, IoFactoryObject}; + +pub trait Local { + fn put(value: ~Self); + fn take() -> ~Self; + fn exists() -> bool; + fn borrow(f: &fn(&mut Self)); + unsafe fn unsafe_borrow() -> *mut Self; + unsafe fn try_unsafe_borrow() -> Option<*mut Self>; +} + +impl Local for Scheduler { + fn put(value: ~Scheduler) { unsafe { local_ptr::put(value) }} + fn take() -> ~Scheduler { unsafe { local_ptr::take() } } + fn exists() -> bool { local_ptr::exists() } + fn borrow(f: &fn(&mut Scheduler)) { unsafe { local_ptr::borrow(f) } } + unsafe fn unsafe_borrow() -> *mut Scheduler { local_ptr::unsafe_borrow() } + unsafe fn try_unsafe_borrow() -> Option<*mut Scheduler> { abort!("unimpl") } +} + +impl Local for Task { + fn put(_value: ~Task) { abort!("unimpl") } + fn take() -> ~Task { abort!("unimpl") } + fn exists() -> bool { abort!("unimpl") } + fn borrow(f: &fn(&mut Task)) { + do Local::borrow:: |sched| { + match sched.current_task { + Some(~ref mut task) => { + f(&mut *task.task) + } + None => { + abort!("no scheduler") + } + } + } + } + unsafe fn unsafe_borrow() -> *mut Task { + match (*Local::unsafe_borrow::()).current_task { + Some(~ref mut task) => { + let s: *mut Task = &mut *task.task; + return s; + } + None => { + // Don't fail. Infinite recursion + abort!("no scheduler") + } + } + } + unsafe fn try_unsafe_borrow() -> Option<*mut Task> { + if Local::exists::() { + Some(Local::unsafe_borrow()) + } else { + None + } + } +} + +// XXX: This formulation won't work once ~IoFactoryObject is a real trait pointer +impl Local for IoFactoryObject { + fn put(_value: ~IoFactoryObject) { abort!("unimpl") } + fn take() -> ~IoFactoryObject { abort!("unimpl") } + fn exists() -> bool { abort!("unimpl") } + fn borrow(_f: &fn(&mut IoFactoryObject)) { abort!("unimpl") } + unsafe fn unsafe_borrow() -> *mut IoFactoryObject { + let sched = Local::unsafe_borrow::(); + let io: *mut IoFactoryObject = (*sched).event_loop.io().unwrap(); + return io; + } + unsafe fn try_unsafe_borrow() -> Option<*mut IoFactoryObject> { abort!("unimpl") } +} + +#[cfg(test)] +mod test { + use rt::sched::Scheduler; + use rt::uv::uvio::UvEventLoop; + use super::*; + + #[test] + fn thread_local_scheduler_smoke_test() { + let scheduler = ~UvEventLoop::new_scheduler(); + Local::put(scheduler); + let _scheduler: ~Scheduler = Local::take(); + } + + #[test] + fn thread_local_scheduler_two_instances() { + let scheduler = ~UvEventLoop::new_scheduler(); + Local::put(scheduler); + let _scheduler: ~Scheduler = Local::take(); + let scheduler = ~UvEventLoop::new_scheduler(); + Local::put(scheduler); + let _scheduler: ~Scheduler = Local::take(); + } + + #[test] + fn borrow_smoke_test() { + let scheduler = ~UvEventLoop::new_scheduler(); + Local::put(scheduler); + unsafe { + let _scheduler: *mut Scheduler = Local::unsafe_borrow(); + } + let _scheduler: ~Scheduler = Local::take(); + } +} diff --git a/src/libcore/rt/local_heap.rs b/src/libstd/rt/local_heap.rs similarity index 100% rename from src/libcore/rt/local_heap.rs rename to src/libstd/rt/local_heap.rs diff --git a/src/libstd/rt/local_ptr.rs b/src/libstd/rt/local_ptr.rs new file mode 100644 index 0000000000000..0db903f81eec7 --- /dev/null +++ b/src/libstd/rt/local_ptr.rs @@ -0,0 +1,145 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Access to a single thread-local pointer. +//! +//! The runtime will use this for storing ~Task. +//! +//! XXX: Add runtime checks for usage of inconsistent pointer types. +//! and for overwriting an existing pointer. + +use libc::c_void; +use cast; +use ptr; +use cell::Cell; +use option::{Option, Some, None}; +use unstable::finally::Finally; +use tls = rt::thread_local_storage; + +/// Initialize the TLS key. Other ops will fail if this isn't executed first. +pub fn init_tls_key() { + unsafe { + rust_initialize_rt_tls_key(); + extern { + fn rust_initialize_rt_tls_key(); + } + } +} + +/// Give a pointer to thread-local storage. +/// +/// # Safety note +/// +/// Does not validate the pointer type. +pub unsafe fn put(sched: ~T) { + let key = tls_key(); + let void_ptr: *mut c_void = cast::transmute(sched); + tls::set(key, void_ptr); +} + +/// Take ownership of a pointer from thread-local storage. +/// +/// # Safety note +/// +/// Does not validate the pointer type. +pub unsafe fn take() -> ~T { + let key = tls_key(); + let void_ptr: *mut c_void = tls::get(key); + rtassert!(void_ptr.is_not_null()); + let ptr: ~T = cast::transmute(void_ptr); + tls::set(key, ptr::mut_null()); + return ptr; +} + +/// Check whether there is a thread-local pointer installed. +pub fn exists() -> bool { + unsafe { + match maybe_tls_key() { + Some(key) => tls::get(key).is_not_null(), + None => false + } + } +} + +/// Borrow the thread-local scheduler from thread-local storage. +/// While the scheduler is borrowed it is not available in TLS. +/// +/// # Safety note +/// +/// Does not validate the pointer type. +pub unsafe fn borrow(f: &fn(&mut T)) { + let mut value = take(); + + // XXX: Need a different abstraction from 'finally' here to avoid unsafety + let unsafe_ptr = cast::transmute_mut_region(&mut *value); + let value_cell = Cell::new(value); + + do (|| { + f(unsafe_ptr); + }).finally { + put(value_cell.take()); + } +} + +/// Borrow a mutable reference to the thread-local Scheduler +/// +/// # Safety Note +/// +/// Because this leaves the Scheduler in thread-local storage it is possible +/// For the Scheduler pointer to be aliased +pub unsafe fn unsafe_borrow() -> *mut T { + let key = tls_key(); + let mut void_sched: *mut c_void = tls::get(key); + rtassert!(void_sched.is_not_null()); + { + let sched: *mut *mut c_void = &mut void_sched; + let sched: *mut ~T = sched as *mut ~T; + let sched: *mut T = &mut **sched; + return sched; + } +} + +fn tls_key() -> tls::Key { + match maybe_tls_key() { + Some(key) => key, + None => abort!("runtime tls key not initialized") + } +} + +fn maybe_tls_key() -> Option { + unsafe { + let key: *mut c_void = rust_get_rt_tls_key(); + let key: &mut tls::Key = cast::transmute(key); + let key = *key; + // Check that the key has been initialized. + + // NB: This is a little racy because, while the key is + // initalized under a mutex and it's assumed to be initalized + // in the Scheduler ctor by any thread that needs to use it, + // we are not accessing the key under a mutex. Threads that + // are not using the new Scheduler but still *want to check* + // whether they are running under a new Scheduler may see a 0 + // value here that is in the process of being initialized in + // another thread. I think this is fine since the only action + // they could take if it was initialized would be to check the + // thread-local value and see that it's not set. + if key != -1 { + return Some(key); + } else { + return None; + } + } + + extern { + #[fast_ffi] + fn rust_get_rt_tls_key() -> *mut c_void; + } + +} diff --git a/src/libstd/rt/logging.rs b/src/libstd/rt/logging.rs new file mode 100644 index 0000000000000..a0d0539768912 --- /dev/null +++ b/src/libstd/rt/logging.rs @@ -0,0 +1,68 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use either::*; + +pub trait Logger { + fn log(&mut self, msg: Either<~str, &'static str>); +} + +pub struct StdErrLogger; + +impl Logger for StdErrLogger { + fn log(&mut self, msg: Either<~str, &'static str>) { + use io::{Writer, WriterUtil}; + + let s: &str = match msg { + Left(ref s) => { + let s: &str = *s; + s + } + Right(ref s) => { + let s: &str = *s; + s + } + }; + let dbg = ::libc::STDERR_FILENO as ::io::fd_t; + dbg.write_str(s); + dbg.write_str("\n"); + dbg.flush(); + } +} + +/// Configure logging by traversing the crate map and setting the +/// per-module global logging flags based on the logging spec +pub fn init(crate_map: *u8) { + use os; + use str; + use ptr; + use option::{Some, None}; + use libc::c_char; + + let log_spec = os::getenv("RUST_LOG"); + match log_spec { + Some(spec) => { + do str::as_c_str(spec) |s| { + unsafe { + rust_update_log_settings(crate_map, s); + } + } + } + None => { + unsafe { + rust_update_log_settings(crate_map, ptr::null()); + } + } + } + + extern { + fn rust_update_log_settings(crate_map: *u8, settings: *c_char); + } +} diff --git a/src/libstd/rt/message_queue.rs b/src/libstd/rt/message_queue.rs new file mode 100644 index 0000000000000..5b60543344de1 --- /dev/null +++ b/src/libstd/rt/message_queue.rs @@ -0,0 +1,57 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use container::Container; +use kinds::Owned; +use vec::OwnedVector; +use cell::Cell; +use option::*; +use unstable::sync::{Exclusive, exclusive}; +use clone::Clone; + +pub struct MessageQueue { + // XXX: Another mystery bug fixed by boxing this lock + priv queue: ~Exclusive<~[T]> +} + +impl MessageQueue { + pub fn new() -> MessageQueue { + MessageQueue { + queue: ~exclusive(~[]) + } + } + + pub fn push(&mut self, value: T) { + unsafe { + let value = Cell::new(value); + self.queue.with(|q| q.push(value.take()) ); + } + } + + pub fn pop(&mut self) -> Option { + unsafe { + do self.queue.with |q| { + if !q.is_empty() { + Some(q.shift()) + } else { + None + } + } + } + } +} + +impl Clone for MessageQueue { + fn clone(&self) -> MessageQueue { + MessageQueue { + queue: self.queue.clone() + } + } +} diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs new file mode 100644 index 0000000000000..f9f433b9416b4 --- /dev/null +++ b/src/libstd/rt/mod.rs @@ -0,0 +1,243 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/*! The Rust Runtime, including the task scheduler and I/O + +The `rt` module provides the private runtime infrastructure necessary +to support core language features like the exchange and local heap, +the garbage collector, logging, local data and unwinding. It also +implements the default task scheduler and task model. Initialization +routines are provided for setting up runtime resources in common +configurations, including that used by `rustc` when generating +executables. + +It is intended that the features provided by `rt` can be factored in a +way such that the core library can be built with different 'profiles' +for different use cases, e.g. excluding the task scheduler. A number +of runtime features though are critical to the functioning of the +language and an implementation must be provided regardless of the +execution environment. + +Of foremost importance is the global exchange heap, in the module +`global_heap`. Very little practical Rust code can be written without +access to the global heap. Unlike most of `rt` the global heap is +truly a global resource and generally operates independently of the +rest of the runtime. + +All other runtime features are task-local, including the local heap, +the garbage collector, local storage, logging and the stack unwinder. + +The relationship between `rt` and the rest of the core library is +not entirely clear yet and some modules will be moving into or +out of `rt` as development proceeds. + +Several modules in `core` are clients of `rt`: + +* `core::task` - The user-facing interface to the Rust task model. +* `core::task::local_data` - The interface to local data. +* `core::gc` - The garbage collector. +* `core::unstable::lang` - Miscellaneous lang items, some of which rely on `core::rt`. +* `core::condition` - Uses local data. +* `core::cleanup` - Local heap destruction. +* `core::io` - In the future `core::io` will use an `rt` implementation. +* `core::logging` +* `core::pipes` +* `core::comm` +* `core::stackwalk` + +*/ + +#[doc(hidden)]; + +use ptr::RawPtr; + +/// The global (exchange) heap. +pub mod global_heap; + +/// Implementations of language-critical runtime features like @. +pub mod task; + +/// The coroutine task scheduler, built on the `io` event loop. +mod sched; + +/// Synchronous I/O. +#[path = "io/mod.rs"] +pub mod io; + +/// The EventLoop and internal synchronous I/O interface. +mod rtio; + +/// libuv and default rtio implementation. +#[path = "uv/mod.rs"] +pub mod uv; + +/// The Local trait for types that are accessible via thread-local +/// or task-local storage. +pub mod local; + +/// A parallel work-stealing deque. +mod work_queue; + +/// A parallel queue. +mod message_queue; + +/// Stack segments and caching. +mod stack; + +/// CPU context swapping. +mod context; + +/// Bindings to system threading libraries. +mod thread; + +/// The runtime configuration, read from environment variables +pub mod env; + +/// The local, managed heap +mod local_heap; + +/// The Logger trait and implementations +pub mod logging; + +/// Tools for testing the runtime +pub mod test; + +/// Reference counting +pub mod rc; + +/// A simple single-threaded channel type for passing buffered data between +/// scheduler and task context +pub mod tube; + +/// Simple reimplementation of core::comm +pub mod comm; + +// FIXME #5248 shouldn't be pub +/// The runtime needs to be able to put a pointer into thread-local storage. +pub mod local_ptr; + +// FIXME #5248: The import in `sched` doesn't resolve unless this is pub! +/// Bindings to pthread/windows thread-local storage. +pub mod thread_local_storage; + + +/// Set up a default runtime configuration, given compiler-supplied arguments. +/// +/// This is invoked by the `start` _language item_ (unstable::lang) to +/// run a Rust executable. +/// +/// # Arguments +/// +/// * `argc` & `argv` - The argument vector. On Unix this information is used +/// by os::args. +/// * `crate_map` - Runtime information about the executing crate, mostly for logging +/// +/// # Return value +/// +/// The return value is used as the process return code. 0 on success, 101 on error. +pub fn start(_argc: int, _argv: **u8, crate_map: *u8, main: ~fn()) -> int { + + use self::sched::{Scheduler, Coroutine}; + use self::uv::uvio::UvEventLoop; + + init(crate_map); + + let loop_ = ~UvEventLoop::new(); + let mut sched = ~Scheduler::new(loop_); + let main_task = ~Coroutine::new(&mut sched.stack_pool, main); + + sched.enqueue_task(main_task); + sched.run(); + + return 0; +} + +/// One-time runtime initialization. Currently all this does is set up logging +/// based on the RUST_LOG environment variable. +pub fn init(crate_map: *u8) { + logging::init(crate_map); +} + +/// Possible contexts in which Rust code may be executing. +/// Different runtime services are available depending on context. +/// Mostly used for determining if we're using the new scheduler +/// or the old scheduler. +#[deriving(Eq)] +pub enum RuntimeContext { + // Only the exchange heap is available + GlobalContext, + // The scheduler may be accessed + SchedulerContext, + // Full task services, e.g. local heap, unwinding + TaskContext, + // Running in an old-style task + OldTaskContext +} + +/// Determine the current RuntimeContext +pub fn context() -> RuntimeContext { + + use task::rt::rust_task; + use self::local::Local; + use self::sched::Scheduler; + + // XXX: Hitting TLS twice to check if the scheduler exists + // then to check for the task is not good for perf + if unsafe { rust_try_get_task().is_not_null() } { + return OldTaskContext; + } else { + if Local::exists::() { + let context = ::cell::Cell::new_empty(); + do Local::borrow:: |sched| { + if sched.in_task_context() { + context.put_back(TaskContext); + } else { + context.put_back(SchedulerContext); + } + } + return context.take(); + } else { + return GlobalContext; + } + } + + pub extern { + #[rust_stack] + fn rust_try_get_task() -> *rust_task; + } +} + +#[test] +fn test_context() { + use unstable::run_in_bare_thread; + use self::sched::{Scheduler, Coroutine}; + use rt::uv::uvio::UvEventLoop; + use cell::Cell; + use rt::local::Local; + + assert_eq!(context(), OldTaskContext); + do run_in_bare_thread { + assert_eq!(context(), GlobalContext); + let mut sched = ~UvEventLoop::new_scheduler(); + let task = ~do Coroutine::new(&mut sched.stack_pool) { + assert_eq!(context(), TaskContext); + let sched = Local::take::(); + do sched.deschedule_running_task_and_then() |task| { + assert_eq!(context(), SchedulerContext); + let task = Cell::new(task); + do Local::borrow:: |sched| { + sched.enqueue_task(task.take()); + } + } + }; + sched.enqueue_task(task); + sched.run(); + } +} diff --git a/src/libstd/rt/rc.rs b/src/libstd/rt/rc.rs new file mode 100644 index 0000000000000..1c0c8c14fdfa6 --- /dev/null +++ b/src/libstd/rt/rc.rs @@ -0,0 +1,142 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! An owned, task-local, reference counted type +//! +//! # Safety note +//! +//! XXX There is currently no type-system mechanism for enforcing that +//! reference counted types are both allocated on the exchange heap +//! and also non-sendable +//! +//! This doesn't prevent borrowing multiple aliasable mutable pointers + +use ops::Drop; +use clone::Clone; +use libc::c_void; +use cast; + +pub struct RC { + p: *c_void // ~(uint, T) +} + +impl RC { + pub fn new(val: T) -> RC { + unsafe { + let v = ~(1, val); + let p: *c_void = cast::transmute(v); + RC { p: p } + } + } + + fn get_mut_state(&mut self) -> *mut (uint, T) { + unsafe { + let p: &mut ~(uint, T) = cast::transmute(&mut self.p); + let p: *mut (uint, T) = &mut **p; + return p; + } + } + + fn get_state(&self) -> *(uint, T) { + unsafe { + let p: &~(uint, T) = cast::transmute(&self.p); + let p: *(uint, T) = &**p; + return p; + } + } + + pub fn unsafe_borrow_mut(&mut self) -> *mut T { + unsafe { + match *self.get_mut_state() { + (_, ref mut p) => { + let p: *mut T = p; + return p; + } + } + } + } + + pub fn refcount(&self) -> uint { + unsafe { + match *self.get_state() { + (count, _) => count + } + } + } +} + +#[unsafe_destructor] +impl Drop for RC { + fn finalize(&self) { + assert!(self.refcount() > 0); + + unsafe { + // XXX: Mutable finalizer + let this: &mut RC = cast::transmute_mut(self); + + match *this.get_mut_state() { + (ref mut count, _) => { + *count = *count - 1 + } + } + + if this.refcount() == 0 { + let _: ~(uint, T) = cast::transmute(this.p); + } + } + } +} + +impl Clone for RC { + fn clone(&self) -> RC { + unsafe { + // XXX: Mutable clone + let this: &mut RC = cast::transmute_mut(self); + + match *this.get_mut_state() { + (ref mut count, _) => { + *count = *count + 1; + } + } + } + + RC { p: self.p } + } +} + +#[cfg(test)] +mod test { + use super::RC; + + #[test] + fn smoke_test() { + unsafe { + let mut v1 = RC::new(100); + assert!(*v1.unsafe_borrow_mut() == 100); + assert!(v1.refcount() == 1); + + let mut v2 = v1.clone(); + assert!(*v2.unsafe_borrow_mut() == 100); + assert!(v2.refcount() == 2); + + *v2.unsafe_borrow_mut() = 200; + assert!(*v2.unsafe_borrow_mut() == 200); + assert!(*v1.unsafe_borrow_mut() == 200); + + let v3 = v2.clone(); + assert!(v3.refcount() == 3); + { + let _v1 = v1; + let _v2 = v2; + } + assert!(v3.refcount() == 1); + } + } +} diff --git a/src/libcore/rt/rtio.rs b/src/libstd/rt/rtio.rs similarity index 55% rename from src/libcore/rt/rtio.rs rename to src/libstd/rt/rtio.rs index fd64438c61b46..4b5eda22ff5de 100644 --- a/src/libcore/rt/rtio.rs +++ b/src/libstd/rt/rtio.rs @@ -11,32 +11,35 @@ use option::*; use result::*; +use rt::io::IoError; use super::io::net::ip::IpAddr; +use rt::uv::uvio; // XXX: ~object doesn't work currently so these are some placeholder // types to use instead -pub type EventLoopObject = super::uvio::UvEventLoop; -pub type IoFactoryObject = super::uvio::UvIoFactory; -pub type StreamObject = super::uvio::UvStream; -pub type TcpListenerObject = super::uvio::UvTcpListener; +pub type EventLoopObject = uvio::UvEventLoop; +pub type IoFactoryObject = uvio::UvIoFactory; +pub type RtioTcpStreamObject = uvio::UvTcpStream; +pub type RtioTcpListenerObject = uvio::UvTcpListener; pub trait EventLoop { fn run(&mut self); fn callback(&mut self, ~fn()); + fn callback_ms(&mut self, ms: u64, ~fn()); /// The asynchronous I/O services. Not all event loops may provide one fn io<'a>(&'a mut self) -> Option<&'a mut IoFactoryObject>; } pub trait IoFactory { - fn connect(&mut self, addr: IpAddr) -> Option<~StreamObject>; - fn bind(&mut self, addr: IpAddr) -> Option<~TcpListenerObject>; + fn tcp_connect(&mut self, addr: IpAddr) -> Result<~RtioTcpStreamObject, IoError>; + fn tcp_bind(&mut self, addr: IpAddr) -> Result<~RtioTcpListenerObject, IoError>; } -pub trait TcpListener { - fn listen(&mut self) -> Option<~StreamObject>; +pub trait RtioTcpListener { + fn accept(&mut self) -> Result<~RtioTcpStreamObject, IoError>; } -pub trait Stream { - fn read(&mut self, buf: &mut [u8]) -> Result; - fn write(&mut self, buf: &[u8]) -> Result<(), ()>; +pub trait RtioTcpStream { + fn read(&mut self, buf: &mut [u8]) -> Result; + fn write(&mut self, buf: &[u8]) -> Result<(), IoError>; } diff --git a/src/libstd/rt/sched.rs b/src/libstd/rt/sched.rs new file mode 100644 index 0000000000000..929b44f79b5d9 --- /dev/null +++ b/src/libstd/rt/sched.rs @@ -0,0 +1,554 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use option::*; +use sys; +use cast::transmute; +use cell::Cell; + +use super::work_queue::WorkQueue; +use super::stack::{StackPool, StackSegment}; +use super::rtio::{EventLoop, EventLoopObject}; +use super::context::Context; +use super::task::Task; +use rt::local_ptr; +use rt::local::Local; + +/// The Scheduler is responsible for coordinating execution of Coroutines +/// on a single thread. When the scheduler is running it is owned by +/// thread local storage and the running task is owned by the +/// scheduler. +pub struct Scheduler { + priv work_queue: WorkQueue<~Coroutine>, + stack_pool: StackPool, + /// The event loop used to drive the scheduler and perform I/O + event_loop: ~EventLoopObject, + /// The scheduler's saved context. + /// Always valid when a task is executing, otherwise not + priv saved_context: Context, + /// The currently executing task + current_task: Option<~Coroutine>, + /// An action performed after a context switch on behalf of the + /// code running before the context switch + priv cleanup_job: Option +} + +// XXX: Some hacks to put a &fn in Scheduler without borrowck +// complaining +type UnsafeTaskReceiver = sys::Closure; +trait ClosureConverter { + fn from_fn(&fn(~Coroutine)) -> Self; + fn to_fn(self) -> &fn(~Coroutine); +} +impl ClosureConverter for UnsafeTaskReceiver { + fn from_fn(f: &fn(~Coroutine)) -> UnsafeTaskReceiver { unsafe { transmute(f) } } + fn to_fn(self) -> &fn(~Coroutine) { unsafe { transmute(self) } } +} + +enum CleanupJob { + DoNothing, + GiveTask(~Coroutine, UnsafeTaskReceiver) +} + +impl Scheduler { + pub fn in_task_context(&self) -> bool { self.current_task.is_some() } + + pub fn new(event_loop: ~EventLoopObject) -> Scheduler { + + // Lazily initialize the runtime TLS key + local_ptr::init_tls_key(); + + Scheduler { + event_loop: event_loop, + work_queue: WorkQueue::new(), + stack_pool: StackPool::new(), + saved_context: Context::empty(), + current_task: None, + cleanup_job: None + } + } + + // XXX: This may eventually need to be refactored so that + // the scheduler itself doesn't have to call event_loop.run. + // That will be important for embedding the runtime into external + // event loops. + pub fn run(~self) -> ~Scheduler { + assert!(!self.in_task_context()); + + let mut self_sched = self; + + unsafe { + let event_loop: *mut ~EventLoopObject = { + let event_loop: *mut ~EventLoopObject = &mut self_sched.event_loop; + event_loop + }; + + // Give ownership of the scheduler (self) to the thread + Local::put(self_sched); + + (*event_loop).run(); + } + + let sched = Local::take::(); + assert!(sched.work_queue.is_empty()); + return sched; + } + + /// Schedule a task to be executed later. + /// + /// Pushes the task onto the work stealing queue and tells the event loop + /// to run it later. Always use this instead of pushing to the work queue + /// directly. + pub fn enqueue_task(&mut self, task: ~Coroutine) { + self.work_queue.push(task); + self.event_loop.callback(resume_task_from_queue); + + fn resume_task_from_queue() { + let scheduler = Local::take::(); + scheduler.resume_task_from_queue(); + } + } + + // * Scheduler-context operations + + pub fn resume_task_from_queue(~self) { + assert!(!self.in_task_context()); + + rtdebug!("looking in work queue for task to schedule"); + + let mut this = self; + match this.work_queue.pop() { + Some(task) => { + rtdebug!("resuming task from work queue"); + this.resume_task_immediately(task); + } + None => { + rtdebug!("no tasks in queue"); + Local::put(this); + } + } + } + + // * Task-context operations + + /// Called by a running task to end execution, after which it will + /// be recycled by the scheduler for reuse in a new task. + pub fn terminate_current_task(~self) { + assert!(self.in_task_context()); + + rtdebug!("ending running task"); + + do self.deschedule_running_task_and_then |dead_task| { + let dead_task = Cell::new(dead_task); + do Local::borrow:: |sched| { + dead_task.take().recycle(&mut sched.stack_pool); + } + } + + abort!("control reached end of task"); + } + + pub fn schedule_new_task(~self, task: ~Coroutine) { + assert!(self.in_task_context()); + + do self.switch_running_tasks_and_then(task) |last_task| { + let last_task = Cell::new(last_task); + do Local::borrow:: |sched| { + sched.enqueue_task(last_task.take()); + } + } + } + + pub fn schedule_task(~self, task: ~Coroutine) { + assert!(self.in_task_context()); + + do self.switch_running_tasks_and_then(task) |last_task| { + let last_task = Cell::new(last_task); + do Local::borrow:: |sched| { + sched.enqueue_task(last_task.take()); + } + } + } + + // Core scheduling ops + + pub fn resume_task_immediately(~self, task: ~Coroutine) { + let mut this = self; + assert!(!this.in_task_context()); + + rtdebug!("scheduling a task"); + + // Store the task in the scheduler so it can be grabbed later + this.current_task = Some(task); + this.enqueue_cleanup_job(DoNothing); + + Local::put(this); + + // Take pointers to both the task and scheduler's saved registers. + unsafe { + let sched = Local::unsafe_borrow::(); + let (sched_context, _, next_task_context) = (*sched).get_contexts(); + let next_task_context = next_task_context.unwrap(); + // Context switch to the task, restoring it's registers + // and saving the scheduler's + Context::swap(sched_context, next_task_context); + + let sched = Local::unsafe_borrow::(); + // The running task should have passed ownership elsewhere + assert!((*sched).current_task.is_none()); + + // Running tasks may have asked us to do some cleanup + (*sched).run_cleanup_job(); + } + } + + /// Block a running task, context switch to the scheduler, then pass the + /// blocked task to a closure. + /// + /// # Safety note + /// + /// The closure here is a *stack* closure that lives in the + /// running task. It gets transmuted to the scheduler's lifetime + /// and called while the task is blocked. + pub fn deschedule_running_task_and_then(~self, f: &fn(~Coroutine)) { + let mut this = self; + assert!(this.in_task_context()); + + rtdebug!("blocking task"); + + unsafe { + let blocked_task = this.current_task.swap_unwrap(); + let f_fake_region = transmute::<&fn(~Coroutine), &fn(~Coroutine)>(f); + let f_opaque = ClosureConverter::from_fn(f_fake_region); + this.enqueue_cleanup_job(GiveTask(blocked_task, f_opaque)); + } + + Local::put(this); + + unsafe { + let sched = Local::unsafe_borrow::(); + let (sched_context, last_task_context, _) = (*sched).get_contexts(); + let last_task_context = last_task_context.unwrap(); + Context::swap(last_task_context, sched_context); + + // We could be executing in a different thread now + let sched = Local::unsafe_borrow::(); + (*sched).run_cleanup_job(); + } + } + + /// Switch directly to another task, without going through the scheduler. + /// You would want to think hard about doing this, e.g. if there are + /// pending I/O events it would be a bad idea. + pub fn switch_running_tasks_and_then(~self, + next_task: ~Coroutine, + f: &fn(~Coroutine)) { + let mut this = self; + assert!(this.in_task_context()); + + rtdebug!("switching tasks"); + + let old_running_task = this.current_task.swap_unwrap(); + let f_fake_region = unsafe { transmute::<&fn(~Coroutine), &fn(~Coroutine)>(f) }; + let f_opaque = ClosureConverter::from_fn(f_fake_region); + this.enqueue_cleanup_job(GiveTask(old_running_task, f_opaque)); + this.current_task = Some(next_task); + + Local::put(this); + + unsafe { + let sched = Local::unsafe_borrow::(); + let (_, last_task_context, next_task_context) = (*sched).get_contexts(); + let last_task_context = last_task_context.unwrap(); + let next_task_context = next_task_context.unwrap(); + Context::swap(last_task_context, next_task_context); + + // We could be executing in a different thread now + let sched = Local::unsafe_borrow::(); + (*sched).run_cleanup_job(); + } + } + + + + // * Other stuff + + pub fn enqueue_cleanup_job(&mut self, job: CleanupJob) { + assert!(self.cleanup_job.is_none()); + self.cleanup_job = Some(job); + } + + pub fn run_cleanup_job(&mut self) { + rtdebug!("running cleanup job"); + + assert!(self.cleanup_job.is_some()); + + let cleanup_job = self.cleanup_job.swap_unwrap(); + match cleanup_job { + DoNothing => { } + GiveTask(task, f) => (f.to_fn())(task) + } + } + + /// Get mutable references to all the contexts that may be involved in a + /// context switch. + /// + /// Returns (the scheduler context, the optional context of the + /// task in the cleanup list, the optional context of the task in + /// the current task slot). When context switching to a task, + /// callers should first arrange for that task to be located in the + /// Scheduler's current_task slot and set up the + /// post-context-switch cleanup job. + pub fn get_contexts<'a>(&'a mut self) -> (&'a mut Context, + Option<&'a mut Context>, + Option<&'a mut Context>) { + let last_task = match self.cleanup_job { + Some(GiveTask(~ref task, _)) => { + Some(task) + } + Some(DoNothing) => { + None + } + None => fail!("all context switches should have a cleanup job") + }; + // XXX: Pattern matching mutable pointers above doesn't work + // because borrowck thinks the three patterns are conflicting + // borrows + unsafe { + let last_task = transmute::, Option<&mut Coroutine>>(last_task); + let last_task_context = match last_task { + Some(t) => Some(&mut t.saved_context), None => None + }; + let next_task_context = match self.current_task { + Some(ref mut t) => Some(&mut t.saved_context), None => None + }; + // XXX: These transmutes can be removed after snapshot + return (transmute(&mut self.saved_context), + last_task_context, + transmute(next_task_context)); + } + } +} + +static MIN_STACK_SIZE: uint = 10000000; // XXX: Too much stack + +pub struct Coroutine { + /// The segment of stack on which the task is currently running or, + /// if the task is blocked, on which the task will resume execution + priv current_stack_segment: StackSegment, + /// These are always valid when the task is not running, unless + /// the task is dead + priv saved_context: Context, + /// The heap, GC, unwinding, local storage, logging + task: ~Task +} + +impl Coroutine { + pub fn new(stack_pool: &mut StackPool, start: ~fn()) -> Coroutine { + Coroutine::with_task(stack_pool, ~Task::new(), start) + } + + pub fn with_task(stack_pool: &mut StackPool, + task: ~Task, + start: ~fn()) -> Coroutine { + let start = Coroutine::build_start_wrapper(start); + let mut stack = stack_pool.take_segment(MIN_STACK_SIZE); + // NB: Context holds a pointer to that ~fn + let initial_context = Context::new(start, &mut stack); + return Coroutine { + current_stack_segment: stack, + saved_context: initial_context, + task: task + }; + } + + fn build_start_wrapper(start: ~fn()) -> ~fn() { + // XXX: The old code didn't have this extra allocation + let wrapper: ~fn() = || { + // This is the first code to execute after the initial + // context switch to the task. The previous context may + // have asked us to do some cleanup. + unsafe { + let sched = Local::unsafe_borrow::(); + (*sched).run_cleanup_job(); + + let sched = Local::unsafe_borrow::(); + let task = (*sched).current_task.get_mut_ref(); + // FIXME #6141: shouldn't neet to put `start()` in another closure + task.task.run(||start()); + } + + let sched = Local::take::(); + sched.terminate_current_task(); + }; + return wrapper; + } + + /// Destroy the task and try to reuse its components + pub fn recycle(~self, stack_pool: &mut StackPool) { + match self { + ~Coroutine {current_stack_segment, _} => { + stack_pool.give_segment(current_stack_segment); + } + } + } +} + +#[cfg(test)] +mod test { + use int; + use cell::Cell; + use rt::uv::uvio::UvEventLoop; + use unstable::run_in_bare_thread; + use task::spawn; + use rt::local::Local; + use rt::test::*; + use super::*; + + #[test] + fn test_simple_scheduling() { + do run_in_bare_thread { + let mut task_ran = false; + let task_ran_ptr: *mut bool = &mut task_ran; + + let mut sched = ~UvEventLoop::new_scheduler(); + let task = ~do Coroutine::new(&mut sched.stack_pool) { + unsafe { *task_ran_ptr = true; } + }; + sched.enqueue_task(task); + sched.run(); + assert!(task_ran); + } + } + + #[test] + fn test_several_tasks() { + do run_in_bare_thread { + let total = 10; + let mut task_count = 0; + let task_count_ptr: *mut int = &mut task_count; + + let mut sched = ~UvEventLoop::new_scheduler(); + for int::range(0, total) |_| { + let task = ~do Coroutine::new(&mut sched.stack_pool) { + unsafe { *task_count_ptr = *task_count_ptr + 1; } + }; + sched.enqueue_task(task); + } + sched.run(); + assert_eq!(task_count, total); + } + } + + #[test] + fn test_swap_tasks_then() { + do run_in_bare_thread { + let mut count = 0; + let count_ptr: *mut int = &mut count; + + let mut sched = ~UvEventLoop::new_scheduler(); + let task1 = ~do Coroutine::new(&mut sched.stack_pool) { + unsafe { *count_ptr = *count_ptr + 1; } + let mut sched = Local::take::(); + let task2 = ~do Coroutine::new(&mut sched.stack_pool) { + unsafe { *count_ptr = *count_ptr + 1; } + }; + // Context switch directly to the new task + do sched.switch_running_tasks_and_then(task2) |task1| { + let task1 = Cell::new(task1); + do Local::borrow:: |sched| { + sched.enqueue_task(task1.take()); + } + } + unsafe { *count_ptr = *count_ptr + 1; } + }; + sched.enqueue_task(task1); + sched.run(); + assert_eq!(count, 3); + } + } + + #[bench] #[test] #[ignore(reason = "long test")] + fn test_run_a_lot_of_tasks_queued() { + do run_in_bare_thread { + static MAX: int = 1000000; + let mut count = 0; + let count_ptr: *mut int = &mut count; + + let mut sched = ~UvEventLoop::new_scheduler(); + + let start_task = ~do Coroutine::new(&mut sched.stack_pool) { + run_task(count_ptr); + }; + sched.enqueue_task(start_task); + sched.run(); + + assert_eq!(count, MAX); + + fn run_task(count_ptr: *mut int) { + do Local::borrow:: |sched| { + let task = ~do Coroutine::new(&mut sched.stack_pool) { + unsafe { + *count_ptr = *count_ptr + 1; + if *count_ptr != MAX { + run_task(count_ptr); + } + } + }; + sched.enqueue_task(task); + } + }; + } + } + + #[test] + fn test_block_task() { + do run_in_bare_thread { + let mut sched = ~UvEventLoop::new_scheduler(); + let task = ~do Coroutine::new(&mut sched.stack_pool) { + let sched = Local::take::(); + assert!(sched.in_task_context()); + do sched.deschedule_running_task_and_then() |task| { + let task = Cell::new(task); + do Local::borrow:: |sched| { + assert!(!sched.in_task_context()); + sched.enqueue_task(task.take()); + } + } + }; + sched.enqueue_task(task); + sched.run(); + } + } + + #[test] + fn test_io_callback() { + // This is a regression test that when there are no schedulable tasks + // in the work queue, but we are performing I/O, that once we do put + // something in the work queue again the scheduler picks it up and doesn't + // exit before emptying the work queue + do run_in_newsched_task { + do spawn { + let sched = Local::take::(); + do sched.deschedule_running_task_and_then |task| { + let mut sched = Local::take::(); + let task = Cell::new(task); + do sched.event_loop.callback_ms(10) { + rtdebug!("in callback"); + let mut sched = Local::take::(); + sched.enqueue_task(task.take()); + Local::put(sched); + } + Local::put(sched); + } + } + } + } +} diff --git a/src/libstd/rt/stack.rs b/src/libstd/rt/stack.rs new file mode 100644 index 0000000000000..b0e87a62c8b72 --- /dev/null +++ b/src/libstd/rt/stack.rs @@ -0,0 +1,76 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use container::Container; +use ptr::RawPtr; +use vec; +use ops::Drop; +use libc::{c_uint, uintptr_t}; + +pub struct StackSegment { + buf: ~[u8], + valgrind_id: c_uint +} + +impl StackSegment { + pub fn new(size: uint) -> StackSegment { + unsafe { + // Crate a block of uninitialized values + let mut stack = vec::with_capacity(size); + vec::raw::set_len(&mut stack, size); + + let mut stk = StackSegment { + buf: stack, + valgrind_id: 0 + }; + + // XXX: Using the FFI to call a C macro. Slow + stk.valgrind_id = rust_valgrind_stack_register(stk.start(), stk.end()); + return stk; + } + } + + /// Point to the low end of the allocated stack + pub fn start(&self) -> *uint { + vec::raw::to_ptr(self.buf) as *uint + } + + /// Point one word beyond the high end of the allocated stack + pub fn end(&self) -> *uint { + vec::raw::to_ptr(self.buf).offset(self.buf.len()) as *uint + } +} + +impl Drop for StackSegment { + fn finalize(&self) { + unsafe { + // XXX: Using the FFI to call a C macro. Slow + rust_valgrind_stack_deregister(self.valgrind_id); + } + } +} + +pub struct StackPool(()); + +impl StackPool { + pub fn new() -> StackPool { StackPool(()) } + + fn take_segment(&self, min_size: uint) -> StackSegment { + StackSegment::new(min_size) + } + + fn give_segment(&self, _stack: StackSegment) { + } +} + +extern { + fn rust_valgrind_stack_register(start: *uintptr_t, end: *uintptr_t) -> c_uint; + fn rust_valgrind_stack_deregister(id: c_uint); +} diff --git a/src/libcore/rt/local_services.rs b/src/libstd/rt/task.rs similarity index 72% rename from src/libcore/rt/local_services.rs rename to src/libstd/rt/task.rs index bc945707e624f..620efed99ca32 100644 --- a/src/libcore/rt/local_services.rs +++ b/src/libstd/rt/task.rs @@ -13,52 +13,49 @@ //! local storage, and logging. Even a 'freestanding' Rust would likely want //! to implement this. -//! Local services may exist in at least three different contexts: -//! when running as a task, when running in the scheduler's context, -//! or when running outside of a scheduler but with local services -//! (freestanding rust with local services?). - -use prelude::*; -use libc::{c_void, uintptr_t}; +use borrow; use cast::transmute; -use super::sched::local_sched; +use libc::{c_void, uintptr_t}; +use ptr; +use prelude::*; +use rt::local::Local; +use rt::logging::StdErrLogger; use super::local_heap::LocalHeap; -pub struct LocalServices { +pub struct Task { heap: LocalHeap, gc: GarbageCollector, storage: LocalStorage, - logger: Logger, + logger: StdErrLogger, unwinder: Option, destroyed: bool } pub struct GarbageCollector; pub struct LocalStorage(*c_void, Option<~fn(*c_void)>); -pub struct Logger; pub struct Unwinder { unwinding: bool, } -impl LocalServices { - pub fn new() -> LocalServices { - LocalServices { +impl Task { + pub fn new() -> Task { + Task { heap: LocalHeap::new(), gc: GarbageCollector, storage: LocalStorage(ptr::null(), None), - logger: Logger, + logger: StdErrLogger, unwinder: Some(Unwinder { unwinding: false }), destroyed: false } } - pub fn without_unwinding() -> LocalServices { - LocalServices { + pub fn without_unwinding() -> Task { + Task { heap: LocalHeap::new(), gc: GarbageCollector, storage: LocalStorage(ptr::null(), None), - logger: Logger, + logger: StdErrLogger, unwinder: None, destroyed: false } @@ -66,9 +63,9 @@ impl LocalServices { pub fn run(&mut self, f: &fn()) { // This is just an assertion that `run` was called unsafely - // and this instance of LocalServices is still accessible. - do borrow_local_services |sched| { - assert!(ptr::ref_eq(sched, self)); + // and this instance of Task is still accessible. + do Local::borrow:: |task| { + assert!(borrow::ref_eq(task, self)); } match self.unwinder { @@ -86,14 +83,14 @@ impl LocalServices { /// Must be called manually before finalization to clean up /// thread-local resources. Some of the routines here expect - /// LocalServices to be available recursively so this must be - /// called unsafely, without removing LocalServices from + /// Task to be available recursively so this must be + /// called unsafely, without removing Task from /// thread-local-storage. fn destroy(&mut self) { // This is just an assertion that `destroy` was called unsafely - // and this instance of LocalServices is still accessible. - do borrow_local_services |sched| { - assert!(ptr::ref_eq(sched, self)); + // and this instance of Task is still accessible. + do Local::borrow:: |task| { + assert!(borrow::ref_eq(task, self)); } match self.storage { LocalStorage(ptr, Some(ref dtor)) => { @@ -105,7 +102,7 @@ impl LocalServices { } } -impl Drop for LocalServices { +impl Drop for Task { fn finalize(&self) { assert!(self.destroyed) } } @@ -154,34 +151,6 @@ impl Unwinder { } } -/// Borrow a pointer to the installed local services. -/// Fails (likely aborting the process) if local services are not available. -pub fn borrow_local_services(f: &fn(&mut LocalServices)) { - do local_sched::borrow |sched| { - match sched.current_task { - Some(~ref mut task) => { - f(&mut task.local_services) - } - None => { - fail!("no local services for schedulers yet") - } - } - } -} - -pub unsafe fn unsafe_borrow_local_services() -> &mut LocalServices { - use cast::transmute_mut_region; - - match local_sched::unsafe_borrow().current_task { - Some(~ref mut task) => { - transmute_mut_region(&mut task.local_services) - } - None => { - fail!("no local services for schedulers yet") - } - } -} - #[cfg(test)] mod test { use rt::test::*; @@ -229,4 +198,34 @@ mod test { let _ = r.next(); } } + + #[test] + fn logging() { + do run_in_newsched_task() { + info!("here i am. logging in a newsched task"); + } + } + + #[test] + fn comm_oneshot() { + use comm::*; + + do run_in_newsched_task { + let (port, chan) = oneshot(); + send_one(chan, 10); + assert!(recv_one(port) == 10); + } + } + + #[test] + fn comm_stream() { + use comm::*; + + do run_in_newsched_task() { + let (port, chan) = stream(); + chan.send(10); + assert!(port.recv() == 10); + } + } } + diff --git a/src/libstd/rt/test.rs b/src/libstd/rt/test.rs new file mode 100644 index 0000000000000..453eab09730ee --- /dev/null +++ b/src/libstd/rt/test.rs @@ -0,0 +1,192 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use uint; +use option::*; +use cell::Cell; +use result::{Result, Ok, Err}; +use super::io::net::ip::{IpAddr, Ipv4}; +use rt::task::Task; +use rt::thread::Thread; +use rt::local::Local; + +/// Creates a new scheduler in a new thread and runs a task in it, +/// then waits for the scheduler to exit. Failure of the task +/// will abort the process. +pub fn run_in_newsched_task(f: ~fn()) { + use super::sched::*; + use unstable::run_in_bare_thread; + use rt::uv::uvio::UvEventLoop; + + let f = Cell::new(f); + + do run_in_bare_thread { + let mut sched = ~UvEventLoop::new_scheduler(); + let task = ~Coroutine::with_task(&mut sched.stack_pool, + ~Task::without_unwinding(), + f.take()); + sched.enqueue_task(task); + sched.run(); + } +} + +/// Test tasks will abort on failure instead of unwinding +pub fn spawntask(f: ~fn()) { + use super::sched::*; + + let mut sched = Local::take::(); + let task = ~Coroutine::with_task(&mut sched.stack_pool, + ~Task::without_unwinding(), + f); + do sched.switch_running_tasks_and_then(task) |task| { + let task = Cell::new(task); + let sched = Local::take::(); + sched.schedule_new_task(task.take()); + } +} + +/// Create a new task and run it right now. Aborts on failure +pub fn spawntask_immediately(f: ~fn()) { + use super::sched::*; + + let mut sched = Local::take::(); + let task = ~Coroutine::with_task(&mut sched.stack_pool, + ~Task::without_unwinding(), + f); + do sched.switch_running_tasks_and_then(task) |task| { + let task = Cell::new(task); + do Local::borrow:: |sched| { + sched.enqueue_task(task.take()); + } + } +} + +/// Create a new task and run it right now. Aborts on failure +pub fn spawntask_later(f: ~fn()) { + use super::sched::*; + + let mut sched = Local::take::(); + let task = ~Coroutine::with_task(&mut sched.stack_pool, + ~Task::without_unwinding(), + f); + + sched.enqueue_task(task); + Local::put(sched); +} + +/// Spawn a task and either run it immediately or run it later +pub fn spawntask_random(f: ~fn()) { + use super::sched::*; + use rand::{Rand, rng}; + + let mut rng = rng(); + let run_now: bool = Rand::rand(&mut rng); + + let mut sched = Local::take::(); + let task = ~Coroutine::with_task(&mut sched.stack_pool, + ~Task::without_unwinding(), + f); + + if run_now { + do sched.switch_running_tasks_and_then(task) |task| { + let task = Cell::new(task); + do Local::borrow:: |sched| { + sched.enqueue_task(task.take()); + } + } + } else { + sched.enqueue_task(task); + Local::put(sched); + } +} + + +/// Spawn a task and wait for it to finish, returning whether it completed successfully or failed +pub fn spawntask_try(f: ~fn()) -> Result<(), ()> { + use cell::Cell; + use super::sched::*; + use task; + use unstable::finally::Finally; + + // Our status variables will be filled in from the scheduler context + let mut failed = false; + let failed_ptr: *mut bool = &mut failed; + + // Switch to the scheduler + let f = Cell::new(Cell::new(f)); + let sched = Local::take::(); + do sched.deschedule_running_task_and_then() |old_task| { + let old_task = Cell::new(old_task); + let f = f.take(); + let mut sched = Local::take::(); + let new_task = ~do Coroutine::new(&mut sched.stack_pool) { + do (|| { + (f.take())() + }).finally { + // Check for failure then resume the parent task + unsafe { *failed_ptr = task::failing(); } + let sched = Local::take::(); + do sched.switch_running_tasks_and_then(old_task.take()) |new_task| { + let new_task = Cell::new(new_task); + do Local::borrow:: |sched| { + sched.enqueue_task(new_task.take()); + } + } + } + }; + + sched.resume_task_immediately(new_task); + } + + if !failed { Ok(()) } else { Err(()) } +} + +// Spawn a new task in a new scheduler and return a thread handle. +pub fn spawntask_thread(f: ~fn()) -> Thread { + use rt::sched::*; + use rt::uv::uvio::UvEventLoop; + + let f = Cell::new(f); + let thread = do Thread::start { + let mut sched = ~UvEventLoop::new_scheduler(); + let task = ~Coroutine::with_task(&mut sched.stack_pool, + ~Task::without_unwinding(), + f.take()); + sched.enqueue_task(task); + sched.run(); + }; + return thread; +} + +/// Get a port number, starting at 9600, for use in tests +pub fn next_test_port() -> u16 { + unsafe { + return rust_dbg_next_port() as u16; + } + extern { + fn rust_dbg_next_port() -> ::libc::uintptr_t; + } +} + +/// Get a unique localhost:port pair starting at 9600 +pub fn next_test_ip4() -> IpAddr { + Ipv4(127, 0, 0, 1, next_test_port()) +} + +/// Get a constant that represents the number of times to repeat stress tests. Default 1. +pub fn stress_factor() -> uint { + use os::getenv; + + match getenv("RUST_RT_STRESS") { + Some(val) => uint::from_str(val).get(), + None => 1 + } +} + diff --git a/src/libcore/rt/thread.rs b/src/libstd/rt/thread.rs similarity index 95% rename from src/libcore/rt/thread.rs rename to src/libstd/rt/thread.rs index 0f1ae09bd944b..bc29019131078 100644 --- a/src/libcore/rt/thread.rs +++ b/src/libstd/rt/thread.rs @@ -19,8 +19,8 @@ pub struct Thread { raw_thread: *raw_thread } -pub impl Thread { - fn start(main: ~fn()) -> Thread { +impl Thread { + pub fn start(main: ~fn()) -> Thread { fn substart(main: &~fn()) -> *raw_thread { unsafe { rust_raw_thread_start(main) } } diff --git a/src/libcore/rt/thread_local_storage.rs b/src/libstd/rt/thread_local_storage.rs similarity index 91% rename from src/libcore/rt/thread_local_storage.rs rename to src/libstd/rt/thread_local_storage.rs index 366996fb93560..7187d2db41cac 100644 --- a/src/libcore/rt/thread_local_storage.rs +++ b/src/libstd/rt/thread_local_storage.rs @@ -21,12 +21,12 @@ pub type Key = pthread_key_t; #[cfg(unix)] pub unsafe fn create(key: &mut Key) { - assert!(0 == pthread_key_create(key, null())); + assert_eq!(0, pthread_key_create(key, null())); } #[cfg(unix)] pub unsafe fn set(key: Key, value: *mut c_void) { - assert!(0 == pthread_setspecific(key, value)); + assert_eq!(0, pthread_setspecific(key, value)); } #[cfg(unix)] @@ -46,8 +46,11 @@ type pthread_key_t = ::libc::c_uint; #[cfg(unix)] extern { + #[fast_ffi] fn pthread_key_create(key: *mut pthread_key_t, dtor: *u8) -> c_int; + #[fast_ffi] fn pthread_setspecific(key: pthread_key_t, value: *mut c_void) -> c_int; + #[fast_ffi] fn pthread_getspecific(key: pthread_key_t) -> *mut c_void; } @@ -88,10 +91,10 @@ fn tls_smoke_test() { create(&mut key); set(key, transmute(value)); let value: ~int = transmute(get(key)); - assert!(value == ~20); + assert_eq!(value, ~20); let value = ~30; set(key, transmute(value)); let value: ~int = transmute(get(key)); - assert!(value == ~30); + assert_eq!(value, ~30); } } diff --git a/src/libstd/rt/tube.rs b/src/libstd/rt/tube.rs new file mode 100644 index 0000000000000..03e11dfad1d8d --- /dev/null +++ b/src/libstd/rt/tube.rs @@ -0,0 +1,185 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! A very simple unsynchronized channel type for sending buffered data from +//! scheduler context to task context. +//! +//! XXX: This would be safer to use if split into two types like Port/Chan + +use option::*; +use clone::Clone; +use super::rc::RC; +use rt::sched::{Scheduler, Coroutine}; +use rt::{context, TaskContext, SchedulerContext}; +use rt::local::Local; +use vec::OwnedVector; +use container::Container; + +struct TubeState { + blocked_task: Option<~Coroutine>, + buf: ~[T] +} + +pub struct Tube { + p: RC> +} + +impl Tube { + pub fn new() -> Tube { + Tube { + p: RC::new(TubeState { + blocked_task: None, + buf: ~[] + }) + } + } + + pub fn send(&mut self, val: T) { + rtdebug!("tube send"); + assert!(context() == SchedulerContext); + + unsafe { + let state = self.p.unsafe_borrow_mut(); + (*state).buf.push(val); + + if (*state).blocked_task.is_some() { + // There's a waiting task. Wake it up + rtdebug!("waking blocked tube"); + let task = (*state).blocked_task.swap_unwrap(); + let sched = Local::take::(); + sched.resume_task_immediately(task); + } + } + } + + pub fn recv(&mut self) -> T { + assert!(context() == TaskContext); + + unsafe { + let state = self.p.unsafe_borrow_mut(); + if !(*state).buf.is_empty() { + return (*state).buf.shift(); + } else { + // Block and wait for the next message + rtdebug!("blocking on tube recv"); + assert!(self.p.refcount() > 1); // There better be somebody to wake us up + assert!((*state).blocked_task.is_none()); + let sched = Local::take::(); + do sched.deschedule_running_task_and_then |task| { + (*state).blocked_task = Some(task); + } + rtdebug!("waking after tube recv"); + let buf = &mut (*state).buf; + assert!(!buf.is_empty()); + return buf.shift(); + } + } + } +} + +impl Clone for Tube { + fn clone(&self) -> Tube { + Tube { p: self.p.clone() } + } +} + +#[cfg(test)] +mod test { + use int; + use cell::Cell; + use rt::test::*; + use rt::rtio::EventLoop; + use rt::sched::Scheduler; + use rt::local::Local; + use super::*; + + #[test] + fn simple_test() { + do run_in_newsched_task { + let mut tube: Tube = Tube::new(); + let tube_clone = tube.clone(); + let tube_clone_cell = Cell::new(tube_clone); + let sched = Local::take::(); + do sched.deschedule_running_task_and_then |task| { + let mut tube_clone = tube_clone_cell.take(); + tube_clone.send(1); + let sched = Local::take::(); + sched.resume_task_immediately(task); + } + + assert!(tube.recv() == 1); + } + } + + #[test] + fn blocking_test() { + do run_in_newsched_task { + let mut tube: Tube = Tube::new(); + let tube_clone = tube.clone(); + let tube_clone = Cell::new(Cell::new(Cell::new(tube_clone))); + let sched = Local::take::(); + do sched.deschedule_running_task_and_then |task| { + let tube_clone = tube_clone.take(); + do Local::borrow:: |sched| { + let tube_clone = tube_clone.take(); + do sched.event_loop.callback { + let mut tube_clone = tube_clone.take(); + // The task should be blocked on this now and + // sending will wake it up. + tube_clone.send(1); + } + } + let sched = Local::take::(); + sched.resume_task_immediately(task); + } + + assert!(tube.recv() == 1); + } + } + + #[test] + fn many_blocking_test() { + static MAX: int = 100; + + do run_in_newsched_task { + let mut tube: Tube = Tube::new(); + let tube_clone = tube.clone(); + let tube_clone = Cell::new(tube_clone); + let sched = Local::take::(); + do sched.deschedule_running_task_and_then |task| { + callback_send(tube_clone.take(), 0); + + fn callback_send(tube: Tube, i: int) { + if i == 100 { return; } + + let tube = Cell::new(Cell::new(tube)); + do Local::borrow:: |sched| { + let tube = tube.take(); + do sched.event_loop.callback { + let mut tube = tube.take(); + // The task should be blocked on this now and + // sending will wake it up. + tube.send(i); + callback_send(tube, i + 1); + } + } + } + + let sched = Local::take::(); + sched.resume_task_immediately(task); + } + + for int::range(0, MAX) |i| { + let j = tube.recv(); + assert!(j == i); + } + } + } +} diff --git a/src/libcore/rt/uv/file.rs b/src/libstd/rt/uv/file.rs similarity index 87% rename from src/libcore/rt/uv/file.rs rename to src/libstd/rt/uv/file.rs index a4aef7485d737..2d14505509759 100644 --- a/src/libcore/rt/uv/file.rs +++ b/src/libstd/rt/uv/file.rs @@ -11,15 +11,11 @@ use prelude::*; use ptr::null; use libc::c_void; -use super::{UvError, Callback, Request, NativeHandle, Loop}; -use super::super::uvll; -use super::super::uvll::*; - -pub type FsCallback = ~fn(FsRequest, Option); -impl Callback for FsCallback { } +use rt::uv::{Request, NativeHandle, Loop, FsCallback}; +use rt::uv::uvll; +use rt::uv::uvll::*; pub struct FsRequest(*uvll::uv_fs_t); - impl Request for FsRequest; impl FsRequest { diff --git a/src/libstd/rt/uv/idle.rs b/src/libstd/rt/uv/idle.rs new file mode 100644 index 0000000000000..e1def9ffd508b --- /dev/null +++ b/src/libstd/rt/uv/idle.rs @@ -0,0 +1,92 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use libc::c_int; +use option::Some; +use rt::uv::uvll; +use rt::uv::{Watcher, Loop, NativeHandle, IdleCallback, NullCallback}; +use rt::uv::status_to_maybe_uv_error; + +pub struct IdleWatcher(*uvll::uv_idle_t); +impl Watcher for IdleWatcher { } + +impl IdleWatcher { + pub fn new(loop_: &mut Loop) -> IdleWatcher { + unsafe { + let handle = uvll::idle_new(); + assert!(handle.is_not_null()); + assert!(0 == uvll::idle_init(loop_.native_handle(), handle)); + let mut watcher: IdleWatcher = NativeHandle::from_native_handle(handle); + watcher.install_watcher_data(); + return watcher + } + } + + pub fn start(&mut self, cb: IdleCallback) { + { + let data = self.get_watcher_data(); + data.idle_cb = Some(cb); + } + + unsafe { + assert!(0 == uvll::idle_start(self.native_handle(), idle_cb)) + }; + + extern fn idle_cb(handle: *uvll::uv_idle_t, status: c_int) { + let mut idle_watcher: IdleWatcher = NativeHandle::from_native_handle(handle); + let data = idle_watcher.get_watcher_data(); + let cb: &IdleCallback = data.idle_cb.get_ref(); + let status = status_to_maybe_uv_error(handle, status); + (*cb)(idle_watcher, status); + } + } + + pub fn stop(&mut self) { + // NB: Not resetting the Rust idle_cb to None here because `stop` is + // likely called from *within* the idle callback, causing a use after + // free + + unsafe { + assert!(0 == uvll::idle_stop(self.native_handle())); + } + } + + pub fn close(self, cb: NullCallback) { + { + let mut this = self; + let data = this.get_watcher_data(); + assert!(data.close_cb.is_none()); + data.close_cb = Some(cb); + } + + unsafe { uvll::close(self.native_handle(), close_cb) }; + + extern fn close_cb(handle: *uvll::uv_idle_t) { + unsafe { + let mut idle_watcher: IdleWatcher = NativeHandle::from_native_handle(handle); + { + let data = idle_watcher.get_watcher_data(); + data.close_cb.swap_unwrap()(); + } + idle_watcher.drop_watcher_data(); + uvll::idle_delete(handle); + } + } + } +} + +impl NativeHandle<*uvll::uv_idle_t> for IdleWatcher { + fn from_native_handle(handle: *uvll::uv_idle_t) -> IdleWatcher { + IdleWatcher(handle) + } + fn native_handle(&self) -> *uvll::uv_idle_t { + match self { &IdleWatcher(ptr) => ptr } + } +} diff --git a/src/libcore/rt/uv/mod.rs b/src/libstd/rt/uv/mod.rs similarity index 56% rename from src/libcore/rt/uv/mod.rs rename to src/libstd/rt/uv/mod.rs index 1d93b3273953c..10c8b84bc512a 100644 --- a/src/libcore/rt/uv/mod.rs +++ b/src/libstd/rt/uv/mod.rs @@ -10,7 +10,7 @@ /*! -Bindings to libuv. +Bindings to libuv, along with the default implementation of `core::rt::rtio`. UV types consist of the event loop (Loop), Watchers, Requests and Callbacks. @@ -38,29 +38,43 @@ use container::Container; use option::*; use str::raw::from_c_str; use to_str::ToStr; +use ptr::RawPtr; +use libc; use vec; use ptr; -use ptr::Ptr; +use cast; +use str; use libc::{c_void, c_int, size_t, malloc, free}; use cast::transmute; use ptr::null; -use super::uvll; use unstable::finally::Finally; +use rt::io::IoError; + #[cfg(test)] use unstable::run_in_bare_thread; -pub use self::file::{FsRequest, FsCallback}; +pub use self::file::FsRequest; pub use self::net::{StreamWatcher, TcpWatcher}; -pub use self::net::{ReadCallback, AllocCallback, ConnectionCallback, ConnectCallback}; +pub use self::idle::IdleWatcher; +pub use self::timer::TimerWatcher; + +/// The implementation of `rtio` for libuv +pub mod uvio; + +/// C bindings to libuv +pub mod uvll; pub mod file; pub mod net; +pub mod idle; +pub mod timer; -/// A trait for callbacks to implement. Provides a little extra type safety -/// for generic, unsafe interop functions like `set_watcher_callback`. -pub trait Callback { } - -pub trait Request { } +/// XXX: Loop(*handle) is buggy with destructors. Normal structs +/// with dtors may not be destructured, but tuple structs can, +/// but the results are not correct. +pub struct Loop { + handle: *uvll::uv_loop_t +} /// The trait implemented by uv 'watchers' (handles). Watchers are /// non-owning wrappers around the uv handles and are not completely @@ -68,12 +82,9 @@ pub trait Request { } /// handle. Watchers are generally created, then `start`ed, `stop`ed /// and `close`ed, but due to their complex life cycle may not be /// entirely memory safe if used in unanticipated patterns. -pub trait Watcher { - fn event_loop(&self) -> Loop; -} +pub trait Watcher { } -pub type NullCallback = ~fn(); -impl Callback for NullCallback { } +pub trait Request { } /// A type that wraps a native handle pub trait NativeHandle { @@ -81,25 +92,18 @@ pub trait NativeHandle { pub fn native_handle(&self) -> T; } -/// XXX: Loop(*handle) is buggy with destructors. Normal structs -/// with dtors may not be destructured, but tuple structs can, -/// but the results are not correct. -pub struct Loop { - handle: *uvll::uv_loop_t -} - -pub impl Loop { - fn new() -> Loop { +impl Loop { + pub fn new() -> Loop { let handle = unsafe { uvll::loop_new() }; assert!(handle.is_not_null()); NativeHandle::from_native_handle(handle) } - fn run(&mut self) { + pub fn run(&mut self) { unsafe { uvll::run(self.native_handle()) }; } - fn close(&mut self) { + pub fn close(&mut self) { unsafe { uvll::loop_delete(self.native_handle()) }; } } @@ -113,64 +117,74 @@ impl NativeHandle<*uvll::uv_loop_t> for Loop { } } -pub struct IdleWatcher(*uvll::uv_idle_t); +// XXX: The uv alloc callback also has a *uv_handle_t arg +pub type AllocCallback = ~fn(uint) -> Buf; +pub type ReadCallback = ~fn(StreamWatcher, int, Buf, Option); +pub type NullCallback = ~fn(); +pub type IdleCallback = ~fn(IdleWatcher, Option); +pub type ConnectionCallback = ~fn(StreamWatcher, Option); +pub type FsCallback = ~fn(FsRequest, Option); +pub type TimerCallback = ~fn(TimerWatcher, Option); -impl Watcher for IdleWatcher { - fn event_loop(&self) -> Loop { - loop_from_watcher(self) - } + +/// Callbacks used by StreamWatchers, set as custom data on the foreign handle +struct WatcherData { + read_cb: Option, + write_cb: Option, + connect_cb: Option, + close_cb: Option, + alloc_cb: Option, + idle_cb: Option, + timer_cb: Option } -pub type IdleCallback = ~fn(IdleWatcher, Option); -impl Callback for IdleCallback { } +pub trait WatcherInterop { + fn event_loop(&self) -> Loop; + fn install_watcher_data(&mut self); + fn get_watcher_data<'r>(&'r mut self) -> &'r mut WatcherData; + fn drop_watcher_data(&mut self); +} -pub impl IdleWatcher { - fn new(loop_: &mut Loop) -> IdleWatcher { +impl> WatcherInterop for W { + /// Get the uv event loop from a Watcher + pub fn event_loop(&self) -> Loop { unsafe { - let handle = uvll::idle_new(); - assert!(handle.is_not_null()); - assert!(0 == uvll::idle_init(loop_.native_handle(), handle)); - uvll::set_data_for_uv_handle(handle, null::<()>()); - NativeHandle::from_native_handle(handle) + let handle = self.native_handle(); + let loop_ = uvll::get_loop_for_uv_handle(handle); + NativeHandle::from_native_handle(loop_) } } - fn start(&mut self, cb: IdleCallback) { - - set_watcher_callback(self, cb); + pub fn install_watcher_data(&mut self) { unsafe { - assert!(0 == uvll::idle_start(self.native_handle(), idle_cb)) - }; - - extern fn idle_cb(handle: *uvll::uv_idle_t, status: c_int) { - let idle_watcher: IdleWatcher = NativeHandle::from_native_handle(handle); - let cb: &IdleCallback = borrow_callback_from_watcher(&idle_watcher); - let status = status_to_maybe_uv_error(handle, status); - (*cb)(idle_watcher, status); + let data = ~WatcherData { + read_cb: None, + write_cb: None, + connect_cb: None, + close_cb: None, + alloc_cb: None, + idle_cb: None, + timer_cb: None + }; + let data = transmute::<~WatcherData, *c_void>(data); + uvll::set_data_for_uv_handle(self.native_handle(), data); } } - fn stop(&mut self) { - unsafe { assert!(0 == uvll::idle_stop(self.native_handle())); } - } - - fn close(self) { - unsafe { uvll::close(self.native_handle(), close_cb) }; - - extern fn close_cb(handle: *uvll::uv_idle_t) { - let mut idle_watcher = NativeHandle::from_native_handle(handle); - drop_watcher_callback::(&mut idle_watcher); - unsafe { uvll::idle_delete(handle) }; + pub fn get_watcher_data<'r>(&'r mut self) -> &'r mut WatcherData { + unsafe { + let data = uvll::get_data_for_uv_handle(self.native_handle()); + let data = transmute::<&*c_void, &mut ~WatcherData>(&data); + return &mut **data; } } -} -impl NativeHandle<*uvll::uv_idle_t> for IdleWatcher { - fn from_native_handle(handle: *uvll::uv_idle_t) -> IdleWatcher { - IdleWatcher(handle) - } - fn native_handle(&self) -> *uvll::uv_idle_t { - match self { &IdleWatcher(ptr) => ptr } + pub fn drop_watcher_data(&mut self) { + unsafe { + let data = uvll::get_data_for_uv_handle(self.native_handle()); + let _data = transmute::<*c_void, ~WatcherData>(data); + uvll::set_data_for_uv_handle(self.native_handle(), null::<()>()); + } } } @@ -179,9 +193,8 @@ impl NativeHandle<*uvll::uv_idle_t> for IdleWatcher { pub struct UvError(uvll::uv_err_t); -pub impl UvError { - - fn name(&self) -> ~str { +impl UvError { + pub fn name(&self) -> ~str { unsafe { let inner = match self { &UvError(ref a) => a }; let name_str = uvll::err_name(inner); @@ -190,7 +203,7 @@ pub impl UvError { } } - fn desc(&self) -> ~str { + pub fn desc(&self) -> ~str { unsafe { let inner = match self { &UvError(ref a) => a }; let desc_str = uvll::strerror(inner); @@ -198,6 +211,10 @@ pub impl UvError { from_c_str(desc_str) } } + + pub fn is_eof(&self) -> bool { + self.code == uvll::EOF + } } impl ToStr for UvError { @@ -210,151 +227,77 @@ impl ToStr for UvError { fn error_smoke_test() { let err = uvll::uv_err_t { code: 1, sys_errno_: 1 }; let err: UvError = UvError(err); - assert!(err.to_str() == ~"EOF: end of file"); -} - - -/// Given a uv handle, convert a callback status to a UvError -// XXX: Follow the pattern below by parameterizing over T: Watcher, not T -pub fn status_to_maybe_uv_error(handle: *T, status: c_int) -> Option { - if status != -1 { - None - } else { - unsafe { - rtdebug!("handle: %x", handle as uint); - let loop_ = uvll::get_loop_for_uv_handle(handle); - rtdebug!("loop: %x", loop_ as uint); - let err = uvll::last_error(loop_); - Some(UvError(err)) - } - } -} - -/// Get the uv event loop from a Watcher -pub fn loop_from_watcher>( - watcher: &W) -> Loop { - - let handle = watcher.native_handle(); - let loop_ = unsafe { uvll::get_loop_for_uv_handle(handle) }; - NativeHandle::from_native_handle(loop_) -} - -/// Set the custom data on a handle to a callback Note: This is only -/// suitable for watchers that make just one type of callback. For -/// others use WatcherData -pub fn set_watcher_callback, CB: Callback>( - watcher: &mut W, cb: CB) { - - drop_watcher_callback::(watcher); - // XXX: Boxing the callback so it fits into a - // pointer. Unfortunate extra allocation - let boxed_cb = ~cb; - let data = unsafe { transmute::<~CB, *c_void>(boxed_cb) }; - unsafe { uvll::set_data_for_uv_handle(watcher.native_handle(), data) }; + assert_eq!(err.to_str(), ~"EOF: end of file"); } -/// Delete a callback from a handle's custom data -pub fn drop_watcher_callback, CB: Callback>( - watcher: &mut W) { - +pub fn last_uv_error>(watcher: &W) -> UvError { unsafe { - let handle = watcher.native_handle(); - let handle_data: *c_void = uvll::get_data_for_uv_handle(handle); - if handle_data.is_not_null() { - // Take ownership of the callback and drop it - let _cb = transmute::<*c_void, ~CB>(handle_data); - // Make sure the pointer is zeroed - uvll::set_data_for_uv_handle(watcher.native_handle(), null::<()>()); - } + let loop_ = watcher.event_loop(); + UvError(uvll::last_error(loop_.native_handle())) } } -/// Take a pointer to the callback installed as custom data -pub fn borrow_callback_from_watcher, - CB: Callback>(watcher: &W) -> &CB { +pub fn uv_error_to_io_error(uverr: UvError) -> IoError { - unsafe { - let handle = watcher.native_handle(); - let handle_data: *c_void = uvll::get_data_for_uv_handle(handle); - assert!(handle_data.is_not_null()); - let cb = transmute::<&*c_void, &~CB>(&handle_data); - return &**cb; - } -} - -/// Take ownership of the callback installed as custom data -pub fn take_callback_from_watcher, CB: Callback>( - watcher: &mut W) -> CB { + // XXX: Could go in str::raw + unsafe fn c_str_to_static_slice(s: *libc::c_char) -> &'static str { + let s = s as *u8; + let mut (curr, len) = (s, 0u); + while *curr != 0u8 { + len += 1u; + curr = ptr::offset(s, len); + } - unsafe { - let handle = watcher.native_handle(); - let handle_data: *c_void = uvll::get_data_for_uv_handle(handle); - assert!(handle_data.is_not_null()); - uvll::set_data_for_uv_handle(handle, null::<()>()); - let cb: ~CB = transmute::<*c_void, ~CB>(handle_data); - let cb = match cb { ~cb => cb }; - return cb; + str::raw::buf_as_slice(s, len, |d| cast::transmute(d)) } -} -/// Callbacks used by StreamWatchers, set as custom data on the foreign handle -struct WatcherData { - read_cb: Option, - write_cb: Option, - connect_cb: Option, - close_cb: Option, - alloc_cb: Option, - buf: Option -} -pub fn install_watcher_data>(watcher: &mut W) { unsafe { - let data = ~WatcherData { - read_cb: None, - write_cb: None, - connect_cb: None, - close_cb: None, - alloc_cb: None, - buf: None + // Importing error constants + use rt::uv::uvll::*; + use rt::io::*; + + // uv error descriptions are static + let c_desc = uvll::strerror(&*uverr); + let desc = c_str_to_static_slice(c_desc); + + let kind = match uverr.code { + UNKNOWN => OtherIoError, + OK => OtherIoError, + EOF => EndOfFile, + EACCES => PermissionDenied, + ECONNREFUSED => ConnectionRefused, + ECONNRESET => ConnectionReset, + EPIPE => BrokenPipe, + _ => { + rtdebug!("uverr.code %u", uverr.code as uint); + // XXX: Need to map remaining uv error types + OtherIoError + } }; - let data = transmute::<~WatcherData, *c_void>(data); - uvll::set_data_for_uv_handle(watcher.native_handle(), data); - } -} - -pub fn get_watcher_data<'r, H, W: Watcher + NativeHandle<*H>>( - watcher: &'r mut W) -> &'r mut WatcherData { - unsafe { - let data = uvll::get_data_for_uv_handle(watcher.native_handle()); - let data = transmute::<&*c_void, &mut ~WatcherData>(&data); - return &mut **data; - } -} - -pub fn drop_watcher_data>(watcher: &mut W) { - unsafe { - let data = uvll::get_data_for_uv_handle(watcher.native_handle()); - let _data = transmute::<*c_void, ~WatcherData>(data); - uvll::set_data_for_uv_handle(watcher.native_handle(), null::<()>()); + IoError { + kind: kind, + desc: desc, + detail: None + } } } -#[test] -fn test_slice_to_uv_buf() { - let slice = [0, .. 20]; - let buf = slice_to_uv_buf(slice); - - assert!(buf.len == 20); - - unsafe { - let base = transmute::<*u8, *mut u8>(buf.base); - (*base) = 1; - (*ptr::mut_offset(base, 1)) = 2; +/// Given a uv handle, convert a callback status to a UvError +// XXX: Follow the pattern below by parameterizing over T: Watcher, not T +pub fn status_to_maybe_uv_error(handle: *T, status: c_int) -> Option { + if status != -1 { + None + } else { + unsafe { + rtdebug!("handle: %x", handle as uint); + let loop_ = uvll::get_loop_for_uv_handle(handle); + rtdebug!("loop: %x", loop_ as uint); + let err = uvll::last_error(loop_); + Some(UvError(err)) + } } - - assert!(slice[0] == 1); - assert!(slice[1] == 2); } /// The uv buffer type @@ -394,6 +337,24 @@ pub fn vec_from_uv_buf(buf: Buf) -> Option<~[u8]> { } } +#[test] +fn test_slice_to_uv_buf() { + let slice = [0, .. 20]; + let buf = slice_to_uv_buf(slice); + + assert!(buf.len == 20); + + unsafe { + let base = transmute::<*u8, *mut u8>(buf.base); + (*base) = 1; + (*ptr::mut_offset(base, 1)) = 2; + } + + assert!(slice[0] == 1); + assert!(slice[1] == 2); +} + + #[test] fn loop_smoke_test() { do run_in_bare_thread { @@ -409,7 +370,7 @@ fn idle_new_then_close() { do run_in_bare_thread { let mut loop_ = Loop::new(); let idle_watcher = { IdleWatcher::new(&mut loop_) }; - idle_watcher.close(); + idle_watcher.close(||()); } } @@ -425,14 +386,14 @@ fn idle_smoke_test() { assert!(status.is_none()); if unsafe { *count_ptr == 10 } { idle_watcher.stop(); - idle_watcher.close(); + idle_watcher.close(||()); } else { unsafe { *count_ptr = *count_ptr + 1; } } } loop_.run(); loop_.close(); - assert!(count == 10); + assert_eq!(count, 10); } } @@ -449,7 +410,7 @@ fn idle_start_stop_start() { assert!(status.is_none()); let mut idle_watcher = idle_watcher; idle_watcher.stop(); - idle_watcher.close(); + idle_watcher.close(||()); } } loop_.run(); diff --git a/src/libcore/rt/uv/net.rs b/src/libstd/rt/uv/net.rs similarity index 56% rename from src/libcore/rt/uv/net.rs rename to src/libstd/rt/uv/net.rs index 3e6aa657c57dd..4571747cebf6c 100644 --- a/src/libcore/rt/uv/net.rs +++ b/src/libstd/rt/uv/net.rs @@ -10,21 +10,15 @@ use prelude::*; use libc::{size_t, ssize_t, c_int, c_void}; -use cast::transmute_mut_region; -use super::super::uvll; -use super::super::uvll::*; -use super::{Loop, Watcher, Request, UvError, Buf, Callback, NativeHandle, NullCallback, - loop_from_watcher, status_to_maybe_uv_error, - install_watcher_data, get_watcher_data, drop_watcher_data, - vec_to_uv_buf, vec_from_uv_buf}; -use super::super::io::net::ip::{IpAddr, Ipv4, Ipv6}; - -#[cfg(test)] use cell::Cell; -#[cfg(test)] use unstable::run_in_bare_thread; -#[cfg(test)] use super::super::thread::Thread; -#[cfg(test)] use super::super::test::*; - -fn ip4_as_uv_ip4(addr: IpAddr, f: &fn(*sockaddr_in)) { +use rt::uv::uvll; +use rt::uv::uvll::*; +use rt::uv::{AllocCallback, ConnectionCallback, ReadCallback}; +use rt::uv::{Loop, Watcher, Request, UvError, Buf, NativeHandle, NullCallback, + status_to_maybe_uv_error}; +use rt::io::net::ip::{IpAddr, Ipv4, Ipv6}; +use rt::uv::last_uv_error; + +fn ip4_as_uv_ip4(addr: IpAddr, f: &fn(*sockaddr_in) -> T) -> T { match addr { Ipv4(a, b, c, d, p) => { unsafe { @@ -34,7 +28,7 @@ fn ip4_as_uv_ip4(addr: IpAddr, f: &fn(*sockaddr_in)) { c as uint, d as uint), p as int); do (|| { - f(addr); + f(addr) }).finally { free_ip4_addr(addr); } @@ -47,34 +41,22 @@ fn ip4_as_uv_ip4(addr: IpAddr, f: &fn(*sockaddr_in)) { // uv_stream t is the parent class of uv_tcp_t, uv_pipe_t, uv_tty_t // and uv_file_t pub struct StreamWatcher(*uvll::uv_stream_t); +impl Watcher for StreamWatcher { } -impl Watcher for StreamWatcher { - fn event_loop(&self) -> Loop { - loop_from_watcher(self) - } -} - -pub type ReadCallback = ~fn(StreamWatcher, int, Buf, Option); -impl Callback for ReadCallback { } - -// XXX: The uv alloc callback also has a *uv_handle_t arg -pub type AllocCallback = ~fn(uint) -> Buf; -impl Callback for AllocCallback { } - -pub impl StreamWatcher { - - fn read_start(&mut self, alloc: AllocCallback, cb: ReadCallback) { - // XXX: Borrowchk problems - let data = get_watcher_data(unsafe { transmute_mut_region(self) }); - data.alloc_cb = Some(alloc); - data.read_cb = Some(cb); +impl StreamWatcher { + pub fn read_start(&mut self, alloc: AllocCallback, cb: ReadCallback) { + { + let data = self.get_watcher_data(); + data.alloc_cb = Some(alloc); + data.read_cb = Some(cb); + } let handle = self.native_handle(); unsafe { uvll::read_start(handle, alloc_cb, read_cb); } extern fn alloc_cb(stream: *uvll::uv_stream_t, suggested_size: size_t) -> Buf { let mut stream_watcher: StreamWatcher = NativeHandle::from_native_handle(stream); - let data = get_watcher_data(&mut stream_watcher); + let data = stream_watcher.get_watcher_data(); let alloc_cb = data.alloc_cb.get_ref(); return (*alloc_cb)(suggested_size as uint); } @@ -83,14 +65,14 @@ pub impl StreamWatcher { rtdebug!("buf addr: %x", buf.base as uint); rtdebug!("buf len: %d", buf.len as int); let mut stream_watcher: StreamWatcher = NativeHandle::from_native_handle(stream); - let data = get_watcher_data(&mut stream_watcher); + let data = stream_watcher.get_watcher_data(); let cb = data.read_cb.get_ref(); let status = status_to_maybe_uv_error(stream, nread as c_int); (*cb)(stream_watcher, nread as int, buf, status); } } - fn read_stop(&mut self) { + pub fn read_stop(&mut self) { // It would be nice to drop the alloc and read callbacks here, // but read_stop may be called from inside one of them and we // would end up freeing the in-use environment @@ -98,22 +80,19 @@ pub impl StreamWatcher { unsafe { uvll::read_stop(handle); } } - // XXX: Needs to take &[u8], not ~[u8] - fn write(&mut self, msg: ~[u8], cb: ConnectionCallback) { - // XXX: Borrowck - let data = get_watcher_data(unsafe { transmute_mut_region(self) }); - assert!(data.write_cb.is_none()); - data.write_cb = Some(cb); + pub fn write(&mut self, buf: Buf, cb: ConnectionCallback) { + { + let data = self.get_watcher_data(); + assert!(data.write_cb.is_none()); + data.write_cb = Some(cb); + } let req = WriteRequest::new(); - let buf = vec_to_uv_buf(msg); - assert!(data.buf.is_none()); - data.buf = Some(buf); let bufs = [buf]; unsafe { assert!(0 == uvll::write(req.native_handle(), - self.native_handle(), - bufs, write_cb)); + self.native_handle(), + bufs, write_cb)); } extern fn write_cb(req: *uvll::uv_write_t, status: c_int) { @@ -121,8 +100,7 @@ pub impl StreamWatcher { let mut stream_watcher = write_request.stream(); write_request.delete(); let cb = { - let data = get_watcher_data(&mut stream_watcher); - let _vec = vec_from_uv_buf(data.buf.swap_unwrap()); + let data = stream_watcher.get_watcher_data(); let cb = data.write_cb.swap_unwrap(); cb }; @@ -131,18 +109,18 @@ pub impl StreamWatcher { } } - fn accept(&mut self, stream: StreamWatcher) { + pub fn accept(&mut self, stream: StreamWatcher) { let self_handle = self.native_handle() as *c_void; let stream_handle = stream.native_handle() as *c_void; unsafe { - assert!(0 == uvll::accept(self_handle, stream_handle)); + assert_eq!(0, uvll::accept(self_handle, stream_handle)); } } - fn close(self, cb: NullCallback) { + pub fn close(self, cb: NullCallback) { { let mut this = self; - let data = get_watcher_data(&mut this); + let data = this.get_watcher_data(); assert!(data.close_cb.is_none()); data.close_cb = Some(cb); } @@ -152,9 +130,10 @@ pub impl StreamWatcher { extern fn close_cb(handle: *uvll::uv_stream_t) { let mut stream_watcher: StreamWatcher = NativeHandle::from_native_handle(handle); { - get_watcher_data(&mut stream_watcher).close_cb.swap_unwrap()(); + let data = stream_watcher.get_watcher_data(); + data.close_cb.swap_unwrap()(); } - drop_watcher_data(&mut stream_watcher); + stream_watcher.drop_watcher_data(); unsafe { free_handle(handle as *c_void) } } } @@ -171,47 +150,42 @@ impl NativeHandle<*uvll::uv_stream_t> for StreamWatcher { } pub struct TcpWatcher(*uvll::uv_tcp_t); +impl Watcher for TcpWatcher { } -impl Watcher for TcpWatcher { - fn event_loop(&self) -> Loop { - loop_from_watcher(self) - } -} - -pub type ConnectionCallback = ~fn(StreamWatcher, Option); -impl Callback for ConnectionCallback { } - -pub impl TcpWatcher { - fn new(loop_: &mut Loop) -> TcpWatcher { +impl TcpWatcher { + pub fn new(loop_: &mut Loop) -> TcpWatcher { unsafe { let handle = malloc_handle(UV_TCP); assert!(handle.is_not_null()); - assert!(0 == uvll::tcp_init(loop_.native_handle(), handle)); - let mut watcher = NativeHandle::from_native_handle(handle); - install_watcher_data(&mut watcher); + assert_eq!(0, uvll::tcp_init(loop_.native_handle(), handle)); + let mut watcher: TcpWatcher = NativeHandle::from_native_handle(handle); + watcher.install_watcher_data(); return watcher; } } - fn bind(&mut self, address: IpAddr) { + pub fn bind(&mut self, address: IpAddr) -> Result<(), UvError> { match address { Ipv4(*) => { do ip4_as_uv_ip4(address) |addr| { let result = unsafe { uvll::tcp_bind(self.native_handle(), addr) }; - // XXX: bind is likely to fail. need real error handling - assert!(result == 0); + if result == 0 { + Ok(()) + } else { + Err(last_uv_error(self)) + } } } _ => fail!() } } - fn connect(&mut self, address: IpAddr, cb: ConnectionCallback) { + pub fn connect(&mut self, address: IpAddr, cb: ConnectionCallback) { unsafe { - assert!(get_watcher_data(self).connect_cb.is_none()); - get_watcher_data(self).connect_cb = Some(cb); + assert!(self.get_watcher_data().connect_cb.is_none()); + self.get_watcher_data().connect_cb = Some(cb); let connect_handle = ConnectRequest::new().native_handle(); match address { @@ -232,7 +206,7 @@ pub impl TcpWatcher { let mut stream_watcher = connect_request.stream(); connect_request.delete(); let cb: ConnectionCallback = { - let data = get_watcher_data(&mut stream_watcher); + let data = stream_watcher.get_watcher_data(); data.connect_cb.swap_unwrap() }; let status = status_to_maybe_uv_error(stream_watcher.native_handle(), status); @@ -241,11 +215,12 @@ pub impl TcpWatcher { } } - fn listen(&mut self, cb: ConnectionCallback) { - // XXX: Borrowck - let data = get_watcher_data(unsafe { transmute_mut_region(self) }); - assert!(data.connect_cb.is_none()); - data.connect_cb = Some(cb); + pub fn listen(&mut self, cb: ConnectionCallback) { + { + let data = self.get_watcher_data(); + assert!(data.connect_cb.is_none()); + data.connect_cb = Some(cb); + } unsafe { static BACKLOG: c_int = 128; // XXX should be configurable @@ -257,13 +232,14 @@ pub impl TcpWatcher { extern fn connection_cb(handle: *uvll::uv_stream_t, status: c_int) { rtdebug!("connection_cb"); let mut stream_watcher: StreamWatcher = NativeHandle::from_native_handle(handle); - let cb = get_watcher_data(&mut stream_watcher).connect_cb.swap_unwrap(); - let status = status_to_maybe_uv_error(stream_watcher.native_handle(), status); - cb(stream_watcher, status); + let data = stream_watcher.get_watcher_data(); + let cb = data.connect_cb.get_ref(); + let status = status_to_maybe_uv_error(handle, status); + (*cb)(stream_watcher, status); } } - fn as_stream(&self) -> StreamWatcher { + pub fn as_stream(&self) -> StreamWatcher { NativeHandle::from_native_handle(self.native_handle() as *uvll::uv_stream_t) } } @@ -277,12 +253,8 @@ impl NativeHandle<*uvll::uv_tcp_t> for TcpWatcher { } } -pub type ConnectCallback = ~fn(ConnectRequest, Option); -impl Callback for ConnectCallback { } - // uv_connect_t is a subclass of uv_req_t struct ConnectRequest(*uvll::uv_connect_t); - impl Request for ConnectRequest { } impl ConnectRequest { @@ -322,9 +294,8 @@ pub struct WriteRequest(*uvll::uv_write_t); impl Request for WriteRequest { } -pub impl WriteRequest { - - fn new() -> WriteRequest { +impl WriteRequest { + pub fn new() -> WriteRequest { let write_handle = unsafe { malloc_req(UV_WRITE) }; @@ -333,14 +304,14 @@ pub impl WriteRequest { WriteRequest(write_handle) } - fn stream(&self) -> StreamWatcher { + pub fn stream(&self) -> StreamWatcher { unsafe { let stream_handle = uvll::get_stream_handle_from_write_req(self.native_handle()); NativeHandle::from_native_handle(stream_handle) } } - fn delete(self) { + pub fn delete(self) { unsafe { free_req(self.native_handle() as *c_void) } } } @@ -355,93 +326,109 @@ impl NativeHandle<*uvll::uv_write_t> for WriteRequest { } -#[test] -fn connect_close() { - do run_in_bare_thread() { - let mut loop_ = Loop::new(); - let mut tcp_watcher = { TcpWatcher::new(&mut loop_) }; - // Connect to a port where nobody is listening - let addr = next_test_ip4(); - do tcp_watcher.connect(addr) |stream_watcher, status| { - rtdebug!("tcp_watcher.connect!"); - assert!(status.is_some()); - assert!(status.get().name() == ~"ECONNREFUSED"); - stream_watcher.close(||()); +#[cfg(test)] +mod test { + use super::*; + use util::ignore; + use cell::Cell; + use vec; + use unstable::run_in_bare_thread; + use rt::thread::Thread; + use rt::test::*; + use rt::uv::{Loop, AllocCallback}; + use rt::uv::{vec_from_uv_buf, vec_to_uv_buf, slice_to_uv_buf}; + + #[test] + fn connect_close() { + do run_in_bare_thread() { + let mut loop_ = Loop::new(); + let mut tcp_watcher = { TcpWatcher::new(&mut loop_) }; + // Connect to a port where nobody is listening + let addr = next_test_ip4(); + do tcp_watcher.connect(addr) |stream_watcher, status| { + rtdebug!("tcp_watcher.connect!"); + assert!(status.is_some()); + assert_eq!(status.get().name(), ~"ECONNREFUSED"); + stream_watcher.close(||()); + } + loop_.run(); + loop_.close(); } - loop_.run(); - loop_.close(); } -} -#[test] -fn listen() { - do run_in_bare_thread() { - static MAX: int = 10; - let mut loop_ = Loop::new(); - let mut server_tcp_watcher = { TcpWatcher::new(&mut loop_) }; - let addr = next_test_ip4(); - server_tcp_watcher.bind(addr); - let loop_ = loop_; - rtdebug!("listening"); - do server_tcp_watcher.listen |server_stream_watcher, status| { - rtdebug!("listened!"); - assert!(status.is_none()); - let mut server_stream_watcher = server_stream_watcher; - let mut loop_ = loop_; - let client_tcp_watcher = TcpWatcher::new(&mut loop_); - let mut client_tcp_watcher = client_tcp_watcher.as_stream(); - server_stream_watcher.accept(client_tcp_watcher); - let count_cell = Cell(0); - let server_stream_watcher = server_stream_watcher; - rtdebug!("starting read"); - let alloc: AllocCallback = |size| { - vec_to_uv_buf(vec::from_elem(size, 0)) - }; - do client_tcp_watcher.read_start(alloc) - |stream_watcher, nread, buf, status| { - - rtdebug!("i'm reading!"); - let buf = vec_from_uv_buf(buf); - let mut count = count_cell.take(); - if status.is_none() { - rtdebug!("got %d bytes", nread); - let buf = buf.unwrap(); - for buf.slice(0, nread as uint).each |byte| { - assert!(*byte == count as u8); - rtdebug!("%u", *byte as uint); - count += 1; - } - } else { - assert!(count == MAX); - do stream_watcher.close { - server_stream_watcher.close(||()); + #[test] + fn listen() { + do run_in_bare_thread() { + static MAX: int = 10; + let mut loop_ = Loop::new(); + let mut server_tcp_watcher = { TcpWatcher::new(&mut loop_) }; + let addr = next_test_ip4(); + server_tcp_watcher.bind(addr); + let loop_ = loop_; + rtdebug!("listening"); + do server_tcp_watcher.listen |server_stream_watcher, status| { + rtdebug!("listened!"); + assert!(status.is_none()); + let mut server_stream_watcher = server_stream_watcher; + let mut loop_ = loop_; + let client_tcp_watcher = TcpWatcher::new(&mut loop_); + let mut client_tcp_watcher = client_tcp_watcher.as_stream(); + server_stream_watcher.accept(client_tcp_watcher); + let count_cell = Cell::new(0); + let server_stream_watcher = server_stream_watcher; + rtdebug!("starting read"); + let alloc: AllocCallback = |size| { + vec_to_uv_buf(vec::from_elem(size, 0)) + }; + do client_tcp_watcher.read_start(alloc) + |stream_watcher, nread, buf, status| { + + rtdebug!("i'm reading!"); + let buf = vec_from_uv_buf(buf); + let mut count = count_cell.take(); + if status.is_none() { + rtdebug!("got %d bytes", nread); + let buf = buf.unwrap(); + for buf.slice(0, nread as uint).each |byte| { + assert!(*byte == count as u8); + rtdebug!("%u", *byte as uint); + count += 1; + } + } else { + assert_eq!(count, MAX); + do stream_watcher.close { + server_stream_watcher.close(||()); + } } + count_cell.put_back(count); } - count_cell.put_back(count); } - } - let _client_thread = do Thread::start { - rtdebug!("starting client thread"); - let mut loop_ = Loop::new(); - let mut tcp_watcher = { TcpWatcher::new(&mut loop_) }; - do tcp_watcher.connect(addr) |stream_watcher, status| { - rtdebug!("connecting"); - assert!(status.is_none()); - let mut stream_watcher = stream_watcher; - let msg = ~[0, 1, 2, 3, 4, 5, 6 ,7 ,8, 9]; - do stream_watcher.write(msg) |stream_watcher, status| { - rtdebug!("writing"); + let _client_thread = do Thread::start { + rtdebug!("starting client thread"); + let mut loop_ = Loop::new(); + let mut tcp_watcher = { TcpWatcher::new(&mut loop_) }; + do tcp_watcher.connect(addr) |stream_watcher, status| { + rtdebug!("connecting"); assert!(status.is_none()); - stream_watcher.close(||()); + let mut stream_watcher = stream_watcher; + let msg = ~[0, 1, 2, 3, 4, 5, 6 ,7 ,8, 9]; + let buf = slice_to_uv_buf(msg); + let msg_cell = Cell::new(msg); + do stream_watcher.write(buf) |stream_watcher, status| { + rtdebug!("writing"); + assert!(status.is_none()); + let msg_cell = Cell::new(msg_cell.take()); + stream_watcher.close(||ignore(msg_cell.take())); + } } - } + loop_.run(); + loop_.close(); + }; + + let mut loop_ = loop_; loop_.run(); loop_.close(); - }; - - let mut loop_ = loop_; - loop_.run(); - loop_.close(); + } } } diff --git a/src/libstd/rt/uv/timer.rs b/src/libstd/rt/uv/timer.rs new file mode 100644 index 0000000000000..5557a58098751 --- /dev/null +++ b/src/libstd/rt/uv/timer.rs @@ -0,0 +1,183 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use libc::{c_void, c_int}; +use option::Some; +use rt::uv::uvll; +use rt::uv::{Watcher, Loop, NativeHandle, TimerCallback, NullCallback}; +use rt::uv::status_to_maybe_uv_error; + +pub struct TimerWatcher(*uvll::uv_timer_t); +impl Watcher for TimerWatcher { } + +impl TimerWatcher { + pub fn new(loop_: &mut Loop) -> TimerWatcher { + unsafe { + let handle = uvll::malloc_handle(uvll::UV_TIMER); + assert!(handle.is_not_null()); + assert!(0 == uvll::timer_init(loop_.native_handle(), handle)); + let mut watcher: TimerWatcher = NativeHandle::from_native_handle(handle); + watcher.install_watcher_data(); + return watcher; + } + } + + pub fn start(&mut self, timeout: u64, repeat: u64, cb: TimerCallback) { + { + let data = self.get_watcher_data(); + data.timer_cb = Some(cb); + } + + unsafe { + uvll::timer_start(self.native_handle(), timer_cb, timeout, repeat); + } + + extern fn timer_cb(handle: *uvll::uv_timer_t, status: c_int) { + let mut watcher: TimerWatcher = NativeHandle::from_native_handle(handle); + let data = watcher.get_watcher_data(); + let cb = data.timer_cb.get_ref(); + let status = status_to_maybe_uv_error(handle, status); + (*cb)(watcher, status); + } + } + + pub fn stop(&mut self) { + unsafe { + uvll::timer_stop(self.native_handle()); + } + } + + pub fn close(self, cb: NullCallback) { + let mut watcher = self; + { + let data = watcher.get_watcher_data(); + assert!(data.close_cb.is_none()); + data.close_cb = Some(cb); + } + + unsafe { + uvll::close(watcher.native_handle(), close_cb); + } + + extern fn close_cb(handle: *uvll::uv_timer_t) { + let mut watcher: TimerWatcher = NativeHandle::from_native_handle(handle); + { + let data = watcher.get_watcher_data(); + data.close_cb.swap_unwrap()(); + } + watcher.drop_watcher_data(); + unsafe { + uvll::free_handle(handle as *c_void); + } + } + } +} + +impl NativeHandle<*uvll::uv_timer_t> for TimerWatcher { + fn from_native_handle(handle: *uvll::uv_timer_t) -> TimerWatcher { + TimerWatcher(handle) + } + fn native_handle(&self) -> *uvll::uv_idle_t { + match self { &TimerWatcher(ptr) => ptr } + } +} + +#[cfg(test)] +mod test { + use super::*; + use rt::uv::Loop; + use unstable::run_in_bare_thread; + + #[test] + fn smoke_test() { + do run_in_bare_thread { + let mut count = 0; + let count_ptr: *mut int = &mut count; + let mut loop_ = Loop::new(); + let mut timer = TimerWatcher::new(&mut loop_); + do timer.start(10, 0) |timer, status| { + assert!(status.is_none()); + unsafe { *count_ptr += 1 }; + timer.close(||()); + } + loop_.run(); + loop_.close(); + assert!(count == 1); + } + } + + #[test] + fn start_twice() { + do run_in_bare_thread { + let mut count = 0; + let count_ptr: *mut int = &mut count; + let mut loop_ = Loop::new(); + let mut timer = TimerWatcher::new(&mut loop_); + do timer.start(10, 0) |timer, status| { + let mut timer = timer; + assert!(status.is_none()); + unsafe { *count_ptr += 1 }; + do timer.start(10, 0) |timer, status| { + assert!(status.is_none()); + unsafe { *count_ptr += 1 }; + timer.close(||()); + } + } + loop_.run(); + loop_.close(); + assert!(count == 2); + } + } + + #[test] + fn repeat_stop() { + do run_in_bare_thread { + let mut count = 0; + let count_ptr: *mut int = &mut count; + let mut loop_ = Loop::new(); + let mut timer = TimerWatcher::new(&mut loop_); + do timer.start(10, 20) |timer, status| { + assert!(status.is_none()); + unsafe { + *count_ptr += 1; + + if *count_ptr == 10 { + + // Stop the timer and do something else + let mut timer = timer; + timer.stop(); + // Freeze timer so it can be captured + let timer = timer; + + let mut loop_ = timer.event_loop(); + let mut timer2 = TimerWatcher::new(&mut loop_); + do timer2.start(10, 0) |timer2, _| { + + unsafe { *count_ptr += 1; } + + timer2.close(||()); + + // Restart the original timer + let mut timer = timer; + do timer.start(10, 0) |timer, _| { + unsafe { *count_ptr += 1; } + timer.close(||()); + } + } + } + }; + } + loop_.run(); + loop_.close(); + assert!(count == 12); + } + } + +} diff --git a/src/libstd/rt/uv/uvio.rs b/src/libstd/rt/uv/uvio.rs new file mode 100644 index 0000000000000..964ee460c1d2e --- /dev/null +++ b/src/libstd/rt/uv/uvio.rs @@ -0,0 +1,491 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use option::*; +use result::*; +use ops::Drop; +use cell::Cell; +use cast::transmute; +use clone::Clone; +use rt::io::IoError; +use rt::io::net::ip::IpAddr; +use rt::uv::*; +use rt::uv::idle::IdleWatcher; +use rt::rtio::*; +use rt::sched::Scheduler; +use rt::io::{standard_error, OtherIoError}; +use rt::tube::Tube; +use rt::local::Local; + +#[cfg(test)] use container::Container; +#[cfg(test)] use uint; +#[cfg(test)] use unstable::run_in_bare_thread; +#[cfg(test)] use rt::test::*; + +pub struct UvEventLoop { + uvio: UvIoFactory +} + +impl UvEventLoop { + pub fn new() -> UvEventLoop { + UvEventLoop { + uvio: UvIoFactory(Loop::new()) + } + } + + /// A convenience constructor + pub fn new_scheduler() -> Scheduler { + Scheduler::new(~UvEventLoop::new()) + } +} + +impl Drop for UvEventLoop { + fn finalize(&self) { + // XXX: Need mutable finalizer + let this = unsafe { + transmute::<&UvEventLoop, &mut UvEventLoop>(self) + }; + this.uvio.uv_loop().close(); + } +} + +impl EventLoop for UvEventLoop { + fn run(&mut self) { + self.uvio.uv_loop().run(); + } + + fn callback(&mut self, f: ~fn()) { + let mut idle_watcher = IdleWatcher::new(self.uvio.uv_loop()); + do idle_watcher.start |idle_watcher, status| { + assert!(status.is_none()); + let mut idle_watcher = idle_watcher; + idle_watcher.stop(); + idle_watcher.close(||()); + f(); + } + } + + fn callback_ms(&mut self, ms: u64, f: ~fn()) { + let mut timer = TimerWatcher::new(self.uvio.uv_loop()); + do timer.start(ms, 0) |timer, status| { + assert!(status.is_none()); + timer.close(||()); + f(); + } + } + + fn io<'a>(&'a mut self) -> Option<&'a mut IoFactoryObject> { + Some(&mut self.uvio) + } +} + +#[test] +fn test_callback_run_once() { + do run_in_bare_thread { + let mut event_loop = UvEventLoop::new(); + let mut count = 0; + let count_ptr: *mut int = &mut count; + do event_loop.callback { + unsafe { *count_ptr += 1 } + } + event_loop.run(); + assert_eq!(count, 1); + } +} + +pub struct UvIoFactory(Loop); + +impl UvIoFactory { + pub fn uv_loop<'a>(&'a mut self) -> &'a mut Loop { + match self { &UvIoFactory(ref mut ptr) => ptr } + } +} + +impl IoFactory for UvIoFactory { + // Connect to an address and return a new stream + // NB: This blocks the task waiting on the connection. + // It would probably be better to return a future + fn tcp_connect(&mut self, addr: IpAddr) -> Result<~RtioTcpStreamObject, IoError> { + // Create a cell in the task to hold the result. We will fill + // the cell before resuming the task. + let result_cell = Cell::new_empty(); + let result_cell_ptr: *Cell> = &result_cell; + + let scheduler = Local::take::(); + assert!(scheduler.in_task_context()); + + // Block this task and take ownership, switch to scheduler context + do scheduler.deschedule_running_task_and_then |task| { + + rtdebug!("connect: entered scheduler context"); + do Local::borrow:: |scheduler| { + assert!(!scheduler.in_task_context()); + } + let mut tcp_watcher = TcpWatcher::new(self.uv_loop()); + let task_cell = Cell::new(task); + + // Wait for a connection + do tcp_watcher.connect(addr) |stream_watcher, status| { + rtdebug!("connect: in connect callback"); + if status.is_none() { + rtdebug!("status is none"); + let res = Ok(~UvTcpStream { watcher: stream_watcher }); + + // Store the stream in the task's stack + unsafe { (*result_cell_ptr).put_back(res); } + + // Context switch + let scheduler = Local::take::(); + scheduler.resume_task_immediately(task_cell.take()); + } else { + rtdebug!("status is some"); + let task_cell = Cell::new(task_cell.take()); + do stream_watcher.close { + let res = Err(uv_error_to_io_error(status.get())); + unsafe { (*result_cell_ptr).put_back(res); } + let scheduler = Local::take::(); + scheduler.resume_task_immediately(task_cell.take()); + } + }; + } + } + + assert!(!result_cell.is_empty()); + return result_cell.take(); + } + + fn tcp_bind(&mut self, addr: IpAddr) -> Result<~RtioTcpListenerObject, IoError> { + let mut watcher = TcpWatcher::new(self.uv_loop()); + match watcher.bind(addr) { + Ok(_) => Ok(~UvTcpListener::new(watcher)), + Err(uverr) => { + let scheduler = Local::take::(); + do scheduler.deschedule_running_task_and_then |task| { + let task_cell = Cell::new(task); + do watcher.as_stream().close { + let scheduler = Local::take::(); + scheduler.resume_task_immediately(task_cell.take()); + } + } + Err(uv_error_to_io_error(uverr)) + } + } + } +} + +// FIXME #6090: Prefer newtype structs but Drop doesn't work +pub struct UvTcpListener { + watcher: TcpWatcher, + listening: bool, + incoming_streams: Tube> +} + +impl UvTcpListener { + fn new(watcher: TcpWatcher) -> UvTcpListener { + UvTcpListener { + watcher: watcher, + listening: false, + incoming_streams: Tube::new() + } + } + + fn watcher(&self) -> TcpWatcher { self.watcher } +} + +impl Drop for UvTcpListener { + fn finalize(&self) { + let watcher = self.watcher(); + let scheduler = Local::take::(); + do scheduler.deschedule_running_task_and_then |task| { + let task_cell = Cell::new(task); + do watcher.as_stream().close { + let scheduler = Local::take::(); + scheduler.resume_task_immediately(task_cell.take()); + } + } + } +} + +impl RtioTcpListener for UvTcpListener { + + fn accept(&mut self) -> Result<~RtioTcpStreamObject, IoError> { + rtdebug!("entering listen"); + + if self.listening { + return self.incoming_streams.recv(); + } + + self.listening = true; + + let server_tcp_watcher = self.watcher(); + let incoming_streams_cell = Cell::new(self.incoming_streams.clone()); + + let incoming_streams_cell = Cell::new(incoming_streams_cell.take()); + let mut server_tcp_watcher = server_tcp_watcher; + do server_tcp_watcher.listen |server_stream_watcher, status| { + let maybe_stream = if status.is_none() { + let mut server_stream_watcher = server_stream_watcher; + let mut loop_ = server_stream_watcher.event_loop(); + let client_tcp_watcher = TcpWatcher::new(&mut loop_); + let client_tcp_watcher = client_tcp_watcher.as_stream(); + // XXX: Need's to be surfaced in interface + server_stream_watcher.accept(client_tcp_watcher); + Ok(~UvTcpStream { watcher: client_tcp_watcher }) + } else { + Err(standard_error(OtherIoError)) + }; + + let mut incoming_streams = incoming_streams_cell.take(); + incoming_streams.send(maybe_stream); + incoming_streams_cell.put_back(incoming_streams); + } + + return self.incoming_streams.recv(); + } +} + +// FIXME #6090: Prefer newtype structs but Drop doesn't work +pub struct UvTcpStream { + watcher: StreamWatcher +} + +impl UvTcpStream { + fn watcher(&self) -> StreamWatcher { self.watcher } +} + +impl Drop for UvTcpStream { + fn finalize(&self) { + rtdebug!("closing tcp stream"); + let watcher = self.watcher(); + let scheduler = Local::take::(); + do scheduler.deschedule_running_task_and_then |task| { + let task_cell = Cell::new(task); + do watcher.close { + let scheduler = Local::take::(); + scheduler.resume_task_immediately(task_cell.take()); + } + } + } +} + +impl RtioTcpStream for UvTcpStream { + fn read(&mut self, buf: &mut [u8]) -> Result { + let result_cell = Cell::new_empty(); + let result_cell_ptr: *Cell> = &result_cell; + + let scheduler = Local::take::(); + assert!(scheduler.in_task_context()); + let watcher = self.watcher(); + let buf_ptr: *&mut [u8] = &buf; + do scheduler.deschedule_running_task_and_then |task| { + rtdebug!("read: entered scheduler context"); + do Local::borrow:: |scheduler| { + assert!(!scheduler.in_task_context()); + } + let mut watcher = watcher; + let task_cell = Cell::new(task); + // XXX: We shouldn't reallocate these callbacks every + // call to read + let alloc: AllocCallback = |_| unsafe { + slice_to_uv_buf(*buf_ptr) + }; + do watcher.read_start(alloc) |watcher, nread, _buf, status| { + + // Stop reading so that no read callbacks are + // triggered before the user calls `read` again. + // XXX: Is there a performance impact to calling + // stop here? + let mut watcher = watcher; + watcher.read_stop(); + + let result = if status.is_none() { + assert!(nread >= 0); + Ok(nread as uint) + } else { + Err(uv_error_to_io_error(status.unwrap())) + }; + + unsafe { (*result_cell_ptr).put_back(result); } + + let scheduler = Local::take::(); + scheduler.resume_task_immediately(task_cell.take()); + } + } + + assert!(!result_cell.is_empty()); + return result_cell.take(); + } + + fn write(&mut self, buf: &[u8]) -> Result<(), IoError> { + let result_cell = Cell::new_empty(); + let result_cell_ptr: *Cell> = &result_cell; + let scheduler = Local::take::(); + assert!(scheduler.in_task_context()); + let watcher = self.watcher(); + let buf_ptr: *&[u8] = &buf; + do scheduler.deschedule_running_task_and_then |task| { + let mut watcher = watcher; + let task_cell = Cell::new(task); + let buf = unsafe { slice_to_uv_buf(*buf_ptr) }; + do watcher.write(buf) |_watcher, status| { + let result = if status.is_none() { + Ok(()) + } else { + Err(uv_error_to_io_error(status.unwrap())) + }; + + unsafe { (*result_cell_ptr).put_back(result); } + + let scheduler = Local::take::(); + scheduler.resume_task_immediately(task_cell.take()); + } + } + + assert!(!result_cell.is_empty()); + return result_cell.take(); + } +} + +#[test] +fn test_simple_io_no_connect() { + do run_in_newsched_task { + unsafe { + let io = Local::unsafe_borrow::(); + let addr = next_test_ip4(); + let maybe_chan = (*io).tcp_connect(addr); + assert!(maybe_chan.is_err()); + } + } +} + +#[test] +fn test_simple_tcp_server_and_client() { + do run_in_newsched_task { + let addr = next_test_ip4(); + + // Start the server first so it's listening when we connect + do spawntask_immediately { + unsafe { + let io = Local::unsafe_borrow::(); + let mut listener = (*io).tcp_bind(addr).unwrap(); + let mut stream = listener.accept().unwrap(); + let mut buf = [0, .. 2048]; + let nread = stream.read(buf).unwrap(); + assert_eq!(nread, 8); + for uint::range(0, nread) |i| { + rtdebug!("%u", buf[i] as uint); + assert_eq!(buf[i], i as u8); + } + } + } + + do spawntask_immediately { + unsafe { + let io = Local::unsafe_borrow::(); + let mut stream = (*io).tcp_connect(addr).unwrap(); + stream.write([0, 1, 2, 3, 4, 5, 6, 7]); + } + } + } +} + +#[test] #[ignore(reason = "busted")] +fn test_read_and_block() { + do run_in_newsched_task { + let addr = next_test_ip4(); + + do spawntask_immediately { + let io = unsafe { Local::unsafe_borrow::() }; + let mut listener = unsafe { (*io).tcp_bind(addr).unwrap() }; + let mut stream = listener.accept().unwrap(); + let mut buf = [0, .. 2048]; + + let expected = 32; + let mut current = 0; + let mut reads = 0; + + while current < expected { + let nread = stream.read(buf).unwrap(); + for uint::range(0, nread) |i| { + let val = buf[i] as uint; + assert_eq!(val, current % 8); + current += 1; + } + reads += 1; + + let scheduler = Local::take::(); + // Yield to the other task in hopes that it + // will trigger a read callback while we are + // not ready for it + do scheduler.deschedule_running_task_and_then |task| { + let task = Cell::new(task); + do Local::borrow:: |scheduler| { + scheduler.enqueue_task(task.take()); + } + } + } + + // Make sure we had multiple reads + assert!(reads > 1); + } + + do spawntask_immediately { + unsafe { + let io = Local::unsafe_borrow::(); + let mut stream = (*io).tcp_connect(addr).unwrap(); + stream.write([0, 1, 2, 3, 4, 5, 6, 7]); + stream.write([0, 1, 2, 3, 4, 5, 6, 7]); + stream.write([0, 1, 2, 3, 4, 5, 6, 7]); + stream.write([0, 1, 2, 3, 4, 5, 6, 7]); + } + } + + } +} + +#[test] +fn test_read_read_read() { + do run_in_newsched_task { + let addr = next_test_ip4(); + static MAX: uint = 500000; + + do spawntask_immediately { + unsafe { + let io = Local::unsafe_borrow::(); + let mut listener = (*io).tcp_bind(addr).unwrap(); + let mut stream = listener.accept().unwrap(); + let buf = [1, .. 2048]; + let mut total_bytes_written = 0; + while total_bytes_written < MAX { + stream.write(buf); + total_bytes_written += buf.len(); + } + } + } + + do spawntask_immediately { + unsafe { + let io = Local::unsafe_borrow::(); + let mut stream = (*io).tcp_connect(addr).unwrap(); + let mut buf = [0, .. 2048]; + let mut total_bytes_read = 0; + while total_bytes_read < MAX { + let nread = stream.read(buf).unwrap(); + rtdebug!("read %u bytes", nread as uint); + total_bytes_read += nread; + for uint::range(0, nread) |i| { + assert_eq!(buf[i], 1); + } + } + rtdebug!("read %u bytes total", total_bytes_read as uint); + } + } + } +} diff --git a/src/libstd/rt/uv/uvll.rs b/src/libstd/rt/uv/uvll.rs new file mode 100644 index 0000000000000..6263fd47df674 --- /dev/null +++ b/src/libstd/rt/uv/uvll.rs @@ -0,0 +1,456 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/*! + * Low-level bindings to the libuv library. + * + * This module contains a set of direct, 'bare-metal' wrappers around + * the libuv C-API. + * + * We're not bothering yet to redefine uv's structs as Rust structs + * because they are quite large and change often between versions. + * The maintenance burden is just too high. Instead we use the uv's + * `uv_handle_size` and `uv_req_size` to find the correct size of the + * structs and allocate them on the heap. This can be revisited later. + * + * There are also a collection of helper functions to ease interacting + * with the low-level API. + * + * As new functionality, existant in uv.h, is added to the rust stdlib, + * the mappings should be added in this module. + */ + +#[allow(non_camel_case_types)]; // C types + +use libc::{size_t, c_int, c_uint, c_void, c_char, uintptr_t}; +use libc::{malloc, free}; +use libc; +use prelude::*; +use ptr; +use str; +use vec; + +pub static UNKNOWN: c_int = -1; +pub static OK: c_int = 0; +pub static EOF: c_int = 1; +pub static EADDRINFO: c_int = 2; +pub static EACCES: c_int = 3; +pub static ECONNREFUSED: c_int = 12; +pub static ECONNRESET: c_int = 13; +pub static EPIPE: c_int = 36; + +pub struct uv_err_t { + code: c_int, + sys_errno_: c_int +} + +pub struct uv_buf_t { + base: *u8, + len: libc::size_t, +} + +pub type uv_handle_t = c_void; +pub type uv_loop_t = c_void; +pub type uv_idle_t = c_void; +pub type uv_tcp_t = c_void; +pub type uv_connect_t = c_void; +pub type uv_write_t = c_void; +pub type uv_async_t = c_void; +pub type uv_timer_t = c_void; +pub type uv_stream_t = c_void; +pub type uv_fs_t = c_void; + +pub type uv_idle_cb = *u8; + +pub type sockaddr_in = c_void; +pub type sockaddr_in6 = c_void; + +#[deriving(Eq)] +pub enum uv_handle_type { + UV_UNKNOWN_HANDLE, + UV_ASYNC, + UV_CHECK, + UV_FS_EVENT, + UV_FS_POLL, + UV_HANDLE, + UV_IDLE, + UV_NAMED_PIPE, + UV_POLL, + UV_PREPARE, + UV_PROCESS, + UV_STREAM, + UV_TCP, + UV_TIMER, + UV_TTY, + UV_UDP, + UV_SIGNAL, + UV_FILE, + UV_HANDLE_TYPE_MAX +} + +#[deriving(Eq)] +pub enum uv_req_type { + UV_UNKNOWN_REQ, + UV_REQ, + UV_CONNECT, + UV_WRITE, + UV_SHUTDOWN, + UV_UDP_SEND, + UV_FS, + UV_WORK, + UV_GETADDRINFO, + UV_REQ_TYPE_MAX +} + +pub unsafe fn malloc_handle(handle: uv_handle_type) -> *c_void { + assert!(handle != UV_UNKNOWN_HANDLE && handle != UV_HANDLE_TYPE_MAX); + let size = rust_uv_handle_size(handle as uint); + let p = malloc(size); + assert!(p.is_not_null()); + return p; +} + +pub unsafe fn free_handle(v: *c_void) { + free(v) +} + +pub unsafe fn malloc_req(req: uv_req_type) -> *c_void { + assert!(req != UV_UNKNOWN_REQ && req != UV_REQ_TYPE_MAX); + let size = rust_uv_req_size(req as uint); + let p = malloc(size); + assert!(p.is_not_null()); + return p; +} + +pub unsafe fn free_req(v: *c_void) { + free(v) +} + +#[test] +fn handle_sanity_check() { + unsafe { + assert_eq!(UV_HANDLE_TYPE_MAX as uint, rust_uv_handle_type_max()); + } +} + +#[test] +fn request_sanity_check() { + unsafe { + assert_eq!(UV_REQ_TYPE_MAX as uint, rust_uv_req_type_max()); + } +} + +pub unsafe fn loop_new() -> *c_void { + return rust_uv_loop_new(); +} + +pub unsafe fn loop_delete(loop_handle: *c_void) { + rust_uv_loop_delete(loop_handle); +} + +pub unsafe fn run(loop_handle: *c_void) { + rust_uv_run(loop_handle); +} + +pub unsafe fn close(handle: *T, cb: *u8) { + rust_uv_close(handle as *c_void, cb); +} + +pub unsafe fn walk(loop_handle: *c_void, cb: *u8, arg: *c_void) { + rust_uv_walk(loop_handle, cb, arg); +} + +pub unsafe fn idle_new() -> *uv_idle_t { + rust_uv_idle_new() +} + +pub unsafe fn idle_delete(handle: *uv_idle_t) { + rust_uv_idle_delete(handle) +} + +pub unsafe fn idle_init(loop_handle: *uv_loop_t, handle: *uv_idle_t) -> c_int { + rust_uv_idle_init(loop_handle, handle) +} + +pub unsafe fn idle_start(handle: *uv_idle_t, cb: uv_idle_cb) -> c_int { + rust_uv_idle_start(handle, cb) +} + +pub unsafe fn idle_stop(handle: *uv_idle_t) -> c_int { + rust_uv_idle_stop(handle) +} + +pub unsafe fn tcp_init(loop_handle: *c_void, handle: *uv_tcp_t) -> c_int { + return rust_uv_tcp_init(loop_handle, handle); +} + +// FIXME ref #2064 +pub unsafe fn tcp_connect(connect_ptr: *uv_connect_t, + tcp_handle_ptr: *uv_tcp_t, + addr_ptr: *sockaddr_in, + after_connect_cb: *u8) -> c_int { + return rust_uv_tcp_connect(connect_ptr, tcp_handle_ptr, + after_connect_cb, addr_ptr); +} +// FIXME ref #2064 +pub unsafe fn tcp_connect6(connect_ptr: *uv_connect_t, + tcp_handle_ptr: *uv_tcp_t, + addr_ptr: *sockaddr_in6, + after_connect_cb: *u8) -> c_int { + return rust_uv_tcp_connect6(connect_ptr, tcp_handle_ptr, + after_connect_cb, addr_ptr); +} +// FIXME ref #2064 +pub unsafe fn tcp_bind(tcp_server_ptr: *uv_tcp_t, addr_ptr: *sockaddr_in) -> c_int { + return rust_uv_tcp_bind(tcp_server_ptr, addr_ptr); +} +// FIXME ref #2064 +pub unsafe fn tcp_bind6(tcp_server_ptr: *uv_tcp_t, addr_ptr: *sockaddr_in6) -> c_int { + return rust_uv_tcp_bind6(tcp_server_ptr, addr_ptr); +} + +pub unsafe fn tcp_getpeername(tcp_handle_ptr: *uv_tcp_t, name: *sockaddr_in) -> c_int { + return rust_uv_tcp_getpeername(tcp_handle_ptr, name); +} + +pub unsafe fn tcp_getpeername6(tcp_handle_ptr: *uv_tcp_t, name: *sockaddr_in6) ->c_int { + return rust_uv_tcp_getpeername6(tcp_handle_ptr, name); +} + +pub unsafe fn listen(stream: *T, backlog: c_int, cb: *u8) -> c_int { + return rust_uv_listen(stream as *c_void, backlog, cb); +} + +pub unsafe fn accept(server: *c_void, client: *c_void) -> c_int { + return rust_uv_accept(server as *c_void, client as *c_void); +} + +pub unsafe fn write(req: *uv_write_t, stream: *T, buf_in: &[uv_buf_t], cb: *u8) -> c_int { + let buf_ptr = vec::raw::to_ptr(buf_in); + let buf_cnt = buf_in.len() as i32; + return rust_uv_write(req as *c_void, stream as *c_void, buf_ptr, buf_cnt, cb); +} +pub unsafe fn read_start(stream: *uv_stream_t, on_alloc: *u8, on_read: *u8) -> c_int { + return rust_uv_read_start(stream as *c_void, on_alloc, on_read); +} + +pub unsafe fn read_stop(stream: *uv_stream_t) -> c_int { + return rust_uv_read_stop(stream as *c_void); +} + +pub unsafe fn last_error(loop_handle: *c_void) -> uv_err_t { + return rust_uv_last_error(loop_handle); +} + +pub unsafe fn strerror(err: *uv_err_t) -> *c_char { + return rust_uv_strerror(err); +} +pub unsafe fn err_name(err: *uv_err_t) -> *c_char { + return rust_uv_err_name(err); +} + +pub unsafe fn async_init(loop_handle: *c_void, async_handle: *uv_async_t, cb: *u8) -> c_int { + return rust_uv_async_init(loop_handle, async_handle, cb); +} + +pub unsafe fn async_send(async_handle: *uv_async_t) { + return rust_uv_async_send(async_handle); +} +pub unsafe fn buf_init(input: *u8, len: uint) -> uv_buf_t { + let out_buf = uv_buf_t { base: ptr::null(), len: 0 as size_t }; + let out_buf_ptr = ptr::to_unsafe_ptr(&out_buf); + rust_uv_buf_init(out_buf_ptr, input, len as size_t); + return out_buf; +} + +pub unsafe fn timer_init(loop_ptr: *c_void, timer_ptr: *uv_timer_t) -> c_int { + return rust_uv_timer_init(loop_ptr, timer_ptr); +} +pub unsafe fn timer_start(timer_ptr: *uv_timer_t, cb: *u8, timeout: u64, + repeat: u64) -> c_int { + return rust_uv_timer_start(timer_ptr, cb, timeout, repeat); +} +pub unsafe fn timer_stop(timer_ptr: *uv_timer_t) -> c_int { + return rust_uv_timer_stop(timer_ptr); +} + +pub unsafe fn malloc_ip4_addr(ip: &str, port: int) -> *sockaddr_in { + do str::as_c_str(ip) |ip_buf| { + rust_uv_ip4_addrp(ip_buf as *u8, port as libc::c_int) + } +} +pub unsafe fn malloc_ip6_addr(ip: &str, port: int) -> *sockaddr_in6 { + do str::as_c_str(ip) |ip_buf| { + rust_uv_ip6_addrp(ip_buf as *u8, port as libc::c_int) + } +} + +pub unsafe fn free_ip4_addr(addr: *sockaddr_in) { + rust_uv_free_ip4_addr(addr); +} + +pub unsafe fn free_ip6_addr(addr: *sockaddr_in6) { + rust_uv_free_ip6_addr(addr); +} + +// data access helpers +pub unsafe fn get_loop_for_uv_handle(handle: *T) -> *c_void { + return rust_uv_get_loop_for_uv_handle(handle as *c_void); +} +pub unsafe fn get_stream_handle_from_connect_req(connect: *uv_connect_t) -> *uv_stream_t { + return rust_uv_get_stream_handle_from_connect_req(connect); +} +pub unsafe fn get_stream_handle_from_write_req(write_req: *uv_write_t) -> *uv_stream_t { + return rust_uv_get_stream_handle_from_write_req(write_req); +} +pub unsafe fn get_data_for_uv_loop(loop_ptr: *c_void) -> *c_void { + rust_uv_get_data_for_uv_loop(loop_ptr) +} +pub unsafe fn set_data_for_uv_loop(loop_ptr: *c_void, data: *c_void) { + rust_uv_set_data_for_uv_loop(loop_ptr, data); +} +pub unsafe fn get_data_for_uv_handle(handle: *T) -> *c_void { + return rust_uv_get_data_for_uv_handle(handle as *c_void); +} +pub unsafe fn set_data_for_uv_handle(handle: *T, data: *U) { + rust_uv_set_data_for_uv_handle(handle as *c_void, data as *c_void); +} +pub unsafe fn get_data_for_req(req: *T) -> *c_void { + return rust_uv_get_data_for_req(req as *c_void); +} +pub unsafe fn set_data_for_req(req: *T, data: *U) { + rust_uv_set_data_for_req(req as *c_void, data as *c_void); +} +pub unsafe fn get_base_from_buf(buf: uv_buf_t) -> *u8 { + return rust_uv_get_base_from_buf(buf); +} +pub unsafe fn get_len_from_buf(buf: uv_buf_t) -> size_t { + return rust_uv_get_len_from_buf(buf); +} +pub unsafe fn malloc_buf_base_of(suggested_size: size_t) -> *u8 { + return rust_uv_malloc_buf_base_of(suggested_size); +} +pub unsafe fn free_base_of_buf(buf: uv_buf_t) { + rust_uv_free_base_of_buf(buf); +} + +pub unsafe fn get_last_err_info(uv_loop: *c_void) -> ~str { + let err = last_error(uv_loop); + let err_ptr = ptr::to_unsafe_ptr(&err); + let err_name = str::raw::from_c_str(err_name(err_ptr)); + let err_msg = str::raw::from_c_str(strerror(err_ptr)); + return fmt!("LIBUV ERROR: name: %s msg: %s", + err_name, err_msg); +} + +pub unsafe fn get_last_err_data(uv_loop: *c_void) -> uv_err_data { + let err = last_error(uv_loop); + let err_ptr = ptr::to_unsafe_ptr(&err); + let err_name = str::raw::from_c_str(err_name(err_ptr)); + let err_msg = str::raw::from_c_str(strerror(err_ptr)); + uv_err_data { err_name: err_name, err_msg: err_msg } +} + +pub struct uv_err_data { + err_name: ~str, + err_msg: ~str, +} + +extern { + + fn rust_uv_handle_size(type_: uintptr_t) -> size_t; + fn rust_uv_req_size(type_: uintptr_t) -> size_t; + fn rust_uv_handle_type_max() -> uintptr_t; + fn rust_uv_req_type_max() -> uintptr_t; + + // libuv public API + fn rust_uv_loop_new() -> *c_void; + fn rust_uv_loop_delete(lp: *c_void); + fn rust_uv_run(loop_handle: *c_void); + fn rust_uv_close(handle: *c_void, cb: *u8); + fn rust_uv_walk(loop_handle: *c_void, cb: *u8, arg: *c_void); + + fn rust_uv_idle_new() -> *uv_idle_t; + fn rust_uv_idle_delete(handle: *uv_idle_t); + fn rust_uv_idle_init(loop_handle: *uv_loop_t, handle: *uv_idle_t) -> c_int; + fn rust_uv_idle_start(handle: *uv_idle_t, cb: uv_idle_cb) -> c_int; + fn rust_uv_idle_stop(handle: *uv_idle_t) -> c_int; + + fn rust_uv_async_send(handle: *uv_async_t); + fn rust_uv_async_init(loop_handle: *c_void, + async_handle: *uv_async_t, + cb: *u8) -> c_int; + fn rust_uv_tcp_init(loop_handle: *c_void, handle_ptr: *uv_tcp_t) -> c_int; + // FIXME ref #2604 .. ? + fn rust_uv_buf_init(out_buf: *uv_buf_t, base: *u8, len: size_t); + fn rust_uv_last_error(loop_handle: *c_void) -> uv_err_t; + // FIXME ref #2064 + fn rust_uv_strerror(err: *uv_err_t) -> *c_char; + // FIXME ref #2064 + fn rust_uv_err_name(err: *uv_err_t) -> *c_char; + fn rust_uv_ip4_addrp(ip: *u8, port: c_int) -> *sockaddr_in; + fn rust_uv_ip6_addrp(ip: *u8, port: c_int) -> *sockaddr_in6; + fn rust_uv_free_ip4_addr(addr: *sockaddr_in); + fn rust_uv_free_ip6_addr(addr: *sockaddr_in6); + fn rust_uv_ip4_name(src: *sockaddr_in, dst: *u8, size: size_t) -> c_int; + fn rust_uv_ip6_name(src: *sockaddr_in6, dst: *u8, size: size_t) -> c_int; + fn rust_uv_ip4_port(src: *sockaddr_in) -> c_uint; + fn rust_uv_ip6_port(src: *sockaddr_in6) -> c_uint; + // FIXME ref #2064 + fn rust_uv_tcp_connect(connect_ptr: *uv_connect_t, + tcp_handle_ptr: *uv_tcp_t, + after_cb: *u8, + addr: *sockaddr_in) -> c_int; + // FIXME ref #2064 + fn rust_uv_tcp_bind(tcp_server: *uv_tcp_t, addr: *sockaddr_in) -> c_int; + // FIXME ref #2064 + fn rust_uv_tcp_connect6(connect_ptr: *uv_connect_t, + tcp_handle_ptr: *uv_tcp_t, + after_cb: *u8, + addr: *sockaddr_in6) -> c_int; + // FIXME ref #2064 + fn rust_uv_tcp_bind6(tcp_server: *uv_tcp_t, addr: *sockaddr_in6) -> c_int; + fn rust_uv_tcp_getpeername(tcp_handle_ptr: *uv_tcp_t, + name: *sockaddr_in) -> c_int; + fn rust_uv_tcp_getpeername6(tcp_handle_ptr: *uv_tcp_t, + name: *sockaddr_in6) ->c_int; + fn rust_uv_listen(stream: *c_void, backlog: c_int, cb: *u8) -> c_int; + fn rust_uv_accept(server: *c_void, client: *c_void) -> c_int; + fn rust_uv_write(req: *c_void, + stream: *c_void, + buf_in: *uv_buf_t, + buf_cnt: c_int, + cb: *u8) -> c_int; + fn rust_uv_read_start(stream: *c_void, + on_alloc: *u8, + on_read: *u8) -> c_int; + fn rust_uv_read_stop(stream: *c_void) -> c_int; + fn rust_uv_timer_init(loop_handle: *c_void, + timer_handle: *uv_timer_t) -> c_int; + fn rust_uv_timer_start(timer_handle: *uv_timer_t, + cb: *u8, + timeout: libc::uint64_t, + repeat: libc::uint64_t) -> c_int; + fn rust_uv_timer_stop(handle: *uv_timer_t) -> c_int; + + fn rust_uv_malloc_buf_base_of(sug_size: size_t) -> *u8; + fn rust_uv_free_base_of_buf(buf: uv_buf_t); + fn rust_uv_get_stream_handle_from_connect_req(connect_req: *uv_connect_t) -> *uv_stream_t; + fn rust_uv_get_stream_handle_from_write_req(write_req: *uv_write_t) -> *uv_stream_t; + fn rust_uv_get_loop_for_uv_handle(handle: *c_void) -> *c_void; + fn rust_uv_get_data_for_uv_loop(loop_ptr: *c_void) -> *c_void; + fn rust_uv_set_data_for_uv_loop(loop_ptr: *c_void, data: *c_void); + fn rust_uv_get_data_for_uv_handle(handle: *c_void) -> *c_void; + fn rust_uv_set_data_for_uv_handle(handle: *c_void, data: *c_void); + fn rust_uv_get_data_for_req(req: *c_void) -> *c_void; + fn rust_uv_set_data_for_req(req: *c_void, data: *c_void); + fn rust_uv_get_base_from_buf(buf: uv_buf_t) -> *u8; + fn rust_uv_get_len_from_buf(buf: uv_buf_t) -> size_t; +} diff --git a/src/libcore/rt/uvio.rs b/src/libstd/rt/uvio.rs similarity index 95% rename from src/libcore/rt/uvio.rs rename to src/libstd/rt/uvio.rs index 24bffd8d1cd24..070ccf7fb446d 100644 --- a/src/libcore/rt/uvio.rs +++ b/src/libstd/rt/uvio.rs @@ -16,7 +16,7 @@ use super::uv::*; use super::rtio::*; use ops::Drop; use old_iter::CopyableIter; -use cell::{Cell, empty_cell}; +use cell::Cell; use cast::transmute; use super::sched::{Scheduler, local_sched}; @@ -29,15 +29,15 @@ pub struct UvEventLoop { uvio: UvIoFactory } -pub impl UvEventLoop { - fn new() -> UvEventLoop { +impl UvEventLoop { + pub fn new() -> UvEventLoop { UvEventLoop { uvio: UvIoFactory(Loop::new()) } } /// A convenience constructor - fn new_scheduler() -> Scheduler { + pub fn new_scheduler() -> Scheduler { Scheduler::new(~UvEventLoop::new()) } } @@ -90,8 +90,8 @@ fn test_callback_run_once() { pub struct UvIoFactory(Loop); -pub impl UvIoFactory { - fn uv_loop<'a>(&'a mut self) -> &'a mut Loop { +impl UvIoFactory { + pub fn uv_loop<'a>(&'a mut self) -> &'a mut Loop { match self { &UvIoFactory(ref mut ptr) => ptr } } } @@ -103,7 +103,7 @@ impl IoFactory for UvIoFactory { fn connect(&mut self, addr: IpAddr) -> Option<~StreamObject> { // Create a cell in the task to hold the result. We will fill // the cell before resuming the task. - let result_cell = empty_cell(); + let result_cell = Cell::new_empty(); let result_cell_ptr: *Cell> = &result_cell; let scheduler = local_sched::take(); @@ -117,7 +117,7 @@ impl IoFactory for UvIoFactory { assert!(!scheduler.in_task_context()); } let mut tcp_watcher = TcpWatcher::new(self.uv_loop()); - let task_cell = Cell(task); + let task_cell = Cell::new(task); // Wait for a connection do tcp_watcher.connect(addr) |stream_watcher, status| { @@ -175,7 +175,7 @@ impl TcpListener for UvTcpListener { fn listen(&mut self) -> Option<~StreamObject> { rtdebug!("entering listen"); - let result_cell = empty_cell(); + let result_cell = Cell::new_empty(); let result_cell_ptr: *Cell> = &result_cell; let server_tcp_watcher = self.watcher(); @@ -184,7 +184,7 @@ impl TcpListener for UvTcpListener { assert!(scheduler.in_task_context()); do scheduler.deschedule_running_task_and_then |task| { - let task_cell = Cell(task); + let task_cell = Cell::new(task); let mut server_tcp_watcher = server_tcp_watcher; do server_tcp_watcher.listen |server_stream_watcher, status| { let maybe_stream = if status.is_none() { @@ -239,7 +239,7 @@ impl Drop for UvStream { impl Stream for UvStream { fn read(&mut self, buf: &mut [u8]) -> Result { - let result_cell = empty_cell(); + let result_cell = Cell::new_empty(); let result_cell_ptr: *Cell> = &result_cell; let scheduler = local_sched::take(); @@ -252,7 +252,7 @@ impl Stream for UvStream { assert!(!scheduler.in_task_context()); } let mut watcher = watcher; - let task_cell = Cell(task); + let task_cell = Cell::new(task); // XXX: We shouldn't reallocate these callbacks every // call to read let alloc: AllocCallback = |_| unsafe { @@ -286,7 +286,7 @@ impl Stream for UvStream { } fn write(&mut self, buf: &[u8]) -> Result<(), ()> { - let result_cell = empty_cell(); + let result_cell = Cell::new_empty(); let result_cell_ptr: *Cell> = &result_cell; let scheduler = local_sched::take(); assert!(scheduler.in_task_context()); @@ -294,7 +294,7 @@ impl Stream for UvStream { let buf_ptr: *&[u8] = &buf; do scheduler.deschedule_running_task_and_then |task| { let mut watcher = watcher; - let task_cell = Cell(task); + let task_cell = Cell::new(task); let buf = unsafe { &*buf_ptr }; // XXX: OMGCOPIES let buf = buf.to_vec(); @@ -390,7 +390,7 @@ fn test_read_and_block() { // will trigger a read callback while we are // not ready for it do scheduler.deschedule_running_task_and_then |task| { - let task = Cell(task); + let task = Cell::new(task); do local_sched::borrow |scheduler| { scheduler.task_queue.push_back(task.take()); } diff --git a/src/libcore/rt/uvll.rs b/src/libstd/rt/uvll.rs similarity index 100% rename from src/libcore/rt/uvll.rs rename to src/libstd/rt/uvll.rs diff --git a/src/libstd/rt/work_queue.rs b/src/libstd/rt/work_queue.rs new file mode 100644 index 0000000000000..cfffc55a58c80 --- /dev/null +++ b/src/libstd/rt/work_queue.rs @@ -0,0 +1,75 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use container::Container; +use option::*; +use vec::OwnedVector; +use unstable::sync::{Exclusive, exclusive}; +use cell::Cell; +use kinds::Owned; +use clone::Clone; + +pub struct WorkQueue { + // XXX: Another mystery bug fixed by boxing this lock + priv queue: ~Exclusive<~[T]> +} + +impl WorkQueue { + pub fn new() -> WorkQueue { + WorkQueue { + queue: ~exclusive(~[]) + } + } + + pub fn push(&mut self, value: T) { + unsafe { + let value = Cell::new(value); + self.queue.with(|q| q.unshift(value.take()) ); + } + } + + pub fn pop(&mut self) -> Option { + unsafe { + do self.queue.with |q| { + if !q.is_empty() { + Some(q.shift()) + } else { + None + } + } + } + } + + pub fn steal(&mut self) -> Option { + unsafe { + do self.queue.with |q| { + if !q.is_empty() { + Some(q.pop()) + } else { + None + } + } + } + } + + pub fn is_empty(&self) -> bool { + unsafe { + self.queue.with_imm(|q| q.is_empty() ) + } + } +} + +impl Clone for WorkQueue { + fn clone(&self) -> WorkQueue { + WorkQueue { + queue: self.queue.clone() + } + } +} diff --git a/src/libstd/run.rs b/src/libstd/run.rs new file mode 100644 index 0000000000000..3b17067feba7f --- /dev/null +++ b/src/libstd/run.rs @@ -0,0 +1,1172 @@ +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Process spawning. + +#[allow(missing_doc)]; + +use cast; +use comm::{stream, SharedChan, GenericChan, GenericPort}; +use int; +use io; +use libc::{pid_t, c_void, c_int}; +use libc; +use option::{Some, None}; +use os; +use prelude::*; +use ptr; +use str; +use task; +use vec; + +/** + * A value representing a child process. + * + * The lifetime of this value is linked to the lifetime of the actual + * process - the Process destructor calls self.finish() which waits + * for the process to terminate. + */ +pub struct Process { + + /// The unique id of the process (this should never be negative). + priv pid: pid_t, + + /** + * A handle to the process - on unix this will always be NULL, but on + * windows it will be a HANDLE to the process, which will prevent the + * pid being re-used until the handle is closed. + */ + priv handle: *(), + + /// Some(fd), or None when stdin is being redirected from a fd not created by Process::new. + priv input: Option, + + /// Some(file), or None when stdout is being redirected to a fd not created by Process::new. + priv output: Option<*libc::FILE>, + + /// Some(file), or None when stderr is being redirected to a fd not created by Process::new. + priv error: Option<*libc::FILE>, + + /// None until finish() is called. + priv exit_code: Option, +} + +/// Options that can be given when starting a Process. +pub struct ProcessOptions<'self> { + + /** + * If this is None then the new process will have the same initial + * environment as the parent process. + * + * If this is Some(vec-of-names-and-values) then the new process will + * have an environment containing the given named values only. + */ + env: Option<&'self [(~str, ~str)]>, + + /** + * If this is None then the new process will use the same initial working + * directory as the parent process. + * + * If this is Some(path) then the new process will use the given path + * for its initial working directory. + */ + dir: Option<&'self Path>, + + /** + * If this is None then a new pipe will be created for the new process's + * input and Process.input() will provide a Writer to write to this pipe. + * + * If this is Some(file-descriptor) then the new process will read its input + * from the given file descriptor, Process.input_redirected() will return + * true, and Process.input() will fail. + */ + in_fd: Option, + + /** + * If this is None then a new pipe will be created for the new progam's + * output and Process.output() will provide a Reader to read from this pipe. + * + * If this is Some(file-descriptor) then the new process will write its output + * to the given file descriptor, Process.output_redirected() will return + * true, and Process.output() will fail. + */ + out_fd: Option, + + /** + * If this is None then a new pipe will be created for the new progam's + * error stream and Process.error() will provide a Reader to read from this pipe. + * + * If this is Some(file-descriptor) then the new process will write its error output + * to the given file descriptor, Process.error_redirected() will return true, and + * and Process.error() will fail. + */ + err_fd: Option, +} + +impl <'self> ProcessOptions<'self> { + /// Return a ProcessOptions that has None in every field. + pub fn new<'a>() -> ProcessOptions<'a> { + ProcessOptions { + env: None, + dir: None, + in_fd: None, + out_fd: None, + err_fd: None, + } + } +} + +/// The output of a finished process. +pub struct ProcessOutput { + + /// The status (exit code) of the process. + status: int, + + /// The data that the process wrote to stdout. + output: ~[u8], + + /// The data that the process wrote to stderr. + error: ~[u8], +} + +impl Process { + /** + * Spawns a new Process. + * + * # Arguments + * + * * prog - The path to an executable. + * * args - Vector of arguments to pass to the child process. + * * options - Options to configure the environment of the process, + * the working directory and the standard IO streams. + */ + pub fn new(prog: &str, args: &[~str], options: ProcessOptions) + -> Process { + let (in_pipe, in_fd) = match options.in_fd { + None => { + let pipe = os::pipe(); + (Some(pipe), pipe.in) + }, + Some(fd) => (None, fd) + }; + let (out_pipe, out_fd) = match options.out_fd { + None => { + let pipe = os::pipe(); + (Some(pipe), pipe.out) + }, + Some(fd) => (None, fd) + }; + let (err_pipe, err_fd) = match options.err_fd { + None => { + let pipe = os::pipe(); + (Some(pipe), pipe.out) + }, + Some(fd) => (None, fd) + }; + + let res = spawn_process_os(prog, args, options.env, options.dir, + in_fd, out_fd, err_fd); + + unsafe { + for in_pipe.each |pipe| { libc::close(pipe.in); } + for out_pipe.each |pipe| { libc::close(pipe.out); } + for err_pipe.each |pipe| { libc::close(pipe.out); } + } + + Process { + pid: res.pid, + handle: res.handle, + input: in_pipe.map(|pipe| pipe.out), + output: out_pipe.map(|pipe| os::fdopen(pipe.in)), + error: err_pipe.map(|pipe| os::fdopen(pipe.in)), + exit_code: None, + } + } + + /// Returns the unique id of the process + pub fn get_id(&self) -> pid_t { self.pid } + + fn input_fd(&mut self) -> c_int { + match self.input { + Some(fd) => fd, + None => fail!("This Process's stdin was redirected to an \ + existing file descriptor.") + } + } + + fn output_file(&mut self) -> *libc::FILE { + match self.output { + Some(file) => file, + None => fail!("This Process's stdout was redirected to an \ + existing file descriptor.") + } + } + + fn error_file(&mut self) -> *libc::FILE { + match self.error { + Some(file) => file, + None => fail!("This Process's stderr was redirected to an \ + existing file descriptor.") + } + } + + /** + * Returns whether this process is reading its stdin from an existing file + * descriptor rather than a pipe that was created specifically for this + * process. + * + * If this method returns true then self.input() will fail. + */ + pub fn input_redirected(&self) -> bool { + self.input.is_none() + } + + /** + * Returns whether this process is writing its stdout to an existing file + * descriptor rather than a pipe that was created specifically for this + * process. + * + * If this method returns true then self.output() will fail. + */ + pub fn output_redirected(&self) -> bool { + self.output.is_none() + } + + /** + * Returns whether this process is writing its stderr to an existing file + * descriptor rather than a pipe that was created specifically for this + * process. + * + * If this method returns true then self.error() will fail. + */ + pub fn error_redirected(&self) -> bool { + self.error.is_none() + } + + /** + * Returns an io::Writer that can be used to write to this Process's stdin. + * + * Fails if this Process's stdin was redirected to an existing file descriptor. + */ + pub fn input(&mut self) -> @io::Writer { + // FIXME: the Writer can still be used after self is destroyed: #2625 + io::fd_writer(self.input_fd(), false) + } + + /** + * Returns an io::Reader that can be used to read from this Process's stdout. + * + * Fails if this Process's stdout was redirected to an existing file descriptor. + */ + pub fn output(&mut self) -> @io::Reader { + // FIXME: the Reader can still be used after self is destroyed: #2625 + io::FILE_reader(self.output_file(), false) + } + + /** + * Returns an io::Reader that can be used to read from this Process's stderr. + * + * Fails if this Process's stderr was redirected to an existing file descriptor. + */ + pub fn error(&mut self) -> @io::Reader { + // FIXME: the Reader can still be used after self is destroyed: #2625 + io::FILE_reader(self.error_file(), false) + } + + /** + * Closes the handle to the child process's stdin. + * + * If this process is reading its stdin from an existing file descriptor, then this + * method does nothing. + */ + pub fn close_input(&mut self) { + match self.input { + Some(-1) | None => (), + Some(fd) => { + unsafe { + libc::close(fd); + } + self.input = Some(-1); + } + } + } + + fn close_outputs(&mut self) { + fclose_and_null(&mut self.output); + fclose_and_null(&mut self.error); + + fn fclose_and_null(f_opt: &mut Option<*libc::FILE>) { + match *f_opt { + Some(f) if !f.is_null() => { + unsafe { + libc::fclose(f); + *f_opt = Some(0 as *libc::FILE); + } + }, + _ => () + } + } + } + + /** + * Closes the handle to stdin, waits for the child process to terminate, + * and returns the exit code. + * + * If the child has already been finished then the exit code is returned. + */ + pub fn finish(&mut self) -> int { + for self.exit_code.each |&code| { + return code; + } + self.close_input(); + let code = waitpid(self.pid); + self.exit_code = Some(code); + return code; + } + + /** + * Closes the handle to stdin, waits for the child process to terminate, and reads + * and returns all remaining output of stdout and stderr, along with the exit code. + * + * If the child has already been finished then the exit code and any remaining + * unread output of stdout and stderr will be returned. + * + * This method will fail if the child process's stdout or stderr streams were + * redirected to existing file descriptors. + */ + pub fn finish_with_output(&mut self) -> ProcessOutput { + let output_file = self.output_file(); + let error_file = self.error_file(); + + // Spawn two entire schedulers to read both stdout and sterr + // in parallel so we don't deadlock while blocking on one + // or the other. FIXME (#2625): Surely there's a much more + // clever way to do this. + let (p, ch) = stream(); + let ch = SharedChan::new(ch); + let ch_clone = ch.clone(); + do task::spawn_sched(task::SingleThreaded) { + let errput = io::FILE_reader(error_file, false); + ch.send((2, errput.read_whole_stream())); + } + do task::spawn_sched(task::SingleThreaded) { + let output = io::FILE_reader(output_file, false); + ch_clone.send((1, output.read_whole_stream())); + } + + let status = self.finish(); + + let (errs, outs) = match (p.recv(), p.recv()) { + ((1, o), (2, e)) => (e, o), + ((2, e), (1, o)) => (e, o), + ((x, _), (y, _)) => { + fail!("unexpected file numbers: %u, %u", x, y); + } + }; + + return ProcessOutput {status: status, + output: outs, + error: errs}; + } + + fn destroy_internal(&mut self, force: bool) { + // if the process has finished, and therefore had waitpid called, + // and we kill it, then on unix we might ending up killing a + // newer process that happens to have the same (re-used) id + if self.exit_code.is_none() { + killpid(self.pid, force); + self.finish(); + } + + #[cfg(windows)] + fn killpid(pid: pid_t, _force: bool) { + unsafe { + libc::funcs::extra::kernel32::TerminateProcess( + cast::transmute(pid), 1); + } + } + + #[cfg(unix)] + fn killpid(pid: pid_t, force: bool) { + let signal = if force { + libc::consts::os::posix88::SIGKILL + } else { + libc::consts::os::posix88::SIGTERM + }; + + unsafe { + libc::funcs::posix88::signal::kill(pid, signal as c_int); + } + } + } + + /** + * Terminates the process, giving it a chance to clean itself up if + * this is supported by the operating system. + * + * On Posix OSs SIGTERM will be sent to the process. On Win32 + * TerminateProcess(..) will be called. + */ + pub fn destroy(&mut self) { self.destroy_internal(false); } + + /** + * Terminates the process as soon as possible without giving it a + * chance to clean itself up. + * + * On Posix OSs SIGKILL will be sent to the process. On Win32 + * TerminateProcess(..) will be called. + */ + pub fn force_destroy(&mut self) { self.destroy_internal(true); } +} + +impl Drop for Process { + fn finalize(&self) { + // FIXME #4943: transmute is bad. + let mut_self: &mut Process = unsafe { cast::transmute(self) }; + + mut_self.finish(); + mut_self.close_outputs(); + free_handle(self.handle); + } +} + +struct SpawnProcessResult { + pid: pid_t, + handle: *(), +} + +#[cfg(windows)] +fn spawn_process_os(prog: &str, args: &[~str], + env: Option<&[(~str, ~str)]>, + dir: Option<&Path>, + in_fd: c_int, out_fd: c_int, err_fd: c_int) -> SpawnProcessResult { + + use libc::types::os::arch::extra::{DWORD, HANDLE, STARTUPINFO}; + use libc::consts::os::extra::{ + TRUE, FALSE, + STARTF_USESTDHANDLES, + INVALID_HANDLE_VALUE, + DUPLICATE_SAME_ACCESS + }; + use libc::funcs::extra::kernel32::{ + GetCurrentProcess, + DuplicateHandle, + CloseHandle, + CreateProcessA + }; + use libc::funcs::extra::msvcrt::get_osfhandle; + + use sys; + use uint; + + unsafe { + + let mut si = zeroed_startupinfo(); + si.cb = sys::size_of::() as DWORD; + si.dwFlags = STARTF_USESTDHANDLES; + + let cur_proc = GetCurrentProcess(); + + let orig_std_in = get_osfhandle(in_fd) as HANDLE; + if orig_std_in == INVALID_HANDLE_VALUE as HANDLE { + fail!("failure in get_osfhandle: %s", os::last_os_error()); + } + if DuplicateHandle(cur_proc, orig_std_in, cur_proc, &mut si.hStdInput, + 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE { + fail!("failure in DuplicateHandle: %s", os::last_os_error()); + } + + let orig_std_out = get_osfhandle(out_fd) as HANDLE; + if orig_std_out == INVALID_HANDLE_VALUE as HANDLE { + fail!("failure in get_osfhandle: %s", os::last_os_error()); + } + if DuplicateHandle(cur_proc, orig_std_out, cur_proc, &mut si.hStdOutput, + 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE { + fail!("failure in DuplicateHandle: %s", os::last_os_error()); + } + + let orig_std_err = get_osfhandle(err_fd) as HANDLE; + if orig_std_err == INVALID_HANDLE_VALUE as HANDLE { + fail!("failure in get_osfhandle: %s", os::last_os_error()); + } + if DuplicateHandle(cur_proc, orig_std_err, cur_proc, &mut si.hStdError, + 0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE { + fail!("failure in DuplicateHandle: %s", os::last_os_error()); + } + + let cmd = make_command_line(prog, args); + let mut pi = zeroed_process_information(); + let mut create_err = None; + + do with_envp(env) |envp| { + do with_dirp(dir) |dirp| { + do str::as_c_str(cmd) |cmdp| { + let created = CreateProcessA(ptr::null(), cast::transmute(cmdp), + ptr::mut_null(), ptr::mut_null(), TRUE, + 0, envp, dirp, &mut si, &mut pi); + if created == FALSE { + create_err = Some(os::last_os_error()); + } + } + } + } + + CloseHandle(si.hStdInput); + CloseHandle(si.hStdOutput); + CloseHandle(si.hStdError); + + for create_err.each |msg| { + fail!("failure in CreateProcess: %s", *msg); + } + + // We close the thread handle because we don't care about keeping the thread id valid, + // and we aren't keeping the thread handle around to be able to close it later. We don't + // close the process handle however because we want the process id to stay valid at least + // until the calling code closes the process handle. + CloseHandle(pi.hThread); + + SpawnProcessResult { + pid: pi.dwProcessId as pid_t, + handle: pi.hProcess as *() + } + } +} + +#[cfg(windows)] +fn zeroed_startupinfo() -> libc::types::os::arch::extra::STARTUPINFO { + libc::types::os::arch::extra::STARTUPINFO { + cb: 0, + lpReserved: ptr::mut_null(), + lpDesktop: ptr::mut_null(), + lpTitle: ptr::mut_null(), + dwX: 0, + dwY: 0, + dwXSize: 0, + dwYSize: 0, + dwXCountChars: 0, + dwYCountCharts: 0, + dwFillAttribute: 0, + dwFlags: 0, + wShowWindow: 0, + cbReserved2: 0, + lpReserved2: ptr::mut_null(), + hStdInput: ptr::mut_null(), + hStdOutput: ptr::mut_null(), + hStdError: ptr::mut_null() + } +} + +#[cfg(windows)] +fn zeroed_process_information() -> libc::types::os::arch::extra::PROCESS_INFORMATION { + libc::types::os::arch::extra::PROCESS_INFORMATION { + hProcess: ptr::mut_null(), + hThread: ptr::mut_null(), + dwProcessId: 0, + dwThreadId: 0 + } +} + +// FIXME: this is only pub so it can be tested (see issue #4536) +#[cfg(windows)] +pub fn make_command_line(prog: &str, args: &[~str]) -> ~str { + + use uint; + + let mut cmd = ~""; + append_arg(&mut cmd, prog); + for args.each |arg| { + cmd.push_char(' '); + append_arg(&mut cmd, *arg); + } + return cmd; + + fn append_arg(cmd: &mut ~str, arg: &str) { + let quote = arg.any(|c| c == ' ' || c == '\t'); + if quote { + cmd.push_char('"'); + } + for uint::range(0, arg.len()) |i| { + append_char_at(cmd, arg, i); + } + if quote { + cmd.push_char('"'); + } + } + + fn append_char_at(cmd: &mut ~str, arg: &str, i: uint) { + match arg[i] as char { + '"' => { + // Escape quotes. + cmd.push_str("\\\""); + } + '\\' => { + if backslash_run_ends_in_quote(arg, i) { + // Double all backslashes that are in runs before quotes. + cmd.push_str("\\\\"); + } else { + // Pass other backslashes through unescaped. + cmd.push_char('\\'); + } + } + c => { + cmd.push_char(c); + } + } + } + + fn backslash_run_ends_in_quote(s: &str, mut i: uint) -> bool { + while i < s.len() && s[i] as char == '\\' { + i += 1; + } + return i < s.len() && s[i] as char == '"'; + } +} + +#[cfg(unix)] +fn spawn_process_os(prog: &str, args: &[~str], + env: Option<&[(~str, ~str)]>, + dir: Option<&Path>, + in_fd: c_int, out_fd: c_int, err_fd: c_int) -> SpawnProcessResult { + + use libc::funcs::posix88::unistd::{fork, dup2, close, chdir, execvp}; + use libc::funcs::bsd44::getdtablesize; + + mod rustrt { + use libc::c_void; + + #[abi = "cdecl"] + pub extern { + unsafe fn rust_unset_sigprocmask(); + unsafe fn rust_set_environ(envp: *c_void); + } + } + + unsafe { + + let pid = fork(); + if pid < 0 { + fail!("failure in fork: %s", os::last_os_error()); + } else if pid > 0 { + return SpawnProcessResult {pid: pid, handle: ptr::null()}; + } + + rustrt::rust_unset_sigprocmask(); + + if dup2(in_fd, 0) == -1 { + fail!("failure in dup2(in_fd, 0): %s", os::last_os_error()); + } + if dup2(out_fd, 1) == -1 { + fail!("failure in dup2(out_fd, 1): %s", os::last_os_error()); + } + if dup2(err_fd, 2) == -1 { + fail!("failure in dup3(err_fd, 2): %s", os::last_os_error()); + } + // close all other fds + for int::range_rev(getdtablesize() as int - 1, 2) |fd| { + close(fd as c_int); + } + + do with_dirp(dir) |dirp| { + if !dirp.is_null() && chdir(dirp) == -1 { + fail!("failure in chdir: %s", os::last_os_error()); + } + } + + do with_envp(env) |envp| { + if !envp.is_null() { + rustrt::rust_set_environ(envp); + } + do with_argv(prog, args) |argv| { + execvp(*argv, argv); + // execvp only returns if an error occurred + fail!("failure in execvp: %s", os::last_os_error()); + } + } + } +} + +#[cfg(unix)] +fn with_argv(prog: &str, args: &[~str], + cb: &fn(**libc::c_char) -> T) -> T { + let mut argptrs = ~[str::as_c_str(prog, |b| b)]; + let mut tmps = ~[]; + for args.each |arg| { + let t = @copy *arg; + tmps.push(t); + argptrs.push(str::as_c_str(*t, |b| b)); + } + argptrs.push(ptr::null()); + vec::as_imm_buf(argptrs, |buf, _len| cb(buf)) +} + +#[cfg(unix)] +fn with_envp(env: Option<&[(~str, ~str)]>, cb: &fn(*c_void) -> T) -> T { + // On posixy systems we can pass a char** for envp, which is + // a null-terminated array of "k=v\n" strings. + match env { + Some(es) => { + let mut tmps = ~[]; + let mut ptrs = ~[]; + + for es.each |&(k, v)| { + let kv = @fmt!("%s=%s", k, v); + tmps.push(kv); + ptrs.push(str::as_c_str(*kv, |b| b)); + } + + ptrs.push(ptr::null()); + vec::as_imm_buf(ptrs, |p, _len| + unsafe { cb(::cast::transmute(p)) } + ) + } + _ => cb(ptr::null()) + } +} + +#[cfg(windows)] +fn with_envp(env: Option<&[(~str, ~str)]>, cb: &fn(*mut c_void) -> T) -> T { + // On win32 we pass an "environment block" which is not a char**, but + // rather a concatenation of null-terminated k=v\0 sequences, with a final + // \0 to terminate. + match env { + Some(es) => { + let mut blk = ~[]; + for es.each |&(k, v)| { + let kv = fmt!("%s=%s", k, v); + blk.push_all(str::as_bytes_slice(kv)); + blk.push(0); + } + blk.push(0); + vec::as_imm_buf(blk, |p, _len| + unsafe { cb(::cast::transmute(p)) } + ) + } + _ => cb(ptr::mut_null()) + } +} + +fn with_dirp(d: Option<&Path>, + cb: &fn(*libc::c_char) -> T) -> T { + match d { + Some(dir) => str::as_c_str(dir.to_str(), cb), + None => cb(ptr::null()) + } +} + +#[cfg(windows)] +priv fn free_handle(handle: *()) { + unsafe { + libc::funcs::extra::kernel32::CloseHandle(cast::transmute(handle)); + } +} + +#[cfg(unix)] +priv fn free_handle(_handle: *()) { + // unix has no process handle object, just a pid +} + +/** + * Spawns a process and waits for it to terminate. The process will + * inherit the current stdin/stdout/stderr file descriptors. + * + * # Arguments + * + * * prog - The path to an executable + * * args - Vector of arguments to pass to the child process + * + * # Return value + * + * The process's exit code + */ +pub fn process_status(prog: &str, args: &[~str]) -> int { + let mut prog = Process::new(prog, args, ProcessOptions { + env: None, + dir: None, + in_fd: Some(0), + out_fd: Some(1), + err_fd: Some(2) + }); + prog.finish() +} + +/** + * Spawns a process, records all its output, and waits for it to terminate. + * + * # Arguments + * + * * prog - The path to an executable + * * args - Vector of arguments to pass to the child process + * + * # Return value + * + * The process's stdout/stderr output and exit code. + */ +pub fn process_output(prog: &str, args: &[~str]) -> ProcessOutput { + let mut prog = Process::new(prog, args, ProcessOptions::new()); + prog.finish_with_output() +} + +/** + * Waits for a process to exit and returns the exit code, failing + * if there is no process with the specified id. + * + * Note that this is private to avoid race conditions on unix where if + * a user calls waitpid(some_process.get_id()) then some_process.finish() + * and some_process.destroy() and some_process.finalize() will then either + * operate on a none-existant process or, even worse, on a newer process + * with the same id. + */ +priv fn waitpid(pid: pid_t) -> int { + return waitpid_os(pid); + + #[cfg(windows)] + fn waitpid_os(pid: pid_t) -> int { + + use libc::types::os::arch::extra::DWORD; + use libc::consts::os::extra::{ + SYNCHRONIZE, + PROCESS_QUERY_INFORMATION, + FALSE, + STILL_ACTIVE, + INFINITE, + WAIT_FAILED + }; + use libc::funcs::extra::kernel32::{ + OpenProcess, + GetExitCodeProcess, + CloseHandle, + WaitForSingleObject + }; + + unsafe { + + let proc = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION, FALSE, pid as DWORD); + if proc.is_null() { + fail!("failure in OpenProcess: %s", os::last_os_error()); + } + + loop { + let mut status = 0; + if GetExitCodeProcess(proc, &mut status) == FALSE { + CloseHandle(proc); + fail!("failure in GetExitCodeProcess: %s", os::last_os_error()); + } + if status != STILL_ACTIVE { + CloseHandle(proc); + return status as int; + } + if WaitForSingleObject(proc, INFINITE) == WAIT_FAILED { + CloseHandle(proc); + fail!("failure in WaitForSingleObject: %s", os::last_os_error()); + } + } + } + } + + #[cfg(unix)] + fn waitpid_os(pid: pid_t) -> int { + + use libc::funcs::posix01::wait::*; + + #[cfg(target_os = "linux")] + #[cfg(target_os = "android")] + fn WIFEXITED(status: i32) -> bool { + (status & 0xffi32) == 0i32 + } + + #[cfg(target_os = "macos")] + #[cfg(target_os = "freebsd")] + fn WIFEXITED(status: i32) -> bool { + (status & 0x7fi32) == 0i32 + } + + #[cfg(target_os = "linux")] + #[cfg(target_os = "android")] + fn WEXITSTATUS(status: i32) -> i32 { + (status >> 8i32) & 0xffi32 + } + + #[cfg(target_os = "macos")] + #[cfg(target_os = "freebsd")] + fn WEXITSTATUS(status: i32) -> i32 { + status >> 8i32 + } + + let mut status = 0 as c_int; + if unsafe { waitpid(pid, &mut status, 0) } == -1 { + fail!("failure in waitpid: %s", os::last_os_error()); + } + + return if WIFEXITED(status) { + WEXITSTATUS(status) as int + } else { + 1 + }; + } +} + +#[cfg(test)] +mod tests { + use io; + use libc::{c_int}; + use option::{Option, None, Some}; + use os; + use path::Path; + use run; + use str; + + #[test] + #[cfg(windows)] + fn test_make_command_line() { + assert_eq!( + run::make_command_line("prog", [~"aaa", ~"bbb", ~"ccc"]), + ~"prog aaa bbb ccc" + ); + assert_eq!( + run::make_command_line("C:\\Program Files\\blah\\blah.exe", [~"aaa"]), + ~"\"C:\\Program Files\\blah\\blah.exe\" aaa" + ); + assert_eq!( + run::make_command_line("C:\\Program Files\\test", [~"aa\"bb"]), + ~"\"C:\\Program Files\\test\" aa\\\"bb" + ); + assert_eq!( + run::make_command_line("echo", [~"a b c"]), + ~"echo \"a b c\"" + ); + } + + #[test] + fn test_process_status() { + assert_eq!(run::process_status("false", []), 1); + assert_eq!(run::process_status("true", []), 0); + } + + #[test] + fn test_process_output_output() { + + let run::ProcessOutput {status, output, error} + = run::process_output("echo", [~"hello"]); + let output_str = str::from_bytes(output); + + assert_eq!(status, 0); + assert_eq!(output_str.trim().to_owned(), ~"hello"); + assert_eq!(error, ~[]); + } + + #[test] + fn test_process_output_error() { + + let run::ProcessOutput {status, output, error} + = run::process_output("mkdir", [~"."]); + + assert_eq!(status, 1); + assert_eq!(output, ~[]); + assert!(!error.is_empty()); + } + + #[test] + fn test_pipes() { + + let pipe_in = os::pipe(); + let pipe_out = os::pipe(); + let pipe_err = os::pipe(); + + let mut proc = run::Process::new("cat", [], run::ProcessOptions { + dir: None, + env: None, + in_fd: Some(pipe_in.in), + out_fd: Some(pipe_out.out), + err_fd: Some(pipe_err.out) + }); + + assert!(proc.input_redirected()); + assert!(proc.output_redirected()); + assert!(proc.error_redirected()); + + os::close(pipe_in.in); + os::close(pipe_out.out); + os::close(pipe_err.out); + + let expected = ~"test"; + writeclose(pipe_in.out, expected); + let actual = readclose(pipe_out.in); + readclose(pipe_err.in); + proc.finish(); + + assert_eq!(expected, actual); + } + + fn writeclose(fd: c_int, s: &str) { + let writer = io::fd_writer(fd, false); + writer.write_str(s); + os::close(fd); + } + + fn readclose(fd: c_int) -> ~str { + unsafe { + let file = os::fdopen(fd); + let reader = io::FILE_reader(file, false); + let buf = reader.read_whole_stream(); + os::fclose(file); + str::from_bytes(buf) + } + } + + #[test] + fn test_finish_once() { + let mut prog = run::Process::new("false", [], run::ProcessOptions::new()); + assert_eq!(prog.finish(), 1); + } + + #[test] + fn test_finish_twice() { + let mut prog = run::Process::new("false", [], run::ProcessOptions::new()); + assert_eq!(prog.finish(), 1); + assert_eq!(prog.finish(), 1); + } + + #[test] + fn test_finish_with_output_once() { + + let mut prog = run::Process::new("echo", [~"hello"], run::ProcessOptions::new()); + let run::ProcessOutput {status, output, error} + = prog.finish_with_output(); + let output_str = str::from_bytes(output); + + assert_eq!(status, 0); + assert_eq!(output_str.trim().to_owned(), ~"hello"); + assert_eq!(error, ~[]); + } + + #[test] + fn test_finish_with_output_twice() { + + let mut prog = run::Process::new("echo", [~"hello"], run::ProcessOptions::new()); + let run::ProcessOutput {status, output, error} + = prog.finish_with_output(); + + let output_str = str::from_bytes(output); + + assert_eq!(status, 0); + assert_eq!(output_str.trim().to_owned(), ~"hello"); + assert_eq!(error, ~[]); + + let run::ProcessOutput {status, output, error} + = prog.finish_with_output(); + + assert_eq!(status, 0); + assert_eq!(output, ~[]); + assert_eq!(error, ~[]); + } + + #[test] + #[should_fail] + #[cfg(not(windows))] + fn test_finish_with_output_redirected() { + let mut prog = run::Process::new("echo", [~"hello"], run::ProcessOptions { + env: None, + dir: None, + in_fd: Some(0), + out_fd: Some(1), + err_fd: Some(2) + }); + // this should fail because it is not valid to read the output when it was redirected + prog.finish_with_output(); + } + + #[cfg(unix)] + fn run_pwd(dir: Option<&Path>) -> run::Process { + run::Process::new("pwd", [], run::ProcessOptions { + dir: dir, + .. run::ProcessOptions::new() + }) + } + + #[cfg(windows)] + fn run_pwd(dir: Option<&Path>) -> run::Process { + run::Process::new("cmd", [~"/c", ~"cd"], run::ProcessOptions { + dir: dir, + .. run::ProcessOptions::new() + }) + } + + #[test] + fn test_keep_current_working_dir() { + let mut prog = run_pwd(None); + + let output = str::from_bytes(prog.finish_with_output().output); + let parent_dir = os::getcwd().normalize(); + let child_dir = Path(output.trim()).normalize(); + + let parent_stat = parent_dir.stat().unwrap(); + let child_stat = child_dir.stat().unwrap(); + + assert_eq!(parent_stat.st_dev, child_stat.st_dev); + assert_eq!(parent_stat.st_ino, child_stat.st_ino); + } + + #[test] + fn test_change_working_directory() { + // test changing to the parent of os::getcwd() because we know + // the path exists (and os::getcwd() is not expected to be root) + let parent_dir = os::getcwd().dir_path().normalize(); + let mut prog = run_pwd(Some(&parent_dir)); + + let output = str::from_bytes(prog.finish_with_output().output); + let child_dir = Path(output.trim()).normalize(); + + let parent_stat = parent_dir.stat().unwrap(); + let child_stat = child_dir.stat().unwrap(); + + assert_eq!(parent_stat.st_dev, child_stat.st_dev); + assert_eq!(parent_stat.st_ino, child_stat.st_ino); + } + + #[cfg(unix)] + fn run_env(env: Option<&[(~str, ~str)]>) -> run::Process { + run::Process::new("env", [], run::ProcessOptions { + env: env, + .. run::ProcessOptions::new() + }) + } + + #[cfg(windows)] + fn run_env(env: Option<&[(~str, ~str)]>) -> run::Process { + run::Process::new("cmd", [~"/c", ~"set"], run::ProcessOptions { + env: env, + .. run::ProcessOptions::new() + }) + } + + #[test] + fn test_inherit_env() { + + let mut prog = run_env(None); + let output = str::from_bytes(prog.finish_with_output().output); + + for os::env().each |&(k, v)| { + // don't check windows magical empty-named variables + assert!(k.is_empty() || output.contains(fmt!("%s=%s", k, v))); + } + } + + #[test] + fn test_add_to_env() { + + let mut new_env = os::env(); + new_env.push((~"RUN_TEST_NEW_ENV", ~"123")); + + let mut prog = run_env(Some(new_env.slice(0, new_env.len()))); + let output = str::from_bytes(prog.finish_with_output().output); + + assert!(output.contains("RUN_TEST_NEW_ENV=123")); + } +} diff --git a/src/libstd/smallintmap.rs b/src/libstd/smallintmap.rs deleted file mode 100644 index afc1d0fe65fcb..0000000000000 --- a/src/libstd/smallintmap.rs +++ /dev/null @@ -1,323 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/*! - * A simple map based on a vector for small integer keys. Space requirements - * are O(highest integer key). - */ - -use core::container::{Container, Mutable, Map, Set}; -use core::old_iter::{BaseIter}; -use core::option::{Some, None}; -use core::util::replace; - -pub struct SmallIntMap { - priv v: ~[Option], -} - -impl Container for SmallIntMap { - /// Return the number of elements in the map - fn len(&const self) -> uint { - let mut sz = 0; - for uint::range(0, vec::uniq_len(&const self.v)) |i| { - match self.v[i] { - Some(_) => sz += 1, - None => {} - } - } - sz - } - - /// Return true if the map contains no elements - fn is_empty(&const self) -> bool { self.len() == 0 } -} - -impl Mutable for SmallIntMap { - /// Clear the map, removing all key-value pairs. - fn clear(&mut self) { self.v.clear() } -} - -impl Map for SmallIntMap { - /// Return true if the map contains a value for the specified key - fn contains_key(&self, key: &uint) -> bool { - self.find(key).is_some() - } - - /// Visit all key-value pairs in order - #[cfg(stage0)] - fn each<'a>(&'a self, it: &fn(&uint, &'a V) -> bool) { - for uint::range(0, self.v.len()) |i| { - match self.v[i] { - Some(ref elt) => if !it(&i, elt) { break }, - None => () - } - } - } - - /// Visit all key-value pairs in order - #[cfg(not(stage0))] - fn each<'a>(&'a self, it: &fn(&uint, &'a V) -> bool) -> bool { - for uint::range(0, self.v.len()) |i| { - match self.v[i] { - Some(ref elt) => if !it(&i, elt) { return false; }, - None => () - } - } - return true; - } - - /// Visit all keys in order - #[cfg(stage0)] - fn each_key(&self, blk: &fn(key: &uint) -> bool) { - self.each(|k, _| blk(k)) - } - #[cfg(not(stage0))] - /// Visit all keys in order - fn each_key(&self, blk: &fn(key: &uint) -> bool) -> bool { - self.each(|k, _| blk(k)) - } - - /// Visit all values in order - #[cfg(stage0)] - fn each_value<'a>(&'a self, blk: &fn(value: &'a V) -> bool) { - self.each(|_, v| blk(v)) - } - - /// Visit all values in order - #[cfg(not(stage0))] - fn each_value<'a>(&'a self, blk: &fn(value: &'a V) -> bool) -> bool { - self.each(|_, v| blk(v)) - } - - /// Iterate over the map and mutate the contained values - #[cfg(stage0)] - fn mutate_values(&mut self, it: &fn(&uint, &mut V) -> bool) { - for uint::range(0, self.v.len()) |i| { - match self.v[i] { - Some(ref mut elt) => if !it(&i, elt) { return; }, - None => () - } - } - } - /// Iterate over the map and mutate the contained values - #[cfg(not(stage0))] - fn mutate_values(&mut self, it: &fn(&uint, &mut V) -> bool) -> bool { - for uint::range(0, self.v.len()) |i| { - match self.v[i] { - Some(ref mut elt) => if !it(&i, elt) { return false; }, - None => () - } - } - return true; - } - - /// Return a reference to the value corresponding to the key - fn find<'a>(&'a self, key: &uint) -> Option<&'a V> { - if *key < self.v.len() { - match self.v[*key] { - Some(ref value) => Some(value), - None => None - } - } else { - None - } - } - - /// Return a mutable reference to the value corresponding to the key - fn find_mut<'a>(&'a mut self, key: &uint) -> Option<&'a mut V> { - if *key < self.v.len() { - match self.v[*key] { - Some(ref mut value) => Some(value), - None => None - } - } else { - None - } - } - - /// Insert a key-value pair into the map. An existing value for a - /// key is replaced by the new value. Return true if the key did - /// not already exist in the map. - fn insert(&mut self, key: uint, value: V) -> bool { - let exists = self.contains_key(&key); - let len = self.v.len(); - if len <= key { - vec::grow_fn(&mut self.v, key - len + 1, |_| None); - } - self.v[key] = Some(value); - !exists - } - - /// Remove a key-value pair from the map. Return true if the key - /// was present in the map, otherwise false. - fn remove(&mut self, key: &uint) -> bool { - self.pop(key).is_some() - } - - /// Insert a key-value pair from the map. If the key already had a value - /// present in the map, that value is returned. Otherwise None is returned. - fn swap(&mut self, key: uint, value: V) -> Option { - match self.find_mut(&key) { - Some(loc) => { return Some(replace(loc, value)); } - None => () - } - self.insert(key, value); - return None; - } - - /// Removes a key from the map, returning the value at the key if the key - /// was previously in the map. - fn pop(&mut self, key: &uint) -> Option { - if *key >= self.v.len() { - return None; - } - replace(&mut self.v[*key], None) - } -} - -pub impl SmallIntMap { - /// Create an empty SmallIntMap - fn new() -> SmallIntMap { SmallIntMap{v: ~[]} } - - /// Visit all key-value pairs in reverse order - #[cfg(stage0)] - fn each_reverse<'a>(&'a self, it: &fn(uint, &'a V) -> bool) { - for uint::range_rev(self.v.len(), 0) |i| { - match self.v[i - 1] { - Some(ref elt) => if !it(i - 1, elt) { break }, - None => () - } - } - } - - /// Visit all key-value pairs in reverse order - #[cfg(not(stage0))] - fn each_reverse<'a>(&'a self, it: &fn(uint, &'a V) -> bool) -> bool { - for uint::range_rev(self.v.len(), 0) |i| { - match self.v[i - 1] { - Some(ref elt) => if !it(i - 1, elt) { return false; }, - None => () - } - } - return true; - } - - fn get<'a>(&'a self, key: &uint) -> &'a V { - self.find(key).expect("key not present") - } -} - -pub impl SmallIntMap { - fn update_with_key(&mut self, key: uint, val: V, - ff: &fn(uint, V, V) -> V) -> bool { - let new_val = match self.find(&key) { - None => val, - Some(orig) => ff(key, *orig, val) - }; - self.insert(key, new_val) - } - - fn update(&mut self, key: uint, newval: V, ff: &fn(V, V) -> V) -> bool { - self.update_with_key(key, newval, |_k, v, v1| ff(v,v1)) - } -} - -#[cfg(test)] -mod tests { - use super::SmallIntMap; - - #[test] - fn test_find_mut() { - let mut m = SmallIntMap::new(); - assert!(m.insert(1, 12)); - assert!(m.insert(2, 8)); - assert!(m.insert(5, 14)); - let new = 100; - match m.find_mut(&5) { - None => fail!(), Some(x) => *x = new - } - assert_eq!(m.find(&5), Some(&new)); - } - - #[test] - fn test_len() { - let mut map = SmallIntMap::new(); - assert!(map.len() == 0); - assert!(map.is_empty()); - assert!(map.insert(5, 20)); - assert!(map.len() == 1); - assert!(!map.is_empty()); - assert!(map.insert(11, 12)); - assert!(map.len() == 2); - assert!(!map.is_empty()); - assert!(map.insert(14, 22)); - assert!(map.len() == 3); - assert!(!map.is_empty()); - } - - #[test] - fn test_clear() { - let mut map = SmallIntMap::new(); - assert!(map.insert(5, 20)); - assert!(map.insert(11, 12)); - assert!(map.insert(14, 22)); - map.clear(); - assert!(map.is_empty()); - assert!(map.find(&5).is_none()); - assert!(map.find(&11).is_none()); - assert!(map.find(&14).is_none()); - } - - #[test] - fn test_insert_with_key() { - let mut map = SmallIntMap::new(); - - // given a new key, initialize it with this new count, given - // given an existing key, add more to its count - fn addMoreToCount(_k: uint, v0: uint, v1: uint) -> uint { - v0 + v1 - } - - fn addMoreToCount_simple(v0: uint, v1: uint) -> uint { - v0 + v1 - } - - // count integers - map.update(3, 1, addMoreToCount_simple); - map.update_with_key(9, 1, addMoreToCount); - map.update(3, 7, addMoreToCount_simple); - map.update_with_key(5, 3, addMoreToCount); - map.update_with_key(3, 2, addMoreToCount); - - // check the total counts - assert!(map.find(&3).get() == &10); - assert!(map.find(&5).get() == &3); - assert!(map.find(&9).get() == &1); - - // sadly, no sevens were counted - assert!(map.find(&7).is_none()); - } - - #[test] - fn test_swap() { - let mut m = SmallIntMap::new(); - assert!(m.swap(1, 2) == None); - assert!(m.swap(1, 3) == Some(2)); - assert!(m.swap(1, 4) == Some(3)); - } - - #[test] - fn test_pop() { - let mut m = SmallIntMap::new(); - m.insert(1, 2); - assert!(m.pop(&1) == Some(2)); - assert!(m.pop(&1) == None); - } -} diff --git a/src/libstd/sort_stage0.rs b/src/libstd/sort_stage0.rs deleted file mode 100644 index 270f7196d294b..0000000000000 --- a/src/libstd/sort_stage0.rs +++ /dev/null @@ -1,1240 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Sorting methods - -use core::cmp::{Eq, Ord}; -use core::vec::len; -use core::vec; -use core::util; - -type Le<'self, T> = &'self fn(v1: &T, v2: &T) -> bool; - -/** - * Merge sort. Returns a new vector containing the sorted list. - * - * Has worst case O(n log n) performance, best case O(n), but - * is not space efficient. This is a stable sort. - */ -pub fn merge_sort(v: &const [T], le: Le) -> ~[T] { - type Slice = (uint, uint); - - return merge_sort_(v, (0u, len(v)), le); - - fn merge_sort_(v: &const [T], slice: Slice, le: Le) - -> ~[T] { - let begin = slice.first(); - let end = slice.second(); - - let v_len = end - begin; - if v_len == 0 { return ~[]; } - if v_len == 1 { return ~[v[begin]]; } - - let mid = v_len / 2 + begin; - let a = (begin, mid); - let b = (mid, end); - return merge(le, merge_sort_(v, a, le), merge_sort_(v, b, le)); - } - - fn merge(le: Le, a: &[T], b: &[T]) -> ~[T] { - let mut rs = vec::with_capacity(len(a) + len(b)); - let a_len = len(a); - let mut a_ix = 0; - let b_len = len(b); - let mut b_ix = 0; - while a_ix < a_len && b_ix < b_len { - if le(&a[a_ix], &b[b_ix]) { - rs.push(a[a_ix]); - a_ix += 1; - } else { rs.push(b[b_ix]); b_ix += 1; } - } - rs.push_all(vec::slice(a, a_ix, a_len)); - rs.push_all(vec::slice(b, b_ix, b_len)); - rs - } -} - -#[cfg(stage0)] -fn part(arr: &mut [T], left: uint, - right: uint, pivot: uint, compare_func: Le) -> uint { - vec::swap(arr, pivot, right); - let mut storage_index: uint = left; - let mut i: uint = left; - while i < right { - let a: &mut T = &mut arr[i]; - let b: &mut T = &mut arr[right]; - if compare_func(a, b) { - vec::swap(arr, i, storage_index); - storage_index += 1; - } - i += 1; - } - vec::swap(arr, storage_index, right); - return storage_index; -} - -#[cfg(not(stage0))] -fn part(arr: &mut [T], left: uint, - right: uint, pivot: uint, compare_func: Le) -> uint { - vec::swap(arr, pivot, right); - let mut storage_index: uint = left; - let mut i: uint = left; - while i < right { - if compare_func(&arr[i], &arr[right]) { - vec::swap(arr, i, storage_index); - storage_index += 1; - } - i += 1; - } - vec::swap(arr, storage_index, right); - return storage_index; -} - -fn qsort(arr: &mut [T], left: uint, - right: uint, compare_func: Le) { - if right > left { - let pivot = (left + right) / 2u; - let new_pivot = part::(arr, left, right, pivot, compare_func); - if new_pivot != 0u { - // Need to do this check before recursing due to overflow - qsort::(arr, left, new_pivot - 1u, compare_func); - } - qsort::(arr, new_pivot + 1u, right, compare_func); - } -} - -/** - * Quicksort. Sorts a mut vector in place. - * - * Has worst case O(n^2) performance, average case O(n log n). - * This is an unstable sort. - */ -pub fn quick_sort(arr: &mut [T], compare_func: Le) { - if len::(arr) == 0u { return; } - qsort::(arr, 0u, len::(arr) - 1u, compare_func); -} - -fn qsort3(arr: &mut [T], left: int, right: int) { - if right <= left { return; } - let v: T = arr[right]; - let mut i: int = left - 1; - let mut j: int = right; - let mut p: int = i; - let mut q: int = j; - loop { - i += 1; - while arr[i] < v { i += 1; } - j -= 1; - while v < arr[j] { - if j == left { break; } - j -= 1; - } - if i >= j { break; } - vec::swap(arr, i as uint, j as uint); - if arr[i] == v { - p += 1; - vec::swap(arr, p as uint, i as uint); - } - if v == arr[j] { - q -= 1; - vec::swap(arr, j as uint, q as uint); - } - } - vec::swap(arr, i as uint, right as uint); - j = i - 1; - i += 1; - let mut k: int = left; - while k < p { - vec::swap(arr, k as uint, j as uint); - k += 1; - j -= 1; - if k == len::(arr) as int { break; } - } - k = right - 1; - while k > q { - vec::swap(arr, i as uint, k as uint); - k -= 1; - i += 1; - if k == 0 { break; } - } - qsort3::(arr, left, j); - qsort3::(arr, i, right); -} - -/** - * Fancy quicksort. Sorts a mut vector in place. - * - * Based on algorithm presented by ~[Sedgewick and Bentley] - * (http://www.cs.princeton.edu/~rs/talks/QuicksortIsOptimal.pdf). - * According to these slides this is the algorithm of choice for - * 'randomly ordered keys, abstract compare' & 'small number of key values'. - * - * This is an unstable sort. - */ -pub fn quick_sort3(arr: &mut [T]) { - if arr.len() <= 1 { return; } - let len = arr.len() - 1; // FIXME(#5074) nested calls - qsort3(arr, 0, (len - 1) as int); -} - -pub trait Sort { - fn qsort(self); -} - -impl<'self, T:Copy + Ord + Eq> Sort for &'self mut [T] { - fn qsort(self) { quick_sort3(self); } -} - -static MIN_MERGE: uint = 64; -static MIN_GALLOP: uint = 7; -static INITIAL_TMP_STORAGE: uint = 128; - -pub fn tim_sort(array: &mut [T]) { - let size = array.len(); - if size < 2 { - return; - } - - if size < MIN_MERGE { - let init_run_len = count_run_ascending(array); - binarysort(array, init_run_len); - return; - } - - let mut ms = MergeState(); - let min_run = min_run_length(size); - - let mut idx = 0; - let mut remaining = size; - loop { - let run_len: uint = { - // This scope contains the slice `arr` here: - let arr = vec::mut_slice(array, idx, size); - let mut run_len: uint = count_run_ascending(arr); - - if run_len < min_run { - let force = if remaining <= min_run {remaining} else {min_run}; - let slice = vec::mut_slice(arr, 0, force); - binarysort(slice, run_len); - run_len = force; - } - - run_len - }; - - ms.push_run(idx, run_len); - ms.merge_collapse(array); - - idx += run_len; - remaining -= run_len; - if remaining == 0 { break; } - } - - ms.merge_force_collapse(array); -} - -fn binarysort(array: &mut [T], start: uint) { - let size = array.len(); - let mut start = start; - assert!(start <= size); - - if start == 0 { start += 1; } - - while start < size { - let pivot = array[start]; - let mut left = 0; - let mut right = start; - assert!(left <= right); - - while left < right { - let mid = (left + right) >> 1; - if pivot < array[mid] { - right = mid; - } else { - left = mid+1; - } - } - assert!(left == right); - let n = start-left; - - copy_vec(array, left+1, array, left, n); - array[left] = pivot; - start += 1; - } -} - -// Reverse the order of elements in a slice, in place -fn reverse_slice(v: &mut [T], start: uint, end:uint) { - let mut i = start; - while i < end / 2 { - vec::swap(v, i, end - i - 1); - i += 1; - } -} - -fn min_run_length(n: uint) -> uint { - let mut n = n; - let mut r = 0; // becomes 1 if any 1 bits are shifted off - - while n >= MIN_MERGE { - r |= n & 1; - n >>= 1; - } - return n + r; -} - -fn count_run_ascending(array: &mut [T]) -> uint { - let size = array.len(); - assert!(size > 0); - if size == 1 { return 1; } - - let mut run = 2; - if array[1] < array[0] { - while run < size && array[run] < array[run-1] { - run += 1; - } - reverse_slice(array, 0, run); - } else { - while run < size && array[run] >= array[run-1] { - run += 1; - } - } - - return run; -} - -fn gallop_left(key: &const T, - array: &const [T], - hint: uint) - -> uint { - let size = array.len(); - assert!(size != 0 && hint < size); - - let mut last_ofs = 0; - let mut ofs = 1; - - if *key > array[hint] { - // Gallop right until array[hint+last_ofs] < key <= array[hint+ofs] - let max_ofs = size - hint; - while ofs < max_ofs && *key > array[hint+ofs] { - last_ofs = ofs; - ofs = (ofs << 1) + 1; - if ofs < last_ofs { ofs = max_ofs; } // uint overflow guard - } - if ofs > max_ofs { ofs = max_ofs; } - - last_ofs += hint; - ofs += hint; - } else { - let max_ofs = hint + 1; - while ofs < max_ofs && *key <= array[hint-ofs] { - last_ofs = ofs; - ofs = (ofs << 1) + 1; - if ofs < last_ofs { ofs = max_ofs; } // uint overflow guard - } - - if ofs > max_ofs { ofs = max_ofs; } - - let tmp = last_ofs; - last_ofs = hint - ofs; - ofs = hint - tmp; - } - assert!((last_ofs < ofs || last_ofs+1 < ofs+1) && ofs <= size); - - last_ofs += 1; - while last_ofs < ofs { - let m = last_ofs + ((ofs - last_ofs) >> 1); - if *key > array[m] { - last_ofs = m+1; - } else { - ofs = m; - } - } - assert!(last_ofs == ofs); - return ofs; -} - -fn gallop_right(key: &const T, - array: &const [T], - hint: uint) - -> uint { - let size = array.len(); - assert!(size != 0 && hint < size); - - let mut last_ofs = 0; - let mut ofs = 1; - - if *key >= array[hint] { - // Gallop right until array[hint+last_ofs] <= key < array[hint+ofs] - let max_ofs = size - hint; - while ofs < max_ofs && *key >= array[hint+ofs] { - last_ofs = ofs; - ofs = (ofs << 1) + 1; - if ofs < last_ofs { ofs = max_ofs; } - } - if ofs > max_ofs { ofs = max_ofs; } - - last_ofs += hint; - ofs += hint; - } else { - // Gallop left until array[hint-ofs] <= key < array[hint-last_ofs] - let max_ofs = hint + 1; - while ofs < max_ofs && *key < array[hint-ofs] { - last_ofs = ofs; - ofs = (ofs << 1) + 1; - if ofs < last_ofs { ofs = max_ofs; } - } - if ofs > max_ofs { ofs = max_ofs; } - - let tmp = last_ofs; - last_ofs = hint - ofs; - ofs = hint - tmp; - } - - assert!((last_ofs < ofs || last_ofs+1 < ofs+1) && ofs <= size); - - last_ofs += 1; - while last_ofs < ofs { - let m = last_ofs + ((ofs - last_ofs) >> 1); - - if *key >= array[m] { - last_ofs = m + 1; - } else { - ofs = m; - } - } - assert!(last_ofs == ofs); - return ofs; -} - -struct RunState { - base: uint, - len: uint, -} - -struct MergeState { - min_gallop: uint, - runs: ~[RunState], -} - -// Fixme (#3853) Move into MergeState -fn MergeState() -> MergeState { - MergeState { - min_gallop: MIN_GALLOP, - runs: ~[], - } -} - -impl MergeState { - fn push_run(&mut self, run_base: uint, run_len: uint) { - let tmp = RunState{base: run_base, len: run_len}; - self.runs.push(tmp); - } - - fn merge_at(&mut self, n: uint, array: &mut [T]) { - let size = self.runs.len(); - assert!(size >= 2); - assert!(n == size-2 || n == size-3); - - let mut b1 = self.runs[n].base; - let mut l1 = self.runs[n].len; - let b2 = self.runs[n+1].base; - let l2 = self.runs[n+1].len; - - assert!(l1 > 0 && l2 > 0); - assert!(b1 + l1 == b2); - - self.runs[n].len = l1 + l2; - if n == size-3 { - self.runs[n+1].base = self.runs[n+2].base; - self.runs[n+1].len = self.runs[n+2].len; - } - - let k = { // constrain lifetime of slice below - let slice = vec::mut_slice(array, b1, b1+l1); - gallop_right(&const array[b2], slice, 0) - }; - b1 += k; - l1 -= k; - if l1 != 0 { - let l2 = { // constrain lifetime of slice below - let slice = vec::mut_slice(array, b2, b2+l2); - gallop_left(&const array[b1+l1-1],slice,l2-1) - }; - if l2 > 0 { - if l1 <= l2 { - self.merge_lo(array, b1, l1, b2, l2); - } else { - self.merge_hi(array, b1, l1, b2, l2); - } - } - } - self.runs.pop(); - } - - fn merge_lo(&mut self, array: &mut [T], base1: uint, len1: uint, - base2: uint, len2: uint) { - assert!(len1 != 0 && len2 != 0 && base1+len1 == base2); - - let mut tmp = ~[]; - for uint::range(base1, base1+len1) |i| { - tmp.push(array[i]); - } - - let mut c1 = 0; - let mut c2 = base2; - let mut dest = base1; - let mut len1 = len1; - let mut len2 = len2; - - vec::swap(array, dest, c2); - dest += 1; c2 += 1; len2 -= 1; - - if len2 == 0 { - copy_vec(array, dest, tmp, 0, len1); - return; - } - if len1 == 1 { - copy_vec(array, dest, array, c2, len2); - util::swap(&mut array[dest+len2], &mut tmp[c1]); - return; - } - - let mut min_gallop = self.min_gallop; - loop { - let mut count1 = 0; - let mut count2 = 0; - let mut break_outer = false; - - loop { - assert!(len1 > 1 && len2 != 0); - if array[c2] < tmp[c1] { - vec::swap(array, dest, c2); - dest += 1; c2 += 1; len2 -= 1; - count2 += 1; count1 = 0; - if len2 == 0 { - break_outer = true; - } - } else { - util::swap(&mut array[dest], &mut tmp[c1]); - dest += 1; c1 += 1; len1 -= 1; - count1 += 1; count2 = 0; - if len1 == 1 { - break_outer = true; - } - } - if break_outer || ((count1 | count2) >= min_gallop) { - break; - } - } - if break_outer { break; } - - // Start to gallop - loop { - assert!(len1 > 1 && len2 != 0); - - let tmp_view = vec::const_slice(tmp, c1, c1+len1); - count1 = gallop_right(&const array[c2], tmp_view, 0); - if count1 != 0 { - copy_vec(array, dest, tmp, c1, count1); - dest += count1; c1 += count1; len1 -= count1; - if len1 <= 1 { break_outer = true; break; } - } - vec::swap(array, dest, c2); - dest += 1; c2 += 1; len2 -= 1; - if len2 == 0 { break_outer = true; break; } - - let tmp_view = vec::const_slice(array, c2, c2+len2); - count2 = gallop_left(&const tmp[c1], tmp_view, 0); - if count2 != 0 { - copy_vec(array, dest, array, c2, count2); - dest += count2; c2 += count2; len2 -= count2; - if len2 == 0 { break_outer = true; break; } - } - util::swap(&mut array[dest], &mut tmp[c1]); - dest += 1; c1 += 1; len1 -= 1; - if len1 == 1 { break_outer = true; break; } - min_gallop -= 1; - if !(count1 >= MIN_GALLOP || count2 >= MIN_GALLOP) { - break; - } - } - if break_outer { break; } - if min_gallop < 0 { min_gallop = 0; } - min_gallop += 2; // Penalize for leaving gallop - } - self.min_gallop = if min_gallop < 1 { 1 } else { min_gallop }; - - if len1 == 1 { - assert!(len2 > 0); - copy_vec(array, dest, array, c2, len2); - util::swap(&mut array[dest+len2], &mut tmp[c1]); - } else if len1 == 0 { - fail!("Comparison violates its contract!"); - } else { - assert!(len2 == 0); - assert!(len1 > 1); - copy_vec(array, dest, tmp, c1, len1); - } - } - - fn merge_hi(&mut self, array: &mut [T], base1: uint, len1: uint, - base2: uint, len2: uint) { - assert!(len1 != 1 && len2 != 0 && base1 + len1 == base2); - - let mut tmp = ~[]; - for uint::range(base2, base2+len2) |i| { - tmp.push(array[i]); - } - - let mut c1 = base1 + len1 - 1; - let mut c2 = len2 - 1; - let mut dest = base2 + len2 - 1; - let mut len1 = len1; - let mut len2 = len2; - - vec::swap(array, dest, c1); - dest -= 1; c1 -= 1; len1 -= 1; - - if len1 == 0 { - copy_vec(array, dest-(len2-1), tmp, 0, len2); - return; - } - if len2 == 1 { - dest -= len1; - c1 -= len1; - copy_vec(array, dest+1, array, c1+1, len1); - util::swap(&mut array[dest], &mut tmp[c2]); - return; - } - - let mut min_gallop = self.min_gallop; - loop { - let mut count1 = 0; - let mut count2 = 0; - let mut break_outer = false; - - loop { - assert!(len1 != 0 && len2 > 1); - if tmp[c2] < array[c1] { - vec::swap(array, dest, c1); - dest -= 1; c1 -= 1; len1 -= 1; - count1 += 1; count2 = 0; - if len1 == 0 { - break_outer = true; - } - } else { - util::swap(&mut array[dest], &mut tmp[c2]); - dest -= 1; c2 -= 1; len2 -= 1; - count2 += 1; count1 = 0; - if len2 == 1 { - break_outer = true; - } - } - if break_outer || ((count1 | count2) >= min_gallop) { - break; - } - } - if break_outer { break; } - - // Start to gallop - loop { - assert!(len2 > 1 && len1 != 0); - - { // constrain scope of tmp_view: - let tmp_view = vec::mut_slice (array, base1, base1+len1); - count1 = len1 - gallop_right( - &const tmp[c2], tmp_view, len1-1); - } - - if count1 != 0 { - dest -= count1; c1 -= count1; len1 -= count1; - copy_vec(array, dest+1, array, c1+1, count1); - if len1 == 0 { break_outer = true; break; } - } - - util::swap(&mut array[dest], &mut tmp[c2]); - dest -= 1; c2 -= 1; len2 -= 1; - if len2 == 1 { break_outer = true; break; } - - let count2; - { // constrain scope of tmp_view - let tmp_view = vec::mut_slice(tmp, 0, len2); - count2 = len2 - gallop_left(&const array[c1], - tmp_view, - len2-1); - } - - if count2 != 0 { - dest -= count2; c2 -= count2; len2 -= count2; - copy_vec(array, dest+1, tmp, c2+1, count2); - if len2 <= 1 { break_outer = true; break; } - } - vec::swap(array, dest, c1); - dest -= 1; c1 -= 1; len1 -= 1; - if len1 == 0 { break_outer = true; break; } - min_gallop -= 1; - if !(count1 >= MIN_GALLOP || count2 >= MIN_GALLOP) { - break; - } - } - - if break_outer { break; } - if min_gallop < 0 { min_gallop = 0; } - min_gallop += 2; // Penalize for leaving gallop - } - self.min_gallop = if min_gallop < 1 { 1 } else { min_gallop }; - - if len2 == 1 { - assert!(len1 > 0); - dest -= len1; - c1 -= len1; - copy_vec(array, dest+1, array, c1+1, len1); - util::swap(&mut array[dest], &mut tmp[c2]); - } else if len2 == 0 { - fail!("Comparison violates its contract!"); - } else { - assert!(len1 == 0); - assert!(len2 != 0); - copy_vec(array, dest-(len2-1), tmp, 0, len2); - } - } - - fn merge_collapse(&mut self, array: &mut [T]) { - while self.runs.len() > 1 { - let mut n = self.runs.len()-2; - if n > 0 && - self.runs[n-1].len <= self.runs[n].len + self.runs[n+1].len - { - if self.runs[n-1].len < self.runs[n+1].len { n -= 1; } - } else if self.runs[n].len <= self.runs[n+1].len { - /* keep going */ - } else { - break; - } - self.merge_at(n, array); - } - } - - fn merge_force_collapse(&mut self, array: &mut [T]) { - while self.runs.len() > 1 { - let mut n = self.runs.len()-2; - if n > 0 { - if self.runs[n-1].len < self.runs[n+1].len { - n -= 1; - } - } - self.merge_at(n, array); - } - } -} - -#[inline(always)] -fn copy_vec(dest: &mut [T], - s1: uint, - from: &const [T], - s2: uint, - len: uint) { - assert!(s1+len <= dest.len() && s2+len <= from.len()); - - let mut slice = ~[]; - for uint::range(s2, s2+len) |i| { - slice.push(from[i]); - } - - for slice.eachi |i, v| { - dest[s1+i] = *v; - } -} - -#[cfg(test)] -mod test_qsort3 { - use sort::*; - - use core::vec; - - fn check_sort(v1: &mut [int], v2: &mut [int]) { - let len = vec::len::(v1); - quick_sort3::(v1); - let mut i = 0; - while i < len { - // debug!(v2[i]); - assert!((v2[i] == v1[i])); - i += 1; - } - } - - #[test] - fn test() { - { - let mut v1 = ~[3, 7, 4, 5, 2, 9, 5, 8]; - let mut v2 = ~[2, 3, 4, 5, 5, 7, 8, 9]; - check_sort(v1, v2); - } - { - let mut v1 = ~[1, 1, 1]; - let mut v2 = ~[1, 1, 1]; - check_sort(v1, v2); - } - { - let mut v1: ~[int] = ~[]; - let mut v2: ~[int] = ~[]; - check_sort(v1, v2); - } - { let mut v1 = ~[9]; let mut v2 = ~[9]; check_sort(v1, v2); } - { - let mut v1 = ~[9, 3, 3, 3, 9]; - let mut v2 = ~[3, 3, 3, 9, 9]; - check_sort(v1, v2); - } - } -} - -#[cfg(test)] -mod test_qsort { - use sort::*; - - use core::int; - use core::vec; - - fn check_sort(v1: &mut [int], v2: &mut [int]) { - let len = vec::len::(v1); - fn leual(a: &int, b: &int) -> bool { *a <= *b } - quick_sort::(v1, leual); - let mut i = 0u; - while i < len { - // debug!(v2[i]); - assert!((v2[i] == v1[i])); - i += 1; - } - } - - #[test] - fn test() { - { - let mut v1 = ~[3, 7, 4, 5, 2, 9, 5, 8]; - let mut v2 = ~[2, 3, 4, 5, 5, 7, 8, 9]; - check_sort(v1, v2); - } - { - let mut v1 = ~[1, 1, 1]; - let mut v2 = ~[1, 1, 1]; - check_sort(v1, v2); - } - { - let mut v1: ~[int] = ~[]; - let mut v2: ~[int] = ~[]; - check_sort(v1, v2); - } - { let mut v1 = ~[9]; let mut v2 = ~[9]; check_sort(v1, v2); } - { - let mut v1 = ~[9, 3, 3, 3, 9]; - let mut v2 = ~[3, 3, 3, 9, 9]; - check_sort(v1, v2); - } - } - - // Regression test for #750 - #[test] - fn test_simple() { - let mut names = ~[2, 1, 3]; - - let expected = ~[1, 2, 3]; - - do quick_sort(names) |x, y| { int::le(*x, *y) }; - - let immut_names = names; - - let pairs = vec::zip_slice(expected, immut_names); - for pairs.each |p| { - let (a, b) = *p; - debug!("%d %d", a, b); - assert!((a == b)); - } - } -} - -#[cfg(test)] -mod tests { - - use sort::*; - - use core::vec; - - fn check_sort(v1: &[int], v2: &[int]) { - let len = vec::len::(v1); - pub fn le(a: &int, b: &int) -> bool { *a <= *b } - let f = le; - let v3 = merge_sort::(v1, f); - let mut i = 0u; - while i < len { - debug!(v3[i]); - assert!((v3[i] == v2[i])); - i += 1; - } - } - - #[test] - fn test() { - { - let v1 = ~[3, 7, 4, 5, 2, 9, 5, 8]; - let v2 = ~[2, 3, 4, 5, 5, 7, 8, 9]; - check_sort(v1, v2); - } - { let v1 = ~[1, 1, 1]; let v2 = ~[1, 1, 1]; check_sort(v1, v2); } - { let v1:~[int] = ~[]; let v2:~[int] = ~[]; check_sort(v1, v2); } - { let v1 = ~[9]; let v2 = ~[9]; check_sort(v1, v2); } - { - let v1 = ~[9, 3, 3, 3, 9]; - let v2 = ~[3, 3, 3, 9, 9]; - check_sort(v1, v2); - } - } - - #[test] - fn test_merge_sort_mutable() { - pub fn le(a: &int, b: &int) -> bool { *a <= *b } - let mut v1 = ~[3, 2, 1]; - let v2 = merge_sort(v1, le); - assert!(v2 == ~[1, 2, 3]); - } - - #[test] - fn test_merge_sort_stability() { - // tjc: funny that we have to use parens - fn ile(x: &(&'static str), y: &(&'static str)) -> bool - { - // FIXME: #4318 Instead of to_ascii and to_str_ascii, could use - // to_ascii_consume and to_str_consume to not do a unnecessary copy. - // (Actually, could just remove the to_str_* call, but needs an deriving(Ord) on - // Ascii) - let x = x.to_ascii().to_lower().to_str_ascii(); - let y = y.to_ascii().to_lower().to_str_ascii(); - x <= y - } - - let names1 = ~["joe bob", "Joe Bob", "Jack Brown", "JOE Bob", - "Sally Mae", "JOE BOB", "Alex Andy"]; - let names2 = ~["Alex Andy", "Jack Brown", "joe bob", "Joe Bob", - "JOE Bob", "JOE BOB", "Sally Mae"]; - let names3 = merge_sort(names1, ile); - assert!(names3 == names2); - } -} - -#[cfg(test)] -mod test_tim_sort { - use sort::tim_sort; - use core::rand::RngUtil; - - struct CVal { - val: float, - } - - impl Ord for CVal { - fn lt(&self, other: &CVal) -> bool { - let rng = rand::rng(); - if rng.gen::() > 0.995 { fail!("It's happening!!!"); } - (*self).val < other.val - } - fn le(&self, other: &CVal) -> bool { (*self).val <= other.val } - fn gt(&self, other: &CVal) -> bool { (*self).val > other.val } - fn ge(&self, other: &CVal) -> bool { (*self).val >= other.val } - } - - fn check_sort(v1: &mut [int], v2: &mut [int]) { - let len = vec::len::(v1); - tim_sort::(v1); - let mut i = 0u; - while i < len { - // debug!(v2[i]); - assert!((v2[i] == v1[i])); - i += 1u; - } - } - - #[test] - fn test() { - { - let mut v1 = ~[3, 7, 4, 5, 2, 9, 5, 8]; - let mut v2 = ~[2, 3, 4, 5, 5, 7, 8, 9]; - check_sort(v1, v2); - } - { - let mut v1 = ~[1, 1, 1]; - let mut v2 = ~[1, 1, 1]; - check_sort(v1, v2); - } - { - let mut v1: ~[int] = ~[]; - let mut v2: ~[int] = ~[]; - check_sort(v1, v2); - } - { let mut v1 = ~[9]; let mut v2 = ~[9]; check_sort(v1, v2); } - { - let mut v1 = ~[9, 3, 3, 3, 9]; - let mut v2 = ~[3, 3, 3, 9, 9]; - check_sort(v1, v2); - } - } - - #[test] - #[should_fail] - #[cfg(unix)] - fn crash_test() { - let rng = rand::rng(); - let mut arr = do vec::from_fn(1000) |_i| { - CVal { val: rng.gen() } - }; - - tim_sort(arr); - fail!("Guarantee the fail"); - } - - struct DVal { val: uint } - - impl Ord for DVal { - fn lt(&self, _x: &DVal) -> bool { true } - fn le(&self, _x: &DVal) -> bool { true } - fn gt(&self, _x: &DVal) -> bool { true } - fn ge(&self, _x: &DVal) -> bool { true } - } - - #[test] - fn test_bad_Ord_impl() { - let rng = rand::rng(); - let mut arr = do vec::from_fn(500) |_i| { - DVal { val: rng.gen() } - }; - - tim_sort(arr); - } -} - -#[cfg(test)] -mod big_tests { - use sort::*; - use core::rand::RngUtil; - - #[test] - fn test_unique() { - let low = 5; - let high = 10; - tabulate_unique(low, high); - } - - #[test] - fn test_managed() { - let low = 5; - let high = 10; - tabulate_managed(low, high); - } - - fn multiplyVec(arr: &const [T], num: uint) -> ~[T] { - let size = arr.len(); - let res = do vec::from_fn(num) |i| { - arr[i % size] - }; - res - } - - fn makeRange(n: uint) -> ~[uint] { - let one = do vec::from_fn(n) |i| { i }; - let mut two = copy one; - vec::reverse(two); - vec::append(two, one) - } - - fn tabulate_unique(lo: uint, hi: uint) { - fn isSorted(arr: &const [T]) { - for uint::range(0, arr.len()-1) |i| { - if arr[i] > arr[i+1] { - fail!("Array not sorted"); - } - } - } - - let rng = rand::rng(); - - for uint::range(lo, hi) |i| { - let n = 1 << i; - let mut arr: ~[float] = do vec::from_fn(n) |_i| { - rng.gen() - }; - - tim_sort(arr); // *sort - isSorted(arr); - - vec::reverse(arr); - tim_sort(arr); // \sort - isSorted(arr); - - tim_sort(arr); // /sort - isSorted(arr); - - for 3.times { - let i1 = rng.gen_uint_range(0, n); - let i2 = rng.gen_uint_range(0, n); - vec::swap(arr, i1, i2); - } - tim_sort(arr); // 3sort - isSorted(arr); - - if n >= 10 { - let size = arr.len(); - let mut idx = 1; - while idx <= 10 { - arr[size-idx] = rng.gen(); - idx += 1; - } - } - tim_sort(arr); // +sort - isSorted(arr); - - for (n/100).times { - let idx = rng.gen_uint_range(0, n); - arr[idx] = rng.gen(); - } - tim_sort(arr); - isSorted(arr); - - let mut arr = if n > 4 { - let part = vec::slice(arr, 0, 4); - multiplyVec(part, n) - } else { arr }; - tim_sort(arr); // ~sort - isSorted(arr); - - let mut arr = vec::from_elem(n, -0.5); - tim_sort(arr); // =sort - isSorted(arr); - - let half = n / 2; - let mut arr = makeRange(half).map(|i| *i as float); - tim_sort(arr); // !sort - isSorted(arr); - } - } - - fn tabulate_managed(lo: uint, hi: uint) { - fn isSorted(arr: &const [@T]) { - for uint::range(0, arr.len()-1) |i| { - if arr[i] > arr[i+1] { - fail!("Array not sorted"); - } - } - } - - let rng = rand::rng(); - - for uint::range(lo, hi) |i| { - let n = 1 << i; - let arr: ~[@float] = do vec::from_fn(n) |_i| { - @rng.gen() - }; - let mut arr = arr; - - tim_sort(arr); // *sort - isSorted(arr); - - vec::reverse(arr); - tim_sort(arr); // \sort - isSorted(arr); - - tim_sort(arr); // /sort - isSorted(arr); - - for 3.times { - let i1 = rng.gen_uint_range(0, n); - let i2 = rng.gen_uint_range(0, n); - vec::swap(arr, i1, i2); - } - tim_sort(arr); // 3sort - isSorted(arr); - - if n >= 10 { - let size = arr.len(); - let mut idx = 1; - while idx <= 10 { - arr[size-idx] = @rng.gen(); - idx += 1; - } - } - tim_sort(arr); // +sort - isSorted(arr); - - for (n/100).times { - let idx = rng.gen_uint_range(0, n); - arr[idx] = @rng.gen(); - } - tim_sort(arr); - isSorted(arr); - - let mut arr = if n > 4 { - let part = vec::slice(arr, 0, 4); - multiplyVec(part, n) - } else { arr }; - tim_sort(arr); // ~sort - isSorted(arr); - - let mut arr = vec::from_elem(n, @(-0.5)); - tim_sort(arr); // =sort - isSorted(arr); - - let half = n / 2; - let mut arr = makeRange(half).map(|i| @(*i as float)); - tim_sort(arr); // !sort - isSorted(arr); - } - } - - struct LVal<'self> { - val: uint, - key: &'self fn(@uint), - } - - #[unsafe_destructor] - impl<'self> Drop for LVal<'self> { - fn finalize(&self) { - let x = unsafe { local_data::local_data_get(self.key) }; - match x { - Some(@y) => { - unsafe { - local_data::local_data_set(self.key, @(y+1)); - } - } - _ => fail!("Expected key to work"), - } - } - } - - impl<'self> Ord for LVal<'self> { - fn lt<'a>(&self, other: &'a LVal<'self>) -> bool { - (*self).val < other.val - } - fn le<'a>(&self, other: &'a LVal<'self>) -> bool { - (*self).val <= other.val - } - fn gt<'a>(&self, other: &'a LVal<'self>) -> bool { - (*self).val > other.val - } - fn ge<'a>(&self, other: &'a LVal<'self>) -> bool { - (*self).val >= other.val - } - } -} - -// Local Variables: -// mode: rust; -// fill-column: 78; -// indent-tabs-mode: nil -// c-basic-offset: 4 -// buffer-file-coding-system: utf-8-unix -// End: diff --git a/src/libcore/stackwalk.rs b/src/libstd/stackwalk.rs similarity index 63% rename from src/libcore/stackwalk.rs rename to src/libstd/stackwalk.rs index e86416f249902..c3e3ca57a8e74 100644 --- a/src/libcore/stackwalk.rs +++ b/src/libstd/stackwalk.rs @@ -8,9 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[doc(hidden)]; // FIXME #3538 +#[allow(missing_doc)]; use cast::transmute; +use unstable::intrinsics; pub type Word = uint; @@ -24,35 +25,6 @@ pub fn Frame(fp: *Word) -> Frame { } } -#[cfg(stage0)] -pub fn walk_stack(visit: &fn(Frame) -> bool) { - - debug!("beginning stack walk"); - - do frame_address |frame_pointer| { - let mut frame_address: *Word = unsafe { - transmute(frame_pointer) - }; - loop { - let fr = Frame(frame_address); - - debug!("frame: %x", unsafe { transmute(fr.fp) }); - visit(fr); - - unsafe { - let next_fp: **Word = transmute(frame_address); - frame_address = *next_fp; - if *frame_address == 0u { - debug!("encountered task_start_wrapper. ending walk"); - // This is the task_start_wrapper_frame. There is - // no stack beneath it and it is a foreign frame. - break; - } - } - } - } -} -#[cfg(not(stage0))] pub fn walk_stack(visit: &fn(Frame) -> bool) -> bool { debug!("beginning stack walk"); @@ -104,13 +76,6 @@ fn test_simple_deep() { fn frame_address(f: &fn(x: *u8)) { unsafe { - rusti::frame_address(f) - } -} - -pub mod rusti { - #[abi = "rust-intrinsic"] - pub extern "rust-intrinsic" { - pub fn frame_address(f: &once fn(x: *u8)); + intrinsics::frame_address(f) } } diff --git a/src/libcore/str.rs b/src/libstd/str.rs similarity index 71% rename from src/libcore/str.rs rename to src/libstd/str.rs index ec7177e52114e..da9ee21583dd9 100644 --- a/src/libcore/str.rs +++ b/src/libstd/str.rs @@ -30,7 +30,7 @@ use libc; use option::{None, Option, Some}; use old_iter::{BaseIter, EqIter}; use ptr; -use ptr::Ptr; +use ptr::RawPtr; use str; use to_str::ToStr; use uint; @@ -67,11 +67,21 @@ pub fn from_bytes(vv: &const [u8]) -> ~str { * Fails if not null terminated */ pub fn from_bytes_with_null<'a>(vv: &'a [u8]) -> &'a str { - assert!(vv[vv.len() - 1] == 0); + assert_eq!(vv[vv.len() - 1], 0); assert!(is_utf8(vv)); return unsafe { raw::from_bytes_with_null(vv) }; } +/** + * Converts a vector to a string slice without performing any allocations. + * + * Once the slice has been validated as utf-8, it is transmuted in-place and + * returned as a '&str' instead of a '&[u8]' + * + * # Failure + * + * Fails if invalid UTF-8 + */ pub fn from_bytes_slice<'a>(vector: &'a [u8]) -> &'a str { unsafe { assert!(is_utf8(vector)); @@ -128,57 +138,43 @@ pub fn push_char(s: &mut ~str, ch: char) { let off = len; do as_buf(*s) |buf, _len| { let buf: *mut u8 = ::cast::transmute(buf); - if nb == 1u { - *ptr::mut_offset(buf, off) = - code as u8; - } else if nb == 2u { - *ptr::mut_offset(buf, off) = - (code >> 6u & 31u | tag_two_b) as u8; - *ptr::mut_offset(buf, off + 1u) = - (code & 63u | tag_cont) as u8; - } else if nb == 3u { - *ptr::mut_offset(buf, off) = - (code >> 12u & 15u | tag_three_b) as u8; - *ptr::mut_offset(buf, off + 1u) = - (code >> 6u & 63u | tag_cont) as u8; - *ptr::mut_offset(buf, off + 2u) = - (code & 63u | tag_cont) as u8; - } else if nb == 4u { - *ptr::mut_offset(buf, off) = - (code >> 18u & 7u | tag_four_b) as u8; - *ptr::mut_offset(buf, off + 1u) = - (code >> 12u & 63u | tag_cont) as u8; - *ptr::mut_offset(buf, off + 2u) = - (code >> 6u & 63u | tag_cont) as u8; - *ptr::mut_offset(buf, off + 3u) = - (code & 63u | tag_cont) as u8; - } else if nb == 5u { - *ptr::mut_offset(buf, off) = - (code >> 24u & 3u | tag_five_b) as u8; - *ptr::mut_offset(buf, off + 1u) = - (code >> 18u & 63u | tag_cont) as u8; - *ptr::mut_offset(buf, off + 2u) = - (code >> 12u & 63u | tag_cont) as u8; - *ptr::mut_offset(buf, off + 3u) = - (code >> 6u & 63u | tag_cont) as u8; - *ptr::mut_offset(buf, off + 4u) = - (code & 63u | tag_cont) as u8; - } else if nb == 6u { - *ptr::mut_offset(buf, off) = - (code >> 30u & 1u | tag_six_b) as u8; - *ptr::mut_offset(buf, off + 1u) = - (code >> 24u & 63u | tag_cont) as u8; - *ptr::mut_offset(buf, off + 2u) = - (code >> 18u & 63u | tag_cont) as u8; - *ptr::mut_offset(buf, off + 3u) = - (code >> 12u & 63u | tag_cont) as u8; - *ptr::mut_offset(buf, off + 4u) = - (code >> 6u & 63u | tag_cont) as u8; - *ptr::mut_offset(buf, off + 5u) = - (code & 63u | tag_cont) as u8; + match nb { + 1u => { + *ptr::mut_offset(buf, off) = code as u8; + } + 2u => { + *ptr::mut_offset(buf, off) = (code >> 6u & 31u | tag_two_b) as u8; + *ptr::mut_offset(buf, off + 1u) = (code & 63u | tag_cont) as u8; + } + 3u => { + *ptr::mut_offset(buf, off) = (code >> 12u & 15u | tag_three_b) as u8; + *ptr::mut_offset(buf, off + 1u) = (code >> 6u & 63u | tag_cont) as u8; + *ptr::mut_offset(buf, off + 2u) = (code & 63u | tag_cont) as u8; + } + 4u => { + *ptr::mut_offset(buf, off) = (code >> 18u & 7u | tag_four_b) as u8; + *ptr::mut_offset(buf, off + 1u) = (code >> 12u & 63u | tag_cont) as u8; + *ptr::mut_offset(buf, off + 2u) = (code >> 6u & 63u | tag_cont) as u8; + *ptr::mut_offset(buf, off + 3u) = (code & 63u | tag_cont) as u8; + } + 5u => { + *ptr::mut_offset(buf, off) = (code >> 24u & 3u | tag_five_b) as u8; + *ptr::mut_offset(buf, off + 1u) = (code >> 18u & 63u | tag_cont) as u8; + *ptr::mut_offset(buf, off + 2u) = (code >> 12u & 63u | tag_cont) as u8; + *ptr::mut_offset(buf, off + 3u) = (code >> 6u & 63u | tag_cont) as u8; + *ptr::mut_offset(buf, off + 4u) = (code & 63u | tag_cont) as u8; + } + 6u => { + *ptr::mut_offset(buf, off) = (code >> 30u & 1u | tag_six_b) as u8; + *ptr::mut_offset(buf, off + 1u) = (code >> 24u & 63u | tag_cont) as u8; + *ptr::mut_offset(buf, off + 2u) = (code >> 18u & 63u | tag_cont) as u8; + *ptr::mut_offset(buf, off + 3u) = (code >> 12u & 63u | tag_cont) as u8; + *ptr::mut_offset(buf, off + 4u) = (code >> 6u & 63u | tag_cont) as u8; + *ptr::mut_offset(buf, off + 5u) = (code & 63u | tag_cont) as u8; + } + _ => {} } } - raw::set_len(s, new_len); } } @@ -245,110 +241,165 @@ pub fn append(lhs: ~str, rhs: &str) -> ~str { } /// Concatenate a vector of strings -pub fn concat(v: &[~str]) -> ~str { - if v.is_empty() { return ~""; } - - let mut len = 0; - for v.each |ss| { - len += ss.len(); - } - let mut s = ~""; +pub fn concat(v: &[~str]) -> ~str { v.concat() } - reserve(&mut s, len); +/// Concatenate a vector of strings +pub fn concat_slices(v: &[&str]) -> ~str { v.concat() } - unsafe { - do as_buf(s) |buf, _len| { - let mut buf = ::cast::transmute_mut_unsafe(buf); - for v.each |ss| { - do as_buf(*ss) |ssbuf, sslen| { - let sslen = sslen - 1; - ptr::copy_memory(buf, ssbuf, sslen); - buf = buf.offset(sslen); - } - } - } - raw::set_len(&mut s, len); - } - s -} +/// Concatenate a vector of strings, placing a given separator between each +pub fn connect(v: &[~str], sep: &str) -> ~str { v.connect(sep) } /// Concatenate a vector of strings, placing a given separator between each -pub fn connect(v: &[~str], sep: &str) -> ~str { - if v.is_empty() { return ~""; } +pub fn connect_slices(v: &[&str], sep: &str) -> ~str { v.connect(sep) } - // concat is faster - if sep.is_empty() { return concat(v); } +#[allow(missing_doc)] +pub trait StrVector { + pub fn concat(&self) -> ~str; + pub fn connect(&self, sep: &str) -> ~str; +} - // this is wrong without the guarantee that v is non-empty - let mut len = sep.len() * (v.len() - 1); - for v.each |ss| { - len += ss.len(); - } - let mut s = ~"", first = true; +impl<'self> StrVector for &'self [~str] { + /// Concatenate a vector of strings. + pub fn concat(&self) -> ~str { + if self.is_empty() { return ~""; } - reserve(&mut s, len); + let mut len = 0; + for self.each |ss| { + len += ss.len(); + } + let mut s = ~""; - unsafe { - do as_buf(s) |buf, _len| { - do as_buf(sep) |sepbuf, seplen| { - let seplen = seplen - 1; + reserve(&mut s, len); + + unsafe { + do as_buf(s) |buf, _| { let mut buf = ::cast::transmute_mut_unsafe(buf); - for v.each |ss| { + for self.each |ss| { do as_buf(*ss) |ssbuf, sslen| { let sslen = sslen - 1; - if first { - first = false; - } else { - ptr::copy_memory(buf, sepbuf, seplen); - buf = buf.offset(seplen); - } ptr::copy_memory(buf, ssbuf, sslen); buf = buf.offset(sslen); } } } + raw::set_len(&mut s, len); } - raw::set_len(&mut s, len); + s } - s -} -/// Concatenate a vector of strings, placing a given separator between each -pub fn connect_slices(v: &[&str], sep: &str) -> ~str { - if v.is_empty() { return ~""; } + /// Concatenate a vector of strings, placing a given separator between each. + pub fn connect(&self, sep: &str) -> ~str { + if self.is_empty() { return ~""; } + + // concat is faster + if sep.is_empty() { return self.concat(); } + + // this is wrong without the guarantee that `self` is non-empty + let mut len = sep.len() * (self.len() - 1); + for self.each |ss| { + len += ss.len(); + } + let mut s = ~""; + let mut first = true; + + reserve(&mut s, len); - // this is wrong without the guarantee that v is non-empty - let mut len = sep.len() * (v.len() - 1); - for v.each |ss| { - len += ss.len(); + unsafe { + do as_buf(s) |buf, _| { + do as_buf(sep) |sepbuf, seplen| { + let seplen = seplen - 1; + let mut buf = ::cast::transmute_mut_unsafe(buf); + for self.each |ss| { + do as_buf(*ss) |ssbuf, sslen| { + let sslen = sslen - 1; + if first { + first = false; + } else { + ptr::copy_memory(buf, sepbuf, seplen); + buf = buf.offset(seplen); + } + ptr::copy_memory(buf, ssbuf, sslen); + buf = buf.offset(sslen); + } + } + } + } + raw::set_len(&mut s, len); + } + s } - let mut s = ~"", first = true; +} - reserve(&mut s, len); +impl<'self> StrVector for &'self [&'self str] { + /// Concatenate a vector of strings. + pub fn concat(&self) -> ~str { + if self.is_empty() { return ~""; } - unsafe { - do as_buf(s) |buf, _len| { - do as_buf(sep) |sepbuf, seplen| { - let seplen = seplen - 1; + let mut len = 0; + for self.each |ss| { + len += ss.len(); + } + let mut s = ~""; + + reserve(&mut s, len); + + unsafe { + do as_buf(s) |buf, _| { let mut buf = ::cast::transmute_mut_unsafe(buf); - for v.each |ss| { + for self.each |ss| { do as_buf(*ss) |ssbuf, sslen| { let sslen = sslen - 1; - if first { - first = false; - } else if seplen > 0 { - ptr::copy_memory(buf, sepbuf, seplen); - buf = buf.offset(seplen); - } ptr::copy_memory(buf, ssbuf, sslen); buf = buf.offset(sslen); } } } + raw::set_len(&mut s, len); + } + s + } + + /// Concatenate a vector of strings, placing a given separator between each. + pub fn connect(&self, sep: &str) -> ~str { + if self.is_empty() { return ~""; } + + // concat is faster + if sep.is_empty() { return self.concat(); } + + // this is wrong without the guarantee that `self` is non-empty + let mut len = sep.len() * (self.len() - 1); + for self.each |ss| { + len += ss.len(); + } + let mut s = ~""; + let mut first = true; + + reserve(&mut s, len); + + unsafe { + do as_buf(s) |buf, _| { + do as_buf(sep) |sepbuf, seplen| { + let seplen = seplen - 1; + let mut buf = ::cast::transmute_mut_unsafe(buf); + for self.each |ss| { + do as_buf(*ss) |ssbuf, sslen| { + let sslen = sslen - 1; + if first { + first = false; + } else { + ptr::copy_memory(buf, sepbuf, seplen); + buf = buf.offset(seplen); + } + ptr::copy_memory(buf, ssbuf, sslen); + buf = buf.offset(sslen); + } + } + } + } + raw::set_len(&mut s, len); } - raw::set_len(&mut s, len); + s } - s } /// Given a string, make a new string with repeated copies of it @@ -571,27 +622,12 @@ pub fn slice<'a>(s: &'a str, begin: uint, end: uint) -> &'a str { } /// Splits a string into substrings at each occurrence of a given character -#[cfg(stage0)] -pub fn each_split_char<'a>(s: &'a str, sep: char, it: &fn(&'a str) -> bool) { - each_split_char_inner(s, sep, len(s), true, true, it); -} - -/// Splits a string into substrings at each occurrence of a given character -#[cfg(not(stage0))] pub fn each_split_char<'a>(s: &'a str, sep: char, it: &fn(&'a str) -> bool) -> bool { each_split_char_inner(s, sep, len(s), true, true, it) } /// Like `each_split_char`, but a trailing empty string is omitted -#[cfg(stage0)] -pub fn each_split_char_no_trailing<'a>(s: &'a str, - sep: char, - it: &fn(&'a str) -> bool) { - each_split_char_inner(s, sep, len(s), true, false, it); -} -/// Like `each_split_char`, but a trailing empty string is omitted -#[cfg(not(stage0))] pub fn each_split_char_no_trailing<'a>(s: &'a str, sep: char, it: &fn(&'a str) -> bool) -> bool { @@ -604,20 +640,6 @@ pub fn each_split_char_no_trailing<'a>(s: &'a str, * * The character must be a valid UTF-8/ASCII character */ -#[cfg(stage0)] -pub fn each_splitn_char<'a>(s: &'a str, - sep: char, - count: uint, - it: &fn(&'a str) -> bool) { - each_split_char_inner(s, sep, count, true, true, it); -} -/** - * Splits a string into substrings at each occurrence of a given - * character up to 'count' times. - * - * The character must be a valid UTF-8/ASCII character - */ -#[cfg(not(stage0))] pub fn each_splitn_char<'a>(s: &'a str, sep: char, count: uint, @@ -626,14 +648,6 @@ pub fn each_splitn_char<'a>(s: &'a str, } /// Like `each_split_char`, but omits empty strings -#[cfg(stage0)] -pub fn each_split_char_nonempty<'a>(s: &'a str, - sep: char, - it: &fn(&'a str) -> bool) { - each_split_char_inner(s, sep, len(s), false, false, it); -} -/// Like `each_split_char`, but omits empty strings -#[cfg(not(stage0))] pub fn each_split_char_nonempty<'a>(s: &'a str, sep: char, it: &fn(&'a str) -> bool) -> bool { @@ -647,9 +661,9 @@ fn each_split_char_inner<'a>(s: &'a str, allow_trailing_empty: bool, it: &fn(&'a str) -> bool) -> bool { if sep < 128u as char { - let b = sep as u8, l = len(s); + let (b, l) = (sep as u8, len(s)); let mut done = 0u; - let mut i = 0u, start = 0u; + let mut (i, start) = (0u, 0u); while i < l && done < count { if s[i] == b { if allow_empty || start < i { @@ -673,14 +687,6 @@ fn each_split_char_inner<'a>(s: &'a str, } /// Splits a string into substrings using a character function -#[cfg(stage0)] -pub fn each_split<'a>(s: &'a str, - sepfn: &fn(char) -> bool, - it: &fn(&'a str) -> bool) { - each_split_inner(s, sepfn, len(s), true, true, it); -} -/// Splits a string into substrings using a character function -#[cfg(not(stage0))] pub fn each_split<'a>(s: &'a str, sepfn: &fn(char) -> bool, it: &fn(&'a str) -> bool) -> bool { @@ -688,14 +694,6 @@ pub fn each_split<'a>(s: &'a str, } /// Like `each_split`, but a trailing empty string is omitted -#[cfg(stage0)] -pub fn each_split_no_trailing<'a>(s: &'a str, - sepfn: &fn(char) -> bool, - it: &fn(&'a str) -> bool) { - each_split_inner(s, sepfn, len(s), true, false, it); -} -/// Like `each_split`, but a trailing empty string is omitted -#[cfg(not(stage0))] pub fn each_split_no_trailing<'a>(s: &'a str, sepfn: &fn(char) -> bool, it: &fn(&'a str) -> bool) -> bool { @@ -706,18 +704,6 @@ pub fn each_split_no_trailing<'a>(s: &'a str, * Splits a string into substrings using a character function, cutting at * most `count` times. */ -#[cfg(stage0)] -pub fn each_splitn<'a>(s: &'a str, - sepfn: &fn(char) -> bool, - count: uint, - it: &fn(&'a str) -> bool) { - each_split_inner(s, sepfn, count, true, true, it); -} -/** - * Splits a string into substrings using a character function, cutting at - * most `count` times. - */ -#[cfg(not(stage0))] pub fn each_splitn<'a>(s: &'a str, sepfn: &fn(char) -> bool, count: uint, @@ -726,14 +712,6 @@ pub fn each_splitn<'a>(s: &'a str, } /// Like `each_split`, but omits empty strings -#[cfg(stage0)] -pub fn each_split_nonempty<'a>(s: &'a str, - sepfn: &fn(char) -> bool, - it: &fn(&'a str) -> bool) { - each_split_inner(s, sepfn, len(s), false, false, it); -} -/// Like `each_split`, but omits empty strings -#[cfg(not(stage0))] pub fn each_split_nonempty<'a>(s: &'a str, sepfn: &fn(char) -> bool, it: &fn(&'a str) -> bool) -> bool { @@ -747,7 +725,7 @@ fn each_split_inner<'a>(s: &'a str, allow_trailing_empty: bool, it: &fn(&'a str) -> bool) -> bool { let l = len(s); - let mut i = 0u, start = 0u, done = 0u; + let mut (i, start, done) = (0u, 0u, 0u); while i < l && done < count { let CharRange {ch, next} = char_range_at(s, i); if sepfn(ch) { @@ -768,41 +746,11 @@ fn each_split_inner<'a>(s: &'a str, } // See Issue #1932 for why this is a naive search -#[cfg(stage0)] -fn iter_matches<'a,'b>(s: &'a str, sep: &'b str, - f: &fn(uint, uint) -> bool) { - let sep_len = len(sep), l = len(s); - assert!(sep_len > 0u); - let mut i = 0u, match_start = 0u, match_i = 0u; - - while i < l { - if s[i] == sep[match_i] { - if match_i == 0u { match_start = i; } - match_i += 1u; - // Found a match - if match_i == sep_len { - if !f(match_start, i + 1u) { return; } - match_i = 0u; - } - i += 1u; - } else { - // Failed match, backtrack - if match_i > 0u { - match_i = 0u; - i = match_start + 1u; - } else { - i += 1u; - } - } - } -} -// See Issue #1932 for why this is a naive search -#[cfg(not(stage0))] fn iter_matches<'a,'b>(s: &'a str, sep: &'b str, f: &fn(uint, uint) -> bool) -> bool { - let sep_len = len(sep), l = len(s); + let (sep_len, l) = (len(sep), len(s)); assert!(sep_len > 0u); - let mut i = 0u, match_start = 0u, match_i = 0u; + let mut (i, match_start, match_i) = (0u, 0u, 0u); while i < l { if s[i] == sep[match_i] { @@ -827,18 +775,6 @@ fn iter_matches<'a,'b>(s: &'a str, sep: &'b str, return true; } -#[cfg(stage0)] -fn iter_between_matches<'a,'b>(s: &'a str, - sep: &'b str, - f: &fn(uint, uint) -> bool) { - let mut last_end = 0u; - for iter_matches(s, sep) |from, to| { - if !f(last_end, from) { return; } - last_end = to; - } - f(last_end, len(s)); -} -#[cfg(not(stage0))] fn iter_between_matches<'a,'b>(s: &'a str, sep: &'b str, f: &fn(uint, uint) -> bool) -> bool { @@ -855,53 +791,33 @@ fn iter_between_matches<'a,'b>(s: &'a str, * * # Example * - * ~~~ + * ~~~ {.rust} * let mut v = ~[]; * for each_split_str(".XXX.YYY.", ".") |subs| { v.push(subs); } * assert!(v == ["", "XXX", "YYY", ""]); * ~~~ */ -#[cfg(stage0)] pub fn each_split_str<'a,'b>(s: &'a str, sep: &'b str, - it: &fn(&'a str) -> bool) { + it: &fn(&'a str) -> bool) -> bool { for iter_between_matches(s, sep) |from, to| { - if !it( unsafe { raw::slice_bytes(s, from, to) } ) { return; } + if !it( unsafe { raw::slice_bytes(s, from, to) } ) { return false; } } + return true; } + /** - * Splits a string into a vector of the substrings separated by a given string + * Splits the string `s` based on `sep`, yielding all splits to the iterator + * function provide * * # Example * - * ~~~ + * ~~~ {.rust} * let mut v = ~[]; * for each_split_str(".XXX.YYY.", ".") |subs| { v.push(subs); } - * assert!(v == ["", "XXX", "YYY", ""]); + * assert!(v == ["XXX", "YYY"]); * ~~~ */ -#[cfg(not(stage0))] -pub fn each_split_str<'a,'b>(s: &'a str, - sep: &'b str, - it: &fn(&'a str) -> bool) -> bool { - for iter_between_matches(s, sep) |from, to| { - if !it( unsafe { raw::slice_bytes(s, from, to) } ) { return false; } - } - return true; -} - -#[cfg(stage0)] -pub fn each_split_str_nonempty<'a,'b>(s: &'a str, - sep: &'b str, - it: &fn(&'a str) -> bool) { - for iter_between_matches(s, sep) |from, to| { - if to > from { - if !it( unsafe { raw::slice_bytes(s, from, to) } ) { return; } - } - } -} - -#[cfg(not(stage0))] pub fn each_split_str_nonempty<'a,'b>(s: &'a str, sep: &'b str, it: &fn(&'a str) -> bool) -> bool { @@ -950,14 +866,6 @@ pub fn levdistance(s: &str, t: &str) -> uint { /** * Splits a string into substrings separated by LF ('\n'). */ -#[cfg(stage0)] -pub fn each_line<'a>(s: &'a str, it: &fn(&'a str) -> bool) { - each_split_char_no_trailing(s, '\n', it); -} -/** - * Splits a string into substrings separated by LF ('\n'). - */ -#[cfg(not(stage0))] pub fn each_line<'a>(s: &'a str, it: &fn(&'a str) -> bool) -> bool { each_split_char_no_trailing(s, '\n', it) } @@ -966,22 +874,6 @@ pub fn each_line<'a>(s: &'a str, it: &fn(&'a str) -> bool) -> bool { * Splits a string into substrings separated by LF ('\n') * and/or CR LF ("\r\n") */ -#[cfg(stage0)] -pub fn each_line_any<'a>(s: &'a str, it: &fn(&'a str) -> bool) { - for each_line(s) |s| { - let l = s.len(); - if l > 0u && s[l - 1u] == '\r' as u8 { - if !it( unsafe { raw::slice_bytes(s, 0, l - 1) } ) { return; } - } else { - if !it( s ) { return; } - } - } -} -/** - * Splits a string into substrings separated by LF ('\n') - * and/or CR LF ("\r\n") - */ -#[cfg(not(stage0))] pub fn each_line_any<'a>(s: &'a str, it: &fn(&'a str) -> bool) -> bool { for each_line(s) |s| { let l = s.len(); @@ -995,12 +887,6 @@ pub fn each_line_any<'a>(s: &'a str, it: &fn(&'a str) -> bool) -> bool { } /// Splits a string into substrings separated by whitespace -#[cfg(stage0)] -pub fn each_word<'a>(s: &'a str, it: &fn(&'a str) -> bool) { - each_split_nonempty(s, char::is_whitespace, it); -} -/// Splits a string into substrings separated by whitespace -#[cfg(not(stage0))] pub fn each_word<'a>(s: &'a str, it: &fn(&'a str) -> bool) -> bool { each_split_nonempty(s, char::is_whitespace, it) } @@ -1014,7 +900,7 @@ pub fn each_word<'a>(s: &'a str, it: &fn(&'a str) -> bool) -> bool { * Fails during iteration if the string contains a non-whitespace * sequence longer than the limit. */ -pub fn _each_split_within<'a>(ss: &'a str, +pub fn each_split_within<'a>(ss: &'a str, lim: uint, it: &fn(&'a str) -> bool) -> bool { // Just for fun, let's write this as an state machine: @@ -1077,19 +963,6 @@ pub fn _each_split_within<'a>(ss: &'a str, return cont; } -#[cfg(stage0)] -pub fn each_split_within<'a>(ss: &'a str, - lim: uint, - it: &fn(&'a str) -> bool) { - _each_split_within(ss, lim, it); -} -#[cfg(not(stage0))] -pub fn each_split_within<'a>(ss: &'a str, - lim: uint, - it: &fn(&'a str) -> bool) -> bool { - _each_split_within(ss, lim, it) -} - /** * Replace all occurrences of one string with another * @@ -1104,7 +977,7 @@ pub fn each_split_within<'a>(ss: &'a str, * The original string with all occurances of `from` replaced with `to` */ pub fn replace(s: &str, from: &str, to: &str) -> ~str { - let mut result = ~"", first = true; + let mut (result, first) = (~"", true); for iter_between_matches(s, from) |start, end| { if first { first = false; @@ -1366,33 +1239,12 @@ pub fn map(ss: &str, ff: &fn(char) -> char) -> ~str { /// Iterate over the bytes in a string #[inline(always)] -#[cfg(stage0)] -pub fn each(s: &str, it: &fn(u8) -> bool) { - eachi(s, |_i, b| it(b)) -} -/// Iterate over the bytes in a string -#[inline(always)] -#[cfg(not(stage0))] pub fn each(s: &str, it: &fn(u8) -> bool) -> bool { eachi(s, |_i, b| it(b)) } /// Iterate over the bytes in a string, with indices #[inline(always)] -#[cfg(stage0)] -pub fn eachi(s: &str, it: &fn(uint, u8) -> bool) { - let mut pos = 0; - let len = s.len(); - - while pos < len { - if !it(pos, s[pos]) { break; } - pos += 1; - } -} - -/// Iterate over the bytes in a string, with indices -#[inline(always)] -#[cfg(not(stage0))] pub fn eachi(s: &str, it: &fn(uint, u8) -> bool) -> bool { let mut pos = 0; let len = s.len(); @@ -1406,30 +1258,12 @@ pub fn eachi(s: &str, it: &fn(uint, u8) -> bool) -> bool { /// Iterate over the bytes in a string in reverse #[inline(always)] -#[cfg(stage0)] -pub fn each_reverse(s: &str, it: &fn(u8) -> bool) { - eachi_reverse(s, |_i, b| it(b) ) -} -/// Iterate over the bytes in a string in reverse -#[inline(always)] -#[cfg(not(stage0))] pub fn each_reverse(s: &str, it: &fn(u8) -> bool) -> bool { eachi_reverse(s, |_i, b| it(b) ) } /// Iterate over the bytes in a string in reverse, with indices #[inline(always)] -#[cfg(stage0)] -pub fn eachi_reverse(s: &str, it: &fn(uint, u8) -> bool) { - let mut pos = s.len(); - while pos > 0 { - pos -= 1; - if !it(pos, s[pos]) { break; } - } -} -/// Iterate over the bytes in a string in reverse, with indices -#[inline(always)] -#[cfg(not(stage0))] pub fn eachi_reverse(s: &str, it: &fn(uint, u8) -> bool) -> bool { let mut pos = s.len(); while pos > 0 { @@ -1441,19 +1275,6 @@ pub fn eachi_reverse(s: &str, it: &fn(uint, u8) -> bool) -> bool { /// Iterate over each char of a string, without allocating #[inline(always)] -#[cfg(stage0)] -pub fn each_char(s: &str, it: &fn(char) -> bool) { - let mut i = 0; - let len = len(s); - while i < len { - let CharRange {ch, next} = char_range_at(s, i); - if !it(ch) { return; } - i = next; - } -} -/// Iterate over each char of a string, without allocating -#[inline(always)] -#[cfg(not(stage0))] pub fn each_char(s: &str, it: &fn(char) -> bool) -> bool { let mut i = 0; let len = len(s); @@ -1467,21 +1288,6 @@ pub fn each_char(s: &str, it: &fn(char) -> bool) -> bool { /// Iterates over the chars in a string, with indices #[inline(always)] -#[cfg(stage0)] -pub fn each_chari(s: &str, it: &fn(uint, char) -> bool) { - let mut pos = 0; - let mut ch_pos = 0u; - let len = s.len(); - while pos < len { - let CharRange {ch, next} = char_range_at(s, pos); - pos = next; - if !it(ch_pos, ch) { break; } - ch_pos += 1u; - } -} -/// Iterates over the chars in a string, with indices -#[inline(always)] -#[cfg(not(stage0))] pub fn each_chari(s: &str, it: &fn(uint, char) -> bool) -> bool { let mut pos = 0; let mut ch_pos = 0u; @@ -1497,35 +1303,12 @@ pub fn each_chari(s: &str, it: &fn(uint, char) -> bool) -> bool { /// Iterates over the chars in a string in reverse #[inline(always)] -#[cfg(stage0)] -pub fn each_char_reverse(s: &str, it: &fn(char) -> bool) { - each_chari_reverse(s, |_, c| it(c)) -} -/// Iterates over the chars in a string in reverse -#[inline(always)] -#[cfg(not(stage0))] pub fn each_char_reverse(s: &str, it: &fn(char) -> bool) -> bool { each_chari_reverse(s, |_, c| it(c)) } -// Iterates over the chars in a string in reverse, with indices -#[inline(always)] -#[cfg(stage0)] -pub fn each_chari_reverse(s: &str, it: &fn(uint, char) -> bool) { - let mut pos = s.len(); - let mut ch_pos = s.char_len(); - while pos > 0 { - let CharRange {ch, next} = char_range_at_reverse(s, pos); - pos = next; - ch_pos -= 1; - - if !it(ch_pos, ch) { break; } - - } -} -// Iterates over the chars in a string in reverse, with indices +/// Iterates over the chars in a string in reverse, with indices #[inline(always)] -#[cfg(not(stage0))] pub fn each_chari_reverse(s: &str, it: &fn(uint, char) -> bool) -> bool { let mut pos = s.len(); let mut ch_pos = s.char_len(); @@ -1978,7 +1761,7 @@ pub fn contains_char(haystack: &str, needle: char) -> bool { * * needle - The string to look for */ pub fn starts_with<'a,'b>(haystack: &'a str, needle: &'b str) -> bool { - let haystack_len = len(haystack), needle_len = len(needle); + let (haystack_len, needle_len) = (len(haystack), len(needle)); if needle_len == 0u { true } else if needle_len > haystack_len { false } else { match_at(haystack, needle, 0u) } @@ -1993,7 +1776,7 @@ pub fn starts_with<'a,'b>(haystack: &'a str, needle: &'b str) -> bool { * * needle - The string to look for */ pub fn ends_with<'a,'b>(haystack: &'a str, needle: &'b str) -> bool { - let haystack_len = len(haystack), needle_len = len(needle); + let (haystack_len, needle_len) = (len(haystack), len(needle)); if needle_len == 0u { true } else if needle_len > haystack_len { false } else { match_at(haystack, needle, haystack_len - needle_len) } @@ -2096,12 +1879,18 @@ pub fn to_utf16(s: &str) -> ~[u16] { ch -= 0x1_0000_u32; let w1 = 0xD800_u16 | ((ch >> 10) as u16); let w2 = 0xDC00_u16 | ((ch as u16) & 0x3FF_u16); - u.push_all(~[w1, w2]) + u.push_all([w1, w2]) } } u } +/// Iterates over the utf-16 characters in the specified slice, yielding each +/// decoded unicode character to the function provided. +/// +/// # Failures +/// +/// * Fails on invalid utf-16 data pub fn utf16_chars(v: &[u16], f: &fn(char)) { let len = v.len(); let mut i = 0u; @@ -2126,6 +1915,9 @@ pub fn utf16_chars(v: &[u16], f: &fn(char)) { } } +/** + * Allocates a new string from the utf-16 slice provided + */ pub fn from_utf16(v: &[u16]) -> ~str { let mut buf = ~""; reserve(&mut buf, v.len()); @@ -2133,6 +1925,10 @@ pub fn from_utf16(v: &[u16]) -> ~str { buf } +/** + * Allocates a new string with the specified capacity. The string returned is + * the empty string, but has capacity for much more. + */ pub fn with_capacity(capacity: uint) -> ~str { let mut buf = ~""; reserve(&mut buf, capacity); @@ -2155,7 +1951,7 @@ pub fn with_capacity(capacity: uint) -> ~str { pub 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; + let mut (i, len) = (start, 0u); while i < end { let next = char_range_at(s, i).next; len += 1u; @@ -2168,7 +1964,7 @@ pub fn count_chars(s: &str, start: uint, end: uint) -> uint { /// starting from `start`. pub fn count_bytes<'b>(s: &'b str, start: uint, n: uint) -> uint { assert!(is_char_boundary(s, start)); - let mut end = start, cnt = n; + let mut (end, cnt) = (start, n); let l = len(s); while cnt > 0u { assert!(end < l); @@ -2211,7 +2007,7 @@ pub fn is_char_boundary(s: &str, index: uint) -> bool { * * # Example * - * ~~~ + * ~~~ {.rust} * let s = "中华Việt Nam"; * let i = 0u; * while i < str::len(s) { @@ -2261,7 +2057,7 @@ pub fn char_range_at(s: &str, i: uint) -> CharRange { let mut i = i + 1u; while i < end { let byte = s[i]; - assert!((byte & 192u8 == tag_cont_u8)); + assert_eq!(byte & 192u8, tag_cont_u8); val <<= 6u; val += (byte & 63u8) as uint; i += 1u; @@ -2278,6 +2074,7 @@ pub fn char_at(s: &str, i: uint) -> char { return char_range_at(s, i).ch; } +#[allow(missing_doc)] pub struct CharRange { ch: char, next: uint @@ -2397,7 +2194,7 @@ static tag_six_b: uint = 252u; * * # Example * - * ~~~ + * ~~~ {.rust} * let i = str::as_bytes("Hello World") { |bytes| bytes.len() }; * ~~~ */ @@ -2423,33 +2220,50 @@ pub fn as_bytes_slice<'a>(s: &'a str) -> &'a [u8] { } /** - * Work with the byte buffer of a string as a null-terminated C string. - * - * Allows for unsafe manipulation of strings, which is useful for foreign - * interop. This is similar to `str::as_buf`, but guarantees null-termination. - * If the given slice is not already null-terminated, this function will - * allocate a temporary, copy the slice, null terminate it, and pass - * that instead. - * - * # Example - * - * ~~~ - * let s = str::as_c_str("PATH", { |path| libc::getenv(path) }); - * ~~~ + * A dummy trait to hold all the utility methods that we implement on strings. */ -#[inline] -pub fn as_c_str(s: &str, f: &fn(*libc::c_char) -> T) -> T { - do as_buf(s) |buf, len| { - // NB: len includes the trailing null. - assert!(len > 0); - if unsafe { *(ptr::offset(buf,len-1)) != 0 } { - as_c_str(to_owned(s), f) - } else { - f(buf as *libc::c_char) +pub trait StrUtil { + /** + * Work with the byte buffer of a string as a null-terminated C string. + * + * Allows for unsafe manipulation of strings, which is useful for foreign + * interop. This is similar to `str::as_buf`, but guarantees null-termination. + * If the given slice is not already null-terminated, this function will + * allocate a temporary, copy the slice, null terminate it, and pass + * that instead. + * + * # Example + * + * ~~~ {.rust} + * let s = "PATH".as_c_str(|path| libc::getenv(path)); + * ~~~ + */ + fn as_c_str(self, f: &fn(*libc::c_char) -> T) -> T; +} + +impl<'self> StrUtil for &'self str { + #[inline] + fn as_c_str(self, f: &fn(*libc::c_char) -> T) -> T { + do as_buf(self) |buf, len| { + // NB: len includes the trailing null. + assert!(len > 0); + if unsafe { *(ptr::offset(buf,len-1)) != 0 } { + to_owned(self).as_c_str(f) + } else { + f(buf as *libc::c_char) + } } } } +/** + * Deprecated. Use the `as_c_str` method on strings instead. + */ +#[inline(always)] +pub fn as_c_str(s: &str, f: &fn(*libc::c_char) -> T) -> T { + s.as_c_str(f) +} + /** * Work with the byte buffer and length of a slice. * @@ -2472,7 +2286,7 @@ pub fn as_buf(s: &str, f: &fn(*u8, uint) -> T) -> T { * * # Example * - * ~~~ + * ~~~ {.rust} * let string = "a\nb\nc"; * let mut lines = ~[]; * for each_line(string) |line| { lines.push(line) } @@ -2486,7 +2300,10 @@ pub fn as_buf(s: &str, f: &fn(*u8, uint) -> T) -> T { pub fn subslice_offset(outer: &str, inner: &str) -> uint { do as_buf(outer) |a, a_len| { do as_buf(inner) |b, b_len| { - let a_start: uint, a_end: uint, b_start: uint, b_end: uint; + let a_start: uint; + let a_end: uint; + let b_start: uint; + let b_end: uint; unsafe { a_start = cast::transmute(a); a_end = a_len + cast::transmute(a); b_start = cast::transmute(b); b_end = b_len + cast::transmute(b); @@ -2590,7 +2407,7 @@ pub mod raw { /// Create a Rust string from a null-terminated *u8 buffer pub unsafe fn from_buf(buf: *u8) -> ~str { - let mut curr = buf, i = 0u; + let mut (curr, i) = (buf, 0u); while *curr != 0u8 { i += 1u; curr = ptr::offset(buf, i); @@ -2747,7 +2564,7 @@ pub mod raw { let a = ~[65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 0u8]; let b = vec::raw::to_ptr(a); let c = from_buf_len(b, 3u); - assert!((c == ~"AAA")); + assert_eq!(c, ~"AAA"); } } @@ -2769,28 +2586,21 @@ pub mod traits { #[cfg(test)] pub mod traits {} +#[allow(missing_doc)] pub trait StrSlice<'self> { fn all(&self, it: &fn(char) -> bool) -> bool; fn any(&self, it: &fn(char) -> bool) -> bool; fn contains<'a>(&self, needle: &'a str) -> bool; fn contains_char(&self, needle: char) -> bool; fn char_iter(&self) -> StrCharIterator<'self>; - #[cfg(stage0)] fn each(&self, it: &fn(u8) -> bool); - #[cfg(not(stage0))] fn each(&self, it: &fn(u8) -> bool) -> bool; - #[cfg(stage0)] fn eachi(&self, it: &fn(uint, u8) -> bool); - #[cfg(not(stage0))] fn eachi(&self, it: &fn(uint, u8) -> bool) -> bool; - #[cfg(stage0)] fn each_reverse(&self, it: &fn(u8) -> bool); - #[cfg(not(stage0))] fn each_reverse(&self, it: &fn(u8) -> bool) -> bool; - #[cfg(stage0)] fn eachi_reverse(&self, it: &fn(uint, u8) -> bool); - #[cfg(not(stage0))] fn eachi_reverse(&self, it: &fn(uint, u8) -> bool) -> bool; - #[cfg(stage0)] fn each_char(&self, it: &fn(char) -> bool); - #[cfg(not(stage0))] fn each_char(&self, it: &fn(char) -> bool) -> bool; - #[cfg(stage0)] fn each_chari(&self, it: &fn(uint, char) -> bool); - #[cfg(not(stage0))] fn each_chari(&self, it: &fn(uint, char) -> bool) -> bool; - #[cfg(stage0)] fn each_char_reverse(&self, it: &fn(char) -> bool); - #[cfg(not(stage0))] fn each_char_reverse(&self, it: &fn(char) -> bool) -> bool; - #[cfg(stage0)] fn each_chari_reverse(&self, it: &fn(uint, char) -> bool); - #[cfg(not(stage0))] fn each_chari_reverse(&self, it: &fn(uint, char) -> bool) -> bool; + fn each(&self, it: &fn(u8) -> bool) -> bool; + fn eachi(&self, it: &fn(uint, u8) -> bool) -> bool; + fn each_reverse(&self, it: &fn(u8) -> bool) -> bool; + fn eachi_reverse(&self, it: &fn(uint, u8) -> bool) -> bool; + fn each_char(&self, it: &fn(char) -> bool) -> bool; + fn each_chari(&self, it: &fn(uint, char) -> bool) -> bool; + fn each_char_reverse(&self, it: &fn(char) -> bool) -> bool; + fn each_chari_reverse(&self, it: &fn(uint, char) -> bool) -> bool; fn ends_with(&self, needle: &str) -> bool; fn is_empty(&self) -> bool; fn is_whitespace(&self) -> bool; @@ -2798,17 +2608,8 @@ pub trait StrSlice<'self> { fn len(&self) -> uint; fn char_len(&self) -> uint; fn slice(&self, begin: uint, end: uint) -> &'self str; - #[cfg(stage0)] - fn each_split(&self, sepfn: &fn(char) -> bool, it: &fn(&'self str) -> bool); - #[cfg(not(stage0))] fn each_split(&self, sepfn: &fn(char) -> bool, it: &fn(&'self str) -> bool) -> bool; - #[cfg(stage0)] - fn each_split_char(&self, sep: char, it: &fn(&'self str) -> bool); - #[cfg(not(stage0))] fn each_split_char(&self, sep: char, it: &fn(&'self str) -> bool) -> bool; - #[cfg(stage0)] - fn each_split_str<'a>(&self, sep: &'a str, it: &fn(&'self str) -> bool); - #[cfg(not(stage0))] fn each_split_str<'a>(&self, sep: &'a str, it: &fn(&'self str) -> bool) -> bool; fn starts_with<'a>(&self, needle: &'a str) -> bool; fn substr(&self, begin: uint, n: uint) -> &'self str; @@ -2862,83 +2663,34 @@ impl<'self> StrSlice<'self> for &'self str { /// Iterate over the bytes in a string #[inline] - #[cfg(stage0)] - fn each(&self, it: &fn(u8) -> bool) { each(*self, it) } - /// Iterate over the bytes in a string - #[inline] - #[cfg(not(stage0))] fn each(&self, it: &fn(u8) -> bool) -> bool { each(*self, it) } /// Iterate over the bytes in a string, with indices #[inline] - #[cfg(stage0)] - fn eachi(&self, it: &fn(uint, u8) -> bool) { eachi(*self, it) } - /// Iterate over the bytes in a string, with indices - #[inline] - #[cfg(not(stage0))] fn eachi(&self, it: &fn(uint, u8) -> bool) -> bool { eachi(*self, it) } /// Iterate over the bytes in a string #[inline] - #[cfg(stage0)] - fn each_reverse(&self, it: &fn(u8) -> bool) { each_reverse(*self, it) } - /// Iterate over the bytes in a string - #[inline] - #[cfg(not(stage0))] fn each_reverse(&self, it: &fn(u8) -> bool) -> bool { each_reverse(*self, it) } /// Iterate over the bytes in a string, with indices #[inline] - #[cfg(stage0)] - fn eachi_reverse(&self, it: &fn(uint, u8) -> bool) { - eachi_reverse(*self, it) - } - /// Iterate over the bytes in a string, with indices - #[inline] - #[cfg(not(stage0))] fn eachi_reverse(&self, it: &fn(uint, u8) -> bool) -> bool { eachi_reverse(*self, it) } /// Iterate over the chars in a string #[inline] - #[cfg(stage0)] - fn each_char(&self, it: &fn(char) -> bool) { each_char(*self, it) } - /// Iterate over the chars in a string - #[inline] - #[cfg(not(stage0))] fn each_char(&self, it: &fn(char) -> bool) -> bool { each_char(*self, it) } /// Iterate over the chars in a string, with indices #[inline] - #[cfg(stage0)] - fn each_chari(&self, it: &fn(uint, char) -> bool) { - each_chari(*self, it) - } - /// Iterate over the chars in a string, with indices - #[inline] - #[cfg(not(stage0))] fn each_chari(&self, it: &fn(uint, char) -> bool) -> bool { each_chari(*self, it) } /// Iterate over the chars in a string in reverse #[inline] - #[cfg(stage0)] - fn each_char_reverse(&self, it: &fn(char) -> bool) { - each_char_reverse(*self, it) - } - /// Iterate over the chars in a string in reverse - #[inline] - #[cfg(not(stage0))] fn each_char_reverse(&self, it: &fn(char) -> bool) -> bool { each_char_reverse(*self, it) } /// Iterate over the chars in a string in reverse, with indices from the /// end #[inline] - #[cfg(stage0)] - fn each_chari_reverse(&self, it: &fn(uint, char) -> bool) { - each_chari_reverse(*self, it) - } - /// Iterate over the chars in a string in reverse, with indices from the - /// end - #[inline] - #[cfg(not(stage0))] fn each_chari_reverse(&self, it: &fn(uint, char) -> bool) -> bool { each_chari_reverse(*self, it) } @@ -2983,13 +2735,6 @@ impl<'self> StrSlice<'self> for &'self str { } /// Splits a string into substrings using a character function #[inline] - #[cfg(stage0)] - fn each_split(&self, sepfn: &fn(char) -> bool, it: &fn(&'self str) -> bool) { - each_split(*self, sepfn, it) - } - /// Splits a string into substrings using a character function - #[inline] - #[cfg(not(stage0))] fn each_split(&self, sepfn: &fn(char) -> bool, it: &fn(&'self str) -> bool) -> bool { each_split(*self, sepfn, it) } @@ -2997,15 +2742,6 @@ impl<'self> StrSlice<'self> for &'self str { * Splits a string into substrings at each occurrence of a given character */ #[inline] - #[cfg(stage0)] - fn each_split_char(&self, sep: char, it: &fn(&'self str) -> bool) { - each_split_char(*self, sep, it) - } - /** - * Splits a string into substrings at each occurrence of a given character - */ - #[inline] - #[cfg(not(stage0))] fn each_split_char(&self, sep: char, it: &fn(&'self str) -> bool) -> bool { each_split_char(*self, sep, it) } @@ -3014,16 +2750,6 @@ impl<'self> StrSlice<'self> for &'self str { * string */ #[inline] - #[cfg(stage0)] - fn each_split_str<'a>(&self, sep: &'a str, it: &fn(&'self str) -> bool) { - each_split_str(*self, sep, it) - } - /** - * Splits a string into a vector of the substrings separated by a given - * string - */ - #[inline] - #[cfg(not(stage0))] fn each_split_str<'a>(&self, sep: &'a str, it: &fn(&'self str) -> bool) -> bool { each_split_str(*self, sep, it) } @@ -3095,6 +2821,7 @@ impl<'self> StrSlice<'self> for &'self str { fn to_bytes(&self) -> ~[u8] { to_bytes(*self) } } +#[allow(missing_doc)] pub trait OwnedStr { fn push_str(&mut self, v: &str); fn push_char(&mut self, c: char); @@ -3118,6 +2845,8 @@ impl Clone for ~str { } } +/// External iterator for a string's characters. Use with the `std::iterator` +/// module. pub struct StrCharIterator<'self> { priv index: uint, priv string: &'self str, @@ -3174,47 +2903,47 @@ mod tests { #[test] fn test_len() { - assert!((len(~"") == 0u)); - assert!((len(~"hello world") == 11u)); - assert!((len(~"\x63") == 1u)); - assert!((len(~"\xa2") == 2u)); - assert!((len(~"\u03c0") == 2u)); - assert!((len(~"\u2620") == 3u)); - assert!((len(~"\U0001d11e") == 4u)); - - assert!((char_len(~"") == 0u)); - assert!((char_len(~"hello world") == 11u)); - assert!((char_len(~"\x63") == 1u)); - assert!((char_len(~"\xa2") == 1u)); - assert!((char_len(~"\u03c0") == 1u)); - assert!((char_len(~"\u2620") == 1u)); - assert!((char_len(~"\U0001d11e") == 1u)); - assert!((char_len(~"ประเทศไทย中华Việt Nam") == 19u)); + assert_eq!(len(""), 0u); + assert_eq!(len("hello world"), 11u); + assert_eq!(len("\x63"), 1u); + assert_eq!(len("\xa2"), 2u); + assert_eq!(len("\u03c0"), 2u); + assert_eq!(len("\u2620"), 3u); + assert_eq!(len("\U0001d11e"), 4u); + + assert_eq!(char_len(""), 0u); + assert_eq!(char_len("hello world"), 11u); + assert_eq!(char_len("\x63"), 1u); + assert_eq!(char_len("\xa2"), 1u); + assert_eq!(char_len("\u03c0"), 1u); + assert_eq!(char_len("\u2620"), 1u); + assert_eq!(char_len("\U0001d11e"), 1u); + assert_eq!(char_len("ประเทศไทย中华Việt Nam"), 19u); } #[test] fn test_rfind_char() { - assert!(rfind_char(~"hello", 'l') == Some(3u)); - assert!(rfind_char(~"hello", 'o') == Some(4u)); - assert!(rfind_char(~"hello", 'h') == Some(0u)); - assert!(rfind_char(~"hello", 'z').is_none()); - assert!(rfind_char(~"ประเทศไทย中华Việt Nam", '华') == Some(30u)); + assert_eq!(rfind_char("hello", 'l'), Some(3u)); + assert_eq!(rfind_char("hello", 'o'), Some(4u)); + assert_eq!(rfind_char("hello", 'h'), Some(0u)); + assert!(rfind_char("hello", 'z').is_none()); + assert_eq!(rfind_char("ประเทศไทย中华Việt Nam", '华'), Some(30u)); } #[test] fn test_pop_char() { let mut data = ~"ประเทศไทย中华"; let cc = pop_char(&mut data); - assert!(~"ประเทศไทย中" == data); - assert!('华' == cc); + assert_eq!(~"ประเทศไทย中", data); + assert_eq!('华', cc); } #[test] fn test_pop_char_2() { let mut data2 = ~"华"; let cc2 = pop_char(&mut data2); - assert!(~"" == data2); - assert!('华' == cc2); + assert_eq!(~"", data2); + assert_eq!('华', cc2); } #[test] @@ -3228,66 +2957,66 @@ mod tests { #[test] fn test_split_char() { fn t(s: &str, c: char, u: &[~str]) { - debug!(~"split_byte: " + s); + debug!("split_byte: %?", s); let mut v = ~[]; for each_split_char(s, c) |s| { v.push(s.to_owned()) } debug!("split_byte to: %?", v); assert!(vec::all2(v, u, |a,b| a == b)); } - t(~"abc.hello.there", '.', ~[~"abc", ~"hello", ~"there"]); - t(~".hello.there", '.', ~[~"", ~"hello", ~"there"]); - t(~"...hello.there.", '.', ~[~"", ~"", ~"", ~"hello", ~"there", ~""]); + t("abc.hello.there", '.', [~"abc", ~"hello", ~"there"]); + t(".hello.there", '.', [~"", ~"hello", ~"there"]); + t("...hello.there.", '.', [~"", ~"", ~"", ~"hello", ~"there", ~""]); - t(~"", 'z', ~[~""]); - t(~"z", 'z', ~[~"",~""]); - t(~"ok", 'z', ~[~"ok"]); + t("", 'z', [~""]); + t("z", 'z', [~"",~""]); + t("ok", 'z', [~"ok"]); } #[test] fn test_split_char_2() { fn t(s: &str, c: char, u: &[~str]) { - debug!(~"split_byte: " + s); + debug!("split_byte: %?", s); let mut v = ~[]; for each_split_char(s, c) |s| { v.push(s.to_owned()) } debug!("split_byte to: %?", v); assert!(vec::all2(v, u, |a,b| a == b)); } - let data = ~"ประเทศไทย中华Việt Nam"; - t(data, 'V', ~[~"ประเทศไทย中华", ~"iệt Nam"]); - t(data, 'ท', ~[~"ประเ", ~"ศไ", ~"ย中华Việt Nam"]); + let data = "ประเทศไทย中华Việt Nam"; + t(data, 'V', [~"ประเทศไทย中华", ~"iệt Nam"]); + t(data, 'ท', [~"ประเ", ~"ศไ", ~"ย中华Việt Nam"]); } #[test] fn test_splitn_char() { fn t(s: &str, c: char, n: uint, u: &[~str]) { - debug!(~"splitn_byte: " + s); + debug!("splitn_byte: %?", s); let mut v = ~[]; for each_splitn_char(s, c, n) |s| { v.push(s.to_owned()) } debug!("split_byte to: %?", v); debug!("comparing vs. %?", u); assert!(vec::all2(v, u, |a,b| a == b)); } - t(~"abc.hello.there", '.', 0u, ~[~"abc.hello.there"]); - t(~"abc.hello.there", '.', 1u, ~[~"abc", ~"hello.there"]); - t(~"abc.hello.there", '.', 2u, ~[~"abc", ~"hello", ~"there"]); - t(~"abc.hello.there", '.', 3u, ~[~"abc", ~"hello", ~"there"]); - t(~".hello.there", '.', 0u, ~[~".hello.there"]); - t(~".hello.there", '.', 1u, ~[~"", ~"hello.there"]); - t(~"...hello.there.", '.', 3u, ~[~"", ~"", ~"", ~"hello.there."]); - t(~"...hello.there.", '.', 5u, ~[~"", ~"", ~"", ~"hello", ~"there", ~""]); - - t(~"", 'z', 5u, ~[~""]); - t(~"z", 'z', 5u, ~[~"",~""]); - t(~"ok", 'z', 5u, ~[~"ok"]); - t(~"z", 'z', 0u, ~[~"z"]); - t(~"w.x.y", '.', 0u, ~[~"w.x.y"]); - t(~"w.x.y", '.', 1u, ~[~"w",~"x.y"]); + t("abc.hello.there", '.', 0u, [~"abc.hello.there"]); + t("abc.hello.there", '.', 1u, [~"abc", ~"hello.there"]); + t("abc.hello.there", '.', 2u, [~"abc", ~"hello", ~"there"]); + t("abc.hello.there", '.', 3u, [~"abc", ~"hello", ~"there"]); + t(".hello.there", '.', 0u, [~".hello.there"]); + t(".hello.there", '.', 1u, [~"", ~"hello.there"]); + t("...hello.there.", '.', 3u, [~"", ~"", ~"", ~"hello.there."]); + t("...hello.there.", '.', 5u, [~"", ~"", ~"", ~"hello", ~"there", ~""]); + + t("", 'z', 5u, [~""]); + t("z", 'z', 5u, [~"",~""]); + t("ok", 'z', 5u, [~"ok"]); + t("z", 'z', 0u, [~"z"]); + t("w.x.y", '.', 0u, [~"w.x.y"]); + t("w.x.y", '.', 1u, [~"w",~"x.y"]); } #[test] - fn test_splitn_char_2 () { + fn test_splitn_char_2() { fn t(s: &str, c: char, n: uint, u: &[~str]) { - debug!(~"splitn_byte: " + s); + debug!("splitn_byte: %?", s); let mut v = ~[]; for each_splitn_char(s, c, n) |s| { v.push(s.to_owned()) } debug!("split_byte to: %?", v); @@ -3295,60 +3024,59 @@ mod tests { assert!(vec::all2(v, u, |a,b| a == b)); } - t(~"ประเทศไทย中华Việt Nam", '华', 1u, ~[~"ประเทศไทย中", ~"Việt Nam"]); - t(~"zzXXXzYYYzWWWz", 'z', 3u, ~[~"", ~"", ~"XXX", ~"YYYzWWWz"]); - t(~"z", 'z', 5u, ~[~"",~""]); - t(~"", 'z', 5u, ~[~""]); - t(~"ok", 'z', 5u, ~[~"ok"]); + t("ประเทศไทย中华Việt Nam", '华', 1u, [~"ประเทศไทย中", ~"Việt Nam"]); + t("zzXXXzYYYzWWWz", 'z', 3u, [~"", ~"", ~"XXX", ~"YYYzWWWz"]); + t("z", 'z', 5u, [~"",~""]); + t("", 'z', 5u, [~""]); + t("ok", 'z', 5u, [~"ok"]); } - #[test] fn test_splitn_char_3() { fn t(s: &str, c: char, n: uint, u: &[~str]) { - debug!(~"splitn_byte: " + s); + debug!("splitn_byte: %?", s); let mut v = ~[]; for each_splitn_char(s, c, n) |s| { v.push(s.to_owned()) } debug!("split_byte to: %?", v); debug!("comparing vs. %?", u); assert!(vec::all2(v, u, |a,b| a == b)); } - let data = ~"ประเทศไทย中华Việt Nam"; - t(data, 'V', 1u, ~[~"ประเทศไทย中华", ~"iệt Nam"]); - t(data, 'ท', 1u, ~[~"ประเ", ~"ศไทย中华Việt Nam"]); + let data = "ประเทศไทย中华Việt Nam"; + t(data, 'V', 1u, [~"ประเทศไทย中华", ~"iệt Nam"]); + t(data, 'ท', 1u, [~"ประเ", ~"ศไทย中华Việt Nam"]); } #[test] fn test_split_char_no_trailing() { fn t(s: &str, c: char, u: &[~str]) { - debug!(~"split_byte: " + s); + debug!("split_byte: %?", s); let mut v = ~[]; for each_split_char_no_trailing(s, c) |s| { v.push(s.to_owned()) } debug!("split_byte to: %?", v); assert!(vec::all2(v, u, |a,b| a == b)); } - t(~"abc.hello.there", '.', ~[~"abc", ~"hello", ~"there"]); - t(~".hello.there", '.', ~[~"", ~"hello", ~"there"]); - t(~"...hello.there.", '.', ~[~"", ~"", ~"", ~"hello", ~"there"]); + t("abc.hello.there", '.', [~"abc", ~"hello", ~"there"]); + t(".hello.there", '.', [~"", ~"hello", ~"there"]); + t("...hello.there.", '.', [~"", ~"", ~"", ~"hello", ~"there"]); - t(~"...hello.there.", '.', ~[~"", ~"", ~"", ~"hello", ~"there"]); - t(~"", 'z', ~[]); - t(~"z", 'z', ~[~""]); - t(~"ok", 'z', ~[~"ok"]); + t("...hello.there.", '.', [~"", ~"", ~"", ~"hello", ~"there"]); + t("", 'z', []); + t("z", 'z', [~""]); + t("ok", 'z', [~"ok"]); } #[test] fn test_split_char_no_trailing_2() { fn t(s: &str, c: char, u: &[~str]) { - debug!(~"split_byte: " + s); + debug!("split_byte: %?", s); let mut v = ~[]; for each_split_char_no_trailing(s, c) |s| { v.push(s.to_owned()) } debug!("split_byte to: %?", v); assert!(vec::all2(v, u, |a,b| a == b)); } - let data = ~"ประเทศไทย中华Việt Nam"; - t(data, 'V', ~[~"ประเทศไทย中华", ~"iệt Nam"]); - t(data, 'ท', ~[~"ประเ", ~"ศไ", ~"ย中华Việt Nam"]); + let data = "ประเทศไทย中华Việt Nam"; + t(data, 'V', [~"ประเทศไทย中华", ~"iệt Nam"]); + t(data, 'ท', [~"ประเ", ~"ศไ", ~"ย中华Việt Nam"]); } #[test] @@ -3358,20 +3086,20 @@ mod tests { for each_split_str(s, sep) |s| { v.push(s.to_owned()) } assert!(vec::all2(v, u, |a,b| a == b)); } - t(~"--1233345--", ~"12345", ~[~"--1233345--"]); - t(~"abc::hello::there", ~"::", ~[~"abc", ~"hello", ~"there"]); - t(~"::hello::there", ~"::", ~[~"", ~"hello", ~"there"]); - t(~"hello::there::", ~"::", ~[~"hello", ~"there", ~""]); - t(~"::hello::there::", ~"::", ~[~"", ~"hello", ~"there", ~""]); - t(~"ประเทศไทย中华Việt Nam", ~"中华", ~[~"ประเทศไทย", ~"Việt Nam"]); - t(~"zzXXXzzYYYzz", ~"zz", ~[~"", ~"XXX", ~"YYY", ~""]); - t(~"zzXXXzYYYz", ~"XXX", ~[~"zz", ~"zYYYz"]); - t(~".XXX.YYY.", ~".", ~[~"", ~"XXX", ~"YYY", ~""]); - t(~"", ~".", ~[~""]); - t(~"zz", ~"zz", ~[~"",~""]); - t(~"ok", ~"z", ~[~"ok"]); - t(~"zzz", ~"zz", ~[~"",~"z"]); - t(~"zzzzz", ~"zz", ~[~"",~"",~"z"]); + t("--1233345--", "12345", [~"--1233345--"]); + t("abc::hello::there", "::", [~"abc", ~"hello", ~"there"]); + t("::hello::there", "::", [~"", ~"hello", ~"there"]); + t("hello::there::", "::", [~"hello", ~"there", ~""]); + t("::hello::there::", "::", [~"", ~"hello", ~"there", ~""]); + t("ประเทศไทย中华Việt Nam", "中华", [~"ประเทศไทย", ~"Việt Nam"]); + t("zzXXXzzYYYzz", "zz", [~"", ~"XXX", ~"YYY", ~""]); + t("zzXXXzYYYz", "XXX", [~"zz", ~"zYYYz"]); + t(".XXX.YYY.", ".", [~"", ~"XXX", ~"YYY", ~""]); + t("", ".", [~""]); + t("zz", "zz", [~"",~""]); + t("ok", "z", [~"ok"]); + t("zzz", "zz", [~"",~"z"]); + t("zzzzz", "zz", [~"",~"",~"z"]); } @@ -3383,12 +3111,12 @@ mod tests { assert!(vec::all2(v, u, |a,b| a == b)); } - t(~"ประเทศไทย中华Việt Nam", |cc| cc == '华', ~[~"ประเทศไทย中", ~"Việt Nam"]); - t(~"zzXXXzYYYz", char::is_lowercase, ~[~"", ~"", ~"XXX", ~"YYY", ~""]); - t(~"zzXXXzYYYz", char::is_uppercase, ~[~"zz", ~"", ~"", ~"z", ~"", ~"", ~"z"]); - t(~"z", |cc| cc == 'z', ~[~"",~""]); - t(~"", |cc| cc == 'z', ~[~""]); - t(~"ok", |cc| cc == 'z', ~[~"ok"]); + t("ประเทศไทย中华Việt Nam", |cc| cc == '华', [~"ประเทศไทย中", ~"Việt Nam"]); + t("zzXXXzYYYz", char::is_lowercase, [~"", ~"", ~"XXX", ~"YYY", ~""]); + t("zzXXXzYYYz", char::is_uppercase, [~"zz", ~"", ~"", ~"z", ~"", ~"", ~"z"]); + t("z", |cc| cc == 'z', [~"",~""]); + t("", |cc| cc == 'z', [~""]); + t("ok", |cc| cc == 'z', [~"ok"]); } #[test] @@ -3399,18 +3127,18 @@ mod tests { assert!(vec::all2(v, u, |a,b| a == b)); } - t(~"ประเทศไทย中华Việt Nam", |cc| cc == '华', ~[~"ประเทศไทย中", ~"Việt Nam"]); - t(~"zzXXXzYYYz", char::is_lowercase, ~[~"", ~"", ~"XXX", ~"YYY"]); - t(~"zzXXXzYYYz", char::is_uppercase, ~[~"zz", ~"", ~"", ~"z", ~"", ~"", ~"z"]); - t(~"z", |cc| cc == 'z', ~[~""]); - t(~"", |cc| cc == 'z', ~[]); - t(~"ok", |cc| cc == 'z', ~[~"ok"]); + t("ประเทศไทย中华Việt Nam", |cc| cc == '华', [~"ประเทศไทย中", ~"Việt Nam"]); + t("zzXXXzYYYz", char::is_lowercase, [~"", ~"", ~"XXX", ~"YYY"]); + t("zzXXXzYYYz", char::is_uppercase, [~"zz", ~"", ~"", ~"z", ~"", ~"", ~"z"]); + t("z", |cc| cc == 'z', [~""]); + t("", |cc| cc == 'z', []); + t("ok", |cc| cc == 'z', [~"ok"]); } #[test] fn test_lines() { - let lf = ~"\nMary had a little lamb\nLittle lamb\n"; - let crlf = ~"\r\nMary had a little lamb\r\nLittle lamb\r\n"; + let lf = "\nMary had a little lamb\nLittle lamb\n"; + let crlf = "\r\nMary had a little lamb\r\nLittle lamb\r\n"; fn t(s: &str, f: &fn(&str, &fn(&str) -> bool) -> bool, u: &[~str]) { let mut v = ~[]; @@ -3418,30 +3146,30 @@ mod tests { assert!(vec::all2(v, u, |a,b| a == b)); } - t(lf, each_line ,~[~"", ~"Mary had a little lamb", ~"Little lamb"]); - t(lf, each_line_any, ~[~"", ~"Mary had a little lamb", ~"Little lamb"]); - t(crlf, each_line, ~[~"\r", ~"Mary had a little lamb\r", ~"Little lamb\r"]); - t(crlf, each_line_any, ~[~"", ~"Mary had a little lamb", ~"Little lamb"]); - t(~"", each_line, ~[]); - t(~"", each_line_any, ~[]); - t(~"\n", each_line, ~[~""]); - t(~"\n", each_line_any, ~[~""]); - t(~"banana", each_line, ~[~"banana"]); - t(~"banana", each_line_any, ~[~"banana"]); + t(lf, each_line, [~"", ~"Mary had a little lamb", ~"Little lamb"]); + t(lf, each_line_any, [~"", ~"Mary had a little lamb", ~"Little lamb"]); + t(crlf, each_line, [~"\r", ~"Mary had a little lamb\r", ~"Little lamb\r"]); + t(crlf, each_line_any, [~"", ~"Mary had a little lamb", ~"Little lamb"]); + t("", each_line, []); + t("", each_line_any, []); + t("\n", each_line, [~""]); + t("\n", each_line_any, [~""]); + t("banana", each_line, [~"banana"]); + t("banana", each_line_any, [~"banana"]); } #[test] - fn test_words () { + fn test_words() { fn t(s: &str, f: &fn(&str, &fn(&str) -> bool) -> bool, u: &[~str]) { let mut v = ~[]; for f(s) |s| { v.push(s.to_owned()) } assert!(vec::all2(v, u, |a,b| a == b)); } - let data = ~"\nMary had a little lamb\nLittle lamb\n"; + let data = "\nMary had a little lamb\nLittle lamb\n"; - t(data, each_word, ~[~"Mary",~"had",~"a",~"little",~"lamb",~"Little",~"lamb"]); - t(~"ok", each_word, ~[~"ok"]); - t(~"", each_word, ~[]); + t(data, each_word, [~"Mary",~"had",~"a",~"little",~"lamb",~"Little",~"lamb"]); + t("ok", each_word, [~"ok"]); + t("", each_word, []); } #[test] @@ -3451,92 +3179,107 @@ mod tests { for each_split_within(s, i) |s| { v.push(s.to_owned()) } assert!(vec::all2(v, u, |a,b| a == b)); } - t(~"", 0, ~[]); - t(~"", 15, ~[]); - t(~"hello", 15, ~[~"hello"]); - t(~"\nMary had a little lamb\nLittle lamb\n", 15, - ~[~"Mary had a", ~"little lamb", ~"Little lamb"]); + t("", 0, []); + t("", 15, []); + t("hello", 15, [~"hello"]); + t("\nMary had a little lamb\nLittle lamb\n", 15, + [~"Mary had a", ~"little lamb", ~"Little lamb"]); } #[test] fn test_find_str() { // byte positions - assert!(find_str(~"banana", ~"apple pie").is_none()); - assert!(find_str(~"", ~"") == Some(0u)); + assert!(find_str("banana", "apple pie").is_none()); + assert_eq!(find_str("", ""), Some(0u)); - let data = ~"ประเทศไทย中华Việt Nam"; - assert!(find_str(data, ~"") == Some(0u)); - assert!(find_str(data, ~"ประเ") == Some( 0u)); - assert!(find_str(data, ~"ะเ") == Some( 6u)); - assert!(find_str(data, ~"中华") == Some(27u)); - assert!(find_str(data, ~"ไท华").is_none()); + let data = "ประเทศไทย中华Việt Nam"; + assert_eq!(find_str(data, ""), Some(0u)); + assert_eq!(find_str(data, "ประเ"), Some( 0u)); + assert_eq!(find_str(data, "ะเ"), Some( 6u)); + assert_eq!(find_str(data, "中华"), Some(27u)); + assert!(find_str(data, "ไท华").is_none()); } #[test] fn test_find_str_between() { // byte positions - assert!(find_str_between(~"", ~"", 0u, 0u) == Some(0u)); + assert_eq!(find_str_between("", "", 0u, 0u), Some(0u)); - let data = ~"abcabc"; - assert!(find_str_between(data, ~"ab", 0u, 6u) == Some(0u)); - assert!(find_str_between(data, ~"ab", 2u, 6u) == Some(3u)); - assert!(find_str_between(data, ~"ab", 2u, 4u).is_none()); + let data = "abcabc"; + assert_eq!(find_str_between(data, "ab", 0u, 6u), Some(0u)); + assert_eq!(find_str_between(data, "ab", 2u, 6u), Some(3u)); + assert!(find_str_between(data, "ab", 2u, 4u).is_none()); let mut data = ~"ประเทศไทย中华Việt Nam"; data = data + data; - assert!(find_str_between(data, ~"", 0u, 43u) == Some(0u)); - assert!(find_str_between(data, ~"", 6u, 43u) == Some(6u)); + assert_eq!(find_str_between(data, "", 0u, 43u), Some(0u)); + assert_eq!(find_str_between(data, "", 6u, 43u), Some(6u)); - assert!(find_str_between(data, ~"ประ", 0u, 43u) == Some( 0u)); - assert!(find_str_between(data, ~"ทศไ", 0u, 43u) == Some(12u)); - assert!(find_str_between(data, ~"ย中", 0u, 43u) == Some(24u)); - assert!(find_str_between(data, ~"iệt", 0u, 43u) == Some(34u)); - assert!(find_str_between(data, ~"Nam", 0u, 43u) == Some(40u)); + assert_eq!(find_str_between(data, "ประ", 0u, 43u), Some( 0u)); + assert_eq!(find_str_between(data, "ทศไ", 0u, 43u), Some(12u)); + assert_eq!(find_str_between(data, "ย中", 0u, 43u), Some(24u)); + assert_eq!(find_str_between(data, "iệt", 0u, 43u), Some(34u)); + assert_eq!(find_str_between(data, "Nam", 0u, 43u), Some(40u)); - assert!(find_str_between(data, ~"ประ", 43u, 86u) == Some(43u)); - assert!(find_str_between(data, ~"ทศไ", 43u, 86u) == Some(55u)); - assert!(find_str_between(data, ~"ย中", 43u, 86u) == Some(67u)); - assert!(find_str_between(data, ~"iệt", 43u, 86u) == Some(77u)); - assert!(find_str_between(data, ~"Nam", 43u, 86u) == Some(83u)); + assert_eq!(find_str_between(data, "ประ", 43u, 86u), Some(43u)); + assert_eq!(find_str_between(data, "ทศไ", 43u, 86u), Some(55u)); + assert_eq!(find_str_between(data, "ย中", 43u, 86u), Some(67u)); + assert_eq!(find_str_between(data, "iệt", 43u, 86u), Some(77u)); + assert_eq!(find_str_between(data, "Nam", 43u, 86u), Some(83u)); } #[test] fn test_substr() { fn t(a: &str, b: &str, start: int) { - assert!(substr(a, start as uint, len(b)) == b); + assert_eq!(substr(a, start as uint, len(b)), b); } t("hello", "llo", 2); t("hello", "el", 1); - assert!("ะเทศไท" == substr("ประเทศไทย中华Việt Nam", 6u, 6u)); + assert_eq!("ะเทศไท", substr("ประเทศไทย中华Việt Nam", 6u, 6u)); } #[test] fn test_concat() { fn t(v: &[~str], s: &str) { - assert!(concat(v) == s.to_str()); + assert_eq!(concat(v), s.to_str()); + assert_eq!(v.concat(), s.to_str()); } - t(~[~"you", ~"know", ~"I'm", ~"no", ~"good"], ~"youknowI'mnogood"); - let v: ~[~str] = ~[]; - t(v, ~""); - t(~[~"hi"], ~"hi"); + t([~"you", ~"know", ~"I'm", ~"no", ~"good"], "youknowI'mnogood"); + let v: &[~str] = []; + t(v, ""); + t([~"hi"], "hi"); } #[test] fn test_connect() { fn t(v: &[~str], sep: &str, s: &str) { - assert!(connect(v, sep) == s.to_str()); + assert_eq!(connect(v, sep), s.to_str()); + assert_eq!(v.connect(sep), s.to_str()); + } + t([~"you", ~"know", ~"I'm", ~"no", ~"good"], + " ", "you know I'm no good"); + let v: &[~str] = []; + t(v, " ", ""); + t([~"hi"], " ", "hi"); + } + + #[test] + fn test_concat_slices() { + fn t(v: &[&str], s: &str) { + assert_eq!(concat_slices(v), s.to_str()); + assert_eq!(v.concat(), s.to_str()); } - t(~[~"you", ~"know", ~"I'm", ~"no", ~"good"], - ~" ", ~"you know I'm no good"); - let v: ~[~str] = ~[]; - t(v, ~" ", ~""); - t(~[~"hi"], ~" ", ~"hi"); + t(["you", "know", "I'm", "no", "good"], "youknowI'mnogood"); + let v: &[&str] = []; + t(v, ""); + t(["hi"], "hi"); } #[test] fn test_connect_slices() { fn t(v: &[&str], sep: &str, s: &str) { - assert!(connect_slices(v, sep) == s.to_str()); + assert_eq!(connect_slices(v, sep), s.to_str()); + assert_eq!(v.connect(sep), s.to_str()); } t(["you", "know", "I'm", "no", "good"], " ", "you know I'm no good"); @@ -3546,18 +3289,18 @@ mod tests { #[test] fn test_repeat() { - assert!(repeat(~"x", 4) == ~"xxxx"); - assert!(repeat(~"hi", 4) == ~"hihihihi"); - assert!(repeat(~"ไท华", 3) == ~"ไท华ไท华ไท华"); - assert!(repeat(~"", 4) == ~""); - assert!(repeat(~"hi", 0) == ~""); + assert_eq!(repeat("x", 4), ~"xxxx"); + assert_eq!(repeat("hi", 4), ~"hihihihi"); + assert_eq!(repeat("ไท华", 3), ~"ไท华ไท华ไท华"); + assert_eq!(repeat("", 4), ~""); + assert_eq!(repeat("hi", 0), ~""); } #[test] fn test_unsafe_slice() { - assert!("ab" == unsafe {raw::slice_bytes("abc", 0, 2)}); - assert!("bc" == unsafe {raw::slice_bytes("abc", 1, 3)}); - assert!("" == unsafe {raw::slice_bytes("abc", 1, 1)}); + assert_eq!("ab", unsafe {raw::slice_bytes("abc", 0, 2)}); + assert_eq!("bc", unsafe {raw::slice_bytes("abc", 1, 3)}); + assert_eq!("", unsafe {raw::slice_bytes("abc", 1, 1)}); fn a_million_letter_a() -> ~str { let mut i = 0; let mut rs = ~""; @@ -3577,38 +3320,38 @@ mod tests { #[test] fn test_starts_with() { - assert!((starts_with(~"", ~""))); - assert!((starts_with(~"abc", ~""))); - assert!((starts_with(~"abc", ~"a"))); - assert!((!starts_with(~"a", ~"abc"))); - assert!((!starts_with(~"", ~"abc"))); + assert!((starts_with("", ""))); + assert!((starts_with("abc", ""))); + assert!((starts_with("abc", "a"))); + assert!((!starts_with("a", "abc"))); + assert!((!starts_with("", "abc"))); } #[test] fn test_ends_with() { - assert!((ends_with(~"", ~""))); - assert!((ends_with(~"abc", ~""))); - assert!((ends_with(~"abc", ~"c"))); - assert!((!ends_with(~"a", ~"abc"))); - assert!((!ends_with(~"", ~"abc"))); + assert!((ends_with("", ""))); + assert!((ends_with("abc", ""))); + assert!((ends_with("abc", "c"))); + assert!((!ends_with("a", "abc"))); + assert!((!ends_with("", "abc"))); } #[test] fn test_is_empty() { - assert!((is_empty(~""))); - assert!((!is_empty(~"a"))); + assert!((is_empty(""))); + assert!((!is_empty("a"))); } #[test] fn test_replace() { - let a = ~"a"; - assert!(replace(~"", a, ~"b") == ~""); - assert!(replace(~"a", a, ~"b") == ~"b"); - assert!(replace(~"ab", a, ~"b") == ~"bb"); - let test = ~"test"; - assert!(replace(~" test test ", test, ~"toast") == + let a = "a"; + assert_eq!(replace("", a, "b"), ~""); + assert_eq!(replace("a", a, "b"), ~"b"); + assert_eq!(replace("ab", a, "b"), ~"bb"); + let test = "test"; + assert!(replace(" test test ", test, "toast") == ~" toast toast "); - assert!(replace(~" test test ", test, ~"") == ~" "); + assert_eq!(replace(" test test ", test, ""), ~" "); } #[test] @@ -3618,7 +3361,7 @@ mod tests { let a = ~"ประเ"; let A = ~"دولة الكويتทศไทย中华"; - assert!((replace(data, a, repl) == A)); + assert_eq!(replace(data, a, repl), A); } #[test] @@ -3628,7 +3371,7 @@ mod tests { let b = ~"ะเ"; let B = ~"ปรدولة الكويتทศไทย中华"; - assert!((replace(data, b, repl) == B)); + assert_eq!(replace(data, b, repl), B); } #[test] @@ -3638,7 +3381,7 @@ mod tests { let c = ~"中华"; let C = ~"ประเทศไทยدولة الكويت"; - assert!((replace(data, c, repl) == C)); + assert_eq!(replace(data, c, repl), C); } #[test] @@ -3647,21 +3390,21 @@ mod tests { let repl = ~"دولة الكويت"; let d = ~"ไท华"; - assert!((replace(data, d, repl) == data)); + assert_eq!(replace(data, d, repl), data); } #[test] fn test_slice() { - assert!("ab" == slice("abc", 0, 2)); - assert!("bc" == slice("abc", 1, 3)); - assert!("" == slice("abc", 1, 1)); - assert!("\u65e5" == slice("\u65e5\u672c", 0, 3)); + assert_eq!("ab", slice("abc", 0, 2)); + assert_eq!("bc", slice("abc", 1, 3)); + assert_eq!("", slice("abc", 1, 1)); + assert_eq!("\u65e5", slice("\u65e5\u672c", 0, 3)); let data = "ประเทศไทย中华"; - assert!("ป" == slice(data, 0, 3)); - assert!("ร" == slice(data, 3, 6)); - assert!("" == slice(data, 3, 3)); - assert!("华" == slice(data, 30, 33)); + assert_eq!("ป", slice(data, 0, 3)); + assert_eq!("ร", slice(data, 3, 6)); + assert_eq!("", slice(data, 3, 3)); + assert_eq!("华", slice(data, 30, 33)); fn a_million_letter_X() -> ~str { let mut i = 0; @@ -3687,16 +3430,16 @@ mod tests { fn test_slice_2() { let ss = "中华Việt Nam"; - assert!("华" == slice(ss, 3u, 6u)); - assert!("Việt Nam" == slice(ss, 6u, 16u)); + assert_eq!("华", slice(ss, 3u, 6u)); + assert_eq!("Việt Nam", slice(ss, 6u, 16u)); - assert!("ab" == slice("abc", 0u, 2u)); - assert!("bc" == slice("abc", 1u, 3u)); - assert!("" == slice("abc", 1u, 1u)); + assert_eq!("ab", slice("abc", 0u, 2u)); + assert_eq!("bc", slice("abc", 1u, 3u)); + assert_eq!("", slice("abc", 1u, 1u)); - assert!("中" == slice(ss, 0u, 3u)); - assert!("华V" == slice(ss, 3u, 7u)); - assert!("" == slice(ss, 3u, 3u)); + assert_eq!("中", slice(ss, 0u, 3u)); + assert_eq!("华V", slice(ss, 3u, 7u)); + assert_eq!("", slice(ss, 3u, 3u)); /*0: 中 3: 华 6: V @@ -3718,94 +3461,88 @@ mod tests { #[test] fn test_trim_left_chars() { - assert!(trim_left_chars(" *** foo *** ", ~[]) == - " *** foo *** "); - assert!(trim_left_chars(" *** foo *** ", ~['*', ' ']) == - "foo *** "); - assert!(trim_left_chars(" *** *** ", ~['*', ' ']) == ""); - assert!(trim_left_chars("foo *** ", ~['*', ' ']) == - "foo *** "); + assert!(trim_left_chars(" *** foo *** ", []) == " *** foo *** "); + assert!(trim_left_chars(" *** foo *** ", ['*', ' ']) == "foo *** "); + assert_eq!(trim_left_chars(" *** *** ", ['*', ' ']), ""); + assert!(trim_left_chars("foo *** ", ['*', ' ']) == "foo *** "); } #[test] fn test_trim_right_chars() { - assert!(trim_right_chars(" *** foo *** ", ~[]) == - " *** foo *** "); - assert!(trim_right_chars(" *** foo *** ", ~['*', ' ']) == - " *** foo"); - assert!(trim_right_chars(" *** *** ", ~['*', ' ']) == ""); - assert!(trim_right_chars(" *** foo", ~['*', ' ']) == - " *** foo"); + assert!(trim_right_chars(" *** foo *** ", []) == " *** foo *** "); + assert!(trim_right_chars(" *** foo *** ", ['*', ' ']) == " *** foo"); + assert_eq!(trim_right_chars(" *** *** ", ['*', ' ']), ""); + assert!(trim_right_chars(" *** foo", ['*', ' ']) == " *** foo"); } #[test] fn test_trim_chars() { - assert!(trim_chars(" *** foo *** ", ~[]) == " *** foo *** "); - assert!(trim_chars(" *** foo *** ", ~['*', ' ']) == "foo"); - assert!(trim_chars(" *** *** ", ~['*', ' ']) == ""); - assert!(trim_chars("foo", ~['*', ' ']) == "foo"); + assert_eq!(trim_chars(" *** foo *** ", []), " *** foo *** "); + assert_eq!(trim_chars(" *** foo *** ", ['*', ' ']), "foo"); + assert_eq!(trim_chars(" *** *** ", ['*', ' ']), ""); + assert_eq!(trim_chars("foo", ['*', ' ']), "foo"); } #[test] fn test_trim_left() { - assert!((trim_left("") == "")); - assert!((trim_left("a") == "a")); - assert!((trim_left(" ") == "")); - assert!((trim_left(" blah") == "blah")); - assert!((trim_left(" \u3000 wut") == "wut")); - assert!((trim_left("hey ") == "hey ")); + assert_eq!(trim_left(""), ""); + assert_eq!(trim_left("a"), "a"); + assert_eq!(trim_left(" "), ""); + assert_eq!(trim_left(" blah"), "blah"); + assert_eq!(trim_left(" \u3000 wut"), "wut"); + assert_eq!(trim_left("hey "), "hey "); } #[test] fn test_trim_right() { - assert!((trim_right("") == "")); - assert!((trim_right("a") == "a")); - assert!((trim_right(" ") == "")); - assert!((trim_right("blah ") == "blah")); - assert!((trim_right("wut \u3000 ") == "wut")); - assert!((trim_right(" hey") == " hey")); + assert_eq!(trim_right(""), ""); + assert_eq!(trim_right("a"), "a"); + assert_eq!(trim_right(" "), ""); + assert_eq!(trim_right("blah "), "blah"); + assert_eq!(trim_right("wut \u3000 "), "wut"); + assert_eq!(trim_right(" hey"), " hey"); } #[test] fn test_trim() { - assert!((trim("") == "")); - assert!((trim("a") == "a")); - assert!((trim(" ") == "")); - assert!((trim(" blah ") == "blah")); - assert!((trim("\nwut \u3000 ") == "wut")); - assert!((trim(" hey dude ") == "hey dude")); + assert_eq!(trim(""), ""); + assert_eq!(trim("a"), "a"); + assert_eq!(trim(" "), ""); + assert_eq!(trim(" blah "), "blah"); + assert_eq!(trim("\nwut \u3000 "), "wut"); + assert_eq!(trim(" hey dude "), "hey dude"); } #[test] fn test_is_whitespace() { - assert!((is_whitespace(~""))); - assert!((is_whitespace(~" "))); - assert!((is_whitespace(~"\u2009"))); // Thin space - assert!((is_whitespace(~" \n\t "))); - assert!((!is_whitespace(~" _ "))); + assert!(is_whitespace("")); + assert!(is_whitespace(" ")); + assert!(is_whitespace("\u2009")); // Thin space + assert!(is_whitespace(" \n\t ")); + assert!(!is_whitespace(" _ ")); } #[test] fn test_shift_byte() { let mut s = ~"ABC"; let b = unsafe{raw::shift_byte(&mut s)}; - assert!((s == ~"BC")); - assert!((b == 65u8)); + assert_eq!(s, ~"BC"); + assert_eq!(b, 65u8); } #[test] fn test_pop_byte() { let mut s = ~"ABC"; let b = unsafe{raw::pop_byte(&mut s)}; - assert!((s == ~"AB")); - assert!((b == 67u8)); + assert_eq!(s, ~"AB"); + assert_eq!(b, 67u8); } #[test] fn test_unsafe_from_bytes() { let a = ~[65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 65u8]; let b = unsafe { raw::from_bytes(a) }; - assert!((b == ~"AAAAAAA")); + assert_eq!(b, ~"AAAAAAA"); } #[test] @@ -3822,7 +3559,7 @@ mod tests { 0x20_u8, 0x4e_u8, 0x61_u8, 0x6d_u8]; - assert!(ss == from_bytes(bb)); + assert_eq!(ss, from_bytes(bb)); } #[test] @@ -3909,7 +3646,7 @@ mod tests { let a = ~[65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 0u8]; let b = vec::raw::to_ptr(a); let c = raw::from_buf(b); - assert!((c == ~"AAAAAAA")); + assert_eq!(c, ~"AAAAAAA"); } } @@ -3923,22 +3660,22 @@ mod tests { #[test] fn test_as_buf() { - let a = ~"Abcdefg"; + let a = "Abcdefg"; let b = as_buf(a, |buf, _l| { - assert!(unsafe { *buf } == 65u8); + assert_eq!(unsafe { *buf }, 65u8); 100 }); - assert!((b == 100)); + assert_eq!(b, 100); } #[test] fn test_as_buf_small() { - let a = ~"A"; + let a = "A"; let b = as_buf(a, |buf, _l| { - assert!(unsafe { *buf } == 65u8); + assert_eq!(unsafe { *buf }, 65u8); 100 }); - assert!((b == 100)); + assert_eq!(b, 100); } #[test] @@ -3947,7 +3684,7 @@ mod tests { let s = ~"hello"; let sb = as_buf(s, |b, _l| b); let s_cstr = raw::from_buf(sb); - assert!(s_cstr == s); + assert_eq!(s_cstr, s); } } @@ -3956,11 +3693,11 @@ mod tests { let a = ~"hello"; do as_buf(a) |buf, len| { unsafe { - assert!(a[0] == 'h' as u8); - assert!(*buf == 'h' as u8); - assert!(len == 6u); - assert!(*ptr::offset(buf,4u) == 'o' as u8); - assert!(*ptr::offset(buf,5u) == 0u8); + assert_eq!(a[0], 'h' as u8); + assert_eq!(*buf, 'h' as u8); + assert_eq!(len, 6u); + assert_eq!(*ptr::offset(buf,4u), 'o' as u8); + assert_eq!(*ptr::offset(buf,5u), 0u8); } } } @@ -3970,15 +3707,15 @@ mod tests { let a = "kernelsprite"; let b = slice(a, 7, len(a)); let c = slice(a, 0, len(a) - 6); - assert!(subslice_offset(a, b) == 7); - assert!(subslice_offset(a, c) == 0); + assert_eq!(subslice_offset(a, b), 7); + assert_eq!(subslice_offset(a, c), 0); let string = "a\nb\nc"; let mut lines = ~[]; for each_line(string) |line| { lines.push(line) } - assert!(subslice_offset(string, lines[0]) == 0); - assert!(subslice_offset(string, lines[1]) == 2); - assert!(subslice_offset(string, lines[2]) == 4); + assert_eq!(subslice_offset(string, lines[0]), 0); + assert_eq!(subslice_offset(string, lines[1]), 2); + assert_eq!(subslice_offset(string, lines[2]), 4); } #[test] @@ -3998,45 +3735,45 @@ mod tests { let mut i: uint = 0u; let n1: uint = len(s1); let n2: uint = vec::len::(v); - assert!((n1 == n2)); + assert_eq!(n1, n2); while i < n1 { let a: u8 = s1[i]; let b: u8 = s2[i]; debug!(a); debug!(b); - assert!((a == b)); + assert_eq!(a, b); i += 1u; } } #[test] fn test_contains() { - assert!(contains(~"abcde", ~"bcd")); - assert!(contains(~"abcde", ~"abcd")); - assert!(contains(~"abcde", ~"bcde")); - assert!(contains(~"abcde", ~"")); - assert!(contains(~"", ~"")); - assert!(!contains(~"abcde", ~"def")); - assert!(!contains(~"", ~"a")); + assert!(contains("abcde", "bcd")); + assert!(contains("abcde", "abcd")); + assert!(contains("abcde", "bcde")); + assert!(contains("abcde", "")); + assert!(contains("", "")); + assert!(!contains("abcde", "def")); + assert!(!contains("", "a")); let data = ~"ประเทศไทย中华Việt Nam"; - assert!(contains(data, ~"ประเ")); - assert!(contains(data, ~"ะเ")); - assert!(contains(data, ~"中华")); - assert!(!contains(data, ~"ไท华")); + assert!(contains(data, "ประเ")); + assert!(contains(data, "ะเ")); + assert!(contains(data, "中华")); + assert!(!contains(data, "ไท华")); } #[test] fn test_contains_char() { - assert!(contains_char(~"abc", 'b')); - assert!(contains_char(~"a", 'a')); - assert!(!contains_char(~"abc", 'd')); - assert!(!contains_char(~"", 'a')); + assert!(contains_char("abc", 'b')); + assert!(contains_char("a", 'a')); + assert!(!contains_char("abc", 'd')); + assert!(!contains_char("", 'a')); } #[test] fn test_split_char_each() { - let data = ~"\nMary had a little lamb\nLittle lamb\n"; + let data = "\nMary had a little lamb\nLittle lamb\n"; let mut ii = 0; @@ -4054,7 +3791,7 @@ mod tests { #[test] fn test_splitn_char_each() { - let data = ~"\nMary had a little lamb\nLittle lamb\n"; + let data = "\nMary had a little lamb\nLittle lamb\n"; let mut ii = 0; @@ -4071,7 +3808,7 @@ mod tests { #[test] fn test_words_each() { - let data = ~"\nMary had a little lamb\nLittle lamb\n"; + let data = "\nMary had a little lamb\nLittle lamb\n"; let mut ii = 0; @@ -4086,12 +3823,12 @@ mod tests { ii += 1; } - each_word(~"", |_x| fail!()); // should not fail + each_word("", |_x| fail!()); // should not fail } #[test] fn test_lines_each () { - let lf = ~"\nMary had a little lamb\nLittle lamb\n"; + let lf = "\nMary had a little lamb\nLittle lamb\n"; let mut ii = 0; @@ -4108,26 +3845,26 @@ mod tests { #[test] fn test_map() { - assert!(~"" == map(~"", |c| unsafe {libc::toupper(c as c_char)} as char)); - assert!(~"YMCA" == map(~"ymca", |c| unsafe {libc::toupper(c as c_char)} as char)); + assert_eq!(~"", map("", |c| unsafe {libc::toupper(c as c_char)} as char)); + assert_eq!(~"YMCA", map("ymca", |c| unsafe {libc::toupper(c as c_char)} as char)); } #[test] fn test_all() { - assert!(true == all(~"", char::is_uppercase)); - assert!(false == all(~"ymca", char::is_uppercase)); - assert!(true == all(~"YMCA", char::is_uppercase)); - assert!(false == all(~"yMCA", char::is_uppercase)); - assert!(false == all(~"YMCy", char::is_uppercase)); + assert_eq!(true, all("", char::is_uppercase)); + assert_eq!(false, all("ymca", char::is_uppercase)); + assert_eq!(true, all("YMCA", char::is_uppercase)); + assert_eq!(false, all("yMCA", char::is_uppercase)); + assert_eq!(false, all("YMCy", char::is_uppercase)); } #[test] fn test_any() { - assert!(false == any(~"", char::is_uppercase)); - assert!(false == any(~"ymca", char::is_uppercase)); - assert!(true == any(~"YMCA", char::is_uppercase)); - assert!(true == any(~"yMCA", char::is_uppercase)); - assert!(true == any(~"Ymcy", char::is_uppercase)); + assert_eq!(false, any("", char::is_uppercase)); + assert_eq!(false, any("ymca", char::is_uppercase)); + assert_eq!(true, any("YMCA", char::is_uppercase)); + assert_eq!(true, any("yMCA", char::is_uppercase)); + assert_eq!(true, any("Ymcy", char::is_uppercase)); } #[test] @@ -4141,41 +3878,41 @@ mod tests { #[test] fn test_utf16() { let pairs = - ~[(~"𐍅𐌿𐌻𐍆𐌹𐌻𐌰\n", + [(~"𐍅𐌿𐌻𐍆𐌹𐌻𐌰\n", ~[0xd800_u16, 0xdf45_u16, 0xd800_u16, 0xdf3f_u16, - 0xd800_u16, 0xdf3b_u16, 0xd800_u16, 0xdf46_u16, - 0xd800_u16, 0xdf39_u16, 0xd800_u16, 0xdf3b_u16, - 0xd800_u16, 0xdf30_u16, 0x000a_u16]), + 0xd800_u16, 0xdf3b_u16, 0xd800_u16, 0xdf46_u16, + 0xd800_u16, 0xdf39_u16, 0xd800_u16, 0xdf3b_u16, + 0xd800_u16, 0xdf30_u16, 0x000a_u16]), (~"𐐒𐑉𐐮𐑀𐐲𐑋 𐐏𐐲𐑍\n", ~[0xd801_u16, 0xdc12_u16, 0xd801_u16, - 0xdc49_u16, 0xd801_u16, 0xdc2e_u16, 0xd801_u16, - 0xdc40_u16, 0xd801_u16, 0xdc32_u16, 0xd801_u16, - 0xdc4b_u16, 0x0020_u16, 0xd801_u16, 0xdc0f_u16, - 0xd801_u16, 0xdc32_u16, 0xd801_u16, 0xdc4d_u16, - 0x000a_u16]), + 0xdc49_u16, 0xd801_u16, 0xdc2e_u16, 0xd801_u16, + 0xdc40_u16, 0xd801_u16, 0xdc32_u16, 0xd801_u16, + 0xdc4b_u16, 0x0020_u16, 0xd801_u16, 0xdc0f_u16, + 0xd801_u16, 0xdc32_u16, 0xd801_u16, 0xdc4d_u16, + 0x000a_u16]), (~"𐌀𐌖𐌋𐌄𐌑𐌉·𐌌𐌄𐌕𐌄𐌋𐌉𐌑\n", ~[0xd800_u16, 0xdf00_u16, 0xd800_u16, 0xdf16_u16, - 0xd800_u16, 0xdf0b_u16, 0xd800_u16, 0xdf04_u16, - 0xd800_u16, 0xdf11_u16, 0xd800_u16, 0xdf09_u16, - 0x00b7_u16, 0xd800_u16, 0xdf0c_u16, 0xd800_u16, - 0xdf04_u16, 0xd800_u16, 0xdf15_u16, 0xd800_u16, - 0xdf04_u16, 0xd800_u16, 0xdf0b_u16, 0xd800_u16, - 0xdf09_u16, 0xd800_u16, 0xdf11_u16, 0x000a_u16 ]), + 0xd800_u16, 0xdf0b_u16, 0xd800_u16, 0xdf04_u16, + 0xd800_u16, 0xdf11_u16, 0xd800_u16, 0xdf09_u16, + 0x00b7_u16, 0xd800_u16, 0xdf0c_u16, 0xd800_u16, + 0xdf04_u16, 0xd800_u16, 0xdf15_u16, 0xd800_u16, + 0xdf04_u16, 0xd800_u16, 0xdf0b_u16, 0xd800_u16, + 0xdf09_u16, 0xd800_u16, 0xdf11_u16, 0x000a_u16 ]), (~"𐒋𐒘𐒈𐒑𐒛𐒒 𐒕𐒓 𐒈𐒚𐒍 𐒏𐒜𐒒𐒖𐒆 𐒕𐒆\n", ~[0xd801_u16, 0xdc8b_u16, 0xd801_u16, 0xdc98_u16, - 0xd801_u16, 0xdc88_u16, 0xd801_u16, 0xdc91_u16, - 0xd801_u16, 0xdc9b_u16, 0xd801_u16, 0xdc92_u16, - 0x0020_u16, 0xd801_u16, 0xdc95_u16, 0xd801_u16, - 0xdc93_u16, 0x0020_u16, 0xd801_u16, 0xdc88_u16, - 0xd801_u16, 0xdc9a_u16, 0xd801_u16, 0xdc8d_u16, - 0x0020_u16, 0xd801_u16, 0xdc8f_u16, 0xd801_u16, - 0xdc9c_u16, 0xd801_u16, 0xdc92_u16, 0xd801_u16, - 0xdc96_u16, 0xd801_u16, 0xdc86_u16, 0x0020_u16, - 0xd801_u16, 0xdc95_u16, 0xd801_u16, 0xdc86_u16, - 0x000a_u16 ]) ]; + 0xd801_u16, 0xdc88_u16, 0xd801_u16, 0xdc91_u16, + 0xd801_u16, 0xdc9b_u16, 0xd801_u16, 0xdc92_u16, + 0x0020_u16, 0xd801_u16, 0xdc95_u16, 0xd801_u16, + 0xdc93_u16, 0x0020_u16, 0xd801_u16, 0xdc88_u16, + 0xd801_u16, 0xdc9a_u16, 0xd801_u16, 0xdc8d_u16, + 0x0020_u16, 0xd801_u16, 0xdc8f_u16, 0xd801_u16, + 0xdc9c_u16, 0xd801_u16, 0xdc92_u16, 0xd801_u16, + 0xdc96_u16, 0xd801_u16, 0xdc86_u16, 0x0020_u16, + 0xd801_u16, 0xdc95_u16, 0xd801_u16, 0xdc86_u16, + 0x000a_u16 ]) ]; for pairs.each |p| { let (s, u) = copy *p; @@ -4219,7 +3956,7 @@ mod tests { let mut pos = 0; for s.each |b| { - assert!(b == v[pos]); + assert_eq!(b, v[pos]); pos += 1; } } @@ -4227,7 +3964,7 @@ mod tests { #[test] fn test_each_empty() { for "".each |b| { - assert!(b == 0u8); + assert_eq!(b, 0u8); } } @@ -4242,8 +3979,8 @@ mod tests { let mut pos = 0; for s.eachi |i, b| { - assert!(pos == i); - assert!(b == v[pos]); + assert_eq!(pos, i); + assert_eq!(b, v[pos]); pos += 1; } } @@ -4251,8 +3988,8 @@ mod tests { #[test] fn test_eachi_empty() { for "".eachi |i, b| { - assert!(i == 0); - assert!(b == 0); + assert_eq!(i, 0); + assert_eq!(b, 0); } } @@ -4268,14 +4005,14 @@ mod tests { for s.each_reverse |b| { pos -= 1; - assert!(b == v[pos]); + assert_eq!(b, v[pos]); } } #[test] fn test_each_empty_reverse() { for "".each_reverse |b| { - assert!(b == 0u8); + assert_eq!(b, 0u8); } } @@ -4291,16 +4028,16 @@ mod tests { for s.eachi_reverse |i, b| { pos -= 1; - assert!(pos == i); - assert!(b == v[pos]); + assert_eq!(pos, i); + assert_eq!(b, v[pos]); } } #[test] fn test_eachi_reverse_empty() { for "".eachi_reverse |i, b| { - assert!(i == 0); - assert!(b == 0); + assert_eq!(i, 0); + assert_eq!(b, 0); } } @@ -4310,7 +4047,7 @@ mod tests { let v = ~['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m']; let mut pos = 0; for s.each_char |ch| { - assert!(ch == v[pos]); + assert_eq!(ch, v[pos]); pos += 1; } } @@ -4321,8 +4058,8 @@ mod tests { let v = ~['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m']; let mut pos = 0; for s.each_chari |i, ch| { - assert!(pos == i); - assert!(ch == v[pos]); + assert_eq!(pos, i); + assert_eq!(ch, v[pos]); pos += 1; } } @@ -4334,7 +4071,7 @@ mod tests { let mut pos = v.len(); for s.each_char_reverse |ch| { pos -= 1; - assert!(ch == v[pos]); + assert_eq!(ch, v[pos]); } } @@ -4345,43 +4082,43 @@ mod tests { let mut pos = v.len(); for s.each_chari_reverse |i, ch| { pos -= 1; - assert!(pos == i); - assert!(ch == v[pos]); + assert_eq!(pos, i); + assert_eq!(ch, v[pos]); } } #[test] fn test_escape_unicode() { - assert!(escape_unicode(~"abc") == ~"\\x61\\x62\\x63"); - assert!(escape_unicode(~"a c") == ~"\\x61\\x20\\x63"); - assert!(escape_unicode(~"\r\n\t") == ~"\\x0d\\x0a\\x09"); - assert!(escape_unicode(~"'\"\\") == ~"\\x27\\x22\\x5c"); - assert!(escape_unicode(~"\x00\x01\xfe\xff") == + assert_eq!(escape_unicode("abc"), ~"\\x61\\x62\\x63"); + assert_eq!(escape_unicode("a c"), ~"\\x61\\x20\\x63"); + assert_eq!(escape_unicode("\r\n\t"), ~"\\x0d\\x0a\\x09"); + assert_eq!(escape_unicode("'\"\\"), ~"\\x27\\x22\\x5c"); + assert!(escape_unicode("\x00\x01\xfe\xff") == ~"\\x00\\x01\\xfe\\xff"); - assert!(escape_unicode(~"\u0100\uffff") == ~"\\u0100\\uffff"); - assert!(escape_unicode(~"\U00010000\U0010ffff") == + assert_eq!(escape_unicode("\u0100\uffff"), ~"\\u0100\\uffff"); + assert!(escape_unicode("\U00010000\U0010ffff") == ~"\\U00010000\\U0010ffff"); - assert!(escape_unicode(~"ab\ufb00") == ~"\\x61\\x62\\ufb00"); - assert!(escape_unicode(~"\U0001d4ea\r") == ~"\\U0001d4ea\\x0d"); + assert_eq!(escape_unicode("ab\ufb00"), ~"\\x61\\x62\\ufb00"); + assert_eq!(escape_unicode("\U0001d4ea\r"), ~"\\U0001d4ea\\x0d"); } #[test] fn test_escape_default() { - assert!(escape_default(~"abc") == ~"abc"); - assert!(escape_default(~"a c") == ~"a c"); - assert!(escape_default(~"\r\n\t") == ~"\\r\\n\\t"); - assert!(escape_default(~"'\"\\") == ~"\\'\\\"\\\\"); - assert!(escape_default(~"\u0100\uffff") == ~"\\u0100\\uffff"); - assert!(escape_default(~"\U00010000\U0010ffff") == + assert_eq!(escape_default("abc"), ~"abc"); + assert_eq!(escape_default("a c"), ~"a c"); + assert_eq!(escape_default("\r\n\t"), ~"\\r\\n\\t"); + assert_eq!(escape_default("'\"\\"), ~"\\'\\\"\\\\"); + assert_eq!(escape_default("\u0100\uffff"), ~"\\u0100\\uffff"); + assert!(escape_default("\U00010000\U0010ffff") == ~"\\U00010000\\U0010ffff"); - assert!(escape_default(~"ab\ufb00") == ~"ab\\ufb00"); - assert!(escape_default(~"\U0001d4ea\r") == ~"\\U0001d4ea\\r"); + assert_eq!(escape_default("ab\ufb00"), ~"ab\\ufb00"); + assert_eq!(escape_default("\U0001d4ea\r"), ~"\\U0001d4ea\\r"); } #[test] fn test_to_managed() { - assert!((~"abc").to_managed() == @"abc"); - assert!(slice("abcdef", 1, 5).to_managed() == @"bcde"); + assert_eq!("abc".to_managed(), @"abc"); + assert_eq!(slice("abcdef", 1, 5).to_managed(), @"bcde"); } #[test] @@ -4395,7 +4132,7 @@ mod tests { #[test] fn test_char_range_at_reverse_underflow() { - assert!(char_range_at_reverse("abc", 0).next == 0); + assert_eq!(char_range_at_reverse("abc", 0).next, 0); } #[test] diff --git a/src/libcore/str/ascii.rs b/src/libstd/str/ascii.rs similarity index 94% rename from src/libcore/str/ascii.rs rename to src/libstd/str/ascii.rs index 4e239c4c82c7d..3b31d70f7a1bd 100644 --- a/src/libcore/str/ascii.rs +++ b/src/libstd/str/ascii.rs @@ -21,22 +21,22 @@ use vec::{CopyableVector, ImmutableVector, OwnedVector}; #[deriving(Clone, Eq)] pub struct Ascii { priv chr: u8 } -pub impl Ascii { +impl Ascii { /// Converts a ascii character into a `u8`. #[inline(always)] - fn to_byte(self) -> u8 { + pub fn to_byte(self) -> u8 { self.chr } /// Converts a ascii character into a `char`. #[inline(always)] - fn to_char(self) -> char { + pub fn to_char(self) -> char { self.chr as char } /// Convert to lowercase. #[inline(always)] - fn to_lower(self) -> Ascii { + pub fn to_lower(self) -> Ascii { if self.chr >= 65 && self.chr <= 90 { Ascii{chr: self.chr | 0x20 } } else { @@ -46,7 +46,7 @@ pub impl Ascii { /// Convert to uppercase. #[inline(always)] - fn to_upper(self) -> Ascii { + pub fn to_upper(self) -> Ascii { if self.chr >= 97 && self.chr <= 122 { Ascii{chr: self.chr & !0x20 } } else { @@ -54,9 +54,9 @@ pub impl Ascii { } } - // Compares two ascii characters of equality, ignoring case. + /// Compares two ascii characters of equality, ignoring case. #[inline(always)] - fn eq_ignore_case(self, other: Ascii) -> bool { + pub fn eq_ignore_case(self, other: Ascii) -> bool { self.to_lower().chr == other.to_lower().chr } } @@ -228,8 +228,8 @@ mod tests { assert_eq!('`'.to_ascii().to_upper().to_char(), '`'); assert_eq!('{'.to_ascii().to_upper().to_char(), '{'); - assert!(str::all(~"banana", |c| c.is_ascii())); - assert!(! str::all(~"ประเทศไทย中华Việt Nam", |c| c.is_ascii())); + assert!(str::all("banana", |c| c.is_ascii())); + assert!(! str::all("ประเทศไทย中华Việt Nam", |c| c.is_ascii())); } #[test] diff --git a/src/libcore/sys.rs b/src/libstd/sys.rs similarity index 76% rename from src/libcore/sys.rs rename to src/libstd/sys.rs index 4eca7ebbb371e..583923bc2e3aa 100644 --- a/src/libcore/sys.rs +++ b/src/libstd/sys.rs @@ -10,6 +10,8 @@ //! Misc low level stuff +#[allow(missing_doc)]; + use option::{Some, None}; use cast; use cmp::{Eq, Ord}; @@ -19,6 +21,7 @@ use libc; use libc::{c_void, c_char, size_t}; use repr; use str; +use unstable::intrinsics; pub type FreeGlue<'self> = &'self fn(*TypeDesc, *c_void); @@ -38,16 +41,6 @@ pub struct Closure { env: *(), } -pub mod rusti { - #[abi = "rust-intrinsic"] - pub extern "rust-intrinsic" { - fn get_tydesc() -> *(); - fn size_of() -> uint; - fn pref_align_of() -> uint; - fn min_align_of() -> uint; - } -} - pub mod rustrt { use libc::{c_char, size_t}; @@ -59,20 +52,6 @@ pub mod rustrt { } } -/// Compares contents of two pointers using the default method. -/// Equivalent to `*x1 == *x2`. Useful for hashtables. -pub fn shape_eq(x1: &T, x2: &T) -> bool { - *x1 == *x2 -} - -pub fn shape_lt(x1: &T, x2: &T) -> bool { - *x1 < *x2 -} - -pub fn shape_le(x1: &T, x2: &T) -> bool { - *x1 <= *x2 -} - /** * Returns a pointer to a type descriptor. * @@ -81,7 +60,7 @@ pub fn shape_le(x1: &T, x2: &T) -> bool { */ #[inline(always)] pub fn get_type_desc() -> *TypeDesc { - unsafe { rusti::get_tydesc::() as *TypeDesc } + unsafe { intrinsics::get_tydesc::() as *TypeDesc } } /// Returns a pointer to a type descriptor. @@ -93,7 +72,7 @@ pub fn get_type_desc_val(_val: &T) -> *TypeDesc { /// Returns the size of a type #[inline(always)] pub fn size_of() -> uint { - unsafe { rusti::size_of::() } + unsafe { intrinsics::size_of::() } } /// Returns the size of the type that `_val` points to @@ -128,7 +107,7 @@ pub fn nonzero_size_of_val(_val: &T) -> uint { */ #[inline(always)] pub fn min_align_of() -> uint { - unsafe { rusti::min_align_of::() } + unsafe { intrinsics::min_align_of::() } } /// Returns the ABI-required minimum alignment of the type of the value that @@ -141,7 +120,7 @@ pub fn min_align_of_val(_val: &T) -> uint { /// Returns the preferred alignment of a type #[inline(always)] pub fn pref_align_of() -> uint { - unsafe { rusti::pref_align_of::() } + unsafe { intrinsics::pref_align_of::() } } /// Returns the preferred alignment of the type of the value that @@ -202,10 +181,13 @@ impl FailWithCause for &'static str { // FIXME #4427: Temporary until rt::rt_fail_ goes away pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! { - use rt::{context, OldTaskContext}; - use rt::local_services::unsafe_borrow_local_services; + use option::Option; + use rt::{context, OldTaskContext, TaskContext}; + use rt::task::{Task, Unwinder}; + use rt::local::Local; - match context() { + let context = context(); + match context { OldTaskContext => { unsafe { gc::cleanup_stack_for_failure(); @@ -214,11 +196,26 @@ pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! { } } _ => { - // XXX: Need to print the failure message - gc::cleanup_stack_for_failure(); unsafe { - let local_services = unsafe_borrow_local_services(); - match local_services.unwinder { + // XXX: Bad re-allocations. fail! needs some refactoring + let msg = str::raw::from_c_str(msg); + let file = str::raw::from_c_str(file); + + let outmsg = fmt!("%s at line %i of file %s", msg, line as int, file); + + // XXX: Logging doesn't work correctly in non-task context because it + // invokes the local heap + if context == TaskContext { + error!(outmsg); + } else { + rtdebug!("%s", outmsg); + } + + gc::cleanup_stack_for_failure(); + + let task = Local::unsafe_borrow::(); + let unwinder: &mut Option = &mut (*task).unwinder; + match *unwinder { Some(ref mut unwinder) => unwinder.begin_unwind(), None => abort!("failure without unwinder. aborting process") } @@ -234,10 +231,10 @@ mod tests { #[test] fn size_of_basic() { - assert!(size_of::() == 1u); - assert!(size_of::() == 2u); - assert!(size_of::() == 4u); - assert!(size_of::() == 8u); + assert_eq!(size_of::(), 1u); + assert_eq!(size_of::(), 2u); + assert_eq!(size_of::(), 4u); + assert_eq!(size_of::(), 8u); } #[test] @@ -245,15 +242,15 @@ mod tests { #[cfg(target_arch = "arm")] #[cfg(target_arch = "mips")] fn size_of_32() { - assert!(size_of::() == 4u); - assert!(size_of::<*uint>() == 4u); + assert_eq!(size_of::(), 4u); + assert_eq!(size_of::<*uint>(), 4u); } #[test] #[cfg(target_arch = "x86_64")] fn size_of_64() { - assert!(size_of::() == 8u); - assert!(size_of::<*uint>() == 8u); + assert_eq!(size_of::(), 8u); + assert_eq!(size_of::<*uint>(), 8u); } #[test] @@ -267,9 +264,9 @@ mod tests { #[test] fn nonzero_size_of_basic() { type Z = [i8, ..0]; - assert!(size_of::() == 0u); - assert!(nonzero_size_of::() == 1u); - assert!(nonzero_size_of::() == size_of::()); + assert_eq!(size_of::(), 0u); + assert_eq!(nonzero_size_of::(), 1u); + assert_eq!(nonzero_size_of::(), size_of::()); } #[test] @@ -282,9 +279,9 @@ mod tests { #[test] fn align_of_basic() { - assert!(pref_align_of::() == 1u); - assert!(pref_align_of::() == 2u); - assert!(pref_align_of::() == 4u); + assert_eq!(pref_align_of::(), 1u); + assert_eq!(pref_align_of::(), 2u); + assert_eq!(pref_align_of::(), 4u); } #[test] @@ -292,15 +289,15 @@ mod tests { #[cfg(target_arch = "arm")] #[cfg(target_arch = "mips")] fn align_of_32() { - assert!(pref_align_of::() == 4u); - assert!(pref_align_of::<*uint>() == 4u); + assert_eq!(pref_align_of::(), 4u); + assert_eq!(pref_align_of::<*uint>(), 4u); } #[test] #[cfg(target_arch = "x86_64")] fn align_of_64() { - assert!(pref_align_of::() == 8u); - assert!(pref_align_of::<*uint>() == 8u); + assert_eq!(pref_align_of::(), 8u); + assert_eq!(pref_align_of::<*uint>(), 8u); } #[test] @@ -316,7 +313,7 @@ mod tests { let x = 10; let f: &fn(int) -> int = |y| x + y; - assert!(f(20) == 30); + assert_eq!(f(20), 30); let original_closure: Closure = cast::transmute(f); @@ -329,7 +326,7 @@ mod tests { }; let new_f: &fn(int) -> int = cast::transmute(new_closure); - assert!(new_f(20) == 30); + assert_eq!(new_f(20), 30); } } diff --git a/src/libcore/task/local_data_priv.rs b/src/libstd/task/local_data_priv.rs similarity index 96% rename from src/libcore/task/local_data_priv.rs rename to src/libstd/task/local_data_priv.rs index 766815a5e90b6..f6b14a5153970 100644 --- a/src/libcore/task/local_data_priv.rs +++ b/src/libstd/task/local_data_priv.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[doc(hidden)]; // FIXME #3538 +#[allow(missing_doc)]; use cast; use cmp::Eq; @@ -18,7 +18,7 @@ use task::rt; use local_data::LocalDataKey; use super::rt::rust_task; -use rt::local_services::LocalStorage; +use rt::task::{Task, LocalStorage}; pub enum Handle { OldHandle(*rust_task), @@ -28,15 +28,15 @@ pub enum Handle { impl Handle { pub fn new() -> Handle { use rt::{context, OldTaskContext}; - use rt::local_services::unsafe_borrow_local_services; + use rt::local::Local; unsafe { match context() { OldTaskContext => { OldHandle(rt::rust_get_task()) } _ => { - let local_services = unsafe_borrow_local_services(); - NewHandle(&mut local_services.storage) + let task = Local::unsafe_borrow::(); + NewHandle(&mut (*task).storage) } } } diff --git a/src/libcore/task/mod.rs b/src/libstd/task/mod.rs similarity index 92% rename from src/libcore/task/mod.rs rename to src/libstd/task/mod.rs index d57bd5528bce4..223afbce091b8 100644 --- a/src/libcore/task/mod.rs +++ b/src/libstd/task/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -33,18 +33,26 @@ * ~~~ */ +#[allow(missing_doc)]; + +use prelude::*; + use cell::Cell; use cmp::Eq; -use result::Result; use comm::{stream, Chan, GenericChan, GenericPort, Port}; -use prelude::*; +use result::Result; use result; +use rt::{context, OldTaskContext}; use task::rt::{task_id, sched_id}; -use util; -use util::replace; use unstable::finally::Finally; +use util::replace; +use util; +#[cfg(test)] use cast; #[cfg(test)] use comm::SharedChan; +#[cfg(test)] use comm; +#[cfg(test)] use ptr; +#[cfg(test)] use task; mod local_data_priv; pub mod rt; @@ -194,8 +202,7 @@ pub fn task() -> TaskBuilder { } } -#[doc(hidden)] // FIXME #3538 -priv impl TaskBuilder { +impl TaskBuilder { fn consume(&mut self) -> TaskBuilder { if self.consumed { fail!("Cannot copy a task_builder"); // Fake move mode on self @@ -217,24 +224,24 @@ priv impl TaskBuilder { } } -pub impl TaskBuilder { +impl TaskBuilder { /// Decouple the child task's failure from the parent's. If either fails, /// the other will not be killed. - fn unlinked(&mut self) { + pub fn unlinked(&mut self) { self.opts.linked = false; } /// Unidirectionally link the child task's failure with the parent's. The /// child's failure will not kill the parent, but the parent's will kill /// the child. - fn supervised(&mut self) { + pub fn supervised(&mut self) { self.opts.supervised = true; self.opts.linked = false; } /// Link the child task's and parent task's failures. If either fails, the /// other will be killed. - fn linked(&mut self) { + pub fn linked(&mut self) { self.opts.linked = true; self.opts.supervised = false; } @@ -256,7 +263,7 @@ pub impl TaskBuilder { * # Failure * Fails if a future_result was already set for this task. */ - fn future_result(&mut self, blk: &fn(v: Port)) { + pub fn future_result(&mut self, blk: &fn(v: Port)) { // FIXME (#3725): Once linked failure and notification are // handled in the library, I can imagine implementing this by just // registering an arbitrary number of task::on_exit handlers and @@ -276,7 +283,7 @@ pub impl TaskBuilder { } /// Configure a custom scheduler mode for the task. - fn sched_mode(&mut self, mode: SchedMode) { + pub fn sched_mode(&mut self, mode: SchedMode) { self.opts.sched.mode = mode; } @@ -292,7 +299,7 @@ pub impl TaskBuilder { * generator by applying the task body which results from the * existing body generator to the new body generator. */ - fn add_wrapper(&mut self, wrapper: ~fn(v: ~fn()) -> ~fn()) { + pub fn add_wrapper(&mut self, wrapper: ~fn(v: ~fn()) -> ~fn()) { let prev_gen_body = replace(&mut self.gen_body, None); let prev_gen_body = match prev_gen_body { Some(gen) => gen, @@ -301,7 +308,7 @@ pub impl TaskBuilder { f } }; - let prev_gen_body = Cell(prev_gen_body); + let prev_gen_body = Cell::new(prev_gen_body); let next_gen_body = { let f: ~fn(~fn()) -> ~fn() = |body| { let prev_gen_body = prev_gen_body.take(); @@ -324,7 +331,7 @@ pub impl TaskBuilder { * When spawning into a new scheduler, the number of threads requested * must be greater than zero. */ - fn spawn(&mut self, f: ~fn()) { + pub fn spawn(&mut self, f: ~fn()) { let gen_body = replace(&mut self.gen_body, None); let notify_chan = replace(&mut self.opts.notify_chan, None); let x = self.consume(); @@ -346,8 +353,8 @@ pub impl TaskBuilder { } /// Runs a task, while transfering ownership of one argument to the child. - fn spawn_with(&mut self, arg: A, f: ~fn(v: A)) { - let arg = Cell(arg); + pub fn spawn_with(&mut self, arg: A, f: ~fn(v: A)) { + let arg = Cell::new(arg); do self.spawn { f(arg.take()); } @@ -366,7 +373,7 @@ pub impl TaskBuilder { * # Failure * Fails if a future_result was already set for this task. */ - fn try(&mut self, f: ~fn() -> T) -> Result { + pub fn try(&mut self, f: ~fn() -> T) -> Result { let (po, ch) = stream::(); let mut result = None; @@ -503,7 +510,8 @@ pub fn failing() -> bool { //! True if the running task has failed use rt::{context, OldTaskContext}; - use rt::local_services::borrow_local_services; + use rt::local::Local; + use rt::task::Task; match context() { OldTaskContext => { @@ -513,7 +521,7 @@ pub fn failing() -> bool { } _ => { let mut unwinding = false; - do borrow_local_services |local| { + do Local::borrow:: |local| { unwinding = match local.unwinder { Some(unwinder) => { unwinder.unwinding @@ -558,23 +566,33 @@ pub fn get_scheduler() -> Scheduler { * ~~~ */ pub unsafe fn unkillable(f: &fn() -> U) -> U { - let t = rt::rust_get_task(); - do (|| { - rt::rust_task_inhibit_kill(t); + if context() == OldTaskContext { + let t = rt::rust_get_task(); + do (|| { + rt::rust_task_inhibit_kill(t); + f() + }).finally { + rt::rust_task_allow_kill(t); + } + } else { + // FIXME #6377 f() - }).finally { - rt::rust_task_allow_kill(t); } } /// The inverse of unkillable. Only ever to be used nested in unkillable(). pub unsafe fn rekillable(f: &fn() -> U) -> U { - let t = rt::rust_get_task(); - do (|| { - rt::rust_task_allow_kill(t); + if context() == OldTaskContext { + let t = rt::rust_get_task(); + do (|| { + rt::rust_task_allow_kill(t); + f() + }).finally { + rt::rust_task_inhibit_kill(t); + } + } else { + // FIXME #6377 f() - }).finally { - rt::rust_task_inhibit_kill(t); } } @@ -583,14 +601,19 @@ pub unsafe fn rekillable(f: &fn() -> U) -> U { * For use with exclusive ARCs, which use pthread mutexes directly. */ pub unsafe fn atomically(f: &fn() -> U) -> U { - let t = rt::rust_get_task(); - do (|| { - rt::rust_task_inhibit_kill(t); - rt::rust_task_inhibit_yield(t); + if context() == OldTaskContext { + let t = rt::rust_get_task(); + do (|| { + rt::rust_task_inhibit_kill(t); + rt::rust_task_inhibit_yield(t); + f() + }).finally { + rt::rust_task_allow_yield(t); + rt::rust_task_allow_kill(t); + } + } else { + // FIXME #6377 f() - }).finally { - rt::rust_task_allow_yield(t); - rt::rust_task_allow_kill(t); } } @@ -619,7 +642,7 @@ fn test_spawn_unlinked_unsup_no_fail_down() { // grandchild sends on a port let ch = ch.clone(); do spawn_unlinked { // Give middle task a chance to fail-but-not-kill-us. - for old_iter::repeat(16) { task::yield(); } + for 16.times { task::yield(); } ch.send(()); // If killed first, grandparent hangs. } fail!(); // Shouldn't kill either (grand)parent or (grand)child. @@ -634,7 +657,7 @@ fn test_spawn_unlinked_unsup_no_fail_up() { // child unlinked fails fn test_spawn_unlinked_sup_no_fail_up() { // child unlinked fails do spawn_supervised { fail!(); } // Give child a chance to fail-but-not-kill-us. - for old_iter::repeat(16) { task::yield(); } + for 16.times { task::yield(); } } #[test] #[should_fail] #[ignore(cfg(windows))] fn test_spawn_unlinked_sup_fail_down() { @@ -709,7 +732,7 @@ fn test_spawn_failure_propagate_grandchild() { loop { task::yield(); } } } - for old_iter::repeat(16) { task::yield(); } + for 16.times { task::yield(); } fail!(); } @@ -721,7 +744,7 @@ fn test_spawn_failure_propagate_secondborn() { loop { task::yield(); } } } - for old_iter::repeat(16) { task::yield(); } + for 16.times { task::yield(); } fail!(); } @@ -733,7 +756,7 @@ fn test_spawn_failure_propagate_nephew_or_niece() { loop { task::yield(); } } } - for old_iter::repeat(16) { task::yield(); } + for 16.times { task::yield(); } fail!(); } @@ -745,7 +768,7 @@ fn test_spawn_linked_sup_propagate_sibling() { loop { task::yield(); } } } - for old_iter::repeat(16) { task::yield(); } + for 16.times { task::yield(); } fail!(); } @@ -768,9 +791,9 @@ struct Wrapper { fn test_add_wrapper() { let (po, ch) = stream::<()>(); let mut b0 = task(); - let ch = Cell(ch); + let ch = Cell::new(ch); do b0.add_wrapper |body| { - let ch = Cell(ch.take()); + let ch = Cell::new(ch.take()); let result: ~fn() = || { let ch = ch.take(); body(); @@ -789,7 +812,7 @@ fn test_future_result() { let mut builder = task(); builder.future_result(|r| result = Some(r)); do builder.spawn {} - assert!(result.unwrap().recv() == Success); + assert_eq!(result.unwrap().recv(), Success); result = None; let mut builder = task(); @@ -798,7 +821,7 @@ fn test_future_result() { do builder.spawn { fail!(); } - assert!(result.unwrap().recv() == Failure); + assert_eq!(result.unwrap().recv(), Failure); } #[test] #[should_fail] #[ignore(cfg(windows))] @@ -867,15 +890,15 @@ fn test_spawn_sched_childs_on_default_sched() { // Assuming tests run on the default scheduler let default_id = unsafe { rt::rust_get_sched_id() }; - let ch = Cell(ch); + let ch = Cell::new(ch); do spawn_sched(SingleThreaded) { let parent_sched_id = unsafe { rt::rust_get_sched_id() }; - let ch = Cell(ch.take()); + let ch = Cell::new(ch.take()); do spawn { let ch = ch.take(); let child_sched_id = unsafe { rt::rust_get_sched_id() }; assert!(parent_sched_id != child_sched_id); - assert!(child_sched_id == default_id); + assert_eq!(child_sched_id, default_id); ch.send(()); }; }; @@ -904,8 +927,7 @@ fn test_spawn_sched_blocking() { // Testing that a task in one scheduler can block in foreign code // without affecting other schedulers - for old_iter::repeat(20u) { - + for 20u.times { let (start_po, start_ch) = stream(); let (fin_po, fin_ch) = stream(); @@ -969,7 +991,7 @@ fn avoid_copying_the_body(spawnfn: &fn(v: ~fn())) { } let x_in_child = p.recv(); - assert!(x_in_parent == x_in_child); + assert_eq!(x_in_parent, x_in_child); } #[test] @@ -1024,7 +1046,7 @@ fn test_unkillable() { // We want to do this after failing do spawn_unlinked { - for old_iter::repeat(10) { yield() } + for 10.times { yield() } ch.send(()); } @@ -1059,7 +1081,7 @@ fn test_unkillable_nested() { // We want to do this after failing do spawn_unlinked || { - for old_iter::repeat(10) { yield() } + for 10.times { yield() } ch.send(()); } @@ -1127,7 +1149,7 @@ fn test_sched_thread_per_core() { unsafe { let cores = rt::rust_num_threads(); let reported_threads = rt::rust_sched_threads(); - assert!((cores as uint == reported_threads as uint)); + assert_eq!(cores as uint, reported_threads as uint); chan.send(()); } } @@ -1142,9 +1164,9 @@ fn test_spawn_thread_on_demand() { do spawn_sched(ManualThreads(2)) || { unsafe { let max_threads = rt::rust_sched_threads(); - assert!((max_threads as int == 2)); + assert_eq!(max_threads as int, 2); let running_threads = rt::rust_sched_current_nonlazy_threads(); - assert!((running_threads as int == 1)); + assert_eq!(running_threads as int, 1); let (port2, chan2) = comm::stream(); @@ -1153,7 +1175,7 @@ fn test_spawn_thread_on_demand() { } let running_threads2 = rt::rust_sched_current_nonlazy_threads(); - assert!((running_threads2 as int == 2)); + assert_eq!(running_threads2 as int, 2); port2.recv(); chan.send(()); diff --git a/src/libcore/task/rt.rs b/src/libstd/task/rt.rs similarity index 98% rename from src/libcore/task/rt.rs rename to src/libstd/task/rt.rs index 760812252bc73..4860ab36f7729 100644 --- a/src/libcore/task/rt.rs +++ b/src/libstd/task/rt.rs @@ -14,7 +14,7 @@ The task interface to the runtime */ -#[doc(hidden)]; // FIXME #3538 +#[doc(hidden)]; use libc; diff --git a/src/libcore/task/spawn.rs b/src/libstd/task/spawn.rs similarity index 98% rename from src/libcore/task/spawn.rs rename to src/libstd/task/spawn.rs index fc38702bc1605..87e9296657f48 100644 --- a/src/libcore/task/spawn.rs +++ b/src/libstd/task/spawn.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -70,14 +70,15 @@ * ****************************************************************************/ -#[doc(hidden)]; // FIXME #3538 +#[doc(hidden)]; + +use prelude::*; use cast::transmute; use cast; use cell::Cell; use container::Map; use comm::{Chan, GenericChan}; -use prelude::*; use ptr; use hashmap::HashSet; use task::local_data_priv::{local_get, local_set, OldHandle}; @@ -90,8 +91,11 @@ use task::unkillable; use uint; use util; use unstable::sync::{Exclusive, exclusive}; +use rt::local::Local; #[cfg(test)] use task::default_task_opts; +#[cfg(test)] use comm; +#[cfg(test)] use task; macro_rules! move_it ( { $x:expr } => ( unsafe { let y = *ptr::to_unsafe_ptr(&($x)); y } ) @@ -110,11 +114,6 @@ fn taskset_remove(tasks: &mut TaskSet, task: *rust_task) { let was_present = tasks.remove(&task); assert!(was_present); } -#[cfg(stage0)] -pub fn taskset_each(tasks: &TaskSet, blk: &fn(v: *rust_task) -> bool) { - tasks.each(|k| blk(*k)) -} -#[cfg(not(stage0))] pub fn taskset_each(tasks: &TaskSet, blk: &fn(v: *rust_task) -> bool) -> bool { tasks.each(|k| blk(*k)) } @@ -163,13 +162,17 @@ struct AncestorList(Option>); // Accessors for taskgroup arcs and ancestor arcs that wrap the unsafety. #[inline(always)] fn access_group(x: &TaskGroupArc, blk: &fn(TaskGroupInner) -> U) -> U { - x.with(blk) + unsafe { + x.with(blk) + } } #[inline(always)] fn access_ancestors(x: &Exclusive, blk: &fn(x: &mut AncestorNode) -> U) -> U { - x.with(blk) + unsafe { + x.with(blk) + } } // Iterates over an ancestor list. @@ -580,8 +583,8 @@ pub fn spawn_raw(opts: TaskOpts, f: ~fn()) { fn spawn_raw_newsched(_opts: TaskOpts, f: ~fn()) { use rt::sched::*; - let mut sched = local_sched::take(); - let task = ~Task::new(&mut sched.stack_pool, f); + let mut sched = Local::take::(); + let task = ~Coroutine::new(&mut sched.stack_pool, f); sched.schedule_new_task(task); } @@ -591,7 +594,7 @@ fn spawn_raw_oldsched(mut opts: TaskOpts, f: ~fn()) { gen_child_taskgroup(opts.linked, opts.supervised); unsafe { - let child_data = Cell((child_tg, ancestors, f)); + let child_data = Cell::new((child_tg, ancestors, f)); // Being killed with the unsafe task/closure pointers would leak them. do unkillable { // Agh. Get move-mode items into the closure. FIXME (#2829) @@ -633,7 +636,7 @@ fn spawn_raw_oldsched(mut opts: TaskOpts, f: ~fn()) { notify_chan: Option>, f: ~fn()) -> ~fn() { - let child_data = Cell((child_arc, ancestors)); + let child_data = Cell::new((child_arc, ancestors)); let result: ~fn() = || { // Agh. Get move-mode items into the closure. FIXME (#2829) let mut (child_arc, ancestors) = child_data.take(); @@ -774,7 +777,7 @@ fn test_spawn_raw_notify_success() { }; do spawn_raw(opts) { } - assert!(notify_po.recv() == Success); + assert_eq!(notify_po.recv(), Success); } #[test] @@ -791,5 +794,5 @@ fn test_spawn_raw_notify_failure() { do spawn_raw(opts) { fail!(); } - assert!(notify_po.recv() == Failure); + assert_eq!(notify_po.recv(), Failure); } diff --git a/src/libstd/term.rs b/src/libstd/term.rs deleted file mode 100644 index 236c7f668c2e0..0000000000000 --- a/src/libstd/term.rs +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Simple ANSI color library - -use core::io; -use core::option; -use core::os; - -// FIXME (#2807): Windows support. - -pub static color_black: u8 = 0u8; -pub static color_red: u8 = 1u8; -pub static color_green: u8 = 2u8; -pub static color_yellow: u8 = 3u8; -pub static color_blue: u8 = 4u8; -pub static color_magenta: u8 = 5u8; -pub static color_cyan: u8 = 6u8; -pub static color_light_gray: u8 = 7u8; -pub static color_light_grey: u8 = 7u8; -pub static color_dark_gray: u8 = 8u8; -pub static color_dark_grey: u8 = 8u8; -pub static color_bright_red: u8 = 9u8; -pub static color_bright_green: u8 = 10u8; -pub static color_bright_yellow: u8 = 11u8; -pub static color_bright_blue: u8 = 12u8; -pub static color_bright_magenta: u8 = 13u8; -pub static color_bright_cyan: u8 = 14u8; -pub static color_bright_white: u8 = 15u8; - -pub fn esc(writer: @io::Writer) { writer.write(~[0x1bu8, '[' as u8]); } - -/// Reset the foreground and background colors to default -pub fn reset(writer: @io::Writer) { - esc(writer); - writer.write(~['0' as u8, 'm' as u8]); -} - -/// Returns true if the terminal supports color -pub fn color_supported() -> bool { - let supported_terms = ~[~"xterm-color", ~"xterm", - ~"screen-bce", ~"xterm-256color"]; - return match os::getenv(~"TERM") { - option::Some(ref env) => { - for supported_terms.each |term| { - if *term == *env { return true; } - } - false - } - option::None => false - }; -} - -pub fn set_color(writer: @io::Writer, first_char: u8, color: u8) { - assert!((color < 16u8)); - esc(writer); - let mut color = color; - if color >= 8u8 { writer.write(~['1' as u8, ';' as u8]); color -= 8u8; } - writer.write(~[first_char, ('0' as u8) + color, 'm' as u8]); -} - -/// Set the foreground color -pub fn fg(writer: @io::Writer, color: u8) { - return set_color(writer, '3' as u8, color); -} - -/// Set the background color -pub fn bg(writer: @io::Writer, color: u8) { - return set_color(writer, '4' as u8, color); -} diff --git a/src/libstd/to_bytes.rs b/src/libstd/to_bytes.rs new file mode 100644 index 0000000000000..77e7583ebe532 --- /dev/null +++ b/src/libstd/to_bytes.rs @@ -0,0 +1,322 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/*! + +The `ToBytes` and `IterBytes` traits + +*/ + +use io; +use io::Writer; +use option::{None, Option, Some}; +use old_iter::BaseIter; +use str; + +pub type Cb<'self> = &'self fn(buf: &[u8]) -> bool; + +/** + * A trait to implement in order to make a type hashable; + * This works in combination with the trait `Hash::Hash`, and + * may in the future be merged with that trait or otherwise + * modified when default methods and trait inheritence are + * completed. + */ +pub trait IterBytes { + /** + * Call the provided callback `f` one or more times with + * byte-slices that should be used when computing a hash + * value or otherwise "flattening" the structure into + * a sequence of bytes. The `lsb0` parameter conveys + * whether the caller is asking for little-endian bytes + * (`true`) or big-endian (`false`); this should only be + * relevant in implementations that represent a single + * multi-byte datum such as a 32 bit integer or 64 bit + * floating-point value. It can be safely ignored for + * larger structured types as they are usually processed + * left-to-right in declaration order, regardless of + * underlying memory endianness. + */ + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool; +} + +impl IterBytes for bool { + #[inline(always)] + fn iter_bytes(&self, _lsb0: bool, f: Cb) -> bool { + f([ + *self as u8 + ]) + } +} + +impl IterBytes for u8 { + #[inline(always)] + fn iter_bytes(&self, _lsb0: bool, f: Cb) -> bool { + f([ + *self + ]) + } +} + +impl IterBytes for u16 { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + if lsb0 { + f([ + *self as u8, + (*self >> 8) as u8 + ]) + } else { + f([ + (*self >> 8) as u8, + *self as u8 + ]) + } + } +} + +impl IterBytes for u32 { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + if lsb0 { + f([ + *self as u8, + (*self >> 8) as u8, + (*self >> 16) as u8, + (*self >> 24) as u8, + ]) + } else { + f([ + (*self >> 24) as u8, + (*self >> 16) as u8, + (*self >> 8) as u8, + *self as u8 + ]) + } + } +} + +impl IterBytes for u64 { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + if lsb0 { + f([ + *self as u8, + (*self >> 8) as u8, + (*self >> 16) as u8, + (*self >> 24) as u8, + (*self >> 32) as u8, + (*self >> 40) as u8, + (*self >> 48) as u8, + (*self >> 56) as u8 + ]) + } else { + f([ + (*self >> 56) as u8, + (*self >> 48) as u8, + (*self >> 40) as u8, + (*self >> 32) as u8, + (*self >> 24) as u8, + (*self >> 16) as u8, + (*self >> 8) as u8, + *self as u8 + ]) + } + } +} + +impl IterBytes for i8 { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + (*self as u8).iter_bytes(lsb0, f) + } +} + +impl IterBytes for i16 { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + (*self as u16).iter_bytes(lsb0, f) + } +} + +impl IterBytes for i32 { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + (*self as u32).iter_bytes(lsb0, f) + } +} + +impl IterBytes for i64 { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + (*self as u64).iter_bytes(lsb0, f) + } +} + +impl IterBytes for char { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + (*self as u32).iter_bytes(lsb0, f) + } +} + +#[cfg(target_word_size = "32")] +impl IterBytes for uint { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + (*self as u32).iter_bytes(lsb0, f) + } +} + +#[cfg(target_word_size = "64")] +impl IterBytes for uint { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + (*self as u64).iter_bytes(lsb0, f) + } +} + +impl IterBytes for int { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + (*self as uint).iter_bytes(lsb0, f) + } +} + +impl<'self,A:IterBytes> IterBytes for &'self [A] { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + self.each(|elt| elt.iter_bytes(lsb0, |b| f(b))) + } +} + +impl IterBytes for (A,B) { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + match *self { + (ref a, ref b) => { a.iter_bytes(lsb0, f) && b.iter_bytes(lsb0, f) } + } + } +} + +impl IterBytes for (A,B,C) { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + match *self { + (ref a, ref b, ref c) => { + a.iter_bytes(lsb0, f) && b.iter_bytes(lsb0, f) && c.iter_bytes(lsb0, f) + } + } + } +} + +// Move this to vec, probably. +fn borrow<'x,A>(a: &'x [A]) -> &'x [A] { + a +} + +impl IterBytes for ~[A] { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + borrow(*self).iter_bytes(lsb0, f) + } +} + +impl IterBytes for @[A] { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + borrow(*self).iter_bytes(lsb0, f) + } +} + +impl<'self> IterBytes for &'self str { + #[inline(always)] + fn iter_bytes(&self, _lsb0: bool, f: Cb) -> bool { + do str::byte_slice(*self) |bytes| { + f(bytes) + } + } +} + +impl IterBytes for ~str { + #[inline(always)] + fn iter_bytes(&self, _lsb0: bool, f: Cb) -> bool { + do str::byte_slice(*self) |bytes| { + f(bytes) + } + } +} + +impl IterBytes for @str { + #[inline(always)] + fn iter_bytes(&self, _lsb0: bool, f: Cb) -> bool { + do str::byte_slice(*self) |bytes| { + f(bytes) + } + } +} + +impl IterBytes for Option { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + match *self { + Some(ref a) => 0u8.iter_bytes(lsb0, f) && a.iter_bytes(lsb0, f), + None => 1u8.iter_bytes(lsb0, f) + } + } +} + +impl<'self,A:IterBytes> IterBytes for &'self A { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + (**self).iter_bytes(lsb0, f) + } +} + +impl IterBytes for @A { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + (**self).iter_bytes(lsb0, f) + } +} + +impl IterBytes for ~A { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + (**self).iter_bytes(lsb0, f) + } +} + +// NB: raw-pointer IterBytes does _not_ dereference +// to the target; it just gives you the pointer-bytes. +impl IterBytes for *const A { + #[inline(always)] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + (*self as uint).iter_bytes(lsb0, f) + } +} + +/// A trait for converting a value to a list of bytes. +pub trait ToBytes { + /// Converts the current value to a list of bytes. This is equivalent to + /// invoking iter_bytes on a type and collecting all yielded values in an + /// array + fn to_bytes(&self, lsb0: bool) -> ~[u8]; +} + +impl ToBytes for A { + fn to_bytes(&self, lsb0: bool) -> ~[u8] { + do io::with_bytes_writer |wr| { + for self.iter_bytes(lsb0) |bytes| { + wr.write(bytes) + } + } + } +} diff --git a/src/libcore/to_str.rs b/src/libstd/to_str.rs similarity index 74% rename from src/libcore/to_str.rs rename to src/libstd/to_str.rs index 365cb847740b2..3cc64147964cb 100644 --- a/src/libcore/to_str.rs +++ b/src/libstd/to_str.rs @@ -22,20 +22,18 @@ use hash::Hash; use cmp::Eq; use old_iter::BaseIter; +/// A generic trait for converting a value to a string pub trait ToStr { + /// Converts the value of `self` to an owned string fn to_str(&self) -> ~str; } /// Trait for converting a type to a string, consuming it in the process. pub trait ToStrConsume { - // Cosume and convert to a string. + /// Cosume and convert to a string. fn to_str_consume(self) -> ~str; } -impl ToStr for bool { - #[inline(always)] - fn to_str(&self) -> ~str { ::bool::to_str(*self) } -} impl ToStr for () { #[inline(always)] fn to_str(&self) -> ~str { ~"()" } @@ -46,7 +44,7 @@ impl ToStr for (A,) { fn to_str(&self) -> ~str { match *self { (ref a,) => { - ~"(" + a.to_str() + ~", " + ~")" + ~"(" + a.to_str() + ",)" } } } @@ -55,7 +53,7 @@ impl ToStr for (A,) { impl ToStr for HashMap { #[inline(always)] fn to_str(&self) -> ~str { - let mut acc = ~"{", first = true; + let mut (acc, first) = (~"{", true); for self.each |key, value| { if first { first = false; @@ -75,18 +73,18 @@ impl ToStr for HashMap { impl ToStr for HashSet { #[inline(always)] fn to_str(&self) -> ~str { - let mut acc = ~"{", first = true; - for self.each |element| { - if first { - first = false; - } - else { - acc.push_str(", "); + let mut (acc, first) = (~"{", true); + for self.each |element| { + if first { + first = false; + } + else { + acc.push_str(", "); + } + acc.push_str(element.to_str()); } - acc.push_str(element.to_str()); - } - acc.push_char('}'); - acc + acc.push_char('}'); + acc } } @@ -97,7 +95,7 @@ impl ToStr for (A, B) { //let &(ref a, ref b) = self; match *self { (ref a, ref b) => { - ~"(" + a.to_str() + ~", " + b.to_str() + ~")" + ~"(" + a.to_str() + ", " + b.to_str() + ")" } } } @@ -123,7 +121,7 @@ impl ToStr for (A, B, C) { impl<'self,A:ToStr> ToStr for &'self [A] { #[inline(always)] fn to_str(&self) -> ~str { - let mut acc = ~"[", first = true; + let mut (acc, first) = (~"[", true); for self.each |elt| { if first { first = false; @@ -141,7 +139,7 @@ impl<'self,A:ToStr> ToStr for &'self [A] { impl ToStr for ~[A] { #[inline(always)] fn to_str(&self) -> ~str { - let mut acc = ~"[", first = true; + let mut (acc, first) = (~"[", true); for self.each |elt| { if first { first = false; @@ -159,7 +157,7 @@ impl ToStr for ~[A] { impl ToStr for @[A] { #[inline(always)] fn to_str(&self) -> ~str { - let mut acc = ~"[", first = true; + let mut (acc, first) = (~"[", true); for self.each |elt| { if first { first = false; @@ -182,30 +180,30 @@ mod tests { use container::Set; #[test] fn test_simple_types() { - assert!(1i.to_str() == ~"1"); - assert!((-1i).to_str() == ~"-1"); - assert!(200u.to_str() == ~"200"); - assert!(2u8.to_str() == ~"2"); - assert!(true.to_str() == ~"true"); - assert!(false.to_str() == ~"false"); - assert!(().to_str() == ~"()"); - assert!((~"hi").to_str() == ~"hi"); - assert!((@"hi").to_str() == ~"hi"); + assert_eq!(1i.to_str(), ~"1"); + assert_eq!((-1i).to_str(), ~"-1"); + assert_eq!(200u.to_str(), ~"200"); + assert_eq!(2u8.to_str(), ~"2"); + assert_eq!(true.to_str(), ~"true"); + assert_eq!(false.to_str(), ~"false"); + assert_eq!(().to_str(), ~"()"); + assert_eq!((~"hi").to_str(), ~"hi"); + assert_eq!((@"hi").to_str(), ~"hi"); } #[test] fn test_tuple_types() { - assert!((1, 2).to_str() == ~"(1, 2)"); - assert!((~"a", ~"b", false).to_str() == ~"(a, b, false)"); - assert!(((), ((), 100)).to_str() == ~"((), ((), 100))"); + assert_eq!((1, 2).to_str(), ~"(1, 2)"); + assert_eq!((~"a", ~"b", false).to_str(), ~"(a, b, false)"); + assert_eq!(((), ((), 100)).to_str(), ~"((), ((), 100))"); } #[test] fn test_vectors() { let x: ~[int] = ~[]; - assert!(x.to_str() == ~"[]"); - assert!((~[1]).to_str() == ~"[1]"); - assert!((~[1, 2, 3]).to_str() == ~"[1, 2, 3]"); + assert_eq!(x.to_str(), ~"[]"); + assert_eq!((~[1]).to_str(), ~"[1]"); + assert_eq!((~[1, 2, 3]).to_str(), ~"[1, 2, 3]"); assert!((~[~[], ~[1], ~[1, 1]]).to_str() == ~"[[], [1], [1, 1]]"); } @@ -221,7 +219,7 @@ mod tests { let table_str = table.to_str(); assert!(table_str == ~"{1: 2, 3: 4}" || table_str == ~"{3: 4, 1: 2}"); - assert!(empty.to_str() == ~"{}"); + assert_eq!(empty.to_str(), ~"{}"); } #[test] @@ -235,6 +233,6 @@ mod tests { let set_str = set.to_str(); assert!(set_str == ~"{1, 2}" || set_str == ~"{2, 1}"); - assert!(empty_set.to_str() == ~"{}"); + assert_eq!(empty_set.to_str(), ~"{}"); } } diff --git a/src/libcore/trie.rs b/src/libstd/trie.rs similarity index 81% rename from src/libcore/trie.rs rename to src/libstd/trie.rs index 05ef1cf433faf..aea03b437ca13 100644 --- a/src/libcore/trie.rs +++ b/src/libstd/trie.rs @@ -11,7 +11,9 @@ //! An ordered map and set for integer keys implemented as a radix trie use prelude::*; +use uint; use util::{swap, replace}; +use vec; // FIXME: #5244: need to manually update the TrieNode constructor static SHIFT: uint = 4; @@ -24,6 +26,7 @@ enum Child { Nothing } +#[allow(missing_doc)] pub struct TrieMap { priv root: TrieNode, priv length: uint @@ -57,56 +60,24 @@ impl Map for TrieMap { /// Visit all key-value pairs in order #[inline(always)] - #[cfg(stage0)] - fn each<'a>(&'a self, f: &fn(&uint, &'a T) -> bool) { - self.root.each(f); - } - - /// Visit all key-value pairs in order - #[inline(always)] - #[cfg(not(stage0))] fn each<'a>(&'a self, f: &fn(&uint, &'a T) -> bool) -> bool { self.root.each(f) } /// Visit all keys in order #[inline(always)] - #[cfg(stage0)] - fn each_key(&self, f: &fn(&uint) -> bool) { - self.each(|k, _| f(k)) - } - - /// Visit all keys in order - #[inline(always)] - #[cfg(not(stage0))] fn each_key(&self, f: &fn(&uint) -> bool) -> bool { self.each(|k, _| f(k)) } /// Visit all values in order #[inline(always)] - #[cfg(stage0)] - fn each_value<'a>(&'a self, f: &fn(&'a T) -> bool) { - self.each(|_, v| f(v)) - } - - /// Visit all values in order - #[inline(always)] - #[cfg(not(stage0))] fn each_value<'a>(&'a self, f: &fn(&'a T) -> bool) -> bool { self.each(|_, v| f(v)) } /// Iterate over the map and mutate the contained values #[inline(always)] - #[cfg(stage0)] - fn mutate_values(&mut self, f: &fn(&uint, &mut T) -> bool) { - self.root.mutate_values(f); - } - - /// Iterate over the map and mutate the contained values - #[inline(always)] - #[cfg(not(stage0))] fn mutate_values(&mut self, f: &fn(&uint, &mut T) -> bool) -> bool { self.root.mutate_values(f) } @@ -174,54 +145,33 @@ impl Map for TrieMap { } } -pub impl TrieMap { +impl TrieMap { /// Create an empty TrieMap #[inline(always)] - fn new() -> TrieMap { + pub fn new() -> TrieMap { TrieMap{root: TrieNode::new(), length: 0} } /// Visit all key-value pairs in reverse order #[inline(always)] - #[cfg(stage0)] - fn each_reverse<'a>(&'a self, f: &fn(&uint, &'a T) -> bool) { - self.root.each_reverse(f); - } - - /// Visit all key-value pairs in reverse order - #[inline(always)] - #[cfg(not(stage0))] - fn each_reverse<'a>(&'a self, f: &fn(&uint, &'a T) -> bool) -> bool { + pub fn each_reverse<'a>(&'a self, f: &fn(&uint, &'a T) -> bool) -> bool { self.root.each_reverse(f) } /// Visit all keys in reverse order #[inline(always)] - #[cfg(stage0)] - fn each_key_reverse(&self, f: &fn(&uint) -> bool) { - self.each_reverse(|k, _| f(k)) - } - /// Visit all keys in reverse order - #[inline(always)] - #[cfg(not(stage0))] - fn each_key_reverse(&self, f: &fn(&uint) -> bool) -> bool { + pub fn each_key_reverse(&self, f: &fn(&uint) -> bool) -> bool { self.each_reverse(|k, _| f(k)) } /// Visit all values in reverse order #[inline(always)] - #[cfg(stage0)] - fn each_value_reverse(&self, f: &fn(&T) -> bool) { - self.each_reverse(|_, v| f(v)) - } - /// Visit all values in reverse order - #[inline(always)] - #[cfg(not(stage0))] - fn each_value_reverse(&self, f: &fn(&T) -> bool) -> bool { + pub fn each_value_reverse(&self, f: &fn(&T) -> bool) -> bool { self.each_reverse(|_, v| f(v)) } } +#[allow(missing_doc)] pub struct TrieSet { priv map: TrieMap<()> } @@ -229,9 +179,6 @@ pub struct TrieSet { impl BaseIter for TrieSet { /// Visit all values in order #[inline(always)] - #[cfg(stage0)] - fn each(&self, f: &fn(&uint) -> bool) { self.map.each_key(f) } - #[cfg(not(stage0))] fn each(&self, f: &fn(&uint) -> bool) -> bool { self.map.each_key(f) } #[inline(always)] fn size_hint(&self) -> Option { Some(self.len()) } @@ -240,11 +187,6 @@ impl BaseIter for TrieSet { impl ReverseIter for TrieSet { /// Visit all values in reverse order #[inline(always)] - #[cfg(stage0)] - fn each_reverse(&self, f: &fn(&uint) -> bool) { - self.map.each_key_reverse(f) - } - #[cfg(not(stage0))] fn each_reverse(&self, f: &fn(&uint) -> bool) -> bool { self.map.each_key_reverse(f) } @@ -266,28 +208,32 @@ impl Mutable for TrieSet { fn clear(&mut self) { self.map.clear() } } -pub impl TrieSet { +impl TrieSet { /// Create an empty TrieSet #[inline(always)] - fn new() -> TrieSet { + pub fn new() -> TrieSet { TrieSet{map: TrieMap::new()} } /// Return true if the set contains a value #[inline(always)] - fn contains(&self, value: &uint) -> bool { + pub fn contains(&self, value: &uint) -> bool { self.map.contains_key(value) } /// Add a value to the set. Return true if the value was not already /// present in the set. #[inline(always)] - fn insert(&mut self, value: uint) -> bool { self.map.insert(value, ()) } + pub fn insert(&mut self, value: uint) -> bool { + self.map.insert(value, ()) + } /// Remove a value from the set. Return true if the value was /// present in the set. #[inline(always)] - fn remove(&mut self, value: &uint) -> bool { self.map.remove(value) } + pub fn remove(&mut self, value: &uint) -> bool { + self.map.remove(value) + } } struct TrieNode { @@ -351,19 +297,6 @@ fn chunk(n: uint, idx: uint) -> uint { (n >> sh) & MASK } -#[cfg(stage0)] -fn find_mut<'r, T>(child: &'r mut Child, key: uint, idx: uint) -> Option<&'r mut T> { - unsafe { - (match *child { - External(_, ref value) => Some(cast::transmute_mut(value)), - Internal(ref x) => find_mut(cast::transmute_mut(&x.children[chunk(key, idx)]), - key, idx + 1), - Nothing => None - }).map_consume(|x| cast::transmute_mut_region(x)) - } -} - -#[cfg(not(stage0))] fn find_mut<'r, T>(child: &'r mut Child, key: uint, idx: uint) -> Option<&'r mut T> { match *child { External(_, ref mut value) => Some(value), @@ -451,7 +384,7 @@ pub fn check_integrity(trie: &TrieNode) { } } - assert!(sum == trie.count); + assert_eq!(sum, trie.count); } #[cfg(test)] @@ -521,8 +454,8 @@ mod tests { let mut n = 0; for m.each |k, v| { - assert!(*k == n); - assert!(*v == n * 2); + assert_eq!(*k, n); + assert_eq!(*v, n * 2); n += 1; } } @@ -540,8 +473,8 @@ mod tests { if n == uint::max_value - 5000 { break } assert!(n < uint::max_value - 5000); - assert!(*k == n); - assert!(*v == n / 2); + assert_eq!(*k, n); + assert_eq!(*v, n / 2); n += 1; } } @@ -558,8 +491,8 @@ mod tests { let mut n = 4; for m.each_reverse |k, v| { - assert!(*k == n); - assert!(*v == n * 2); + assert_eq!(*k, n); + assert_eq!(*v, n * 2); n -= 1; } } @@ -577,8 +510,8 @@ mod tests { if n == uint::max_value - 5000 { break } assert!(n > uint::max_value - 5000); - assert!(*k == n); - assert!(*v == n / 2); + assert_eq!(*k, n); + assert_eq!(*v, n / 2); n -= 1; } } @@ -593,14 +526,14 @@ mod tests { assert!(trie.insert(x)); assert!(trie.insert(y)); - assert!(trie.len() == 2); + assert_eq!(trie.len(), 2); let expected = [x, y]; let mut i = 0; for trie.each |x| { - assert!(expected[i] == *x); + assert_eq!(expected[i], *x); i += 1; } } @@ -608,16 +541,16 @@ mod tests { #[test] fn test_swap() { let mut m = TrieMap::new(); - assert!(m.swap(1, 2) == None); - assert!(m.swap(1, 3) == Some(2)); - assert!(m.swap(1, 4) == Some(3)); + assert_eq!(m.swap(1, 2), None); + assert_eq!(m.swap(1, 3), Some(2)); + assert_eq!(m.swap(1, 4), Some(3)); } #[test] fn test_pop() { let mut m = TrieMap::new(); m.insert(1, 2); - assert!(m.pop(&1) == Some(2)); - assert!(m.pop(&1) == None); + assert_eq!(m.pop(&1), Some(2)); + assert_eq!(m.pop(&1), None); } } diff --git a/src/libstd/tuple.rs b/src/libstd/tuple.rs new file mode 100644 index 0000000000000..589c18de0abf5 --- /dev/null +++ b/src/libstd/tuple.rs @@ -0,0 +1,449 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Operations on tuples + +#[allow(missing_doc)]; + +use kinds::Copy; +use vec; + +pub use self::inner::*; + +/// Method extensions to pairs where both types satisfy the `Copy` bound +pub trait CopyableTuple { + /// Return the first element of self + fn first(&self) -> T; + /// Return the second element of self + fn second(&self) -> U; + /// Return the results of swapping the two elements of self + fn swap(&self) -> (U, T); +} + +impl CopyableTuple for (T, U) { + /// Return the first element of self + #[inline(always)] + fn first(&self) -> T { + match *self { + (t, _) => t, + } + } + + /// Return the second element of self + #[inline(always)] + fn second(&self) -> U { + match *self { + (_, u) => u, + } + } + + /// Return the results of swapping the two elements of self + #[inline(always)] + fn swap(&self) -> (U, T) { + match *self { + (t, u) => (u, t), + } + } +} + +/// Method extensions for pairs where the types don't necessarily satisfy the +/// `Copy` bound +pub trait ImmutableTuple { + /// Return a reference to the first element of self + fn first_ref<'a>(&'a self) -> &'a T; + /// Return a reference to the second element of self + fn second_ref<'a>(&'a self) -> &'a U; +} + +impl ImmutableTuple for (T, U) { + #[inline(always)] + fn first_ref<'a>(&'a self) -> &'a T { + match *self { + (ref t, _) => t, + } + } + #[inline(always)] + fn second_ref<'a>(&'a self) -> &'a U { + match *self { + (_, ref u) => u, + } + } +} + +pub trait ExtendedTupleOps { + fn zip(&self) -> ~[(A, B)]; + fn map(&self, f: &fn(a: &A, b: &B) -> C) -> ~[C]; +} + +impl<'self,A:Copy,B:Copy> ExtendedTupleOps for (&'self [A], &'self [B]) { + #[inline(always)] + fn zip(&self) -> ~[(A, B)] { + match *self { + (ref a, ref b) => { + vec::zip_slice(*a, *b) + } + } + } + + #[inline(always)] + fn map(&self, f: &fn(a: &A, b: &B) -> C) -> ~[C] { + match *self { + (ref a, ref b) => { + vec::map_zip(*a, *b, f) + } + } + } +} + +impl ExtendedTupleOps for (~[A], ~[B]) { + #[inline(always)] + fn zip(&self) -> ~[(A, B)] { + match *self { + (ref a, ref b) => { + vec::zip_slice(*a, *b) + } + } + } + + #[inline(always)] + fn map(&self, f: &fn(a: &A, b: &B) -> C) -> ~[C] { + match *self { + (ref a, ref b) => { + vec::map_zip(*a, *b, f) + } + } + } +} + +// macro for implementing n-ary tuple functions and operations + +macro_rules! tuple_impls { + ($( + ($cloneable_trait:ident, $immutable_trait:ident) { + $(($get_fn:ident, $get_ref_fn:ident) -> $T:ident { + $get_pattern:pat => $ret:expr + })+ + } + )+) => { + pub mod inner { + use clone::Clone; + #[cfg(not(test))] use cmp::*; + + $( + pub trait $cloneable_trait<$($T),+> { + $(fn $get_fn(&self) -> $T;)+ + } + + impl<$($T:Clone),+> $cloneable_trait<$($T),+> for ($($T),+) { + $( + #[inline(always)] + fn $get_fn(&self) -> $T { + self.$get_ref_fn().clone() + } + )+ + } + + pub trait $immutable_trait<$($T),+> { + $(fn $get_ref_fn<'a>(&'a self) -> &'a $T;)+ + } + + impl<$($T),+> $immutable_trait<$($T),+> for ($($T),+) { + $( + #[inline(always)] + fn $get_ref_fn<'a>(&'a self) -> &'a $T { + match *self { $get_pattern => $ret } + } + )+ + } + + impl<$($T:Clone),+> Clone for ($($T),+) { + fn clone(&self) -> ($($T),+) { + ($(self.$get_ref_fn().clone()),+) + } + } + + #[cfg(not(test))] + impl<$($T:Eq),+> Eq for ($($T),+) { + #[inline(always)] + fn eq(&self, other: &($($T),+)) -> bool { + $(*self.$get_ref_fn() == *other.$get_ref_fn())&&+ + } + #[inline(always)] + fn ne(&self, other: &($($T),+)) -> bool { + !(*self == *other) + } + } + + #[cfg(not(test))] + impl<$($T:TotalEq),+> TotalEq for ($($T),+) { + #[inline(always)] + fn equals(&self, other: &($($T),+)) -> bool { + $(self.$get_ref_fn().equals(other.$get_ref_fn()))&&+ + } + } + + #[cfg(not(test))] + impl<$($T:Ord),+> Ord for ($($T),+) { + #[inline(always)] + fn lt(&self, other: &($($T),+)) -> bool { + lexical_lt!($(self.$get_ref_fn(), other.$get_ref_fn()),+) + } + #[inline(always)] + fn le(&self, other: &($($T),+)) -> bool { !(*other).lt(&(*self)) } + #[inline(always)] + fn ge(&self, other: &($($T),+)) -> bool { !(*self).lt(other) } + #[inline(always)] + fn gt(&self, other: &($($T),+)) -> bool { (*other).lt(&(*self)) } + } + + #[cfg(not(test))] + impl<$($T:TotalOrd),+> TotalOrd for ($($T),+) { + #[inline] + fn cmp(&self, other: &($($T),+)) -> Ordering { + lexical_cmp!($(self.$get_ref_fn(), other.$get_ref_fn()),+) + } + } + )+ + } + } +} + +// Constructs an expression that performs a lexical less-than +// ordering. The values are interleaved, so the macro invocation for +// `(a1, a2, a3) < (b1, b2, b3)` would be `lexical_lt!(a1, b1, a2, b2, +// a3, b3)` (and similarly for `lexical_cmp`) +macro_rules! lexical_lt { + ($a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => { + if *$a < *$b { true } + else if !(*$b < *$a) { lexical_lt!($($rest_a, $rest_b),+) } + else { false } + }; + ($a:expr, $b:expr) => { *$a < *$b }; +} + +macro_rules! lexical_cmp { + ($a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => { + match ($a).cmp($b) { + Equal => lexical_cmp!($($rest_a, $rest_b),+), + ordering => ordering + } + }; + ($a:expr, $b:expr) => { ($a).cmp($b) }; +} + + +tuple_impls! { + (CloneableTuple2, ImmutableTuple2) { + (n0, n0_ref) -> A { (ref a,_) => a } + (n1, n1_ref) -> B { (_,ref b) => b } + } + + (CloneableTuple3, ImmutableTuple3) { + (n0, n0_ref) -> A { (ref a,_,_) => a } + (n1, n1_ref) -> B { (_,ref b,_) => b } + (n2, n2_ref) -> C { (_,_,ref c) => c } + } + + (CloneableTuple4, ImmutableTuple4) { + (n0, n0_ref) -> A { (ref a,_,_,_) => a } + (n1, n1_ref) -> B { (_,ref b,_,_) => b } + (n2, n2_ref) -> C { (_,_,ref c,_) => c } + (n3, n3_ref) -> D { (_,_,_,ref d) => d } + } + + (CloneableTuple5, ImmutableTuple5) { + (n0, n0_ref) -> A { (ref a,_,_,_,_) => a } + (n1, n1_ref) -> B { (_,ref b,_,_,_) => b } + (n2, n2_ref) -> C { (_,_,ref c,_,_) => c } + (n3, n3_ref) -> D { (_,_,_,ref d,_) => d } + (n4, n4_ref) -> E { (_,_,_,_,ref e) => e } + } + + (CloneableTuple6, ImmutableTuple6) { + (n0, n0_ref) -> A { (ref a,_,_,_,_,_) => a } + (n1, n1_ref) -> B { (_,ref b,_,_,_,_) => b } + (n2, n2_ref) -> C { (_,_,ref c,_,_,_) => c } + (n3, n3_ref) -> D { (_,_,_,ref d,_,_) => d } + (n4, n4_ref) -> E { (_,_,_,_,ref e,_) => e } + (n5, n5_ref) -> F { (_,_,_,_,_,ref f) => f } + } + + (CloneableTuple7, ImmutableTuple7) { + (n0, n0_ref) -> A { (ref a,_,_,_,_,_,_) => a } + (n1, n1_ref) -> B { (_,ref b,_,_,_,_,_) => b } + (n2, n2_ref) -> C { (_,_,ref c,_,_,_,_) => c } + (n3, n3_ref) -> D { (_,_,_,ref d,_,_,_) => d } + (n4, n4_ref) -> E { (_,_,_,_,ref e,_,_) => e } + (n5, n5_ref) -> F { (_,_,_,_,_,ref f,_) => f } + (n6, n6_ref) -> G { (_,_,_,_,_,_,ref g) => g } + } + + (CloneableTuple8, ImmutableTuple8) { + (n0, n0_ref) -> A { (ref a,_,_,_,_,_,_,_) => a } + (n1, n1_ref) -> B { (_,ref b,_,_,_,_,_,_) => b } + (n2, n2_ref) -> C { (_,_,ref c,_,_,_,_,_) => c } + (n3, n3_ref) -> D { (_,_,_,ref d,_,_,_,_) => d } + (n4, n4_ref) -> E { (_,_,_,_,ref e,_,_,_) => e } + (n5, n5_ref) -> F { (_,_,_,_,_,ref f,_,_) => f } + (n6, n6_ref) -> G { (_,_,_,_,_,_,ref g,_) => g } + (n7, n7_ref) -> H { (_,_,_,_,_,_,_,ref h) => h } + } + + (CloneableTuple9, ImmutableTuple9) { + (n0, n0_ref) -> A { (ref a,_,_,_,_,_,_,_,_) => a } + (n1, n1_ref) -> B { (_,ref b,_,_,_,_,_,_,_) => b } + (n2, n2_ref) -> C { (_,_,ref c,_,_,_,_,_,_) => c } + (n3, n3_ref) -> D { (_,_,_,ref d,_,_,_,_,_) => d } + (n4, n4_ref) -> E { (_,_,_,_,ref e,_,_,_,_) => e } + (n5, n5_ref) -> F { (_,_,_,_,_,ref f,_,_,_) => f } + (n6, n6_ref) -> G { (_,_,_,_,_,_,ref g,_,_) => g } + (n7, n7_ref) -> H { (_,_,_,_,_,_,_,ref h,_) => h } + (n8, n8_ref) -> I { (_,_,_,_,_,_,_,_,ref i) => i } + } + + (CloneableTuple10, ImmutableTuple10) { + (n0, n0_ref) -> A { (ref a,_,_,_,_,_,_,_,_,_) => a } + (n1, n1_ref) -> B { (_,ref b,_,_,_,_,_,_,_,_) => b } + (n2, n2_ref) -> C { (_,_,ref c,_,_,_,_,_,_,_) => c } + (n3, n3_ref) -> D { (_,_,_,ref d,_,_,_,_,_,_) => d } + (n4, n4_ref) -> E { (_,_,_,_,ref e,_,_,_,_,_) => e } + (n5, n5_ref) -> F { (_,_,_,_,_,ref f,_,_,_,_) => f } + (n6, n6_ref) -> G { (_,_,_,_,_,_,ref g,_,_,_) => g } + (n7, n7_ref) -> H { (_,_,_,_,_,_,_,ref h,_,_) => h } + (n8, n8_ref) -> I { (_,_,_,_,_,_,_,_,ref i,_) => i } + (n9, n9_ref) -> J { (_,_,_,_,_,_,_,_,_,ref j) => j } + } + + (CloneableTuple11, ImmutableTuple11) { + (n0, n0_ref) -> A { (ref a,_,_,_,_,_,_,_,_,_,_) => a } + (n1, n1_ref) -> B { (_,ref b,_,_,_,_,_,_,_,_,_) => b } + (n2, n2_ref) -> C { (_,_,ref c,_,_,_,_,_,_,_,_) => c } + (n3, n3_ref) -> D { (_,_,_,ref d,_,_,_,_,_,_,_) => d } + (n4, n4_ref) -> E { (_,_,_,_,ref e,_,_,_,_,_,_) => e } + (n5, n5_ref) -> F { (_,_,_,_,_,ref f,_,_,_,_,_) => f } + (n6, n6_ref) -> G { (_,_,_,_,_,_,ref g,_,_,_,_) => g } + (n7, n7_ref) -> H { (_,_,_,_,_,_,_,ref h,_,_,_) => h } + (n8, n8_ref) -> I { (_,_,_,_,_,_,_,_,ref i,_,_) => i } + (n9, n9_ref) -> J { (_,_,_,_,_,_,_,_,_,ref j,_) => j } + (n10, n10_ref) -> K { (_,_,_,_,_,_,_,_,_,_,ref k) => k } + } + + (CloneableTuple12, ImmutableTuple12) { + (n0, n0_ref) -> A { (ref a,_,_,_,_,_,_,_,_,_,_,_) => a } + (n1, n1_ref) -> B { (_,ref b,_,_,_,_,_,_,_,_,_,_) => b } + (n2, n2_ref) -> C { (_,_,ref c,_,_,_,_,_,_,_,_,_) => c } + (n3, n3_ref) -> D { (_,_,_,ref d,_,_,_,_,_,_,_,_) => d } + (n4, n4_ref) -> E { (_,_,_,_,ref e,_,_,_,_,_,_,_) => e } + (n5, n5_ref) -> F { (_,_,_,_,_,ref f,_,_,_,_,_,_) => f } + (n6, n6_ref) -> G { (_,_,_,_,_,_,ref g,_,_,_,_,_) => g } + (n7, n7_ref) -> H { (_,_,_,_,_,_,_,ref h,_,_,_,_) => h } + (n8, n8_ref) -> I { (_,_,_,_,_,_,_,_,ref i,_,_,_) => i } + (n9, n9_ref) -> J { (_,_,_,_,_,_,_,_,_,ref j,_,_) => j } + (n10, n10_ref) -> K { (_,_,_,_,_,_,_,_,_,_,ref k,_) => k } + (n11, n11_ref) -> L { (_,_,_,_,_,_,_,_,_,_,_,ref l) => l } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use clone::Clone; + use cmp::*; + + #[test] + fn test_tuple_ref() { + let x = (~"foo", ~"bar"); + assert_eq!(x.first_ref(), &~"foo"); + assert_eq!(x.second_ref(), &~"bar"); + } + + #[test] + #[allow(non_implicitly_copyable_typarams)] + fn test_tuple() { + assert_eq!((948, 4039.48).first(), 948); + assert_eq!((34.5, ~"foo").second(), ~"foo"); + assert_eq!(('a', 2).swap(), (2, 'a')); + } + + #[test] + fn test_clone() { + let a = (1, ~"2"); + let b = a.clone(); + assert_eq!(a.first(), b.first()); + assert_eq!(a.second(), b.second()); + } + + #[test] + fn test_n_tuple() { + let t = (0u8, 1u16, 2u32, 3u64, 4u, 5i8, 6i16, 7i32, 8i64, 9i, 10f32, 11f64); + assert_eq!(t.n0(), 0u8); + assert_eq!(t.n1(), 1u16); + assert_eq!(t.n2(), 2u32); + assert_eq!(t.n3(), 3u64); + assert_eq!(t.n4(), 4u); + assert_eq!(t.n5(), 5i8); + assert_eq!(t.n6(), 6i16); + assert_eq!(t.n7(), 7i32); + assert_eq!(t.n8(), 8i64); + assert_eq!(t.n9(), 9i); + assert_eq!(t.n10(), 10f32); + assert_eq!(t.n11(), 11f64); + + assert_eq!(t.n0_ref(), &0u8); + assert_eq!(t.n1_ref(), &1u16); + assert_eq!(t.n2_ref(), &2u32); + assert_eq!(t.n3_ref(), &3u64); + assert_eq!(t.n4_ref(), &4u); + assert_eq!(t.n5_ref(), &5i8); + assert_eq!(t.n6_ref(), &6i16); + assert_eq!(t.n7_ref(), &7i32); + assert_eq!(t.n8_ref(), &8i64); + assert_eq!(t.n9_ref(), &9i); + assert_eq!(t.n10_ref(), &10f32); + assert_eq!(t.n11_ref(), &11f64); + } + + #[test] + fn test_tuple_cmp() { + let (small, big) = ((1u, 2u, 3u), (3u, 2u, 1u)); + + // Eq + assert_eq!(small, small); + assert_eq!(big, big); + assert!(small != big); + assert!(big != small); + + // Ord + assert!(small < big); + assert!(!(small < small)); + assert!(!(big < small)); + assert!(!(big < big)); + + assert!(small <= small); + assert!(big <= big); + + assert!(big > small); + assert!(small >= small); + assert!(big >= small); + assert!(big >= big); + + // TotalEq + assert!(small.equals(&small)); + assert!(big.equals(&big)); + assert!(!small.equals(&big)); + assert!(!big.equals(&small)); + + // TotalOrd + assert_eq!(small.cmp(&small), Equal); + assert_eq!(big.cmp(&big), Equal); + assert_eq!(small.cmp(&big), Less); + assert_eq!(big.cmp(&small), Greater); + } +} diff --git a/src/libstd/unicode.rs b/src/libstd/unicode.rs index 77996de6d8394..f8f56c75a295c 100644 --- a/src/libstd/unicode.rs +++ b/src/libstd/unicode.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,241 +8,2637 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[forbid(deprecated_mode)]; - -pub mod icu { - pub type UBool = u8; - pub type UProperty = int; - pub type UChar32 = char; - - pub static TRUE : u8 = 1u8; - pub static FALSE : u8 = 1u8; - - pub static UCHAR_ALPHABETIC : UProperty = 0; - pub static UCHAR_BINARY_START : UProperty = 0; // = UCHAR_ALPHABETIC - pub static UCHAR_ASCII_HEX_DIGIT : UProperty = 1; - pub static UCHAR_BIDI_CONTROL : UProperty = 2; - - pub static UCHAR_BIDI_MIRRORED : UProperty = 3; - pub static UCHAR_DASH : UProperty = 4; - pub static UCHAR_DEFAULT_IGNORABLE_CODE_POINT : UProperty = 5; - pub static UCHAR_DEPRECATED : UProperty = 6; - - pub static UCHAR_DIACRITIC : UProperty = 7; - pub static UCHAR_EXTENDER : UProperty = 8; - pub static UCHAR_FULL_COMPOSITION_EXCLUSION : UProperty = 9; - pub static UCHAR_GRAPHEME_BASE : UProperty = 10; - - pub static UCHAR_GRAPHEME_EXTEND : UProperty = 11; - pub static UCHAR_GRAPHEME_LINK : UProperty = 12; - pub static UCHAR_HEX_DIGIT : UProperty = 13; - pub static UCHAR_HYPHEN : UProperty = 14; - - pub static UCHAR_ID_CONTINUE : UProperty = 15; - pub static UCHAR_ID_START : UProperty = 16; - pub static UCHAR_IDEOGRAPHIC : UProperty = 17; - pub static UCHAR_IDS_BINARY_OPERATOR : UProperty = 18; - - pub static UCHAR_IDS_TRINARY_OPERATOR : UProperty = 19; - pub static UCHAR_JOIN_CONTROL : UProperty = 20; - pub static UCHAR_LOGICAL_ORDER_EXCEPTION : UProperty = 21; - pub static UCHAR_LOWERCASE : UProperty = 22; - - pub static UCHAR_MATH : UProperty = 23; - pub static UCHAR_NONCHARACTER_CODE_POINT : UProperty = 24; - pub static UCHAR_QUOTATION_MARK : UProperty = 25; - pub static UCHAR_RADICAL : UProperty = 26; - - pub static UCHAR_SOFT_DOTTED : UProperty = 27; - pub static UCHAR_TERMINAL_PUNCTUATION : UProperty = 28; - pub static UCHAR_UNIFIED_IDEOGRAPH : UProperty = 29; - pub static UCHAR_UPPERCASE : UProperty = 30; - - pub static UCHAR_WHITE_SPACE : UProperty = 31; - pub static UCHAR_XID_CONTINUE : UProperty = 32; - pub static UCHAR_XID_START : UProperty = 33; - pub static UCHAR_CASE_SENSITIVE : UProperty = 34; - - pub static UCHAR_S_TERM : UProperty = 35; - pub static UCHAR_VARIATION_SELECTOR : UProperty = 36; - pub static UCHAR_NFD_INERT : UProperty = 37; - pub static UCHAR_NFKD_INERT : UProperty = 38; - - pub static UCHAR_NFC_INERT : UProperty = 39; - pub static UCHAR_NFKC_INERT : UProperty = 40; - pub static UCHAR_SEGMENT_STARTER : UProperty = 41; - pub static UCHAR_PATTERN_SYNTAX : UProperty = 42; - - pub static UCHAR_PATTERN_WHITE_SPACE : UProperty = 43; - pub static UCHAR_POSIX_ALNUM : UProperty = 44; - pub static UCHAR_POSIX_BLANK : UProperty = 45; - pub static UCHAR_POSIX_GRAPH : UProperty = 46; - - pub static UCHAR_POSIX_PRINT : UProperty = 47; - pub static UCHAR_POSIX_XDIGIT : UProperty = 48; - pub static UCHAR_CASED : UProperty = 49; - pub static UCHAR_CASE_IGNORABLE : UProperty = 50; - - pub static UCHAR_CHANGES_WHEN_LOWERCASED : UProperty = 51; - pub static UCHAR_CHANGES_WHEN_UPPERCASED : UProperty = 52; - pub static UCHAR_CHANGES_WHEN_TITLECASED : UProperty = 53; - pub static UCHAR_CHANGES_WHEN_CASEFOLDED : UProperty = 54; - - pub static UCHAR_CHANGES_WHEN_CASEMAPPED : UProperty = 55; - pub static UCHAR_CHANGES_WHEN_NFKC_CASEFOLDED : UProperty = 56; - pub static UCHAR_BINARY_LIMIT : UProperty = 57; - pub static UCHAR_BIDI_CLASS : UProperty = 0x1000; - - pub static UCHAR_INT_START : UProperty = 0x1000; // UCHAR_BIDI_CLASS - pub static UCHAR_BLOCK : UProperty = 0x1001; - pub static UCHAR_CANONICAL_COMBINING_CLASS : UProperty = 0x1002; - pub static UCHAR_DECOMPOSITION_TYPE : UProperty = 0x1003; - - pub static UCHAR_EAST_ASIAN_WIDTH : UProperty = 0x1004; - pub static UCHAR_GENERAL_CATEGORY : UProperty = 0x1005; - pub static UCHAR_JOINING_GROUP : UProperty = 0x1006; - pub static UCHAR_JOINING_TYPE : UProperty = 0x1007; - - pub static UCHAR_LINE_BREAK : UProperty = 0x1008; - pub static UCHAR_NUMERIC_TYPE : UProperty = 0x1009; - pub static UCHAR_SCRIPT : UProperty = 0x100A; - pub static UCHAR_HANGUL_SYLLABLE_TYPE : UProperty = 0x100B; - - pub static UCHAR_NFD_QUICK_CHECK : UProperty = 0x100C; - pub static UCHAR_NFKD_QUICK_CHECK : UProperty = 0x100D; - pub static UCHAR_NFC_QUICK_CHECK : UProperty = 0x100E; - pub static UCHAR_NFKC_QUICK_CHECK : UProperty = 0x100F; - - pub static UCHAR_LEAD_CANONICAL_COMBINING_CLASS : UProperty = 0x1010; - pub static UCHAR_TRAIL_CANONICAL_COMBINING_CLASS : UProperty = 0x1011; - pub static UCHAR_GRAPHEME_CLUSTER_BREAK : UProperty = 0x1012; - pub static UCHAR_SENTENCE_BREAK : UProperty = 0x1013; - - pub static UCHAR_WORD_BREAK : UProperty = 0x1014; - pub static UCHAR_INT_LIMIT : UProperty = 0x1015; - - pub static UCHAR_GENERAL_CATEGORY_MASK : UProperty = 0x2000; - pub static UCHAR_MASK_START : UProperty = 0x2000; - // = UCHAR_GENERAL_CATEGORY_MASK - pub static UCHAR_MASK_LIMIT : UProperty = 0x2001; - - pub static UCHAR_NUMERIC_VALUE : UProperty = 0x3000; - pub static UCHAR_DOUBLE_START : UProperty = 0x3000; - // = UCHAR_NUMERIC_VALUE - pub static UCHAR_DOUBLE_LIMIT : UProperty = 0x3001; - - pub static UCHAR_AGE : UProperty = 0x4000; - pub static UCHAR_STRING_START : UProperty = 0x4000; // = UCHAR_AGE - pub static UCHAR_BIDI_MIRRORING_GLYPH : UProperty = 0x4001; - pub static UCHAR_CASE_FOLDING : UProperty = 0x4002; - - pub static UCHAR_ISO_COMMENT : UProperty = 0x4003; - pub static UCHAR_LOWERCASE_MAPPING : UProperty = 0x4004; - pub static UCHAR_NAME : UProperty = 0x4005; - pub static UCHAR_SIMPLE_CASE_FOLDING : UProperty = 0x4006; - - pub static UCHAR_SIMPLE_LOWERCASE_MAPPING : UProperty = 0x4007; - pub static UCHAR_SIMPLE_TITLECASE_MAPPING : UProperty = 0x4008; - pub static UCHAR_SIMPLE_UPPERCASE_MAPPING : UProperty = 0x4009; - pub static UCHAR_TITLECASE_MAPPING : UProperty = 0x400A; - - pub static UCHAR_UNICODE_1_NAME : UProperty = 0x400B; - pub static UCHAR_UPPERCASE_MAPPING : UProperty = 0x400C; - pub static UCHAR_STRING_LIMIT : UProperty = 0x400D; - - pub static UCHAR_SCRIPT_EXTENSIONS : UProperty = 0x7000; - pub static UCHAR_OTHER_PROPERTY_START : UProperty = 0x7000; - // = UCHAR_SCRIPT_EXTENSIONS; - pub static UCHAR_OTHER_PROPERTY_LIMIT : UProperty = 0x7001; - - pub static UCHAR_INVALID_CODE : UProperty = -1; - - pub mod libicu { - #[link_name = "icuuc"] - #[abi = "cdecl"] - pub extern { - unsafe fn u_hasBinaryProperty(c: UChar32, which: UProperty) - -> UBool; - unsafe fn u_isdigit(c: UChar32) -> UBool; - unsafe fn u_islower(c: UChar32) -> UBool; - unsafe fn u_isspace(c: UChar32) -> UBool; - unsafe fn u_isupper(c: UChar32) -> UBool; - unsafe fn u_tolower(c: UChar32) -> UChar32; - unsafe fn u_toupper(c: UChar32) -> UChar32; - } +// The following code was generated by "src/etc/unicode.py" + +#[allow(missing_doc)]; + +pub mod general_category { + + fn bsearch_range_table(c: char, r: &'static [(char,char)]) -> bool { + use cmp::{Equal, Less, Greater}; + use vec::bsearch; + use option::None; + (do bsearch(r) |&(lo,hi)| { + if lo <= c && c <= hi { Equal } + else if hi < c { Less } + else { Greater } + }) != None } -} -pub fn is_XID_start(c: char) -> bool { - return icu::libicu::u_hasBinaryProperty(c, icu::UCHAR_XID_START) - == icu::TRUE; -} -pub fn is_XID_continue(c: char) -> bool { - return icu::libicu::u_hasBinaryProperty(c, icu::UCHAR_XID_START) - == icu::TRUE; -} + static Cc_table : &'static [(char,char)] = &[ + ('\x00', '\x1f'), ('\x7f', '\x9f') + ]; -/* -Function: is_digit + pub fn Cc(c: char) -> bool { + bsearch_range_table(c, Cc_table) + } -Returns true if a character is a digit. -*/ -pub fn is_digit(c: char) -> bool { - return icu::libicu::u_isdigit(c) == icu::TRUE; -} + static Cf_table : &'static [(char,char)] = &[ + ('\xad', '\xad'), ('\u0600', '\u0604'), + ('\u06dd', '\u06dd'), ('\u070f', '\u070f'), + ('\u200b', '\u200f'), ('\u202a', '\u202e'), + ('\u2060', '\u206f'), ('\ufeff', '\ufeff'), + ('\ufff9', '\ufffb'), ('\U000110bd', '\U000110bd'), + ('\U0001d173', '\U0001d17a'), ('\U000e0001', '\U000e007f') + ]; -/* -Function: is_lower + pub fn Cf(c: char) -> bool { + bsearch_range_table(c, Cf_table) + } -Returns true if a character is a lowercase letter. -*/ -pub fn is_lower(c: char) -> bool { - return icu::libicu::u_islower(c) == icu::TRUE; -} + static Co_table : &'static [(char,char)] = &[ + ('\ue000', '\uf8ff') + ]; -/* -Function: is_space + pub fn Co(c: char) -> bool { + bsearch_range_table(c, Co_table) + } -Returns true if a character is space. -*/ -pub fn is_space(c: char) -> bool { - return icu::libicu::u_isspace(c) == icu::TRUE; -} + static Cs_table : &'static [(char,char)] = &[ + ('\ud800', '\udfff') + ]; + + pub fn Cs(c: char) -> bool { + bsearch_range_table(c, Cs_table) + } + + static Ll_table : &'static [(char,char)] = &[ + ('\x61', '\x7a'), ('\xb5', '\xb5'), + ('\xdf', '\xf6'), ('\xf8', '\xff'), + ('\u0101', '\u0101'), ('\u0103', '\u0103'), + ('\u0105', '\u0105'), ('\u0107', '\u0107'), + ('\u0109', '\u0109'), ('\u010b', '\u010b'), + ('\u010d', '\u010d'), ('\u010f', '\u010f'), + ('\u0111', '\u0111'), ('\u0113', '\u0113'), + ('\u0115', '\u0115'), ('\u0117', '\u0117'), + ('\u0119', '\u0119'), ('\u011b', '\u011b'), + ('\u011d', '\u011d'), ('\u011f', '\u011f'), + ('\u0121', '\u0121'), ('\u0123', '\u0123'), + ('\u0125', '\u0125'), ('\u0127', '\u0127'), + ('\u0129', '\u0129'), ('\u012b', '\u012b'), + ('\u012d', '\u012d'), ('\u012f', '\u012f'), + ('\u0131', '\u0131'), ('\u0133', '\u0133'), + ('\u0135', '\u0135'), ('\u0137', '\u0138'), + ('\u013a', '\u013a'), ('\u013c', '\u013c'), + ('\u013e', '\u013e'), ('\u0140', '\u0140'), + ('\u0142', '\u0142'), ('\u0144', '\u0144'), + ('\u0146', '\u0146'), ('\u0148', '\u0149'), + ('\u014b', '\u014b'), ('\u014d', '\u014d'), + ('\u014f', '\u014f'), ('\u0151', '\u0151'), + ('\u0153', '\u0153'), ('\u0155', '\u0155'), + ('\u0157', '\u0157'), ('\u0159', '\u0159'), + ('\u015b', '\u015b'), ('\u015d', '\u015d'), + ('\u015f', '\u015f'), ('\u0161', '\u0161'), + ('\u0163', '\u0163'), ('\u0165', '\u0165'), + ('\u0167', '\u0167'), ('\u0169', '\u0169'), + ('\u016b', '\u016b'), ('\u016d', '\u016d'), + ('\u016f', '\u016f'), ('\u0171', '\u0171'), + ('\u0173', '\u0173'), ('\u0175', '\u0175'), + ('\u0177', '\u0177'), ('\u017a', '\u017a'), + ('\u017c', '\u017c'), ('\u017e', '\u0180'), + ('\u0183', '\u0183'), ('\u0185', '\u0185'), + ('\u0188', '\u0188'), ('\u018c', '\u018d'), + ('\u0192', '\u0192'), ('\u0195', '\u0195'), + ('\u0199', '\u019b'), ('\u019e', '\u019e'), + ('\u01a1', '\u01a1'), ('\u01a3', '\u01a3'), + ('\u01a5', '\u01a5'), ('\u01a8', '\u01a8'), + ('\u01aa', '\u01ab'), ('\u01ad', '\u01ad'), + ('\u01b0', '\u01b0'), ('\u01b4', '\u01b4'), + ('\u01b6', '\u01b6'), ('\u01b9', '\u01ba'), + ('\u01bd', '\u01bf'), ('\u01c6', '\u01c6'), + ('\u01c9', '\u01c9'), ('\u01cc', '\u01cc'), + ('\u01ce', '\u01ce'), ('\u01d0', '\u01d0'), + ('\u01d2', '\u01d2'), ('\u01d4', '\u01d4'), + ('\u01d6', '\u01d6'), ('\u01d8', '\u01d8'), + ('\u01da', '\u01da'), ('\u01dc', '\u01dd'), + ('\u01df', '\u01df'), ('\u01e1', '\u01e1'), + ('\u01e3', '\u01e3'), ('\u01e5', '\u01e5'), + ('\u01e7', '\u01e7'), ('\u01e9', '\u01e9'), + ('\u01eb', '\u01eb'), ('\u01ed', '\u01ed'), + ('\u01ef', '\u01f0'), ('\u01f3', '\u01f3'), + ('\u01f5', '\u01f5'), ('\u01f9', '\u01f9'), + ('\u01fb', '\u01fb'), ('\u01fd', '\u01fd'), + ('\u01ff', '\u01ff'), ('\u0201', '\u0201'), + ('\u0203', '\u0203'), ('\u0205', '\u0205'), + ('\u0207', '\u0207'), ('\u0209', '\u0209'), + ('\u020b', '\u020b'), ('\u020d', '\u020d'), + ('\u020f', '\u020f'), ('\u0211', '\u0211'), + ('\u0213', '\u0213'), ('\u0215', '\u0215'), + ('\u0217', '\u0217'), ('\u0219', '\u0219'), + ('\u021b', '\u021b'), ('\u021d', '\u021d'), + ('\u021f', '\u021f'), ('\u0221', '\u0221'), + ('\u0223', '\u0223'), ('\u0225', '\u0225'), + ('\u0227', '\u0227'), ('\u0229', '\u0229'), + ('\u022b', '\u022b'), ('\u022d', '\u022d'), + ('\u022f', '\u022f'), ('\u0231', '\u0231'), + ('\u0233', '\u0239'), ('\u023c', '\u023c'), + ('\u023f', '\u0240'), ('\u0242', '\u0242'), + ('\u0247', '\u0247'), ('\u0249', '\u0249'), + ('\u024b', '\u024b'), ('\u024d', '\u024d'), + ('\u024f', '\u0293'), ('\u0295', '\u02af'), + ('\u0371', '\u0371'), ('\u0373', '\u0373'), + ('\u0377', '\u0377'), ('\u037b', '\u037d'), + ('\u0390', '\u0390'), ('\u03ac', '\u03ce'), + ('\u03d0', '\u03d1'), ('\u03d5', '\u03d7'), + ('\u03d9', '\u03d9'), ('\u03db', '\u03db'), + ('\u03dd', '\u03dd'), ('\u03df', '\u03df'), + ('\u03e1', '\u03e1'), ('\u03e3', '\u03e3'), + ('\u03e5', '\u03e5'), ('\u03e7', '\u03e7'), + ('\u03e9', '\u03e9'), ('\u03eb', '\u03eb'), + ('\u03ed', '\u03ed'), ('\u03ef', '\u03f3'), + ('\u03f5', '\u03f5'), ('\u03f8', '\u03f8'), + ('\u03fb', '\u03fc'), ('\u0430', '\u045f'), + ('\u0461', '\u0461'), ('\u0463', '\u0463'), + ('\u0465', '\u0465'), ('\u0467', '\u0467'), + ('\u0469', '\u0469'), ('\u046b', '\u046b'), + ('\u046d', '\u046d'), ('\u046f', '\u046f'), + ('\u0471', '\u0471'), ('\u0473', '\u0473'), + ('\u0475', '\u0475'), ('\u0477', '\u0477'), + ('\u0479', '\u0479'), ('\u047b', '\u047b'), + ('\u047d', '\u047d'), ('\u047f', '\u047f'), + ('\u0481', '\u0481'), ('\u048b', '\u048b'), + ('\u048d', '\u048d'), ('\u048f', '\u048f'), + ('\u0491', '\u0491'), ('\u0493', '\u0493'), + ('\u0495', '\u0495'), ('\u0497', '\u0497'), + ('\u0499', '\u0499'), ('\u049b', '\u049b'), + ('\u049d', '\u049d'), ('\u049f', '\u049f'), + ('\u04a1', '\u04a1'), ('\u04a3', '\u04a3'), + ('\u04a5', '\u04a5'), ('\u04a7', '\u04a7'), + ('\u04a9', '\u04a9'), ('\u04ab', '\u04ab'), + ('\u04ad', '\u04ad'), ('\u04af', '\u04af'), + ('\u04b1', '\u04b1'), ('\u04b3', '\u04b3'), + ('\u04b5', '\u04b5'), ('\u04b7', '\u04b7'), + ('\u04b9', '\u04b9'), ('\u04bb', '\u04bb'), + ('\u04bd', '\u04bd'), ('\u04bf', '\u04bf'), + ('\u04c2', '\u04c2'), ('\u04c4', '\u04c4'), + ('\u04c6', '\u04c6'), ('\u04c8', '\u04c8'), + ('\u04ca', '\u04ca'), ('\u04cc', '\u04cc'), + ('\u04ce', '\u04cf'), ('\u04d1', '\u04d1'), + ('\u04d3', '\u04d3'), ('\u04d5', '\u04d5'), + ('\u04d7', '\u04d7'), ('\u04d9', '\u04d9'), + ('\u04db', '\u04db'), ('\u04dd', '\u04dd'), + ('\u04df', '\u04df'), ('\u04e1', '\u04e1'), + ('\u04e3', '\u04e3'), ('\u04e5', '\u04e5'), + ('\u04e7', '\u04e7'), ('\u04e9', '\u04e9'), + ('\u04eb', '\u04eb'), ('\u04ed', '\u04ed'), + ('\u04ef', '\u04ef'), ('\u04f1', '\u04f1'), + ('\u04f3', '\u04f3'), ('\u04f5', '\u04f5'), + ('\u04f7', '\u04f7'), ('\u04f9', '\u04f9'), + ('\u04fb', '\u04fb'), ('\u04fd', '\u04fd'), + ('\u04ff', '\u04ff'), ('\u0501', '\u0501'), + ('\u0503', '\u0503'), ('\u0505', '\u0505'), + ('\u0507', '\u0507'), ('\u0509', '\u0509'), + ('\u050b', '\u050b'), ('\u050d', '\u050d'), + ('\u050f', '\u050f'), ('\u0511', '\u0511'), + ('\u0513', '\u0513'), ('\u0515', '\u0515'), + ('\u0517', '\u0517'), ('\u0519', '\u0519'), + ('\u051b', '\u051b'), ('\u051d', '\u051d'), + ('\u051f', '\u051f'), ('\u0521', '\u0521'), + ('\u0523', '\u0523'), ('\u0525', '\u0525'), + ('\u0527', '\u0527'), ('\u0561', '\u0587'), + ('\u1d00', '\u1d2b'), ('\u1d6b', '\u1d77'), + ('\u1d79', '\u1d9a'), ('\u1e01', '\u1e01'), + ('\u1e03', '\u1e03'), ('\u1e05', '\u1e05'), + ('\u1e07', '\u1e07'), ('\u1e09', '\u1e09'), + ('\u1e0b', '\u1e0b'), ('\u1e0d', '\u1e0d'), + ('\u1e0f', '\u1e0f'), ('\u1e11', '\u1e11'), + ('\u1e13', '\u1e13'), ('\u1e15', '\u1e15'), + ('\u1e17', '\u1e17'), ('\u1e19', '\u1e19'), + ('\u1e1b', '\u1e1b'), ('\u1e1d', '\u1e1d'), + ('\u1e1f', '\u1e1f'), ('\u1e21', '\u1e21'), + ('\u1e23', '\u1e23'), ('\u1e25', '\u1e25'), + ('\u1e27', '\u1e27'), ('\u1e29', '\u1e29'), + ('\u1e2b', '\u1e2b'), ('\u1e2d', '\u1e2d'), + ('\u1e2f', '\u1e2f'), ('\u1e31', '\u1e31'), + ('\u1e33', '\u1e33'), ('\u1e35', '\u1e35'), + ('\u1e37', '\u1e37'), ('\u1e39', '\u1e39'), + ('\u1e3b', '\u1e3b'), ('\u1e3d', '\u1e3d'), + ('\u1e3f', '\u1e3f'), ('\u1e41', '\u1e41'), + ('\u1e43', '\u1e43'), ('\u1e45', '\u1e45'), + ('\u1e47', '\u1e47'), ('\u1e49', '\u1e49'), + ('\u1e4b', '\u1e4b'), ('\u1e4d', '\u1e4d'), + ('\u1e4f', '\u1e4f'), ('\u1e51', '\u1e51'), + ('\u1e53', '\u1e53'), ('\u1e55', '\u1e55'), + ('\u1e57', '\u1e57'), ('\u1e59', '\u1e59'), + ('\u1e5b', '\u1e5b'), ('\u1e5d', '\u1e5d'), + ('\u1e5f', '\u1e5f'), ('\u1e61', '\u1e61'), + ('\u1e63', '\u1e63'), ('\u1e65', '\u1e65'), + ('\u1e67', '\u1e67'), ('\u1e69', '\u1e69'), + ('\u1e6b', '\u1e6b'), ('\u1e6d', '\u1e6d'), + ('\u1e6f', '\u1e6f'), ('\u1e71', '\u1e71'), + ('\u1e73', '\u1e73'), ('\u1e75', '\u1e75'), + ('\u1e77', '\u1e77'), ('\u1e79', '\u1e79'), + ('\u1e7b', '\u1e7b'), ('\u1e7d', '\u1e7d'), + ('\u1e7f', '\u1e7f'), ('\u1e81', '\u1e81'), + ('\u1e83', '\u1e83'), ('\u1e85', '\u1e85'), + ('\u1e87', '\u1e87'), ('\u1e89', '\u1e89'), + ('\u1e8b', '\u1e8b'), ('\u1e8d', '\u1e8d'), + ('\u1e8f', '\u1e8f'), ('\u1e91', '\u1e91'), + ('\u1e93', '\u1e93'), ('\u1e95', '\u1e9d'), + ('\u1e9f', '\u1e9f'), ('\u1ea1', '\u1ea1'), + ('\u1ea3', '\u1ea3'), ('\u1ea5', '\u1ea5'), + ('\u1ea7', '\u1ea7'), ('\u1ea9', '\u1ea9'), + ('\u1eab', '\u1eab'), ('\u1ead', '\u1ead'), + ('\u1eaf', '\u1eaf'), ('\u1eb1', '\u1eb1'), + ('\u1eb3', '\u1eb3'), ('\u1eb5', '\u1eb5'), + ('\u1eb7', '\u1eb7'), ('\u1eb9', '\u1eb9'), + ('\u1ebb', '\u1ebb'), ('\u1ebd', '\u1ebd'), + ('\u1ebf', '\u1ebf'), ('\u1ec1', '\u1ec1'), + ('\u1ec3', '\u1ec3'), ('\u1ec5', '\u1ec5'), + ('\u1ec7', '\u1ec7'), ('\u1ec9', '\u1ec9'), + ('\u1ecb', '\u1ecb'), ('\u1ecd', '\u1ecd'), + ('\u1ecf', '\u1ecf'), ('\u1ed1', '\u1ed1'), + ('\u1ed3', '\u1ed3'), ('\u1ed5', '\u1ed5'), + ('\u1ed7', '\u1ed7'), ('\u1ed9', '\u1ed9'), + ('\u1edb', '\u1edb'), ('\u1edd', '\u1edd'), + ('\u1edf', '\u1edf'), ('\u1ee1', '\u1ee1'), + ('\u1ee3', '\u1ee3'), ('\u1ee5', '\u1ee5'), + ('\u1ee7', '\u1ee7'), ('\u1ee9', '\u1ee9'), + ('\u1eeb', '\u1eeb'), ('\u1eed', '\u1eed'), + ('\u1eef', '\u1eef'), ('\u1ef1', '\u1ef1'), + ('\u1ef3', '\u1ef3'), ('\u1ef5', '\u1ef5'), + ('\u1ef7', '\u1ef7'), ('\u1ef9', '\u1ef9'), + ('\u1efb', '\u1efb'), ('\u1efd', '\u1efd'), + ('\u1eff', '\u1f07'), ('\u1f10', '\u1f15'), + ('\u1f20', '\u1f27'), ('\u1f30', '\u1f37'), + ('\u1f40', '\u1f45'), ('\u1f50', '\u1f57'), + ('\u1f60', '\u1f67'), ('\u1f70', '\u1f87'), + ('\u1f90', '\u1f97'), ('\u1fa0', '\u1fa7'), + ('\u1fb0', '\u1fb7'), ('\u1fbe', '\u1fbe'), + ('\u1fc2', '\u1fc7'), ('\u1fd0', '\u1fd7'), + ('\u1fe0', '\u1fe7'), ('\u1ff2', '\u1ff7'), + ('\u210a', '\u210a'), ('\u210e', '\u210f'), + ('\u2113', '\u2113'), ('\u212f', '\u212f'), + ('\u2134', '\u2134'), ('\u2139', '\u2139'), + ('\u213c', '\u213d'), ('\u2146', '\u2149'), + ('\u214e', '\u214e'), ('\u2184', '\u2184'), + ('\u2c30', '\u2c5e'), ('\u2c61', '\u2c61'), + ('\u2c65', '\u2c66'), ('\u2c68', '\u2c68'), + ('\u2c6a', '\u2c6a'), ('\u2c6c', '\u2c6c'), + ('\u2c71', '\u2c71'), ('\u2c73', '\u2c74'), + ('\u2c76', '\u2c7b'), ('\u2c81', '\u2c81'), + ('\u2c83', '\u2c83'), ('\u2c85', '\u2c85'), + ('\u2c87', '\u2c87'), ('\u2c89', '\u2c89'), + ('\u2c8b', '\u2c8b'), ('\u2c8d', '\u2c8d'), + ('\u2c8f', '\u2c8f'), ('\u2c91', '\u2c91'), + ('\u2c93', '\u2c93'), ('\u2c95', '\u2c95'), + ('\u2c97', '\u2c97'), ('\u2c99', '\u2c99'), + ('\u2c9b', '\u2c9b'), ('\u2c9d', '\u2c9d'), + ('\u2c9f', '\u2c9f'), ('\u2ca1', '\u2ca1'), + ('\u2ca3', '\u2ca3'), ('\u2ca5', '\u2ca5'), + ('\u2ca7', '\u2ca7'), ('\u2ca9', '\u2ca9'), + ('\u2cab', '\u2cab'), ('\u2cad', '\u2cad'), + ('\u2caf', '\u2caf'), ('\u2cb1', '\u2cb1'), + ('\u2cb3', '\u2cb3'), ('\u2cb5', '\u2cb5'), + ('\u2cb7', '\u2cb7'), ('\u2cb9', '\u2cb9'), + ('\u2cbb', '\u2cbb'), ('\u2cbd', '\u2cbd'), + ('\u2cbf', '\u2cbf'), ('\u2cc1', '\u2cc1'), + ('\u2cc3', '\u2cc3'), ('\u2cc5', '\u2cc5'), + ('\u2cc7', '\u2cc7'), ('\u2cc9', '\u2cc9'), + ('\u2ccb', '\u2ccb'), ('\u2ccd', '\u2ccd'), + ('\u2ccf', '\u2ccf'), ('\u2cd1', '\u2cd1'), + ('\u2cd3', '\u2cd3'), ('\u2cd5', '\u2cd5'), + ('\u2cd7', '\u2cd7'), ('\u2cd9', '\u2cd9'), + ('\u2cdb', '\u2cdb'), ('\u2cdd', '\u2cdd'), + ('\u2cdf', '\u2cdf'), ('\u2ce1', '\u2ce1'), + ('\u2ce3', '\u2ce4'), ('\u2cec', '\u2cec'), + ('\u2cee', '\u2cee'), ('\u2cf3', '\u2cf3'), + ('\u2d00', '\u2d2d'), ('\ua641', '\ua641'), + ('\ua643', '\ua643'), ('\ua645', '\ua645'), + ('\ua647', '\ua647'), ('\ua649', '\ua649'), + ('\ua64b', '\ua64b'), ('\ua64d', '\ua64d'), + ('\ua64f', '\ua64f'), ('\ua651', '\ua651'), + ('\ua653', '\ua653'), ('\ua655', '\ua655'), + ('\ua657', '\ua657'), ('\ua659', '\ua659'), + ('\ua65b', '\ua65b'), ('\ua65d', '\ua65d'), + ('\ua65f', '\ua65f'), ('\ua661', '\ua661'), + ('\ua663', '\ua663'), ('\ua665', '\ua665'), + ('\ua667', '\ua667'), ('\ua669', '\ua669'), + ('\ua66b', '\ua66b'), ('\ua66d', '\ua66d'), + ('\ua681', '\ua681'), ('\ua683', '\ua683'), + ('\ua685', '\ua685'), ('\ua687', '\ua687'), + ('\ua689', '\ua689'), ('\ua68b', '\ua68b'), + ('\ua68d', '\ua68d'), ('\ua68f', '\ua68f'), + ('\ua691', '\ua691'), ('\ua693', '\ua693'), + ('\ua695', '\ua695'), ('\ua697', '\ua697'), + ('\ua723', '\ua723'), ('\ua725', '\ua725'), + ('\ua727', '\ua727'), ('\ua729', '\ua729'), + ('\ua72b', '\ua72b'), ('\ua72d', '\ua72d'), + ('\ua72f', '\ua731'), ('\ua733', '\ua733'), + ('\ua735', '\ua735'), ('\ua737', '\ua737'), + ('\ua739', '\ua739'), ('\ua73b', '\ua73b'), + ('\ua73d', '\ua73d'), ('\ua73f', '\ua73f'), + ('\ua741', '\ua741'), ('\ua743', '\ua743'), + ('\ua745', '\ua745'), ('\ua747', '\ua747'), + ('\ua749', '\ua749'), ('\ua74b', '\ua74b'), + ('\ua74d', '\ua74d'), ('\ua74f', '\ua74f'), + ('\ua751', '\ua751'), ('\ua753', '\ua753'), + ('\ua755', '\ua755'), ('\ua757', '\ua757'), + ('\ua759', '\ua759'), ('\ua75b', '\ua75b'), + ('\ua75d', '\ua75d'), ('\ua75f', '\ua75f'), + ('\ua761', '\ua761'), ('\ua763', '\ua763'), + ('\ua765', '\ua765'), ('\ua767', '\ua767'), + ('\ua769', '\ua769'), ('\ua76b', '\ua76b'), + ('\ua76d', '\ua76d'), ('\ua76f', '\ua76f'), + ('\ua771', '\ua778'), ('\ua77a', '\ua77a'), + ('\ua77c', '\ua77c'), ('\ua77f', '\ua77f'), + ('\ua781', '\ua781'), ('\ua783', '\ua783'), + ('\ua785', '\ua785'), ('\ua787', '\ua787'), + ('\ua78c', '\ua78c'), ('\ua78e', '\ua78e'), + ('\ua791', '\ua791'), ('\ua793', '\ua793'), + ('\ua7a1', '\ua7a1'), ('\ua7a3', '\ua7a3'), + ('\ua7a5', '\ua7a5'), ('\ua7a7', '\ua7a7'), + ('\ua7a9', '\ua7a9'), ('\ua7fa', '\ua7fa'), + ('\ufb00', '\ufb17'), ('\uff41', '\uff5a'), + ('\U00010428', '\U0001044f'), ('\U0001d41a', '\U0001d433'), + ('\U0001d44e', '\U0001d467'), ('\U0001d482', '\U0001d49b'), + ('\U0001d4b6', '\U0001d4cf'), ('\U0001d4ea', '\U0001d503'), + ('\U0001d51e', '\U0001d537'), ('\U0001d552', '\U0001d56b'), + ('\U0001d586', '\U0001d59f'), ('\U0001d5ba', '\U0001d5d3'), + ('\U0001d5ee', '\U0001d607'), ('\U0001d622', '\U0001d63b'), + ('\U0001d656', '\U0001d66f'), ('\U0001d68a', '\U0001d6a5'), + ('\U0001d6c2', '\U0001d6da'), ('\U0001d6dc', '\U0001d6e1'), + ('\U0001d6fc', '\U0001d714'), ('\U0001d716', '\U0001d71b'), + ('\U0001d736', '\U0001d74e'), ('\U0001d750', '\U0001d755'), + ('\U0001d770', '\U0001d788'), ('\U0001d78a', '\U0001d78f'), + ('\U0001d7aa', '\U0001d7c2'), ('\U0001d7c4', '\U0001d7c9'), + ('\U0001d7cb', '\U0001d7cb') + ]; + + pub fn Ll(c: char) -> bool { + bsearch_range_table(c, Ll_table) + } + + static Lm_table : &'static [(char,char)] = &[ + ('\u02b0', '\u02c1'), ('\u02c6', '\u02d1'), + ('\u02e0', '\u02e4'), ('\u02ec', '\u02ec'), + ('\u02ee', '\u02ee'), ('\u0374', '\u0374'), + ('\u037a', '\u037a'), ('\u0559', '\u0559'), + ('\u0640', '\u0640'), ('\u06e5', '\u06e6'), + ('\u07f4', '\u07f5'), ('\u07fa', '\u07fa'), + ('\u081a', '\u081a'), ('\u0824', '\u0824'), + ('\u0828', '\u0828'), ('\u0971', '\u0971'), + ('\u0e46', '\u0e46'), ('\u0ec6', '\u0ec6'), + ('\u10fc', '\u10fc'), ('\u17d7', '\u17d7'), + ('\u1843', '\u1843'), ('\u1aa7', '\u1aa7'), + ('\u1c78', '\u1c7d'), ('\u1d2c', '\u1d6a'), + ('\u1d78', '\u1d78'), ('\u1d9b', '\u1dbf'), + ('\u2071', '\u2071'), ('\u207f', '\u207f'), + ('\u2090', '\u209c'), ('\u2c7c', '\u2c7d'), + ('\u2d6f', '\u2d6f'), ('\u2e2f', '\u2e2f'), + ('\u3005', '\u3005'), ('\u3031', '\u3035'), + ('\u303b', '\u303b'), ('\u309d', '\u309e'), + ('\u30fc', '\u30fe'), ('\ua015', '\ua015'), + ('\ua4f8', '\ua4fd'), ('\ua60c', '\ua60c'), + ('\ua67f', '\ua67f'), ('\ua717', '\ua71f'), + ('\ua770', '\ua770'), ('\ua788', '\ua788'), + ('\ua7f8', '\ua7f9'), ('\ua9cf', '\ua9cf'), + ('\uaa70', '\uaa70'), ('\uaadd', '\uaadd'), + ('\uaaf3', '\uaaf4'), ('\uff70', '\uff70'), + ('\uff9e', '\uff9f'), ('\U00016f93', '\U00016f9f') + ]; + + pub fn Lm(c: char) -> bool { + bsearch_range_table(c, Lm_table) + } + + static Lo_table : &'static [(char,char)] = &[ + ('\xaa', '\xaa'), ('\xba', '\xba'), + ('\u01bb', '\u01bb'), ('\u01c0', '\u01c3'), + ('\u0294', '\u0294'), ('\u05d0', '\u05f2'), + ('\u0620', '\u063f'), ('\u0641', '\u064a'), + ('\u066e', '\u066f'), ('\u0671', '\u06d3'), + ('\u06d5', '\u06d5'), ('\u06ee', '\u06ef'), + ('\u06fa', '\u06fc'), ('\u06ff', '\u06ff'), + ('\u0710', '\u0710'), ('\u0712', '\u072f'), + ('\u074d', '\u07a5'), ('\u07b1', '\u07b1'), + ('\u07ca', '\u07ea'), ('\u0800', '\u0815'), + ('\u0840', '\u0858'), ('\u08a0', '\u08ac'), + ('\u0904', '\u0939'), ('\u093d', '\u093d'), + ('\u0950', '\u0950'), ('\u0958', '\u0961'), + ('\u0972', '\u097f'), ('\u0985', '\u09b9'), + ('\u09bd', '\u09bd'), ('\u09ce', '\u09ce'), + ('\u09dc', '\u09e1'), ('\u09f0', '\u09f1'), + ('\u0a05', '\u0a39'), ('\u0a59', '\u0a5e'), + ('\u0a72', '\u0a74'), ('\u0a85', '\u0ab9'), + ('\u0abd', '\u0abd'), ('\u0ad0', '\u0ae1'), + ('\u0b05', '\u0b39'), ('\u0b3d', '\u0b3d'), + ('\u0b5c', '\u0b61'), ('\u0b71', '\u0b71'), + ('\u0b83', '\u0bb9'), ('\u0bd0', '\u0bd0'), + ('\u0c05', '\u0c3d'), ('\u0c58', '\u0c61'), + ('\u0c85', '\u0cb9'), ('\u0cbd', '\u0cbd'), + ('\u0cde', '\u0ce1'), ('\u0cf1', '\u0cf2'), + ('\u0d05', '\u0d3d'), ('\u0d4e', '\u0d4e'), + ('\u0d60', '\u0d61'), ('\u0d7a', '\u0d7f'), + ('\u0d85', '\u0dc6'), ('\u0e01', '\u0e30'), + ('\u0e32', '\u0e33'), ('\u0e40', '\u0e45'), + ('\u0e81', '\u0eb0'), ('\u0eb2', '\u0eb3'), + ('\u0ebd', '\u0ec4'), ('\u0edc', '\u0f00'), + ('\u0f40', '\u0f6c'), ('\u0f88', '\u0f8c'), + ('\u1000', '\u102a'), ('\u103f', '\u103f'), + ('\u1050', '\u1055'), ('\u105a', '\u105d'), + ('\u1061', '\u1061'), ('\u1065', '\u1066'), + ('\u106e', '\u1070'), ('\u1075', '\u1081'), + ('\u108e', '\u108e'), ('\u10d0', '\u10fa'), + ('\u10fd', '\u135a'), ('\u1380', '\u138f'), + ('\u13a0', '\u13f4'), ('\u1401', '\u166c'), + ('\u166f', '\u167f'), ('\u1681', '\u169a'), + ('\u16a0', '\u16ea'), ('\u1700', '\u1711'), + ('\u1720', '\u1731'), ('\u1740', '\u1751'), + ('\u1760', '\u1770'), ('\u1780', '\u17b3'), + ('\u17dc', '\u17dc'), ('\u1820', '\u1842'), + ('\u1844', '\u18a8'), ('\u18aa', '\u191c'), + ('\u1950', '\u19ab'), ('\u19c1', '\u19c7'), + ('\u1a00', '\u1a16'), ('\u1a20', '\u1a54'), + ('\u1b05', '\u1b33'), ('\u1b45', '\u1b4b'), + ('\u1b83', '\u1ba0'), ('\u1bae', '\u1baf'), + ('\u1bba', '\u1be5'), ('\u1c00', '\u1c23'), + ('\u1c4d', '\u1c4f'), ('\u1c5a', '\u1c77'), + ('\u1ce9', '\u1cec'), ('\u1cee', '\u1cf1'), + ('\u1cf5', '\u1cf6'), ('\u2135', '\u2138'), + ('\u2d30', '\u2d67'), ('\u2d80', '\u2dde'), + ('\u3006', '\u3006'), ('\u303c', '\u303c'), + ('\u3041', '\u3096'), ('\u309f', '\u309f'), + ('\u30a1', '\u30fa'), ('\u30ff', '\u318e'), + ('\u31a0', '\u31ba'), ('\u31f0', '\u31ff'), + ('\u3400', '\u4db5'), ('\u4e00', '\ua014'), + ('\ua016', '\ua48c'), ('\ua4d0', '\ua4f7'), + ('\ua500', '\ua60b'), ('\ua610', '\ua61f'), + ('\ua62a', '\ua62b'), ('\ua66e', '\ua66e'), + ('\ua6a0', '\ua6e5'), ('\ua7fb', '\ua801'), + ('\ua803', '\ua805'), ('\ua807', '\ua80a'), + ('\ua80c', '\ua822'), ('\ua840', '\ua873'), + ('\ua882', '\ua8b3'), ('\ua8f2', '\ua8f7'), + ('\ua8fb', '\ua8fb'), ('\ua90a', '\ua925'), + ('\ua930', '\ua946'), ('\ua960', '\ua97c'), + ('\ua984', '\ua9b2'), ('\uaa00', '\uaa28'), + ('\uaa40', '\uaa42'), ('\uaa44', '\uaa4b'), + ('\uaa60', '\uaa6f'), ('\uaa71', '\uaa76'), + ('\uaa7a', '\uaa7a'), ('\uaa80', '\uaaaf'), + ('\uaab1', '\uaab1'), ('\uaab5', '\uaab6'), + ('\uaab9', '\uaabd'), ('\uaac0', '\uaac0'), + ('\uaac2', '\uaadc'), ('\uaae0', '\uaaea'), + ('\uaaf2', '\uaaf2'), ('\uab01', '\uabe2'), + ('\uac00', '\ud7fb'), ('\uf900', '\ufad9'), + ('\ufb1d', '\ufb1d'), ('\ufb1f', '\ufb28'), + ('\ufb2a', '\ufbb1'), ('\ufbd3', '\ufd3d'), + ('\ufd50', '\ufdfb'), ('\ufe70', '\ufefc'), + ('\uff66', '\uff6f'), ('\uff71', '\uff9d'), + ('\uffa0', '\uffdc'), ('\U00010000', '\U000100fa'), + ('\U00010280', '\U0001031e'), ('\U00010330', '\U00010340'), + ('\U00010342', '\U00010349'), ('\U00010380', '\U0001039d'), + ('\U000103a0', '\U000103cf'), ('\U00010450', '\U0001049d'), + ('\U00010800', '\U00010855'), ('\U00010900', '\U00010915'), + ('\U00010920', '\U00010939'), ('\U00010980', '\U00010a00'), + ('\U00010a10', '\U00010a33'), ('\U00010a60', '\U00010a7c'), + ('\U00010b00', '\U00010b35'), ('\U00010b40', '\U00010b55'), + ('\U00010b60', '\U00010b72'), ('\U00010c00', '\U00010c48'), + ('\U00011003', '\U00011037'), ('\U00011083', '\U000110af'), + ('\U000110d0', '\U000110e8'), ('\U00011103', '\U00011126'), + ('\U00011183', '\U000111b2'), ('\U000111c1', '\U000111c4'), + ('\U00011680', '\U000116aa'), ('\U00012000', '\U0001236e'), + ('\U00013000', '\U00016f50'), ('\U0001b000', '\U0001b001'), + ('\U0001ee00', '\U0001eebb'), ('\U00020000', '\U0002fa1d') + ]; + + pub fn Lo(c: char) -> bool { + bsearch_range_table(c, Lo_table) + } + + static Lt_table : &'static [(char,char)] = &[ + ('\u01c5', '\u01c5'), ('\u01c8', '\u01c8'), + ('\u01cb', '\u01cb'), ('\u01f2', '\u01f2'), + ('\u1f88', '\u1f8f'), ('\u1f98', '\u1f9f'), + ('\u1fa8', '\u1faf'), ('\u1fbc', '\u1fbc'), + ('\u1fcc', '\u1fcc'), ('\u1ffc', '\u1ffc') + ]; + + pub fn Lt(c: char) -> bool { + bsearch_range_table(c, Lt_table) + } + + static Lu_table : &'static [(char,char)] = &[ + ('\x41', '\x5a'), ('\xc0', '\xd6'), + ('\xd8', '\xde'), ('\u0100', '\u0100'), + ('\u0102', '\u0102'), ('\u0104', '\u0104'), + ('\u0106', '\u0106'), ('\u0108', '\u0108'), + ('\u010a', '\u010a'), ('\u010c', '\u010c'), + ('\u010e', '\u010e'), ('\u0110', '\u0110'), + ('\u0112', '\u0112'), ('\u0114', '\u0114'), + ('\u0116', '\u0116'), ('\u0118', '\u0118'), + ('\u011a', '\u011a'), ('\u011c', '\u011c'), + ('\u011e', '\u011e'), ('\u0120', '\u0120'), + ('\u0122', '\u0122'), ('\u0124', '\u0124'), + ('\u0126', '\u0126'), ('\u0128', '\u0128'), + ('\u012a', '\u012a'), ('\u012c', '\u012c'), + ('\u012e', '\u012e'), ('\u0130', '\u0130'), + ('\u0132', '\u0132'), ('\u0134', '\u0134'), + ('\u0136', '\u0136'), ('\u0139', '\u0139'), + ('\u013b', '\u013b'), ('\u013d', '\u013d'), + ('\u013f', '\u013f'), ('\u0141', '\u0141'), + ('\u0143', '\u0143'), ('\u0145', '\u0145'), + ('\u0147', '\u0147'), ('\u014a', '\u014a'), + ('\u014c', '\u014c'), ('\u014e', '\u014e'), + ('\u0150', '\u0150'), ('\u0152', '\u0152'), + ('\u0154', '\u0154'), ('\u0156', '\u0156'), + ('\u0158', '\u0158'), ('\u015a', '\u015a'), + ('\u015c', '\u015c'), ('\u015e', '\u015e'), + ('\u0160', '\u0160'), ('\u0162', '\u0162'), + ('\u0164', '\u0164'), ('\u0166', '\u0166'), + ('\u0168', '\u0168'), ('\u016a', '\u016a'), + ('\u016c', '\u016c'), ('\u016e', '\u016e'), + ('\u0170', '\u0170'), ('\u0172', '\u0172'), + ('\u0174', '\u0174'), ('\u0176', '\u0176'), + ('\u0178', '\u0179'), ('\u017b', '\u017b'), + ('\u017d', '\u017d'), ('\u0181', '\u0182'), + ('\u0184', '\u0184'), ('\u0186', '\u0187'), + ('\u0189', '\u018b'), ('\u018e', '\u0191'), + ('\u0193', '\u0194'), ('\u0196', '\u0198'), + ('\u019c', '\u019d'), ('\u019f', '\u01a0'), + ('\u01a2', '\u01a2'), ('\u01a4', '\u01a4'), + ('\u01a6', '\u01a7'), ('\u01a9', '\u01a9'), + ('\u01ac', '\u01ac'), ('\u01ae', '\u01af'), + ('\u01b1', '\u01b3'), ('\u01b5', '\u01b5'), + ('\u01b7', '\u01b8'), ('\u01bc', '\u01bc'), + ('\u01c4', '\u01c4'), ('\u01c7', '\u01c7'), + ('\u01ca', '\u01ca'), ('\u01cd', '\u01cd'), + ('\u01cf', '\u01cf'), ('\u01d1', '\u01d1'), + ('\u01d3', '\u01d3'), ('\u01d5', '\u01d5'), + ('\u01d7', '\u01d7'), ('\u01d9', '\u01d9'), + ('\u01db', '\u01db'), ('\u01de', '\u01de'), + ('\u01e0', '\u01e0'), ('\u01e2', '\u01e2'), + ('\u01e4', '\u01e4'), ('\u01e6', '\u01e6'), + ('\u01e8', '\u01e8'), ('\u01ea', '\u01ea'), + ('\u01ec', '\u01ec'), ('\u01ee', '\u01ee'), + ('\u01f1', '\u01f1'), ('\u01f4', '\u01f4'), + ('\u01f6', '\u01f8'), ('\u01fa', '\u01fa'), + ('\u01fc', '\u01fc'), ('\u01fe', '\u01fe'), + ('\u0200', '\u0200'), ('\u0202', '\u0202'), + ('\u0204', '\u0204'), ('\u0206', '\u0206'), + ('\u0208', '\u0208'), ('\u020a', '\u020a'), + ('\u020c', '\u020c'), ('\u020e', '\u020e'), + ('\u0210', '\u0210'), ('\u0212', '\u0212'), + ('\u0214', '\u0214'), ('\u0216', '\u0216'), + ('\u0218', '\u0218'), ('\u021a', '\u021a'), + ('\u021c', '\u021c'), ('\u021e', '\u021e'), + ('\u0220', '\u0220'), ('\u0222', '\u0222'), + ('\u0224', '\u0224'), ('\u0226', '\u0226'), + ('\u0228', '\u0228'), ('\u022a', '\u022a'), + ('\u022c', '\u022c'), ('\u022e', '\u022e'), + ('\u0230', '\u0230'), ('\u0232', '\u0232'), + ('\u023a', '\u023b'), ('\u023d', '\u023e'), + ('\u0241', '\u0241'), ('\u0243', '\u0246'), + ('\u0248', '\u0248'), ('\u024a', '\u024a'), + ('\u024c', '\u024c'), ('\u024e', '\u024e'), + ('\u0370', '\u0370'), ('\u0372', '\u0372'), + ('\u0376', '\u0376'), ('\u0386', '\u0386'), + ('\u0388', '\u038f'), ('\u0391', '\u03ab'), + ('\u03cf', '\u03cf'), ('\u03d2', '\u03d4'), + ('\u03d8', '\u03d8'), ('\u03da', '\u03da'), + ('\u03dc', '\u03dc'), ('\u03de', '\u03de'), + ('\u03e0', '\u03e0'), ('\u03e2', '\u03e2'), + ('\u03e4', '\u03e4'), ('\u03e6', '\u03e6'), + ('\u03e8', '\u03e8'), ('\u03ea', '\u03ea'), + ('\u03ec', '\u03ec'), ('\u03ee', '\u03ee'), + ('\u03f4', '\u03f4'), ('\u03f7', '\u03f7'), + ('\u03f9', '\u03fa'), ('\u03fd', '\u042f'), + ('\u0460', '\u0460'), ('\u0462', '\u0462'), + ('\u0464', '\u0464'), ('\u0466', '\u0466'), + ('\u0468', '\u0468'), ('\u046a', '\u046a'), + ('\u046c', '\u046c'), ('\u046e', '\u046e'), + ('\u0470', '\u0470'), ('\u0472', '\u0472'), + ('\u0474', '\u0474'), ('\u0476', '\u0476'), + ('\u0478', '\u0478'), ('\u047a', '\u047a'), + ('\u047c', '\u047c'), ('\u047e', '\u047e'), + ('\u0480', '\u0480'), ('\u048a', '\u048a'), + ('\u048c', '\u048c'), ('\u048e', '\u048e'), + ('\u0490', '\u0490'), ('\u0492', '\u0492'), + ('\u0494', '\u0494'), ('\u0496', '\u0496'), + ('\u0498', '\u0498'), ('\u049a', '\u049a'), + ('\u049c', '\u049c'), ('\u049e', '\u049e'), + ('\u04a0', '\u04a0'), ('\u04a2', '\u04a2'), + ('\u04a4', '\u04a4'), ('\u04a6', '\u04a6'), + ('\u04a8', '\u04a8'), ('\u04aa', '\u04aa'), + ('\u04ac', '\u04ac'), ('\u04ae', '\u04ae'), + ('\u04b0', '\u04b0'), ('\u04b2', '\u04b2'), + ('\u04b4', '\u04b4'), ('\u04b6', '\u04b6'), + ('\u04b8', '\u04b8'), ('\u04ba', '\u04ba'), + ('\u04bc', '\u04bc'), ('\u04be', '\u04be'), + ('\u04c0', '\u04c1'), ('\u04c3', '\u04c3'), + ('\u04c5', '\u04c5'), ('\u04c7', '\u04c7'), + ('\u04c9', '\u04c9'), ('\u04cb', '\u04cb'), + ('\u04cd', '\u04cd'), ('\u04d0', '\u04d0'), + ('\u04d2', '\u04d2'), ('\u04d4', '\u04d4'), + ('\u04d6', '\u04d6'), ('\u04d8', '\u04d8'), + ('\u04da', '\u04da'), ('\u04dc', '\u04dc'), + ('\u04de', '\u04de'), ('\u04e0', '\u04e0'), + ('\u04e2', '\u04e2'), ('\u04e4', '\u04e4'), + ('\u04e6', '\u04e6'), ('\u04e8', '\u04e8'), + ('\u04ea', '\u04ea'), ('\u04ec', '\u04ec'), + ('\u04ee', '\u04ee'), ('\u04f0', '\u04f0'), + ('\u04f2', '\u04f2'), ('\u04f4', '\u04f4'), + ('\u04f6', '\u04f6'), ('\u04f8', '\u04f8'), + ('\u04fa', '\u04fa'), ('\u04fc', '\u04fc'), + ('\u04fe', '\u04fe'), ('\u0500', '\u0500'), + ('\u0502', '\u0502'), ('\u0504', '\u0504'), + ('\u0506', '\u0506'), ('\u0508', '\u0508'), + ('\u050a', '\u050a'), ('\u050c', '\u050c'), + ('\u050e', '\u050e'), ('\u0510', '\u0510'), + ('\u0512', '\u0512'), ('\u0514', '\u0514'), + ('\u0516', '\u0516'), ('\u0518', '\u0518'), + ('\u051a', '\u051a'), ('\u051c', '\u051c'), + ('\u051e', '\u051e'), ('\u0520', '\u0520'), + ('\u0522', '\u0522'), ('\u0524', '\u0524'), + ('\u0526', '\u0526'), ('\u0531', '\u0556'), + ('\u10a0', '\u10cd'), ('\u1e00', '\u1e00'), + ('\u1e02', '\u1e02'), ('\u1e04', '\u1e04'), + ('\u1e06', '\u1e06'), ('\u1e08', '\u1e08'), + ('\u1e0a', '\u1e0a'), ('\u1e0c', '\u1e0c'), + ('\u1e0e', '\u1e0e'), ('\u1e10', '\u1e10'), + ('\u1e12', '\u1e12'), ('\u1e14', '\u1e14'), + ('\u1e16', '\u1e16'), ('\u1e18', '\u1e18'), + ('\u1e1a', '\u1e1a'), ('\u1e1c', '\u1e1c'), + ('\u1e1e', '\u1e1e'), ('\u1e20', '\u1e20'), + ('\u1e22', '\u1e22'), ('\u1e24', '\u1e24'), + ('\u1e26', '\u1e26'), ('\u1e28', '\u1e28'), + ('\u1e2a', '\u1e2a'), ('\u1e2c', '\u1e2c'), + ('\u1e2e', '\u1e2e'), ('\u1e30', '\u1e30'), + ('\u1e32', '\u1e32'), ('\u1e34', '\u1e34'), + ('\u1e36', '\u1e36'), ('\u1e38', '\u1e38'), + ('\u1e3a', '\u1e3a'), ('\u1e3c', '\u1e3c'), + ('\u1e3e', '\u1e3e'), ('\u1e40', '\u1e40'), + ('\u1e42', '\u1e42'), ('\u1e44', '\u1e44'), + ('\u1e46', '\u1e46'), ('\u1e48', '\u1e48'), + ('\u1e4a', '\u1e4a'), ('\u1e4c', '\u1e4c'), + ('\u1e4e', '\u1e4e'), ('\u1e50', '\u1e50'), + ('\u1e52', '\u1e52'), ('\u1e54', '\u1e54'), + ('\u1e56', '\u1e56'), ('\u1e58', '\u1e58'), + ('\u1e5a', '\u1e5a'), ('\u1e5c', '\u1e5c'), + ('\u1e5e', '\u1e5e'), ('\u1e60', '\u1e60'), + ('\u1e62', '\u1e62'), ('\u1e64', '\u1e64'), + ('\u1e66', '\u1e66'), ('\u1e68', '\u1e68'), + ('\u1e6a', '\u1e6a'), ('\u1e6c', '\u1e6c'), + ('\u1e6e', '\u1e6e'), ('\u1e70', '\u1e70'), + ('\u1e72', '\u1e72'), ('\u1e74', '\u1e74'), + ('\u1e76', '\u1e76'), ('\u1e78', '\u1e78'), + ('\u1e7a', '\u1e7a'), ('\u1e7c', '\u1e7c'), + ('\u1e7e', '\u1e7e'), ('\u1e80', '\u1e80'), + ('\u1e82', '\u1e82'), ('\u1e84', '\u1e84'), + ('\u1e86', '\u1e86'), ('\u1e88', '\u1e88'), + ('\u1e8a', '\u1e8a'), ('\u1e8c', '\u1e8c'), + ('\u1e8e', '\u1e8e'), ('\u1e90', '\u1e90'), + ('\u1e92', '\u1e92'), ('\u1e94', '\u1e94'), + ('\u1e9e', '\u1e9e'), ('\u1ea0', '\u1ea0'), + ('\u1ea2', '\u1ea2'), ('\u1ea4', '\u1ea4'), + ('\u1ea6', '\u1ea6'), ('\u1ea8', '\u1ea8'), + ('\u1eaa', '\u1eaa'), ('\u1eac', '\u1eac'), + ('\u1eae', '\u1eae'), ('\u1eb0', '\u1eb0'), + ('\u1eb2', '\u1eb2'), ('\u1eb4', '\u1eb4'), + ('\u1eb6', '\u1eb6'), ('\u1eb8', '\u1eb8'), + ('\u1eba', '\u1eba'), ('\u1ebc', '\u1ebc'), + ('\u1ebe', '\u1ebe'), ('\u1ec0', '\u1ec0'), + ('\u1ec2', '\u1ec2'), ('\u1ec4', '\u1ec4'), + ('\u1ec6', '\u1ec6'), ('\u1ec8', '\u1ec8'), + ('\u1eca', '\u1eca'), ('\u1ecc', '\u1ecc'), + ('\u1ece', '\u1ece'), ('\u1ed0', '\u1ed0'), + ('\u1ed2', '\u1ed2'), ('\u1ed4', '\u1ed4'), + ('\u1ed6', '\u1ed6'), ('\u1ed8', '\u1ed8'), + ('\u1eda', '\u1eda'), ('\u1edc', '\u1edc'), + ('\u1ede', '\u1ede'), ('\u1ee0', '\u1ee0'), + ('\u1ee2', '\u1ee2'), ('\u1ee4', '\u1ee4'), + ('\u1ee6', '\u1ee6'), ('\u1ee8', '\u1ee8'), + ('\u1eea', '\u1eea'), ('\u1eec', '\u1eec'), + ('\u1eee', '\u1eee'), ('\u1ef0', '\u1ef0'), + ('\u1ef2', '\u1ef2'), ('\u1ef4', '\u1ef4'), + ('\u1ef6', '\u1ef6'), ('\u1ef8', '\u1ef8'), + ('\u1efa', '\u1efa'), ('\u1efc', '\u1efc'), + ('\u1efe', '\u1efe'), ('\u1f08', '\u1f0f'), + ('\u1f18', '\u1f1d'), ('\u1f28', '\u1f2f'), + ('\u1f38', '\u1f3f'), ('\u1f48', '\u1f4d'), + ('\u1f59', '\u1f5f'), ('\u1f68', '\u1f6f'), + ('\u1fb8', '\u1fbb'), ('\u1fc8', '\u1fcb'), + ('\u1fd8', '\u1fdb'), ('\u1fe8', '\u1fec'), + ('\u1ff8', '\u1ffb'), ('\u2102', '\u2102'), + ('\u2107', '\u2107'), ('\u210b', '\u210d'), + ('\u2110', '\u2112'), ('\u2115', '\u2115'), + ('\u2119', '\u211d'), ('\u2124', '\u2124'), + ('\u2126', '\u2126'), ('\u2128', '\u2128'), + ('\u212a', '\u212d'), ('\u2130', '\u2133'), + ('\u213e', '\u213f'), ('\u2145', '\u2145'), + ('\u2183', '\u2183'), ('\u2c00', '\u2c2e'), + ('\u2c60', '\u2c60'), ('\u2c62', '\u2c64'), + ('\u2c67', '\u2c67'), ('\u2c69', '\u2c69'), + ('\u2c6b', '\u2c6b'), ('\u2c6d', '\u2c70'), + ('\u2c72', '\u2c72'), ('\u2c75', '\u2c75'), + ('\u2c7e', '\u2c80'), ('\u2c82', '\u2c82'), + ('\u2c84', '\u2c84'), ('\u2c86', '\u2c86'), + ('\u2c88', '\u2c88'), ('\u2c8a', '\u2c8a'), + ('\u2c8c', '\u2c8c'), ('\u2c8e', '\u2c8e'), + ('\u2c90', '\u2c90'), ('\u2c92', '\u2c92'), + ('\u2c94', '\u2c94'), ('\u2c96', '\u2c96'), + ('\u2c98', '\u2c98'), ('\u2c9a', '\u2c9a'), + ('\u2c9c', '\u2c9c'), ('\u2c9e', '\u2c9e'), + ('\u2ca0', '\u2ca0'), ('\u2ca2', '\u2ca2'), + ('\u2ca4', '\u2ca4'), ('\u2ca6', '\u2ca6'), + ('\u2ca8', '\u2ca8'), ('\u2caa', '\u2caa'), + ('\u2cac', '\u2cac'), ('\u2cae', '\u2cae'), + ('\u2cb0', '\u2cb0'), ('\u2cb2', '\u2cb2'), + ('\u2cb4', '\u2cb4'), ('\u2cb6', '\u2cb6'), + ('\u2cb8', '\u2cb8'), ('\u2cba', '\u2cba'), + ('\u2cbc', '\u2cbc'), ('\u2cbe', '\u2cbe'), + ('\u2cc0', '\u2cc0'), ('\u2cc2', '\u2cc2'), + ('\u2cc4', '\u2cc4'), ('\u2cc6', '\u2cc6'), + ('\u2cc8', '\u2cc8'), ('\u2cca', '\u2cca'), + ('\u2ccc', '\u2ccc'), ('\u2cce', '\u2cce'), + ('\u2cd0', '\u2cd0'), ('\u2cd2', '\u2cd2'), + ('\u2cd4', '\u2cd4'), ('\u2cd6', '\u2cd6'), + ('\u2cd8', '\u2cd8'), ('\u2cda', '\u2cda'), + ('\u2cdc', '\u2cdc'), ('\u2cde', '\u2cde'), + ('\u2ce0', '\u2ce0'), ('\u2ce2', '\u2ce2'), + ('\u2ceb', '\u2ceb'), ('\u2ced', '\u2ced'), + ('\u2cf2', '\u2cf2'), ('\ua640', '\ua640'), + ('\ua642', '\ua642'), ('\ua644', '\ua644'), + ('\ua646', '\ua646'), ('\ua648', '\ua648'), + ('\ua64a', '\ua64a'), ('\ua64c', '\ua64c'), + ('\ua64e', '\ua64e'), ('\ua650', '\ua650'), + ('\ua652', '\ua652'), ('\ua654', '\ua654'), + ('\ua656', '\ua656'), ('\ua658', '\ua658'), + ('\ua65a', '\ua65a'), ('\ua65c', '\ua65c'), + ('\ua65e', '\ua65e'), ('\ua660', '\ua660'), + ('\ua662', '\ua662'), ('\ua664', '\ua664'), + ('\ua666', '\ua666'), ('\ua668', '\ua668'), + ('\ua66a', '\ua66a'), ('\ua66c', '\ua66c'), + ('\ua680', '\ua680'), ('\ua682', '\ua682'), + ('\ua684', '\ua684'), ('\ua686', '\ua686'), + ('\ua688', '\ua688'), ('\ua68a', '\ua68a'), + ('\ua68c', '\ua68c'), ('\ua68e', '\ua68e'), + ('\ua690', '\ua690'), ('\ua692', '\ua692'), + ('\ua694', '\ua694'), ('\ua696', '\ua696'), + ('\ua722', '\ua722'), ('\ua724', '\ua724'), + ('\ua726', '\ua726'), ('\ua728', '\ua728'), + ('\ua72a', '\ua72a'), ('\ua72c', '\ua72c'), + ('\ua72e', '\ua72e'), ('\ua732', '\ua732'), + ('\ua734', '\ua734'), ('\ua736', '\ua736'), + ('\ua738', '\ua738'), ('\ua73a', '\ua73a'), + ('\ua73c', '\ua73c'), ('\ua73e', '\ua73e'), + ('\ua740', '\ua740'), ('\ua742', '\ua742'), + ('\ua744', '\ua744'), ('\ua746', '\ua746'), + ('\ua748', '\ua748'), ('\ua74a', '\ua74a'), + ('\ua74c', '\ua74c'), ('\ua74e', '\ua74e'), + ('\ua750', '\ua750'), ('\ua752', '\ua752'), + ('\ua754', '\ua754'), ('\ua756', '\ua756'), + ('\ua758', '\ua758'), ('\ua75a', '\ua75a'), + ('\ua75c', '\ua75c'), ('\ua75e', '\ua75e'), + ('\ua760', '\ua760'), ('\ua762', '\ua762'), + ('\ua764', '\ua764'), ('\ua766', '\ua766'), + ('\ua768', '\ua768'), ('\ua76a', '\ua76a'), + ('\ua76c', '\ua76c'), ('\ua76e', '\ua76e'), + ('\ua779', '\ua779'), ('\ua77b', '\ua77b'), + ('\ua77d', '\ua77e'), ('\ua780', '\ua780'), + ('\ua782', '\ua782'), ('\ua784', '\ua784'), + ('\ua786', '\ua786'), ('\ua78b', '\ua78b'), + ('\ua78d', '\ua78d'), ('\ua790', '\ua790'), + ('\ua792', '\ua792'), ('\ua7a0', '\ua7a0'), + ('\ua7a2', '\ua7a2'), ('\ua7a4', '\ua7a4'), + ('\ua7a6', '\ua7a6'), ('\ua7a8', '\ua7a8'), + ('\ua7aa', '\ua7aa'), ('\uff21', '\uff3a'), + ('\U00010400', '\U00010427'), ('\U0001d400', '\U0001d419'), + ('\U0001d434', '\U0001d44d'), ('\U0001d468', '\U0001d481'), + ('\U0001d49c', '\U0001d4b5'), ('\U0001d4d0', '\U0001d4e9'), + ('\U0001d504', '\U0001d51c'), ('\U0001d538', '\U0001d550'), + ('\U0001d56c', '\U0001d585'), ('\U0001d5a0', '\U0001d5b9'), + ('\U0001d5d4', '\U0001d5ed'), ('\U0001d608', '\U0001d621'), + ('\U0001d63c', '\U0001d655'), ('\U0001d670', '\U0001d689'), + ('\U0001d6a8', '\U0001d6c0'), ('\U0001d6e2', '\U0001d6fa'), + ('\U0001d71c', '\U0001d734'), ('\U0001d756', '\U0001d76e'), + ('\U0001d790', '\U0001d7a8'), ('\U0001d7ca', '\U0001d7ca') + ]; + + pub fn Lu(c: char) -> bool { + bsearch_range_table(c, Lu_table) + } + + static Mc_table : &'static [(char,char)] = &[ + ('\u0903', '\u0903'), ('\u093b', '\u093b'), + ('\u093e', '\u0940'), ('\u0949', '\u094c'), + ('\u094e', '\u094f'), ('\u0982', '\u0983'), + ('\u09be', '\u09c0'), ('\u09c7', '\u09cc'), + ('\u09d7', '\u09d7'), ('\u0a03', '\u0a03'), + ('\u0a3e', '\u0a40'), ('\u0a83', '\u0a83'), + ('\u0abe', '\u0ac0'), ('\u0ac9', '\u0acc'), + ('\u0b02', '\u0b03'), ('\u0b3e', '\u0b3e'), + ('\u0b40', '\u0b40'), ('\u0b47', '\u0b4c'), + ('\u0b57', '\u0b57'), ('\u0bbe', '\u0bbf'), + ('\u0bc1', '\u0bcc'), ('\u0bd7', '\u0bd7'), + ('\u0c01', '\u0c03'), ('\u0c41', '\u0c44'), + ('\u0c82', '\u0c83'), ('\u0cbe', '\u0cbe'), + ('\u0cc0', '\u0cc4'), ('\u0cc7', '\u0ccb'), + ('\u0cd5', '\u0cd6'), ('\u0d02', '\u0d03'), + ('\u0d3e', '\u0d40'), ('\u0d46', '\u0d4c'), + ('\u0d57', '\u0d57'), ('\u0d82', '\u0d83'), + ('\u0dcf', '\u0dd1'), ('\u0dd8', '\u0df3'), + ('\u0f3e', '\u0f3f'), ('\u0f7f', '\u0f7f'), + ('\u102b', '\u102c'), ('\u1031', '\u1031'), + ('\u1038', '\u1038'), ('\u103b', '\u103c'), + ('\u1056', '\u1057'), ('\u1062', '\u1064'), + ('\u1067', '\u106d'), ('\u1083', '\u1084'), + ('\u1087', '\u108c'), ('\u108f', '\u108f'), + ('\u109a', '\u109c'), ('\u17b6', '\u17b6'), + ('\u17be', '\u17c5'), ('\u17c7', '\u17c8'), + ('\u1923', '\u1926'), ('\u1929', '\u1931'), + ('\u1933', '\u1938'), ('\u19b0', '\u19c0'), + ('\u19c8', '\u19c9'), ('\u1a19', '\u1a1b'), + ('\u1a55', '\u1a55'), ('\u1a57', '\u1a57'), + ('\u1a61', '\u1a61'), ('\u1a63', '\u1a64'), + ('\u1a6d', '\u1a72'), ('\u1b04', '\u1b04'), + ('\u1b35', '\u1b35'), ('\u1b3b', '\u1b3b'), + ('\u1b3d', '\u1b41'), ('\u1b43', '\u1b44'), + ('\u1b82', '\u1b82'), ('\u1ba1', '\u1ba1'), + ('\u1ba6', '\u1ba7'), ('\u1baa', '\u1baa'), + ('\u1bac', '\u1bad'), ('\u1be7', '\u1be7'), + ('\u1bea', '\u1bec'), ('\u1bee', '\u1bee'), + ('\u1bf2', '\u1bf3'), ('\u1c24', '\u1c2b'), + ('\u1c34', '\u1c35'), ('\u1ce1', '\u1ce1'), + ('\u1cf2', '\u1cf3'), ('\u302e', '\u302f'), + ('\ua823', '\ua824'), ('\ua827', '\ua827'), + ('\ua880', '\ua881'), ('\ua8b4', '\ua8c3'), + ('\ua952', '\ua953'), ('\ua983', '\ua983'), + ('\ua9b4', '\ua9b5'), ('\ua9ba', '\ua9bb'), + ('\ua9bd', '\ua9c0'), ('\uaa2f', '\uaa30'), + ('\uaa33', '\uaa34'), ('\uaa4d', '\uaa4d'), + ('\uaa7b', '\uaa7b'), ('\uaaeb', '\uaaeb'), + ('\uaaee', '\uaaef'), ('\uaaf5', '\uaaf5'), + ('\uabe3', '\uabe4'), ('\uabe6', '\uabe7'), + ('\uabe9', '\uabea'), ('\uabec', '\uabec'), + ('\U00011000', '\U00011000'), ('\U00011002', '\U00011002'), + ('\U00011082', '\U00011082'), ('\U000110b0', '\U000110b2'), + ('\U000110b7', '\U000110b8'), ('\U0001112c', '\U0001112c'), + ('\U00011182', '\U00011182'), ('\U000111b3', '\U000111b5'), + ('\U000111bf', '\U000111c0'), ('\U000116ac', '\U000116ac'), + ('\U000116ae', '\U000116af'), ('\U000116b6', '\U000116b6'), + ('\U00016f51', '\U00016f7e'), ('\U0001d165', '\U0001d166'), + ('\U0001d16d', '\U0001d172') + ]; + + pub fn Mc(c: char) -> bool { + bsearch_range_table(c, Mc_table) + } + + static Me_table : &'static [(char,char)] = &[ + ('\u0488', '\u0489'), ('\u20dd', '\u20e0'), + ('\u20e2', '\u20e4'), ('\ua670', '\ua672') + ]; + + pub fn Me(c: char) -> bool { + bsearch_range_table(c, Me_table) + } + + static Mn_table : &'static [(char,char)] = &[ + ('\u0300', '\u036f'), ('\u0483', '\u0487'), + ('\u0591', '\u05bd'), ('\u05bf', '\u05bf'), + ('\u05c1', '\u05c2'), ('\u05c4', '\u05c5'), + ('\u05c7', '\u05c7'), ('\u0610', '\u061a'), + ('\u064b', '\u065f'), ('\u0670', '\u0670'), + ('\u06d6', '\u06dc'), ('\u06df', '\u06e4'), + ('\u06e7', '\u06e8'), ('\u06ea', '\u06ed'), + ('\u0711', '\u0711'), ('\u0730', '\u074a'), + ('\u07a6', '\u07b0'), ('\u07eb', '\u07f3'), + ('\u0816', '\u0819'), ('\u081b', '\u0823'), + ('\u0825', '\u0827'), ('\u0829', '\u082d'), + ('\u0859', '\u085b'), ('\u08e4', '\u0902'), + ('\u093a', '\u093a'), ('\u093c', '\u093c'), + ('\u0941', '\u0948'), ('\u094d', '\u094d'), + ('\u0951', '\u0957'), ('\u0962', '\u0963'), + ('\u0981', '\u0981'), ('\u09bc', '\u09bc'), + ('\u09c1', '\u09c4'), ('\u09cd', '\u09cd'), + ('\u09e2', '\u09e3'), ('\u0a01', '\u0a02'), + ('\u0a3c', '\u0a3c'), ('\u0a41', '\u0a51'), + ('\u0a70', '\u0a71'), ('\u0a75', '\u0a82'), + ('\u0abc', '\u0abc'), ('\u0ac1', '\u0ac8'), + ('\u0acd', '\u0acd'), ('\u0ae2', '\u0ae3'), + ('\u0b01', '\u0b01'), ('\u0b3c', '\u0b3c'), + ('\u0b3f', '\u0b3f'), ('\u0b41', '\u0b44'), + ('\u0b4d', '\u0b56'), ('\u0b62', '\u0b63'), + ('\u0b82', '\u0b82'), ('\u0bc0', '\u0bc0'), + ('\u0bcd', '\u0bcd'), ('\u0c3e', '\u0c40'), + ('\u0c46', '\u0c56'), ('\u0c62', '\u0c63'), + ('\u0cbc', '\u0cbc'), ('\u0cbf', '\u0cbf'), + ('\u0cc6', '\u0cc6'), ('\u0ccc', '\u0ccd'), + ('\u0ce2', '\u0ce3'), ('\u0d41', '\u0d44'), + ('\u0d4d', '\u0d4d'), ('\u0d62', '\u0d63'), + ('\u0dca', '\u0dca'), ('\u0dd2', '\u0dd6'), + ('\u0e31', '\u0e31'), ('\u0e34', '\u0e3a'), + ('\u0e47', '\u0e4e'), ('\u0eb1', '\u0eb1'), + ('\u0eb4', '\u0ebc'), ('\u0ec8', '\u0ecd'), + ('\u0f18', '\u0f19'), ('\u0f35', '\u0f35'), + ('\u0f37', '\u0f37'), ('\u0f39', '\u0f39'), + ('\u0f71', '\u0f7e'), ('\u0f80', '\u0f84'), + ('\u0f86', '\u0f87'), ('\u0f8d', '\u0fbc'), + ('\u0fc6', '\u0fc6'), ('\u102d', '\u1030'), + ('\u1032', '\u1037'), ('\u1039', '\u103a'), + ('\u103d', '\u103e'), ('\u1058', '\u1059'), + ('\u105e', '\u1060'), ('\u1071', '\u1074'), + ('\u1082', '\u1082'), ('\u1085', '\u1086'), + ('\u108d', '\u108d'), ('\u109d', '\u109d'), + ('\u135d', '\u135f'), ('\u1712', '\u1714'), + ('\u1732', '\u1734'), ('\u1752', '\u1753'), + ('\u1772', '\u1773'), ('\u17b4', '\u17b5'), + ('\u17b7', '\u17bd'), ('\u17c6', '\u17c6'), + ('\u17c9', '\u17d3'), ('\u17dd', '\u17dd'), + ('\u180b', '\u180d'), ('\u18a9', '\u18a9'), + ('\u1920', '\u1922'), ('\u1927', '\u1928'), + ('\u1932', '\u1932'), ('\u1939', '\u193b'), + ('\u1a17', '\u1a18'), ('\u1a56', '\u1a56'), + ('\u1a58', '\u1a60'), ('\u1a62', '\u1a62'), + ('\u1a65', '\u1a6c'), ('\u1a73', '\u1a7f'), + ('\u1b00', '\u1b03'), ('\u1b34', '\u1b34'), + ('\u1b36', '\u1b3a'), ('\u1b3c', '\u1b3c'), + ('\u1b42', '\u1b42'), ('\u1b6b', '\u1b73'), + ('\u1b80', '\u1b81'), ('\u1ba2', '\u1ba5'), + ('\u1ba8', '\u1ba9'), ('\u1bab', '\u1bab'), + ('\u1be6', '\u1be6'), ('\u1be8', '\u1be9'), + ('\u1bed', '\u1bed'), ('\u1bef', '\u1bf1'), + ('\u1c2c', '\u1c33'), ('\u1c36', '\u1c37'), + ('\u1cd0', '\u1cd2'), ('\u1cd4', '\u1ce0'), + ('\u1ce2', '\u1ce8'), ('\u1ced', '\u1ced'), + ('\u1cf4', '\u1cf4'), ('\u1dc0', '\u1dff'), + ('\u20d0', '\u20dc'), ('\u20e1', '\u20e1'), + ('\u20e5', '\u20f0'), ('\u2cef', '\u2cf1'), + ('\u2d7f', '\u2d7f'), ('\u2de0', '\u2dff'), + ('\u302a', '\u302d'), ('\u3099', '\u309a'), + ('\ua66f', '\ua66f'), ('\ua674', '\ua67d'), + ('\ua69f', '\ua69f'), ('\ua6f0', '\ua6f1'), + ('\ua802', '\ua802'), ('\ua806', '\ua806'), + ('\ua80b', '\ua80b'), ('\ua825', '\ua826'), + ('\ua8c4', '\ua8c4'), ('\ua8e0', '\ua8f1'), + ('\ua926', '\ua92d'), ('\ua947', '\ua951'), + ('\ua980', '\ua982'), ('\ua9b3', '\ua9b3'), + ('\ua9b6', '\ua9b9'), ('\ua9bc', '\ua9bc'), + ('\uaa29', '\uaa2e'), ('\uaa31', '\uaa32'), + ('\uaa35', '\uaa36'), ('\uaa43', '\uaa43'), + ('\uaa4c', '\uaa4c'), ('\uaab0', '\uaab0'), + ('\uaab2', '\uaab4'), ('\uaab7', '\uaab8'), + ('\uaabe', '\uaabf'), ('\uaac1', '\uaac1'), + ('\uaaec', '\uaaed'), ('\uaaf6', '\uaaf6'), + ('\uabe5', '\uabe5'), ('\uabe8', '\uabe8'), + ('\uabed', '\uabed'), ('\ufb1e', '\ufb1e'), + ('\ufe00', '\ufe0f'), ('\ufe20', '\ufe26'), + ('\U000101fd', '\U000101fd'), ('\U00010a01', '\U00010a0f'), + ('\U00010a38', '\U00010a3f'), ('\U00011001', '\U00011001'), + ('\U00011038', '\U00011046'), ('\U00011080', '\U00011081'), + ('\U000110b3', '\U000110b6'), ('\U000110b9', '\U000110ba'), + ('\U00011100', '\U00011102'), ('\U00011127', '\U0001112b'), + ('\U0001112d', '\U00011134'), ('\U00011180', '\U00011181'), + ('\U000111b6', '\U000111be'), ('\U000116ab', '\U000116ab'), + ('\U000116ad', '\U000116ad'), ('\U000116b0', '\U000116b5'), + ('\U000116b7', '\U000116b7'), ('\U00016f8f', '\U00016f92'), + ('\U0001d167', '\U0001d169'), ('\U0001d17b', '\U0001d182'), + ('\U0001d185', '\U0001d18b'), ('\U0001d1aa', '\U0001d1ad'), + ('\U0001d242', '\U0001d244'), ('\U000e0100', '\U000e01ef') + ]; + + pub fn Mn(c: char) -> bool { + bsearch_range_table(c, Mn_table) + } + + static Nd_table : &'static [(char,char)] = &[ + ('\x30', '\x39'), ('\u0660', '\u0669'), + ('\u06f0', '\u06f9'), ('\u07c0', '\u07c9'), + ('\u0966', '\u096f'), ('\u09e6', '\u09ef'), + ('\u0a66', '\u0a6f'), ('\u0ae6', '\u0aef'), + ('\u0b66', '\u0b6f'), ('\u0be6', '\u0bef'), + ('\u0c66', '\u0c6f'), ('\u0ce6', '\u0cef'), + ('\u0d66', '\u0d6f'), ('\u0e50', '\u0e59'), + ('\u0ed0', '\u0ed9'), ('\u0f20', '\u0f29'), + ('\u1040', '\u1049'), ('\u1090', '\u1099'), + ('\u17e0', '\u17e9'), ('\u1810', '\u1819'), + ('\u1946', '\u194f'), ('\u19d0', '\u19d9'), + ('\u1a80', '\u1a99'), ('\u1b50', '\u1b59'), + ('\u1bb0', '\u1bb9'), ('\u1c40', '\u1c49'), + ('\u1c50', '\u1c59'), ('\ua620', '\ua629'), + ('\ua8d0', '\ua8d9'), ('\ua900', '\ua909'), + ('\ua9d0', '\ua9d9'), ('\uaa50', '\uaa59'), + ('\uabf0', '\uabf9'), ('\uff10', '\uff19'), + ('\U000104a0', '\U000104a9'), ('\U00011066', '\U0001106f'), + ('\U000110f0', '\U000110f9'), ('\U00011136', '\U0001113f'), + ('\U000111d0', '\U000111d9'), ('\U000116c0', '\U000116c9'), + ('\U0001d7ce', '\U0001d7ff') + ]; + + pub fn Nd(c: char) -> bool { + bsearch_range_table(c, Nd_table) + } + + static Nl_table : &'static [(char,char)] = &[ + ('\u16ee', '\u16f0'), ('\u2160', '\u2182'), + ('\u2185', '\u2188'), ('\u3007', '\u3007'), + ('\u3021', '\u3029'), ('\u3038', '\u303a'), + ('\ua6e6', '\ua6ef'), ('\U00010140', '\U00010174'), + ('\U00010341', '\U00010341'), ('\U0001034a', '\U0001034a'), + ('\U000103d1', '\U000103d5'), ('\U00012400', '\U00012462') + ]; + + pub fn Nl(c: char) -> bool { + bsearch_range_table(c, Nl_table) + } + + static No_table : &'static [(char,char)] = &[ + ('\xb2', '\xb3'), ('\xb9', '\xb9'), + ('\xbc', '\xbe'), ('\u09f4', '\u09f9'), + ('\u0b72', '\u0b77'), ('\u0bf0', '\u0bf2'), + ('\u0c78', '\u0c7e'), ('\u0d70', '\u0d75'), + ('\u0f2a', '\u0f33'), ('\u1369', '\u137c'), + ('\u17f0', '\u17f9'), ('\u19da', '\u19da'), + ('\u2070', '\u2070'), ('\u2074', '\u2079'), + ('\u2080', '\u2089'), ('\u2150', '\u215f'), + ('\u2189', '\u2189'), ('\u2460', '\u249b'), + ('\u24ea', '\u24ff'), ('\u2776', '\u2793'), + ('\u2cfd', '\u2cfd'), ('\u3192', '\u3195'), + ('\u3220', '\u3229'), ('\u3248', '\u324f'), + ('\u3251', '\u325f'), ('\u3280', '\u3289'), + ('\u32b1', '\u32bf'), ('\ua830', '\ua835'), + ('\U00010107', '\U00010133'), ('\U00010175', '\U00010178'), + ('\U0001018a', '\U0001018a'), ('\U00010320', '\U00010323'), + ('\U00010858', '\U0001085f'), ('\U00010916', '\U0001091b'), + ('\U00010a40', '\U00010a47'), ('\U00010a7d', '\U00010a7e'), + ('\U00010b58', '\U00010b5f'), ('\U00010b78', '\U00010b7f'), + ('\U00010e60', '\U00010e7e'), ('\U00011052', '\U00011065'), + ('\U0001d360', '\U0001d371'), ('\U0001f100', '\U0001f10a') + ]; + + pub fn No(c: char) -> bool { + bsearch_range_table(c, No_table) + } -/* -Function: is_upper + static Pc_table : &'static [(char,char)] = &[ + ('\x5f', '\x5f'), ('\u203f', '\u2040'), + ('\u2054', '\u2054'), ('\ufe33', '\ufe34'), + ('\ufe4d', '\ufe4f'), ('\uff3f', '\uff3f') + ]; + + pub fn Pc(c: char) -> bool { + bsearch_range_table(c, Pc_table) + } + + static Pd_table : &'static [(char,char)] = &[ + ('\x2d', '\x2d'), ('\u058a', '\u058a'), + ('\u05be', '\u05be'), ('\u1400', '\u1400'), + ('\u1806', '\u1806'), ('\u2010', '\u2015'), + ('\u2e17', '\u2e17'), ('\u2e1a', '\u2e1a'), + ('\u2e3a', '\u2e3b'), ('\u301c', '\u301c'), + ('\u3030', '\u3030'), ('\u30a0', '\u30a0'), + ('\ufe31', '\ufe32'), ('\ufe58', '\ufe58'), + ('\ufe63', '\ufe63'), ('\uff0d', '\uff0d') + ]; + + pub fn Pd(c: char) -> bool { + bsearch_range_table(c, Pd_table) + } + + static Pe_table : &'static [(char,char)] = &[ + ('\x29', '\x29'), ('\x5d', '\x5d'), + ('\x7d', '\x7d'), ('\u0f3b', '\u0f3b'), + ('\u0f3d', '\u0f3d'), ('\u169c', '\u169c'), + ('\u2046', '\u2046'), ('\u207e', '\u207e'), + ('\u208e', '\u208e'), ('\u232a', '\u232a'), + ('\u2769', '\u2769'), ('\u276b', '\u276b'), + ('\u276d', '\u276d'), ('\u276f', '\u276f'), + ('\u2771', '\u2771'), ('\u2773', '\u2773'), + ('\u2775', '\u2775'), ('\u27c6', '\u27c6'), + ('\u27e7', '\u27e7'), ('\u27e9', '\u27e9'), + ('\u27eb', '\u27eb'), ('\u27ed', '\u27ed'), + ('\u27ef', '\u27ef'), ('\u2984', '\u2984'), + ('\u2986', '\u2986'), ('\u2988', '\u2988'), + ('\u298a', '\u298a'), ('\u298c', '\u298c'), + ('\u298e', '\u298e'), ('\u2990', '\u2990'), + ('\u2992', '\u2992'), ('\u2994', '\u2994'), + ('\u2996', '\u2996'), ('\u2998', '\u2998'), + ('\u29d9', '\u29d9'), ('\u29db', '\u29db'), + ('\u29fd', '\u29fd'), ('\u2e23', '\u2e23'), + ('\u2e25', '\u2e25'), ('\u2e27', '\u2e27'), + ('\u2e29', '\u2e29'), ('\u3009', '\u3009'), + ('\u300b', '\u300b'), ('\u300d', '\u300d'), + ('\u300f', '\u300f'), ('\u3011', '\u3011'), + ('\u3015', '\u3015'), ('\u3017', '\u3017'), + ('\u3019', '\u3019'), ('\u301b', '\u301b'), + ('\u301e', '\u301f'), ('\ufd3f', '\ufd3f'), + ('\ufe18', '\ufe18'), ('\ufe36', '\ufe36'), + ('\ufe38', '\ufe38'), ('\ufe3a', '\ufe3a'), + ('\ufe3c', '\ufe3c'), ('\ufe3e', '\ufe3e'), + ('\ufe40', '\ufe40'), ('\ufe42', '\ufe42'), + ('\ufe44', '\ufe44'), ('\ufe48', '\ufe48'), + ('\ufe5a', '\ufe5a'), ('\ufe5c', '\ufe5c'), + ('\ufe5e', '\ufe5e'), ('\uff09', '\uff09'), + ('\uff3d', '\uff3d'), ('\uff5d', '\uff5d'), + ('\uff60', '\uff60'), ('\uff63', '\uff63') + ]; + + pub fn Pe(c: char) -> bool { + bsearch_range_table(c, Pe_table) + } + + static Pf_table : &'static [(char,char)] = &[ + ('\xbb', '\xbb'), ('\u2019', '\u2019'), + ('\u201d', '\u201d'), ('\u203a', '\u203a'), + ('\u2e03', '\u2e03'), ('\u2e05', '\u2e05'), + ('\u2e0a', '\u2e0a'), ('\u2e0d', '\u2e0d'), + ('\u2e1d', '\u2e1d'), ('\u2e21', '\u2e21') + ]; + + pub fn Pf(c: char) -> bool { + bsearch_range_table(c, Pf_table) + } + + static Pi_table : &'static [(char,char)] = &[ + ('\xab', '\xab'), ('\u2018', '\u2018'), + ('\u201b', '\u201c'), ('\u201f', '\u201f'), + ('\u2039', '\u2039'), ('\u2e02', '\u2e02'), + ('\u2e04', '\u2e04'), ('\u2e09', '\u2e09'), + ('\u2e0c', '\u2e0c'), ('\u2e1c', '\u2e1c'), + ('\u2e20', '\u2e20') + ]; + + pub fn Pi(c: char) -> bool { + bsearch_range_table(c, Pi_table) + } + + static Po_table : &'static [(char,char)] = &[ + ('\x21', '\x23'), ('\x25', '\x27'), + ('\x2a', '\x2a'), ('\x2c', '\x2c'), + ('\x2e', '\x2f'), ('\x3a', '\x3b'), + ('\x3f', '\x40'), ('\x5c', '\x5c'), + ('\xa1', '\xa1'), ('\xa7', '\xa7'), + ('\xb6', '\xb7'), ('\xbf', '\xbf'), + ('\u037e', '\u037e'), ('\u0387', '\u0387'), + ('\u055a', '\u055f'), ('\u0589', '\u0589'), + ('\u05c0', '\u05c0'), ('\u05c3', '\u05c3'), + ('\u05c6', '\u05c6'), ('\u05f3', '\u05f4'), + ('\u0609', '\u060a'), ('\u060c', '\u060d'), + ('\u061b', '\u061f'), ('\u066a', '\u066d'), + ('\u06d4', '\u06d4'), ('\u0700', '\u070d'), + ('\u07f7', '\u07f9'), ('\u0830', '\u083e'), + ('\u085e', '\u085e'), ('\u0964', '\u0965'), + ('\u0970', '\u0970'), ('\u0af0', '\u0af0'), + ('\u0df4', '\u0df4'), ('\u0e4f', '\u0e4f'), + ('\u0e5a', '\u0e5b'), ('\u0f04', '\u0f12'), + ('\u0f14', '\u0f14'), ('\u0f85', '\u0f85'), + ('\u0fd0', '\u0fd4'), ('\u0fd9', '\u0fda'), + ('\u104a', '\u104f'), ('\u10fb', '\u10fb'), + ('\u1360', '\u1368'), ('\u166d', '\u166e'), + ('\u16eb', '\u16ed'), ('\u1735', '\u1736'), + ('\u17d4', '\u17d6'), ('\u17d8', '\u17da'), + ('\u1800', '\u1805'), ('\u1807', '\u180a'), + ('\u1944', '\u1945'), ('\u1a1e', '\u1a1f'), + ('\u1aa0', '\u1aa6'), ('\u1aa8', '\u1aad'), + ('\u1b5a', '\u1b60'), ('\u1bfc', '\u1bff'), + ('\u1c3b', '\u1c3f'), ('\u1c7e', '\u1cc7'), + ('\u1cd3', '\u1cd3'), ('\u2016', '\u2017'), + ('\u2020', '\u2027'), ('\u2030', '\u2038'), + ('\u203b', '\u203e'), ('\u2041', '\u2043'), + ('\u2047', '\u2051'), ('\u2053', '\u2053'), + ('\u2055', '\u205e'), ('\u2cf9', '\u2cfc'), + ('\u2cfe', '\u2cff'), ('\u2d70', '\u2d70'), + ('\u2e00', '\u2e01'), ('\u2e06', '\u2e08'), + ('\u2e0b', '\u2e0b'), ('\u2e0e', '\u2e16'), + ('\u2e18', '\u2e19'), ('\u2e1b', '\u2e1b'), + ('\u2e1e', '\u2e1f'), ('\u2e2a', '\u2e2e'), + ('\u2e30', '\u2e39'), ('\u3001', '\u3003'), + ('\u303d', '\u303d'), ('\u30fb', '\u30fb'), + ('\ua4fe', '\ua4ff'), ('\ua60d', '\ua60f'), + ('\ua673', '\ua673'), ('\ua67e', '\ua67e'), + ('\ua6f2', '\ua6f7'), ('\ua874', '\ua877'), + ('\ua8ce', '\ua8cf'), ('\ua8f8', '\ua8fa'), + ('\ua92e', '\ua92f'), ('\ua95f', '\ua95f'), + ('\ua9c1', '\ua9cd'), ('\ua9de', '\ua9df'), + ('\uaa5c', '\uaa5f'), ('\uaade', '\uaadf'), + ('\uaaf0', '\uaaf1'), ('\uabeb', '\uabeb'), + ('\ufe10', '\ufe16'), ('\ufe19', '\ufe19'), + ('\ufe30', '\ufe30'), ('\ufe45', '\ufe46'), + ('\ufe49', '\ufe4c'), ('\ufe50', '\ufe57'), + ('\ufe5f', '\ufe61'), ('\ufe68', '\ufe68'), + ('\ufe6a', '\ufe6b'), ('\uff01', '\uff03'), + ('\uff05', '\uff07'), ('\uff0a', '\uff0a'), + ('\uff0c', '\uff0c'), ('\uff0e', '\uff0f'), + ('\uff1a', '\uff1b'), ('\uff1f', '\uff20'), + ('\uff3c', '\uff3c'), ('\uff61', '\uff61'), + ('\uff64', '\uff65'), ('\U00010100', '\U00010102'), + ('\U0001039f', '\U0001039f'), ('\U000103d0', '\U000103d0'), + ('\U00010857', '\U00010857'), ('\U0001091f', '\U0001091f'), + ('\U0001093f', '\U0001093f'), ('\U00010a50', '\U00010a58'), + ('\U00010a7f', '\U00010a7f'), ('\U00010b39', '\U00010b3f'), + ('\U00011047', '\U0001104d'), ('\U000110bb', '\U000110bc'), + ('\U000110be', '\U000110c1'), ('\U00011140', '\U00011143'), + ('\U000111c5', '\U000111c8'), ('\U00012470', '\U00012473') + ]; + + pub fn Po(c: char) -> bool { + bsearch_range_table(c, Po_table) + } + + static Ps_table : &'static [(char,char)] = &[ + ('\x28', '\x28'), ('\x5b', '\x5b'), + ('\x7b', '\x7b'), ('\u0f3a', '\u0f3a'), + ('\u0f3c', '\u0f3c'), ('\u169b', '\u169b'), + ('\u201a', '\u201a'), ('\u201e', '\u201e'), + ('\u2045', '\u2045'), ('\u207d', '\u207d'), + ('\u208d', '\u208d'), ('\u2329', '\u2329'), + ('\u2768', '\u2768'), ('\u276a', '\u276a'), + ('\u276c', '\u276c'), ('\u276e', '\u276e'), + ('\u2770', '\u2770'), ('\u2772', '\u2772'), + ('\u2774', '\u2774'), ('\u27c5', '\u27c5'), + ('\u27e6', '\u27e6'), ('\u27e8', '\u27e8'), + ('\u27ea', '\u27ea'), ('\u27ec', '\u27ec'), + ('\u27ee', '\u27ee'), ('\u2983', '\u2983'), + ('\u2985', '\u2985'), ('\u2987', '\u2987'), + ('\u2989', '\u2989'), ('\u298b', '\u298b'), + ('\u298d', '\u298d'), ('\u298f', '\u298f'), + ('\u2991', '\u2991'), ('\u2993', '\u2993'), + ('\u2995', '\u2995'), ('\u2997', '\u2997'), + ('\u29d8', '\u29d8'), ('\u29da', '\u29da'), + ('\u29fc', '\u29fc'), ('\u2e22', '\u2e22'), + ('\u2e24', '\u2e24'), ('\u2e26', '\u2e26'), + ('\u2e28', '\u2e28'), ('\u3008', '\u3008'), + ('\u300a', '\u300a'), ('\u300c', '\u300c'), + ('\u300e', '\u300e'), ('\u3010', '\u3010'), + ('\u3014', '\u3014'), ('\u3016', '\u3016'), + ('\u3018', '\u3018'), ('\u301a', '\u301a'), + ('\u301d', '\u301d'), ('\ufd3e', '\ufd3e'), + ('\ufe17', '\ufe17'), ('\ufe35', '\ufe35'), + ('\ufe37', '\ufe37'), ('\ufe39', '\ufe39'), + ('\ufe3b', '\ufe3b'), ('\ufe3d', '\ufe3d'), + ('\ufe3f', '\ufe3f'), ('\ufe41', '\ufe41'), + ('\ufe43', '\ufe43'), ('\ufe47', '\ufe47'), + ('\ufe59', '\ufe59'), ('\ufe5b', '\ufe5b'), + ('\ufe5d', '\ufe5d'), ('\uff08', '\uff08'), + ('\uff3b', '\uff3b'), ('\uff5b', '\uff5b'), + ('\uff5f', '\uff5f'), ('\uff62', '\uff62') + ]; + + pub fn Ps(c: char) -> bool { + bsearch_range_table(c, Ps_table) + } + + static Sc_table : &'static [(char,char)] = &[ + ('\x24', '\x24'), ('\xa2', '\xa5'), + ('\u058f', '\u058f'), ('\u060b', '\u060b'), + ('\u09f2', '\u09f3'), ('\u09fb', '\u09fb'), + ('\u0af1', '\u0af1'), ('\u0bf9', '\u0bf9'), + ('\u0e3f', '\u0e3f'), ('\u17db', '\u17db'), + ('\u20a0', '\u20ba'), ('\ua838', '\ua838'), + ('\ufdfc', '\ufdfc'), ('\ufe69', '\ufe69'), + ('\uff04', '\uff04'), ('\uffe0', '\uffe1'), + ('\uffe5', '\uffe6') + ]; + + pub fn Sc(c: char) -> bool { + bsearch_range_table(c, Sc_table) + } + + static Sk_table : &'static [(char,char)] = &[ + ('\x5e', '\x5e'), ('\x60', '\x60'), + ('\xa8', '\xa8'), ('\xaf', '\xaf'), + ('\xb4', '\xb4'), ('\xb8', '\xb8'), + ('\u02c2', '\u02c5'), ('\u02d2', '\u02df'), + ('\u02e5', '\u02eb'), ('\u02ed', '\u02ed'), + ('\u02ef', '\u02ff'), ('\u0375', '\u0375'), + ('\u0384', '\u0385'), ('\u1fbd', '\u1fbd'), + ('\u1fbf', '\u1fc1'), ('\u1fcd', '\u1fcf'), + ('\u1fdd', '\u1fdf'), ('\u1fed', '\u1fef'), + ('\u1ffd', '\u1ffe'), ('\u309b', '\u309c'), + ('\ua700', '\ua716'), ('\ua720', '\ua721'), + ('\ua789', '\ua78a'), ('\ufbb2', '\ufbc1'), + ('\uff3e', '\uff3e'), ('\uff40', '\uff40'), + ('\uffe3', '\uffe3') + ]; + + pub fn Sk(c: char) -> bool { + bsearch_range_table(c, Sk_table) + } + + static Sm_table : &'static [(char,char)] = &[ + ('\x2b', '\x2b'), ('\x3c', '\x3e'), + ('\x7c', '\x7c'), ('\x7e', '\x7e'), + ('\xac', '\xac'), ('\xb1', '\xb1'), + ('\xd7', '\xd7'), ('\xf7', '\xf7'), + ('\u03f6', '\u03f6'), ('\u0606', '\u0608'), + ('\u2044', '\u2044'), ('\u2052', '\u2052'), + ('\u207a', '\u207c'), ('\u208a', '\u208c'), + ('\u2118', '\u2118'), ('\u2140', '\u2144'), + ('\u214b', '\u214b'), ('\u2190', '\u2194'), + ('\u219a', '\u219b'), ('\u21a0', '\u21a0'), + ('\u21a3', '\u21a3'), ('\u21a6', '\u21a6'), + ('\u21ae', '\u21ae'), ('\u21ce', '\u21cf'), + ('\u21d2', '\u21d2'), ('\u21d4', '\u21d4'), + ('\u21f4', '\u22ff'), ('\u2308', '\u230b'), + ('\u2320', '\u2321'), ('\u237c', '\u237c'), + ('\u239b', '\u23b3'), ('\u23dc', '\u23e1'), + ('\u25b7', '\u25b7'), ('\u25c1', '\u25c1'), + ('\u25f8', '\u25ff'), ('\u266f', '\u266f'), + ('\u27c0', '\u27c4'), ('\u27c7', '\u27e5'), + ('\u27f0', '\u27ff'), ('\u2900', '\u2982'), + ('\u2999', '\u29d7'), ('\u29dc', '\u29fb'), + ('\u29fe', '\u2aff'), ('\u2b30', '\u2b44'), + ('\u2b47', '\u2b4c'), ('\ufb29', '\ufb29'), + ('\ufe62', '\ufe62'), ('\ufe64', '\ufe66'), + ('\uff0b', '\uff0b'), ('\uff1c', '\uff1e'), + ('\uff5c', '\uff5c'), ('\uff5e', '\uff5e'), + ('\uffe2', '\uffe2'), ('\uffe9', '\uffec'), + ('\U0001d6c1', '\U0001d6c1'), ('\U0001d6db', '\U0001d6db'), + ('\U0001d6fb', '\U0001d6fb'), ('\U0001d715', '\U0001d715'), + ('\U0001d735', '\U0001d735'), ('\U0001d74f', '\U0001d74f'), + ('\U0001d76f', '\U0001d76f'), ('\U0001d789', '\U0001d789'), + ('\U0001d7a9', '\U0001d7a9'), ('\U0001d7c3', '\U0001d7c3'), + ('\U0001eef0', '\U0001eef1') + ]; + + pub fn Sm(c: char) -> bool { + bsearch_range_table(c, Sm_table) + } + + static So_table : &'static [(char,char)] = &[ + ('\xa6', '\xa6'), ('\xa9', '\xa9'), + ('\xae', '\xae'), ('\xb0', '\xb0'), + ('\u0482', '\u0482'), ('\u060e', '\u060f'), + ('\u06de', '\u06de'), ('\u06e9', '\u06e9'), + ('\u06fd', '\u06fe'), ('\u07f6', '\u07f6'), + ('\u09fa', '\u09fa'), ('\u0b70', '\u0b70'), + ('\u0bf3', '\u0bf8'), ('\u0bfa', '\u0bfa'), + ('\u0c7f', '\u0c7f'), ('\u0d79', '\u0d79'), + ('\u0f01', '\u0f03'), ('\u0f13', '\u0f13'), + ('\u0f15', '\u0f17'), ('\u0f1a', '\u0f1f'), + ('\u0f34', '\u0f34'), ('\u0f36', '\u0f36'), + ('\u0f38', '\u0f38'), ('\u0fbe', '\u0fc5'), + ('\u0fc7', '\u0fcf'), ('\u0fd5', '\u0fd8'), + ('\u109e', '\u109f'), ('\u1390', '\u1399'), + ('\u1940', '\u1940'), ('\u19de', '\u19ff'), + ('\u1b61', '\u1b6a'), ('\u1b74', '\u1b7c'), + ('\u2100', '\u2101'), ('\u2103', '\u2106'), + ('\u2108', '\u2109'), ('\u2114', '\u2114'), + ('\u2116', '\u2117'), ('\u211e', '\u2123'), + ('\u2125', '\u2125'), ('\u2127', '\u2127'), + ('\u2129', '\u2129'), ('\u212e', '\u212e'), + ('\u213a', '\u213b'), ('\u214a', '\u214a'), + ('\u214c', '\u214d'), ('\u214f', '\u214f'), + ('\u2195', '\u2199'), ('\u219c', '\u219f'), + ('\u21a1', '\u21a2'), ('\u21a4', '\u21a5'), + ('\u21a7', '\u21ad'), ('\u21af', '\u21cd'), + ('\u21d0', '\u21d1'), ('\u21d3', '\u21d3'), + ('\u21d5', '\u21f3'), ('\u2300', '\u2307'), + ('\u230c', '\u231f'), ('\u2322', '\u2328'), + ('\u232b', '\u237b'), ('\u237d', '\u239a'), + ('\u23b4', '\u23db'), ('\u23e2', '\u244a'), + ('\u249c', '\u24e9'), ('\u2500', '\u25b6'), + ('\u25b8', '\u25c0'), ('\u25c2', '\u25f7'), + ('\u2600', '\u266e'), ('\u2670', '\u2767'), + ('\u2794', '\u27bf'), ('\u2800', '\u28ff'), + ('\u2b00', '\u2b2f'), ('\u2b45', '\u2b46'), + ('\u2b50', '\u2b59'), ('\u2ce5', '\u2cea'), + ('\u2e80', '\u2ffb'), ('\u3004', '\u3004'), + ('\u3012', '\u3013'), ('\u3020', '\u3020'), + ('\u3036', '\u3037'), ('\u303e', '\u303f'), + ('\u3190', '\u3191'), ('\u3196', '\u319f'), + ('\u31c0', '\u31e3'), ('\u3200', '\u321e'), + ('\u322a', '\u3247'), ('\u3250', '\u3250'), + ('\u3260', '\u327f'), ('\u328a', '\u32b0'), + ('\u32c0', '\u33ff'), ('\u4dc0', '\u4dff'), + ('\ua490', '\ua4c6'), ('\ua828', '\ua82b'), + ('\ua836', '\ua837'), ('\ua839', '\ua839'), + ('\uaa77', '\uaa79'), ('\ufdfd', '\ufdfd'), + ('\uffe4', '\uffe4'), ('\uffe8', '\uffe8'), + ('\uffed', '\uffee'), ('\ufffc', '\ufffd'), + ('\U00010137', '\U0001013f'), ('\U00010179', '\U00010189'), + ('\U00010190', '\U000101fc'), ('\U0001d000', '\U0001d164'), + ('\U0001d16a', '\U0001d16c'), ('\U0001d183', '\U0001d184'), + ('\U0001d18c', '\U0001d1a9'), ('\U0001d1ae', '\U0001d241'), + ('\U0001d245', '\U0001d356'), ('\U0001f000', '\U0001f0df'), + ('\U0001f110', '\U0001f773') + ]; + + pub fn So(c: char) -> bool { + bsearch_range_table(c, So_table) + } + + static Zl_table : &'static [(char,char)] = &[ + ('\u2028', '\u2028') + ]; + + pub fn Zl(c: char) -> bool { + bsearch_range_table(c, Zl_table) + } + + static Zp_table : &'static [(char,char)] = &[ + ('\u2029', '\u2029') + ]; + + pub fn Zp(c: char) -> bool { + bsearch_range_table(c, Zp_table) + } + + static Zs_table : &'static [(char,char)] = &[ + ('\x20', '\x20'), ('\xa0', '\xa0'), + ('\u1680', '\u1680'), ('\u180e', '\u180e'), + ('\u2000', '\u200a'), ('\u202f', '\u202f'), + ('\u205f', '\u205f'), ('\u3000', '\u3000') + ]; + + pub fn Zs(c: char) -> bool { + bsearch_range_table(c, Zs_table) + } -Returns true if a character is an uppercase letter. -*/ -pub fn is_upper(c: char) -> bool { - return icu::libicu::u_isupper(c) == icu::TRUE; } -#[cfg(test)] -mod tests { +pub mod derived_property { - #[test] - fn test_is_digit() { - assert!((unicode::icu::is_digit('0'))); - assert!((!unicode::icu::is_digit('m'))); + + fn bsearch_range_table(c: char, r: &'static [(char,char)]) -> bool { + use cmp::{Equal, Less, Greater}; + use vec::bsearch; + use option::None; + (do bsearch(r) |&(lo,hi)| { + if lo <= c && c <= hi { Equal } + else if hi < c { Less } + else { Greater } + }) != None } - #[test] - fn test_is_lower() { - assert!((unicode::icu::is_lower('m'))); - assert!((!unicode::icu::is_lower('M'))); + + static Alphabetic_table : &'static [(char,char)] = &[ + ('\x41', '\x5a'), ('\x61', '\x7a'), + ('\xaa', '\xaa'), ('\xb5', '\xb5'), + ('\xba', '\xba'), ('\xc0', '\xd6'), + ('\xd8', '\xf6'), ('\xf8', '\u01ba'), + ('\u01bb', '\u01bb'), ('\u01bc', '\u01bf'), + ('\u01c0', '\u01c3'), ('\u01c4', '\u0293'), + ('\u0294', '\u0294'), ('\u0295', '\u02af'), + ('\u02b0', '\u02c1'), ('\u02c6', '\u02d1'), + ('\u02e0', '\u02e4'), ('\u02ec', '\u02ec'), + ('\u02ee', '\u02ee'), ('\u0345', '\u0345'), + ('\u0370', '\u0373'), ('\u0374', '\u0374'), + ('\u0376', '\u0377'), ('\u037a', '\u037a'), + ('\u037b', '\u037d'), ('\u0386', '\u0386'), + ('\u0388', '\u038a'), ('\u038c', '\u038c'), + ('\u038e', '\u03a1'), ('\u03a3', '\u03f5'), + ('\u03f7', '\u0481'), ('\u048a', '\u0527'), + ('\u0531', '\u0556'), ('\u0559', '\u0559'), + ('\u0561', '\u0587'), ('\u05b0', '\u05bd'), + ('\u05bf', '\u05bf'), ('\u05c1', '\u05c2'), + ('\u05c4', '\u05c5'), ('\u05c7', '\u05c7'), + ('\u05d0', '\u05ea'), ('\u05f0', '\u05f2'), + ('\u0610', '\u061a'), ('\u0620', '\u063f'), + ('\u0640', '\u0640'), ('\u0641', '\u064a'), + ('\u064b', '\u0657'), ('\u0659', '\u065f'), + ('\u066e', '\u066f'), ('\u0670', '\u0670'), + ('\u0671', '\u06d3'), ('\u06d5', '\u06d5'), + ('\u06d6', '\u06dc'), ('\u06e1', '\u06e4'), + ('\u06e5', '\u06e6'), ('\u06e7', '\u06e8'), + ('\u06ed', '\u06ed'), ('\u06ee', '\u06ef'), + ('\u06fa', '\u06fc'), ('\u06ff', '\u06ff'), + ('\u0710', '\u0710'), ('\u0711', '\u0711'), + ('\u0712', '\u072f'), ('\u0730', '\u073f'), + ('\u074d', '\u07a5'), ('\u07a6', '\u07b0'), + ('\u07b1', '\u07b1'), ('\u07ca', '\u07ea'), + ('\u07f4', '\u07f5'), ('\u07fa', '\u07fa'), + ('\u0800', '\u0815'), ('\u0816', '\u0817'), + ('\u081a', '\u081a'), ('\u081b', '\u0823'), + ('\u0824', '\u0824'), ('\u0825', '\u0827'), + ('\u0828', '\u0828'), ('\u0829', '\u082c'), + ('\u0840', '\u0858'), ('\u08a0', '\u08a0'), + ('\u08a2', '\u08ac'), ('\u08e4', '\u08e9'), + ('\u08f0', '\u08fe'), ('\u0900', '\u0902'), + ('\u0903', '\u0903'), ('\u0904', '\u0939'), + ('\u093a', '\u093a'), ('\u093b', '\u093b'), + ('\u093d', '\u093d'), ('\u093e', '\u0940'), + ('\u0941', '\u0948'), ('\u0949', '\u094c'), + ('\u094e', '\u094f'), ('\u0950', '\u0950'), + ('\u0955', '\u0957'), ('\u0958', '\u0961'), + ('\u0962', '\u0963'), ('\u0971', '\u0971'), + ('\u0972', '\u0977'), ('\u0979', '\u097f'), + ('\u0981', '\u0981'), ('\u0982', '\u0983'), + ('\u0985', '\u098c'), ('\u098f', '\u0990'), + ('\u0993', '\u09a8'), ('\u09aa', '\u09b0'), + ('\u09b2', '\u09b2'), ('\u09b6', '\u09b9'), + ('\u09bd', '\u09bd'), ('\u09be', '\u09c0'), + ('\u09c1', '\u09c4'), ('\u09c7', '\u09c8'), + ('\u09cb', '\u09cc'), ('\u09ce', '\u09ce'), + ('\u09d7', '\u09d7'), ('\u09dc', '\u09dd'), + ('\u09df', '\u09e1'), ('\u09e2', '\u09e3'), + ('\u09f0', '\u09f1'), ('\u0a01', '\u0a02'), + ('\u0a03', '\u0a03'), ('\u0a05', '\u0a0a'), + ('\u0a0f', '\u0a10'), ('\u0a13', '\u0a28'), + ('\u0a2a', '\u0a30'), ('\u0a32', '\u0a33'), + ('\u0a35', '\u0a36'), ('\u0a38', '\u0a39'), + ('\u0a3e', '\u0a40'), ('\u0a41', '\u0a42'), + ('\u0a47', '\u0a48'), ('\u0a4b', '\u0a4c'), + ('\u0a51', '\u0a51'), ('\u0a59', '\u0a5c'), + ('\u0a5e', '\u0a5e'), ('\u0a70', '\u0a71'), + ('\u0a72', '\u0a74'), ('\u0a75', '\u0a75'), + ('\u0a81', '\u0a82'), ('\u0a83', '\u0a83'), + ('\u0a85', '\u0a8d'), ('\u0a8f', '\u0a91'), + ('\u0a93', '\u0aa8'), ('\u0aaa', '\u0ab0'), + ('\u0ab2', '\u0ab3'), ('\u0ab5', '\u0ab9'), + ('\u0abd', '\u0abd'), ('\u0abe', '\u0ac0'), + ('\u0ac1', '\u0ac5'), ('\u0ac7', '\u0ac8'), + ('\u0ac9', '\u0ac9'), ('\u0acb', '\u0acc'), + ('\u0ad0', '\u0ad0'), ('\u0ae0', '\u0ae1'), + ('\u0ae2', '\u0ae3'), ('\u0b01', '\u0b01'), + ('\u0b02', '\u0b03'), ('\u0b05', '\u0b0c'), + ('\u0b0f', '\u0b10'), ('\u0b13', '\u0b28'), + ('\u0b2a', '\u0b30'), ('\u0b32', '\u0b33'), + ('\u0b35', '\u0b39'), ('\u0b3d', '\u0b3d'), + ('\u0b3e', '\u0b3e'), ('\u0b3f', '\u0b3f'), + ('\u0b40', '\u0b40'), ('\u0b41', '\u0b44'), + ('\u0b47', '\u0b48'), ('\u0b4b', '\u0b4c'), + ('\u0b56', '\u0b56'), ('\u0b57', '\u0b57'), + ('\u0b5c', '\u0b5d'), ('\u0b5f', '\u0b61'), + ('\u0b62', '\u0b63'), ('\u0b71', '\u0b71'), + ('\u0b82', '\u0b82'), ('\u0b83', '\u0b83'), + ('\u0b85', '\u0b8a'), ('\u0b8e', '\u0b90'), + ('\u0b92', '\u0b95'), ('\u0b99', '\u0b9a'), + ('\u0b9c', '\u0b9c'), ('\u0b9e', '\u0b9f'), + ('\u0ba3', '\u0ba4'), ('\u0ba8', '\u0baa'), + ('\u0bae', '\u0bb9'), ('\u0bbe', '\u0bbf'), + ('\u0bc0', '\u0bc0'), ('\u0bc1', '\u0bc2'), + ('\u0bc6', '\u0bc8'), ('\u0bca', '\u0bcc'), + ('\u0bd0', '\u0bd0'), ('\u0bd7', '\u0bd7'), + ('\u0c01', '\u0c03'), ('\u0c05', '\u0c0c'), + ('\u0c0e', '\u0c10'), ('\u0c12', '\u0c28'), + ('\u0c2a', '\u0c33'), ('\u0c35', '\u0c39'), + ('\u0c3d', '\u0c3d'), ('\u0c3e', '\u0c40'), + ('\u0c41', '\u0c44'), ('\u0c46', '\u0c48'), + ('\u0c4a', '\u0c4c'), ('\u0c55', '\u0c56'), + ('\u0c58', '\u0c59'), ('\u0c60', '\u0c61'), + ('\u0c62', '\u0c63'), ('\u0c82', '\u0c83'), + ('\u0c85', '\u0c8c'), ('\u0c8e', '\u0c90'), + ('\u0c92', '\u0ca8'), ('\u0caa', '\u0cb3'), + ('\u0cb5', '\u0cb9'), ('\u0cbd', '\u0cbd'), + ('\u0cbe', '\u0cbe'), ('\u0cbf', '\u0cbf'), + ('\u0cc0', '\u0cc4'), ('\u0cc6', '\u0cc6'), + ('\u0cc7', '\u0cc8'), ('\u0cca', '\u0ccb'), + ('\u0ccc', '\u0ccc'), ('\u0cd5', '\u0cd6'), + ('\u0cde', '\u0cde'), ('\u0ce0', '\u0ce1'), + ('\u0ce2', '\u0ce3'), ('\u0cf1', '\u0cf2'), + ('\u0d02', '\u0d03'), ('\u0d05', '\u0d0c'), + ('\u0d0e', '\u0d10'), ('\u0d12', '\u0d3a'), + ('\u0d3d', '\u0d3d'), ('\u0d3e', '\u0d40'), + ('\u0d41', '\u0d44'), ('\u0d46', '\u0d48'), + ('\u0d4a', '\u0d4c'), ('\u0d4e', '\u0d4e'), + ('\u0d57', '\u0d57'), ('\u0d60', '\u0d61'), + ('\u0d62', '\u0d63'), ('\u0d7a', '\u0d7f'), + ('\u0d82', '\u0d83'), ('\u0d85', '\u0d96'), + ('\u0d9a', '\u0db1'), ('\u0db3', '\u0dbb'), + ('\u0dbd', '\u0dbd'), ('\u0dc0', '\u0dc6'), + ('\u0dcf', '\u0dd1'), ('\u0dd2', '\u0dd4'), + ('\u0dd6', '\u0dd6'), ('\u0dd8', '\u0ddf'), + ('\u0df2', '\u0df3'), ('\u0e01', '\u0e30'), + ('\u0e31', '\u0e31'), ('\u0e32', '\u0e33'), + ('\u0e34', '\u0e3a'), ('\u0e40', '\u0e45'), + ('\u0e46', '\u0e46'), ('\u0e4d', '\u0e4d'), + ('\u0e81', '\u0e82'), ('\u0e84', '\u0e84'), + ('\u0e87', '\u0e88'), ('\u0e8a', '\u0e8a'), + ('\u0e8d', '\u0e8d'), ('\u0e94', '\u0e97'), + ('\u0e99', '\u0e9f'), ('\u0ea1', '\u0ea3'), + ('\u0ea5', '\u0ea5'), ('\u0ea7', '\u0ea7'), + ('\u0eaa', '\u0eab'), ('\u0ead', '\u0eb0'), + ('\u0eb1', '\u0eb1'), ('\u0eb2', '\u0eb3'), + ('\u0eb4', '\u0eb9'), ('\u0ebb', '\u0ebc'), + ('\u0ebd', '\u0ebd'), ('\u0ec0', '\u0ec4'), + ('\u0ec6', '\u0ec6'), ('\u0ecd', '\u0ecd'), + ('\u0edc', '\u0edf'), ('\u0f00', '\u0f00'), + ('\u0f40', '\u0f47'), ('\u0f49', '\u0f6c'), + ('\u0f71', '\u0f7e'), ('\u0f7f', '\u0f7f'), + ('\u0f80', '\u0f81'), ('\u0f88', '\u0f8c'), + ('\u0f8d', '\u0f97'), ('\u0f99', '\u0fbc'), + ('\u1000', '\u102a'), ('\u102b', '\u102c'), + ('\u102d', '\u1030'), ('\u1031', '\u1031'), + ('\u1032', '\u1036'), ('\u1038', '\u1038'), + ('\u103b', '\u103c'), ('\u103d', '\u103e'), + ('\u103f', '\u103f'), ('\u1050', '\u1055'), + ('\u1056', '\u1057'), ('\u1058', '\u1059'), + ('\u105a', '\u105d'), ('\u105e', '\u1060'), + ('\u1061', '\u1061'), ('\u1062', '\u1062'), + ('\u1065', '\u1066'), ('\u1067', '\u1068'), + ('\u106e', '\u1070'), ('\u1071', '\u1074'), + ('\u1075', '\u1081'), ('\u1082', '\u1082'), + ('\u1083', '\u1084'), ('\u1085', '\u1086'), + ('\u108e', '\u108e'), ('\u109c', '\u109c'), + ('\u109d', '\u109d'), ('\u10a0', '\u10c5'), + ('\u10c7', '\u10c7'), ('\u10cd', '\u10cd'), + ('\u10d0', '\u10fa'), ('\u10fc', '\u10fc'), + ('\u10fd', '\u1248'), ('\u124a', '\u124d'), + ('\u1250', '\u1256'), ('\u1258', '\u1258'), + ('\u125a', '\u125d'), ('\u1260', '\u1288'), + ('\u128a', '\u128d'), ('\u1290', '\u12b0'), + ('\u12b2', '\u12b5'), ('\u12b8', '\u12be'), + ('\u12c0', '\u12c0'), ('\u12c2', '\u12c5'), + ('\u12c8', '\u12d6'), ('\u12d8', '\u1310'), + ('\u1312', '\u1315'), ('\u1318', '\u135a'), + ('\u135f', '\u135f'), ('\u1380', '\u138f'), + ('\u13a0', '\u13f4'), ('\u1401', '\u166c'), + ('\u166f', '\u167f'), ('\u1681', '\u169a'), + ('\u16a0', '\u16ea'), ('\u16ee', '\u16f0'), + ('\u1700', '\u170c'), ('\u170e', '\u1711'), + ('\u1712', '\u1713'), ('\u1720', '\u1731'), + ('\u1732', '\u1733'), ('\u1740', '\u1751'), + ('\u1752', '\u1753'), ('\u1760', '\u176c'), + ('\u176e', '\u1770'), ('\u1772', '\u1773'), + ('\u1780', '\u17b3'), ('\u17b6', '\u17b6'), + ('\u17b7', '\u17bd'), ('\u17be', '\u17c5'), + ('\u17c6', '\u17c6'), ('\u17c7', '\u17c8'), + ('\u17d7', '\u17d7'), ('\u17dc', '\u17dc'), + ('\u1820', '\u1842'), ('\u1843', '\u1843'), + ('\u1844', '\u1877'), ('\u1880', '\u18a8'), + ('\u18a9', '\u18a9'), ('\u18aa', '\u18aa'), + ('\u18b0', '\u18f5'), ('\u1900', '\u191c'), + ('\u1920', '\u1922'), ('\u1923', '\u1926'), + ('\u1927', '\u1928'), ('\u1929', '\u192b'), + ('\u1930', '\u1931'), ('\u1932', '\u1932'), + ('\u1933', '\u1938'), ('\u1950', '\u196d'), + ('\u1970', '\u1974'), ('\u1980', '\u19ab'), + ('\u19b0', '\u19c0'), ('\u19c1', '\u19c7'), + ('\u19c8', '\u19c9'), ('\u1a00', '\u1a16'), + ('\u1a17', '\u1a18'), ('\u1a19', '\u1a1b'), + ('\u1a20', '\u1a54'), ('\u1a55', '\u1a55'), + ('\u1a56', '\u1a56'), ('\u1a57', '\u1a57'), + ('\u1a58', '\u1a5e'), ('\u1a61', '\u1a61'), + ('\u1a62', '\u1a62'), ('\u1a63', '\u1a64'), + ('\u1a65', '\u1a6c'), ('\u1a6d', '\u1a72'), + ('\u1a73', '\u1a74'), ('\u1aa7', '\u1aa7'), + ('\u1b00', '\u1b03'), ('\u1b04', '\u1b04'), + ('\u1b05', '\u1b33'), ('\u1b35', '\u1b35'), + ('\u1b36', '\u1b3a'), ('\u1b3b', '\u1b3b'), + ('\u1b3c', '\u1b3c'), ('\u1b3d', '\u1b41'), + ('\u1b42', '\u1b42'), ('\u1b43', '\u1b43'), + ('\u1b45', '\u1b4b'), ('\u1b80', '\u1b81'), + ('\u1b82', '\u1b82'), ('\u1b83', '\u1ba0'), + ('\u1ba1', '\u1ba1'), ('\u1ba2', '\u1ba5'), + ('\u1ba6', '\u1ba7'), ('\u1ba8', '\u1ba9'), + ('\u1bac', '\u1bad'), ('\u1bae', '\u1baf'), + ('\u1bba', '\u1be5'), ('\u1be7', '\u1be7'), + ('\u1be8', '\u1be9'), ('\u1bea', '\u1bec'), + ('\u1bed', '\u1bed'), ('\u1bee', '\u1bee'), + ('\u1bef', '\u1bf1'), ('\u1c00', '\u1c23'), + ('\u1c24', '\u1c2b'), ('\u1c2c', '\u1c33'), + ('\u1c34', '\u1c35'), ('\u1c4d', '\u1c4f'), + ('\u1c5a', '\u1c77'), ('\u1c78', '\u1c7d'), + ('\u1ce9', '\u1cec'), ('\u1cee', '\u1cf1'), + ('\u1cf2', '\u1cf3'), ('\u1cf5', '\u1cf6'), + ('\u1d00', '\u1d2b'), ('\u1d2c', '\u1d6a'), + ('\u1d6b', '\u1d77'), ('\u1d78', '\u1d78'), + ('\u1d79', '\u1d9a'), ('\u1d9b', '\u1dbf'), + ('\u1e00', '\u1f15'), ('\u1f18', '\u1f1d'), + ('\u1f20', '\u1f45'), ('\u1f48', '\u1f4d'), + ('\u1f50', '\u1f57'), ('\u1f59', '\u1f59'), + ('\u1f5b', '\u1f5b'), ('\u1f5d', '\u1f5d'), + ('\u1f5f', '\u1f7d'), ('\u1f80', '\u1fb4'), + ('\u1fb6', '\u1fbc'), ('\u1fbe', '\u1fbe'), + ('\u1fc2', '\u1fc4'), ('\u1fc6', '\u1fcc'), + ('\u1fd0', '\u1fd3'), ('\u1fd6', '\u1fdb'), + ('\u1fe0', '\u1fec'), ('\u1ff2', '\u1ff4'), + ('\u1ff6', '\u1ffc'), ('\u2071', '\u2071'), + ('\u207f', '\u207f'), ('\u2090', '\u209c'), + ('\u2102', '\u2102'), ('\u2107', '\u2107'), + ('\u210a', '\u2113'), ('\u2115', '\u2115'), + ('\u2119', '\u211d'), ('\u2124', '\u2124'), + ('\u2126', '\u2126'), ('\u2128', '\u2128'), + ('\u212a', '\u212d'), ('\u212f', '\u2134'), + ('\u2135', '\u2138'), ('\u2139', '\u2139'), + ('\u213c', '\u213f'), ('\u2145', '\u2149'), + ('\u214e', '\u214e'), ('\u2160', '\u2182'), + ('\u2183', '\u2184'), ('\u2185', '\u2188'), + ('\u24b6', '\u24e9'), ('\u2c00', '\u2c2e'), + ('\u2c30', '\u2c5e'), ('\u2c60', '\u2c7b'), + ('\u2c7c', '\u2c7d'), ('\u2c7e', '\u2ce4'), + ('\u2ceb', '\u2cee'), ('\u2cf2', '\u2cf3'), + ('\u2d00', '\u2d25'), ('\u2d27', '\u2d27'), + ('\u2d2d', '\u2d2d'), ('\u2d30', '\u2d67'), + ('\u2d6f', '\u2d6f'), ('\u2d80', '\u2d96'), + ('\u2da0', '\u2da6'), ('\u2da8', '\u2dae'), + ('\u2db0', '\u2db6'), ('\u2db8', '\u2dbe'), + ('\u2dc0', '\u2dc6'), ('\u2dc8', '\u2dce'), + ('\u2dd0', '\u2dd6'), ('\u2dd8', '\u2dde'), + ('\u2de0', '\u2dff'), ('\u2e2f', '\u2e2f'), + ('\u3005', '\u3005'), ('\u3006', '\u3006'), + ('\u3007', '\u3007'), ('\u3021', '\u3029'), + ('\u3031', '\u3035'), ('\u3038', '\u303a'), + ('\u303b', '\u303b'), ('\u303c', '\u303c'), + ('\u3041', '\u3096'), ('\u309d', '\u309e'), + ('\u309f', '\u309f'), ('\u30a1', '\u30fa'), + ('\u30fc', '\u30fe'), ('\u30ff', '\u30ff'), + ('\u3105', '\u312d'), ('\u3131', '\u318e'), + ('\u31a0', '\u31ba'), ('\u31f0', '\u31ff'), + ('\u3400', '\u4db5'), ('\u4e00', '\u9fcc'), + ('\ua000', '\ua014'), ('\ua015', '\ua015'), + ('\ua016', '\ua48c'), ('\ua4d0', '\ua4f7'), + ('\ua4f8', '\ua4fd'), ('\ua500', '\ua60b'), + ('\ua60c', '\ua60c'), ('\ua610', '\ua61f'), + ('\ua62a', '\ua62b'), ('\ua640', '\ua66d'), + ('\ua66e', '\ua66e'), ('\ua674', '\ua67b'), + ('\ua67f', '\ua67f'), ('\ua680', '\ua697'), + ('\ua69f', '\ua69f'), ('\ua6a0', '\ua6e5'), + ('\ua6e6', '\ua6ef'), ('\ua717', '\ua71f'), + ('\ua722', '\ua76f'), ('\ua770', '\ua770'), + ('\ua771', '\ua787'), ('\ua788', '\ua788'), + ('\ua78b', '\ua78e'), ('\ua790', '\ua793'), + ('\ua7a0', '\ua7aa'), ('\ua7f8', '\ua7f9'), + ('\ua7fa', '\ua7fa'), ('\ua7fb', '\ua801'), + ('\ua803', '\ua805'), ('\ua807', '\ua80a'), + ('\ua80c', '\ua822'), ('\ua823', '\ua824'), + ('\ua825', '\ua826'), ('\ua827', '\ua827'), + ('\ua840', '\ua873'), ('\ua880', '\ua881'), + ('\ua882', '\ua8b3'), ('\ua8b4', '\ua8c3'), + ('\ua8f2', '\ua8f7'), ('\ua8fb', '\ua8fb'), + ('\ua90a', '\ua925'), ('\ua926', '\ua92a'), + ('\ua930', '\ua946'), ('\ua947', '\ua951'), + ('\ua952', '\ua952'), ('\ua960', '\ua97c'), + ('\ua980', '\ua982'), ('\ua983', '\ua983'), + ('\ua984', '\ua9b2'), ('\ua9b4', '\ua9b5'), + ('\ua9b6', '\ua9b9'), ('\ua9ba', '\ua9bb'), + ('\ua9bc', '\ua9bc'), ('\ua9bd', '\ua9bf'), + ('\ua9cf', '\ua9cf'), ('\uaa00', '\uaa28'), + ('\uaa29', '\uaa2e'), ('\uaa2f', '\uaa30'), + ('\uaa31', '\uaa32'), ('\uaa33', '\uaa34'), + ('\uaa35', '\uaa36'), ('\uaa40', '\uaa42'), + ('\uaa43', '\uaa43'), ('\uaa44', '\uaa4b'), + ('\uaa4c', '\uaa4c'), ('\uaa4d', '\uaa4d'), + ('\uaa60', '\uaa6f'), ('\uaa70', '\uaa70'), + ('\uaa71', '\uaa76'), ('\uaa7a', '\uaa7a'), + ('\uaa80', '\uaaaf'), ('\uaab0', '\uaab0'), + ('\uaab1', '\uaab1'), ('\uaab2', '\uaab4'), + ('\uaab5', '\uaab6'), ('\uaab7', '\uaab8'), + ('\uaab9', '\uaabd'), ('\uaabe', '\uaabe'), + ('\uaac0', '\uaac0'), ('\uaac2', '\uaac2'), + ('\uaadb', '\uaadc'), ('\uaadd', '\uaadd'), + ('\uaae0', '\uaaea'), ('\uaaeb', '\uaaeb'), + ('\uaaec', '\uaaed'), ('\uaaee', '\uaaef'), + ('\uaaf2', '\uaaf2'), ('\uaaf3', '\uaaf4'), + ('\uaaf5', '\uaaf5'), ('\uab01', '\uab06'), + ('\uab09', '\uab0e'), ('\uab11', '\uab16'), + ('\uab20', '\uab26'), ('\uab28', '\uab2e'), + ('\uabc0', '\uabe2'), ('\uabe3', '\uabe4'), + ('\uabe5', '\uabe5'), ('\uabe6', '\uabe7'), + ('\uabe8', '\uabe8'), ('\uabe9', '\uabea'), + ('\uac00', '\ud7a3'), ('\ud7b0', '\ud7c6'), + ('\ud7cb', '\ud7fb'), ('\uf900', '\ufa6d'), + ('\ufa70', '\ufad9'), ('\ufb00', '\ufb06'), + ('\ufb13', '\ufb17'), ('\ufb1d', '\ufb1d'), + ('\ufb1e', '\ufb1e'), ('\ufb1f', '\ufb28'), + ('\ufb2a', '\ufb36'), ('\ufb38', '\ufb3c'), + ('\ufb3e', '\ufb3e'), ('\ufb40', '\ufb41'), + ('\ufb43', '\ufb44'), ('\ufb46', '\ufbb1'), + ('\ufbd3', '\ufd3d'), ('\ufd50', '\ufd8f'), + ('\ufd92', '\ufdc7'), ('\ufdf0', '\ufdfb'), + ('\ufe70', '\ufe74'), ('\ufe76', '\ufefc'), + ('\uff21', '\uff3a'), ('\uff41', '\uff5a'), + ('\uff66', '\uff6f'), ('\uff70', '\uff70'), + ('\uff71', '\uff9d'), ('\uff9e', '\uff9f'), + ('\uffa0', '\uffbe'), ('\uffc2', '\uffc7'), + ('\uffca', '\uffcf'), ('\uffd2', '\uffd7'), + ('\uffda', '\uffdc'), ('\U00010000', '\U0001000b'), + ('\U0001000d', '\U00010026'), ('\U00010028', '\U0001003a'), + ('\U0001003c', '\U0001003d'), ('\U0001003f', '\U0001004d'), + ('\U00010050', '\U0001005d'), ('\U00010080', '\U000100fa'), + ('\U00010140', '\U00010174'), ('\U00010280', '\U0001029c'), + ('\U000102a0', '\U000102d0'), ('\U00010300', '\U0001031e'), + ('\U00010330', '\U00010340'), ('\U00010341', '\U00010341'), + ('\U00010342', '\U00010349'), ('\U0001034a', '\U0001034a'), + ('\U00010380', '\U0001039d'), ('\U000103a0', '\U000103c3'), + ('\U000103c8', '\U000103cf'), ('\U000103d1', '\U000103d5'), + ('\U00010400', '\U0001044f'), ('\U00010450', '\U0001049d'), + ('\U00010800', '\U00010805'), ('\U00010808', '\U00010808'), + ('\U0001080a', '\U00010835'), ('\U00010837', '\U00010838'), + ('\U0001083c', '\U0001083c'), ('\U0001083f', '\U00010855'), + ('\U00010900', '\U00010915'), ('\U00010920', '\U00010939'), + ('\U00010980', '\U000109b7'), ('\U000109be', '\U000109bf'), + ('\U00010a00', '\U00010a00'), ('\U00010a01', '\U00010a03'), + ('\U00010a05', '\U00010a06'), ('\U00010a0c', '\U00010a0f'), + ('\U00010a10', '\U00010a13'), ('\U00010a15', '\U00010a17'), + ('\U00010a19', '\U00010a33'), ('\U00010a60', '\U00010a7c'), + ('\U00010b00', '\U00010b35'), ('\U00010b40', '\U00010b55'), + ('\U00010b60', '\U00010b72'), ('\U00010c00', '\U00010c48'), + ('\U00011000', '\U00011000'), ('\U00011001', '\U00011001'), + ('\U00011002', '\U00011002'), ('\U00011003', '\U00011037'), + ('\U00011038', '\U00011045'), ('\U00011082', '\U00011082'), + ('\U00011083', '\U000110af'), ('\U000110b0', '\U000110b2'), + ('\U000110b3', '\U000110b6'), ('\U000110b7', '\U000110b8'), + ('\U000110d0', '\U000110e8'), ('\U00011100', '\U00011102'), + ('\U00011103', '\U00011126'), ('\U00011127', '\U0001112b'), + ('\U0001112c', '\U0001112c'), ('\U0001112d', '\U00011132'), + ('\U00011180', '\U00011181'), ('\U00011182', '\U00011182'), + ('\U00011183', '\U000111b2'), ('\U000111b3', '\U000111b5'), + ('\U000111b6', '\U000111be'), ('\U000111bf', '\U000111bf'), + ('\U000111c1', '\U000111c4'), ('\U00011680', '\U000116aa'), + ('\U000116ab', '\U000116ab'), ('\U000116ac', '\U000116ac'), + ('\U000116ad', '\U000116ad'), ('\U000116ae', '\U000116af'), + ('\U000116b0', '\U000116b5'), ('\U00012000', '\U0001236e'), + ('\U00012400', '\U00012462'), ('\U00013000', '\U0001342e'), + ('\U00016800', '\U00016a38'), ('\U00016f00', '\U00016f44'), + ('\U00016f50', '\U00016f50'), ('\U00016f51', '\U00016f7e'), + ('\U00016f93', '\U00016f9f'), ('\U0001b000', '\U0001b001'), + ('\U0001d400', '\U0001d454'), ('\U0001d456', '\U0001d49c'), + ('\U0001d49e', '\U0001d49f'), ('\U0001d4a2', '\U0001d4a2'), + ('\U0001d4a5', '\U0001d4a6'), ('\U0001d4a9', '\U0001d4ac'), + ('\U0001d4ae', '\U0001d4b9'), ('\U0001d4bb', '\U0001d4bb'), + ('\U0001d4bd', '\U0001d4c3'), ('\U0001d4c5', '\U0001d505'), + ('\U0001d507', '\U0001d50a'), ('\U0001d50d', '\U0001d514'), + ('\U0001d516', '\U0001d51c'), ('\U0001d51e', '\U0001d539'), + ('\U0001d53b', '\U0001d53e'), ('\U0001d540', '\U0001d544'), + ('\U0001d546', '\U0001d546'), ('\U0001d54a', '\U0001d550'), + ('\U0001d552', '\U0001d6a5'), ('\U0001d6a8', '\U0001d6c0'), + ('\U0001d6c2', '\U0001d6da'), ('\U0001d6dc', '\U0001d6fa'), + ('\U0001d6fc', '\U0001d714'), ('\U0001d716', '\U0001d734'), + ('\U0001d736', '\U0001d74e'), ('\U0001d750', '\U0001d76e'), + ('\U0001d770', '\U0001d788'), ('\U0001d78a', '\U0001d7a8'), + ('\U0001d7aa', '\U0001d7c2'), ('\U0001d7c4', '\U0001d7cb'), + ('\U0001ee00', '\U0001ee03'), ('\U0001ee05', '\U0001ee1f'), + ('\U0001ee21', '\U0001ee22'), ('\U0001ee24', '\U0001ee24'), + ('\U0001ee27', '\U0001ee27'), ('\U0001ee29', '\U0001ee32'), + ('\U0001ee34', '\U0001ee37'), ('\U0001ee39', '\U0001ee39'), + ('\U0001ee3b', '\U0001ee3b'), ('\U0001ee42', '\U0001ee42'), + ('\U0001ee47', '\U0001ee47'), ('\U0001ee49', '\U0001ee49'), + ('\U0001ee4b', '\U0001ee4b'), ('\U0001ee4d', '\U0001ee4f'), + ('\U0001ee51', '\U0001ee52'), ('\U0001ee54', '\U0001ee54'), + ('\U0001ee57', '\U0001ee57'), ('\U0001ee59', '\U0001ee59'), + ('\U0001ee5b', '\U0001ee5b'), ('\U0001ee5d', '\U0001ee5d'), + ('\U0001ee5f', '\U0001ee5f'), ('\U0001ee61', '\U0001ee62'), + ('\U0001ee64', '\U0001ee64'), ('\U0001ee67', '\U0001ee6a'), + ('\U0001ee6c', '\U0001ee72'), ('\U0001ee74', '\U0001ee77'), + ('\U0001ee79', '\U0001ee7c'), ('\U0001ee7e', '\U0001ee7e'), + ('\U0001ee80', '\U0001ee89'), ('\U0001ee8b', '\U0001ee9b'), + ('\U0001eea1', '\U0001eea3'), ('\U0001eea5', '\U0001eea9'), + ('\U0001eeab', '\U0001eebb'), ('\U00020000', '\U0002a6d6'), + ('\U0002a700', '\U0002b734'), ('\U0002b740', '\U0002b81d'), + ('\U0002f800', '\U0002fa1d') + ]; + + pub fn Alphabetic(c: char) -> bool { + bsearch_range_table(c, Alphabetic_table) } - #[test] - fn test_is_space() { - assert!((unicode::icu::is_space(' '))); - assert!((!unicode::icu::is_space('m'))); + static XID_Continue_table : &'static [(char,char)] = &[ + ('\x30', '\x39'), ('\x41', '\x5a'), + ('\x5f', '\x5f'), ('\x61', '\x7a'), + ('\xaa', '\xaa'), ('\xb5', '\xb5'), + ('\xb7', '\xb7'), ('\xba', '\xba'), + ('\xc0', '\xd6'), ('\xd8', '\xf6'), + ('\xf8', '\u01ba'), ('\u01bb', '\u01bb'), + ('\u01bc', '\u01bf'), ('\u01c0', '\u01c3'), + ('\u01c4', '\u0293'), ('\u0294', '\u0294'), + ('\u0295', '\u02af'), ('\u02b0', '\u02c1'), + ('\u02c6', '\u02d1'), ('\u02e0', '\u02e4'), + ('\u02ec', '\u02ec'), ('\u02ee', '\u02ee'), + ('\u0300', '\u036f'), ('\u0370', '\u0373'), + ('\u0374', '\u0374'), ('\u0376', '\u0377'), + ('\u037b', '\u037d'), ('\u0386', '\u0386'), + ('\u0387', '\u0387'), ('\u0388', '\u038a'), + ('\u038c', '\u038c'), ('\u038e', '\u03a1'), + ('\u03a3', '\u03f5'), ('\u03f7', '\u0481'), + ('\u0483', '\u0487'), ('\u048a', '\u0527'), + ('\u0531', '\u0556'), ('\u0559', '\u0559'), + ('\u0561', '\u0587'), ('\u0591', '\u05bd'), + ('\u05bf', '\u05bf'), ('\u05c1', '\u05c2'), + ('\u05c4', '\u05c5'), ('\u05c7', '\u05c7'), + ('\u05d0', '\u05ea'), ('\u05f0', '\u05f2'), + ('\u0610', '\u061a'), ('\u0620', '\u063f'), + ('\u0640', '\u0640'), ('\u0641', '\u064a'), + ('\u064b', '\u065f'), ('\u0660', '\u0669'), + ('\u066e', '\u066f'), ('\u0670', '\u0670'), + ('\u0671', '\u06d3'), ('\u06d5', '\u06d5'), + ('\u06d6', '\u06dc'), ('\u06df', '\u06e4'), + ('\u06e5', '\u06e6'), ('\u06e7', '\u06e8'), + ('\u06ea', '\u06ed'), ('\u06ee', '\u06ef'), + ('\u06f0', '\u06f9'), ('\u06fa', '\u06fc'), + ('\u06ff', '\u06ff'), ('\u0710', '\u0710'), + ('\u0711', '\u0711'), ('\u0712', '\u072f'), + ('\u0730', '\u074a'), ('\u074d', '\u07a5'), + ('\u07a6', '\u07b0'), ('\u07b1', '\u07b1'), + ('\u07c0', '\u07c9'), ('\u07ca', '\u07ea'), + ('\u07eb', '\u07f3'), ('\u07f4', '\u07f5'), + ('\u07fa', '\u07fa'), ('\u0800', '\u0815'), + ('\u0816', '\u0819'), ('\u081a', '\u081a'), + ('\u081b', '\u0823'), ('\u0824', '\u0824'), + ('\u0825', '\u0827'), ('\u0828', '\u0828'), + ('\u0829', '\u082d'), ('\u0840', '\u0858'), + ('\u0859', '\u085b'), ('\u08a0', '\u08a0'), + ('\u08a2', '\u08ac'), ('\u08e4', '\u08fe'), + ('\u0900', '\u0902'), ('\u0903', '\u0903'), + ('\u0904', '\u0939'), ('\u093a', '\u093a'), + ('\u093b', '\u093b'), ('\u093c', '\u093c'), + ('\u093d', '\u093d'), ('\u093e', '\u0940'), + ('\u0941', '\u0948'), ('\u0949', '\u094c'), + ('\u094d', '\u094d'), ('\u094e', '\u094f'), + ('\u0950', '\u0950'), ('\u0951', '\u0957'), + ('\u0958', '\u0961'), ('\u0962', '\u0963'), + ('\u0966', '\u096f'), ('\u0971', '\u0971'), + ('\u0972', '\u0977'), ('\u0979', '\u097f'), + ('\u0981', '\u0981'), ('\u0982', '\u0983'), + ('\u0985', '\u098c'), ('\u098f', '\u0990'), + ('\u0993', '\u09a8'), ('\u09aa', '\u09b0'), + ('\u09b2', '\u09b2'), ('\u09b6', '\u09b9'), + ('\u09bc', '\u09bc'), ('\u09bd', '\u09bd'), + ('\u09be', '\u09c0'), ('\u09c1', '\u09c4'), + ('\u09c7', '\u09c8'), ('\u09cb', '\u09cc'), + ('\u09cd', '\u09cd'), ('\u09ce', '\u09ce'), + ('\u09d7', '\u09d7'), ('\u09dc', '\u09dd'), + ('\u09df', '\u09e1'), ('\u09e2', '\u09e3'), + ('\u09e6', '\u09ef'), ('\u09f0', '\u09f1'), + ('\u0a01', '\u0a02'), ('\u0a03', '\u0a03'), + ('\u0a05', '\u0a0a'), ('\u0a0f', '\u0a10'), + ('\u0a13', '\u0a28'), ('\u0a2a', '\u0a30'), + ('\u0a32', '\u0a33'), ('\u0a35', '\u0a36'), + ('\u0a38', '\u0a39'), ('\u0a3c', '\u0a3c'), + ('\u0a3e', '\u0a40'), ('\u0a41', '\u0a42'), + ('\u0a47', '\u0a48'), ('\u0a4b', '\u0a4d'), + ('\u0a51', '\u0a51'), ('\u0a59', '\u0a5c'), + ('\u0a5e', '\u0a5e'), ('\u0a66', '\u0a6f'), + ('\u0a70', '\u0a71'), ('\u0a72', '\u0a74'), + ('\u0a75', '\u0a75'), ('\u0a81', '\u0a82'), + ('\u0a83', '\u0a83'), ('\u0a85', '\u0a8d'), + ('\u0a8f', '\u0a91'), ('\u0a93', '\u0aa8'), + ('\u0aaa', '\u0ab0'), ('\u0ab2', '\u0ab3'), + ('\u0ab5', '\u0ab9'), ('\u0abc', '\u0abc'), + ('\u0abd', '\u0abd'), ('\u0abe', '\u0ac0'), + ('\u0ac1', '\u0ac5'), ('\u0ac7', '\u0ac8'), + ('\u0ac9', '\u0ac9'), ('\u0acb', '\u0acc'), + ('\u0acd', '\u0acd'), ('\u0ad0', '\u0ad0'), + ('\u0ae0', '\u0ae1'), ('\u0ae2', '\u0ae3'), + ('\u0ae6', '\u0aef'), ('\u0b01', '\u0b01'), + ('\u0b02', '\u0b03'), ('\u0b05', '\u0b0c'), + ('\u0b0f', '\u0b10'), ('\u0b13', '\u0b28'), + ('\u0b2a', '\u0b30'), ('\u0b32', '\u0b33'), + ('\u0b35', '\u0b39'), ('\u0b3c', '\u0b3c'), + ('\u0b3d', '\u0b3d'), ('\u0b3e', '\u0b3e'), + ('\u0b3f', '\u0b3f'), ('\u0b40', '\u0b40'), + ('\u0b41', '\u0b44'), ('\u0b47', '\u0b48'), + ('\u0b4b', '\u0b4c'), ('\u0b4d', '\u0b4d'), + ('\u0b56', '\u0b56'), ('\u0b57', '\u0b57'), + ('\u0b5c', '\u0b5d'), ('\u0b5f', '\u0b61'), + ('\u0b62', '\u0b63'), ('\u0b66', '\u0b6f'), + ('\u0b71', '\u0b71'), ('\u0b82', '\u0b82'), + ('\u0b83', '\u0b83'), ('\u0b85', '\u0b8a'), + ('\u0b8e', '\u0b90'), ('\u0b92', '\u0b95'), + ('\u0b99', '\u0b9a'), ('\u0b9c', '\u0b9c'), + ('\u0b9e', '\u0b9f'), ('\u0ba3', '\u0ba4'), + ('\u0ba8', '\u0baa'), ('\u0bae', '\u0bb9'), + ('\u0bbe', '\u0bbf'), ('\u0bc0', '\u0bc0'), + ('\u0bc1', '\u0bc2'), ('\u0bc6', '\u0bc8'), + ('\u0bca', '\u0bcc'), ('\u0bcd', '\u0bcd'), + ('\u0bd0', '\u0bd0'), ('\u0bd7', '\u0bd7'), + ('\u0be6', '\u0bef'), ('\u0c01', '\u0c03'), + ('\u0c05', '\u0c0c'), ('\u0c0e', '\u0c10'), + ('\u0c12', '\u0c28'), ('\u0c2a', '\u0c33'), + ('\u0c35', '\u0c39'), ('\u0c3d', '\u0c3d'), + ('\u0c3e', '\u0c40'), ('\u0c41', '\u0c44'), + ('\u0c46', '\u0c48'), ('\u0c4a', '\u0c4d'), + ('\u0c55', '\u0c56'), ('\u0c58', '\u0c59'), + ('\u0c60', '\u0c61'), ('\u0c62', '\u0c63'), + ('\u0c66', '\u0c6f'), ('\u0c82', '\u0c83'), + ('\u0c85', '\u0c8c'), ('\u0c8e', '\u0c90'), + ('\u0c92', '\u0ca8'), ('\u0caa', '\u0cb3'), + ('\u0cb5', '\u0cb9'), ('\u0cbc', '\u0cbc'), + ('\u0cbd', '\u0cbd'), ('\u0cbe', '\u0cbe'), + ('\u0cbf', '\u0cbf'), ('\u0cc0', '\u0cc4'), + ('\u0cc6', '\u0cc6'), ('\u0cc7', '\u0cc8'), + ('\u0cca', '\u0ccb'), ('\u0ccc', '\u0ccd'), + ('\u0cd5', '\u0cd6'), ('\u0cde', '\u0cde'), + ('\u0ce0', '\u0ce1'), ('\u0ce2', '\u0ce3'), + ('\u0ce6', '\u0cef'), ('\u0cf1', '\u0cf2'), + ('\u0d02', '\u0d03'), ('\u0d05', '\u0d0c'), + ('\u0d0e', '\u0d10'), ('\u0d12', '\u0d3a'), + ('\u0d3d', '\u0d3d'), ('\u0d3e', '\u0d40'), + ('\u0d41', '\u0d44'), ('\u0d46', '\u0d48'), + ('\u0d4a', '\u0d4c'), ('\u0d4d', '\u0d4d'), + ('\u0d4e', '\u0d4e'), ('\u0d57', '\u0d57'), + ('\u0d60', '\u0d61'), ('\u0d62', '\u0d63'), + ('\u0d66', '\u0d6f'), ('\u0d7a', '\u0d7f'), + ('\u0d82', '\u0d83'), ('\u0d85', '\u0d96'), + ('\u0d9a', '\u0db1'), ('\u0db3', '\u0dbb'), + ('\u0dbd', '\u0dbd'), ('\u0dc0', '\u0dc6'), + ('\u0dca', '\u0dca'), ('\u0dcf', '\u0dd1'), + ('\u0dd2', '\u0dd4'), ('\u0dd6', '\u0dd6'), + ('\u0dd8', '\u0ddf'), ('\u0df2', '\u0df3'), + ('\u0e01', '\u0e30'), ('\u0e31', '\u0e31'), + ('\u0e32', '\u0e33'), ('\u0e34', '\u0e3a'), + ('\u0e40', '\u0e45'), ('\u0e46', '\u0e46'), + ('\u0e47', '\u0e4e'), ('\u0e50', '\u0e59'), + ('\u0e81', '\u0e82'), ('\u0e84', '\u0e84'), + ('\u0e87', '\u0e88'), ('\u0e8a', '\u0e8a'), + ('\u0e8d', '\u0e8d'), ('\u0e94', '\u0e97'), + ('\u0e99', '\u0e9f'), ('\u0ea1', '\u0ea3'), + ('\u0ea5', '\u0ea5'), ('\u0ea7', '\u0ea7'), + ('\u0eaa', '\u0eab'), ('\u0ead', '\u0eb0'), + ('\u0eb1', '\u0eb1'), ('\u0eb2', '\u0eb3'), + ('\u0eb4', '\u0eb9'), ('\u0ebb', '\u0ebc'), + ('\u0ebd', '\u0ebd'), ('\u0ec0', '\u0ec4'), + ('\u0ec6', '\u0ec6'), ('\u0ec8', '\u0ecd'), + ('\u0ed0', '\u0ed9'), ('\u0edc', '\u0edf'), + ('\u0f00', '\u0f00'), ('\u0f18', '\u0f19'), + ('\u0f20', '\u0f29'), ('\u0f35', '\u0f35'), + ('\u0f37', '\u0f37'), ('\u0f39', '\u0f39'), + ('\u0f3e', '\u0f3f'), ('\u0f40', '\u0f47'), + ('\u0f49', '\u0f6c'), ('\u0f71', '\u0f7e'), + ('\u0f7f', '\u0f7f'), ('\u0f80', '\u0f84'), + ('\u0f86', '\u0f87'), ('\u0f88', '\u0f8c'), + ('\u0f8d', '\u0f97'), ('\u0f99', '\u0fbc'), + ('\u0fc6', '\u0fc6'), ('\u1000', '\u102a'), + ('\u102b', '\u102c'), ('\u102d', '\u1030'), + ('\u1031', '\u1031'), ('\u1032', '\u1037'), + ('\u1038', '\u1038'), ('\u1039', '\u103a'), + ('\u103b', '\u103c'), ('\u103d', '\u103e'), + ('\u103f', '\u103f'), ('\u1040', '\u1049'), + ('\u1050', '\u1055'), ('\u1056', '\u1057'), + ('\u1058', '\u1059'), ('\u105a', '\u105d'), + ('\u105e', '\u1060'), ('\u1061', '\u1061'), + ('\u1062', '\u1064'), ('\u1065', '\u1066'), + ('\u1067', '\u106d'), ('\u106e', '\u1070'), + ('\u1071', '\u1074'), ('\u1075', '\u1081'), + ('\u1082', '\u1082'), ('\u1083', '\u1084'), + ('\u1085', '\u1086'), ('\u1087', '\u108c'), + ('\u108d', '\u108d'), ('\u108e', '\u108e'), + ('\u108f', '\u108f'), ('\u1090', '\u1099'), + ('\u109a', '\u109c'), ('\u109d', '\u109d'), + ('\u10a0', '\u10c5'), ('\u10c7', '\u10c7'), + ('\u10cd', '\u10cd'), ('\u10d0', '\u10fa'), + ('\u10fc', '\u10fc'), ('\u10fd', '\u1248'), + ('\u124a', '\u124d'), ('\u1250', '\u1256'), + ('\u1258', '\u1258'), ('\u125a', '\u125d'), + ('\u1260', '\u1288'), ('\u128a', '\u128d'), + ('\u1290', '\u12b0'), ('\u12b2', '\u12b5'), + ('\u12b8', '\u12be'), ('\u12c0', '\u12c0'), + ('\u12c2', '\u12c5'), ('\u12c8', '\u12d6'), + ('\u12d8', '\u1310'), ('\u1312', '\u1315'), + ('\u1318', '\u135a'), ('\u135d', '\u135f'), + ('\u1369', '\u1371'), ('\u1380', '\u138f'), + ('\u13a0', '\u13f4'), ('\u1401', '\u166c'), + ('\u166f', '\u167f'), ('\u1681', '\u169a'), + ('\u16a0', '\u16ea'), ('\u16ee', '\u16f0'), + ('\u1700', '\u170c'), ('\u170e', '\u1711'), + ('\u1712', '\u1714'), ('\u1720', '\u1731'), + ('\u1732', '\u1734'), ('\u1740', '\u1751'), + ('\u1752', '\u1753'), ('\u1760', '\u176c'), + ('\u176e', '\u1770'), ('\u1772', '\u1773'), + ('\u1780', '\u17b3'), ('\u17b4', '\u17b5'), + ('\u17b6', '\u17b6'), ('\u17b7', '\u17bd'), + ('\u17be', '\u17c5'), ('\u17c6', '\u17c6'), + ('\u17c7', '\u17c8'), ('\u17c9', '\u17d3'), + ('\u17d7', '\u17d7'), ('\u17dc', '\u17dc'), + ('\u17dd', '\u17dd'), ('\u17e0', '\u17e9'), + ('\u180b', '\u180d'), ('\u1810', '\u1819'), + ('\u1820', '\u1842'), ('\u1843', '\u1843'), + ('\u1844', '\u1877'), ('\u1880', '\u18a8'), + ('\u18a9', '\u18a9'), ('\u18aa', '\u18aa'), + ('\u18b0', '\u18f5'), ('\u1900', '\u191c'), + ('\u1920', '\u1922'), ('\u1923', '\u1926'), + ('\u1927', '\u1928'), ('\u1929', '\u192b'), + ('\u1930', '\u1931'), ('\u1932', '\u1932'), + ('\u1933', '\u1938'), ('\u1939', '\u193b'), + ('\u1946', '\u194f'), ('\u1950', '\u196d'), + ('\u1970', '\u1974'), ('\u1980', '\u19ab'), + ('\u19b0', '\u19c0'), ('\u19c1', '\u19c7'), + ('\u19c8', '\u19c9'), ('\u19d0', '\u19d9'), + ('\u19da', '\u19da'), ('\u1a00', '\u1a16'), + ('\u1a17', '\u1a18'), ('\u1a19', '\u1a1b'), + ('\u1a20', '\u1a54'), ('\u1a55', '\u1a55'), + ('\u1a56', '\u1a56'), ('\u1a57', '\u1a57'), + ('\u1a58', '\u1a5e'), ('\u1a60', '\u1a60'), + ('\u1a61', '\u1a61'), ('\u1a62', '\u1a62'), + ('\u1a63', '\u1a64'), ('\u1a65', '\u1a6c'), + ('\u1a6d', '\u1a72'), ('\u1a73', '\u1a7c'), + ('\u1a7f', '\u1a7f'), ('\u1a80', '\u1a89'), + ('\u1a90', '\u1a99'), ('\u1aa7', '\u1aa7'), + ('\u1b00', '\u1b03'), ('\u1b04', '\u1b04'), + ('\u1b05', '\u1b33'), ('\u1b34', '\u1b34'), + ('\u1b35', '\u1b35'), ('\u1b36', '\u1b3a'), + ('\u1b3b', '\u1b3b'), ('\u1b3c', '\u1b3c'), + ('\u1b3d', '\u1b41'), ('\u1b42', '\u1b42'), + ('\u1b43', '\u1b44'), ('\u1b45', '\u1b4b'), + ('\u1b50', '\u1b59'), ('\u1b6b', '\u1b73'), + ('\u1b80', '\u1b81'), ('\u1b82', '\u1b82'), + ('\u1b83', '\u1ba0'), ('\u1ba1', '\u1ba1'), + ('\u1ba2', '\u1ba5'), ('\u1ba6', '\u1ba7'), + ('\u1ba8', '\u1ba9'), ('\u1baa', '\u1baa'), + ('\u1bab', '\u1bab'), ('\u1bac', '\u1bad'), + ('\u1bae', '\u1baf'), ('\u1bb0', '\u1bb9'), + ('\u1bba', '\u1be5'), ('\u1be6', '\u1be6'), + ('\u1be7', '\u1be7'), ('\u1be8', '\u1be9'), + ('\u1bea', '\u1bec'), ('\u1bed', '\u1bed'), + ('\u1bee', '\u1bee'), ('\u1bef', '\u1bf1'), + ('\u1bf2', '\u1bf3'), ('\u1c00', '\u1c23'), + ('\u1c24', '\u1c2b'), ('\u1c2c', '\u1c33'), + ('\u1c34', '\u1c35'), ('\u1c36', '\u1c37'), + ('\u1c40', '\u1c49'), ('\u1c4d', '\u1c4f'), + ('\u1c50', '\u1c59'), ('\u1c5a', '\u1c77'), + ('\u1c78', '\u1c7d'), ('\u1cd0', '\u1cd2'), + ('\u1cd4', '\u1ce0'), ('\u1ce1', '\u1ce1'), + ('\u1ce2', '\u1ce8'), ('\u1ce9', '\u1cec'), + ('\u1ced', '\u1ced'), ('\u1cee', '\u1cf1'), + ('\u1cf2', '\u1cf3'), ('\u1cf4', '\u1cf4'), + ('\u1cf5', '\u1cf6'), ('\u1d00', '\u1d2b'), + ('\u1d2c', '\u1d6a'), ('\u1d6b', '\u1d77'), + ('\u1d78', '\u1d78'), ('\u1d79', '\u1d9a'), + ('\u1d9b', '\u1dbf'), ('\u1dc0', '\u1de6'), + ('\u1dfc', '\u1dff'), ('\u1e00', '\u1f15'), + ('\u1f18', '\u1f1d'), ('\u1f20', '\u1f45'), + ('\u1f48', '\u1f4d'), ('\u1f50', '\u1f57'), + ('\u1f59', '\u1f59'), ('\u1f5b', '\u1f5b'), + ('\u1f5d', '\u1f5d'), ('\u1f5f', '\u1f7d'), + ('\u1f80', '\u1fb4'), ('\u1fb6', '\u1fbc'), + ('\u1fbe', '\u1fbe'), ('\u1fc2', '\u1fc4'), + ('\u1fc6', '\u1fcc'), ('\u1fd0', '\u1fd3'), + ('\u1fd6', '\u1fdb'), ('\u1fe0', '\u1fec'), + ('\u1ff2', '\u1ff4'), ('\u1ff6', '\u1ffc'), + ('\u203f', '\u2040'), ('\u2054', '\u2054'), + ('\u2071', '\u2071'), ('\u207f', '\u207f'), + ('\u2090', '\u209c'), ('\u20d0', '\u20dc'), + ('\u20e1', '\u20e1'), ('\u20e5', '\u20f0'), + ('\u2102', '\u2102'), ('\u2107', '\u2107'), + ('\u210a', '\u2113'), ('\u2115', '\u2115'), + ('\u2118', '\u2118'), ('\u2119', '\u211d'), + ('\u2124', '\u2124'), ('\u2126', '\u2126'), + ('\u2128', '\u2128'), ('\u212a', '\u212d'), + ('\u212e', '\u212e'), ('\u212f', '\u2134'), + ('\u2135', '\u2138'), ('\u2139', '\u2139'), + ('\u213c', '\u213f'), ('\u2145', '\u2149'), + ('\u214e', '\u214e'), ('\u2160', '\u2182'), + ('\u2183', '\u2184'), ('\u2185', '\u2188'), + ('\u2c00', '\u2c2e'), ('\u2c30', '\u2c5e'), + ('\u2c60', '\u2c7b'), ('\u2c7c', '\u2c7d'), + ('\u2c7e', '\u2ce4'), ('\u2ceb', '\u2cee'), + ('\u2cef', '\u2cf1'), ('\u2cf2', '\u2cf3'), + ('\u2d00', '\u2d25'), ('\u2d27', '\u2d27'), + ('\u2d2d', '\u2d2d'), ('\u2d30', '\u2d67'), + ('\u2d6f', '\u2d6f'), ('\u2d7f', '\u2d7f'), + ('\u2d80', '\u2d96'), ('\u2da0', '\u2da6'), + ('\u2da8', '\u2dae'), ('\u2db0', '\u2db6'), + ('\u2db8', '\u2dbe'), ('\u2dc0', '\u2dc6'), + ('\u2dc8', '\u2dce'), ('\u2dd0', '\u2dd6'), + ('\u2dd8', '\u2dde'), ('\u2de0', '\u2dff'), + ('\u3005', '\u3005'), ('\u3006', '\u3006'), + ('\u3007', '\u3007'), ('\u3021', '\u3029'), + ('\u302a', '\u302d'), ('\u302e', '\u302f'), + ('\u3031', '\u3035'), ('\u3038', '\u303a'), + ('\u303b', '\u303b'), ('\u303c', '\u303c'), + ('\u3041', '\u3096'), ('\u3099', '\u309a'), + ('\u309d', '\u309e'), ('\u309f', '\u309f'), + ('\u30a1', '\u30fa'), ('\u30fc', '\u30fe'), + ('\u30ff', '\u30ff'), ('\u3105', '\u312d'), + ('\u3131', '\u318e'), ('\u31a0', '\u31ba'), + ('\u31f0', '\u31ff'), ('\u3400', '\u4db5'), + ('\u4e00', '\u9fcc'), ('\ua000', '\ua014'), + ('\ua015', '\ua015'), ('\ua016', '\ua48c'), + ('\ua4d0', '\ua4f7'), ('\ua4f8', '\ua4fd'), + ('\ua500', '\ua60b'), ('\ua60c', '\ua60c'), + ('\ua610', '\ua61f'), ('\ua620', '\ua629'), + ('\ua62a', '\ua62b'), ('\ua640', '\ua66d'), + ('\ua66e', '\ua66e'), ('\ua66f', '\ua66f'), + ('\ua674', '\ua67d'), ('\ua67f', '\ua67f'), + ('\ua680', '\ua697'), ('\ua69f', '\ua69f'), + ('\ua6a0', '\ua6e5'), ('\ua6e6', '\ua6ef'), + ('\ua6f0', '\ua6f1'), ('\ua717', '\ua71f'), + ('\ua722', '\ua76f'), ('\ua770', '\ua770'), + ('\ua771', '\ua787'), ('\ua788', '\ua788'), + ('\ua78b', '\ua78e'), ('\ua790', '\ua793'), + ('\ua7a0', '\ua7aa'), ('\ua7f8', '\ua7f9'), + ('\ua7fa', '\ua7fa'), ('\ua7fb', '\ua801'), + ('\ua802', '\ua802'), ('\ua803', '\ua805'), + ('\ua806', '\ua806'), ('\ua807', '\ua80a'), + ('\ua80b', '\ua80b'), ('\ua80c', '\ua822'), + ('\ua823', '\ua824'), ('\ua825', '\ua826'), + ('\ua827', '\ua827'), ('\ua840', '\ua873'), + ('\ua880', '\ua881'), ('\ua882', '\ua8b3'), + ('\ua8b4', '\ua8c3'), ('\ua8c4', '\ua8c4'), + ('\ua8d0', '\ua8d9'), ('\ua8e0', '\ua8f1'), + ('\ua8f2', '\ua8f7'), ('\ua8fb', '\ua8fb'), + ('\ua900', '\ua909'), ('\ua90a', '\ua925'), + ('\ua926', '\ua92d'), ('\ua930', '\ua946'), + ('\ua947', '\ua951'), ('\ua952', '\ua953'), + ('\ua960', '\ua97c'), ('\ua980', '\ua982'), + ('\ua983', '\ua983'), ('\ua984', '\ua9b2'), + ('\ua9b3', '\ua9b3'), ('\ua9b4', '\ua9b5'), + ('\ua9b6', '\ua9b9'), ('\ua9ba', '\ua9bb'), + ('\ua9bc', '\ua9bc'), ('\ua9bd', '\ua9c0'), + ('\ua9cf', '\ua9cf'), ('\ua9d0', '\ua9d9'), + ('\uaa00', '\uaa28'), ('\uaa29', '\uaa2e'), + ('\uaa2f', '\uaa30'), ('\uaa31', '\uaa32'), + ('\uaa33', '\uaa34'), ('\uaa35', '\uaa36'), + ('\uaa40', '\uaa42'), ('\uaa43', '\uaa43'), + ('\uaa44', '\uaa4b'), ('\uaa4c', '\uaa4c'), + ('\uaa4d', '\uaa4d'), ('\uaa50', '\uaa59'), + ('\uaa60', '\uaa6f'), ('\uaa70', '\uaa70'), + ('\uaa71', '\uaa76'), ('\uaa7a', '\uaa7a'), + ('\uaa7b', '\uaa7b'), ('\uaa80', '\uaaaf'), + ('\uaab0', '\uaab0'), ('\uaab1', '\uaab1'), + ('\uaab2', '\uaab4'), ('\uaab5', '\uaab6'), + ('\uaab7', '\uaab8'), ('\uaab9', '\uaabd'), + ('\uaabe', '\uaabf'), ('\uaac0', '\uaac0'), + ('\uaac1', '\uaac1'), ('\uaac2', '\uaac2'), + ('\uaadb', '\uaadc'), ('\uaadd', '\uaadd'), + ('\uaae0', '\uaaea'), ('\uaaeb', '\uaaeb'), + ('\uaaec', '\uaaed'), ('\uaaee', '\uaaef'), + ('\uaaf2', '\uaaf2'), ('\uaaf3', '\uaaf4'), + ('\uaaf5', '\uaaf5'), ('\uaaf6', '\uaaf6'), + ('\uab01', '\uab06'), ('\uab09', '\uab0e'), + ('\uab11', '\uab16'), ('\uab20', '\uab26'), + ('\uab28', '\uab2e'), ('\uabc0', '\uabe2'), + ('\uabe3', '\uabe4'), ('\uabe5', '\uabe5'), + ('\uabe6', '\uabe7'), ('\uabe8', '\uabe8'), + ('\uabe9', '\uabea'), ('\uabec', '\uabec'), + ('\uabed', '\uabed'), ('\uabf0', '\uabf9'), + ('\uac00', '\ud7a3'), ('\ud7b0', '\ud7c6'), + ('\ud7cb', '\ud7fb'), ('\uf900', '\ufa6d'), + ('\ufa70', '\ufad9'), ('\ufb00', '\ufb06'), + ('\ufb13', '\ufb17'), ('\ufb1d', '\ufb1d'), + ('\ufb1e', '\ufb1e'), ('\ufb1f', '\ufb28'), + ('\ufb2a', '\ufb36'), ('\ufb38', '\ufb3c'), + ('\ufb3e', '\ufb3e'), ('\ufb40', '\ufb41'), + ('\ufb43', '\ufb44'), ('\ufb46', '\ufbb1'), + ('\ufbd3', '\ufc5d'), ('\ufc64', '\ufd3d'), + ('\ufd50', '\ufd8f'), ('\ufd92', '\ufdc7'), + ('\ufdf0', '\ufdf9'), ('\ufe00', '\ufe0f'), + ('\ufe20', '\ufe26'), ('\ufe33', '\ufe34'), + ('\ufe4d', '\ufe4f'), ('\ufe71', '\ufe71'), + ('\ufe73', '\ufe73'), ('\ufe77', '\ufe77'), + ('\ufe79', '\ufe79'), ('\ufe7b', '\ufe7b'), + ('\ufe7d', '\ufe7d'), ('\ufe7f', '\ufefc'), + ('\uff10', '\uff19'), ('\uff21', '\uff3a'), + ('\uff3f', '\uff3f'), ('\uff41', '\uff5a'), + ('\uff66', '\uff6f'), ('\uff70', '\uff70'), + ('\uff71', '\uff9d'), ('\uff9e', '\uff9f'), + ('\uffa0', '\uffbe'), ('\uffc2', '\uffc7'), + ('\uffca', '\uffcf'), ('\uffd2', '\uffd7'), + ('\uffda', '\uffdc'), ('\U00010000', '\U0001000b'), + ('\U0001000d', '\U00010026'), ('\U00010028', '\U0001003a'), + ('\U0001003c', '\U0001003d'), ('\U0001003f', '\U0001004d'), + ('\U00010050', '\U0001005d'), ('\U00010080', '\U000100fa'), + ('\U00010140', '\U00010174'), ('\U000101fd', '\U000101fd'), + ('\U00010280', '\U0001029c'), ('\U000102a0', '\U000102d0'), + ('\U00010300', '\U0001031e'), ('\U00010330', '\U00010340'), + ('\U00010341', '\U00010341'), ('\U00010342', '\U00010349'), + ('\U0001034a', '\U0001034a'), ('\U00010380', '\U0001039d'), + ('\U000103a0', '\U000103c3'), ('\U000103c8', '\U000103cf'), + ('\U000103d1', '\U000103d5'), ('\U00010400', '\U0001044f'), + ('\U00010450', '\U0001049d'), ('\U000104a0', '\U000104a9'), + ('\U00010800', '\U00010805'), ('\U00010808', '\U00010808'), + ('\U0001080a', '\U00010835'), ('\U00010837', '\U00010838'), + ('\U0001083c', '\U0001083c'), ('\U0001083f', '\U00010855'), + ('\U00010900', '\U00010915'), ('\U00010920', '\U00010939'), + ('\U00010980', '\U000109b7'), ('\U000109be', '\U000109bf'), + ('\U00010a00', '\U00010a00'), ('\U00010a01', '\U00010a03'), + ('\U00010a05', '\U00010a06'), ('\U00010a0c', '\U00010a0f'), + ('\U00010a10', '\U00010a13'), ('\U00010a15', '\U00010a17'), + ('\U00010a19', '\U00010a33'), ('\U00010a38', '\U00010a3a'), + ('\U00010a3f', '\U00010a3f'), ('\U00010a60', '\U00010a7c'), + ('\U00010b00', '\U00010b35'), ('\U00010b40', '\U00010b55'), + ('\U00010b60', '\U00010b72'), ('\U00010c00', '\U00010c48'), + ('\U00011000', '\U00011000'), ('\U00011001', '\U00011001'), + ('\U00011002', '\U00011002'), ('\U00011003', '\U00011037'), + ('\U00011038', '\U00011046'), ('\U00011066', '\U0001106f'), + ('\U00011080', '\U00011081'), ('\U00011082', '\U00011082'), + ('\U00011083', '\U000110af'), ('\U000110b0', '\U000110b2'), + ('\U000110b3', '\U000110b6'), ('\U000110b7', '\U000110b8'), + ('\U000110b9', '\U000110ba'), ('\U000110d0', '\U000110e8'), + ('\U000110f0', '\U000110f9'), ('\U00011100', '\U00011102'), + ('\U00011103', '\U00011126'), ('\U00011127', '\U0001112b'), + ('\U0001112c', '\U0001112c'), ('\U0001112d', '\U00011134'), + ('\U00011136', '\U0001113f'), ('\U00011180', '\U00011181'), + ('\U00011182', '\U00011182'), ('\U00011183', '\U000111b2'), + ('\U000111b3', '\U000111b5'), ('\U000111b6', '\U000111be'), + ('\U000111bf', '\U000111c0'), ('\U000111c1', '\U000111c4'), + ('\U000111d0', '\U000111d9'), ('\U00011680', '\U000116aa'), + ('\U000116ab', '\U000116ab'), ('\U000116ac', '\U000116ac'), + ('\U000116ad', '\U000116ad'), ('\U000116ae', '\U000116af'), + ('\U000116b0', '\U000116b5'), ('\U000116b6', '\U000116b6'), + ('\U000116b7', '\U000116b7'), ('\U000116c0', '\U000116c9'), + ('\U00012000', '\U0001236e'), ('\U00012400', '\U00012462'), + ('\U00013000', '\U0001342e'), ('\U00016800', '\U00016a38'), + ('\U00016f00', '\U00016f44'), ('\U00016f50', '\U00016f50'), + ('\U00016f51', '\U00016f7e'), ('\U00016f8f', '\U00016f92'), + ('\U00016f93', '\U00016f9f'), ('\U0001b000', '\U0001b001'), + ('\U0001d165', '\U0001d166'), ('\U0001d167', '\U0001d169'), + ('\U0001d16d', '\U0001d172'), ('\U0001d17b', '\U0001d182'), + ('\U0001d185', '\U0001d18b'), ('\U0001d1aa', '\U0001d1ad'), + ('\U0001d242', '\U0001d244'), ('\U0001d400', '\U0001d454'), + ('\U0001d456', '\U0001d49c'), ('\U0001d49e', '\U0001d49f'), + ('\U0001d4a2', '\U0001d4a2'), ('\U0001d4a5', '\U0001d4a6'), + ('\U0001d4a9', '\U0001d4ac'), ('\U0001d4ae', '\U0001d4b9'), + ('\U0001d4bb', '\U0001d4bb'), ('\U0001d4bd', '\U0001d4c3'), + ('\U0001d4c5', '\U0001d505'), ('\U0001d507', '\U0001d50a'), + ('\U0001d50d', '\U0001d514'), ('\U0001d516', '\U0001d51c'), + ('\U0001d51e', '\U0001d539'), ('\U0001d53b', '\U0001d53e'), + ('\U0001d540', '\U0001d544'), ('\U0001d546', '\U0001d546'), + ('\U0001d54a', '\U0001d550'), ('\U0001d552', '\U0001d6a5'), + ('\U0001d6a8', '\U0001d6c0'), ('\U0001d6c2', '\U0001d6da'), + ('\U0001d6dc', '\U0001d6fa'), ('\U0001d6fc', '\U0001d714'), + ('\U0001d716', '\U0001d734'), ('\U0001d736', '\U0001d74e'), + ('\U0001d750', '\U0001d76e'), ('\U0001d770', '\U0001d788'), + ('\U0001d78a', '\U0001d7a8'), ('\U0001d7aa', '\U0001d7c2'), + ('\U0001d7c4', '\U0001d7cb'), ('\U0001d7ce', '\U0001d7ff'), + ('\U0001ee00', '\U0001ee03'), ('\U0001ee05', '\U0001ee1f'), + ('\U0001ee21', '\U0001ee22'), ('\U0001ee24', '\U0001ee24'), + ('\U0001ee27', '\U0001ee27'), ('\U0001ee29', '\U0001ee32'), + ('\U0001ee34', '\U0001ee37'), ('\U0001ee39', '\U0001ee39'), + ('\U0001ee3b', '\U0001ee3b'), ('\U0001ee42', '\U0001ee42'), + ('\U0001ee47', '\U0001ee47'), ('\U0001ee49', '\U0001ee49'), + ('\U0001ee4b', '\U0001ee4b'), ('\U0001ee4d', '\U0001ee4f'), + ('\U0001ee51', '\U0001ee52'), ('\U0001ee54', '\U0001ee54'), + ('\U0001ee57', '\U0001ee57'), ('\U0001ee59', '\U0001ee59'), + ('\U0001ee5b', '\U0001ee5b'), ('\U0001ee5d', '\U0001ee5d'), + ('\U0001ee5f', '\U0001ee5f'), ('\U0001ee61', '\U0001ee62'), + ('\U0001ee64', '\U0001ee64'), ('\U0001ee67', '\U0001ee6a'), + ('\U0001ee6c', '\U0001ee72'), ('\U0001ee74', '\U0001ee77'), + ('\U0001ee79', '\U0001ee7c'), ('\U0001ee7e', '\U0001ee7e'), + ('\U0001ee80', '\U0001ee89'), ('\U0001ee8b', '\U0001ee9b'), + ('\U0001eea1', '\U0001eea3'), ('\U0001eea5', '\U0001eea9'), + ('\U0001eeab', '\U0001eebb'), ('\U00020000', '\U0002a6d6'), + ('\U0002a700', '\U0002b734'), ('\U0002b740', '\U0002b81d'), + ('\U0002f800', '\U0002fa1d'), ('\U000e0100', '\U000e01ef') + ]; + + pub fn XID_Continue(c: char) -> bool { + bsearch_range_table(c, XID_Continue_table) } - #[test] - fn test_is_upper() { - assert!((unicode::icu::is_upper('M'))); - assert!((!unicode::icu::is_upper('m'))); + static XID_Start_table : &'static [(char,char)] = &[ + ('\x41', '\x5a'), ('\x61', '\x7a'), + ('\xaa', '\xaa'), ('\xb5', '\xb5'), + ('\xba', '\xba'), ('\xc0', '\xd6'), + ('\xd8', '\xf6'), ('\xf8', '\u01ba'), + ('\u01bb', '\u01bb'), ('\u01bc', '\u01bf'), + ('\u01c0', '\u01c3'), ('\u01c4', '\u0293'), + ('\u0294', '\u0294'), ('\u0295', '\u02af'), + ('\u02b0', '\u02c1'), ('\u02c6', '\u02d1'), + ('\u02e0', '\u02e4'), ('\u02ec', '\u02ec'), + ('\u02ee', '\u02ee'), ('\u0370', '\u0373'), + ('\u0374', '\u0374'), ('\u0376', '\u0377'), + ('\u037b', '\u037d'), ('\u0386', '\u0386'), + ('\u0388', '\u038a'), ('\u038c', '\u038c'), + ('\u038e', '\u03a1'), ('\u03a3', '\u03f5'), + ('\u03f7', '\u0481'), ('\u048a', '\u0527'), + ('\u0531', '\u0556'), ('\u0559', '\u0559'), + ('\u0561', '\u0587'), ('\u05d0', '\u05ea'), + ('\u05f0', '\u05f2'), ('\u0620', '\u063f'), + ('\u0640', '\u0640'), ('\u0641', '\u064a'), + ('\u066e', '\u066f'), ('\u0671', '\u06d3'), + ('\u06d5', '\u06d5'), ('\u06e5', '\u06e6'), + ('\u06ee', '\u06ef'), ('\u06fa', '\u06fc'), + ('\u06ff', '\u06ff'), ('\u0710', '\u0710'), + ('\u0712', '\u072f'), ('\u074d', '\u07a5'), + ('\u07b1', '\u07b1'), ('\u07ca', '\u07ea'), + ('\u07f4', '\u07f5'), ('\u07fa', '\u07fa'), + ('\u0800', '\u0815'), ('\u081a', '\u081a'), + ('\u0824', '\u0824'), ('\u0828', '\u0828'), + ('\u0840', '\u0858'), ('\u08a0', '\u08a0'), + ('\u08a2', '\u08ac'), ('\u0904', '\u0939'), + ('\u093d', '\u093d'), ('\u0950', '\u0950'), + ('\u0958', '\u0961'), ('\u0971', '\u0971'), + ('\u0972', '\u0977'), ('\u0979', '\u097f'), + ('\u0985', '\u098c'), ('\u098f', '\u0990'), + ('\u0993', '\u09a8'), ('\u09aa', '\u09b0'), + ('\u09b2', '\u09b2'), ('\u09b6', '\u09b9'), + ('\u09bd', '\u09bd'), ('\u09ce', '\u09ce'), + ('\u09dc', '\u09dd'), ('\u09df', '\u09e1'), + ('\u09f0', '\u09f1'), ('\u0a05', '\u0a0a'), + ('\u0a0f', '\u0a10'), ('\u0a13', '\u0a28'), + ('\u0a2a', '\u0a30'), ('\u0a32', '\u0a33'), + ('\u0a35', '\u0a36'), ('\u0a38', '\u0a39'), + ('\u0a59', '\u0a5c'), ('\u0a5e', '\u0a5e'), + ('\u0a72', '\u0a74'), ('\u0a85', '\u0a8d'), + ('\u0a8f', '\u0a91'), ('\u0a93', '\u0aa8'), + ('\u0aaa', '\u0ab0'), ('\u0ab2', '\u0ab3'), + ('\u0ab5', '\u0ab9'), ('\u0abd', '\u0abd'), + ('\u0ad0', '\u0ad0'), ('\u0ae0', '\u0ae1'), + ('\u0b05', '\u0b0c'), ('\u0b0f', '\u0b10'), + ('\u0b13', '\u0b28'), ('\u0b2a', '\u0b30'), + ('\u0b32', '\u0b33'), ('\u0b35', '\u0b39'), + ('\u0b3d', '\u0b3d'), ('\u0b5c', '\u0b5d'), + ('\u0b5f', '\u0b61'), ('\u0b71', '\u0b71'), + ('\u0b83', '\u0b83'), ('\u0b85', '\u0b8a'), + ('\u0b8e', '\u0b90'), ('\u0b92', '\u0b95'), + ('\u0b99', '\u0b9a'), ('\u0b9c', '\u0b9c'), + ('\u0b9e', '\u0b9f'), ('\u0ba3', '\u0ba4'), + ('\u0ba8', '\u0baa'), ('\u0bae', '\u0bb9'), + ('\u0bd0', '\u0bd0'), ('\u0c05', '\u0c0c'), + ('\u0c0e', '\u0c10'), ('\u0c12', '\u0c28'), + ('\u0c2a', '\u0c33'), ('\u0c35', '\u0c39'), + ('\u0c3d', '\u0c3d'), ('\u0c58', '\u0c59'), + ('\u0c60', '\u0c61'), ('\u0c85', '\u0c8c'), + ('\u0c8e', '\u0c90'), ('\u0c92', '\u0ca8'), + ('\u0caa', '\u0cb3'), ('\u0cb5', '\u0cb9'), + ('\u0cbd', '\u0cbd'), ('\u0cde', '\u0cde'), + ('\u0ce0', '\u0ce1'), ('\u0cf1', '\u0cf2'), + ('\u0d05', '\u0d0c'), ('\u0d0e', '\u0d10'), + ('\u0d12', '\u0d3a'), ('\u0d3d', '\u0d3d'), + ('\u0d4e', '\u0d4e'), ('\u0d60', '\u0d61'), + ('\u0d7a', '\u0d7f'), ('\u0d85', '\u0d96'), + ('\u0d9a', '\u0db1'), ('\u0db3', '\u0dbb'), + ('\u0dbd', '\u0dbd'), ('\u0dc0', '\u0dc6'), + ('\u0e01', '\u0e30'), ('\u0e32', '\u0e32'), + ('\u0e40', '\u0e45'), ('\u0e46', '\u0e46'), + ('\u0e81', '\u0e82'), ('\u0e84', '\u0e84'), + ('\u0e87', '\u0e88'), ('\u0e8a', '\u0e8a'), + ('\u0e8d', '\u0e8d'), ('\u0e94', '\u0e97'), + ('\u0e99', '\u0e9f'), ('\u0ea1', '\u0ea3'), + ('\u0ea5', '\u0ea5'), ('\u0ea7', '\u0ea7'), + ('\u0eaa', '\u0eab'), ('\u0ead', '\u0eb0'), + ('\u0eb2', '\u0eb2'), ('\u0ebd', '\u0ebd'), + ('\u0ec0', '\u0ec4'), ('\u0ec6', '\u0ec6'), + ('\u0edc', '\u0edf'), ('\u0f00', '\u0f00'), + ('\u0f40', '\u0f47'), ('\u0f49', '\u0f6c'), + ('\u0f88', '\u0f8c'), ('\u1000', '\u102a'), + ('\u103f', '\u103f'), ('\u1050', '\u1055'), + ('\u105a', '\u105d'), ('\u1061', '\u1061'), + ('\u1065', '\u1066'), ('\u106e', '\u1070'), + ('\u1075', '\u1081'), ('\u108e', '\u108e'), + ('\u10a0', '\u10c5'), ('\u10c7', '\u10c7'), + ('\u10cd', '\u10cd'), ('\u10d0', '\u10fa'), + ('\u10fc', '\u10fc'), ('\u10fd', '\u1248'), + ('\u124a', '\u124d'), ('\u1250', '\u1256'), + ('\u1258', '\u1258'), ('\u125a', '\u125d'), + ('\u1260', '\u1288'), ('\u128a', '\u128d'), + ('\u1290', '\u12b0'), ('\u12b2', '\u12b5'), + ('\u12b8', '\u12be'), ('\u12c0', '\u12c0'), + ('\u12c2', '\u12c5'), ('\u12c8', '\u12d6'), + ('\u12d8', '\u1310'), ('\u1312', '\u1315'), + ('\u1318', '\u135a'), ('\u1380', '\u138f'), + ('\u13a0', '\u13f4'), ('\u1401', '\u166c'), + ('\u166f', '\u167f'), ('\u1681', '\u169a'), + ('\u16a0', '\u16ea'), ('\u16ee', '\u16f0'), + ('\u1700', '\u170c'), ('\u170e', '\u1711'), + ('\u1720', '\u1731'), ('\u1740', '\u1751'), + ('\u1760', '\u176c'), ('\u176e', '\u1770'), + ('\u1780', '\u17b3'), ('\u17d7', '\u17d7'), + ('\u17dc', '\u17dc'), ('\u1820', '\u1842'), + ('\u1843', '\u1843'), ('\u1844', '\u1877'), + ('\u1880', '\u18a8'), ('\u18aa', '\u18aa'), + ('\u18b0', '\u18f5'), ('\u1900', '\u191c'), + ('\u1950', '\u196d'), ('\u1970', '\u1974'), + ('\u1980', '\u19ab'), ('\u19c1', '\u19c7'), + ('\u1a00', '\u1a16'), ('\u1a20', '\u1a54'), + ('\u1aa7', '\u1aa7'), ('\u1b05', '\u1b33'), + ('\u1b45', '\u1b4b'), ('\u1b83', '\u1ba0'), + ('\u1bae', '\u1baf'), ('\u1bba', '\u1be5'), + ('\u1c00', '\u1c23'), ('\u1c4d', '\u1c4f'), + ('\u1c5a', '\u1c77'), ('\u1c78', '\u1c7d'), + ('\u1ce9', '\u1cec'), ('\u1cee', '\u1cf1'), + ('\u1cf5', '\u1cf6'), ('\u1d00', '\u1d2b'), + ('\u1d2c', '\u1d6a'), ('\u1d6b', '\u1d77'), + ('\u1d78', '\u1d78'), ('\u1d79', '\u1d9a'), + ('\u1d9b', '\u1dbf'), ('\u1e00', '\u1f15'), + ('\u1f18', '\u1f1d'), ('\u1f20', '\u1f45'), + ('\u1f48', '\u1f4d'), ('\u1f50', '\u1f57'), + ('\u1f59', '\u1f59'), ('\u1f5b', '\u1f5b'), + ('\u1f5d', '\u1f5d'), ('\u1f5f', '\u1f7d'), + ('\u1f80', '\u1fb4'), ('\u1fb6', '\u1fbc'), + ('\u1fbe', '\u1fbe'), ('\u1fc2', '\u1fc4'), + ('\u1fc6', '\u1fcc'), ('\u1fd0', '\u1fd3'), + ('\u1fd6', '\u1fdb'), ('\u1fe0', '\u1fec'), + ('\u1ff2', '\u1ff4'), ('\u1ff6', '\u1ffc'), + ('\u2071', '\u2071'), ('\u207f', '\u207f'), + ('\u2090', '\u209c'), ('\u2102', '\u2102'), + ('\u2107', '\u2107'), ('\u210a', '\u2113'), + ('\u2115', '\u2115'), ('\u2118', '\u2118'), + ('\u2119', '\u211d'), ('\u2124', '\u2124'), + ('\u2126', '\u2126'), ('\u2128', '\u2128'), + ('\u212a', '\u212d'), ('\u212e', '\u212e'), + ('\u212f', '\u2134'), ('\u2135', '\u2138'), + ('\u2139', '\u2139'), ('\u213c', '\u213f'), + ('\u2145', '\u2149'), ('\u214e', '\u214e'), + ('\u2160', '\u2182'), ('\u2183', '\u2184'), + ('\u2185', '\u2188'), ('\u2c00', '\u2c2e'), + ('\u2c30', '\u2c5e'), ('\u2c60', '\u2c7b'), + ('\u2c7c', '\u2c7d'), ('\u2c7e', '\u2ce4'), + ('\u2ceb', '\u2cee'), ('\u2cf2', '\u2cf3'), + ('\u2d00', '\u2d25'), ('\u2d27', '\u2d27'), + ('\u2d2d', '\u2d2d'), ('\u2d30', '\u2d67'), + ('\u2d6f', '\u2d6f'), ('\u2d80', '\u2d96'), + ('\u2da0', '\u2da6'), ('\u2da8', '\u2dae'), + ('\u2db0', '\u2db6'), ('\u2db8', '\u2dbe'), + ('\u2dc0', '\u2dc6'), ('\u2dc8', '\u2dce'), + ('\u2dd0', '\u2dd6'), ('\u2dd8', '\u2dde'), + ('\u3005', '\u3005'), ('\u3006', '\u3006'), + ('\u3007', '\u3007'), ('\u3021', '\u3029'), + ('\u3031', '\u3035'), ('\u3038', '\u303a'), + ('\u303b', '\u303b'), ('\u303c', '\u303c'), + ('\u3041', '\u3096'), ('\u309d', '\u309e'), + ('\u309f', '\u309f'), ('\u30a1', '\u30fa'), + ('\u30fc', '\u30fe'), ('\u30ff', '\u30ff'), + ('\u3105', '\u312d'), ('\u3131', '\u318e'), + ('\u31a0', '\u31ba'), ('\u31f0', '\u31ff'), + ('\u3400', '\u4db5'), ('\u4e00', '\u9fcc'), + ('\ua000', '\ua014'), ('\ua015', '\ua015'), + ('\ua016', '\ua48c'), ('\ua4d0', '\ua4f7'), + ('\ua4f8', '\ua4fd'), ('\ua500', '\ua60b'), + ('\ua60c', '\ua60c'), ('\ua610', '\ua61f'), + ('\ua62a', '\ua62b'), ('\ua640', '\ua66d'), + ('\ua66e', '\ua66e'), ('\ua67f', '\ua67f'), + ('\ua680', '\ua697'), ('\ua6a0', '\ua6e5'), + ('\ua6e6', '\ua6ef'), ('\ua717', '\ua71f'), + ('\ua722', '\ua76f'), ('\ua770', '\ua770'), + ('\ua771', '\ua787'), ('\ua788', '\ua788'), + ('\ua78b', '\ua78e'), ('\ua790', '\ua793'), + ('\ua7a0', '\ua7aa'), ('\ua7f8', '\ua7f9'), + ('\ua7fa', '\ua7fa'), ('\ua7fb', '\ua801'), + ('\ua803', '\ua805'), ('\ua807', '\ua80a'), + ('\ua80c', '\ua822'), ('\ua840', '\ua873'), + ('\ua882', '\ua8b3'), ('\ua8f2', '\ua8f7'), + ('\ua8fb', '\ua8fb'), ('\ua90a', '\ua925'), + ('\ua930', '\ua946'), ('\ua960', '\ua97c'), + ('\ua984', '\ua9b2'), ('\ua9cf', '\ua9cf'), + ('\uaa00', '\uaa28'), ('\uaa40', '\uaa42'), + ('\uaa44', '\uaa4b'), ('\uaa60', '\uaa6f'), + ('\uaa70', '\uaa70'), ('\uaa71', '\uaa76'), + ('\uaa7a', '\uaa7a'), ('\uaa80', '\uaaaf'), + ('\uaab1', '\uaab1'), ('\uaab5', '\uaab6'), + ('\uaab9', '\uaabd'), ('\uaac0', '\uaac0'), + ('\uaac2', '\uaac2'), ('\uaadb', '\uaadc'), + ('\uaadd', '\uaadd'), ('\uaae0', '\uaaea'), + ('\uaaf2', '\uaaf2'), ('\uaaf3', '\uaaf4'), + ('\uab01', '\uab06'), ('\uab09', '\uab0e'), + ('\uab11', '\uab16'), ('\uab20', '\uab26'), + ('\uab28', '\uab2e'), ('\uabc0', '\uabe2'), + ('\uac00', '\ud7a3'), ('\ud7b0', '\ud7c6'), + ('\ud7cb', '\ud7fb'), ('\uf900', '\ufa6d'), + ('\ufa70', '\ufad9'), ('\ufb00', '\ufb06'), + ('\ufb13', '\ufb17'), ('\ufb1d', '\ufb1d'), + ('\ufb1f', '\ufb28'), ('\ufb2a', '\ufb36'), + ('\ufb38', '\ufb3c'), ('\ufb3e', '\ufb3e'), + ('\ufb40', '\ufb41'), ('\ufb43', '\ufb44'), + ('\ufb46', '\ufbb1'), ('\ufbd3', '\ufc5d'), + ('\ufc64', '\ufd3d'), ('\ufd50', '\ufd8f'), + ('\ufd92', '\ufdc7'), ('\ufdf0', '\ufdf9'), + ('\ufe71', '\ufe71'), ('\ufe73', '\ufe73'), + ('\ufe77', '\ufe77'), ('\ufe79', '\ufe79'), + ('\ufe7b', '\ufe7b'), ('\ufe7d', '\ufe7d'), + ('\ufe7f', '\ufefc'), ('\uff21', '\uff3a'), + ('\uff41', '\uff5a'), ('\uff66', '\uff6f'), + ('\uff70', '\uff70'), ('\uff71', '\uff9d'), + ('\uffa0', '\uffbe'), ('\uffc2', '\uffc7'), + ('\uffca', '\uffcf'), ('\uffd2', '\uffd7'), + ('\uffda', '\uffdc'), ('\U00010000', '\U0001000b'), + ('\U0001000d', '\U00010026'), ('\U00010028', '\U0001003a'), + ('\U0001003c', '\U0001003d'), ('\U0001003f', '\U0001004d'), + ('\U00010050', '\U0001005d'), ('\U00010080', '\U000100fa'), + ('\U00010140', '\U00010174'), ('\U00010280', '\U0001029c'), + ('\U000102a0', '\U000102d0'), ('\U00010300', '\U0001031e'), + ('\U00010330', '\U00010340'), ('\U00010341', '\U00010341'), + ('\U00010342', '\U00010349'), ('\U0001034a', '\U0001034a'), + ('\U00010380', '\U0001039d'), ('\U000103a0', '\U000103c3'), + ('\U000103c8', '\U000103cf'), ('\U000103d1', '\U000103d5'), + ('\U00010400', '\U0001044f'), ('\U00010450', '\U0001049d'), + ('\U00010800', '\U00010805'), ('\U00010808', '\U00010808'), + ('\U0001080a', '\U00010835'), ('\U00010837', '\U00010838'), + ('\U0001083c', '\U0001083c'), ('\U0001083f', '\U00010855'), + ('\U00010900', '\U00010915'), ('\U00010920', '\U00010939'), + ('\U00010980', '\U000109b7'), ('\U000109be', '\U000109bf'), + ('\U00010a00', '\U00010a00'), ('\U00010a10', '\U00010a13'), + ('\U00010a15', '\U00010a17'), ('\U00010a19', '\U00010a33'), + ('\U00010a60', '\U00010a7c'), ('\U00010b00', '\U00010b35'), + ('\U00010b40', '\U00010b55'), ('\U00010b60', '\U00010b72'), + ('\U00010c00', '\U00010c48'), ('\U00011003', '\U00011037'), + ('\U00011083', '\U000110af'), ('\U000110d0', '\U000110e8'), + ('\U00011103', '\U00011126'), ('\U00011183', '\U000111b2'), + ('\U000111c1', '\U000111c4'), ('\U00011680', '\U000116aa'), + ('\U00012000', '\U0001236e'), ('\U00012400', '\U00012462'), + ('\U00013000', '\U0001342e'), ('\U00016800', '\U00016a38'), + ('\U00016f00', '\U00016f44'), ('\U00016f50', '\U00016f50'), + ('\U00016f93', '\U00016f9f'), ('\U0001b000', '\U0001b001'), + ('\U0001d400', '\U0001d454'), ('\U0001d456', '\U0001d49c'), + ('\U0001d49e', '\U0001d49f'), ('\U0001d4a2', '\U0001d4a2'), + ('\U0001d4a5', '\U0001d4a6'), ('\U0001d4a9', '\U0001d4ac'), + ('\U0001d4ae', '\U0001d4b9'), ('\U0001d4bb', '\U0001d4bb'), + ('\U0001d4bd', '\U0001d4c3'), ('\U0001d4c5', '\U0001d505'), + ('\U0001d507', '\U0001d50a'), ('\U0001d50d', '\U0001d514'), + ('\U0001d516', '\U0001d51c'), ('\U0001d51e', '\U0001d539'), + ('\U0001d53b', '\U0001d53e'), ('\U0001d540', '\U0001d544'), + ('\U0001d546', '\U0001d546'), ('\U0001d54a', '\U0001d550'), + ('\U0001d552', '\U0001d6a5'), ('\U0001d6a8', '\U0001d6c0'), + ('\U0001d6c2', '\U0001d6da'), ('\U0001d6dc', '\U0001d6fa'), + ('\U0001d6fc', '\U0001d714'), ('\U0001d716', '\U0001d734'), + ('\U0001d736', '\U0001d74e'), ('\U0001d750', '\U0001d76e'), + ('\U0001d770', '\U0001d788'), ('\U0001d78a', '\U0001d7a8'), + ('\U0001d7aa', '\U0001d7c2'), ('\U0001d7c4', '\U0001d7cb'), + ('\U0001ee00', '\U0001ee03'), ('\U0001ee05', '\U0001ee1f'), + ('\U0001ee21', '\U0001ee22'), ('\U0001ee24', '\U0001ee24'), + ('\U0001ee27', '\U0001ee27'), ('\U0001ee29', '\U0001ee32'), + ('\U0001ee34', '\U0001ee37'), ('\U0001ee39', '\U0001ee39'), + ('\U0001ee3b', '\U0001ee3b'), ('\U0001ee42', '\U0001ee42'), + ('\U0001ee47', '\U0001ee47'), ('\U0001ee49', '\U0001ee49'), + ('\U0001ee4b', '\U0001ee4b'), ('\U0001ee4d', '\U0001ee4f'), + ('\U0001ee51', '\U0001ee52'), ('\U0001ee54', '\U0001ee54'), + ('\U0001ee57', '\U0001ee57'), ('\U0001ee59', '\U0001ee59'), + ('\U0001ee5b', '\U0001ee5b'), ('\U0001ee5d', '\U0001ee5d'), + ('\U0001ee5f', '\U0001ee5f'), ('\U0001ee61', '\U0001ee62'), + ('\U0001ee64', '\U0001ee64'), ('\U0001ee67', '\U0001ee6a'), + ('\U0001ee6c', '\U0001ee72'), ('\U0001ee74', '\U0001ee77'), + ('\U0001ee79', '\U0001ee7c'), ('\U0001ee7e', '\U0001ee7e'), + ('\U0001ee80', '\U0001ee89'), ('\U0001ee8b', '\U0001ee9b'), + ('\U0001eea1', '\U0001eea3'), ('\U0001eea5', '\U0001eea9'), + ('\U0001eeab', '\U0001eebb'), ('\U00020000', '\U0002a6d6'), + ('\U0002a700', '\U0002b734'), ('\U0002b740', '\U0002b81d'), + ('\U0002f800', '\U0002fa1d') + ]; + + pub fn XID_Start(c: char) -> bool { + bsearch_range_table(c, XID_Start_table) } } diff --git a/src/libcore/unstable/at_exit.rs b/src/libstd/unstable/at_exit.rs similarity index 97% rename from src/libcore/unstable/at_exit.rs rename to src/libstd/unstable/at_exit.rs index 39c930d415f1c..d214b509dfbf9 100644 --- a/src/libcore/unstable/at_exit.rs +++ b/src/libstd/unstable/at_exit.rs @@ -83,7 +83,7 @@ fn test_at_exit() { let i = 10; do at_exit { debug!("at_exit1"); - assert!(i == 10); + assert_eq!(i, 10); } } @@ -93,7 +93,7 @@ fn test_at_exit_many() { for uint::range(20, 100) |j| { do at_exit { debug!("at_exit2"); - assert!(i == 10); + assert_eq!(i, 10); assert!(j > i); } } diff --git a/src/libstd/unstable/atomics.rs b/src/libstd/unstable/atomics.rs new file mode 100644 index 0000000000000..58d0c01f990d0 --- /dev/null +++ b/src/libstd/unstable/atomics.rs @@ -0,0 +1,393 @@ +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/*! + * Atomic types + * + * Basic atomic types supporting atomic operations. Each method takes an `Ordering` which + * represents the strength of the memory barrier for that operation. These orderings are the same + * as C++11 atomic orderings [http://gcc.gnu.org/wiki/Atomic/GCCMM/AtomicSync] + * + * All atomic types are a single word in size. + */ + +use unstable::intrinsics; +use cast; +use option::{Option,Some,None}; +use libc::c_void; +use ops::Drop; + +/** + * A simple atomic flag, that can be set and cleared. The most basic atomic type. + */ +pub struct AtomicFlag { + priv v: int +} + +/** + * An atomic boolean type. + */ +pub struct AtomicBool { + priv v: uint +} + +/** + * A signed atomic integer type, supporting basic atomic aritmetic operations + */ +pub struct AtomicInt { + priv v: int +} + +/** + * An unsigned atomic integer type, supporting basic atomic aritmetic operations + */ +pub struct AtomicUint { + priv v: uint +} + +/** + * An unsafe atomic pointer. Only supports basic atomic operations + */ +pub struct AtomicPtr { + priv p: *mut T +} + +/** + * An owned atomic pointer. Ensures that only a single reference to the data is held at any time. + */ +pub struct AtomicOption { + priv p: *mut c_void +} + +pub enum Ordering { + Release, + Acquire, + SeqCst +} + + +impl AtomicFlag { + + pub fn new() -> AtomicFlag { + AtomicFlag { v: 0 } + } + + /** + * Clears the atomic flag + */ + #[inline(always)] + pub fn clear(&mut self, order: Ordering) { + unsafe {atomic_store(&mut self.v, 0, order)} + } + + /** + * Sets the flag if it was previously unset, returns the previous value of the + * flag. + */ + #[inline(always)] + pub fn test_and_set(&mut self, order: Ordering) -> bool { + unsafe {atomic_compare_and_swap(&mut self.v, 0, 1, order) > 0} + } +} + +impl AtomicBool { + pub fn new(v: bool) -> AtomicBool { + AtomicBool { v: if v { 1 } else { 0 } } + } + + #[inline(always)] + pub fn load(&self, order: Ordering) -> bool { + unsafe { atomic_load(&self.v, order) > 0 } + } + + #[inline(always)] + pub fn store(&mut self, val: bool, order: Ordering) { + let val = if val { 1 } else { 0 }; + + unsafe { atomic_store(&mut self.v, val, order); } + } + + #[inline(always)] + pub fn swap(&mut self, val: bool, order: Ordering) -> bool { + let val = if val { 1 } else { 0 }; + + unsafe { atomic_swap(&mut self.v, val, order) > 0} + } + + #[inline(always)] + pub fn compare_and_swap(&mut self, old: bool, new: bool, order: Ordering) -> bool { + let old = if old { 1 } else { 0 }; + let new = if new { 1 } else { 0 }; + + unsafe { atomic_compare_and_swap(&mut self.v, old, new, order) > 0 } + } +} + +impl AtomicInt { + pub fn new(v: int) -> AtomicInt { + AtomicInt { v:v } + } + + #[inline(always)] + pub fn load(&self, order: Ordering) -> int { + unsafe { atomic_load(&self.v, order) } + } + + #[inline(always)] + pub fn store(&mut self, val: int, order: Ordering) { + unsafe { atomic_store(&mut self.v, val, order); } + } + + #[inline(always)] + pub fn swap(&mut self, val: int, order: Ordering) -> int { + unsafe { atomic_swap(&mut self.v, val, order) } + } + + #[inline(always)] + pub fn compare_and_swap(&mut self, old: int, new: int, order: Ordering) -> int { + unsafe { atomic_compare_and_swap(&mut self.v, old, new, order) } + } + + #[inline(always)] + pub fn fetch_add(&mut self, val: int, order: Ordering) -> int { + unsafe { atomic_add(&mut self.v, val, order) } + } + + #[inline(always)] + pub fn fetch_sub(&mut self, val: int, order: Ordering) -> int { + unsafe { atomic_sub(&mut self.v, val, order) } + } +} + +impl AtomicUint { + pub fn new(v: uint) -> AtomicUint { + AtomicUint { v:v } + } + + #[inline(always)] + pub fn load(&self, order: Ordering) -> uint { + unsafe { atomic_load(&self.v, order) } + } + + #[inline(always)] + pub fn store(&mut self, val: uint, order: Ordering) { + unsafe { atomic_store(&mut self.v, val, order); } + } + + #[inline(always)] + pub fn swap(&mut self, val: uint, order: Ordering) -> uint { + unsafe { atomic_swap(&mut self.v, val, order) } + } + + #[inline(always)] + pub fn compare_and_swap(&mut self, old: uint, new: uint, order: Ordering) -> uint { + unsafe { atomic_compare_and_swap(&mut self.v, old, new, order) } + } + + #[inline(always)] + pub fn fetch_add(&mut self, val: uint, order: Ordering) -> uint { + unsafe { atomic_add(&mut self.v, val, order) } + } + + #[inline(always)] + pub fn fetch_sub(&mut self, val: uint, order: Ordering) -> uint { + unsafe { atomic_sub(&mut self.v, val, order) } + } +} + +impl AtomicPtr { + pub fn new(p: *mut T) -> AtomicPtr { + AtomicPtr { p:p } + } + + #[inline(always)] + pub fn load(&self, order: Ordering) -> *mut T { + unsafe { atomic_load(&self.p, order) } + } + + #[inline(always)] + pub fn store(&mut self, ptr: *mut T, order: Ordering) { + unsafe { atomic_store(&mut self.p, ptr, order); } + } + + #[inline(always)] + pub fn swap(&mut self, ptr: *mut T, order: Ordering) -> *mut T { + unsafe { atomic_swap(&mut self.p, ptr, order) } + } + + #[inline(always)] + pub fn compare_and_swap(&mut self, old: *mut T, new: *mut T, order: Ordering) -> *mut T { + unsafe { atomic_compare_and_swap(&mut self.p, old, new, order) } + } +} + +impl AtomicOption { + pub fn new(p: ~T) -> AtomicOption { + unsafe { + AtomicOption { + p: cast::transmute(p) + } + } + } + + pub fn empty() -> AtomicOption { + unsafe { + AtomicOption { + p: cast::transmute(0) + } + } + } + + #[inline(always)] + pub fn swap(&mut self, val: ~T, order: Ordering) -> Option<~T> { + unsafe { + let val = cast::transmute(val); + + let p = atomic_swap(&mut self.p, val, order); + let pv : &uint = cast::transmute(&p); + + if *pv == 0 { + None + } else { + Some(cast::transmute(p)) + } + } + } + + #[inline(always)] + pub fn take(&mut self, order: Ordering) -> Option<~T> { + unsafe { + self.swap(cast::transmute(0), order) + } + } +} + +#[unsafe_destructor] +impl Drop for AtomicOption { + fn finalize(&self) { + // This will ensure that the contained data is + // destroyed, unless it's null. + unsafe { + let this : &mut AtomicOption = cast::transmute(self); + let _ = this.take(SeqCst); + } + } +} + +#[inline(always)] +pub unsafe fn atomic_store(dst: &mut T, val: T, order:Ordering) { + let dst = cast::transmute(dst); + let val = cast::transmute(val); + + match order { + Release => intrinsics::atomic_store_rel(dst, val), + _ => intrinsics::atomic_store(dst, val) + } +} + +#[inline(always)] +pub unsafe fn atomic_load(dst: &T, order:Ordering) -> T { + let dst = cast::transmute(dst); + + cast::transmute(match order { + Acquire => intrinsics::atomic_load_acq(dst), + _ => intrinsics::atomic_load(dst) + }) +} + +#[inline(always)] +pub unsafe fn atomic_swap(dst: &mut T, val: T, order: Ordering) -> T { + let dst = cast::transmute(dst); + let val = cast::transmute(val); + + cast::transmute(match order { + Acquire => intrinsics::atomic_xchg_acq(dst, val), + Release => intrinsics::atomic_xchg_rel(dst, val), + _ => intrinsics::atomic_xchg(dst, val) + }) +} + +#[inline(always)] +pub unsafe fn atomic_add(dst: &mut T, val: T, order: Ordering) -> T { + let dst = cast::transmute(dst); + let val = cast::transmute(val); + + cast::transmute(match order { + Acquire => intrinsics::atomic_xadd_acq(dst, val), + Release => intrinsics::atomic_xadd_rel(dst, val), + _ => intrinsics::atomic_xadd(dst, val) + }) +} + +#[inline(always)] +pub unsafe fn atomic_sub(dst: &mut T, val: T, order: Ordering) -> T { + let dst = cast::transmute(dst); + let val = cast::transmute(val); + + cast::transmute(match order { + Acquire => intrinsics::atomic_xsub_acq(dst, val), + Release => intrinsics::atomic_xsub_rel(dst, val), + _ => intrinsics::atomic_xsub(dst, val) + }) +} + +#[inline(always)] +pub unsafe fn atomic_compare_and_swap(dst:&mut T, old:T, new:T, order: Ordering) -> T { + let dst = cast::transmute(dst); + let old = cast::transmute(old); + let new = cast::transmute(new); + + cast::transmute(match order { + Acquire => intrinsics::atomic_cxchg_acq(dst, old, new), + Release => intrinsics::atomic_cxchg_rel(dst, old, new), + _ => intrinsics::atomic_cxchg(dst, old, new), + }) +} + +#[cfg(test)] +mod test { + use option::*; + use super::*; + + #[test] + fn flag() { + let mut flg = AtomicFlag::new(); + assert!(!flg.test_and_set(SeqCst)); + assert!(flg.test_and_set(SeqCst)); + + flg.clear(SeqCst); + assert!(!flg.test_and_set(SeqCst)); + } + + #[test] + fn option_swap() { + let mut p = AtomicOption::new(~1); + let a = ~2; + + let b = p.swap(a, SeqCst); + + assert_eq!(b, Some(~1)); + assert_eq!(p.take(SeqCst), Some(~2)); + } + + #[test] + fn option_take() { + let mut p = AtomicOption::new(~1); + + assert_eq!(p.take(SeqCst), Some(~1)); + assert_eq!(p.take(SeqCst), None); + + let p2 = ~2; + p.swap(p2, SeqCst); + + assert_eq!(p.take(SeqCst), Some(~2)); + } + +} diff --git a/src/libcore/unstable/exchange_alloc.rs b/src/libstd/unstable/exchange_alloc.rs similarity index 100% rename from src/libcore/unstable/exchange_alloc.rs rename to src/libstd/unstable/exchange_alloc.rs diff --git a/src/libcore/unstable/extfmt.rs b/src/libstd/unstable/extfmt.rs similarity index 97% rename from src/libcore/unstable/extfmt.rs rename to src/libstd/unstable/extfmt.rs index 11ac8c14fe46d..07bcf6d953c3a 100644 --- a/src/libcore/unstable/extfmt.rs +++ b/src/libstd/unstable/extfmt.rs @@ -139,8 +139,8 @@ pub mod ct { next: uint } - pub impl Parsed { - fn new(val: T, next: uint) -> Parsed { + impl Parsed { + pub fn new(val: T, next: uint) -> Parsed { Parsed {val: val, next: next} } } @@ -178,7 +178,7 @@ pub mod ct { i += 1; if i >= lim { - err(~"unterminated conversion at end of string"); + err("unterminated conversion at end of string"); } else if s[i] == '%' as u8 { push_slice(&mut pieces, s, h, i); i += 1; @@ -309,7 +309,7 @@ pub mod ct { pub fn parse_type(s: &str, i: uint, lim: uint, err: ErrorFn) -> Parsed { - if i >= lim { err(~"missing type in conversion"); } + if i >= lim { err("missing type in conversion"); } // FIXME (#2249): Do we really want two signed types here? // How important is it to be printf compatible? @@ -355,8 +355,8 @@ pub mod ct { fn test(s: &str, flags: &[Flag], next: uint) { let f = parse_flags(s, 0, s.len()); - assert!(pack(f.val) == pack(flags)); - assert!(f.next == next); + assert_eq!(pack(f.val), pack(flags)); + assert_eq!(f.next, next); } test("", [], 0); @@ -459,10 +459,10 @@ pub mod ct { assert!(peek_num(s2, 0, s2.len()).is_none()); let s3 = "123"; - assert!(peek_num(s3, 0, s3.len()) == Some(Parsed::new(123, 3))); + assert_eq!(peek_num(s3, 0, s3.len()), Some(Parsed::new(123, 3))); let s4 = "123foo"; - assert!(peek_num(s4, 0, s4.len()) == Some(Parsed::new(123, 3))); + assert_eq!(peek_num(s4, 0, s4.len()), Some(Parsed::new(123, 3))); } } diff --git a/src/libcore/unstable/finally.rs b/src/libstd/unstable/finally.rs similarity index 93% rename from src/libcore/unstable/finally.rs rename to src/libstd/unstable/finally.rs index 559287b529772..5001fb421cd86 100644 --- a/src/libcore/unstable/finally.rs +++ b/src/libstd/unstable/finally.rs @@ -79,10 +79,10 @@ fn test_success() { i = 10; }).finally { assert!(!failing()); - assert!(i == 10); + assert_eq!(i, 10); i = 20; } - assert!(i == 20); + assert_eq!(i, 20); } #[test] @@ -95,7 +95,7 @@ fn test_fail() { fail!(); }).finally { assert!(failing()); - assert!(i == 10); + assert_eq!(i, 10); } } @@ -103,7 +103,7 @@ fn test_fail() { fn test_retval() { let closure: &fn() -> int = || 10; let i = do closure.finally { }; - assert!(i == 10); + assert_eq!(i, 10); } #[test] @@ -134,6 +134,6 @@ fn test_managed() { *i += 10; r }; - assert!(do managed.finally {} == 10); - assert!(*i == 20); + assert_eq!(do managed.finally {}, 10); + assert_eq!(*i, 20); } \ No newline at end of file diff --git a/src/libcore/unstable/global.rs b/src/libstd/unstable/global.rs similarity index 99% rename from src/libcore/unstable/global.rs rename to src/libstd/unstable/global.rs index 88433f9cefe51..96549a83a8cf3 100644 --- a/src/libcore/unstable/global.rs +++ b/src/libstd/unstable/global.rs @@ -200,7 +200,7 @@ fn get_global_state() -> Exclusive { let prev_i = unsafe { atomic_cxchg(&mut *global_ptr, state_i, POISON) }; - assert!(prev_i == state_i); + assert_eq!(prev_i, state_i); // Capture the global state object in the at_exit closure // so that it is destroyed at the right time diff --git a/src/libcore/unstable/intrinsics.rs b/src/libstd/unstable/intrinsics.rs similarity index 82% rename from src/libcore/unstable/intrinsics.rs rename to src/libstd/unstable/intrinsics.rs index 1636abedf7a7d..908c5e23ab070 100644 --- a/src/libcore/unstable/intrinsics.rs +++ b/src/libstd/unstable/intrinsics.rs @@ -16,7 +16,7 @@ The corresponding definitions are in librustc/middle/trans/foreign.rs. The atomic intrinsics provide common atomic operations on machine words, with multiple possible memory orderings. They obey the same -semantics as C++0x. See the LLVM documentation on [[atomics]]. +semantics as C++11. See the LLVM documentation on [[atomics]]. [atomics]: http://llvm.org/docs/Atomics.html @@ -43,17 +43,13 @@ pub extern "rust-intrinsic" { pub fn atomic_cxchg_rel(dst: &mut int, old: int, src: int) -> int; /// Atomic load, sequentially consistent. - #[cfg(not(stage0))] pub fn atomic_load(src: &int) -> int; /// Atomic load, acquire ordering. - #[cfg(not(stage0))] pub fn atomic_load_acq(src: &int) -> int; /// Atomic store, sequentially consistent. - #[cfg(not(stage0))] pub fn atomic_store(dst: &mut int, val: int); /// Atomic store, release ordering. - #[cfg(not(stage0))] pub fn atomic_store_rel(dst: &mut int, val: int); /// Atomic exchange, sequentially consistent. @@ -111,7 +107,6 @@ pub extern "rust-intrinsic" { pub unsafe fn init() -> T; /// Create an uninitialized value. - #[cfg(not(stage0))] pub unsafe fn uninit() -> T; /// Move a value out of scope without running drop glue. @@ -119,6 +114,7 @@ pub extern "rust-intrinsic" { /// `forget` is unsafe because the caller is responsible for /// ensuring the argument is deallocated already. pub unsafe fn forget(_: T) -> (); + pub fn transmute(e: T) -> U; /// Returns `true` if a type requires drop glue. pub fn needs_drop() -> bool; @@ -126,17 +122,46 @@ pub extern "rust-intrinsic" { // XXX: intrinsic uses legacy modes and has reference to TyDesc // and TyVisitor which are in librustc //fn visit_tydesc(++td: *TyDesc, &&tv: TyVisitor) -> (); - // XXX: intrinsic uses legacy modes - //fn frame_address(f: &once fn(*u8)); + + pub fn frame_address(f: &once fn(*u8)); /// Get the address of the `__morestack` stack growth function. pub fn morestack_addr() -> *(); + /// Equivalent to the `llvm.memcpy.p0i8.0i8.i32` intrinsic, with a size of + /// `count` * `size_of::()` and an alignment of `min_align_of::()` + #[cfg(not(stage0))] + pub fn memcpy32(dst: *mut T, src: *T, count: u32); + /// Equivalent to the `llvm.memcpy.p0i8.0i8.i64` intrinsic, with a size of + /// `count` * `size_of::()` and an alignment of `min_align_of::()` + #[cfg(not(stage0))] + pub fn memcpy64(dst: *mut T, src: *T, count: u64); + /// Equivalent to the `llvm.memmove.p0i8.0i8.i32` intrinsic. + #[cfg(stage0)] pub fn memmove32(dst: *mut u8, src: *u8, size: u32); /// Equivalent to the `llvm.memmove.p0i8.0i8.i64` intrinsic. + #[cfg(stage0)] pub fn memmove64(dst: *mut u8, src: *u8, size: u64); + /// Equivalent to the `llvm.memmove.p0i8.0i8.i32` intrinsic, with a size of + /// `count` * `size_of::()` and an alignment of `min_align_of::()` + #[cfg(not(stage0))] + pub fn memmove32(dst: *mut T, src: *T, count: u32); + /// Equivalent to the `llvm.memmove.p0i8.0i8.i64` intrinsic, with a size of + /// `count` * `size_of::()` and an alignment of `min_align_of::()` + #[cfg(not(stage0))] + pub fn memmove64(dst: *mut T, src: *T, count: u64); + + /// Equivalent to the `llvm.memset.p0i8.i32` intrinsic, with a size of + /// `count` * `size_of::()` and an alignment of `min_align_of::()` + #[cfg(not(stage0))] + pub fn memset32(dst: *mut T, val: u8, count: u32); + /// Equivalent to the `llvm.memset.p0i8.i64` intrinsic, with a size of + /// `count` * `size_of::()` and an alignment of `min_align_of::()` + #[cfg(not(stage0))] + pub fn memset64(dst: *mut T, val: u8, count: u64); + pub fn sqrtf32(x: f32) -> f32; pub fn sqrtf64(x: f64) -> f64; diff --git a/src/libcore/unstable/lang.rs b/src/libstd/unstable/lang.rs similarity index 88% rename from src/libcore/unstable/lang.rs rename to src/libstd/unstable/lang.rs index 8153c2d43d998..350b18d454169 100644 --- a/src/libcore/unstable/lang.rs +++ b/src/libstd/unstable/lang.rs @@ -16,12 +16,12 @@ use libc::{c_char, c_uchar, c_void, size_t, uintptr_t, c_int, STDERR_FILENO}; use managed::raw::BoxRepr; use str; use sys; -use unstable::exchange_alloc; -use cast::transmute; use rt::{context, OldTaskContext}; -use rt::local_services::borrow_local_services; +use rt::task::Task; +use rt::local::Local; use option::{Option, Some, None}; use io; +use rt::global_heap; #[allow(non_camel_case_types)] pub type rust_task = c_void; @@ -153,7 +153,7 @@ unsafe fn fail_borrowed(box: *mut BoxRepr, file: *c_char, line: size_t) { #[lang="exchange_malloc"] #[inline(always)] pub unsafe fn exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char { - transmute(exchange_alloc::malloc(transmute(td), transmute(size))) + transmute(global_heap::malloc(transmute(td), transmute(size))) } /// Because this code is so perf. sensitive, use a static constant so that @@ -233,7 +233,7 @@ impl DebugPrints for io::fd_t { #[lang="exchange_free"] #[inline(always)] pub unsafe fn exchange_free(ptr: *c_char) { - exchange_alloc::free(transmute(ptr)) + global_heap::free(transmute(ptr)) } #[lang="malloc"] @@ -244,8 +244,8 @@ pub unsafe fn local_malloc(td: *c_char, size: uintptr_t) -> *c_char { } _ => { let mut alloc = ::ptr::null(); - do borrow_local_services |srv| { - alloc = srv.heap.alloc(td as *c_void, size as uint) as *c_char; + do Local::borrow:: |task| { + alloc = task.heap.alloc(td as *c_void, size as uint) as *c_char; } return alloc; } @@ -262,22 +262,13 @@ pub unsafe fn local_free(ptr: *c_char) { rustrt::rust_upcall_free_noswitch(ptr); } _ => { - do borrow_local_services |srv| { - srv.heap.free(ptr as *c_void); + do Local::borrow:: |task| { + task.heap.free(ptr as *c_void); } } } } -#[cfg(stage0)] -#[lang="borrow_as_imm"] -#[inline(always)] -pub unsafe fn borrow_as_imm(a: *u8) { - let a: *mut BoxRepr = transmute(a); - (*a).header.ref_count |= FROZEN_BIT; -} - -#[cfg(not(stage0))] #[lang="borrow_as_imm"] #[inline(always)] pub unsafe fn borrow_as_imm(a: *u8, file: *c_char, line: size_t) -> uint { @@ -296,7 +287,6 @@ pub unsafe fn borrow_as_imm(a: *u8, file: *c_char, line: size_t) -> uint { old_ref_count } -#[cfg(not(stage0))] #[lang="borrow_as_mut"] #[inline(always)] pub unsafe fn borrow_as_mut(a: *u8, file: *c_char, line: size_t) -> uint { @@ -316,7 +306,6 @@ pub unsafe fn borrow_as_mut(a: *u8, file: *c_char, line: size_t) -> uint { } -#[cfg(not(stage0))] #[lang="record_borrow"] pub unsafe fn record_borrow(a: *u8, old_ref_count: uint, file: *c_char, line: size_t) { @@ -332,7 +321,6 @@ pub unsafe fn record_borrow(a: *u8, old_ref_count: uint, } } -#[cfg(not(stage0))] #[lang="unrecord_borrow"] pub unsafe fn unrecord_borrow(a: *u8, old_ref_count: uint, file: *c_char, line: size_t) { @@ -356,19 +344,6 @@ pub unsafe fn unrecord_borrow(a: *u8, old_ref_count: uint, } } -#[cfg(stage0)] -#[lang="return_to_mut"] -#[inline(always)] -pub unsafe fn return_to_mut(a: *u8) { - // Sometimes the box is null, if it is conditionally frozen. - // See e.g. #4904. - if !a.is_null() { - let a: *mut BoxRepr = transmute(a); - (*a).header.ref_count &= !FROZEN_BIT; - } -} - -#[cfg(not(stage0))] #[lang="return_to_mut"] #[inline(always)] pub unsafe fn return_to_mut(a: *u8, orig_ref_count: uint, @@ -388,19 +363,6 @@ pub unsafe fn return_to_mut(a: *u8, orig_ref_count: uint, } } -#[cfg(stage0)] -#[lang="check_not_borrowed"] -#[inline(always)] -pub unsafe fn check_not_borrowed(a: *u8) { - let a: *mut BoxRepr = transmute(a); - if ((*a).header.ref_count & FROZEN_BIT) != 0 { - do str::as_buf("XXX") |file_p, _| { - fail_borrowed(a, file_p as *c_char, 0); - } - } -} - -#[cfg(not(stage0))] #[lang="check_not_borrowed"] #[inline(always)] pub unsafe fn check_not_borrowed(a: *u8, @@ -423,18 +385,31 @@ pub unsafe fn strdup_uniq(ptr: *c_uchar, len: uint) -> ~str { #[lang="start"] pub fn start(main: *u8, argc: int, argv: **c_char, crate_map: *u8) -> int { - use libc::getenv; - use rt::start; + use rt; + use sys::Closure; + use ptr; + use cast; + use os; unsafe { - let use_old_rt = do str::as_c_str("RUST_NEWRT") |s| { - getenv(s).is_null() - }; + let use_old_rt = os::getenv("RUST_NEWRT").is_none(); if use_old_rt { return rust_start(main as *c_void, argc as c_int, argv, crate_map as *c_void) as int; } else { - return start(main, argc, argv, crate_map); + return do rt::start(argc, argv as **u8, crate_map) { + unsafe { + // `main` is an `fn() -> ()` that doesn't take an environment + // XXX: Could also call this as an `extern "Rust" fn` once they work + let main = Closure { + code: main as *(), + env: ptr::null(), + }; + let mainfn: &fn() = cast::transmute(main); + + mainfn(); + } + }; } } diff --git a/src/libcore/unstable/mod.rs b/src/libstd/unstable/mod.rs similarity index 93% rename from src/libcore/unstable/mod.rs rename to src/libstd/unstable/mod.rs index bef7a7f87d3bd..1e226da271d48 100644 --- a/src/libcore/unstable/mod.rs +++ b/src/libstd/unstable/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -10,8 +10,9 @@ #[doc(hidden)]; -use libc; use comm::{GenericChan, GenericPort}; +use comm; +use libc; use prelude::*; use task; @@ -19,13 +20,13 @@ pub mod at_exit; pub mod global; pub mod finally; pub mod weak_task; -pub mod exchange_alloc; pub mod intrinsics; pub mod simd; pub mod extfmt; #[cfg(not(test))] pub mod lang; pub mod sync; +pub mod atomics; /** @@ -56,7 +57,7 @@ pub fn run_in_bare_thread(f: ~fn()) { fn test_run_in_bare_thread() { let i = 100; do run_in_bare_thread { - assert!(i == 100); + assert_eq!(i, 100); } } diff --git a/src/libcore/unstable/simd.rs b/src/libstd/unstable/simd.rs similarity index 100% rename from src/libcore/unstable/simd.rs rename to src/libstd/unstable/simd.rs diff --git a/src/libcore/unstable/sync.rs b/src/libstd/unstable/sync.rs similarity index 74% rename from src/libcore/unstable/sync.rs rename to src/libstd/unstable/sync.rs index 4d5c3bf7a78a4..f0b178c667013 100644 --- a/src/libcore/unstable/sync.rs +++ b/src/libstd/unstable/sync.rs @@ -41,18 +41,6 @@ impl UnsafeAtomicRcBox { } #[inline(always)] - #[cfg(stage0)] - pub unsafe fn get(&self) -> *mut T - { - let mut data: ~AtomicRcBoxData = cast::transmute(self.data); - assert!(data.count > 0); - let r: *mut T = cast::transmute(data.data.get_mut_ref()); - cast::forget(data); - return r; - } - - #[inline(always)] - #[cfg(not(stage0))] pub unsafe fn get(&self) -> *mut T { let mut data: ~AtomicRcBoxData = cast::transmute(self.data); @@ -63,18 +51,6 @@ impl UnsafeAtomicRcBox { } #[inline(always)] - #[cfg(stage0)] - pub unsafe fn get_immut(&self) -> *T - { - let mut data: ~AtomicRcBoxData = cast::transmute(self.data); - assert!(data.count > 0); - let r: *T = cast::transmute(data.data.get_mut_ref()); - cast::forget(data); - return r; - } - - #[inline(always)] - #[cfg(not(stage0))] pub unsafe fn get_immut(&self) -> *T { let mut data: ~AtomicRcBoxData = cast::transmute(self.data); @@ -141,9 +117,9 @@ fn LittleLock() -> LittleLock { } } -pub impl LittleLock { +impl LittleLock { #[inline(always)] - unsafe fn lock(&self, f: &fn() -> T) -> T { + pub unsafe fn lock(&self, f: &fn() -> T) -> T { do atomically { rust_lock_little_lock(self.l); do (|| { @@ -186,7 +162,7 @@ impl Clone for Exclusive { } } -pub impl Exclusive { +impl Exclusive { // Exactly like std::arc::mutex_arc,access(), but with the little_lock // instead of a proper mutex. Same reason for being unsafe. // @@ -194,7 +170,7 @@ pub impl Exclusive { // accessing the provided condition variable) are prohibited while inside // the exclusive. Supporting that is a work in progress. #[inline(always)] - unsafe fn with(&self, f: &fn(x: &mut T) -> U) -> U { + pub unsafe fn with(&self, f: &fn(x: &mut T) -> U) -> U { let rec = self.x.get(); do (*rec).lock.lock { if (*rec).failed { @@ -208,7 +184,7 @@ pub impl Exclusive { } #[inline(always)] - unsafe fn with_imm(&self, f: &fn(x: &T) -> U) -> U { + pub unsafe fn with_imm(&self, f: &fn(x: &T) -> U) -> U { do self.with |x| { f(cast::transmute_immut(x)) } @@ -238,48 +214,52 @@ mod tests { #[test] fn exclusive_arc() { - let mut futures = ~[]; + unsafe { + let mut futures = ~[]; - let num_tasks = 10; - let count = 10; + let num_tasks = 10; + let count = 10; - let total = exclusive(~0); + let total = exclusive(~0); - for uint::range(0, num_tasks) |_i| { - let total = total.clone(); - let (port, chan) = comm::stream(); - futures.push(port); + for uint::range(0, num_tasks) |_i| { + let total = total.clone(); + let (port, chan) = comm::stream(); + futures.push(port); - do task::spawn || { - for uint::range(0, count) |_i| { - do total.with |count| { - **count += 1; + do task::spawn || { + for uint::range(0, count) |_i| { + do total.with |count| { + **count += 1; + } } + chan.send(()); } - chan.send(()); - } - }; + }; - for futures.each |f| { f.recv() } + for futures.each |f| { f.recv() } - do total.with |total| { - assert!(**total == num_tasks * count) - }; + do total.with |total| { + assert!(**total == num_tasks * count) + }; + } } #[test] #[should_fail] #[ignore(cfg(windows))] fn exclusive_poison() { - // Tests that if one task fails inside of an exclusive, subsequent - // accesses will also fail. - let x = exclusive(1); - let x2 = x.clone(); - do task::try || { - do x2.with |one| { - assert!(*one == 2); + unsafe { + // Tests that if one task fails inside of an exclusive, subsequent + // accesses will also fail. + let x = exclusive(1); + let x2 = x.clone(); + do task::try || { + do x2.with |one| { + assert_eq!(*one, 2); + } + }; + do x.with |one| { + assert_eq!(*one, 1); } - }; - do x.with |one| { - assert!(*one == 1); } } } diff --git a/src/libcore/unstable/weak_task.rs b/src/libstd/unstable/weak_task.rs similarity index 97% rename from src/libcore/unstable/weak_task.rs rename to src/libstd/unstable/weak_task.rs index d5c5230cef819..7819fe0059755 100644 --- a/src/libcore/unstable/weak_task.rs +++ b/src/libstd/unstable/weak_task.rs @@ -39,7 +39,7 @@ pub unsafe fn weaken_task(f: &fn(Port)) { let service = global_data_clone_create(global_data_key, create_global_service); let (shutdown_port, shutdown_chan) = stream::(); - let shutdown_port = Cell(shutdown_port); + let shutdown_port = Cell::new(shutdown_port); let task = get_task_id(); // Expect the weak task service to be alive assert!(service.try_send(RegisterWeakTask(task, shutdown_chan))); @@ -68,7 +68,7 @@ fn create_global_service() -> ~WeakTaskService { debug!("creating global weak task service"); let (port, chan) = stream::(); - let port = Cell(port); + let port = Cell::new(port); let chan = SharedChan::new(chan); let chan_clone = chan.clone(); @@ -76,7 +76,7 @@ fn create_global_service() -> ~WeakTaskService { task.unlinked(); do task.spawn { debug!("running global weak task service"); - let port = Cell(port.take()); + let port = Cell::new(port.take()); do (|| { let port = port.take(); // The weak task service is itself a weak task @@ -192,7 +192,7 @@ fn test_select_stream_and_oneshot() { use either::{Left, Right}; let (port, chan) = stream(); - let port = Cell(port); + let port = Cell::new(port); let (waitport, waitchan) = stream(); do spawn { unsafe { diff --git a/src/libcore/util.rs b/src/libstd/util.rs similarity index 65% rename from src/libcore/util.rs rename to src/libstd/util.rs index e5067fb90bcc0..376ead608bc06 100644 --- a/src/libcore/util.rs +++ b/src/libstd/util.rs @@ -8,12 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - -Miscellaneous helpers for common patterns. - -*/ +//! Miscellaneous helpers for common patterns. +use cast; +use ptr; use prelude::*; use unstable::intrinsics; @@ -51,56 +49,21 @@ pub fn with( #[inline(always)] pub fn swap(x: &mut T, y: &mut T) { unsafe { - swap_ptr(ptr::to_mut_unsafe_ptr(x), ptr::to_mut_unsafe_ptr(y)); + // Give ourselves some scratch space to work with + let mut tmp: T = intrinsics::uninit(); + let t: *mut T = &mut tmp; + + // Perform the swap, `&mut` pointers never alias + ptr::copy_nonoverlapping_memory(t, x, 1); + ptr::copy_nonoverlapping_memory(x, y, 1); + ptr::copy_nonoverlapping_memory(y, t, 1); + + // y and t now point to the same thing, but we need to completely forget `tmp` + // because it's no longer relevant. + cast::forget(tmp); } } -/** - * Swap the values at two mutable locations of the same type, without - * deinitialising or copying either one. - */ -#[inline] -#[cfg(not(stage0))] -pub unsafe fn swap_ptr(x: *mut T, y: *mut T) { - if x == y { return } - - // Give ourselves some scratch space to work with - let mut tmp: T = intrinsics::uninit(); - let t = ptr::to_mut_unsafe_ptr(&mut tmp); - - // Perform the swap - ptr::copy_memory(t, x, 1); - ptr::copy_memory(x, y, 1); - ptr::copy_memory(y, t, 1); - - // y and t now point to the same thing, but we need to completely forget t - // because it's no longer relevant. - cast::forget(tmp); -} - -/** - * Swap the values at two mutable locations of the same type, without - * deinitialising or copying either one. - */ -#[inline] -#[cfg(stage0)] -pub unsafe fn swap_ptr(x: *mut T, y: *mut T) { - if x == y { return } - - // Give ourselves some scratch space to work with - let mut tmp: T = intrinsics::init(); - let t = ptr::to_mut_unsafe_ptr(&mut tmp); - - // Perform the swap - ptr::copy_memory(t, x, 1); - ptr::copy_memory(x, y, 1); - ptr::copy_memory(y, t, 1); - - // y and t now point to the same thing, but we need to completely forget t - // because it's no longer relevant. - cast::forget(tmp); -} - /** * Replace the value at a mutable location with a new one, returning the old * value, without deinitialising or copying either one. @@ -111,34 +74,27 @@ pub fn replace(dest: &mut T, mut src: T) -> T { src } -/** - * Replace the value at a mutable location with a new one, returning the old - * value, without deinitialising or copying either one. - */ -#[inline(always)] -pub unsafe fn replace_ptr(dest: *mut T, mut src: T) -> T { - swap_ptr(dest, ptr::to_mut_unsafe_ptr(&mut src)); - src -} - /// A non-copyable dummy type. pub struct NonCopyable { - i: (), + priv i: (), +} + +impl NonCopyable { + /// Creates a dummy non-copyable structure and returns it for use. + pub fn new() -> NonCopyable { NonCopyable { i: () } } } impl Drop for NonCopyable { fn finalize(&self) { } } -pub fn NonCopyable() -> NonCopyable { NonCopyable { i: () } } - /// A type with no inhabitants pub enum Void { } -pub impl Void { +impl Void { /// A utility function for ignoring this uninhabited type - fn uninhabited(self) -> ! { + pub fn uninhabited(self) -> ! { match self { // Nothing to match on } @@ -153,7 +109,7 @@ terminate normally, but instead directly return from a function. # Example -~~~ +~~~ {.rust} fn choose_weighted_item(v: &[Item]) -> Item { assert!(!v.is_empty()); let mut so_far = 0u; @@ -193,12 +149,12 @@ mod tests { let mut x = 31337; let mut y = 42; swap(&mut x, &mut y); - assert!(x == 42); - assert!(y == 31337); + assert_eq!(x, 42); + assert_eq!(y, 31337); } #[test] pub fn test_replace() { - let mut x = Some(NonCopyable()); + let mut x = Some(NonCopyable::new()); let y = replace(&mut x, None); assert!(x.is_none()); assert!(y.is_some()); diff --git a/src/libcore/vec.rs b/src/libstd/vec.rs similarity index 81% rename from src/libcore/vec.rs rename to src/libstd/vec.rs index 4c6e0791ba2ca..f078cd3bda350 100644 --- a/src/libcore/vec.rs +++ b/src/libstd/vec.rs @@ -22,11 +22,11 @@ use old_iter; use iterator::Iterator; use kinds::Copy; use libc; -use old_iter::{BaseIter, CopyableIter}; +use old_iter::CopyableIter; use option::{None, Option, Some}; use ptr::to_unsafe_ptr; use ptr; -use ptr::Ptr; +use ptr::RawPtr; use sys; use uint; use unstable::intrinsics; @@ -129,6 +129,7 @@ pub fn len(v: &const [T]) -> uint { } // A botch to tide us over until core and std are fully demuted. +#[allow(missing_doc)] pub fn uniq_len(v: &const ~[T]) -> uint { unsafe { let v: &~[T] = transmute(v); @@ -148,8 +149,7 @@ pub fn from_fn(n_elts: uint, op: old_iter::InitOp) -> ~[T] { do as_mut_buf(v) |p, _len| { let mut i: uint = 0u; while i < n_elts { - intrinsics::move_val_init(&mut(*ptr::mut_offset(p, i)), - op(i)); + intrinsics::move_val_init(&mut(*ptr::mut_offset(p, i)), op(i)); i += 1u; } } @@ -165,7 +165,20 @@ pub fn from_fn(n_elts: uint, op: old_iter::InitOp) -> ~[T] { * to the value `t`. */ pub fn from_elem(n_elts: uint, t: T) -> ~[T] { - from_fn(n_elts, |_i| copy t) + // hack: manually inline from_fn for 2x plus speedup (sadly very important, from_elem is a + // bottleneck in borrowck!) + unsafe { + let mut v = with_capacity(n_elts); + do as_mut_buf(v) |p, _len| { + let mut i = 0u; + while i < n_elts { + intrinsics::move_val_init(&mut(*ptr::mut_offset(p, i)), copy t); + i += 1u; + } + } + raw::set_len(&mut v, n_elts); + v + } } /// Creates a new unique vector with the same contents as the slice @@ -505,7 +518,7 @@ pub fn shift(v: &mut ~[T]) -> T { let vp = raw::to_mut_ptr(*v); let vp = ptr::mut_offset(vp, next_ln - 1); - util::replace_ptr(vp, work_elt) + ptr::replace_ptr(vp, work_elt) } } @@ -543,6 +556,22 @@ pub fn remove(v: &mut ~[T], i: uint) -> T { v.pop() } +/// Consumes all elements, in a vector, moving them out into the / closure +/// provided. The vector is traversed from the start to the end. +/// +/// This method does not impose any requirements on the type of the vector being +/// consumed, but it prevents any usage of the vector after this function is +/// called. +/// +/// # Examples +/// +/// ~~~ {.rust} +/// let v = ~[~"a", ~"b"]; +/// do vec::consume(v) |i, s| { +/// // s has type ~str, not &~str +/// io::println(s + fmt!(" %d", i)); +/// } +/// ~~~ pub fn consume(mut v: ~[T], f: &fn(uint, v: T)) { unsafe { do as_mut_buf(v) |p, ln| { @@ -553,7 +582,7 @@ pub fn consume(mut v: ~[T], f: &fn(uint, v: T)) { // elements during unwinding let x = intrinsics::init(); let p = ptr::mut_offset(p, i); - f(i, util::replace_ptr(p, x)); + f(i, ptr::replace_ptr(p, x)); } } @@ -561,6 +590,12 @@ pub fn consume(mut v: ~[T], f: &fn(uint, v: T)) { } } +/// Consumes all elements, in a vector, moving them out into the / closure +/// provided. The vectors is traversed in reverse order (from end to start). +/// +/// This method does not impose any requirements on the type of the vector being +/// consumed, but it prevents any usage of the vector after this function is +/// called. pub fn consume_reverse(mut v: ~[T], f: &fn(uint, v: T)) { unsafe { do as_mut_buf(v) |p, ln| { @@ -574,7 +609,7 @@ pub fn consume_reverse(mut v: ~[T], f: &fn(uint, v: T)) { // elements during unwinding let x = intrinsics::init(); let p = ptr::mut_offset(p, i); - f(i, util::replace_ptr(p, x)); + f(i, ptr::replace_ptr(p, x)); } } @@ -583,7 +618,6 @@ pub fn consume_reverse(mut v: ~[T], f: &fn(uint, v: T)) { } /// Remove the last element from a vector and return it -#[cfg(not(stage0))] pub fn pop(v: &mut ~[T]) -> T { let ln = v.len(); if ln == 0 { @@ -591,21 +625,7 @@ pub fn pop(v: &mut ~[T]) -> T { } let valptr = ptr::to_mut_unsafe_ptr(&mut v[ln - 1u]); unsafe { - let val = util::replace_ptr(valptr, intrinsics::uninit()); - raw::set_len(v, ln - 1u); - val - } -} - -#[cfg(stage0)] -pub fn pop(v: &mut ~[T]) -> T { - let ln = v.len(); - if ln == 0 { - fail!("sorry, cannot vec::pop an empty vector") - } - let valptr = ptr::to_mut_unsafe_ptr(&mut v[ln - 1u]); - unsafe { - let val = util::replace_ptr(valptr, intrinsics::init()); + let val = ptr::replace_ptr(valptr, intrinsics::init()); raw::set_len(v, ln - 1u); val } @@ -661,6 +681,16 @@ fn push_slow(v: &mut ~[T], initval: T) { unsafe { push_fast(v, initval) } } +/// Iterates over the slice `rhs`, copies each element, and then appends it to +/// the vector provided `v`. The `rhs` vector is traversed in-order. +/// +/// # Example +/// +/// ~~~ {.rust} +/// let mut a = ~[1]; +/// vec::push_all(&mut a, [2, 3, 4]); +/// assert!(a == ~[1, 2, 3, 4]); +/// ~~~ #[inline(always)] pub fn push_all(v: &mut ~[T], rhs: &const [T]) { let new_len = v.len() + rhs.len(); @@ -671,16 +701,26 @@ pub fn push_all(v: &mut ~[T], rhs: &const [T]) { } } +/// Takes ownership of the vector `rhs`, moving all elements into the specified +/// vector `v`. This does not copy any elements, and it is illegal to use the +/// `rhs` vector after calling this method (because it is moved here). +/// +/// # Example +/// +/// ~~~ {.rust} +/// let mut a = ~[~1]; +/// vec::push_all_move(&mut a, ~[~2, ~3, ~4]); +/// assert!(a == ~[~1, ~2, ~3, ~4]); +/// ~~~ #[inline(always)] -#[cfg(not(stage0))] pub fn push_all_move(v: &mut ~[T], mut rhs: ~[T]) { let new_len = v.len() + rhs.len(); reserve(&mut *v, new_len); unsafe { do as_mut_buf(rhs) |p, len| { for uint::range(0, len) |i| { - let x = util::replace_ptr(ptr::mut_offset(p, i), - intrinsics::uninit()); + let x = ptr::replace_ptr(ptr::mut_offset(p, i), + intrinsics::uninit()); push(&mut *v, x); } } @@ -688,47 +728,14 @@ pub fn push_all_move(v: &mut ~[T], mut rhs: ~[T]) { } } -#[inline(always)] -#[cfg(stage0)] -pub fn push_all_move(v: &mut ~[T], mut rhs: ~[T]) { - let new_len = v.len() + rhs.len(); - reserve(&mut *v, new_len); - unsafe { - do as_mut_buf(rhs) |p, len| { - for uint::range(0, len) |i| { - let x = util::replace_ptr(ptr::mut_offset(p, i), - intrinsics::init()); - push(&mut *v, x); - } - } - raw::set_len(&mut rhs, 0); - } -} - -/// Shorten a vector, dropping excess elements. -#[cfg(not(stage0))] -pub fn truncate(v: &mut ~[T], newlen: uint) { - do as_mut_buf(*v) |p, oldlen| { - assert!(newlen <= oldlen); - unsafe { - // This loop is optimized out for non-drop types. - for uint::range(newlen, oldlen) |i| { - util::replace_ptr(ptr::mut_offset(p, i), intrinsics::uninit()); - } - } - } - unsafe { raw::set_len(&mut *v, newlen); } -} - /// Shorten a vector, dropping excess elements. -#[cfg(stage0)] pub fn truncate(v: &mut ~[T], newlen: uint) { do as_mut_buf(*v) |p, oldlen| { assert!(newlen <= oldlen); unsafe { // This loop is optimized out for non-drop types. for uint::range(newlen, oldlen) |i| { - util::replace_ptr(ptr::mut_offset(p, i), intrinsics::init()); + ptr::replace_ptr(ptr::mut_offset(p, i), intrinsics::uninit()); } } } @@ -739,11 +746,10 @@ pub fn truncate(v: &mut ~[T], newlen: uint) { * Remove consecutive repeated elements from a vector; if the vector is * sorted, this removes all duplicates. */ -#[cfg(not(stage0))] pub fn dedup(v: &mut ~[T]) { unsafe { if v.len() < 1 { return; } - let mut last_written = 0, next_to_read = 1; + let mut (last_written, next_to_read) = (0, 1); do as_const_buf(*v) |p, ln| { // We have a mutable reference to v, so we can make arbitrary // changes. (cf. push and pop) @@ -753,14 +759,14 @@ pub fn dedup(v: &mut ~[T]) { // last_written < next_to_read < ln if *ptr::mut_offset(p, next_to_read) == *ptr::mut_offset(p, last_written) { - util::replace_ptr(ptr::mut_offset(p, next_to_read), - intrinsics::uninit()); + ptr::replace_ptr(ptr::mut_offset(p, next_to_read), + intrinsics::uninit()); } else { last_written += 1; // last_written <= next_to_read < ln if next_to_read != last_written { - util::swap_ptr(ptr::mut_offset(p, last_written), - ptr::mut_offset(p, next_to_read)); + ptr::swap_ptr(ptr::mut_offset(p, last_written), + ptr::mut_offset(p, next_to_read)); } } // last_written <= next_to_read < ln @@ -773,46 +779,10 @@ pub fn dedup(v: &mut ~[T]) { } } -/** - * Remove consecutive repeated elements from a vector; if the vector is - * sorted, this removes all duplicates. - */ -#[cfg(stage0)] -pub fn dedup(v: &mut ~[T]) { - unsafe { - if v.len() < 1 { return; } - let mut last_written = 0, next_to_read = 1; - do as_const_buf(*v) |p, ln| { - // We have a mutable reference to v, so we can make arbitrary - // changes. (cf. push and pop) - let p = p as *mut T; - // last_written < next_to_read <= ln - while next_to_read < ln { - // last_written < next_to_read < ln - if *ptr::mut_offset(p, next_to_read) == - *ptr::mut_offset(p, last_written) { - util::replace_ptr(ptr::mut_offset(p, next_to_read), - intrinsics::init()); - } else { - last_written += 1; - // last_written <= next_to_read < ln - if next_to_read != last_written { - util::swap_ptr(ptr::mut_offset(p, last_written), - ptr::mut_offset(p, next_to_read)); - } - } - // last_written <= next_to_read < ln - next_to_read += 1; - // last_written < next_to_read <= ln - } - } - // last_written < next_to_read == ln - raw::set_len(v, last_written + 1); - } -} - - // Appending + +/// Iterates over the `rhs` vector, copying each element and appending it to the +/// `lhs`. Afterwards, the `lhs` is then returned for use again. #[inline(always)] pub fn append(lhs: ~[T], rhs: &const [T]) -> ~[T] { let mut v = lhs; @@ -820,6 +790,8 @@ pub fn append(lhs: ~[T], rhs: &const [T]) -> ~[T] { v } +/// Appends one element to the vector provided. The vector itself is then +/// returned for use again. #[inline(always)] pub fn append_one(lhs: ~[T], x: T) -> ~[T] { let mut v = lhs; @@ -895,6 +867,13 @@ pub fn map(v: &[T], f: &fn(t: &T) -> U) -> ~[U] { result } +/// Consumes a vector, mapping it into a different vector. This function takes +/// ownership of the supplied vector `v`, moving each element into the closure +/// provided to generate a new element. The vector of new elements is then +/// returned. +/// +/// The original vector `v` cannot be used after this function call (it is moved +/// inside), but there are no restrictions on the type of the vector. pub fn map_consume(v: ~[T], f: &fn(v: T) -> U) -> ~[U] { let mut result = ~[]; do consume(v) |_i, x| { @@ -1032,26 +1011,58 @@ pub fn retain(v: &mut ~[T], f: &fn(t: &T) -> bool) { } } -/** - * Concatenate a vector of vectors. - * - * Flattens a vector of vectors of T into a single vector of T. - */ -pub fn concat(v: &[~[T]]) -> ~[T] { - let mut r = ~[]; - for each(v) |inner| { r.push_all(*inner); } - r -} +/// Flattens a vector of vectors of T into a single vector of T. +pub fn concat(v: &[~[T]]) -> ~[T] { v.concat() } /// Concatenate a vector of vectors, placing a given separator between each -pub fn connect(v: &[~[T]], sep: &T) -> ~[T] { - let mut r: ~[T] = ~[]; - let mut first = true; - for each(v) |inner| { - if first { first = false; } else { r.push(*sep); } - r.push_all(*inner); +pub fn connect(v: &[~[T]], sep: &T) -> ~[T] { v.connect(sep) } + +/// Flattens a vector of vectors of T into a single vector of T. +pub fn concat_slices(v: &[&[T]]) -> ~[T] { v.concat() } + +/// Concatenate a vector of vectors, placing a given separator between each +pub fn connect_slices(v: &[&[T]], sep: &T) -> ~[T] { v.connect(sep) } + +#[allow(missing_doc)] +pub trait VectorVector { + pub fn concat(&self) -> ~[T]; + pub fn connect(&self, sep: &T) -> ~[T]; +} + +impl<'self, T:Copy> VectorVector for &'self [~[T]] { + /// Flattens a vector of slices of T into a single vector of T. + pub fn concat(&self) -> ~[T] { + self.flat_map(|&inner| inner) + } + + /// Concatenate a vector of vectors, placing a given separator between each. + pub fn connect(&self, sep: &T) -> ~[T] { + let mut r = ~[]; + let mut first = true; + for self.each |&inner| { + if first { first = false; } else { r.push(*sep); } + r.push_all(inner); + } + r + } +} + +impl<'self, T:Copy> VectorVector for &'self [&'self [T]] { + /// Flattens a vector of slices of T into a single vector of T. + pub fn concat(&self) -> ~[T] { + self.flat_map(|&inner| inner.to_owned()) + } + + /// Concatenate a vector of slices, placing a given separator between each. + pub fn connect(&self, sep: &T) -> ~[T] { + let mut r = ~[]; + let mut first = true; + for self.each |&inner| { + if first { first = false; } else { r.push(*sep); } + r.push_all(inner); + } + r } - r } /** @@ -1066,7 +1077,7 @@ pub fn connect(v: &[~[T]], sep: &T) -> ~[T] { * * Sum all values in the vector [1, 2, 3]: * - * ~~~ + * ~~~ {.rust} * vec::foldl(0, [1, 2, 3], |a, b| a + *b); * ~~~ * @@ -1098,7 +1109,7 @@ pub fn foldl<'a, T, U>(z: T, v: &'a [U], p: &fn(t: T, u: &'a U) -> T) -> T { * * Sum all values in the vector [1, 2, 3]: * - * ~~~ + * ~~~ {.rust} * vec::foldr([1, 2, 3], 0, |a, b| a + *b); * ~~~ * @@ -1354,7 +1365,7 @@ pub fn bsearch_elem(v: &[T], x: &T) -> Option { * Convert a vector of pairs into a pair of vectors, by reference. As unzip(). */ pub fn unzip_slice(v: &[(T, U)]) -> (~[T], ~[U]) { - let mut ts = ~[], us = ~[]; + let mut (ts, us) = (~[], ~[]); for each(v) |p| { let (t, u) = *p; ts.push(t); @@ -1372,7 +1383,7 @@ pub fn unzip_slice(v: &[(T, U)]) -> (~[T], ~[U]) { * of the i-th tuple of the input vector. */ pub fn unzip(v: ~[(T, U)]) -> (~[T], ~[U]) { - let mut ts = ~[], us = ~[]; + let mut (ts, us) = (~[], ~[]); do consume(v) |_i, p| { let (t, u) = p; ts.push(t); @@ -1389,7 +1400,7 @@ pub fn zip_slice(v: &const [T], u: &const [U]) let mut zipped = ~[]; let sz = len(v); let mut i = 0u; - assert!(sz == len(u)); + assert_eq!(sz, len(u)); while i < sz { zipped.push((v[i], u[i])); i += 1u; @@ -1405,7 +1416,7 @@ pub fn zip_slice(v: &const [T], u: &const [U]) */ pub fn zip(mut v: ~[T], mut u: ~[U]) -> ~[(T, U)] { let mut i = len(v); - assert!(i == len(u)); + assert_eq!(i, len(u)); let mut w = with_capacity(i); while i > 0 { w.push((v.pop(),u.pop())); @@ -1431,7 +1442,7 @@ pub fn swap(v: &mut [T], a: uint, b: uint) { // them to their raw pointers to do the swap let pa: *mut T = ptr::to_mut_unsafe_ptr(&mut v[a]); let pb: *mut T = ptr::to_mut_unsafe_ptr(&mut v[b]); - util::swap_ptr(pa, pb); + ptr::swap_ptr(pa, pb); } } @@ -1465,10 +1476,8 @@ pub fn reverse(v: &mut [T]) { * * Assume a mutable vector `v` contains `[1,2,3,4,5]`. After the call: * - * ~~~ - * + * ~~~ {.rust} * reverse_part(v, 1, 4); - * * ~~~ * * `v` now contains `[1,4,3,2,5]`. @@ -1505,14 +1514,15 @@ pub fn reversed(v: &const [T]) -> ~[T] { * * continue iterating, false to break. * * # Examples - * ~~~ + * + * ~~~ {.rust} * [1,2,3].each(|&i| { * io::println(int::str(i)); * true * }); * ~~~ * - * ~~~ + * ~~~ {.rust} * [1,2,3,4,5].each(|&i| { * if i < 4 { * io::println(int::str(i)); @@ -1527,15 +1537,15 @@ pub fn reversed(v: &const [T]) -> ~[T] { * You probably will want to use each with a `for`/`do` expression, depending * on your iteration needs: * - * ~~~ + * ~~~ {.rust} * for [1,2,3].each |&i| { * io::println(int::str(i)); * } * ~~~ */ #[inline(always)] -pub fn _each<'r,T>(v: &'r [T], f: &fn(&'r T) -> bool) -> bool { - // ^^^^ +pub fn each<'r,T>(v: &'r [T], f: &fn(&'r T) -> bool) -> bool { + // ^^^^ // NB---this CANNOT be &const [T]! The reason // is that you are passing it to `f()` using // an immutable. @@ -1554,19 +1564,14 @@ pub fn _each<'r,T>(v: &'r [T], f: &fn(&'r T) -> bool) -> bool { } broke = n > 0; } - return true; + return !broke; } -#[cfg(stage0)] -pub fn each<'r,T>(v: &'r [T], f: &fn(&'r T) -> bool) { _each(v, f); } -#[cfg(not(stage0))] -pub fn each<'r,T>(v: &'r [T], f: &fn(&'r T) -> bool) -> bool { _each(v, f) } - /// Like `each()`, but for the case where you have /// a vector with mutable contents and you would like /// to mutate the contents as you iterate. #[inline(always)] -pub fn _each_mut<'r,T>(v: &'r mut [T], f: &fn(elem: &'r mut T) -> bool) -> bool { +pub fn each_mut<'r,T>(v: &'r mut [T], f: &fn(elem: &'r mut T) -> bool) -> bool { let mut broke = false; do as_mut_buf(v) |p, n| { let mut n = n; @@ -1581,22 +1586,13 @@ pub fn _each_mut<'r,T>(v: &'r mut [T], f: &fn(elem: &'r mut T) -> bool) -> bool } broke = n > 0; } - return broke; -} - -#[cfg(stage0)] -pub fn each_mut<'r,T>(v: &'r mut [T], f: &fn(elem: &'r mut T) -> bool) { - _each_mut(v, f); -} -#[cfg(not(stage0))] -pub fn each_mut<'r,T>(v: &'r mut [T], f: &fn(elem: &'r mut T) -> bool) -> bool { - _each_mut(v, f) + return !broke; } /// Like `each()`, but for the case where you have a vector that *may or may /// not* have mutable contents. #[inline(always)] -pub fn _each_const(v: &const [T], f: &fn(elem: &const T) -> bool) -> bool { +pub fn each_const(v: &const [T], f: &fn(elem: &const T) -> bool) -> bool { let mut i = 0; let n = v.len(); while i < n { @@ -1608,22 +1604,13 @@ pub fn _each_const(v: &const [T], f: &fn(elem: &const T) -> bool) -> bool { return true; } -#[cfg(stage0)] -pub fn each_const(v: &const [t], f: &fn(elem: &const t) -> bool) { - _each_const(v, f); -} -#[cfg(not(stage0))] -pub fn each_const(v: &const [t], f: &fn(elem: &const t) -> bool) -> bool { - _each_const(v, f) -} - /** * Iterates over a vector's elements and indices * * Return true to continue, false to break. */ #[inline(always)] -pub fn _eachi<'r,T>(v: &'r [T], f: &fn(uint, v: &'r T) -> bool) -> bool { +pub fn eachi<'r,T>(v: &'r [T], f: &fn(uint, v: &'r T) -> bool) -> bool { let mut i = 0; for each(v) |p| { if !f(i, p) { return false; } @@ -1632,21 +1619,14 @@ pub fn _eachi<'r,T>(v: &'r [T], f: &fn(uint, v: &'r T) -> bool) -> bool { return true; } -#[cfg(stage0)] -pub fn eachi<'r,T>(v: &'r [T], f: &fn(uint, v: &'r T) -> bool) { _eachi(v, f); } -#[cfg(not(stage0))] -pub fn eachi<'r,T>(v: &'r [T], f: &fn(uint, v: &'r T) -> bool) -> bool { - _eachi(v, f) -} - /** * Iterates over a mutable vector's elements and indices * * Return true to continue, false to break. */ #[inline(always)] -pub fn _eachi_mut<'r,T>(v: &'r mut [T], - f: &fn(uint, v: &'r mut T) -> bool) -> bool { +pub fn eachi_mut<'r,T>(v: &'r mut [T], + f: &fn(uint, v: &'r mut T) -> bool) -> bool { let mut i = 0; for each_mut(v) |p| { if !f(i, p) { @@ -1657,33 +1637,14 @@ pub fn _eachi_mut<'r,T>(v: &'r mut [T], return true; } -#[cfg(stage0)] -pub fn eachi_mut<'r,T>(v: &'r mut [T], f: &fn(uint, v: &'r mut T) -> bool) { - _eachi_mut(v, f); -} -#[cfg(not(stage0))] -pub fn eachi_mut<'r,T>(v: &'r mut [T], - f: &fn(uint, v: &'r mut T) -> bool) -> bool { - _eachi_mut(v, f) -} - /** * Iterates over a vector's elements in reverse * * Return true to continue, false to break. */ #[inline(always)] -pub fn _each_reverse<'r,T>(v: &'r [T], blk: &fn(v: &'r T) -> bool) -> bool { - _eachi_reverse(v, |_i, v| blk(v)) -} - -#[cfg(stage0)] -pub fn each_reverse<'r,T>(v: &'r [T], blk: &fn(v: &'r T) -> bool) { - _each_reverse(v, blk); -} -#[cfg(not(stage0))] pub fn each_reverse<'r,T>(v: &'r [T], blk: &fn(v: &'r T) -> bool) -> bool { - _each_reverse(v, blk) + eachi_reverse(v, |_i, v| blk(v)) } /** @@ -1692,7 +1653,7 @@ pub fn each_reverse<'r,T>(v: &'r [T], blk: &fn(v: &'r T) -> bool) -> bool { * Return true to continue, false to break. */ #[inline(always)] -pub fn _eachi_reverse<'r,T>(v: &'r [T], +pub fn eachi_reverse<'r,T>(v: &'r [T], blk: &fn(i: uint, v: &'r T) -> bool) -> bool { let mut i = v.len(); while i > 0 { @@ -1704,16 +1665,6 @@ pub fn _eachi_reverse<'r,T>(v: &'r [T], return true; } -#[cfg(stage0)] -pub fn eachi_reverse<'r,T>(v: &'r [T], blk: &fn(i: uint, v: &'r T) -> bool) { - _eachi_reverse(v, blk); -} -#[cfg(not(stage0))] -pub fn eachi_reverse<'r,T>(v: &'r [T], - blk: &fn(i: uint, v: &'r T) -> bool) -> bool { - _eachi_reverse(v, blk) -} - /** * Iterates over two vectors simultaneously * @@ -1722,8 +1673,8 @@ pub fn eachi_reverse<'r,T>(v: &'r [T], * Both vectors must have the same length */ #[inline] -pub fn _each2(v1: &[U], v2: &[T], f: &fn(u: &U, t: &T) -> bool) -> bool { - assert!(v1.len() == v2.len()); +pub fn each2(v1: &[U], v2: &[T], f: &fn(u: &U, t: &T) -> bool) -> bool { + assert_eq!(v1.len(), v2.len()); for uint::range(0u, v1.len()) |i| { if !f(&v1[i], &v2[i]) { return false; @@ -1732,15 +1683,6 @@ pub fn _each2(v1: &[U], v2: &[T], f: &fn(u: &U, t: &T) -> bool) -> bool { return true; } -#[cfg(stage0)] -pub fn each2(v1: &[U], v2: &[T], f: &fn(u: &U, t: &T) -> bool) { - _each2(v1, v2, f); -} -#[cfg(not(stage0))] -pub fn each2(v1: &[U], v2: &[T], f: &fn(u: &U, t: &T) -> bool) -> bool { - _each2(v1, v2, f) -} - /** * * Iterates over two vector with mutable. @@ -1750,8 +1692,9 @@ pub fn each2(v1: &[U], v2: &[T], f: &fn(u: &U, t: &T) -> bool) -> bool { * Both vectors must have the same length */ #[inline] -pub fn _each2_mut(v1: &mut [U], v2: &mut [T], f: &fn(u: &mut U, t: &mut T) -> bool) -> bool { - assert!(v1.len() == v2.len()); +pub fn each2_mut(v1: &mut [U], v2: &mut [T], + f: &fn(u: &mut U, t: &mut T) -> bool) -> bool { + assert_eq!(v1.len(), v2.len()); for uint::range(0u, v1.len()) |i| { if !f(&mut v1[i], &mut v2[i]) { return false; @@ -1760,16 +1703,6 @@ pub fn _each2_mut(v1: &mut [U], v2: &mut [T], f: &fn(u: &mut U, t: &mut T) return true; } -#[cfg(stage0)] -pub fn each2_mut(v1: &mut [U], v2: &mut [T], f: &fn(u: &mut U, t: &mut T) -> bool) { - _each2_mut(v1, v2, f); -} - -#[cfg(not(stage0))] -pub fn each2_mut(v1: &mut [U], v2: &mut [T], f: &fn(u: &mut U, t: &mut T) -> bool) -> bool { - _each2_mut(v1, v2, f) -} - /** * Iterate over all permutations of vector `v`. * @@ -1831,36 +1764,13 @@ pub fn each_permutation(values: &[T], fun: &fn(perm : &[T]) -> bool) -> * * Print the adjacent pairs of a vector (i.e. `[1,2]`, `[2,3]`, `[3,4]`) * - * ~~~ - * for windowed(2, &[1,2,3,4]) |v| { - * io::println(fmt!("%?", v)); - * } - * ~~~ - * - */ -#[cfg(stage0)] -pub fn windowed<'r, T>(n: uint, v: &'r [T], it: &fn(&'r [T]) -> bool) { - assert!(1u <= n); - if n > v.len() { return; } - for uint::range(0, v.len() - n + 1) |i| { - if !it(v.slice(i, i + n)) { return } - } -} -/** - * Iterate over all contiguous windows of length `n` of the vector `v`. - * - * # Example - * - * Print the adjacent pairs of a vector (i.e. `[1,2]`, `[2,3]`, `[3,4]`) - * - * ~~~ + * ~~~ {.rust} * for windowed(2, &[1,2,3,4]) |v| { * io::println(fmt!("%?", v)); * } * ~~~ * */ -#[cfg(not(stage0))] pub fn windowed<'r, T>(n: uint, v: &'r [T], it: &fn(&'r [T]) -> bool) -> bool { assert!(1u <= n); if n > v.len() { return true; } @@ -1916,6 +1826,9 @@ pub fn as_mut_buf(s: &mut [T], f: &fn(*mut T, uint) -> U) -> U { // Equality +/// Tests whether two slices are equal to one another. This is only true if both +/// slices are of the same length, and each of the corresponding elements return +/// true when queried via the `eq` function. fn eq(a: &[T], b: &[T]) -> bool { let (a_len, b_len) = (a.len(), b.len()); if a_len != b_len { return false; } @@ -1928,6 +1841,9 @@ fn eq(a: &[T], b: &[T]) -> bool { true } +/// Similar to the `vec::eq` function, but this is defined for types which +/// implement `TotalEq` as opposed to types which implement `Eq`. Equality +/// comparisons are done via the `equals` function instead of `eq`. fn equals(a: &[T], b: &[T]) -> bool { let (a_len, b_len) = (a.len(), b.len()); if a_len != b_len { return false; } @@ -2101,6 +2017,7 @@ impl<'self,T> Container for &'self const [T] { fn len(&const self) -> uint { len(*self) } } +#[allow(missing_doc)] pub trait CopyableVector { fn to_owned(&self) -> ~[T]; } @@ -2120,6 +2037,7 @@ impl<'self,T:Copy> CopyableVector for &'self [T] { } } +#[allow(missing_doc)] pub trait ImmutableVector<'self, T> { fn slice(&self, start: uint, end: uint) -> &'self [T]; fn iter(self) -> VecIterator<'self, T>; @@ -2133,13 +2051,7 @@ pub trait ImmutableVector<'self, T> { fn last_opt(&self) -> Option<&'self T>; fn position(&self, f: &fn(t: &T) -> bool) -> Option; fn rposition(&self, f: &fn(t: &T) -> bool) -> Option; - #[cfg(stage0)] - fn each_reverse(&self, blk: &fn(&T) -> bool); - #[cfg(not(stage0))] fn each_reverse(&self, blk: &fn(&T) -> bool) -> bool; - #[cfg(stage0)] - fn eachi_reverse(&self, blk: &fn(uint, &T) -> bool); - #[cfg(not(stage0))] fn eachi_reverse(&self, blk: &fn(uint, &T) -> bool) -> bool; fn foldr<'a, U>(&'a self, z: U, p: &fn(t: &'a T, u: U) -> U) -> U; fn map(&self, f: &fn(t: &T) -> U) -> ~[U]; @@ -2226,25 +2138,11 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] { /// Iterates over a vector's elements in reverse. #[inline] - #[cfg(stage0)] - fn each_reverse(&self, blk: &fn(&T) -> bool) { - each_reverse(*self, blk) - } - /// Iterates over a vector's elements in reverse. - #[inline] - #[cfg(not(stage0))] fn each_reverse(&self, blk: &fn(&T) -> bool) -> bool { each_reverse(*self, blk) } /// Iterates over a vector's elements and indices in reverse. - #[cfg(stage0)] - #[inline] - fn eachi_reverse(&self, blk: &fn(uint, &T) -> bool) { - eachi_reverse(*self, blk) - } - /// Iterates over a vector's elements and indices in reverse. - #[cfg(not(stage0))] #[inline] fn eachi_reverse(&self, blk: &fn(uint, &T) -> bool) -> bool { eachi_reverse(*self, blk) @@ -2315,6 +2213,7 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] { } } +#[allow(missing_doc)] pub trait ImmutableEqVector { fn position_elem(&self, t: &T) -> Option; fn rposition_elem(&self, t: &T) -> Option; @@ -2334,6 +2233,7 @@ impl<'self,T:Eq> ImmutableEqVector for &'self [T] { } } +#[allow(missing_doc)] pub trait ImmutableCopyableVector { fn filtered(&self, f: &fn(&T) -> bool) -> ~[T]; fn rfind(&self, f: &fn(t: &T) -> bool) -> Option; @@ -2383,6 +2283,7 @@ impl<'self,T:Copy> ImmutableCopyableVector for &'self [T] { } } +#[allow(missing_doc)] pub trait OwnedVector { fn push(&mut self, t: T); fn push_all_move(&mut self, rhs: ~[T]); @@ -2487,6 +2388,7 @@ impl Mutable for ~[T] { fn clear(&mut self) { self.truncate(0) } } +#[allow(missing_doc)] pub trait OwnedCopyableVector { fn push_all(&mut self, rhs: &const [T]); fn grow(&mut self, n: uint, initval: &T); @@ -2510,6 +2412,7 @@ impl OwnedCopyableVector for ~[T] { } } +#[allow(missing_doc)] trait OwnedEqVector { fn dedup(&mut self); } @@ -2521,12 +2424,20 @@ impl OwnedEqVector for ~[T] { } } -pub trait MutableVector { +#[allow(missing_doc)] +pub trait MutableVector<'self, T> { + fn mut_slice(self, start: uint, end: uint) -> &'self mut [T]; + unsafe fn unsafe_mut_ref(&self, index: uint) -> *mut T; unsafe fn unsafe_set(&self, index: uint, val: T); } -impl<'self,T> MutableVector for &'self mut [T] { +impl<'self,T> MutableVector<'self, T> for &'self mut [T] { + #[inline] + fn mut_slice(self, start: uint, end: uint) -> &'self mut [T] { + mut_slice(self, start, end) + } + #[inline(always)] unsafe fn unsafe_mut_ref(&self, index: uint) -> *mut T { let pair_ptr: &(*mut T, uint) = transmute(self); @@ -2554,6 +2465,7 @@ pub unsafe fn from_buf(ptr: *T, elts: uint) -> ~[T] { } /// The internal 'unboxed' representation of a vector +#[allow(missing_doc)] pub struct UnboxedVecRepr { fill: uint, alloc: uint, @@ -2573,13 +2485,17 @@ pub mod raw { use util; /// The internal representation of a (boxed) vector + #[allow(missing_doc)] pub struct VecRepr { box_header: managed::raw::BoxHeaderRepr, unboxed: UnboxedVecRepr } + /// The internal representation of a slice pub struct SliceRepr { + /// Pointer to the base of this slice data: *u8, + /// The length of the slice len: uint } @@ -2780,12 +2696,6 @@ pub mod bytes { // ITERATION TRAIT METHODS impl<'self,A> old_iter::BaseIter for &'self [A] { - #[cfg(stage0)] - #[inline(always)] - fn each<'a>(&'a self, blk: &fn(v: &'a A) -> bool) { - each(*self, blk) - } - #[cfg(not(stage0))] #[inline(always)] fn each<'a>(&'a self, blk: &fn(v: &'a A) -> bool) -> bool { each(*self, blk) @@ -2796,12 +2706,6 @@ impl<'self,A> old_iter::BaseIter for &'self [A] { // FIXME(#4148): This should be redundant impl old_iter::BaseIter for ~[A] { - #[cfg(stage0)] - #[inline(always)] - fn each<'a>(&'a self, blk: &fn(v: &'a A) -> bool) { - each(*self, blk) - } - #[cfg(not(stage0))] #[inline(always)] fn each<'a>(&'a self, blk: &fn(v: &'a A) -> bool) -> bool { each(*self, blk) @@ -2812,12 +2716,6 @@ impl old_iter::BaseIter for ~[A] { // FIXME(#4148): This should be redundant impl old_iter::BaseIter for @[A] { - #[cfg(stage0)] - #[inline(always)] - fn each<'a>(&'a self, blk: &fn(v: &'a A) -> bool) { - each(*self, blk) - } - #[cfg(not(stage0))] #[inline(always)] fn each<'a>(&'a self, blk: &fn(v: &'a A) -> bool) -> bool { each(*self, blk) @@ -2827,12 +2725,6 @@ impl old_iter::BaseIter for @[A] { } impl<'self,A> old_iter::MutableIter for &'self mut [A] { - #[cfg(stage0)] - #[inline(always)] - fn each_mut<'a>(&'a mut self, blk: &fn(v: &'a mut A) -> bool) { - each_mut(*self, blk) - } - #[cfg(not(stage0))] #[inline(always)] fn each_mut<'a>(&'a mut self, blk: &fn(v: &'a mut A) -> bool) -> bool { each_mut(*self, blk) @@ -2841,12 +2733,6 @@ impl<'self,A> old_iter::MutableIter for &'self mut [A] { // FIXME(#4148): This should be redundant impl old_iter::MutableIter for ~[A] { - #[cfg(stage0)] - #[inline(always)] - fn each_mut<'a>(&'a mut self, blk: &fn(v: &'a mut A) -> bool) { - each_mut(*self, blk) - } - #[cfg(not(stage0))] #[inline(always)] fn each_mut<'a>(&'a mut self, blk: &fn(v: &'a mut A) -> bool) -> bool { each_mut(*self, blk) @@ -2854,15 +2740,6 @@ impl old_iter::MutableIter for ~[A] { } // FIXME(#4148): This should be redundant -#[cfg(stage0)] -impl old_iter::MutableIter for @mut [A] { - #[inline(always)] - fn each_mut(&mut self, blk: &fn(v: &mut A) -> bool) { - each_mut(*self, blk) - } -} - -#[cfg(not(stage0))] impl old_iter::MutableIter for @mut [A] { #[inline(always)] fn each_mut(&mut self, blk: &fn(v: &mut A) -> bool) -> bool { @@ -2871,11 +2748,6 @@ impl old_iter::MutableIter for @mut [A] { } impl<'self,A> old_iter::ExtendedIter for &'self [A] { - #[cfg(stage0)] - pub fn eachi(&self, blk: &fn(uint, v: &A) -> bool) { - old_iter::eachi(self, blk) - } - #[cfg(not(stage0))] pub fn eachi(&self, blk: &fn(uint, v: &A) -> bool) -> bool { old_iter::eachi(self, blk) } @@ -2902,12 +2774,6 @@ impl<'self,A> old_iter::ExtendedIter for &'self [A] { impl<'self,A> old_iter::ExtendedMutableIter for &'self mut [A] { #[inline(always)] - #[cfg(stage0)] - pub fn eachi_mut(&mut self, blk: &fn(uint, v: &mut A) -> bool) { - eachi_mut(*self, blk) - } - #[inline(always)] - #[cfg(not(stage0))] pub fn eachi_mut(&mut self, blk: &fn(uint, v: &mut A) -> bool) -> bool { eachi_mut(*self, blk) } @@ -2915,11 +2781,6 @@ impl<'self,A> old_iter::ExtendedMutableIter for &'self mut [A] { // FIXME(#4148): This should be redundant impl old_iter::ExtendedIter for ~[A] { - #[cfg(stage0)] - pub fn eachi(&self, blk: &fn(uint, v: &A) -> bool) { - old_iter::eachi(self, blk) - } - #[cfg(not(stage0))] pub fn eachi(&self, blk: &fn(uint, v: &A) -> bool) -> bool { old_iter::eachi(self, blk) } @@ -2946,11 +2807,6 @@ impl old_iter::ExtendedIter for ~[A] { // FIXME(#4148): This should be redundant impl old_iter::ExtendedIter for @[A] { - #[cfg(stage0)] - pub fn eachi(&self, blk: &fn(uint, v: &A) -> bool) { - old_iter::eachi(self, blk) - } - #[cfg(not(stage0))] pub fn eachi(&self, blk: &fn(uint, v: &A) -> bool) -> bool { old_iter::eachi(self, blk) } @@ -3083,13 +2939,14 @@ impl Clone for ~[A] { } } -// could be implemented with &[T] with .slice(), but this avoids bounds checks +/// An external iterator for vectors (use with the std::iterator module) pub struct VecIterator<'self, T> { priv ptr: *T, priv end: *T, priv lifetime: &'self T // FIXME: #5922 } +// could be implemented with &[T] with .slice(), but this avoids bounds checks impl<'self, T> Iterator<&'self T> for VecIterator<'self, T> { #[inline] fn next(&mut self) -> Option<&'self T> { @@ -3139,21 +2996,21 @@ mod tests { let a = ~[1, 2, 3]; let mut ptr = raw::to_ptr(a); let b = from_buf(ptr, 3u); - assert!(b.len() == 3u); - assert!(b[0] == 1); - assert!(b[1] == 2); - assert!(b[2] == 3); + assert_eq!(b.len(), 3u); + assert_eq!(b[0], 1); + assert_eq!(b[1], 2); + assert_eq!(b[2], 3); // Test on-heap copy-from-buf. let c = ~[1, 2, 3, 4, 5]; ptr = raw::to_ptr(c); let d = from_buf(ptr, 5u); - assert!(d.len() == 5u); - assert!(d[0] == 1); - assert!(d[1] == 2); - assert!(d[2] == 3); - assert!(d[3] == 4); - assert!(d[4] == 5); + assert_eq!(d.len(), 5u); + assert_eq!(d[0], 1); + assert_eq!(d[1], 2); + assert_eq!(d[2], 3); + assert_eq!(d[3], 4); + assert_eq!(d[4], 5); } } @@ -3161,43 +3018,43 @@ mod tests { fn test_from_fn() { // Test on-stack from_fn. let mut v = from_fn(3u, square); - assert!(v.len() == 3u); - assert!(v[0] == 0u); - assert!(v[1] == 1u); - assert!(v[2] == 4u); + assert_eq!(v.len(), 3u); + assert_eq!(v[0], 0u); + assert_eq!(v[1], 1u); + assert_eq!(v[2], 4u); // Test on-heap from_fn. v = from_fn(5u, square); - assert!(v.len() == 5u); - assert!(v[0] == 0u); - assert!(v[1] == 1u); - assert!(v[2] == 4u); - assert!(v[3] == 9u); - assert!(v[4] == 16u); + assert_eq!(v.len(), 5u); + assert_eq!(v[0], 0u); + assert_eq!(v[1], 1u); + assert_eq!(v[2], 4u); + assert_eq!(v[3], 9u); + assert_eq!(v[4], 16u); } #[test] fn test_from_elem() { // Test on-stack from_elem. let mut v = from_elem(2u, 10u); - assert!(v.len() == 2u); - assert!(v[0] == 10u); - assert!(v[1] == 10u); + assert_eq!(v.len(), 2u); + assert_eq!(v[0], 10u); + assert_eq!(v[1], 10u); // Test on-heap from_elem. v = from_elem(6u, 20u); - assert!(v[0] == 20u); - assert!(v[1] == 20u); - assert!(v[2] == 20u); - assert!(v[3] == 20u); - assert!(v[4] == 20u); - assert!(v[5] == 20u); + assert_eq!(v[0], 20u); + assert_eq!(v[1], 20u); + assert_eq!(v[2], 20u); + assert_eq!(v[3], 20u); + assert_eq!(v[4], 20u); + assert_eq!(v[5], 20u); } #[test] fn test_is_empty() { - assert!(is_empty::(~[])); - assert!(!is_empty(~[0])); + assert!(is_empty::([])); + assert!(!is_empty([0])); } #[test] @@ -3206,18 +3063,18 @@ mod tests { let v0 : &[Z] = &[]; let v1 : &[Z] = &[[]]; let v2 : &[Z] = &[[], []]; - assert!(sys::size_of::() == 0); - assert!(v0.len() == 0); - assert!(v1.len() == 1); - assert!(v2.len() == 2); + assert_eq!(sys::size_of::(), 0); + assert_eq!(v0.len(), 0); + assert_eq!(v1.len(), 1); + assert_eq!(v2.len(), 2); } #[test] fn test_head() { let mut a = ~[11]; - assert!(a.head() == &11); + assert_eq!(a.head(), &11); a = ~[11, 12]; - assert!(a.head() == &11); + assert_eq!(a.head(), &11); } #[test] @@ -3231,19 +3088,19 @@ mod tests { #[test] fn test_head_opt() { let mut a = ~[]; - assert!(a.head_opt() == None); + assert_eq!(a.head_opt(), None); a = ~[11]; - assert!(a.head_opt().unwrap() == &11); + assert_eq!(a.head_opt().unwrap(), &11); a = ~[11, 12]; - assert!(a.head_opt().unwrap() == &11); + assert_eq!(a.head_opt().unwrap(), &11); } #[test] fn test_tail() { let mut a = ~[11]; - assert!(a.tail() == &[]); + assert_eq!(a.tail(), &[]); a = ~[11, 12]; - assert!(a.tail() == &[12]); + assert_eq!(a.tail(), &[12]); } #[test] @@ -3257,9 +3114,9 @@ mod tests { #[test] fn test_tailn() { let mut a = ~[11, 12, 13]; - assert!(a.tailn(0) == &[11, 12, 13]); + assert_eq!(a.tailn(0), &[11, 12, 13]); a = ~[11, 12, 13]; - assert!(a.tailn(2) == &[13]); + assert_eq!(a.tailn(2), &[13]); } #[test] @@ -3273,9 +3130,9 @@ mod tests { #[test] fn test_init() { let mut a = ~[11]; - assert!(a.init() == &[]); + assert_eq!(a.init(), &[]); a = ~[11, 12]; - assert!(a.init() == &[11]); + assert_eq!(a.init(), &[11]); } #[init] @@ -3289,9 +3146,9 @@ mod tests { #[test] fn test_initn() { let mut a = ~[11, 12, 13]; - assert!(a.initn(0) == &[11, 12, 13]); + assert_eq!(a.initn(0), &[11, 12, 13]); a = ~[11, 12, 13]; - assert!(a.initn(2) == &[11]); + assert_eq!(a.initn(2), &[11]); } #[init] @@ -3305,9 +3162,9 @@ mod tests { #[test] fn test_last() { let mut a = ~[11]; - assert!(a.last() == &11); + assert_eq!(a.last(), &11); a = ~[11, 12]; - assert!(a.last() == &12); + assert_eq!(a.last(), &12); } #[test] @@ -3321,11 +3178,11 @@ mod tests { #[test] fn test_last_opt() { let mut a = ~[]; - assert!(a.last_opt() == None); + assert_eq!(a.last_opt(), None); a = ~[11]; - assert!(a.last_opt().unwrap() == &11); + assert_eq!(a.last_opt().unwrap(), &11); a = ~[11, 12]; - assert!(a.last_opt().unwrap() == &12); + assert_eq!(a.last_opt().unwrap(), &12); } #[test] @@ -3333,35 +3190,35 @@ mod tests { // Test fixed length vector. let vec_fixed = [1, 2, 3, 4]; let v_a = slice(vec_fixed, 1u, vec_fixed.len()).to_vec(); - assert!(v_a.len() == 3u); - assert!(v_a[0] == 2); - assert!(v_a[1] == 3); - assert!(v_a[2] == 4); + assert_eq!(v_a.len(), 3u); + assert_eq!(v_a[0], 2); + assert_eq!(v_a[1], 3); + assert_eq!(v_a[2], 4); // Test on stack. let vec_stack = &[1, 2, 3]; let v_b = slice(vec_stack, 1u, 3u).to_vec(); - assert!(v_b.len() == 2u); - assert!(v_b[0] == 2); - assert!(v_b[1] == 3); + assert_eq!(v_b.len(), 2u); + assert_eq!(v_b[0], 2); + assert_eq!(v_b[1], 3); // Test on managed heap. let vec_managed = @[1, 2, 3, 4, 5]; let v_c = slice(vec_managed, 0u, 3u).to_vec(); - assert!(v_c.len() == 3u); - assert!(v_c[0] == 1); - assert!(v_c[1] == 2); - assert!(v_c[2] == 3); + assert_eq!(v_c.len(), 3u); + assert_eq!(v_c[0], 1); + assert_eq!(v_c[1], 2); + assert_eq!(v_c[2], 3); // Test on exchange heap. let vec_unique = ~[1, 2, 3, 4, 5, 6]; let v_d = slice(vec_unique, 1u, 6u).to_vec(); - assert!(v_d.len() == 5u); - assert!(v_d[0] == 2); - assert!(v_d[1] == 3); - assert!(v_d[2] == 4); - assert!(v_d[3] == 5); - assert!(v_d[4] == 6); + assert_eq!(v_d.len(), 5u); + assert_eq!(v_d[0], 2); + assert_eq!(v_d[1], 3); + assert_eq!(v_d[2], 4); + assert_eq!(v_d[3], 5); + assert_eq!(v_d[4], 6); } #[test] @@ -3369,27 +3226,27 @@ mod tests { // Test on-heap pop. let mut v = ~[1, 2, 3, 4, 5]; let e = v.pop(); - assert!(v.len() == 4u); - assert!(v[0] == 1); - assert!(v[1] == 2); - assert!(v[2] == 3); - assert!(v[3] == 4); - assert!(e == 5); + assert_eq!(v.len(), 4u); + assert_eq!(v[0], 1); + assert_eq!(v[1], 2); + assert_eq!(v[2], 3); + assert_eq!(v[3], 4); + assert_eq!(e, 5); } #[test] fn test_swap_remove() { let mut v = ~[1, 2, 3, 4, 5]; let mut e = v.swap_remove(0); - assert!(v.len() == 4); - assert!(e == 1); - assert!(v[0] == 5); + assert_eq!(v.len(), 4); + assert_eq!(e, 1); + assert_eq!(v[0], 5); e = v.swap_remove(3); - assert!(v.len() == 3); - assert!(e == 4); - assert!(v[0] == 5); - assert!(v[1] == 2); - assert!(v[2] == 3); + assert_eq!(v.len(), 3); + assert_eq!(e, 4); + assert_eq!(v[0], 5); + assert_eq!(v[1], 2); + assert_eq!(v[2], 3); } #[test] @@ -3399,11 +3256,11 @@ mod tests { ::unstable::sync::exclusive(()), ::unstable::sync::exclusive(())]; let mut _e = v.swap_remove(0); - assert!(v.len() == 2); + assert_eq!(v.len(), 2); _e = v.swap_remove(1); - assert!(v.len() == 1); + assert_eq!(v.len(), 1); _e = v.swap_remove(0); - assert!(v.len() == 0); + assert_eq!(v.len(), 0); } #[test] @@ -3411,14 +3268,14 @@ mod tests { // Test on-stack push(). let mut v = ~[]; v.push(1); - assert!(v.len() == 1u); - assert!(v[0] == 1); + assert_eq!(v.len(), 1u); + assert_eq!(v[0], 1); // Test on-heap push(). v.push(2); - assert!(v.len() == 2u); - assert!(v[0] == 1); - assert!(v[1] == 2); + assert_eq!(v.len(), 2u); + assert_eq!(v[0], 1); + assert_eq!(v[1], 2); } #[test] @@ -3426,48 +3283,48 @@ mod tests { // Test on-stack grow(). let mut v = ~[]; v.grow(2u, &1); - assert!(v.len() == 2u); - assert!(v[0] == 1); - assert!(v[1] == 1); + assert_eq!(v.len(), 2u); + assert_eq!(v[0], 1); + assert_eq!(v[1], 1); // Test on-heap grow(). v.grow(3u, &2); - assert!(v.len() == 5u); - assert!(v[0] == 1); - assert!(v[1] == 1); - assert!(v[2] == 2); - assert!(v[3] == 2); - assert!(v[4] == 2); + assert_eq!(v.len(), 5u); + assert_eq!(v[0], 1); + assert_eq!(v[1], 1); + assert_eq!(v[2], 2); + assert_eq!(v[3], 2); + assert_eq!(v[4], 2); } #[test] fn test_grow_fn() { let mut v = ~[]; v.grow_fn(3u, square); - assert!(v.len() == 3u); - assert!(v[0] == 0u); - assert!(v[1] == 1u); - assert!(v[2] == 4u); + assert_eq!(v.len(), 3u); + assert_eq!(v[0], 0u); + assert_eq!(v[1], 1u); + assert_eq!(v[2], 4u); } #[test] fn test_grow_set() { let mut v = ~[1, 2, 3]; v.grow_set(4u, &4, 5); - assert!(v.len() == 5u); - assert!(v[0] == 1); - assert!(v[1] == 2); - assert!(v[2] == 3); - assert!(v[3] == 4); - assert!(v[4] == 5); + assert_eq!(v.len(), 5u); + assert_eq!(v[0], 1); + assert_eq!(v[1], 2); + assert_eq!(v[2], 3); + assert_eq!(v[3], 4); + assert_eq!(v[4], 5); } #[test] fn test_truncate() { let mut v = ~[@6,@5,@4]; v.truncate(1); - assert!(v.len() == 1); - assert!(*(v[0]) == 6); + assert_eq!(v.len(), 1); + assert_eq!(*(v[0]), 6); // If the unsafe block didn't drop things properly, we blow up here. } @@ -3475,7 +3332,7 @@ mod tests { fn test_clear() { let mut v = ~[@6,@5,@4]; v.clear(); - assert!(v.len() == 0); + assert_eq!(v.len(), 0); // If the unsafe block didn't drop things properly, we blow up here. } @@ -3484,7 +3341,7 @@ mod tests { fn case(a: ~[uint], b: ~[uint]) { let mut v = a; v.dedup(); - assert!(v == b); + assert_eq!(v, b); } case(~[], ~[]); case(~[1], ~[1]); @@ -3529,20 +3386,20 @@ mod tests { // Test on-stack map. let mut v = ~[1u, 2u, 3u]; let mut w = map(v, square_ref); - assert!(w.len() == 3u); - assert!(w[0] == 1u); - assert!(w[1] == 4u); - assert!(w[2] == 9u); + assert_eq!(w.len(), 3u); + assert_eq!(w[0], 1u); + assert_eq!(w[1], 4u); + assert_eq!(w[2], 9u); // Test on-heap map. v = ~[1u, 2u, 3u, 4u, 5u]; w = map(v, square_ref); - assert!(w.len() == 5u); - assert!(w[0] == 1u); - assert!(w[1] == 4u); - assert!(w[2] == 9u); - assert!(w[3] == 16u); - assert!(w[4] == 25u); + assert_eq!(w.len(), 5u); + assert_eq!(w[0], 1u); + assert_eq!(w[1], 4u); + assert_eq!(w[2], 9u); + assert_eq!(w[3], 16u); + assert_eq!(w[4], 25u); } #[test] @@ -3561,17 +3418,17 @@ mod tests { // Test on-stack filter-map. let mut v = ~[1u, 2u, 3u]; let mut w = filter_mapped(v, square_if_odd_r); - assert!(w.len() == 2u); - assert!(w[0] == 1u); - assert!(w[1] == 9u); + assert_eq!(w.len(), 2u); + assert_eq!(w[0], 1u); + assert_eq!(w[1], 9u); // Test on-heap filter-map. v = ~[1u, 2u, 3u, 4u, 5u]; w = filter_mapped(v, square_if_odd_r); - assert!(w.len() == 3u); - assert!(w[0] == 1u); - assert!(w[1] == 9u); - assert!(w[2] == 25u); + assert_eq!(w.len(), 3u); + assert_eq!(w[0], 1u); + assert_eq!(w[1], 9u); + assert_eq!(w[2], 25u); fn halve(i: &int) -> Option { if *i % 2 == 0 { @@ -3588,9 +3445,9 @@ mod tests { let mix_dest: ~[int] = ~[1, 3, 0, 0]; assert!(filter_mapped(all_even, halve) == map(all_even, halve_for_sure)); - assert!(filter_mapped(all_odd1, halve) == ~[]); - assert!(filter_mapped(all_odd2, halve) == ~[]); - assert!(filter_mapped(mix, halve) == mix_dest); + assert_eq!(filter_mapped(all_odd1, halve), ~[]); + assert_eq!(filter_mapped(all_odd2, halve), ~[]); + assert_eq!(filter_mapped(mix, halve), mix_dest); } #[test] @@ -3598,17 +3455,17 @@ mod tests { // Test on-stack filter-map. let mut v = ~[1u, 2u, 3u]; let mut w = filter_map(v, square_if_odd_v); - assert!(w.len() == 2u); - assert!(w[0] == 1u); - assert!(w[1] == 9u); + assert_eq!(w.len(), 2u); + assert_eq!(w[0], 1u); + assert_eq!(w[1], 9u); // Test on-heap filter-map. v = ~[1u, 2u, 3u, 4u, 5u]; w = filter_map(v, square_if_odd_v); - assert!(w.len() == 3u); - assert!(w[0] == 1u); - assert!(w[1] == 9u); - assert!(w[2] == 25u); + assert_eq!(w.len(), 3u); + assert_eq!(w[0], 1u); + assert_eq!(w[1], 9u); + assert_eq!(w[2], 25u); fn halve(i: int) -> Option { if i % 2 == 0 { @@ -3626,22 +3483,22 @@ mod tests { let mix_dest: ~[int] = ~[1, 3, 0, 0]; assert!(filter_map(all_even, halve) == map(all_even0, halve_for_sure)); - assert!(filter_map(all_odd1, halve) == ~[]); - assert!(filter_map(all_odd2, halve) == ~[]); - assert!(filter_map(mix, halve) == mix_dest); + assert_eq!(filter_map(all_odd1, halve), ~[]); + assert_eq!(filter_map(all_odd2, halve), ~[]); + assert_eq!(filter_map(mix, halve), mix_dest); } #[test] fn test_filter() { - assert!(filter(~[1u, 2u, 3u], is_odd) == ~[1u, 3u]); - assert!(filter(~[1u, 2u, 4u, 8u, 16u], is_three) == ~[]); + assert_eq!(filter(~[1u, 2u, 3u], is_odd), ~[1u, 3u]); + assert_eq!(filter(~[1u, 2u, 4u, 8u, 16u], is_three), ~[]); } #[test] fn test_retain() { let mut v = ~[1, 2, 3, 4, 5]; v.retain(is_odd); - assert!(v == ~[1, 3, 5]); + assert_eq!(v, ~[1, 3, 5]); } #[test] @@ -3649,12 +3506,12 @@ mod tests { // Test on-stack fold. let mut v = ~[1u, 2u, 3u]; let mut sum = foldl(0u, v, add); - assert!(sum == 6u); + assert_eq!(sum, 6u); // Test on-heap fold. v = ~[1u, 2u, 3u, 4u, 5u]; sum = foldl(0u, v, add); - assert!(sum == 15u); + assert_eq!(sum, 15u); } #[test] @@ -3664,7 +3521,7 @@ mod tests { } let v = ~[1, 2, 3, 4]; let sum = foldl(0, v, sub); - assert!(sum == -10); + assert_eq!(sum, -10); } #[test] @@ -3674,12 +3531,12 @@ mod tests { } let v = ~[1, 2, 3, 4]; let sum = foldr(v, 0, sub); - assert!(sum == -2); + assert_eq!(sum, -2); } #[test] fn test_each_empty() { - for each::(~[]) |_v| { + for each::([]) |_v| { fail!(); // should never be executed } } @@ -3687,21 +3544,21 @@ mod tests { #[test] fn test_each_nonempty() { let mut i = 0; - for each(~[1, 2, 3]) |v| { + for each([1, 2, 3]) |v| { i += *v; } - assert!(i == 6); + assert_eq!(i, 6); } #[test] fn test_eachi() { let mut i = 0; - for eachi(~[1, 2, 3]) |j, v| { + for eachi([1, 2, 3]) |j, v| { if i == 0 { assert!(*v == 1); } - assert!(j + 1u == *v as uint); + assert_eq!(j + 1u, *v as uint); i += *v; } - assert!(i == 6); + assert_eq!(i, 6); } #[test] @@ -3715,22 +3572,22 @@ mod tests { #[test] fn test_each_reverse_nonempty() { let mut i = 0; - for each_reverse(~[1, 2, 3]) |v| { + for each_reverse([1, 2, 3]) |v| { if i == 0 { assert!(*v == 3); } i += *v } - assert!(i == 6); + assert_eq!(i, 6); } #[test] fn test_eachi_reverse() { let mut i = 0; - for eachi_reverse(~[0, 1, 2]) |j, v| { + for eachi_reverse([0, 1, 2]) |j, v| { if i == 0 { assert!(*v == 2); } - assert!(j == *v as uint); + assert_eq!(j, *v as uint); i += *v; } - assert!(i == 3); + assert_eq!(i, 3); } #[test] @@ -3741,53 +3598,70 @@ mod tests { } } + #[test] + fn test_each_ret_len0() { + let mut a0 : [int, .. 0] = []; + assert_eq!(each(a0, |_p| fail!()), true); + assert_eq!(each_mut(a0, |_p| fail!()), true); + } + + #[test] + fn test_each_ret_len1() { + let mut a1 = [17]; + assert_eq!(each(a1, |_p| true), true); + assert_eq!(each_mut(a1, |_p| true), true); + assert_eq!(each(a1, |_p| false), false); + assert_eq!(each_mut(a1, |_p| false), false); + } + + #[test] fn test_each_permutation() { let mut results: ~[~[int]]; results = ~[]; - for each_permutation(~[]) |v| { results.push(to_owned(v)); } - assert!(results == ~[~[]]); + for each_permutation([]) |v| { results.push(to_owned(v)); } + assert_eq!(results, ~[~[]]); results = ~[]; - for each_permutation(~[7]) |v| { results.push(to_owned(v)); } - assert!(results == ~[~[7]]); + for each_permutation([7]) |v| { results.push(to_owned(v)); } + assert_eq!(results, ~[~[7]]); results = ~[]; - for each_permutation(~[1,1]) |v| { results.push(to_owned(v)); } - assert!(results == ~[~[1,1],~[1,1]]); + for each_permutation([1,1]) |v| { results.push(to_owned(v)); } + assert_eq!(results, ~[~[1,1],~[1,1]]); results = ~[]; - for each_permutation(~[5,2,0]) |v| { results.push(to_owned(v)); } + for each_permutation([5,2,0]) |v| { results.push(to_owned(v)); } assert!(results == ~[~[5,2,0],~[5,0,2],~[2,5,0],~[2,0,5],~[0,5,2],~[0,2,5]]); } #[test] fn test_any_and_all() { - assert!(any(~[1u, 2u, 3u], is_three)); - assert!(!any(~[0u, 1u, 2u], is_three)); - assert!(any(~[1u, 2u, 3u, 4u, 5u], is_three)); - assert!(!any(~[1u, 2u, 4u, 5u, 6u], is_three)); + assert!(any([1u, 2u, 3u], is_three)); + assert!(!any([0u, 1u, 2u], is_three)); + assert!(any([1u, 2u, 3u, 4u, 5u], is_three)); + assert!(!any([1u, 2u, 4u, 5u, 6u], is_three)); - assert!(all(~[3u, 3u, 3u], is_three)); - assert!(!all(~[3u, 3u, 2u], is_three)); - assert!(all(~[3u, 3u, 3u, 3u, 3u], is_three)); - assert!(!all(~[3u, 3u, 0u, 1u, 2u], is_three)); + assert!(all([3u, 3u, 3u], is_three)); + assert!(!all([3u, 3u, 2u], is_three)); + assert!(all([3u, 3u, 3u, 3u, 3u], is_three)); + assert!(!all([3u, 3u, 0u, 1u, 2u], is_three)); } #[test] fn test_any2_and_all2() { - assert!(any2(~[2u, 4u, 6u], ~[2u, 4u, 6u], is_equal)); - assert!(any2(~[1u, 2u, 3u], ~[4u, 5u, 3u], is_equal)); - assert!(!any2(~[1u, 2u, 3u], ~[4u, 5u, 6u], is_equal)); - assert!(any2(~[2u, 4u, 6u], ~[2u, 4u], is_equal)); + assert!(any2([2u, 4u, 6u], [2u, 4u, 6u], is_equal)); + assert!(any2([1u, 2u, 3u], [4u, 5u, 3u], is_equal)); + assert!(!any2([1u, 2u, 3u], [4u, 5u, 6u], is_equal)); + assert!(any2([2u, 4u, 6u], [2u, 4u], is_equal)); - assert!(all2(~[2u, 4u, 6u], ~[2u, 4u, 6u], is_equal)); - assert!(!all2(~[1u, 2u, 3u], ~[4u, 5u, 3u], is_equal)); - assert!(!all2(~[1u, 2u, 3u], ~[4u, 5u, 6u], is_equal)); - assert!(!all2(~[2u, 4u, 6u], ~[2u, 4u], is_equal)); + assert!(all2([2u, 4u, 6u], [2u, 4u, 6u], is_equal)); + assert!(!all2([1u, 2u, 3u], [4u, 5u, 3u], is_equal)); + assert!(!all2([1u, 2u, 3u], [4u, 5u, 6u], is_equal)); + assert!(!all2([2u, 4u, 6u], [2u, 4u], is_equal)); } #[test] @@ -3797,25 +3671,25 @@ mod tests { let z1 = zip(v1, v2); - assert!((1, 4) == z1[0]); - assert!((2, 5) == z1[1]); - assert!((3, 6) == z1[2]); + assert_eq!((1, 4), z1[0]); + assert_eq!((2, 5), z1[1]); + assert_eq!((3, 6), z1[2]); let (left, right) = unzip(z1); - assert!((1, 4) == (left[0], right[0])); - assert!((2, 5) == (left[1], right[1])); - assert!((3, 6) == (left[2], right[2])); + assert_eq!((1, 4), (left[0], right[0])); + assert_eq!((2, 5), (left[1], right[1])); + assert_eq!((3, 6), (left[2], right[2])); } #[test] fn test_position_elem() { - assert!(position_elem(~[], &1).is_none()); + assert!(position_elem([], &1).is_none()); let v1 = ~[1, 2, 3, 3, 2, 5]; - assert!(position_elem(v1, &1) == Some(0u)); - assert!(position_elem(v1, &2) == Some(1u)); - assert!(position_elem(v1, &5) == Some(5u)); + assert_eq!(position_elem(v1, &1), Some(0u)); + assert_eq!(position_elem(v1, &2), Some(1u)); + assert_eq!(position_elem(v1, &5), Some(5u)); assert!(position_elem(v1, &4).is_none()); } @@ -3824,254 +3698,254 @@ mod tests { fn less_than_three(i: &int) -> bool { *i < 3 } fn is_eighteen(i: &int) -> bool { *i == 18 } - assert!(position(~[], less_than_three).is_none()); + assert!(position([], less_than_three).is_none()); let v1 = ~[5, 4, 3, 2, 1]; - assert!(position(v1, less_than_three) == Some(3u)); + assert_eq!(position(v1, less_than_three), Some(3u)); assert!(position(v1, is_eighteen).is_none()); } #[test] fn test_position_between() { - assert!(position_between(~[], 0u, 0u, f).is_none()); + assert!(position_between([], 0u, 0u, f).is_none()); fn f(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'b' } let v = ~[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')]; assert!(position_between(v, 0u, 0u, f).is_none()); assert!(position_between(v, 0u, 1u, f).is_none()); - assert!(position_between(v, 0u, 2u, f) == Some(1u)); - assert!(position_between(v, 0u, 3u, f) == Some(1u)); - assert!(position_between(v, 0u, 4u, f) == Some(1u)); + assert_eq!(position_between(v, 0u, 2u, f), Some(1u)); + assert_eq!(position_between(v, 0u, 3u, f), Some(1u)); + assert_eq!(position_between(v, 0u, 4u, f), Some(1u)); assert!(position_between(v, 1u, 1u, f).is_none()); - assert!(position_between(v, 1u, 2u, f) == Some(1u)); - assert!(position_between(v, 1u, 3u, f) == Some(1u)); - assert!(position_between(v, 1u, 4u, f) == Some(1u)); + assert_eq!(position_between(v, 1u, 2u, f), Some(1u)); + assert_eq!(position_between(v, 1u, 3u, f), Some(1u)); + assert_eq!(position_between(v, 1u, 4u, f), Some(1u)); assert!(position_between(v, 2u, 2u, f).is_none()); assert!(position_between(v, 2u, 3u, f).is_none()); - assert!(position_between(v, 2u, 4u, f) == Some(3u)); + assert_eq!(position_between(v, 2u, 4u, f), Some(3u)); assert!(position_between(v, 3u, 3u, f).is_none()); - assert!(position_between(v, 3u, 4u, f) == Some(3u)); + assert_eq!(position_between(v, 3u, 4u, f), Some(3u)); assert!(position_between(v, 4u, 4u, f).is_none()); } #[test] fn test_find() { - assert!(find(~[], f).is_none()); + assert!(find([], f).is_none()); fn f(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'b' } fn g(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'd' } let v = ~[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')]; - assert!(find(v, f) == Some((1, 'b'))); + assert_eq!(find(v, f), Some((1, 'b'))); assert!(find(v, g).is_none()); } #[test] fn test_find_between() { - assert!(find_between(~[], 0u, 0u, f).is_none()); + assert!(find_between([], 0u, 0u, f).is_none()); fn f(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'b' } let v = ~[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')]; assert!(find_between(v, 0u, 0u, f).is_none()); assert!(find_between(v, 0u, 1u, f).is_none()); - assert!(find_between(v, 0u, 2u, f) == Some((1, 'b'))); - assert!(find_between(v, 0u, 3u, f) == Some((1, 'b'))); - assert!(find_between(v, 0u, 4u, f) == Some((1, 'b'))); + assert_eq!(find_between(v, 0u, 2u, f), Some((1, 'b'))); + assert_eq!(find_between(v, 0u, 3u, f), Some((1, 'b'))); + assert_eq!(find_between(v, 0u, 4u, f), Some((1, 'b'))); assert!(find_between(v, 1u, 1u, f).is_none()); - assert!(find_between(v, 1u, 2u, f) == Some((1, 'b'))); - assert!(find_between(v, 1u, 3u, f) == Some((1, 'b'))); - assert!(find_between(v, 1u, 4u, f) == Some((1, 'b'))); + assert_eq!(find_between(v, 1u, 2u, f), Some((1, 'b'))); + assert_eq!(find_between(v, 1u, 3u, f), Some((1, 'b'))); + assert_eq!(find_between(v, 1u, 4u, f), Some((1, 'b'))); assert!(find_between(v, 2u, 2u, f).is_none()); assert!(find_between(v, 2u, 3u, f).is_none()); - assert!(find_between(v, 2u, 4u, f) == Some((3, 'b'))); + assert_eq!(find_between(v, 2u, 4u, f), Some((3, 'b'))); assert!(find_between(v, 3u, 3u, f).is_none()); - assert!(find_between(v, 3u, 4u, f) == Some((3, 'b'))); + assert_eq!(find_between(v, 3u, 4u, f), Some((3, 'b'))); assert!(find_between(v, 4u, 4u, f).is_none()); } #[test] fn test_rposition() { - assert!(find(~[], f).is_none()); + assert!(find([], f).is_none()); fn f(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'b' } fn g(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'd' } let v = ~[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')]; - assert!(position(v, f) == Some(1u)); + assert_eq!(position(v, f), Some(1u)); assert!(position(v, g).is_none()); } #[test] fn test_rposition_between() { - assert!(rposition_between(~[], 0u, 0u, f).is_none()); + assert!(rposition_between([], 0u, 0u, f).is_none()); fn f(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'b' } let v = ~[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')]; assert!(rposition_between(v, 0u, 0u, f).is_none()); assert!(rposition_between(v, 0u, 1u, f).is_none()); - assert!(rposition_between(v, 0u, 2u, f) == Some(1u)); - assert!(rposition_between(v, 0u, 3u, f) == Some(1u)); - assert!(rposition_between(v, 0u, 4u, f) == Some(3u)); + assert_eq!(rposition_between(v, 0u, 2u, f), Some(1u)); + assert_eq!(rposition_between(v, 0u, 3u, f), Some(1u)); + assert_eq!(rposition_between(v, 0u, 4u, f), Some(3u)); assert!(rposition_between(v, 1u, 1u, f).is_none()); - assert!(rposition_between(v, 1u, 2u, f) == Some(1u)); - assert!(rposition_between(v, 1u, 3u, f) == Some(1u)); - assert!(rposition_between(v, 1u, 4u, f) == Some(3u)); + assert_eq!(rposition_between(v, 1u, 2u, f), Some(1u)); + assert_eq!(rposition_between(v, 1u, 3u, f), Some(1u)); + assert_eq!(rposition_between(v, 1u, 4u, f), Some(3u)); assert!(rposition_between(v, 2u, 2u, f).is_none()); assert!(rposition_between(v, 2u, 3u, f).is_none()); - assert!(rposition_between(v, 2u, 4u, f) == Some(3u)); + assert_eq!(rposition_between(v, 2u, 4u, f), Some(3u)); assert!(rposition_between(v, 3u, 3u, f).is_none()); - assert!(rposition_between(v, 3u, 4u, f) == Some(3u)); + assert_eq!(rposition_between(v, 3u, 4u, f), Some(3u)); assert!(rposition_between(v, 4u, 4u, f).is_none()); } #[test] fn test_rfind() { - assert!(rfind(~[], f).is_none()); + assert!(rfind([], f).is_none()); fn f(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'b' } fn g(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'd' } let v = ~[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')]; - assert!(rfind(v, f) == Some((3, 'b'))); + assert_eq!(rfind(v, f), Some((3, 'b'))); assert!(rfind(v, g).is_none()); } #[test] fn test_rfind_between() { - assert!(rfind_between(~[], 0u, 0u, f).is_none()); + assert!(rfind_between([], 0u, 0u, f).is_none()); fn f(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'b' } let v = ~[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')]; assert!(rfind_between(v, 0u, 0u, f).is_none()); assert!(rfind_between(v, 0u, 1u, f).is_none()); - assert!(rfind_between(v, 0u, 2u, f) == Some((1, 'b'))); - assert!(rfind_between(v, 0u, 3u, f) == Some((1, 'b'))); - assert!(rfind_between(v, 0u, 4u, f) == Some((3, 'b'))); + assert_eq!(rfind_between(v, 0u, 2u, f), Some((1, 'b'))); + assert_eq!(rfind_between(v, 0u, 3u, f), Some((1, 'b'))); + assert_eq!(rfind_between(v, 0u, 4u, f), Some((3, 'b'))); assert!(rfind_between(v, 1u, 1u, f).is_none()); - assert!(rfind_between(v, 1u, 2u, f) == Some((1, 'b'))); - assert!(rfind_between(v, 1u, 3u, f) == Some((1, 'b'))); - assert!(rfind_between(v, 1u, 4u, f) == Some((3, 'b'))); + assert_eq!(rfind_between(v, 1u, 2u, f), Some((1, 'b'))); + assert_eq!(rfind_between(v, 1u, 3u, f), Some((1, 'b'))); + assert_eq!(rfind_between(v, 1u, 4u, f), Some((3, 'b'))); assert!(rfind_between(v, 2u, 2u, f).is_none()); assert!(rfind_between(v, 2u, 3u, f).is_none()); - assert!(rfind_between(v, 2u, 4u, f) == Some((3, 'b'))); + assert_eq!(rfind_between(v, 2u, 4u, f), Some((3, 'b'))); assert!(rfind_between(v, 3u, 3u, f).is_none()); - assert!(rfind_between(v, 3u, 4u, f) == Some((3, 'b'))); + assert_eq!(rfind_between(v, 3u, 4u, f), Some((3, 'b'))); assert!(rfind_between(v, 4u, 4u, f).is_none()); } #[test] fn test_bsearch_elem() { - assert!(bsearch_elem([1,2,3,4,5], &5) == Some(4)); - assert!(bsearch_elem([1,2,3,4,5], &4) == Some(3)); - assert!(bsearch_elem([1,2,3,4,5], &3) == Some(2)); - assert!(bsearch_elem([1,2,3,4,5], &2) == Some(1)); - assert!(bsearch_elem([1,2,3,4,5], &1) == Some(0)); - - assert!(bsearch_elem([2,4,6,8,10], &1) == None); - assert!(bsearch_elem([2,4,6,8,10], &5) == None); - assert!(bsearch_elem([2,4,6,8,10], &4) == Some(1)); - assert!(bsearch_elem([2,4,6,8,10], &10) == Some(4)); - - assert!(bsearch_elem([2,4,6,8], &1) == None); - assert!(bsearch_elem([2,4,6,8], &5) == None); - assert!(bsearch_elem([2,4,6,8], &4) == Some(1)); - assert!(bsearch_elem([2,4,6,8], &8) == Some(3)); - - assert!(bsearch_elem([2,4,6], &1) == None); - assert!(bsearch_elem([2,4,6], &5) == None); - assert!(bsearch_elem([2,4,6], &4) == Some(1)); - assert!(bsearch_elem([2,4,6], &6) == Some(2)); - - assert!(bsearch_elem([2,4], &1) == None); - assert!(bsearch_elem([2,4], &5) == None); - assert!(bsearch_elem([2,4], &2) == Some(0)); - assert!(bsearch_elem([2,4], &4) == Some(1)); - - assert!(bsearch_elem([2], &1) == None); - assert!(bsearch_elem([2], &5) == None); - assert!(bsearch_elem([2], &2) == Some(0)); - - assert!(bsearch_elem([], &1) == None); - assert!(bsearch_elem([], &5) == None); + assert_eq!(bsearch_elem([1,2,3,4,5], &5), Some(4)); + assert_eq!(bsearch_elem([1,2,3,4,5], &4), Some(3)); + assert_eq!(bsearch_elem([1,2,3,4,5], &3), Some(2)); + assert_eq!(bsearch_elem([1,2,3,4,5], &2), Some(1)); + assert_eq!(bsearch_elem([1,2,3,4,5], &1), Some(0)); + + assert_eq!(bsearch_elem([2,4,6,8,10], &1), None); + assert_eq!(bsearch_elem([2,4,6,8,10], &5), None); + assert_eq!(bsearch_elem([2,4,6,8,10], &4), Some(1)); + assert_eq!(bsearch_elem([2,4,6,8,10], &10), Some(4)); + + assert_eq!(bsearch_elem([2,4,6,8], &1), None); + assert_eq!(bsearch_elem([2,4,6,8], &5), None); + assert_eq!(bsearch_elem([2,4,6,8], &4), Some(1)); + assert_eq!(bsearch_elem([2,4,6,8], &8), Some(3)); + + assert_eq!(bsearch_elem([2,4,6], &1), None); + assert_eq!(bsearch_elem([2,4,6], &5), None); + assert_eq!(bsearch_elem([2,4,6], &4), Some(1)); + assert_eq!(bsearch_elem([2,4,6], &6), Some(2)); + + assert_eq!(bsearch_elem([2,4], &1), None); + assert_eq!(bsearch_elem([2,4], &5), None); + assert_eq!(bsearch_elem([2,4], &2), Some(0)); + assert_eq!(bsearch_elem([2,4], &4), Some(1)); + + assert_eq!(bsearch_elem([2], &1), None); + assert_eq!(bsearch_elem([2], &5), None); + assert_eq!(bsearch_elem([2], &2), Some(0)); + + assert_eq!(bsearch_elem([], &1), None); + assert_eq!(bsearch_elem([], &5), None); assert!(bsearch_elem([1,1,1,1,1], &1) != None); assert!(bsearch_elem([1,1,1,1,2], &1) != None); assert!(bsearch_elem([1,1,1,2,2], &1) != None); assert!(bsearch_elem([1,1,2,2,2], &1) != None); - assert!(bsearch_elem([1,2,2,2,2], &1) == Some(0)); + assert_eq!(bsearch_elem([1,2,2,2,2], &1), Some(0)); - assert!(bsearch_elem([1,2,3,4,5], &6) == None); - assert!(bsearch_elem([1,2,3,4,5], &0) == None); + assert_eq!(bsearch_elem([1,2,3,4,5], &6), None); + assert_eq!(bsearch_elem([1,2,3,4,5], &0), None); } #[test] fn reverse_and_reversed() { let mut v: ~[int] = ~[10, 20]; - assert!(v[0] == 10); - assert!(v[1] == 20); + assert_eq!(v[0], 10); + assert_eq!(v[1], 20); reverse(v); - assert!(v[0] == 20); - assert!(v[1] == 10); - let v2 = reversed::(~[10, 20]); - assert!(v2[0] == 20); - assert!(v2[1] == 10); + assert_eq!(v[0], 20); + assert_eq!(v[1], 10); + let v2 = reversed::([10, 20]); + assert_eq!(v2[0], 20); + assert_eq!(v2[1], 10); v[0] = 30; - assert!(v2[0] == 20); + assert_eq!(v2[0], 20); // Make sure they work with 0-length vectors too. - let v4 = reversed::(~[]); - assert!(v4 == ~[]); + let v4 = reversed::([]); + assert_eq!(v4, ~[]); let mut v3: ~[int] = ~[]; reverse::(v3); } #[test] fn reversed_mut() { - let v2 = reversed::(~[10, 20]); - assert!(v2[0] == 20); - assert!(v2[1] == 10); + let v2 = reversed::([10, 20]); + assert_eq!(v2[0], 20); + assert_eq!(v2[1], 10); } #[test] fn test_split() { fn f(x: &int) -> bool { *x == 3 } - assert!(split(~[], f) == ~[]); - assert!(split(~[1, 2], f) == ~[~[1, 2]]); - assert!(split(~[3, 1, 2], f) == ~[~[], ~[1, 2]]); - assert!(split(~[1, 2, 3], f) == ~[~[1, 2], ~[]]); - assert!(split(~[1, 2, 3, 4, 3, 5], f) == ~[~[1, 2], ~[4], ~[5]]); + assert_eq!(split([], f), ~[]); + assert_eq!(split([1, 2], f), ~[~[1, 2]]); + assert_eq!(split([3, 1, 2], f), ~[~[], ~[1, 2]]); + assert_eq!(split([1, 2, 3], f), ~[~[1, 2], ~[]]); + assert_eq!(split([1, 2, 3, 4, 3, 5], f), ~[~[1, 2], ~[4], ~[5]]); } #[test] fn test_splitn() { fn f(x: &int) -> bool { *x == 3 } - assert!(splitn(~[], 1u, f) == ~[]); - assert!(splitn(~[1, 2], 1u, f) == ~[~[1, 2]]); - assert!(splitn(~[3, 1, 2], 1u, f) == ~[~[], ~[1, 2]]); - assert!(splitn(~[1, 2, 3], 1u, f) == ~[~[1, 2], ~[]]); - assert!(splitn(~[1, 2, 3, 4, 3, 5], 1u, f) == + assert_eq!(splitn([], 1u, f), ~[]); + assert_eq!(splitn([1, 2], 1u, f), ~[~[1, 2]]); + assert_eq!(splitn([3, 1, 2], 1u, f), ~[~[], ~[1, 2]]); + assert_eq!(splitn([1, 2, 3], 1u, f), ~[~[1, 2], ~[]]); + assert!(splitn([1, 2, 3, 4, 3, 5], 1u, f) == ~[~[1, 2], ~[4, 3, 5]]); } @@ -4079,10 +3953,10 @@ mod tests { fn test_rsplit() { fn f(x: &int) -> bool { *x == 3 } - assert!(rsplit(~[], f) == ~[]); - assert!(rsplit(~[1, 2], f) == ~[~[1, 2]]); - assert!(rsplit(~[1, 2, 3], f) == ~[~[1, 2], ~[]]); - assert!(rsplit(~[1, 2, 3, 4, 3, 5], f) == + assert_eq!(rsplit([], f), ~[]); + assert_eq!(rsplit([1, 2], f), ~[~[1, 2]]); + assert_eq!(rsplit([1, 2, 3], f), ~[~[1, 2], ~[]]); + assert!(rsplit([1, 2, 3, 4, 3, 5], f) == ~[~[1, 2], ~[4], ~[5]]); } @@ -4090,53 +3964,58 @@ mod tests { fn test_rsplitn() { fn f(x: &int) -> bool { *x == 3 } - assert!(rsplitn(~[], 1u, f) == ~[]); - assert!(rsplitn(~[1, 2], 1u, f) == ~[~[1, 2]]); - assert!(rsplitn(~[1, 2, 3], 1u, f) == ~[~[1, 2], ~[]]); - assert!(rsplitn(~[1, 2, 3, 4, 3, 5], 1u, f) == - ~[~[1, 2, 3, 4], ~[5]]); + assert_eq!(rsplitn([], 1u, f), ~[]); + assert_eq!(rsplitn([1, 2], 1u, f), ~[~[1, 2]]); + assert_eq!(rsplitn([1, 2, 3], 1u, f), ~[~[1, 2], ~[]]); + assert_eq!(rsplitn([1, 2, 3, 4, 3, 5], 1u, f), ~[~[1, 2, 3, 4], ~[5]]); } #[test] fn test_partition() { // FIXME (#4355 maybe): using v.partition here crashes - assert!(partition(~[], |x: &int| *x < 3) == (~[], ~[])); - assert!(partition(~[1, 2, 3], |x: &int| *x < 4) == - (~[1, 2, 3], ~[])); - assert!(partition(~[1, 2, 3], |x: &int| *x < 2) == - (~[1], ~[2, 3])); - assert!(partition(~[1, 2, 3], |x: &int| *x < 0) == - (~[], ~[1, 2, 3])); + assert_eq!(partition(~[], |x: &int| *x < 3), (~[], ~[])); + assert_eq!(partition(~[1, 2, 3], |x: &int| *x < 4), (~[1, 2, 3], ~[])); + assert_eq!(partition(~[1, 2, 3], |x: &int| *x < 2), (~[1], ~[2, 3])); + assert_eq!(partition(~[1, 2, 3], |x: &int| *x < 0), (~[], ~[1, 2, 3])); } #[test] fn test_partitioned() { - assert!((~[]).partitioned(|x: &int| *x < 3) == (~[], ~[])); - assert!((~[1, 2, 3]).partitioned(|x: &int| *x < 4) == - (~[1, 2, 3], ~[])); - assert!((~[1, 2, 3]).partitioned(|x: &int| *x < 2) == - (~[1], ~[2, 3])); - assert!((~[1, 2, 3]).partitioned(|x: &int| *x < 0) == - (~[], ~[1, 2, 3])); + assert_eq!(([]).partitioned(|x: &int| *x < 3), (~[], ~[])) + assert_eq!(([1, 2, 3]).partitioned(|x: &int| *x < 4), (~[1, 2, 3], ~[])); + assert_eq!(([1, 2, 3]).partitioned(|x: &int| *x < 2), (~[1], ~[2, 3])); + assert_eq!(([1, 2, 3]).partitioned(|x: &int| *x < 0), (~[], ~[1, 2, 3])); } #[test] fn test_concat() { - assert!(concat(~[~[1], ~[2,3]]) == ~[1, 2, 3]); + assert_eq!(concat([~[1], ~[2,3]]), ~[1, 2, 3]); + assert_eq!([~[1], ~[2,3]].concat(), ~[1, 2, 3]); + + assert_eq!(concat_slices([&[1], &[2,3]]), ~[1, 2, 3]); + assert_eq!([&[1], &[2,3]].concat(), ~[1, 2, 3]); } #[test] fn test_connect() { - assert!(connect(~[], &0) == ~[]); - assert!(connect(~[~[1], ~[2, 3]], &0) == ~[1, 0, 2, 3]); - assert!(connect(~[~[1], ~[2], ~[3]], &0) == ~[1, 0, 2, 0, 3]); + assert_eq!(connect([], &0), ~[]); + assert_eq!(connect([~[1], ~[2, 3]], &0), ~[1, 0, 2, 3]); + assert_eq!(connect([~[1], ~[2], ~[3]], &0), ~[1, 0, 2, 0, 3]); + assert_eq!([~[1], ~[2, 3]].connect(&0), ~[1, 0, 2, 3]); + assert_eq!([~[1], ~[2], ~[3]].connect(&0), ~[1, 0, 2, 0, 3]); + + assert_eq!(connect_slices([], &0), ~[]); + assert_eq!(connect_slices([&[1], &[2, 3]], &0), ~[1, 0, 2, 3]); + assert_eq!(connect_slices([&[1], &[2], &[3]], &0), ~[1, 0, 2, 0, 3]); + assert_eq!([&[1], &[2, 3]].connect(&0), ~[1, 0, 2, 3]); + assert_eq!([&[1], &[2], &[3]].connect(&0), ~[1, 0, 2, 0, 3]); } #[test] fn test_windowed () { fn t(n: uint, expected: &[&[int]]) { let mut i = 0; - for windowed(n, ~[1,2,3,4,5,6]) |v| { + for windowed(n, [1,2,3,4,5,6]) |v| { assert_eq!(v, expected[i]); i += 1; } @@ -4154,33 +4033,33 @@ mod tests { #[should_fail] #[ignore(cfg(windows))] fn test_windowed_() { - for windowed (0u, ~[1u,2u,3u,4u,5u,6u]) |_v| {} + for windowed (0u, [1u,2u,3u,4u,5u,6u]) |_v| {} } #[test] fn test_unshift() { let mut x = ~[1, 2, 3]; x.unshift(0); - assert!(x == ~[0, 1, 2, 3]); + assert_eq!(x, ~[0, 1, 2, 3]); } #[test] fn test_insert() { let mut a = ~[1, 2, 4]; a.insert(2, 3); - assert!(a == ~[1, 2, 3, 4]); + assert_eq!(a, ~[1, 2, 3, 4]); let mut a = ~[1, 2, 3]; a.insert(0, 0); - assert!(a == ~[0, 1, 2, 3]); + assert_eq!(a, ~[0, 1, 2, 3]); let mut a = ~[1, 2, 3]; a.insert(3, 4); - assert!(a == ~[1, 2, 3, 4]); + assert_eq!(a, ~[1, 2, 3, 4]); let mut a = ~[]; a.insert(0, 1); - assert!(a == ~[1]); + assert_eq!(a, ~[1]); } #[test] @@ -4195,15 +4074,15 @@ mod tests { fn test_remove() { let mut a = ~[1, 2, 3, 4]; a.remove(2); - assert!(a == ~[1, 2, 4]); + assert_eq!(a, ~[1, 2, 4]); let mut a = ~[1, 2, 3]; a.remove(0); - assert!(a == ~[2, 3]); + assert_eq!(a, ~[2, 3]); let mut a = ~[1]; a.remove(0); - assert!(a == ~[]); + assert_eq!(a, ~[]); } #[test] @@ -4218,19 +4097,19 @@ mod tests { fn test_capacity() { let mut v = ~[0u64]; reserve(&mut v, 10u); - assert!(capacity(&v) == 10u); + assert_eq!(capacity(&v), 10u); let mut v = ~[0u32]; reserve(&mut v, 10u); - assert!(capacity(&v) == 10u); + assert_eq!(capacity(&v), 10u); } #[test] fn test_slice_2() { let v = ~[1, 2, 3, 4, 5]; let v = v.slice(1u, 3u); - assert!(v.len() == 2u); - assert!(v[0] == 2); - assert!(v[1] == 3); + assert_eq!(v.len(), 2u); + assert_eq!(v[0], 2); + assert_eq!(v[1], 3); } @@ -4844,6 +4723,6 @@ mod tests { for [1, 2, 3].each_val |v| { i += v; } - assert!(i == 6); + assert_eq!(i, 6); } } diff --git a/src/libsyntax/abi.rs b/src/libsyntax/abi.rs index 1b166dcf36618..75439dfaa786c 100644 --- a/src/libsyntax/abi.rs +++ b/src/libsyntax/abi.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + +use core::str; use core::to_bytes; #[deriving(Eq)] @@ -79,20 +82,6 @@ static AbiDatas: &'static [AbiData] = &[ AbiData {abi: RustIntrinsic, name: "rust-intrinsic", abi_arch: RustArch}, ]; -#[cfg(stage0)] -fn each_abi(op: &fn(abi: Abi) -> bool) { - /*! - * - * Iterates through each of the defined ABIs. - */ - - for AbiDatas.each |abi_data| { - if !op(abi_data.abi) { - return; - } - } -} -#[cfg(not(stage0))] fn each_abi(op: &fn(abi: Abi) -> bool) -> bool { /*! * @@ -120,18 +109,18 @@ pub fn all_names() -> ~[&'static str] { AbiDatas.map(|d| d.name) } -pub impl Abi { +impl Abi { #[inline] - fn index(&self) -> uint { + pub fn index(&self) -> uint { *self as uint } #[inline] - fn data(&self) -> &'static AbiData { + pub fn data(&self) -> &'static AbiData { &AbiDatas[self.index()] } - fn name(&self) -> &'static str { + pub fn name(&self) -> &'static str { self.data().name } } @@ -142,81 +131,70 @@ impl Architecture { } } -pub impl AbiSet { - fn from(abi: Abi) -> AbiSet { +impl AbiSet { + pub fn from(abi: Abi) -> AbiSet { AbiSet { bits: (1 << abi.index()) } } #[inline] - fn Rust() -> AbiSet { + pub fn Rust() -> AbiSet { AbiSet::from(Rust) } #[inline] - fn C() -> AbiSet { + pub fn C() -> AbiSet { AbiSet::from(C) } #[inline] - fn Intrinsic() -> AbiSet { + pub fn Intrinsic() -> AbiSet { AbiSet::from(RustIntrinsic) } - fn default() -> AbiSet { + pub fn default() -> AbiSet { AbiSet::C() } - fn empty() -> AbiSet { + pub fn empty() -> AbiSet { AbiSet { bits: 0 } } #[inline] - fn is_rust(&self) -> bool { + pub fn is_rust(&self) -> bool { self.bits == 1 << Rust.index() } #[inline] - fn is_c(&self) -> bool { + pub fn is_c(&self) -> bool { self.bits == 1 << C.index() } #[inline] - fn is_intrinsic(&self) -> bool { + pub fn is_intrinsic(&self) -> bool { self.bits == 1 << RustIntrinsic.index() } - fn contains(&self, abi: Abi) -> bool { + pub fn contains(&self, abi: Abi) -> bool { (self.bits & (1 << abi.index())) != 0 } - fn subset_of(&self, other_abi_set: AbiSet) -> bool { + pub fn subset_of(&self, other_abi_set: AbiSet) -> bool { (self.bits & other_abi_set.bits) == self.bits } - fn add(&mut self, abi: Abi) { + pub fn add(&mut self, abi: Abi) { self.bits |= (1 << abi.index()); } - #[cfg(stage0)] - fn each(&self, op: &fn(abi: Abi) -> bool) { - for each_abi |abi| { - if self.contains(abi) { - if !op(abi) { - return; - } - } - } - } - #[cfg(not(stage0))] - fn each(&self, op: &fn(abi: Abi) -> bool) -> bool { + pub fn each(&self, op: &fn(abi: Abi) -> bool) -> bool { each_abi(|abi| !self.contains(abi) || op(abi)) } - fn is_empty(&self) -> bool { + pub fn is_empty(&self) -> bool { self.bits == 0 } - fn for_arch(&self, arch: Architecture) -> Option { + pub fn for_arch(&self, arch: Architecture) -> Option { // NB---Single platform ABIs come first for self.each |abi| { let data = abi.data(); @@ -230,7 +208,7 @@ pub impl AbiSet { None } - fn check_valid(&self) -> Option<(Abi, Abi)> { + pub fn check_valid(&self) -> Option<(Abi, Abi)> { let mut abis = ~[]; for self.each |abi| { abis.push(abi); } @@ -265,26 +243,12 @@ pub impl AbiSet { } } -#[cfg(stage0)] -impl to_bytes::IterBytes for Abi { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - self.index().iter_bytes(lsb0, f) - } -} -#[cfg(not(stage0))] impl to_bytes::IterBytes for Abi { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { self.index().iter_bytes(lsb0, f) } } -#[cfg(stage0)] -impl to_bytes::IterBytes for AbiSet { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - self.bits.iter_bytes(lsb0, f) - } -} -#[cfg(not(stage0))] impl to_bytes::IterBytes for AbiSet { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { self.bits.iter_bytes(lsb0, f) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index dcbbd7ab53111..5bbc5d4e819e0 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -10,24 +10,30 @@ // The Rust abstract syntax tree. +use core::prelude::*; + use codemap::{span, spanned}; use abi::AbiSet; use opt_vec::OptVec; +use parse::token::{ident_to_str, interner_get, str_to_ident}; -use core::cast; -use core::option::{None, Option, Some}; -use core::to_bytes; +use core::hashmap::HashMap; +use core::option::Option; use core::to_bytes::IterBytes; +use core::to_bytes; use core::to_str::ToStr; -use std::serialize::{Encodable, Decodable, Encoder, Decoder}; +use extra::serialize::{Encodable, Decodable, Encoder, Decoder}; -// an identifier contains an index into the interner -// table and a SyntaxContext to track renaming and +// an identifier contains a Name (index into the interner +// table) and a SyntaxContext to track renaming and // macro expansion per Flatt et al., "Macros // That Work Together" #[deriving(Eq)] -pub struct ident { repr: Name, ctxt: SyntaxContext } +pub struct ident { name: Name, ctxt: SyntaxContext } + +/// Construct an identifier with the given name and an empty context: +pub fn new_ident(name: Name) -> ident { ident {name: name, ctxt: empty_ctxt}} // a SyntaxContext represents a chain of macro-expandings // and renamings. Each macro expansion corresponds to @@ -38,14 +44,20 @@ pub struct ident { repr: Name, ctxt: SyntaxContext } // that's causing unreleased memory to cause core dumps // and also perhaps to save some work in destructor checks. // the special uint '0' will be used to indicate an empty -// syntax context +// syntax context. // this uint is a reference to a table stored in thread-local // storage. pub type SyntaxContext = uint; -pub type SCTable = ~[SyntaxContext_]; +pub struct SCTable { + table : ~[SyntaxContext_], + mark_memo : HashMap<(SyntaxContext,Mrk),SyntaxContext>, + rename_memo : HashMap<(SyntaxContext,ident,Name),SyntaxContext> +} +// NB: these must be placed in any SCTable... pub static empty_ctxt : uint = 0; +pub static illegal_ctxt : uint = 1; #[deriving(Eq, Encodable, Decodable)] pub enum SyntaxContext_ { @@ -59,10 +71,12 @@ pub enum SyntaxContext_ { // "to" slot must have the same name and context // in the "from" slot. In essence, they're all // pointers to a single "rename" event node. - Rename (ident,Name,SyntaxContext) + Rename (ident,Name,SyntaxContext), + IllegalCtxt() } -// a name represents an identifier +// a name is a part of an identifier, representing a string +// or gensym. It's the result of interning. pub type Name = uint; // a mark represents a unique id associated // with a macro expansion @@ -70,43 +84,20 @@ pub type Mrk = uint; impl Encodable for ident { fn encode(&self, s: &mut S) { - unsafe { - let intr = - match local_data::local_data_get(interner_key!()) { - None => fail!("encode: TLS interner not set up"), - Some(intr) => intr - }; - - s.emit_str(*(*intr).get(*self)); - } + s.emit_str(*interner_get(self.name)); } } impl Decodable for ident { fn decode(d: &mut D) -> ident { - let intr = match unsafe { - local_data::local_data_get(interner_key!()) - } { - None => fail!("decode: TLS interner not set up"), - Some(intr) => intr - }; - - (*intr).intern(d.read_str()) + str_to_ident(d.read_str()) } } -#[cfg(stage0)] -impl to_bytes::IterBytes for ident { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - self.repr.iter_bytes(lsb0, f) - } -} -#[cfg(not(stage0))] impl to_bytes::IterBytes for ident { #[inline(always)] fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { - self.repr.iter_bytes(lsb0, f) + self.name.iter_bytes(lsb0, f) } } @@ -120,17 +111,11 @@ pub struct Lifetime { ident: ident } -#[cfg(stage0)] -impl to_bytes::IterBytes for Lifetime { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - to_bytes::iter_bytes_3(&self.id, &self.span, &self.ident, lsb0, f) - } -} - -#[cfg(not(stage0))] impl to_bytes::IterBytes for Lifetime { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { - to_bytes::iter_bytes_3(&self.id, &self.span, &self.ident, lsb0, f) + self.id.iter_bytes(lsb0, f) && + self.span.iter_bytes(lsb0, f) && + self.ident.iter_bytes(lsb0, f) } } @@ -183,14 +168,14 @@ pub struct Generics { ty_params: OptVec } -pub impl Generics { - fn is_parameterized(&self) -> bool { +impl Generics { + pub fn is_parameterized(&self) -> bool { self.lifetimes.len() + self.ty_params.len() > 0 } - fn is_lt_parameterized(&self) -> bool { + pub fn is_lt_parameterized(&self) -> bool { self.lifetimes.len() > 0 } - fn is_type_parameterized(&self) -> bool { + pub fn is_type_parameterized(&self) -> bool { self.ty_params.len() > 0 } } @@ -274,34 +259,20 @@ pub struct field_pat { #[deriving(Eq, Encodable, Decodable)] pub enum binding_mode { - bind_by_copy, bind_by_ref(mutability), bind_infer } -#[cfg(stage0)] -impl to_bytes::IterBytes for binding_mode { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - match *self { - bind_by_copy => 0u8.iter_bytes(lsb0, f), - - bind_by_ref(ref m) => - to_bytes::iter_bytes_2(&1u8, m, lsb0, f), - - bind_infer => - 2u8.iter_bytes(lsb0, f), - } - } -} -#[cfg(not(stage0))] impl to_bytes::IterBytes for binding_mode { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { match *self { - bind_by_copy => 0u8.iter_bytes(lsb0, f), + bind_by_ref(ref m) => { + 0u8.iter_bytes(lsb0, f) && m.iter_bytes(lsb0, f) + } - bind_by_ref(ref m) => to_bytes::iter_bytes_2(&1u8, m, lsb0, f), - - bind_infer => 2u8.iter_bytes(lsb0, f), + bind_infer => { + 1u8.iter_bytes(lsb0, f) + } } } } @@ -334,13 +305,6 @@ pub enum pat_ { #[deriving(Eq, Encodable, Decodable)] pub enum mutability { m_mutbl, m_imm, m_const, } -#[cfg(stage0)] -impl to_bytes::IterBytes for mutability { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - (*self as u8).iter_bytes(lsb0, f) - } -} -#[cfg(not(stage0))] impl to_bytes::IterBytes for mutability { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { (*self as u8).iter_bytes(lsb0, f) @@ -354,13 +318,6 @@ pub enum Sigil { ManagedSigil } -#[cfg(stage0)] -impl to_bytes::IterBytes for Sigil { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - (*self as uint).iter_bytes(lsb0, f) - } -} -#[cfg(not(stage0))] impl to_bytes::IterBytes for Sigil { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { (*self as uint).iter_bytes(lsb0, f) @@ -430,6 +387,7 @@ pub type stmt = spanned; #[deriving(Eq, Encodable, Decodable)] pub enum stmt_ { + // could be an item or a local (let) binding: stmt_decl(@decl, node_id), // expr without trailing semi-colon (must have unit type): @@ -458,7 +416,12 @@ pub type local = spanned; pub type decl = spanned; #[deriving(Eq, Encodable, Decodable)] -pub enum decl_ { decl_local(~[@local]), decl_item(@item), } +pub enum decl_ { + // a local (let) binding: + decl_local(@local), + // an item binding: + decl_item(@item), +} #[deriving(Eq, Encodable, Decodable)] pub struct arm { @@ -469,7 +432,6 @@ pub struct arm { #[deriving(Eq, Encodable, Decodable)] pub struct field_ { - mutbl: mutability, ident: ident, expr: @expr, } @@ -482,13 +444,23 @@ pub enum blk_check_mode { default_blk, unsafe_blk, } #[deriving(Eq, Encodable, Decodable)] pub struct expr { id: node_id, - // Extra node ID is only used for index, assign_op, unary, binary, method - // call - callee_id: node_id, node: expr_, span: span, } +impl expr { + pub fn get_callee_id(&self) -> Option { + match self.node { + expr_method_call(callee_id, _, _, _, _, _) | + expr_index(callee_id, _, _) | + expr_binary(callee_id, _, _, _) | + expr_assign_op(callee_id, _, _, _) | + expr_unary(callee_id, _, _) => Some(callee_id), + _ => None, + } + } +} + #[deriving(Eq, Encodable, Decodable)] pub enum CallSugar { NoSugar, @@ -501,10 +473,10 @@ pub enum expr_ { expr_vstore(@expr, expr_vstore), expr_vec(~[@expr], mutability), expr_call(@expr, ~[@expr], CallSugar), - expr_method_call(@expr, ident, ~[@Ty], ~[@expr], CallSugar), + expr_method_call(node_id, @expr, ident, ~[@Ty], ~[@expr], CallSugar), expr_tup(~[@expr]), - expr_binary(binop, @expr, @expr), - expr_unary(unop, @expr), + expr_binary(node_id, binop, @expr, @expr), + expr_unary(node_id, unop, @expr), expr_lit(@lit), expr_cast(@expr, @Ty), expr_if(@expr, blk, Option<@expr>), @@ -525,9 +497,9 @@ pub enum expr_ { expr_copy(@expr), expr_assign(@expr, @expr), - expr_assign_op(binop, @expr, @expr), + expr_assign_op(node_id, binop, @expr, @expr), expr_field(@expr, ident, ~[@Ty]), - expr_index(@expr, @expr), + expr_index(node_id, @expr, @expr), expr_path(@Path), /// The special identifier `self`. @@ -718,13 +690,6 @@ impl ToStr for int_ty { } } -#[cfg(stage0)] -impl to_bytes::IterBytes for int_ty { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - (*self as u8).iter_bytes(lsb0, f) - } -} -#[cfg(not(stage0))] impl to_bytes::IterBytes for int_ty { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { (*self as u8).iter_bytes(lsb0, f) @@ -740,13 +705,6 @@ impl ToStr for uint_ty { } } -#[cfg(stage0)] -impl to_bytes::IterBytes for uint_ty { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - (*self as u8).iter_bytes(lsb0, f) - } -} -#[cfg(not(stage0))] impl to_bytes::IterBytes for uint_ty { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { (*self as u8).iter_bytes(lsb0, f) @@ -762,13 +720,6 @@ impl ToStr for float_ty { } } -#[cfg(stage0)] -impl to_bytes::IterBytes for float_ty { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - (*self as u8).iter_bytes(lsb0, f) - } -} -#[cfg(not(stage0))] impl to_bytes::IterBytes for float_ty { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { (*self as u8).iter_bytes(lsb0, f) @@ -808,13 +759,6 @@ impl ToStr for Onceness { } } -#[cfg(stage0)] -impl to_bytes::IterBytes for Onceness { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - (*self as uint).iter_bytes(lsb0, f); - } -} -#[cfg(not(stage0))] impl to_bytes::IterBytes for Onceness { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { (*self as uint).iter_bytes(lsb0, f) @@ -861,16 +805,9 @@ pub enum ty_ { ty_infer, } -#[cfg(stage0)] -impl to_bytes::IterBytes for Ty { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - to_bytes::iter_bytes_2(&self.span.lo, &self.span.hi, lsb0, f); - } -} -#[cfg(not(stage0))] impl to_bytes::IterBytes for Ty { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { - to_bytes::iter_bytes_2(&self.span.lo, &self.span.hi, lsb0, f) + self.span.lo.iter_bytes(lsb0, f) && self.span.hi.iter_bytes(lsb0, f) } } @@ -925,13 +862,6 @@ impl ToStr for purity { } } -#[cfg(stage0)] -impl to_bytes::IterBytes for purity { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - (*self as u8).iter_bytes(lsb0, f) - } -} -#[cfg(not(stage0))] impl to_bytes::IterBytes for purity { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { (*self as u8).iter_bytes(lsb0, f) @@ -945,13 +875,6 @@ pub enum ret_style { return_val, // everything else } -#[cfg(stage0)] -impl to_bytes::IterBytes for ret_style { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - (*self as u8).iter_bytes(lsb0, f) - } -} -#[cfg(not(stage0))] impl to_bytes::IterBytes for ret_style { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { (*self as u8).iter_bytes(lsb0, f) @@ -967,28 +890,20 @@ pub enum explicit_self_ { sty_uniq(mutability) // `~self` } -#[cfg(stage0)] -impl to_bytes::IterBytes for explicit_self_ { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - match *self { - sty_static => 0u8.iter_bytes(lsb0, f), - sty_value => 1u8.iter_bytes(lsb0, f), - sty_region(ref lft, ref mutbl) => to_bytes::iter_bytes_3(&2u8, &lft, mutbl, lsb0, f), - sty_box(ref mutbl) => to_bytes::iter_bytes_2(&3u8, mutbl, lsb0, f), - sty_uniq(ref mutbl) => to_bytes::iter_bytes_2(&4u8, mutbl, lsb0, f), - } - } -} - -#[cfg(not(stage0))] impl to_bytes::IterBytes for explicit_self_ { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { match *self { sty_static => 0u8.iter_bytes(lsb0, f), sty_value => 1u8.iter_bytes(lsb0, f), - sty_region(ref lft, ref mutbl) => to_bytes::iter_bytes_3(&2u8, &lft, mutbl, lsb0, f), - sty_box(ref mutbl) => to_bytes::iter_bytes_2(&3u8, mutbl, lsb0, f), - sty_uniq(ref mutbl) => to_bytes::iter_bytes_2(&4u8, mutbl, lsb0, f), + sty_region(ref lft, ref mutbl) => { + 2u8.iter_bytes(lsb0, f) && lft.iter_bytes(lsb0, f) && mutbl.iter_bytes(lsb0, f) + } + sty_box(ref mutbl) => { + 3u8.iter_bytes(lsb0, f) && mutbl.iter_bytes(lsb0, f) + } + sty_uniq(ref mutbl) => { + 4u8.iter_bytes(lsb0, f) && mutbl.iter_bytes(lsb0, f) + } } } } @@ -1227,7 +1142,7 @@ pub enum inlined_item { mod test { use core::option::{None, Option, Some}; use core::uint; - use std; + use extra; use codemap::*; use super::*; @@ -1316,7 +1231,7 @@ mod test { }, span: bogus_span}; // doesn't matter which encoder we use.... - let _f = (@e as @std::serialize::Encodable); + let _f = (@e as @extra::serialize::Encodable); } diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs index e9f15c0a8f5ce..ec77ba8853041 100644 --- a/src/libsyntax/ast_map.rs +++ b/src/libsyntax/ast_map.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use abi::AbiSet; use ast::*; use ast; @@ -20,7 +22,10 @@ use print::pprust; use visit; use syntax::parse::token::special_idents; +use core::cmp; use core::hashmap::HashMap; +use core::str; +use core::vec; pub enum path_elt { path_mod(ident), @@ -49,12 +54,12 @@ impl cmp::Eq for path_elt { pub type path = ~[path_elt]; -pub fn path_to_str_with_sep(p: &[path_elt], sep: ~str, itr: @ident_interner) +pub fn path_to_str_with_sep(p: &[path_elt], sep: &str, itr: @ident_interner) -> ~str { let strs = do p.map |e| { match *e { - path_mod(s) => copy *itr.get(s), - path_name(s) => copy *itr.get(s) + path_mod(s) => copy *itr.get(s.name), + path_name(s) => copy *itr.get(s.name) } }; str::connect(strs, sep) @@ -63,20 +68,20 @@ pub fn path_to_str_with_sep(p: &[path_elt], sep: ~str, itr: @ident_interner) pub fn path_ident_to_str(p: &path, i: ident, itr: @ident_interner) -> ~str { if vec::is_empty(*p) { //FIXME /* FIXME (#2543) */ copy *i - copy *itr.get(i) + copy *itr.get(i.name) } else { - fmt!("%s::%s", path_to_str(*p, itr), *itr.get(i)) + fmt!("%s::%s", path_to_str(*p, itr), *itr.get(i.name)) } } pub fn path_to_str(p: &[path_elt], itr: @ident_interner) -> ~str { - path_to_str_with_sep(p, ~"::", itr) + path_to_str_with_sep(p, "::", itr) } pub fn path_elt_to_str(pe: path_elt, itr: @ident_interner) -> ~str { match pe { - path_mod(s) => copy *itr.get(s), - path_name(s) => copy *itr.get(s) + path_mod(s) => copy *itr.get(s.name), + path_name(s) => copy *itr.get(s.name) } } @@ -107,7 +112,7 @@ pub struct Ctx { pub type vt = visit::vt<@mut Ctx>; pub fn extend(cx: @mut Ctx, elt: ident) -> @path { - @(vec::append(copy cx.path, ~[path_name(elt)])) + @(vec::append(copy cx.path, [path_name(elt)])) } pub fn mk_ast_map_visitor() -> vt { @@ -312,17 +317,9 @@ pub fn map_struct_def( pub fn map_expr(ex: @expr, cx: @mut Ctx, v: visit::vt<@mut Ctx>) { cx.map.insert(ex.id, node_expr(ex)); - match ex.node { - // Expressions which are or might be calls: - ast::expr_call(*) | - ast::expr_method_call(*) | - ast::expr_index(*) | - ast::expr_binary(*) | - ast::expr_assign_op(*) | - ast::expr_unary(*) => { - cx.map.insert(ex.callee_id, node_callee_scope(ex)); - } - _ => {} + // Expressions which are or might be calls: + for ex.get_callee_id().each |callee_id| { + cx.map.insert(*callee_id, node_callee_scope(ex)); } visit::visit_expr(ex, cx, v); } @@ -359,16 +356,16 @@ pub fn node_id_to_str(map: map, id: node_id, itr: @ident_interner) -> ~str { } Some(&node_method(m, _, path)) => { fmt!("method %s in %s (id=%?)", - *itr.get(m.ident), path_to_str(*path, itr), id) + *itr.get(m.ident.name), path_to_str(*path, itr), id) } Some(&node_trait_method(ref tm, _, path)) => { let m = ast_util::trait_method_to_ty_method(&**tm); fmt!("method %s in %s (id=%?)", - *itr.get(m.ident), path_to_str(*path, itr), id) + *itr.get(m.ident.name), path_to_str(*path, itr), id) } Some(&node_variant(ref variant, _, path)) => { fmt!("variant %s in %s (id=%?)", - *itr.get(variant.node.name), path_to_str(*path, itr), id) + *itr.get(variant.node.name.name), path_to_str(*path, itr), id) } Some(&node_expr(expr)) => { fmt!("expr %s (id=%?)", pprust::expr_to_str(expr, itr), id) @@ -384,7 +381,7 @@ pub fn node_id_to_str(map: map, id: node_id, itr: @ident_interner) -> ~str { fmt!("arg (id=%?)", id) } Some(&node_local(ident)) => { - fmt!("local (id=%?, name=%s)", id, *itr.get(ident)) + fmt!("local (id=%?, name=%s)", id, *itr.get(ident.name)) } Some(&node_block(_)) => { fmt!("block") diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index d4a67d61d94b6..d99363d7ee5f7 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -8,22 +8,29 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use ast::*; use ast; use ast_util; use codemap::{span, spanned}; +use core::cast; +use core::local_data; +use opt_vec; use parse::token; use visit; -use opt_vec; +use core::hashmap::HashMap; +use core::int; +use core::option; +use core::str; use core::to_bytes; -pub fn path_name_i(idents: &[ident], intr: @token::ident_interner) -> ~str { +pub fn path_name_i(idents: &[ident]) -> ~str { // FIXME: Bad copies (#2543 -- same for everything else that says "bad") - str::connect(idents.map(|i| copy *intr.get(*i)), ~"::") + str::connect(idents.map(|i| copy *token::interner_get(i.name)), "::") } - pub fn path_to_ident(p: @Path) -> ident { copy *p.idents.last() } pub fn local_def(id: node_id) -> def_id { @@ -187,23 +194,14 @@ pub fn float_ty_to_str(t: float_ty) -> ~str { } pub fn is_call_expr(e: @expr) -> bool { - match e.node { expr_call(_, _, _) => true, _ => false } + match e.node { expr_call(*) => true, _ => false } } // This makes def_id hashable -#[cfg(stage0)] -impl to_bytes::IterBytes for def_id { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - to_bytes::iter_bytes_2(&self.crate, &self.node, lsb0, f); - } -} -// This makes def_id hashable -#[cfg(not(stage0))] impl to_bytes::IterBytes for def_id { #[inline(always)] fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { - to_bytes::iter_bytes_2(&self.crate, &self.node, lsb0, f) + self.crate.iter_bytes(lsb0, f) && self.node.iter_bytes(lsb0, f) } } @@ -236,7 +234,7 @@ pub fn ident_to_path(s: span, i: ident) -> @Path { pub fn ident_to_pat(id: node_id, s: span, i: ident) -> @pat { @ast::pat { id: id, - node: pat_ident(bind_by_copy, ident_to_path(s, i), None), + node: pat_ident(bind_infer, ident_to_path(s, i), None), span: s } } @@ -282,7 +280,8 @@ pub fn trait_method_to_ty_method(method: &trait_method) -> ty_method { pub fn split_trait_methods(trait_methods: &[trait_method]) -> (~[ty_method], ~[@method]) { - let mut reqd = ~[], provd = ~[]; + let mut reqd = ~[]; + let mut provd = ~[]; for trait_methods.each |trt_method| { match *trt_method { required(ref tm) => reqd.push(copy *tm), @@ -376,98 +375,123 @@ pub struct id_range { max: node_id, } -pub impl id_range { - fn max() -> id_range { - id_range {min: int::max_value, - max: int::min_value} +impl id_range { + pub fn max() -> id_range { + id_range { + min: int::max_value, + max: int::min_value, + } } - fn empty(&self) -> bool { + pub fn empty(&self) -> bool { self.min >= self.max } - fn add(&mut self, id: node_id) { + pub fn add(&mut self, id: node_id) { self.min = int::min(self.min, id); self.max = int::max(self.max, id + 1); } } -pub fn id_visitor(vfn: @fn(node_id)) -> visit::vt<()> { - let visit_generics: @fn(&Generics) = |generics| { +pub fn id_visitor(vfn: @fn(node_id, T)) -> visit::vt { + let visit_generics: @fn(&Generics, T) = |generics, t| { for generics.ty_params.each |p| { - vfn(p.id); + vfn(p.id, t); } for generics.lifetimes.each |p| { - vfn(p.id); + vfn(p.id, t); } }; - visit::mk_simple_visitor(@visit::SimpleVisitor { - visit_mod: |_m, _sp, id| vfn(id), + visit::mk_vt(@visit::Visitor { + visit_mod: |m, sp, id, t, vt| { + vfn(id, t); + visit::visit_mod(m, sp, id, t, vt); + }, - visit_view_item: |vi| { + visit_view_item: |vi, t, vt| { match vi.node { - view_item_extern_mod(_, _, id) => vfn(id), + view_item_extern_mod(_, _, id) => vfn(id, t), view_item_use(ref vps) => { for vps.each |vp| { match vp.node { - view_path_simple(_, _, id) => vfn(id), - view_path_glob(_, id) => vfn(id), + view_path_simple(_, _, id) => vfn(id, t), + view_path_glob(_, id) => vfn(id, t), view_path_list(_, ref paths, id) => { - vfn(id); + vfn(id, t); for paths.each |p| { - vfn(p.node.id); + vfn(p.node.id, t); } } } } } } + visit::visit_view_item(vi, t, vt); }, - visit_foreign_item: |ni| vfn(ni.id), + visit_foreign_item: |ni, t, vt| { + vfn(ni.id, t); + visit::visit_foreign_item(ni, t, vt); + }, - visit_item: |i| { - vfn(i.id); + visit_item: |i, t, vt| { + vfn(i.id, t); match i.node { item_enum(ref enum_definition, _) => - for (*enum_definition).variants.each |v| { vfn(v.node.id); }, + for (*enum_definition).variants.each |v| { vfn(v.node.id, t); }, _ => () } + visit::visit_item(i, t, vt); }, - visit_local: |l| vfn(l.node.id), - visit_block: |b| vfn(b.node.id), - visit_stmt: |s| vfn(ast_util::stmt_id(s)), - visit_arm: |_| {}, - visit_pat: |p| vfn(p.id), - visit_decl: |_| {}, - - visit_expr: |e| { - vfn(e.callee_id); - vfn(e.id); + visit_local: |l, t, vt| { + vfn(l.node.id, t); + visit::visit_local(l, t, vt); + }, + visit_block: |b, t, vt| { + vfn(b.node.id, t); + visit::visit_block(b, t, vt); + }, + visit_stmt: |s, t, vt| { + vfn(ast_util::stmt_id(s), t); + visit::visit_stmt(s, t, vt); + }, + visit_pat: |p, t, vt| { + vfn(p.id, t); + visit::visit_pat(p, t, vt); }, - visit_expr_post: |_| {}, + visit_expr: |e, t, vt| { + for e.get_callee_id().each |callee_id| { + vfn(*callee_id, t); + } + vfn(e.id, t); + visit::visit_expr(e, t, vt); + }, - visit_ty: |t| { - match t.node { - ty_path(_, id) => vfn(id), + visit_ty: |ty, t, vt| { + match ty.node { + ty_path(_, id) => vfn(id, t), _ => { /* fall through */ } } + visit::visit_ty(ty, t, vt); }, - visit_generics: visit_generics, + visit_generics: |generics, t, vt| { + visit_generics(generics, t); + visit::visit_generics(generics, t, vt); + }, - visit_fn: |fk, d, _, _, id| { - vfn(id); + visit_fn: |fk, d, a, b, id, t, vt| { + vfn(id, t); match *fk { visit::fk_item_fn(_, generics, _, _) => { - visit_generics(generics); + visit_generics(generics, t); } visit::fk_method(_, generics, m) => { - vfn(m.self_id); - visit_generics(generics); + vfn(m.self_id, t); + visit_generics(generics, t); } visit::fk_anon(_) | visit::fk_fn_block => { @@ -475,20 +499,22 @@ pub fn id_visitor(vfn: @fn(node_id)) -> visit::vt<()> { } for d.inputs.each |arg| { - vfn(arg.id) + vfn(arg.id, t) } + visit::visit_fn(fk, d, a, b, id, t, vt); + }, + + visit_struct_field: |f, t, vt| { + vfn(f.node.id, t); + visit::visit_struct_field(f, t, vt); }, - visit_ty_method: |_| {}, - visit_trait_method: |_| {}, - visit_struct_def: |_, _, _, _| {}, - visit_struct_field: |f| vfn(f.node.id), - visit_struct_method: |_| {} + .. *visit::default_visitor() }) } pub fn visit_ids_for_inlined_item(item: &inlined_item, vfn: @fn(node_id)) { - item.accept((), id_visitor(vfn)); + item.accept((), id_visitor(|id, ()| vfn(id))); } pub fn compute_id_range(visit_ids_fn: &fn(@fn(node_id))) -> id_range { @@ -510,36 +536,46 @@ pub fn is_item_impl(item: @ast::item) -> bool { } } -pub fn walk_pat(pat: @pat, it: &fn(@pat)) { - it(pat); +pub fn walk_pat(pat: @pat, it: &fn(@pat) -> bool) -> bool { + if !it(pat) { + return false; + } + match pat.node { pat_ident(_, _, Some(p)) => walk_pat(p, it), pat_struct(_, ref fields, _) => { - for fields.each |f| { - walk_pat(f.pat, it) - } + fields.each(|f| walk_pat(f.pat, it)) } pat_enum(_, Some(ref s)) | pat_tup(ref s) => { - for s.each |p| { - walk_pat(*p, it) - } + s.each(|&p| walk_pat(p, it)) } pat_box(s) | pat_uniq(s) | pat_region(s) => { walk_pat(s, it) } pat_vec(ref before, ref slice, ref after) => { - for before.each |p| { - walk_pat(*p, it) - } - for slice.each |p| { - walk_pat(*p, it) - } - for after.each |p| { - walk_pat(*p, it) - } + before.each(|&p| walk_pat(p, it)) && + slice.each(|&p| walk_pat(p, it)) && + after.each(|&p| walk_pat(p, it)) } pat_wild | pat_lit(_) | pat_range(_, _) | pat_ident(_, _, _) | - pat_enum(_, _) => { } + pat_enum(_, _) => { + true + } + } +} + +pub trait EachViewItem { + pub fn each_view_item(&self, f: @fn(@ast::view_item) -> bool) -> bool; +} + +impl EachViewItem for ast::crate { + fn each_view_item(&self, f: @fn(@ast::view_item) -> bool) -> bool { + let broke = @mut false; + let vtor: visit::vt<()> = visit::mk_simple_visitor(@visit::SimpleVisitor { + visit_view_item: |vi| { *broke = f(vi); }, ..*visit::default_simple_visitor() + }); + visit::visit_crate(self, (), vtor); + true } } @@ -585,23 +621,92 @@ pub enum Privacy { // HYGIENE FUNCTIONS -/// Construct an identifier with the given repr and an empty context: -pub fn mk_ident(repr: uint) -> ident { ident {repr: repr, ctxt: 0}} +/// Construct an identifier with the given name and an empty context: +pub fn new_ident(name: Name) -> ident { ident {name: name, ctxt: 0}} /// Extend a syntax context with a given mark -pub fn mk_mark (m:Mrk,ctxt:SyntaxContext,table:&mut SCTable) +pub fn new_mark(m:Mrk, tail:SyntaxContext) -> SyntaxContext { + new_mark_internal(m,tail,get_sctable()) +} + +// Extend a syntax context with a given mark and table +// FIXME #4536 : currently pub to allow testing +pub fn new_mark_internal(m:Mrk, tail:SyntaxContext,table:&mut SCTable) -> SyntaxContext { - idx_push(table,Mark(m,ctxt)) + let key = (tail,m); + // FIXME #5074 : can't use more natural style because we're missing + // flow-sensitivity. Results in two lookups on a hash table hit. + // also applies to new_rename_internal, below. + // let try_lookup = table.mark_memo.find(&key); + match table.mark_memo.contains_key(&key) { + false => { + let new_idx = idx_push(&mut table.table,Mark(m,tail)); + table.mark_memo.insert(key,new_idx); + new_idx + } + true => { + match table.mark_memo.find(&key) { + None => fail!(~"internal error: key disappeared 2013042901"), + Some(idxptr) => {*idxptr} + } + } + } } /// Extend a syntax context with a given rename -pub fn mk_rename (id:ident, to:Name, tail:SyntaxContext, table: &mut SCTable) +pub fn new_rename(id:ident, to:Name, tail:SyntaxContext) -> SyntaxContext { + new_rename_internal(id, to, tail, get_sctable()) +} + +// Extend a syntax context with a given rename and sctable +// FIXME #4536 : currently pub to allow testing +pub fn new_rename_internal(id:ident, to:Name, tail:SyntaxContext, table: &mut SCTable) -> SyntaxContext { - idx_push(table,Rename(id,to,tail)) + let key = (tail,id,to); + // FIXME #5074 + //let try_lookup = table.rename_memo.find(&key); + match table.rename_memo.contains_key(&key) { + false => { + let new_idx = idx_push(&mut table.table,Rename(id,to,tail)); + table.rename_memo.insert(key,new_idx); + new_idx + } + true => { + match table.rename_memo.find(&key) { + None => fail!(~"internal error: key disappeared 2013042902"), + Some(idxptr) => {*idxptr} + } + } + } } /// Make a fresh syntax context table with EmptyCtxt in slot zero -pub fn mk_sctable() -> SCTable { ~[EmptyCtxt] } +/// and IllegalCtxt in slot one. +// FIXME #4536 : currently pub to allow testing +pub fn new_sctable_internal() -> SCTable { + SCTable { + table: ~[EmptyCtxt,IllegalCtxt], + mark_memo: HashMap::new(), + rename_memo: HashMap::new() + } +} + +// fetch the SCTable from TLS, create one if it doesn't yet exist. +pub fn get_sctable() -> @mut SCTable { + unsafe { + let sctable_key = (cast::transmute::<(uint, uint), + &fn(v: @@mut SCTable)>( + (-4 as uint, 0u))); + match local_data::local_data_get(sctable_key) { + None => { + let new_table = @@mut new_sctable_internal(); + local_data::local_data_set(sctable_key,new_table); + *new_table + }, + Some(intr) => *intr + } + } +} /// Add a value to the end of a vec, return its index fn idx_push(vec: &mut ~[T], val: T) -> uint { @@ -610,24 +715,31 @@ fn idx_push(vec: &mut ~[T], val: T) -> uint { } /// Resolve a syntax object to a name, per MTWT. -pub fn resolve (id : ident, table : &SCTable) -> Name { - match table[id.ctxt] { - EmptyCtxt => id.repr, +pub fn resolve(id : ident) -> Name { + resolve_internal(id, get_sctable()) +} + +// Resolve a syntax object to a name, per MTWT. +// FIXME #4536 : currently pub to allow testing +pub fn resolve_internal(id : ident, table : &mut SCTable) -> Name { + match table.table[id.ctxt] { + EmptyCtxt => id.name, // ignore marks here: - Mark(_,subctxt) => resolve (ident{repr:id.repr, ctxt: subctxt},table), + Mark(_,subctxt) => resolve_internal(ident{name:id.name, ctxt: subctxt},table), // do the rename if necessary: - Rename(ident{repr,ctxt},toname,subctxt) => { + Rename(ident{name,ctxt},toname,subctxt) => { // this could be cached or computed eagerly: - let resolvedfrom = resolve(ident{repr:repr,ctxt:ctxt},table); - let resolvedthis = resolve(ident{repr:id.repr,ctxt:subctxt},table); + let resolvedfrom = resolve_internal(ident{name:name,ctxt:ctxt},table); + let resolvedthis = resolve_internal(ident{name:id.name,ctxt:subctxt},table); if ((resolvedthis == resolvedfrom) - && (marksof (ctxt,resolvedthis,table) - == marksof (subctxt,resolvedthis,table))) { + && (marksof(ctxt,resolvedthis,table) + == marksof(subctxt,resolvedthis,table))) { toname } else { resolvedthis } } + IllegalCtxt() => fail!(~"expected resolvable context, got IllegalCtxt") } } @@ -638,7 +750,7 @@ pub fn marksof(ctxt: SyntaxContext, stopname: Name, table: &SCTable) -> ~[Mrk] { let mut result = ~[]; let mut loopvar = ctxt; loop { - match table[loopvar] { + match table.table[loopvar] { EmptyCtxt => {return result;}, Mark(mark,tl) => { xorPush(&mut result,mark); @@ -653,6 +765,7 @@ pub fn marksof(ctxt: SyntaxContext, stopname: Name, table: &SCTable) -> ~[Mrk] { loopvar = tl; } } + IllegalCtxt => fail!(~"expected resolvable context, got IllegalCtxt") } } } @@ -701,11 +814,11 @@ mod test { // convert a list of uints to an @~[ident] // (ignores the interner completely) fn uints_to_idents (uints: &~[uint]) -> @~[ident] { - @uints.map(|u|{ ident {repr:*u, ctxt: empty_ctxt} }) + @uints.map(|u|{ ident {name:*u, ctxt: empty_ctxt} }) } fn id (u : uint, s: SyntaxContext) -> ident { - ident{repr:u, ctxt: s} + ident{name:u, ctxt: s} } // because of the SCTable, I now need a tidy way of @@ -722,15 +835,15 @@ mod test { -> SyntaxContext { tscs.foldr(tail, |tsc : &TestSC,tail : SyntaxContext| {match *tsc { - M(mrk) => mk_mark(mrk,tail,table), - R(ident,name) => mk_rename(ident,name,tail,table)}}) + M(mrk) => new_mark_internal(mrk,tail,table), + R(ident,name) => new_rename_internal(ident,name,tail,table)}}) } // gather a SyntaxContext back into a vector of TestSCs fn refold_test_sc(mut sc: SyntaxContext, table : &SCTable) -> ~[TestSC] { let mut result = ~[]; loop { - match table[sc] { + match table.table[sc] { EmptyCtxt => {return result;}, Mark(mrk,tail) => { result.push(M(mrk)); @@ -742,40 +855,41 @@ mod test { sc = tail; loop; } + IllegalCtxt => fail!("expected resolvable context, got IllegalCtxt") } } } #[test] fn test_unfold_refold(){ - let mut t = mk_sctable(); + let mut t = new_sctable_internal(); let test_sc = ~[M(3),R(id(101,0),14),M(9)]; - assert_eq!(unfold_test_sc(copy test_sc,empty_ctxt,&mut t),3); - assert_eq!(t[1],Mark(9,0)); - assert_eq!(t[2],Rename(id(101,0),14,1)); - assert_eq!(t[3],Mark(3,2)); - assert_eq!(refold_test_sc(3,&t),test_sc); + assert_eq!(unfold_test_sc(copy test_sc,empty_ctxt,&mut t),4); + assert_eq!(t.table[2],Mark(9,0)); + assert_eq!(t.table[3],Rename(id(101,0),14,2)); + assert_eq!(t.table[4],Mark(3,3)); + assert_eq!(refold_test_sc(4,&t),test_sc); } // extend a syntax context with a sequence of marks given // in a vector. v[0] will be the outermost mark. fn unfold_marks(mrks:~[Mrk],tail:SyntaxContext,table: &mut SCTable) -> SyntaxContext { mrks.foldr(tail, |mrk:&Mrk,tail:SyntaxContext| - {mk_mark(*mrk,tail,table)}) + {new_mark_internal(*mrk,tail,table)}) } #[test] fn unfold_marks_test() { - let mut t = ~[EmptyCtxt]; + let mut t = new_sctable_internal(); - assert_eq!(unfold_marks(~[3,7],empty_ctxt,&mut t),2); - assert_eq!(t[1],Mark(7,0)); - assert_eq!(t[2],Mark(3,1)); + assert_eq!(unfold_marks(~[3,7],empty_ctxt,&mut t),3); + assert_eq!(t.table[2],Mark(7,0)); + assert_eq!(t.table[3],Mark(3,2)); } #[test] fn test_marksof () { let stopname = 242; let name1 = 243; - let mut t = mk_sctable(); + let mut t = new_sctable_internal(); assert_eq!(marksof (empty_ctxt,stopname,&t),~[]); // FIXME #5074: ANF'd to dodge nested calls { let ans = unfold_marks(~[4,98],empty_ctxt,&mut t); @@ -789,13 +903,13 @@ mod test { // rename where stop doesn't match: { let chain = ~[M(9), R(id(name1, - mk_mark (4, empty_ctxt,&mut t)), + new_mark_internal (4, empty_ctxt,&mut t)), 100101102), M(14)]; let ans = unfold_test_sc(chain,empty_ctxt,&mut t); assert_eq! (marksof (ans, stopname, &t), ~[9,14]);} // rename where stop does match - { let name1sc = mk_mark(4, empty_ctxt, &mut t); + { let name1sc = new_mark_internal(4, empty_ctxt, &mut t); let chain = ~[M(9), R(id(name1, name1sc), stopname), @@ -807,30 +921,30 @@ mod test { #[test] fn resolve_tests () { let a = 40; - let mut t = mk_sctable(); + let mut t = new_sctable_internal(); // - ctxt is MT - assert_eq!(resolve(id(a,empty_ctxt),&t),a); + assert_eq!(resolve_internal(id(a,empty_ctxt),&mut t),a); // - simple ignored marks { let sc = unfold_marks(~[1,2,3],empty_ctxt,&mut t); - assert_eq!(resolve(id(a,sc),&t),a);} + assert_eq!(resolve_internal(id(a,sc),&mut t),a);} // - orthogonal rename where names don't match { let sc = unfold_test_sc(~[R(id(50,empty_ctxt),51),M(12)],empty_ctxt,&mut t); - assert_eq!(resolve(id(a,sc),&t),a);} + assert_eq!(resolve_internal(id(a,sc),&mut t),a);} // - rename where names do match, but marks don't - { let sc1 = mk_mark(1,empty_ctxt,&mut t); + { let sc1 = new_mark_internal(1,empty_ctxt,&mut t); let sc = unfold_test_sc(~[R(id(a,sc1),50), M(1), M(2)], empty_ctxt,&mut t); - assert_eq!(resolve(id(a,sc),&t), a);} + assert_eq!(resolve_internal(id(a,sc),&mut t), a);} // - rename where names and marks match { let sc1 = unfold_test_sc(~[M(1),M(2)],empty_ctxt,&mut t); let sc = unfold_test_sc(~[R(id(a,sc1),50),M(1),M(2)],empty_ctxt,&mut t); - assert_eq!(resolve(id(a,sc),&t), 50); } + assert_eq!(resolve_internal(id(a,sc),&mut t), 50); } // - rename where names and marks match by literal sharing { let sc1 = unfold_test_sc(~[M(1),M(2)],empty_ctxt,&mut t); let sc = unfold_test_sc(~[R(id(a,sc1),50)],sc1,&mut t); - assert_eq!(resolve(id(a,sc),&t), 50); } + assert_eq!(resolve_internal(id(a,sc),&mut t), 50); } // - two renames of the same var.. can only happen if you use // local-expand to prevent the inner binding from being renamed // during the rename-pass caused by the first: @@ -838,20 +952,29 @@ mod test { { let sc = unfold_test_sc(~[R(id(a,empty_ctxt),50), R(id(a,empty_ctxt),51)], empty_ctxt,&mut t); - assert_eq!(resolve(id(a,sc),&t), 51); } + assert_eq!(resolve_internal(id(a,sc),&mut t), 51); } // the simplest double-rename: - { let a_to_a50 = mk_rename(id(a,empty_ctxt),50,empty_ctxt,&mut t); - let a50_to_a51 = mk_rename(id(a,a_to_a50),51,a_to_a50,&mut t); - assert_eq!(resolve(id(a,a50_to_a51),&t),51); + { let a_to_a50 = new_rename_internal(id(a,empty_ctxt),50,empty_ctxt,&mut t); + let a50_to_a51 = new_rename_internal(id(a,a_to_a50),51,a_to_a50,&mut t); + assert_eq!(resolve_internal(id(a,a50_to_a51),&mut t),51); // mark on the outside doesn't stop rename: - let sc = mk_mark(9,a50_to_a51,&mut t); - assert_eq!(resolve(id(a,sc),&t),51); + let sc = new_mark_internal(9,a50_to_a51,&mut t); + assert_eq!(resolve_internal(id(a,sc),&mut t),51); // but mark on the inside does: let a50_to_a51_b = unfold_test_sc(~[R(id(a,a_to_a50),51), M(9)], a_to_a50, &mut t); - assert_eq!(resolve(id(a,a50_to_a51_b),&t),50);} + assert_eq!(resolve_internal(id(a,a50_to_a51_b),&mut t),50);} + } + + #[test] fn hashing_tests () { + let mut t = new_sctable_internal(); + assert_eq!(new_mark_internal(12,empty_ctxt,&mut t),2); + assert_eq!(new_mark_internal(13,empty_ctxt,&mut t),3); + // using the same one again should result in the same index: + assert_eq!(new_mark_internal(12,empty_ctxt,&mut t),2); + // I'm assuming that the rename table will behave the same.... } } diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index aebe5bbfc748a..2da64563159ed 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -10,6 +10,8 @@ // Functions dealing with attributes and meta_items +use core::prelude::*; + use ast; use codemap::{spanned, dummy_spanned}; use attr; @@ -18,7 +20,8 @@ use diagnostic::span_handler; use parse::comments::{doc_comment_style, strip_doc_comment_decoration}; use core::hashmap::HashSet; -use std; +use core::vec; +use extra; /* Constructors */ @@ -256,7 +259,7 @@ pub fn last_meta_item_list_by_name(items: ~[@ast::meta_item], name: &str) pub fn sort_meta_items(items: &[@ast::meta_item]) -> ~[@ast::meta_item] { // This is sort of stupid here, converting to a vec of mutables and back let mut v = vec::to_owned(items); - do std::sort::quick_sort(v) |ma, mb| { + do extra::sort::quick_sort(v) |ma, mb| { get_meta_item_name(*ma) <= get_meta_item_name(*mb) } @@ -291,7 +294,7 @@ pub fn remove_meta_items_by_name(items: ~[@ast::meta_item], name: &str) -> * linkage */ pub fn find_linkage_metas(attrs: &[ast::attribute]) -> ~[@ast::meta_item] { - do find_attrs_by_name(attrs, ~"link").flat_map |attr| { + do find_attrs_by_name(attrs, "link").flat_map |attr| { match attr.node.value.node { ast::meta_list(_, ref items) => /* FIXME (#2543) */ copy *items, _ => ~[] @@ -314,9 +317,9 @@ pub fn find_inline_attr(attrs: &[ast::attribute]) -> inline_attr { match attr.node.value.node { ast::meta_word(@~"inline") => ia_hint, ast::meta_list(@~"inline", ref items) => { - if !find_meta_items_by_name(*items, ~"always").is_empty() { + if !find_meta_items_by_name(*items, "always").is_empty() { ia_always - } else if !find_meta_items_by_name(*items, ~"never").is_empty() { + } else if !find_meta_items_by_name(*items, "never").is_empty() { ia_never } else { ia_hint diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 44a368738fd16..5f8d6e73cefab 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -21,8 +21,13 @@ source code snippets, etc. */ +use core::prelude::*; + +use core::cmp; +use core::str; use core::to_bytes; -use std::serialize::{Encodable, Decodable, Encoder, Decoder}; +use core::uint; +use extra::serialize::{Encodable, Decodable, Encoder, Decoder}; pub trait Pos { fn from_uint(n: uint) -> Self; @@ -65,13 +70,6 @@ impl Sub for BytePos { } } -#[cfg(stage0)] -impl to_bytes::IterBytes for BytePos { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - (**self).iter_bytes(lsb0, f) - } -} -#[cfg(not(stage0))] impl to_bytes::IterBytes for BytePos { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { (**self).iter_bytes(lsb0, f) @@ -90,13 +88,6 @@ impl cmp::Ord for CharPos { fn gt(&self, other: &CharPos) -> bool { **self > **other } } -#[cfg(stage0)] -impl to_bytes::IterBytes for CharPos { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - (**self).iter_bytes(lsb0, f) - } -} -#[cfg(not(stage0))] impl to_bytes::IterBytes for CharPos { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { (**self).iter_bytes(lsb0, f) @@ -150,17 +141,11 @@ impl Decodable for span { } } -#[cfg(stage0)] -impl to_bytes::IterBytes for span { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - to_bytes::iter_bytes_3(&self.lo, &self.hi, &self.expn_info, lsb0, f); - } -} - -#[cfg(not(stage0))] impl to_bytes::IterBytes for span { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { - to_bytes::iter_bytes_3(&self.lo, &self.hi, &self.expn_info, lsb0, f) + self.lo.iter_bytes(lsb0, f) && + self.hi.iter_bytes(lsb0, f) && + self.expn_info.iter_bytes(lsb0, f) } } @@ -211,17 +196,9 @@ pub struct FileMapAndLine {fm: @FileMap, line: uint} pub struct FileMapAndBytePos {fm: @FileMap, pos: BytePos} pub struct NameAndSpan {name: ~str, span: Option} -#[cfg(stage0)] -impl to_bytes::IterBytes for NameAndSpan { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - to_bytes::iter_bytes_2(&self.name, &self.span, lsb0, f) - } -} - -#[cfg(not(stage0))] impl to_bytes::IterBytes for NameAndSpan { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { - to_bytes::iter_bytes_2(&self.name, &self.span, lsb0, f) + self.name.iter_bytes(lsb0, f) && self.span.iter_bytes(lsb0, f) } } @@ -230,17 +207,9 @@ pub struct CallInfo { callee: NameAndSpan } -#[cfg(stage0)] -impl to_bytes::IterBytes for CallInfo { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - to_bytes::iter_bytes_2(&self.call_site, &self.callee, lsb0, f) - } -} - -#[cfg(not(stage0))] impl to_bytes::IterBytes for CallInfo { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { - to_bytes::iter_bytes_2(&self.call_site, &self.callee, lsb0, f) + self.call_site.iter_bytes(lsb0, f) && self.callee.iter_bytes(lsb0, f) } } @@ -249,20 +218,12 @@ pub enum ExpnInfo { ExpandedFrom(CallInfo) } -#[cfg(stage0)] -impl to_bytes::IterBytes for ExpnInfo { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - match *self { - ExpandedFrom(ref call_info) => to_bytes::iter_bytes_2(&0u8, call_info, lsb0, f) - } - } -} - -#[cfg(not(stage0))] impl to_bytes::IterBytes for ExpnInfo { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { match *self { - ExpandedFrom(ref call_info) => to_bytes::iter_bytes_2(&0u8, call_info, lsb0, f) + ExpandedFrom(ref call_info) => { + 0u8.iter_bytes(lsb0, f) && call_info.iter_bytes(lsb0, f) + } } } } @@ -310,16 +271,16 @@ pub struct FileMap { multibyte_chars: @mut ~[MultiByteChar], } -pub impl FileMap { +impl FileMap { // EFFECT: register a start-of-line offset in the // table of line-beginnings. // UNCHECKED INVARIANT: these offsets must be added in the right // order and must be in the right places; there is shared knowledge // about what ends a line between this file and parse.rs - fn next_line(&self, pos: BytePos) { + pub fn next_line(&self, pos: BytePos) { // the new charpos must be > the last one (or it's the first one). let lines = &mut *self.lines; - assert!((lines.len() == 0) || (lines[lines.len() - 1] < pos)); + assert!((lines.len() == 0) || (lines[lines.len() - 1] < pos)) lines.push(pos); } @@ -348,7 +309,7 @@ pub struct CodeMap { files: @mut ~[@FileMap] } -pub impl CodeMap { +impl CodeMap { pub fn new() -> CodeMap { CodeMap { files: @mut ~[], @@ -356,16 +317,15 @@ pub impl CodeMap { } /// Add a new FileMap to the CodeMap and return it - fn new_filemap(&self, filename: FileName, src: @~str) -> @FileMap { + pub fn new_filemap(&self, filename: FileName, src: @~str) -> @FileMap { return self.new_filemap_w_substr(filename, FssNone, src); } - fn new_filemap_w_substr( - &self, - filename: FileName, - substr: FileSubstr, - src: @~str - ) -> @FileMap { + pub fn new_filemap_w_substr(&self, + filename: FileName, + substr: FileSubstr, + src: @~str) + -> @FileMap { let files = &mut *self.files; let start_pos = if files.len() == 0 { 0 @@ -398,8 +358,7 @@ pub impl CodeMap { return self.lookup_pos(pos); } - pub fn lookup_char_pos_adj(&self, pos: BytePos) -> LocWithOpt - { + pub fn lookup_char_pos_adj(&self, pos: BytePos) -> LocWithOpt { let loc = self.lookup_char_pos(pos); match (loc.file.substr) { FssNone => @@ -458,7 +417,7 @@ pub impl CodeMap { pub fn span_to_snippet(&self, sp: span) -> ~str { let begin = self.lookup_byte_offset(sp.lo); let end = self.lookup_byte_offset(sp.hi); - assert!(begin.fm.start_pos == end.fm.start_pos); + assert_eq!(begin.fm.start_pos, end.fm.start_pos); return str::slice(*begin.fm.src, begin.pos.to_uint(), end.pos.to_uint()).to_owned(); } @@ -469,11 +428,9 @@ pub impl CodeMap { // (or expected function, found _|_) fail!(); // ("asking for " + filename + " which we don't know about"); } - } -priv impl CodeMap { - +impl CodeMap { fn lookup_filemap_idx(&self, pos: BytePos) -> uint { let files = &*self.files; let len = files.len(); diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 993fa612a2709..fa4a74b895454 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -8,10 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use codemap::{Pos, span}; use codemap; -use std::term; +use core::io; +use core::str; +use core::uint; +use core::vec; +use extra::term; pub type Emitter = @fn(cmsp: Option<(@codemap::CodeMap, span)>, msg: &str, @@ -185,19 +191,27 @@ fn diagnosticcolor(lvl: level) -> u8 { } fn print_diagnostic(topic: &str, lvl: level, msg: &str) { - let use_color = term::color_supported() && - io::stderr().get_type() == io::Screen; + let t = term::Terminal::new(io::stderr()); + + let stderr = io::stderr(); + if !topic.is_empty() { - io::stderr().write_str(fmt!("%s ", topic)); + stderr.write_str(fmt!("%s ", topic)); } - if use_color { - term::fg(io::stderr(), diagnosticcolor(lvl)); - } - io::stderr().write_str(fmt!("%s:", diagnosticstr(lvl))); - if use_color { - term::reset(io::stderr()); + + match t { + Ok(term) => { + if stderr.get_type() == io::Screen { + term.fg(diagnosticcolor(lvl)); + stderr.write_str(fmt!("%s: ", diagnosticstr(lvl))); + term.reset(); + stderr.write_str(fmt!("%s\n", msg)); + } else { + stderr.write_str(fmt!("%s: %s\n", diagnosticstr(lvl), msg)); + } + }, + _ => stderr.write_str(fmt!("%s: %s\n", diagnosticstr(lvl), msg)) } - io::stderr().write_str(fmt!(" %s\n", msg)); } pub fn collect(messages: @mut ~[~str]) @@ -218,7 +232,7 @@ pub fn emit(cmsp: Option<(@codemap::CodeMap, span)>, msg: &str, lvl: level) { print_macro_backtrace(cm, sp); } None => { - print_diagnostic(~"", lvl, msg); + print_diagnostic("", lvl, msg); } } } @@ -239,7 +253,7 @@ fn highlight_lines(cm: @codemap::CodeMap, // Print the offending lines for display_lines.each |line| { io::stderr().write_str(fmt!("%s:%u ", fm.name, *line + 1u)); - let s = fm.get_line(*line as int) + ~"\n"; + let s = fm.get_line(*line as int) + "\n"; io::stderr().write_str(s); } if elided { @@ -247,8 +261,8 @@ fn highlight_lines(cm: @codemap::CodeMap, let s = fmt!("%s:%u ", fm.name, last_line + 1u); let mut indent = str::len(s); let mut out = ~""; - while indent > 0u { out += ~" "; indent -= 1u; } - out += ~"...\n"; + while indent > 0u { out += " "; indent -= 1u; } + out += "...\n"; io::stderr().write_str(out); } @@ -269,7 +283,7 @@ fn highlight_lines(cm: @codemap::CodeMap, // part of the 'filename:line ' part of the previous line. let skip = str::len(fm.name) + digits + 3u; for skip.times() { - s += ~" "; + s += " "; } let orig = fm.get_line(lines.lines[0] as int); for uint::range(0u,left-skip) |pos| { @@ -279,14 +293,14 @@ fn highlight_lines(cm: @codemap::CodeMap, _ => " " // -squigly-line as well (instead of a }; // space). This way the squigly-line will } // usually appear in the correct position. - s += ~"^"; + s += "^"; let hi = cm.lookup_char_pos(sp.hi); if hi.col != lo.col { // the ^ already takes up one space let num_squiglies = hi.col.to_uint()-lo.col.to_uint()-1u; - for num_squiglies.times() { s += ~"~"; } + for num_squiglies.times() { s += "~"; } } - io::stderr().write_str(s + ~"\n"); + io::stderr().write_str(s + "\n"); } } @@ -296,7 +310,7 @@ fn print_macro_backtrace(cm: @codemap::CodeMap, sp: span) { print_diagnostic(*ss, note, fmt!("in expansion of %s!", ei.callee.name)); let ss = cm.span_to_str(ei.call_site); - print_diagnostic(ss, note, ~"expansion site"); + print_diagnostic(ss, note, "expansion site"); print_macro_backtrace(cm, ei.call_site); } } diff --git a/src/libsyntax/ext/asm.rs b/src/libsyntax/ext/asm.rs index 97c5797cf57d2..7f8f2be6f6e1e 100644 --- a/src/libsyntax/ext/asm.rs +++ b/src/libsyntax/ext/asm.rs @@ -12,6 +12,8 @@ * Inline assembly support. */ +use core::prelude::*; + use ast; use codemap::span; use ext::base; @@ -19,6 +21,9 @@ use ext::base::*; use parse; use parse::token; +use core::str; +use core::vec; + enum State { Asm, Outputs, @@ -37,7 +42,7 @@ fn next_state(s: State) -> Option { } } -pub fn expand_asm(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree]) +pub fn expand_asm(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree]) -> base::MacResult { let p = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(), @@ -77,7 +82,6 @@ pub fn expand_asm(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree]) let out = @ast::expr { id: cx.next_id(), - callee_id: cx.next_id(), span: out.span, node: ast::expr_addr_of(ast::m_mutbl, out) }; @@ -112,7 +116,7 @@ pub fn expand_asm(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree]) p.eat(&token::COMMA); } - let clob = ~"~{" + *p.parse_str() + ~"}"; + let clob = ~"~{" + *p.parse_str() + "}"; clobs.push(clob); } @@ -174,7 +178,6 @@ pub fn expand_asm(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree]) MRExpr(@ast::expr { id: cx.next_id(), - callee_id: cx.next_id(), node: ast::expr_inline_asm(ast::inline_asm { asm: @asm, clobbers: @cons, diff --git a/src/libsyntax/ext/auto_encode.rs b/src/libsyntax/ext/auto_encode.rs index 6bb3ac5eba4cd..64d2644b38310 100644 --- a/src/libsyntax/ext/auto_encode.rs +++ b/src/libsyntax/ext/auto_encode.rs @@ -15,7 +15,7 @@ use codemap::span; use ext::base::*; pub fn expand_auto_encode( - cx: @ext_ctxt, + cx: @ExtCtxt, span: span, _mitem: @ast::meta_item, in_items: ~[@ast::item] @@ -25,7 +25,7 @@ pub fn expand_auto_encode( } pub fn expand_auto_decode( - cx: @ext_ctxt, + cx: @ExtCtxt, span: span, _mitem: @ast::meta_item, in_items: ~[@ast::item] diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index a97c69ba4ffec..a3432a00edc03 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -8,7 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use ast; +use ast::Name; use codemap; use codemap::{CodeMap, span, ExpnInfo, ExpandedFrom}; use codemap::CallInfo; @@ -16,8 +19,10 @@ use diagnostic::span_handler; use ext; use parse; use parse::token; +use parse::token::{ident_to_str, intern, str_to_ident}; use core::hashmap::HashMap; +use core::vec; // new-style macro! tt code: // @@ -33,7 +38,7 @@ pub struct MacroDef { ext: SyntaxExtension } -pub type ItemDecorator = @fn(@ext_ctxt, +pub type ItemDecorator = @fn(@ExtCtxt, span, @ast::meta_item, ~[@ast::item]) @@ -44,7 +49,7 @@ pub struct SyntaxExpanderTT { span: Option } -pub type SyntaxExpanderTTFun = @fn(@ext_ctxt, +pub type SyntaxExpanderTTFun = @fn(@ExtCtxt, span, &[ast::token_tree]) -> MacResult; @@ -54,7 +59,7 @@ pub struct SyntaxExpanderTTItem { span: Option } -pub type SyntaxExpanderTTItemFun = @fn(@ext_ctxt, +pub type SyntaxExpanderTTItemFun = @fn(@ExtCtxt, span, ast::ident, ~[ast::token_tree]) @@ -88,29 +93,33 @@ pub enum SyntaxExtension { IdentTT(SyntaxExpanderTTItem), } +// The SyntaxEnv is the environment that's threaded through the expansion +// of macros. It contains bindings for macros, and also a special binding +// for " block" (not a legal identifier) that maps to a BlockInfo pub type SyntaxEnv = @mut MapChain; -// Name : the domain of SyntaxEnvs -// want to change these to uints.... -// note that we use certain strings that are not legal as identifiers -// to indicate, for instance, how blocks are supposed to behave. -type Name = @~str; - // Transformer : the codomain of SyntaxEnvs -// NB: it may seem crazy to lump both of these into one environment; -// what would it mean to bind "foo" to BlockLimit(true)? The idea -// is that this follows the lead of MTWT, and accommodates growth -// toward a more uniform syntax syntax (sorry) where blocks are just -// another kind of transformer. - pub enum Transformer { // this identifier maps to a syntax extension or macro SE(SyntaxExtension), - // should blocks occurring here limit macro scopes? - ScopeMacros(bool) + // blockinfo : this is ... well, it's simpler than threading + // another whole data stack-structured data structure through + // expansion. Basically, there's an invariant that every + // map must contain a binding for " block". + BlockInfo(BlockInfo) } +pub struct BlockInfo { + // should macros escape from this scope? + macros_escape : bool, + // what are the pending renames? + pending_renames : @mut RenameList +} + +// a list of ident->name renamings +type RenameList = ~[(ast::ident,Name)]; + // The base map of methods for expanding syntax extension // AST nodes into full ASTs pub fn syntax_expander_table() -> SyntaxEnv { @@ -124,77 +133,80 @@ pub fn syntax_expander_table() -> SyntaxEnv { } let mut syntax_expanders = HashMap::new(); // NB identifier starts with space, and can't conflict with legal idents - syntax_expanders.insert(@~" block", - @ScopeMacros(true)); - syntax_expanders.insert(@~"macro_rules", + syntax_expanders.insert(intern(&" block"), + @BlockInfo(BlockInfo{ + macros_escape : false, + pending_renames : @mut ~[] + })); + syntax_expanders.insert(intern(&"macro_rules"), builtin_item_tt( ext::tt::macro_rules::add_new_extension)); - syntax_expanders.insert(@~"fmt", + syntax_expanders.insert(intern(&"fmt"), builtin_normal_tt(ext::fmt::expand_syntax_ext)); syntax_expanders.insert( - @~"auto_encode", + intern(&"auto_encode"), @SE(ItemDecorator(ext::auto_encode::expand_auto_encode))); syntax_expanders.insert( - @~"auto_decode", + intern(&"auto_decode"), @SE(ItemDecorator(ext::auto_encode::expand_auto_decode))); - syntax_expanders.insert(@~"env", + syntax_expanders.insert(intern(&"env"), builtin_normal_tt(ext::env::expand_syntax_ext)); - syntax_expanders.insert(@~"bytes", + syntax_expanders.insert(intern("bytes"), builtin_normal_tt(ext::bytes::expand_syntax_ext)); - syntax_expanders.insert(@~"concat_idents", + syntax_expanders.insert(intern("concat_idents"), builtin_normal_tt( ext::concat_idents::expand_syntax_ext)); - syntax_expanders.insert(@~"log_syntax", + syntax_expanders.insert(intern(&"log_syntax"), builtin_normal_tt( ext::log_syntax::expand_syntax_ext)); - syntax_expanders.insert(@~"deriving", + syntax_expanders.insert(intern(&"deriving"), @SE(ItemDecorator( ext::deriving::expand_meta_deriving))); // Quasi-quoting expanders - syntax_expanders.insert(@~"quote_tokens", + syntax_expanders.insert(intern(&"quote_tokens"), builtin_normal_tt(ext::quote::expand_quote_tokens)); - syntax_expanders.insert(@~"quote_expr", + syntax_expanders.insert(intern(&"quote_expr"), builtin_normal_tt(ext::quote::expand_quote_expr)); - syntax_expanders.insert(@~"quote_ty", + syntax_expanders.insert(intern(&"quote_ty"), builtin_normal_tt(ext::quote::expand_quote_ty)); - syntax_expanders.insert(@~"quote_item", + syntax_expanders.insert(intern(&"quote_item"), builtin_normal_tt(ext::quote::expand_quote_item)); - syntax_expanders.insert(@~"quote_pat", + syntax_expanders.insert(intern(&"quote_pat"), builtin_normal_tt(ext::quote::expand_quote_pat)); - syntax_expanders.insert(@~"quote_stmt", + syntax_expanders.insert(intern(&"quote_stmt"), builtin_normal_tt(ext::quote::expand_quote_stmt)); - syntax_expanders.insert(@~"line", + syntax_expanders.insert(intern(&"line"), builtin_normal_tt( ext::source_util::expand_line)); - syntax_expanders.insert(@~"col", + syntax_expanders.insert(intern(&"col"), builtin_normal_tt( ext::source_util::expand_col)); - syntax_expanders.insert(@~"file", + syntax_expanders.insert(intern(&"file"), builtin_normal_tt( ext::source_util::expand_file)); - syntax_expanders.insert(@~"stringify", + syntax_expanders.insert(intern(&"stringify"), builtin_normal_tt( ext::source_util::expand_stringify)); - syntax_expanders.insert(@~"include", + syntax_expanders.insert(intern(&"include"), builtin_normal_tt( ext::source_util::expand_include)); - syntax_expanders.insert(@~"include_str", + syntax_expanders.insert(intern(&"include_str"), builtin_normal_tt( ext::source_util::expand_include_str)); - syntax_expanders.insert(@~"include_bin", + syntax_expanders.insert(intern(&"include_bin"), builtin_normal_tt( ext::source_util::expand_include_bin)); - syntax_expanders.insert(@~"module_path", + syntax_expanders.insert(intern(&"module_path"), builtin_normal_tt( ext::source_util::expand_mod)); - syntax_expanders.insert(@~"proto", + syntax_expanders.insert(intern(&"proto"), builtin_item_tt(ext::pipes::expand_proto)); - syntax_expanders.insert(@~"asm", + syntax_expanders.insert(intern(&"asm"), builtin_normal_tt(ext::asm::expand_asm)); syntax_expanders.insert( - @~"trace_macros", + intern(&"trace_macros"), builtin_normal_tt(ext::trace_macros::expand_trace_macros)); MapChain::new(~syntax_expanders) } @@ -202,134 +214,110 @@ pub fn syntax_expander_table() -> SyntaxEnv { // One of these is made during expansion and incrementally updated as we go; // when a macro expansion occurs, the resulting nodes have the backtrace() // -> expn_info of their expansion context stored into their span. -pub trait ext_ctxt { - fn codemap(&self) -> @CodeMap; - fn parse_sess(&self) -> @mut parse::ParseSess; - fn cfg(&self) -> ast::crate_cfg; - fn call_site(&self) -> span; - fn print_backtrace(&self); - fn backtrace(&self) -> Option<@ExpnInfo>; - fn mod_push(&self, mod_name: ast::ident); - fn mod_pop(&self); - fn mod_path(&self) -> ~[ast::ident]; - fn bt_push(&self, ei: codemap::ExpnInfo); - fn bt_pop(&self); - fn span_fatal(&self, sp: span, msg: &str) -> !; - fn span_err(&self, sp: span, msg: &str); - fn span_warn(&self, sp: span, msg: &str); - fn span_unimpl(&self, sp: span, msg: &str) -> !; - fn span_bug(&self, sp: span, msg: &str) -> !; - fn bug(&self, msg: &str) -> !; - fn next_id(&self) -> ast::node_id; - fn trace_macros(&self) -> bool; - fn set_trace_macros(&self, x: bool); - /* for unhygienic identifier transformation */ - fn str_of(&self, id: ast::ident) -> ~str; - fn ident_of(&self, st: &str) -> ast::ident; +pub struct ExtCtxt { + parse_sess: @mut parse::ParseSess, + cfg: ast::crate_cfg, + backtrace: @mut Option<@ExpnInfo>, + + // These two @mut's should really not be here, + // but the self types for CtxtRepr are all wrong + // and there are bugs in the code for object + // types that make this hard to get right at the + // moment. - nmatsakis + mod_path: @mut ~[ast::ident], + trace_mac: @mut bool } -pub fn mk_ctxt(parse_sess: @mut parse::ParseSess, cfg: ast::crate_cfg) - -> @ext_ctxt { - struct CtxtRepr { - parse_sess: @mut parse::ParseSess, - cfg: ast::crate_cfg, - backtrace: @mut Option<@ExpnInfo>, - - // These two @mut's should really not be here, - // but the self types for CtxtRepr are all wrong - // and there are bugs in the code for object - // types that make this hard to get right at the - // moment. - nmatsakis - mod_path: @mut ~[ast::ident], - trace_mac: @mut bool - } - impl ext_ctxt for CtxtRepr { - fn codemap(&self) -> @CodeMap { self.parse_sess.cm } - fn parse_sess(&self) -> @mut parse::ParseSess { self.parse_sess } - fn cfg(&self) -> ast::crate_cfg { copy self.cfg } - fn call_site(&self) -> span { - match *self.backtrace { - Some(@ExpandedFrom(CallInfo {call_site: cs, _})) => cs, - None => self.bug(~"missing top span") - } +impl ExtCtxt { + pub fn new(parse_sess: @mut parse::ParseSess, cfg: ast::crate_cfg) + -> @ExtCtxt { + @ExtCtxt { + parse_sess: parse_sess, + cfg: cfg, + backtrace: @mut None, + mod_path: @mut ~[], + trace_mac: @mut false } - fn print_backtrace(&self) { } - fn backtrace(&self) -> Option<@ExpnInfo> { *self.backtrace } - fn mod_push(&self, i: ast::ident) { self.mod_path.push(i); } - fn mod_pop(&self) { self.mod_path.pop(); } - fn mod_path(&self) -> ~[ast::ident] { copy *self.mod_path } - fn bt_push(&self, ei: codemap::ExpnInfo) { - match ei { - ExpandedFrom(CallInfo {call_site: cs, callee: ref callee}) => { + } + + pub fn codemap(&self) -> @CodeMap { self.parse_sess.cm } + pub fn parse_sess(&self) -> @mut parse::ParseSess { self.parse_sess } + pub fn cfg(&self) -> ast::crate_cfg { copy self.cfg } + pub fn call_site(&self) -> span { + match *self.backtrace { + Some(@ExpandedFrom(CallInfo {call_site: cs, _})) => cs, + None => self.bug("missing top span") + } + } + pub fn print_backtrace(&self) { } + pub fn backtrace(&self) -> Option<@ExpnInfo> { *self.backtrace } + pub fn mod_push(&self, i: ast::ident) { self.mod_path.push(i); } + pub fn mod_pop(&self) { self.mod_path.pop(); } + pub fn mod_path(&self) -> ~[ast::ident] { copy *self.mod_path } + pub fn bt_push(&self, ei: codemap::ExpnInfo) { + match ei { + ExpandedFrom(CallInfo {call_site: cs, callee: ref callee}) => { *self.backtrace = Some(@ExpandedFrom(CallInfo { call_site: span {lo: cs.lo, hi: cs.hi, expn_info: *self.backtrace}, callee: copy *callee})); - } } } - fn bt_pop(&self) { - match *self.backtrace { - Some(@ExpandedFrom(CallInfo { - call_site: span {expn_info: prev, _}, _ - })) => { + } + pub fn bt_pop(&self) { + match *self.backtrace { + Some(@ExpandedFrom( + CallInfo { + call_site: span {expn_info: prev, _}, _ + })) => { *self.backtrace = prev - } - _ => self.bug(~"tried to pop without a push") } + _ => self.bug("tried to pop without a push") } - fn span_fatal(&self, sp: span, msg: &str) -> ! { - self.print_backtrace(); - self.parse_sess.span_diagnostic.span_fatal(sp, msg); - } - fn span_err(&self, sp: span, msg: &str) { - self.print_backtrace(); - self.parse_sess.span_diagnostic.span_err(sp, msg); - } - fn span_warn(&self, sp: span, msg: &str) { - self.print_backtrace(); - self.parse_sess.span_diagnostic.span_warn(sp, msg); - } - fn span_unimpl(&self, sp: span, msg: &str) -> ! { - self.print_backtrace(); - self.parse_sess.span_diagnostic.span_unimpl(sp, msg); - } - fn span_bug(&self, sp: span, msg: &str) -> ! { - self.print_backtrace(); - self.parse_sess.span_diagnostic.span_bug(sp, msg); - } - fn bug(&self, msg: &str) -> ! { - self.print_backtrace(); - self.parse_sess.span_diagnostic.handler().bug(msg); - } - fn next_id(&self) -> ast::node_id { - return parse::next_node_id(self.parse_sess); - } - fn trace_macros(&self) -> bool { - *self.trace_mac - } - fn set_trace_macros(&self, x: bool) { - *self.trace_mac = x - } - fn str_of(&self, id: ast::ident) -> ~str { - copy *self.parse_sess.interner.get(id) - } - fn ident_of(&self, st: &str) -> ast::ident { - self.parse_sess.interner.intern(st) - } } - let imp: @CtxtRepr = @CtxtRepr { - parse_sess: parse_sess, - cfg: cfg, - backtrace: @mut None, - mod_path: @mut ~[], - trace_mac: @mut false - }; - ((imp) as @ext_ctxt) + pub fn span_fatal(&self, sp: span, msg: &str) -> ! { + self.print_backtrace(); + self.parse_sess.span_diagnostic.span_fatal(sp, msg); + } + pub fn span_err(&self, sp: span, msg: &str) { + self.print_backtrace(); + self.parse_sess.span_diagnostic.span_err(sp, msg); + } + pub fn span_warn(&self, sp: span, msg: &str) { + self.print_backtrace(); + self.parse_sess.span_diagnostic.span_warn(sp, msg); + } + pub fn span_unimpl(&self, sp: span, msg: &str) -> ! { + self.print_backtrace(); + self.parse_sess.span_diagnostic.span_unimpl(sp, msg); + } + pub fn span_bug(&self, sp: span, msg: &str) -> ! { + self.print_backtrace(); + self.parse_sess.span_diagnostic.span_bug(sp, msg); + } + pub fn bug(&self, msg: &str) -> ! { + self.print_backtrace(); + self.parse_sess.span_diagnostic.handler().bug(msg); + } + pub fn next_id(&self) -> ast::node_id { + parse::next_node_id(self.parse_sess) + } + pub fn trace_macros(&self) -> bool { + *self.trace_mac + } + pub fn set_trace_macros(&self, x: bool) { + *self.trace_mac = x + } + pub fn str_of(&self, id: ast::ident) -> ~str { + copy *ident_to_str(&id) + } + pub fn ident_of(&self, st: &str) -> ast::ident { + str_to_ident(st) + } } -pub fn expr_to_str(cx: @ext_ctxt, expr: @ast::expr, err_msg: ~str) -> ~str { +pub fn expr_to_str(cx: @ExtCtxt, expr: @ast::expr, err_msg: ~str) -> ~str { match expr.node { ast::expr_lit(l) => match l.node { ast::lit_str(s) => copy *s, @@ -339,7 +327,7 @@ pub fn expr_to_str(cx: @ext_ctxt, expr: @ast::expr, err_msg: ~str) -> ~str { } } -pub fn expr_to_ident(cx: @ext_ctxt, +pub fn expr_to_ident(cx: @ExtCtxt, expr: @ast::expr, err_msg: &str) -> ast::ident { match expr.node { @@ -353,14 +341,14 @@ pub fn expr_to_ident(cx: @ext_ctxt, } } -pub fn check_zero_tts(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree], +pub fn check_zero_tts(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree], name: &str) { if tts.len() != 0 { cx.span_fatal(sp, fmt!("%s takes no arguments", name)); } } -pub fn get_single_str_from_tts(cx: @ext_ctxt, +pub fn get_single_str_from_tts(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree], name: &str) -> ~str { @@ -375,7 +363,7 @@ pub fn get_single_str_from_tts(cx: @ext_ctxt, } } -pub fn get_exprs_from_tts(cx: @ext_ctxt, tts: &[ast::token_tree]) +pub fn get_exprs_from_tts(cx: @ExtCtxt, tts: &[ast::token_tree]) -> ~[@ast::expr] { let p = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(), @@ -458,7 +446,7 @@ impl MapChain{ } // traits just don't work anywhere...? -//pub impl Map for MapChain { +//impl Map for MapChain { fn contains_key (&self, key: &K) -> bool { match *self { @@ -491,6 +479,15 @@ impl MapChain{ } } + fn find_in_topmost_frame(&self, key: &K) -> Option<@V> { + let map = match *self { + BaseMapChain(ref map) => map, + ConsMapChain(ref map,_) => map + }; + // strip one layer of indirection off the pointer. + map.find(key).map(|r| {**r}) + } + // insert the binding into the top-level map fn insert (&mut self, key: K, ext: @V) -> bool { // can't abstract over get_map because of flow sensitivity... @@ -499,7 +496,40 @@ impl MapChain{ ConsMapChain (~ref mut map,_) => map.insert(key,ext) } } + // insert the binding into the topmost frame for which the binding + // associated with 'n' exists and satisfies pred + // ... there are definitely some opportunities for abstraction + // here that I'm ignoring. (e.g., manufacturing a predicate on + // the maps in the chain, and using an abstract "find". + fn insert_into_frame(&mut self, key: K, ext: @V, n: K, pred: &fn(&@V)->bool) { + match *self { + BaseMapChain (~ref mut map) => { + if satisfies_pred(map,&n,pred) { + map.insert(key,ext); + } else { + fail!(~"expected map chain containing satisfying frame") + } + }, + ConsMapChain (~ref mut map, rest) => { + if satisfies_pred(map,&n,pred) { + map.insert(key,ext); + } else { + rest.insert_into_frame(key,ext,n,pred) + } + } + } + } +} +// returns true if the binding for 'n' satisfies 'pred' in 'map' +fn satisfies_pred(map : &mut HashMap, + n: &K, + pred: &fn(&V)->bool) + -> bool { + match map.find(n) { + Some(ref v) => (pred(*v)), + None => false + } } #[cfg(test)] diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 624e0495e5950..324b909fbb033 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -8,13 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + +use abi::AbiSet; +use ast::ident; use ast; -use codemap; -use codemap::span; +use ast_util; +use codemap::{span, respan, dummy_sp}; use fold; -use ext::base::ext_ctxt; -use ext::build; - +use ext::base::ExtCtxt; +use ext::quote::rt::*; +use opt_vec; use opt_vec::OptVec; pub struct Field { @@ -22,818 +26,831 @@ pub struct Field { ex: @ast::expr } -pub fn mk_expr(cx: @ext_ctxt, - sp: codemap::span, - expr: ast::expr_) - -> @ast::expr { - @ast::expr { - id: cx.next_id(), - callee_id: cx.next_id(), - node: expr, - span: sp, - } +// Transitional reexports so qquote can find the paths it is looking for +mod syntax { + pub use ext; + pub use parse; } -pub fn mk_lit(cx: @ext_ctxt, sp: span, lit: ast::lit_) -> @ast::expr { - let sp_lit = @codemap::spanned { node: lit, span: sp }; - mk_expr(cx, sp, ast::expr_lit(sp_lit)) -} -pub fn mk_int(cx: @ext_ctxt, sp: span, i: int) -> @ast::expr { - let lit = ast::lit_int(i as i64, ast::ty_i); - return mk_lit(cx, sp, lit); -} -pub fn mk_uint(cx: @ext_ctxt, sp: span, u: uint) -> @ast::expr { - let lit = ast::lit_uint(u as u64, ast::ty_u); - return mk_lit(cx, sp, lit); -} -pub fn mk_u8(cx: @ext_ctxt, sp: span, u: u8) -> @ast::expr { - let lit = ast::lit_uint(u as u64, ast::ty_u8); - return mk_lit(cx, sp, lit); -} -pub fn mk_binary(cx: @ext_ctxt, sp: span, op: ast::binop, - lhs: @ast::expr, rhs: @ast::expr) -> @ast::expr { - cx.next_id(); // see ast_util::op_expr_callee_id - mk_expr(cx, sp, ast::expr_binary(op, lhs, rhs)) -} +pub trait AstBuilder { + // paths + fn path(&self, span: span, strs: ~[ast::ident]) -> @ast::Path; + fn path_ident(&self, span: span, id: ast::ident) -> @ast::Path; + fn path_global(&self, span: span, strs: ~[ast::ident]) -> @ast::Path; + fn path_all(&self, sp: span, + global: bool, + idents: ~[ast::ident], + rp: Option<@ast::Lifetime>, + types: ~[@ast::Ty]) + -> @ast::Path; + + // types + fn ty_mt(&self, ty: @ast::Ty, mutbl: ast::mutability) -> ast::mt; + + fn ty(&self, span: span, ty: ast::ty_) -> @ast::Ty; + fn ty_path(&self, @ast::Path) -> @ast::Ty; + fn ty_ident(&self, span: span, idents: ast::ident) -> @ast::Ty; + + fn ty_rptr(&self, span: span, + ty: @ast::Ty, + lifetime: Option<@ast::Lifetime>, + mutbl: ast::mutability) + -> @ast::Ty; + fn ty_uniq(&self, span: span, ty: @ast::Ty) -> @ast::Ty; + fn ty_box(&self, span: span, ty: @ast::Ty, mutbl: ast::mutability) -> @ast::Ty; + + fn ty_option(&self, ty: @ast::Ty) -> @ast::Ty; + fn ty_infer(&self, sp: span) -> @ast::Ty; + fn ty_nil(&self) -> @ast::Ty; + + fn ty_vars(&self, ty_params: &OptVec) -> ~[@ast::Ty]; + fn ty_vars_global(&self, ty_params: &OptVec) -> ~[@ast::Ty]; + fn ty_field_imm(&self, span: span, name: ident, ty: @ast::Ty) -> ast::ty_field; + fn strip_bounds(&self, bounds: &Generics) -> Generics; + + fn typaram(&self, id: ast::ident, bounds: @OptVec) -> ast::TyParam; + + fn trait_ref(&self, path: @ast::Path) -> @ast::trait_ref; + fn typarambound(&self, path: @ast::Path) -> ast::TyParamBound; + fn lifetime(&self, span: span, ident: ast::ident) -> ast::Lifetime; + + // statements + fn stmt_expr(&self, expr: @ast::expr) -> @ast::stmt; + fn stmt_let(&self, sp: span, mutbl: bool, ident: ast::ident, ex: @ast::expr) -> @ast::stmt; + + // blocks + fn blk(&self, span: span, stmts: ~[@ast::stmt], expr: Option<@ast::expr>) -> ast::blk; + fn blk_expr(&self, expr: @ast::expr) -> ast::blk; + fn blk_all(&self, span: span, + view_items: ~[@ast::view_item], + stmts: ~[@ast::stmt], + expr: Option<@ast::expr>) -> ast::blk; + + // expressions + fn expr(&self, span: span, node: ast::expr_) -> @ast::expr; + fn expr_path(&self, path: @ast::Path) -> @ast::expr; + fn expr_ident(&self, span: span, id: ast::ident) -> @ast::expr; -pub fn mk_deref(cx: @ext_ctxt, sp: span, e: @ast::expr) -> @ast::expr { - mk_unary(cx, sp, ast::deref, e) -} -pub fn mk_unary(cx: @ext_ctxt, sp: span, op: ast::unop, e: @ast::expr) - -> @ast::expr { - cx.next_id(); // see ast_util::op_expr_callee_id - mk_expr(cx, sp, ast::expr_unary(op, e)) -} -pub fn mk_raw_path(sp: span, idents: ~[ast::ident]) -> @ast::Path { - mk_raw_path_(sp, idents, None, ~[]) -} -pub fn mk_raw_path_(sp: span, - idents: ~[ast::ident], - rp: Option<@ast::Lifetime>, - types: ~[@ast::Ty]) - -> @ast::Path { - @ast::Path { span: sp, - global: false, - idents: idents, - rp: rp, - types: types } -} -pub fn mk_raw_path_global(sp: span, idents: ~[ast::ident]) -> @ast::Path { - mk_raw_path_global_(sp, idents, None, ~[]) -} -pub fn mk_raw_path_global_(sp: span, - idents: ~[ast::ident], - rp: Option<@ast::Lifetime>, - types: ~[@ast::Ty]) -> @ast::Path { - @ast::Path { span: sp, - global: true, - idents: idents, - rp: rp, - types: types } -} -pub fn mk_path_raw(cx: @ext_ctxt, sp: span, path: @ast::Path)-> @ast::expr { - mk_expr(cx, sp, ast::expr_path(path)) -} -pub fn mk_path(cx: @ext_ctxt, sp: span, idents: ~[ast::ident]) - -> @ast::expr { - mk_path_raw(cx, sp, mk_raw_path(sp, idents)) -} -pub fn mk_path_global(cx: @ext_ctxt, sp: span, idents: ~[ast::ident]) - -> @ast::expr { - mk_path_raw(cx, sp, mk_raw_path_global(sp, idents)) -} -pub fn mk_access_(cx: @ext_ctxt, sp: span, p: @ast::expr, m: ast::ident) - -> @ast::expr { - mk_expr(cx, sp, ast::expr_field(p, m, ~[])) -} -pub fn mk_access(cx: @ext_ctxt, sp: span, p: ~[ast::ident], m: ast::ident) - -> @ast::expr { - let pathexpr = mk_path(cx, sp, p); - return mk_access_(cx, sp, pathexpr, m); -} -pub fn mk_addr_of(cx: @ext_ctxt, sp: span, e: @ast::expr) -> @ast::expr { - return mk_expr(cx, sp, ast::expr_addr_of(ast::m_imm, e)); -} -pub fn mk_mut_addr_of(cx: @ext_ctxt, sp: span, e: @ast::expr) -> @ast::expr { - return mk_expr(cx, sp, ast::expr_addr_of(ast::m_mutbl, e)); -} -pub fn mk_method_call(cx: @ext_ctxt, - sp: span, - rcvr_expr: @ast::expr, - method_ident: ast::ident, - args: ~[@ast::expr]) -> @ast::expr { - mk_expr(cx, sp, ast::expr_method_call(rcvr_expr, method_ident, ~[], args, ast::NoSugar)) -} -pub fn mk_call_(cx: @ext_ctxt, sp: span, fn_expr: @ast::expr, - args: ~[@ast::expr]) -> @ast::expr { - mk_expr(cx, sp, ast::expr_call(fn_expr, args, ast::NoSugar)) -} -pub fn mk_call(cx: @ext_ctxt, sp: span, fn_path: ~[ast::ident], - args: ~[@ast::expr]) -> @ast::expr { - let pathexpr = mk_path(cx, sp, fn_path); - return mk_call_(cx, sp, pathexpr, args); -} -pub fn mk_call_global(cx: @ext_ctxt, sp: span, fn_path: ~[ast::ident], - args: ~[@ast::expr]) -> @ast::expr { - let pathexpr = mk_path_global(cx, sp, fn_path); - return mk_call_(cx, sp, pathexpr, args); -} -// e = expr, t = type -pub fn mk_base_vec_e(cx: @ext_ctxt, sp: span, exprs: ~[@ast::expr]) - -> @ast::expr { - let vecexpr = ast::expr_vec(exprs, ast::m_imm); - mk_expr(cx, sp, vecexpr) -} -pub fn mk_vstore_e(cx: @ext_ctxt, sp: span, expr: @ast::expr, - vst: ast::expr_vstore) -> - @ast::expr { - mk_expr(cx, sp, ast::expr_vstore(expr, vst)) -} -pub fn mk_uniq_vec_e(cx: @ext_ctxt, sp: span, exprs: ~[@ast::expr]) - -> @ast::expr { - mk_vstore_e(cx, sp, mk_base_vec_e(cx, sp, exprs), ast::expr_vstore_uniq) -} -pub fn mk_slice_vec_e(cx: @ext_ctxt, sp: span, exprs: ~[@ast::expr]) - -> @ast::expr { - mk_vstore_e(cx, sp, mk_base_vec_e(cx, sp, exprs), - ast::expr_vstore_slice) -} -pub fn mk_base_str(cx: @ext_ctxt, sp: span, s: ~str) -> @ast::expr { - let lit = ast::lit_str(@s); - return mk_lit(cx, sp, lit); -} -pub fn mk_uniq_str(cx: @ext_ctxt, sp: span, s: ~str) -> @ast::expr { - mk_vstore_e(cx, sp, mk_base_str(cx, sp, s), ast::expr_vstore_uniq) + fn expr_self(&self, span: span) -> @ast::expr; + fn expr_binary(&self, sp: span, op: ast::binop, + lhs: @ast::expr, rhs: @ast::expr) -> @ast::expr; + fn expr_deref(&self, sp: span, e: @ast::expr) -> @ast::expr; + fn expr_unary(&self, sp: span, op: ast::unop, e: @ast::expr) -> @ast::expr; + + fn expr_copy(&self, sp: span, e: @ast::expr) -> @ast::expr; + fn expr_managed(&self, sp: span, e: @ast::expr) -> @ast::expr; + fn expr_addr_of(&self, sp: span, e: @ast::expr) -> @ast::expr; + fn expr_mut_addr_of(&self, sp: span, e: @ast::expr) -> @ast::expr; + fn expr_field_access(&self, span: span, expr: @ast::expr, ident: ast::ident) -> @ast::expr; + fn expr_call(&self, span: span, expr: @ast::expr, args: ~[@ast::expr]) -> @ast::expr; + fn expr_call_ident(&self, span: span, id: ast::ident, args: ~[@ast::expr]) -> @ast::expr; + fn expr_call_global(&self, sp: span, fn_path: ~[ast::ident], + args: ~[@ast::expr]) -> @ast::expr; + fn expr_method_call(&self, span: span, + expr: @ast::expr, ident: ast::ident, + args: ~[@ast::expr]) -> @ast::expr; + fn expr_blk(&self, b: ast::blk) -> @ast::expr; + + fn field_imm(&self, span: span, name: ident, e: @ast::expr) -> ast::field; + fn expr_struct(&self, span: span, path: @ast::Path, fields: ~[ast::field]) -> @ast::expr; + fn expr_struct_ident(&self, span: span, id: ast::ident, fields: ~[ast::field]) -> @ast::expr; + + fn expr_lit(&self, sp: span, lit: ast::lit_) -> @ast::expr; + + fn expr_uint(&self, span: span, i: uint) -> @ast::expr; + fn expr_int(&self, sp: span, i: int) -> @ast::expr; + fn expr_u8(&self, sp: span, u: u8) -> @ast::expr; + fn expr_bool(&self, sp: span, value: bool) -> @ast::expr; + + fn expr_vstore(&self, sp: span, expr: @ast::expr, vst: ast::expr_vstore) -> @ast::expr; + fn expr_vec(&self, sp: span, exprs: ~[@ast::expr]) -> @ast::expr; + fn expr_vec_uniq(&self, sp: span, exprs: ~[@ast::expr]) -> @ast::expr; + fn expr_vec_slice(&self, sp: span, exprs: ~[@ast::expr]) -> @ast::expr; + fn expr_str(&self, sp: span, s: ~str) -> @ast::expr; + fn expr_str_uniq(&self, sp: span, s: ~str) -> @ast::expr; + + fn expr_unreachable(&self, span: span) -> @ast::expr; + + fn pat(&self, span: span, pat: ast::pat_) -> @ast::pat; + fn pat_wild(&self, span: span) -> @ast::pat; + fn pat_lit(&self, span: span, expr: @ast::expr) -> @ast::pat; + fn pat_ident(&self, span: span, ident: ast::ident) -> @ast::pat; + + fn pat_ident_binding_mode(&self, + span: span, + ident: ast::ident, + bm: ast::binding_mode) -> @ast::pat; + fn pat_enum(&self, span: span, path: @ast::Path, subpats: ~[@ast::pat]) -> @ast::pat; + fn pat_struct(&self, span: span, + path: @ast::Path, field_pats: ~[ast::field_pat]) -> @ast::pat; + + fn arm(&self, span: span, pats: ~[@ast::pat], expr: @ast::expr) -> ast::arm; + fn arm_unreachable(&self, span: span) -> ast::arm; + + fn expr_match(&self, span: span, arg: @ast::expr, arms: ~[ast::arm]) -> @ast::expr; + fn expr_if(&self, span: span, + cond: @ast::expr, then: @ast::expr, els: Option<@ast::expr>) -> @ast::expr; + + fn lambda_fn_decl(&self, span: span, fn_decl: ast::fn_decl, blk: ast::blk) -> @ast::expr; + + fn lambda(&self, span: span, ids: ~[ast::ident], blk: ast::blk) -> @ast::expr; + fn lambda0(&self, span: span, blk: ast::blk) -> @ast::expr; + fn lambda1(&self, span: span, blk: ast::blk, ident: ast::ident) -> @ast::expr; + + fn lambda_expr(&self, span: span, ids: ~[ast::ident], blk: @ast::expr) -> @ast::expr; + fn lambda_expr_0(&self, span: span, expr: @ast::expr) -> @ast::expr; + fn lambda_expr_1(&self, span: span, expr: @ast::expr, ident: ast::ident) -> @ast::expr; + + fn lambda_stmts(&self, span: span, ids: ~[ast::ident], blk: ~[@ast::stmt]) -> @ast::expr; + fn lambda_stmts_0(&self, span: span, stmts: ~[@ast::stmt]) -> @ast::expr; + fn lambda_stmts_1(&self, span: span, stmts: ~[@ast::stmt], ident: ast::ident) -> @ast::expr; + + // items + fn item(&self, span: span, + name: ident, attrs: ~[ast::attribute], node: ast::item_) -> @ast::item; + + fn arg(&self, span: span, name: ident, ty: @ast::Ty) -> ast::arg; + // XXX unused self + fn fn_decl(&self, inputs: ~[ast::arg], output: @ast::Ty) -> ast::fn_decl; + + fn item_fn_poly(&self, + span: span, + name: ident, + inputs: ~[ast::arg], + output: @ast::Ty, + generics: Generics, + body: ast::blk) -> @ast::item; + fn item_fn(&self, + span: span, + name: ident, + inputs: ~[ast::arg], + output: @ast::Ty, + body: ast::blk) -> @ast::item; + + fn variant(&self, span: span, name: ident, tys: ~[@ast::Ty]) -> ast::variant; + fn item_enum_poly(&self, + span: span, + name: ident, + enum_definition: ast::enum_def, + generics: Generics) -> @ast::item; + fn item_enum(&self, span: span, name: ident, enum_def: ast::enum_def) -> @ast::item; + + fn item_struct_poly(&self, + span: span, + name: ident, + struct_def: ast::struct_def, + generics: Generics) -> @ast::item; + fn item_struct(&self, span: span, name: ident, struct_def: ast::struct_def) -> @ast::item; + + fn item_mod(&self, span: span, + name: ident, attrs: ~[ast::attribute], + vi: ~[@ast::view_item], items: ~[@ast::item]) -> @ast::item; + + fn item_ty_poly(&self, + span: span, + name: ident, + ty: @ast::Ty, + generics: Generics) -> @ast::item; + fn item_ty(&self, span: span, name: ident, ty: @ast::Ty) -> @ast::item; + + fn attribute(&self, sp: span, mi: @ast::meta_item) -> ast::attribute; + + fn meta_word(&self, sp: span, w: ~str) -> @ast::meta_item; + fn meta_list(&self, sp: span, name: ~str, mis: ~[@ast::meta_item]) -> @ast::meta_item; + fn meta_name_value(&self, sp: span, name: ~str, value: ast::lit_) -> @ast::meta_item; + + fn view_use(&self, sp: span, + vis: ast::visibility, vp: ~[@ast::view_path]) -> @ast::view_item; + fn view_use_list(&self, sp: span, vis: ast::visibility, + path: ~[ast::ident], imports: &[ast::ident]) -> @ast::view_item; + fn view_use_glob(&self, sp: span, + vis: ast::visibility, path: ~[ast::ident]) -> @ast::view_item; } -pub fn mk_field(sp: span, f: &Field) -> ast::field { - codemap::spanned { - node: ast::field_ { mutbl: ast::m_imm, ident: f.ident, expr: f.ex }, - span: sp, + +impl AstBuilder for @ExtCtxt { + fn path(&self, span: span, strs: ~[ast::ident]) -> @ast::Path { + self.path_all(span, false, strs, None, ~[]) } -} -pub fn mk_fields(sp: span, fields: ~[Field]) -> ~[ast::field] { - fields.map(|f| mk_field(sp, f)) -} -pub fn mk_struct_e(cx: @ext_ctxt, - sp: span, - ctor_path: ~[ast::ident], - fields: ~[Field]) - -> @ast::expr { - mk_expr(cx, sp, - ast::expr_struct(mk_raw_path(sp, ctor_path), - mk_fields(sp, fields), - option::None::<@ast::expr>)) -} -pub fn mk_global_struct_e(cx: @ext_ctxt, - sp: span, - ctor_path: ~[ast::ident], - fields: ~[Field]) - -> @ast::expr { - mk_expr(cx, sp, - ast::expr_struct(mk_raw_path_global(sp, ctor_path), - mk_fields(sp, fields), - option::None::<@ast::expr>)) -} -pub fn mk_glob_use(cx: @ext_ctxt, - sp: span, - vis: ast::visibility, - path: ~[ast::ident]) -> @ast::view_item { - let glob = @codemap::spanned { - node: ast::view_path_glob(mk_raw_path(sp, path), cx.next_id()), - span: sp, - }; - @ast::view_item { node: ast::view_item_use(~[glob]), - attrs: ~[], - vis: vis, - span: sp } -} -pub fn mk_local(cx: @ext_ctxt, sp: span, mutbl: bool, - ident: ast::ident, ex: @ast::expr) -> @ast::stmt { - - let pat = @ast::pat { - id: cx.next_id(), - node: ast::pat_ident( - ast::bind_by_copy, - mk_raw_path(sp, ~[ident]), - None), - span: sp, - }; - let ty = @ast::Ty { id: cx.next_id(), node: ast::ty_infer, span: sp }; - let local = @codemap::spanned { - node: ast::local_ { - is_mutbl: mutbl, - ty: ty, - pat: pat, - init: Some(ex), - id: cx.next_id(), - }, - span: sp, - }; - let decl = codemap::spanned {node: ast::decl_local(~[local]), span: sp}; - @codemap::spanned { node: ast::stmt_decl(@decl, cx.next_id()), span: sp } -} -pub fn mk_block(cx: @ext_ctxt, span: span, - view_items: ~[@ast::view_item], - stmts: ~[@ast::stmt], - expr: Option<@ast::expr>) -> @ast::expr { - let blk = codemap::spanned { - node: ast::blk_ { - view_items: view_items, - stmts: stmts, - expr: expr, - id: cx.next_id(), - rules: ast::default_blk, - }, - span: span, - }; - mk_expr(cx, span, ast::expr_block(blk)) -} -pub fn mk_block_(cx: @ext_ctxt, - span: span, - stmts: ~[@ast::stmt]) - -> ast::blk { - codemap::spanned { - node: ast::blk_ { - view_items: ~[], - stmts: stmts, - expr: None, - id: cx.next_id(), - rules: ast::default_blk, - }, - span: span, + fn path_ident(&self, span: span, id: ast::ident) -> @ast::Path { + self.path(span, ~[id]) } -} -pub fn mk_simple_block(cx: @ext_ctxt, - span: span, - expr: @ast::expr) - -> ast::blk { - codemap::spanned { - node: ast::blk_ { - view_items: ~[], - stmts: ~[], - expr: Some(expr), - id: cx.next_id(), - rules: ast::default_blk, - }, - span: span, + fn path_global(&self, span: span, strs: ~[ast::ident]) -> @ast::Path { + self.path_all(span, true, strs, None, ~[]) + } + fn path_all(&self, sp: span, + global: bool, + idents: ~[ast::ident], + rp: Option<@ast::Lifetime>, + types: ~[@ast::Ty]) + -> @ast::Path { + @ast::Path { + span: sp, + global: global, + idents: idents, + rp: rp, + types: types + } } -} -pub fn mk_lambda_(cx: @ext_ctxt, - span: span, - fn_decl: ast::fn_decl, - blk: ast::blk) - -> @ast::expr { - mk_expr(cx, span, ast::expr_fn_block(fn_decl, blk)) -} -pub fn mk_lambda(cx: @ext_ctxt, - span: span, - fn_decl: ast::fn_decl, - expr: @ast::expr) - -> @ast::expr { - let blk = mk_simple_block(cx, span, expr); - mk_lambda_(cx, span, fn_decl, blk) -} -pub fn mk_lambda_stmts(cx: @ext_ctxt, - span: span, - fn_decl: ast::fn_decl, - stmts: ~[@ast::stmt]) - -> @ast::expr { - let blk = mk_block(cx, span, ~[], stmts, None); - mk_lambda(cx, span, fn_decl, blk) -} -pub fn mk_lambda_no_args(cx: @ext_ctxt, - span: span, - expr: @ast::expr) - -> @ast::expr { - let fn_decl = mk_fn_decl(~[], mk_ty_infer(cx, span)); - mk_lambda(cx, span, fn_decl, expr) -} -pub fn mk_copy(cx: @ext_ctxt, sp: span, e: @ast::expr) -> @ast::expr { - mk_expr(cx, sp, ast::expr_copy(e)) -} -pub fn mk_managed(cx: @ext_ctxt, sp: span, e: @ast::expr) -> @ast::expr { - mk_expr(cx, sp, ast::expr_unary(ast::box(ast::m_imm), e)) -} -pub fn mk_pat(cx: @ext_ctxt, span: span, pat: ast::pat_) -> @ast::pat { - @ast::pat { id: cx.next_id(), node: pat, span: span } -} -pub fn mk_pat_wild(cx: @ext_ctxt, span: span) -> @ast::pat { - mk_pat(cx, span, ast::pat_wild) -} -pub fn mk_pat_lit(cx: @ext_ctxt, - span: span, - expr: @ast::expr) -> @ast::pat { - mk_pat(cx, span, ast::pat_lit(expr)) -} -pub fn mk_pat_ident(cx: @ext_ctxt, - span: span, - ident: ast::ident) -> @ast::pat { - mk_pat_ident_with_binding_mode(cx, span, ident, ast::bind_by_copy) -} -pub fn mk_pat_ident_with_binding_mode(cx: @ext_ctxt, - span: span, - ident: ast::ident, - bm: ast::binding_mode) -> @ast::pat { - let path = mk_raw_path(span, ~[ ident ]); - let pat = ast::pat_ident(bm, path, None); - mk_pat(cx, span, pat) -} -pub fn mk_pat_enum(cx: @ext_ctxt, - span: span, - path: @ast::Path, - subpats: ~[@ast::pat]) - -> @ast::pat { - let pat = ast::pat_enum(path, Some(subpats)); - mk_pat(cx, span, pat) -} -pub fn mk_pat_struct(cx: @ext_ctxt, - span: span, - path: @ast::Path, - field_pats: ~[ast::field_pat]) - -> @ast::pat { - let pat = ast::pat_struct(path, field_pats, false); - mk_pat(cx, span, pat) -} -pub fn mk_bool(cx: @ext_ctxt, span: span, value: bool) -> @ast::expr { - let lit_expr = ast::expr_lit(@codemap::spanned { - node: ast::lit_bool(value), - span: span }); - build::mk_expr(cx, span, lit_expr) -} -pub fn mk_stmt(cx: @ext_ctxt, span: span, expr: @ast::expr) -> @ast::stmt { - let stmt_ = ast::stmt_semi(expr, cx.next_id()); - @codemap::spanned { node: stmt_, span: span } -} + fn ty_mt(&self, ty: @ast::Ty, mutbl: ast::mutability) -> ast::mt { + ast::mt { + ty: ty, + mutbl: mutbl + } + } -pub fn mk_ty_mt(ty: @ast::Ty, mutbl: ast::mutability) -> ast::mt { - ast::mt { - ty: ty, - mutbl: mutbl + fn ty(&self, span: span, ty: ast::ty_) -> @ast::Ty { + @ast::Ty { + id: self.next_id(), + span: span, + node: ty + } } -} -pub fn mk_ty(cx: @ext_ctxt, - span: span, - ty: ast::ty_) -> @ast::Ty { - @ast::Ty { - id: cx.next_id(), - span: span, - node: ty + fn ty_path(&self, path: @ast::Path) -> @ast::Ty { + self.ty(path.span, + ast::ty_path(path, self.next_id())) } -} -pub fn mk_ty_path(cx: @ext_ctxt, - span: span, - idents: ~[ ast::ident ]) - -> @ast::Ty { - let ty = build::mk_raw_path(span, idents); - mk_ty_path_path(cx, span, ty) -} + fn ty_ident(&self, span: span, ident: ast::ident) + -> @ast::Ty { + self.ty_path(self.path_ident(span, ident)) + } -pub fn mk_ty_path_global(cx: @ext_ctxt, - span: span, - idents: ~[ ast::ident ]) - -> @ast::Ty { - let ty = build::mk_raw_path_global(span, idents); - mk_ty_path_path(cx, span, ty) -} + fn ty_rptr(&self, + span: span, + ty: @ast::Ty, + lifetime: Option<@ast::Lifetime>, + mutbl: ast::mutability) + -> @ast::Ty { + self.ty(span, + ast::ty_rptr(lifetime, self.ty_mt(ty, mutbl))) + } + fn ty_uniq(&self, span: span, ty: @ast::Ty) -> @ast::Ty { + self.ty(span, ast::ty_uniq(self.ty_mt(ty, ast::m_imm))) + } + fn ty_box(&self, span: span, + ty: @ast::Ty, mutbl: ast::mutability) -> @ast::Ty { + self.ty(span, ast::ty_box(self.ty_mt(ty, mutbl))) + } -pub fn mk_ty_path_path(cx: @ext_ctxt, - span: span, - path: @ast::Path) - -> @ast::Ty { - let ty = ast::ty_path(path, cx.next_id()); - mk_ty(cx, span, ty) -} + fn ty_option(&self, ty: @ast::Ty) -> @ast::Ty { + self.ty_path( + self.path_all(dummy_sp(), + true, + ~[ + self.ident_of("std"), + self.ident_of("option"), + self.ident_of("Option") + ], + None, + ~[ ty ])) + } -pub fn mk_ty_rptr(cx: @ext_ctxt, - span: span, - ty: @ast::Ty, - lifetime: Option<@ast::Lifetime>, - mutbl: ast::mutability) - -> @ast::Ty { - mk_ty(cx, span, - ast::ty_rptr(lifetime, mk_ty_mt(ty, mutbl))) -} -pub fn mk_ty_uniq(cx: @ext_ctxt, span: span, ty: @ast::Ty) -> @ast::Ty { - mk_ty(cx, span, ast::ty_uniq(mk_ty_mt(ty, ast::m_imm))) -} -pub fn mk_ty_box(cx: @ext_ctxt, span: span, - ty: @ast::Ty, mutbl: ast::mutability) -> @ast::Ty { - mk_ty(cx, span, ast::ty_box(mk_ty_mt(ty, mutbl))) -} + fn ty_field_imm(&self, span: span, name: ident, ty: @ast::Ty) -> ast::ty_field { + respan(span, + ast::ty_field_ { + ident: name, + mt: ast::mt { ty: ty, mutbl: ast::m_imm }, + }) + } + fn ty_infer(&self, span: span) -> @ast::Ty { + self.ty(span, ast::ty_infer) + } + fn ty_nil(&self) -> @ast::Ty { + @ast::Ty { + id: self.next_id(), + node: ast::ty_nil, + span: dummy_sp(), + } + } -pub fn mk_ty_infer(cx: @ext_ctxt, span: span) -> @ast::Ty { - mk_ty(cx, span, ast::ty_infer) -} -pub fn mk_trait_ref_global(cx: @ext_ctxt, - span: span, - idents: ~[ ast::ident ]) - -> @ast::trait_ref -{ - mk_trait_ref_(cx, build::mk_raw_path_global(span, idents)) -} -pub fn mk_trait_ref_(cx: @ext_ctxt, path: @ast::Path) -> @ast::trait_ref { - @ast::trait_ref { - path: path, - ref_id: cx.next_id() + fn typaram(&self, id: ast::ident, bounds: @OptVec) -> ast::TyParam { + ast::TyParam { ident: id, id: self.next_id(), bounds: bounds } } -} -pub fn mk_simple_ty_path(cx: @ext_ctxt, - span: span, - ident: ast::ident) - -> @ast::Ty { - mk_ty_path(cx, span, ~[ ident ]) -} -pub fn mk_arg(cx: @ext_ctxt, - span: span, - ident: ast::ident, - ty: @ast::Ty) - -> ast::arg { - let arg_pat = mk_pat_ident(cx, span, ident); - ast::arg { - is_mutbl: false, - ty: ty, - pat: arg_pat, - id: cx.next_id() + + // these are strange, and probably shouldn't be used outside of + // pipes. Specifically, the global version possible generates + // incorrect code. + fn ty_vars(&self, ty_params: &OptVec) -> ~[@ast::Ty] { + opt_vec::take_vec( + ty_params.map(|p| self.ty_ident(dummy_sp(), p.ident))) } -} -pub fn mk_fn_decl(inputs: ~[ast::arg], output: @ast::Ty) -> ast::fn_decl { - ast::fn_decl { inputs: inputs, output: output, cf: ast::return_val } -} -pub fn mk_trait_ty_param_bound_global(cx: @ext_ctxt, - span: span, - idents: ~[ast::ident]) - -> ast::TyParamBound { - ast::TraitTyParamBound(mk_trait_ref_global(cx, span, idents)) -} -pub fn mk_trait_ty_param_bound_(cx: @ext_ctxt, - path: @ast::Path) -> ast::TyParamBound { - ast::TraitTyParamBound(mk_trait_ref_(cx, path)) -} -pub fn mk_ty_param(cx: @ext_ctxt, - ident: ast::ident, - bounds: @OptVec) - -> ast::TyParam { - ast::TyParam { ident: ident, id: cx.next_id(), bounds: bounds } -} -pub fn mk_lifetime(cx: @ext_ctxt, - span: span, - ident: ast::ident) - -> ast::Lifetime { - ast::Lifetime { id: cx.next_id(), span: span, ident: ident } -} -pub fn mk_arm(cx: @ext_ctxt, - span: span, - pats: ~[@ast::pat], - expr: @ast::expr) - -> ast::arm { - ast::arm { - pats: pats, - guard: None, - body: mk_simple_block(cx, span, expr) + + fn ty_vars_global(&self, ty_params: &OptVec) -> ~[@ast::Ty] { + opt_vec::take_vec( + ty_params.map(|p| self.ty_path( + self.path_global(dummy_sp(), ~[p.ident])))) } -} -pub fn mk_unreachable(cx: @ext_ctxt, span: span) -> @ast::expr { - let loc = cx.codemap().lookup_char_pos(span.lo); - mk_call_global( - cx, - span, - ~[ - cx.ident_of("core"), - cx.ident_of("sys"), - cx.ident_of("FailWithCause"), - cx.ident_of("fail_with"), - ], - ~[ - mk_base_str(cx, span, ~"internal error: entered unreachable code"), - mk_base_str(cx, span, copy loc.file.name), - mk_uint(cx, span, loc.line), - ] - ) -} -pub fn mk_unreachable_arm(cx: @ext_ctxt, span: span) -> ast::arm { - mk_arm(cx, span, ~[mk_pat_wild(cx, span)], mk_unreachable(cx, span)) -} -pub fn make_self(cx: @ext_ctxt, span: span) -> @ast::expr { - build::mk_expr(cx, span, ast::expr_self) -} + fn strip_bounds(&self, generics: &Generics) -> Generics { + let no_bounds = @opt_vec::Empty; + let new_params = do generics.ty_params.map |ty_param| { + ast::TyParam { bounds: no_bounds, ..copy *ty_param } + }; + Generics { + ty_params: new_params, + .. copy *generics + } + } -// -// Duplication functions -// -// These functions just duplicate AST nodes. -// + fn trait_ref(&self, path: @ast::Path) -> @ast::trait_ref { + @ast::trait_ref { + path: path, + ref_id: self.next_id() + } + } -pub fn duplicate_expr(cx: @ext_ctxt, expr: @ast::expr) -> @ast::expr { - let folder = fold::default_ast_fold(); - let folder = @fold::AstFoldFns { - new_id: |_| cx.next_id(), - ..*folder - }; - let folder = fold::make_fold(folder); - folder.fold_expr(expr) -} + fn typarambound(&self, path: @ast::Path) -> ast::TyParamBound { + ast::TraitTyParamBound(self.trait_ref(path)) + } + fn lifetime(&self, span: span, ident: ast::ident) -> ast::Lifetime { + ast::Lifetime { id: self.next_id(), span: span, ident: ident } + } + fn stmt_expr(&self, expr: @ast::expr) -> @ast::stmt { + @respan(expr.span, ast::stmt_semi(expr, self.next_id())) + } -// Transitional reexports so qquote can find the paths it is looking for -mod syntax { - pub use ext; - pub use parse; -} + fn stmt_let(&self, sp: span, mutbl: bool, ident: ast::ident, ex: @ast::expr) -> @ast::stmt { + let pat = self.pat_ident(sp, ident); + let local = @respan(sp, + ast::local_ { + is_mutbl: mutbl, + ty: self.ty_infer(sp), + pat: pat, + init: Some(ex), + id: self.next_id(), + }); + let decl = respan(sp, ast::decl_local(local)); + @respan(sp, ast::stmt_decl(@decl, self.next_id())) + } -trait ExtCtxtMethods { - fn bind_path(&self, - span: span, - ident: ast::ident, - path: @ast::Path, - bounds: @OptVec) - -> ast::TyParam; - fn expr(&self, span: span, node: ast::expr_) -> @ast::expr; - fn path(&self, span: span, strs: ~[ast::ident]) -> @ast::Path; - fn path_global(&self, span: span, strs: ~[ast::ident]) -> @ast::Path; - fn path_tps(&self, span: span, strs: ~[ast::ident], tps: ~[@ast::Ty]) - -> @ast::Path; - fn path_tps_global(&self, - span: span, - strs: ~[ast::ident], - tps: ~[@ast::Ty]) - -> @ast::Path; - fn ty_path(&self, span: span, strs: ~[ast::ident], tps: ~[@ast::Ty]) - -> @ast::Ty; - fn binder_pat(&self, span: span, nm: ast::ident) -> @ast::pat; - fn stmt(&self, expr: @ast::expr) -> @ast::stmt; - fn lit_str(&self, span: span, s: @~str) -> @ast::expr; - fn lit_uint(&self, span: span, i: uint) -> @ast::expr; - fn lambda0(&self, blk: ast::blk) -> @ast::expr; - fn lambda1(&self, blk: ast::blk, ident: ast::ident) -> @ast::expr; - fn blk(&self, span: span, stmts: ~[@ast::stmt]) -> ast::blk; - fn expr_blk(&self, expr: @ast::expr) -> ast::blk; - fn expr_path(&self, span: span, strs: ~[ast::ident]) -> @ast::expr; - fn expr_path_global(&self, span: span, strs: ~[ast::ident]) -> @ast::expr; - fn expr_var(&self, span: span, var: &str) -> @ast::expr; - fn expr_self(&self, span: span) -> @ast::expr; - fn expr_field(&self, span: span, expr: @ast::expr, ident: ast::ident) - -> @ast::expr; - fn expr_call(&self, span: span, expr: @ast::expr, args: ~[@ast::expr]) - -> @ast::expr; - fn expr_method_call(&self, - span: span, - expr: @ast::expr, - ident: ast::ident, - args: ~[@ast::expr]) - -> @ast::expr; - fn lambda_expr_0(&self, expr: @ast::expr) -> @ast::expr; - fn lambda_expr_1(&self, expr: @ast::expr, ident: ast::ident) - -> @ast::expr; - fn lambda_stmts_0(&self, span: span, stmts: ~[@ast::stmt]) -> @ast::expr; - fn lambda_stmts_1(&self, - span: span, - stmts: ~[@ast::stmt], - ident: ast::ident) - -> @ast::expr; -} + fn blk(&self, span: span, stmts: ~[@ast::stmt], expr: Option<@expr>) -> ast::blk { + self.blk_all(span, ~[], stmts, expr) + } -impl ExtCtxtMethods for @ext_ctxt { - fn bind_path( - &self, - _span: span, - ident: ast::ident, - path: @ast::Path, - bounds: @OptVec - ) -> ast::TyParam { - let bound = ast::TraitTyParamBound(@ast::trait_ref { - ref_id: self.next_id(), - path: path - }); - - ast::TyParam { - ident: ident, - id: self.next_id(), - bounds: @bounds.prepend(bound) - } + fn blk_expr(&self, expr: @ast::expr) -> ast::blk { + self.blk_all(expr.span, ~[], ~[], Some(expr)) + } + fn blk_all(&self, + span: span, + view_items: ~[@ast::view_item], + stmts: ~[@ast::stmt], + expr: Option<@ast::expr>) -> ast::blk { + respan(span, + ast::blk_ { + view_items: view_items, + stmts: stmts, + expr: expr, + id: self.next_id(), + rules: ast::default_blk, + }) } fn expr(&self, span: span, node: ast::expr_) -> @ast::expr { @ast::expr { id: self.next_id(), - callee_id: self.next_id(), node: node, span: span, } } - fn path(&self, span: span, strs: ~[ast::ident]) -> @ast::Path { - @ast::Path { - span: span, - global: false, - idents: strs, - rp: None, - types: ~[] - } + fn expr_path(&self, path: @ast::Path) -> @ast::expr { + self.expr(path.span, ast::expr_path(path)) } - fn path_global(&self, span: span, strs: ~[ast::ident]) -> @ast::Path { - @ast::Path { - span: span, - global: true, - idents: strs, - rp: None, - types: ~[] - } + fn expr_ident(&self, span: span, id: ast::ident) -> @ast::expr { + self.expr_path(self.path_ident(span, id)) + } + fn expr_self(&self, span: span) -> @ast::expr { + self.expr(span, ast::expr_self) } - fn path_tps( - &self, - span: span, - strs: ~[ast::ident], - tps: ~[@ast::Ty] - ) -> @ast::Path { - @ast::Path { - span: span, - global: false, - idents: strs, - rp: None, - types: tps - } + fn expr_binary(&self, sp: span, op: ast::binop, + lhs: @ast::expr, rhs: @ast::expr) -> @ast::expr { + self.expr(sp, ast::expr_binary(self.next_id(), op, lhs, rhs)) } - fn path_tps_global( - &self, - span: span, - strs: ~[ast::ident], - tps: ~[@ast::Ty] - ) -> @ast::Path { - @ast::Path { - span: span, - global: true, - idents: strs, - rp: None, - types: tps - } + fn expr_deref(&self, sp: span, e: @ast::expr) -> @ast::expr { + self.expr_unary(sp, ast::deref, e) + } + fn expr_unary(&self, sp: span, op: ast::unop, e: @ast::expr) + -> @ast::expr { + self.expr(sp, ast::expr_unary(self.next_id(), op, e)) } - fn ty_path( - &self, - span: span, - strs: ~[ast::ident], - tps: ~[@ast::Ty] - ) -> @ast::Ty { - @ast::Ty { - id: self.next_id(), - node: ast::ty_path( - self.path_tps(span, strs, tps), - self.next_id()), - span: span, - } + fn expr_copy(&self, sp: span, e: @ast::expr) -> @ast::expr { + self.expr(sp, ast::expr_copy(e)) + } + fn expr_managed(&self, sp: span, e: @ast::expr) -> @ast::expr { + self.expr_unary(sp, ast::box(ast::m_imm), e) } - fn binder_pat(&self, span: span, nm: ast::ident) -> @ast::pat { - @ast::pat { - id: self.next_id(), - node: ast::pat_ident( - ast::bind_by_ref(ast::m_imm), - self.path(span, ~[nm]), - None), - span: span, - } + fn expr_field_access(&self, sp: span, expr: @ast::expr, ident: ast::ident) -> @ast::expr { + self.expr(sp, ast::expr_field(expr, ident, ~[])) + } + fn expr_addr_of(&self, sp: span, e: @ast::expr) -> @ast::expr { + self.expr(sp, ast::expr_addr_of(ast::m_imm, e)) + } + fn expr_mut_addr_of(&self, sp: span, e: @ast::expr) -> @ast::expr { + self.expr(sp, ast::expr_addr_of(ast::m_mutbl, e)) + } + + fn expr_call(&self, span: span, expr: @ast::expr, args: ~[@ast::expr]) -> @ast::expr { + self.expr(span, ast::expr_call(expr, args, ast::NoSugar)) + } + fn expr_call_ident(&self, span: span, id: ast::ident, args: ~[@ast::expr]) -> @ast::expr { + self.expr(span, + ast::expr_call(self.expr_ident(span, id), args, ast::NoSugar)) + } + fn expr_call_global(&self, sp: span, fn_path: ~[ast::ident], + args: ~[@ast::expr]) -> @ast::expr { + let pathexpr = self.expr_path(self.path_global(sp, fn_path)); + self.expr_call(sp, pathexpr, args) + } + fn expr_method_call(&self, span: span, + expr: @ast::expr, + ident: ast::ident, + args: ~[@ast::expr]) -> @ast::expr { + self.expr(span, + ast::expr_method_call(self.next_id(), expr, ident, ~[], args, ast::NoSugar)) + } + fn expr_blk(&self, b: ast::blk) -> @ast::expr { + self.expr(b.span, ast::expr_block(b)) + } + fn field_imm(&self, span: span, name: ident, e: @ast::expr) -> ast::field { + respan(span, ast::field_ { ident: name, expr: e }) + } + fn expr_struct(&self, span: span, path: @ast::Path, fields: ~[ast::field]) -> @ast::expr { + self.expr(span, ast::expr_struct(path, fields, None)) + } + fn expr_struct_ident(&self, span: span, + id: ast::ident, fields: ~[ast::field]) -> @ast::expr { + self.expr_struct(span, self.path_ident(span, id), fields) } - fn stmt(&self, expr: @ast::expr) -> @ast::stmt { - @codemap::spanned { node: ast::stmt_semi(expr, self.next_id()), - span: expr.span } + fn expr_lit(&self, sp: span, lit: ast::lit_) -> @ast::expr { + self.expr(sp, ast::expr_lit(@respan(sp, lit))) + } + fn expr_uint(&self, span: span, i: uint) -> @ast::expr { + self.expr_lit(span, ast::lit_uint(i as u64, ast::ty_u)) + } + fn expr_int(&self, sp: span, i: int) -> @ast::expr { + self.expr_lit(sp, ast::lit_int(i as i64, ast::ty_i)) + } + fn expr_u8(&self, sp: span, u: u8) -> @ast::expr { + self.expr_lit(sp, ast::lit_uint(u as u64, ast::ty_u8)) + } + fn expr_bool(&self, sp: span, value: bool) -> @ast::expr { + self.expr_lit(sp, ast::lit_bool(value)) } - fn lit_str(&self, span: span, s: @~str) -> @ast::expr { - self.expr( - span, - ast::expr_vstore( - self.expr( - span, - ast::expr_lit( - @codemap::spanned { node: ast::lit_str(s), - span: span})), - ast::expr_vstore_uniq)) + fn expr_vstore(&self, sp: span, expr: @ast::expr, vst: ast::expr_vstore) -> @ast::expr { + self.expr(sp, ast::expr_vstore(expr, vst)) + } + fn expr_vec(&self, sp: span, exprs: ~[@ast::expr]) -> @ast::expr { + self.expr(sp, ast::expr_vec(exprs, ast::m_imm)) + } + fn expr_vec_uniq(&self, sp: span, exprs: ~[@ast::expr]) -> @ast::expr { + self.expr_vstore(sp, self.expr_vec(sp, exprs), ast::expr_vstore_uniq) + } + fn expr_vec_slice(&self, sp: span, exprs: ~[@ast::expr]) -> @ast::expr { + self.expr_vstore(sp, self.expr_vec(sp, exprs), ast::expr_vstore_slice) + } + fn expr_str(&self, sp: span, s: ~str) -> @ast::expr { + self.expr_lit(sp, ast::lit_str(@s)) + } + fn expr_str_uniq(&self, sp: span, s: ~str) -> @ast::expr { + self.expr_vstore(sp, self.expr_str(sp, s), ast::expr_vstore_uniq) } - fn lit_uint(&self, span: span, i: uint) -> @ast::expr { - self.expr( + + fn expr_unreachable(&self, span: span) -> @ast::expr { + let loc = self.codemap().lookup_char_pos(span.lo); + self.expr_call_global( span, - ast::expr_lit( - @codemap::spanned { node: ast::lit_uint(i as u64, ast::ty_u), - span: span})) + ~[ + self.ident_of("std"), + self.ident_of("sys"), + self.ident_of("FailWithCause"), + self.ident_of("fail_with"), + ], + ~[ + self.expr_str(span, ~"internal error: entered unreachable code"), + self.expr_str(span, copy loc.file.name), + self.expr_uint(span, loc.line), + ]) + } + + + fn pat(&self, span: span, pat: ast::pat_) -> @ast::pat { + @ast::pat { id: self.next_id(), node: pat, span: span } + } + fn pat_wild(&self, span: span) -> @ast::pat { + self.pat(span, ast::pat_wild) + } + fn pat_lit(&self, span: span, expr: @ast::expr) -> @ast::pat { + self.pat(span, ast::pat_lit(expr)) + } + fn pat_ident(&self, span: span, ident: ast::ident) -> @ast::pat { + self.pat_ident_binding_mode(span, ident, ast::bind_infer) + } + + fn pat_ident_binding_mode(&self, + span: span, + ident: ast::ident, + bm: ast::binding_mode) -> @ast::pat { + let path = self.path_ident(span, ident); + let pat = ast::pat_ident(bm, path, None); + self.pat(span, pat) + } + fn pat_enum(&self, span: span, path: @ast::Path, subpats: ~[@ast::pat]) -> @ast::pat { + let pat = ast::pat_enum(path, Some(subpats)); + self.pat(span, pat) + } + fn pat_struct(&self, span: span, + path: @ast::Path, field_pats: ~[ast::field_pat]) -> @ast::pat { + let pat = ast::pat_struct(path, field_pats, false); + self.pat(span, pat) + } + + fn arm(&self, _span: span, pats: ~[@ast::pat], expr: @ast::expr) -> ast::arm { + ast::arm { + pats: pats, + guard: None, + body: self.blk_expr(expr) + } } - fn lambda0(&self, blk: ast::blk) -> @ast::expr { + fn arm_unreachable(&self, span: span) -> ast::arm { + self.arm(span, ~[self.pat_wild(span)], self.expr_unreachable(span)) + } + + fn expr_match(&self, span: span, arg: @ast::expr, arms: ~[ast::arm]) -> @expr { + self.expr(span, ast::expr_match(arg, arms)) + } + + fn expr_if(&self, span: span, + cond: @ast::expr, then: @ast::expr, els: Option<@ast::expr>) -> @ast::expr { + let els = els.map(|x| self.expr_blk(self.blk_expr(*x))); + self.expr(span, ast::expr_if(cond, self.blk_expr(then), els)) + } + + fn lambda_fn_decl(&self, span: span, fn_decl: ast::fn_decl, blk: ast::blk) -> @ast::expr { + self.expr(span, ast::expr_fn_block(fn_decl, blk)) + } + fn lambda(&self, span: span, ids: ~[ast::ident], blk: ast::blk) -> @ast::expr { + let fn_decl = self.fn_decl( + ids.map(|id| self.arg(span, *id, self.ty_infer(span))), + self.ty_infer(span)); + + self.expr(span, ast::expr_fn_block(fn_decl, blk)) + } + fn lambda0(&self, _span: span, blk: ast::blk) -> @ast::expr { let ext_cx = *self; let blk_e = self.expr(copy blk.span, ast::expr_block(copy blk)); - quote_expr!( || $blk_e ) + quote_expr!(|| $blk_e ) } - fn lambda1(&self, blk: ast::blk, ident: ast::ident) -> @ast::expr { + fn lambda1(&self, _span: span, blk: ast::blk, ident: ast::ident) -> @ast::expr { let ext_cx = *self; let blk_e = self.expr(copy blk.span, ast::expr_block(copy blk)); - quote_expr!( |$ident| $blk_e ) - } - - fn blk(&self, span: span, stmts: ~[@ast::stmt]) -> ast::blk { - codemap::spanned { - node: ast::blk_ { - view_items: ~[], - stmts: stmts, - expr: None, - id: self.next_id(), - rules: ast::default_blk, - }, - span: span, + quote_expr!(|$ident| $blk_e ) + } + + fn lambda_expr(&self, span: span, ids: ~[ast::ident], expr: @ast::expr) -> @ast::expr { + self.lambda(span, ids, self.blk_expr(expr)) + } + fn lambda_expr_0(&self, span: span, expr: @ast::expr) -> @ast::expr { + self.lambda0(span, self.blk_expr(expr)) + } + fn lambda_expr_1(&self, span: span, expr: @ast::expr, ident: ast::ident) -> @ast::expr { + self.lambda1(span, self.blk_expr(expr), ident) + } + + fn lambda_stmts(&self, span: span, ids: ~[ast::ident], stmts: ~[@ast::stmt]) -> @ast::expr { + self.lambda(span, ids, self.blk(span, stmts, None)) + } + fn lambda_stmts_0(&self, span: span, stmts: ~[@ast::stmt]) -> @ast::expr { + self.lambda0(span, self.blk(span, stmts, None)) + } + fn lambda_stmts_1(&self, span: span, stmts: ~[@ast::stmt], ident: ast::ident) -> @ast::expr { + self.lambda1(span, self.blk(span, stmts, None), ident) + } + + fn arg(&self, span: span, ident: ast::ident, ty: @ast::Ty) -> ast::arg { + let arg_pat = self.pat_ident(span, ident); + ast::arg { + is_mutbl: false, + ty: ty, + pat: arg_pat, + id: self.next_id() } } - fn expr_blk(&self, expr: @ast::expr) -> ast::blk { - codemap::spanned { - node: ast::blk_ { - view_items: ~[], - stmts: ~[], - expr: Some(expr), - id: self.next_id(), - rules: ast::default_blk, - }, - span: expr.span, + // XXX unused self + fn fn_decl(&self, inputs: ~[ast::arg], output: @ast::Ty) -> ast::fn_decl { + ast::fn_decl { + inputs: inputs, + output: output, + cf: ast::return_val, } } - fn expr_path(&self, span: span, strs: ~[ast::ident]) -> @ast::expr { - self.expr(span, ast::expr_path(self.path(span, strs))) + fn item(&self, span: span, + name: ident, attrs: ~[ast::attribute], node: ast::item_) -> @ast::item { + // XXX: Would be nice if our generated code didn't violate + // Rust coding conventions + @ast::item { ident: name, + attrs: attrs, + id: self.next_id(), + node: node, + vis: ast::public, + span: span } } - fn expr_path_global( - &self, - span: span, - strs: ~[ast::ident] - ) -> @ast::expr { - self.expr(span, ast::expr_path(self.path_global(span, strs))) + fn item_fn_poly(&self, + span: span, + name: ident, + inputs: ~[ast::arg], + output: @ast::Ty, + generics: Generics, + body: ast::blk) -> @ast::item { + self.item(span, + name, + ~[], + ast::item_fn(self.fn_decl(inputs, output), + ast::impure_fn, + AbiSet::Rust(), + generics, + body)) + } + + fn item_fn(&self, + span: span, + name: ident, + inputs: ~[ast::arg], + output: @ast::Ty, + body: ast::blk + ) -> @ast::item { + self.item_fn_poly( + span, + name, + inputs, + output, + ast_util::empty_generics(), + body) } - fn expr_var(&self, span: span, var: &str) -> @ast::expr { - self.expr_path(span, ~[self.ident_of(var)]) + fn variant(&self, span: span, name: ident, tys: ~[@ast::Ty]) -> ast::variant { + let args = do tys.map |ty| { + ast::variant_arg { ty: *ty, id: self.next_id() } + }; + + respan(span, + ast::variant_ { + name: name, + attrs: ~[], + kind: ast::tuple_variant_kind(args), + id: self.next_id(), + disr_expr: None, + vis: ast::public + }) } - fn expr_self(&self, span: span) -> @ast::expr { - self.expr(span, ast::expr_self) + fn item_enum_poly(&self, span: span, name: ident, + enum_definition: ast::enum_def, + generics: Generics) -> @ast::item { + self.item(span, name, ~[], ast::item_enum(enum_definition, generics)) } - fn expr_field( - &self, - span: span, - expr: @ast::expr, - ident: ast::ident - ) -> @ast::expr { - self.expr(span, ast::expr_field(expr, ident, ~[])) + fn item_enum(&self, span: span, name: ident, + enum_definition: ast::enum_def) -> @ast::item { + self.item_enum_poly(span, name, enum_definition, + ast_util::empty_generics()) } - fn expr_call( + fn item_struct( &self, span: span, - expr: @ast::expr, - args: ~[@ast::expr] - ) -> @ast::expr { - self.expr(span, ast::expr_call(expr, args, ast::NoSugar)) + name: ident, + struct_def: ast::struct_def + ) -> @ast::item { + self.item_struct_poly( + span, + name, + struct_def, + ast_util::empty_generics() + ) } - fn expr_method_call( + fn item_struct_poly( &self, span: span, - expr: @ast::expr, - ident: ast::ident, - args: ~[@ast::expr] - ) -> @ast::expr { - self.expr(span, - ast::expr_method_call(expr, ident, ~[], args, ast::NoSugar)) + name: ident, + struct_def: ast::struct_def, + generics: Generics + ) -> @ast::item { + self.item(span, name, ~[], ast::item_struct(@struct_def, generics)) + } + + fn item_mod(&self, span: span, name: ident, + attrs: ~[ast::attribute], + vi: ~[@ast::view_item], + items: ~[@ast::item]) -> @ast::item { + self.item( + span, + name, + attrs, + ast::item_mod(ast::_mod { + view_items: vi, + items: items, + }) + ) } - fn lambda_expr_0(&self, expr: @ast::expr) -> @ast::expr { - self.lambda0(self.expr_blk(expr)) + fn item_ty_poly(&self, span: span, name: ident, ty: @ast::Ty, + generics: Generics) -> @ast::item { + self.item(span, name, ~[], ast::item_ty(ty, generics)) } - fn lambda_expr_1(&self, expr: @ast::expr, ident: ast::ident) - -> @ast::expr { - self.lambda1(self.expr_blk(expr), ident) + fn item_ty(&self, span: span, name: ident, ty: @ast::Ty) -> @ast::item { + self.item_ty_poly(span, name, ty, ast_util::empty_generics()) } - fn lambda_stmts_0(&self, span: span, stmts: ~[@ast::stmt]) -> @ast::expr { - self.lambda0(self.blk(span, stmts)) + fn attribute(&self, sp: span, mi: @ast::meta_item) -> ast::attribute { + respan(sp, + ast::attribute_ { + style: ast::attr_outer, + value: mi, + is_sugared_doc: false + }) } - fn lambda_stmts_1(&self, - span: span, - stmts: ~[@ast::stmt], - ident: ast::ident) - -> @ast::expr { - self.lambda1(self.blk(span, stmts), ident) + fn meta_word(&self, sp: span, w: ~str) -> @ast::meta_item { + @respan(sp, ast::meta_word(@w)) + } + fn meta_list(&self, sp: span, name: ~str, mis: ~[@ast::meta_item]) -> @ast::meta_item { + @respan(sp, ast::meta_list(@name, mis)) + } + fn meta_name_value(&self, sp: span, name: ~str, value: ast::lit_) -> @ast::meta_item { + @respan(sp, ast::meta_name_value(@name, respan(sp, value))) + } + + fn view_use(&self, sp: span, + vis: ast::visibility, vp: ~[@ast::view_path]) -> @ast::view_item { + @ast::view_item { + node: ast::view_item_use(vp), + attrs: ~[], + vis: vis, + span: sp + } + } + + fn view_use_list(&self, sp: span, vis: ast::visibility, + path: ~[ast::ident], imports: &[ast::ident]) -> @ast::view_item { + let imports = do imports.map |id| { + respan(sp, ast::path_list_ident_ { name: *id, id: self.next_id() }) + }; + + self.view_use(sp, vis, + ~[@respan(sp, + ast::view_path_list(self.path(sp, path), + imports, + self.next_id()))]) + } + + fn view_use_glob(&self, sp: span, + vis: ast::visibility, path: ~[ast::ident]) -> @ast::view_item { + self.view_use(sp, vis, + ~[@respan(sp, + ast::view_path_glob(self.path(sp, path), self.next_id()))]) + } +} + + +pub trait Duplicate { + // + // Duplication functions + // + // These functions just duplicate AST nodes. + // + + fn duplicate(&self, cx: @ExtCtxt) -> Self; +} + +impl Duplicate for @ast::expr { + fn duplicate(&self, cx: @ExtCtxt) -> @ast::expr { + let folder = fold::default_ast_fold(); + let folder = @fold::AstFoldFns { + new_id: |_| cx.next_id(), + ..*folder + }; + let folder = fold::make_fold(folder); + folder.fold_expr(*self) } } diff --git a/src/libsyntax/ext/bytes.rs b/src/libsyntax/ext/bytes.rs index 7c2f27ada3bce..a046395b6f5c8 100644 --- a/src/libsyntax/ext/bytes.rs +++ b/src/libsyntax/ext/bytes.rs @@ -14,9 +14,9 @@ use ast; use codemap::span; use ext::base::*; use ext::base; -use ext::build::{mk_u8, mk_slice_vec_e}; +use ext::build::AstBuilder; -pub fn expand_syntax_ext(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree]) -> base::MacResult { +pub fn expand_syntax_ext(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree]) -> base::MacResult { // Gather all argument expressions let exprs = get_exprs_from_tts(cx, tts); let mut bytes = ~[]; @@ -28,7 +28,7 @@ pub fn expand_syntax_ext(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree]) -> ba // string literal, push each byte to vector expression ast::lit_str(s) => { for s.each |byte| { - bytes.push(mk_u8(cx, sp, byte)); + bytes.push(cx.expr_u8(sp, byte)); } } @@ -37,7 +37,7 @@ pub fn expand_syntax_ext(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree]) -> ba if v > 0xFF { cx.span_err(sp, "Too large u8 literal in bytes!") } else { - bytes.push(mk_u8(cx, sp, v as u8)); + bytes.push(cx.expr_u8(sp, v as u8)); } } @@ -48,14 +48,14 @@ pub fn expand_syntax_ext(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree]) -> ba } else if v < 0 { cx.span_err(sp, "Negative integer literal in bytes!") } else { - bytes.push(mk_u8(cx, sp, v as u8)); + bytes.push(cx.expr_u8(sp, v as u8)); } } // char literal, push to vector expression ast::lit_int(v, ast::ty_char) => { if (v as char).is_ascii() { - bytes.push(mk_u8(cx, sp, v as u8)); + bytes.push(cx.expr_u8(sp, v as u8)); } else { cx.span_err(sp, "Non-ascii char literal in bytes!") } @@ -68,6 +68,6 @@ pub fn expand_syntax_ext(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree]) -> ba } } - let e = mk_slice_vec_e(cx, sp, bytes); + let e = cx.expr_vec_slice(sp, bytes); MRExpr(e) } diff --git a/src/libsyntax/ext/concat_idents.rs b/src/libsyntax/ext/concat_idents.rs index 96e5e4143226c..bfb234106b8b1 100644 --- a/src/libsyntax/ext/concat_idents.rs +++ b/src/libsyntax/ext/concat_idents.rs @@ -8,36 +8,36 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use ast; use codemap::span; use ext::base::*; use ext::base; use parse::token; +use parse::token::{str_to_ident}; -pub fn expand_syntax_ext(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree]) +pub fn expand_syntax_ext(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree]) -> base::MacResult { let mut res_str = ~""; for tts.eachi |i, e| { if i & 1 == 1 { match *e { ast::tt_tok(_, token::COMMA) => (), - _ => cx.span_fatal(sp, ~"concat_idents! \ - expecting comma.") + _ => cx.span_fatal(sp, "concat_idents! expecting comma.") } } else { match *e { ast::tt_tok(_, token::IDENT(ident,_)) => res_str += cx.str_of(ident), - _ => cx.span_fatal(sp, ~"concat_idents! \ - requires ident args.") + _ => cx.span_fatal(sp, "concat_idents! requires ident args.") } } } - let res = cx.parse_sess().interner.intern(res_str); + let res = str_to_ident(res_str); let e = @ast::expr { id: cx.next_id(), - callee_id: cx.next_id(), node: ast::expr_path( @ast::Path { span: sp, diff --git a/src/libsyntax/ext/deriving/clone.rs b/src/libsyntax/ext/deriving/clone.rs index aceb60ebbd7d6..8d9abb186fd1c 100644 --- a/src/libsyntax/ext/deriving/clone.rs +++ b/src/libsyntax/ext/deriving/clone.rs @@ -8,25 +8,26 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use ast::{meta_item, item, expr}; use codemap::span; -use ext::base::ext_ctxt; -use ext::build; +use ext::base::ExtCtxt; +use ext::build::AstBuilder; use ext::deriving::generic::*; - -pub fn expand_deriving_clone(cx: @ext_ctxt, +pub fn expand_deriving_clone(cx: @ExtCtxt, span: span, mitem: @meta_item, in_items: ~[@item]) -> ~[@item] { let trait_def = TraitDef { - path: Path::new(~[~"core", ~"clone", ~"Clone"]), + path: Path::new(~["std", "clone", "Clone"]), additional_bounds: ~[], generics: LifetimeBounds::empty(), methods: ~[ MethodDef { - name: ~"clone", + name: "clone", generics: LifetimeBounds::empty(), explicit_self: borrowed_explicit_self(), args: ~[], @@ -42,18 +43,18 @@ pub fn expand_deriving_clone(cx: @ext_ctxt, &trait_def) } -pub fn expand_deriving_deep_clone(cx: @ext_ctxt, +pub fn expand_deriving_deep_clone(cx: @ExtCtxt, span: span, mitem: @meta_item, in_items: ~[@item]) -> ~[@item] { let trait_def = TraitDef { - path: Path::new(~[~"core", ~"clone", ~"DeepClone"]), + path: Path::new(~["std", "clone", "DeepClone"]), additional_bounds: ~[], generics: LifetimeBounds::empty(), methods: ~[ MethodDef { - name: ~"deep_clone", + name: "deep_clone", generics: LifetimeBounds::empty(), explicit_self: borrowed_explicit_self(), args: ~[], @@ -73,21 +74,21 @@ pub fn expand_deriving_deep_clone(cx: @ext_ctxt, fn cs_clone( name: &str, - cx: @ext_ctxt, span: span, + cx: @ExtCtxt, span: span, substr: &Substructure) -> @expr { let clone_ident = substr.method_ident; let ctor_ident; let all_fields; let subcall = |field| - build::mk_method_call(cx, span, field, clone_ident, ~[]); + cx.expr_method_call(span, field, clone_ident, ~[]); match *substr.fields { Struct(ref af) => { - ctor_ident = ~[ substr.type_ident ]; + ctor_ident = substr.type_ident; all_fields = af; } EnumMatching(_, variant, ref af) => { - ctor_ident = ~[ variant.node.name ]; + ctor_ident = variant.node.name; all_fields = af; }, EnumNonMatching(*) => cx.span_bug(span, @@ -102,7 +103,7 @@ fn cs_clone( [(None, _, _), .. _] => { // enum-like let subcalls = all_fields.map(|&(_, self_f, _)| subcall(self_f)); - build::mk_call(cx, span, ctor_ident, subcalls) + cx.expr_call_ident(span, ctor_ident, subcalls) }, _ => { // struct-like @@ -113,16 +114,14 @@ fn cs_clone( fmt!("unnamed field in normal struct in `deriving(%s)`", name)) }; - build::Field { ident: ident, ex: subcall(self_f) } + cx.field_imm(span, ident, subcall(self_f)) }; if fields.is_empty() { // no fields, so construct like `None` - build::mk_path(cx, span, ctor_ident) + cx.expr_ident(span, ctor_ident) } else { - build::mk_struct_e(cx, span, - ctor_ident, - fields) + cx.expr_struct_ident(span, ctor_ident, fields) } } } diff --git a/src/libsyntax/ext/deriving/cmp/eq.rs b/src/libsyntax/ext/deriving/cmp/eq.rs index 3d93f844ea3bb..67107b4218acf 100644 --- a/src/libsyntax/ext/deriving/cmp/eq.rs +++ b/src/libsyntax/ext/deriving/cmp/eq.rs @@ -8,24 +8,26 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use ast::{meta_item, item, expr}; use codemap::span; -use ext::base::ext_ctxt; -use ext::build; +use ext::base::ExtCtxt; +use ext::build::AstBuilder; use ext::deriving::generic::*; -pub fn expand_deriving_eq(cx: @ext_ctxt, +pub fn expand_deriving_eq(cx: @ExtCtxt, span: span, mitem: @meta_item, in_items: ~[@item]) -> ~[@item] { // structures are equal if all fields are equal, and non equal, if // any fields are not equal or if the enum variants are different - fn cs_eq(cx: @ext_ctxt, span: span, substr: &Substructure) -> @expr { - cs_and(|cx, span, _, _| build::mk_bool(cx, span, false), + fn cs_eq(cx: @ExtCtxt, span: span, substr: &Substructure) -> @expr { + cs_and(|cx, span, _, _| cx.expr_bool(span, false), cx, span, substr) } - fn cs_ne(cx: @ext_ctxt, span: span, substr: &Substructure) -> @expr { - cs_or(|cx, span, _, _| build::mk_bool(cx, span, true), + fn cs_ne(cx: @ExtCtxt, span: span, substr: &Substructure) -> @expr { + cs_or(|cx, span, _, _| cx.expr_bool(span, true), cx, span, substr) } @@ -36,7 +38,7 @@ pub fn expand_deriving_eq(cx: @ext_ctxt, generics: LifetimeBounds::empty(), explicit_self: borrowed_explicit_self(), args: ~[borrowed_self()], - ret_ty: Literal(Path::new(~[~"bool"])), + ret_ty: Literal(Path::new(~["bool"])), const_nonmatching: true, combine_substructure: $f }, @@ -44,12 +46,12 @@ pub fn expand_deriving_eq(cx: @ext_ctxt, ); let trait_def = TraitDef { - path: Path::new(~[~"core", ~"cmp", ~"Eq"]), + path: Path::new(~["std", "cmp", "Eq"]), additional_bounds: ~[], generics: LifetimeBounds::empty(), methods: ~[ - md!(~"eq", cs_eq), - md!(~"ne", cs_ne) + md!("eq", cs_eq), + md!("ne", cs_ne) ] }; diff --git a/src/libsyntax/ext/deriving/cmp/ord.rs b/src/libsyntax/ext/deriving/cmp/ord.rs index 5445aef4491be..8b8ee37691cb0 100644 --- a/src/libsyntax/ext/deriving/cmp/ord.rs +++ b/src/libsyntax/ext/deriving/cmp/ord.rs @@ -8,14 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; -use ast::{meta_item, item, expr_if, expr}; +use ast::{meta_item, item, expr}; use codemap::span; -use ext::base::ext_ctxt; -use ext::build; +use ext::base::ExtCtxt; +use ext::build::AstBuilder; use ext::deriving::generic::*; -pub fn expand_deriving_ord(cx: @ext_ctxt, +pub fn expand_deriving_ord(cx: @ExtCtxt, span: span, mitem: @meta_item, in_items: ~[@item]) -> ~[@item] { @@ -26,7 +27,7 @@ pub fn expand_deriving_ord(cx: @ext_ctxt, generics: LifetimeBounds::empty(), explicit_self: borrowed_explicit_self(), args: ~[borrowed_self()], - ret_ty: Literal(Path::new(~[~"bool"])), + ret_ty: Literal(Path::new(~["bool"])), const_nonmatching: false, combine_substructure: |cx, span, substr| cs_ord($less, $equal, cx, span, substr) @@ -37,15 +38,15 @@ pub fn expand_deriving_ord(cx: @ext_ctxt, let trait_def = TraitDef { - path: Path::new(~[~"core", ~"cmp", ~"Ord"]), + path: Path::new(~["std", "cmp", "Ord"]), // XXX: Ord doesn't imply Eq yet - additional_bounds: ~[Literal(Path::new(~[~"core", ~"cmp", ~"Eq"]))], + additional_bounds: ~[Literal(Path::new(~["std", "cmp", "Eq"]))], generics: LifetimeBounds::empty(), methods: ~[ - md!(~"lt", true, false), - md!(~"le", true, true), - md!(~"gt", false, false), - md!(~"ge", false, true) + md!("lt", true, false), + md!("le", true, true), + md!("gt", false, false), + md!("ge", false, true) ] }; @@ -55,17 +56,14 @@ pub fn expand_deriving_ord(cx: @ext_ctxt, /// `less`: is this `lt` or `le`? `equal`: is this `le` or `ge`? fn cs_ord(less: bool, equal: bool, - cx: @ext_ctxt, span: span, + cx: @ExtCtxt, span: span, substr: &Substructure) -> @expr { let binop = if less { cx.ident_of("lt") } else { cx.ident_of("gt") }; - let false_blk_expr = build::mk_block(cx, span, - ~[], ~[], - Some(build::mk_bool(cx, span, false))); - let base = build::mk_bool(cx, span, equal); + let base = cx.expr_bool(span, equal); cs_fold( false, // need foldr, @@ -98,19 +96,15 @@ fn cs_ord(less: bool, equal: bool, cx.span_bug(span, "Not exactly 2 arguments in `deriving(Ord)`"); } - let cmp = build::mk_method_call(cx, span, - self_f, cx.ident_of("eq"), other_fs.to_owned()); - let subexpr = build::mk_simple_block(cx, span, subexpr); - let elseif = expr_if(cmp, subexpr, Some(false_blk_expr)); - let elseif = build::mk_expr(cx, span, elseif); + let cmp = cx.expr_method_call(span, + self_f, cx.ident_of("eq"), other_fs.to_owned()); + let elseif = cx.expr_if(span, cmp, + subexpr, Some(cx.expr_bool(span, false))); - let cmp = build::mk_method_call(cx, span, - self_f, binop, other_fs.to_owned()); - let true_blk = build::mk_simple_block(cx, span, - build::mk_bool(cx, span, true)); - let if_ = expr_if(cmp, true_blk, Some(elseif)); - - build::mk_expr(cx, span, if_) + let cmp = cx.expr_method_call(span, + self_f, binop, other_fs.to_owned()); + cx.expr_if(span, cmp, + cx.expr_bool(span, true), Some(elseif)) }, base, |cx, span, args, _| { @@ -119,7 +113,7 @@ fn cs_ord(less: bool, equal: bool, match args { [(self_var, _, _), (other_var, _, _)] => - build::mk_bool(cx, span, + cx.expr_bool(span, if less { self_var < other_var } else { diff --git a/src/libsyntax/ext/deriving/cmp/totaleq.rs b/src/libsyntax/ext/deriving/cmp/totaleq.rs index 4541569b829ac..f07c894943868 100644 --- a/src/libsyntax/ext/deriving/cmp/totaleq.rs +++ b/src/libsyntax/ext/deriving/cmp/totaleq.rs @@ -8,34 +8,35 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; use ast::{meta_item, item, expr}; use codemap::span; -use ext::base::ext_ctxt; -use ext::build; +use ext::base::ExtCtxt; +use ext::build::AstBuilder; use ext::deriving::generic::*; -pub fn expand_deriving_totaleq(cx: @ext_ctxt, +pub fn expand_deriving_totaleq(cx: @ExtCtxt, span: span, mitem: @meta_item, in_items: ~[@item]) -> ~[@item] { - fn cs_equals(cx: @ext_ctxt, span: span, substr: &Substructure) -> @expr { - cs_and(|cx, span, _, _| build::mk_bool(cx, span, false), + fn cs_equals(cx: @ExtCtxt, span: span, substr: &Substructure) -> @expr { + cs_and(|cx, span, _, _| cx.expr_bool(span, false), cx, span, substr) } let trait_def = TraitDef { - path: Path::new(~[~"core", ~"cmp", ~"TotalEq"]), + path: Path::new(~["std", "cmp", "TotalEq"]), additional_bounds: ~[], generics: LifetimeBounds::empty(), methods: ~[ MethodDef { - name: ~"equals", + name: "equals", generics: LifetimeBounds::empty(), explicit_self: borrowed_explicit_self(), args: ~[borrowed_self()], - ret_ty: Literal(Path::new(~[~"bool"])), + ret_ty: Literal(Path::new(~["bool"])), const_nonmatching: true, combine_substructure: cs_equals } diff --git a/src/libsyntax/ext/deriving/cmp/totalord.rs b/src/libsyntax/ext/deriving/cmp/totalord.rs index 8f156e6a9e315..4c1c940927b9b 100644 --- a/src/libsyntax/ext/deriving/cmp/totalord.rs +++ b/src/libsyntax/ext/deriving/cmp/totalord.rs @@ -8,28 +8,30 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use ast::{meta_item, item, expr}; use codemap::span; -use ext::base::ext_ctxt; -use ext::build; +use ext::base::ExtCtxt; +use ext::build::AstBuilder; use ext::deriving::generic::*; use core::cmp::{Ordering, Equal, Less, Greater}; -pub fn expand_deriving_totalord(cx: @ext_ctxt, +pub fn expand_deriving_totalord(cx: @ExtCtxt, span: span, mitem: @meta_item, in_items: ~[@item]) -> ~[@item] { let trait_def = TraitDef { - path: Path::new(~[~"core", ~"cmp", ~"TotalOrd"]), + path: Path::new(~["std", "cmp", "TotalOrd"]), additional_bounds: ~[], generics: LifetimeBounds::empty(), methods: ~[ MethodDef { - name: ~"cmp", + name: "cmp", generics: LifetimeBounds::empty(), explicit_self: borrowed_explicit_self(), args: ~[borrowed_self()], - ret_ty: Literal(Path::new(~[~"core", ~"cmp", ~"Ordering"])), + ret_ty: Literal(Path::new(~["std", "cmp", "Ordering"])), const_nonmatching: false, combine_substructure: cs_cmp } @@ -41,30 +43,31 @@ pub fn expand_deriving_totalord(cx: @ext_ctxt, } -pub fn ordering_const(cx: @ext_ctxt, span: span, cnst: Ordering) -> @expr { +pub fn ordering_const(cx: @ExtCtxt, span: span, cnst: Ordering) -> @expr { let cnst = match cnst { Less => "Less", Equal => "Equal", Greater => "Greater" }; - build::mk_path_global(cx, span, - ~[cx.ident_of("core"), - cx.ident_of("cmp"), - cx.ident_of(cnst)]) + cx.expr_path( + cx.path_global(span, + ~[cx.ident_of("std"), + cx.ident_of("cmp"), + cx.ident_of(cnst)])) } -pub fn cs_cmp(cx: @ext_ctxt, span: span, +pub fn cs_cmp(cx: @ExtCtxt, span: span, substr: &Substructure) -> @expr { cs_same_method_fold( // foldr (possibly) nests the matches in lexical_ordering better false, |cx, span, old, new| { - build::mk_call_global(cx, span, - ~[cx.ident_of("core"), - cx.ident_of("cmp"), - cx.ident_of("lexical_ordering")], - ~[old, new]) + cx.expr_call_global(span, + ~[cx.ident_of("std"), + cx.ident_of("cmp"), + cx.ident_of("lexical_ordering")], + ~[old, new]) }, ordering_const(cx, span, Equal), |cx, span, list, _| { diff --git a/src/libsyntax/ext/deriving/decodable.rs b/src/libsyntax/ext/deriving/decodable.rs index 2e2f382a7687b..1991b2456d97d 100644 --- a/src/libsyntax/ext/deriving/decodable.rs +++ b/src/libsyntax/ext/deriving/decodable.rs @@ -13,485 +13,151 @@ The compiler code necessary for #[deriving(Decodable)]. See encodable.rs for more. */ -use ast; -use ast::*; -use ext::base::ext_ctxt; -use ext::build; -use ext::deriving::*; -use codemap::{span, spanned}; -use ast_util; -use opt_vec; - -pub fn expand_deriving_decodable( - cx: @ext_ctxt, - span: span, - _mitem: @meta_item, - in_items: ~[@item] -) -> ~[@item] { - expand_deriving( - cx, - span, - in_items, - expand_deriving_decodable_struct_def, - expand_deriving_decodable_enum_def - ) -} - -fn create_derived_decodable_impl( - cx: @ext_ctxt, - span: span, - type_ident: ident, - generics: &Generics, - method: @method -) -> @item { - let decoder_ty_param = build::mk_ty_param( - cx, - cx.ident_of("__D"), - @opt_vec::with( - build::mk_trait_ty_param_bound_global( - cx, - span, - ~[ - cx.ident_of("std"), - cx.ident_of("serialize"), - cx.ident_of("Decoder"), - ] - ) - ) - ); - - // All the type parameters need to bound to the trait. - let generic_ty_params = opt_vec::with(decoder_ty_param); - - let methods = [method]; - let trait_path = build::mk_raw_path_global_( - span, - ~[ - cx.ident_of("std"), - cx.ident_of("serialize"), - cx.ident_of("Decodable") - ], - None, - ~[ - build::mk_simple_ty_path(cx, span, cx.ident_of("__D")) - ] - ); - create_derived_impl( - cx, - span, - type_ident, - generics, - methods, - trait_path, - Generics { ty_params: generic_ty_params, lifetimes: opt_vec::Empty }, - opt_vec::Empty - ) -} - -// Creates a method from the given set of statements conforming to the -// signature of the `decodable` method. -fn create_decode_method( - cx: @ext_ctxt, - span: span, - type_ident: ast::ident, - generics: &Generics, - expr: @ast::expr -) -> @method { - // Create the `e` parameter. - let d_arg_type = build::mk_ty_rptr( - cx, - span, - build::mk_simple_ty_path(cx, span, cx.ident_of("__D")), - None, - ast::m_mutbl - ); - let d_ident = cx.ident_of("__d"); - let d_arg = build::mk_arg(cx, span, d_ident, d_arg_type); - - // Create the type of the return value. - let output_type = create_self_type_with_params( - cx, - span, - type_ident, - generics - ); - - // Create the function declaration. - let inputs = ~[d_arg]; - let fn_decl = build::mk_fn_decl(inputs, output_type); - - // Create the body block. - let body_block = build::mk_simple_block(cx, span, expr); - - // Create the method. - let explicit_self = spanned { node: sty_static, span: span }; - let method_ident = cx.ident_of("decode"); - @ast::method { - ident: method_ident, - attrs: ~[], - generics: ast_util::empty_generics(), - explicit_self: explicit_self, - purity: impure_fn, - decl: fn_decl, - body: body_block, - id: cx.next_id(), - span: span, - self_id: cx.next_id(), - vis: public - } -} - -fn call_substructure_decode_method( - cx: @ext_ctxt, - span: span -) -> @ast::expr { - // Call the substructure method. - build::mk_call_( - cx, - span, - build::mk_path_global( - cx, - span, - ~[ - cx.ident_of("std"), - cx.ident_of("serialize"), - cx.ident_of("Decodable"), - cx.ident_of("decode"), - ] - ), - ~[ - build::mk_path(cx, span, ~[cx.ident_of("__d")]) - ] - ) -} - -fn expand_deriving_decodable_struct_def( - cx: @ext_ctxt, - span: span, - struct_def: &struct_def, - type_ident: ident, - generics: &Generics -) -> @item { - // Create the method. - let method = expand_deriving_decodable_struct_method( - cx, - span, - struct_def, - type_ident, - generics - ); - - // Create the implementation. - create_derived_decodable_impl( - cx, - span, - type_ident, - generics, - method - ) -} - -fn expand_deriving_decodable_enum_def( - cx: @ext_ctxt, - span: span, - enum_definition: &enum_def, - type_ident: ident, - generics: &Generics -) -> @item { - // Create the method. - let method = expand_deriving_decodable_enum_method( - cx, - span, - enum_definition, - type_ident, - generics - ); - - // Create the implementation. - create_derived_decodable_impl( - cx, - span, - type_ident, - generics, - method - ) -} - -fn create_read_struct_field( - cx: @ext_ctxt, - span: span, - idx: uint, - ident: ident -) -> build::Field { - // Call the substructure method. - let decode_expr = call_substructure_decode_method(cx, span); - - let d_arg = build::mk_arg(cx, - span, - cx.ident_of("__d"), - build::mk_ty_infer(cx, span)); - - let call_expr = build::mk_method_call( - cx, - span, - build::mk_path(cx, span, ~[cx.ident_of("__d")]), - cx.ident_of("read_struct_field"), - ~[ - build::mk_base_str(cx, span, cx.str_of(ident)), - build::mk_uint(cx, span, idx), - build::mk_lambda(cx, - span, - build::mk_fn_decl(~[d_arg], - build::mk_ty_infer(cx, span)), - decode_expr), - ] - ); - - build::Field { ident: ident, ex: call_expr } -} - -fn create_read_struct_arg( - cx: @ext_ctxt, - span: span, - idx: uint, - ident: ident -) -> build::Field { - // Call the substructure method. - let decode_expr = call_substructure_decode_method(cx, span); - - let call_expr = build::mk_method_call( - cx, - span, - build::mk_path(cx, span, ~[cx.ident_of("__d")]), - cx.ident_of("read_struct_arg"), - ~[ - build::mk_uint(cx, span, idx), - build::mk_lambda_no_args(cx, span, decode_expr), +use core::prelude::*; +use core::vec; +use core::uint; + +use ast::{meta_item, item, expr, m_mutbl}; +use codemap::span; +use ext::base::ExtCtxt; +use ext::build::AstBuilder; +use ext::deriving::generic::*; + +pub fn expand_deriving_decodable(cx: @ExtCtxt, + span: span, + mitem: @meta_item, + in_items: ~[@item]) -> ~[@item] { + let trait_def = TraitDef { + path: Path::new_(~["extra", "serialize", "Decodable"], None, + ~[~Literal(Path::new_local("__D"))], true), + additional_bounds: ~[], + generics: LifetimeBounds { + lifetimes: ~[], + bounds: ~[("__D", ~[Path::new(~["extra", "serialize", "Decoder"])])], + }, + methods: ~[ + MethodDef { + name: "decode", + generics: LifetimeBounds::empty(), + explicit_self: None, + args: ~[Ptr(~Literal(Path::new_local("__D")), + Borrowed(None, m_mutbl))], + ret_ty: Self, + const_nonmatching: true, + combine_substructure: decodable_substructure, + }, ] - ); - - build::Field { ident: ident, ex: call_expr } -} - -fn expand_deriving_decodable_struct_method( - cx: @ext_ctxt, - span: span, - struct_def: &struct_def, - type_ident: ident, - generics: &Generics -) -> @method { - // Create the body of the method. - let mut i = 0; - let mut fields = ~[]; - for struct_def.fields.each |struct_field| { - match struct_field.node.kind { - named_field(ident, _) => { - fields.push(create_read_struct_field(cx, span, i, ident)); - } - unnamed_field => { - cx.span_unimpl( - span, - ~"unnamed fields with `deriving(Decodable)`" - ); - } - } - i += 1; - } - - let d_arg = build::mk_arg(cx, - span, - cx.ident_of("__d"), - build::mk_ty_infer(cx, span)); - - let read_struct_expr = build::mk_method_call( - cx, - span, - build::mk_path( - cx, - span, - ~[cx.ident_of("__d")] - ), - cx.ident_of("read_struct"), - ~[ - build::mk_base_str(cx, span, cx.str_of(type_ident)), - build::mk_uint(cx, span, fields.len()), - build::mk_lambda( - cx, - span, - build::mk_fn_decl(~[d_arg], build::mk_ty_infer(cx, span)), - build::mk_struct_e( - cx, - span, - ~[type_ident], - fields - ) - ), - ] - ); - - // Create the method itself. - create_decode_method(cx, span, type_ident, generics, read_struct_expr) -} - -fn create_read_variant_arg( - cx: @ext_ctxt, - span: span, - idx: uint, - variant: &ast::variant -) -> ast::arm { - // Create the matching pattern. - let pat = build::mk_pat_lit(cx, span, build::mk_uint(cx, span, idx)); - - // Feed each argument in this variant to the decode function - // as well. - let variant_arg_len = variant_arg_count(cx, span, variant); - - let expr = if variant_arg_len == 0 { - build::mk_path(cx, span, ~[variant.node.name]) - } else { - // Feed the discriminant to the decode function. - let mut args = ~[]; - - for uint::range(0, variant_arg_len) |j| { - // Call the substructure method. - let expr = call_substructure_decode_method(cx, span); - - let d_arg = build::mk_arg(cx, - span, - cx.ident_of("__d"), - build::mk_ty_infer(cx, span)); - let t_infer = build::mk_ty_infer(cx, span); - - let call_expr = build::mk_method_call( - cx, - span, - build::mk_path(cx, span, ~[cx.ident_of("__d")]), - cx.ident_of("read_enum_variant_arg"), - ~[ - build::mk_uint(cx, span, j), - build::mk_lambda(cx, - span, - build::mk_fn_decl(~[d_arg], t_infer), - expr), - ] - ); - - args.push(call_expr); - } - - build::mk_call( - cx, - span, - ~[variant.node.name], - args - ) }; - // Create the arm. - build::mk_arm(cx, span, ~[pat], expr) + expand_deriving_generic(cx, span, mitem, in_items, + &trait_def) } -fn create_read_enum_variant( - cx: @ext_ctxt, - span: span, - enum_definition: &enum_def -) -> @expr { - // Create a vector that contains all the variant names. - let expr_arm_names = build::mk_base_vec_e( - cx, - span, - do enum_definition.variants.map |variant| { - build::mk_base_str( - cx, - span, - cx.str_of(variant.node.name) - ) +fn decodable_substructure(cx: @ExtCtxt, span: span, + substr: &Substructure) -> @expr { + let decoder = substr.nonself_args[0]; + let recurse = ~[cx.ident_of("extra"), + cx.ident_of("serialize"), + cx.ident_of("Decodable"), + cx.ident_of("decode")]; + // throw an underscore in front to suppress unused variable warnings + let blkarg = cx.ident_of("_d"); + let blkdecoder = cx.expr_ident(span, blkarg); + let calldecode = cx.expr_call_global(span, recurse, ~[blkdecoder]); + let lambdadecode = cx.lambda_expr_1(span, calldecode, blkarg); + + return match *substr.fields { + StaticStruct(_, ref summary) => { + let nfields = match *summary { + Left(n) => n, Right(ref fields) => fields.len() + }; + let read_struct_field = cx.ident_of("read_struct_field"); + + let getarg = |name: ~str, field: uint| { + cx.expr_method_call(span, blkdecoder, read_struct_field, + ~[cx.expr_str(span, name), + cx.expr_uint(span, field), + lambdadecode]) + }; + + let result = match *summary { + Left(n) => { + if n == 0 { + cx.expr_ident(span, substr.type_ident) + } else { + let mut fields = vec::with_capacity(n); + for uint::range(0, n) |i| { + fields.push(getarg(fmt!("_field%u", i), i)); + } + cx.expr_call_ident(span, substr.type_ident, fields) + } + } + Right(ref fields) => { + let fields = do fields.mapi |i, f| { + cx.field_imm(span, *f, getarg(cx.str_of(*f), i)) + }; + cx.expr_struct_ident(span, substr.type_ident, fields) + } + }; + + cx.expr_method_call(span, decoder, cx.ident_of("read_struct"), + ~[cx.expr_str(span, cx.str_of(substr.type_ident)), + cx.expr_uint(span, nfields), + cx.lambda_expr_1(span, result, blkarg)]) } - ); + StaticEnum(_, ref fields) => { + let variant = cx.ident_of("i"); + + let mut arms = ~[]; + let mut variants = ~[]; + let rvariant_arg = cx.ident_of("read_enum_variant_arg"); + + for fields.eachi |i, f| { + let (name, parts) = match *f { (i, ref p) => (i, p) }; + variants.push(cx.expr_str(span, cx.str_of(name))); + + let getarg = |field: uint| { + cx.expr_method_call(span, blkdecoder, rvariant_arg, + ~[cx.expr_uint(span, field), + lambdadecode]) + }; + + let decoded = match *parts { + Left(n) => { + if n == 0 { + cx.expr_ident(span, name) + } else { + let mut fields = vec::with_capacity(n); + for uint::range(0, n) |i| { + fields.push(getarg(i)); + } + cx.expr_call_ident(span, name, fields) + } + } + Right(ref fields) => { + let fields = do fields.mapi |i, f| { + cx.field_imm(span, *f, getarg(i)) + }; + cx.expr_struct_ident(span, name, fields) + } + }; + arms.push(cx.arm(span, + ~[cx.pat_lit(span, cx.expr_uint(span, i))], + decoded)); + } - // Create the arms of the match in the method body. - let mut arms = do enum_definition.variants.mapi |i, variant| { - create_read_variant_arg(cx, span, i, variant) + arms.push(cx.arm_unreachable(span)); + + let result = cx.expr_match(span, cx.expr_ident(span, variant), arms); + let lambda = cx.lambda_expr(span, ~[blkarg, variant], result); + let variant_vec = cx.expr_vec(span, variants); + let result = cx.expr_method_call(span, blkdecoder, + cx.ident_of("read_enum_variant"), + ~[variant_vec, lambda]); + cx.expr_method_call(span, decoder, cx.ident_of("read_enum"), + ~[cx.expr_str(span, cx.str_of(substr.type_ident)), + cx.lambda_expr_1(span, result, blkarg)]) + } + _ => cx.bug("expected StaticEnum or StaticStruct in deriving(Decodable)") }; - - // Add the impossible case arm. - arms.push(build::mk_unreachable_arm(cx, span)); - - // Create the read_enum_variant expression. - build::mk_method_call( - cx, - span, - build::mk_path(cx, span, ~[cx.ident_of("__d")]), - cx.ident_of("read_enum_variant"), - ~[ - expr_arm_names, - build::mk_lambda( - cx, - span, - build::mk_fn_decl( - ~[ - build::mk_arg( - cx, - span, - cx.ident_of("__d"), - build::mk_ty_infer(cx, span) - ), - build::mk_arg( - cx, - span, - cx.ident_of("__i"), - build::mk_ty_infer(cx, span) - ) - ], - build::mk_ty_infer(cx, span) - ), - build::mk_expr( - cx, - span, - ast::expr_match( - build::mk_path(cx, span, ~[cx.ident_of("__i")]), - arms - ) - ) - ) - ] - ) -} - -fn expand_deriving_decodable_enum_method( - cx: @ext_ctxt, - span: span, - enum_definition: &enum_def, - type_ident: ast::ident, - generics: &Generics -) -> @method { - let read_enum_variant_expr = create_read_enum_variant( - cx, - span, - enum_definition - ); - - let d_arg = build::mk_arg(cx, - span, - cx.ident_of("__d"), - build::mk_ty_infer(cx, span)); - - // Create the read_enum expression - let read_enum_expr = build::mk_method_call( - cx, - span, - build::mk_path(cx, span, ~[cx.ident_of("__d")]), - cx.ident_of("read_enum"), - ~[ - build::mk_base_str(cx, span, cx.str_of(type_ident)), - build::mk_lambda(cx, - span, - build::mk_fn_decl(~[d_arg], - build::mk_ty_infer(cx, span)), - read_enum_variant_expr), - ] - ); - - // Create the method. - create_decode_method(cx, span, type_ident, generics, read_enum_expr) } diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs index 8a1c3933f5127..b9c4bf7bf26af 100644 --- a/src/libsyntax/ext/deriving/encodable.rs +++ b/src/libsyntax/ext/deriving/encodable.rs @@ -22,7 +22,7 @@ For example, a type like: would generate two implementations like: -impl Encodable for Node { +impl Encodable for Node { fn encode(&self, s: &S) { do s.emit_struct("Node", 1) { s.emit_field("id", 0, || s.emit_uint(self.id)) @@ -75,643 +75,115 @@ would yield functions like: } */ - -use ast; -use ast::*; -use ext::base::ext_ctxt; -use ext::build; -use ext::deriving::*; -use codemap::{span, spanned}; -use ast_util; -use opt_vec; - -pub fn expand_deriving_encodable( - cx: @ext_ctxt, - span: span, - _mitem: @meta_item, - in_items: ~[@item] -) -> ~[@item] { - expand_deriving( - cx, - span, - in_items, - expand_deriving_encodable_struct_def, - expand_deriving_encodable_enum_def - ) -} - -fn create_derived_encodable_impl( - cx: @ext_ctxt, - span: span, - type_ident: ident, - generics: &Generics, - method: @method -) -> @item { - let encoder_ty_param = build::mk_ty_param( - cx, - cx.ident_of("__E"), - @opt_vec::with( - build::mk_trait_ty_param_bound_global( - cx, - span, - ~[ - cx.ident_of("std"), - cx.ident_of("serialize"), - cx.ident_of("Encoder"), - ] - ) - ) - ); - - // All the type parameters need to bound to the trait. - let generic_ty_params = opt_vec::with(encoder_ty_param); - - let methods = [method]; - let trait_path = build::mk_raw_path_global_( - span, - ~[ - cx.ident_of("std"), - cx.ident_of("serialize"), - cx.ident_of("Encodable") - ], - None, - ~[ - build::mk_simple_ty_path(cx, span, cx.ident_of("__E")) +use core::prelude::*; + +use ast::{meta_item, item, expr, m_imm, m_mutbl}; +use codemap::span; +use ext::base::ExtCtxt; +use ext::build::AstBuilder; +use ext::deriving::generic::*; + +pub fn expand_deriving_encodable(cx: @ExtCtxt, + span: span, + mitem: @meta_item, + in_items: ~[@item]) -> ~[@item] { + let trait_def = TraitDef { + path: Path::new_(~["extra", "serialize", "Encodable"], None, + ~[~Literal(Path::new_local("__E"))], true), + additional_bounds: ~[], + generics: LifetimeBounds { + lifetimes: ~[], + bounds: ~[("__E", ~[Path::new(~["extra", "serialize", "Encoder"])])], + }, + methods: ~[ + MethodDef { + name: "encode", + generics: LifetimeBounds::empty(), + explicit_self: Some(Some(Borrowed(None, m_imm))), + args: ~[Ptr(~Literal(Path::new_local("__E")), + Borrowed(None, m_mutbl))], + ret_ty: nil_ty(), + const_nonmatching: true, + combine_substructure: encodable_substructure, + }, ] - ); - create_derived_impl( - cx, - span, - type_ident, - generics, - methods, - trait_path, - Generics { ty_params: generic_ty_params, lifetimes: opt_vec::Empty }, - opt_vec::Empty - ) -} - -// Creates a method from the given set of statements conforming to the -// signature of the `encodable` method. -fn create_encode_method( - cx: @ext_ctxt, - span: span, - statements: ~[@stmt] -) -> @method { - // Create the `e` parameter. - let e_arg_type = build::mk_ty_rptr( - cx, - span, - build::mk_simple_ty_path(cx, span, cx.ident_of("__E")), - None, - ast::m_mutbl - ); - let e_arg = build::mk_arg(cx, span, cx.ident_of("__e"), e_arg_type); - - // Create the type of the return value. - let output_type = @ast::Ty { id: cx.next_id(), node: ty_nil, span: span }; - - // Create the function declaration. - let inputs = ~[e_arg]; - let fn_decl = build::mk_fn_decl(inputs, output_type); - - // Create the body block. - let body_block = build::mk_block_(cx, span, statements); - - // Create the method. - let explicit_self = spanned { node: sty_region(None, m_imm), span: span }; - let method_ident = cx.ident_of("encode"); - @ast::method { - ident: method_ident, - attrs: ~[], - generics: ast_util::empty_generics(), - explicit_self: explicit_self, - purity: impure_fn, - decl: fn_decl, - body: body_block, - id: cx.next_id(), - span: span, - self_id: cx.next_id(), - vis: public - } -} - -fn call_substructure_encode_method( - cx: @ext_ctxt, - span: span, - self_field: @expr -) -> @ast::expr { - // Gather up the parameters we want to chain along. - let e_ident = cx.ident_of("__e"); - let e_expr = build::mk_path(cx, span, ~[e_ident]); - - // Call the substructure method. - let encode_ident = cx.ident_of("encode"); - build::mk_method_call( - cx, - span, - self_field, - encode_ident, - ~[e_expr] - ) -} - -fn expand_deriving_encodable_struct_def( - cx: @ext_ctxt, - span: span, - struct_def: &struct_def, - type_ident: ident, - generics: &Generics -) -> @item { - // Create the method. - let method = expand_deriving_encodable_struct_method( - cx, - span, - type_ident, - struct_def - ); - - // Create the implementation. - create_derived_encodable_impl( - cx, - span, - type_ident, - generics, - method - ) -} - -fn expand_deriving_encodable_enum_def( - cx: @ext_ctxt, - span: span, - enum_definition: &enum_def, - type_ident: ident, - generics: &Generics -) -> @item { - // Create the method. - let method = expand_deriving_encodable_enum_method( - cx, - span, - type_ident, - enum_definition - ); + }; - // Create the implementation. - create_derived_encodable_impl( - cx, - span, - type_ident, - generics, - method - ) + expand_deriving_generic(cx, span, mitem, in_items, + &trait_def) } -fn expand_deriving_encodable_struct_method( - cx: @ext_ctxt, - span: span, - type_ident: ident, - struct_def: &struct_def -) -> @method { - // Create the body of the method. - let mut idx = 0; - let mut statements = ~[]; - for struct_def.fields.each |struct_field| { - match struct_field.node.kind { - named_field(ident, _) => { - // Create the accessor for this field. - let self_field = build::mk_access_(cx, - span, - build::make_self(cx, span), - ident); - - // Call the substructure method. - let encode_expr = call_substructure_encode_method( - cx, - span, - self_field - ); - - let e_ident = cx.ident_of("__e"); - let e_arg = build::mk_arg(cx, - span, - e_ident, - build::mk_ty_infer(cx, span)); - - let blk_expr = build::mk_lambda( - cx, - span, - build::mk_fn_decl(~[e_arg], build::mk_ty_infer(cx, span)), - encode_expr - ); - - let call_expr = build::mk_method_call( - cx, - span, - build::mk_path(cx, span, ~[cx.ident_of("__e")]), - cx.ident_of("emit_struct_field"), - ~[ - build::mk_base_str(cx, span, cx.str_of(ident)), - build::mk_uint(cx, span, idx), - blk_expr - ] - ); - - statements.push(build::mk_stmt(cx, span, call_expr)); - } - unnamed_field => { - cx.span_unimpl( - span, - ~"unnamed fields with `deriving(Encodable)`" - ); +fn encodable_substructure(cx: @ExtCtxt, span: span, + substr: &Substructure) -> @expr { + let encoder = substr.nonself_args[0]; + // throw an underscore in front to suppress unused variable warnings + let blkarg = cx.ident_of("_e"); + let blkencoder = cx.expr_ident(span, blkarg); + let encode = cx.ident_of("encode"); + + return match *substr.fields { + Struct(ref fields) => { + let emit_struct_field = cx.ident_of("emit_struct_field"); + let mut stmts = ~[]; + for fields.eachi |i, f| { + let (name, val) = match *f { + (Some(id), e, _) => (cx.str_of(id), e), + (None, e, _) => (fmt!("_field%u", i), e) + }; + let enc = cx.expr_method_call(span, val, encode, ~[blkencoder]); + let lambda = cx.lambda_expr_1(span, enc, blkarg); + let call = cx.expr_method_call(span, blkencoder, + emit_struct_field, + ~[cx.expr_str(span, name), + cx.expr_uint(span, i), + lambda]); + stmts.push(cx.stmt_expr(call)); } - } - idx += 1; - } - - let e_arg = build::mk_arg(cx, - span, - cx.ident_of("__e"), - build::mk_ty_infer(cx, span)); - - let emit_struct_stmt = build::mk_method_call( - cx, - span, - build::mk_path( - cx, - span, - ~[cx.ident_of("__e")] - ), - cx.ident_of("emit_struct"), - ~[ - build::mk_base_str(cx, span, cx.str_of(type_ident)), - build::mk_uint(cx, span, statements.len()), - build::mk_lambda_stmts( - cx, - span, - build::mk_fn_decl(~[e_arg], build::mk_ty_infer(cx, span)), - statements - ), - ] - ); - - let statements = ~[build::mk_stmt(cx, span, emit_struct_stmt)]; - - // Create the method itself. - return create_encode_method(cx, span, statements); -} - -fn expand_deriving_encodable_enum_method( - cx: @ext_ctxt, - span: span, - type_ident: ast::ident, - enum_definition: &enum_def -) -> @method { - // Create the arms of the match in the method body. - let arms = do enum_definition.variants.mapi |i, variant| { - // Create the matching pattern. - let (pat, fields) = create_enum_variant_pattern(cx, span, variant, "__self", ast::m_imm); - - // Feed the discriminant to the encode function. - let mut stmts = ~[]; - - // Feed each argument in this variant to the encode function - // as well. - let variant_arg_len = variant_arg_count(cx, span, variant); - for fields.eachi |j, &(_, field)| { - // Call the substructure method. - let expr = call_substructure_encode_method(cx, span, field); - - let e_ident = cx.ident_of("__e"); - let e_arg = build::mk_arg(cx, - span, - e_ident, - build::mk_ty_infer(cx, span)); - - let blk_expr = build::mk_lambda( - cx, - span, - build::mk_fn_decl(~[e_arg], build::mk_ty_infer(cx, span)), - expr - ); - - let call_expr = build::mk_method_call( - cx, - span, - build::mk_path(cx, span, ~[cx.ident_of("__e")]), - cx.ident_of("emit_enum_variant_arg"), - ~[ - build::mk_uint(cx, span, j), - blk_expr, - ] - ); - - stmts.push(build::mk_stmt(cx, span, call_expr)); - } - // Create the pattern body. - let e_arg = build::mk_arg(cx, - span, - cx.ident_of("__e"), - build::mk_ty_infer(cx, span)); - let call_expr = build::mk_method_call( - cx, - span, - build::mk_path(cx, span, ~[cx.ident_of("__e")]), - cx.ident_of("emit_enum_variant"), - ~[ - build::mk_base_str(cx, span, cx.str_of(variant.node.name)), - build::mk_uint(cx, span, i), - build::mk_uint(cx, span, variant_arg_len), - build::mk_lambda_stmts( - cx, - span, - build::mk_fn_decl(~[e_arg], build::mk_ty_infer(cx, span)), - stmts - ) - ] - ); - - let match_body_block = build::mk_simple_block(cx, span, call_expr); + let blk = cx.lambda_stmts_1(span, stmts, blkarg); + cx.expr_method_call(span, encoder, cx.ident_of("emit_struct"), + ~[cx.expr_str(span, cx.str_of(substr.type_ident)), + cx.expr_uint(span, fields.len()), + blk]) + } + + EnumMatching(idx, variant, ref fields) => { + // We're not generating an AST that the borrow checker is expecting, + // so we need to generate a unique local variable to take the + // mutable loan out on, otherwise we get conflicts which don't + // actually exist. + let me = cx.stmt_let(span, false, blkarg, encoder); + let encoder = cx.expr_ident(span, blkarg); + let emit_variant_arg = cx.ident_of("emit_enum_variant_arg"); + let mut stmts = ~[]; + for fields.eachi |i, f| { + let val = match *f { (_, e, _) => e }; + let enc = cx.expr_method_call(span, val, encode, ~[blkencoder]); + let lambda = cx.lambda_expr_1(span, enc, blkarg); + let call = cx.expr_method_call(span, blkencoder, + emit_variant_arg, + ~[cx.expr_uint(span, i), + lambda]); + stmts.push(cx.stmt_expr(call)); + } - // Create the arm. - ast::arm { - pats: ~[pat], - guard: None, - body: match_body_block, - } + let blk = cx.lambda_stmts_1(span, stmts, blkarg); + let name = cx.expr_str(span, cx.str_of(variant.node.name)); + let call = cx.expr_method_call(span, blkencoder, + cx.ident_of("emit_enum_variant"), + ~[name, + cx.expr_uint(span, idx), + cx.expr_uint(span, fields.len()), + blk]); + let blk = cx.lambda_expr_1(span, call, blkarg); + let ret = cx.expr_method_call(span, encoder, + cx.ident_of("emit_enum"), + ~[cx.expr_str(span, + cx.str_of(substr.type_ident)), + blk]); + cx.expr_blk(cx.blk(span, ~[me], Some(ret))) + } + + _ => cx.bug("expected Struct or EnumMatching in deriving(Encodable)") }; - - let e_ident = cx.ident_of("__e"); - let e_arg = build::mk_arg(cx, - span, - e_ident, - build::mk_ty_infer(cx, span)); - - // Create the method body. - let lambda_expr = build::mk_lambda( - cx, - span, - build::mk_fn_decl(~[e_arg], build::mk_ty_infer(cx, span)), - expand_enum_or_struct_match(cx, span, arms) - ); - - let call_expr = build::mk_method_call( - cx, - span, - build::mk_path(cx, span, ~[cx.ident_of("__e")]), - cx.ident_of("emit_enum"), - ~[ - build::mk_base_str(cx, span, cx.str_of(type_ident)), - lambda_expr, - ] - ); - - let stmt = build::mk_stmt(cx, span, call_expr); - - // Create the method. - create_encode_method(cx, span, ~[stmt]) -} - -#[cfg(test)] -mod test { - extern mod std; - use core::option::{None, Some}; - use std::serialize::Encodable; - use std::serialize::Encoder; - - // just adding the ones I want to test, for now: - #[deriving(Eq)] - pub enum call { - CallToEmitEnum(~str), - CallToEmitEnumVariant(~str, uint, uint), - CallToEmitEnumVariantArg(uint), - CallToEmitUint(uint), - CallToEmitNil, - CallToEmitStruct(~str,uint), - CallToEmitField(~str,uint), - CallToEmitOption, - CallToEmitOptionNone, - CallToEmitOptionSome, - // all of the ones I was too lazy to handle: - CallToOther - } - // using `@mut` rather than changing the - // type of self in every method of every encoder everywhere. - pub struct TestEncoder {call_log : @mut ~[call]} - - pub impl TestEncoder { - // these self's should be &mut self's, as well.... - fn add_to_log (&self, c : call) { - self.call_log.push(copy c); - } - fn add_unknown_to_log (&self) { - self.add_to_log (CallToOther) - } - } - - impl Encoder for TestEncoder { - fn emit_nil(&mut self) { self.add_to_log(CallToEmitNil) } - - fn emit_uint(&mut self, v: uint) { - self.add_to_log(CallToEmitUint(v)); - } - fn emit_u64(&mut self, _v: u64) { self.add_unknown_to_log(); } - fn emit_u32(&mut self, _v: u32) { self.add_unknown_to_log(); } - fn emit_u16(&mut self, _v: u16) { self.add_unknown_to_log(); } - fn emit_u8(&mut self, _v: u8) { self.add_unknown_to_log(); } - - fn emit_int(&mut self, _v: int) { self.add_unknown_to_log(); } - fn emit_i64(&mut self, _v: i64) { self.add_unknown_to_log(); } - fn emit_i32(&mut self, _v: i32) { self.add_unknown_to_log(); } - fn emit_i16(&mut self, _v: i16) { self.add_unknown_to_log(); } - fn emit_i8(&mut self, _v: i8) { self.add_unknown_to_log(); } - - fn emit_bool(&mut self, _v: bool) { self.add_unknown_to_log(); } - - fn emit_f64(&mut self, _v: f64) { self.add_unknown_to_log(); } - fn emit_f32(&mut self, _v: f32) { self.add_unknown_to_log(); } - fn emit_float(&mut self, _v: float) { self.add_unknown_to_log(); } - - fn emit_char(&mut self, _v: char) { self.add_unknown_to_log(); } - fn emit_str(&mut self, _v: &str) { self.add_unknown_to_log(); } - - fn emit_enum(&mut self, name: &str, f: &fn(&mut TestEncoder)) { - self.add_to_log(CallToEmitEnum(name.to_str())); - f(self); - } - - fn emit_enum_variant(&mut self, - name: &str, - id: uint, - cnt: uint, - f: &fn(&mut TestEncoder)) { - self.add_to_log(CallToEmitEnumVariant(name.to_str(), id, cnt)); - f(self); - } - - fn emit_enum_variant_arg(&mut self, - idx: uint, - f: &fn(&mut TestEncoder)) { - self.add_to_log(CallToEmitEnumVariantArg(idx)); - f(self); - } - - fn emit_enum_struct_variant(&mut self, - name: &str, - id: uint, - cnt: uint, - f: &fn(&mut TestEncoder)) { - self.emit_enum_variant(name, id, cnt, f) - } - - fn emit_enum_struct_variant_field(&mut self, - _name: &str, - idx: uint, - f: &fn(&mut TestEncoder)) { - self.emit_enum_variant_arg(idx, f) - } - - fn emit_struct(&mut self, - name: &str, - len: uint, - f: &fn(&mut TestEncoder)) { - self.add_to_log(CallToEmitStruct (name.to_str(),len)); - f(self); - } - fn emit_struct_field(&mut self, - name: &str, - idx: uint, - f: &fn(&mut TestEncoder)) { - self.add_to_log(CallToEmitField (name.to_str(),idx)); - f(self); - } - - fn emit_tuple(&mut self, _len: uint, f: &fn(&mut TestEncoder)) { - self.add_unknown_to_log(); - f(self); - } - fn emit_tuple_arg(&mut self, _idx: uint, f: &fn(&mut TestEncoder)) { - self.add_unknown_to_log(); - f(self); - } - - fn emit_tuple_struct(&mut self, - _name: &str, - _len: uint, - f: &fn(&mut TestEncoder)) { - self.add_unknown_to_log(); - f(self); - } - - fn emit_tuple_struct_arg(&mut self, - _idx: uint, - f: &fn(&mut TestEncoder)) { - self.add_unknown_to_log(); - f(self); - } - - fn emit_option(&mut self, f: &fn(&mut TestEncoder)) { - self.add_to_log(CallToEmitOption); - f(self); - } - fn emit_option_none(&mut self) { - self.add_to_log(CallToEmitOptionNone); - } - fn emit_option_some(&mut self, f: &fn(&mut TestEncoder)) { - self.add_to_log(CallToEmitOptionSome); - f(self); - } - - fn emit_seq(&mut self, _len: uint, f: &fn(&mut TestEncoder)) { - self.add_unknown_to_log(); - f(self); - } - fn emit_seq_elt(&mut self, _idx: uint, f: &fn(&mut TestEncoder)) { - self.add_unknown_to_log(); - f(self); - } - - fn emit_map(&mut self, _len: uint, f: &fn(&mut TestEncoder)) { - self.add_unknown_to_log(); - f(self); - } - fn emit_map_elt_key(&mut self, _idx: uint, f: &fn(&mut TestEncoder)) { - self.add_unknown_to_log(); - f(self); - } - fn emit_map_elt_val(&mut self, _idx: uint, f: &fn(&mut TestEncoder)) { - self.add_unknown_to_log(); - f(self); - } - } - - - fn to_call_log>(val: E) -> ~[call] { - let mut te = TestEncoder { - call_log: @mut ~[] - }; - val.encode(&mut te); - copy *te.call_log - } - - #[deriving(Encodable)] - enum Written { - Book(uint,uint), - Magazine(~str) - } - - #[test] - fn test_encode_enum() { - assert_eq!( - to_call_log(Book(34,44)), - ~[ - CallToEmitEnum(~"Written"), - CallToEmitEnumVariant(~"Book",0,2), - CallToEmitEnumVariantArg(0), - CallToEmitUint(34), - CallToEmitEnumVariantArg(1), - CallToEmitUint(44), - ] - ); - } - - pub struct BPos(uint); - - #[deriving(Encodable)] - pub struct HasPos { pos : BPos } - - #[test] - fn test_encode_newtype() { - assert_eq!( - to_call_log(HasPos { pos:BPos(48) }), - ~[ - CallToEmitStruct(~"HasPos",1), - CallToEmitField(~"pos",0), - CallToEmitUint(48), - ] - ); - } - - #[test] - fn test_encode_option() { - let mut v = None; - - assert_eq!( - to_call_log(v), - ~[ - CallToEmitOption, - CallToEmitOptionNone, - ] - ); - - v = Some(54u); - assert_eq!( - to_call_log(v), - ~[ - CallToEmitOption, - CallToEmitOptionSome, - CallToEmitUint(54) - ] - ); - } } diff --git a/src/libsyntax/ext/deriving/generic.rs b/src/libsyntax/ext/deriving/generic.rs index fc14e3c3f732b..2e6cac1876bbb 100644 --- a/src/libsyntax/ext/deriving/generic.rs +++ b/src/libsyntax/ext/deriving/generic.rs @@ -162,19 +162,24 @@ StaticEnum(, ~[(, Left(1)), */ +use core::prelude::*; + use ast; use ast::{enum_def, expr, ident, Generics, struct_def}; -use ext::base::ext_ctxt; -use ext::build; +use ext::base::ExtCtxt; +use ext::build::AstBuilder; use ext::deriving::*; use codemap::{span,respan}; use opt_vec; +use core::uint; +use core::vec; + pub use self::ty::*; mod ty; -pub fn expand_deriving_generic(cx: @ext_ctxt, +pub fn expand_deriving_generic(cx: @ExtCtxt, span: span, _mitem: @ast::meta_item, in_items: ~[@ast::item], @@ -195,13 +200,13 @@ pub fn expand_deriving_generic(cx: @ext_ctxt, pub struct TraitDef<'self> { /// Path of the trait, including any type parameters - path: Path, + path: Path<'self>, /// Additional bounds required of any type parameters of the type, /// other than the current trait - additional_bounds: ~[Ty], + additional_bounds: ~[Ty<'self>], - /// Any extra lifetimes and/or bounds, e.g. `D: std::serialize::Decoder` - generics: LifetimeBounds, + /// Any extra lifetimes and/or bounds, e.g. `D: extra::serialize::Decoder` + generics: LifetimeBounds<'self>, methods: ~[MethodDef<'self>] } @@ -209,20 +214,20 @@ pub struct TraitDef<'self> { pub struct MethodDef<'self> { /// name of the method - name: ~str, + name: &'self str, /// List of generics, e.g. `R: core::rand::Rng` - generics: LifetimeBounds, + generics: LifetimeBounds<'self>, /// Whether there is a self argument (outer Option) i.e. whether /// this is a static function, and whether it is a pointer (inner /// Option) - explicit_self: Option>, + explicit_self: Option>>, /// Arguments other than the self argument - args: ~[Ty], + args: ~[Ty<'self>], /// Return type - ret_ty: Ty, + ret_ty: Ty<'self>, /// if the value of the nonmatching enums is independent of the /// actual enum variants, i.e. can use _ => .. match. @@ -281,7 +286,7 @@ Combine the values of all the fields together. The last argument is all the fields of all the structures, see above for details. */ pub type CombineSubstructureFunc<'self> = - &'self fn(@ext_ctxt, span, &Substructure) -> @expr; + &'self fn(@ExtCtxt, span, &Substructure) -> @expr; /** Deal with non-matching enum variants, the arguments are a list @@ -289,14 +294,14 @@ representing each variant: (variant index, ast::variant instance, [variant fields]), and a list of the nonself args of the type */ pub type EnumNonMatchFunc<'self> = - &'self fn(@ext_ctxt, span, + &'self fn(@ExtCtxt, span, &[(uint, ast::variant, ~[(Option, @expr)])], &[@expr]) -> @expr; impl<'self> TraitDef<'self> { - fn create_derived_impl(&self, cx: @ext_ctxt, span: span, + fn create_derived_impl(&self, cx: @ExtCtxt, span: span, type_ident: ident, generics: &Generics, methods: ~[@ast::method]) -> @ast::item { let trait_path = self.path.to_path(cx, span, type_ident, generics); @@ -315,7 +320,7 @@ impl<'self> TraitDef<'self> { additional_bounds) } - fn expand_struct_def(&self, cx: @ext_ctxt, + fn expand_struct_def(&self, cx: @ExtCtxt, span: span, struct_def: &struct_def, type_ident: ident, @@ -347,7 +352,7 @@ impl<'self> TraitDef<'self> { } fn expand_enum_def(&self, - cx: @ext_ctxt, span: span, + cx: @ExtCtxt, span: span, enum_def: &enum_def, type_ident: ident, generics: &Generics) -> @ast::item { @@ -380,7 +385,7 @@ impl<'self> TraitDef<'self> { impl<'self> MethodDef<'self> { fn call_substructure_method(&self, - cx: @ext_ctxt, + cx: @ExtCtxt, span: span, type_ident: ident, self_args: &[@expr], @@ -398,7 +403,7 @@ impl<'self> MethodDef<'self> { &substructure) } - fn get_ret_ty(&self, cx: @ext_ctxt, span: span, + fn get_ret_ty(&self, cx: @ExtCtxt, span: span, generics: &Generics, type_ident: ident) -> @ast::Ty { self.ret_ty.to_ty(cx, span, type_ident, generics) } @@ -407,11 +412,13 @@ impl<'self> MethodDef<'self> { self.explicit_self.is_none() } - fn split_self_nonself_args(&self, cx: @ext_ctxt, span: span, + fn split_self_nonself_args(&self, cx: @ExtCtxt, span: span, type_ident: ident, generics: &Generics) -> (ast::explicit_self, ~[@expr], ~[@expr], ~[(ident, @ast::Ty)]) { - let mut self_args = ~[], nonself_args = ~[], arg_tys = ~[]; + let mut self_args = ~[]; + let mut nonself_args = ~[]; + let mut arg_tys = ~[]; let mut nonstatic = false; let ast_explicit_self = match self.explicit_self { @@ -431,7 +438,7 @@ impl<'self> MethodDef<'self> { let ident = cx.ident_of(fmt!("__arg_%u", i)); arg_tys.push((ident, ast_ty)); - let arg_expr = build::mk_path(cx, span, ~[ident]); + let arg_expr = cx.expr_ident(span, ident); match *ty { // for static methods, just treat any Self @@ -440,7 +447,7 @@ impl<'self> MethodDef<'self> { self_args.push(arg_expr); } Ptr(~Self, _) if nonstatic => { - self_args.push(build::mk_deref(cx, span, arg_expr)) + self_args.push(cx.expr_deref(span, arg_expr)) } _ => { nonself_args.push(arg_expr); @@ -451,7 +458,7 @@ impl<'self> MethodDef<'self> { (ast_explicit_self, self_args, nonself_args, arg_tys) } - fn create_method(&self, cx: @ext_ctxt, span: span, + fn create_method(&self, cx: @ExtCtxt, span: span, type_ident: ident, generics: &Generics, explicit_self: ast::explicit_self, @@ -461,14 +468,14 @@ impl<'self> MethodDef<'self> { let fn_generics = self.generics.to_generics(cx, span, type_ident, generics); let args = do arg_types.map |&(id, ty)| { - build::mk_arg(cx, span, id, ty) + cx.arg(span, id, ty) }; let ret_type = self.get_ret_ty(cx, span, generics, type_ident); let method_ident = cx.ident_of(self.name); - let fn_decl = build::mk_fn_decl(args, ret_type); - let body_block = build::mk_simple_block(cx, span, body); + let fn_decl = cx.fn_decl(args, ret_type); + let body_block = cx.blk_expr(body); // Create the method. @@ -509,7 +516,7 @@ impl<'self> MethodDef<'self> { ~~~ */ fn expand_struct_method_body(&self, - cx: @ext_ctxt, + cx: @ExtCtxt, span: span, struct_def: &struct_def, type_ident: ident, @@ -517,8 +524,9 @@ impl<'self> MethodDef<'self> { nonself_args: &[@expr]) -> @expr { - let mut raw_fields = ~[], // ~[[fields of self], [fields of next Self arg], [etc]] - patterns = ~[]; + let mut raw_fields = ~[]; // ~[[fields of self], + // [fields of next Self arg], [etc]] + let mut patterns = ~[]; for uint::range(0, self_args.len()) |i| { let (pat, ident_expr) = create_struct_pattern(cx, span, type_ident, struct_def, @@ -539,8 +547,8 @@ impl<'self> MethodDef<'self> { (opt_id, field, other_fields) } } - [] => { cx.span_bug(span, ~"No self arguments to non-static \ - method in generic `deriving`") } + [] => { cx.span_bug(span, "No self arguments to non-static \ + method in generic `deriving`") } }; // body of the inner most destructuring match @@ -555,19 +563,14 @@ impl<'self> MethodDef<'self> { // structs. This is actually right-to-left, but it shoudn't // matter. for vec::each2(self_args, patterns) |&arg_expr, &pat| { - let match_arm = ast::arm { - pats: ~[ pat ], - guard: None, - body: build::mk_simple_block(cx, span, body) - }; - - body = build::mk_expr(cx, span, ast::expr_match(arg_expr, ~[match_arm])) + body = cx.expr_match(span, arg_expr, + ~[ cx.arm(span, ~[pat], body) ]) } body } fn expand_static_struct_method_body(&self, - cx: @ext_ctxt, + cx: @ExtCtxt, span: span, struct_def: &struct_def, type_ident: ident, @@ -609,7 +612,7 @@ impl<'self> MethodDef<'self> { ~~~ */ fn expand_enum_method_body(&self, - cx: @ext_ctxt, + cx: @ExtCtxt, span: span, enum_def: &enum_def, type_ident: ident, @@ -645,7 +648,7 @@ impl<'self> MethodDef<'self> { the first call). */ fn build_enum_match(&self, - cx: @ext_ctxt, span: span, + cx: @ExtCtxt, span: span, enum_def: &enum_def, type_ident: ident, self_args: &[@expr], @@ -658,8 +661,8 @@ impl<'self> MethodDef<'self> { // we've matched against all arguments, so make the final // expression at the bottom of the match tree if matches_so_far.len() == 0 { - cx.span_bug(span, ~"no self match on an enum in generic \ - `deriving`"); + cx.span_bug(span, "no self match on an enum in generic \ + `deriving`"); } // we currently have a vec of vecs, where each // subvec is the fields of one of the arguments, @@ -690,7 +693,7 @@ impl<'self> MethodDef<'self> { } let field_tuples = do vec::map_zip(*self_vec, - enum_matching_fields) |&(id, self_f), &other| { + enum_matching_fields) |&(id, self_f), &other| { (id, self_f, other) }; substructure = EnumMatching(variant_index, variant, field_tuples); @@ -718,8 +721,8 @@ impl<'self> MethodDef<'self> { // make a matching-variant match, and a _ match. let index = match matching { Some(i) => i, - None => cx.span_bug(span, ~"Non-matching variants when required to \ - be matching in generic `deriving`") + None => cx.span_bug(span, "Non-matching variants when required to \ + be matching in generic `deriving`") }; // matching-variant match @@ -738,16 +741,16 @@ impl<'self> MethodDef<'self> { matches_so_far, match_count + 1); matches_so_far.pop(); - arms.push(build::mk_arm(cx, span, ~[ pattern ], arm_expr)); + arms.push(cx.arm(span, ~[ pattern ], arm_expr)); if enum_def.variants.len() > 1 { let e = &EnumNonMatching(&[]); let wild_expr = self.call_substructure_method(cx, span, type_ident, self_args, nonself_args, e); - let wild_arm = build::mk_arm(cx, span, - ~[ build::mk_pat_wild(cx, span) ], - wild_expr); + let wild_arm = cx.arm(span, + ~[ cx.pat_wild(span) ], + wild_expr); arms.push(wild_arm); } } else { @@ -774,19 +777,18 @@ impl<'self> MethodDef<'self> { match_count + 1); matches_so_far.pop(); - let arm = build::mk_arm(cx, span, ~[ pattern ], arm_expr); + let arm = cx.arm(span, ~[ pattern ], arm_expr); arms.push(arm); } } // match foo { arm, arm, arm, ... } - build::mk_expr(cx, span, - ast::expr_match(self_args[match_count], arms)) + cx.expr_match(span, self_args[match_count], arms) } } fn expand_static_enum_method_body(&self, - cx: @ext_ctxt, + cx: @ExtCtxt, span: span, enum_def: &enum_def, type_ident: ident, @@ -810,7 +812,7 @@ impl<'self> MethodDef<'self> { } } -fn summarise_struct(cx: @ext_ctxt, span: span, +fn summarise_struct(cx: @ExtCtxt, span: span, struct_def: &struct_def) -> Either { let mut named_idents = ~[]; let mut unnamed_count = 0; @@ -840,12 +842,12 @@ Fold the fields. `use_foldl` controls whether this is done left-to-right (`true`) or right-to-left (`false`). */ pub fn cs_fold(use_foldl: bool, - f: &fn(@ext_ctxt, span, + f: &fn(@ExtCtxt, span, old: @expr, self_f: @expr, other_fs: &[@expr]) -> @expr, base: @expr, enum_nonmatch_f: EnumNonMatchFunc, - cx: @ext_ctxt, span: span, + cx: @ExtCtxt, span: span, substructure: &Substructure) -> @expr { match *substructure.fields { EnumMatching(_, _, ref all_fields) | Struct(ref all_fields) => { @@ -879,18 +881,18 @@ f(cx, span, ~[self_1.method(__arg_1_1, __arg_2_1), ~~~ */ #[inline(always)] -pub fn cs_same_method(f: &fn(@ext_ctxt, span, ~[@expr]) -> @expr, +pub fn cs_same_method(f: &fn(@ExtCtxt, span, ~[@expr]) -> @expr, enum_nonmatch_f: EnumNonMatchFunc, - cx: @ext_ctxt, span: span, + cx: @ExtCtxt, span: span, substructure: &Substructure) -> @expr { match *substructure.fields { EnumMatching(_, _, ref all_fields) | Struct(ref all_fields) => { // call self_n.method(other_1_n, other_2_n, ...) let called = do all_fields.map |&(_, self_field, other_fields)| { - build::mk_method_call(cx, span, - self_field, - substructure.method_ident, - other_fields) + cx.expr_method_call(span, + self_field, + substructure.method_ident, + other_fields) }; f(cx, span, called) @@ -911,10 +913,10 @@ fields. `use_foldl` controls whether this is done left-to-right */ #[inline(always)] pub fn cs_same_method_fold(use_foldl: bool, - f: &fn(@ext_ctxt, span, @expr, @expr) -> @expr, + f: &fn(@ExtCtxt, span, @expr, @expr) -> @expr, base: @expr, enum_nonmatch_f: EnumNonMatchFunc, - cx: @ext_ctxt, span: span, + cx: @ExtCtxt, span: span, substructure: &Substructure) -> @expr { cs_same_method( |cx, span, vals| { @@ -940,14 +942,14 @@ on all the fields. #[inline(always)] pub fn cs_binop(binop: ast::binop, base: @expr, enum_nonmatch_f: EnumNonMatchFunc, - cx: @ext_ctxt, span: span, + cx: @ExtCtxt, span: span, substructure: &Substructure) -> @expr { cs_same_method_fold( true, // foldl is good enough |cx, span, old, new| { - build::mk_binary(cx, span, - binop, - old, new) + cx.expr_binary(span, + binop, + old, new) }, base, @@ -958,18 +960,18 @@ pub fn cs_binop(binop: ast::binop, base: @expr, /// cs_binop with binop == or #[inline(always)] pub fn cs_or(enum_nonmatch_f: EnumNonMatchFunc, - cx: @ext_ctxt, span: span, + cx: @ExtCtxt, span: span, substructure: &Substructure) -> @expr { - cs_binop(ast::or, build::mk_bool(cx, span, false), + cs_binop(ast::or, cx.expr_bool(span, false), enum_nonmatch_f, cx, span, substructure) } /// cs_binop with binop == and #[inline(always)] pub fn cs_and(enum_nonmatch_f: EnumNonMatchFunc, - cx: @ext_ctxt, span: span, + cx: @ExtCtxt, span: span, substructure: &Substructure) -> @expr { - cs_binop(ast::and, build::mk_bool(cx, span, true), + cs_binop(ast::and, cx.expr_bool(span, true), enum_nonmatch_f, cx, span, substructure) } diff --git a/src/libsyntax/ext/deriving/iter_bytes.rs b/src/libsyntax/ext/deriving/iter_bytes.rs index 1c9ec6ece2e1d..10fb4b8ecd4a2 100644 --- a/src/libsyntax/ext/deriving/iter_bytes.rs +++ b/src/libsyntax/ext/deriving/iter_bytes.rs @@ -8,30 +8,34 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use ast::{meta_item, item, expr, and}; use codemap::span; -use ext::base::ext_ctxt; -use ext::build; +use ext::base::ExtCtxt; +use ext::build::AstBuilder; use ext::deriving::generic::*; -pub fn expand_deriving_iter_bytes(cx: @ext_ctxt, +use core::vec; + +pub fn expand_deriving_iter_bytes(cx: @ExtCtxt, span: span, mitem: @meta_item, in_items: ~[@item]) -> ~[@item] { let trait_def = TraitDef { - path: Path::new(~[~"core", ~"to_bytes", ~"IterBytes"]), + path: Path::new(~["std", "to_bytes", "IterBytes"]), additional_bounds: ~[], generics: LifetimeBounds::empty(), methods: ~[ MethodDef { - name: ~"iter_bytes", + name: "iter_bytes", generics: LifetimeBounds::empty(), explicit_self: borrowed_explicit_self(), args: ~[ - Literal(Path::new(~[~"bool"])), - Literal(Path::new(~[~"core", ~"to_bytes", ~"Cb"])) + Literal(Path::new(~["bool"])), + Literal(Path::new(~["std", "to_bytes", "Cb"])) ], - ret_ty: Literal(Path::new(~[~"bool"])), + ret_ty: Literal(Path::new(~["bool"])), const_nonmatching: false, combine_substructure: iter_bytes_substructure } @@ -41,14 +45,14 @@ pub fn expand_deriving_iter_bytes(cx: @ext_ctxt, expand_deriving_generic(cx, span, mitem, in_items, &trait_def) } -fn iter_bytes_substructure(cx: @ext_ctxt, span: span, substr: &Substructure) -> @expr { +fn iter_bytes_substructure(cx: @ExtCtxt, span: span, substr: &Substructure) -> @expr { let lsb0_f = match substr.nonself_args { [l, f] => ~[l, f], _ => cx.span_bug(span, "Incorrect number of arguments in `deriving(IterBytes)`") }; let iter_bytes_ident = substr.method_ident; let call_iterbytes = |thing_expr| { - build::mk_method_call(cx, span, + cx.expr_method_call(span, thing_expr, iter_bytes_ident, copy lsb0_f) }; @@ -58,12 +62,12 @@ fn iter_bytes_substructure(cx: @ext_ctxt, span: span, substr: &Substructure) -> Struct(ref fs) => { fields = fs } - EnumMatching(copy index, ref variant, ref fs) => { + EnumMatching(index, ref variant, ref fs) => { // Determine the discriminant. We will feed this value to the byte // iteration function. let discriminant = match variant.node.disr_expr { - Some(copy d)=> d, - None => build::mk_uint(cx, span, index) + Some(d)=> d, + None => cx.expr_uint(span, index) }; exprs.push(call_iterbytes(discriminant)); @@ -82,6 +86,6 @@ fn iter_bytes_substructure(cx: @ext_ctxt, span: span, substr: &Substructure) -> } do vec::foldl(exprs[0], exprs.slice(1, exprs.len())) |prev, me| { - build::mk_binary(cx, span, and, prev, *me) + cx.expr_binary(span, and, prev, *me) } } diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index 78cd5cdb423d9..13c552388e14e 100644 --- a/src/libsyntax/ext/deriving/mod.rs +++ b/src/libsyntax/ext/deriving/mod.rs @@ -13,19 +13,24 @@ The compiler code necessary to implement the #[deriving] extensions. FIXME (#2810)--Hygiene. Search for "__" strings (in other files too). -We also assume "std" is the standard library, and "core" is the core +We also assume "extra" is the standard library, and "std" is the core library. */ +use core::prelude::*; + use ast; use ast::{Ty, enum_def, expr, ident, item, Generics, meta_item, struct_def}; -use ext::base::ext_ctxt; -use ext::build; -use codemap::{span, respan}; +use ext::base::ExtCtxt; +use ext::build::AstBuilder; +use codemap::span; use parse::token::special_idents::clownshoes_extensions; use opt_vec; +use core::uint; +use core::vec; + pub mod clone; pub mod iter_bytes; pub mod encodable; @@ -45,20 +50,20 @@ pub mod totalord; pub mod generic; -pub type ExpandDerivingStructDefFn<'self> = &'self fn(@ext_ctxt, +pub type ExpandDerivingStructDefFn<'self> = &'self fn(@ExtCtxt, span, x: &struct_def, ident, y: &Generics) -> @item; -pub type ExpandDerivingEnumDefFn<'self> = &'self fn(@ext_ctxt, +pub type ExpandDerivingEnumDefFn<'self> = &'self fn(@ExtCtxt, span, x: &enum_def, ident, y: &Generics) -> @item; -pub fn expand_meta_deriving(cx: @ext_ctxt, +pub fn expand_meta_deriving(cx: @ExtCtxt, _span: span, mitem: @meta_item, in_items: ~[@item]) @@ -67,11 +72,11 @@ pub fn expand_meta_deriving(cx: @ext_ctxt, match mitem.node { meta_name_value(_, ref l) => { - cx.span_err(l.span, ~"unexpected value in `deriving`"); + cx.span_err(l.span, "unexpected value in `deriving`"); in_items } meta_word(_) | meta_list(_, []) => { - cx.span_warn(mitem.span, ~"empty trait list in `deriving`"); + cx.span_warn(mitem.span, "empty trait list in `deriving`"); in_items } meta_list(_, ref titems) => { @@ -113,7 +118,7 @@ pub fn expand_meta_deriving(cx: @ext_ctxt, } } -pub fn expand_deriving(cx: @ext_ctxt, +pub fn expand_deriving(cx: @ExtCtxt, span: span, in_items: ~[@item], expand_deriving_struct_def: ExpandDerivingStructDefFn, @@ -143,38 +148,15 @@ pub fn expand_deriving(cx: @ext_ctxt, result } -fn create_impl_item(cx: @ext_ctxt, span: span, item: ast::item_) -> @item { - let doc_attr = respan(span, - ast::lit_str(@~"Automatically derived.")); - let doc_attr = respan(span, ast::meta_name_value(@~"doc", doc_attr)); - let doc_attr = ast::attribute_ { - style: ast::attr_outer, - value: @doc_attr, - is_sugared_doc: false - }; - let doc_attr = respan(span, doc_attr); - - @ast::item { - ident: clownshoes_extensions, - attrs: ~[doc_attr], - id: cx.next_id(), - node: item, - vis: ast::public, - span: span, - } -} - -pub fn create_self_type_with_params(cx: @ext_ctxt, - span: span, - type_ident: ident, - generics: &Generics) - -> @Ty { +pub fn create_self_type_with_params(cx: @ExtCtxt, + span: span, + type_ident: ident, + generics: &Generics) + -> @Ty { // Create the type parameters on the `self` path. let mut self_ty_params = ~[]; for generics.ty_params.each |ty_param| { - let self_ty_param = build::mk_simple_ty_path(cx, - span, - ty_param.ident); + let self_ty_param = cx.ty_ident(span, ty_param.ident); self_ty_params.push(self_ty_param); } @@ -186,14 +168,10 @@ pub fn create_self_type_with_params(cx: @ext_ctxt, // Create the type of `self`. - let self_type = build::mk_raw_path_(span, - ~[ type_ident ], - lifetime, - self_ty_params); - build::mk_ty_path_path(cx, span, self_type) + cx.ty_path(cx.path_all(span, false, ~[ type_ident ], lifetime, self_ty_params)) } -pub fn create_derived_impl(cx: @ext_ctxt, +pub fn create_derived_impl(cx: @ExtCtxt, span: span, type_ident: ident, generics: &Generics, @@ -222,18 +200,17 @@ pub fn create_derived_impl(cx: @ext_ctxt, for generics.ty_params.each |ty_param| { // extra restrictions on the generics parameters to the type being derived upon let mut bounds = do bounds_paths.map |&bound_path| { - build::mk_trait_ty_param_bound_(cx, bound_path) + cx.typarambound(bound_path) }; - let this_trait_bound = - build::mk_trait_ty_param_bound_(cx, trait_path); + let this_trait_bound = cx.typarambound(trait_path); bounds.push(this_trait_bound); - impl_generics.ty_params.push(build::mk_ty_param(cx, ty_param.ident, @bounds)); + impl_generics.ty_params.push(cx.typaram(ty_param.ident, @bounds)); } // Create the reference to the trait. - let trait_ref = build::mk_trait_ref_(cx, trait_path); + let trait_ref = cx.trait_ref(trait_path); // Create the type of `self`. let self_type = create_self_type_with_params(cx, @@ -241,21 +218,27 @@ pub fn create_derived_impl(cx: @ext_ctxt, type_ident, generics); - // Create the impl item. - let impl_item = ast::item_impl(impl_generics, - Some(trait_ref), - self_type, - methods.map(|x| *x)); - return create_impl_item(cx, span, impl_item); + let doc_attr = cx.attribute( + span, + cx.meta_name_value(span, + ~"doc", ast::lit_str(@~"Automatically derived."))); + cx.item( + span, + clownshoes_extensions, + ~[doc_attr], + ast::item_impl(impl_generics, + Some(trait_ref), + self_type, + methods.map(|x| *x))) } -pub fn create_subpatterns(cx: @ext_ctxt, +pub fn create_subpatterns(cx: @ExtCtxt, span: span, field_paths: ~[@ast::Path], mutbl: ast::mutability) -> ~[@ast::pat] { do field_paths.map |&path| { - build::mk_pat(cx, span, + cx.pat(span, ast::pat_ident(ast::bind_by_ref(mutbl), path, None)) } } @@ -265,7 +248,7 @@ enum StructType { Unknown, Record, Tuple } -pub fn create_struct_pattern(cx: @ext_ctxt, +pub fn create_struct_pattern(cx: @ExtCtxt, span: span, struct_ident: ident, struct_def: &struct_def, @@ -274,15 +257,15 @@ pub fn create_struct_pattern(cx: @ext_ctxt, -> (@ast::pat, ~[(Option, @expr)]) { if struct_def.fields.is_empty() { return ( - build::mk_pat_ident_with_binding_mode( - cx, span, struct_ident, ast::bind_infer), + cx.pat_ident_binding_mode( + span, struct_ident, ast::bind_infer), ~[]); } - let matching_path = build::mk_raw_path(span, ~[ struct_ident ]); - - let mut paths = ~[], ident_expr = ~[]; + let matching_path = cx.path(span, ~[ struct_ident ]); + let mut paths = ~[]; + let mut ident_expr = ~[]; let mut struct_type = Unknown; for struct_def.fields.eachi |i, struct_field| { @@ -301,10 +284,10 @@ pub fn create_struct_pattern(cx: @ext_ctxt, cx.span_bug(span, "A struct with named and unnamed fields in `deriving`"); } }; - let path = build::mk_raw_path(span, - ~[ cx.ident_of(fmt!("%s_%u", prefix, i)) ]); + let path = cx.path_ident(span, + cx.ident_of(fmt!("%s_%u", prefix, i))); paths.push(path); - ident_expr.push((opt_id, build::mk_path_raw(cx, span, path))); + ident_expr.push((opt_id, cx.expr_path(path))); } let subpats = create_subpatterns(cx, span, paths, mutbl); @@ -318,15 +301,15 @@ pub fn create_struct_pattern(cx: @ext_ctxt, push(ast::field_pat { ident: id.get(), pat: pat }) } }; - build::mk_pat_struct(cx, span, matching_path, field_pats) + cx.pat_struct(span, matching_path, field_pats) } else { - build::mk_pat_enum(cx, span, matching_path, subpats) + cx.pat_enum(span, matching_path, subpats) }; (pattern, ident_expr) } -pub fn create_enum_variant_pattern(cx: @ext_ctxt, +pub fn create_enum_variant_pattern(cx: @ExtCtxt, span: span, variant: &ast::variant, prefix: &str, @@ -337,24 +320,25 @@ pub fn create_enum_variant_pattern(cx: @ext_ctxt, match variant.node.kind { ast::tuple_variant_kind(ref variant_args) => { if variant_args.is_empty() { - return (build::mk_pat_ident_with_binding_mode( - cx, span, variant_ident, ast::bind_infer), ~[]); + return (cx.pat_ident_binding_mode( + span, variant_ident, ast::bind_infer), ~[]); } - let matching_path = build::mk_raw_path(span, ~[ variant_ident ]); + let matching_path = cx.path_ident(span, variant_ident); - let mut paths = ~[], ident_expr = ~[]; + let mut paths = ~[]; + let mut ident_expr = ~[]; for uint::range(0, variant_args.len()) |i| { - let path = build::mk_raw_path(span, - ~[ cx.ident_of(fmt!("%s_%u", prefix, i)) ]); + let path = cx.path_ident(span, + cx.ident_of(fmt!("%s_%u", prefix, i))); paths.push(path); - ident_expr.push((None, build::mk_path_raw(cx, span, path))); + ident_expr.push((None, cx.expr_path(path))); } let subpats = create_subpatterns(cx, span, paths, mutbl); - (build::mk_pat_enum(cx, span, matching_path, subpats), + (cx.pat_enum(span, matching_path, subpats), ident_expr) } ast::struct_variant_kind(struct_def) => { @@ -366,19 +350,17 @@ pub fn create_enum_variant_pattern(cx: @ext_ctxt, } } -pub fn variant_arg_count(_cx: @ext_ctxt, _span: span, variant: &ast::variant) -> uint { +pub fn variant_arg_count(_cx: @ExtCtxt, _span: span, variant: &ast::variant) -> uint { match variant.node.kind { ast::tuple_variant_kind(ref args) => args.len(), ast::struct_variant_kind(ref struct_def) => struct_def.fields.len(), } } -pub fn expand_enum_or_struct_match(cx: @ext_ctxt, +pub fn expand_enum_or_struct_match(cx: @ExtCtxt, span: span, arms: ~[ ast::arm ]) -> @expr { - let self_expr = build::make_self(cx, span); - let self_expr = build::mk_unary(cx, span, ast::deref, self_expr); - let self_match_expr = ast::expr_match(self_expr, arms); - build::mk_expr(cx, span, self_match_expr) + let self_expr = cx.expr_deref(span, cx.expr_self(span)); + cx.expr_match(span, self_expr, arms) } diff --git a/src/libsyntax/ext/deriving/rand.rs b/src/libsyntax/ext/deriving/rand.rs index 2d91fcd346ae5..54d31de7c50d4 100644 --- a/src/libsyntax/ext/deriving/rand.rs +++ b/src/libsyntax/ext/deriving/rand.rs @@ -8,33 +8,37 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use ast; use ast::{meta_item, item, expr, ident}; use codemap::span; -use ext::base::ext_ctxt; -use ext::build; +use ext::base::ExtCtxt; +use ext::build::{AstBuilder, Duplicate}; use ext::deriving::generic::*; -pub fn expand_deriving_rand(cx: @ext_ctxt, +use core::vec; + +pub fn expand_deriving_rand(cx: @ExtCtxt, span: span, mitem: @meta_item, in_items: ~[@item]) -> ~[@item] { let trait_def = TraitDef { - path: Path::new(~[~"core", ~"rand", ~"Rand"]), + path: Path::new(~["std", "rand", "Rand"]), additional_bounds: ~[], generics: LifetimeBounds::empty(), methods: ~[ MethodDef { - name: ~"rand", + name: "rand", generics: LifetimeBounds { lifetimes: ~[], - bounds: ~[(~"R", - ~[ Path::new(~[~"core", ~"rand", ~"Rng"]) ])] + bounds: ~[("R", + ~[ Path::new(~["std", "rand", "Rng"]) ])] }, explicit_self: None, args: ~[ - Ptr(~Literal(Path::new_local(~"R")), + Ptr(~Literal(Path::new_local("R")), Borrowed(None, ast::m_mutbl)) ], ret_ty: Self, @@ -47,22 +51,21 @@ pub fn expand_deriving_rand(cx: @ext_ctxt, expand_deriving_generic(cx, span, mitem, in_items, &trait_def) } -fn rand_substructure(cx: @ext_ctxt, span: span, substr: &Substructure) -> @expr { +fn rand_substructure(cx: @ExtCtxt, span: span, substr: &Substructure) -> @expr { let rng = match substr.nonself_args { [rng] => ~[ rng ], _ => cx.bug("Incorrect number of arguments to `rand` in `deriving(Rand)`") }; let rand_ident = ~[ - cx.ident_of("core"), + cx.ident_of("std"), cx.ident_of("rand"), cx.ident_of("Rand"), cx.ident_of("rand") ]; let rand_call = || { - build::mk_call_global(cx, - span, - copy rand_ident, - ~[ build::duplicate_expr(cx, rng[0]) ]) + cx.expr_call_global(span, + copy rand_ident, + ~[ rng[0].duplicate(cx) ]) }; return match *substr.fields { @@ -74,67 +77,61 @@ fn rand_substructure(cx: @ext_ctxt, span: span, substr: &Substructure) -> @expr cx.span_fatal(span, "`Rand` cannot be derived for enums with no variants"); } - let variant_count = build::mk_uint(cx, span, variants.len()); + let variant_count = cx.expr_uint(span, variants.len()); // need to specify the uint-ness of the random number - let u32_ty = build::mk_ty_path(cx, span, ~[cx.ident_of("uint")]); - let r_ty = build::mk_ty_path(cx, span, ~[cx.ident_of("R")]); - let rand_name = build::mk_raw_path_(span, copy rand_ident, None, ~[ u32_ty, r_ty ]); - let rand_name = build::mk_path_raw(cx, span, rand_name); + let u32_ty = cx.ty_ident(span, cx.ident_of("uint")); + let r_ty = cx.ty_ident(span, cx.ident_of("R")); + let rand_name = cx.path_all(span, false, copy rand_ident, None, ~[ u32_ty, r_ty ]); + let rand_name = cx.expr_path(rand_name); - let rv_call = build::mk_call_(cx, - span, - rand_name, - ~[ build::duplicate_expr(cx, rng[0]) ]); + let rv_call = cx.expr_call(span, + rand_name, + ~[ rng[0].duplicate(cx) ]); // rand() % variants.len() - let rand_variant = build::mk_binary(cx, span, ast::rem, + let rand_variant = cx.expr_binary(span, ast::rem, rv_call, variant_count); let mut arms = do variants.mapi |i, id_sum| { - let i_expr = build::mk_uint(cx, span, i); - let pat = build::mk_pat_lit(cx, span, i_expr); + let i_expr = cx.expr_uint(span, i); + let pat = cx.pat_lit(span, i_expr); match *id_sum { (ident, ref summary) => { - build::mk_arm(cx, span, - ~[ pat ], - rand_thing(cx, span, ident, summary, rand_call)) + cx.arm(span, + ~[ pat ], + rand_thing(cx, span, ident, summary, rand_call)) } } }; // _ => {} at the end. Should never occur - arms.push(build::mk_unreachable_arm(cx, span)); + arms.push(cx.arm_unreachable(span)); - build::mk_expr(cx, span, - ast::expr_match(rand_variant, arms)) + cx.expr_match(span, rand_variant, arms) } _ => cx.bug("Non-static method in `deriving(Rand)`") }; - fn rand_thing(cx: @ext_ctxt, span: span, + fn rand_thing(cx: @ExtCtxt, span: span, ctor_ident: ident, summary: &Either, rand_call: &fn() -> @expr) -> @expr { - let ctor_ident = ~[ ctor_ident ]; match *summary { - Left(copy count) => { + Left(count) => { if count == 0 { - build::mk_path(cx, span, ctor_ident) + cx.expr_ident(span, ctor_ident) } else { let exprs = vec::from_fn(count, |_| rand_call()); - build::mk_call(cx, span, ctor_ident, exprs) + cx.expr_call_ident(span, ctor_ident, exprs) } } Right(ref fields) => { let rand_fields = do fields.map |ident| { - build::Field { - ident: *ident, - ex: rand_call() - } + cx.field_imm(span, *ident, rand_call()) }; - build::mk_struct_e(cx, span, ctor_ident, rand_fields) + cx.expr_struct_ident(span, ctor_ident, rand_fields) } } } diff --git a/src/libsyntax/ext/deriving/to_str.rs b/src/libsyntax/ext/deriving/to_str.rs index 13cb09e970df6..52efabd4b9b87 100644 --- a/src/libsyntax/ext/deriving/to_str.rs +++ b/src/libsyntax/ext/deriving/to_str.rs @@ -8,28 +8,30 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use ast::{meta_item, item, expr}; use codemap::span; -use ext::base::ext_ctxt; -use ext::build; +use ext::base::ExtCtxt; +use ext::build::AstBuilder; use ext::deriving::generic::*; -pub fn expand_deriving_to_str(cx: @ext_ctxt, +pub fn expand_deriving_to_str(cx: @ExtCtxt, span: span, mitem: @meta_item, in_items: ~[@item]) -> ~[@item] { let trait_def = TraitDef { - path: Path::new(~[~"core", ~"to_str", ~"ToStr"]), + path: Path::new(~["std", "to_str", "ToStr"]), additional_bounds: ~[], generics: LifetimeBounds::empty(), methods: ~[ MethodDef { - name: ~"to_str", + name: "to_str", generics: LifetimeBounds::empty(), explicit_self: borrowed_explicit_self(), args: ~[], - ret_ty: Ptr(~Literal(Path::new_local(~"str")), Owned), + ret_ty: Ptr(~Literal(Path::new_local("str")), Owned), const_nonmatching: false, combine_substructure: to_str_substructure } @@ -39,16 +41,16 @@ pub fn expand_deriving_to_str(cx: @ext_ctxt, expand_deriving_generic(cx, span, mitem, in_items, &trait_def) } -fn to_str_substructure(cx: @ext_ctxt, span: span, substr: &Substructure) -> @expr { +fn to_str_substructure(cx: @ExtCtxt, span: span, substr: &Substructure) -> @expr { match substr.self_args { [self_obj] => { - let self_addr = build::mk_addr_of(cx, span, self_obj); - build::mk_call_global(cx, span, - ~[cx.ident_of("core"), - cx.ident_of("sys"), - cx.ident_of("log_str")], - ~[self_addr]) + let self_addr = cx.expr_addr_of(span, self_obj); + cx.expr_call_global(span, + ~[cx.ident_of("std"), + cx.ident_of("sys"), + cx.ident_of("log_str")], + ~[self_addr]) } - _ => cx.span_bug(span, ~"Invalid number of arguments in `deriving(ToStr)`") + _ => cx.span_bug(span, "Invalid number of arguments in `deriving(ToStr)`") } } diff --git a/src/libsyntax/ext/deriving/ty.rs b/src/libsyntax/ext/deriving/ty.rs index 8fd372e479286..3b39cb691a629 100644 --- a/src/libsyntax/ext/deriving/ty.rs +++ b/src/libsyntax/ext/deriving/ty.rs @@ -13,39 +13,43 @@ A mini version of ast::Ty, which is easier to use, and features an explicit `Self` type to use when specifying impls to be derived. */ +use core::prelude::*; + use ast; use ast::{expr,Generics,ident}; -use ext::base::ext_ctxt; -use ext::build; +use ext::base::ExtCtxt; +use ext::build::AstBuilder; use codemap::{span,respan}; use opt_vec; /// The types of pointers -#[deriving(Eq)] -pub enum PtrTy { +pub enum PtrTy<'self> { Owned, // ~ Managed(ast::mutability), // @[mut] - Borrowed(Option<~str>, ast::mutability), // &['lifetime] [mut] + Borrowed(Option<&'self str>, ast::mutability), // &['lifetime] [mut] } /// A path, e.g. `::core::option::Option::` (global). Has support /// for type parameters and a lifetime. -#[deriving(Eq)] -pub struct Path { - path: ~[~str], - lifetime: Option<~str>, - params: ~[~Ty], +pub struct Path<'self> { + path: ~[&'self str], + lifetime: Option<&'self str>, + params: ~[~Ty<'self>], global: bool } -pub impl Path { - fn new(path: ~[~str]) -> Path { +impl<'self> Path<'self> { + pub fn new<'r>(path: ~[&'r str]) -> Path<'r> { Path::new_(path, None, ~[], true) } - fn new_local(path: ~str) -> Path { + pub fn new_local<'r>(path: &'r str) -> Path<'r> { Path::new_(~[ path ], None, ~[], false) } - fn new_(path: ~[~str], lifetime: Option<~str>, params: ~[~Ty], global: bool) -> Path { + pub fn new_<'r>(path: ~[&'r str], + lifetime: Option<&'r str>, + params: ~[~Ty<'r>], + global: bool) + -> Path<'r> { Path { path: path, lifetime: lifetime, @@ -54,87 +58,93 @@ pub impl Path { } } - fn to_ty(&self, cx: @ext_ctxt, span: span, - self_ty: ident, self_generics: &Generics) -> @ast::Ty { - build::mk_ty_path_path(cx, span, - self.to_path(cx, span, - self_ty, self_generics)) + pub fn to_ty(&self, + cx: @ExtCtxt, + span: span, + self_ty: ident, + self_generics: &Generics) + -> @ast::Ty { + cx.ty_path(self.to_path(cx, span, + self_ty, self_generics)) } - fn to_path(&self, cx: @ext_ctxt, span: span, - self_ty: ident, self_generics: &Generics) -> @ast::Path { + pub fn to_path(&self, + cx: @ExtCtxt, + span: span, + self_ty: ident, + self_generics: &Generics) + -> @ast::Path { let idents = self.path.map(|s| cx.ident_of(*s) ); let lt = mk_lifetime(cx, span, &self.lifetime); let tys = self.params.map(|t| t.to_ty(cx, span, self_ty, self_generics)); - if self.global { - build::mk_raw_path_global_(span, idents, lt, tys) - } else { - build::mk_raw_path_(span, idents, lt, tys) - } + cx.path_all(span, self.global, idents, lt, tys) } } /// A type. Supports pointers (except for *), Self, and literals -#[deriving(Eq)] -pub enum Ty { +pub enum Ty<'self> { Self, // &/~/@ Ty - Ptr(~Ty, PtrTy), + Ptr(~Ty<'self>, PtrTy<'self>), // mod::mod::Type<[lifetime], [Params...]>, including a plain type // parameter, and things like `int` - Literal(Path), + Literal(Path<'self>), // includes nil - Tuple(~[Ty]) + Tuple(~[Ty<'self>]) } -pub fn borrowed_ptrty() -> PtrTy { +pub fn borrowed_ptrty<'r>() -> PtrTy<'r> { Borrowed(None, ast::m_imm) } -pub fn borrowed(ty: ~Ty) -> Ty { +pub fn borrowed<'r>(ty: ~Ty<'r>) -> Ty<'r> { Ptr(ty, borrowed_ptrty()) } -pub fn borrowed_explicit_self() -> Option> { +pub fn borrowed_explicit_self<'r>() -> Option>> { Some(Some(borrowed_ptrty())) } -pub fn borrowed_self() -> Ty { +pub fn borrowed_self<'r>() -> Ty<'r> { borrowed(~Self) } -pub fn nil_ty() -> Ty { +pub fn nil_ty() -> Ty<'static> { Tuple(~[]) } -fn mk_lifetime(cx: @ext_ctxt, span: span, lt: &Option<~str>) -> Option<@ast::Lifetime> { +fn mk_lifetime(cx: @ExtCtxt, span: span, lt: &Option<&str>) -> Option<@ast::Lifetime> { match *lt { - Some(ref s) => Some(@build::mk_lifetime(cx, span, cx.ident_of(*s))), + Some(ref s) => Some(@cx.lifetime(span, cx.ident_of(*s))), None => None } } -pub impl Ty { - fn to_ty(&self, cx: @ext_ctxt, span: span, - self_ty: ident, self_generics: &Generics) -> @ast::Ty { +impl<'self> Ty<'self> { + pub fn to_ty(&self, + cx: @ExtCtxt, + span: span, + self_ty: ident, + self_generics: &Generics) + -> @ast::Ty { match *self { Ptr(ref ty, ref ptr) => { let raw_ty = ty.to_ty(cx, span, self_ty, self_generics); match *ptr { Owned => { - build::mk_ty_uniq(cx, span, raw_ty) + cx.ty_uniq(span, raw_ty) } Managed(mutbl) => { - build::mk_ty_box(cx, span, raw_ty, mutbl) + cx.ty_box(span, raw_ty, mutbl) } Borrowed(ref lt, mutbl) => { let lt = mk_lifetime(cx, span, lt); - build::mk_ty_rptr(cx, span, raw_ty, lt, mutbl) + cx.ty_rptr(span, raw_ty, lt, mutbl) } } } Literal(ref p) => { p.to_ty(cx, span, self_ty, self_generics) } Self => { - build::mk_ty_path_path(cx, span, self.to_path(cx, span, self_ty, self_generics)) + cx.ty_path(self.to_path(cx, span, self_ty, self_generics)) } Tuple(ref fields) => { let ty = if fields.is_empty() { @@ -143,17 +153,21 @@ pub impl Ty { ast::ty_tup(fields.map(|f| f.to_ty(cx, span, self_ty, self_generics))) }; - build::mk_ty(cx, span, ty) + cx.ty(span, ty) } } } - fn to_path(&self, cx: @ext_ctxt, span: span, - self_ty: ident, self_generics: &Generics) -> @ast::Path { + pub fn to_path(&self, + cx: @ExtCtxt, + span: span, + self_ty: ident, + self_generics: &Generics) + -> @ast::Path { match *self { Self => { let self_params = do self_generics.ty_params.map |ty_param| { - build::mk_ty_path(cx, span, ~[ ty_param.ident ]) + cx.ty_ident(span, ty_param.ident) }; let lifetime = if self_generics.lifetimes.is_empty() { None @@ -161,27 +175,27 @@ pub impl Ty { Some(@*self_generics.lifetimes.get(0)) }; - build::mk_raw_path_(span, ~[self_ty], lifetime, - opt_vec::take_vec(self_params)) + cx.path_all(span, false, ~[self_ty], lifetime, + opt_vec::take_vec(self_params)) } Literal(ref p) => { p.to_path(cx, span, self_ty, self_generics) } - Ptr(*) => { cx.span_bug(span, ~"Pointer in a path in generic `deriving`") } - Tuple(*) => { cx.span_bug(span, ~"Tuple in a path in generic `deriving`") } + Ptr(*) => { cx.span_bug(span, "Pointer in a path in generic `deriving`") } + Tuple(*) => { cx.span_bug(span, "Tuple in a path in generic `deriving`") } } } } -fn mk_ty_param(cx: @ext_ctxt, span: span, name: ~str, bounds: ~[Path], +fn mk_ty_param(cx: @ExtCtxt, span: span, name: &str, bounds: &[Path], self_ident: ident, self_generics: &Generics) -> ast::TyParam { let bounds = opt_vec::from( do bounds.map |b| { let path = b.to_path(cx, span, self_ident, self_generics); - build::mk_trait_ty_param_bound_(cx, path) + cx.typarambound(path) }); - build::mk_ty_param(cx, cx.ident_of(name), @bounds) + cx.typaram(cx.ident_of(name), @bounds) } fn mk_generics(lifetimes: ~[ast::Lifetime], ty_params: ~[ast::TyParam]) -> Generics { @@ -192,33 +206,41 @@ fn mk_generics(lifetimes: ~[ast::Lifetime], ty_params: ~[ast::TyParam]) -> Gene } /// Lifetimes and bounds on type parameters -pub struct LifetimeBounds { - lifetimes: ~[~str], - bounds: ~[(~str, ~[Path])] +pub struct LifetimeBounds<'self> { + lifetimes: ~[&'self str], + bounds: ~[(&'self str, ~[Path<'self>])] } -pub impl LifetimeBounds { - fn empty() -> LifetimeBounds { +impl<'self> LifetimeBounds<'self> { + pub fn empty() -> LifetimeBounds<'static> { LifetimeBounds { lifetimes: ~[], bounds: ~[] } } - fn to_generics(&self, cx: @ext_ctxt, span: span, - self_ty: ident, self_generics: &Generics) -> Generics { - let lifetimes = do self.lifetimes.map |<| { - build::mk_lifetime(cx, span, cx.ident_of(lt)) + pub fn to_generics(&self, + cx: @ExtCtxt, + span: span, + self_ty: ident, + self_generics: &Generics) + -> Generics { + let lifetimes = do self.lifetimes.map |lt| { + cx.lifetime(span, cx.ident_of(*lt)) }; - let ty_params = do self.bounds.map |&(name, bounds)| { - mk_ty_param(cx, span, name, bounds, self_ty, self_generics) + let ty_params = do self.bounds.map |t| { + match t { + &(ref name, ref bounds) => { + mk_ty_param(cx, span, *name, *bounds, self_ty, self_generics) + } + } }; mk_generics(lifetimes, ty_params) } } -pub fn get_explicit_self(cx: @ext_ctxt, span: span, self_ptr: &Option) +pub fn get_explicit_self(cx: @ExtCtxt, span: span, self_ptr: &Option) -> (@expr, ast::explicit_self) { - let self_path = build::make_self(cx, span); + let self_path = cx.expr_self(span); match *self_ptr { None => { (self_path, respan(span, ast::sty_value)) @@ -230,12 +252,12 @@ pub fn get_explicit_self(cx: @ext_ctxt, span: span, self_ptr: &Option) Owned => ast::sty_uniq(ast::m_imm), Managed(mutbl) => ast::sty_box(mutbl), Borrowed(ref lt, mutbl) => { - let lt = lt.map(|s| @build::mk_lifetime(cx, span, - cx.ident_of(*s))); + let lt = lt.map(|s| @cx.lifetime(span, + cx.ident_of(*s))); ast::sty_region(lt, mutbl) } }); - let self_expr = build::mk_deref(cx, span, self_path); + let self_expr = cx.expr_deref(span, self_path); (self_expr, self_ty) } } diff --git a/src/libsyntax/ext/env.rs b/src/libsyntax/ext/env.rs index 5b1e3737b236b..4d074b4d0e644 100644 --- a/src/libsyntax/ext/env.rs +++ b/src/libsyntax/ext/env.rs @@ -14,13 +14,17 @@ * interface. */ +use core::prelude::*; + use ast; use codemap::span; use ext::base::*; use ext::base; -use ext::build::mk_uniq_str; +use ext::build::AstBuilder; + +use core::os; -pub fn expand_syntax_ext(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree]) +pub fn expand_syntax_ext(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree]) -> base::MacResult { let var = get_single_str_from_tts(cx, sp, tts, "env!"); @@ -29,8 +33,8 @@ pub fn expand_syntax_ext(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree]) // Option rather than just an maybe-empty string. let e = match os::getenv(var) { - None => mk_uniq_str(cx, sp, ~""), - Some(ref s) => mk_uniq_str(cx, sp, copy *s) + None => cx.expr_str(sp, ~""), + Some(ref s) => cx.expr_str(sp, copy *s) }; MRExpr(e) } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index f9ca84473fb3c..96a0461de1eb2 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -8,10 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use ast::{blk_, attribute_, attr_outer, meta_word}; -use ast::{crate, expr_, expr_mac, mac_invoc_tt}; -use ast::{item_mac, stmt_, stmt_mac, stmt_expr, stmt_semi}; +use ast::{crate, decl_local, expr_, expr_mac, mac_invoc_tt}; +use ast::{item_mac, local_, stmt_, stmt_decl, stmt_mac, stmt_expr, stmt_semi}; +use ast::{SCTable, illegal_ctxt}; use ast; +use ast_util::{new_rename, new_mark, resolve, get_sctable}; use attr; use codemap; use codemap::{span, CallInfo, ExpandedFrom, NameAndSpan, spanned}; @@ -19,9 +23,14 @@ use ext::base::*; use fold::*; use parse; use parse::{parse_item_from_source_str}; +use parse::token::{ident_to_str, intern, fresh_name}; +use visit; +use visit::{Visitor,mk_vt}; + +use core::vec; pub fn expand_expr(extsbox: @mut SyntaxEnv, - cx: @ext_ctxt, + cx: @ExtCtxt, e: &expr_, s: span, fld: @ast_fold, @@ -40,15 +49,14 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv, fmt!("expected macro name without module \ separators")); } - /* using idents and token::special_idents would make the - the macro names be hygienic */ - let extname = cx.parse_sess().interner.get(pth.idents[0]); + let extname = &pth.idents[0]; + let extnamestr = ident_to_str(extname); // leaving explicit deref here to highlight unbox op: - match (*extsbox).find(&extname) { + match (*extsbox).find(&extname.name) { None => { cx.span_fatal( pth.span, - fmt!("macro undefined: '%s'", *extname)) + fmt!("macro undefined: '%s'", *extnamestr)) } Some(@SE(NormalTT(SyntaxExpanderTT{ expander: exp, @@ -57,7 +65,7 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv, cx.bt_push(ExpandedFrom(CallInfo { call_site: s, callee: NameAndSpan { - name: copy *extname, + name: copy *extnamestr, span: exp_sp, }, })); @@ -70,7 +78,7 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv, pth.span, fmt!( "non-expr macro in expr pos: %s", - *extname + *extnamestr ) ) } @@ -86,7 +94,7 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv, _ => { cx.span_fatal( pth.span, - fmt!("'%s' is not a tt-style macro", *extname) + fmt!("'%s' is not a tt-style macro", *extnamestr) ) } } @@ -107,7 +115,7 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv, // NB: there is some redundancy between this and expand_item, below, and // they might benefit from some amount of semantic and language-UI merger. pub fn expand_mod_items(extsbox: @mut SyntaxEnv, - cx: @ext_ctxt, + cx: @ExtCtxt, module_: &ast::_mod, fld: @ast_fold, orig: @fn(&ast::_mod, @ast_fold) -> ast::_mod) @@ -123,7 +131,7 @@ pub fn expand_mod_items(extsbox: @mut SyntaxEnv, do vec::foldr(item.attrs, ~[*item]) |attr, items| { let mname = attr::get_attr_name(attr); - match (*extsbox).find(&mname) { + match (*extsbox).find(&intern(*mname)) { Some(@SE(ItemDecorator(dec_fn))) => { cx.bt_push(ExpandedFrom(CallInfo { call_site: attr.span, @@ -147,19 +155,23 @@ pub fn expand_mod_items(extsbox: @mut SyntaxEnv, // eval $e with a new exts frame: macro_rules! with_exts_frame ( - ($extsboxexpr:expr,$e:expr) => + ($extsboxexpr:expr,$macros_escape:expr,$e:expr) => ({let extsbox = $extsboxexpr; let oldexts = *extsbox; *extsbox = oldexts.push_frame(); + extsbox.insert(intern(special_block_name), + @BlockInfo(BlockInfo{macros_escape:$macros_escape,pending_renames:@mut ~[]})); let result = $e; *extsbox = oldexts; result }) ) +static special_block_name : &'static str = " block"; + // When we enter a module, record it, for the sake of `module!` pub fn expand_item(extsbox: @mut SyntaxEnv, - cx: @ext_ctxt, + cx: @ExtCtxt, it: @ast::item, fld: @ast_fold, orig: @fn(@ast::item, @ast_fold) -> Option<@ast::item>) @@ -174,14 +186,8 @@ pub fn expand_item(extsbox: @mut SyntaxEnv, match it.node { ast::item_mod(_) | ast::item_foreign_mod(_) => { cx.mod_push(it.ident); - let result = - // don't push a macro scope for macro_escape: - if contains_macro_escape(it.attrs) { - orig(it,fld) - } else { - // otherwise, push a scope: - with_exts_frame!(extsbox,orig(it,fld)) - }; + let macro_escape = contains_macro_escape(it.attrs); + let result = with_exts_frame!(extsbox,macro_escape,orig(it,fld)); cx.mod_pop(); result } @@ -197,60 +203,36 @@ pub fn contains_macro_escape (attrs: &[ast::attribute]) -> bool { attrs.any(|attr| "macro_escape" == *attr::get_attr_name(attr)) } -// this macro disables (one layer of) macro -// scoping, to allow a block to add macro bindings -// to its parent env -macro_rules! without_macro_scoping( - ($extsexpr:expr,$exp:expr) => - ({ - // only evaluate this once: - let exts = $extsexpr; - // capture the existing binding: - let existingBlockBinding = - match exts.find(&@~" block"){ - Some(binding) => binding, - None => cx.bug("expected to find \" block\" binding") - }; - // this prevents the block from limiting the macros' scope: - exts.insert(@~" block",@ScopeMacros(false)); - let result = $exp; - // reset the block binding. Note that since the original - // one may have been inherited, this procedure may wind - // up introducing a block binding where one didn't exist - // before. - exts.insert(@~" block",existingBlockBinding); - result - })) - // Support for item-position macro invocations, exactly the same // logic as for expression-position macro invocations. pub fn expand_item_mac(extsbox: @mut SyntaxEnv, - cx: @ext_ctxt, it: @ast::item, + cx: @ExtCtxt, it: @ast::item, fld: @ast_fold) -> Option<@ast::item> { let (pth, tts) = match it.node { item_mac(codemap::spanned { node: mac_invoc_tt(pth, ref tts), _}) => { (pth, copy *tts) } - _ => cx.span_bug(it.span, ~"invalid item macro invocation") + _ => cx.span_bug(it.span, "invalid item macro invocation") }; - let extname = cx.parse_sess().interner.get(pth.idents[0]); - let expanded = match (*extsbox).find(&extname) { + let extname = &pth.idents[0]; + let extnamestr = ident_to_str(extname); + let expanded = match (*extsbox).find(&extname.name) { None => cx.span_fatal(pth.span, - fmt!("macro undefined: '%s!'", *extname)), + fmt!("macro undefined: '%s!'", *extnamestr)), Some(@SE(NormalTT(ref expand))) => { if it.ident != parse::token::special_idents::invalid { cx.span_fatal(pth.span, fmt!("macro %s! expects no ident argument, \ - given '%s'", *extname, - *cx.parse_sess().interner.get(it.ident))); + given '%s'", *extnamestr, + *ident_to_str(&it.ident))); } cx.bt_push(ExpandedFrom(CallInfo { call_site: it.span, callee: NameAndSpan { - name: copy *extname, + name: copy *extnamestr, span: expand.span } })); @@ -260,29 +242,29 @@ pub fn expand_item_mac(extsbox: @mut SyntaxEnv, if it.ident == parse::token::special_idents::invalid { cx.span_fatal(pth.span, fmt!("macro %s! expects an ident argument", - *extname)); + *extnamestr)); } cx.bt_push(ExpandedFrom(CallInfo { call_site: it.span, callee: NameAndSpan { - name: copy *extname, + name: copy *extnamestr, span: expand.span } })); ((*expand).expander)(cx, it.span, it.ident, tts) } _ => cx.span_fatal( - it.span, fmt!("%s! is not legal in item position", *extname)) + it.span, fmt!("%s! is not legal in item position", *extnamestr)) }; let maybe_it = match expanded { MRItem(it) => fld.fold_item(it), MRExpr(_) => cx.span_fatal(pth.span, ~"expr macro in item position: " - + *extname), + + *extnamestr), MRAny(_, item_maker, _) => item_maker().chain(|i| {fld.fold_item(i)}), MRDef(ref mdef) => { - extsbox.insert(@/*bad*/ copy mdef.name, @SE((*mdef).ext)); + insert_macro(*extsbox,intern(mdef.name), @SE((*mdef).ext)); None } }; @@ -290,14 +272,32 @@ pub fn expand_item_mac(extsbox: @mut SyntaxEnv, return maybe_it; } + +// insert a macro into the innermost frame that doesn't have the +// macro_escape tag. +fn insert_macro(exts: SyntaxEnv, name: ast::Name, transformer: @Transformer) { + let is_non_escaping_block = + |t : &@Transformer| -> bool{ + match t { + &@BlockInfo(BlockInfo {macros_escape:false,_}) => true, + &@BlockInfo(BlockInfo {_}) => false, + _ => fail!(fmt!("special identifier %? was bound to a non-BlockInfo", + special_block_name)) + } + }; + exts.insert_into_frame(name,transformer,intern(special_block_name), + is_non_escaping_block) +} + // expand a stmt pub fn expand_stmt(extsbox: @mut SyntaxEnv, - cx: @ext_ctxt, + cx: @ExtCtxt, s: &stmt_, sp: span, fld: @ast_fold, - orig: @fn(&stmt_, span, @ast_fold) -> (stmt_, span)) - -> (stmt_, span) { + orig: @fn(&stmt_, span, @ast_fold) + -> (Option, span)) + -> (Option, span) { let (mac, pth, tts, semi) = match *s { stmt_mac(ref mac, semi) => { match mac.node { @@ -314,16 +314,17 @@ pub fn expand_stmt(extsbox: @mut SyntaxEnv, fmt!("expected macro name without module \ separators")); } - let extname = cx.parse_sess().interner.get(pth.idents[0]); - let (fully_expanded, sp) = match (*extsbox).find(&extname) { + let extname = &pth.idents[0]; + let extnamestr = ident_to_str(extname); + let (fully_expanded, sp) = match (*extsbox).find(&extname.name) { None => - cx.span_fatal(pth.span, fmt!("macro undefined: '%s'", *extname)), + cx.span_fatal(pth.span, fmt!("macro undefined: '%s'", *extnamestr)), Some(@SE(NormalTT( SyntaxExpanderTT{expander: exp, span: exp_sp}))) => { cx.bt_push(ExpandedFrom(CallInfo { call_site: sp, - callee: NameAndSpan { name: copy *extname, span: exp_sp } + callee: NameAndSpan { name: copy *extnamestr, span: exp_sp } })); let expanded = match exp(cx, mac.span, tts) { MRExpr(e) => @@ -332,55 +333,117 @@ pub fn expand_stmt(extsbox: @mut SyntaxEnv, MRAny(_,_,stmt_mkr) => stmt_mkr(), _ => cx.span_fatal( pth.span, - fmt!("non-stmt macro in stmt pos: %s", *extname)) + fmt!("non-stmt macro in stmt pos: %s", *extnamestr)) }; //keep going, outside-in - let fully_expanded = copy fld.fold_stmt(expanded).node; - cx.bt_pop(); + let fully_expanded = match fld.fold_stmt(expanded) { + Some(stmt) => { + let fully_expanded = &stmt.node; + cx.bt_pop(); + copy *fully_expanded + } + None => { + cx.span_fatal(pth.span, + "macro didn't expand to a statement") + } + }; (fully_expanded, sp) } _ => { cx.span_fatal(pth.span, - fmt!("'%s' is not a tt-style macro", *extname)) + fmt!("'%s' is not a tt-style macro", *extnamestr)) } }; (match fully_expanded { - stmt_expr(e, stmt_id) if semi => stmt_semi(e, stmt_id), - _ => { fully_expanded } /* might already have a semi */ + stmt_expr(e, stmt_id) if semi => Some(stmt_semi(e, stmt_id)), + _ => { Some(fully_expanded) } /* might already have a semi */ }, sp) } - +// return a visitor that extracts the pat_ident paths +// from a given pattern and puts them in a mutable +// array (passed in to the traversal) +pub fn new_name_finder() -> @Visitor<@mut ~[ast::ident]> { + let default_visitor = visit::default_visitor(); + @Visitor{ + visit_pat : |p:@ast::pat,ident_accum:@mut ~[ast::ident],v:visit::vt<@mut ~[ast::ident]>| { + match *p { + // we found a pat_ident! + ast::pat{id:_, node: ast::pat_ident(_,path,ref inner), span:_} => { + match path { + // a path of length one: + @ast::Path{global: false,idents: [id], span:_,rp:_,types:_} => + ident_accum.push(id), + // I believe these must be enums... + _ => () + } + // visit optional subpattern of pat_ident: + for inner.each |subpat: &@ast::pat| { (v.visit_pat)(*subpat, ident_accum, v) } + } + // use the default traversal for non-pat_idents + _ => visit::visit_pat(p,ident_accum,v) + } + }, + .. *default_visitor + } +} pub fn expand_block(extsbox: @mut SyntaxEnv, - cx: @ext_ctxt, + cx: @ExtCtxt, blk: &blk_, sp: span, fld: @ast_fold, orig: @fn(&blk_, span, @ast_fold) -> (blk_, span)) -> (blk_, span) { - match (*extsbox).find(&@~" block") { - // no scope limit on macros in this block, no need - // to push an exts frame: - Some(@ScopeMacros(false)) => { - orig (blk,sp,fld) - }, - // this block should limit the scope of its macros: - Some(@ScopeMacros(true)) => { - // see note below about treatment of exts table - with_exts_frame!(extsbox,orig(blk,sp,fld)) + // see note below about treatment of exts table + with_exts_frame!(extsbox,false,orig(blk,sp,fld)) +} + + +// get the (innermost) BlockInfo from an exts stack +fn get_block_info(exts : SyntaxEnv) -> BlockInfo { + match exts.find_in_topmost_frame(&intern(special_block_name)) { + Some(@BlockInfo(bi)) => bi, + _ => fail!(fmt!("special identifier %? was bound to a non-BlockInfo", + @~" block")) + } +} + + +// given a mutable list of renames, return a tree-folder that applies those +// renames. +fn renames_to_fold(renames : @mut ~[(ast::ident,ast::Name)]) -> @ast_fold { + let afp = default_ast_fold(); + let f_pre = @AstFoldFns { + fold_ident: |id,_| { + // the individual elements are memoized... it would + // also be possible to memoize on the whole list at once. + let new_ctxt = renames.foldl(id.ctxt,|ctxt,&(from,to)| { + new_rename(from,to,*ctxt) + }); + ast::ident{name:id.name,ctxt:new_ctxt} }, - _ => cx.span_bug(sp, - ~"expected ScopeMacros binding for \" block\"") + .. *afp + }; + make_fold(f_pre) +} + +// perform a bunch of renames +fn apply_pending_renames(folder : @ast_fold, stmt : ast::stmt) -> @ast::stmt { + match folder.fold_stmt(&stmt) { + Some(s) => s, + None => fail!(fmt!("renaming of stmt produced None")) } } -pub fn new_span(cx: @ext_ctxt, sp: span) -> span { + + +pub fn new_span(cx: @ExtCtxt, sp: span) -> span { /* this discards information in the case of macro-defining macros */ return span {lo: sp.lo, hi: sp.hi, expn_info: cx.backtrace()}; } @@ -435,28 +498,28 @@ pub fn core_macros() -> ~str { fail!(\"explicit failure\") ); ($msg:expr) => ( - ::core::sys::FailWithCause::fail_with($msg, file!(), line!()) + ::std::sys::FailWithCause::fail_with($msg, file!(), line!()) ); ($( $arg:expr ),+) => ( - ::core::sys::FailWithCause::fail_with(fmt!( $($arg),+ ), file!(), line!()) + ::std::sys::FailWithCause::fail_with(fmt!( $($arg),+ ), file!(), line!()) ) ) macro_rules! assert( ($cond:expr) => { if !$cond { - ::core::sys::FailWithCause::fail_with( + ::std::sys::FailWithCause::fail_with( ~\"assertion failed: \" + stringify!($cond), file!(), line!()) } }; ($cond:expr, $msg:expr) => { if !$cond { - ::core::sys::FailWithCause::fail_with($msg, file!(), line!()) + ::std::sys::FailWithCause::fail_with($msg, file!(), line!()) } }; ($cond:expr, $( $arg:expr ),+) => { if !$cond { - ::core::sys::FailWithCause::fail_with(fmt!( $($arg),+ ), file!(), line!()) + ::std::sys::FailWithCause::fail_with(fmt!( $($arg),+ ), file!(), line!()) } } ) @@ -477,7 +540,7 @@ pub fn core_macros() -> ~str { macro_rules! assert_approx_eq ( ($given:expr , $expected:expr) => ( { - use core::cmp::ApproxEq; + use std::cmp::ApproxEq; let given_val = $given; let expected_val = $expected; @@ -493,7 +556,7 @@ pub fn core_macros() -> ~str { ); ($given:expr , $expected:expr , $epsilon:expr) => ( { - use core::cmp::ApproxEq; + use std::cmp::ApproxEq; let given_val = $given; let expected_val = $expected; @@ -515,11 +578,11 @@ pub fn core_macros() -> ~str { { pub $c:ident: $in:ty -> $out:ty; } => { pub mod $c { - fn key(_x: @::core::condition::Handler<$in,$out>) { } + fn key(_x: @::std::condition::Handler<$in,$out>) { } pub static cond : - ::core::condition::Condition<'static,$in,$out> = - ::core::condition::Condition { + ::std::condition::Condition<'static,$in,$out> = + ::std::condition::Condition { name: stringify!($c), key: key }; @@ -530,11 +593,11 @@ pub fn core_macros() -> ~str { // FIXME (#6009): remove mod's `pub` below once variant above lands. pub mod $c { - fn key(_x: @::core::condition::Handler<$in,$out>) { } + fn key(_x: @::std::condition::Handler<$in,$out>) { } pub static cond : - ::core::condition::Condition<'static,$in,$out> = - ::core::condition::Condition { + ::std::condition::Condition<'static,$in,$out> = + ::std::condition::Condition { name: stringify!($c), key: key }; @@ -589,7 +652,7 @@ pub fn expand_crate(parse_sess: @mut parse::ParseSess, // every method/element of AstFoldFns in fold.rs. let extsbox = @mut syntax_expander_table(); let afp = default_ast_fold(); - let cx: @ext_ctxt = mk_ctxt(parse_sess, copy cfg); + let cx = ExtCtxt::new(parse_sess, copy cfg); let f_pre = @AstFoldFns { fold_expr: |expr,span,recur| expand_expr(extsbox, cx, expr, span, recur, afp.fold_expr), @@ -626,7 +689,7 @@ pub fn expand_crate(parse_sess: @mut parse::ParseSess, attrs, parse_sess) { Some(item) => item, - None => cx.bug(~"expected core macros to parse correctly") + None => cx.bug("expected core macros to parse correctly") }; // This is run for its side-effects on the expander env, // as it registers all the core macros as expanders. @@ -635,61 +698,66 @@ pub fn expand_crate(parse_sess: @mut parse::ParseSess, @f.fold_crate(&*c) } -// given a function from paths to paths, produce +// given a function from idents to idents, produce // an ast_fold that applies that function: -fn fun_to_path_folder(f: @fn(&ast::Path)->ast::Path) -> @ast_fold{ +pub fn fun_to_ident_folder(f: @fn(ast::ident)->ast::ident) -> @ast_fold{ let afp = default_ast_fold(); let f_pre = @AstFoldFns{ - fold_path : |p, _| f(p), + fold_ident : |id, _| f(id), .. *afp }; make_fold(f_pre) } -/* going to have to figure out whether the table is passed in or -extracted from TLS... + // update the ctxts in a path to get a rename node -fn ctxt_update_rename(from: ast::Name, - fromctx: ast::SyntaxContext, to: ast::Name) -> - @fn(&ast::Path,@ast_fold)->ast::Path { - return |p:&ast::Path,_| - ast::Path {span: p.span, - global: p.global, - idents: p.idents.map(|id| - ast::ident{ - repr: id.repr, - // this needs to be cached.... - ctxt: Some(@ast::Rename(from,fromctx, - to,id.ctxt)) - }), - rp: p.rp, - types: p.types}; +pub fn new_ident_renamer(from: ast::ident, + to: ast::Name) -> + @fn(ast::ident)->ast::ident { + |id : ast::ident| + ast::ident{ + name: id.name, + ctxt: new_rename(from,to,id.ctxt) + } } + // update the ctxts in a path to get a mark node -fn ctxt_update_mark(mark: uint) -> - @fn(&ast::Path,@ast_fold)->ast::Path { - return |p:&ast::Path,_| - ast::Path {span: p.span, - global: p.global, - idents: p.idents.map(|id| - ast::ident{ - repr: id.repr, - // this needs to be cached.... - ctxt: Some(@ast::Mark(mark,id.ctxt)) - }), - rp: p.rp, - types: p.types}; +pub fn new_ident_marker(mark: uint) -> + @fn(ast::ident)->ast::ident { + |id : ast::ident| + ast::ident{ + name: id.name, + ctxt: new_mark(mark,id.ctxt) + } +} + +// perform resolution (in the MTWT sense) on all of the +// idents in the tree. This is the final step in expansion. +pub fn new_ident_resolver() -> + @fn(ast::ident)->ast::ident { + |id : ast::ident| + ast::ident { + name : resolve(id), + ctxt : illegal_ctxt + } } -*/ + #[cfg(test)] mod test { use super::*; use ast; - use ast::{attribute_, attr_outer, meta_word}; + use ast::{attribute_, attr_outer, meta_word, empty_ctxt}; + use ast_util::{get_sctable}; use codemap; use codemap::spanned; use parse; + use parse::token::{gensym, intern, get_ident_interner}; + use print::pprust; + use util::parser_testing::{string_to_item, string_to_pat, strs_to_idents}; + use visit::{mk_vt,Visitor}; + + use core::io; use core::option::{None, Some}; // make sure that fail! is present @@ -792,4 +860,35 @@ mod test { } } + #[test] + fn renaming () { + let maybe_item_ast = string_to_item(@~"fn a() -> int { let b = 13; b }"); + let item_ast = match maybe_item_ast { + Some(x) => x, + None => fail!("test case fail") + }; + let a_name = intern("a"); + let a2_name = intern("a2"); + let renamer = new_ident_renamer(ast::ident{name:a_name,ctxt:empty_ctxt}, + a2_name); + let renamed_ast = fun_to_ident_folder(renamer).fold_item(item_ast).get(); + let resolver = new_ident_resolver(); + let resolved_ast = fun_to_ident_folder(resolver).fold_item(renamed_ast).get(); + let resolved_as_str = pprust::item_to_str(resolved_ast, + get_ident_interner()); + assert_eq!(resolved_as_str,~"fn a2() -> int { let b = 13; b }"); + + + } + + // sigh... it looks like I have two different renaming mechanisms, now... + + #[test] + fn pat_idents(){ + let pat = string_to_pat(@~"(a,Foo{x:c @ (b,9),y:Bar(4,d)})"); + let pat_idents = new_name_finder(); + let idents = @mut ~[]; + ((*pat_idents).visit_pat)(pat,idents, mk_vt(pat_idents)); + assert_eq!(idents,@mut strs_to_idents(~["a","c","b","d"])); + } } diff --git a/src/libsyntax/ext/fmt.rs b/src/libsyntax/ext/fmt.rs index 26b3178a91110..67d3f84d1ff3e 100644 --- a/src/libsyntax/ext/fmt.rs +++ b/src/libsyntax/ext/fmt.rs @@ -14,16 +14,20 @@ * compiler syntax extension plugin interface. */ +use core::prelude::*; + use ast; use codemap::span; use ext::base::*; use ext::base; -use ext::build; -use ext::build::*; +use ext::build::AstBuilder; +use core::option; use core::unstable::extfmt::ct::*; +use core::vec; +use parse::token::{str_to_ident}; -pub fn expand_syntax_ext(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree]) +pub fn expand_syntax_ext(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree]) -> base::MacResult { let args = get_exprs_from_tts(cx, tts); if args.len() == 0 { @@ -34,7 +38,7 @@ pub fn expand_syntax_ext(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree]) ~"first argument to fmt! must be a string literal."); let fmtspan = args[0].span; debug!("Format string: %s", fmt); - fn parse_fmt_err_(cx: @ext_ctxt, sp: span, msg: &str) -> ! { + fn parse_fmt_err_(cx: @ExtCtxt, sp: span, msg: &str) -> ! { cx.span_fatal(sp, msg); } let parse_fmt_err: @fn(&str) -> ! = |s| parse_fmt_err_(cx, fmtspan, s); @@ -46,23 +50,25 @@ pub fn expand_syntax_ext(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree]) // probably be factored out in common with other code that builds // expressions. Also: Cleanup the naming of these functions. // Note: Moved many of the common ones to build.rs --kevina -fn pieces_to_expr(cx: @ext_ctxt, sp: span, +fn pieces_to_expr(cx: @ExtCtxt, sp: span, pieces: ~[Piece], args: ~[@ast::expr]) -> @ast::expr { - fn make_path_vec(cx: @ext_ctxt, ident: &str) -> ~[ast::ident] { - let intr = cx.parse_sess().interner; - return ~[intr.intern("unstable"), intr.intern("extfmt"), - intr.intern("rt"), intr.intern(ident)]; + fn make_path_vec(cx: @ExtCtxt, ident: &str) -> ~[ast::ident] { + return ~[str_to_ident("std"), + str_to_ident("unstable"), + str_to_ident("extfmt"), + str_to_ident("rt"), + str_to_ident(ident)]; } - fn make_rt_path_expr(cx: @ext_ctxt, sp: span, nm: &str) -> @ast::expr { + fn make_rt_path_expr(cx: @ExtCtxt, sp: span, nm: &str) -> @ast::expr { let path = make_path_vec(cx, nm); - return mk_path_global(cx, sp, path); + cx.expr_path(cx.path_global(sp, path)) } // Produces an AST expression that represents a RT::conv record, // which tells the RT::conv* functions how to perform the conversion - fn make_rt_conv_expr(cx: @ext_ctxt, sp: span, cnv: &Conv) -> @ast::expr { - fn make_flags(cx: @ext_ctxt, sp: span, flags: &[Flag]) -> @ast::expr { + fn make_rt_conv_expr(cx: @ExtCtxt, sp: span, cnv: &Conv) -> @ast::expr { + fn make_flags(cx: @ExtCtxt, sp: span, flags: &[Flag]) -> @ast::expr { let mut tmp_expr = make_rt_path_expr(cx, sp, "flag_none"); for flags.each |f| { let fstr = match *f { @@ -72,26 +78,26 @@ fn pieces_to_expr(cx: @ext_ctxt, sp: span, FlagSignAlways => "flag_sign_always", FlagAlternate => "flag_alternate" }; - tmp_expr = mk_binary(cx, sp, ast::bitor, tmp_expr, - make_rt_path_expr(cx, sp, fstr)); + tmp_expr = cx.expr_binary(sp, ast::bitor, tmp_expr, + make_rt_path_expr(cx, sp, fstr)); } return tmp_expr; } - fn make_count(cx: @ext_ctxt, sp: span, cnt: Count) -> @ast::expr { + fn make_count(cx: @ExtCtxt, sp: span, cnt: Count) -> @ast::expr { match cnt { CountImplied => { return make_rt_path_expr(cx, sp, "CountImplied"); } CountIs(c) => { - let count_lit = mk_uint(cx, sp, c as uint); + let count_lit = cx.expr_uint(sp, c as uint); let count_is_path = make_path_vec(cx, "CountIs"); let count_is_args = ~[count_lit]; - return mk_call_global(cx, sp, count_is_path, count_is_args); + return cx.expr_call_global(sp, count_is_path, count_is_args); } - _ => cx.span_unimpl(sp, ~"unimplemented fmt! conversion") + _ => cx.span_unimpl(sp, "unimplemented fmt! conversion") } } - fn make_ty(cx: @ext_ctxt, sp: span, t: Ty) -> @ast::expr { + fn make_ty(cx: @ExtCtxt, sp: span, t: Ty) -> @ast::expr { let rt_type = match t { TyHex(c) => match c { CaseUpper => "TyHexUpper", @@ -103,27 +109,17 @@ fn pieces_to_expr(cx: @ext_ctxt, sp: span, }; return make_rt_path_expr(cx, sp, rt_type); } - fn make_conv_struct(cx: @ext_ctxt, sp: span, flags_expr: @ast::expr, + fn make_conv_struct(cx: @ExtCtxt, sp: span, flags_expr: @ast::expr, width_expr: @ast::expr, precision_expr: @ast::expr, ty_expr: @ast::expr) -> @ast::expr { - let intr = cx.parse_sess().interner; - mk_global_struct_e( - cx, + cx.expr_struct( sp, - make_path_vec(cx, "Conv"), + cx.path_global(sp, make_path_vec(cx, "Conv")), ~[ - build::Field { - ident: intr.intern("flags"), ex: flags_expr - }, - build::Field { - ident: intr.intern("width"), ex: width_expr - }, - build::Field { - ident: intr.intern("precision"), ex: precision_expr - }, - build::Field { - ident: intr.intern("ty"), ex: ty_expr - }, + cx.field_imm(sp, str_to_ident("flags"), flags_expr), + cx.field_imm(sp, str_to_ident("width"), width_expr), + cx.field_imm(sp, str_to_ident("precision"), precision_expr), + cx.field_imm(sp, str_to_ident("ty"), ty_expr) ] ) } @@ -134,16 +130,16 @@ fn pieces_to_expr(cx: @ext_ctxt, sp: span, make_conv_struct(cx, sp, rt_conv_flags, rt_conv_width, rt_conv_precision, rt_conv_ty) } - fn make_conv_call(cx: @ext_ctxt, sp: span, conv_type: &str, cnv: &Conv, + fn make_conv_call(cx: @ExtCtxt, sp: span, conv_type: &str, cnv: &Conv, arg: @ast::expr, buf: @ast::expr) -> @ast::expr { let fname = ~"conv_" + conv_type; let path = make_path_vec(cx, fname); let cnv_expr = make_rt_conv_expr(cx, sp, cnv); let args = ~[cnv_expr, arg, buf]; - return mk_call_global(cx, arg.span, path, args); + cx.expr_call_global(arg.span, path, args) } - fn make_new_conv(cx: @ext_ctxt, sp: span, cnv: &Conv, + fn make_new_conv(cx: @ExtCtxt, sp: span, cnv: &Conv, arg: @ast::expr, buf: @ast::expr) -> @ast::expr { fn is_signed_type(cnv: &Conv) -> bool { match cnv.ty { @@ -166,15 +162,15 @@ fn pieces_to_expr(cx: @ext_ctxt, sp: span, FlagSignAlways => { if !is_signed_type(cnv) { cx.span_fatal(sp, - ~"+ flag only valid in " + - ~"signed fmt! conversion"); + "+ flag only valid in \ + signed fmt! conversion"); } } FlagSpaceForSign => { if !is_signed_type(cnv) { cx.span_fatal(sp, - ~"space flag only valid in " + - ~"signed fmt! conversions"); + "space flag only valid in \ + signed fmt! conversions"); } } FlagLeftZeroPad => (), @@ -198,10 +194,10 @@ fn pieces_to_expr(cx: @ext_ctxt, sp: span, TyChar => ("char", arg), TyBits | TyOctal | TyHex(_) | TyInt(Unsigned) => ("uint", arg), TyFloat => ("float", arg), - TyPoly => ("poly", mk_addr_of(cx, sp, arg)) + TyPoly => ("poly", cx.expr_addr_of(sp, arg)) }; return make_conv_call(cx, arg.span, name, cnv, actual_arg, - mk_mut_addr_of(cx, arg.span, buf)); + cx.expr_mut_addr_of(arg.span, buf)); } fn log_conv(c: &Conv) { debug!("Building conversion:"); @@ -258,10 +254,11 @@ fn pieces_to_expr(cx: @ext_ctxt, sp: span, let nargs = args.len(); /* 'ident' is the local buffer building up the result of fmt! */ - let ident = cx.parse_sess().interner.intern("__fmtbuf"); - let buf = || mk_path(cx, fmt_sp, ~[ident]); - let str_ident = cx.parse_sess().interner.intern("str"); - let push_ident = cx.parse_sess().interner.intern("push_str"); + let ident = str_to_ident("__fmtbuf"); + let buf = || cx.expr_ident(fmt_sp, ident); + let core_ident = str_to_ident("std"); + let str_ident = str_to_ident("str"); + let push_ident = str_to_ident("push_str"); let mut stms = ~[]; /* Translate each piece (portion of the fmt expression) by invoking the @@ -276,14 +273,16 @@ fn pieces_to_expr(cx: @ext_ctxt, sp: span, buffer with it directly. If it's actually the only piece, then there's no need for it to be mutable */ if i == 0 { - stms.push(mk_local(cx, fmt_sp, npieces > 1, ident, mk_uniq_str(cx, fmt_sp, s))); + stms.push(cx.stmt_let(fmt_sp, npieces > 1, + ident, cx.expr_str_uniq(fmt_sp, s))); } else { - let args = ~[mk_mut_addr_of(cx, fmt_sp, buf()), mk_base_str(cx, fmt_sp, s)]; - let call = mk_call_global(cx, - fmt_sp, - ~[str_ident, push_ident], - args); - stms.push(mk_stmt(cx, fmt_sp, call)); + let args = ~[cx.expr_mut_addr_of(fmt_sp, buf()), cx.expr_str(fmt_sp, s)]; + let call = cx.expr_call_global(fmt_sp, + ~[core_ident, + str_ident, + push_ident], + args); + stms.push(cx.stmt_expr(call)); } } @@ -292,20 +291,19 @@ fn pieces_to_expr(cx: @ext_ctxt, sp: span, n += 1u; if n >= nargs { cx.span_fatal(sp, - ~"not enough arguments to fmt! " + - ~"for the given format string"); + "not enough arguments to fmt! \ + for the given format string"); } log_conv(conv); /* If the first portion is a conversion, then the local buffer must be initialized as an empty string */ if i == 0 { - stms.push(mk_local(cx, fmt_sp, true, ident, - mk_uniq_str(cx, fmt_sp, ~""))); + stms.push(cx.stmt_let(fmt_sp, true, ident, + cx.expr_str_uniq(fmt_sp, ~""))); } - stms.push(mk_stmt(cx, fmt_sp, - make_new_conv(cx, fmt_sp, conv, - args[n], buf()))); + stms.push(cx.stmt_expr(make_new_conv(cx, fmt_sp, conv, + args[n], buf()))); } } } @@ -317,5 +315,5 @@ fn pieces_to_expr(cx: @ext_ctxt, sp: span, nargs, expected_nargs)); } - return mk_block(cx, fmt_sp, ~[], stms, Some(buf())); + cx.expr_blk(cx.blk(fmt_sp, stms, Some(buf()))) } diff --git a/src/libsyntax/ext/log_syntax.rs b/src/libsyntax/ext/log_syntax.rs index 76d9a9420ce50..3ad4f87083f3d 100644 --- a/src/libsyntax/ext/log_syntax.rs +++ b/src/libsyntax/ext/log_syntax.rs @@ -8,13 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use ast; use codemap; use ext::base::*; use ext::base; use print; +use parse::token::{get_ident_interner}; + +use core::io; +use core::vec; -pub fn expand_syntax_ext(cx: @ext_ctxt, +pub fn expand_syntax_ext(cx: @ExtCtxt, sp: codemap::span, tt: &[ast::token_tree]) -> base::MacResult { @@ -23,12 +29,11 @@ pub fn expand_syntax_ext(cx: @ext_ctxt, io::stdout().write_line( print::pprust::tt_to_str( ast::tt_delim(vec::to_owned(tt)), - cx.parse_sess().interner)); + get_ident_interner())); //trivial expression MRExpr(@ast::expr { id: cx.next_id(), - callee_id: cx.next_id(), node: ast::expr_lit(@codemap::spanned { node: ast::lit_nil, span: sp diff --git a/src/libsyntax/ext/pipes/ast_builder.rs b/src/libsyntax/ext/pipes/ast_builder.rs index a514828725866..08f1540918e68 100644 --- a/src/libsyntax/ext/pipes/ast_builder.rs +++ b/src/libsyntax/ext/pipes/ast_builder.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -13,16 +13,13 @@ // To start with, it will be use dummy spans, but it might someday do // something smarter. -use abi::AbiSet; +use core::prelude::*; + use ast::ident; use ast; -use ast_util; -use codemap::{span, respan, dummy_sp, spanned}; -use codemap; -use ext::base::ext_ctxt; -use ext::quote::rt::*; -use opt_vec; -use opt_vec::OptVec; +use codemap::span; + +use core::vec; // Transitional reexports so qquote can find the paths it is looking for mod syntax { @@ -67,376 +64,3 @@ impl append_types for @ast::Path { } } -pub trait ext_ctxt_ast_builder { - fn ty_param(&self, id: ast::ident, bounds: @OptVec) - -> ast::TyParam; - fn arg(&self, name: ident, ty: @ast::Ty) -> ast::arg; - fn expr_block(&self, e: @ast::expr) -> ast::blk; - fn fn_decl(&self, inputs: ~[ast::arg], output: @ast::Ty) -> ast::fn_decl; - fn item(&self, name: ident, span: span, node: ast::item_) -> @ast::item; - fn item_fn_poly(&self, - ame: ident, - inputs: ~[ast::arg], - output: @ast::Ty, - generics: Generics, - body: ast::blk) -> @ast::item; - fn item_fn(&self, - name: ident, - inputs: ~[ast::arg], - output: @ast::Ty, - body: ast::blk) -> @ast::item; - fn item_enum_poly(&self, - name: ident, - span: span, - enum_definition: ast::enum_def, - generics: Generics) -> @ast::item; - fn item_enum(&self, - name: ident, - span: span, - enum_definition: ast::enum_def) -> @ast::item; - fn item_struct_poly(&self, - name: ident, - span: span, - struct_def: ast::struct_def, - generics: Generics) -> @ast::item; - fn item_struct(&self, - name: ident, - span: span, - struct_def: ast::struct_def) -> @ast::item; - fn struct_expr(&self, - path: @ast::Path, - fields: ~[ast::field]) -> @ast::expr; - fn variant(&self, - name: ident, - span: span, - tys: ~[@ast::Ty]) -> ast::variant; - fn item_mod(&self, - name: ident, - span: span, - items: ~[@ast::item]) -> @ast::item; - fn ty_path_ast_builder(&self, path: @ast::Path) -> @ast::Ty; - fn item_ty_poly(&self, - name: ident, - span: span, - ty: @ast::Ty, - generics: Generics) -> @ast::item; - fn item_ty(&self, name: ident, span: span, ty: @ast::Ty) -> @ast::item; - fn ty_vars(&self, ty_params: &OptVec) -> ~[@ast::Ty]; - fn ty_vars_global(&self, ty_params: &OptVec) -> ~[@ast::Ty]; - fn ty_field_imm(&self, name: ident, ty: @ast::Ty) -> ast::ty_field; - fn field_imm(&self, name: ident, e: @ast::expr) -> ast::field; - fn block(&self, stmts: ~[@ast::stmt], e: @ast::expr) -> ast::blk; - fn stmt_let(&self, ident: ident, e: @ast::expr) -> @ast::stmt; - fn stmt_expr(&self, e: @ast::expr) -> @ast::stmt; - fn block_expr(&self, b: ast::blk) -> @ast::expr; - fn ty_option(&self, ty: @ast::Ty) -> @ast::Ty; - fn ty_infer(&self) -> @ast::Ty; - fn ty_nil_ast_builder(&self) -> @ast::Ty; - fn strip_bounds(&self, bounds: &Generics) -> Generics; -} - -impl ext_ctxt_ast_builder for @ext_ctxt { - fn ty_option(&self, ty: @ast::Ty) -> @ast::Ty { - self.ty_path_ast_builder(path_global(~[ - self.ident_of("core"), - self.ident_of("option"), - self.ident_of("Option") - ], dummy_sp()).add_ty(ty)) - } - - fn block_expr(&self, b: ast::blk) -> @ast::expr { - @expr { - id: self.next_id(), - callee_id: self.next_id(), - node: ast::expr_block(b), - span: dummy_sp(), - } - } - - fn stmt_expr(&self, e: @ast::expr) -> @ast::stmt { - @spanned { node: ast::stmt_expr(e, self.next_id()), - span: dummy_sp()} - } - - fn stmt_let(&self, ident: ident, e: @ast::expr) -> @ast::stmt { - let ext_cx = *self; - quote_stmt!( let $ident = $e; ) - } - - fn field_imm(&self, name: ident, e: @ast::expr) -> ast::field { - spanned { - node: ast::field_ { mutbl: ast::m_imm, ident: name, expr: e }, - span: dummy_sp(), - } - } - - fn ty_field_imm(&self, name: ident, ty: @ast::Ty) -> ast::ty_field { - spanned { - node: ast::ty_field_ { - ident: name, - mt: ast::mt { ty: ty, mutbl: ast::m_imm }, - }, - span: dummy_sp(), - } - } - - fn ty_infer(&self) -> @ast::Ty { - @ast::Ty { - id: self.next_id(), - node: ast::ty_infer, - span: dummy_sp(), - } - } - - fn ty_param(&self, id: ast::ident, bounds: @OptVec) - -> ast::TyParam - { - ast::TyParam { ident: id, id: self.next_id(), bounds: bounds } - } - - fn arg(&self, name: ident, ty: @ast::Ty) -> ast::arg { - ast::arg { - is_mutbl: false, - ty: ty, - pat: @ast::pat { - id: self.next_id(), - node: ast::pat_ident( - ast::bind_by_copy, - ast_util::ident_to_path(dummy_sp(), name), - None), - span: dummy_sp(), - }, - id: self.next_id(), - } - } - - fn block(&self, stmts: ~[@ast::stmt], e: @ast::expr) -> ast::blk { - let blk = ast::blk_ { - view_items: ~[], - stmts: stmts, - expr: Some(e), - id: self.next_id(), - rules: ast::default_blk, - }; - - spanned { node: blk, span: dummy_sp() } - } - - fn expr_block(&self, e: @ast::expr) -> ast::blk { - self.block(~[], e) - } - - fn fn_decl(&self, inputs: ~[ast::arg], - output: @ast::Ty) -> ast::fn_decl { - ast::fn_decl { - inputs: inputs, - output: output, - cf: ast::return_val, - } - } - - fn item(&self, name: ident, span: span, - node: ast::item_) -> @ast::item { - - // XXX: Would be nice if our generated code didn't violate - // Rust coding conventions - let non_camel_case_attribute = respan(dummy_sp(), ast::attribute_ { - style: ast::attr_outer, - value: @respan(dummy_sp(), - ast::meta_list(@~"allow", ~[ - @respan(dummy_sp(), - ast::meta_word( - @~"non_camel_case_types")) - ])), - is_sugared_doc: false - }); - - @ast::item { ident: name, - attrs: ~[non_camel_case_attribute], - id: self.next_id(), - node: node, - vis: ast::public, - span: span } - } - - fn item_fn_poly(&self, name: ident, - inputs: ~[ast::arg], - output: @ast::Ty, - generics: Generics, - body: ast::blk) -> @ast::item { - self.item(name, - dummy_sp(), - ast::item_fn(self.fn_decl(inputs, output), - ast::impure_fn, - AbiSet::Rust(), - generics, - body)) - } - - fn item_fn(&self, - name: ident, - inputs: ~[ast::arg], - output: @ast::Ty, - body: ast::blk - ) -> @ast::item { - self.item_fn_poly( - name, - inputs, - output, - ast_util::empty_generics(), - body - ) - } - - fn item_enum_poly(&self, name: ident, span: span, - enum_definition: ast::enum_def, - generics: Generics) -> @ast::item { - self.item(name, span, ast::item_enum(enum_definition, generics)) - } - - fn item_enum(&self, name: ident, span: span, - enum_definition: ast::enum_def) -> @ast::item { - self.item_enum_poly(name, span, enum_definition, - ast_util::empty_generics()) - } - - fn item_struct( - &self, name: ident, - span: span, - struct_def: ast::struct_def - ) -> @ast::item { - self.item_struct_poly( - name, - span, - struct_def, - ast_util::empty_generics() - ) - } - - fn item_struct_poly( - &self, - name: ident, - span: span, - struct_def: ast::struct_def, - generics: Generics - ) -> @ast::item { - self.item(name, span, ast::item_struct(@struct_def, generics)) - } - - fn struct_expr(&self, path: @ast::Path, - fields: ~[ast::field]) -> @ast::expr { - @ast::expr { - id: self.next_id(), - callee_id: self.next_id(), - node: ast::expr_struct(path, fields, None), - span: dummy_sp() - } - } - - fn variant(&self, name: ident, span: span, - tys: ~[@ast::Ty]) -> ast::variant { - let args = do tys.map |ty| { - ast::variant_arg { ty: *ty, id: self.next_id() } - }; - - spanned { - node: ast::variant_ { - name: name, - attrs: ~[], - kind: ast::tuple_variant_kind(args), - id: self.next_id(), - disr_expr: None, - vis: ast::public - }, - span: span, - } - } - - fn item_mod(&self, name: ident, span: span, - items: ~[@ast::item]) -> @ast::item { - - // XXX: Total hack: import `core::kinds::Owned` to work around a - // parser bug whereby `fn f` doesn't parse. - let vi = ast::view_item_use(~[ - @codemap::spanned { - node: ast::view_path_simple( - self.ident_of("Owned"), - path( - ~[ - self.ident_of("core"), - self.ident_of("kinds"), - self.ident_of("Owned") - ], - codemap::dummy_sp() - ), - self.next_id() - ), - span: codemap::dummy_sp() - } - ]); - let vi = @ast::view_item { - node: vi, - attrs: ~[], - vis: ast::private, - span: codemap::dummy_sp() - }; - - self.item( - name, - span, - ast::item_mod(ast::_mod { - view_items: ~[vi], - items: items, - }) - ) - } - - fn ty_path_ast_builder(&self, path: @ast::Path) -> @ast::Ty { - @ast::Ty { - id: self.next_id(), - node: ast::ty_path(path, self.next_id()), - span: path.span, - } - } - - fn ty_nil_ast_builder(&self) -> @ast::Ty { - @ast::Ty { - id: self.next_id(), - node: ast::ty_nil, - span: dummy_sp(), - } - } - - fn strip_bounds(&self, generics: &Generics) -> Generics { - let no_bounds = @opt_vec::Empty; - let new_params = do generics.ty_params.map |ty_param| { - ast::TyParam { bounds: no_bounds, ..copy *ty_param } - }; - Generics { - ty_params: new_params, - .. copy *generics - } - } - - fn item_ty_poly(&self, name: ident, span: span, ty: @ast::Ty, - generics: Generics) -> @ast::item { - self.item(name, span, ast::item_ty(ty, generics)) - } - - fn item_ty(&self, name: ident, span: span, ty: @ast::Ty) -> @ast::item { - self.item_ty_poly(name, span, ty, ast_util::empty_generics()) - } - - fn ty_vars(&self, ty_params: &OptVec) -> ~[@ast::Ty] { - opt_vec::take_vec( - ty_params.map(|p| self.ty_path_ast_builder( - path(~[p.ident], dummy_sp())))) - } - - fn ty_vars_global(&self, - ty_params: &OptVec) -> ~[@ast::Ty] { - opt_vec::take_vec( - ty_params.map(|p| self.ty_path_ast_builder( - path(~[p.ident], dummy_sp())))) - } -} diff --git a/src/libsyntax/ext/pipes/check.rs b/src/libsyntax/ext/pipes/check.rs index 38e43d1ade562..694a7c1cf8411 100644 --- a/src/libsyntax/ext/pipes/check.rs +++ b/src/libsyntax/ext/pipes/check.rs @@ -29,13 +29,15 @@ that. */ +use core::prelude::*; + use ast; use codemap::span; -use ext::base::ext_ctxt; +use ext::base::ExtCtxt; use ext::pipes::proto::{state, protocol, next_state}; use ext::pipes::proto; -impl proto::visitor<(), (), ()> for @ext_ctxt { +impl proto::visitor<(), (), ()> for @ExtCtxt { fn visit_proto(&self, _proto: protocol, _states: &[()]) { } fn visit_state(&self, state: state, _m: &[()]) { diff --git a/src/libsyntax/ext/pipes/liveness.rs b/src/libsyntax/ext/pipes/liveness.rs index 8799bd064f658..43bcb68b8e08f 100644 --- a/src/libsyntax/ext/pipes/liveness.rs +++ b/src/libsyntax/ext/pipes/liveness.rs @@ -37,12 +37,15 @@ updating the states using rule (2) until there are no changes. */ -use ext::base::ext_ctxt; +use core::prelude::*; + +use ext::base::ExtCtxt; use ext::pipes::proto::{protocol_}; -use std::bitv::Bitv; +use core::str; +use extra::bitv::Bitv; -pub fn analyze(proto: @mut protocol_, _cx: @ext_ctxt) { +pub fn analyze(proto: @mut protocol_, _cx: @ExtCtxt) { debug!("initializing colive analysis"); let num_states = proto.num_states(); let mut colive = do (copy proto.states).map_to_vec |state| { @@ -85,7 +88,7 @@ pub fn analyze(proto: @mut protocol_, _cx: @ext_ctxt) { } if self_live.len() > 0 { - let states = str::connect(self_live.map(|s| copy s.name), ~" "); + let states = str::connect(self_live.map(|s| copy s.name), " "); debug!("protocol %s is unbounded due to loops involving: %s", copy proto.name, states); diff --git a/src/libsyntax/ext/pipes/mod.rs b/src/libsyntax/ext/pipes/mod.rs index 642f22e973680..3f4b5ee54f193 100644 --- a/src/libsyntax/ext/pipes/mod.rs +++ b/src/libsyntax/ext/pipes/mod.rs @@ -46,13 +46,12 @@ FIXME (#3072) - This is still incomplete. use ast; use codemap::span; use ext::base; -use ext::base::ext_ctxt; +use ext::base::ExtCtxt; use ext::pipes::parse_proto::proto_parser; use ext::pipes::pipec::gen_init; use ext::pipes::proto::visit; use parse::lexer::{new_tt_reader, reader}; use parse::parser::Parser; - use core::option::None; pub mod ast_builder; @@ -63,12 +62,11 @@ pub mod check; pub mod liveness; -pub fn expand_proto(cx: @ext_ctxt, _sp: span, id: ast::ident, +pub fn expand_proto(cx: @ExtCtxt, _sp: span, id: ast::ident, tt: ~[ast::token_tree]) -> base::MacResult { let sess = cx.parse_sess(); let cfg = cx.cfg(); let tt_rdr = new_tt_reader(copy cx.parse_sess().span_diagnostic, - cx.parse_sess().interner, None, copy tt); let rdr = tt_rdr as @reader; diff --git a/src/libsyntax/ext/pipes/parse_proto.rs b/src/libsyntax/ext/pipes/parse_proto.rs index 5c99ddc9040ab..a89fd26df4c8b 100644 --- a/src/libsyntax/ext/pipes/parse_proto.rs +++ b/src/libsyntax/ext/pipes/parse_proto.rs @@ -10,11 +10,14 @@ // Parsing pipes protocols from token trees. +use core::prelude::*; + use ast_util; use ext::pipes::proto::*; use parse::common::SeqSep; use parse::parser; use parse::token; +use parse::token::{interner_get}; pub trait proto_parser { fn parse_proto(&self, id: ~str) -> protocol; @@ -40,11 +43,11 @@ impl proto_parser for parser::Parser { fn parse_state(&self, proto: protocol) { let id = self.parse_ident(); - let name = copy *self.interner.get(id); + let name = copy *interner_get(id.name); self.expect(&token::COLON); let dir = match copy *self.token { - token::IDENT(n, _) => self.interner.get(n), + token::IDENT(n, _) => interner_get(n.name), _ => fail!() }; self.bump(); @@ -75,7 +78,7 @@ impl proto_parser for parser::Parser { } fn parse_message(&self, state: state) { - let mname = copy *self.interner.get(self.parse_ident()); + let mname = copy *interner_get(self.parse_ident().name); let args = if *self.token == token::LPAREN { self.parse_unspanned_seq( @@ -94,7 +97,7 @@ impl proto_parser for parser::Parser { let next = match *self.token { token::IDENT(_, _) => { - let name = copy *self.interner.get(self.parse_ident()); + let name = copy *interner_get(self.parse_ident().name); let ntys = if *self.token == token::LT { self.parse_unspanned_seq( &token::LT, @@ -114,7 +117,7 @@ impl proto_parser for parser::Parser { self.bump(); None } - _ => self.fatal(~"invalid next state") + _ => self.fatal("invalid next state") }; state.add_message(mname, *self.span, args, next); diff --git a/src/libsyntax/ext/pipes/pipec.rs b/src/libsyntax/ext/pipes/pipec.rs index b537ef87d543f..1e5b3c3ee7eb4 100644 --- a/src/libsyntax/ext/pipes/pipec.rs +++ b/src/libsyntax/ext/pipes/pipec.rs @@ -10,38 +10,44 @@ // A protocol compiler for Rust. +use core::prelude::*; + use ast; use codemap::{dummy_sp, spanned}; -use ext::base::ext_ctxt; -use ext::pipes::ast_builder::{append_types, ext_ctxt_ast_builder, path}; +use ext::base::ExtCtxt; +use ext::build::AstBuilder; +use ext::pipes::ast_builder::{append_types, path}; use ext::pipes::ast_builder::{path_global}; use ext::pipes::proto::*; use ext::quote::rt::*; use opt_vec; use opt_vec::OptVec; +use core::str; +use core::vec; + pub trait gen_send { - fn gen_send(&mut self, cx: @ext_ctxt, try: bool) -> @ast::item; - fn to_ty(&mut self, cx: @ext_ctxt) -> @ast::Ty; + fn gen_send(&mut self, cx: @ExtCtxt, try: bool) -> @ast::item; + fn to_ty(&mut self, cx: @ExtCtxt) -> @ast::Ty; } pub trait to_type_decls { - fn to_type_decls(&self, cx: @ext_ctxt) -> ~[@ast::item]; - fn to_endpoint_decls(&self, cx: @ext_ctxt, + fn to_type_decls(&self, cx: @ExtCtxt) -> ~[@ast::item]; + fn to_endpoint_decls(&self, cx: @ExtCtxt, dir: direction) -> ~[@ast::item]; } pub trait gen_init { - fn gen_init(&self, cx: @ext_ctxt) -> @ast::item; - fn compile(&self, cx: @ext_ctxt) -> @ast::item; - fn buffer_ty_path(&self, cx: @ext_ctxt) -> @ast::Ty; - fn gen_buffer_type(&self, cx: @ext_ctxt) -> @ast::item; - fn gen_buffer_init(&self, ext_cx: @ext_ctxt) -> @ast::expr; - fn gen_init_bounded(&self, ext_cx: @ext_ctxt) -> @ast::expr; + fn gen_init(&self, cx: @ExtCtxt) -> @ast::item; + fn compile(&self, cx: @ExtCtxt) -> @ast::item; + fn buffer_ty_path(&self, cx: @ExtCtxt) -> @ast::Ty; + fn gen_buffer_type(&self, cx: @ExtCtxt) -> @ast::item; + fn gen_buffer_init(&self, ext_cx: @ExtCtxt) -> @ast::expr; + fn gen_init_bounded(&self, ext_cx: @ExtCtxt) -> @ast::expr; } impl gen_send for message { - fn gen_send(&mut self, cx: @ext_ctxt, try: bool) -> @ast::item { + fn gen_send(&mut self, cx: @ExtCtxt, try: bool) -> @ast::item { debug!("pipec: gen_send"); let name = self.name(); @@ -52,19 +58,18 @@ impl gen_send for message { assert!(next_state.tys.len() == next.generics.ty_params.len()); let arg_names = tys.mapi(|i, _ty| cx.ident_of(~"x_"+i.to_str())); - let args_ast = vec::map_zip(arg_names, *tys, |n, t| cx.arg(*n, *t)); + let args_ast = vec::map_zip(arg_names, *tys, |n, t| cx.arg(span, *n, *t)); - let pipe_ty = cx.ty_path_ast_builder( + let pipe_ty = cx.ty_path( path(~[this.data_name()], span) - .add_tys(cx.ty_vars_global(&this.generics.ty_params))); + .add_tys(cx.ty_vars(&this.generics.ty_params))); let args_ast = vec::append( - ~[cx.arg(cx.ident_of("pipe"), - pipe_ty)], + ~[cx.arg(span, cx.ident_of("pipe"), pipe_ty)], args_ast); let mut body = ~"{\n"; body += fmt!("use super::%s;\n", name); - body += ~"let mut pipe = pipe;\n"; + body += "let mut pipe = pipe;\n"; if this.proto.is_bounded() { let (sp, rp) = match (this.dir, next.dir) { @@ -74,57 +79,58 @@ impl gen_send for message { (recv, recv) => (~"c", ~"s") }; - body += ~"let mut b = pipe.reuse_buffer();\n"; - body += fmt!("let %s = ::core::pipes::SendPacketBuffered(\ + body += "let mut b = pipe.reuse_buffer();\n"; + body += fmt!("let %s = ::std::pipes::SendPacketBuffered(\ &mut (b.buffer.data.%s));\n", sp, next.name); - body += fmt!("let %s = ::core::pipes::RecvPacketBuffered(\ + body += fmt!("let %s = ::std::pipes::RecvPacketBuffered(\ &mut (b.buffer.data.%s));\n", rp, next.name); } else { let pat = match (this.dir, next.dir) { - (send, send) => "(c, s)", - (send, recv) => "(s, c)", - (recv, send) => "(s, c)", - (recv, recv) => "(c, s)" + (send, send) => "(s, c)", + (send, recv) => "(c, s)", + (recv, send) => "(c, s)", + (recv, recv) => "(s, c)" }; - body += fmt!("let %s = ::core::pipes::entangle();\n", pat); + body += fmt!("let %s = ::std::pipes::entangle();\n", pat); } body += fmt!("let message = %s(%s);\n", name, str::connect(vec::append_one( arg_names.map(|x| cx.str_of(*x)), - ~"s"), ~", ")); + ~"s"), ", ")); if !try { - body += fmt!("::core::pipes::send(pipe, message);\n"); + body += fmt!("::std::pipes::send(pipe, message);\n"); // return the new channel - body += ~"c }"; + body += "c }"; } else { - body += fmt!("if ::core::pipes::send(pipe, message) {\n \ - ::core::pipes::rt::make_some(c) \ - } else { ::core::pipes::rt::make_none() } }"); + body += fmt!("if ::std::pipes::send(pipe, message) {\n \ + ::std::pipes::rt::make_some(c) \ + } else { ::std::pipes::rt::make_none() } }"); } let body = cx.parse_expr(body); - let mut rty = cx.ty_path_ast_builder(path(~[next.data_name()], - span) - .add_tys(copy next_state.tys)); + let mut rty = cx.ty_path(path(~[next.data_name()], + span) + .add_tys(copy next_state.tys)); if try { rty = cx.ty_option(rty); } let name = cx.ident_of(if try { ~"try_" + name } else { name } ); - cx.item_fn_poly(name, + cx.item_fn_poly(dummy_sp(), + name, args_ast, rty, self.get_generics(), - cx.expr_block(body)) + cx.blk_expr(body)) } message(ref _id, span, ref tys, this, None) => { @@ -132,14 +138,15 @@ impl gen_send for message { let arg_names = tys.mapi(|i, _ty| (~"x_" + i.to_str())); let args_ast = do vec::map_zip(arg_names, *tys) |n, t| { - cx.arg(cx.ident_of(*n), *t) + cx.arg(span, cx.ident_of(*n), *t) }; let args_ast = vec::append( - ~[cx.arg(cx.ident_of("pipe"), - cx.ty_path_ast_builder( + ~[cx.arg(span, + cx.ident_of("pipe"), + cx.ty_path( path(~[this.data_name()], span) - .add_tys(cx.ty_vars_global( + .add_tys(cx.ty_vars( &this.generics.ty_params))))], args_ast); @@ -148,7 +155,7 @@ impl gen_send for message { } else { ~"(" + str::connect(arg_names.map(|x| copy *x), - ~", ") + ~")" + ", ") + ")" }; let mut body = ~"{ "; @@ -156,14 +163,14 @@ impl gen_send for message { body += fmt!("let message = %s%s;\n", name, message_args); if !try { - body += fmt!("::core::pipes::send(pipe, message);\n"); - body += ~" }"; + body += fmt!("::std::pipes::send(pipe, message);\n"); + body += " }"; } else { - body += fmt!("if ::core::pipes::send(pipe, message) \ + body += fmt!("if ::std::pipes::send(pipe, message) \ { \ - ::core::pipes::rt::make_some(()) \ + ::std::pipes::rt::make_some(()) \ } else { \ - ::core::pipes::rt::make_none() \ + ::std::pipes::rt::make_none() \ } }"); } @@ -171,27 +178,28 @@ impl gen_send for message { let name = if try { ~"try_" + name } else { name }; - cx.item_fn_poly(cx.ident_of(name), + cx.item_fn_poly(dummy_sp(), + cx.ident_of(name), args_ast, if try { - cx.ty_option(cx.ty_nil_ast_builder()) + cx.ty_option(cx.ty_nil()) } else { - cx.ty_nil_ast_builder() + cx.ty_nil() }, self.get_generics(), - cx.expr_block(body)) + cx.blk_expr(body)) } } } - fn to_ty(&mut self, cx: @ext_ctxt) -> @ast::Ty { - cx.ty_path_ast_builder(path(~[cx.ident_of(self.name())], self.span()) - .add_tys(cx.ty_vars_global(&self.get_generics().ty_params))) + fn to_ty(&mut self, cx: @ExtCtxt) -> @ast::Ty { + cx.ty_path(path(~[cx.ident_of(self.name())], self.span()) + .add_tys(cx.ty_vars(&self.get_generics().ty_params))) } } impl to_type_decls for state { - fn to_type_decls(&self, cx: @ext_ctxt) -> ~[@ast::item] { + fn to_type_decls(&self, cx: @ExtCtxt) -> ~[@ast::item] { debug!("pipec: to_type_decls"); // This compiles into two different type declarations. Say the // state is called ping. This will generate both `ping` and @@ -217,7 +225,7 @@ impl to_type_decls for state { }; vec::append_one(tys, - cx.ty_path_ast_builder( + cx.ty_path( path(~[cx.ident_of(dir), cx.ident_of(next_name)], span) .add_tys(copy next_state.tys))) @@ -225,22 +233,22 @@ impl to_type_decls for state { None => tys }; - let v = cx.variant(cx.ident_of(name), span, tys); + let v = cx.variant(span, cx.ident_of(name), tys); items_msg.push(v); } ~[ cx.item_enum_poly( - name, self.span, + name, ast::enum_def { variants: items_msg }, cx.strip_bounds(&self.generics) ) ] } - fn to_endpoint_decls(&self, cx: @ext_ctxt, + fn to_endpoint_decls(&self, cx: @ExtCtxt, dir: direction) -> ~[@ast::item] { debug!("pipec: to_endpoint_decls"); let dir = match dir { @@ -262,33 +270,33 @@ impl to_type_decls for state { if !self.proto.is_bounded() { items.push( cx.item_ty_poly( - self.data_name(), self.span, - cx.ty_path_ast_builder( - path_global(~[cx.ident_of("core"), + self.data_name(), + cx.ty_path( + path_global(~[cx.ident_of("std"), cx.ident_of("pipes"), cx.ident_of(dir.to_str() + "Packet")], dummy_sp()) - .add_ty(cx.ty_path_ast_builder( + .add_ty(cx.ty_path( path(~[cx.ident_of("super"), self.data_name()], dummy_sp()) - .add_tys(cx.ty_vars_global( + .add_tys(cx.ty_vars( &self.generics.ty_params))))), cx.strip_bounds(&self.generics))); } else { items.push( cx.item_ty_poly( - self.data_name(), self.span, - cx.ty_path_ast_builder( - path_global(~[cx.ident_of("core"), + self.data_name(), + cx.ty_path( + path_global(~[cx.ident_of("std"), cx.ident_of("pipes"), cx.ident_of(dir.to_str() + "PacketBuffered")], dummy_sp()) - .add_tys(~[cx.ty_path_ast_builder( + .add_tys(~[cx.ty_path( path(~[cx.ident_of("super"), self.data_name()], dummy_sp()) @@ -302,83 +310,70 @@ impl to_type_decls for state { } impl gen_init for protocol { - fn gen_init(&self, cx: @ext_ctxt) -> @ast::item { + fn gen_init(&self, cx: @ExtCtxt) -> @ast::item { let ext_cx = cx; debug!("gen_init"); let start_state = self.states[0]; let body = if !self.is_bounded() { - match start_state.dir { - send => quote_expr!( ::core::pipes::entangle() ), - recv => { - quote_expr!({ - let (s, c) = ::core::pipes::entangle(); - (c, s) - }) - } - } + quote_expr!( ::std::pipes::entangle() ) } else { - let body = self.gen_init_bounded(ext_cx); - match start_state.dir { - send => body, - recv => { - quote_expr!({ - let (s, c) = $body; - (c, s) - }) - } - } + self.gen_init_bounded(ext_cx) }; - cx.parse_item(fmt!("pub fn init%s() -> (client::%s, server::%s)\ - { pub use core::pipes::HasBuffer; %s }", - start_state.generics.to_source(cx), - start_state.to_ty(cx).to_source(cx), - start_state.to_ty(cx).to_source(cx), - body.to_source(cx))) + cx.parse_item(fmt!("pub fn init%s() -> (server::%s, client::%s)\ + { pub use std::pipes::HasBuffer; %s }", + start_state.generics.to_source(), + start_state.to_ty(cx).to_source(), + start_state.to_ty(cx).to_source(), + body.to_source())) } - fn gen_buffer_init(&self, ext_cx: @ext_ctxt) -> @ast::expr { - ext_cx.struct_expr(path(~[ext_cx.ident_of("__Buffer")], - dummy_sp()), - self.states.map_to_vec(|s| { - let fty = s.to_ty(ext_cx); - ext_cx.field_imm(ext_cx.ident_of(s.name), - quote_expr!( - ::core::pipes::mk_packet::<$fty>() - )) - })) + fn gen_buffer_init(&self, ext_cx: @ExtCtxt) -> @ast::expr { + ext_cx.expr_struct( + dummy_sp(), + path(~[ext_cx.ident_of("__Buffer")], + dummy_sp()), + self.states.map_to_vec(|s| { + let fty = s.to_ty(ext_cx); + ext_cx.field_imm(dummy_sp(), + ext_cx.ident_of(s.name), + quote_expr!( + ::std::pipes::mk_packet::<$fty>() + )) + })) } - fn gen_init_bounded(&self, ext_cx: @ext_ctxt) -> @ast::expr { + fn gen_init_bounded(&self, ext_cx: @ExtCtxt) -> @ast::expr { debug!("gen_init_bounded"); let buffer_fields = self.gen_buffer_init(ext_cx); - let buffer = quote_expr!(~::core::pipes::Buffer { - header: ::core::pipes::BufferHeader(), + let buffer = quote_expr!(~::std::pipes::Buffer { + header: ::std::pipes::BufferHeader(), data: $buffer_fields, }); - let entangle_body = ext_cx.block_expr( - ext_cx.block( + let entangle_body = ext_cx.expr_blk( + ext_cx.blk( + dummy_sp(), self.states.map_to_vec( |s| ext_cx.parse_stmt( fmt!("data.%s.set_buffer(buffer)", s.name))), - ext_cx.parse_expr(fmt!( - "::core::ptr::to_mut_unsafe_ptr(&mut (data.%s))", - self.states[0].name)))); + Some(ext_cx.parse_expr(fmt!( + "::std::ptr::to_mut_unsafe_ptr(&mut (data.%s))", + self.states[0].name))))); quote_expr!({ let buffer = $buffer; - do ::core::pipes::entangle_buffer(buffer) |buffer, data| { + do ::std::pipes::entangle_buffer(buffer) |buffer, data| { $entangle_body } }) } - fn buffer_ty_path(&self, cx: @ext_ctxt) -> @ast::Ty { + fn buffer_ty_path(&self, cx: @ExtCtxt) -> @ast::Ty { let mut params: OptVec = opt_vec::Empty; for (copy self.states).each |s| { for s.generics.ty_params.each |tp| { @@ -389,13 +384,13 @@ impl gen_init for protocol { } } - cx.ty_path_ast_builder(path(~[cx.ident_of("super"), - cx.ident_of("__Buffer")], - copy self.span) - .add_tys(cx.ty_vars_global(¶ms))) + cx.ty_path(path(~[cx.ident_of("super"), + cx.ident_of("__Buffer")], + copy self.span) + .add_tys(cx.ty_vars_global(¶ms))) } - fn gen_buffer_type(&self, cx: @ext_ctxt) -> @ast::item { + fn gen_buffer_type(&self, cx: @ExtCtxt) -> @ast::item { let ext_cx = cx; let mut params: OptVec = opt_vec::Empty; let fields = do (copy self.states).map_to_vec |s| { @@ -407,7 +402,7 @@ impl gen_init for protocol { } let ty = s.to_ty(cx); - let fty = quote_ty!( ::core::pipes::Packet<$ty> ); + let fty = quote_ty!( ::std::pipes::Packet<$ty> ); @spanned { node: ast::struct_field_ { @@ -427,8 +422,8 @@ impl gen_init for protocol { }; cx.item_struct_poly( - cx.ident_of("__Buffer"), dummy_sp(), + cx.ident_of("__Buffer"), ast::struct_def { fields: fields, ctor_id: None @@ -436,7 +431,7 @@ impl gen_init for protocol { cx.strip_bounds(&generics)) } - fn compile(&self, cx: @ext_ctxt) -> @ast::item { + fn compile(&self, cx: @ExtCtxt) -> @ast::item { let mut items = ~[self.gen_init(cx)]; let mut client_states = ~[]; let mut server_states = ~[]; @@ -452,13 +447,24 @@ impl gen_init for protocol { items.push(self.gen_buffer_type(cx)) } - items.push(cx.item_mod(cx.ident_of("client"), - copy self.span, + items.push(cx.item_mod(copy self.span, + cx.ident_of("client"), + ~[], ~[], client_states)); - items.push(cx.item_mod(cx.ident_of("server"), - copy self.span, + items.push(cx.item_mod(copy self.span, + cx.ident_of("server"), + ~[], ~[], server_states)); - cx.item_mod(cx.ident_of(copy self.name), copy self.span, items) + // XXX: Would be nice if our generated code didn't violate + // Rust coding conventions + let allows = cx.attribute( + copy self.span, + cx.meta_list(copy self.span, + ~"allow", + ~[cx.meta_word(copy self.span, ~"non_camel_case_types"), + cx.meta_word(copy self.span, ~"unused_mut")])); + cx.item_mod(copy self.span, cx.ident_of(copy self.name), + ~[allows], ~[], items) } } diff --git a/src/libsyntax/ext/pipes/proto.rs b/src/libsyntax/ext/pipes/proto.rs index f897eb787e566..0eb0f5c615927 100644 --- a/src/libsyntax/ext/pipes/proto.rs +++ b/src/libsyntax/ext/pipes/proto.rs @@ -8,10 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use ast; use codemap::span; -use ext::base::ext_ctxt; -use ext::pipes::ast_builder::{append_types, ext_ctxt_ast_builder, path}; +use ext::base::ExtCtxt; +use ext::build::AstBuilder; +use ext::pipes::ast_builder::{append_types, path}; #[deriving(Eq)] pub enum direction { send, recv } @@ -25,8 +28,8 @@ impl ToStr for direction { } } -pub impl direction { - fn reverse(&self) -> direction { +impl direction { + pub fn reverse(&self) -> direction { match *self { send => recv, recv => send @@ -42,21 +45,21 @@ pub struct next_state { // name, span, data, current state, next state pub struct message(~str, span, ~[@ast::Ty], state, Option); -pub impl message { - fn name(&mut self) -> ~str { +impl message { + pub fn name(&mut self) -> ~str { match *self { message(ref id, _, _, _, _) => copy *id } } - fn span(&mut self) -> span { + pub fn span(&mut self) -> span { match *self { message(_, span, _, _, _) => span } } /// Return the type parameters actually used by this message - fn get_generics(&self) -> ast::Generics { + pub fn get_generics(&self) -> ast::Generics { match *self { message(_, _, _, this, _) => copy this.generics } @@ -76,46 +79,34 @@ pub struct state_ { proto: protocol } -pub impl state_ { - fn add_message(@self, name: ~str, span: span, - data: ~[@ast::Ty], next: Option) { +impl state_ { + pub fn add_message(@self, + name: ~str, + span: span, + data: ~[@ast::Ty], + next: Option) { self.messages.push(message(name, span, data, self, next)); } - fn filename(&self) -> ~str { + pub fn filename(&self) -> ~str { self.proto.filename() } - fn data_name(&self) -> ast::ident { + pub fn data_name(&self) -> ast::ident { self.ident } /// Returns the type that is used for the messages. - fn to_ty(&self, cx: @ext_ctxt) -> @ast::Ty { - cx.ty_path_ast_builder + pub fn to_ty(&self, cx: @ExtCtxt) -> @ast::Ty { + cx.ty_path (path(~[cx.ident_of(self.name)],self.span).add_tys( cx.ty_vars(&self.generics.ty_params))) } /// Iterate over the states that can be reached in one message /// from this state. - #[cfg(stage0)] - fn reachable(&self, f: &fn(state) -> bool) { - for self.messages.each |m| { - match *m { - message(_, _, _, _, Some(next_state { state: ref id, _ })) => { - let state = self.proto.get_state((*id)); - if !f(state) { break } - } - _ => () - } - } - } - /// Iterate over the states that can be reached in one message - /// from this state. - #[cfg(not(stage0))] - fn reachable(&self, f: &fn(state) -> bool) -> bool { + pub fn reachable(&self, f: &fn(state) -> bool) -> bool { for self.messages.each |m| { match *m { message(_, _, _, _, Some(next_state { state: ref id, _ })) => { @@ -152,28 +143,28 @@ pub struct protocol_ { bounded: Option, } -pub impl protocol_ { +impl protocol_ { /// Get a state. - fn get_state(&self, name: &str) -> state { + pub fn get_state(&self, name: &str) -> state { self.states.find(|i| name == i.name).get() } - fn get_state_by_id(&self, id: uint) -> state { self.states[id] } + pub fn get_state_by_id(&self, id: uint) -> state { self.states[id] } - fn has_state(&self, name: &str) -> bool { + pub fn has_state(&self, name: &str) -> bool { self.states.find(|i| name == i.name).is_some() } - fn filename(&self) -> ~str { + pub fn filename(&self) -> ~str { ~"proto://" + self.name } - fn num_states(&self) -> uint { + pub fn num_states(&self) -> uint { let states = &mut *self.states; states.len() } - fn has_ty_params(&self) -> bool { + pub fn has_ty_params(&self) -> bool { for self.states.each |s| { if s.generics.ty_params.len() > 0 { return true; @@ -181,19 +172,20 @@ pub impl protocol_ { } false } - fn is_bounded(&self) -> bool { + + pub fn is_bounded(&self) -> bool { let bounded = self.bounded.get(); bounded } } -pub impl protocol_ { - fn add_state_poly(@mut self, - name: ~str, - ident: ast::ident, - dir: direction, - generics: ast::Generics) - -> state { +impl protocol_ { + pub fn add_state_poly(@mut self, + name: ~str, + ident: ast::ident, + dir: direction, + generics: ast::Generics) + -> state { let messages = @mut ~[]; let states = &mut *self.states; diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index fc673c4422f1d..062532afef8d6 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -8,15 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use ast; use codemap::{BytePos, Pos, span}; -use ext::base::ext_ctxt; +use ext::base::ExtCtxt; use ext::base; -use ext::build; +use ext::build::AstBuilder; use parse::token::*; use parse::token; use parse; +use core::vec; + /** * * Quasiquoting works via token trees. @@ -29,8 +33,10 @@ use parse; */ pub mod rt { + use core::prelude::*; + use ast; - use ext::base::ext_ctxt; + use ext::base::ExtCtxt; use parse; use print::pprust; @@ -44,11 +50,11 @@ pub mod rt { use print::pprust::{item_to_str, ty_to_str}; pub trait ToTokens { - pub fn to_tokens(&self, _cx: @ext_ctxt) -> ~[token_tree]; + pub fn to_tokens(&self, _cx: @ExtCtxt) -> ~[token_tree]; } impl ToTokens for ~[token_tree] { - pub fn to_tokens(&self, _cx: @ext_ctxt) -> ~[token_tree] { + pub fn to_tokens(&self, _cx: @ExtCtxt) -> ~[token_tree] { copy *self } } @@ -57,11 +63,11 @@ pub mod rt { trait ToSource : ToTokens { // Takes a thing and generates a string containing rust code for it. - pub fn to_source(cx: @ext_ctxt) -> ~str; + pub fn to_source() -> ~str; // If you can make source, you can definitely make tokens. - pub fn to_tokens(cx: @ext_ctxt) -> ~[token_tree] { - cx.parse_tts(self.to_source(cx)) + pub fn to_tokens(cx: @ExtCtxt) -> ~[token_tree] { + cx.parse_tts(self.to_source()) } } @@ -69,80 +75,80 @@ pub mod rt { pub trait ToSource { // Takes a thing and generates a string containing rust code for it. - pub fn to_source(&self, cx: @ext_ctxt) -> ~str; + pub fn to_source(&self) -> ~str; } impl ToSource for ast::ident { - fn to_source(&self, cx: @ext_ctxt) -> ~str { - copy *cx.parse_sess().interner.get(*self) + fn to_source(&self) -> ~str { + copy *ident_to_str(self) } } impl ToSource for @ast::item { - fn to_source(&self, cx: @ext_ctxt) -> ~str { - item_to_str(*self, cx.parse_sess().interner) + fn to_source(&self) -> ~str { + item_to_str(*self, get_ident_interner()) } } impl<'self> ToSource for &'self [@ast::item] { - fn to_source(&self, cx: @ext_ctxt) -> ~str { - str::connect(self.map(|i| i.to_source(cx)), ~"\n\n") + fn to_source(&self) -> ~str { + str::connect(self.map(|i| i.to_source()), ~"\n\n") } } impl ToSource for @ast::Ty { - fn to_source(&self, cx: @ext_ctxt) -> ~str { - ty_to_str(*self, cx.parse_sess().interner) + fn to_source(&self) -> ~str { + ty_to_str(*self, get_ident_interner()) } } impl<'self> ToSource for &'self [@ast::Ty] { - fn to_source(&self, cx: @ext_ctxt) -> ~str { - str::connect(self.map(|i| i.to_source(cx)), ~", ") + fn to_source(&self) -> ~str { + str::connect(self.map(|i| i.to_source()), ~", ") } } impl ToSource for Generics { - fn to_source(&self, cx: @ext_ctxt) -> ~str { - pprust::generics_to_str(self, cx.parse_sess().interner) + fn to_source(&self) -> ~str { + pprust::generics_to_str(self, get_ident_interner()) } } impl ToSource for @ast::expr { - fn to_source(&self, cx: @ext_ctxt) -> ~str { - pprust::expr_to_str(*self, cx.parse_sess().interner) + fn to_source(&self) -> ~str { + pprust::expr_to_str(*self, get_ident_interner()) } } impl ToSource for ast::blk { - fn to_source(&self, cx: @ext_ctxt) -> ~str { - pprust::block_to_str(self, cx.parse_sess().interner) + fn to_source(&self) -> ~str { + pprust::block_to_str(self, get_ident_interner()) } } impl<'self> ToSource for &'self str { - fn to_source(&self, _cx: @ext_ctxt) -> ~str { + fn to_source(&self) -> ~str { let lit = dummy_spanned(ast::lit_str(@str::to_owned(*self))); pprust::lit_to_str(@lit) } } impl ToSource for int { - fn to_source(&self, _cx: @ext_ctxt) -> ~str { + fn to_source(&self) -> ~str { let lit = dummy_spanned(ast::lit_int(*self as i64, ast::ty_i)); pprust::lit_to_str(@lit) } } impl ToSource for i8 { - fn to_source(&self, _cx: @ext_ctxt) -> ~str { + fn to_source(&self) -> ~str { let lit = dummy_spanned(ast::lit_int(*self as i64, ast::ty_i8)); pprust::lit_to_str(@lit) } } impl ToSource for i16 { - fn to_source(&self, _cx: @ext_ctxt) -> ~str { + fn to_source(&self) -> ~str { let lit = dummy_spanned(ast::lit_int(*self as i64, ast::ty_i16)); pprust::lit_to_str(@lit) } @@ -150,49 +156,49 @@ pub mod rt { impl ToSource for i32 { - fn to_source(&self, _cx: @ext_ctxt) -> ~str { + fn to_source(&self) -> ~str { let lit = dummy_spanned(ast::lit_int(*self as i64, ast::ty_i32)); pprust::lit_to_str(@lit) } } impl ToSource for i64 { - fn to_source(&self, _cx: @ext_ctxt) -> ~str { + fn to_source(&self) -> ~str { let lit = dummy_spanned(ast::lit_int(*self as i64, ast::ty_i64)); pprust::lit_to_str(@lit) } } impl ToSource for uint { - fn to_source(&self, _cx: @ext_ctxt) -> ~str { + fn to_source(&self) -> ~str { let lit = dummy_spanned(ast::lit_uint(*self as u64, ast::ty_u)); pprust::lit_to_str(@lit) } } impl ToSource for u8 { - fn to_source(&self, _cx: @ext_ctxt) -> ~str { + fn to_source(&self) -> ~str { let lit = dummy_spanned(ast::lit_uint(*self as u64, ast::ty_u8)); pprust::lit_to_str(@lit) } } impl ToSource for u16 { - fn to_source(&self, _cx: @ext_ctxt) -> ~str { + fn to_source(&self) -> ~str { let lit = dummy_spanned(ast::lit_uint(*self as u64, ast::ty_u16)); pprust::lit_to_str(@lit) } } impl ToSource for u32 { - fn to_source(&self, _cx: @ext_ctxt) -> ~str { + fn to_source(&self) -> ~str { let lit = dummy_spanned(ast::lit_uint(*self as u64, ast::ty_u32)); pprust::lit_to_str(@lit) } } impl ToSource for u64 { - fn to_source(&self, _cx: @ext_ctxt) -> ~str { + fn to_source(&self) -> ~str { let lit = dummy_spanned(ast::lit_uint(*self as u64, ast::ty_u64)); pprust::lit_to_str(@lit) } @@ -201,116 +207,116 @@ pub mod rt { // Alas ... we write these out instead. All redundant. impl ToTokens for ast::ident { - fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] { - cx.parse_tts(self.to_source(cx)) + fn to_tokens(&self, cx: @ExtCtxt) -> ~[token_tree] { + cx.parse_tts(self.to_source()) } } impl ToTokens for @ast::item { - fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] { - cx.parse_tts(self.to_source(cx)) + fn to_tokens(&self, cx: @ExtCtxt) -> ~[token_tree] { + cx.parse_tts(self.to_source()) } } impl<'self> ToTokens for &'self [@ast::item] { - fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] { - cx.parse_tts(self.to_source(cx)) + fn to_tokens(&self, cx: @ExtCtxt) -> ~[token_tree] { + cx.parse_tts(self.to_source()) } } impl ToTokens for @ast::Ty { - fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] { - cx.parse_tts(self.to_source(cx)) + fn to_tokens(&self, cx: @ExtCtxt) -> ~[token_tree] { + cx.parse_tts(self.to_source()) } } impl<'self> ToTokens for &'self [@ast::Ty] { - fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] { - cx.parse_tts(self.to_source(cx)) + fn to_tokens(&self, cx: @ExtCtxt) -> ~[token_tree] { + cx.parse_tts(self.to_source()) } } impl ToTokens for Generics { - fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] { - cx.parse_tts(self.to_source(cx)) + fn to_tokens(&self, cx: @ExtCtxt) -> ~[token_tree] { + cx.parse_tts(self.to_source()) } } impl ToTokens for @ast::expr { - fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] { - cx.parse_tts(self.to_source(cx)) + fn to_tokens(&self, cx: @ExtCtxt) -> ~[token_tree] { + cx.parse_tts(self.to_source()) } } impl ToTokens for ast::blk { - fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] { - cx.parse_tts(self.to_source(cx)) + fn to_tokens(&self, cx: @ExtCtxt) -> ~[token_tree] { + cx.parse_tts(self.to_source()) } } impl<'self> ToTokens for &'self str { - fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] { - cx.parse_tts(self.to_source(cx)) + fn to_tokens(&self, cx: @ExtCtxt) -> ~[token_tree] { + cx.parse_tts(self.to_source()) } } impl ToTokens for int { - fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] { - cx.parse_tts(self.to_source(cx)) + fn to_tokens(&self, cx: @ExtCtxt) -> ~[token_tree] { + cx.parse_tts(self.to_source()) } } impl ToTokens for i8 { - fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] { - cx.parse_tts(self.to_source(cx)) + fn to_tokens(&self, cx: @ExtCtxt) -> ~[token_tree] { + cx.parse_tts(self.to_source()) } } impl ToTokens for i16 { - fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] { - cx.parse_tts(self.to_source(cx)) + fn to_tokens(&self, cx: @ExtCtxt) -> ~[token_tree] { + cx.parse_tts(self.to_source()) } } impl ToTokens for i32 { - fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] { - cx.parse_tts(self.to_source(cx)) + fn to_tokens(&self, cx: @ExtCtxt) -> ~[token_tree] { + cx.parse_tts(self.to_source()) } } impl ToTokens for i64 { - fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] { - cx.parse_tts(self.to_source(cx)) + fn to_tokens(&self, cx: @ExtCtxt) -> ~[token_tree] { + cx.parse_tts(self.to_source()) } } impl ToTokens for uint { - fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] { - cx.parse_tts(self.to_source(cx)) + fn to_tokens(&self, cx: @ExtCtxt) -> ~[token_tree] { + cx.parse_tts(self.to_source()) } } impl ToTokens for u8 { - fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] { - cx.parse_tts(self.to_source(cx)) + fn to_tokens(&self, cx: @ExtCtxt) -> ~[token_tree] { + cx.parse_tts(self.to_source()) } } impl ToTokens for u16 { - fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] { - cx.parse_tts(self.to_source(cx)) + fn to_tokens(&self, cx: @ExtCtxt) -> ~[token_tree] { + cx.parse_tts(self.to_source()) } } impl ToTokens for u32 { - fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] { - cx.parse_tts(self.to_source(cx)) + fn to_tokens(&self, cx: @ExtCtxt) -> ~[token_tree] { + cx.parse_tts(self.to_source()) } } impl ToTokens for u64 { - fn to_tokens(&self, cx: @ext_ctxt) -> ~[token_tree] { - cx.parse_tts(self.to_source(cx)) + fn to_tokens(&self, cx: @ExtCtxt) -> ~[token_tree] { + cx.parse_tts(self.to_source()) } } @@ -321,7 +327,7 @@ pub mod rt { fn parse_tts(&self, s: ~str) -> ~[ast::token_tree]; } - impl ExtParseUtils for @ext_ctxt { + impl ExtParseUtils for ExtCtxt { fn parse_item(&self, s: ~str) -> @ast::item { let res = parse::parse_item_from_source_str( @@ -367,74 +373,74 @@ pub mod rt { } -pub fn expand_quote_tokens(cx: @ext_ctxt, +pub fn expand_quote_tokens(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree]) -> base::MacResult { base::MRExpr(expand_tts(cx, sp, tts)) } -pub fn expand_quote_expr(cx: @ext_ctxt, +pub fn expand_quote_expr(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree]) -> base::MacResult { base::MRExpr(expand_parse_call(cx, sp, "parse_expr", ~[], tts)) } -pub fn expand_quote_item(cx: @ext_ctxt, +pub fn expand_quote_item(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree]) -> base::MacResult { - let e_attrs = build::mk_uniq_vec_e(cx, sp, ~[]); + let e_attrs = cx.expr_vec_uniq(sp, ~[]); base::MRExpr(expand_parse_call(cx, sp, "parse_item", ~[e_attrs], tts)) } -pub fn expand_quote_pat(cx: @ext_ctxt, +pub fn expand_quote_pat(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree]) -> base::MacResult { - let e_refutable = build::mk_lit(cx, sp, ast::lit_bool(true)); + let e_refutable = cx.expr_lit(sp, ast::lit_bool(true)); base::MRExpr(expand_parse_call(cx, sp, "parse_pat", ~[e_refutable], tts)) } -pub fn expand_quote_ty(cx: @ext_ctxt, +pub fn expand_quote_ty(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree]) -> base::MacResult { - let e_param_colons = build::mk_lit(cx, sp, ast::lit_bool(false)); + let e_param_colons = cx.expr_lit(sp, ast::lit_bool(false)); base::MRExpr(expand_parse_call(cx, sp, "parse_ty", ~[e_param_colons], tts)) } -pub fn expand_quote_stmt(cx: @ext_ctxt, +pub fn expand_quote_stmt(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree]) -> base::MacResult { - let e_attrs = build::mk_uniq_vec_e(cx, sp, ~[]); + let e_attrs = cx.expr_vec_uniq(sp, ~[]); base::MRExpr(expand_parse_call(cx, sp, "parse_stmt", ~[e_attrs], tts)) } -fn ids_ext(cx: @ext_ctxt, strs: ~[~str]) -> ~[ast::ident] { - strs.map(|str| cx.parse_sess().interner.intern(*str)) +fn ids_ext(strs: ~[~str]) -> ~[ast::ident] { + strs.map(|str| str_to_ident(*str)) } -fn id_ext(cx: @ext_ctxt, str: &str) -> ast::ident { - cx.parse_sess().interner.intern(str) +fn id_ext(str: &str) -> ast::ident { + str_to_ident(str) } // Lift an ident to the expr that evaluates to that ident. -fn mk_ident(cx: @ext_ctxt, sp: span, ident: ast::ident) -> @ast::expr { - let e_str = build::mk_uniq_str(cx, sp, cx.str_of(ident)); - build::mk_method_call(cx, sp, - build::mk_path(cx, sp, ids_ext(cx, ~[~"ext_cx"])), - id_ext(cx, "ident_of"), - ~[e_str]) +fn mk_ident(cx: @ExtCtxt, sp: span, ident: ast::ident) -> @ast::expr { + let e_str = cx.expr_str(sp, cx.str_of(ident)); + cx.expr_method_call(sp, + cx.expr_ident(sp, id_ext("ext_cx")), + id_ext("ident_of"), + ~[e_str]) } -fn mk_bytepos(cx: @ext_ctxt, sp: span, bpos: BytePos) -> @ast::expr { - let path = ids_ext(cx, ~[~"BytePos"]); - let arg = build::mk_uint(cx, sp, bpos.to_uint()); - build::mk_call(cx, sp, path, ~[arg]) +fn mk_bytepos(cx: @ExtCtxt, sp: span, bpos: BytePos) -> @ast::expr { + let path = id_ext("BytePos"); + let arg = cx.expr_uint(sp, bpos.to_uint()); + cx.expr_call_ident(sp, path, ~[arg]) } -fn mk_binop(cx: @ext_ctxt, sp: span, bop: token::binop) -> @ast::expr { +fn mk_binop(cx: @ExtCtxt, sp: span, bop: token::binop) -> @ast::expr { let name = match bop { PLUS => "PLUS", MINUS => "MINUS", @@ -447,22 +453,21 @@ fn mk_binop(cx: @ext_ctxt, sp: span, bop: token::binop) -> @ast::expr { SHL => "SHL", SHR => "SHR" }; - build::mk_path(cx, sp, - ids_ext(cx, ~[name.to_owned()])) + cx.expr_ident(sp, id_ext(name)) } -fn mk_token(cx: @ext_ctxt, sp: span, tok: &token::Token) -> @ast::expr { +fn mk_token(cx: @ExtCtxt, sp: span, tok: &token::Token) -> @ast::expr { match *tok { BINOP(binop) => { - return build::mk_call(cx, sp, - ids_ext(cx, ~[~"BINOP"]), - ~[mk_binop(cx, sp, binop)]); + return cx.expr_call_ident(sp, + id_ext("BINOP"), + ~[mk_binop(cx, sp, binop)]); } BINOPEQ(binop) => { - return build::mk_call(cx, sp, - ids_ext(cx, ~[~"BINOPEQ"]), - ~[mk_binop(cx, sp, binop)]); + return cx.expr_call_ident(sp, + id_ext("BINOPEQ"), + ~[mk_binop(cx, sp, binop)]); } LIT_INT(i, ity) => { @@ -474,15 +479,13 @@ fn mk_token(cx: @ext_ctxt, sp: span, tok: &token::Token) -> @ast::expr { ast::ty_i32 => ~"ty_i32", ast::ty_i64 => ~"ty_i64" }; - let e_ity = - build::mk_path(cx, sp, - ids_ext(cx, ~[s_ity])); + let e_ity = cx.expr_ident(sp, id_ext(s_ity)); - let e_i64 = build::mk_lit(cx, sp, ast::lit_int(i, ast::ty_i64)); + let e_i64 = cx.expr_lit(sp, ast::lit_int(i, ast::ty_i64)); - return build::mk_call(cx, sp, - ids_ext(cx, ~[~"LIT_INT"]), - ~[e_i64, e_ity]); + return cx.expr_call_ident(sp, + id_ext("LIT_INT"), + ~[e_i64, e_ity]); } LIT_UINT(u, uty) => { @@ -493,24 +496,21 @@ fn mk_token(cx: @ext_ctxt, sp: span, tok: &token::Token) -> @ast::expr { ast::ty_u32 => ~"ty_u32", ast::ty_u64 => ~"ty_u64" }; - let e_uty = - build::mk_path(cx, sp, - ids_ext(cx, ~[s_uty])); + let e_uty = cx.expr_ident(sp, id_ext(s_uty)); - let e_u64 = build::mk_lit(cx, sp, ast::lit_uint(u, ast::ty_u64)); + let e_u64 = cx.expr_lit(sp, ast::lit_uint(u, ast::ty_u64)); - return build::mk_call(cx, sp, - ids_ext(cx, ~[~"LIT_UINT"]), - ~[e_u64, e_uty]); + return cx.expr_call_ident(sp, + id_ext("LIT_UINT"), + ~[e_u64, e_uty]); } LIT_INT_UNSUFFIXED(i) => { - let e_i64 = build::mk_lit(cx, sp, - ast::lit_int(i, ast::ty_i64)); + let e_i64 = cx.expr_lit(sp, ast::lit_int(i, ast::ty_i64)); - return build::mk_call(cx, sp, - ids_ext(cx, ~[~"LIT_INT_UNSUFFIXED"]), - ~[e_i64]); + return cx.expr_call_ident(sp, + id_ext("LIT_INT_UNSUFFIXED"), + ~[e_i64]); } LIT_FLOAT(fident, fty) => { @@ -519,40 +519,38 @@ fn mk_token(cx: @ext_ctxt, sp: span, tok: &token::Token) -> @ast::expr { ast::ty_f32 => ~"ty_f32", ast::ty_f64 => ~"ty_f64" }; - let e_fty = - build::mk_path(cx, sp, - ids_ext(cx, ~[s_fty])); + let e_fty = cx.expr_ident(sp, id_ext(s_fty)); let e_fident = mk_ident(cx, sp, fident); - return build::mk_call(cx, sp, - ids_ext(cx, ~[~"LIT_FLOAT"]), - ~[e_fident, e_fty]); + return cx.expr_call_ident(sp, + id_ext("LIT_FLOAT"), + ~[e_fident, e_fty]); } LIT_STR(ident) => { - return build::mk_call(cx, sp, - ids_ext(cx, ~[~"LIT_STR"]), - ~[mk_ident(cx, sp, ident)]); + return cx.expr_call_ident(sp, + id_ext("LIT_STR"), + ~[mk_ident(cx, sp, ident)]); } IDENT(ident, b) => { - return build::mk_call(cx, sp, - ids_ext(cx, ~[~"IDENT"]), - ~[mk_ident(cx, sp, ident), - build::mk_lit(cx, sp, ast::lit_bool(b))]); + return cx.expr_call_ident(sp, + id_ext("IDENT"), + ~[mk_ident(cx, sp, ident), + cx.expr_bool(sp, b)]); } LIFETIME(ident) => { - return build::mk_call(cx, sp, - ids_ext(cx, ~[~"LIFETIME"]), - ~[mk_ident(cx, sp, ident)]); + return cx.expr_call_ident(sp, + id_ext("LIFETIME"), + ~[mk_ident(cx, sp, ident)]); } DOC_COMMENT(ident) => { - return build::mk_call(cx, sp, - ids_ext(cx, ~[~"DOC_COMMENT"]), - ~[mk_ident(cx, sp, ident)]); + return cx.expr_call_ident(sp, + id_ext("DOC_COMMENT"), + ~[mk_ident(cx, sp, ident)]); } INTERPOLATED(_) => fail!("quote! with interpolated token"), @@ -595,30 +593,26 @@ fn mk_token(cx: @ext_ctxt, sp: span, tok: &token::Token) -> @ast::expr { EOF => "EOF", _ => fail!() }; - build::mk_path(cx, sp, - ids_ext(cx, ~[name.to_owned()])) + cx.expr_ident(sp, id_ext(name)) } -fn mk_tt(cx: @ext_ctxt, sp: span, tt: &ast::token_tree) +fn mk_tt(cx: @ExtCtxt, sp: span, tt: &ast::token_tree) -> ~[@ast::stmt] { match *tt { ast::tt_tok(sp, ref tok) => { - let e_sp = build::mk_path(cx, sp, - ids_ext(cx, ~[~"sp"])); - let e_tok = - build::mk_call(cx, sp, - ids_ext(cx, ~[~"tt_tok"]), - ~[e_sp, mk_token(cx, sp, tok)]); + let e_sp = cx.expr_ident(sp, id_ext("sp")); + let e_tok = cx.expr_call_ident(sp, + id_ext("tt_tok"), + ~[e_sp, mk_token(cx, sp, tok)]); let e_push = - build::mk_method_call(cx, sp, - build::mk_path(cx, sp, ids_ext(cx, ~[~"tt"])), - id_ext(cx, "push"), - ~[e_tok]); - ~[build::mk_stmt(cx, sp, e_push)] - + cx.expr_method_call(sp, + cx.expr_ident(sp, id_ext("tt")), + id_ext("push"), + ~[e_tok]); + ~[cx.stmt_expr(e_push)] } ast::tt_delim(ref tts) => mk_tts(cx, sp, *tts), @@ -629,24 +623,23 @@ fn mk_tt(cx: @ext_ctxt, sp: span, tt: &ast::token_tree) // tt.push_all_move($ident.to_tokens(ext_cx)) let e_to_toks = - build::mk_method_call(cx, sp, - build::mk_path(cx, sp, ~[ident]), - id_ext(cx, "to_tokens"), - ~[build::mk_path(cx, sp, - ids_ext(cx, ~[~"ext_cx"]))]); + cx.expr_method_call(sp, + cx.expr_ident(sp, ident), + id_ext("to_tokens"), + ~[cx.expr_ident(sp, id_ext("ext_cx"))]); let e_push = - build::mk_method_call(cx, sp, - build::mk_path(cx, sp, ids_ext(cx, ~[~"tt"])), - id_ext(cx, "push_all_move"), - ~[e_to_toks]); + cx.expr_method_call(sp, + cx.expr_ident(sp, id_ext("tt")), + id_ext("push_all_move"), + ~[e_to_toks]); - ~[build::mk_stmt(cx, sp, e_push)] + ~[cx.stmt_expr(e_push)] } } } -fn mk_tts(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree]) +fn mk_tts(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree]) -> ~[@ast::stmt] { let mut ss = ~[]; for tts.each |tt| { @@ -655,7 +648,7 @@ fn mk_tts(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree]) ss } -fn expand_tts(cx: @ext_ctxt, +fn expand_tts(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree]) -> @ast::expr { @@ -677,11 +670,11 @@ fn expand_tts(cx: @ext_ctxt, // We want to emit a block expression that does a sequence of 'use's to // import the runtime module, followed by a tt-building expression. - let uses = ~[ build::mk_glob_use(cx, sp, ast::public, - ids_ext(cx, ~[~"syntax", - ~"ext", - ~"quote", - ~"rt"])) ]; + let uses = ~[ cx.view_use_glob(sp, ast::public, + ids_ext(~[~"syntax", + ~"ext", + ~"quote", + ~"rt"])) ]; // We also bind a single value, sp, to ext_cx.call_site() // @@ -709,54 +702,53 @@ fn expand_tts(cx: @ext_ctxt, // of quotes, for example) but at this point it seems not likely to be // worth the hassle. - let e_sp = build::mk_method_call(cx, sp, - build::mk_path(cx, sp, ids_ext(cx, ~[~"ext_cx"])), - id_ext(cx, "call_site"), - ~[]); + let e_sp = cx.expr_method_call(sp, + cx.expr_ident(sp, id_ext("ext_cx")), + id_ext("call_site"), + ~[]); - let stmt_let_sp = build::mk_local(cx, sp, false, - id_ext(cx, "sp"), - e_sp); + let stmt_let_sp = cx.stmt_let(sp, false, + id_ext("sp"), + e_sp); - let stmt_let_tt = build::mk_local(cx, sp, true, - id_ext(cx, "tt"), - build::mk_uniq_vec_e(cx, sp, ~[])); + let stmt_let_tt = cx.stmt_let(sp, true, + id_ext("tt"), + cx.expr_vec_uniq(sp, ~[])); - build::mk_block(cx, sp, uses, - ~[stmt_let_sp, - stmt_let_tt] + mk_tts(cx, sp, tts), - Some(build::mk_path(cx, sp, - ids_ext(cx, ~[~"tt"])))) + cx.expr_blk( + cx.blk_all(sp, uses, + ~[stmt_let_sp, + stmt_let_tt] + mk_tts(cx, sp, tts), + Some(cx.expr_ident(sp, id_ext("tt"))))) } -fn expand_parse_call(cx: @ext_ctxt, +fn expand_parse_call(cx: @ExtCtxt, sp: span, parse_method: &str, arg_exprs: ~[@ast::expr], tts: &[ast::token_tree]) -> @ast::expr { let tts_expr = expand_tts(cx, sp, tts); - let cfg_call = || build::mk_method_call( - cx, sp, build::mk_path(cx, sp, ids_ext(cx, ~[~"ext_cx"])), - id_ext(cx, "cfg"), ~[]); + let cfg_call = || cx.expr_method_call( + sp, cx.expr_ident(sp, id_ext("ext_cx")), + id_ext("cfg"), ~[]); - let parse_sess_call = || build::mk_method_call( - cx, sp, build::mk_path(cx, sp, ids_ext(cx, ~[~"ext_cx"])), - id_ext(cx, "parse_sess"), ~[]); + let parse_sess_call = || cx.expr_method_call( + sp, cx.expr_ident(sp, id_ext("ext_cx")), + id_ext("parse_sess"), ~[]); let new_parser_call = - build::mk_call_global(cx, sp, - ids_ext(cx, ~[~"syntax", - ~"ext", - ~"quote", - ~"rt", - ~"new_parser_from_tts"]), - ~[parse_sess_call(), - cfg_call(), - tts_expr]); - - build::mk_method_call(cx, sp, - new_parser_call, - id_ext(cx, parse_method), - arg_exprs) + cx.expr_call_global(sp, + ids_ext(~[~"syntax", + ~"ext", + ~"quote", + ~"rt", + ~"new_parser_from_tts"]), + ~[parse_sess_call(), + cfg_call(), + tts_expr]); + + cx.expr_method_call(sp, new_parser_call, + id_ext(parse_method), + arg_exprs) } diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs index ab22b3152f477..fcdfb0a6ba7b6 100644 --- a/src/libsyntax/ext/source_util.rs +++ b/src/libsyntax/ext/source_util.rs @@ -8,72 +8,80 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use ast; use codemap; use codemap::{FileMap, Loc, Pos, ExpandedFrom, span}; use codemap::{CallInfo, NameAndSpan}; use ext::base::*; use ext::base; -use ext::build::{mk_base_vec_e, mk_uint, mk_u8, mk_base_str}; +use ext::build::AstBuilder; use parse; +use parse::token::{get_ident_interner}; use print::pprust; +use core::io; +use core::result; +use core::str; +use core::vec; + // These macros all relate to the file system; they either return // the column/row/filename of the expression, or they include // a given file into the current one. /* line!(): expands to the current line number */ -pub fn expand_line(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree]) +pub fn expand_line(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree]) -> base::MacResult { base::check_zero_tts(cx, sp, tts, "line!"); let topmost = topmost_expn_info(cx.backtrace().get()); let loc = cx.codemap().lookup_char_pos(topmost.call_site.lo); - base::MRExpr(mk_uint(cx, topmost.call_site, loc.line)) + base::MRExpr(cx.expr_uint(topmost.call_site, loc.line)) } /* col!(): expands to the current column number */ -pub fn expand_col(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree]) +pub fn expand_col(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree]) -> base::MacResult { base::check_zero_tts(cx, sp, tts, "col!"); let topmost = topmost_expn_info(cx.backtrace().get()); let loc = cx.codemap().lookup_char_pos(topmost.call_site.lo); - base::MRExpr(mk_uint(cx, topmost.call_site, loc.col.to_uint())) + base::MRExpr(cx.expr_uint(topmost.call_site, loc.col.to_uint())) } /* file!(): expands to the current filename */ /* The filemap (`loc.file`) contains a bunch more information we could spit * out if we wanted. */ -pub fn expand_file(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree]) +pub fn expand_file(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree]) -> base::MacResult { base::check_zero_tts(cx, sp, tts, "file!"); let topmost = topmost_expn_info(cx.backtrace().get()); - let Loc { file: @FileMap { name: filename, _ }, _ } = - cx.codemap().lookup_char_pos(topmost.call_site.lo); - base::MRExpr(mk_base_str(cx, topmost.call_site, filename)) + let loc = cx.codemap().lookup_char_pos(topmost.call_site.lo); + let filename = copy loc.file.name; + base::MRExpr(cx.expr_str(topmost.call_site, filename)) } -pub fn expand_stringify(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree]) +pub fn expand_stringify(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree]) -> base::MacResult { - let s = pprust::tts_to_str(tts, cx.parse_sess().interner); - base::MRExpr(mk_base_str(cx, sp, s)) + let s = pprust::tts_to_str(tts, get_ident_interner()); + base::MRExpr(cx.expr_str(sp, s)) } -pub fn expand_mod(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree]) +pub fn expand_mod(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree]) -> base::MacResult { base::check_zero_tts(cx, sp, tts, "module_path!"); - base::MRExpr(mk_base_str(cx, sp, + base::MRExpr(cx.expr_str(sp, str::connect(cx.mod_path().map( - |x| cx.str_of(*x)), ~"::"))) + |x| cx.str_of(*x)), "::"))) } // include! : parse the given file as an expr // This is generally a bad idea because it's going to behave // unhygienically. -pub fn expand_include(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree]) +pub fn expand_include(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree]) -> base::MacResult { let file = get_single_str_from_tts(cx, sp, tts, "include!"); let p = parse::new_sub_parser_from_file( @@ -83,7 +91,7 @@ pub fn expand_include(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree]) } // include_str! : read the given file, insert it as a literal string expr -pub fn expand_include_str(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree]) +pub fn expand_include_str(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree]) -> base::MacResult { let file = get_single_str_from_tts(cx, sp, tts, "include_str!"); let res = io::read_whole_file_str(&res_rel_file(cx, sp, &Path(file))); @@ -94,18 +102,18 @@ pub fn expand_include_str(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree]) } } - base::MRExpr(mk_base_str(cx, sp, result::unwrap(res))) + base::MRExpr(cx.expr_str(sp, result::unwrap(res))) } -pub fn expand_include_bin(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree]) +pub fn expand_include_bin(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree]) -> base::MacResult { let file = get_single_str_from_tts(cx, sp, tts, "include_bin!"); match io::read_whole_file(&res_rel_file(cx, sp, &Path(file))) { result::Ok(src) => { let u8_exprs = vec::map(src, |char| { - mk_u8(cx, sp, *char) + cx.expr_u8(sp, *char) }); - base::MRExpr(mk_base_vec_e(cx, sp, u8_exprs)) + base::MRExpr(cx.expr_vec(sp, u8_exprs)) } result::Err(ref e) => { cx.parse_sess().span_diagnostic.handler().fatal((*e)) @@ -141,7 +149,7 @@ fn topmost_expn_info(expn_info: @codemap::ExpnInfo) -> @codemap::ExpnInfo { // resolve a file-system path to an absolute file-system path (if it // isn't already) -fn res_rel_file(cx: @ext_ctxt, sp: codemap::span, arg: &Path) -> Path { +fn res_rel_file(cx: @ExtCtxt, sp: codemap::span, arg: &Path) -> Path { // NB: relative paths are resolved relative to the compilation unit if !arg.is_absolute { let cu = Path(cx.codemap().span_to_filename(sp)); diff --git a/src/libsyntax/ext/trace_macros.rs b/src/libsyntax/ext/trace_macros.rs index 1bb4080814226..3baf432f24d65 100644 --- a/src/libsyntax/ext/trace_macros.rs +++ b/src/libsyntax/ext/trace_macros.rs @@ -8,14 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use ast; use codemap::span; -use ext::base::ext_ctxt; +use ext::base::ExtCtxt; use ext::base; use parse::lexer::{new_tt_reader, reader}; use parse::parser::Parser; +use parse::token::keywords; + +use core::vec; -pub fn expand_trace_macros(cx: @ext_ctxt, +pub fn expand_trace_macros(cx: @ExtCtxt, sp: span, tt: &[ast::token_tree]) -> base::MacResult { @@ -23,7 +28,6 @@ pub fn expand_trace_macros(cx: @ext_ctxt, let cfg = cx.cfg(); let tt_rdr = new_tt_reader( copy cx.parse_sess().span_diagnostic, - cx.parse_sess().interner, None, vec::to_owned(tt) ); @@ -34,12 +38,12 @@ pub fn expand_trace_macros(cx: @ext_ctxt, rdr.dup() ); - if rust_parser.is_keyword("true") { + if rust_parser.is_keyword(keywords::True) { cx.set_trace_macros(true); - } else if rust_parser.is_keyword("false") { + } else if rust_parser.is_keyword(keywords::False) { cx.set_trace_macros(false); } else { - cx.span_fatal(sp, ~"trace_macros! only accepts `true` or `false`") + cx.span_fatal(sp, "trace_macros! only accepts `true` or `false`") } rust_parser.bump(); diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index aa211973f1c52..9fb9def84e9cb 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -9,6 +9,9 @@ // except according to those terms. // Earley-like parser for macros. + +use core::prelude::*; + use ast; use ast::{matcher, match_tok, match_seq, match_nonterminal, ident}; use codemap::{BytePos, mk_sp}; @@ -16,10 +19,13 @@ use codemap; use parse::lexer::*; //resolve bug? use parse::ParseSess; use parse::parser::Parser; -use parse::token::{Token, EOF, to_str, nonterminal}; +use parse::token::{Token, EOF, to_str, nonterminal, get_ident_interner, ident_to_str}; use parse::token; use core::hashmap::HashMap; +use core::str; +use core::uint; +use core::vec; /* This is an Earley-like parser, without support for in-grammar nonterminals, only by calling out to the main rust parser for named nonterminals (which it @@ -195,13 +201,13 @@ pub fn nameize(p_s: @mut ParseSess, ms: &[matcher], res: &[@named_match]) }; } codemap::spanned { - node: match_nonterminal(bind_name, _, idx), span: sp + node: match_nonterminal(ref bind_name, _, idx), span: sp } => { - if ret_val.contains_key(&bind_name) { + if ret_val.contains_key(bind_name) { p_s.span_diagnostic.span_fatal(sp, ~"Duplicated bind name: "+ - *p_s.interner.get(bind_name)) + *ident_to_str(bind_name)) } - ret_val.insert(bind_name, res[idx]); + ret_val.insert(*bind_name, res[idx]); } } } @@ -366,19 +372,19 @@ pub fn parse( || bb_eis.len() > 1u { let nts = str::connect(vec::map(bb_eis, |ei| { match ei.elts[ei.idx].node { - match_nonterminal(bind,name,_) => { - fmt!("%s ('%s')", *sess.interner.get(name), - *sess.interner.get(bind)) + match_nonterminal(ref bind,ref name,_) => { + fmt!("%s ('%s')", *ident_to_str(name), + *ident_to_str(bind)) } _ => fail!() - } }), ~" or "); + } }), " or "); return error(sp, fmt!( "Local ambiguity: multiple parsing options: \ built-in NTs %s or %u other options.", nts, next_eis.len())); } else if (bb_eis.len() == 0u && next_eis.len() == 0u) { return failure(sp, ~"No rules expected the token: " - + to_str(rdr.interner(), &tok)); + + to_str(get_ident_interner(), &tok)); } else if (next_eis.len() > 0u) { /* Now process the next token */ while(next_eis.len() > 0u) { @@ -390,9 +396,9 @@ pub fn parse( let mut ei = bb_eis.pop(); match ei.elts[ei.idx].node { - match_nonterminal(_, name, idx) => { + match_nonterminal(_, ref name, idx) => { ei.matches[idx].push(@matched_nonterminal( - parse_nt(&rust_parser, *sess.interner.get(name)))); + parse_nt(&rust_parser, *ident_to_str(name)))); ei.idx += 1u; } _ => fail!() @@ -413,18 +419,18 @@ pub fn parse_nt(p: &Parser, name: &str) -> nonterminal { match name { "item" => match p.parse_item(~[]) { Some(i) => token::nt_item(i), - None => p.fatal(~"expected an item keyword") + None => p.fatal("expected an item keyword") }, "block" => token::nt_block(p.parse_block()), "stmt" => token::nt_stmt(p.parse_stmt(~[])), - "pat" => token::nt_pat(p.parse_pat(true)), + "pat" => token::nt_pat(p.parse_pat()), "expr" => token::nt_expr(p.parse_expr()), "ty" => token::nt_ty(p.parse_ty(false /* no need to disambiguate*/)), // this could be handled like a token, since it is one "ident" => match *p.token { token::IDENT(sn,b) => { p.bump(); token::nt_ident(sn,b) } _ => p.fatal(~"expected ident, found " - + token::to_str(p.reader.interner(), © *p.token)) + + token::to_str(get_ident_interner(), © *p.token)) }, "path" => token::nt_path(p.parse_path_with_tps(false)), "tt" => { diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index be6cc7a846ad3..1822117507d7f 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -8,25 +8,27 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; use ast::{ident, matcher_, matcher, match_tok, match_nonterminal, match_seq}; use ast::{tt_delim}; use ast; use codemap::{span, spanned, dummy_sp}; -use ext::base::{ext_ctxt, MacResult, MRAny, MRDef, MacroDef, NormalTT}; +use ext::base::{ExtCtxt, MacResult, MRAny, MRDef, MacroDef, NormalTT}; use ext::base; use ext::tt::macro_parser::{error}; use ext::tt::macro_parser::{named_match, matched_seq, matched_nonterminal}; use ext::tt::macro_parser::{parse, parse_or_else, success, failure}; use parse::lexer::{new_tt_reader, reader}; use parse::parser::Parser; -use parse::token::special_idents; +use parse::token::{get_ident_interner, special_idents, gensym_ident, ident_to_str}; use parse::token::{FAT_ARROW, SEMI, nt_matchers, nt_tt}; use print; use core::io; +use core::vec; -pub fn add_new_extension(cx: @ext_ctxt, +pub fn add_new_extension(cx: @ExtCtxt, sp: span, name: ident, arg: ~[ast::token_tree]) @@ -36,8 +38,8 @@ pub fn add_new_extension(cx: @ext_ctxt, spanned { node: copy m, span: dummy_sp() } } - let lhs_nm = cx.parse_sess().interner.gensym("lhs"); - let rhs_nm = cx.parse_sess().interner.gensym("rhs"); + let lhs_nm = gensym_ident("lhs"); + let rhs_nm = gensym_ident("rhs"); // The grammar for macro_rules! is: // $( $lhs:mtcs => $rhs:tt );+ @@ -55,7 +57,7 @@ pub fn add_new_extension(cx: @ext_ctxt, // Parse the macro_rules! invocation (`none` is for no interpolations): let arg_reader = new_tt_reader(copy cx.parse_sess().span_diagnostic, - cx.parse_sess().interner, None, copy arg); + None, copy arg); let argument_map = parse_or_else(cx.parse_sess(), cx.cfg(), arg_reader as @reader, @@ -64,16 +66,16 @@ pub fn add_new_extension(cx: @ext_ctxt, // Extract the arguments: let lhses = match *argument_map.get(&lhs_nm) { @matched_seq(ref s, _) => /* FIXME (#2543) */ @copy *s, - _ => cx.span_bug(sp, ~"wrong-structured lhs") + _ => cx.span_bug(sp, "wrong-structured lhs") }; let rhses = match *argument_map.get(&rhs_nm) { @matched_seq(ref s, _) => /* FIXME (#2543) */ @copy *s, - _ => cx.span_bug(sp, ~"wrong-structured rhs") + _ => cx.span_bug(sp, "wrong-structured rhs") }; // Given `lhses` and `rhses`, this is the new macro we create - fn generic_extension(cx: @ext_ctxt, sp: span, name: ident, + fn generic_extension(cx: @ExtCtxt, sp: span, name: ident, arg: &[ast::token_tree], lhses: &[@named_match], rhses: &[@named_match]) -> MacResult { @@ -83,7 +85,7 @@ pub fn add_new_extension(cx: @ext_ctxt, cx.str_of(name), print::pprust::tt_to_str( ast::tt_delim(vec::to_owned(arg)), - cx.parse_sess().interner))); + get_ident_interner()))); } // Which arm's failure should we report? (the one furthest along) @@ -91,7 +93,6 @@ pub fn add_new_extension(cx: @ext_ctxt, let mut best_fail_msg = ~"internal error: ran no matchers"; let s_d = cx.parse_sess().span_diagnostic; - let itr = cx.parse_sess().interner; for lhses.eachi |i, lhs| { // try each arm's matchers match *lhs { @@ -99,7 +100,6 @@ pub fn add_new_extension(cx: @ext_ctxt, // `none` is because we're not interpolating let arg_rdr = new_tt_reader( s_d, - itr, None, vec::to_owned(arg) ) as @reader; @@ -114,13 +114,13 @@ pub fn add_new_extension(cx: @ext_ctxt, (*tts).slice(1u,(*tts).len()-1u).to_owned() } _ => cx.span_fatal( - sp, ~"macro rhs must be delimited") + sp, "macro rhs must be delimited") } }, - _ => cx.span_bug(sp, ~"bad thing in rhs") + _ => cx.span_bug(sp, "bad thing in rhs") }; // rhs has holes ( `$id` and `$(...)` that need filled) - let trncbr = new_tt_reader(s_d, itr, Some(named_matches), + let trncbr = new_tt_reader(s_d, Some(named_matches), rhs); let p = @Parser(cx.parse_sess(), cx.cfg(), @@ -139,17 +139,17 @@ pub fn add_new_extension(cx: @ext_ctxt, error(sp, ref msg) => cx.span_fatal(sp, (*msg)) } } - _ => cx.bug(~"non-matcher found in parsed lhses") + _ => cx.bug("non-matcher found in parsed lhses") } } cx.span_fatal(best_fail_spot, best_fail_msg); } - let exp: @fn(@ext_ctxt, span, &[ast::token_tree]) -> MacResult = + let exp: @fn(@ExtCtxt, span, &[ast::token_tree]) -> MacResult = |cx, sp, arg| generic_extension(cx, sp, name, arg, *lhses, *rhses); return MRDef(MacroDef{ - name: copy *cx.parse_sess().interner.get(name), + name: copy *ident_to_str(&name), ext: NormalTT(base::SyntaxExpanderTT{expander: exp, span: Some(sp)}) }); } diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 438efb2326c7a..f0b078603dbd0 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -8,15 +8,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use ast; use ast::{token_tree, tt_delim, tt_tok, tt_seq, tt_nonterminal,ident}; use codemap::{span, dummy_sp}; use diagnostic::span_handler; use ext::tt::macro_parser::{named_match, matched_seq, matched_nonterminal}; -use parse::token::{EOF, INTERPOLATED, IDENT, Token, nt_ident, ident_interner}; +use parse::token::{EOF, INTERPOLATED, IDENT, Token, nt_ident}; +use parse::token::{ident_to_str}; use parse::lexer::TokenAndSpan; use core::hashmap::HashMap; +use core::option; +use core::vec; ///an unzipping of `token_tree`s struct TtFrame { @@ -29,7 +34,6 @@ struct TtFrame { pub struct TtReader { sp_diag: @span_handler, - interner: @ident_interner, // the unzipped tree: stack: @mut TtFrame, /* for MBE-style macro transcription */ @@ -45,13 +49,11 @@ pub struct TtReader { * `src` contains no `tt_seq`s and `tt_nonterminal`s, `interp` can (and * should) be none. */ pub fn new_tt_reader(sp_diag: @span_handler, - itr: @ident_interner, interp: Option>, src: ~[ast::token_tree]) -> @mut TtReader { let r = @mut TtReader { sp_diag: sp_diag, - interner: itr, stack: @mut TtFrame { forest: @mut src, idx: 0u, @@ -89,7 +91,6 @@ fn dup_tt_frame(f: @mut TtFrame) -> @mut TtFrame { pub fn dup_tt_reader(r: @mut TtReader) -> @mut TtReader { @mut TtReader { sp_diag: r.sp_diag, - interner: r.interner, stack: dup_tt_frame(r.stack), repeat_idx: copy r.repeat_idx, repeat_len: copy r.repeat_len, @@ -118,10 +119,13 @@ fn lookup_cur_matched_by_matched(r: &mut TtReader, } fn lookup_cur_matched(r: &mut TtReader, name: ident) -> @named_match { - // FIXME (#3850): this looks a bit silly with an extra scope. - let start; - { start = *r.interpolations.get(&name); } - return lookup_cur_matched_by_matched(r, start); + match r.interpolations.find_copy(&name) { + Some(s) => lookup_cur_matched_by_matched(r, s), + None => { + r.sp_diag.span_fatal(r.cur_span, fmt!("unknown macro variable `%s`", + *ident_to_str(&name))); + } + } } enum lis { lis_unconstrained, lis_constraint(uint, ident), lis_contradiction(~str) @@ -132,13 +136,13 @@ fn lockstep_iter_size(t: &token_tree, r: &mut TtReader) -> lis { match lhs { lis_unconstrained => copy rhs, lis_contradiction(_) => copy lhs, - lis_constraint(l_len, l_id) => match rhs { + lis_constraint(l_len, ref l_id) => match rhs { lis_unconstrained => copy lhs, lis_contradiction(_) => copy rhs, lis_constraint(r_len, _) if l_len == r_len => copy lhs, - lis_constraint(r_len, r_id) => { - let l_n = copy *r.interner.get(l_id); - let r_n = copy *r.interner.get(r_id); + lis_constraint(r_len, ref r_id) => { + let l_n = copy *ident_to_str(l_id); + let r_n = copy *ident_to_str(r_id); lis_contradiction(fmt!("Inconsistent lockstep iteration: \ '%s' has %u items, but '%s' has %u", l_n, l_len, r_n, r_len)) @@ -200,8 +204,8 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { } else { /* repeat */ r.stack.idx = 0u; r.repeat_idx[r.repeat_idx.len() - 1u] += 1u; - match r.stack.sep { - Some(copy tk) => { + match copy r.stack.sep { + Some(tk) => { r.cur_tok = tk; /* repeat same span, I guess */ return ret_val; } @@ -211,8 +215,8 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { } loop { /* because it's easiest, this handles `tt_delim` not starting with a `tt_tok`, even though it won't happen */ - match r.stack.forest[r.stack.idx] { - tt_delim(copy tts) => { + match copy r.stack.forest[r.stack.idx] { + tt_delim(tts) => { r.stack = @mut TtFrame { forest: @mut tts, idx: 0u, @@ -222,21 +226,21 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { }; // if this could be 0-length, we'd need to potentially recur here } - tt_tok(sp, copy tok) => { + tt_tok(sp, tok) => { r.cur_span = sp; r.cur_tok = tok; r.stack.idx += 1u; return ret_val; } - tt_seq(sp, copy tts, copy sep, zerok) => { + tt_seq(sp, tts, sep, zerok) => { let t = tt_seq(sp, copy tts, copy sep, zerok); match lockstep_iter_size(&t, r) { lis_unconstrained => { r.sp_diag.span_fatal( sp, /* blame macro writer */ - ~"attempted to repeat an expression \ - containing no syntax \ - variables matched as repeating at this depth"); + "attempted to repeat an expression \ + containing no syntax \ + variables matched as repeating at this depth"); } lis_contradiction(ref msg) => { /* FIXME #2887 blame macro invoker instead*/ @@ -247,8 +251,8 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { if !zerok { r.sp_diag.span_fatal(sp, /* FIXME #2887 blame invoker */ - ~"this must repeat at least \ - once"); + "this must repeat at least \ + once"); } r.stack.idx += 1u; @@ -288,7 +292,7 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { r.sp_diag.span_fatal( copy r.cur_span, /* blame the macro writer */ fmt!("variable '%s' is still repeating at this depth", - *r.interner.get(ident))); + *ident_to_str(&ident))); } } } diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 275a7b963a4bf..d419ce6f18857 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -8,11 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use ast::*; use ast; use codemap::{span, spanned}; use opt_vec::OptVec; +use core::vec; + pub trait ast_fold { fn fold_crate(@self, &crate) -> crate; fn fold_view_item(@self, @view_item) -> @view_item; @@ -22,10 +26,10 @@ pub trait ast_fold { fn fold_item_underscore(@self, &item_) -> item_; fn fold_method(@self, @method) -> @method; fn fold_block(@self, &blk) -> blk; - fn fold_stmt(@self, &stmt) -> @stmt; + fn fold_stmt(@self, &stmt) -> Option<@stmt>; fn fold_arm(@self, &arm) -> arm; fn fold_pat(@self, @pat) -> @pat; - fn fold_decl(@self, @decl) -> @decl; + fn fold_decl(@self, @decl) -> Option<@decl>; fn fold_expr(@self, @expr) -> @expr; fn fold_ty(@self, @Ty) -> @Ty; fn fold_mod(@self, &_mod) -> _mod; @@ -51,10 +55,10 @@ pub struct AstFoldFns { fold_item_underscore: @fn(&item_, @ast_fold) -> item_, fold_method: @fn(@method, @ast_fold) -> @method, fold_block: @fn(&blk_, span, @ast_fold) -> (blk_, span), - fold_stmt: @fn(&stmt_, span, @ast_fold) -> (stmt_, span), + fold_stmt: @fn(&stmt_, span, @ast_fold) -> (Option, span), fold_arm: @fn(&arm, @ast_fold) -> arm, fold_pat: @fn(&pat_, span, @ast_fold) -> (pat_, span), - fold_decl: @fn(&decl_, span, @ast_fold) -> (decl_, span), + fold_decl: @fn(&decl_, span, @ast_fold) -> (Option, span), fold_expr: @fn(&expr_, span, @ast_fold) -> (expr_, span), fold_ty: @fn(&ty_, span, @ast_fold) -> (ty_, span), fold_mod: @fn(&_mod, @ast_fold) -> _mod, @@ -336,22 +340,39 @@ fn noop_fold_method(m: @method, fld: @ast_fold) -> @method { pub fn noop_fold_block(b: &blk_, fld: @ast_fold) -> blk_ { + let view_items = b.view_items.map(|x| fld.fold_view_item(*x)); + let mut stmts = ~[]; + for b.stmts.each |stmt| { + match fld.fold_stmt(*stmt) { + None => {} + Some(stmt) => stmts.push(stmt) + } + } ast::blk_ { - view_items: b.view_items.map(|x| fld.fold_view_item(*x)), - stmts: b.stmts.map(|x| fld.fold_stmt(*x)), + view_items: view_items, + stmts: stmts, expr: b.expr.map(|x| fld.fold_expr(*x)), id: fld.new_id(b.id), rules: b.rules, } } -fn noop_fold_stmt(s: &stmt_, fld: @ast_fold) -> stmt_ { +fn noop_fold_stmt(s: &stmt_, fld: @ast_fold) -> Option { let fold_mac = |x| fold_mac_(x, fld); match *s { - stmt_decl(d, nid) => stmt_decl(fld.fold_decl(d), fld.new_id(nid)), - stmt_expr(e, nid) => stmt_expr(fld.fold_expr(e), fld.new_id(nid)), - stmt_semi(e, nid) => stmt_semi(fld.fold_expr(e), fld.new_id(nid)), - stmt_mac(ref mac, semi) => stmt_mac(fold_mac(mac), semi) + stmt_decl(d, nid) => { + match fld.fold_decl(d) { + Some(d) => Some(stmt_decl(d, fld.new_id(nid))), + None => None, + } + } + stmt_expr(e, nid) => { + Some(stmt_expr(fld.fold_expr(e), fld.new_id(nid))) + } + stmt_semi(e, nid) => { + Some(stmt_semi(fld.fold_expr(e), fld.new_id(nid))) + } + stmt_mac(ref mac, semi) => Some(stmt_mac(fold_mac(mac), semi)) } } @@ -407,13 +428,13 @@ pub fn noop_fold_pat(p: &pat_, fld: @ast_fold) -> pat_ { } } -fn noop_fold_decl(d: &decl_, fld: @ast_fold) -> decl_ { +fn noop_fold_decl(d: &decl_, fld: @ast_fold) -> Option { match *d { - decl_local(ref ls) => decl_local(ls.map(|x| fld.fold_local(*x))), + decl_local(ref l) => Some(decl_local(fld.fold_local(*l))), decl_item(it) => { match fld.fold_item(it) { - Some(it_folded) => decl_item(it_folded), - None => decl_local(~[]), + Some(it_folded) => Some(decl_item(it_folded)), + None => None, } } } @@ -431,7 +452,6 @@ pub fn noop_fold_expr(e: &expr_, fld: @ast_fold) -> expr_ { fn fold_field_(field: field, fld: @ast_fold) -> field { spanned { node: ast::field_ { - mutbl: field.node.mutbl, ident: fld.fold_ident(field.node.ident), expr: fld.fold_expr(field.node.expr), }, @@ -460,8 +480,9 @@ pub fn noop_fold_expr(e: &expr_, fld: @ast_fold) -> expr_ { blk ) } - expr_method_call(f, i, ref tps, ref args, blk) => { + expr_method_call(callee_id, f, i, ref tps, ref args, blk) => { expr_method_call( + fld.new_id(callee_id), fld.fold_expr(f), fld.fold_ident(i), tps.map(|x| fld.fold_ty(*x)), @@ -469,10 +490,21 @@ pub fn noop_fold_expr(e: &expr_, fld: @ast_fold) -> expr_ { blk ) } - expr_binary(binop, lhs, rhs) => { - expr_binary(binop, fld.fold_expr(lhs), fld.fold_expr(rhs)) + expr_binary(callee_id, binop, lhs, rhs) => { + expr_binary( + fld.new_id(callee_id), + binop, + fld.fold_expr(lhs), + fld.fold_expr(rhs) + ) + } + expr_unary(callee_id, binop, ohs) => { + expr_unary( + fld.new_id(callee_id), + binop, + fld.fold_expr(ohs) + ) } - expr_unary(binop, ohs) => expr_unary(binop, fld.fold_expr(ohs)), expr_loop_body(f) => expr_loop_body(fld.fold_expr(f)), expr_do_body(f) => expr_do_body(fld.fold_expr(f)), expr_lit(_) => copy *e, @@ -511,8 +543,13 @@ pub fn noop_fold_expr(e: &expr_, fld: @ast_fold) -> expr_ { expr_assign(el, er) => { expr_assign(fld.fold_expr(el), fld.fold_expr(er)) } - expr_assign_op(op, el, er) => { - expr_assign_op(op, fld.fold_expr(el), fld.fold_expr(er)) + expr_assign_op(callee_id, op, el, er) => { + expr_assign_op( + fld.new_id(callee_id), + op, + fld.fold_expr(el), + fld.fold_expr(er) + ) } expr_field(el, id, ref tys) => { expr_field( @@ -520,8 +557,12 @@ pub fn noop_fold_expr(e: &expr_, fld: @ast_fold) -> expr_ { tys.map(|x| fld.fold_ty(*x)) ) } - expr_index(el, er) => { - expr_index(fld.fold_expr(el), fld.fold_expr(er)) + expr_index(callee_id, el, er) => { + expr_index( + fld.new_id(callee_id), + fld.fold_expr(el), + fld.fold_expr(er) + ) } expr_path(pth) => expr_path(fld.fold_path(pth)), expr_self => expr_self, @@ -714,10 +755,10 @@ pub fn default_ast_fold() -> ast_fold_fns { fold_item_underscore: noop_fold_item_underscore, fold_method: noop_fold_method, fold_block: wrap(noop_fold_block), - fold_stmt: wrap(noop_fold_stmt), + fold_stmt: |x, s, fld| (noop_fold_stmt(x, fld), s), fold_arm: noop_fold_arm, fold_pat: wrap(noop_fold_pat), - fold_decl: wrap(noop_fold_decl), + fold_decl: |x, s, fld| (noop_fold_decl(x, fld), s), fold_expr: wrap(noop_fold_expr), fold_ty: wrap(noop_fold_ty), fold_mod: noop_fold_mod, @@ -775,9 +816,12 @@ impl ast_fold for AstFoldFns { let (n, s) = (self.fold_block)(&x.node, x.span, self as @ast_fold); spanned { node: n, span: (self.new_span)(s) } } - fn fold_stmt(@self, x: &stmt) -> @stmt { - let (n, s) = (self.fold_stmt)(&x.node, x.span, self as @ast_fold); - @spanned { node: n, span: (self.new_span)(s) } + fn fold_stmt(@self, x: &stmt) -> Option<@stmt> { + let (n_opt, s) = (self.fold_stmt)(&x.node, x.span, self as @ast_fold); + match n_opt { + Some(n) => Some(@spanned { node: n, span: (self.new_span)(s) }), + None => None, + } } fn fold_arm(@self, x: &arm) -> arm { (self.fold_arm)(x, self as @ast_fold) @@ -790,15 +834,17 @@ impl ast_fold for AstFoldFns { span: (self.new_span)(s), } } - fn fold_decl(@self, x: @decl) -> @decl { - let (n, s) = (self.fold_decl)(&x.node, x.span, self as @ast_fold); - @spanned { node: n, span: (self.new_span)(s) } + fn fold_decl(@self, x: @decl) -> Option<@decl> { + let (n_opt, s) = (self.fold_decl)(&x.node, x.span, self as @ast_fold); + match n_opt { + Some(n) => Some(@spanned { node: n, span: (self.new_span)(s) }), + None => None, + } } fn fold_expr(@self, x: @expr) -> @expr { let (n, s) = (self.fold_expr)(&x.node, x.span, self as @ast_fold); @expr { id: (self.new_id)(x.id), - callee_id: (self.new_id)(x.callee_id), node: n, span: (self.new_span)(s), } @@ -858,4 +904,3 @@ impl AstFoldExtensions for @ast_fold { pub fn make_fold(afp: ast_fold_fns) -> @ast_fold { afp as @ast_fold } - diff --git a/src/libsyntax/opt_vec.rs b/src/libsyntax/opt_vec.rs index fb3622396c951..791f7444b6226 100644 --- a/src/libsyntax/opt_vec.rs +++ b/src/libsyntax/opt_vec.rs @@ -17,6 +17,7 @@ */ use core::prelude::*; + use core::old_iter; use core::old_iter::BaseIter; @@ -131,14 +132,6 @@ impl Eq for OptVec { } impl BaseIter for OptVec { - #[cfg(stage0)] - fn each(&self, blk: &fn(v: &A) -> bool) { - match *self { - Empty => {} - Vec(ref v) => v.each(blk) - } - } - #[cfg(not(stage0))] fn each(&self, blk: &fn(v: &A) -> bool) -> bool { match *self { Empty => true, @@ -153,12 +146,6 @@ impl BaseIter for OptVec { impl old_iter::ExtendedIter for OptVec { #[inline(always)] - #[cfg(stage0)] - fn eachi(&self, blk: &fn(v: uint, v: &A) -> bool) { - old_iter::eachi(self, blk) - } - #[inline(always)] - #[cfg(not(stage0))] fn eachi(&self, blk: &fn(v: uint, v: &A) -> bool) -> bool { old_iter::eachi(self, blk) } diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index 93584b00d39e6..ed9a83d6b1ebc 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -42,7 +42,7 @@ impl parser_attr for Parser { if self.look_ahead(1u) != token::LBRACKET { break; } - attrs += ~[self.parse_attribute(ast::attr_outer)]; + attrs += [self.parse_attribute(ast::attr_outer)]; } token::DOC_COMMENT(s) => { let attr = ::attr::mk_sugared_doc_attr( @@ -51,9 +51,9 @@ impl parser_attr for Parser { self.span.hi ); if attr.node.style != ast::attr_outer { - self.fatal(~"expected outer comment"); + self.fatal("expected outer comment"); } - attrs += ~[attr]; + attrs += [attr]; self.bump(); } _ => break @@ -105,7 +105,7 @@ impl parser_attr for Parser { let attr = self.parse_attribute(ast::attr_inner); if *self.token == token::SEMI { self.bump(); - inner_attrs += ~[attr]; + inner_attrs += [attr]; } else { // It's not really an inner attribute let outer_attr = @@ -113,7 +113,7 @@ impl parser_attr for Parser { ast::attribute_ { style: ast::attr_outer, value: attr.node.value, is_sugared_doc: false }); - next_outer_attrs += ~[outer_attr]; + next_outer_attrs += [outer_attr]; break; } } @@ -125,9 +125,9 @@ impl parser_attr for Parser { ); self.bump(); if attr.node.style == ast::attr_inner { - inner_attrs += ~[attr]; + inner_attrs += [attr]; } else { - next_outer_attrs += ~[attr]; + next_outer_attrs += [attr]; break; } } diff --git a/src/libsyntax/parse/classify.rs b/src/libsyntax/parse/classify.rs index e04914c0f1e83..62b36b12f2669 100644 --- a/src/libsyntax/parse/classify.rs +++ b/src/libsyntax/parse/classify.rs @@ -31,8 +31,8 @@ pub fn expr_requires_semi_to_be_stmt(e: @ast::expr) -> bool { | ast::expr_loop(*) | ast::expr_call(_, _, ast::DoSugar) | ast::expr_call(_, _, ast::ForSugar) - | ast::expr_method_call(_, _, _, _, ast::DoSugar) - | ast::expr_method_call(_, _, _, _, ast::ForSugar) => false, + | ast::expr_method_call(_, _, _, _, _, ast::DoSugar) + | ast::expr_method_call(_, _, _, _, _, ast::ForSugar) => false, _ => true } } diff --git a/src/libsyntax/parse/comments.rs b/src/libsyntax/parse/comments.rs index 89873b2793566..dab8dd3b4b6a3 100644 --- a/src/libsyntax/parse/comments.rs +++ b/src/libsyntax/parse/comments.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use ast; use codemap::{BytePos, CharPos, CodeMap, Pos}; use diagnostic; @@ -16,8 +18,13 @@ use parse::lexer::{StringReader, bump, is_eof, nextch, TokenAndSpan}; use parse::lexer::{is_line_non_doc_comment, is_block_non_doc_comment}; use parse::lexer; use parse::token; +use parse::token::{get_ident_interner}; use parse; +use core::io; +use core::str; +use core::uint; + #[deriving(Eq)] pub enum cmnt_style { isolated, // No code on either side of each line of the comment @@ -33,15 +40,15 @@ pub struct cmnt { } pub fn is_doc_comment(s: &str) -> bool { - (s.starts_with(~"///") && !is_line_non_doc_comment(s)) || - s.starts_with(~"//!") || - (s.starts_with(~"/**") && !is_block_non_doc_comment(s)) || - s.starts_with(~"/*!") + (s.starts_with("///") && !is_line_non_doc_comment(s)) || + s.starts_with("//!") || + (s.starts_with("/**") && !is_block_non_doc_comment(s)) || + s.starts_with("/*!") } pub fn doc_comment_style(comment: &str) -> ast::attr_style { assert!(is_doc_comment(comment)); - if comment.starts_with(~"//!") || comment.starts_with(~"/*!") { + if comment.starts_with("//!") || comment.starts_with("/*!") { ast::attr_inner } else { ast::attr_outer @@ -52,7 +59,8 @@ pub fn strip_doc_comment_decoration(comment: &str) -> ~str { /// remove whitespace-only lines from the start/end of lines fn vertical_trim(lines: ~[~str]) -> ~[~str] { - let mut i = 0u, j = lines.len(); + let mut i = 0u; + let mut j = lines.len(); while i < j && lines[i].trim().is_empty() { i += 1u; } @@ -92,14 +100,14 @@ pub fn strip_doc_comment_decoration(comment: &str) -> ~str { }; } - if comment.starts_with(~"//") { + if comment.starts_with("//") { // FIXME #5475: // return comment.slice(3u, comment.len()).trim().to_owned(); let r = comment.slice(3u, comment.len()); return r.trim().to_owned(); } - if comment.starts_with(~"/*") { + if comment.starts_with("/*") { let mut lines = ~[]; for str::each_line_any(comment.slice(3u, comment.len() - 2u)) |line| { lines.push(line.to_owned()) @@ -108,7 +116,7 @@ pub fn strip_doc_comment_decoration(comment: &str) -> ~str { let lines = block_trim(lines, ~"\t ", None); let lines = block_trim(lines, ~"*", Some(1u)); let lines = block_trim(lines, ~"\t ", None); - return str::connect(lines, ~"\n"); + return str::connect(lines, "\n"); } fail!("not a doc-comment: %s", comment); @@ -233,7 +241,7 @@ fn read_block_comment(rdr: @mut StringReader, bump(rdr); } if !is_eof(rdr) { - curr_line += ~"*/"; + curr_line += "*/"; bump(rdr); bump(rdr); } @@ -257,13 +265,13 @@ fn read_block_comment(rdr: @mut StringReader, if rdr.curr == '/' && nextch(rdr) == '*' { bump(rdr); bump(rdr); - curr_line += ~"*"; + curr_line += "*"; level += 1; } else { if rdr.curr == '*' && nextch(rdr) == '/' { bump(rdr); bump(rdr); - curr_line += ~"/"; + curr_line += "/"; level -= 1; } else { bump(rdr); } } @@ -316,12 +324,9 @@ pub fn gather_comments_and_literals(span_diagnostic: srdr: @io::Reader) -> (~[cmnt], ~[lit]) { let src = @str::from_bytes(srdr.read_whole_stream()); - let itr = parse::token::mk_fake_ident_interner(); let cm = CodeMap::new(); let filemap = cm.new_filemap(path, src); - let rdr = lexer::new_low_level_string_reader(span_diagnostic, - filemap, - itr); + let rdr = lexer::new_low_level_string_reader(span_diagnostic, filemap); let mut comments: ~[cmnt] = ~[]; let mut literals: ~[lit] = ~[]; @@ -351,7 +356,7 @@ pub fn gather_comments_and_literals(span_diagnostic: debug!("tok lit: %s", s); literals.push(lit {lit: s, pos: sp.lo}); } else { - debug!("tok: %s", token::to_str(rdr.interner, &tok)); + debug!("tok: %s", token::to_str(get_ident_interner(), &tok)); } first_read = false; } diff --git a/src/libsyntax/parse/common.rs b/src/libsyntax/parse/common.rs index 6595343654f11..9fb69821953ac 100644 --- a/src/libsyntax/parse/common.rs +++ b/src/libsyntax/parse/common.rs @@ -8,11 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use ast; use codemap::{BytePos, spanned}; use parse::lexer::reader; use parse::parser::Parser; +use parse::token::keywords; use parse::token; +use parse::token::{get_ident_interner}; use opt_vec; use opt_vec::OptVec; @@ -46,21 +50,21 @@ pub fn seq_sep_none() -> SeqSep { // maps any token back to a string. not necessary if you know it's // an identifier.... pub fn token_to_str(reader: @reader, token: &token::Token) -> ~str { - token::to_str(reader.interner(), token) + token::to_str(get_ident_interner(), token) } -pub impl Parser { +impl Parser { // convert a token to a string using self's reader - fn token_to_str(&self, token: &token::Token) -> ~str { - token::to_str(self.reader.interner(), token) + pub fn token_to_str(&self, token: &token::Token) -> ~str { + token::to_str(get_ident_interner(), token) } // convert the current token to a string using self's reader - fn this_token_to_str(&self) -> ~str { + pub fn this_token_to_str(&self) -> ~str { self.token_to_str(self.token) } - fn unexpected_last(&self, t: &token::Token) -> ! { + pub fn unexpected_last(&self, t: &token::Token) -> ! { self.span_fatal( *self.last_span, fmt!( @@ -70,7 +74,7 @@ pub impl Parser { ); } - fn unexpected(&self) -> ! { + pub fn unexpected(&self) -> ! { self.fatal( fmt!( "unexpected token: `%s`", @@ -81,7 +85,7 @@ pub impl Parser { // expect and consume the token t. Signal an error if // the next token is not t. - fn expect(&self, t: &token::Token) { + pub fn expect(&self, t: &token::Token) { if *self.token == *t { self.bump(); } else { @@ -95,7 +99,7 @@ pub impl Parser { } } - fn parse_ident(&self) -> ast::ident { + pub fn parse_ident(&self) -> ast::ident { self.check_strict_keywords(); self.check_reserved_keywords(); match *self.token { @@ -104,9 +108,7 @@ pub impl Parser { i } token::INTERPOLATED(token::nt_ident(*)) => { - self.bug( - ~"ident interpolation not converted to real token" - ); + self.bug("ident interpolation not converted to real token"); } _ => { self.fatal( @@ -119,7 +121,7 @@ pub impl Parser { } } - fn parse_path_list_ident(&self) -> ast::path_list_ident { + pub fn parse_path_list_ident(&self) -> ast::path_list_ident { let lo = self.span.lo; let ident = self.parse_ident(); let hi = self.last_span.hi; @@ -129,58 +131,19 @@ pub impl Parser { // consume token 'tok' if it exists. Returns true if the given // token was present, false otherwise. - fn eat(&self, tok: &token::Token) -> bool { + pub fn eat(&self, tok: &token::Token) -> bool { return if *self.token == *tok { self.bump(); true } else { false }; } - // Storing keywords as interned idents instead of strings would be nifty. - - // A sanity check that the word we are asking for is a known keyword - // NOTE: this could be done statically.... - fn require_keyword(&self, word: &str) { - if !self.keywords.contains_equiv(&word) { - self.bug(fmt!("unknown keyword: %s", word)); - } - } - - // return true when this token represents the given string, and is not - // followed immediately by :: . - fn token_is_word(&self, word: &str, tok: &token::Token) -> bool { - match *tok { - token::IDENT(sid, false) => { word == *self.id_to_str(sid) } - _ => { false } - } - } - - fn token_is_keyword(&self, word: &str, tok: &token::Token) -> bool { - self.require_keyword(word); - self.token_is_word(word, tok) - } - - fn is_keyword(&self, word: &str) -> bool { - self.token_is_keyword(word, © *self.token) - } - - fn id_is_any_keyword(&self, id: ast::ident) -> bool { - self.keywords.contains(self.id_to_str(id)) - } - - fn is_any_keyword(&self, tok: &token::Token) -> bool { - match *tok { - token::IDENT(sid, false) => { - self.keywords.contains(self.id_to_str(sid)) - } - _ => false - } + pub fn is_keyword(&self, kw: keywords::Keyword) -> bool { + token::is_keyword(kw, self.token) } - // if the given word is not a keyword, signal an error. // if the next token is the given keyword, eat it and return // true. Otherwise, return false. - fn eat_keyword(&self, word: &str) -> bool { - self.require_keyword(word); + pub fn eat_keyword(&self, kw: keywords::Keyword) -> bool { let is_kw = match *self.token { - token::IDENT(sid, false) => word == *self.id_to_str(sid), + token::IDENT(sid, false) => kw.to_ident().name == sid.name, _ => false }; if is_kw { self.bump() } @@ -190,70 +153,37 @@ pub impl Parser { // if the given word is not a keyword, signal an error. // if the next token is not the given word, signal an error. // otherwise, eat it. - fn expect_keyword(&self, word: &str) { - self.require_keyword(word); - if !self.eat_keyword(word) { + pub fn expect_keyword(&self, kw: keywords::Keyword) { + if !self.eat_keyword(kw) { self.fatal( fmt!( "expected `%s`, found `%s`", - word, + *self.id_to_str(kw.to_ident()), self.this_token_to_str() ) ); } } - // return true if the given string is a strict keyword - fn is_strict_keyword(&self, word: &str) -> bool { - self.strict_keywords.contains_equiv(&word) - } - - // signal an error if the current token is a strict keyword - fn check_strict_keywords(&self) { - match *self.token { - token::IDENT(_, false) => { - let w = token_to_str(self.reader, © *self.token); - self.check_strict_keywords_(w); - } - _ => () - } - } - // signal an error if the given string is a strict keyword - fn check_strict_keywords_(&self, w: &str) { - if self.is_strict_keyword(w) { + pub fn check_strict_keywords(&self) { + if token::is_strict_keyword(self.token) { self.span_err(*self.last_span, - fmt!("found `%s` in ident position", w)); + fmt!("found `%s` in ident position", self.this_token_to_str())); } } - // return true if this is a reserved keyword - fn is_reserved_keyword(&self, word: &str) -> bool { - self.reserved_keywords.contains_equiv(&word) - } - // signal an error if the current token is a reserved keyword - fn check_reserved_keywords(&self) { - match *self.token { - token::IDENT(_, false) => { - let w = token_to_str(self.reader, © *self.token); - self.check_reserved_keywords_(w); - } - _ => () - } - } - - // signal an error if the given string is a reserved keyword - fn check_reserved_keywords_(&self, w: &str) { - if self.is_reserved_keyword(w) { - self.fatal(fmt!("`%s` is a reserved keyword", w)); + pub fn check_reserved_keywords(&self) { + if token::is_reserved_keyword(self.token) { + self.fatal(fmt!("`%s` is a reserved keyword", self.this_token_to_str())); } } // expect and consume a GT. if a >> is seen, replace it // with a single > and continue. If a GT is not seen, // signal an error. - fn expect_gt(&self) { + pub fn expect_gt(&self) { if *self.token == token::GT { self.bump(); } else if *self.token == token::BINOP(token::SHR) { @@ -265,20 +195,19 @@ pub impl Parser { } else { let mut s: ~str = ~"expected `"; s += self.token_to_str(&token::GT); - s += ~"`, found `"; + s += "`, found `"; s += self.this_token_to_str(); - s += ~"`"; + s += "`"; self.fatal(s); } } // parse a sequence bracketed by '<' and '>', stopping // before the '>'. - fn parse_seq_to_before_gt( - &self, - sep: Option, - f: &fn(&Parser) -> T - ) -> OptVec { + pub fn parse_seq_to_before_gt(&self, + sep: Option, + f: &fn(&Parser) -> T) + -> OptVec { let mut first = true; let mut v = opt_vec::Empty; while *self.token != token::GT @@ -295,11 +224,10 @@ pub impl Parser { return v; } - fn parse_seq_to_gt( - &self, - sep: Option, - f: &fn(&Parser) -> T - ) -> OptVec { + pub fn parse_seq_to_gt(&self, + sep: Option, + f: &fn(&Parser) -> T) + -> OptVec { let v = self.parse_seq_to_before_gt(sep, f); self.expect_gt(); return v; @@ -308,12 +236,11 @@ pub impl Parser { // parse a sequence, including the closing delimiter. The function // f must consume tokens until reaching the next separator or // closing bracket. - fn parse_seq_to_end( - &self, - ket: &token::Token, - sep: SeqSep, - f: &fn(&Parser) -> T - ) -> ~[T] { + pub fn parse_seq_to_end(&self, + ket: &token::Token, + sep: SeqSep, + f: &fn(&Parser) -> T) + -> ~[T] { let val = self.parse_seq_to_before_end(ket, sep, f); self.bump(); val @@ -322,12 +249,11 @@ pub impl Parser { // parse a sequence, not including the closing delimiter. The function // f must consume tokens until reaching the next separator or // closing bracket. - fn parse_seq_to_before_end( - &self, - ket: &token::Token, - sep: SeqSep, - f: &fn(&Parser) -> T - ) -> ~[T] { + pub fn parse_seq_to_before_end(&self, + ket: &token::Token, + sep: SeqSep, + f: &fn(&Parser) -> T) + -> ~[T] { let mut first: bool = true; let mut v: ~[T] = ~[]; while *self.token != *ket { @@ -347,13 +273,12 @@ pub impl Parser { // parse a sequence, including the closing delimiter. The function // f must consume tokens until reaching the next separator or // closing bracket. - fn parse_unspanned_seq( - &self, - bra: &token::Token, - ket: &token::Token, - sep: SeqSep, - f: &fn(&Parser) -> T - ) -> ~[T] { + pub fn parse_unspanned_seq(&self, + bra: &token::Token, + ket: &token::Token, + sep: SeqSep, + f: &fn(&Parser) -> T) + -> ~[T] { self.expect(bra); let result = self.parse_seq_to_before_end(ket, sep, f); self.bump(); @@ -362,13 +287,12 @@ pub impl Parser { // NB: Do not use this function unless you actually plan to place the // spanned list in the AST. - fn parse_seq( - &self, - bra: &token::Token, - ket: &token::Token, - sep: SeqSep, - f: &fn(&Parser) -> T - ) -> spanned<~[T]> { + pub fn parse_seq(&self, + bra: &token::Token, + ket: &token::Token, + sep: SeqSep, + f: &fn(&Parser) -> T) + -> spanned<~[T]> { let lo = self.span.lo; self.expect(bra); let result = self.parse_seq_to_before_end(ket, sep, f); diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs index 764dec0eeb391..84700f052c9c4 100644 --- a/src/libsyntax/parse/lexer.rs +++ b/src/libsyntax/parse/lexer.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use ast; use codemap::{BytePos, CharPos, CodeMap, Pos, span}; use codemap; @@ -15,17 +17,20 @@ use diagnostic::span_handler; use ext::tt::transcribe::{tt_next_token}; use ext::tt::transcribe::{dup_tt_reader}; use parse::token; +use parse::token::{str_to_ident}; -pub use ext::tt::transcribe::{TtReader, new_tt_reader}; +use core::char; +use core::either; +use core::str; +use core::u64; -//use std; +pub use ext::tt::transcribe::{TtReader, new_tt_reader}; pub trait reader { fn is_eof(@mut self) -> bool; fn next_token(@mut self) -> TokenAndSpan; fn fatal(@mut self, ~str) -> !; fn span_diag(@mut self) -> @span_handler; - fn interner(@mut self) -> @token::ident_interner; fn peek(@mut self) -> TokenAndSpan; fn dup(@mut self) -> @reader; } @@ -45,25 +50,22 @@ pub struct StringReader { // The last character to be read curr: char, filemap: @codemap::FileMap, - interner: @token::ident_interner, /* cached: */ peek_tok: token::Token, peek_span: span } pub fn new_string_reader(span_diagnostic: @span_handler, - filemap: @codemap::FileMap, - itr: @token::ident_interner) + filemap: @codemap::FileMap) -> @mut StringReader { - let r = new_low_level_string_reader(span_diagnostic, filemap, itr); + let r = new_low_level_string_reader(span_diagnostic, filemap); string_advance_token(r); /* fill in peek_* */ return r; } /* For comments.rs, which hackily pokes into 'pos' and 'curr' */ pub fn new_low_level_string_reader(span_diagnostic: @span_handler, - filemap: @codemap::FileMap, - itr: @token::ident_interner) + filemap: @codemap::FileMap) -> @mut StringReader { // Force the initial reader bump to start on a fresh line let initial_char = '\n'; @@ -74,7 +76,6 @@ pub fn new_low_level_string_reader(span_diagnostic: @span_handler, col: CharPos(0), curr: initial_char, filemap: filemap, - interner: itr, /* dummy values; not read */ peek_tok: token::EOF, peek_span: codemap::dummy_sp() @@ -95,7 +96,6 @@ fn dup_string_reader(r: @mut StringReader) -> @mut StringReader { col: r.col, curr: r.curr, filemap: r.filemap, - interner: r.interner, peek_tok: copy r.peek_tok, peek_span: copy r.peek_span } @@ -116,7 +116,6 @@ impl reader for StringReader { self.span_diagnostic.span_fatal(copy self.peek_span, m) } fn span_diag(@mut self) -> @span_handler { self.span_diagnostic } - fn interner(@mut self) -> @token::ident_interner { self.interner } fn peek(@mut self) -> TokenAndSpan { TokenAndSpan { tok: copy self.peek_tok, @@ -133,7 +132,6 @@ impl reader for TtReader { self.sp_diag.span_fatal(copy self.cur_span, m); } fn span_diag(@mut self) -> @span_handler { self.sp_diag } - fn interner(@mut self) -> @token::ident_interner { self.interner } fn peek(@mut self) -> TokenAndSpan { TokenAndSpan { tok: copy self.cur_tok, @@ -247,7 +245,8 @@ fn consume_whitespace_and_comments(rdr: @mut StringReader) } pub fn is_line_non_doc_comment(s: &str) -> bool { - s.trim_right().all(|ch| ch == '/') + let s = s.trim_right(); + s.len() > 3 && s.all(|ch| ch == '/') } // PRECONDITION: rdr.curr is not whitespace @@ -268,10 +267,10 @@ fn consume_any_line_comment(rdr: @mut StringReader) str::push_char(&mut acc, rdr.curr); bump(rdr); } - // but comments with only "/"s are not + // but comments with only more "/"s are not if !is_line_non_doc_comment(acc) { return Some(TokenAndSpan{ - tok: token::DOC_COMMENT(rdr.interner.intern(acc)), + tok: token::DOC_COMMENT(str_to_ident(acc)), sp: codemap::mk_sp(start_bpos, rdr.pos) }); } @@ -319,13 +318,13 @@ fn consume_block_comment(rdr: @mut StringReader) if is_eof(rdr) { rdr.fatal(~"unterminated block doc-comment"); } else { - acc += ~"*/"; + acc += "*/"; bump(rdr); bump(rdr); // but comments with only "*"s between two "/"s are not if !is_block_non_doc_comment(acc) { return Some(TokenAndSpan{ - tok: token::DOC_COMMENT(rdr.interner.intern(acc)), + tok: token::DOC_COMMENT(str_to_ident(acc)), sp: codemap::mk_sp(start_bpos, rdr.pos) }); } @@ -381,7 +380,10 @@ fn scan_digits(rdr: @mut StringReader, radix: uint) -> ~str { } fn scan_number(c: char, rdr: @mut StringReader) -> token::Token { - let mut num_str, base = 10u, c = c, n = nextch(rdr); + let mut num_str; + let mut base = 10u; + let mut c = c; + let mut n = nextch(rdr); if c == '0' && n == 'x' { bump(rdr); bump(rdr); @@ -442,7 +444,8 @@ fn scan_number(c: char, rdr: @mut StringReader) -> token::Token { is_float = true; bump(rdr); let dec_part = scan_digits(rdr, 10u); - num_str += ~"." + dec_part; + num_str += "."; + num_str += dec_part; } if is_float { match base { @@ -467,12 +470,12 @@ fn scan_number(c: char, rdr: @mut StringReader) -> token::Token { if c == '3' && n == '2' { bump(rdr); bump(rdr); - return token::LIT_FLOAT(rdr.interner.intern(num_str), + return token::LIT_FLOAT(str_to_ident(num_str), ast::ty_f32); } else if c == '6' && n == '4' { bump(rdr); bump(rdr); - return token::LIT_FLOAT(rdr.interner.intern(num_str), + return token::LIT_FLOAT(str_to_ident(num_str), ast::ty_f64); /* FIXME (#2252): if this is out of range for either a 32-bit or 64-bit float, it won't be noticed till the @@ -484,9 +487,9 @@ fn scan_number(c: char, rdr: @mut StringReader) -> token::Token { } if is_float { if is_machine_float { - return token::LIT_FLOAT(rdr.interner.intern(num_str), ast::ty_f); + return token::LIT_FLOAT(str_to_ident(num_str), ast::ty_f); } - return token::LIT_FLOAT_UNSUFFIXED(rdr.interner.intern(num_str)); + return token::LIT_FLOAT_UNSUFFIXED(str_to_ident(num_str)); } else { if str::len(num_str) == 0u { rdr.fatal(~"no valid digits found for number"); @@ -503,7 +506,8 @@ fn scan_number(c: char, rdr: @mut StringReader) -> token::Token { } fn scan_numeric_escape(rdr: @mut StringReader, n_hex_digits: uint) -> char { - let mut accum_int = 0, i = n_hex_digits; + let mut accum_int = 0; + let mut i = n_hex_digits; while i != 0u { let n = rdr.curr; bump(rdr); @@ -548,7 +552,7 @@ fn next_token_inner(rdr: @mut StringReader) -> token::Token { let is_mod_name = c == ':' && nextch(rdr) == ':'; // FIXME: perform NFKC normalization here. (Issue #2253) - return token::IDENT(rdr.interner.intern(accum_str), is_mod_name); + return token::IDENT(str_to_ident(accum_str), is_mod_name); } if is_dec_digit(c) { return scan_number(c, rdr); @@ -658,7 +662,7 @@ fn next_token_inner(rdr: @mut StringReader) -> token::Token { lifetime_name.push_char(rdr.curr); bump(rdr); } - return token::LIFETIME(rdr.interner.intern(lifetime_name)); + return token::LIFETIME(str_to_ident(lifetime_name)); } // Otherwise it is a character constant: @@ -731,7 +735,7 @@ fn next_token_inner(rdr: @mut StringReader) -> token::Token { } } bump(rdr); - return token::LIT_STR(rdr.interner.intern(accum_str)); + return token::LIT_STR(str_to_ident(accum_str)); } '-' => { if nextch(rdr) == '>' { @@ -775,10 +779,10 @@ mod test { use core::option::None; use diagnostic; use parse::token; + use parse::token::{str_to_ident}; // represents a testing reader (incl. both reader and interner) struct Env { - interner: @token::ident_interner, string_reader: @mut StringReader } @@ -786,20 +790,18 @@ mod test { fn setup(teststr: ~str) -> Env { let cm = CodeMap::new(); let fm = cm.new_filemap(~"zebra.rs", @teststr); - let ident_interner = token::mk_ident_interner(); // interner::mk(); let span_handler = diagnostic::mk_span_handler(diagnostic::mk_handler(None),@cm); Env { - interner: ident_interner, - string_reader: new_string_reader(span_handler,fm,ident_interner) + string_reader: new_string_reader(span_handler,fm) } } #[test] fn t1 () { - let Env {interner: ident_interner, string_reader} = + let Env {string_reader} = setup(~"/* my source file */ \ fn main() { io::println(~\"zebra\"); }\n"); - let id = ident_interner.intern("fn"); + let id = str_to_ident("fn"); let tok1 = string_reader.next_token(); let tok2 = TokenAndSpan{ tok:token::IDENT(id, false), @@ -810,7 +812,7 @@ mod test { // read another token: let tok3 = string_reader.next_token(); let tok4 = TokenAndSpan{ - tok:token::IDENT(ident_interner.intern("main"), false), + tok:token::IDENT(str_to_ident("main"), false), sp:span {lo:BytePos(24),hi:BytePos(28),expn_info: None}}; assert_eq!(tok3,tok4); // the lparen is already read: @@ -828,39 +830,39 @@ mod test { } // make the identifier by looking up the string in the interner - fn mk_ident (env: Env, id: &str, is_mod_name: bool) -> token::Token { - token::IDENT (env.interner.intern(id),is_mod_name) + fn mk_ident (id: &str, is_mod_name: bool) -> token::Token { + token::IDENT (str_to_ident(id),is_mod_name) } #[test] fn doublecolonparsing () { let env = setup (~"a b"); check_tokenization (env, - ~[mk_ident (env,"a",false), - mk_ident (env,"b",false)]); + ~[mk_ident("a",false), + mk_ident("b",false)]); } #[test] fn dcparsing_2 () { let env = setup (~"a::b"); check_tokenization (env, - ~[mk_ident (env,"a",true), + ~[mk_ident("a",true), token::MOD_SEP, - mk_ident (env,"b",false)]); + mk_ident("b",false)]); } #[test] fn dcparsing_3 () { let env = setup (~"a ::b"); check_tokenization (env, - ~[mk_ident (env,"a",false), + ~[mk_ident("a",false), token::MOD_SEP, - mk_ident (env,"b",false)]); + mk_ident("b",false)]); } #[test] fn dcparsing_4 () { let env = setup (~"a:: b"); check_tokenization (env, - ~[mk_ident (env,"a",true), + ~[mk_ident("a",true), token::MOD_SEP, - mk_ident (env,"b",false)]); + mk_ident("b",false)]); } #[test] fn character_a() { @@ -888,7 +890,13 @@ mod test { let env = setup(~"'abc"); let TokenAndSpan {tok, sp: _} = env.string_reader.next_token(); - let id = env.interner.intern("abc"); + let id = token::str_to_ident("abc"); assert_eq!(tok, token::LIFETIME(id)); } + + #[test] fn line_doc_comments() { + assert!(!is_line_non_doc_comment("///")); + assert!(!is_line_non_doc_comment("/// blah")); + assert!(is_line_non_doc_comment("////")); + } } diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 9a8a662065234..d7248204e1cf7 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -19,7 +19,6 @@ use diagnostic::{span_handler, mk_span_handler, mk_handler, Emitter}; use parse::attr::parser_attr; use parse::lexer::reader; use parse::parser::Parser; -use parse::token::{ident_interner, mk_ident_interner}; use core::io; use core::option::{None, Option, Some}; @@ -43,14 +42,10 @@ pub mod classify; pub mod obsolete; // info about a parsing session. -// This structure and the reader both have -// an interner associated with them. If they're -// not the same, bad things can happen. pub struct ParseSess { cm: @codemap::CodeMap, // better be the same as the one in the reader! next_id: node_id, span_diagnostic: @span_handler, // better be the same as the one in the reader! - interner: @ident_interner, } pub fn new_parse_sess(demitter: Option) -> @mut ParseSess { @@ -59,7 +54,6 @@ pub fn new_parse_sess(demitter: Option) -> @mut ParseSess { cm: cm, next_id: 1, span_diagnostic: mk_span_handler(mk_handler(demitter), cm), - interner: mk_ident_interner(), } } @@ -70,7 +64,6 @@ pub fn new_parse_sess_special_handler(sh: @span_handler, cm: cm, next_id: 1, span_diagnostic: sh, - interner: mk_ident_interner(), } } @@ -312,9 +305,7 @@ pub fn filemap_to_tts(sess: @mut ParseSess, filemap: @FileMap) // it appears to me that the cfg doesn't matter here... indeed, // parsing tt's probably shouldn't require a parser at all. let cfg = ~[]; - let srdr = lexer::new_string_reader(copy sess.span_diagnostic, - filemap, - sess.interner); + let srdr = lexer::new_string_reader(copy sess.span_diagnostic, filemap); let p1 = Parser(sess, cfg, srdr as @reader); p1.parse_all_token_trees() } @@ -325,7 +316,6 @@ pub fn tts_to_parser(sess: @mut ParseSess, cfg: ast::crate_cfg) -> Parser { let trdr = lexer::new_tt_reader( copy sess.span_diagnostic, - sess.interner, None, tts ); @@ -343,120 +333,47 @@ pub fn maybe_aborted(result : T, p: Parser) -> T { #[cfg(test)] mod test { use super::*; - use std::serialize::Encodable; - use std; + use extra::serialize::Encodable; + use extra; use core::io; - use core::option::Option; use core::option::Some; use core::option::None; - use core::int; - use core::num::NumCast; - use codemap::{CodeMap, span, BytePos, spanned}; + use codemap::{span, BytePos, spanned}; use opt_vec; use ast; + use ast::{new_ident}; use abi; - use ast_util::mk_ident; use parse::parser::Parser; - use parse::token::{ident_interner, mk_fresh_ident_interner}; - use diagnostic::{mk_span_handler, mk_handler}; - - // add known names to interner for testing - fn mk_testing_interner() -> @ident_interner { - let i = mk_fresh_ident_interner(); - // baby hack; in order to put the identifiers - // 'a' and 'b' at known locations, we're going - // to fill up the interner to length 100. If - // the # of preloaded items on the interner - // ever gets larger than 100, we'll have to - // adjust this number (say, to 200) and - // change the numbers in the identifier - // test cases below. - - assert!(i.len() < 100); - for int::range(0,100-((i.len()).to_int())) |_dc| { - i.gensym("dontcare"); - } - i.intern("a"); - i.intern("b"); - i.intern("c"); - i.intern("d"); - i.intern("return"); - assert!(i.get(ast::ident{repr:101,ctxt:0}) == @~"b"); - i - } - - // make a parse_sess that's closed over a - // testing interner (where a -> 100, b -> 101) - fn mk_testing_parse_sess() -> @mut ParseSess { - let interner = mk_testing_interner(); - let cm = @CodeMap::new(); - @mut ParseSess { - cm: cm, - next_id: 1, - span_diagnostic: mk_span_handler(mk_handler(None), cm), - interner: interner, - } - } - - // map a string to tts, using a made-up filename: return both the token_trees - // and the ParseSess - fn string_to_tts_t (source_str : @~str) -> (~[ast::token_tree],@mut ParseSess) { - let ps = mk_testing_parse_sess(); - (filemap_to_tts(ps,string_to_filemap(ps,source_str,~"bogofile")),ps) - } + use parse::token::{intern, str_to_ident}; + use util::parser_testing::{string_to_tts_and_sess, string_to_parser}; + use util::parser_testing::{string_to_expr, string_to_item}; + use util::parser_testing::{string_to_stmt, strs_to_idents}; // map a string to tts, return the tt without its parsesess fn string_to_tts_only(source_str : @~str) -> ~[ast::token_tree] { - let (tts,_ps) = string_to_tts_t(source_str); + let (tts,_ps) = string_to_tts_and_sess(source_str); tts } - // map string to parser (via tts) - fn string_to_parser(source_str: @~str) -> Parser { - let ps = mk_testing_parse_sess(); - new_parser_from_source_str(ps,~[],~"bogofile",source_str) - } - #[cfg(test)] fn to_json_str>(val: @E) -> ~str { + #[cfg(test)] fn to_json_str>(val: @E) -> ~str { do io::with_str_writer |writer| { - let mut encoder = std::json::Encoder(writer); + let mut encoder = extra::json::Encoder(writer); val.encode(&mut encoder); } } - fn string_to_crate (source_str : @~str) -> @ast::crate { - string_to_parser(source_str).parse_crate_mod() - } - - fn string_to_expr (source_str : @~str) -> @ast::expr { - string_to_parser(source_str).parse_expr() - } - - fn string_to_item (source_str : @~str) -> Option<@ast::item> { - string_to_parser(source_str).parse_item(~[]) - } - - fn string_to_stmt (source_str : @~str) -> @ast::stmt { - string_to_parser(source_str).parse_stmt(~[]) - } - // produce a codemap::span fn sp (a: uint, b: uint) -> span { span{lo:BytePos(a),hi:BytePos(b),expn_info:None} } - // convert a vector of uints to a vector of ast::idents - fn ints_to_idents(ids: ~[uint]) -> ~[ast::ident] { - ids.map(|u| mk_ident(*u)) - } - #[test] fn path_exprs_1 () { assert_eq!(string_to_expr(@~"a"), @ast::expr{id:1, - callee_id:2, node:ast::expr_path(@ast::Path {span:sp(0,1), global:false, - idents:~[mk_ident(100)], + idents:~[str_to_ident("a")], rp:None, types:~[]}), span:sp(0,1)}) @@ -465,12 +382,12 @@ mod test { #[test] fn path_exprs_2 () { assert_eq!(string_to_expr(@~"::a::b"), @ast::expr{id:1, - callee_id:2, - node:ast::expr_path(@ast::Path {span:sp(0,6), - global:true, - idents:ints_to_idents(~[100,101]), - rp:None, - types:~[]}), + node:ast::expr_path( + @ast::Path {span:sp(0,6), + global:true, + idents:strs_to_idents(~["a","b"]), + rp:None, + types:~[]}), span:sp(0,6)}) } @@ -482,7 +399,7 @@ mod test { }*/ #[test] fn string_to_tts_1 () { - let (tts,_ps) = string_to_tts_t(@~"fn a (b : int) { b; }"); + let (tts,_ps) = string_to_tts_and_sess(@~"fn a (b : int) { b; }"); assert_eq!(to_json_str(@tts), ~"[\ [\"tt_tok\",null,[\"IDENT\",\"fn\",false]],\ @@ -512,14 +429,13 @@ mod test { #[test] fn ret_expr() { assert_eq!(string_to_expr(@~"return d"), - @ast::expr{id:3, - callee_id:4, + @ast::expr{id:2, node:ast::expr_ret( - Some(@ast::expr{id:1,callee_id:2, + Some(@ast::expr{id:1, node:ast::expr_path( @ast::Path{span:sp(7,8), global:false, - idents:~[mk_ident(103)], + idents:~[str_to_ident("d")], rp:None, types:~[] }), @@ -532,16 +448,15 @@ mod test { @spanned{ node: ast::stmt_expr(@ast::expr{ id: 1, - callee_id: 2, node: ast::expr_path( @ast::Path{ span:sp(0,1), global:false, - idents:~[mk_ident(101)], + idents:~[str_to_ident("b")], rp:None, types: ~[]}), span: sp(0,1)}, - 3), // fixme + 2), // fixme span: sp(0,1)}) } @@ -552,13 +467,13 @@ mod test { #[test] fn parse_ident_pat () { let parser = string_to_parser(@~"b"); - assert_eq!(parser.parse_pat(false), + assert_eq!(parser.parse_pat(), @ast::pat{id:1, // fixme - node: ast::pat_ident(ast::bind_by_copy, + node: ast::pat_ident(ast::bind_infer, @ast::Path{ span:sp(0,1), global:false, - idents:~[mk_ident(101)], + idents:~[str_to_ident("b")], rp: None, types: ~[]}, None // no idea @@ -577,17 +492,17 @@ mod test { span:sp(4,4), // this is bizarre... // check this in the original parser? global:false, - idents:~[mk_ident(105)], + idents:~[str_to_ident("int")], rp: None, types: ~[]}, 2), span:sp(4,7)}, pat: @ast::pat{id:1, - node: ast::pat_ident(ast::bind_by_copy, + node: ast::pat_ident(ast::bind_infer, @ast::Path{ span:sp(0,1), global:false, - idents:~[mk_ident(101)], + idents:~[str_to_ident("b")], rp: None, types: ~[]}, None // no idea @@ -603,9 +518,9 @@ mod test { // assignment order of the node_ids. assert_eq!(string_to_item(@~"fn a (b : int) { b; }"), Some( - @ast::item{ident:mk_ident(100), + @ast::item{ident:str_to_ident("a"), attrs:~[], - id: 10, // fixme + id: 9, // fixme node: ast::item_fn(ast::fn_decl{ inputs: ~[ast::arg{ is_mutbl: false, @@ -613,18 +528,18 @@ mod test { node: ast::ty_path(@ast::Path{ span:sp(10,13), global:false, - idents:~[mk_ident(106)], + idents:~[str_to_ident("int")], rp: None, types: ~[]}, 2), span:sp(10,13)}, pat: @ast::pat{id:1, // fixme node: ast::pat_ident( - ast::bind_by_copy, + ast::bind_infer, @ast::Path{ span:sp(6,7), global:false, - idents:~[mk_ident(101)], + idents:~[str_to_ident("b")], rp: None, types: ~[]}, None // no idea @@ -650,19 +565,18 @@ mod test { stmts: ~[@spanned{ node: ast::stmt_semi(@ast::expr{ id: 6, - callee_id: 7, node: ast::expr_path( @ast::Path{ span:sp(17,18), global:false, - idents:~[mk_ident(101)], + idents:~[str_to_ident("b")], rp:None, types: ~[]}), span: sp(17,18)}, - 8), // fixme + 7), // fixme span: sp(17,18)}], expr: None, - id: 9, // fixme + id: 8, // fixme rules: ast::default_blk // no idea }}), vis: ast::inherited, @@ -675,4 +589,20 @@ mod test { string_to_expr(@~"3 + 4"); string_to_expr(@~"a::z.froob(b,@(987+3))"); } + + #[test] fn attrs_fix_bug () { + string_to_item(@~"pub fn mk_file_writer(path: &Path, flags: &[FileFlag]) + -> Result<@Writer, ~str> { + #[cfg(windows)] + fn wb() -> c_int { + (O_WRONLY | libc::consts::os::extra::O_BINARY) as c_int + } + + #[cfg(unix)] + fn wb() -> c_int { O_WRONLY as c_int } + + let mut fflags: c_int = wb(); +}"); + } + } diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index 859fde90e2998..61b7f1403e642 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -17,14 +17,16 @@ Obsolete syntax that becomes too hard to parse can be removed. */ +use core::prelude::*; use ast::{expr, expr_lit, lit_nil, attribute}; use ast; use codemap::{span, respan}; use parse::parser::Parser; -use parse::token::Token; +use parse::token::{keywords, Token}; use parse::token; +use core::str; use core::to_bytes; /// The specific types of unsupported syntax @@ -47,7 +49,7 @@ pub enum ObsoleteSyntax { ObsoleteTraitBoundSeparator, ObsoleteMutOwnedPointer, ObsoleteMutVector, - ObsoleteTraitImplVisibility, + ObsoleteImplVisibility, ObsoleteRecordType, ObsoleteRecordPattern, ObsoletePostFnTySigil, @@ -62,16 +64,9 @@ pub enum ObsoleteSyntax { ObsoleteConstItem, ObsoleteFixedLengthVectorType, ObsoleteNamedExternModule, + ObsoleteMultipleLocalDecl, } -#[cfg(stage0)] -impl to_bytes::IterBytes for ObsoleteSyntax { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - (*self as uint).iter_bytes(lsb0, f); - } -} -#[cfg(not(stage0))] impl to_bytes::IterBytes for ObsoleteSyntax { #[inline(always)] fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { @@ -79,9 +74,9 @@ impl to_bytes::IterBytes for ObsoleteSyntax { } } -pub impl Parser { +impl Parser { /// Reports an obsolete syntax non-fatal error. - fn obsolete(&self, sp: span, kind: ObsoleteSyntax) { + pub fn obsolete(&self, sp: span, kind: ObsoleteSyntax) { let (kind_str, desc) = match kind { ObsoleteLowerCaseKindBounds => ( "lower-case kind bounds", @@ -164,11 +159,10 @@ pub impl Parser { in a mutable location, like a mutable local variable or an \ `@mut` box" ), - ObsoleteTraitImplVisibility => ( - "visibility-qualified trait implementation", - "`pub` or `priv` is meaningless for trait implementations, \ - because the `impl...for...` form defines overloads for \ - methods that already exist; remove the `pub` or `priv`" + ObsoleteImplVisibility => ( + "visibility-qualified implementation", + "`pub` or `priv` goes on individual functions; remove the \ + `pub` or `priv`" ), ObsoleteRecordType => ( "structural record type", @@ -231,6 +225,11 @@ pub impl Parser { "instead of `extern mod foo { ... }`, write `mod foo { \ extern { ... } }`" ), + ObsoleteMultipleLocalDecl => ( + "declaration of multiple locals at once", + "instead of e.g. `let a = 1, b = 2`, write \ + `let (a, b) = (1, 2)`." + ), }; self.report(sp, kind, kind_str, desc); @@ -238,13 +237,16 @@ pub impl Parser { // Reports an obsolete syntax non-fatal error, and returns // a placeholder expression - fn obsolete_expr(&self, sp: span, kind: ObsoleteSyntax) -> @expr { + pub fn obsolete_expr(&self, sp: span, kind: ObsoleteSyntax) -> @expr { self.obsolete(sp, kind); self.mk_expr(sp.lo, sp.hi, expr_lit(@respan(sp, lit_nil))) } - priv fn report(&self, sp: span, kind: ObsoleteSyntax, kind_str: &str, - desc: &str) { + fn report(&self, + sp: span, + kind: ObsoleteSyntax, + kind_str: &str, + desc: &str) { self.span_err(sp, fmt!("obsolete syntax: %s", kind_str)); if !self.obsolete_set.contains(&kind) { @@ -253,7 +255,8 @@ pub impl Parser { } } - fn token_is_obsolete_ident(&self, ident: &str, token: &Token) -> bool { + pub fn token_is_obsolete_ident(&self, ident: &str, token: &Token) + -> bool { match *token { token::IDENT(sid, _) => { str::eq_slice(*self.id_to_str(sid), ident) @@ -262,11 +265,11 @@ pub impl Parser { } } - fn is_obsolete_ident(&self, ident: &str) -> bool { + pub fn is_obsolete_ident(&self, ident: &str) -> bool { self.token_is_obsolete_ident(ident, self.token) } - fn eat_obsolete_ident(&self, ident: &str) -> bool { + pub fn eat_obsolete_ident(&self, ident: &str) -> bool { if self.is_obsolete_ident(ident) { self.bump(); true @@ -275,7 +278,7 @@ pub impl Parser { } } - fn try_parse_obsolete_struct_ctor(&self) -> bool { + pub fn try_parse_obsolete_struct_ctor(&self) -> bool { if self.eat_obsolete_ident("new") { self.obsolete(*self.last_span, ObsoleteStructCtor); self.parse_fn_decl(); @@ -286,7 +289,7 @@ pub impl Parser { } } - fn try_parse_obsolete_with(&self) -> bool { + pub fn try_parse_obsolete_with(&self) -> bool { if *self.token == token::COMMA && self.token_is_obsolete_ident("with", &self.look_ahead(1u)) { @@ -301,10 +304,11 @@ pub impl Parser { } } - fn try_parse_obsolete_priv_section(&self, attrs: &[attribute]) -> bool { - if self.is_keyword("priv") && self.look_ahead(1) == token::LBRACE { + pub fn try_parse_obsolete_priv_section(&self, attrs: &[attribute]) + -> bool { + if self.is_keyword(keywords::Priv) && self.look_ahead(1) == token::LBRACE { self.obsolete(copy *self.span, ObsoletePrivSection); - self.eat_keyword("priv"); + self.eat_keyword(keywords::Priv); self.bump(); while *self.token != token::RBRACE { self.parse_single_struct_field(ast::private, attrs.to_owned()); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 25b45a5f3b5cc..2fd0a7e33fff0 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use abi; use abi::AbiSet; use ast::{Sigil, BorrowedSigil, ManagedSigil, OwnedSigil}; @@ -16,7 +18,7 @@ use ast::{TyBareFn, TyClosure}; use ast::{RegionTyParamBound, TraitTyParamBound}; use ast::{provided, public, purity}; use ast::{_mod, add, arg, arm, attribute, bind_by_ref, bind_infer}; -use ast::{bind_by_copy, bitand, bitor, bitxor, blk}; +use ast::{bitand, bitor, bitxor, blk}; use ast::{blk_check_mode, box}; use ast::{crate, crate_cfg, decl, decl_item}; use ast::{decl_local, default_blk, deref, div, enum_def, explicit_self}; @@ -30,10 +32,10 @@ use ast::{expr_ret, expr_self, expr_struct, expr_tup, expr_unary}; use ast::{expr_vec, expr_vstore, expr_vstore_mut_box}; use ast::{expr_vstore_slice, expr_vstore_box}; use ast::{expr_vstore_mut_slice, expr_while, extern_fn, field, fn_decl}; -use ast::{expr_vstore_uniq, TyClosure, TyBareFn, Onceness, Once, Many}; +use ast::{expr_vstore_uniq, Onceness, Once, Many}; use ast::{foreign_item, foreign_item_const, foreign_item_fn, foreign_mod}; use ast::{ident, impure_fn, inherited, item, item_, item_const}; -use ast::{item_const, item_enum, item_fn, item_foreign_mod, item_impl}; +use ast::{item_enum, item_fn, item_foreign_mod, item_impl}; use ast::{item_mac, item_mod, item_struct, item_trait, item_ty, lit, lit_}; use ast::{lit_bool, lit_float, lit_float_unsuffixed, lit_int}; use ast::{lit_int_unsuffixed, lit_nil, lit_str, lit_uint, local, m_const}; @@ -74,7 +76,7 @@ use parse::obsolete::{ObsoleteMoveInit, ObsoleteBinaryMove, ObsoleteSwap}; use parse::obsolete::{ObsoleteSyntax, ObsoleteLowerCaseKindBounds}; use parse::obsolete::{ObsoleteUnsafeBlock, ObsoleteImplSyntax}; use parse::obsolete::{ObsoleteTraitBoundSeparator, ObsoleteMutOwnedPointer}; -use parse::obsolete::{ObsoleteMutVector, ObsoleteTraitImplVisibility}; +use parse::obsolete::{ObsoleteMutVector, ObsoleteImplVisibility}; use parse::obsolete::{ObsoleteRecordType, ObsoleteRecordPattern}; use parse::obsolete::{ObsoletePostFnTySigil}; use parse::obsolete::{ObsoleteBareFnType, ObsoleteNewtypeEnum}; @@ -82,9 +84,9 @@ use parse::obsolete::ObsoleteMode; use parse::obsolete::{ObsoleteLifetimeNotation, ObsoleteConstManagedPointer}; use parse::obsolete::{ObsoletePurity, ObsoleteStaticMethod}; use parse::obsolete::{ObsoleteConstItem, ObsoleteFixedLengthVectorType}; -use parse::obsolete::{ObsoleteNamedExternModule}; -use parse::token::{can_begin_expr, is_ident, is_ident_or_path}; -use parse::token::{is_plain_ident, INTERPOLATED, special_idents, token_to_binop}; +use parse::obsolete::{ObsoleteNamedExternModule, ObsoleteMultipleLocalDecl}; +use parse::token::{can_begin_expr, get_ident_interner, ident_to_str, is_ident, is_ident_or_path}; +use parse::token::{is_plain_ident, INTERPOLATED, keywords, special_idents, token_to_binop}; use parse::token; use parse::{new_sub_parser_from_file, next_node_id, ParseSess}; use opt_vec; @@ -93,6 +95,7 @@ use opt_vec::OptVec; use core::either::Either; use core::either; use core::hashmap::HashSet; +use core::str; use core::vec; #[deriving(Eq)] @@ -127,11 +130,11 @@ at INTERPOLATED tokens */ macro_rules! maybe_whole_expr ( ($p:expr) => ( match *($p).token { - INTERPOLATED(token::nt_expr(copy e)) => { + INTERPOLATED(token::nt_expr(e)) => { $p.bump(); return e; } - INTERPOLATED(token::nt_path(copy pt)) => { + INTERPOLATED(token::nt_path(pt)) => { $p.bump(); return $p.mk_expr( ($p).span.lo, @@ -146,8 +149,8 @@ macro_rules! maybe_whole_expr ( macro_rules! maybe_whole ( ($p:expr, $constructor:ident) => ( - match *($p).token { - INTERPOLATED(token::$constructor(copy x)) => { + match copy *($p).token { + INTERPOLATED(token::$constructor(x)) => { $p.bump(); return x; } @@ -155,8 +158,8 @@ macro_rules! maybe_whole ( } ); (deref $p:expr, $constructor:ident) => ( - match *($p).token { - INTERPOLATED(token::$constructor(copy x)) => { + match copy *($p).token { + INTERPOLATED(token::$constructor(x)) => { $p.bump(); return copy *x; } @@ -164,8 +167,8 @@ macro_rules! maybe_whole ( } ); (Some $p:expr, $constructor:ident) => ( - match *($p).token { - INTERPOLATED(token::$constructor(copy x)) => { + match copy *($p).token { + INTERPOLATED(token::$constructor(x)) => { $p.bump(); return Some(x); } @@ -173,8 +176,8 @@ macro_rules! maybe_whole ( } ); (iovi $p:expr, $constructor:ident) => ( - match *($p).token { - INTERPOLATED(token::$constructor(copy x)) => { + match copy *($p).token { + INTERPOLATED(token::$constructor(x)) => { $p.bump(); return iovi_item(x); } @@ -182,8 +185,8 @@ macro_rules! maybe_whole ( } ); (pair_empty $p:expr, $constructor:ident) => ( - match *($p).token { - INTERPOLATED(token::$constructor(copy x)) => { + match copy *($p).token { + INTERPOLATED(token::$constructor(x)) => { $p.bump(); return (~[], x); } @@ -216,7 +219,7 @@ pub fn Parser(sess: @mut ParseSess, rdr: @reader) -> Parser { let tok0 = copy rdr.next_token(); - let interner = rdr.interner(); + let interner = get_ident_interner(); Parser { reader: rdr, @@ -232,9 +235,6 @@ pub fn Parser(sess: @mut ParseSess, tokens_consumed: @mut 0, restriction: @mut UNRESTRICTED, quote_depth: @mut 0, - keywords: token::keyword_table(), - strict_keywords: token::strict_keyword_table(), - reserved_keywords: token::reserved_keyword_table(), obsolete_set: @mut HashSet::new(), mod_path_stack: @mut ~[], } @@ -258,9 +258,6 @@ pub struct Parser { quote_depth: @mut uint, // not (yet) related to the quasiquoter reader: @reader, interner: @token::ident_interner, - keywords: HashSet<~str>, - strict_keywords: HashSet<~str>, - reserved_keywords: HashSet<~str>, /// The set of seen errors about obsolete syntax. Used to suppress /// extra detail when the same error is seen twice obsolete_set: @mut HashSet, @@ -275,9 +272,9 @@ impl Drop for Parser { fn finalize(&self) {} } -pub impl Parser { +impl Parser { // advance the parser by one token - fn bump(&self) { + pub fn bump(&self) { *self.last_span = copy *self.span; let next = if *self.buffer_start == *self.buffer_end { self.reader.next_token() @@ -291,17 +288,20 @@ pub impl Parser { *self.tokens_consumed += 1u; } // EFFECT: replace the current token and span with the given one - fn replace_token(&self, next: token::Token, lo: BytePos, hi: BytePos) { + pub fn replace_token(&self, + next: token::Token, + lo: BytePos, + hi: BytePos) { *self.token = next; *self.span = mk_sp(lo, hi); } - fn buffer_length(&self) -> int { + pub fn buffer_length(&self) -> int { if *self.buffer_start <= *self.buffer_end { return *self.buffer_end - *self.buffer_start; } return (4 - *self.buffer_start) + *self.buffer_end; } - fn look_ahead(&self, distance: uint) -> token::Token { + pub fn look_ahead(&self, distance: uint) -> token::Token { let dist = distance as int; while self.buffer_length() < dist { self.buffer[*self.buffer_end] = self.reader.next_token(); @@ -309,58 +309,57 @@ pub impl Parser { } return copy self.buffer[(*self.buffer_start + dist - 1) & 3].tok; } - fn fatal(&self, m: &str) -> ! { + pub fn fatal(&self, m: &str) -> ! { self.sess.span_diagnostic.span_fatal(*copy self.span, m) } - fn span_fatal(&self, sp: span, m: &str) -> ! { + pub fn span_fatal(&self, sp: span, m: &str) -> ! { self.sess.span_diagnostic.span_fatal(sp, m) } - fn span_note(&self, sp: span, m: &str) { + pub fn span_note(&self, sp: span, m: &str) { self.sess.span_diagnostic.span_note(sp, m) } - fn bug(&self, m: &str) -> ! { + pub fn bug(&self, m: &str) -> ! { self.sess.span_diagnostic.span_bug(*copy self.span, m) } - fn warn(&self, m: &str) { + pub fn warn(&self, m: &str) { self.sess.span_diagnostic.span_warn(*copy self.span, m) } - fn span_err(&self, sp: span, m: &str) { + pub fn span_err(&self, sp: span, m: &str) { self.sess.span_diagnostic.span_err(sp, m) } - fn abort_if_errors(&self) { + pub fn abort_if_errors(&self) { self.sess.span_diagnostic.handler().abort_if_errors(); } - fn get_id(&self) -> node_id { next_node_id(self.sess) } + pub fn get_id(&self) -> node_id { next_node_id(self.sess) } - fn id_to_str(&self, id: ident) -> @~str { - self.sess.interner.get(id) + pub fn id_to_str(&self, id: ident) -> @~str { + get_ident_interner().get(id.name) } // is this one of the keywords that signals a closure type? - fn token_is_closure_keyword(&self, tok: &token::Token) -> bool { - self.token_is_keyword("pure", tok) || - self.token_is_keyword("unsafe", tok) || - self.token_is_keyword("once", tok) || - self.token_is_keyword("fn", tok) + pub fn token_is_closure_keyword(&self, tok: &token::Token) -> bool { + token::is_keyword(keywords::Pure, tok) || + token::is_keyword(keywords::Unsafe, tok) || + token::is_keyword(keywords::Once, tok) || + token::is_keyword(keywords::Fn, tok) } - fn token_is_lifetime(&self, tok: &token::Token) -> bool { + pub fn token_is_lifetime(&self, tok: &token::Token) -> bool { match *tok { token::LIFETIME(*) => true, _ => false, } } - fn get_lifetime(&self, tok: &token::Token) -> ast::ident { + pub fn get_lifetime(&self, tok: &token::Token) -> ast::ident { match *tok { token::LIFETIME(ref ident) => copy *ident, - _ => self.bug(~"not a lifetime"), + _ => self.bug("not a lifetime"), } } // parse a ty_bare_fun type: - fn parse_ty_bare_fn(&self) -> ty_ - { + pub fn parse_ty_bare_fn(&self) -> ty_ { /* extern "ABI" [pure|unsafe] fn <'lt> (S) -> T @@ -378,7 +377,7 @@ pub impl Parser { let opt_abis = self.parse_opt_abis(); let abis = opt_abis.get_or_default(AbiSet::Rust()); let purity = self.parse_unsafety(); - self.expect_keyword("fn"); + self.expect_keyword(keywords::Fn); let (decl, lifetimes) = self.parse_ty_fn_decl(); return ty_bare_fn(@TyBareFn { abis: abis, @@ -389,10 +388,10 @@ pub impl Parser { } // parse a ty_closure type - fn parse_ty_closure(&self, - sigil: ast::Sigil, - region: Option<@ast::Lifetime>) - -> ty_ { + pub fn parse_ty_closure(&self, + sigil: ast::Sigil, + region: Option<@ast::Lifetime>) + -> ty_ { /* (&|~|@) ['r] [pure|unsafe] [once] fn [:Bounds] <'lt> (S) -> T @@ -414,7 +413,7 @@ pub impl Parser { let purity = self.parse_unsafety(); let onceness = parse_onceness(self); - self.expect_keyword("fn"); + self.expect_keyword(keywords::Fn); let bounds = self.parse_optional_ty_param_bounds(); if self.parse_fn_ty_sigil().is_some() { @@ -434,7 +433,7 @@ pub impl Parser { }); fn parse_onceness(this: &Parser) -> Onceness { - if this.eat_keyword(~"once") { + if this.eat_keyword(keywords::Once) { Once } else { Many @@ -443,11 +442,11 @@ pub impl Parser { } // looks like this should be called parse_unsafety - fn parse_unsafety(&self) -> purity { - if self.eat_keyword("pure") { + pub fn parse_unsafety(&self) -> purity { + if self.eat_keyword(keywords::Pure) { self.obsolete(*self.last_span, ObsoletePurity); return impure_fn; - } else if self.eat_keyword("unsafe") { + } else if self.eat_keyword(keywords::Unsafe) { return unsafe_fn; } else { return impure_fn; @@ -455,7 +454,7 @@ pub impl Parser { } // parse a function type (following the 'fn') - fn parse_ty_fn_decl(&self) -> (fn_decl, OptVec) { + pub fn parse_ty_fn_decl(&self) -> (fn_decl, OptVec) { /* (fn) <'lt> (S) -> T @@ -490,7 +489,7 @@ pub impl Parser { } // parse the methods in a trait declaration - fn parse_trait_methods(&self) -> ~[trait_method] { + pub fn parse_trait_methods(&self) -> ~[trait_method] { do self.parse_unspanned_seq( &token::LBRACE, &token::RBRACE, @@ -566,9 +565,8 @@ pub impl Parser { } } - // parse a possibly mutable type - fn parse_mt(&self) -> mt { + pub fn parse_mt(&self) -> mt { let mutbl = self.parse_mutability(); let t = self.parse_ty(false); mt { ty: t, mutbl: mutbl } @@ -576,7 +574,7 @@ pub impl Parser { // parse [mut/const/imm] ID : TY // now used only by obsolete record syntax parser... - fn parse_ty_field(&self) -> ty_field { + pub fn parse_ty_field(&self) -> ty_field { let lo = self.span.lo; let mutbl = self.parse_mutability(); let id = self.parse_ident(); @@ -593,7 +591,7 @@ pub impl Parser { } // parse optional return type [ -> TY ] in function decl - fn parse_ret_ty(&self) -> (ret_style, @Ty) { + pub fn parse_ret_ty(&self) -> (ret_style, @Ty) { return if self.eat(&token::RARROW) { let lo = self.span.lo; if self.eat(&token::NOT) { @@ -624,7 +622,7 @@ pub impl Parser { // parse a type. // Useless second parameter for compatibility with quasiquote macros. // Bleh! - fn parse_ty(&self, _: bool) -> @Ty { + pub fn parse_ty(&self, _: bool) -> @Ty { maybe_whole!(self, nt_ty); let lo = self.span.lo; @@ -702,7 +700,7 @@ pub impl Parser { // BORROWED POINTER self.bump(); self.parse_borrowed_pointee() - } else if self.eat_keyword("extern") { + } else if self.eat_keyword(keywords::Extern) { // EXTERN FUNCTION self.parse_ty_bare_fn() } else if self.token_is_closure_keyword(© *self.token) { @@ -725,11 +723,9 @@ pub impl Parser { } // parse the type following a @ or a ~ - fn parse_box_or_uniq_pointee( - &self, - sigil: ast::Sigil, - ctor: &fn(v: mt) -> ty_) -> ty_ - { + pub fn parse_box_or_uniq_pointee(&self, + sigil: ast::Sigil, + ctor: &fn(v: mt) -> ty_) -> ty_ { // @'foo fn() or @foo/fn() or @fn() are parsed directly as fn types: match *self.token { token::LIFETIME(*) => { @@ -768,7 +764,7 @@ pub impl Parser { ctor(mt) } - fn parse_borrowed_pointee(&self) -> ty_ { + pub fn parse_borrowed_pointee(&self) -> ty_ { // look for `&'lt` or `&'foo ` and interpret `foo` as the region name: let opt_lifetime = self.parse_opt_lifetime(); @@ -781,7 +777,7 @@ pub impl Parser { } // parse an optional, obsolete argument mode. - fn parse_arg_mode(&self) { + pub fn parse_arg_mode(&self) { if self.eat(&token::BINOP(token::MINUS)) { self.obsolete(*self.span, ObsoleteMode); } else if self.eat(&token::ANDAND) { @@ -797,7 +793,7 @@ pub impl Parser { } } - fn is_named_argument(&self) -> bool { + pub fn is_named_argument(&self) -> bool { let offset = if *self.token == token::BINOP(token::AND) { 1 } else if *self.token == token::BINOP(token::MINUS) { @@ -822,12 +818,12 @@ pub impl Parser { // This version of parse arg doesn't necessarily require // identifier names. - fn parse_arg_general(&self, require_name: bool) -> arg { + pub fn parse_arg_general(&self, require_name: bool) -> arg { let mut is_mutbl = false; let pat = if require_name || self.is_named_argument() { self.parse_arg_mode(); - is_mutbl = self.eat_keyword("mut"); - let pat = self.parse_pat(false); + is_mutbl = self.eat_keyword(keywords::Mut); + let pat = self.parse_pat(); self.expect(&token::COLON); pat } else { @@ -847,15 +843,15 @@ pub impl Parser { } // parse a single function argument - fn parse_arg(&self) -> arg_or_capture_item { + pub fn parse_arg(&self) -> arg_or_capture_item { either::Left(self.parse_arg_general(true)) } // parse an argument in a lambda header e.g. |arg, arg| - fn parse_fn_block_arg(&self) -> arg_or_capture_item { + pub fn parse_fn_block_arg(&self) -> arg_or_capture_item { self.parse_arg_mode(); - let is_mutbl = self.eat_keyword("mut"); - let pat = self.parse_pat(false); + let is_mutbl = self.eat_keyword(keywords::Mut); + let pat = self.parse_pat(); let t = if self.eat(&token::COLON) { self.parse_ty(false) } else { @@ -873,7 +869,7 @@ pub impl Parser { }) } - fn maybe_parse_fixed_vstore(&self) -> Option<@ast::expr> { + pub fn maybe_parse_fixed_vstore(&self) -> Option<@ast::expr> { if self.eat(&token::BINOP(token::STAR)) { self.obsolete(*self.last_span, ObsoleteFixedLengthVectorType); Some(self.parse_expr()) @@ -888,7 +884,7 @@ pub impl Parser { } // matches token_lit = LIT_INT | ... - fn lit_from_token(&self, tok: &token::Token) -> lit_ { + pub fn lit_from_token(&self, tok: &token::Token) -> lit_ { match *tok { token::LIT_INT(i, it) => lit_int(i, it), token::LIT_UINT(u, ut) => lit_uint(u, ut), @@ -903,11 +899,11 @@ pub impl Parser { } // matches lit = true | false | token_lit - fn parse_lit(&self) -> lit { + pub fn parse_lit(&self) -> lit { let lo = self.span.lo; - let lit = if self.eat_keyword("true") { + let lit = if self.eat_keyword(keywords::True) { lit_bool(true) - } else if self.eat_keyword("false") { + } else if self.eat_keyword(keywords::False) { lit_bool(false) } else { // XXX: This is a really bad copy! @@ -919,7 +915,7 @@ pub impl Parser { } // matches '-' lit | lit - fn parse_literal_maybe_minus(&self) -> @expr { + pub fn parse_literal_maybe_minus(&self) -> @expr { let minus_lo = self.span.lo; let minus_present = self.eat(&token::BINOP(token::MINUS)); @@ -930,7 +926,7 @@ pub impl Parser { if minus_present { let minus_hi = self.span.hi; - self.mk_expr(minus_lo, minus_hi, expr_unary(neg, expr)) + self.mk_expr(minus_lo, minus_hi, self.mk_unary(neg, expr)) } else { expr } @@ -938,7 +934,7 @@ pub impl Parser { // parse a path into a vector of idents, whether the path starts // with ::, and a span. - fn parse_path(&self) -> (~[ast::ident],bool,span) { + pub fn parse_path(&self) -> (~[ast::ident],bool,span) { let lo = self.span.lo; let is_global = self.eat(&token::MOD_SEP); let (ids,span{lo:_,hi,expn_info}) = self.parse_path_non_global(); @@ -946,7 +942,7 @@ pub impl Parser { } // parse a path beginning with an identifier into a vector of idents and a span - fn parse_path_non_global(&self) -> (~[ast::ident],span) { + pub fn parse_path_non_global(&self) -> (~[ast::ident],span) { let lo = self.span.lo; let mut ids = ~[]; // must be at least one to begin: @@ -969,8 +965,7 @@ pub impl Parser { } // parse a path that doesn't have type parameters attached - fn parse_path_without_tps(&self) - -> @ast::Path { + pub fn parse_path_without_tps(&self) -> @ast::Path { maybe_whole!(self, nt_path); let (ids,is_global,sp) = self.parse_path(); @ast::Path { span: sp, @@ -983,7 +978,7 @@ pub impl Parser { // parse a path optionally with type parameters. If 'colons' // is true, then type parameters must be preceded by colons, // as in a::t:: - fn parse_path_with_tps(&self, colons: bool) -> @ast::Path { + pub fn parse_path_with_tps(&self, colons: bool) -> @ast::Path { debug!("parse_path_with_tps(colons=%b)", colons); maybe_whole!(self, nt_path); @@ -1045,7 +1040,7 @@ pub impl Parser { } /// parses 0 or 1 lifetime - fn parse_opt_lifetime(&self) -> Option<@ast::Lifetime> { + pub fn parse_opt_lifetime(&self) -> Option<@ast::Lifetime> { match *self.token { token::LIFETIME(*) => { Some(@self.parse_lifetime()) @@ -1067,7 +1062,7 @@ pub impl Parser { } } - fn token_is_lifetime(&self, tok: &token::Token) -> bool { + pub fn token_is_lifetime(&self, tok: &token::Token) -> bool { match *tok { token::LIFETIME(_) => true, _ => false @@ -1076,7 +1071,7 @@ pub impl Parser { /// Parses a single lifetime // matches lifetime = ( LIFETIME ) | ( IDENT / ) - fn parse_lifetime(&self) -> ast::Lifetime { + pub fn parse_lifetime(&self) -> ast::Lifetime { match *self.token { token::LIFETIME(i) => { let span = copy self.span; @@ -1110,7 +1105,7 @@ pub impl Parser { // matches lifetimes = ( lifetime ) | ( lifetime , lifetimes ) // actually, it matches the empty one too, but putting that in there // messes up the grammar.... - fn parse_lifetimes(&self) -> OptVec { + pub fn parse_lifetimes(&self) -> OptVec { /*! * * Parses zero or more comma separated lifetimes. @@ -1142,16 +1137,16 @@ pub impl Parser { } } - fn token_is_mutability(&self, tok: &token::Token) -> bool { - self.token_is_keyword("mut", tok) || - self.token_is_keyword("const", tok) + pub fn token_is_mutability(&self, tok: &token::Token) -> bool { + token::is_keyword(keywords::Mut, tok) || + token::is_keyword(keywords::Const, tok) } // parse mutability declaration (mut/const/imm) - fn parse_mutability(&self) -> mutability { - if self.eat_keyword("mut") { + pub fn parse_mutability(&self) -> mutability { + if self.eat_keyword(keywords::Mut) { m_mutbl - } else if self.eat_keyword("const") { + } else if self.eat_keyword(keywords::Const) { m_const } else { m_imm @@ -1159,34 +1154,67 @@ pub impl Parser { } // parse ident COLON expr - fn parse_field(&self) -> field { + pub fn parse_field(&self) -> field { let lo = self.span.lo; - let m = self.parse_mutability(); let i = self.parse_ident(); self.expect(&token::COLON); let e = self.parse_expr(); - spanned(lo, e.span.hi, ast::field_ { mutbl: m, ident: i, expr: e }) + spanned(lo, e.span.hi, ast::field_ { + ident: i, + expr: e + }) } - fn mk_expr(&self, lo: BytePos, hi: BytePos, node: expr_) -> @expr { + pub fn mk_expr(&self, lo: BytePos, hi: BytePos, node: expr_) -> @expr { @expr { id: self.get_id(), - callee_id: self.get_id(), node: node, span: mk_sp(lo, hi), } } - fn mk_mac_expr(&self, lo: BytePos, hi: BytePos, m: mac_) -> @expr { + pub fn mk_unary(&self, unop: ast::unop, expr: @expr) -> ast::expr_ { + expr_unary(self.get_id(), unop, expr) + } + + pub fn mk_binary(&self, binop: ast::binop, lhs: @expr, rhs: @expr) -> ast::expr_ { + expr_binary(self.get_id(), binop, lhs, rhs) + } + + pub fn mk_call(&self, f: @expr, args: ~[@expr], sugar: CallSugar) -> ast::expr_ { + expr_call(f, args, sugar) + } + + pub fn mk_method_call(&self, + rcvr: @expr, + ident: ident, + tps: ~[@Ty], + args: ~[@expr], + sugar: CallSugar) -> ast::expr_ { + expr_method_call(self.get_id(), rcvr, ident, tps, args, sugar) + } + + pub fn mk_index(&self, expr: @expr, idx: @expr) -> ast::expr_ { + expr_index(self.get_id(), expr, idx) + } + + pub fn mk_field(&self, expr: @expr, ident: ident, tys: ~[@Ty]) -> ast::expr_ { + expr_field(expr, ident, tys) + } + + pub fn mk_assign_op(&self, binop: ast::binop, lhs: @expr, rhs: @expr) -> ast::expr_ { + expr_assign_op(self.get_id(), binop, lhs, rhs) + } + + pub fn mk_mac_expr(&self, lo: BytePos, hi: BytePos, m: mac_) -> @expr { @expr { id: self.get_id(), - callee_id: self.get_id(), node: expr_mac(codemap::spanned {node: m, span: mk_sp(lo, hi)}), span: mk_sp(lo, hi), } } - fn mk_lit_u32(&self, i: u32) -> @expr { + pub fn mk_lit_u32(&self, i: u32) -> @expr { let span = self.span; let lv_lit = @codemap::spanned { node: lit_uint(i as u64, ty_u32), @@ -1195,7 +1223,6 @@ pub impl Parser { @expr { id: self.get_id(), - callee_id: self.get_id(), node: expr_lit(lv_lit), span: *span, } @@ -1204,7 +1231,7 @@ pub impl Parser { // at the bottom (top?) of the precedence hierarchy, // parse things like parenthesized exprs, // macros, return, etc. - fn parse_bottom_expr(&self) -> @expr { + pub fn parse_bottom_expr(&self) -> @expr { maybe_whole_expr!(self); let lo = self.span.lo; @@ -1249,30 +1276,30 @@ pub impl Parser { expr_block(blk)); } else if token::is_bar(&*self.token) { return self.parse_lambda_expr(); - } else if self.eat_keyword("self") { + } else if self.eat_keyword(keywords::Self) { ex = expr_self; hi = self.span.hi; - } else if self.eat_keyword("if") { + } else if self.eat_keyword(keywords::If) { return self.parse_if_expr(); - } else if self.eat_keyword("for") { + } else if self.eat_keyword(keywords::For) { return self.parse_sugary_call_expr(~"for", ForSugar, expr_loop_body); - } else if self.eat_keyword("do") { + } else if self.eat_keyword(keywords::Do) { return self.parse_sugary_call_expr(~"do", DoSugar, expr_do_body); - } else if self.eat_keyword("while") { + } else if self.eat_keyword(keywords::While) { return self.parse_while_expr(); } else if self.token_is_lifetime(&*self.token) { let lifetime = self.get_lifetime(&*self.token); self.bump(); self.expect(&token::COLON); - self.expect_keyword("loop"); + self.expect_keyword(keywords::Loop); return self.parse_loop_expr(Some(lifetime)); - } else if self.eat_keyword("loop") { + } else if self.eat_keyword(keywords::Loop) { return self.parse_loop_expr(None); - } else if self.eat_keyword("match") { + } else if self.eat_keyword(keywords::Match) { return self.parse_match_expr(); - } else if self.eat_keyword("unsafe") { + } else if self.eat_keyword(keywords::Unsafe) { return self.parse_block_expr(lo, unsafe_blk); } else if *self.token == token::LBRACKET { self.bump(); @@ -1311,8 +1338,8 @@ pub impl Parser { ex = expr_vec(~[first_expr], mutbl); } } - hi = self.span.hi; - } else if self.eat_keyword("__log") { + hi = self.last_span.hi; + } else if self.eat_keyword(keywords::__Log) { // LOG expression self.expect(&token::LPAREN); let lvl = self.parse_expr(); @@ -1321,14 +1348,14 @@ pub impl Parser { ex = expr_log(lvl, e); hi = self.span.hi; self.expect(&token::RPAREN); - } else if self.eat_keyword("return") { + } else if self.eat_keyword(keywords::Return) { // RETURN expression if can_begin_expr(&*self.token) { let e = self.parse_expr(); hi = e.span.hi; ex = expr_ret(Some(e)); } else { ex = expr_ret(None); } - } else if self.eat_keyword("break") { + } else if self.eat_keyword(keywords::Break) { // BREAK expression if self.token_is_lifetime(&*self.token) { let lifetime = self.get_lifetime(&*self.token); @@ -1338,14 +1365,14 @@ pub impl Parser { ex = expr_break(None); } hi = self.span.hi; - } else if self.eat_keyword("copy") { + } else if self.eat_keyword(keywords::Copy) { // COPY expression let e = self.parse_expr(); ex = expr_copy(e); hi = e.span.hi; } else if *self.token == token::MOD_SEP || - is_ident(&*self.token) && !self.is_keyword("true") && - !self.is_keyword("false") { + is_ident(&*self.token) && !self.is_keyword(keywords::True) && + !self.is_keyword(keywords::False) { let pth = self.parse_path_with_tps(true); // `!`, as an operator, is prefix, so we know this isn't that @@ -1354,7 +1381,7 @@ pub impl Parser { self.bump(); match *self.token { token::LPAREN | token::LBRACE => {} - _ => self.fatal(~"expected open delimiter") + _ => self.fatal("expected open delimiter") }; let ket = token::flip_delimiter(&*self.token); @@ -1415,23 +1442,20 @@ pub impl Parser { } // parse a block or unsafe block - fn parse_block_expr( - &self, - lo: BytePos, - blk_mode: blk_check_mode - ) -> @expr { + pub fn parse_block_expr(&self, lo: BytePos, blk_mode: blk_check_mode) + -> @expr { self.expect(&token::LBRACE); let blk = self.parse_block_tail(lo, blk_mode); return self.mk_expr(blk.span.lo, blk.span.hi, expr_block(blk)); } // parse a.b or a(13) or a[4] or just a - fn parse_dot_or_call_expr(&self) -> @expr { + pub fn parse_dot_or_call_expr(&self) -> @expr { let b = self.parse_bottom_expr(); self.parse_dot_or_call_expr_with(b) } - fn parse_dot_or_call_expr_with(&self, e0: @expr) -> @expr { + pub fn parse_dot_or_call_expr_with(&self, e0: @expr) -> @expr { let mut e = e0; let lo = e.span.lo; let mut hi; @@ -1460,11 +1484,11 @@ pub impl Parser { ); hi = self.span.hi; - let nd = expr_method_call(e, i, tys, es, NoSugar); + let nd = self.mk_method_call(e, i, tys, es, NoSugar); e = self.mk_expr(lo, hi, nd); } _ => { - e = self.mk_expr(lo, hi, expr_field(e, i, tys)); + e = self.mk_expr(lo, hi, self.mk_field(e, i, tys)); } } } @@ -1484,7 +1508,7 @@ pub impl Parser { ); hi = self.span.hi; - let nd = expr_call(e, es, NoSugar); + let nd = self.mk_call(e, es, NoSugar); e = self.mk_expr(lo, hi, nd); } @@ -1494,7 +1518,7 @@ pub impl Parser { let ix = self.parse_expr(); hi = ix.span.hi; self.expect(&token::RBRACKET); - e = self.mk_expr(lo, hi, expr_index(e, ix)); + e = self.mk_expr(lo, hi, self.mk_index(e, ix)); } _ => return e @@ -1505,7 +1529,7 @@ pub impl Parser { // parse an optional separator followed by a kleene-style // repetition token (+ or *). - fn parse_sep_and_zerok(&self) -> (Option, bool) { + pub fn parse_sep_and_zerok(&self) -> (Option, bool) { if *self.token == token::BINOP(token::STAR) || *self.token == token::BINOP(token::PLUS) { let zerok = *self.token == token::BINOP(token::STAR); @@ -1520,13 +1544,13 @@ pub impl Parser { self.bump(); (Some(sep), zerok) } else { - self.fatal(~"expected `*` or `+`"); + self.fatal("expected `*` or `+`"); } } } // parse a single token tree from the input. - fn parse_token_tree(&self) -> token_tree { + pub fn parse_token_tree(&self) -> token_tree { maybe_whole!(deref self, nt_tt); // this is the fall-through for the 'match' below. @@ -1587,7 +1611,7 @@ pub impl Parser { match *self.token { token::EOF => { - self.fatal(~"file ended with unbalanced delimiters"); + self.fatal("file ended with unbalanced delimiters"); } token::LPAREN | token::LBRACE | token::LBRACKET => { let close_delim = token::flip_delimiter(&*self.token); @@ -1602,7 +1626,7 @@ pub impl Parser { |p| p.parse_token_tree() ), // the close delimiter: - ~[parse_any_tt_tok(self)] + [parse_any_tt_tok(self)] ) ) ) @@ -1613,7 +1637,7 @@ pub impl Parser { // parse a stream of tokens into a list of token_trees, // up to EOF. - fn parse_all_token_trees(&self) -> ~[token_tree] { + pub fn parse_all_token_trees(&self) -> ~[token_tree] { let mut tts = ~[]; while *self.token != token::EOF { tts.push(self.parse_token_tree()); @@ -1621,7 +1645,7 @@ pub impl Parser { tts } - fn parse_matchers(&self) -> ~[matcher] { + pub fn parse_matchers(&self) -> ~[matcher] { // unification of matchers and token_trees would vastly improve // the interpolation of matchers maybe_whole!(self, nt_matchers); @@ -1635,7 +1659,7 @@ pub impl Parser { token::flip_delimiter(self.token) ) } - _ => self.fatal(~"expected open delimiter") + _ => self.fatal("expected open delimiter") } } @@ -1643,12 +1667,11 @@ pub impl Parser { // This goofy function is necessary to correctly match parens in matchers. // Otherwise, `$( ( )` would be a valid matcher, and `$( () )` would be // invalid. It's similar to common::parse_seq. - fn parse_matcher_subseq( - &self, - name_idx: @mut uint, - bra: token::Token, - ket: token::Token - ) -> ~[matcher] { + pub fn parse_matcher_subseq(&self, + name_idx: @mut uint, + bra: token::Token, + ket: token::Token) + -> ~[matcher] { let mut ret_val = ~[]; let mut lparens = 0u; @@ -1665,7 +1688,7 @@ pub impl Parser { return ret_val; } - fn parse_matcher(&self, name_idx: @mut uint) -> matcher { + pub fn parse_matcher(&self, name_idx: @mut uint) -> matcher { let lo = self.span.lo; let m = if *self.token == token::DOLLAR { @@ -1678,7 +1701,7 @@ pub impl Parser { token::RPAREN ); if ms.len() == 0u { - self.fatal(~"repetition body must be nonempty"); + self.fatal("repetition body must be nonempty"); } let (sep, zerok) = self.parse_sep_and_zerok(); match_seq(ms, sep, zerok, name_idx_lo, *name_idx) @@ -1700,7 +1723,7 @@ pub impl Parser { } // parse a prefix-operator expr - fn parse_prefix_expr(&self) -> @expr { + pub fn parse_prefix_expr(&self) -> @expr { let lo = self.span.lo; let hi; @@ -1710,7 +1733,7 @@ pub impl Parser { self.bump(); let e = self.parse_prefix_expr(); hi = e.span.hi; - ex = expr_unary(not, e); + ex = self.mk_unary(not, e); } token::BINOP(b) => { match b { @@ -1718,13 +1741,13 @@ pub impl Parser { self.bump(); let e = self.parse_prefix_expr(); hi = e.span.hi; - ex = expr_unary(neg, e); + ex = self.mk_unary(neg, e); } token::STAR => { self.bump(); let e = self.parse_prefix_expr(); hi = e.span.hi; - ex = expr_unary(deref, e); + ex = self.mk_unary(deref, e); } token::AND => { self.bump(); @@ -1765,7 +1788,7 @@ pub impl Parser { expr_vec(*) | expr_lit(@codemap::spanned { node: lit_str(_), span: _}) | expr_repeat(*) if m == m_imm => expr_vstore(e, expr_vstore_box), - _ => expr_unary(box(m), e) + _ => self.mk_unary(box(m), e) }; } token::TILDE => { @@ -1783,7 +1806,7 @@ pub impl Parser { expr_lit(@codemap::spanned { node: lit_str(_), span: _}) | expr_repeat(*) if m == m_imm => expr_vstore(e, expr_vstore_uniq), - _ => expr_unary(uniq(m), e) + _ => self.mk_unary(uniq(m), e) }; } _ => return self.parse_dot_or_call_expr() @@ -1792,13 +1815,12 @@ pub impl Parser { } // parse an expression of binops - fn parse_binops(&self) -> @expr { + pub fn parse_binops(&self) -> @expr { self.parse_more_binops(self.parse_prefix_expr(), 0) } // parse an expression of binops of at least min_prec precedence - fn parse_more_binops(&self, lhs: @expr, min_prec: uint) -> - @expr { + pub fn parse_more_binops(&self, lhs: @expr, min_prec: uint) -> @expr { if self.expr_is_complete(lhs) { return lhs; } let peeked = copy *self.token; if peeked == token::BINOP(token::OR) && @@ -1818,14 +1840,14 @@ pub impl Parser { let expr = self.parse_prefix_expr(); let rhs = self.parse_more_binops(expr, cur_prec); let bin = self.mk_expr(lhs.span.lo, rhs.span.hi, - expr_binary(cur_op, lhs, rhs)); + self.mk_binary(cur_op, lhs, rhs)); self.parse_more_binops(bin, min_prec) } else { lhs } } None => { - if as_prec > min_prec && self.eat_keyword("as") { + if as_prec > min_prec && self.eat_keyword(keywords::As) { let rhs = self.parse_ty(true); let _as = self.mk_expr(lhs.span.lo, rhs.span.hi, @@ -1842,7 +1864,7 @@ pub impl Parser { // parse an assignment expression.... // actually, this seems to be the main entry point for // parsing an arbitrary expression. - fn parse_assign_expr(&self) -> @expr { + pub fn parse_assign_expr(&self) -> @expr { let lo = self.span.lo; let lhs = self.parse_binops(); match *self.token { @@ -1868,7 +1890,7 @@ pub impl Parser { token::SHR => aop = shr } self.mk_expr(lo, rhs.span.hi, - expr_assign_op(aop, lhs, rhs)) + self.mk_assign_op(aop, lhs, rhs)) } token::LARROW => { self.obsolete(*self.span, ObsoleteBinaryMove); @@ -1893,13 +1915,13 @@ pub impl Parser { } // parse an 'if' expression ('if' token already eaten) - fn parse_if_expr(&self) -> @expr { + pub fn parse_if_expr(&self) -> @expr { let lo = self.last_span.lo; let cond = self.parse_expr(); let thn = self.parse_block(); let mut els: Option<@expr> = None; let mut hi = thn.span.hi; - if self.eat_keyword("else") { + if self.eat_keyword(keywords::Else) { let elexpr = self.parse_else_expr(); els = Some(elexpr); hi = elexpr.span.hi; @@ -1908,7 +1930,7 @@ pub impl Parser { } // `|args| { ... }` or `{ ...}` like in `do` expressions - fn parse_lambda_block_expr(&self) -> @expr { + pub fn parse_lambda_block_expr(&self) -> @expr { self.parse_lambda_expr_( || { match *self.token { @@ -1936,7 +1958,7 @@ pub impl Parser { } // `|args| expr` - fn parse_lambda_expr(&self) -> @expr { + pub fn parse_lambda_expr(&self) -> @expr { self.parse_lambda_expr_(|| self.parse_fn_block_decl(), || self.parse_expr()) } @@ -1944,11 +1966,10 @@ pub impl Parser { // parse something of the form |args| expr // this is used both in parsing a lambda expr // and in parsing a block expr as e.g. in for... - fn parse_lambda_expr_( - &self, - parse_decl: &fn() -> fn_decl, - parse_body: &fn() -> @expr - ) -> @expr { + pub fn parse_lambda_expr_(&self, + parse_decl: &fn() -> fn_decl, + parse_body: &fn() -> @expr) + -> @expr { let lo = self.last_span.lo; let decl = parse_decl(); let body = parse_body(); @@ -1965,8 +1986,8 @@ pub impl Parser { expr_fn_block(decl, fakeblock)); } - fn parse_else_expr(&self) -> @expr { - if self.eat_keyword("if") { + pub fn parse_else_expr(&self) -> @expr { + if self.eat_keyword(keywords::If) { return self.parse_if_expr(); } else { let blk = self.parse_block(); @@ -1977,9 +1998,11 @@ pub impl Parser { // parse a 'for' or 'do'. // the 'for' and 'do' expressions parse as calls, but look like // function calls followed by a closure expression. - fn parse_sugary_call_expr(&self, keyword: ~str, - sugar: CallSugar, - ctor: &fn(v: @expr) -> expr_) -> @expr { + pub fn parse_sugary_call_expr(&self, + keyword: ~str, + sugar: CallSugar, + ctor: &fn(v: @expr) -> expr_) + -> @expr { let lo = self.last_span; // Parse the callee `foo` in // for foo || { @@ -1992,36 +2015,37 @@ pub impl Parser { // them as the lambda arguments let e = self.parse_expr_res(RESTRICT_NO_BAR_OR_DOUBLEBAR_OP); match e.node { - expr_call(f, /*bad*/ copy args, NoSugar) => { + expr_call(f, ref args, NoSugar) => { let block = self.parse_lambda_block_expr(); let last_arg = self.mk_expr(block.span.lo, block.span.hi, ctor(block)); - let args = vec::append(args, ~[last_arg]); + let args = vec::append(copy *args, [last_arg]); self.mk_expr(lo.lo, block.span.hi, expr_call(f, args, sugar)) } - expr_method_call(f, i, /*bad*/ copy tps, - /*bad*/ copy args, NoSugar) => { + expr_method_call(_, f, i, ref tps, ref args, NoSugar) => { let block = self.parse_lambda_block_expr(); let last_arg = self.mk_expr(block.span.lo, block.span.hi, ctor(block)); - let args = vec::append(args, ~[last_arg]); + let args = vec::append(copy *args, [last_arg]); self.mk_expr(lo.lo, block.span.hi, - expr_method_call(f, i, tps, args, sugar)) + self.mk_method_call(f, i, copy *tps, args, sugar)) } - expr_field(f, i, /*bad*/ copy tps) => { + expr_field(f, i, ref tps) => { let block = self.parse_lambda_block_expr(); let last_arg = self.mk_expr(block.span.lo, block.span.hi, ctor(block)); self.mk_expr(lo.lo, block.span.hi, - expr_method_call(f, i, tps, ~[last_arg], sugar)) + self.mk_method_call(f, i, copy *tps, ~[last_arg], sugar)) } expr_path(*) | expr_call(*) | expr_method_call(*) | expr_paren(*) => { let block = self.parse_lambda_block_expr(); let last_arg = self.mk_expr(block.span.lo, block.span.hi, ctor(block)); - self.mk_expr(lo.lo, last_arg.span.hi, - expr_call(e, ~[last_arg], sugar)) + self.mk_expr( + lo.lo, + last_arg.span.hi, + self.mk_call(e, ~[last_arg], sugar)) } _ => { // There may be other types of expressions that can @@ -2035,7 +2059,7 @@ pub impl Parser { } } - fn parse_while_expr(&self) -> @expr { + pub fn parse_while_expr(&self) -> @expr { let lo = self.last_span.lo; let cond = self.parse_expr(); let body = self.parse_block(); @@ -2043,7 +2067,7 @@ pub impl Parser { return self.mk_expr(lo, hi, expr_while(cond, body)); } - fn parse_loop_expr(&self, opt_ident: Option) -> @expr { + pub fn parse_loop_expr(&self, opt_ident: Option) -> @expr { // loop headers look like 'loop {' or 'loop unsafe {' let is_loop_header = *self.token == token::LBRACE @@ -2080,7 +2104,7 @@ pub impl Parser { fn looking_at_record_literal(&self) -> bool { let lookahead = self.look_ahead(1); *self.token == token::LBRACE && - (self.token_is_keyword("mut", &lookahead) || + (token::is_keyword(keywords::Mut, &lookahead) || (is_plain_ident(&lookahead) && self.look_ahead(2) == token::COLON)) } @@ -2093,7 +2117,7 @@ pub impl Parser { while *self.token != token::RBRACE { let pats = self.parse_pats(); let mut guard = None; - if self.eat_keyword("if") { guard = Some(self.parse_expr()); } + if self.eat_keyword(keywords::If) { guard = Some(self.parse_expr()); } self.expect(&token::FAT_ARROW); let expr = self.parse_expr_res(RESTRICT_STMT_EXPR); @@ -2126,7 +2150,7 @@ pub impl Parser { } // parse an expression - fn parse_expr(&self) -> @expr { + pub fn parse_expr(&self) -> @expr { return self.parse_expr_res(UNRESTRICTED); } @@ -2162,7 +2186,7 @@ pub impl Parser { fn parse_pats(&self) -> ~[@pat] { let mut pats = ~[]; loop { - pats.push(self.parse_pat(true)); + pats.push(self.parse_pat()); if *self.token == token::BINOP(token::OR) { self.bump(); } else { return pats; } }; @@ -2170,7 +2194,6 @@ pub impl Parser { fn parse_pat_vec_elements( &self, - refutable: bool ) -> (~[@pat], Option<@pat>, ~[@pat]) { let mut before = ~[]; let mut slice = None; @@ -2191,7 +2214,7 @@ pub impl Parser { } } - let subpat = self.parse_pat(refutable); + let subpat = self.parse_pat(); if is_slice { match subpat { @ast::pat { node: pat_wild, _ } => (), @@ -2214,7 +2237,7 @@ pub impl Parser { } // parse the fields of a struct-like pattern - fn parse_pat_fields(&self, refutable: bool) -> (~[ast::field_pat], bool) { + fn parse_pat_fields(&self) -> (~[ast::field_pat], bool) { let mut fields = ~[]; let mut etc = false; let mut first = true; @@ -2244,7 +2267,7 @@ pub impl Parser { let subpat; if *self.token == token::COLON { self.bump(); - subpat = self.parse_pat(refutable); + subpat = self.parse_pat(); } else { subpat = @ast::pat { id: self.get_id(), @@ -2257,10 +2280,8 @@ pub impl Parser { return (fields, etc); } - // parse a pattern. The 'refutable' argument - // appears to control whether the binding_mode - // 'bind_infer' or 'bind_by_copy' is used. - fn parse_pat(&self, refutable: bool) -> @pat { + // parse a pattern. + pub fn parse_pat(&self) -> @pat { maybe_whole!(self, nt_pat); let lo = self.span.lo; @@ -2272,7 +2293,7 @@ pub impl Parser { // parse @pat token::AT => { self.bump(); - let sub = self.parse_pat(refutable); + let sub = self.parse_pat(); hi = sub.span.hi; // HACK: parse @"..." as a literal of a vstore @str pat = match sub.node { @@ -2283,7 +2304,6 @@ pub impl Parser { }) => { let vst = @expr { id: self.get_id(), - callee_id: self.get_id(), node: expr_vstore(e, expr_vstore_box), span: mk_sp(lo, hi), }; @@ -2295,7 +2315,7 @@ pub impl Parser { token::TILDE => { // parse ~pat self.bump(); - let sub = self.parse_pat(refutable); + let sub = self.parse_pat(); hi = sub.span.hi; // HACK: parse ~"..." as a literal of a vstore ~str pat = match sub.node { @@ -2306,7 +2326,6 @@ pub impl Parser { }) => { let vst = @expr { id: self.get_id(), - callee_id: self.get_id(), node: expr_vstore(e, expr_vstore_uniq), span: mk_sp(lo, hi), }; @@ -2319,7 +2338,7 @@ pub impl Parser { // parse &pat let lo = self.span.lo; self.bump(); - let sub = self.parse_pat(refutable); + let sub = self.parse_pat(); hi = sub.span.hi; // HACK: parse &"..." as a literal of a borrowed str pat = match sub.node { @@ -2329,7 +2348,6 @@ pub impl Parser { }) => { let vst = @expr { id: self.get_id(), - callee_id: self.get_id(), node: expr_vstore(e, expr_vstore_slice), span: mk_sp(lo, hi) }; @@ -2340,7 +2358,7 @@ pub impl Parser { } token::LBRACE => { self.bump(); - let (_, _) = self.parse_pat_fields(refutable); + let (_, _) = self.parse_pat_fields(); hi = self.span.hi; self.bump(); self.obsolete(*self.span, ObsoleteRecordPattern); @@ -2358,11 +2376,11 @@ pub impl Parser { let expr = self.mk_expr(lo, hi, expr_lit(lit)); pat = pat_lit(expr); } else { - let mut fields = ~[self.parse_pat(refutable)]; + let mut fields = ~[self.parse_pat()]; if self.look_ahead(1) != token::RPAREN { while *self.token == token::COMMA { self.bump(); - fields.push(self.parse_pat(refutable)); + fields.push(self.parse_pat()); } } if fields.len() == 1 { self.expect(&token::COMMA); } @@ -2375,15 +2393,15 @@ pub impl Parser { // parse [pat,pat,...] as vector pattern self.bump(); let (before, slice, after) = - self.parse_pat_vec_elements(refutable); + self.parse_pat_vec_elements(); hi = self.span.hi; self.expect(&token::RBRACKET); pat = ast::pat_vec(before, slice, after); } ref tok => { if !is_ident_or_path(tok) - || self.is_keyword("true") - || self.is_keyword("false") + || self.is_keyword(keywords::True) + || self.is_keyword(keywords::False) { // Parse an expression pattern or exp .. exp. // @@ -2402,18 +2420,16 @@ pub impl Parser { } else { pat = pat_lit(val); } - } else if self.eat_keyword("ref") { + } else if self.eat_keyword(keywords::Ref) { // parse ref pat let mutbl = self.parse_mutability(); - pat = self.parse_pat_ident(refutable, bind_by_ref(mutbl)); - } else if self.eat_keyword("copy") { + pat = self.parse_pat_ident(bind_by_ref(mutbl)); + } else if self.eat_keyword(keywords::Copy) { // parse copy pat - pat = self.parse_pat_ident(refutable, bind_by_copy); + self.warn("copy keyword in patterns no longer has any effect, \ + remove it"); + pat = self.parse_pat_ident(bind_infer); } else { - // XXX---refutable match bindings should work same as let - let binding_mode = - if refutable {bind_infer} else {bind_by_copy}; - let can_be_enum_or_struct; match self.look_ahead(1) { token::LPAREN | token::LBRACKET | token::LT | @@ -2434,12 +2450,12 @@ pub impl Parser { let sub; if self.eat(&token::AT) { // parse foo @ pat - sub = Some(self.parse_pat(refutable)); + sub = Some(self.parse_pat()); } else { // or just foo sub = None; } - pat = pat_ident(binding_mode, name, sub); + pat = pat_ident(bind_infer, name, sub); } else { // parse an enum pat let enum_path = self.parse_path_with_tps(true); @@ -2447,7 +2463,7 @@ pub impl Parser { token::LBRACE => { self.bump(); let (fields, etc) = - self.parse_pat_fields(refutable); + self.parse_pat_fields(); self.bump(); pat = pat_struct(enum_path, fields, etc); } @@ -2468,7 +2484,7 @@ pub impl Parser { seq_sep_trailing_disallowed( token::COMMA ), - |p| p.parse_pat(refutable) + |p| p.parse_pat() ); pat = pat_enum(enum_path, Some(args)); } @@ -2478,7 +2494,7 @@ pub impl Parser { // it could still be either an enum // or an identifier pattern, resolve // will sort it out: - pat = pat_ident(binding_mode, + pat = pat_ident(bind_infer, enum_path, None); } else { @@ -2496,10 +2512,10 @@ pub impl Parser { @ast::pat { id: self.get_id(), node: pat, span: mk_sp(lo, hi) } } + // parse ident or ident @ pat // used by the copy foo and ref foo patterns to give a good // error message when parsing mistakes like ref foo(a,b) fn parse_pat_ident(&self, - refutable: bool, binding_mode: ast::binding_mode) -> ast::pat_ { if !is_plain_ident(&*self.token) { @@ -2509,7 +2525,7 @@ pub impl Parser { // why a path here, and not just an identifier? let name = self.parse_path_without_tps(); let sub = if self.eat(&token::AT) { - Some(self.parse_pat(refutable)) + Some(self.parse_pat()) } else { None }; @@ -2532,7 +2548,7 @@ pub impl Parser { // parse a local variable declaration fn parse_local(&self, is_mutbl: bool) -> @local { let lo = self.span.lo; - let pat = self.parse_pat(false); + let pat = self.parse_pat(); let mut ty = @Ty { id: self.get_id(), node: ty_infer, @@ -2555,13 +2571,14 @@ pub impl Parser { // parse a "let" stmt fn parse_let(&self) -> @decl { - let is_mutbl = self.eat_keyword("mut"); + let is_mutbl = self.eat_keyword(keywords::Mut); let lo = self.span.lo; - let mut locals = ~[self.parse_local(is_mutbl)]; + let mut local = self.parse_local(is_mutbl); while self.eat(&token::COMMA) { - locals.push(self.parse_local(is_mutbl)); + let _ = self.parse_local(is_mutbl); + self.obsolete(*self.span, ObsoleteMultipleLocalDecl); } - return @spanned(lo, self.last_span.hi, decl_local(locals)); + return @spanned(lo, self.last_span.hi, decl_local(local)); } // parse a structure field @@ -2569,12 +2586,8 @@ pub impl Parser { pr: visibility, attrs: ~[attribute]) -> @struct_field { let lo = self.span.lo; - if self.eat_keyword("mut") { - // Do nothing, for backwards compatibility. - // XXX: Remove after snapshot. - } if !is_plain_ident(&*self.token) { - self.fatal(~"expected ident"); + self.fatal("expected ident"); } let name = self.parse_ident(); self.expect(&token::COLON); @@ -2587,25 +2600,27 @@ pub impl Parser { }) } - // parse a statement. may include decl - fn parse_stmt(&self, first_item_attrs: ~[attribute]) -> @stmt { + // parse a statement. may include decl. + // precondition: any attributes are parsed already + pub fn parse_stmt(&self, item_attrs: ~[attribute]) -> @stmt { maybe_whole!(self, nt_stmt); fn check_expected_item(p: &Parser, current_attrs: &[attribute]) { // If we have attributes then we should have an item if !current_attrs.is_empty() { - p.fatal(~"expected item after attrs"); + p.span_err(*p.last_span, + "expected item after attributes"); } } let lo = self.span.lo; - if self.is_keyword("let") { - check_expected_item(self, first_item_attrs); - self.expect_keyword("let"); + if self.is_keyword(keywords::Let) { + check_expected_item(self, item_attrs); + self.expect_keyword(keywords::Let); let decl = self.parse_let(); return @spanned(lo, decl.span.hi, stmt_decl(decl, self.get_id())); } else if is_ident(&*self.token) - && !self.is_any_keyword(© *self.token) + && !token::is_any_keyword(self.token) && self.look_ahead(1) == token::NOT { // parse a macro invocation. Looks like there's serious // overlap here; if this clause doesn't catch it (and it @@ -2613,7 +2628,14 @@ pub impl Parser { // to the macro clause of parse_item_or_view_item. This // could use some cleanup, it appears to me. - check_expected_item(self, first_item_attrs); + // whoops! I now have a guess: I'm guessing the "parens-only" + // rule here is deliberate, to allow macro users to use parens + // for things that should be parsed as stmt_mac, and braces + // for things that should expand into items. Tricky, and + // somewhat awkward... and probably undocumented. Of course, + // I could just be wrong. + + check_expected_item(self, item_attrs); // Potential trouble: if we allow macros with paths instead of // idents, we'd need to look ahead past the whole path here... @@ -2649,9 +2671,6 @@ pub impl Parser { } } else { - let item_attrs = vec::append(first_item_attrs, - self.parse_outer_attributes()); - match self.parse_item_or_view_item(/*bad*/ copy item_attrs, false) { iovi_item(i) => { @@ -2664,7 +2683,7 @@ pub impl Parser { "view items must be declared at the top of the block"); } iovi_foreign_item(_) => { - self.fatal(~"foreign items are not allowed here"); + self.fatal("foreign items are not allowed here"); } iovi_none() => { /* fallthrough */ } } @@ -2684,11 +2703,11 @@ pub impl Parser { } // parse a block. No inner attrs are allowed. - fn parse_block(&self) -> blk { + pub fn parse_block(&self) -> blk { maybe_whole!(self, nt_block); let lo = self.span.lo; - if self.eat_keyword("unsafe") { + if self.eat_keyword(keywords::Unsafe) { self.obsolete(copy *self.span, ObsoleteUnsafeBlock); } self.expect(&token::LBRACE); @@ -2703,7 +2722,7 @@ pub impl Parser { maybe_whole!(pair_empty self, nt_block); let lo = self.span.lo; - if self.eat_keyword("unsafe") { + if self.eat_keyword(keywords::Unsafe) { self.obsolete(copy *self.span, ObsoleteUnsafeBlock); } self.expect(&token::LBRACE); @@ -2726,6 +2745,7 @@ pub impl Parser { let mut stmts = ~[]; let mut expr = None; + // wouldn't it be more uniform to parse view items only, here? let ParsedItemsAndViewItems { attrs_remaining: attrs_remaining, view_items: view_items, @@ -2740,24 +2760,30 @@ pub impl Parser { stmt_decl(decl, self.get_id()))); } - let mut initial_attrs = attrs_remaining; - - if *self.token == token::RBRACE && !vec::is_empty(initial_attrs) { - self.fatal(~"expected item"); - } + let mut attributes_box = attrs_remaining; - while *self.token != token::RBRACE { + while (*self.token != token::RBRACE) { + // parsing items even when they're not allowed lets us give + // better error messages and recover more gracefully. + attributes_box.push_all(self.parse_outer_attributes()); match *self.token { token::SEMI => { + if !vec::is_empty(attributes_box) { + self.span_err(*self.last_span, "expected item after attributes"); + attributes_box = ~[]; + } self.bump(); // empty } + token::RBRACE => { + // fall through and out. + } _ => { - let stmt = self.parse_stmt(initial_attrs); - initial_attrs = ~[]; + let stmt = self.parse_stmt(attributes_box); + attributes_box = ~[]; match stmt.node { stmt_expr(e, stmt_id) => { - // Expression without semicolon - match *self.token { + // expression without semicolon + match copy *self.token { token::SEMI => { self.bump(); stmts.push(@codemap::spanned { @@ -2767,12 +2793,12 @@ pub impl Parser { token::RBRACE => { expr = Some(e); } - copy t => { + t => { if classify::stmt_ends_with_semi(stmt) { self.fatal( fmt!( "expected `;` or `}` after \ - expression but found `%s`", + expression but found `%s`", self.token_to_str(&t) ) ); @@ -2781,9 +2807,8 @@ pub impl Parser { } } } - stmt_mac(ref m, _) => { - // Statement macro; might be an expr + // statement macro; might be an expr match *self.token { token::SEMI => { self.bump(); @@ -2802,8 +2827,7 @@ pub impl Parser { _ => { stmts.push(stmt); } } } - - _ => { // All other kinds of statements: + _ => { // all other kinds of statements: stmts.push(stmt); if classify::stmt_ends_with_semi(stmt) { @@ -2814,6 +2838,11 @@ pub impl Parser { } } } + + if !vec::is_empty(attributes_box) { + self.span_err(*self.last_span, "expected item after attributes"); + } + let hi = self.span.hi; self.bump(); let bloc = ast::blk_ { @@ -2837,10 +2866,10 @@ pub impl Parser { } fn parse_optional_purity(&self) -> ast::purity { - if self.eat_keyword("pure") { + if self.eat_keyword(keywords::Pure) { self.obsolete(*self.last_span, ObsoletePurity); ast::impure_fn - } else if self.eat_keyword("unsafe") { + } else if self.eat_keyword(keywords::Unsafe) { ast::unsafe_fn } else { ast::impure_fn @@ -2848,7 +2877,7 @@ pub impl Parser { } fn parse_optional_onceness(&self) -> ast::Onceness { - if self.eat_keyword("once") { ast::Once } else { ast::Many } + if self.eat_keyword(keywords::Once) { ast::Once } else { ast::Many } } // matches optbounds = ( ( : ( boundseq )? )? ) @@ -2874,7 +2903,7 @@ pub impl Parser { token::MOD_SEP | token::IDENT(*) => { let obsolete_bound = match *self.token { token::MOD_SEP => false, - token::IDENT(copy sid, _) => { + token::IDENT(sid, _) => { match *self.id_to_str(sid) { ~"send" | ~"copy" | @@ -2924,7 +2953,7 @@ pub impl Parser { // matches generics = ( ) | ( < > ) | ( < typaramseq ( , )? > ) | ( < lifetimes ( , )? > ) // | ( < lifetimes , typaramseq ( , )? > ) // where typaramseq = ( typaram ) | ( typaram , typaramseq ) - fn parse_generics(&self) -> ast::Generics { + pub fn parse_generics(&self) -> ast::Generics { if self.eat(&token::LT) { let lifetimes = self.parse_lifetimes(); let ty_params = self.parse_seq_to_gt( @@ -2958,9 +2987,7 @@ pub impl Parser { } // parse the argument list and result type of a function declaration - fn parse_fn_decl(&self) - -> fn_decl - { + pub fn parse_fn_decl(&self) -> fn_decl { let args_or_capture_items: ~[arg_or_capture_item] = self.parse_unspanned_seq( &token::LPAREN, @@ -3011,10 +3038,10 @@ pub impl Parser { p: &Parser ) -> ast::explicit_self_ { // We need to make sure it isn't a mode or a type - if p.token_is_keyword("self", &p.look_ahead(1)) || - ((p.token_is_keyword("const", &p.look_ahead(1)) || - p.token_is_keyword("mut", &p.look_ahead(1))) && - p.token_is_keyword("self", &p.look_ahead(2))) { + if token::is_keyword(keywords::Self, &p.look_ahead(1)) || + ((token::is_keyword(keywords::Const, &p.look_ahead(1)) || + token::is_keyword(keywords::Mut, &p.look_ahead(1))) && + token::is_keyword(keywords::Self, &p.look_ahead(2))) { p.bump(); let mutability = p.parse_mutability(); @@ -3035,25 +3062,25 @@ pub impl Parser { // // We already know that the current token is `&`. - if (this.token_is_keyword("self", &this.look_ahead(1))) { + if (token::is_keyword(keywords::Self, &this.look_ahead(1))) { this.bump(); this.expect_self_ident(); sty_region(None, m_imm) } else if (this.token_is_mutability(&this.look_ahead(1)) && - this.token_is_keyword("self", &this.look_ahead(2))) { + token::is_keyword(keywords::Self, &this.look_ahead(2))) { this.bump(); let mutability = this.parse_mutability(); this.expect_self_ident(); sty_region(None, mutability) } else if (this.token_is_lifetime(&this.look_ahead(1)) && - this.token_is_keyword("self", &this.look_ahead(2))) { + token::is_keyword(keywords::Self, &this.look_ahead(2))) { this.bump(); let lifetime = @this.parse_lifetime(); this.expect_self_ident(); sty_region(Some(lifetime), m_imm) } else if (this.token_is_lifetime(&this.look_ahead(1)) && this.token_is_mutability(&this.look_ahead(2)) && - this.token_is_keyword("self", &this.look_ahead(3))) { + token::is_keyword(keywords::Self, &this.look_ahead(3))) { this.bump(); let lifetime = @this.parse_lifetime(); let mutability = this.parse_mutability(); @@ -3262,7 +3289,7 @@ pub impl Parser { let mut ty = self.parse_ty(false); // Parse traits, if necessary. - let opt_trait = if could_be_trait && self.eat_keyword("for") { + let opt_trait = if could_be_trait && self.eat_keyword(keywords::For) { // New-style trait. Reinterpret the type as a trait. let opt_trait_ref = match ty.node { ty_path(path, node_id) => { @@ -3286,10 +3313,9 @@ pub impl Parser { None }; - // Do not allow visibility to be specified in `impl...for...`. It is - // meaningless. - if opt_trait.is_some() && visibility != ast::inherited { - self.obsolete(*self.span, ObsoleteTraitImplVisibility); + // Do not allow visibility to be specified. + if visibility != ast::inherited { + self.obsolete(*self.span, ObsoleteImplVisibility); } let mut meths = ~[]; @@ -3344,7 +3370,7 @@ pub impl Parser { } if fields.len() == 0 { self.fatal(fmt!("Unit-like struct should be written as `struct %s;`", - *self.interner.get(class_name))); + *get_ident_interner().get(class_name.name))); } self.bump(); } else if *self.token == token::LPAREN { @@ -3398,9 +3424,10 @@ pub impl Parser { } // parse a structure field declaration - fn parse_single_struct_field(&self, - vis: visibility, - attrs: ~[attribute]) -> @struct_field { + pub fn parse_single_struct_field(&self, + vis: visibility, + attrs: ~[attribute]) + -> @struct_field { if self.eat_obsolete_ident("let") { self.obsolete(*self.last_span, ObsoleteLet); } @@ -3437,11 +3464,11 @@ pub impl Parser { return ~[]; } - if self.eat_keyword("priv") { + if self.eat_keyword(keywords::Priv) { return ~[self.parse_single_struct_field(private, attrs)] } - if self.eat_keyword("pub") { + if self.eat_keyword(keywords::Pub) { return ~[self.parse_single_struct_field(public, attrs)]; } @@ -3454,13 +3481,13 @@ pub impl Parser { // parse visiility: PUB, PRIV, or nothing fn parse_visibility(&self) -> visibility { - if self.eat_keyword("pub") { public } - else if self.eat_keyword("priv") { private } + if self.eat_keyword(keywords::Pub) { public } + else if self.eat_keyword(keywords::Priv) { private } else { inherited } } fn parse_staticness(&self) -> bool { - if self.eat_keyword("static") { + if self.eat_keyword(keywords::Static) { self.obsolete(*self.last_span, ObsoleteStaticMethod); true } else { @@ -3518,7 +3545,7 @@ pub impl Parser { if first && attrs_remaining_len > 0u { // We parsed attributes for the first item but didn't find it - self.fatal(~"expected item"); + self.span_err(*self.last_span, "expected item after attributes"); } ast::_mod { view_items: view_items, items: items } @@ -3538,8 +3565,7 @@ pub impl Parser { fn parse_item_mod(&self, outer_attrs: ~[ast::attribute]) -> item_info { let id_span = *self.span; let id = self.parse_ident(); - let merge = ::attr::first_attr_value_str_by_name(outer_attrs, "merge"); - let info_ = if *self.token == token::SEMI { + if *self.token == token::SEMI { self.bump(); // This mod is in an external file. Let's go get it! let (m, attrs) = self.eval_src_mod(id, outer_attrs, id_span); @@ -3552,45 +3578,13 @@ pub impl Parser { self.expect(&token::RBRACE); self.pop_mod_path(); (id, item_mod(m), Some(inner)) - }; - - // XXX: Transitionary hack to do the template work inside core - // (int-template, iter-trait). If there's a 'merge' attribute - // on the mod, then we'll go and suck in another file and merge - // its contents - match merge { - Some(path) => { - let prefix = Path( - self.sess.cm.span_to_filename(*self.span)); - let prefix = prefix.dir_path(); - let path = Path(copy *path); - let (new_mod_item, new_attrs) = self.eval_src_mod_from_path( - prefix, path, ~[], id_span); - - let (main_id, main_mod_item, main_attrs) = info_; - let main_attrs = main_attrs.get(); - - let (main_mod, new_mod) = - match (main_mod_item, new_mod_item) { - (item_mod(m), item_mod(n)) => (m, n), - _ => self.bug(~"parsed mod item should be mod") - }; - let merged_mod = ast::_mod { - view_items: main_mod.view_items + new_mod.view_items, - items: main_mod.items + new_mod.items - }; - - let merged_attrs = main_attrs + new_attrs; - (main_id, item_mod(merged_mod), Some(merged_attrs)) - } - None => info_ } } fn push_mod_path(&self, id: ident, attrs: ~[ast::attribute]) { - let default_path = self.sess.interner.get(id); + let default_path = token::interner_get(id.name); let file_path = match ::attr::first_attr_value_str_by_name( - attrs, ~"path") { + attrs, "path") { Some(d) => copy *d, None => copy *default_path @@ -3611,9 +3605,9 @@ pub impl Parser { let prefix = prefix.dir_path(); let mod_path_stack = &*self.mod_path_stack; let mod_path = Path(".").push_many(*mod_path_stack); - let default_path = *self.sess.interner.get(id) + ~".rs"; + let default_path = *token::interner_get(id.name) + ".rs"; let file_path = match ::attr::first_attr_value_str_by_name( - outer_attrs, ~"path") { + outer_attrs, "path") { Some(d) => { let path = Path(copy *d); if !path.is_absolute { @@ -3650,7 +3644,7 @@ pub impl Parser { return (ast::item_mod(m0), mod_attrs); fn cdir_path_opt(default: ~str, attrs: ~[ast::attribute]) -> ~str { - match ::attr::first_attr_value_str_by_name(attrs, ~"path") { + match ::attr::first_attr_value_str_by_name(attrs, "path") { Some(d) => copy *d, None => default } @@ -3680,10 +3674,10 @@ pub impl Parser { let lo = self.span.lo; // XXX: Obsolete; remove after snap. - if self.eat_keyword("const") { + if self.eat_keyword(keywords::Const) { self.obsolete(*self.last_span, ObsoleteConstItem); } else { - self.expect_keyword("static"); + self.expect_keyword(keywords::Static); } let ident = self.parse_ident(); @@ -3701,14 +3695,14 @@ pub impl Parser { // parse safe/unsafe and fn fn parse_fn_purity(&self) -> purity { - if self.eat_keyword("fn") { impure_fn } - else if self.eat_keyword("pure") { + if self.eat_keyword(keywords::Fn) { impure_fn } + else if self.eat_keyword(keywords::Pure) { self.obsolete(*self.last_span, ObsoletePurity); - self.expect_keyword("fn"); + self.expect_keyword(keywords::Fn); // NB: We parse this as impure for bootstrapping purposes. impure_fn - } else if self.eat_keyword("unsafe") { - self.expect_keyword("fn"); + } else if self.eat_keyword(keywords::Unsafe) { + self.expect_keyword(keywords::Fn); unsafe_fn } else { self.unexpected(); } @@ -3723,11 +3717,15 @@ pub impl Parser { first_item_attrs: ~[attribute]) -> foreign_mod { let ParsedItemsAndViewItems { - attrs_remaining: _, + attrs_remaining: attrs_remaining, view_items: view_items, items: _, foreign_items: foreign_items } = self.parse_foreign_items(first_item_attrs, true); + if (! attrs_remaining.is_empty()) { + self.span_err(*self.last_span, + "expected item after attributes"); + } assert!(*self.token == token::RBRACE); ast::foreign_mod { sort: sort, @@ -3746,9 +3744,9 @@ pub impl Parser { items_allowed: bool) -> item_or_view_item { let mut must_be_named_mod = false; - if self.is_keyword("mod") { + if self.is_keyword(keywords::Mod) { must_be_named_mod = true; - self.expect_keyword("mod"); + self.expect_keyword(keywords::Mod); } else if *self.token != token::LBRACE { self.span_fatal( copy *self.span, @@ -3850,15 +3848,18 @@ pub impl Parser { // parse the part of an "enum" decl following the '{' fn parse_enum_def(&self, _generics: &ast::Generics) -> enum_def { let mut variants = ~[]; - let mut all_nullary = true, have_disr = false; + let mut all_nullary = true; + let mut have_disr = false; while *self.token != token::RBRACE { let variant_attrs = self.parse_outer_attributes(); let vlo = self.span.lo; let vis = self.parse_visibility(); - let ident, kind; - let mut args = ~[], disr_expr = None; + let ident; + let kind; + let mut args = ~[]; + let mut disr_expr = None; ident = self.parse_ident(); if self.eat(&token::LBRACE) { // Parse a struct variant. @@ -3901,7 +3902,7 @@ pub impl Parser { } self.expect(&token::RBRACE); if (have_disr && !all_nullary) { - self.fatal(~"discriminator values can only be used with a c-like \ + self.fatal("discriminator values can only be used with a c-like \ enum"); } @@ -3979,7 +3980,7 @@ pub impl Parser { match *self.token { token::LIT_STR(s) => { self.bump(); - let the_string = self.id_to_str(s); + let the_string = ident_to_str(&s); let mut words = ~[]; for str::each_word(*the_string) |s| { words.push(s) } let mut abis = AbiSet::empty(); @@ -4033,7 +4034,7 @@ pub impl Parser { let visibility = self.parse_visibility(); // must be a view item: - if self.eat_keyword("use") { + if self.eat_keyword(keywords::Use) { // USE ITEM (iovi_view_item) let view_item = self.parse_use(); self.expect(&token::SEMI); @@ -4045,10 +4046,10 @@ pub impl Parser { }); } // either a view item or an item: - if self.eat_keyword("extern") { + if self.eat_keyword(keywords::Extern) { let opt_abis = self.parse_opt_abis(); - if self.eat_keyword("fn") { + if self.eat_keyword(keywords::Fn) { // EXTERN FUNCTION ITEM let abis = opt_abis.get_or_default(AbiSet::C()); let (ident, item_, extra_attrs) = @@ -4064,11 +4065,11 @@ pub impl Parser { } } // the rest are all guaranteed to be items: - if (self.is_keyword("const") || - (self.is_keyword("static") && - !self.token_is_keyword("fn", &self.look_ahead(1)))) { + if (self.is_keyword(keywords::Const) || + (self.is_keyword(keywords::Static) && + !token::is_keyword(keywords::Fn, &self.look_ahead(1)))) { // CONST / STATIC ITEM - if self.is_keyword("const") { + if self.is_keyword(keywords::Const) { self.obsolete(*self.span, ObsoleteConstItem); } self.bump(); @@ -4077,7 +4078,7 @@ pub impl Parser { visibility, maybe_append(attrs, extra_attrs))); } - if self.is_keyword("fn") && + if self.is_keyword(keywords::Fn) && !self.fn_expr_lookahead(self.look_ahead(1u)) { // FUNCTION ITEM self.bump(); @@ -4087,28 +4088,28 @@ pub impl Parser { visibility, maybe_append(attrs, extra_attrs))); } - if self.eat_keyword("pure") { + if self.eat_keyword(keywords::Pure) { // PURE FUNCTION ITEM (obsolete) self.obsolete(*self.last_span, ObsoletePurity); - self.expect_keyword("fn"); + self.expect_keyword(keywords::Fn); let (ident, item_, extra_attrs) = self.parse_item_fn(impure_fn, AbiSet::Rust()); return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_, visibility, maybe_append(attrs, extra_attrs))); } - if self.is_keyword("unsafe") + if self.is_keyword(keywords::Unsafe) && self.look_ahead(1u) != token::LBRACE { // UNSAFE FUNCTION ITEM self.bump(); - self.expect_keyword("fn"); + self.expect_keyword(keywords::Fn); let (ident, item_, extra_attrs) = self.parse_item_fn(unsafe_fn, AbiSet::Rust()); return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_, visibility, maybe_append(attrs, extra_attrs))); } - if self.eat_keyword("mod") { + if self.eat_keyword(keywords::Mod) { // MODULE ITEM let (ident, item_, extra_attrs) = self.parse_item_mod(/*bad*/ copy attrs); @@ -4116,28 +4117,28 @@ pub impl Parser { visibility, maybe_append(attrs, extra_attrs))); } - if self.eat_keyword("type") { + if self.eat_keyword(keywords::Type) { // TYPE ITEM let (ident, item_, extra_attrs) = self.parse_item_type(); return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_, visibility, maybe_append(attrs, extra_attrs))); } - if self.eat_keyword("enum") { + if self.eat_keyword(keywords::Enum) { // ENUM ITEM let (ident, item_, extra_attrs) = self.parse_item_enum(); return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_, visibility, maybe_append(attrs, extra_attrs))); } - if self.eat_keyword("trait") { + if self.eat_keyword(keywords::Trait) { // TRAIT ITEM let (ident, item_, extra_attrs) = self.parse_item_trait(); return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_, visibility, maybe_append(attrs, extra_attrs))); } - if self.eat_keyword("impl") { + if self.eat_keyword(keywords::Impl) { // IMPL ITEM let (ident, item_, extra_attrs) = self.parse_item_impl(visibility); @@ -4145,7 +4146,7 @@ pub impl Parser { visibility, maybe_append(attrs, extra_attrs))); } - if self.eat_keyword("struct") { + if self.eat_keyword(keywords::Struct) { // STRUCT ITEM let (ident, item_, extra_attrs) = self.parse_item_struct(); return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_, @@ -4166,16 +4167,16 @@ pub impl Parser { let visibility = self.parse_visibility(); - if (self.is_keyword("const") || self.is_keyword("static")) { + if (self.is_keyword(keywords::Const) || self.is_keyword(keywords::Static)) { // FOREIGN CONST ITEM let item = self.parse_item_foreign_const(visibility, attrs); return iovi_foreign_item(item); } - if (self.is_keyword("fn") || self.is_keyword("pure") || - self.is_keyword("unsafe")) { + if (self.is_keyword(keywords::Fn) || self.is_keyword(keywords::Pure) || + self.is_keyword(keywords::Unsafe)) { // FOREIGN FUNCTION ITEM - let item = self.parse_item_foreign_fn(attrs); - return iovi_foreign_item(item); + let item = self.parse_item_foreign_fn(attrs); + return iovi_foreign_item(item); } self.parse_macro_use_or_failure(attrs,macros_allowed,lo,visibility) } @@ -4188,14 +4189,14 @@ pub impl Parser { lo : BytePos, visibility : visibility ) -> item_or_view_item { - if macros_allowed && !self.is_any_keyword(© *self.token) + if macros_allowed && !token::is_any_keyword(self.token) && self.look_ahead(1) == token::NOT && (is_plain_ident(&self.look_ahead(2)) || self.look_ahead(2) == token::LPAREN || self.look_ahead(2) == token::LBRACE) { // MACRO INVOCATION ITEM if attrs.len() > 0 { - self.fatal(~"attrs on macros are not yet supported"); + self.fatal("attrs on macros are not yet supported"); } // item macro. @@ -4221,7 +4222,7 @@ pub impl Parser { |p| p.parse_token_tree() ) } - _ => self.fatal(~"expected open delimiter") + _ => self.fatal("expected open delimiter") }; // single-variant-enum... : let m = ast::mac_invoc_tt(pth, tts); @@ -4236,21 +4237,21 @@ pub impl Parser { // FAILURE TO PARSE ITEM if visibility != inherited { let mut s = ~"unmatched visibility `"; - s += if visibility == public { ~"pub" } else { ~"priv" }; - s += ~"`"; + s += if visibility == public { "pub" } else { "priv" }; + s += "`"; self.span_fatal(*self.last_span, s); } return iovi_none; } - fn parse_item(&self, attrs: ~[attribute]) -> Option<@ast::item> { + pub fn parse_item(&self, attrs: ~[attribute]) -> Option<@ast::item> { match self.parse_item_or_view_item(attrs, true) { iovi_none => None, iovi_view_item(_) => - self.fatal(~"view items are not allowed here"), + self.fatal("view items are not allowed here"), iovi_foreign_item(_) => - self.fatal(~"foreign items are not allowed here"), + self.fatal("foreign items are not allowed here"), iovi_item(item) => Some(item) } @@ -4362,17 +4363,18 @@ pub impl Parser { } fn is_view_item(&self) -> bool { - let tok, next_tok; - if !self.is_keyword("pub") && !self.is_keyword("priv") { + let tok; + let next_tok; + if !self.is_keyword(keywords::Pub) && !self.is_keyword(keywords::Priv) { tok = copy *self.token; next_tok = self.look_ahead(1); } else { tok = self.look_ahead(1); next_tok = self.look_ahead(2); }; - self.token_is_keyword("use", &tok) - || (self.token_is_keyword("extern", &tok) && - self.token_is_keyword("mod", &next_tok)) + token::is_keyword(keywords::Use, &tok) + || (token::is_keyword(keywords::Extern, &tok) && + token::is_keyword(keywords::Mod, &next_tok)) } // parse a view item. @@ -4382,15 +4384,15 @@ pub impl Parser { vis: visibility ) -> @view_item { let lo = self.span.lo; - let node = if self.eat_keyword("use") { + let node = if self.eat_keyword(keywords::Use) { self.parse_use() - } else if self.eat_keyword("extern") { - self.expect_keyword("mod"); + } else if self.eat_keyword(keywords::Extern) { + self.expect_keyword(keywords::Mod); let ident = self.parse_ident(); let metadata = self.parse_optional_meta(); view_item_extern_mod(ident, metadata, self.get_id()) } else { - self.bug(~"expected view item"); + self.bug("expected view item"); }; self.expect(&token::SEMI); @ast::view_item { node: node, @@ -4490,7 +4492,12 @@ pub impl Parser { let mut foreign_items = ~[]; loop { match self.parse_foreign_item(/*bad*/ copy attrs, macros_allowed) { - iovi_none => break, + iovi_none => { + if *self.token == token::RBRACE { + break + } + self.unexpected(); + }, iovi_view_item(view_item) => { // I think this can't occur: self.span_err(view_item.span, @@ -4517,7 +4524,7 @@ pub impl Parser { // Parses a source module as a crate. This is the main // entry point for the parser. - fn parse_crate_mod(&self) -> @crate { + pub fn parse_crate_mod(&self) -> @crate { let lo = self.span.lo; // parse the crate's inner attrs, maybe (oops) one // of the attrs of an item: @@ -4531,13 +4538,13 @@ pub impl Parser { config: copy self.cfg }) } - fn parse_str(&self) -> @~str { + pub fn parse_str(&self) -> @~str { match *self.token { token::LIT_STR(s) => { self.bump(); - self.id_to_str(s) + ident_to_str(&s) } - _ => self.fatal(~"expected string literal") + _ => self.fatal("expected string literal") } } } diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 36f241b64279a..ecf83483c21fe 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,14 +8,23 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use ast; +use ast::Name; use ast_util; use parse::token; use util::interner::StrInterner; use util::interner; +use core::cast; +use core::char; use core::cmp::Equiv; +use core::local_data; +use core::str; use core::hashmap::HashSet; +use core::rand; +use core::rand::RngUtil; use core::to_bytes; #[deriving(Encodable, Decodable, Eq)] @@ -137,7 +146,7 @@ pub fn to_str(in: @ident_interner, t: &Token) -> ~str { OROR => ~"||", ANDAND => ~"&&", BINOP(op) => binop_to_str(op), - BINOPEQ(op) => binop_to_str(op) + ~"=", + BINOPEQ(op) => binop_to_str(op) + "=", /* Structural symbols */ AT => ~"@", @@ -162,7 +171,7 @@ pub fn to_str(in: @ident_interner, t: &Token) -> ~str { /* Literals */ LIT_INT(c, ast::ty_char) => { - ~"'" + char::escape_default(c as char) + ~"'" + ~"'" + char::escape_default(c as char) + "'" } LIT_INT(i, t) => { i.to_str() + ast_util::int_ty_to_str(t) @@ -171,29 +180,29 @@ pub fn to_str(in: @ident_interner, t: &Token) -> ~str { u.to_str() + ast_util::uint_ty_to_str(t) } LIT_INT_UNSUFFIXED(i) => { i.to_str() } - LIT_FLOAT(s, t) => { - let mut body = copy *in.get(s); - if body.ends_with(~".") { - body = body + ~"0"; // `10.f` is not a float literal + LIT_FLOAT(ref s, t) => { + let mut body = copy *ident_to_str(s); + if body.ends_with(".") { + body += "0"; // `10.f` is not a float literal } body + ast_util::float_ty_to_str(t) } - LIT_FLOAT_UNSUFFIXED(s) => { - let mut body = copy *in.get(s); - if body.ends_with(~".") { - body = body + ~"0"; // `10.f` is not a float literal + LIT_FLOAT_UNSUFFIXED(ref s) => { + let mut body = copy *ident_to_str(s); + if body.ends_with(".") { + body += "0"; // `10.f` is not a float literal } body } - LIT_STR(s) => { ~"\"" + str::escape_default(*in.get(s)) + ~"\"" } + LIT_STR(ref s) => { ~"\"" + str::escape_default(*ident_to_str(s)) + "\"" } /* Name components */ - IDENT(s, _) => copy *in.get(s), - LIFETIME(s) => fmt!("'%s", *in.get(s)), + IDENT(s, _) => copy *in.get(s.name), + LIFETIME(s) => fmt!("'%s", *in.get(s.name)), UNDERSCORE => ~"_", /* Other */ - DOC_COMMENT(s) => copy *in.get(s), + DOC_COMMENT(ref s) => copy *ident_to_str(s), EOF => ~"", INTERPOLATED(ref nt) => { match nt { @@ -299,47 +308,47 @@ pub fn is_bar(t: &Token) -> bool { pub mod special_idents { use ast::ident; - pub static underscore : ident = ident { repr: 0, ctxt: 0}; - pub static anon : ident = ident { repr: 1, ctxt: 0}; - pub static invalid : ident = ident { repr: 2, ctxt: 0}; // '' - pub static unary : ident = ident { repr: 3, ctxt: 0}; - pub static not_fn : ident = ident { repr: 4, ctxt: 0}; - pub static idx_fn : ident = ident { repr: 5, ctxt: 0}; - pub static unary_minus_fn : ident = ident { repr: 6, ctxt: 0}; - pub static clownshoes_extensions : ident = ident { repr: 7, ctxt: 0}; + pub static underscore : ident = ident { name: 0, ctxt: 0}; + pub static anon : ident = ident { name: 1, ctxt: 0}; + pub static invalid : ident = ident { name: 2, ctxt: 0}; // '' + pub static unary : ident = ident { name: 3, ctxt: 0}; + pub static not_fn : ident = ident { name: 4, ctxt: 0}; + pub static idx_fn : ident = ident { name: 5, ctxt: 0}; + pub static unary_minus_fn : ident = ident { name: 6, ctxt: 0}; + pub static clownshoes_extensions : ident = ident { name: 7, ctxt: 0}; - pub static self_ : ident = ident { repr: 8, ctxt: 0}; // 'self' + pub static self_ : ident = ident { name: 8, ctxt: 0}; // 'self' /* for matcher NTs */ - pub static item : ident = ident { repr: 9, ctxt: 0}; - pub static block : ident = ident { repr: 10, ctxt: 0}; - pub static stmt : ident = ident { repr: 11, ctxt: 0}; - pub static pat : ident = ident { repr: 12, ctxt: 0}; - pub static expr : ident = ident { repr: 13, ctxt: 0}; - pub static ty : ident = ident { repr: 14, ctxt: 0}; - pub static ident : ident = ident { repr: 15, ctxt: 0}; - pub static path : ident = ident { repr: 16, ctxt: 0}; - pub static tt : ident = ident { repr: 17, ctxt: 0}; - pub static matchers : ident = ident { repr: 18, ctxt: 0}; - - pub static str : ident = ident { repr: 19, ctxt: 0}; // for the type + pub static item : ident = ident { name: 9, ctxt: 0}; + pub static block : ident = ident { name: 10, ctxt: 0}; + pub static stmt : ident = ident { name: 11, ctxt: 0}; + pub static pat : ident = ident { name: 12, ctxt: 0}; + pub static expr : ident = ident { name: 13, ctxt: 0}; + pub static ty : ident = ident { name: 14, ctxt: 0}; + pub static ident : ident = ident { name: 15, ctxt: 0}; + pub static path : ident = ident { name: 16, ctxt: 0}; + pub static tt : ident = ident { name: 17, ctxt: 0}; + pub static matchers : ident = ident { name: 18, ctxt: 0}; + + pub static str : ident = ident { name: 19, ctxt: 0}; // for the type /* outside of libsyntax */ - pub static ty_visitor : ident = ident { repr: 20, ctxt: 0}; - pub static arg : ident = ident { repr: 21, ctxt: 0}; - pub static descrim : ident = ident { repr: 22, ctxt: 0}; - pub static clownshoe_abi : ident = ident { repr: 23, ctxt: 0}; - pub static clownshoe_stack_shim : ident = ident { repr: 24, ctxt: 0}; - pub static tydesc : ident = ident { repr: 25, ctxt: 0}; - pub static main : ident = ident { repr: 26, ctxt: 0}; - pub static opaque : ident = ident { repr: 27, ctxt: 0}; - pub static blk : ident = ident { repr: 28, ctxt: 0}; - pub static statik : ident = ident { repr: 29, ctxt: 0}; - pub static intrinsic : ident = ident { repr: 30, ctxt: 0}; - pub static clownshoes_foreign_mod: ident = ident { repr: 31, ctxt: 0}; - pub static unnamed_field: ident = ident { repr: 32, ctxt: 0}; - pub static c_abi: ident = ident { repr: 33, ctxt: 0}; - pub static type_self: ident = ident { repr: 34, ctxt: 0}; // `Self` + pub static ty_visitor : ident = ident { name: 20, ctxt: 0}; + pub static arg : ident = ident { name: 21, ctxt: 0}; + pub static descrim : ident = ident { name: 22, ctxt: 0}; + pub static clownshoe_abi : ident = ident { name: 23, ctxt: 0}; + pub static clownshoe_stack_shim : ident = ident { name: 24, ctxt: 0}; + pub static tydesc : ident = ident { name: 25, ctxt: 0}; + pub static main : ident = ident { name: 26, ctxt: 0}; + pub static opaque : ident = ident { name: 27, ctxt: 0}; + pub static blk : ident = ident { name: 28, ctxt: 0}; + pub static statik : ident = ident { name: 29, ctxt: 0}; + pub static intrinsic : ident = ident { name: 30, ctxt: 0}; + pub static clownshoes_foreign_mod: ident = ident { name: 31, ctxt: 0}; + pub static unnamed_field: ident = ident { name: 32, ctxt: 0}; + pub static c_abi: ident = ident { name: 33, ctxt: 0}; + pub static type_self: ident = ident { name: 34, ctxt: 0}; // `Self` } pub struct StringRef<'self>(&'self str); @@ -349,14 +358,6 @@ impl<'self> Equiv<@~str> for StringRef<'self> { fn equiv(&self, other: &@~str) -> bool { str::eq_slice(**self, **other) } } -#[cfg(stage0)] -impl<'self> to_bytes::IterBytes for StringRef<'self> { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - (**self).iter_bytes(lsb0, f); - } -} -#[cfg(not(stage0))] impl<'self> to_bytes::IterBytes for StringRef<'self> { #[inline(always)] fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { @@ -396,31 +397,28 @@ pub struct ident_interner { priv interner: StrInterner, } -pub impl ident_interner { - fn intern(&self, val: &str) -> ast::ident { - ast::ident { repr: self.interner.intern(val), ctxt: 0 } +impl ident_interner { + pub fn intern(&self, val: &str) -> Name { + self.interner.intern(val) } - fn gensym(&self, val: &str) -> ast::ident { - ast::ident { repr: self.interner.gensym(val), ctxt: 0 } + pub fn gensym(&self, val: &str) -> Name { + self.interner.gensym(val) } - fn get(&self, idx: ast::ident) -> @~str { - self.interner.get(idx.repr) + pub fn get(&self, idx: Name) -> @~str { + self.interner.get(idx) } - fn len(&self) -> uint { + // is this really something that should be exposed? + pub fn len(&self) -> uint { self.interner.len() } - fn find_equiv>(&self, val: &Q) - -> Option { - match self.interner.find_equiv(val) { - Some(v) => Some(ast::ident { repr: v, ctxt: 0 }), - None => None, - } + pub fn find_equiv>(&self, val: &Q) + -> Option { + self.interner.find_equiv(val) } } // return a fresh interner, preloaded with special identifiers. -// EFFECT: stores this interner in TLS -pub fn mk_fresh_ident_interner() -> @ident_interner { +fn mk_fresh_ident_interner() -> @ident_interner { // the indices here must correspond to the numbers in // special_idents. let init_vec = ~[ @@ -459,25 +457,68 @@ pub fn mk_fresh_ident_interner() -> @ident_interner { "__field__", // 32 "C", // 33 "Self", // 34 + + "as", // 35 + "break", // 36 + "const", // 37 + "copy", // 38 + "do", // 39 + "drop", // 40 + "else", // 41 + "enum", // 42 + "extern", // 43 + "false", // 44 + "fn", // 45 + "for", // 46 + "if", // 47 + "impl", // 48 + "let", // 49 + "__log", // 50 + "loop", // 51 + "match", // 52 + "mod", // 53 + "mut", // 54 + "once", // 55 + "priv", // 56 + "pub", // 57 + "pure", // 58 + "ref", // 59 + "return", // 60 + "static", // 29 -- also a special ident + "self", // 8 -- also a special ident + "struct", // 61 + "super", // 62 + "true", // 63 + "trait", // 64 + "type", // 65 + "unsafe", // 66 + "use", // 67 + "while", // 68 + + "be", // 69 ]; - let rv = @ident_interner { + @ident_interner { interner: interner::StrInterner::prefill(init_vec) - }; - unsafe { - local_data::local_data_set(interner_key!(), @rv); } - rv } // if an interner exists in TLS, return it. Otherwise, prepare a // fresh one. -pub fn mk_ident_interner() -> @ident_interner { +pub fn get_ident_interner() -> @ident_interner { unsafe { - match local_data::local_data_get(interner_key!()) { + let key = + (cast::transmute::<(uint, uint), + &fn(v: @@::parse::token::ident_interner)>( + (-3 as uint, 0u))); + match local_data::local_data_get(key) { Some(interner) => *interner, None => { - mk_fresh_ident_interner() + let interner = mk_fresh_ident_interner(); + unsafe { + local_data::local_data_set(key, @interner); + } + interner } } } @@ -489,64 +530,192 @@ pub fn mk_fake_ident_interner() -> @ident_interner { @ident_interner { interner: interner::StrInterner::new() } } +// maps a string to its interned representation +pub fn intern(str : &str) -> Name { + let interner = get_ident_interner(); + interner.intern(str) +} + +// gensyms a new uint, using the current interner +pub fn gensym(str : &str) -> Name { + let interner = get_ident_interner(); + interner.gensym(str) +} + +// map an interned representation back to a string +pub fn interner_get(name : Name) -> @~str { + get_ident_interner().get(name) +} + +// maps an identifier to the string that it corresponds to +pub fn ident_to_str(id : &ast::ident) -> @~str { + interner_get(id.name) +} + +// maps a string to an identifier with an empty syntax context +pub fn str_to_ident(str : &str) -> ast::ident { + ast::new_ident(intern(str)) +} + +// maps a string to a gensym'ed identifier +pub fn gensym_ident(str : &str) -> ast::ident { + ast::new_ident(gensym(str)) +} + + +// create a fresh name. In principle, this is just a +// gensym, but for debugging purposes, you'd like the +// resulting name to have a suggestive stringify, without +// paying the cost of guaranteeing that the name is +// truly unique. I'm going to try to strike a balance +// by using a gensym with a name that has a random number +// at the end. So, the gensym guarantees the uniqueness, +// and the int helps to avoid confusion. +pub fn fresh_name(src_name : &str) -> Name { + let num = rand::rng().gen_uint_range(0,0xffff); + gensym(fmt!("%s_%u",src_name,num)) +} + /** * All the valid words that have meaning in the Rust language. * - * Rust keywords are either 'temporary', 'strict' or 'reserved'. Temporary - * keywords are contextual and may be used as identifiers anywhere. They are - * expected to disappear from the grammar soon. Strict keywords may not + * Rust keywords are either 'strict' or 'reserved'. Strict keywords may not * appear as identifiers at all. Reserved keywords are not used anywhere in * the language and may not appear as identifiers. */ -pub fn keyword_table() -> HashSet<~str> { - let mut keywords = HashSet::new(); - let mut strict = strict_keyword_table(); - let mut reserved = reserved_keyword_table(); +pub mod keywords { + use ast::ident; - do strict.consume |word| { - keywords.insert(word); + pub enum Keyword { + // Strict keywords + As, + Break, + Const, + Copy, + Do, + Else, + Enum, + Extern, + False, + Fn, + For, + If, + Impl, + Let, + __Log, + Loop, + Match, + Mod, + Mut, + Once, + Priv, + Pub, + Pure, + Ref, + Return, + Static, + Self, + Struct, + Super, + True, + Trait, + Type, + Unsafe, + Use, + While, + + // Reserved keywords + Be, } - do reserved.consume |word| { - keywords.insert(word); + + impl Keyword { + pub fn to_ident(&self) -> ident { + match *self { + As => ident { name: 35, ctxt: 0 }, + Break => ident { name: 36, ctxt: 0 }, + Const => ident { name: 37, ctxt: 0 }, + Copy => ident { name: 38, ctxt: 0 }, + Do => ident { name: 39, ctxt: 0 }, + Else => ident { name: 41, ctxt: 0 }, + Enum => ident { name: 42, ctxt: 0 }, + Extern => ident { name: 43, ctxt: 0 }, + False => ident { name: 44, ctxt: 0 }, + Fn => ident { name: 45, ctxt: 0 }, + For => ident { name: 46, ctxt: 0 }, + If => ident { name: 47, ctxt: 0 }, + Impl => ident { name: 48, ctxt: 0 }, + Let => ident { name: 49, ctxt: 0 }, + __Log => ident { name: 50, ctxt: 0 }, + Loop => ident { name: 51, ctxt: 0 }, + Match => ident { name: 52, ctxt: 0 }, + Mod => ident { name: 53, ctxt: 0 }, + Mut => ident { name: 54, ctxt: 0 }, + Once => ident { name: 55, ctxt: 0 }, + Priv => ident { name: 56, ctxt: 0 }, + Pub => ident { name: 57, ctxt: 0 }, + Pure => ident { name: 58, ctxt: 0 }, + Ref => ident { name: 59, ctxt: 0 }, + Return => ident { name: 60, ctxt: 0 }, + Static => ident { name: 29, ctxt: 0 }, + Self => ident { name: 8, ctxt: 0 }, + Struct => ident { name: 61, ctxt: 0 }, + Super => ident { name: 62, ctxt: 0 }, + True => ident { name: 63, ctxt: 0 }, + Trait => ident { name: 64, ctxt: 0 }, + Type => ident { name: 65, ctxt: 0 }, + Unsafe => ident { name: 66, ctxt: 0 }, + Use => ident { name: 67, ctxt: 0 }, + While => ident { name: 68, ctxt: 0 }, + Be => ident { name: 69, ctxt: 0 }, + } + } } +} - keywords -} - -/// Full keywords. May not appear anywhere else. -pub fn strict_keyword_table() -> HashSet<~str> { - let mut words = HashSet::new(); - let keys = ~[ - ~"as", - ~"break", - ~"const", ~"copy", - ~"do", ~"drop", - ~"else", ~"enum", ~"extern", - ~"false", ~"fn", ~"for", - ~"if", ~"impl", - ~"let", ~"__log", ~"loop", - ~"match", ~"mod", ~"mut", - ~"once", - ~"priv", ~"pub", ~"pure", - ~"ref", ~"return", - ~"static", ~"self", ~"struct", ~"super", - ~"true", ~"trait", ~"type", - ~"unsafe", ~"use", - ~"while" - ]; - do vec::consume(keys) |_, w| { - words.insert(w); +pub fn is_keyword(kw: keywords::Keyword, tok: &Token) -> bool { + match *tok { + token::IDENT(sid, false) => { kw.to_ident().name == sid.name } + _ => { false } } - return words; } -pub fn reserved_keyword_table() -> HashSet<~str> { - let mut words = HashSet::new(); - let keys = ~[ - ~"be" - ]; - do vec::consume(keys) |_, s| { - words.insert(s); +pub fn is_any_keyword(tok: &Token) -> bool { + match *tok { + token::IDENT(sid, false) => match sid.name { + 8 | 29 | 35 .. 69 => true, + _ => false, + }, + _ => false + } +} + +pub fn is_strict_keyword(tok: &Token) -> bool { + match *tok { + token::IDENT(sid, false) => match sid.name { + 8 | 29 | 35 .. 68 => true, + _ => false, + }, + _ => false, + } +} + +pub fn is_reserved_keyword(tok: &Token) -> bool { + match *tok { + token::IDENT(sid, false) => match sid.name { + 69 => true, + _ => false, + }, + _ => false, + } +} + +#[cfg(test)] +mod test { + use super::*; + use std::io; + #[test] fn t1() { + let a = fresh_name("ghi"); + io::println(fmt!("interned name: %u,\ntextual name: %s\n", + a,*interner_get(a))); } - return words; } diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index 38c58612f43a7..f6059980697fa 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -60,6 +60,12 @@ * line (which it can't) and so naturally place the content on its own line to * avoid combining it with other lines and making matters even worse. */ + +use core::prelude::*; + +use core::io; +use core::vec; + #[deriving(Eq)] pub enum breaks { consistent, inconsistent, } @@ -81,11 +87,12 @@ pub enum token { EOF, } -pub impl token { - fn is_eof(&self) -> bool { +impl token { + pub fn is_eof(&self) -> bool { match *self { EOF => true, _ => false } } - fn is_hardbreak_tok(&self) -> bool { + + pub fn is_hardbreak_tok(&self) -> bool { match *self { BREAK(break_t { offset: 0, @@ -111,18 +118,18 @@ pub fn tok_str(t: token) -> ~str { pub fn buf_str(toks: ~[token], szs: ~[int], left: uint, right: uint, lim: uint) -> ~str { let n = toks.len(); - assert!(n == szs.len()); + assert_eq!(n, szs.len()); let mut i = left; let mut L = lim; let mut s = ~"["; while i != right && L != 0u { L -= 1u; - if i != left { s += ~", "; } + if i != left { s += ", "; } s += fmt!("%d=%s", szs[i], tok_str(toks[i])); i += 1u; i %= n; } - s += ~"]"; + s += "]"; return s; } @@ -268,11 +275,13 @@ pub struct Printer { pending_indentation: int, } -pub impl Printer { - fn last_token(&mut self) -> token { self.token[self.right] } +impl Printer { + pub fn last_token(&mut self) -> token { self.token[self.right] } // be very careful with this! - fn replace_last_token(&mut self, t: token) { self.token[self.right] = t; } - fn pretty_print(&mut self, t: token) { + pub fn replace_last_token(&mut self, t: token) { + self.token[self.right] = t; + } + pub fn pretty_print(&mut self, t: token) { debug!("pp ~[%u,%u]", self.left, self.right); match t { EOF => { @@ -340,7 +349,7 @@ pub impl Printer { } } } - fn check_stream(&mut self) { + pub fn check_stream(&mut self) { debug!("check_stream ~[%u, %u] with left_total=%d, right_total=%d", self.left, self.right, self.left_total, self.right_total); if self.right_total - self.left_total > self.space { @@ -356,7 +365,7 @@ pub impl Printer { if self.left != self.right { self.check_stream(); } } } - fn scan_push(&mut self, x: uint) { + pub fn scan_push(&mut self, x: uint) { debug!("scan_push %u", x); if self.scan_stack_empty { self.scan_stack_empty = false; @@ -367,7 +376,7 @@ pub impl Printer { } self.scan_stack[self.top] = x; } - fn scan_pop(&mut self) -> uint { + pub fn scan_pop(&mut self) -> uint { assert!((!self.scan_stack_empty)); let x = self.scan_stack[self.top]; if self.top == self.bottom { @@ -375,11 +384,11 @@ pub impl Printer { } else { self.top += self.buf_len - 1u; self.top %= self.buf_len; } return x; } - fn scan_top(&mut self) -> uint { + pub fn scan_top(&mut self) -> uint { assert!((!self.scan_stack_empty)); return self.scan_stack[self.top]; } - fn scan_pop_bottom(&mut self) -> uint { + pub fn scan_pop_bottom(&mut self) -> uint { assert!((!self.scan_stack_empty)); let x = self.scan_stack[self.bottom]; if self.top == self.bottom { @@ -387,12 +396,12 @@ pub impl Printer { } else { self.bottom += 1u; self.bottom %= self.buf_len; } return x; } - fn advance_right(&mut self) { + pub fn advance_right(&mut self) { self.right += 1u; self.right %= self.buf_len; assert!((self.right != self.left)); } - fn advance_left(&mut self, x: token, L: int) { + pub fn advance_left(&mut self, x: token, L: int) { debug!("advnce_left ~[%u,%u], sizeof(%u)=%d", self.left, self.right, self.left, L); if L >= 0 { @@ -400,7 +409,7 @@ pub impl Printer { match x { BREAK(b) => self.left_total += b.blank_space, STRING(_, len) => { - assert!((len == L)); self.left_total += len; + assert_eq!(len, L); self.left_total += len; } _ => () } @@ -412,7 +421,7 @@ pub impl Printer { } } } - fn check_stack(&mut self, k: int) { + pub fn check_stack(&mut self, k: int) { if !self.scan_stack_empty { let x = self.scan_top(); match copy self.token[x] { @@ -435,17 +444,17 @@ pub impl Printer { } } } - fn print_newline(&mut self, amount: int) { + pub fn print_newline(&mut self, amount: int) { debug!("NEWLINE %d", amount); - (*self.out).write_str(~"\n"); + (*self.out).write_str("\n"); self.pending_indentation = 0; self.indent(amount); } - fn indent(&mut self, amount: int) { + pub fn indent(&mut self, amount: int) { debug!("INDENT %d", amount); self.pending_indentation += amount; } - fn get_top(&mut self) -> print_stack_elt { + pub fn get_top(&mut self) -> print_stack_elt { let print_stack = &mut *self.print_stack; let n = print_stack.len(); if n != 0u { @@ -457,14 +466,14 @@ pub impl Printer { } } } - fn print_str(&mut self, s: &str) { + pub fn print_str(&mut self, s: &str) { while self.pending_indentation > 0 { (*self.out).write_str(" "); self.pending_indentation -= 1; } (*self.out).write_str(s); } - fn print(&mut self, x: token, L: int) { + pub fn print(&mut self, x: token, L: int) { debug!("print %s %d (remaining line space=%d)", tok_str(x), L, self.space); debug!("%s", buf_str(copy self.token, @@ -526,7 +535,7 @@ pub impl Printer { } STRING(s, len) => { debug!("print STRING(%s)", *s); - assert!((L == len)); + assert_eq!(L, len); // assert!(L <= space); self.space -= len; self.print_str(*s); diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index ea1682978a463..57e78d3ad8409 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; use abi::AbiSet; use ast::{RegionTyParamBound, TraitTyParamBound, required, provided}; @@ -20,7 +21,7 @@ use codemap::{CodeMap, BytePos}; use codemap; use diagnostic; use parse::classify::expr_is_simple_block; -use parse::token::ident_interner; +use parse::token::{ident_interner, ident_to_str}; use parse::{comments, token}; use parse; use print::pp::{break_offset, word, space, zerobreak, hardbreak}; @@ -28,6 +29,13 @@ use print::pp::{breaks, consistent, inconsistent, eof}; use print::pp; use print::pprust; +use core::char; +use core::io; +use core::str; +use core::u64; +use core::uint; +use core::vec; + // The @ps is stored here to prevent recursive type. pub enum ann_node<'self> { node_block(@ps, &'self ast::blk), @@ -227,17 +235,17 @@ pub fn box(s: @ps, u: uint, b: pp::breaks) { pp::box(s.s, u, b); } -pub fn nbsp(s: @ps) { word(s.s, ~" "); } +pub fn nbsp(s: @ps) { word(s.s, " "); } pub fn word_nbsp(s: @ps, w: &str) { word(s.s, w); nbsp(s); } pub fn word_space(s: @ps, w: &str) { word(s.s, w); space(s.s); } -pub fn popen(s: @ps) { word(s.s, ~"("); } +pub fn popen(s: @ps) { word(s.s, "("); } -pub fn pclose(s: @ps) { word(s.s, ~")"); } +pub fn pclose(s: @ps) { word(s.s, ")"); } -pub fn head(s: @ps, w: ~str) { +pub fn head(s: @ps, w: &str) { // outer-box is consistent cbox(s, indent_unit); // head-box is inconsistent @@ -249,7 +257,7 @@ pub fn head(s: @ps, w: ~str) { } pub fn bopen(s: @ps) { - word(s.s, ~"{"); + word(s.s, "{"); end(s); // close the head-box } @@ -260,7 +268,7 @@ pub fn bclose_maybe_open (s: @ps, span: codemap::span, indented: uint, close_box: bool) { maybe_print_comment(s, span.hi); break_offset_if_not_bol(s, 1u, -(indented as int)); - word(s.s, ~"}"); + word(s.s, "}"); if close_box { end(s); // close the outer-box } @@ -304,18 +312,18 @@ pub fn break_offset_if_not_bol(s: @ps, n: uint, off: int) { // Synthesizes a comment that was not textually present in the original source // file. pub fn synth_comment(s: @ps, text: ~str) { - word(s.s, ~"/*"); + word(s.s, "/*"); space(s.s); word(s.s, text); space(s.s); - word(s.s, ~"*/"); + word(s.s, "*/"); } pub fn commasep(s: @ps, b: breaks, elts: &[IN], op: &fn(@ps, IN)) { box(s, 0u, b); let mut first = true; for elts.each |elt| { - if first { first = false; } else { word_space(s, ~","); } + if first { first = false; } else { word_space(s, ","); } op(s, *elt); } end(s); @@ -332,7 +340,7 @@ pub fn commasep_cmnt(s: @ps, b: breaks, elts: &[IN], op: &fn(@ps, IN), op(s, *elt); i += 1u; if i < len { - word(s.s, ~","); + word(s.s, ","); maybe_print_trailing_comment(s, get_span(*elt), Some(get_span(elts[i]).hi)); space_if_not_bol(s); @@ -374,23 +382,23 @@ pub fn print_type(s: @ps, ty: @ast::Ty) { maybe_print_comment(s, ty.span.lo); ibox(s, 0u); match ty.node { - ast::ty_nil => word(s.s, ~"()"), - ast::ty_bot => word(s.s, ~"!"), - ast::ty_box(ref mt) => { word(s.s, ~"@"); print_mt(s, mt); } - ast::ty_uniq(ref mt) => { word(s.s, ~"~"); print_mt(s, mt); } + ast::ty_nil => word(s.s, "()"), + ast::ty_bot => word(s.s, "!"), + ast::ty_box(ref mt) => { word(s.s, "@"); print_mt(s, mt); } + ast::ty_uniq(ref mt) => { word(s.s, "~"); print_mt(s, mt); } ast::ty_vec(ref mt) => { - word(s.s, ~"["); + word(s.s, "["); match mt.mutbl { - ast::m_mutbl => word_space(s, ~"mut"), - ast::m_const => word_space(s, ~"const"), + ast::m_mutbl => word_space(s, "mut"), + ast::m_const => word_space(s, "const"), ast::m_imm => () } print_type(s, mt.ty); - word(s.s, ~"]"); + word(s.s, "]"); } - ast::ty_ptr(ref mt) => { word(s.s, ~"*"); print_mt(s, mt); } + ast::ty_ptr(ref mt) => { word(s.s, "*"); print_mt(s, mt); } ast::ty_rptr(lifetime, ref mt) => { - word(s.s, ~"&"); + word(s.s, "&"); print_opt_lifetime(s, lifetime); print_mt(s, mt); } @@ -398,7 +406,7 @@ pub fn print_type(s: @ps, ty: @ast::Ty) { popen(s); commasep(s, inconsistent, *elts, print_type); if elts.len() == 1 { - word(s.s, ~","); + word(s.s, ","); } pclose(s); } @@ -418,16 +426,16 @@ pub fn print_type(s: @ps, ty: @ast::Ty) { } ast::ty_path(path, _) => print_path(s, path, false), ast::ty_fixed_length_vec(ref mt, v) => { - word(s.s, ~"["); + word(s.s, "["); match mt.mutbl { - ast::m_mutbl => word_space(s, ~"mut"), - ast::m_const => word_space(s, ~"const"), + ast::m_mutbl => word_space(s, "mut"), + ast::m_const => word_space(s, "const"), ast::m_imm => () } print_type(s, mt.ty); - word(s.s, ~", .."); + word(s.s, ", .."); print_expr(s, v); - word(s.s, ~"]"); + word(s.s, "]"); } ast::ty_mac(_) => { fail!("print_type doesn't know how to print a ty_mac"); @@ -449,15 +457,15 @@ pub fn print_foreign_item(s: @ps, item: @ast::foreign_item) { print_fn(s, decl, Some(purity), AbiSet::Rust(), item.ident, generics, None, ast::inherited); end(s); // end head-ibox - word(s.s, ~";"); + word(s.s, ";"); end(s); // end the outer fn box } ast::foreign_item_const(t) => { - head(s, ~"static"); + head(s, "static"); print_ident(s, item.ident); - word_space(s, ~":"); + word_space(s, ":"); print_type(s, t); - word(s.s, ~";"); + word(s.s, ";"); end(s); // end the head-ibox end(s); // end the outer cbox } @@ -472,16 +480,16 @@ pub fn print_item(s: @ps, item: @ast::item) { (s.ann.pre)(ann_node); match item.node { ast::item_const(ty, expr) => { - head(s, visibility_qualified(item.vis, ~"static")); + head(s, visibility_qualified(item.vis, "static")); print_ident(s, item.ident); - word_space(s, ~":"); + word_space(s, ":"); print_type(s, ty); space(s.s); end(s); // end the head-ibox - word_space(s, ~"="); + word_space(s, "="); print_expr(s, expr); - word(s.s, ~";"); + word(s.s, ";"); end(s); // end the outer cbox } @@ -496,11 +504,11 @@ pub fn print_item(s: @ps, item: @ast::item) { None, item.vis ); - word(s.s, ~" "); + word(s.s, " "); print_block_with_attrs(s, body, item.attrs); } ast::item_mod(ref _mod) => { - head(s, visibility_qualified(item.vis, ~"mod")); + head(s, visibility_qualified(item.vis, "mod")); print_ident(s, item.ident); nbsp(s); bopen(s); @@ -508,11 +516,11 @@ pub fn print_item(s: @ps, item: @ast::item) { bclose(s, item.span); } ast::item_foreign_mod(ref nmod) => { - head(s, visibility_qualified(item.vis, ~"extern")); + head(s, visibility_qualified(item.vis, "extern")); word_nbsp(s, nmod.abis.to_str()); match nmod.sort { ast::named => { - word_nbsp(s, ~"mod"); + word_nbsp(s, "mod"); print_ident(s, item.ident); nbsp(s); } @@ -525,15 +533,15 @@ pub fn print_item(s: @ps, item: @ast::item) { ast::item_ty(ty, ref params) => { ibox(s, indent_unit); ibox(s, 0u); - word_nbsp(s, visibility_qualified(item.vis, ~"type")); + word_nbsp(s, visibility_qualified(item.vis, "type")); print_ident(s, item.ident); print_generics(s, params); end(s); // end the inner ibox space(s.s); - word_space(s, ~"="); + word_space(s, "="); print_type(s, ty); - word(s.s, ~";"); + word(s.s, ";"); end(s); // end the outer ibox } ast::item_enum(ref enum_definition, ref params) => { @@ -547,12 +555,12 @@ pub fn print_item(s: @ps, item: @ast::item) { ); } ast::item_struct(struct_def, ref generics) => { - head(s, visibility_qualified(item.vis, ~"struct")); + head(s, visibility_qualified(item.vis, "struct")); print_struct(s, struct_def, generics, item.ident, item.span); } ast::item_impl(ref generics, opt_trait, ty, ref methods) => { - head(s, visibility_qualified(item.vis, ~"impl")); + head(s, visibility_qualified(item.vis, "impl")); if generics.is_parameterized() { print_generics(s, generics); space(s.s); @@ -562,7 +570,7 @@ pub fn print_item(s: @ps, item: @ast::item) { Some(t) => { print_trait_ref(s, t); space(s.s); - word_space(s, ~"for"); + word_space(s, "for"); } None => () }; @@ -571,7 +579,7 @@ pub fn print_item(s: @ps, item: @ast::item) { space(s.s); if methods.len() == 0 { - word(s.s, ~";"); + word(s.s, ";"); } else { bopen(s); for methods.each |meth| { @@ -581,20 +589,20 @@ pub fn print_item(s: @ps, item: @ast::item) { } } ast::item_trait(ref generics, ref traits, ref methods) => { - head(s, visibility_qualified(item.vis, ~"trait")); + head(s, visibility_qualified(item.vis, "trait")); print_ident(s, item.ident); print_generics(s, generics); if traits.len() != 0u { - word(s.s, ~":"); + word(s.s, ":"); for traits.eachi |i, trait_| { nbsp(s); if i != 0 { - word_space(s, ~"+"); + word_space(s, "+"); } print_path(s, trait_.path, false); } } - word(s.s, ~" "); + word(s.s, " "); bopen(s); for methods.each |meth| { print_trait_method(s, meth); @@ -605,7 +613,7 @@ pub fn print_item(s: @ps, item: @ast::item) { _}) => { print_visibility(s, item.vis); print_path(s, pth, false); - word(s.s, ~"! "); + word(s.s, "! "); print_ident(s, item.ident); cbox(s, indent_unit); popen(s); @@ -624,7 +632,7 @@ fn print_trait_ref(s: @ps, t: &ast::trait_ref) { pub fn print_enum_def(s: @ps, enum_definition: &ast::enum_def, generics: &ast::Generics, ident: ast::ident, span: codemap::span, visibility: ast::visibility) { - head(s, visibility_qualified(visibility, ~"enum")); + head(s, visibility_qualified(visibility, "enum")); print_ident(s, ident); print_generics(s, generics); space(s.s); @@ -641,7 +649,7 @@ pub fn print_variants(s: @ps, print_outer_attributes(s, v.node.attrs); ibox(s, indent_unit); print_variant(s, v); - word(s.s, ~","); + word(s.s, ","); end(s); maybe_print_trailing_comment(s, v.span, None); } @@ -656,10 +664,10 @@ pub fn visibility_to_str(vis: ast::visibility) -> ~str { } } -pub fn visibility_qualified(vis: ast::visibility, s: ~str) -> ~str { +pub fn visibility_qualified(vis: ast::visibility, s: &str) -> ~str { match vis { ast::private | ast::public => visibility_to_str(vis) + " " + s, - ast::inherited => copy s + ast::inherited => s.to_owned() } } @@ -692,7 +700,7 @@ pub fn print_struct(s: @ps, } pclose(s); } - word(s.s, ~";"); + word(s.s, ";"); end(s); end(s); // close the outer-box } else { @@ -709,9 +717,9 @@ pub fn print_struct(s: @ps, print_outer_attributes(s, field.node.attrs); print_visibility(s, visibility); print_ident(s, ident); - word_nbsp(s, ~":"); + word_nbsp(s, ":"); print_type(s, field.node.ty); - word(s.s, ~","); + word(s.s, ","); } } } @@ -734,17 +742,17 @@ pub fn print_tt(s: @ps, tt: &ast::token_tree) { word(s.s, parse::token::to_str(s.intr, tk)); } ast::tt_seq(_, ref tts, ref sep, zerok) => { - word(s.s, ~"$("); + word(s.s, "$("); for (*tts).each() |tt_elt| { print_tt(s, tt_elt); } - word(s.s, ~")"); + word(s.s, ")"); match (*sep) { Some(ref tk) => word(s.s, parse::token::to_str(s.intr, tk)), None => () } - word(s.s, if zerok { ~"*" } else { ~"+" }); + word(s.s, if zerok { "*" } else { "+" }); } ast::tt_nonterminal(_, name) => { - word(s.s, ~"$"); + word(s.s, "$"); print_ident(s, name); } } @@ -776,7 +784,7 @@ pub fn print_variant(s: @ps, v: &ast::variant) { } } ast::struct_variant_kind(struct_def) => { - head(s, ~""); + head(s, ""); let generics = ast_util::empty_generics(); print_struct(s, struct_def, &generics, v.node.name, v.span); } @@ -784,7 +792,7 @@ pub fn print_variant(s: @ps, v: &ast::variant) { match v.node.disr_expr { Some(d) => { space(s.s); - word_space(s, ~"="); + word_space(s, "="); print_expr(s, d); } _ => () @@ -798,7 +806,7 @@ pub fn print_ty_method(s: @ps, m: &ast::ty_method) { print_ty_fn(s, None, None, None, m.purity, ast::Many, &m.decl, Some(m.ident), Some(&m.generics), Some(/*bad*/ copy m.explicit_self.node)); - word(s.s, ~";"); + word(s.s, ";"); } pub fn print_trait_method(s: @ps, m: &ast::trait_method) { @@ -815,7 +823,7 @@ pub fn print_method(s: @ps, meth: @ast::method) { print_fn(s, &meth.decl, Some(meth.purity), AbiSet::Rust(), meth.ident, &meth.generics, Some(meth.explicit_self.node), meth.vis); - word(s.s, ~" "); + word(s.s, " "); print_block_with_attrs(s, &meth.body, meth.attrs); } @@ -837,7 +845,7 @@ pub fn print_inner_attributes(s: @ps, attrs: &[ast::attribute]) { ast::attr_inner => { print_attribute(s, *attr); if !attr.node.is_sugared_doc { - word(s.s, ~";"); + word(s.s, ";"); } count += 1; } @@ -855,9 +863,9 @@ pub fn print_attribute(s: @ps, attr: ast::attribute) { let comment = attr::get_meta_item_value_str(meta).get(); word(s.s, *comment); } else { - word(s.s, ~"#["); + word(s.s, "#["); print_meta_item(s, attr.node.value); - word(s.s, ~"]"); + word(s.s, "]"); } } @@ -875,15 +883,15 @@ pub fn print_stmt(s: @ps, st: &ast::stmt) { ast::stmt_semi(expr, _) => { space_if_not_bol(s); print_expr(s, expr); - word(s.s, ~";"); + word(s.s, ";"); } ast::stmt_mac(ref mac, semi) => { space_if_not_bol(s); print_mac(s, mac); - if semi { word(s.s, ~";"); } + if semi { word(s.s, ";"); } } } - if parse::classify::stmt_ends_with_semi(st) { word(s.s, ~";"); } + if parse::classify::stmt_ends_with_semi(st) { word(s.s, ";"); } maybe_print_trailing_comment(s, st.span, None); } @@ -925,7 +933,7 @@ pub fn print_possibly_embedded_block_(s: @ps, attrs: &[ast::attribute], close_box: bool) { match blk.node.rules { - ast::unsafe_blk => word_space(s, ~"unsafe"), + ast::unsafe_blk => word_space(s, "unsafe"), ast::default_blk => () } maybe_print_comment(s, blk.span.lo); @@ -956,8 +964,8 @@ pub fn print_possibly_embedded_block_(s: @ps, pub fn print_if(s: @ps, test: @ast::expr, blk: &ast::blk, elseopt: Option<@ast::expr>, chk: bool) { - head(s, ~"if"); - if chk { word_nbsp(s, ~"check"); } + head(s, "if"); + if chk { word_nbsp(s, "check"); } print_expr(s, test); space(s.s); print_block(s, blk); @@ -969,7 +977,7 @@ pub fn print_if(s: @ps, test: @ast::expr, blk: &ast::blk, ast::expr_if(i, ref t, e) => { cbox(s, indent_unit - 1u); ibox(s, 0u); - word(s.s, ~" else if "); + word(s.s, " else if "); print_expr(s, i); space(s.s); print_block(s, t); @@ -979,7 +987,7 @@ pub fn print_if(s: @ps, test: @ast::expr, blk: &ast::blk, ast::expr_block(ref b) => { cbox(s, indent_unit - 1u); ibox(s, 0u); - word(s.s, ~" else "); + word(s.s, " else "); print_block(s, b); } // BLEAH, constraints would be great here @@ -998,7 +1006,7 @@ pub fn print_mac(s: @ps, m: &ast::mac) { match m.node { ast::mac_invoc_tt(pth, ref tts) => { print_path(s, pth, false); - word(s.s, ~"!"); + word(s.s, "!"); popen(s); print_tts(s, *tts); pclose(s); @@ -1009,11 +1017,11 @@ pub fn print_mac(s: @ps, m: &ast::mac) { pub fn print_vstore(s: @ps, t: ast::vstore) { match t { ast::vstore_fixed(Some(i)) => word(s.s, fmt!("%u", i)), - ast::vstore_fixed(None) => word(s.s, ~"_"), - ast::vstore_uniq => word(s.s, ~"~"), - ast::vstore_box => word(s.s, ~"@"), + ast::vstore_fixed(None) => word(s.s, "_"), + ast::vstore_uniq => word(s.s, "~"), + ast::vstore_box => word(s.s, "@"), ast::vstore_slice(r) => { - word(s.s, ~"&"); + word(s.s, "&"); print_opt_lifetime(s, r); } } @@ -1021,16 +1029,16 @@ pub fn print_vstore(s: @ps, t: ast::vstore) { pub fn print_expr_vstore(s: @ps, t: ast::expr_vstore) { match t { - ast::expr_vstore_uniq => word(s.s, ~"~"), - ast::expr_vstore_box => word(s.s, ~"@"), + ast::expr_vstore_uniq => word(s.s, "~"), + ast::expr_vstore_box => word(s.s, "@"), ast::expr_vstore_mut_box => { - word(s.s, ~"@"); - word(s.s, ~"mut"); + word(s.s, "@"); + word(s.s, "mut"); } - ast::expr_vstore_slice => word(s.s, ~"&"), + ast::expr_vstore_slice => word(s.s, "&"), ast::expr_vstore_mut_slice => { - word(s.s, ~"&"); - word(s.s, ~"mut"); + word(s.s, "&"); + word(s.s, "mut"); } } } @@ -1041,11 +1049,11 @@ pub fn print_call_pre(s: @ps, -> Option<@ast::expr> { match sugar { ast::DoSugar => { - head(s, ~"do"); + head(s, "do"); Some(base_args.pop()) } ast::ForSugar => { - head(s, ~"for"); + head(s, "for"); Some(base_args.pop()) } ast::NoSugar => None @@ -1082,9 +1090,8 @@ pub fn print_call_post(s: @ps, pub fn print_expr(s: @ps, expr: @ast::expr) { fn print_field(s: @ps, field: ast::field) { ibox(s, indent_unit); - if field.node.mutbl == ast::m_mutbl { word_nbsp(s, ~"mut"); } print_ident(s, field.node.ident); - word_space(s, ~":"); + word_space(s, ":"); print_expr(s, field.node.expr); end(s); } @@ -1101,53 +1108,53 @@ pub fn print_expr(s: @ps, expr: @ast::expr) { }, ast::expr_vec(ref exprs, mutbl) => { ibox(s, indent_unit); - word(s.s, ~"["); + word(s.s, "["); if mutbl == ast::m_mutbl { - word(s.s, ~"mut"); + word(s.s, "mut"); if exprs.len() > 0u { nbsp(s); } } commasep_exprs(s, inconsistent, *exprs); - word(s.s, ~"]"); + word(s.s, "]"); end(s); } ast::expr_repeat(element, count, mutbl) => { ibox(s, indent_unit); - word(s.s, ~"["); + word(s.s, "["); if mutbl == ast::m_mutbl { - word(s.s, ~"mut"); + word(s.s, "mut"); nbsp(s); } print_expr(s, element); - word(s.s, ~","); - word(s.s, ~".."); + word(s.s, ","); + word(s.s, ".."); print_expr(s, count); - word(s.s, ~"]"); + word(s.s, "]"); end(s); } ast::expr_struct(path, ref fields, wth) => { print_path(s, path, true); - word(s.s, ~"{"); + word(s.s, "{"); commasep_cmnt(s, consistent, (*fields), print_field, get_span); match wth { Some(expr) => { ibox(s, indent_unit); - word(s.s, ~","); + word(s.s, ","); space(s.s); - word(s.s, ~".."); + word(s.s, ".."); print_expr(s, expr); end(s); } - _ => (word(s.s, ~",")) + _ => (word(s.s, ",")) } - word(s.s, ~"}"); + word(s.s, "}"); } ast::expr_tup(ref exprs) => { popen(s); commasep_exprs(s, inconsistent, *exprs); if exprs.len() == 1 { - word(s.s, ~","); + word(s.s, ","); } pclose(s); } @@ -1157,31 +1164,31 @@ pub fn print_expr(s: @ps, expr: @ast::expr) { print_expr(s, func); print_call_post(s, sugar, &blk, &mut base_args); } - ast::expr_method_call(func, ident, ref tys, ref args, sugar) => { + ast::expr_method_call(_, func, ident, ref tys, ref args, sugar) => { let mut base_args = copy *args; let blk = print_call_pre(s, sugar, &mut base_args); print_expr(s, func); - word(s.s, ~"."); + word(s.s, "."); print_ident(s, ident); if tys.len() > 0u { - word(s.s, ~"::<"); + word(s.s, "::<"); commasep(s, inconsistent, *tys, print_type); - word(s.s, ~">"); + word(s.s, ">"); } print_call_post(s, sugar, &blk, &mut base_args); } - ast::expr_binary(op, lhs, rhs) => { + ast::expr_binary(_, op, lhs, rhs) => { print_expr(s, lhs); space(s.s); word_space(s, ast_util::binop_to_str(op)); print_expr(s, rhs); } - ast::expr_unary(op, expr) => { + ast::expr_unary(_, op, expr) => { word(s.s, ast_util::unop_to_str(op)); print_expr(s, expr); } ast::expr_addr_of(m, expr) => { - word(s.s, ~"&"); + word(s.s, "&"); print_mutability(s, m); // Avoid `& &e` => `&&e`. match (m, &expr.node) { @@ -1194,32 +1201,32 @@ pub fn print_expr(s: @ps, expr: @ast::expr) { ast::expr_cast(expr, ty) => { print_expr(s, expr); space(s.s); - word_space(s, ~"as"); + word_space(s, "as"); print_type(s, ty); } ast::expr_if(test, ref blk, elseopt) => { print_if(s, test, blk, elseopt, false); } ast::expr_while(test, ref blk) => { - head(s, ~"while"); + head(s, "while"); print_expr(s, test); space(s.s); print_block(s, blk); } ast::expr_loop(ref blk, opt_ident) => { for opt_ident.each |ident| { - word(s.s, ~"'"); + word(s.s, "'"); print_ident(s, *ident); - word_space(s, ~":"); + word_space(s, ":"); } - head(s, ~"loop"); + head(s, "loop"); space(s.s); print_block(s, blk); } ast::expr_match(expr, ref arms) => { cbox(s, indent_unit); ibox(s, 4); - word_nbsp(s, ~"match"); + word_nbsp(s, "match"); print_expr(s, expr); space(s.s); bopen(s); @@ -1232,19 +1239,19 @@ pub fn print_expr(s: @ps, expr: @ast::expr) { for arm.pats.each |p| { if first { first = false; - } else { space(s.s); word_space(s, ~"|"); } + } else { space(s.s); word_space(s, "|"); } print_refutable_pat(s, *p); } space(s.s); match arm.guard { Some(e) => { - word_space(s, ~"if"); + word_space(s, "if"); print_expr(s, e); space(s.s); } None => () } - word_space(s, ~"=>"); + word_space(s, "=>"); // Extract the expression from the extra block the parser adds // in the case of foo => expr @@ -1268,7 +1275,7 @@ pub fn print_expr(s: @ps, expr: @ast::expr) { } if !expr_is_simple_block(expr) && i < len - 1 { - word(s.s, ~","); + word(s.s, ","); } end(s); // close enclosing cbox } @@ -1321,97 +1328,97 @@ pub fn print_expr(s: @ps, expr: @ast::expr) { ibox(s, 0u); print_block(s, blk); } - ast::expr_copy(e) => { word_space(s, ~"copy"); print_expr(s, e); } + ast::expr_copy(e) => { word_space(s, "copy"); print_expr(s, e); } ast::expr_assign(lhs, rhs) => { print_expr(s, lhs); space(s.s); - word_space(s, ~"="); + word_space(s, "="); print_expr(s, rhs); } - ast::expr_assign_op(op, lhs, rhs) => { + ast::expr_assign_op(_, op, lhs, rhs) => { print_expr(s, lhs); space(s.s); word(s.s, ast_util::binop_to_str(op)); - word_space(s, ~"="); + word_space(s, "="); print_expr(s, rhs); } ast::expr_field(expr, id, ref tys) => { print_expr(s, expr); - word(s.s, ~"."); + word(s.s, "."); print_ident(s, id); if tys.len() > 0u { - word(s.s, ~"::<"); + word(s.s, "::<"); commasep(s, inconsistent, *tys, print_type); - word(s.s, ~">"); + word(s.s, ">"); } } - ast::expr_index(expr, index) => { + ast::expr_index(_, expr, index) => { print_expr(s, expr); - word(s.s, ~"["); + word(s.s, "["); print_expr(s, index); - word(s.s, ~"]"); + word(s.s, "]"); } ast::expr_path(path) => print_path(s, path, true), - ast::expr_self => word(s.s, ~"self"), + ast::expr_self => word(s.s, "self"), ast::expr_break(opt_ident) => { - word(s.s, ~"break"); + word(s.s, "break"); space(s.s); for opt_ident.each |ident| { - word(s.s, ~"'"); + word(s.s, "'"); print_ident(s, *ident); space(s.s); } } ast::expr_again(opt_ident) => { - word(s.s, ~"loop"); + word(s.s, "loop"); space(s.s); for opt_ident.each |ident| { - word(s.s, ~"'"); + word(s.s, "'"); print_ident(s, *ident); space(s.s) } } ast::expr_ret(result) => { - word(s.s, ~"return"); + word(s.s, "return"); match result { - Some(expr) => { word(s.s, ~" "); print_expr(s, expr); } + Some(expr) => { word(s.s, " "); print_expr(s, expr); } _ => () } } ast::expr_log(lexp, expr) => { - word(s.s, ~"__log"); + word(s.s, "__log"); popen(s); print_expr(s, lexp); - word(s.s, ~","); + word(s.s, ","); space_if_not_bol(s); print_expr(s, expr); pclose(s); } ast::expr_inline_asm(ref a) => { if a.volatile { - word(s.s, ~"__volatile__ asm!"); + word(s.s, "__volatile__ asm!"); } else { - word(s.s, ~"asm!"); + word(s.s, "asm!"); } popen(s); print_string(s, *a.asm); - word_space(s, ~":"); + word_space(s, ":"); for a.outputs.each |&(co, o)| { print_string(s, *co); popen(s); print_expr(s, o); pclose(s); - word_space(s, ~","); + word_space(s, ","); } - word_space(s, ~":"); + word_space(s, ":"); for a.inputs.each |&(co, o)| { print_string(s, *co); popen(s); print_expr(s, o); pclose(s); - word_space(s, ~","); + word_space(s, ","); } - word_space(s, ~":"); + word_space(s, ":"); print_string(s, *a.clobbers); pclose(s); } @@ -1430,22 +1437,20 @@ pub fn print_local_decl(s: @ps, loc: @ast::local) { print_irrefutable_pat(s, loc.node.pat); match loc.node.ty.node { ast::ty_infer => (), - _ => { word_space(s, ~":"); print_type(s, loc.node.ty); } + _ => { word_space(s, ":"); print_type(s, loc.node.ty); } } } pub fn print_decl(s: @ps, decl: @ast::decl) { maybe_print_comment(s, decl.span.lo); match decl.node { - ast::decl_local(ref locs) => { + ast::decl_local(ref loc) => { space_if_not_bol(s); ibox(s, indent_unit); - word_nbsp(s, ~"let"); + word_nbsp(s, "let"); - // if any are mut, all are mut - if locs.any(|l| l.node.is_mutbl) { - assert!(locs.all(|l| l.node.is_mutbl)); - word_nbsp(s, ~"mut"); + if loc.node.is_mutbl { + word_nbsp(s, "mut"); } fn print_local(s: @ps, loc: @ast::local) { @@ -1455,13 +1460,14 @@ pub fn print_decl(s: @ps, decl: @ast::decl) { match loc.node.init { Some(init) => { nbsp(s); - word_space(s, ~"="); + word_space(s, "="); print_expr(s, init); } _ => () } } - commasep(s, consistent, *locs, print_local); + + print_local(s, *loc); end(s); } ast::decl_item(item) => print_item(s, item) @@ -1469,40 +1475,40 @@ pub fn print_decl(s: @ps, decl: @ast::decl) { } pub fn print_ident(s: @ps, ident: ast::ident) { - word(s.s, *s.intr.get(ident)); + word(s.s, *ident_to_str(&ident)); } pub fn print_for_decl(s: @ps, loc: @ast::local, coll: @ast::expr) { print_local_decl(s, loc); space(s.s); - word_space(s, ~"in"); + word_space(s, "in"); print_expr(s, coll); } pub fn print_path(s: @ps, path: @ast::Path, colons_before_params: bool) { maybe_print_comment(s, path.span.lo); - if path.global { word(s.s, ~"::"); } + if path.global { word(s.s, "::"); } let mut first = true; for path.idents.each |id| { - if first { first = false; } else { word(s.s, ~"::"); } + if first { first = false; } else { word(s.s, "::"); } print_ident(s, *id); } if path.rp.is_some() || !path.types.is_empty() { - if colons_before_params { word(s.s, ~"::"); } + if colons_before_params { word(s.s, "::"); } if path.rp.is_some() || !path.types.is_empty() { - word(s.s, ~"<"); + word(s.s, "<"); for path.rp.each |r| { print_lifetime(s, *r); if !path.types.is_empty() { - word_space(s, ~","); + word_space(s, ","); } } commasep(s, inconsistent, path.types, print_type); - word(s.s, ~">"); + word(s.s, ">"); } } } @@ -1522,24 +1528,21 @@ pub fn print_pat(s: @ps, pat: @ast::pat, refutable: bool) { /* Pat isn't normalized, but the beauty of it is that it doesn't matter */ match pat.node { - ast::pat_wild => word(s.s, ~"_"), + ast::pat_wild => word(s.s, "_"), ast::pat_ident(binding_mode, path, sub) => { if refutable { match binding_mode { ast::bind_by_ref(mutbl) => { - word_nbsp(s, ~"ref"); + word_nbsp(s, "ref"); print_mutability(s, mutbl); } - ast::bind_by_copy => { - word_nbsp(s, ~"copy"); - } ast::bind_infer => {} } } print_path(s, path, true); match sub { Some(p) => { - word(s.s, ~"@"); + word(s.s, "@"); print_pat(s, p, refutable); } None => () @@ -1548,7 +1551,7 @@ pub fn print_pat(s: @ps, pat: @ast::pat, refutable: bool) { ast::pat_enum(path, ref args_) => { print_path(s, path, true); match *args_ { - None => word(s.s, ~"(*)"), + None => word(s.s, "(*)"), Some(ref args) => { if !args.is_empty() { popen(s); @@ -1561,11 +1564,11 @@ pub fn print_pat(s: @ps, pat: @ast::pat, refutable: bool) { } ast::pat_struct(path, ref fields, etc) => { print_path(s, path, true); - word(s.s, ~"{"); + word(s.s, "{"); fn print_field(s: @ps, f: ast::field_pat, refutable: bool) { cbox(s, indent_unit); print_ident(s, f.ident); - word_space(s, ~":"); + word_space(s, ":"); print_pat(s, f.pat, refutable); end(s); } @@ -1574,53 +1577,53 @@ pub fn print_pat(s: @ps, pat: @ast::pat, refutable: bool) { |s, f| print_field(s,f,refutable), get_span); if etc { - if fields.len() != 0u { word_space(s, ~","); } - word(s.s, ~"_"); + if fields.len() != 0u { word_space(s, ","); } + word(s.s, "_"); } - word(s.s, ~"}"); + word(s.s, "}"); } ast::pat_tup(ref elts) => { popen(s); commasep(s, inconsistent, *elts, |s, p| print_pat(s, p, refutable)); if elts.len() == 1 { - word(s.s, ~","); + word(s.s, ","); } pclose(s); } ast::pat_box(inner) => { - word(s.s, ~"@"); + word(s.s, "@"); print_pat(s, inner, refutable); } ast::pat_uniq(inner) => { - word(s.s, ~"~"); + word(s.s, "~"); print_pat(s, inner, refutable); } ast::pat_region(inner) => { - word(s.s, ~"&"); + word(s.s, "&"); print_pat(s, inner, refutable); } ast::pat_lit(e) => print_expr(s, e), ast::pat_range(begin, end) => { print_expr(s, begin); space(s.s); - word(s.s, ~".."); + word(s.s, ".."); print_expr(s, end); } ast::pat_vec(ref before, slice, ref after) => { - word(s.s, ~"["); + word(s.s, "["); do commasep(s, inconsistent, *before) |s, p| { print_pat(s, p, refutable); } for slice.each |&p| { - if !before.is_empty() { word_space(s, ~","); } - word(s.s, ~".."); + if !before.is_empty() { word_space(s, ","); } + word(s.s, ".."); print_pat(s, p, refutable); - if !after.is_empty() { word_space(s, ~","); } + if !after.is_empty() { word_space(s, ","); } } do commasep(s, inconsistent, *after) |s, p| { print_pat(s, p, refutable); } - word(s.s, ~"]"); + word(s.s, "]"); } } (s.ann.post)(ann_node); @@ -1634,18 +1637,18 @@ pub fn explicit_self_to_str(explicit_self: ast::explicit_self_, intr: @ident_int pub fn print_explicit_self(s: @ps, explicit_self: ast::explicit_self_) -> bool { match explicit_self { ast::sty_static => { return false; } - ast::sty_value => { word(s.s, ~"self"); } + ast::sty_value => { word(s.s, "self"); } ast::sty_region(lt, m) => { - word(s.s, ~"&"); + word(s.s, "&"); print_opt_lifetime(s, lt); print_mutability(s, m); - word(s.s, ~"self"); + word(s.s, "self"); } ast::sty_box(m) => { - word(s.s, ~"@"); print_mutability(s, m); word(s.s, ~"self"); + word(s.s, "@"); print_mutability(s, m); word(s.s, "self"); } ast::sty_uniq(m) => { - word(s.s, ~"~"); print_mutability(s, m); word(s.s, ~"self"); + word(s.s, "~"); print_mutability(s, m); word(s.s, "self"); } } return true; @@ -1659,7 +1662,7 @@ pub fn print_fn(s: @ps, generics: &ast::Generics, opt_explicit_self: Option, vis: ast::visibility) { - head(s, ~""); + head(s, ""); print_fn_header_info(s, opt_explicit_self, purity, abis, ast::Many, None, vis); nbsp(s); print_ident(s, name); @@ -1678,7 +1681,7 @@ pub fn print_fn_args(s: @ps, decl: &ast::fn_decl, } for decl.inputs.each |arg| { - if first { first = false; } else { word_space(s, ~","); } + if first { first = false; } else { word_space(s, ","); } print_arg(s, *arg); } @@ -1696,22 +1699,22 @@ pub fn print_fn_args_and_ret(s: @ps, decl: &ast::fn_decl, ast::ty_nil => {} _ => { space_if_not_bol(s); - word_space(s, ~"->"); + word_space(s, "->"); print_type(s, decl.output); } } } pub fn print_fn_block_args(s: @ps, decl: &ast::fn_decl) { - word(s.s, ~"|"); + word(s.s, "|"); print_fn_args(s, decl, None); - word(s.s, ~"|"); + word(s.s, "|"); match decl.output.node { ast::ty_infer => {} _ => { space_if_not_bol(s); - word_space(s, ~"->"); + word_space(s, "->"); print_type(s, decl.output); } } @@ -1721,33 +1724,33 @@ pub fn print_fn_block_args(s: @ps, decl: &ast::fn_decl) { pub fn print_bounds(s: @ps, bounds: @OptVec) { if !bounds.is_empty() { - word(s.s, ~":"); + word(s.s, ":"); let mut first = true; for bounds.each |bound| { nbsp(s); if first { first = false; } else { - word_space(s, ~"+"); + word_space(s, "+"); } match *bound { TraitTyParamBound(tref) => print_trait_ref(s, tref), - RegionTyParamBound => word(s.s, ~"'static"), + RegionTyParamBound => word(s.s, "'static"), } } } } pub fn print_lifetime(s: @ps, lifetime: &ast::Lifetime) { - word(s.s, ~"'"); + word(s.s, "'"); print_ident(s, lifetime.ident); } pub fn print_generics(s: @ps, generics: &ast::Generics) { let total = generics.lifetimes.len() + generics.ty_params.len(); if total > 0 { - word(s.s, ~"<"); + word(s.s, "<"); fn print_item(s: @ps, generics: &ast::Generics, idx: uint) { if idx < generics.lifetimes.len() { let lifetime = generics.lifetimes.get(idx); @@ -1767,7 +1770,7 @@ pub fn print_generics(s: @ps, generics: &ast::Generics) { commasep(s, inconsistent, ints, |s, i| print_item(s, generics, i)); - word(s.s, ~">"); + word(s.s, ">"); } } @@ -1777,7 +1780,7 @@ pub fn print_meta_item(s: @ps, item: @ast::meta_item) { ast::meta_word(name) => word(s.s, *name), ast::meta_name_value(name, value) => { word_space(s, *name); - word_space(s, ~"="); + word_space(s, "="); print_literal(s, @value); } ast::meta_list(name, ref items) => { @@ -1801,23 +1804,23 @@ pub fn print_view_path(s: @ps, vp: @ast::view_path) { if path.idents[path.idents.len()-1u] != ident { print_ident(s, ident); space(s.s); - word_space(s, ~"="); + word_space(s, "="); } print_path(s, path, false); } ast::view_path_glob(path, _) => { print_path(s, path, false); - word(s.s, ~"::*"); + word(s.s, "::*"); } ast::view_path_list(path, ref idents, _) => { print_path(s, path, false); - word(s.s, ~"::{"); + word(s.s, "::{"); do commasep(s, inconsistent, (*idents)) |s, w| { print_ident(s, w.node.name); } - word(s.s, ~"}"); + word(s.s, "}"); } } } @@ -1833,7 +1836,7 @@ pub fn print_view_item(s: @ps, item: @ast::view_item) { print_visibility(s, item.vis); match item.node { ast::view_item_extern_mod(id, ref mta, _) => { - head(s, ~"extern mod"); + head(s, "extern mod"); print_ident(s, id); if !mta.is_empty() { popen(s); @@ -1843,19 +1846,19 @@ pub fn print_view_item(s: @ps, item: @ast::view_item) { } ast::view_item_use(ref vps) => { - head(s, ~"use"); + head(s, "use"); print_view_paths(s, *vps); } } - word(s.s, ~";"); + word(s.s, ";"); end(s); // end inner head-block end(s); // end outer head-block } pub fn print_mutability(s: @ps, mutbl: ast::mutability) { match mutbl { - ast::m_mutbl => word_nbsp(s, ~"mut"), - ast::m_const => word_nbsp(s, ~"const"), + ast::m_mutbl => word_nbsp(s, "mut"), + ast::m_const => word_nbsp(s, "const"), ast::m_imm => {/* nothing */ } } } @@ -1868,7 +1871,7 @@ pub fn print_mt(s: @ps, mt: &ast::mt) { pub fn print_arg(s: @ps, input: ast::arg) { ibox(s, indent_unit); if input.is_mutbl { - word_space(s, ~"mut"); + word_space(s, "mut"); } match input.ty.node { ast::ty_infer => print_irrefutable_pat(s, input.pat), @@ -1881,7 +1884,7 @@ pub fn print_arg(s: @ps, input: ast::arg) { } _ => { print_irrefutable_pat(s, input.pat); - word(s.s, ~":"); + word(s.s, ":"); space(s.s); } } @@ -1910,8 +1913,8 @@ pub fn print_ty_fn(s: @ps, print_opt_lifetime(s, opt_region); print_purity(s, purity); print_onceness(s, onceness); - word(s.s, ~"fn"); - match id { Some(id) => { word(s.s, ~" "); print_ident(s, id); } _ => () } + word(s.s, "fn"); + match id { Some(id) => { word(s.s, " "); print_ident(s, id); } _ => () } match generics { Some(g) => print_generics(s, g), _ => () } zerobreak(s.s); @@ -1924,7 +1927,7 @@ pub fn print_ty_fn(s: @ps, first = !print_explicit_self(s, *explicit_self); } for decl.inputs.each |arg| { - if first { first = false; } else { word_space(s, ~","); } + if first { first = false; } else { word_space(s, ","); } print_arg(s, *arg); } end(s); @@ -1937,8 +1940,8 @@ pub fn print_ty_fn(s: @ps, _ => { space_if_not_bol(s); ibox(s, indent_unit); - word_space(s, ~"->"); - if decl.cf == ast::noreturn { word_nbsp(s, ~"!"); } + word_space(s, "->"); + if decl.cf == ast::noreturn { word_nbsp(s, "!"); } else { print_type(s, decl.output); } end(s); } @@ -1995,7 +1998,7 @@ pub fn print_literal(s: @ps, lit: @ast::lit) { match lit.node { ast::lit_str(st) => print_string(s, *st), ast::lit_int(ch, ast::ty_char) => { - word(s.s, ~"'" + char::escape_default(ch as char) + ~"'"); + word(s.s, ~"'" + char::escape_default(ch as char) + "'"); } ast::lit_int(i, t) => { if i < 0_i64 { @@ -2024,9 +2027,9 @@ pub fn print_literal(s: @ps, lit: @ast::lit) { word(s.s, *f + ast_util::float_ty_to_str(t)); } ast::lit_float_unsuffixed(f) => word(s.s, *f), - ast::lit_nil => word(s.s, ~"()"), + ast::lit_nil => word(s.s, "()"), ast::lit_bool(val) => { - if val { word(s.s, ~"true"); } else { word(s.s, ~"false"); } + if val { word(s.s, "true"); } else { word(s.s, "false"); } } } } @@ -2067,7 +2070,7 @@ pub fn maybe_print_comment(s: @ps, pos: BytePos) { pub fn print_comment(s: @ps, cmnt: &comments::cmnt) { match cmnt.style { comments::mixed => { - assert!(cmnt.lines.len() == 1u); + assert_eq!(cmnt.lines.len(), 1u); zerobreak(s.s); word(s.s, cmnt.lines[0]); zerobreak(s.s); @@ -2082,7 +2085,7 @@ pub fn print_comment(s: @ps, cmnt: &comments::cmnt) { } } comments::trailing => { - word(s.s, ~" "); + word(s.s, " "); if cmnt.lines.len() == 1u { word(s.s, cmnt.lines[0]); hardbreak(s.s); @@ -2109,9 +2112,9 @@ pub fn print_comment(s: @ps, cmnt: &comments::cmnt) { } pub fn print_string(s: @ps, st: &str) { - word(s.s, ~"\""); + word(s.s, "\""); word(s.s, str::escape_default(st)); - word(s.s, ~"\""); + word(s.s, "\""); } pub fn to_str(t: T, f: @fn(@ps, T), intr: @ident_interner) -> ~str { @@ -2146,7 +2149,7 @@ pub fn print_opt_purity(s: @ps, opt_purity: Option) { pub fn print_extern_opt_abis(s: @ps, opt_abis: Option) { match opt_abis { Some(abis) => { - word_nbsp(s, ~"extern"); + word_nbsp(s, "extern"); word_nbsp(s, abis.to_str()); } None => {} @@ -2155,9 +2158,9 @@ pub fn print_extern_opt_abis(s: @ps, opt_abis: Option) { pub fn print_opt_sigil(s: @ps, opt_sigil: Option) { match opt_sigil { - Some(ast::BorrowedSigil) => { word(s.s, ~"&"); } - Some(ast::OwnedSigil) => { word(s.s, ~"~"); } - Some(ast::ManagedSigil) => { word(s.s, ~"@"); } + Some(ast::BorrowedSigil) => { word(s.s, "&"); } + Some(ast::OwnedSigil) => { word(s.s, "~"); } + Some(ast::ManagedSigil) => { word(s.s, "@"); } None => {} }; } @@ -2169,10 +2172,10 @@ pub fn print_fn_header_info(s: @ps, onceness: ast::Onceness, opt_sigil: Option, vis: ast::visibility) { - word(s.s, visibility_qualified(vis, ~"")); + word(s.s, visibility_qualified(vis, "")); if abis != AbiSet::Rust() { - word_nbsp(s, ~"extern"); + word_nbsp(s, "extern"); word_nbsp(s, abis.to_str()); if opt_purity != Some(ast::extern_fn) { @@ -2183,7 +2186,7 @@ pub fn print_fn_header_info(s: @ps, } print_onceness(s, onceness); - word(s.s, ~"fn"); + word(s.s, "fn"); print_opt_sigil(s, opt_sigil); } @@ -2219,7 +2222,7 @@ pub fn print_purity(s: @ps, p: ast::purity) { pub fn print_onceness(s: @ps, o: ast::Onceness) { match o { - ast::Once => { word_nbsp(s, ~"once"); } + ast::Once => { word_nbsp(s, "once"); } ast::Many => {} } } @@ -2233,7 +2236,7 @@ mod test { use codemap; use core::cmp::Eq; use core::option::None; - use parse; + use parse::token; fn string_check (given : &T, expected: &T) { if !(given == expected) { @@ -2243,8 +2246,7 @@ mod test { #[test] fn test_fun_to_str() { - let mock_interner = parse::token::mk_fake_ident_interner(); - let abba_ident = mock_interner.intern("abba"); + let abba_ident = token::str_to_ident("abba"); let decl = ast::fn_decl { inputs: ~[], @@ -2255,14 +2257,13 @@ mod test { }; let generics = ast_util::empty_generics(); assert_eq!(&fun_to_str(&decl, ast::impure_fn, abba_ident, - None, &generics, mock_interner), + None, &generics, token::get_ident_interner()), &~"fn abba()"); } #[test] fn test_variant_to_str() { - let mock_interner = parse::token::mk_fake_ident_interner(); - let ident = mock_interner.intern("principal_skinner"); + let ident = token::str_to_ident("principal_skinner"); let var = codemap::respan(codemap::dummy_sp(), ast::variant_ { name: ident, @@ -2274,7 +2275,7 @@ mod test { vis: ast::public, }); - let varstr = variant_to_str(&var,mock_interner); + let varstr = variant_to_str(&var,token::get_ident_interner()); assert_eq!(&varstr,&~"pub principal_skinner"); } } diff --git a/src/libsyntax/syntax.rc b/src/libsyntax/syntax.rc index 565a8a18c6fad..78fbcab213c81 100644 --- a/src/libsyntax/syntax.rc +++ b/src/libsyntax/syntax.rc @@ -23,13 +23,30 @@ #[allow(non_camel_case_types)]; #[deny(deprecated_pattern)]; -extern mod std(vers = "0.7-pre"); +#[no_core]; +#[no_std]; + +extern mod core(name = "std"); +extern mod extra(name = "extra"); + +// For deriving(Encodable) purposes... +#[cfg(stage0)] +extern mod std(name = "extra"); +#[cfg(not(stage0))] +extern mod std(name = "std"); + +// For bootstrapping purposes. +#[cfg(stage0)] +pub use core::str; +#[cfg(stage0)] +pub use core::unstable; + +use core::prelude::*; -// allow the interner_key macro -// to escape this module: -#[macro_escape] pub mod util { pub mod interner; + #[cfg(test)] + pub mod parser_testing; } pub mod syntax { diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs index cca2ec89fd421..b55050184fedc 100644 --- a/src/libsyntax/util/interner.rs +++ b/src/libsyntax/util/interner.rs @@ -15,6 +15,8 @@ // allow the interner_key macro to escape this module: #[macro_escape]; +use core::prelude::*; + use core::cmp::Equiv; use core::hashmap::HashMap; use syntax::parse::token::StringRef; @@ -25,21 +27,21 @@ pub struct Interner { } // when traits can extend traits, we should extend index to get [] -pub impl Interner { - fn new() -> Interner { +impl Interner { + pub fn new() -> Interner { Interner { map: @mut HashMap::new(), vect: @mut ~[], } } - fn prefill(init: &[T]) -> Interner { + pub fn prefill(init: &[T]) -> Interner { let rv = Interner::new(); for init.each() |v| { rv.intern(*v); } rv } - fn intern(&self, val: T) -> uint { + pub fn intern(&self, val: T) -> uint { match self.map.find(&val) { Some(&idx) => return idx, None => (), @@ -52,7 +54,7 @@ pub impl Interner { new_idx } - fn gensym(&self, val: T) -> uint { + pub fn gensym(&self, val: T) -> uint { let new_idx = { let vect = &*self.vect; vect.len() @@ -62,14 +64,11 @@ pub impl Interner { new_idx } - // this isn't "pure" in the traditional sense, because it can go from - // failing to returning a value as items are interned. But for typestate, - // where we first check a pred and then rely on it, ceasing to fail is ok. - fn get(&self, idx: uint) -> T { self.vect[idx] } + pub fn get(&self, idx: uint) -> T { self.vect[idx] } - fn len(&self) -> uint { let vect = &*self.vect; vect.len() } + pub fn len(&self) -> uint { let vect = &*self.vect; vect.len() } - fn find_equiv>(&self, val: &Q) + pub fn find_equiv>(&self, val: &Q) -> Option { match self.map.find_equiv(val) { Some(v) => Some(*v), @@ -78,27 +77,29 @@ pub impl Interner { } } +// A StrInterner differs from Interner in that it accepts +// borrowed pointers rather than @ ones, resulting in less allocation. pub struct StrInterner { priv map: @mut HashMap<@~str, uint>, priv vect: @mut ~[@~str], } // when traits can extend traits, we should extend index to get [] -pub impl StrInterner { - fn new() -> StrInterner { +impl StrInterner { + pub fn new() -> StrInterner { StrInterner { map: @mut HashMap::new(), vect: @mut ~[], } } - fn prefill(init: &[&str]) -> StrInterner { + pub fn prefill(init: &[&str]) -> StrInterner { let rv = StrInterner::new(); for init.each() |v| { rv.intern(*v); } rv } - fn intern(&self, val: &str) -> uint { + pub fn intern(&self, val: &str) -> uint { match self.map.find_equiv(&StringRef(val)) { Some(&idx) => return idx, None => (), @@ -110,7 +111,7 @@ pub impl StrInterner { new_idx } - fn gensym(&self, val: &str) -> uint { + pub fn gensym(&self, val: &str) -> uint { let new_idx = self.len(); // leave out of .map to avoid colliding self.vect.push(@val.to_owned()); @@ -120,12 +121,12 @@ pub impl StrInterner { // this isn't "pure" in the traditional sense, because it can go from // failing to returning a value as items are interned. But for typestate, // where we first check a pred and then rely on it, ceasing to fail is ok. - fn get(&self, idx: uint) -> @~str { self.vect[idx] } + pub fn get(&self, idx: uint) -> @~str { self.vect[idx] } - fn len(&self) -> uint { let vect = &*self.vect; vect.len() } + pub fn len(&self) -> uint { let vect = &*self.vect; vect.len() } - fn find_equiv>(&self, val: &Q) - -> Option { + pub fn find_equiv>(&self, val: &Q) + -> Option { match self.map.find_equiv(val) { Some(v) => Some(*v), None => None, @@ -133,17 +134,6 @@ pub impl StrInterner { } } -/* Key for thread-local data for sneaking interner information to the -* encoder/decoder. It sounds like a hack because it is one. -* Bonus ultra-hack: functions as keys don't work across crates, -* so we have to use a unique number. See taskgroup_key! in task.rs -* for another case of this. */ -macro_rules! interner_key ( - () => (cast::transmute::<(uint, uint), - &fn(v: @@::parse::token::ident_interner)>( - (-3 as uint, 0u))) -) - #[cfg(test)] mod tests { use super::*; diff --git a/src/libsyntax/util/parser_testing.rs b/src/libsyntax/util/parser_testing.rs new file mode 100644 index 0000000000000..c5528069926f0 --- /dev/null +++ b/src/libsyntax/util/parser_testing.rs @@ -0,0 +1,71 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::option::{Option,None}; +use ast; +use parse::{new_parse_sess}; +use parse::{ParseSess,string_to_filemap,filemap_to_tts}; +use parse::{new_parser_from_source_str}; +use parse::parser::Parser; +use parse::token; + +// map a string to tts, using a made-up filename: return both the token_trees +// and the ParseSess +pub fn string_to_tts_and_sess (source_str : @~str) -> (~[ast::token_tree],@mut ParseSess) { + let ps = new_parse_sess(None); + (filemap_to_tts(ps,string_to_filemap(ps,source_str,~"bogofile")),ps) +} + +pub fn string_to_parser_and_sess(source_str: @~str) -> (Parser,@mut ParseSess) { + let ps = new_parse_sess(None); + (new_parser_from_source_str(ps,~[],~"bogofile",source_str),ps) +} + +// map string to parser (via tts) +pub fn string_to_parser(source_str: @~str) -> Parser { + let (p,_) = string_to_parser_and_sess(source_str); + p +} + +pub fn string_to_crate (source_str : @~str) -> @ast::crate { + string_to_parser(source_str).parse_crate_mod() +} + +// parse a string, return an expr +pub fn string_to_expr (source_str : @~str) -> @ast::expr { + string_to_parser(source_str).parse_expr() +} + +// parse a string, return an item +pub fn string_to_item (source_str : @~str) -> Option<@ast::item> { + string_to_parser(source_str).parse_item(~[]) +} + +// parse a string, return an item and the ParseSess +pub fn string_to_item_and_sess (source_str : @~str) -> (Option<@ast::item>,@mut ParseSess) { + let (p,ps) = string_to_parser_and_sess(source_str); + (p.parse_item(~[]),ps) +} + +// parse a string, return a stmt +pub fn string_to_stmt(source_str : @~str) -> @ast::stmt { + string_to_parser(source_str).parse_stmt(~[]) +} + +// parse a string, return a pat. Uses "irrefutable"... which doesn't +// (currently) affect parsing. +pub fn string_to_pat(source_str : @~str) -> @ast::pat { + string_to_parser(source_str).parse_pat() +} + +// convert a vector of strings to a vector of ast::idents +pub fn strs_to_idents(ids: ~[&str]) -> ~[ast::ident] { + ids.map(|u| token::str_to_ident(*u)) +} diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 4cfd54256f82e..bf75efb805f24 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use abi::AbiSet; use ast::*; use ast; @@ -428,11 +430,7 @@ pub fn visit_stmt(s: @stmt, e: E, v: vt) { pub fn visit_decl(d: @decl, e: E, v: vt) { match d.node { - decl_local(ref locs) => { - for locs.each |loc| { - (v.visit_local)(*loc, e, v) - } - }, + decl_local(ref loc) => (v.visit_local)(*loc, e, v), decl_item(it) => (v.visit_item)(it, e, v) } } @@ -469,16 +467,16 @@ pub fn visit_expr(ex: @expr, e: E, v: vt) { visit_exprs(*args, e, v); (v.visit_expr)(callee, e, v); } - expr_method_call(callee, _, ref tys, ref args, _) => { + expr_method_call(_, callee, _, ref tys, ref args, _) => { visit_exprs(*args, e, v); for tys.each |tp| { (v.visit_ty)(*tp, e, v); } (v.visit_expr)(callee, e, v); } - expr_binary(_, a, b) => { + expr_binary(_, _, a, b) => { (v.visit_expr)(a, e, v); (v.visit_expr)(b, e, v); } - expr_addr_of(_, x) | expr_unary(_, x) | + expr_addr_of(_, x) | expr_unary(_, _, x) | expr_loop_body(x) | expr_do_body(x) => (v.visit_expr)(x, e, v), expr_lit(_) => (), expr_cast(x, t) => { @@ -516,7 +514,7 @@ pub fn visit_expr(ex: @expr, e: E, v: vt) { (v.visit_expr)(a, e, v); } expr_copy(a) => (v.visit_expr)(a, e, v), - expr_assign_op(_, a, b) => { + expr_assign_op(_, _, a, b) => { (v.visit_expr)(b, e, v); (v.visit_expr)(a, e, v); } @@ -524,7 +522,7 @@ pub fn visit_expr(ex: @expr, e: E, v: vt) { (v.visit_expr)(x, e, v); for tys.each |tp| { (v.visit_ty)(*tp, e, v); } } - expr_index(a, b) => { + expr_index(_, a, b) => { (v.visit_expr)(a, e, v); (v.visit_expr)(b, e, v); } diff --git a/src/rt/arch/arm/context.cpp b/src/rt/arch/arm/context.cpp index 2c735e410fa4a..7d90668aad53a 100644 --- a/src/rt/arch/arm/context.cpp +++ b/src/rt/arch/arm/context.cpp @@ -26,9 +26,11 @@ void context::call(void *f, void *arg, void *stack) // set up the stack uint32_t *sp = ( uint32_t *)stack; - //sp = align_down(sp); + sp = align_down(sp); // The final return address. 0 indicates the bottom of the stack - *--sp = 0; + // sp of arm eabi is 8-byte aligned + sp -= 2; + *sp = 0; regs.data[0] = ( uint32_t )arg; // r0 regs.data[13] = ( uint32_t )sp; //#52 sp, r13 diff --git a/src/rt/arch/arm/record_sp.S b/src/rt/arch/arm/record_sp.S index 95fce8746a118..8d5f24bc5a8c5 100644 --- a/src/rt/arch/arm/record_sp.S +++ b/src/rt/arch/arm/record_sp.S @@ -15,13 +15,21 @@ record_sp_limit: mrc p15, #0, r3, c13, c0, #3 +#if __ANDROID__ add r3, r3, #252 +#elif __linux__ + add r3, r3, #4 +#endif str r0, [r3] mov pc, lr get_sp_limit: mrc p15, #0, r3, c13, c0, #3 +#if __ANDROID__ add r3, r3, #252 +#elif __linux__ + add r3, r3, #4 +#endif ldr r0, [r3] mov pc, lr diff --git a/src/rt/arch/mips/context.cpp b/src/rt/arch/mips/context.cpp index 7347a92e98b92..e1e5776bc1a65 100644 --- a/src/rt/arch/mips/context.cpp +++ b/src/rt/arch/mips/context.cpp @@ -34,9 +34,11 @@ void context::call(void *f, void *arg, void *stack) // set up the stack uint32_t *sp = (uint32_t *)stack; - //sp = align_down(sp); + sp = align_down(sp); // The final return address. 0 indicates the bottom of the stack - *--sp = 0; + // sp of mips o32 is 8-byte aligned + sp -= 2; + *sp = 0; regs.data[4] = (uint32_t)arg; regs.data[29] = (uint32_t)sp; diff --git a/src/rt/linenoise/linenoise.c b/src/rt/linenoise/linenoise.c index 5e3216e4591d7..0ce4d559bed99 100644 --- a/src/rt/linenoise/linenoise.c +++ b/src/rt/linenoise/linenoise.c @@ -150,6 +150,9 @@ enum { SPECIAL_DELETE = -24, SPECIAL_HOME = -25, SPECIAL_END = -26, + SPECIAL_INSERT = -27, + SPECIAL_PAGE_UP = -28, + SPECIAL_PAGE_DOWN = -29 }; static int history_max_len = LINENOISE_DEFAULT_HISTORY_MAX_LEN; @@ -165,6 +168,7 @@ struct current { int pos; /* Cursor position, measured in chars */ int cols; /* Size of the window, in chars */ const char *prompt; + char *capture; /* Allocated capture buffer, or NULL for none. Always null terminated */ #if defined(USE_TERMIOS) int fd; /* Terminal fd */ #elif defined(USE_WINCONSOLE) @@ -187,6 +191,7 @@ void linenoiseHistoryFree(void) { free(history[j]); free(history); history = NULL; + history_len = 0; } } @@ -268,7 +273,10 @@ static void linenoiseAtExit(void) { linenoiseHistoryFree(); } -/* gcc/glibc insists that we care about the return code of write! */ +/* gcc/glibc insists that we care about the return code of write! + * Clarification: This means that a void-cast like "(void) (EXPR)" + * does not work. + */ #define IGNORE_RC(EXPR) if (EXPR) {} /* This is fdprintf() on some systems, but use a different @@ -374,6 +382,70 @@ static int fd_read(struct current *current) #endif } +static int countColorControlChars(const char* prompt, int plen) +{ + /* ANSI color control sequences have the form: + * "\x1b" "[" [0-9;]+ "m" + * We parse them with a simple state machine. + */ + + enum { + search_esc, + expect_bracket, + expect_inner, + expect_trail + } state = search_esc; + int len = 0, found = 0; + char ch; + + /* XXX: Strictly we should be checking utf8 chars rather than + * bytes in case of the extremely unlikely scenario where + * an ANSI sequence is part of a utf8 sequence. + */ + for (; plen ; plen--, prompt++) { + ch = *prompt; + + switch (state) { + case search_esc: + len = 0; + if (ch == '\x1b') { + state = expect_bracket; + len++; + } + break; + case expect_bracket: + if (ch == '[') { + state = expect_inner; + len++; + } else { + state = search_esc; + } + break; + case expect_inner: + if (ch >= '0' && ch <= '9') { + len++; + state = expect_trail; + } else { + state = search_esc; + } + break; + case expect_trail: + if (ch == 'm') { + len++; + found += len; + state = search_esc; + } else if ((ch != ';') && ((ch < '0') || (ch > '9'))) { + state = search_esc; + } + /* 0-9, or semicolon */ + len++; + break; + } + } + + return found; +} + static int getWindowSize(struct current *current) { struct winsize ws; @@ -467,8 +539,14 @@ static int check_special(int fd) c = fd_read_char(fd, 50); if (c == '~') { switch (c2) { + case '2': + return SPECIAL_INSERT; case '3': return SPECIAL_DELETE; + case '5': + return SPECIAL_PAGE_UP; + case '6': + return SPECIAL_PAGE_DOWN; case '7': return SPECIAL_HOME; case '8': @@ -538,7 +616,7 @@ static int outputChars(struct current *current, const char *buf, int len) { COORD pos = { (SHORT)current->x, (SHORT)current->y }; DWORD n; - + WriteConsoleOutputCharacter(current->outh, buf, len, pos, &n); current->x += len; return 0; @@ -593,12 +671,18 @@ static int fd_read(struct current *current) return SPECIAL_UP; case VK_DOWN: return SPECIAL_DOWN; + case VK_INSERT: + return SPECIAL_INSERT; case VK_DELETE: return SPECIAL_DELETE; case VK_HOME: return SPECIAL_HOME; case VK_END: return SPECIAL_END; + case VK_PRIOR: + return SPECIAL_PAGE_UP; + case VK_NEXT: + return SPECIAL_PAGE_DOWN; } } /* Note that control characters are already translated in AsciiChar */ @@ -614,6 +698,14 @@ static int fd_read(struct current *current) return -1; } +static int countColorControlChars(const char* prompt, int plen) +{ + /* For windows we assume that there are no embedded ansi color + * control sequences. + */ + return 0; +} + static int getWindowSize(struct current *current) { CONSOLE_SCREEN_BUFFER_INFO info; @@ -676,6 +768,11 @@ static void refreshLine(const char *prompt, struct current *current) plen = strlen(prompt); pchars = utf8_strlen(prompt, plen); + /* Scan the prompt for embedded ansi color control sequences and + * discount them as characters/columns. + */ + pchars -= countColorControlChars(prompt, plen); + /* Account for a line which is too long to fit in the window. * Note that control chars require an extra column */ @@ -692,7 +789,7 @@ static void refreshLine(const char *prompt, struct current *current) } } - /* If too many are need, strip chars off the front of 'buf' + /* If too many are needed, strip chars off the front of 'buf' * until it fits. Note that if the current char is a control character, * we need one extra col. */ @@ -843,16 +940,64 @@ static int insert_char(struct current *current, int pos, int ch) } /** + * Captures up to 'n' characters starting at 'pos' for the cut buffer. + * + * This replaces any existing characters in the cut buffer. + */ +static void capture_chars(struct current *current, int pos, int n) +{ + if (pos >= 0 && (pos + n - 1) < current->chars) { + int p1 = utf8_index(current->buf, pos); + int nbytes = utf8_index(current->buf + p1, n); + + if (nbytes) { + free(current->capture); + /* Include space for the null terminator */ + current->capture = (char *)malloc(nbytes + 1); + memcpy(current->capture, current->buf + p1, nbytes); + current->capture[nbytes] = '\0'; + } + } +} + +/** + * Removes up to 'n' characters at cursor position 'pos'. + * * Returns 0 if no chars were removed or non-zero otherwise. */ static int remove_chars(struct current *current, int pos, int n) { int removed = 0; + + /* First save any chars which will be removed */ + capture_chars(current, pos, n); + while (n-- && remove_char(current, pos)) { removed++; } return removed; } +/** + * Inserts the characters (string) 'chars' at the cursor position 'pos'. + * + * Returns 0 if no chars were inserted or non-zero otherwise. + */ +static int insert_chars(struct current *current, int pos, const char *chars) +{ + int inserted = 0; + + while (*chars) { + int ch; + int n = utf8_tounicode(chars, &ch); + if (insert_char(current, pos, ch) == 0) { + break; + } + inserted++; + pos++; + chars += n; + } + return inserted; +} #ifndef NO_COMPLETION static linenoiseCompletionCallback *completionCallback = NULL; @@ -937,7 +1082,7 @@ void linenoiseAddCompletion(linenoiseCompletions *lc, const char *str) { #endif -static int linenoisePrompt(struct current *current) { +static int linenoiseEdit(struct current *current) { int history_index = 0; /* The latest history entry is always our current buffer, that @@ -998,7 +1143,12 @@ static int linenoisePrompt(struct current *current) { refreshLine(current->prompt, current); } break; - case ctrl('W'): /* ctrl-w */ + case SPECIAL_INSERT: + /* Ignore. Expansion Hook. + * Future possibility: Toggle Insert/Overwrite Modes + */ + break; + case ctrl('W'): /* ctrl-w, delete word at left. save deleted chars */ /* eat any spaces on the left */ { int pos = current->pos; @@ -1118,9 +1268,11 @@ static int linenoisePrompt(struct current *current) { } break; case ctrl('T'): /* ctrl-t */ - if (current->pos > 0 && current->pos < current->chars) { - c = get_char(current, current->pos); - remove_char(current, current->pos); + if (current->pos > 0 && current->pos <= current->chars) { + /* If cursor is at end, transpose the previous two chars */ + int fixer = (current->pos == current->chars); + c = get_char(current, current->pos - fixer); + remove_char(current, current->pos - fixer); insert_char(current, current->pos - 1, c); refreshLine(current->prompt, current); } @@ -1157,26 +1309,34 @@ static int linenoisePrompt(struct current *current) { refreshLine(current->prompt, current); } break; + case SPECIAL_PAGE_UP: + dir = history_len - history_index - 1; /* move to start of history */ + goto history_navigation; + case SPECIAL_PAGE_DOWN: + dir = -history_index; /* move to 0 == end of history, i.e. current */ + goto history_navigation; case ctrl('P'): case SPECIAL_UP: dir = 1; + goto history_navigation; case ctrl('N'): case SPECIAL_DOWN: +history_navigation: if (history_len > 1) { /* Update the current history entry before to * overwrite it with tne next one. */ - free(history[history_len-1-history_index]); - history[history_len-1-history_index] = strdup(current->buf); + free(history[history_len - 1 - history_index]); + history[history_len - 1 - history_index] = strdup(current->buf); /* Show the new entry */ history_index += dir; if (history_index < 0) { history_index = 0; break; } else if (history_index >= history_len) { - history_index = history_len-1; + history_index = history_len - 1; break; } - set_current(current, history[history_len-1-history_index]); + set_current(current, history[history_len - 1 - history_index]); refreshLine(current->prompt, current); } break; @@ -1190,16 +1350,21 @@ static int linenoisePrompt(struct current *current) { current->pos = current->chars; refreshLine(current->prompt, current); break; - case ctrl('U'): /* Ctrl+u, delete to beginning of line. */ + case ctrl('U'): /* Ctrl+u, delete to beginning of line, save deleted chars. */ if (remove_chars(current, 0, current->pos)) { refreshLine(current->prompt, current); } break; - case ctrl('K'): /* Ctrl+k, delete from current to end of line. */ + case ctrl('K'): /* Ctrl+k, delete from current to end of line, save deleted chars. */ if (remove_chars(current, current->pos, current->chars - current->pos)) { refreshLine(current->prompt, current); } break; + case ctrl('Y'): /* Ctrl+y, insert saved chars at current position */ + if (current->capture && insert_chars(current, current->pos, current->capture)) { + refreshLine(current->prompt, current); + } + break; case ctrl('L'): /* Ctrl+L, clear screen */ clearScreen(current); /* Force recalc of window size for serial terminals */ @@ -1219,6 +1384,15 @@ static int linenoisePrompt(struct current *current) { return current->len; } +int linenoiseColumns(void) +{ + struct current current; + enableRawMode (¤t); + getWindowSize (¤t); + disableRawMode (¤t); + return current.cols; +} + char *linenoise(const char *prompt) { int count; @@ -1226,10 +1400,10 @@ char *linenoise(const char *prompt) char buf[LINENOISE_MAX_LINE]; if (enableRawMode(¤t) == -1) { - printf("%s", prompt); + printf("%s", prompt); fflush(stdout); if (fgets(buf, sizeof(buf), stdin) == NULL) { - return NULL; + return NULL; } count = strlen(buf); if (count && buf[count-1] == '\n') { @@ -1245,10 +1419,14 @@ char *linenoise(const char *prompt) current.chars = 0; current.pos = 0; current.prompt = prompt; + current.capture = NULL; + + count = linenoiseEdit(¤t); - count = linenoisePrompt(¤t); disableRawMode(¤t); printf("\n"); + + free(current.capture); if (count == -1) { return NULL; } @@ -1284,6 +1462,10 @@ int linenoiseHistoryAdd(const char *line) { return 1; } +int linenoiseHistoryGetMaxLen(void) { + return history_max_len; +} + int linenoiseHistorySetMaxLen(int len) { char **newHistory; @@ -1293,8 +1475,16 @@ int linenoiseHistorySetMaxLen(int len) { newHistory = (char **)malloc(sizeof(char*)*len); if (newHistory == NULL) return 0; - if (len < tocopy) tocopy = len; - memcpy(newHistory,history+(history_max_len-tocopy), sizeof(char*)*tocopy); + + /* If we can't copy everything, free the elements we'll not use. */ + if (len < tocopy) { + int j; + + for (j = 0; j < tocopy-len; j++) free(history[j]); + tocopy = len; + } + memset(newHistory,0,sizeof(char*)*len); + memcpy(newHistory,history+(history_len-tocopy), sizeof(char*)*tocopy); free(history); history = newHistory; } diff --git a/src/rt/linenoise/linenoise.h b/src/rt/linenoise/linenoise.h index 59f28976d67e5..7ebf244ee80e7 100644 --- a/src/rt/linenoise/linenoise.h +++ b/src/rt/linenoise/linenoise.h @@ -51,9 +51,11 @@ void linenoiseAddCompletion(linenoiseCompletions *, const char *); char *linenoise(const char *prompt); int linenoiseHistoryAdd(const char *line); int linenoiseHistorySetMaxLen(int len); +int linenoiseHistoryGetMaxLen(void); int linenoiseHistorySave(const char *filename); int linenoiseHistoryLoad(const char *filename); void linenoiseHistoryFree(void); char **linenoiseHistory(int *len); +int linenoiseColumns(void); #endif /* __LINENOISE_H */ diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index 903289281222b..5e7357c9b7b25 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -459,18 +459,18 @@ rust_localtime(int64_t sec, int32_t nsec, rust_tm *timeptr) { tm_to_rust_tm(&tm, timeptr, gmtoff, zone, nsec); } -extern "C" CDECL void -rust_timegm(rust_tm* timeptr, int64_t *out) { +extern "C" CDECL int64_t +rust_timegm(rust_tm* timeptr) { tm t; rust_tm_to_tm(timeptr, &t); - *out = TIMEGM(&t); + return TIMEGM(&t); } -extern "C" CDECL void -rust_mktime(rust_tm* timeptr, int64_t *out) { +extern "C" CDECL int64_t +rust_mktime(rust_tm* timeptr) { tm t; rust_tm_to_tm(timeptr, &t); - *out = mktime(&t); + return mktime(&t); } extern "C" CDECL rust_sched_id @@ -731,10 +731,17 @@ rust_task_deref(rust_task *task) { // Must call on rust stack. extern "C" CDECL void rust_call_tydesc_glue(void *root, size_t *tydesc, size_t glue_index) { +#ifdef _RUST_STAGE0 void (*glue_fn)(void *, void *, void *, void *) = (void (*)(void *, void *, void *, void *))tydesc[glue_index]; if (glue_fn) glue_fn(0, 0, 0, root); +#else + void (*glue_fn)(void *, void *, void *) = + (void (*)(void *, void *, void *))tydesc[glue_index]; + if (glue_fn) + glue_fn(0, 0, root); +#endif } // Don't run on the Rust stack! @@ -754,7 +761,11 @@ class raw_thread: public rust_thread { virtual void run() { record_sp_limit(0); +#ifdef _RUST_STAGE0 fn.f(NULL, fn.env, NULL); +#else + fn.f(fn.env, NULL); +#endif } }; @@ -830,19 +841,19 @@ rust_get_rt_env() { } #ifndef _WIN32 -pthread_key_t sched_key; +pthread_key_t rt_key = -1; #else -DWORD sched_key; +DWORD rt_key = -1; #endif extern "C" void* -rust_get_sched_tls_key() { - return &sched_key; +rust_get_rt_tls_key() { + return &rt_key; } -// Initialize the global state required by the new scheduler +// Initialize the TLS key used by the new scheduler extern "C" CDECL void -rust_initialize_global_state() { +rust_initialize_rt_tls_key() { static lock_and_signal init_lock; static bool initialized = false; @@ -852,10 +863,10 @@ rust_initialize_global_state() { if (!initialized) { #ifndef _WIN32 - assert(!pthread_key_create(&sched_key, NULL)); + assert(!pthread_key_create(&rt_key, NULL)); #else - sched_key = TlsAlloc(); - assert(sched_key != TLS_OUT_OF_INDEXES); + rt_key = TlsAlloc(); + assert(rt_key != TLS_OUT_OF_INDEXES); #endif initialized = true; diff --git a/src/rt/rust_env.cpp b/src/rt/rust_env.cpp index 360d611492853..ed38be3550f74 100644 --- a/src/rt/rust_env.cpp +++ b/src/rt/rust_env.cpp @@ -13,6 +13,7 @@ // that might come from the environment is loaded here, once, during // init. +#include "sync/lock_and_signal.h" #include "rust_env.h" // The environment variables that the runtime knows about @@ -26,6 +27,18 @@ #define RUST_DEBUG_MEM "RUST_DEBUG_MEM" #define RUST_DEBUG_BORROW "RUST_DEBUG_BORROW" +static lock_and_signal env_lock; + +extern "C" CDECL void +rust_take_env_lock() { + env_lock.lock(); +} + +extern "C" CDECL void +rust_drop_env_lock() { + env_lock.unlock(); +} + #if defined(__WIN32__) static int get_num_cpus() { @@ -119,6 +132,8 @@ copyenv(const char* name) { rust_env* load_env(int argc, char **argv) { + scoped_lock with(env_lock); + rust_env *env = (rust_env*)malloc(sizeof(rust_env)); env->num_sched_threads = (size_t)get_num_threads(); @@ -141,3 +156,4 @@ free_env(rust_env *env) { free(env->rust_seed); free(env); } + diff --git a/src/rt/rust_exchange_alloc.cpp b/src/rt/rust_exchange_alloc.cpp index 5958c68f3e7d1..89257dc9f6e43 100644 --- a/src/rt/rust_exchange_alloc.cpp +++ b/src/rt/rust_exchange_alloc.cpp @@ -15,14 +15,15 @@ #include #include -uintptr_t exchange_count = 0; +extern uintptr_t rust_exchange_count; +uintptr_t rust_exchange_count = 0; void * rust_exchange_alloc::malloc(size_t size) { void *value = ::malloc(size); assert(value); - sync::increment(exchange_count); + sync::increment(rust_exchange_count); return value; } @@ -36,20 +37,15 @@ rust_exchange_alloc::realloc(void *ptr, size_t size) { void rust_exchange_alloc::free(void *ptr) { - sync::decrement(exchange_count); + sync::decrement(rust_exchange_count); ::free(ptr); } -extern "C" uintptr_t * -rust_get_exchange_count_ptr() { - return &exchange_count; -} - void rust_check_exchange_count_on_exit() { - if (exchange_count != 0) { + if (rust_exchange_count != 0) { printf("exchange heap not empty on exit\n"); - printf("%d dangling allocations\n", (int)exchange_count); + printf("%d dangling allocations\n", (int)rust_exchange_count); abort(); } } diff --git a/src/rt/rust_log.cpp b/src/rt/rust_log.cpp index c2b58c9fda732..df24f569495b4 100644 --- a/src/rt/rust_log.cpp +++ b/src/rt/rust_log.cpp @@ -324,6 +324,10 @@ void update_log_settings(void* crate_map, char* settings) { free(buffer); } +extern "C" CDECL void +rust_update_log_settings(void* crate_map, char* settings) { + update_log_settings(crate_map, settings); +} // // Local Variables: diff --git a/src/rt/rust_stack.cpp b/src/rt/rust_stack.cpp index f07690a955ea2..a609ac573245d 100644 --- a/src/rt/rust_stack.cpp +++ b/src/rt/rust_stack.cpp @@ -92,3 +92,14 @@ destroy_exchange_stack(rust_exchange_alloc *exchange, stk_seg *stk) { deregister_valgrind_stack(stk); exchange->free(stk); } + + +extern "C" CDECL unsigned int +rust_valgrind_stack_register(void *start, void *end) { + return VALGRIND_STACK_REGISTER(start, end); +} + +extern "C" CDECL void +rust_valgrind_stack_deregister(unsigned int id) { + VALGRIND_STACK_DEREGISTER(id); +} diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp index 266c0652c6e59..b5ecb1661755a 100644 --- a/src/rt/rust_task.cpp +++ b/src/rt/rust_task.cpp @@ -162,9 +162,11 @@ void task_start_wrapper(spawn_args *a) bool threw_exception = false; try { - // The first argument is the return pointer; as the task fn - // must have void return type, we can safely pass 0. - a->f(0, a->envptr, a->argptr); +#ifdef _RUST_STAGE0 + a->f(NULL, a->envptr, a->argptr); +#else + a->f(a->envptr, a->argptr); +#endif } catch (rust_task *ex) { assert(ex == task && "Expected this task to be thrown for unwinding"); threw_exception = true; @@ -185,7 +187,11 @@ void task_start_wrapper(spawn_args *a) if(env) { // free the environment (which should be a unique closure). const type_desc *td = env->td; +#ifdef _RUST_STAGE0 td->drop_glue(NULL, NULL, NULL, box_body(env)); +#else + td->drop_glue(NULL, NULL, box_body(env)); +#endif task->kernel->region()->free(env); } diff --git a/src/rt/rust_task.h b/src/rt/rust_task.h index 672af608db863..213aee6a9ebcc 100644 --- a/src/rt/rust_task.h +++ b/src/rt/rust_task.h @@ -146,6 +146,9 @@ #ifdef __mips__ #define RED_ZONE_SIZE RZ_MAC_32 #endif +#ifdef __arm__ +#define RED_ZONE_SIZE RZ_LINUX_32 +#endif #endif #ifdef __APPLE__ #ifdef __i386__ diff --git a/src/rt/rust_type.h b/src/rt/rust_type.h index ece0d48c3ae44..b50c08379de7f 100644 --- a/src/rt/rust_type.h +++ b/src/rt/rust_type.h @@ -21,11 +21,19 @@ struct rust_opaque_box; // - the main function: has a NULL environment, but uses the void* arg // - unique closures of type fn~(): have a non-NULL environment, but // no arguments (and hence the final void*) is harmless -typedef void (*CDECL spawn_fn)(void*, rust_opaque_box*, void *); +#ifdef _RUST_STAGE0 +typedef void (*CDECL spawn_fn)(void *, rust_opaque_box*, void *); +#else +typedef void (*CDECL spawn_fn)(rust_opaque_box*, void *); +#endif struct type_desc; +#ifdef _RUST_STAGE0 typedef void CDECL (glue_fn)(void *, void *, const type_desc **, void *); +#else +typedef void CDECL (glue_fn)(void *, const type_desc **, void *); +#endif // Corresponds to the boxed data in the @ region. The body follows the // header; you can obtain a ptr via box_body() below. diff --git a/src/rt/rust_uv.cpp b/src/rt/rust_uv.cpp index 8cf2bd4b4acb9..fefcbbcacf7d4 100644 --- a/src/rt/rust_uv.cpp +++ b/src/rt/rust_uv.cpp @@ -229,7 +229,7 @@ rust_uv_timer_init(uv_loop_t* loop, uv_timer_t* timer) { extern "C" int rust_uv_timer_start(uv_timer_t* the_timer, uv_timer_cb cb, - uint32_t timeout, uint32_t repeat) { + int64_t timeout, int64_t repeat) { return uv_timer_start(the_timer, cb, timeout, repeat); } diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index 6be41251f1bd9..e3e522aa7ceec 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -195,8 +195,8 @@ rust_register_exit_function rust_get_global_data_ptr rust_inc_kernel_live_count rust_dec_kernel_live_count -rust_get_exchange_count_ptr -rust_get_sched_tls_key +rust_exchange_count +rust_get_rt_tls_key swap_registers rust_readdir rust_opendir @@ -222,7 +222,7 @@ rust_uv_ip4_addrp rust_uv_ip6_addrp rust_uv_free_ip4_addr rust_uv_free_ip6_addr -rust_initialize_global_state +rust_initialize_rt_tls_key rust_dbg_next_port rust_new_memory_region rust_delete_memory_region @@ -234,3 +234,8 @@ rust_try rust_begin_unwind rust_take_task_borrow_list rust_set_task_borrow_list +rust_valgrind_stack_register +rust_valgrind_stack_deregister +rust_take_env_lock +rust_drop_env_lock +rust_update_log_settings diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp new file mode 100644 index 0000000000000..53b291ff470d1 --- /dev/null +++ b/src/rustllvm/PassWrapper.cpp @@ -0,0 +1,65 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#include "rustllvm.h" + +using namespace llvm; + +// Pass conversion fns +typedef struct LLVMOpaquePass *LLVMPassRef; + +inline Pass *unwrap(LLVMPassRef P) { + return reinterpret_cast(P); +} + +inline LLVMPassRef wrap(const Pass *P) { + return reinterpret_cast(const_cast(P)); +} + +template +inline T *unwrap(LLVMPassRef P) { + T *Q = (T*)unwrap(P); + assert(Q && "Invalid cast!"); + return Q; +} + +extern "C" void LLVMInitializePasses() { + PassRegistry &Registry = *PassRegistry::getPassRegistry(); + initializeCore(Registry); + initializeCodeGen(Registry); + initializeScalarOpts(Registry); + initializeVectorization(Registry); + initializeIPO(Registry); + initializeAnalysis(Registry); + initializeIPA(Registry); + initializeTransformUtils(Registry); + initializeInstCombine(Registry); + initializeInstrumentation(Registry); + initializeTarget(Registry); +} + +extern "C" void LLVMAddPass(LLVMPassManagerRef PM, LLVMPassRef P) { + PassManagerBase * pm = unwrap(PM); + Pass * p = unwrap(P); + + pm->add(p); +} + +extern "C" LLVMPassRef LLVMCreatePass(const char * PassName) { + StringRef SR(PassName); + PassRegistry * PR = PassRegistry::getPassRegistry(); + + const PassInfo * PI = PR->getPassInfo(SR); + if (PI) { + return wrap(PI->createPass()); + } else { + return (LLVMPassRef)0; + } +} diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 9e44abe081c95..4ee5df28d24ee 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#include "rustllvm.h" + //===----------------------------------------------------------------------=== // // This file defines alternate interfaces to core functions that are more @@ -15,50 +17,6 @@ // //===----------------------------------------------------------------------=== -#include "llvm/IR/InlineAsm.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/Linker.h" -#include "llvm/PassManager.h" -#include "llvm/IR/InlineAsm.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/Analysis/Verifier.h" -#include "llvm/Analysis/Passes.h" -#include "llvm/ADT/Triple.h" -#include "llvm/ADT/DenseSet.h" -#include "llvm/Assembly/Parser.h" -#include "llvm/Assembly/PrintModulePass.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/FormattedStream.h" -#include "llvm/Support/Timer.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/TargetSelect.h" -#include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/SourceMgr.h" -#include "llvm/Support/Host.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/DynamicLibrary.h" -#include "llvm/Support/Memory.h" -#include "llvm/ExecutionEngine/ExecutionEngine.h" -#include "llvm/ExecutionEngine/JIT.h" -#include "llvm/ExecutionEngine/JITMemoryManager.h" -#include "llvm/ExecutionEngine/MCJIT.h" -#include "llvm/ExecutionEngine/Interpreter.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetOptions.h" -#include "llvm/Transforms/Scalar.h" -#include "llvm/Transforms/IPO.h" -#include "llvm-c/Core.h" -#include "llvm-c/BitReader.h" -#include "llvm-c/Object.h" - -// Used by RustMCJITMemoryManager::getPointerToNamedFunction() -// to get around glibc issues. See the function for more information. -#ifdef __linux__ -#include -#include -#include -#endif - using namespace llvm; using namespace llvm::sys; @@ -548,22 +506,24 @@ extern "C" LLVMTypeRef LLVMMetadataType(void) { extern "C" LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef B, LLVMValueRef source, const char* Name, - AtomicOrdering order) { + AtomicOrdering order, + unsigned alignment) { LoadInst* li = new LoadInst(unwrap(source),0); li->setVolatile(true); li->setAtomic(order); - li->setAlignment(sizeof(intptr_t)); + li->setAlignment(alignment); return wrap(unwrap(B)->Insert(li, Name)); } extern "C" LLVMValueRef LLVMBuildAtomicStore(LLVMBuilderRef B, - LLVMValueRef val, - LLVMValueRef target, - AtomicOrdering order) { + LLVMValueRef val, + LLVMValueRef target, + AtomicOrdering order, + unsigned alignment) { StoreInst* si = new StoreInst(unwrap(val),unwrap(target)); si->setVolatile(true); si->setAtomic(order); - si->setAlignment(sizeof(intptr_t)); + si->setAlignment(alignment); return wrap(unwrap(B)->Insert(si)); } diff --git a/src/rustllvm/rustllvm.def.in b/src/rustllvm/rustllvm.def.in index dd5dc7102d1e9..8ebdbd0f307a6 100644 --- a/src/rustllvm/rustllvm.def.in +++ b/src/rustllvm/rustllvm.def.in @@ -584,3 +584,6 @@ LLVMConstNamedStruct LLVMStructCreateNamed LLVMStructSetBody LLVMInlineAsm +LLVMInitializePasses +LLVMAddPass +LLVMCreatePass diff --git a/src/rustllvm/rustllvm.h b/src/rustllvm/rustllvm.h new file mode 100644 index 0000000000000..1c8842f7b4a77 --- /dev/null +++ b/src/rustllvm/rustllvm.h @@ -0,0 +1,57 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#include "llvm/IR/InlineAsm.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/Linker.h" +#include "llvm/PassManager.h" +#include "llvm/IR/InlineAsm.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/Lint.h" +#include "llvm/ADT/Triple.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/Assembly/Parser.h" +#include "llvm/Assembly/PrintModulePass.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/Support/Timer.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/Memory.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/JIT.h" +#include "llvm/ExecutionEngine/JITMemoryManager.h" +#include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/ExecutionEngine/Interpreter.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/IPO.h" +#include "llvm/Transforms/Instrumentation.h" +#include "llvm/Transforms/Vectorize.h" +#include "llvm-c/Core.h" +#include "llvm-c/BitReader.h" +#include "llvm-c/Object.h" + +// Used by RustMCJITMemoryManager::getPointerToNamedFunction() +// to get around glibc issues. See the function for more information. +#ifdef __linux__ +#include +#include +#include +#endif + diff --git a/src/snapshots.txt b/src/snapshots.txt index c643b4dd25d43..a68d2205cfba8 100644 --- a/src/snapshots.txt +++ b/src/snapshots.txt @@ -1,3 +1,11 @@ +S 2013-05-17 2d28d64 + macos-i386 abadafb33c9f858543351c822fb468195163559f + macos-x86_64 4a484693f73bcc8ce2a85708fd4f0c3f6e34969d + winnt-i386 558dac018b2b6dbb23841772e1f4b9591558850c + freebsd-x86_64 59ca6fc1eae2d160525c705928d551dd8993e01c + linux-i386 2d3e61efe30f55176c72b3dbe31d693630f59abd + linux-x86_64 86ecc1833df8e28d08ff3a9a952ec424abdcb157 + S 2013-05-03 213f7b2 macos-i386 0bf8b88ea01cc4cdd81ac4db1d301ea9b3371f13 macos-x86_64 2da3990639ab5a9c9d51b3478c437cb459de84e3 diff --git a/src/test/auxiliary/anon-extern-mod-cross-crate-1.rs b/src/test/auxiliary/anon-extern-mod-cross-crate-1.rs index bccbb8173aad1..77f257ea4f52c 100644 --- a/src/test/auxiliary/anon-extern-mod-cross-crate-1.rs +++ b/src/test/auxiliary/anon-extern-mod-cross-crate-1.rs @@ -14,6 +14,10 @@ vers = "0.1")]; #[crate_type = "lib"]; + +use std::libc; + extern { - fn rust_get_argc() -> libc::c_int; + pub fn rust_get_argc() -> libc::c_int; } + diff --git a/src/test/auxiliary/anon_trait_static_method_lib.rs b/src/test/auxiliary/anon_trait_static_method_lib.rs index 6e111381cba34..a15373a703377 100644 --- a/src/test/auxiliary/anon_trait_static_method_lib.rs +++ b/src/test/auxiliary/anon_trait_static_method_lib.rs @@ -12,8 +12,8 @@ pub struct Foo { x: int } -pub impl Foo { - fn new() -> Foo { +impl Foo { + pub fn new() -> Foo { Foo { x: 3 } } } diff --git a/src/test/auxiliary/cci_capture_clause.rs b/src/test/auxiliary/cci_capture_clause.rs index f2749ed1d0c05..e58b28aa3ded1 100644 --- a/src/test/auxiliary/cci_capture_clause.rs +++ b/src/test/auxiliary/cci_capture_clause.rs @@ -8,7 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::comm::*; +use std::comm::*; +use std::task; pub fn foo(x: T) -> Port { let (p, c) = stream(); diff --git a/src/test/auxiliary/cci_class_2.rs b/src/test/auxiliary/cci_class_2.rs index b120a4d759f90..c0275249ca6d4 100644 --- a/src/test/auxiliary/cci_class_2.rs +++ b/src/test/auxiliary/cci_class_2.rs @@ -16,8 +16,8 @@ pub mod kitties { } - pub impl cat { - fn speak(&self) {} + impl cat { + pub fn speak(&self) {} } pub fn cat(in_x : uint, in_y : int) -> cat { diff --git a/src/test/auxiliary/cci_class_3.rs b/src/test/auxiliary/cci_class_3.rs index a516f5398df62..7ebf5a1e75a7f 100644 --- a/src/test/auxiliary/cci_class_3.rs +++ b/src/test/auxiliary/cci_class_3.rs @@ -15,9 +15,9 @@ pub mod kitties { how_hungry : int, } - pub impl cat { - fn speak(&mut self) { self.meows += 1u; } - fn meow_count(&mut self) -> uint { self.meows } + impl cat { + pub fn speak(&mut self) { self.meows += 1u; } + pub fn meow_count(&mut self) -> uint { self.meows } } pub fn cat(in_x : uint, in_y : int) -> cat { diff --git a/src/test/auxiliary/cci_class_4.rs b/src/test/auxiliary/cci_class_4.rs index 68143b32741c8..98e5c8c2b5bbd 100644 --- a/src/test/auxiliary/cci_class_4.rs +++ b/src/test/auxiliary/cci_class_4.rs @@ -16,10 +16,10 @@ pub mod kitties { name : ~str, } - pub impl cat { - fn speak(&mut self) { self.meow(); } + impl cat { + pub fn speak(&mut self) { self.meow(); } - fn eat(&mut self) -> bool { + pub fn eat(&mut self) -> bool { if self.how_hungry > 0 { error!("OM NOM NOM"); self.how_hungry -= 2; @@ -31,8 +31,8 @@ pub mod kitties { } } - pub impl cat { - fn meow(&mut self) { + impl cat { + pub fn meow(&mut self) { error!("Meow"); self.meows += 1u; if self.meows % 5u == 0u { diff --git a/src/test/auxiliary/cci_class_5.rs b/src/test/auxiliary/cci_class_5.rs index c04cdbcab1adb..d64930b3dab22 100644 --- a/src/test/auxiliary/cci_class_5.rs +++ b/src/test/auxiliary/cci_class_5.rs @@ -9,13 +9,15 @@ // except according to those terms. pub mod kitties { + use std::uint; + pub struct cat { priv meows : uint, how_hungry : int, } - pub impl cat { - priv fn nap(&self) { for uint::range(1, 10000u) |_i|{}} + impl cat { + priv fn nap(&self) { for uint::range(1, 10000u) |_i|{}} } pub fn cat(in_x : uint, in_y : int) -> cat { diff --git a/src/test/auxiliary/cci_class_6.rs b/src/test/auxiliary/cci_class_6.rs index 7ad617cebdbb3..90344a544bff4 100644 --- a/src/test/auxiliary/cci_class_6.rs +++ b/src/test/auxiliary/cci_class_6.rs @@ -16,11 +16,12 @@ pub mod kitties { how_hungry : int, } - pub impl cat { - fn speak(&mut self, stuff: ~[T]) { + impl cat { + pub fn speak(&mut self, stuff: ~[T]) { self.meows += stuff.len(); } - fn meow_count(&mut self) -> uint { self.meows } + + pub fn meow_count(&mut self) -> uint { self.meows } } pub fn cat(in_x : uint, in_y : int, in_info: ~[U]) -> cat { diff --git a/src/test/auxiliary/cci_class_cast.rs b/src/test/auxiliary/cci_class_cast.rs index ae0407a5bed33..1e82b85f728c0 100644 --- a/src/test/auxiliary/cci_class_cast.rs +++ b/src/test/auxiliary/cci_class_cast.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::to_str::*; +use std::to_str::*; pub mod kitty { pub struct cat { @@ -21,7 +21,7 @@ pub mod kitty { fn to_str(&self) -> ~str { copy self.name } } - priv impl cat { + impl cat { fn meow(&mut self) { error!("Meow"); self.meows += 1u; @@ -32,10 +32,10 @@ pub mod kitty { } - pub impl cat { - fn speak(&mut self) { self.meow(); } + impl cat { + pub fn speak(&mut self) { self.meow(); } - fn eat(&mut self) -> bool { + pub fn eat(&mut self) -> bool { if self.how_hungry > 0 { error!("OM NOM NOM"); self.how_hungry -= 2; diff --git a/src/test/auxiliary/explicit_self_xcrate.rs b/src/test/auxiliary/explicit_self_xcrate.rs index 058cb53f9186b..be65cadcc7f80 100644 --- a/src/test/auxiliary/explicit_self_xcrate.rs +++ b/src/test/auxiliary/explicit_self_xcrate.rs @@ -20,6 +20,6 @@ pub struct Bar { impl Foo for Bar { #[inline(always)] fn f(&self) { - io::println((*self).x); + println((*self).x); } } diff --git a/src/test/auxiliary/extern-crosscrate-source.rs b/src/test/auxiliary/extern-crosscrate-source.rs index d59057f01f2de..ba9091ce0e5bf 100644 --- a/src/test/auxiliary/extern-crosscrate-source.rs +++ b/src/test/auxiliary/extern-crosscrate-source.rs @@ -13,10 +13,14 @@ #[crate_type = "lib"]; +use std::libc; + pub mod rustrt { + use std::libc; + pub extern { pub fn rust_dbg_call(cb: *u8, data: libc::uintptr_t) - -> libc::uintptr_t; + -> libc::uintptr_t; } } diff --git a/src/test/auxiliary/foreign_lib.rs b/src/test/auxiliary/foreign_lib.rs index fe5b9e45593e3..f8b2c2f458afb 100644 --- a/src/test/auxiliary/foreign_lib.rs +++ b/src/test/auxiliary/foreign_lib.rs @@ -11,6 +11,8 @@ #[link(name="foreign_lib", vers="0.0")]; pub mod rustrt { + use std::libc; + pub extern { pub fn rust_get_argc() -> libc::c_int; } diff --git a/src/test/auxiliary/impl_privacy_xc_1.rs b/src/test/auxiliary/impl_privacy_xc_1.rs index 4d98c4d9d2b54..4752c5a3bac56 100644 --- a/src/test/auxiliary/impl_privacy_xc_1.rs +++ b/src/test/auxiliary/impl_privacy_xc_1.rs @@ -4,6 +4,6 @@ pub struct Fish { x: int } -pub impl Fish { - fn swim(&self) {} +impl Fish { + pub fn swim(&self) {} } diff --git a/src/test/auxiliary/issue-2526.rs b/src/test/auxiliary/issue-2526.rs index 0e9cf39929f1c..bbc0f1ad3e558 100644 --- a/src/test/auxiliary/issue-2526.rs +++ b/src/test/auxiliary/issue-2526.rs @@ -13,7 +13,7 @@ uuid = "54cc1bc9-02b8-447c-a227-75ebc923bc29")]; #[crate_type = "lib"]; -extern mod std; +extern mod extra; struct arc_destruct { _data: int, diff --git a/src/test/auxiliary/issue-2631-a.rs b/src/test/auxiliary/issue-2631-a.rs index bee754f5bd448..8afc032775590 100644 --- a/src/test/auxiliary/issue-2631-a.rs +++ b/src/test/auxiliary/issue-2631-a.rs @@ -11,9 +11,9 @@ #[link(name = "req")]; #[crate_type = "lib"]; -extern mod std; +extern mod extra; -use core::hashmap::HashMap; +use std::hashmap::HashMap; pub type header_map = HashMap<~str, @mut ~[@~str]>; diff --git a/src/test/auxiliary/issue-3012-1.rs b/src/test/auxiliary/issue-3012-1.rs index 36343d42b7589..ce40afff3ae3d 100644 --- a/src/test/auxiliary/issue-3012-1.rs +++ b/src/test/auxiliary/issue-3012-1.rs @@ -12,6 +12,8 @@ #[crate_type = "lib"]; pub mod socket { + use std::libc; + pub struct socket_handle { sockfd: libc::c_int, } diff --git a/src/test/auxiliary/issue_2472_b.rs b/src/test/auxiliary/issue_2472_b.rs index 7969128ce5285..1475b1a75a665 100644 --- a/src/test/auxiliary/issue_2472_b.rs +++ b/src/test/auxiliary/issue_2472_b.rs @@ -11,8 +11,8 @@ pub struct S(()); -pub impl S { - fn foo(&self) { } +impl S { + pub fn foo(&self) { } } pub trait T { diff --git a/src/test/auxiliary/moves_based_on_type_lib.rs b/src/test/auxiliary/moves_based_on_type_lib.rs index 857593a84d2c0..b3a9b3e1ee9ac 100644 --- a/src/test/auxiliary/moves_based_on_type_lib.rs +++ b/src/test/auxiliary/moves_based_on_type_lib.rs @@ -16,7 +16,7 @@ pub struct S { impl Drop for S { fn finalize(&self) { - io::println("goodbye"); + println("goodbye"); } } diff --git a/src/test/auxiliary/private_variant_xc.rs b/src/test/auxiliary/private_variant_xc.rs new file mode 100644 index 0000000000000..d7d55c691b683 --- /dev/null +++ b/src/test/auxiliary/private_variant_xc.rs @@ -0,0 +1,5 @@ +pub enum Foo { + pub Bar, + priv Baz, +} + diff --git a/src/test/auxiliary/reexported_static_methods.rs b/src/test/auxiliary/reexported_static_methods.rs new file mode 100644 index 0000000000000..811bf082ae891 --- /dev/null +++ b/src/test/auxiliary/reexported_static_methods.rs @@ -0,0 +1,53 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub use sub_foo::Foo; +pub use Baz = self::Bar; +pub use sub_foo::Boz; +pub use sub_foo::Bort; + +pub trait Bar { + pub fn bar() -> Self; +} + +impl Bar for int { + pub fn bar() -> int { 84 } +} + +pub mod sub_foo { + pub trait Foo { + pub fn foo() -> Self; + } + + impl Foo for int { + pub fn foo() -> int { 42 } + } + + pub struct Boz { + unused_str: ~str + } + + impl Boz { + pub fn boz(i: int) -> bool { + i > 0 + } + } + + pub enum Bort { + Bort1, + Bort2 + } + + impl Bort { + pub fn bort() -> ~str { + ~"bort()" + } + } +} diff --git a/src/test/auxiliary/static-methods-crate.rs b/src/test/auxiliary/static-methods-crate.rs index 2ecd318db3c92..b5b3385312949 100644 --- a/src/test/auxiliary/static-methods-crate.rs +++ b/src/test/auxiliary/static-methods-crate.rs @@ -13,6 +13,8 @@ #[crate_type = "lib"]; +use std::int; + pub trait read { fn readMaybe(s: ~str) -> Option; } diff --git a/src/test/auxiliary/trait_inheritance_overloading_xc.rs b/src/test/auxiliary/trait_inheritance_overloading_xc.rs index 1fb0db25b31a8..f938c9c56ed94 100644 --- a/src/test/auxiliary/trait_inheritance_overloading_xc.rs +++ b/src/test/auxiliary/trait_inheritance_overloading_xc.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::cmp::Eq; +use std::cmp::Eq; pub trait MyNum : Add + Sub + Mul + Eq { } diff --git a/src/test/auxiliary/use_from_trait_xc.rs b/src/test/auxiliary/use_from_trait_xc.rs new file mode 100644 index 0000000000000..2ab95c271aec7 --- /dev/null +++ b/src/test/auxiliary/use_from_trait_xc.rs @@ -0,0 +1,10 @@ +pub trait Trait { + fn foo(); +} + +struct Foo; + +impl Foo { + pub fn new() {} +} + diff --git a/src/test/bench/core-map.rs b/src/test/bench/core-map.rs index cb494ec9d206a..fd1110abb224a 100644 --- a/src/test/bench/core-map.rs +++ b/src/test/bench/core-map.rs @@ -8,14 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; - -use core::io; -use std::time; -use std::treemap::TreeMap; -use core::hashmap::{HashMap, HashSet}; -use core::trie::TrieMap; -use core::rand::Rng; +extern mod extra; + +use extra::time; +use extra::treemap::TreeMap; +use std::hashmap::{HashMap, HashSet}; +use std::io; +use std::os; +use std::rand::Rng; +use std::trie::TrieMap; +use std::uint; +use std::vec; fn timed(label: &str, f: &fn()) { let start = time::precise_time_s(); @@ -35,7 +38,7 @@ fn ascending>(map: &mut M, n_keys: uint) { do timed("search") { for uint::range(0, n_keys) |i| { - assert!(map.find(&i).unwrap() == &(i + 1)); + assert_eq!(map.find(&i).unwrap(), &(i + 1)); } } @@ -57,7 +60,7 @@ fn descending>(map: &mut M, n_keys: uint) { do timed("search") { for uint::range_rev(n_keys, 0) |i| { - assert!(map.find(&i).unwrap() == &(i + 1)); + assert_eq!(map.find(&i).unwrap(), &(i + 1)); } } @@ -78,7 +81,7 @@ fn vector>(map: &mut M, n_keys: uint, dist: &[uint]) { do timed("search") { for uint::range(0, n_keys) |i| { - assert!(map.find(&dist[i]).unwrap() == &(i + 1)); + assert_eq!(map.find(&dist[i]).unwrap(), &(i + 1)); } } @@ -103,7 +106,7 @@ fn main() { let mut rand = vec::with_capacity(n_keys); { - let mut rng = core::rand::IsaacRng::new_seeded([1, 1, 1, 1, 1, 1, 1]); + let mut rng = std::rand::IsaacRng::new_seeded([1, 1, 1, 1, 1, 1, 1]); let mut set = HashSet::new(); while set.len() != n_keys { let next = rng.next() as uint; diff --git a/src/test/bench/core-set.rs b/src/test/bench/core-set.rs index bae21c6d4a325..a0b742515494c 100644 --- a/src/test/bench/core-set.rs +++ b/src/test/bench/core-set.rs @@ -8,10 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; -use core::hashmap::HashSet; -use std::bitv::BitvSet; -use std::treemap::TreeSet; +extern mod extra; + +use extra::bitv::BitvSet; +use extra::treemap::TreeSet; +use std::hashmap::HashSet; +use std::io; +use std::os; +use std::rand; +use std::uint; struct Results { sequential_ints: float, @@ -24,14 +29,14 @@ struct Results { } fn timed(result: &mut float, op: &fn()) { - let start = std::time::precise_time_s(); + let start = extra::time::precise_time_s(); op(); - let end = std::time::precise_time_s(); + let end = extra::time::precise_time_s(); *result = (end - start); } -pub impl Results { - fn bench_int, +impl Results { + pub fn bench_int, R: rand::Rng>( &mut self, rng: &mut R, @@ -74,7 +79,7 @@ pub impl Results { } } - fn bench_str, + pub fn bench_str, R:rand::Rng>( &mut self, rng: &mut R, @@ -168,7 +173,7 @@ fn main() { let mut results = empty_results(); results.bench_int(&mut rng, num_keys, max, || HashSet::new::()); results.bench_str(&mut rng, num_keys, || HashSet::new::<~str>()); - write_results("core::hashmap::HashSet", &results); + write_results("std::hashmap::HashSet", &results); } { @@ -176,13 +181,13 @@ fn main() { let mut results = empty_results(); results.bench_int(&mut rng, num_keys, max, || TreeSet::new::()); results.bench_str(&mut rng, num_keys, || TreeSet::new::<~str>()); - write_results("std::treemap::TreeSet", &results); + write_results("extra::treemap::TreeSet", &results); } { let mut rng = rand::IsaacRng::new_seeded(seed); let mut results = empty_results(); results.bench_int(&mut rng, num_keys, max, || BitvSet::new()); - write_results("std::bitv::BitvSet", &results); + write_results("extra::bitv::BitvSet", &results); } } diff --git a/src/test/bench/core-std.rs b/src/test/bench/core-std.rs index e6b3b3bbe20d3..287daf68effbe 100644 --- a/src/test/bench/core-std.rs +++ b/src/test/bench/core-std.rs @@ -8,13 +8,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Microbenchmarks for various functions in core and std - -extern mod std; - -use std::time::precise_time_s; -use core::rand::RngUtil; -use core::util; +// Microbenchmarks for various functions in std and extra + +extern mod extra; + +use extra::time::precise_time_s; +use std::int; +use std::io; +use std::os; +use std::rand::RngUtil; +use std::rand; +use std::result; +use std::uint; +use std::util; +use std::vec; macro_rules! bench ( ($id:ident) => (maybe_run_test(argv, stringify!($id).to_owned(), $id)) diff --git a/src/test/bench/core-uint-to-str.rs b/src/test/bench/core-uint-to-str.rs index c637fcbaf50f4..cbf73d5c0594f 100644 --- a/src/test/bench/core-uint-to-str.rs +++ b/src/test/bench/core-uint-to-str.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::os; +use std::uint; + fn main() { let args = os::args(); let args = if os::getenv(~"RUST_BENCH").is_some() { diff --git a/src/test/bench/graph500-bfs.rs b/src/test/bench/graph500-bfs.rs index ddf6f4bfc55cf..38cc312734302 100644 --- a/src/test/bench/graph500-bfs.rs +++ b/src/test/bench/graph500-bfs.rs @@ -1,6 +1,6 @@ // xfail-pretty -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -16,14 +16,19 @@ An implementation of the Graph500 Breadth First Search problem in Rust. */ -extern mod std; -use std::arc; -use std::time; -use std::deque::Deque; -use std::par; -use core::hashmap::HashSet; -use core::int::abs; -use core::rand::RngUtil; +extern mod extra; +use extra::arc; +use extra::time; +use extra::deque::Deque; +use extra::par; +use std::hashmap::HashSet; +use std::int::abs; +use std::io; +use std::os; +use std::rand::RngUtil; +use std::rand; +use std::uint; +use std::vec; type node_id = i64; type graph = ~[~[node_id]]; @@ -234,7 +239,7 @@ fn pbfs(graph: &arc::ARC, key: node_id) -> bfs_result { black(node_id) }; - let graph_vec = arc::get(graph); // FIXME #3387 requires this temp + let graph_vec = graph.get(); // FIXME #3387 requires this temp let mut colors = do vec::from_fn(graph_vec.len()) |i| { if i as node_id == key { gray(key) @@ -266,13 +271,13 @@ fn pbfs(graph: &arc::ARC, key: node_id) -> bfs_result { let color = arc::ARC(colors); - let color_vec = arc::get(&color); // FIXME #3387 requires this temp + let color_vec = color.get(); // FIXME #3387 requires this temp colors = do par::mapi(*color_vec) { - let colors = arc::clone(&color); - let graph = arc::clone(graph); + let colors = color.clone(); + let graph = graph.clone(); let result: ~fn(x: uint, y: &color) -> color = |i, c| { - let colors = arc::get(&colors); - let graph = arc::get(&graph); + let colors = colors.get(); + let graph = graph.get(); match *c { white => { let i = i as node_id; @@ -296,7 +301,7 @@ fn pbfs(graph: &arc::ARC, key: node_id) -> bfs_result { }; result }; - assert!((colors.len() == old_len)); + assert_eq!(colors.len(), old_len); } // Convert the results. diff --git a/src/test/bench/msgsend-pipes-shared.rs b/src/test/bench/msgsend-pipes-shared.rs index 95758b3fe6406..9fbc1d4590de4 100644 --- a/src/test/bench/msgsend-pipes-shared.rs +++ b/src/test/bench/msgsend-pipes-shared.rs @@ -18,11 +18,17 @@ // different scalability characteristics compared to the select // version. -extern mod std; -use core::io::Writer; -use core::io::WriterUtil; +extern mod extra; -use core::comm::{Port, Chan, SharedChan}; +use std::comm::{Port, Chan, SharedChan}; +use std::comm; +use std::io::{Writer, WriterUtil}; +use std::io; +use std::os; +use std::task; +use std::ptr; +use std::uint; +use std::vec; macro_rules! move_out ( { $x:expr } => { unsafe { let y = *ptr::to_unsafe_ptr(&($x)); y } } @@ -61,7 +67,7 @@ fn run(args: &[~str]) { let size = uint::from_str(args[1]).get(); let workers = uint::from_str(args[2]).get(); let num_bytes = 100; - let start = std::time::precise_time_s(); + let start = extra::time::precise_time_s(); let mut worker_results = ~[]; for uint::range(0, workers) |_i| { let to_child = to_child.clone(); @@ -87,13 +93,13 @@ fn run(args: &[~str]) { to_child.send(stop); move_out!(to_child); let result = from_child.recv(); - let end = std::time::precise_time_s(); + let end = extra::time::precise_time_s(); let elapsed = end - start; io::stdout().write_str(fmt!("Count is %?\n", result)); io::stdout().write_str(fmt!("Test took %? seconds\n", elapsed)); let thruput = ((size / workers * workers) as float) / (elapsed as float); io::stdout().write_str(fmt!("Throughput=%f per sec\n", thruput)); - assert!(result == num_bytes * size); + assert_eq!(result, num_bytes * size); } fn main() { diff --git a/src/test/bench/msgsend-pipes.rs b/src/test/bench/msgsend-pipes.rs index e213a44b49ae7..2663bb266706d 100644 --- a/src/test/bench/msgsend-pipes.rs +++ b/src/test/bench/msgsend-pipes.rs @@ -14,11 +14,16 @@ // // I *think* it's the same, more or less. -extern mod std; -use core::io::Writer; -use core::io::WriterUtil; +extern mod extra; -use core::comm::{Port, PortSet, Chan, stream}; +use std::comm::{Port, PortSet, Chan, stream}; +use std::io::{Writer, WriterUtil}; +use std::io; +use std::os; +use std::ptr; +use std::task; +use std::uint; +use std::vec; macro_rules! move_out ( { $x:expr } => { unsafe { let y = *ptr::to_unsafe_ptr(&($x)); y } } @@ -57,7 +62,7 @@ fn run(args: &[~str]) { let size = uint::from_str(args[1]).get(); let workers = uint::from_str(args[2]).get(); let num_bytes = 100; - let start = std::time::precise_time_s(); + let start = extra::time::precise_time_s(); let mut worker_results = ~[]; for uint::range(0, workers) |_i| { let (from_parent_, to_child) = stream(); @@ -84,13 +89,13 @@ fn run(args: &[~str]) { to_child.send(stop); move_out!(to_child); let result = from_child.recv(); - let end = std::time::precise_time_s(); + let end = extra::time::precise_time_s(); let elapsed = end - start; io::stdout().write_str(fmt!("Count is %?\n", result)); io::stdout().write_str(fmt!("Test took %? seconds\n", elapsed)); let thruput = ((size / workers * workers) as float) / (elapsed as float); io::stdout().write_str(fmt!("Throughput=%f per sec\n", thruput)); - assert!(result == num_bytes * size); + assert_eq!(result, num_bytes * size); } fn main() { diff --git a/src/test/bench/msgsend-ring-mutex-arcs.rs b/src/test/bench/msgsend-ring-mutex-arcs.rs index 2d234634cc8ba..c0e147b2db556 100644 --- a/src/test/bench/msgsend-ring-mutex-arcs.rs +++ b/src/test/bench/msgsend-ring-mutex-arcs.rs @@ -15,27 +15,36 @@ // This also serves as a pipes test, because ARCs are implemented with pipes. -extern mod std; -use std::time; -use std::arc; -use std::future; -use core::cell::Cell; +extern mod extra; + +use extra::arc; +use extra::future; +use extra::time; +use std::cell::Cell; +use std::io; +use std::os; +use std::uint; +use std::vec; // A poor man's pipe. type pipe = arc::MutexARC<~[uint]>; fn send(p: &pipe, msg: uint) { - do p.access_cond |state, cond| { - state.push(msg); - cond.signal(); + unsafe { + do p.access_cond |state, cond| { + state.push(msg); + cond.signal(); + } } } fn recv(p: &pipe) -> uint { - do p.access_cond |state, cond| { - while vec::is_empty(*state) { - cond.wait(); + unsafe { + do p.access_cond |state, cond| { + while vec::is_empty(*state) { + cond.wait(); + } + state.pop() } - state.pop() } } @@ -75,7 +84,7 @@ fn main() { let msg_per_task = uint::from_str(args[2]).get(); let (num_chan, num_port) = init(); - let mut num_chan = Cell(num_chan); + let mut num_chan = Cell::new(num_chan); let start = time::precise_time_s(); @@ -85,8 +94,8 @@ fn main() { for uint::range(1u, num_tasks) |i| { //error!("spawning %?", i); let (new_chan, num_port) = init(); - let num_chan2 = Cell(num_chan.take()); - let num_port = Cell(num_port); + let num_chan2 = Cell::new(num_chan.take()); + let num_port = Cell::new(num_port); let new_future = do future::spawn() { let num_chan = num_chan2.take(); let num_port1 = num_port.take(); diff --git a/src/test/bench/msgsend-ring-pipes.rs b/src/test/bench/msgsend-ring-pipes.rs index f698b2c3c1137..d7b05ea635065 100644 --- a/src/test/bench/msgsend-ring-pipes.rs +++ b/src/test/bench/msgsend-ring-pipes.rs @@ -16,13 +16,17 @@ // This version uses automatically compiled channel contracts. -extern mod std; - -use core::cell::Cell; -use core::pipes::recv; -use core::util; -use std::time; -use std::future; +extern mod extra; + +use extra::future; +use extra::time; +use std::cell::Cell; +use std::io; +use std::os; +use std::pipes::recv; +use std::ptr; +use std::uint; +use std::util; proto! ring ( num:send { @@ -69,8 +73,8 @@ fn main() { let num_tasks = uint::from_str(args[1]).get(); let msg_per_task = uint::from_str(args[2]).get(); - let (num_chan, num_port) = ring::init(); - let mut num_chan = Cell(num_chan); + let (num_port, num_chan) = ring::init(); + let mut num_chan = Cell::new(num_chan); let start = time::precise_time_s(); @@ -79,9 +83,9 @@ fn main() { for uint::range(1u, num_tasks) |i| { //error!("spawning %?", i); - let (new_chan, num_port) = ring::init(); - let num_chan2 = Cell(num_chan.take()); - let num_port = Cell(num_port); + let (num_port, new_chan) = ring::init(); + let num_chan2 = Cell::new(num_chan.take()); + let num_port = Cell::new(num_port); let new_future = do future::spawn || { let num_chan = num_chan2.take(); let num_port1 = num_port.take(); diff --git a/src/test/bench/msgsend-ring-rw-arcs.rs b/src/test/bench/msgsend-ring-rw-arcs.rs index 02415c4bcfce7..9aaf565f36834 100644 --- a/src/test/bench/msgsend-ring-rw-arcs.rs +++ b/src/test/bench/msgsend-ring-rw-arcs.rs @@ -15,12 +15,16 @@ // This also serves as a pipes test, because ARCs are implemented with pipes. -extern mod std; +extern mod extra; -use core::cell::Cell; -use std::time; -use std::arc; -use std::future; +use extra::arc; +use extra::future; +use extra::time; +use std::cell::Cell; +use std::io; +use std::os; +use std::uint; +use std::vec; // A poor man's pipe. type pipe = arc::RWARC<~[uint]>; @@ -76,7 +80,7 @@ fn main() { let msg_per_task = uint::from_str(args[2]).get(); let (num_chan, num_port) = init(); - let mut num_chan = Cell(num_chan); + let mut num_chan = Cell::new(num_chan); let start = time::precise_time_s(); @@ -86,8 +90,8 @@ fn main() { for uint::range(1u, num_tasks) |i| { //error!("spawning %?", i); let (new_chan, num_port) = init(); - let num_chan2 = Cell(num_chan.take()); - let num_port = Cell(num_port); + let num_chan2 = Cell::new(num_chan.take()); + let num_port = Cell::new(num_port); let new_future = do future::spawn { let num_chan = num_chan2.take(); let num_port1 = num_port.take(); diff --git a/src/test/bench/noise.rs b/src/test/bench/noise.rs index 992ce73a4bff7..25bdf7dc3feff 100644 --- a/src/test/bench/noise.rs +++ b/src/test/bench/noise.rs @@ -1,6 +1,10 @@ // Perlin noise benchmark from https://gist.github.com/1170424 -use core::rand::{Rng, RngUtil}; +use std::f32; +use std::float; +use std::int; +use std::rand::{Rng, RngUtil}; +use std::rand; struct Vec2 { x: f32, @@ -31,8 +35,8 @@ struct Noise2DContext { permutations: [int, ..256], } -pub impl Noise2DContext { - fn new() -> Noise2DContext { +impl Noise2DContext { + pub fn new() -> Noise2DContext { let mut r = rand::rng(); let mut rgradients = [ Vec2 { x: 0.0, y: 0.0 }, ..256 ]; for int::range(0, 256) |i| { @@ -51,17 +55,17 @@ pub impl Noise2DContext { } #[inline(always)] - fn get_gradient(&self, x: int, y: int) -> Vec2 { + pub fn get_gradient(&self, x: int, y: int) -> Vec2 { let idx = self.permutations[x & 255] + self.permutations[y & 255]; self.rgradients[idx & 255] } #[inline] - fn get_gradients(&self, - gradients: &mut [Vec2, ..4], - origins: &mut [Vec2, ..4], - x: f32, - y: f32) { + pub fn get_gradients(&self, + gradients: &mut [Vec2, ..4], + origins: &mut [Vec2, ..4], + x: f32, + y: f32) { let x0f = f32::floor(x); let y0f = f32::floor(y); let x0 = x0f as int; @@ -81,7 +85,7 @@ pub impl Noise2DContext { } #[inline] - fn get(&self, x: f32, y: f32) -> f32 { + pub fn get(&self, x: f32, y: f32) -> f32 { let p = Vec2 {x: x, y: y}; let mut gradients = [ Vec2 { x: 0.0, y: 0.0 }, ..4 ]; let mut origins = [ Vec2 { x: 0.0, y: 0.0 }, ..4 ]; diff --git a/src/test/bench/pingpong.rs b/src/test/bench/pingpong.rs index cfad253cfed5b..63e4174a0fc7c 100644 --- a/src/test/bench/pingpong.rs +++ b/src/test/bench/pingpong.rs @@ -12,11 +12,14 @@ // xfail-pretty -extern mod std; +extern mod extra; -use core::cell::Cell; -use core::pipes::*; -use std::time::precise_time_s; +use extra::time::precise_time_s; +use std::cell::Cell; +use std::io; +use std::os; +use std::pipes::*; +use std::task; proto! pingpong ( ping: send { @@ -80,15 +83,15 @@ endpoint is passed to the new task. */ pub fn spawn_service( - init: extern fn() -> (SendPacketBuffered, - RecvPacketBuffered), + init: extern fn() -> (RecvPacketBuffered, + SendPacketBuffered), service: ~fn(v: RecvPacketBuffered)) -> SendPacketBuffered { - let (client, server) = init(); + let (server, client) = init(); // This is some nasty gymnastics required to safely move the pipe // into a new task. - let server = Cell(server); + let server = Cell::new(server); do task::spawn { service(server.take()); } @@ -101,15 +104,15 @@ receive state. */ pub fn spawn_service_recv( - init: extern fn() -> (RecvPacketBuffered, - SendPacketBuffered), + init: extern fn() -> (SendPacketBuffered, + RecvPacketBuffered), service: ~fn(v: SendPacketBuffered)) -> RecvPacketBuffered { - let (client, server) = init(); + let (server, client) = init(); // This is some nasty gymnastics required to safely move the pipe // into a new task. - let server = Cell(server); + let server = Cell::new(server); do task::spawn { service(server.take()) } @@ -117,10 +120,10 @@ pub fn spawn_service_recv( client } -fn switch(endp: core::pipes::RecvPacketBuffered, +fn switch(endp: std::pipes::RecvPacketBuffered, f: &fn(v: Option) -> U) -> U { - f(core::pipes::try_recv(endp)) + f(std::pipes::try_recv(endp)) } // Here's the benchmark diff --git a/src/test/bench/shootout-ackermann.rs b/src/test/bench/shootout-ackermann.rs index c8ffad025fa68..51fec4dbfe8b6 100644 --- a/src/test/bench/shootout-ackermann.rs +++ b/src/test/bench/shootout-ackermann.rs @@ -8,7 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; +extern mod extra; + +use std::int; +use std::io; +use std::os; fn ack(m: int, n: int) -> int { if m == 0 { diff --git a/src/test/bench/shootout-binarytrees.rs b/src/test/bench/shootout-binarytrees.rs index c420e0cbb2fd0..e7aed911cb0a2 100644 --- a/src/test/bench/shootout-binarytrees.rs +++ b/src/test/bench/shootout-binarytrees.rs @@ -12,8 +12,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; -use std::arena; +extern mod extra; +use extra::arena; enum tree<'self> { nil, diff --git a/src/test/bench/shootout-chameneos-redux.rs b/src/test/bench/shootout-chameneos-redux.rs index 03d4525243272..53b47b1214437 100644 --- a/src/test/bench/shootout-chameneos-redux.rs +++ b/src/test/bench/shootout-chameneos-redux.rs @@ -10,17 +10,24 @@ // chameneos -extern mod std; -use std::sort; -use core::cell::Cell; -use core::comm::*; +extern mod extra; + +use extra::sort; +use std::cell::Cell; +use std::comm::*; +use std::io; +use std::option; +use std::os; +use std::task; +use std::uint; +use std::vec; fn print_complements() { let all = ~[Blue, Red, Yellow]; for vec::each(all) |aa| { for vec::each(all) |bb| { - io::println(show_color(*aa) + ~" + " + show_color(*bb) + - ~" -> " + show_color(transform(*aa, *bb))); + io::println(show_color(*aa) + " + " + show_color(*bb) + + " -> " + show_color(transform(*aa, *bb))); } } } @@ -43,7 +50,7 @@ fn show_color(cc: color) -> ~str { fn show_color_list(set: ~[color]) -> ~str { let mut out = ~""; for vec::eachi(set) |_ii, col| { - out += ~" "; + out += " "; out += show_color(*col); } return out; @@ -75,7 +82,7 @@ fn show_number(nn: uint) -> ~str { while num != 0 { dig = num % 10; num = num / 10; - out = show_digit(dig) + ~" " + out; + out = show_digit(dig) + " " + out; } return out; @@ -124,8 +131,8 @@ fn creature( } option::None => { // log creatures met and evil clones of self - let report = fmt!("%u", creatures_met) + ~" " + - show_number(evil_clones_met); + let report = fmt!("%u %s", + creatures_met, show_number(evil_clones_met)); to_rendezvous_log.send(report); break; } @@ -153,7 +160,7 @@ fn rendezvous(nn: uint, set: ~[color]) { let to_rendezvous = to_rendezvous.clone(); let to_rendezvous_log = to_rendezvous_log.clone(); let (from_rendezvous, to_creature) = stream(); - let from_rendezvous = Cell(from_rendezvous); + let from_rendezvous = Cell::new(from_rendezvous); do task::spawn || { creature(ii, col, from_rendezvous.take(), to_rendezvous.clone(), to_rendezvous_log.clone()); diff --git a/src/test/bench/shootout-fannkuch-redux.rs b/src/test/bench/shootout-fannkuch-redux.rs index cb32e0e496e95..b1db5843b7cdb 100644 --- a/src/test/bench/shootout-fannkuch-redux.rs +++ b/src/test/bench/shootout-fannkuch-redux.rs @@ -1,6 +1,8 @@ -use core::from_str::FromStr; -use core::i32::range; -use core::vec::MutableVector; +use std::from_str::FromStr; +use std::i32::range; +use std::os; +use std::vec::MutableVector; +use std::vec; fn max(a: i32, b: i32) -> i32 { if a > b { @@ -15,7 +17,9 @@ fn fannkuch_redux(n: i32) -> i32 { let mut perm = vec::from_elem(n as uint, 0i32); let mut perm1 = vec::from_fn(n as uint, |i| i as i32); let mut count = vec::from_elem(n as uint, 0i32); - let mut max_flips_count = 0i32, perm_count = 0i32, checksum = 0i32; + let mut max_flips_count = 0i32; + let mut perm_count = 0i32; + let mut checksum = 0i32; let mut r = n; loop { diff --git a/src/test/bench/shootout-fasta-redux.rs b/src/test/bench/shootout-fasta-redux.rs index d6a0f4b8b255e..cb9972a709fec 100644 --- a/src/test/bench/shootout-fasta-redux.rs +++ b/src/test/bench/shootout-fasta-redux.rs @@ -1,8 +1,11 @@ -use core::cast::transmute; -use core::from_str::FromStr; -use core::libc::{FILE, STDOUT_FILENO, c_int, fdopen, fputc, fputs, fwrite, size_t}; -use core::uint::{min, range}; -use core::vec::bytes::copy_memory; +use std::cast::transmute; +use std::from_str::FromStr; +use std::libc::{FILE, STDOUT_FILENO, c_int, fdopen, fputc, fputs, fwrite, size_t}; +use std::os; +use std::str; +use std::uint::{min, range}; +use std::vec::bytes::copy_memory; +use std::vec; static LINE_LEN: uint = 60; static LOOKUP_SIZE: uint = 4 * 1024; @@ -96,7 +99,9 @@ impl RepeatFasta { alu, LINE_LEN); - let mut pos = 0, bytes, n = n; + let mut pos = 0; + let mut bytes; + let mut n = n; while n > 0 { bytes = min(LINE_LEN, n); fwrite(transmute(&buf[pos]), bytes as size_t, 1, stdout); @@ -155,7 +160,8 @@ impl RandomFasta { fn make(&mut self, n: uint) { unsafe { - let lines = n / LINE_LEN, chars_left = n % LINE_LEN; + let lines = n / LINE_LEN; + let chars_left = n % LINE_LEN; let mut buf = [0, ..LINE_LEN + 1]; for lines.times { diff --git a/src/test/bench/shootout-fasta.rs b/src/test/bench/shootout-fasta.rs index 7316b68f8bd42..3cff8baa82928 100644 --- a/src/test/bench/shootout-fasta.rs +++ b/src/test/bench/shootout-fasta.rs @@ -15,8 +15,18 @@ * Computer Language Benchmarks Game * http://shootout.alioth.debian.org/ */ -extern mod std; -use core::rand::Rng; +extern mod extra; + +use std::int; +use std::io; +use std::option; +use std::os; +use std::rand::Rng; +use std::rand; +use std::result; +use std::str; +use std::uint; +use std::vec; fn LINE_LENGTH() -> uint { return 60u; } @@ -39,7 +49,7 @@ fn make_cumulative(aa: ~[AminoAcids]) -> ~[AminoAcids] { let mut ans: ~[AminoAcids] = ~[]; for aa.each |a| { cp += a.prob; - ans += ~[AminoAcids {ch: a.ch, prob: cp}]; + ans += [AminoAcids {ch: a.ch, prob: cp}]; } return ans; } @@ -62,7 +72,7 @@ fn make_random_fasta(wr: @io::Writer, desc: ~str, genelist: ~[AminoAcids], n: int) { - wr.write_line(~">" + id + ~" " + desc); + wr.write_line(~">" + id + " " + desc); let mut rng = rand::rng(); let rng = @mut MyRandom { last: rng.next() @@ -81,7 +91,7 @@ fn make_random_fasta(wr: @io::Writer, fn make_repeat_fasta(wr: @io::Writer, id: ~str, desc: ~str, s: ~str, n: int) { unsafe { - wr.write_line(~">" + id + ~" " + desc); + wr.write_line(~">" + id + " " + desc); let mut op: ~str = ~""; let sl: uint = str::len(s); for uint::range(0u, n as uint) |i| { @@ -129,13 +139,13 @@ fn main() { make_cumulative(~[acid('a', 30u32), acid('c', 20u32), acid('g', 20u32), acid('t', 30u32)]); let alu: ~str = - ~"GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG" + - ~"GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA" + - ~"CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT" + - ~"ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA" + - ~"GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG" + - ~"AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC" + - ~"AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA"; + ~"GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG\ + GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA\ + CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT\ + ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA\ + GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG\ + AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC\ + AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA"; make_repeat_fasta(writer, ~"ONE", ~"Homo sapiens alu", alu, n * 2); make_random_fasta(writer, ~"TWO", ~"IUB ambiguity codes", iub, n * 3); make_random_fasta(writer, ~"THREE", diff --git a/src/test/bench/shootout-fibo.rs b/src/test/bench/shootout-fibo.rs index b080aded8c45e..a1bb0e9e6d8d5 100644 --- a/src/test/bench/shootout-fibo.rs +++ b/src/test/bench/shootout-fibo.rs @@ -8,7 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; +extern mod extra; + +use std::int; +use std::io; +use std::os; fn fib(n: int) -> int { if n < 2 { diff --git a/src/test/bench/shootout-k-nucleotide-pipes.rs b/src/test/bench/shootout-k-nucleotide-pipes.rs index 3c32ec338b7ec..e403ba6e73dec 100644 --- a/src/test/bench/shootout-k-nucleotide-pipes.rs +++ b/src/test/bench/shootout-k-nucleotide-pipes.rs @@ -11,13 +11,22 @@ // xfail-pretty (extra blank line is inserted in vec::mapi call) // multi tasking k-nucleotide -extern mod std; -use std::sort; -use core::hashmap::HashMap; -use core::io::ReaderUtil; -use core::comm::{stream, Port, Chan}; -use core::cmp::Ord; -use core::util; +extern mod extra; + +use extra::sort; +use std::cmp::Ord; +use std::comm::{stream, Port, Chan}; +use std::comm; +use std::hashmap::HashMap; +use std::io::ReaderUtil; +use std::io; +use std::option; +use std::os; +use std::result; +use std::str; +use std::task; +use std::util; +use std::vec; // given a map, print a sorted version of it fn sort_and_fmt(mm: &HashMap<~[u8], uint>, total: uint) -> ~str { diff --git a/src/test/bench/shootout-k-nucleotide.rs b/src/test/bench/shootout-k-nucleotide.rs index 1791af67ed040..a70e073007306 100644 --- a/src/test/bench/shootout-k-nucleotide.rs +++ b/src/test/bench/shootout-k-nucleotide.rs @@ -1,15 +1,15 @@ // xfail-test -extern mod std; - -use core::cast::transmute; -use core::i32::range; -use core::libc::{STDIN_FILENO, c_int, fdopen, fgets, fileno, fopen, fstat}; -use core::libc::{stat, strlen}; -use core::ptr::null; -use core::unstable::intrinsics::init; -use core::vec::{reverse, slice}; -use std::sort::quick_sort3; +extern mod extra; + +use std::cast::transmute; +use std::i32::range; +use std::libc::{STDIN_FILENO, c_int, fdopen, fgets, fileno, fopen, fstat}; +use std::libc::{stat, strlen}; +use std::ptr::null; +use std::unstable::intrinsics::init; +use std::vec::{reverse, slice}; +use extra::sort::quick_sort3; static LINE_LEN: uint = 80; static TABLE: [u8, ..4] = [ 'A' as u8, 'C' as u8, 'G' as u8, 'T' as u8 ]; diff --git a/src/test/bench/shootout-mandelbrot.rs b/src/test/bench/shootout-mandelbrot.rs index 7d2b25792ec57..70f56f5c5a399 100644 --- a/src/test/bench/shootout-mandelbrot.rs +++ b/src/test/bench/shootout-mandelbrot.rs @@ -1,7 +1,8 @@ -use core::cast::transmute; -use core::from_str::FromStr; -use core::i32::range; -use core::libc::{STDOUT_FILENO, c_int, fdopen, fputc}; +use std::cast::transmute; +use std::from_str::FromStr; +use std::i32::range; +use std::libc::{STDOUT_FILENO, c_int, fdopen, fputc}; +use std::os; static ITER: uint = 50; static LIMIT: f64 = 2.0; @@ -9,7 +10,8 @@ static LIMIT: f64 = 2.0; #[fixed_stack_segment] fn main() { unsafe { - let w: i32 = FromStr::from_str(os::args()[1]).get(), h = w; + let w: i32 = FromStr::from_str(os::args()[1]).get(); + let h = w; let mut byte_acc: i8 = 0; let mut bit_num: i32 = 0; diff --git a/src/test/bench/shootout-nbody.rs b/src/test/bench/shootout-nbody.rs index da06b36af67ee..242b3a3f7a4f6 100644 --- a/src/test/bench/shootout-nbody.rs +++ b/src/test/bench/shootout-nbody.rs @@ -1,5 +1,8 @@ -use core::from_str::FromStr; -use core::uint::range; +use std::f64; +use std::from_str::FromStr; +use std::os; +use std::uint::range; +use std::vec; static PI: f64 = 3.141592653589793; static SOLAR_MASS: f64 = 4.0 * PI * PI; @@ -89,7 +92,8 @@ fn advance(bodies: &mut [Planet, ..N_BODIES], dt: f64, steps: i32) { let d2 = d[0]*d[0] + d[1]*d[1] + d[2]*d[2]; let mag = dt / (d2 * f64::sqrt(d2)); - let a_mass = bodies[i].mass, b_mass = bodies[j].mass; + let a_mass = bodies[i].mass; + let b_mass = bodies[j].mass; bodies[i].v[0] -= d[0] * b_mass * mag; bodies[i].v[1] -= d[1] * b_mass * mag; bodies[i].v[2] -= d[2] * b_mass * mag; diff --git a/src/test/bench/shootout-pfib.rs b/src/test/bench/shootout-pfib.rs index b7ae331c8f376..0a093d87a1586 100644 --- a/src/test/bench/shootout-pfib.rs +++ b/src/test/bench/shootout-pfib.rs @@ -19,14 +19,20 @@ */ -extern mod std; - -use std::{time, getopts}; -use core::int::range; -use core::comm::*; -use core::io::WriterUtil; - -use core::result::{Ok, Err}; +extern mod extra; + +use extra::{time, getopts}; +use std::comm::*; +use std::int::range; +use std::io::WriterUtil; +use std::io; +use std::os; +use std::result::{Ok, Err}; +use std::str; +use std::task; +use std::u64; +use std::uint; +use std::vec; fn fib(n: int) -> int { fn pfib(c: &Chan, n: int) { @@ -70,7 +76,7 @@ fn stress_task(id: int) { let mut i = 0; loop { let n = 15; - assert!((fib(n) == fib(n))); + assert_eq!(fib(n), fib(n)); i += 1; error!("%d: Completed %d iterations", id, i); } diff --git a/src/test/bench/shootout-pidigits.rs b/src/test/bench/shootout-pidigits.rs index cb7fa969be7a7..e84a4ea4327aa 100644 --- a/src/test/bench/shootout-pidigits.rs +++ b/src/test/bench/shootout-pidigits.rs @@ -1,10 +1,10 @@ // xfail-test -use core::cast::transmute; -use core::from_str::FromStr; -use core::libc::{STDOUT_FILENO, c_char, c_int, c_uint, c_void, fdopen, fputc}; -use core::libc::{fputs}; -use core::ptr::null; +use std::cast::transmute; +use std::from_str::FromStr; +use std::libc::{STDOUT_FILENO, c_char, c_int, c_uint, c_void, fdopen, fputc}; +use std::libc::{fputs}; +use std::ptr::null; struct mpz_t { _mp_alloc: c_int, diff --git a/src/test/bench/shootout-reverse-complement.rs b/src/test/bench/shootout-reverse-complement.rs index a9cb3c7636a9b..9893785ecfa22 100644 --- a/src/test/bench/shootout-reverse-complement.rs +++ b/src/test/bench/shootout-reverse-complement.rs @@ -1,12 +1,12 @@ // xfail-pretty // xfail-test -use core::cast::transmute; -use core::libc::{STDOUT_FILENO, c_int, fdopen, fgets, fopen, fputc, fwrite}; -use core::libc::{size_t}; -use core::ptr::null; -use core::vec::{capacity, reserve, reserve_at_least}; -use core::vec::raw::set_len; +use std::cast::transmute; +use std::libc::{STDOUT_FILENO, c_int, fdopen, fgets, fopen, fputc, fwrite}; +use std::libc::{size_t}; +use std::ptr::null; +use std::vec::{capacity, reserve, reserve_at_least}; +use std::vec::raw::set_len; static LINE_LEN: u32 = 80; diff --git a/src/test/bench/shootout-spectralnorm.rs b/src/test/bench/shootout-spectralnorm.rs index 6840384ca7c8a..1623eaaa7d3c3 100644 --- a/src/test/bench/shootout-spectralnorm.rs +++ b/src/test/bench/shootout-spectralnorm.rs @@ -1,5 +1,8 @@ -use core::from_str::FromStr; -use core::iter::ExtendedMutableIter; +use std::f64; +use std::from_str::FromStr; +use std::iter::ExtendedMutableIter; +use std::os; +use std::vec; #[inline] fn A(i: i32, j: i32) -> i32 { @@ -42,7 +45,9 @@ fn mult_AtAv(v: &mut [f64], out: &mut [f64], tmp: &mut [f64]) { #[fixed_stack_segment] fn main() { let n: uint = FromStr::from_str(os::args()[1]).get(); - let mut u = vec::from_elem(n, 1f64), v = u.clone(), tmp = u.clone(); + let mut u = vec::from_elem(n, 1f64); + let mut v = u.clone(); + let mut tmp = u.clone(); for 8.times { mult_AtAv(u, v, tmp); mult_AtAv(v, u, tmp); diff --git a/src/test/bench/std-smallintmap.rs b/src/test/bench/std-smallintmap.rs index 4b0d34d231511..23ac68315e3a0 100644 --- a/src/test/bench/std-smallintmap.rs +++ b/src/test/bench/std-smallintmap.rs @@ -10,9 +10,13 @@ // Microbenchmark for the smallintmap library -extern mod std; -use std::smallintmap::SmallIntMap; -use core::io::WriterUtil; +extern mod extra; + +use extra::smallintmap::SmallIntMap; +use std::io::WriterUtil; +use std::io; +use std::os; +use std::uint; fn append_sequential(min: uint, max: uint, map: &mut SmallIntMap) { for uint::range(min, max) |i| { @@ -22,7 +26,7 @@ fn append_sequential(min: uint, max: uint, map: &mut SmallIntMap) { fn check_sequential(min: uint, max: uint, map: &SmallIntMap) { for uint::range(min, max) |i| { - assert!(*map.get(&i) == i + 22u); + assert_eq!(*map.get(&i), i + 22u); } } @@ -43,11 +47,11 @@ fn main() { for uint::range(0u, rep) |_r| { let mut map = SmallIntMap::new(); - let start = std::time::precise_time_s(); + let start = extra::time::precise_time_s(); append_sequential(0u, max, &mut map); - let mid = std::time::precise_time_s(); + let mid = extra::time::precise_time_s(); check_sequential(0u, max, &map); - let end = std::time::precise_time_s(); + let end = extra::time::precise_time_s(); checkf += (end - mid) as float; appendf += (mid - start) as float; diff --git a/src/test/bench/sudoku.rs b/src/test/bench/sudoku.rs index c18c1eaedd613..3bf08cfb934f8 100644 --- a/src/test/bench/sudoku.rs +++ b/src/test/bench/sudoku.rs @@ -10,11 +10,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; +extern mod extra; -use core::io::{ReaderUtil, WriterUtil}; -use core::io; -use core::unstable::intrinsics::cttz16; +use std::io::{ReaderUtil, WriterUtil}; +use std::io; +use std::os; +use std::str; +use std::u8; +use std::uint; +use std::unstable::intrinsics::cttz16; +use std::vec; // Computes a single solution to a given 9x9 sudoku // @@ -39,7 +44,7 @@ struct Sudoku { grid: grid } -pub impl Sudoku { +impl Sudoku { pub fn new(g: grid) -> Sudoku { return Sudoku { grid: g } } @@ -98,7 +103,7 @@ pub impl Sudoku { for u8::range(0u8, 9u8) |row| { for u8::range(0u8, 9u8) |col| { let color = self.grid[row][col]; - if color == 0u8 { work += ~[(row, col)]; } + if color == 0u8 { work += [(row, col)]; } } } @@ -167,10 +172,10 @@ impl Colors { let val = **self & heads; if (0u16 == val) { return 0u8; - } - else - { - return cttz16(val as i16) as u8; + } else { + unsafe { + return cttz16(val as i16) as u8; + } } } @@ -212,30 +217,30 @@ static default_solution: [[u8, ..9], ..9] = [ #[test] fn colors_new_works() { - assert!(*Colors::new(1) == 1022u16); - assert!(*Colors::new(2) == 1020u16); - assert!(*Colors::new(3) == 1016u16); - assert!(*Colors::new(4) == 1008u16); - assert!(*Colors::new(5) == 992u16); - assert!(*Colors::new(6) == 960u16); - assert!(*Colors::new(7) == 896u16); - assert!(*Colors::new(8) == 768u16); - assert!(*Colors::new(9) == 512u16); + assert_eq!(*Colors::new(1), 1022u16); + assert_eq!(*Colors::new(2), 1020u16); + assert_eq!(*Colors::new(3), 1016u16); + assert_eq!(*Colors::new(4), 1008u16); + assert_eq!(*Colors::new(5), 992u16); + assert_eq!(*Colors::new(6), 960u16); + assert_eq!(*Colors::new(7), 896u16); + assert_eq!(*Colors::new(8), 768u16); + assert_eq!(*Colors::new(9), 512u16); } #[test] fn colors_next_works() { - assert!(Colors(0).next() == 0u8); - assert!(Colors(2).next() == 1u8); - assert!(Colors(4).next() == 2u8); - assert!(Colors(8).next() == 3u8); - assert!(Colors(16).next() == 4u8); - assert!(Colors(32).next() == 5u8); - assert!(Colors(64).next() == 6u8); - assert!(Colors(128).next() == 7u8); - assert!(Colors(256).next() == 8u8); - assert!(Colors(512).next() == 9u8); - assert!(Colors(1024).next() == 0u8); + assert_eq!(Colors(0).next(), 0u8); + assert_eq!(Colors(2).next(), 1u8); + assert_eq!(Colors(4).next(), 2u8); + assert_eq!(Colors(8).next(), 3u8); + assert_eq!(Colors(16).next(), 4u8); + assert_eq!(Colors(32).next(), 5u8); + assert_eq!(Colors(64).next(), 6u8); + assert_eq!(Colors(128).next(), 7u8); + assert_eq!(Colors(256).next(), 8u8); + assert_eq!(Colors(512).next(), 9u8); + assert_eq!(Colors(1024).next(), 0u8); } #[test] @@ -247,7 +252,7 @@ fn colors_remove_works() { colors.remove(1); // THEN - assert!(colors.next() == 2u8); + assert_eq!(colors.next(), 2u8); } #[test] diff --git a/src/test/bench/task-perf-alloc-unwind.rs b/src/test/bench/task-perf-alloc-unwind.rs index 2588916705045..7a04a06d6a64d 100644 --- a/src/test/bench/task-perf-alloc-unwind.rs +++ b/src/test/bench/task-perf-alloc-unwind.rs @@ -10,10 +10,12 @@ // xfail-win32 -extern mod std; +extern mod extra; -use std::list::{List, Cons, Nil}; -use std::time::precise_time_s; +use extra::list::{List, Cons, Nil}; +use extra::time::precise_time_s; +use std::os; +use std::task; enum UniqueList { ULNil, ULCons(~UniqueList) @@ -30,7 +32,7 @@ fn main() { } fn run(repeat: int, depth: int) { - for old_iter::repeat(repeat as uint) { + for (repeat as uint).times { debug!("starting %.4f", precise_time_s()); do task::try { recurse_or_fail(depth, None) @@ -94,7 +96,7 @@ fn recurse_or_fail(depth: int, st: Option) { fn_box: || @Cons((), fn_box()), tuple: (@Cons((), st.tuple.first()), ~Cons((), @*st.tuple.second())), - vec: st.vec + ~[@Cons((), *st.vec.last())], + vec: st.vec + [@Cons((), *st.vec.last())], res: r(@Cons((), st.res._l)) } } diff --git a/src/test/bench/task-perf-jargon-metal-smoke.rs b/src/test/bench/task-perf-jargon-metal-smoke.rs index a6eaf89231089..e5732b7d5800e 100644 --- a/src/test/bench/task-perf-jargon-metal-smoke.rs +++ b/src/test/bench/task-perf-jargon-metal-smoke.rs @@ -17,13 +17,17 @@ // // The filename is a song reference; google it in quotes. -use core::cell::Cell; +use std::cell::Cell; +use std::comm; +use std::os; +use std::task; +use std::uint; fn child_generation(gens_left: uint, c: comm::Chan<()>) { // This used to be O(n^2) in the number of generations that ever existed. // With this code, only as many generations are alive at a time as tasks // alive at a time, - let c = Cell(c); + let c = Cell::new(c); do task::spawn_supervised { let c = c.take(); if gens_left & 1 == 1 { diff --git a/src/test/bench/task-perf-linked-failure.rs b/src/test/bench/task-perf-linked-failure.rs index 6015f21be727f..514b85c6ae05f 100644 --- a/src/test/bench/task-perf-linked-failure.rs +++ b/src/test/bench/task-perf-linked-failure.rs @@ -22,7 +22,11 @@ // Creates in the background 'num_tasks' tasks, all blocked forever. // Doesn't return until all such tasks are ready, but doesn't block forever itself. -use core::comm::*; +use std::comm::*; +use std::os; +use std::result; +use std::task; +use std::uint; fn grandchild_group(num_tasks: uint) { let (po, ch) = stream(); @@ -54,7 +58,7 @@ fn spawn_supervised_blocking(myname: &str, f: ~fn()) { builder.spawn(f); error!("%s group waiting", myname); let x = res.unwrap().recv(); - assert!(x == task::Success); + assert_eq!(x, task::Success); } fn main() { diff --git a/src/test/bench/task-perf-one-million.rs b/src/test/bench/task-perf-one-million.rs index 8e1cbb9e17bdd..e1a5253444f88 100644 --- a/src/test/bench/task-perf-one-million.rs +++ b/src/test/bench/task-perf-one-million.rs @@ -10,7 +10,11 @@ // Test for concurrent tasks -use core::comm::*; +use std::comm::*; +use std::os; +use std::task; +use std::uint; +use std::vec; fn calc(children: uint, parent_wait_chan: &Chan>>) { diff --git a/src/test/bench/task-perf-spawnalot.rs b/src/test/bench/task-perf-spawnalot.rs index e6da898a03493..1a8fc7e098ddb 100644 --- a/src/test/bench/task-perf-spawnalot.rs +++ b/src/test/bench/task-perf-spawnalot.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::os; +use std::task; +use std::uint; + fn f(n: uint) { let mut i = 0u; while i < n { diff --git a/src/test/compile-fail/arc-cant-nest-rw-arc-3177.rs b/src/test/compile-fail/arc-cant-nest-rw-arc-3177.rs index 7806436ef83b7..3dafb076afefb 100644 --- a/src/test/compile-fail/arc-cant-nest-rw-arc-3177.rs +++ b/src/test/compile-fail/arc-cant-nest-rw-arc-3177.rs @@ -10,8 +10,8 @@ // xfail-test // error-pattern: instantiating a type parameter with an incompatible type -extern mod std; -use std::arc::rw_arc; +extern mod extra; +use extra::arc::rw_arc; fn main() { let arc1 = ~rw_arc(true); diff --git a/src/test/compile-fail/arc-rw-cond-shouldnt-escape.rs b/src/test/compile-fail/arc-rw-cond-shouldnt-escape.rs index f59eb509156ac..82868647e57da 100644 --- a/src/test/compile-fail/arc-rw-cond-shouldnt-escape.rs +++ b/src/test/compile-fail/arc-rw-cond-shouldnt-escape.rs @@ -9,8 +9,8 @@ // except according to those terms. // error-pattern: reference is not valid outside of its lifetime -extern mod std; -use std::arc; +extern mod extra; +use extra::arc; fn main() { let x = ~arc::RWARC(1); let mut y = None; diff --git a/src/test/compile-fail/arc-rw-read-mode-shouldnt-escape.rs b/src/test/compile-fail/arc-rw-read-mode-shouldnt-escape.rs index 85f60f34bdb80..6d4b774fd5f60 100644 --- a/src/test/compile-fail/arc-rw-read-mode-shouldnt-escape.rs +++ b/src/test/compile-fail/arc-rw-read-mode-shouldnt-escape.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; -use std::arc; +extern mod extra; +use extra::arc; fn main() { let x = ~arc::RWARC(1); let mut y = None; diff --git a/src/test/compile-fail/arc-rw-state-shouldnt-escape.rs b/src/test/compile-fail/arc-rw-state-shouldnt-escape.rs index 22f5a8eac03d2..6bd32866f8989 100644 --- a/src/test/compile-fail/arc-rw-state-shouldnt-escape.rs +++ b/src/test/compile-fail/arc-rw-state-shouldnt-escape.rs @@ -9,8 +9,8 @@ // except according to those terms. // error-pattern: reference is not valid outside of its lifetime -extern mod std; -use std::arc; +extern mod extra; +use extra::arc; fn main() { let x = ~arc::RWARC(1); let mut y = None; diff --git a/src/test/compile-fail/arc-rw-write-mode-cond-shouldnt-escape.rs b/src/test/compile-fail/arc-rw-write-mode-cond-shouldnt-escape.rs index c8273cb016797..534475319033f 100644 --- a/src/test/compile-fail/arc-rw-write-mode-cond-shouldnt-escape.rs +++ b/src/test/compile-fail/arc-rw-write-mode-cond-shouldnt-escape.rs @@ -9,8 +9,8 @@ // except according to those terms. // error-pattern: reference is not valid outside of its lifetime -extern mod std; -use std::arc; +extern mod extra; +use extra::arc; fn main() { let x = ~arc::RWARC(1); let mut y = None; diff --git a/src/test/compile-fail/arc-rw-write-mode-shouldnt-escape.rs b/src/test/compile-fail/arc-rw-write-mode-shouldnt-escape.rs index c7ae6a0dc6c52..decb7b8af9f3a 100644 --- a/src/test/compile-fail/arc-rw-write-mode-shouldnt-escape.rs +++ b/src/test/compile-fail/arc-rw-write-mode-shouldnt-escape.rs @@ -9,8 +9,8 @@ // except according to those terms. // error-pattern: reference is not valid outside of its lifetime -extern mod std; -use std::arc; +extern mod extra; +use extra::arc; fn main() { let x = ~arc::RWARC(1); let mut y = None; diff --git a/src/test/compile-fail/assign-to-method.rs b/src/test/compile-fail/assign-to-method.rs index 4993846f44559..85bb60e05853e 100644 --- a/src/test/compile-fail/assign-to-method.rs +++ b/src/test/compile-fail/assign-to-method.rs @@ -9,14 +9,13 @@ // except according to those terms. struct cat { - priv mut meows : uint, + priv meows : uint, how_hungry : int, } -pub impl cat { - - fn speak(&self) { self.meows += 1u; } +impl cat { + pub fn speak(&self) { self.meows += 1u; } } fn cat(in_x : uint, in_y : int) -> cat { diff --git a/src/test/compile-fail/attr-before-ext.rs b/src/test/compile-fail/attr-before-ext.rs index 2675b865e9017..cf0f4a6240e2b 100644 --- a/src/test/compile-fail/attr-before-ext.rs +++ b/src/test/compile-fail/attr-before-ext.rs @@ -9,6 +9,6 @@ // except according to those terms. fn main() { - #[attr] - debug!("hi"); //~ ERROR expected item after attrs + #[attr] //~ ERROR expected item after attributes + debug!("hi"); } diff --git a/src/test/compile-fail/attr-before-let.rs b/src/test/compile-fail/attr-before-let.rs index 51ee903b1b1db..acc9aa8a9a13e 100644 --- a/src/test/compile-fail/attr-before-let.rs +++ b/src/test/compile-fail/attr-before-let.rs @@ -9,6 +9,6 @@ // except according to those terms. fn main() { - #[attr] - let _i = 0; //~ ERROR expected item + #[attr] //~ ERROR expected item + let _i = 0; } diff --git a/src/test/compile-fail/autoderef-full-lval.rs b/src/test/compile-fail/autoderef-full-lval.rs index ecd31d0dde456..e38c22004ed13 100644 --- a/src/test/compile-fail/autoderef-full-lval.rs +++ b/src/test/compile-fail/autoderef-full-lval.rs @@ -22,10 +22,10 @@ fn main() { let b: clam = clam{x: @10, y: @20}; let z: int = a.x + b.y; //~ ERROR binary operation + cannot be applied to type `@int` debug!(z); - assert!((z == 21)); + assert_eq!(z, 21); let forty: fish = fish{a: @40}; let two: fish = fish{a: @2}; let answer: int = forty.a + two.a; //~ ERROR binary operation + cannot be applied to type `@int` debug!(answer); - assert!((answer == 42)); + assert_eq!(answer, 42); } diff --git a/src/test/compile-fail/bad-alt.rs b/src/test/compile-fail/bad-match.rs similarity index 100% rename from src/test/compile-fail/bad-alt.rs rename to src/test/compile-fail/bad-match.rs diff --git a/src/test/compile-fail/bind-by-move-no-guards.rs b/src/test/compile-fail/bind-by-move-no-guards.rs index ffc160ac11118..348781d74977e 100644 --- a/src/test/compile-fail/bind-by-move-no-guards.rs +++ b/src/test/compile-fail/bind-by-move-no-guards.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::comm; + fn main() { let (p,c) = comm::stream(); let x = Some(p); diff --git a/src/test/compile-fail/block-arg-as-stmt-with-value.rs b/src/test/compile-fail/block-arg-as-stmt-with-value.rs index 42c5ffe3e916b..dc90dfb2cadde 100644 --- a/src/test/compile-fail/block-arg-as-stmt-with-value.rs +++ b/src/test/compile-fail/block-arg-as-stmt-with-value.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::vec; fn compute1() -> float { let v = ~[0f, 1f, 2f, 3f]; @@ -19,5 +20,5 @@ fn compute1() -> float { fn main() { let x = compute1(); debug!(x); - assert!((x == -4f)); + assert_eq!(x, -4f); } diff --git a/src/test/compile-fail/block-must-not-have-result-for.rs b/src/test/compile-fail/block-must-not-have-result-for.rs index d1e001f722c3f..778309122cba1 100644 --- a/src/test/compile-fail/block-must-not-have-result-for.rs +++ b/src/test/compile-fail/block-must-not-have-result-for.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::vec; + fn main() { for vec::each(~[0]) |_i| { //~ ERROR A for-loop body must return (), but true diff --git a/src/test/compile-fail/borrowck-alias-mut-base-ptr.rs b/src/test/compile-fail/borrowck-alias-mut-base-ptr.rs new file mode 100644 index 0000000000000..c51cf5b9538d9 --- /dev/null +++ b/src/test/compile-fail/borrowck-alias-mut-base-ptr.rs @@ -0,0 +1,15 @@ +// Test that attempt to alias `&mut` pointer while pointee is borrowed +// yields an error. +// +// Example from src/middle/borrowck/doc.rs + +use std::util::swap; + +fn foo(t0: &mut int) { + let p: &int = &*t0; // Freezes `*t0` + let q: &const &mut int = &const t0; //~ ERROR cannot borrow `t0` + **q = 22; //~ ERROR cannot assign to an `&mut` in a `&const` pointer +} + +fn main() { +} \ No newline at end of file diff --git a/src/test/compile-fail/borrowck-anon-fields-struct.rs b/src/test/compile-fail/borrowck-anon-fields-struct.rs new file mode 100644 index 0000000000000..45a26068d8285 --- /dev/null +++ b/src/test/compile-fail/borrowck-anon-fields-struct.rs @@ -0,0 +1,37 @@ +// Tests that we are able to distinguish when loans borrow different +// anonymous fields of an tuple vs the same anonymous field. + +struct Y(uint, uint); + +fn distinct_variant() { + let mut y = Y(1, 2); + + let a = match y { + Y(ref mut a, _) => a + }; + + let b = match y { + Y(_, ref mut b) => b + }; + + *a += 1; + *b += 1; +} + +fn same_variant() { + let mut y = Y(1, 2); + + let a = match y { + Y(ref mut a, _) => a + }; + + let b = match y { + Y(ref mut b, _) => b //~ ERROR cannot borrow + }; + + *a += 1; + *b += 1; +} + +fn main() { +} \ No newline at end of file diff --git a/src/test/compile-fail/borrowck-anon-fields-tuple.rs b/src/test/compile-fail/borrowck-anon-fields-tuple.rs new file mode 100644 index 0000000000000..ae02245c97f52 --- /dev/null +++ b/src/test/compile-fail/borrowck-anon-fields-tuple.rs @@ -0,0 +1,35 @@ +// Tests that we are able to distinguish when loans borrow different +// anonymous fields of a tuple vs the same anonymous field. + +fn distinct_variant() { + let mut y = (1, 2); + + let a = match y { + (ref mut a, _) => a + }; + + let b = match y { + (_, ref mut b) => b + }; + + *a += 1; + *b += 1; +} + +fn same_variant() { + let mut y = (1, 2); + + let a = match y { + (ref mut a, _) => a + }; + + let b = match y { + (ref mut b, _) => b //~ ERROR cannot borrow + }; + + *a += 1; + *b += 1; +} + +fn main() { +} \ No newline at end of file diff --git a/src/test/compile-fail/borrowck-anon-fields-variant.rs b/src/test/compile-fail/borrowck-anon-fields-variant.rs new file mode 100644 index 0000000000000..3d9738df059ca --- /dev/null +++ b/src/test/compile-fail/borrowck-anon-fields-variant.rs @@ -0,0 +1,43 @@ +// Tests that we are able to distinguish when loans borrow different +// anonymous fields of an enum variant vs the same anonymous field. + +enum Foo { + X, Y(uint, uint) +} + +fn distinct_variant() { + let mut y = Y(1, 2); + + let a = match y { + Y(ref mut a, _) => a, + X => fail!() + }; + + let b = match y { + Y(_, ref mut b) => b, + X => fail!() + }; + + *a += 1; + *b += 1; +} + +fn same_variant() { + let mut y = Y(1, 2); + + let a = match y { + Y(ref mut a, _) => a, + X => fail!() + }; + + let b = match y { + Y(ref mut b, _) => b, //~ ERROR cannot borrow + X => fail!() + }; + + *a += 1; + *b += 1; +} + +fn main() { +} \ No newline at end of file diff --git a/src/test/compile-fail/borrowck-auto-mut-ref-to-immut-var.rs b/src/test/compile-fail/borrowck-auto-mut-ref-to-immut-var.rs index 2ba5d0473cc62..e2fbce6e195f5 100644 --- a/src/test/compile-fail/borrowck-auto-mut-ref-to-immut-var.rs +++ b/src/test/compile-fail/borrowck-auto-mut-ref-to-immut-var.rs @@ -10,12 +10,14 @@ // Tests that auto-ref can't create mutable aliases to immutable memory. +use std::io; + struct Foo { x: int } -pub impl Foo { - fn printme(&mut self) { +impl Foo { + pub fn printme(&mut self) { io::println(fmt!("%d", self.x)); } } diff --git a/src/test/compile-fail/borrowck-autoref-3261.rs b/src/test/compile-fail/borrowck-autoref-3261.rs index 192fe669f57ae..4bbd1b0decf57 100644 --- a/src/test/compile-fail/borrowck-autoref-3261.rs +++ b/src/test/compile-fail/borrowck-autoref-3261.rs @@ -10,11 +10,12 @@ struct X(Either<(uint,uint),extern fn()>); -pub impl X { - fn with(&self, blk: &fn(x: &Either<(uint,uint),extern fn()>)) { +impl X { + pub fn with(&self, blk: &fn(x: &Either<(uint,uint),extern fn()>)) { blk(&**self) } } + fn main() { let mut x = X(Right(main)); do (&mut x).with |opt| { diff --git a/src/test/compile-fail/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs b/src/test/compile-fail/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs new file mode 100644 index 0000000000000..7e9c298ba4732 --- /dev/null +++ b/src/test/compile-fail/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs @@ -0,0 +1,31 @@ +// Test that attempt to reborrow an `&mut` pointer in an aliasable +// location yields an error. +// +// Example from src/middle/borrowck/doc.rs + +use std::util::swap; + +fn foo(t0: & &mut int) { + let t1 = t0; + let p: &int = &**t0; //~ ERROR cannot borrow an `&mut` in a `&` pointer + **t1 = 22; //~ ERROR cannot assign +} + +fn foo2(t0: &const &mut int) { + // Note: reborrowing from an &const actually yields two errors, since it + // is unsafe in two ways: we can't control the aliasing, and we can't + // control the mutation. + let t1 = t0; + let p: &int = &**t0; //~ ERROR cannot borrow an `&mut` in a `&const` pointer + //~^ ERROR unsafe borrow of aliasable, const value + **t1 = 22; //~ ERROR cannot assign +} + +fn foo3(t0: &mut &mut int) { + let t1 = &mut *t0; + let p: &int = &**t0; //~ ERROR cannot borrow + **t1 = 22; +} + +fn main() { +} \ No newline at end of file diff --git a/src/test/compile-fail/borrowck-borrowed-uniq-rvalue.rs b/src/test/compile-fail/borrowck-borrowed-uniq-rvalue.rs index 887cb59930ebc..bd87a57af2570 100644 --- a/src/test/compile-fail/borrowck-borrowed-uniq-rvalue.rs +++ b/src/test/compile-fail/borrowck-borrowed-uniq-rvalue.rs @@ -10,7 +10,7 @@ //buggy.rs -use core::hashmap::HashMap; +use std::hashmap::HashMap; fn main() { let mut buggy_map :HashMap = diff --git a/src/test/compile-fail/borrowck-call-method-from-mut-aliasable.rs b/src/test/compile-fail/borrowck-call-method-from-mut-aliasable.rs index 3abd19e5a1136..0aa7cbf50b7a3 100644 --- a/src/test/compile-fail/borrowck-call-method-from-mut-aliasable.rs +++ b/src/test/compile-fail/borrowck-call-method-from-mut-aliasable.rs @@ -12,10 +12,10 @@ struct Foo { x: int, } -pub impl Foo { - fn f(&self) {} - fn g(&const self) {} - fn h(&mut self) {} +impl Foo { + pub fn f(&self) {} + pub fn g(&const self) {} + pub fn h(&mut self) {} } fn a(x: &mut Foo) { diff --git a/src/test/compile-fail/borrowck-insert-during-each.rs b/src/test/compile-fail/borrowck-insert-during-each.rs index 109753b38e70b..1a0bec7d723b3 100644 --- a/src/test/compile-fail/borrowck-insert-during-each.rs +++ b/src/test/compile-fail/borrowck-insert-during-each.rs @@ -8,18 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::hashmap::HashSet; +use std::hashmap::HashSet; struct Foo { n: HashSet, } -pub impl Foo { - fn foo(&mut self, fun: &fn(&int)) { - for self.n.each |f| { - fun(f); +impl Foo { + pub fn foo(&mut self, fun: &fn(&int)) { + for self.n.each |f| { + fun(f); + } } - } } fn bar(f: &mut Foo) { diff --git a/src/test/compile-fail/borrowck-lend-flow-loop.rs b/src/test/compile-fail/borrowck-lend-flow-loop.rs index f7a72d6e6108c..e66acddd05e2b 100644 --- a/src/test/compile-fail/borrowck-lend-flow-loop.rs +++ b/src/test/compile-fail/borrowck-lend-flow-loop.rs @@ -49,7 +49,8 @@ fn block_overarching_alias_mut() { fn loop_aliased_mut() { // In this instance, the borrow is carried through the loop. - let mut v = ~3, w = ~4; + let mut v = ~3; + let mut w = ~4; let mut _x = &w; loop { borrow_mut(v); //~ ERROR cannot borrow @@ -60,7 +61,8 @@ fn loop_aliased_mut() { fn while_aliased_mut() { // In this instance, the borrow is carried through the loop. - let mut v = ~3, w = ~4; + let mut v = ~3; + let mut w = ~4; let mut _x = &w; while cond() { borrow_mut(v); //~ ERROR cannot borrow @@ -71,7 +73,8 @@ fn while_aliased_mut() { fn for_loop_aliased_mut() { // In this instance, the borrow is carried through the loop. - let mut v = ~3, w = ~4; + let mut v = ~3; + let mut w = ~4; let mut _x = &w; for for_func { borrow_mut(v); //~ ERROR cannot borrow @@ -82,7 +85,8 @@ fn for_loop_aliased_mut() { fn loop_aliased_mut_break() { // In this instance, the borrow is carried through the loop. - let mut v = ~3, w = ~4; + let mut v = ~3; + let mut w = ~4; let mut _x = &w; loop { borrow_mut(v); @@ -95,7 +99,8 @@ fn loop_aliased_mut_break() { fn while_aliased_mut_break() { // In this instance, the borrow is carried through the loop. - let mut v = ~3, w = ~4; + let mut v = ~3; + let mut w = ~4; let mut _x = &w; while cond() { borrow_mut(v); @@ -108,7 +113,8 @@ fn while_aliased_mut_break() { fn for_aliased_mut_break() { // In this instance, the borrow is carried through the loop. - let mut v = ~3, w = ~4; + let mut v = ~3; + let mut w = ~4; let mut _x = &w; for for_func { // here we cannot be sure that `for_func` respects the break below @@ -120,7 +126,8 @@ fn for_aliased_mut_break() { } fn while_aliased_mut_cond(cond: bool, cond2: bool) { - let mut v = ~3, w = ~4; + let mut v = ~3; + let mut w = ~4; let mut x = &mut w; while cond { **x += 1; diff --git a/src/test/compile-fail/borrowck-loan-blocks-move-cc.rs b/src/test/compile-fail/borrowck-loan-blocks-move-cc.rs index 50dd815d49302..1e74e91a82196 100644 --- a/src/test/compile-fail/borrowck-loan-blocks-move-cc.rs +++ b/src/test/compile-fail/borrowck-loan-blocks-move-cc.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::task; + fn borrow(v: &int, f: &fn(x: &int)) { f(v); } diff --git a/src/test/compile-fail/borrowck-loan-blocks-mut-uniq.rs b/src/test/compile-fail/borrowck-loan-blocks-mut-uniq.rs index f8415a38573c4..ae8779eafcc70 100644 --- a/src/test/compile-fail/borrowck-loan-blocks-mut-uniq.rs +++ b/src/test/compile-fail/borrowck-loan-blocks-mut-uniq.rs @@ -16,8 +16,8 @@ fn box_imm() { let mut v = ~3; do borrow(v) |w| { v = ~4; //~ ERROR cannot assign to `v` because it is borrowed - assert!(*v == 3); - assert!(*w == 4); + assert_eq!(*v, 3); + assert_eq!(*w, 4); } } diff --git a/src/test/compile-fail/borrowck-loan-local-as-both-mut-and-imm.rs b/src/test/compile-fail/borrowck-loan-local-as-both-mut-and-imm.rs index 6e8e3da143e4f..01ca3cd1c282f 100644 --- a/src/test/compile-fail/borrowck-loan-local-as-both-mut-and-imm.rs +++ b/src/test/compile-fail/borrowck-loan-local-as-both-mut-and-imm.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::either::{Either, Left, Right}; +use std::either::{Either, Left, Right}; fn f(x: &mut Either, y: &Either) -> int { match *y { @@ -22,7 +22,7 @@ use core::either::{Either, Left, Right}; fn g() { let mut x: Either = Left(3); - io::println(f(&mut x, &x).to_str()); //~ ERROR cannot borrow + println(f(&mut x, &x).to_str()); //~ ERROR cannot borrow } fn h() { diff --git a/src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs b/src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs index 061a6c553e4b0..b205c5be2179c 100644 --- a/src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs +++ b/src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs @@ -13,14 +13,14 @@ struct Point { y: int, } -impl ops::Add for Point { +impl Add for Point { fn add(&self, z: &int) -> int { self.x + self.y + (*z) } } -pub impl Point { - fn times(&self, z: int) -> int { +impl Point { + pub fn times(&self, z: int) -> int { self.x * self.y * z } } diff --git a/src/test/compile-fail/borrowck-move-by-capture.rs b/src/test/compile-fail/borrowck-move-by-capture.rs index c199c8795756d..0efde1df6c22b 100644 --- a/src/test/compile-fail/borrowck-move-by-capture.rs +++ b/src/test/compile-fail/borrowck-move-by-capture.rs @@ -1,4 +1,4 @@ -extern mod std; +extern mod extra; fn main() { let foo = ~3; @@ -7,8 +7,7 @@ fn main() { //~^ ERROR cannot move `foo` let bar = ~3; - let _g = || { + let _g = || { //~ ERROR capture of moved value let _h: @fn() -> int = || *bar; - //~^ ERROR illegal by-move capture }; } diff --git a/src/test/compile-fail/borrowck-move-mut-base-ptr.rs b/src/test/compile-fail/borrowck-move-mut-base-ptr.rs new file mode 100644 index 0000000000000..6a3832d2304cf --- /dev/null +++ b/src/test/compile-fail/borrowck-move-mut-base-ptr.rs @@ -0,0 +1,15 @@ +// Test that attempt to move `&mut` pointer while pointee is borrowed +// yields an error. +// +// Example from src/middle/borrowck/doc.rs + +use std::util::swap; + +fn foo(t0: &mut int) { + let p: &int = &*t0; // Freezes `*t0` + let t1 = t0; //~ ERROR cannot move out of `t0` + *t1 = 22; +} + +fn main() { +} \ No newline at end of file diff --git a/src/test/compile-fail/borrowck-move-out-of-vec-tail.rs b/src/test/compile-fail/borrowck-move-out-of-vec-tail.rs new file mode 100644 index 0000000000000..dec976e0a6068 --- /dev/null +++ b/src/test/compile-fail/borrowck-move-out-of-vec-tail.rs @@ -0,0 +1,31 @@ +// Test that we do not permit moves from &[] matched by a vec pattern. + +struct Foo { + string: ~str +} + +pub fn main() { + let x = [ + Foo { string: ~"foo" }, + Foo { string: ~"bar" }, + Foo { string: ~"baz" } + ]; + match x { + [first, ..tail] => { + match tail { + [Foo { string: a }, Foo { string: b }] => { + //~^ ERROR cannot move out of dereference of & pointer + //~^^ ERROR cannot move out of dereference of & pointer + } + _ => { + ::std::util::unreachable(); + } + } + let z = copy tail[0]; + debug!(fmt!("%?", z)); + } + _ => { + ::std::util::unreachable(); + } + } +} diff --git a/src/test/compile-fail/borrowck-pat-by-value-binding.rs b/src/test/compile-fail/borrowck-pat-by-value-binding.rs index d60ed3d0e372b..e77f5245d7d8b 100644 --- a/src/test/compile-fail/borrowck-pat-by-value-binding.rs +++ b/src/test/compile-fail/borrowck-pat-by-value-binding.rs @@ -36,7 +36,7 @@ fn match_const_opt_by_imm_ref(v: &const Option) { fn match_const_opt_by_value(v: &const Option) { match *v { - Some(copy i) => process(i), + Some(i) => process(i), None => () } } diff --git a/src/test/compile-fail/borrowck-ref-into-rvalue.rs b/src/test/compile-fail/borrowck-ref-into-rvalue.rs index 7026f06c2b7bb..cb56e929754da 100644 --- a/src/test/compile-fail/borrowck-ref-into-rvalue.rs +++ b/src/test/compile-fail/borrowck-ref-into-rvalue.rs @@ -16,5 +16,5 @@ fn main() { }, None => { fail!() } } - io::println(*msg); + println(*msg); } diff --git a/src/test/compile-fail/borrowck-ref-mut-of-imm.rs b/src/test/compile-fail/borrowck-ref-mut-of-imm.rs index 3a37116a1664d..4a34b85c3edfa 100644 --- a/src/test/compile-fail/borrowck-ref-mut-of-imm.rs +++ b/src/test/compile-fail/borrowck-ref-mut-of-imm.rs @@ -16,5 +16,5 @@ fn destructure(x: Option) -> int { } fn main() { - assert!(destructure(Some(22)) == 22); + assert_eq!(destructure(Some(22)), 22); } diff --git a/src/test/compile-fail/borrowck-swap-mut-base-ptr.rs b/src/test/compile-fail/borrowck-swap-mut-base-ptr.rs new file mode 100644 index 0000000000000..bea5f1f6ea765 --- /dev/null +++ b/src/test/compile-fail/borrowck-swap-mut-base-ptr.rs @@ -0,0 +1,16 @@ +// Test that attempt to swap `&mut` pointer while pointee is borrowed +// yields an error. +// +// Example from src/middle/borrowck/doc.rs + +use std::util::swap; + +fn foo<'a>(mut t0: &'a mut int, + mut t1: &'a mut int) { + let p: &int = &*t0; // Freezes `*t0` + swap(&mut t0, &mut t1); //~ ERROR cannot borrow `t0` + *t1 = 22; +} + +fn main() { +} \ No newline at end of file diff --git a/src/test/compile-fail/borrowck-unary-move.rs b/src/test/compile-fail/borrowck-unary-move.rs index cf7529865118a..a67a12f9d0f73 100644 --- a/src/test/compile-fail/borrowck-unary-move.rs +++ b/src/test/compile-fail/borrowck-unary-move.rs @@ -10,7 +10,7 @@ fn foo(x: ~int) -> int { let y = &*x; - free(x); //~ ERROR cannot move out of `*x` because it is borrowed + free(x); //~ ERROR cannot move out of `x` because it is borrowed *y } diff --git a/src/test/compile-fail/borrowck-uniq-via-lend.rs b/src/test/compile-fail/borrowck-uniq-via-lend.rs index 80ba1968bc751..43459acaaf185 100644 --- a/src/test/compile-fail/borrowck-uniq-via-lend.rs +++ b/src/test/compile-fail/borrowck-uniq-via-lend.rs @@ -48,13 +48,15 @@ fn aliased_mut() { } fn aliased_other() { - let mut v = ~3, w = ~4; + let mut v = ~3; + let mut w = ~4; let _x = &mut w; borrow(v); } fn aliased_other_reassign() { - let mut v = ~3, w = ~4; + let mut v = ~3; + let mut w = ~4; let mut _x = &mut w; _x = &mut v; borrow(v); //~ ERROR cannot borrow `*v` diff --git a/src/test/compile-fail/borrowck-vec-pattern-move-tail.rs b/src/test/compile-fail/borrowck-vec-pattern-move-tail.rs index 2898e312930fe..db8127d0854d2 100644 --- a/src/test/compile-fail/borrowck-vec-pattern-move-tail.rs +++ b/src/test/compile-fail/borrowck-vec-pattern-move-tail.rs @@ -2,7 +2,7 @@ fn main() { let mut a = [1, 2, 3, 4]; let t = match a { [1, 2, ..tail] => tail, - _ => core::util::unreachable() + _ => std::util::unreachable() }; a[0] = 0; //~ ERROR cannot assign to `a[]` because it is borrowed t[0]; diff --git a/src/test/compile-fail/borrowck-vec-pattern-tail-element-loan.rs b/src/test/compile-fail/borrowck-vec-pattern-tail-element-loan.rs index 6f669e67ec7dd..c02a0b4cfafd5 100644 --- a/src/test/compile-fail/borrowck-vec-pattern-tail-element-loan.rs +++ b/src/test/compile-fail/borrowck-vec-pattern-tail-element-loan.rs @@ -9,5 +9,5 @@ fn a() -> &int { fn main() { let fifth = a(); - io::println(fmt!("%d", *fifth)); + println(fmt!("%d", *fifth)); } diff --git a/src/test/compile-fail/by-move-pattern-binding.rs b/src/test/compile-fail/by-move-pattern-binding.rs index 1efed154286ec..8c0cf68c164b1 100644 --- a/src/test/compile-fail/by-move-pattern-binding.rs +++ b/src/test/compile-fail/by-move-pattern-binding.rs @@ -13,10 +13,10 @@ fn main() { let s = S { x: Bar(~"hello") }; match &s.x { &Foo => {} - &Bar(identifier) => f(copy identifier) //~ ERROR by-move pattern bindings may not occur + &Bar(identifier) => f(copy identifier) //~ ERROR cannot move }; match &s.x { &Foo => {} - &Bar(ref identifier) => io::println(*identifier) + &Bar(ref identifier) => println(*identifier) }; } diff --git a/src/test/compile-fail/call-extern-trait-as-function.rs b/src/test/compile-fail/call-extern-trait-as-function.rs new file mode 100644 index 0000000000000..86ebeedda6795 --- /dev/null +++ b/src/test/compile-fail/call-extern-trait-as-function.rs @@ -0,0 +1,17 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// issue #6698 + +fn V() -> bool { + std::clone::Clone::clone(true) //~ ERROR error: unresolved name `std::clone::Clone::clone`. +} + +fn main() {} diff --git a/src/test/compile-fail/class-cast-to-trait.rs b/src/test/compile-fail/class-cast-to-trait.rs index 0662736545166..7f7c58a60df05 100644 --- a/src/test/compile-fail/class-cast-to-trait.rs +++ b/src/test/compile-fail/class-cast-to-trait.rs @@ -13,15 +13,14 @@ trait noisy { } struct cat { - priv mut meows : uint, + priv meows : uint, - mut how_hungry : int, + how_hungry : int, name : ~str, } -pub impl cat { - - fn eat(&self) -> bool { +impl cat { + pub fn eat(&self) -> bool { if self.how_hungry > 0 { error!("OM NOM NOM"); self.how_hungry -= 2; @@ -39,7 +38,7 @@ impl noisy for cat { } -priv impl cat { +impl cat { fn meow(&self) { error!("Meow"); self.meows += 1; diff --git a/src/test/compile-fail/class-missing-self.rs b/src/test/compile-fail/class-missing-self.rs index b78b065d028f5..c27c27b5942e1 100644 --- a/src/test/compile-fail/class-missing-self.rs +++ b/src/test/compile-fail/class-missing-self.rs @@ -9,10 +9,10 @@ // except according to those terms. struct cat { - priv mut meows : uint, + priv meows : uint, } -priv impl cat { +impl cat { fn sleep(&self) { loop{} } fn meow(&self) { error!("Meow"); diff --git a/src/test/compile-fail/core-tls-store-pointer.rs b/src/test/compile-fail/core-tls-store-pointer.rs index fcb25069de6dd..63bbaf80177e1 100644 --- a/src/test/compile-fail/core-tls-store-pointer.rs +++ b/src/test/compile-fail/core-tls-store-pointer.rs @@ -10,7 +10,7 @@ // Testing that we can't store a borrowed pointer it task-local storage -use core::local_data::*; +use std::local_data::*; fn key(_x: @&int) { } diff --git a/src/test/compile-fail/dead-code-ret.rs b/src/test/compile-fail/dead-code-ret.rs index 5fa796db88444..91b89a67ee348 100644 --- a/src/test/compile-fail/dead-code-ret.rs +++ b/src/test/compile-fail/dead-code-ret.rs @@ -9,13 +9,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -fn f(caller: &str) { - debug!(caller); - let x: uint = 0u32; // induce type error //~ ERROR mismatched types -} +#[deny(unreachable_code)]; fn main() { - return f("main"); - debug!("Paul is dead"); //~ WARNING unreachable + return; + debug!("Paul is dead"); //~ ERROR: unreachable } diff --git a/src/test/compile-fail/die-not-static.rs b/src/test/compile-fail/die-not-static.rs index d33c591d8c87f..c7f5e27181837 100644 --- a/src/test/compile-fail/die-not-static.rs +++ b/src/test/compile-fail/die-not-static.rs @@ -1,3 +1,5 @@ +use std::str; + fn main() { let v = ~"test"; let sslice = str::slice(v, 0, v.len()); diff --git a/src/test/compile-fail/disallowed-deconstructing-destructing-struct-match.rs b/src/test/compile-fail/disallowed-deconstructing-destructing-struct-match.rs index 40305ba8b95c9..478a56c03010a 100644 --- a/src/test/compile-fail/disallowed-deconstructing-destructing-struct-match.rs +++ b/src/test/compile-fail/disallowed-deconstructing-destructing-struct-match.rs @@ -23,6 +23,6 @@ fn main() { match x { X { x: y } => error!("contents: %s", y) - //~^ ERROR cannot bind by-move within struct + //~^ ERROR cannot move out of type `X`, which defines the `Drop` trait } } diff --git a/src/test/compile-fail/drop-on-non-struct.rs b/src/test/compile-fail/drop-on-non-struct.rs index b2f87686ac664..5e422d267538b 100644 --- a/src/test/compile-fail/drop-on-non-struct.rs +++ b/src/test/compile-fail/drop-on-non-struct.rs @@ -13,7 +13,7 @@ type Foo = @[u8]; impl Drop for Foo { //~ ERROR the Drop trait may only be implemented //~^ ERROR cannot provide an extension implementation fn finalize(&self) { - io::println("kaboom"); + println("kaboom"); } } diff --git a/src/test/compile-fail/explicit-call-to-dtor.rs b/src/test/compile-fail/explicit-call-to-dtor.rs index 24fedaaabe3a0..ce2942c3146c4 100644 --- a/src/test/compile-fail/explicit-call-to-dtor.rs +++ b/src/test/compile-fail/explicit-call-to-dtor.rs @@ -14,7 +14,7 @@ struct Foo { impl Drop for Foo { fn finalize(&self) { - io::println("kaboom"); + println("kaboom"); } } diff --git a/src/test/compile-fail/explicit-call-to-supertrait-dtor.rs b/src/test/compile-fail/explicit-call-to-supertrait-dtor.rs index fd49889a3f796..1a5eb696fa2e7 100644 --- a/src/test/compile-fail/explicit-call-to-supertrait-dtor.rs +++ b/src/test/compile-fail/explicit-call-to-supertrait-dtor.rs @@ -18,7 +18,7 @@ trait Bar : Drop { impl Drop for Foo { fn finalize(&self) { - io::println("kaboom"); + println("kaboom"); } } diff --git a/src/test/run-pass/mod-merge-hack-inst.rs b/src/test/compile-fail/extern-no-fn.rs similarity index 80% rename from src/test/run-pass/mod-merge-hack-inst.rs rename to src/test/compile-fail/extern-no-fn.rs index 999c6ac2a71d5..164cbe5417402 100644 --- a/src/test/run-pass/mod-merge-hack-inst.rs +++ b/src/test/compile-fail/extern-no-fn.rs @@ -8,9 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// xfail-test not a test. used by mod-merge-hack.rs +// error-pattern:unexpected token +extern { + f(); +} -mod inst { - pub type T = i32; - pub static bits: uint = 32; +fn main() { } diff --git a/src/test/compile-fail/extfmt-not-enough-args.rs b/src/test/compile-fail/extfmt-not-enough-args.rs index 5f078a288d929..f18ae748ee07f 100644 --- a/src/test/compile-fail/extfmt-not-enough-args.rs +++ b/src/test/compile-fail/extfmt-not-enough-args.rs @@ -10,6 +10,6 @@ // error-pattern:not enough arguments -extern mod std; +extern mod extra; fn main() { let s = fmt!("%s%s%s", "test", "test"); } diff --git a/src/test/compile-fail/extfmt-too-many-args.rs b/src/test/compile-fail/extfmt-too-many-args.rs index 3a16db6638b64..2a72dcf89889e 100644 --- a/src/test/compile-fail/extfmt-too-many-args.rs +++ b/src/test/compile-fail/extfmt-too-many-args.rs @@ -10,6 +10,6 @@ // error-pattern:too many arguments -extern mod std; +extern mod extra; fn main() { let s = fmt!("%s", "test", "test"); } diff --git a/src/test/compile-fail/fail-expr.rs b/src/test/compile-fail/fail-expr.rs index e17c8d6a182c5..98270bdc58383 100644 --- a/src/test/compile-fail/fail-expr.rs +++ b/src/test/compile-fail/fail-expr.rs @@ -8,6 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:failed to find an implementation of trait core::sys::FailWithCause for int +// error-pattern:failed to find an implementation of trait std::sys::FailWithCause for int fn main() { fail!(5); } diff --git a/src/test/compile-fail/fail-type-err.rs b/src/test/compile-fail/fail-type-err.rs index fbfa85ea6f87f..b6755249bcf98 100644 --- a/src/test/compile-fail/fail-type-err.rs +++ b/src/test/compile-fail/fail-type-err.rs @@ -8,5 +8,5 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:failed to find an implementation of trait core::sys::FailWithCause for ~[int] +// error-pattern:failed to find an implementation of trait std::sys::FailWithCause for ~[int] fn main() { fail!(~[0i]); } diff --git a/src/test/compile-fail/foreign-unsafe-fn-called.rs b/src/test/compile-fail/foreign-unsafe-fn-called.rs index ed8b8088ee41a..2f5258aa7f23e 100644 --- a/src/test/compile-fail/foreign-unsafe-fn-called.rs +++ b/src/test/compile-fail/foreign-unsafe-fn-called.rs @@ -19,5 +19,5 @@ mod test { fn main() { test::free(); - //~^ ERROR access to unsafe function requires unsafe function or block + //~^ ERROR call to unsafe function requires unsafe function or block } diff --git a/src/test/compile-fail/forget-init-unsafe.rs b/src/test/compile-fail/forget-init-unsafe.rs index 2361b5ad6a9cf..9ad7a178fb188 100644 --- a/src/test/compile-fail/forget-init-unsafe.rs +++ b/src/test/compile-fail/forget-init-unsafe.rs @@ -8,10 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::unstable::intrinsics::{init, forget}; +use std::unstable::intrinsics::{init, forget}; // Test that the `forget` and `init` intrinsics are really unsafe pub fn main() { - let stuff = init::(); //~ ERROR access to unsafe function requires unsafe - forget(stuff); //~ ERROR access to unsafe function requires unsafe -} \ No newline at end of file + let stuff = init::(); //~ ERROR call to unsafe function requires unsafe + forget(stuff); //~ ERROR call to unsafe function requires unsafe +} diff --git a/src/test/compile-fail/fully-qualified-type-name1.rs b/src/test/compile-fail/fully-qualified-type-name1.rs index c5e7fc82cc994..dd9833ad41fb1 100644 --- a/src/test/compile-fail/fully-qualified-type-name1.rs +++ b/src/test/compile-fail/fully-qualified-type-name1.rs @@ -13,5 +13,5 @@ fn main() { let x: Option; x = 5; - //~^ ERROR mismatched types: expected `core::option::Option` + //~^ ERROR mismatched types: expected `std::option::Option` } diff --git a/src/test/compile-fail/fully-qualified-type-name4.rs b/src/test/compile-fail/fully-qualified-type-name4.rs index a91d8284e71ef..f49eb5ee85aa8 100644 --- a/src/test/compile-fail/fully-qualified-type-name4.rs +++ b/src/test/compile-fail/fully-qualified-type-name4.rs @@ -10,11 +10,11 @@ // Test that we use fully-qualified type names in error messages. -use core::task::Task; +use std::task::Task; fn bar(x: uint) -> Task { return x; - //~^ ERROR mismatched types: expected `core::task::Task` + //~^ ERROR mismatched types: expected `std::task::Task` } fn main() { diff --git a/src/test/compile-fail/issue-1896-1.rs b/src/test/compile-fail/issue-1896-1.rs index 13adcd42da2b8..4750f68d59b34 100644 --- a/src/test/compile-fail/issue-1896-1.rs +++ b/src/test/compile-fail/issue-1896-1.rs @@ -22,5 +22,5 @@ fn main () { let myInt: uint = (aFn.theFn)(); - assert!(myInt == 10); + assert_eq!(myInt, 10); } diff --git a/src/test/compile-fail/issue-2150.rs b/src/test/compile-fail/issue-2150.rs index 9f2f9a855ed52..0b35104841e64 100644 --- a/src/test/compile-fail/issue-2150.rs +++ b/src/test/compile-fail/issue-2150.rs @@ -8,11 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[deny(unreachable_code)]; +#[allow(unused_variable)]; + fn fail_len(v: ~[int]) -> uint { - let mut i = fail!(); + let mut i = 3; + fail!(); for v.each |x| { i += 1u; } - //~^ WARNING unreachable statement - //~^^ ERROR the type of this value must be known + //~^ ERROR: unreachable statement return i; } fn main() {} diff --git a/src/test/compile-fail/issue-2151.rs b/src/test/compile-fail/issue-2151.rs index bb6d47a47622b..8f4bbe4eabc74 100644 --- a/src/test/compile-fail/issue-2151.rs +++ b/src/test/compile-fail/issue-2151.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::vec; + fn main() { for vec::each(fail!()) |i| { let _ = i * 2; //~ ERROR the type of this value must be known diff --git a/src/test/compile-fail/issue-2356.rs b/src/test/compile-fail/issue-2356.rs index 9a574b984ca47..cb559b91889bb 100644 --- a/src/test/compile-fail/issue-2356.rs +++ b/src/test/compile-fail/issue-2356.rs @@ -14,6 +14,6 @@ struct cat { tail: int, } -pub impl cat { - fn meow() { tail += 1; } //~ ERROR: Did you mean: `self.tail` +impl cat { + pub fn meow() { tail += 1; } //~ ERROR: Did you mean: `self.tail` } diff --git a/src/test/compile-fail/issue-2467.rs b/src/test/compile-fail/issue-2467.rs index fd6e5a762b248..3149db8a03f27 100644 --- a/src/test/compile-fail/issue-2467.rs +++ b/src/test/compile-fail/issue-2467.rs @@ -12,5 +12,5 @@ enum test { thing = 3u } //~ ERROR mismatched types //~^ ERROR expected signed integer constant fn main() { error!(thing as int); - assert!((thing as int == 3)); + assert_eq!(thing as int, 3); } diff --git a/src/test/compile-fail/issue-2478.rs b/src/test/compile-fail/issue-2478.rs index d5663e57f4bf7..c6793e71ad97e 100644 --- a/src/test/compile-fail/issue-2478.rs +++ b/src/test/compile-fail/issue-2478.rs @@ -9,7 +9,7 @@ // except according to those terms. // xfail-test -fn foo() -> &'a int { +fn foo<'a>() -> &'a int { //~ ERROR unconstrained region return &x; } static x: int = 5; diff --git a/src/test/compile-fail/issue-2548.rs b/src/test/compile-fail/issue-2548.rs index 9c2d7baa23c26..2f69000844060 100644 --- a/src/test/compile-fail/issue-2548.rs +++ b/src/test/compile-fail/issue-2548.rs @@ -20,7 +20,7 @@ struct foo { impl Drop for foo { fn finalize(&self) { unsafe { - io::println("Goodbye, World!"); + println("Goodbye, World!"); *self.x += 1; } } @@ -38,8 +38,8 @@ fn main() { let mut v = ~[]; v = ~[(res)] + v; //~ instantiating a type parameter with an incompatible type `foo`, which does not fulfill `Copy` - assert!((v.len() == 2)); + assert_eq!(v.len(), 2); } - assert!(*x == 1); + assert_eq!(*x, 1); } diff --git a/src/test/compile-fail/issue-2590.rs b/src/test/compile-fail/issue-2590.rs index a0b967d59593a..92f2e5ea689c1 100644 --- a/src/test/compile-fail/issue-2590.rs +++ b/src/test/compile-fail/issue-2590.rs @@ -18,7 +18,7 @@ trait parse { impl parse for parser { fn parse(&self) -> ~[int] { - self.tokens //~ ERROR cannot move out of field + self.tokens //~ ERROR cannot move out of dereference of & pointer } } diff --git a/src/test/compile-fail/issue-2766-a.rs b/src/test/compile-fail/issue-2766-a.rs index 5b55cc772fde8..91ae0e1c07a55 100644 --- a/src/test/compile-fail/issue-2766-a.rs +++ b/src/test/compile-fail/issue-2766-a.rs @@ -11,10 +11,10 @@ pub mod stream { pub enum Stream { send(T, ::stream::server::Stream), } pub mod server { - use core::option; - use core::pipes; + use std::option; + use std::pipes; - pub impl Stream { + impl Stream { pub fn recv() -> extern fn(v: Stream) -> ::stream::Stream { // resolve really should report just one error here. // Change the test case when it changes. diff --git a/src/test/compile-fail/issue-2817-2.rs b/src/test/compile-fail/issue-2817-2.rs index 17b0d88a6a827..166f7e048df1c 100644 --- a/src/test/compile-fail/issue-2817-2.rs +++ b/src/test/compile-fail/issue-2817-2.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::uint; + fn not_bool(f: &fn(int) -> ~str) -> bool {} fn main() { diff --git a/src/test/compile-fail/issue-2817.rs b/src/test/compile-fail/issue-2817.rs index 77585d15b6b3e..49516831904be 100644 --- a/src/test/compile-fail/issue-2817.rs +++ b/src/test/compile-fail/issue-2817.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::uint; + fn uuid() -> uint { fail!(); } fn from_str(s: ~str) -> uint { fail!(); } diff --git a/src/test/compile-fail/issue-2969.rs b/src/test/compile-fail/issue-2969.rs index 927e81db5c1c4..a9c26fc415ead 100644 --- a/src/test/compile-fail/issue-2969.rs +++ b/src/test/compile-fail/issue-2969.rs @@ -15,5 +15,5 @@ fn main() let mut x = [1, 2, 4]; let v : &int = &x[2]; x[2] = 6; - assert!(*v == 6); + assert_eq!(*v, 6); } diff --git a/src/test/compile-fail/issue-3021-b.rs b/src/test/compile-fail/issue-3021-b.rs index 3769154c9d948..d3aec178c238a 100644 --- a/src/test/compile-fail/issue-3021-b.rs +++ b/src/test/compile-fail/issue-3021-b.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; +extern mod extra; fn siphash(k0 : u64) { @@ -16,8 +16,8 @@ fn siphash(k0 : u64) { v0: u64, } - pub impl siphash { - fn reset(&mut self) { + impl siphash { + pub fn reset(&mut self) { self.v0 = k0 ^ 0x736f6d6570736575; //~ ERROR attempted dynamic environment-capture //~^ ERROR unresolved name `k0`. } diff --git a/src/test/compile-fail/issue-3021-c.rs b/src/test/compile-fail/issue-3021-c.rs index 4fc4c005cf611..a0b78a4bc79b1 100644 --- a/src/test/compile-fail/issue-3021-c.rs +++ b/src/test/compile-fail/issue-3021-c.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; +extern mod extra; fn siphash() { diff --git a/src/test/compile-fail/issue-3021-d.rs b/src/test/compile-fail/issue-3021-d.rs index 55c8e8aa51dd8..c6b5d8c42d595 100644 --- a/src/test/compile-fail/issue-3021-d.rs +++ b/src/test/compile-fail/issue-3021-d.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; +extern mod extra; trait siphash { fn result(&self) -> u64; @@ -23,8 +23,8 @@ fn siphash(k0 : u64, k1 : u64) -> siphash { fn mk_result(st : SipState) -> u64 { - let v0 = st.v0, - v1 = st.v1; + let v0 = st.v0; + let v1 = st.v1; return v0 ^ v1; } diff --git a/src/test/compile-fail/issue-3021.rs b/src/test/compile-fail/issue-3021.rs index f2cf2d19a864e..0ca6173275cb2 100644 --- a/src/test/compile-fail/issue-3021.rs +++ b/src/test/compile-fail/issue-3021.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; +extern mod extra; trait SipHash { fn reset(&self); diff --git a/src/test/compile-fail/issue-3044.rs b/src/test/compile-fail/issue-3044.rs index 06fb18d7e4777..4cac844bdea70 100644 --- a/src/test/compile-fail/issue-3044.rs +++ b/src/test/compile-fail/issue-3044.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::vec; + fn main() { let needlesArr: ~[char] = ~['a', 'f']; do vec::foldr(needlesArr) |x, y| { diff --git a/src/test/compile-fail/issue-3080.rs b/src/test/compile-fail/issue-3080.rs index 02df25d87d7fb..02ccf14138a35 100644 --- a/src/test/compile-fail/issue-3080.rs +++ b/src/test/compile-fail/issue-3080.rs @@ -10,8 +10,8 @@ // xfail-test struct x(()); -pub impl x { - unsafe fn with() { } // This should fail +impl x { + pub unsafe fn with() { } // This should fail } fn main() { diff --git a/src/test/compile-fail/issue-3096-2.rs b/src/test/compile-fail/issue-3096-2.rs index eb58cf3e13b36..5f3af86545462 100644 --- a/src/test/compile-fail/issue-3096-2.rs +++ b/src/test/compile-fail/issue-3096-2.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::ptr; + enum bottom { } fn main() { diff --git a/src/test/compile-fail/issue-3296.rs b/src/test/compile-fail/issue-3296.rs index 062ee8fd01e46..ba0ad02f91ccc 100644 --- a/src/test/compile-fail/issue-3296.rs +++ b/src/test/compile-fail/issue-3296.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std; +use extra; -struct Deserializer : std::serialization::deserializer{ //~ ERROR obsolete syntax: class traits +struct Deserializer : extra::serialization::deserializer{ //~ ERROR obsolete syntax: class traits x: () } @@ -18,7 +18,7 @@ struct Foo { a: () } -fn deserialize_foo<__D: std::serialization::deserializer>(__d: __D) { +fn deserialize_foo<__D: extra::serialization::deserializer>(__d: __D) { } fn main() { let des = Deserializer(); let foo = deserialize_foo(des); } diff --git a/src/test/compile-fail/issue-3344.rs b/src/test/compile-fail/issue-3344.rs index e931a8fa7e144..ac5b469c56e20 100644 --- a/src/test/compile-fail/issue-3344.rs +++ b/src/test/compile-fail/issue-3344.rs @@ -9,7 +9,7 @@ // except according to those terms. struct thing(uint); -impl cmp::Ord for thing { //~ ERROR missing method `gt` +impl Ord for thing { //~ ERROR missing method `gt` fn lt(&self, other: &thing) -> bool { **self < **other } fn le(&self, other: &thing) -> bool { **self < **other } fn ge(&self, other: &thing) -> bool { **self < **other } diff --git a/src/test/compile-fail/issue-3651.rs b/src/test/compile-fail/issue-3651.rs index 8d704859fe574..7e65d8ab82d9b 100644 --- a/src/test/compile-fail/issue-3651.rs +++ b/src/test/compile-fail/issue-3651.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::task; + fn main() { for task::spawn { return true; } //~ ERROR A `for` loop iterator should expect a closure that //~^ ERROR expected `for` closure to return `bool` diff --git a/src/test/compile-fail/issue-3680.rs b/src/test/compile-fail/issue-3680.rs index 18b5d290f3d6d..b453384c0c890 100644 --- a/src/test/compile-fail/issue-3680.rs +++ b/src/test/compile-fail/issue-3680.rs @@ -10,6 +10,6 @@ fn main() { match None { - Err(_) => () //~ ERROR mismatched types: expected `core::option::Option<>` but found `core::result::Result<,>` + Err(_) => () //~ ERROR mismatched types: expected `std::option::Option<>` but found `std::result::Result<,>` } } diff --git a/src/test/compile-fail/issue-3707.rs b/src/test/compile-fail/issue-3707.rs index 5e8230686d506..4e128b63e9257 100644 --- a/src/test/compile-fail/issue-3707.rs +++ b/src/test/compile-fail/issue-3707.rs @@ -12,11 +12,11 @@ struct Obj { member: uint } -pub impl Obj { - fn boom() -> bool { +impl Obj { + pub fn boom() -> bool { return 1+1 == 2 } - fn chirp(&self) { + pub fn chirp(&self) { self.boom(); //~ ERROR `&Obj` does not implement any method in scope named `boom` } } diff --git a/src/test/compile-fail/issue-3763.rs b/src/test/compile-fail/issue-3763.rs index f6226032eeef3..9647d412d2cdb 100644 --- a/src/test/compile-fail/issue-3763.rs +++ b/src/test/compile-fail/issue-3763.rs @@ -15,7 +15,7 @@ mod my_mod { pub fn MyStruct () -> MyStruct { MyStruct {priv_field: 4} } - pub impl MyStruct { + impl MyStruct { priv fn happyfun(&self) {} } } diff --git a/src/test/compile-fail/issue-3820.rs b/src/test/compile-fail/issue-3820.rs index 2bd11b5111adf..8fafd04d1e2a5 100644 --- a/src/test/compile-fail/issue-3820.rs +++ b/src/test/compile-fail/issue-3820.rs @@ -22,5 +22,5 @@ fn main() { let u = Thing {x: 2}; let _v = u.mul(&3); // This is ok let w = u * 3; //~ ERROR binary operation * cannot be applied to type `Thing` - io::println(fmt!("%i", w.x)); + println(fmt!("%i", w.x)); } diff --git a/src/test/compile-fail/issue-3953.rs b/src/test/compile-fail/issue-3953.rs index b726f090e7db7..e3af6ce78e2c9 100644 --- a/src/test/compile-fail/issue-3953.rs +++ b/src/test/compile-fail/issue-3953.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::cmp::Eq; +use std::cmp::Eq; trait Hahaha: Eq + Eq + Eq + Eq + Eq + //~ ERROR Duplicate supertrait Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + Eq + @@ -31,8 +31,8 @@ impl Eq for Lol { fn main() { if Lol(2) == Lol(4) { - io::println("2 == 4"); + println("2 == 4"); } else { - io::println("2 != 4"); + println("2 != 4"); } } diff --git a/src/test/compile-fail/issue-4335.rs b/src/test/compile-fail/issue-4335.rs index 5f907b35e412f..ffa11e592608d 100644 --- a/src/test/compile-fail/issue-4335.rs +++ b/src/test/compile-fail/issue-4335.rs @@ -14,5 +14,5 @@ fn f<'r, T>(v: &'r T) -> &'r fn()->T { id::<&'r fn()->T>(|| *v) } //~ ERROR cann fn main() { let v = &5; - io::println(fmt!("%d", f(v)())); + println(fmt!("%d", f(v)())); } diff --git a/src/test/compile-fail/issue-511.rs b/src/test/compile-fail/issue-511.rs index c872f89d88450..ed2eede76c670 100644 --- a/src/test/compile-fail/issue-511.rs +++ b/src/test/compile-fail/issue-511.rs @@ -8,14 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; -use core::cmp::Eq; +extern mod extra; +use std::cmp::Eq; fn f(o: &mut Option) { - assert!(*o == option::None); + assert!(*o == None); } fn main() { - f::(&mut option::None); + f::(&mut None); //~^ ERROR cannot borrow } diff --git a/src/test/compile-fail/issue-5358-1.rs b/src/test/compile-fail/issue-5358-1.rs index 0b6e2fb0ff5f2..a3d25e7d2adca 100644 --- a/src/test/compile-fail/issue-5358-1.rs +++ b/src/test/compile-fail/issue-5358-1.rs @@ -12,7 +12,7 @@ struct S(Either); fn main() { match S(Left(5)) { - Right(_) => {} //~ ERROR mismatched types: expected `S` but found `core::either::Either + Right(_) => {} //~ ERROR mismatched types: expected `S` but found `std::either::Either _ => {} } } diff --git a/src/test/compile-fail/issue-5358.rs b/src/test/compile-fail/issue-5358.rs index 7d11a127f9ae8..8d4f463346693 100644 --- a/src/test/compile-fail/issue-5358.rs +++ b/src/test/compile-fail/issue-5358.rs @@ -12,6 +12,6 @@ struct S(Either); fn main() { match *S(Left(5)) { - S(_) => {} //~ ERROR mismatched types: expected `core::either::Either` but found a structure pattern + S(_) => {} //~ ERROR mismatched types: expected `std::either::Either` but found a structure pattern } } diff --git a/src/test/compile-fail/foreign-unsafe-fn.rs b/src/test/compile-fail/issue-5543.rs similarity index 61% rename from src/test/compile-fail/foreign-unsafe-fn.rs rename to src/test/compile-fail/issue-5543.rs index 3633267d02c40..cad47eff01321 100644 --- a/src/test/compile-fail/foreign-unsafe-fn.rs +++ b/src/test/compile-fail/issue-5543.rs @@ -1,5 +1,4 @@ -// -*- rust -*- -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -9,15 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// xfail-test +use core::io::ReaderUtil; +use core::io::Reader; -mod test { - #[abi = "cdecl"] - pub extern { - pub unsafe fn free(); - } -} +fn bar(r:@ReaderUtil) -> ~str { r.read_line() } fn main() { - let x = test::free; - //~^ ERROR access to unsafe function requires unsafe function or block + let r : @Reader = io::stdin(); + let _m = bar(r as @ReaderUtil); } diff --git a/src/test/compile-fail/issue-6596.rs b/src/test/compile-fail/issue-6596.rs new file mode 100644 index 0000000000000..3c952dbc59087 --- /dev/null +++ b/src/test/compile-fail/issue-6596.rs @@ -0,0 +1,9 @@ +macro_rules! e( //~ ERROR unknown macro variable `nonexistent` + ($inp:ident) => ( + $nonexistent + ); +) + +fn main() { + e!(foo); +} diff --git a/src/test/compile-fail/issue-6762.rs b/src/test/compile-fail/issue-6762.rs new file mode 100644 index 0000000000000..391c1019a9468 --- /dev/null +++ b/src/test/compile-fail/issue-6762.rs @@ -0,0 +1,24 @@ +//xfail-test + +// Creating a stack closure which references an owned pointer and then +// transferring ownership of the owned box before invoking the stack +// closure results in a crash. + +fn twice(x: ~uint) -> uint +{ + *x * 2 +} + +fn invoke(f : &fn() -> uint) +{ + f(); +} + +fn main() +{ + let x : ~uint = ~9; + let sq : &fn() -> uint = || { *x * *x }; + + twice(x); + invoke(sq); +} \ No newline at end of file diff --git a/src/test/compile-fail/issue-897-2.rs b/src/test/compile-fail/issue-897-2.rs index 253563c12195c..eb60e34df8f14 100644 --- a/src/test/compile-fail/issue-897-2.rs +++ b/src/test/compile-fail/issue-897-2.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[deny(unreachable_code)]; + fn g() -> ! { fail!(); } fn f() -> ! { - return 42i; //~ ERROR expected `!` but found `int` - g(); //~ WARNING unreachable statement + return g(); + g(); //~ ERROR: unreachable statement } fn main() { } diff --git a/src/test/compile-fail/issue-897.rs b/src/test/compile-fail/issue-897.rs index 503574fce8773..103156175a3fd 100644 --- a/src/test/compile-fail/issue-897.rs +++ b/src/test/compile-fail/issue-897.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[deny(unreachable_code)]; + fn f() -> ! { - return 42i; //~ ERROR expected `!` but found `int` - fail!(); //~ WARNING unreachable statement + return fail!(); + fail!(); //~ ERROR: unreachable statement } fn main() { } diff --git a/src/test/compile-fail/kindck-implicit-close-over-mut-var.rs b/src/test/compile-fail/kindck-implicit-close-over-mut-var.rs index c2732d383ab5b..b21063361abcc 100644 --- a/src/test/compile-fail/kindck-implicit-close-over-mut-var.rs +++ b/src/test/compile-fail/kindck-implicit-close-over-mut-var.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::task; + fn user(_i: int) {} fn foo() { diff --git a/src/test/compile-fail/kindck-owned-trait-scoped.rs b/src/test/compile-fail/kindck-owned-trait-scoped.rs index bb0ba87c098cf..808bfba829858 100644 --- a/src/test/compile-fail/kindck-owned-trait-scoped.rs +++ b/src/test/compile-fail/kindck-owned-trait-scoped.rs @@ -30,14 +30,14 @@ fn to_foo(t: T) { let v = &3; struct F { f: T } let x = @F {f:t} as @foo; - assert!(x.foo(v) == 3); + assert_eq!(x.foo(v), 3); } fn to_foo_2(t: T) -> @foo { // Not OK---T may contain borrowed ptrs and it is going to escape // as part of the returned foo value struct F { f: T } - @F {f:t} as @foo //~ ERROR value may contain borrowed pointers; use `'static` bound + @F {f:t} as @foo //~ ERROR value may contain borrowed pointers; add `'static` bound } fn to_foo_3(t: T) -> @foo { diff --git a/src/test/compile-fail/kindck-owned-trait.rs b/src/test/compile-fail/kindck-owned-trait.rs index c61bbc69be519..857c71db72ce0 100644 --- a/src/test/compile-fail/kindck-owned-trait.rs +++ b/src/test/compile-fail/kindck-owned-trait.rs @@ -11,7 +11,7 @@ trait foo { fn foo(&self); } fn to_foo(t: T) -> @foo { - @t as @foo //~ ERROR value may contain borrowed pointers; use `'static` bound + @t as @foo //~ ERROR value may contain borrowed pointers; add `'static` bound } fn to_foo2(t: T) -> @foo { diff --git a/src/test/compile-fail/lint-default-methods.rs b/src/test/compile-fail/lint-default-methods.rs index 89b99fcebca5d..23befde7559c7 100644 --- a/src/test/compile-fail/lint-default-methods.rs +++ b/src/test/compile-fail/lint-default-methods.rs @@ -1,7 +1,7 @@ #[forbid(default_methods)]; trait Foo { //~ ERROR default methods are experimental - fn bar(&self) { io::println("hi"); } + fn bar(&self) { println("hi"); } } fn main() {} diff --git a/src/test/compile-fail/lint-missing-doc.rs b/src/test/compile-fail/lint-missing-doc.rs new file mode 100644 index 0000000000000..2350ca68b9747 --- /dev/null +++ b/src/test/compile-fail/lint-missing-doc.rs @@ -0,0 +1,85 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// When denying at the crate level, be sure to not get random warnings from the +// injected intrinsics by the compiler. +#[deny(missing_doc)]; + +struct Foo { + a: int, + priv b: int, + pub c: int, // doesn't matter, Foo is private +} + +pub struct PubFoo { //~ ERROR: missing documentation + a: int, //~ ERROR: missing documentation + priv b: int, + pub c: int, //~ ERROR: missing documentation +} + +#[allow(missing_doc)] +pub struct PubFoo2 { + a: int, + pub c: int, +} + +/// dox +pub fn foo() {} +pub fn foo2() {} //~ ERROR: missing documentation +fn foo3() {} +#[allow(missing_doc)] pub fn foo4() {} + +/// dox +pub trait A {} +trait B {} +pub trait C {} //~ ERROR: missing documentation +#[allow(missing_doc)] pub trait D {} + +trait Bar { + /// dox + pub fn foo(); + fn foo2(); //~ ERROR: missing documentation + pub fn foo3(); //~ ERROR: missing documentation +} + +impl Foo { + pub fn foo() {} //~ ERROR: missing documentation + /// dox + pub fn foo1() {} + fn foo2() {} + #[allow(missing_doc)] pub fn foo3() {} +} + +#[allow(missing_doc)] +trait F { + pub fn a(); + fn b(&self); +} + +// should need to redefine documentation for implementations of traits +impl F for Foo { + pub fn a() {} + fn b(&self) {} +} + +// It sure is nice if doc(hidden) implies allow(missing_doc), and that it +// applies recursively +#[doc(hidden)] +mod a { + pub fn baz() {} + pub mod b { + pub fn baz() {} + } +} + +#[doc(hidden)] +pub fn baz() {} + +fn main() {} diff --git a/src/test/compile-fail/noncopyable-match-pattern.rs b/src/test/compile-fail/lint-unused-import-tricky-names.rs similarity index 55% rename from src/test/compile-fail/noncopyable-match-pattern.rs rename to src/test/compile-fail/lint-unused-import-tricky-names.rs index 155b398148339..e36b5572909d8 100644 --- a/src/test/compile-fail/noncopyable-match-pattern.rs +++ b/src/test/compile-fail/lint-unused-import-tricky-names.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,12 +8,22 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn main() { - let x = Some(unstable::sync::exclusive(false)); - match x { - Some(copy z) => { //~ ERROR copying a value of non-copyable type - do z.with |b| { assert!(!*b); } +#[deny(unused_imports)]; + +// Regression test for issue #6633 + +use foo::name::name; //~ ERROR: unused import +use foo::name; + +pub mod foo { + pub mod name { + pub type a = int; + pub mod name { + pub type a = float; } - None => fail!() } } + +fn bar() -> name::a { 1 } + +fn main(){} diff --git a/src/test/compile-fail/lint-unused-imports.rs b/src/test/compile-fail/lint-unused-imports.rs index f3b0a1f73f933..4a748cc56700a 100644 --- a/src/test/compile-fail/lint-unused-imports.rs +++ b/src/test/compile-fail/lint-unused-imports.rs @@ -12,23 +12,25 @@ use cal = bar::c::cc; -use core::either::Right; //~ ERROR unused import +use std::io; -use core::util::*; // shouldn't get errors for not using +use std::either::Right; //~ ERROR unused import + +use std::util::*; // shouldn't get errors for not using // everything imported // Should get errors for both 'Some' and 'None' -use core::option::{Some, None}; //~ ERROR unused import +use std::option::{Some, None}; //~ ERROR unused import //~^ ERROR unused import -use core::io::ReaderUtil; //~ ERROR unused import +use std::io::ReaderUtil; //~ ERROR unused import // Be sure that if we just bring some methods into scope that they're also // counted as being used. -use core::io::WriterUtil; +use std::io::WriterUtil; // Make sure this import is warned about when at least one of its imported names // is unused -use core::vec::{filter, map}; //~ ERROR unused import +use std::vec::{filter, map}; //~ ERROR unused import mod foo { pub struct Point{x: int, y: int} @@ -37,7 +39,7 @@ mod foo { mod bar { // Don't ignore on 'pub use' because we're not sure if it's used or not - pub use core::cmp::Eq; + pub use std::cmp::Eq; pub mod c { use foo::Point; @@ -47,7 +49,7 @@ mod bar { #[allow(unused_imports)] mod foo { - use core::cmp::Eq; + use std::cmp::Eq; } } @@ -55,8 +57,8 @@ fn main() { cal(foo::Point{x:3, y:9}); let a = 3; ignore(a); - io::stdout().write_str(~"a"); - let _a = do map(~[2]) |&x| { + io::stdout().write_str("a"); + let _a = do map([2]) |&x| { x + 2 }; } diff --git a/src/test/compile-fail/lint-unused-mut-variables.rs b/src/test/compile-fail/lint-unused-mut-variables.rs index d1223cd889307..9b0249bdc2a59 100644 --- a/src/test/compile-fail/lint-unused-mut-variables.rs +++ b/src/test/compile-fail/lint-unused-mut-variables.rs @@ -17,8 +17,8 @@ fn main() { // negative cases let mut a = 3; //~ ERROR: variable does not need to be mutable - let mut a = 2, b = 3; //~ ERROR: variable does not need to be mutable - //~^ ERROR: variable does not need to be mutable + let mut a = 2; //~ ERROR: variable does not need to be mutable + let mut b = 3; //~ ERROR: variable does not need to be mutable let mut a = ~[3]; //~ ERROR: variable does not need to be mutable // positive cases diff --git a/src/test/compile-fail/lint-unused-unsafe.rs b/src/test/compile-fail/lint-unused-unsafe.rs index 465e5548f679c..1b5aabb953713 100644 --- a/src/test/compile-fail/lint-unused-unsafe.rs +++ b/src/test/compile-fail/lint-unused-unsafe.rs @@ -27,8 +27,8 @@ unsafe fn bad3() { unsafe {} } //~ ERROR: unnecessary `unsafe` block fn bad4() { unsafe { do callback {} } } //~ ERROR: unnecessary `unsafe` block unsafe fn bad5() { unsafe { unsf() } } //~ ERROR: unnecessary `unsafe` block fn bad6() { - unsafe { //~ ERROR: unnecessary `unsafe` block - unsafe { // don't put the warning here + unsafe { // don't put the warning here + unsafe { //~ ERROR: unnecessary `unsafe` block unsf() } } diff --git a/src/test/compile-fail/liveness-break-uninit-2.rs b/src/test/compile-fail/liveness-break-uninit-2.rs index c87439db6173a..2ed02e2cdd7db 100644 --- a/src/test/compile-fail/liveness-break-uninit-2.rs +++ b/src/test/compile-fail/liveness-break-uninit-2.rs @@ -13,7 +13,7 @@ fn foo() -> int { while 1 != 2 { break; - x = 0; //~ WARNING unreachable statement + x = 0; } debug!(x); //~ ERROR use of possibly uninitialized variable: `x` diff --git a/src/test/compile-fail/liveness-break-uninit.rs b/src/test/compile-fail/liveness-break-uninit.rs index 07075e4ef6398..2dcbad2804c16 100644 --- a/src/test/compile-fail/liveness-break-uninit.rs +++ b/src/test/compile-fail/liveness-break-uninit.rs @@ -13,7 +13,7 @@ fn foo() -> int { loop { break; - x = 0; //~ WARNING unreachable statement + x = 0; } debug!(x); //~ ERROR use of possibly uninitialized variable: `x` diff --git a/src/test/compile-fail/liveness-issue-2163.rs b/src/test/compile-fail/liveness-issue-2163.rs index 914b7d9d677ad..ec4f3f9a3fdba 100644 --- a/src/test/compile-fail/liveness-issue-2163.rs +++ b/src/test/compile-fail/liveness-issue-2163.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::vec; + fn main() { let a: ~[int] = ~[]; vec::each(a, |_| -> bool { diff --git a/src/test/compile-fail/liveness-move-in-loop.rs b/src/test/compile-fail/liveness-move-in-loop.rs index d1663bc356b18..6fe59f0ca52d1 100644 --- a/src/test/compile-fail/liveness-move-in-loop.rs +++ b/src/test/compile-fail/liveness-move-in-loop.rs @@ -16,10 +16,7 @@ fn main() { loop { loop { loop { -// tjc: Not sure why it prints the same error twice x = y; //~ ERROR use of moved value - //~^ ERROR use of moved value - copy x; } } diff --git a/src/test/compile-fail/liveness-move-in-while.rs b/src/test/compile-fail/liveness-move-in-while.rs index 6b4147242d19b..26e82dd367343 100644 --- a/src/test/compile-fail/liveness-move-in-while.rs +++ b/src/test/compile-fail/liveness-move-in-while.rs @@ -13,10 +13,8 @@ fn main() { let y: ~int = ~42; let mut x: ~int; loop { - debug!(y); -// tjc: not sure why it prints the same error twice + debug!(y); //~ ERROR use of moved value: `y` while true { while true { while true { x = y; copy x; } } } //~^ ERROR use of moved value: `y` - //~^^ ERROR use of moved value: `y` } } diff --git a/src/test/compile-fail/map-types.rs b/src/test/compile-fail/map-types.rs index ebc5b015d2752..f5d6e95fe2f4d 100644 --- a/src/test/compile-fail/map-types.rs +++ b/src/test/compile-fail/map-types.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::container::Map; -use core::hashmap::HashMap; +use std::container::Map; +use std::hashmap::HashMap; // Test that trait types printed in error msgs include the type arguments. @@ -17,5 +17,5 @@ fn main() { let x: @Map<~str, ~str> = @HashMap::new::<~str, ~str>() as @Map<~str, ~str>; let y: @Map = @x; - //~^ ERROR mismatched types: expected `@core::container::Map` + //~^ ERROR mismatched types: expected `@std::container::Map` } diff --git a/src/test/compile-fail/alt-arrows-block-then-binop.rs b/src/test/compile-fail/match-arrows-block-then-binop.rs similarity index 100% rename from src/test/compile-fail/alt-arrows-block-then-binop.rs rename to src/test/compile-fail/match-arrows-block-then-binop.rs diff --git a/src/test/compile-fail/match-ill-type1.rs b/src/test/compile-fail/match-ill-type1.rs new file mode 100644 index 0000000000000..4d2b95b61ea8d --- /dev/null +++ b/src/test/compile-fail/match-ill-type1.rs @@ -0,0 +1,6 @@ +fn main() { + match 1 { + 1..2u => 1, //~ ERROR mismatched types in range + _ => 2, + }; +} diff --git a/src/test/compile-fail/match-ill-type2.rs b/src/test/compile-fail/match-ill-type2.rs new file mode 100644 index 0000000000000..020ccde845246 --- /dev/null +++ b/src/test/compile-fail/match-ill-type2.rs @@ -0,0 +1,7 @@ +fn main() { + match 1 { + 1 => 1, //~ ERROR mismatched types between arms + 2u => 1, + _ => 2, + }; +} diff --git a/src/test/compile-fail/alt-join.rs b/src/test/compile-fail/match-join.rs similarity index 100% rename from src/test/compile-fail/alt-join.rs rename to src/test/compile-fail/match-join.rs diff --git a/src/test/compile-fail/alt-pattern-field-mismatch-2.rs b/src/test/compile-fail/match-pattern-field-mismatch-2.rs similarity index 100% rename from src/test/compile-fail/alt-pattern-field-mismatch-2.rs rename to src/test/compile-fail/match-pattern-field-mismatch-2.rs diff --git a/src/test/compile-fail/alt-pattern-field-mismatch.rs b/src/test/compile-fail/match-pattern-field-mismatch.rs similarity index 100% rename from src/test/compile-fail/alt-pattern-field-mismatch.rs rename to src/test/compile-fail/match-pattern-field-mismatch.rs diff --git a/src/test/compile-fail/alt-range-fail-dominate.rs b/src/test/compile-fail/match-range-fail-dominate.rs similarity index 100% rename from src/test/compile-fail/alt-range-fail-dominate.rs rename to src/test/compile-fail/match-range-fail-dominate.rs diff --git a/src/test/compile-fail/alt-range-fail.rs b/src/test/compile-fail/match-range-fail.rs similarity index 100% rename from src/test/compile-fail/alt-range-fail.rs rename to src/test/compile-fail/match-range-fail.rs diff --git a/src/test/compile-fail/alt-tag-nullary.rs b/src/test/compile-fail/match-tag-nullary.rs similarity index 100% rename from src/test/compile-fail/alt-tag-nullary.rs rename to src/test/compile-fail/match-tag-nullary.rs diff --git a/src/test/compile-fail/alt-tag-unary.rs b/src/test/compile-fail/match-tag-unary.rs similarity index 100% rename from src/test/compile-fail/alt-tag-unary.rs rename to src/test/compile-fail/match-tag-unary.rs diff --git a/src/test/compile-fail/alt-vec-invalid.rs b/src/test/compile-fail/match-vec-invalid.rs similarity index 100% rename from src/test/compile-fail/alt-vec-invalid.rs rename to src/test/compile-fail/match-vec-invalid.rs diff --git a/src/test/compile-fail/alt-vec-mismatch-2.rs b/src/test/compile-fail/match-vec-mismatch-2.rs similarity index 100% rename from src/test/compile-fail/alt-vec-mismatch-2.rs rename to src/test/compile-fail/match-vec-mismatch-2.rs diff --git a/src/test/compile-fail/alt-vec-mismatch.rs b/src/test/compile-fail/match-vec-mismatch.rs similarity index 100% rename from src/test/compile-fail/alt-vec-mismatch.rs rename to src/test/compile-fail/match-vec-mismatch.rs diff --git a/src/test/compile-fail/alt-vec-unreachable.rs b/src/test/compile-fail/match-vec-unreachable.rs similarity index 91% rename from src/test/compile-fail/alt-vec-unreachable.rs rename to src/test/compile-fail/match-vec-unreachable.rs index 2719d84b2dd25..3930e7d219201 100644 --- a/src/test/compile-fail/alt-vec-unreachable.rs +++ b/src/test/compile-fail/match-vec-unreachable.rs @@ -7,7 +7,7 @@ fn main() { } match [~"foo", ~"bar", ~"baz"] { - [a, _, _, .._] => { io::println(a); } + [a, _, _, .._] => { println(a); } [~"foo", ~"bar", ~"baz", ~"foo", ~"bar"] => { } //~ ERROR unreachable pattern _ => { } } diff --git a/src/test/compile-fail/mod_file_not_exist.rs b/src/test/compile-fail/mod_file_not_exist.rs index 17ca8dca27352..9b16738e951f7 100644 --- a/src/test/compile-fail/mod_file_not_exist.rs +++ b/src/test/compile-fail/mod_file_not_exist.rs @@ -11,5 +11,5 @@ mod not_a_real_file; //~ ERROR not_a_real_file.rs fn main() { - assert!(mod_file_aux::bar() == 10); + assert_eq!(mod_file_aux::bar(), 10); } diff --git a/src/test/compile-fail/mod_file_with_path_attr.rs b/src/test/compile-fail/mod_file_with_path_attr.rs index 827c77bda471d..ff330047c4e96 100644 --- a/src/test/compile-fail/mod_file_with_path_attr.rs +++ b/src/test/compile-fail/mod_file_with_path_attr.rs @@ -12,5 +12,5 @@ mod m; //~ ERROR not_a_real_file.rs fn main() { - assert!(m::foo() == 10); + assert_eq!(m::foo(), 10); } diff --git a/src/test/compile-fail/moves-based-on-type-access-to-field.rs b/src/test/compile-fail/moves-based-on-type-access-to-field.rs index 6cc19b18c20a6..1a2beedff9306 100644 --- a/src/test/compile-fail/moves-based-on-type-access-to-field.rs +++ b/src/test/compile-fail/moves-based-on-type-access-to-field.rs @@ -7,13 +7,13 @@ fn touch(_a: &A) {} fn f10() { let x = Foo { f: ~"hi", y: 3 }; - consume(x.f); //~ NOTE field of `x` moved here + consume(x.f); //~ NOTE `x.f` moved here touch(&x.y); //~ ERROR use of partially moved value: `x` } fn f20() { let x = ~[~"hi"]; - consume(x[0]); //~ NOTE element of `x` moved here + consume(x[0]); //~ NOTE `(*x)[]` moved here touch(&x[0]); //~ ERROR use of partially moved value: `x` } diff --git a/src/test/compile-fail/moves-based-on-type-block-bad.rs b/src/test/compile-fail/moves-based-on-type-block-bad.rs index 76d50710bb8c1..11c4d078208ee 100644 --- a/src/test/compile-fail/moves-based-on-type-block-bad.rs +++ b/src/test/compile-fail/moves-based-on-type-block-bad.rs @@ -16,9 +16,9 @@ fn main() { let s = S { x: ~Bar(~42) }; loop { do f(&s) |hellothere| { - match hellothere.x { //~ ERROR cannot move out + match hellothere.x { ~Foo(_) => {} - ~Bar(x) => io::println(x.to_str()), + ~Bar(x) => println(x.to_str()), //~ ERROR cannot move out ~Baz => {} } } diff --git a/src/test/compile-fail/moves-based-on-type-capture-clause-bad.rs b/src/test/compile-fail/moves-based-on-type-capture-clause-bad.rs index 6dce011ddc896..706ab051ca1a0 100644 --- a/src/test/compile-fail/moves-based-on-type-capture-clause-bad.rs +++ b/src/test/compile-fail/moves-based-on-type-capture-clause-bad.rs @@ -1,7 +1,9 @@ +use std::task; + fn main() { let x = ~"Hello world!"; do task::spawn { - io::println(x); + println(x); } - io::println(x); //~ ERROR use of moved value + println(x); //~ ERROR use of moved value } diff --git a/src/test/compile-fail/moves-based-on-type-cyclic-types-issue-4821.rs b/src/test/compile-fail/moves-based-on-type-cyclic-types-issue-4821.rs index 2b9291ce3284c..7c01ddb6c9331 100644 --- a/src/test/compile-fail/moves-based-on-type-cyclic-types-issue-4821.rs +++ b/src/test/compile-fail/moves-based-on-type-cyclic-types-issue-4821.rs @@ -12,7 +12,7 @@ // temporary kinds wound up being stored in a cache and used later. // See middle::ty::type_contents() for more information. -extern mod std; +extern mod extra; struct List { key: int, next: Option<~List> } diff --git a/src/test/compile-fail/moves-based-on-type-exprs.rs b/src/test/compile-fail/moves-based-on-type-exprs.rs index 5b733129ee5dc..38718006d8b18 100644 --- a/src/test/compile-fail/moves-based-on-type-exprs.rs +++ b/src/test/compile-fail/moves-based-on-type-exprs.rs @@ -1,6 +1,8 @@ // Tests that references to move-by-default values trigger moves when // they occur as part of various kinds of expressions. +use std::vec; + struct Foo { f: A } fn guard(_s: ~str) -> bool {fail!()} fn touch(_a: &A) {} @@ -24,7 +26,8 @@ fn f21() { } fn f30(cond: bool) { - let x = ~"hi", y = ~"ho"; + let x = ~"hi"; + let y = ~"ho"; let _y = if cond { x } else { @@ -35,7 +38,8 @@ fn f30(cond: bool) { } fn f40(cond: bool) { - let x = ~"hi", y = ~"ho"; + let x = ~"hi"; + let y = ~"ho"; let _y = match cond { true => x, false => y @@ -45,7 +49,8 @@ fn f40(cond: bool) { } fn f50(cond: bool) { - let x = ~"hi", y = ~"ho"; + let x = ~"hi"; + let y = ~"ho"; let _y = match cond { _ if guard(x) => 10, true => 10, @@ -86,7 +91,7 @@ fn f110() { } fn f120() { - let x = ~[~"hi", ~"ho"]; + let mut x = ~[~"hi", ~"ho"]; vec::swap(x, 0, 1); touch(&x[0]); touch(&x[1]); diff --git a/src/test/compile-fail/moves-based-on-type-match-bindings.rs b/src/test/compile-fail/moves-based-on-type-match-bindings.rs new file mode 100644 index 0000000000000..42944a206b360 --- /dev/null +++ b/src/test/compile-fail/moves-based-on-type-match-bindings.rs @@ -0,0 +1,19 @@ +// Tests that bindings to move-by-default values trigger moves of the +// discriminant. Also tests that the compiler explains the move in +// terms of the binding, not the discriminant. + +struct Foo { f: A } +fn guard(_s: ~str) -> bool {fail!()} +fn touch(_a: &A) {} + +fn f10() { + let x = Foo {f: ~"hi"}; + + let y = match x { + Foo {f} => {} //~ NOTE moved here + }; + + touch(&x); //~ ERROR use of partially moved value: `x` +} + +fn main() {} diff --git a/src/test/compile-fail/moves-based-on-type-move-out-of-closure-env-issue-1965.rs b/src/test/compile-fail/moves-based-on-type-move-out-of-closure-env-issue-1965.rs index ecd58d485a89d..e25ba0f39f2e8 100644 --- a/src/test/compile-fail/moves-based-on-type-move-out-of-closure-env-issue-1965.rs +++ b/src/test/compile-fail/moves-based-on-type-move-out-of-closure-env-issue-1965.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::uint; + fn test(_x: ~uint) {} fn main() { diff --git a/src/test/compile-fail/mutable-class-fields-2.rs b/src/test/compile-fail/mutable-class-fields-2.rs index f5d24b316414e..30c2b9eef8ca0 100644 --- a/src/test/compile-fail/mutable-class-fields-2.rs +++ b/src/test/compile-fail/mutable-class-fields-2.rs @@ -9,13 +9,13 @@ // except according to those terms. struct cat { - priv mut meows : uint, + priv meows : uint, how_hungry : int, } -pub impl cat { - fn eat(&self) { +impl cat { + pub fn eat(&self) { self.how_hungry -= 5; //~ ERROR cannot assign } diff --git a/src/test/compile-fail/mutable-class-fields.rs b/src/test/compile-fail/mutable-class-fields.rs index 8bebec7134cc3..a88156a4b477d 100644 --- a/src/test/compile-fail/mutable-class-fields.rs +++ b/src/test/compile-fail/mutable-class-fields.rs @@ -9,7 +9,7 @@ // except according to those terms. struct cat { - priv mut meows : uint, + priv meows : uint, how_hungry : int, } diff --git a/src/test/compile-fail/mutable-huh-ptr-assign.rs b/src/test/compile-fail/mutable-huh-ptr-assign.rs index c907eb4be49f8..4460da72e2059 100644 --- a/src/test/compile-fail/mutable-huh-ptr-assign.rs +++ b/src/test/compile-fail/mutable-huh-ptr-assign.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; +extern mod extra; fn main() { unsafe fn f(v: *const int) { diff --git a/src/test/compile-fail/name-clash-nullary.rs b/src/test/compile-fail/name-clash-nullary.rs index e64d651dab2b4..68f5d921d0239 100644 --- a/src/test/compile-fail/name-clash-nullary.rs +++ b/src/test/compile-fail/name-clash-nullary.rs @@ -9,7 +9,7 @@ // except according to those terms. // error-pattern:declaration of `None` shadows -use core::option::*; +use std::option::*; fn main() { let None: int = 42; diff --git a/src/test/compile-fail/no-capture-arc.rs b/src/test/compile-fail/no-capture-arc.rs index 2c8c98ad5d6de..b036071fd8794 100644 --- a/src/test/compile-fail/no-capture-arc.rs +++ b/src/test/compile-fail/no-capture-arc.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -10,19 +10,21 @@ // error-pattern: use of moved value -extern mod std; -use std::arc; +extern mod extra; +use extra::arc; + +use std::task; fn main() { let v = ~[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; let arc_v = arc::ARC(v); do task::spawn() { - let v = *arc::get(&arc_v); - assert!(v[3] == 4); + let v = arc_v.get(); + assert_eq!(v[3], 4); }; - assert!((*arc::get(&arc_v))[2] == 3); + assert_eq!((arc_v.get())[2], 3); info!(arc_v); } diff --git a/src/test/compile-fail/no-reuse-move-arc.rs b/src/test/compile-fail/no-reuse-move-arc.rs index 75cd706985c64..28f3ea7af9f8c 100644 --- a/src/test/compile-fail/no-reuse-move-arc.rs +++ b/src/test/compile-fail/no-reuse-move-arc.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,19 +8,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; -use std::arc; +extern mod extra; +use extra::arc; + +use std::task; fn main() { let v = ~[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; let arc_v = arc::ARC(v); - do task::spawn() { //~ NOTE `arc_v` moved into closure environment here - let v = *arc::get(&arc_v); - assert!(v[3] == 4); + do task::spawn() { + let v = arc_v.get(); + assert_eq!(v[3], 4); }; - assert!((*arc::get(&arc_v))[2] == 3); //~ ERROR use of moved value: `arc_v` + assert_eq!((arc_v.get())[2], 3); //~ ERROR use of moved value: `arc_v` - info!(arc_v); + info!(arc_v); //~ ERROR use of moved value: `arc_v` } diff --git a/src/test/compile-fail/no-send-res-ports.rs b/src/test/compile-fail/no-send-res-ports.rs index c1071e5a8c4d9..5e18a40a99c80 100644 --- a/src/test/compile-fail/no-send-res-ports.rs +++ b/src/test/compile-fail/no-send-res-ports.rs @@ -8,7 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::cell::Cell; +use std::cell::Cell; +use std::task; struct Port(@T); @@ -28,7 +29,7 @@ fn main() { } } - let x = Cell(foo(Port(@()))); + let x = Cell::new(foo(Port(@()))); do task::spawn { let y = x.take(); //~ ERROR value has non-owned type diff --git a/src/test/compile-fail/noexporttypeexe.rs b/src/test/compile-fail/noexporttypeexe.rs index 95428568e4c35..3add0134d002a 100644 --- a/src/test/compile-fail/noexporttypeexe.rs +++ b/src/test/compile-fail/noexporttypeexe.rs @@ -18,5 +18,5 @@ fn main() { // because the def_id associated with the type was // not convertible to a path. let x: int = noexporttypelib::foo(); - //~^ ERROR expected `int` but found `core::option::Option` + //~^ ERROR expected `int` but found `std::option::Option` } diff --git a/src/test/compile-fail/non-copyable-void.rs b/src/test/compile-fail/non-copyable-void.rs index b89e22582bb3a..f979f8273a04e 100644 --- a/src/test/compile-fail/non-copyable-void.rs +++ b/src/test/compile-fail/non-copyable-void.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::libc; + fn main() { let x : *~[int] = &~[1,2,3]; let y : *libc::c_void = x as *libc::c_void; diff --git a/src/test/compile-fail/packed-struct-generic-transmute.rs b/src/test/compile-fail/packed-struct-generic-transmute.rs index c03261816ef31..3b9b17e051d6f 100644 --- a/src/test/compile-fail/packed-struct-generic-transmute.rs +++ b/src/test/compile-fail/packed-struct-generic-transmute.rs @@ -15,6 +15,8 @@ // error-pattern: transmute called on types with different size +use std::cast; + #[packed] struct Foo { bar: T, diff --git a/src/test/compile-fail/packed-struct-transmute.rs b/src/test/compile-fail/packed-struct-transmute.rs index cad78f9e5d1f5..bf62bab8b408f 100644 --- a/src/test/compile-fail/packed-struct-transmute.rs +++ b/src/test/compile-fail/packed-struct-transmute.rs @@ -15,6 +15,8 @@ // error-pattern: transmute called on types with different size +use std::cast; + #[packed] struct Foo { bar: u8, diff --git a/src/test/compile-fail/pattern-tyvar-2.rs b/src/test/compile-fail/pattern-tyvar-2.rs index 41529b3da93ed..537d095d2d7a3 100644 --- a/src/test/compile-fail/pattern-tyvar-2.rs +++ b/src/test/compile-fail/pattern-tyvar-2.rs @@ -10,7 +10,7 @@ // except according to those terms. -extern mod std; +extern mod extra; enum bar { t1((), Option<~[int]>), t2, } diff --git a/src/test/compile-fail/pattern-tyvar.rs b/src/test/compile-fail/pattern-tyvar.rs index 506c71f493ae3..4ca0aac35ee66 100644 --- a/src/test/compile-fail/pattern-tyvar.rs +++ b/src/test/compile-fail/pattern-tyvar.rs @@ -9,7 +9,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; +extern mod extra; // error-pattern: mismatched types diff --git a/src/test/compile-fail/private-impl-method.rs b/src/test/compile-fail/private-impl-method.rs index a6728f82ec3b3..26b7d73ab2af2 100644 --- a/src/test/compile-fail/private-impl-method.rs +++ b/src/test/compile-fail/private-impl-method.rs @@ -13,7 +13,7 @@ mod a { x: int } - pub impl Foo { + impl Foo { priv fn foo(&self) {} } } diff --git a/src/test/compile-fail/private-method.rs b/src/test/compile-fail/private-method.rs index 0d84bc2fc605c..0c67980a5515c 100644 --- a/src/test/compile-fail/private-method.rs +++ b/src/test/compile-fail/private-method.rs @@ -11,13 +11,15 @@ // error-pattern:method `nap` is private mod kitties { + use std::uint; + pub struct cat { - priv mut meows : uint, + priv meows : uint, how_hungry : int, } - pub impl cat { + impl cat { priv fn nap(&self) { uint::range(1u, 10000u, |_i| false); } } diff --git a/src/test/compile-fail/private-variant-xc.rs b/src/test/compile-fail/private-variant-xc.rs new file mode 100644 index 0000000000000..c7838b9885508 --- /dev/null +++ b/src/test/compile-fail/private-variant-xc.rs @@ -0,0 +1,9 @@ +// aux-build:private_variant_xc.rs + +extern mod private_variant_xc; + +pub fn main() { + let _ = private_variant_xc::Bar; + let _ = private_variant_xc::Baz; //~ ERROR unresolved name +} + diff --git a/src/test/compile-fail/qquote-1.rs b/src/test/compile-fail/qquote-1.rs index 1241190b5371f..156d09cedff6c 100644 --- a/src/test/compile-fail/qquote-1.rs +++ b/src/test/compile-fail/qquote-1.rs @@ -10,7 +10,7 @@ // xfail-test Can't use syntax crate here -extern mod std; +extern mod extra; extern mod syntax; use io::*; diff --git a/src/test/compile-fail/qquote-2.rs b/src/test/compile-fail/qquote-2.rs index 07500825a952b..2a593c51759c0 100644 --- a/src/test/compile-fail/qquote-2.rs +++ b/src/test/compile-fail/qquote-2.rs @@ -10,10 +10,10 @@ // xfail-test Can't use syntax crate here -extern mod std; +extern mod extra; extern mod syntax; -use std::io::*; +use extra::io::*; use syntax::diagnostic; use syntax::ast; diff --git a/src/test/compile-fail/refutable-pattern-in-fn-arg.rs b/src/test/compile-fail/refutable-pattern-in-fn-arg.rs index 957925709e179..524deed20f243 100644 --- a/src/test/compile-fail/refutable-pattern-in-fn-arg.rs +++ b/src/test/compile-fail/refutable-pattern-in-fn-arg.rs @@ -9,6 +9,6 @@ // except according to those terms. fn main() { - let f = |3: int| io::println("hello"); //~ ERROR refutable pattern + let f = |3: int| println("hello"); //~ ERROR refutable pattern f(4); } diff --git a/src/test/compile-fail/regions-addr-of-self.rs b/src/test/compile-fail/regions-addr-of-self.rs index f96ef639e756c..0516264d45797 100644 --- a/src/test/compile-fail/regions-addr-of-self.rs +++ b/src/test/compile-fail/regions-addr-of-self.rs @@ -12,13 +12,13 @@ struct dog { cats_chased: uint, } -pub impl dog { - fn chase_cat(&mut self) { +impl dog { + pub fn chase_cat(&mut self) { let p: &'static mut uint = &mut self.cats_chased; //~ ERROR cannot infer an appropriate lifetime due to conflicting requirements *p += 1u; } - fn chase_cat_2(&mut self) { + pub fn chase_cat_2(&mut self) { let p: &'blk mut uint = &mut self.cats_chased; *p += 1u; } diff --git a/src/test/compile-fail/regions-addr-of-upvar-self.rs b/src/test/compile-fail/regions-addr-of-upvar-self.rs index b9a9e2f38f5aa..f1172690f4dfa 100644 --- a/src/test/compile-fail/regions-addr-of-upvar-self.rs +++ b/src/test/compile-fail/regions-addr-of-upvar-self.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::uint; + struct dog { food: uint, } -pub impl dog { - fn chase_cat(&mut self) { +impl dog { + pub fn chase_cat(&mut self) { for uint::range(0u, 10u) |_i| { let p: &'static mut uint = &mut self.food; //~ ERROR cannot infer an appropriate lifetime due to conflicting requirements *p = 3u; diff --git a/src/test/compile-fail/regions-glb-free-free.rs b/src/test/compile-fail/regions-glb-free-free.rs index 9a4974849a50d..d438b55f4af79 100644 --- a/src/test/compile-fail/regions-glb-free-free.rs +++ b/src/test/compile-fail/regions-glb-free-free.rs @@ -9,7 +9,7 @@ // except according to those terms. mod argparse { - extern mod std; + extern mod extra; pub struct Flag<'self> { name: &'self str, @@ -22,8 +22,8 @@ mod argparse { Flag { name: name, desc: desc, max_count: 1, value: 0 } } - pub impl<'self> Flag<'self> { - fn set_desc(self, s: &str) -> Flag<'self> { + impl<'self> Flag<'self> { + pub fn set_desc(self, s: &str) -> Flag<'self> { Flag { //~ ERROR cannot infer an appropriate lifetime name: self.name, desc: s, @@ -37,5 +37,5 @@ mod argparse { fn main () { let f : argparse::Flag = argparse::flag(~"flag", ~"My flag"); let updated_flag = f.set_desc(~"My new flag"); - assert!(updated_flag.desc == "My new flag"); + assert_eq!(updated_flag.desc, "My new flag"); } diff --git a/src/test/compile-fail/regions-infer-borrow-scope-too-big.rs b/src/test/compile-fail/regions-infer-borrow-scope-too-big.rs index d519397f68c58..5710188ed9fe5 100644 --- a/src/test/compile-fail/regions-infer-borrow-scope-too-big.rs +++ b/src/test/compile-fail/regions-infer-borrow-scope-too-big.rs @@ -19,7 +19,7 @@ fn x_coord<'r>(p: &'r point) -> &'r int { fn foo(p: @point) -> &int { let xc = x_coord(p); //~ ERROR cannot root - assert!(*xc == 3); + assert_eq!(*xc, 3); return xc; } diff --git a/src/test/compile-fail/regions-infer-borrow-scope-within-loop.rs b/src/test/compile-fail/regions-infer-borrow-scope-within-loop.rs index 50ac5f65772fc..2ffd0796e30e7 100644 --- a/src/test/compile-fail/regions-infer-borrow-scope-within-loop.rs +++ b/src/test/compile-fail/regions-infer-borrow-scope-within-loop.rs @@ -15,11 +15,11 @@ fn foo(cond: &fn() -> bool, box: &fn() -> @int) { loop { let x = box(); - // Here we complain because the resulting region - // of this borrow is the fn body as a whole. + // Here we complain because the resulting region + // of this borrow is the fn body as a whole. y = borrow(x); //~ ERROR cannot root - assert!(*x == *y); + assert_eq!(*x, *y); if cond() { break; } } assert!(*y != 0); diff --git a/src/test/compile-fail/regions-trait-1.rs b/src/test/compile-fail/regions-trait-1.rs index ff75ba4473de7..ae697ad1181c3 100644 --- a/src/test/compile-fail/regions-trait-1.rs +++ b/src/test/compile-fail/regions-trait-1.rs @@ -34,5 +34,5 @@ fn get_v(gc: @get_ctxt) -> uint { fn main() { let ctxt = ctxt { v: 22u }; let hc = has_ctxt { c: &ctxt }; - assert!(get_v(@hc as @get_ctxt) == 22u); + assert_eq!(get_v(@hc as @get_ctxt), 22u); } diff --git a/src/test/compile-fail/regions-var-type-out-of-scope.rs b/src/test/compile-fail/regions-var-type-out-of-scope.rs index addf20fd70249..8955a26de0b93 100644 --- a/src/test/compile-fail/regions-var-type-out-of-scope.rs +++ b/src/test/compile-fail/regions-var-type-out-of-scope.rs @@ -15,7 +15,7 @@ fn foo(cond: bool) { if cond { x = &3; //~ ERROR borrowed value does not live long enough - assert!((*x == 3)); + assert_eq!(*x, 3); } } diff --git a/src/test/compile-fail/repeat-to-run-dtor-twice.rs b/src/test/compile-fail/repeat-to-run-dtor-twice.rs index e1e1e2313f42a..0dd12822dfae5 100644 --- a/src/test/compile-fail/repeat-to-run-dtor-twice.rs +++ b/src/test/compile-fail/repeat-to-run-dtor-twice.rs @@ -18,7 +18,7 @@ struct Foo { impl Drop for Foo { fn finalize(&self) { - io::println("Goodbye!"); + println("Goodbye!"); } } diff --git a/src/test/compile-fail/resolve-inconsistent-binding-mode.rs b/src/test/compile-fail/resolve-inconsistent-binding-mode.rs index 33cc934c7b3fe..65fbbfc6e1985 100644 --- a/src/test/compile-fail/resolve-inconsistent-binding-mode.rs +++ b/src/test/compile-fail/resolve-inconsistent-binding-mode.rs @@ -14,7 +14,7 @@ enum opts { fn matcher1(x: opts) { match x { - a(ref i) | b(copy i) => {} //~ ERROR variable `i` is bound with different mode in pattern #2 than in pattern #1 + a(ref i) | b(i) => {} //~ ERROR variable `i` is bound with different mode in pattern #2 than in pattern #1 c(_) => {} } } diff --git a/src/test/compile-fail/seq-args.rs b/src/test/compile-fail/seq-args.rs index 0d253d782832a..a6ab41a3d6b74 100644 --- a/src/test/compile-fail/seq-args.rs +++ b/src/test/compile-fail/seq-args.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; +extern mod extra; fn main() { trait seq { } diff --git a/src/test/compile-fail/spawn-non-nil-fn.rs b/src/test/compile-fail/spawn-non-nil-fn.rs index 00e3e612e8f5b..8db2c686f30ac 100644 --- a/src/test/compile-fail/spawn-non-nil-fn.rs +++ b/src/test/compile-fail/spawn-non-nil-fn.rs @@ -10,6 +10,8 @@ // error-pattern: mismatched types -extern mod std; +extern mod extra; + +use std::task; fn main() { task::spawn(|| -> int { 10 }); } diff --git a/src/test/compile-fail/static-assert.rs b/src/test/compile-fail/static-assert.rs new file mode 100644 index 0000000000000..06f8c9f1a3257 --- /dev/null +++ b/src/test/compile-fail/static-assert.rs @@ -0,0 +1,5 @@ +#[static_assert] +static a: bool = false; //~ ERROR static assertion failed + +fn main() { +} diff --git a/src/test/compile-fail/static-assert2.rs b/src/test/compile-fail/static-assert2.rs new file mode 100644 index 0000000000000..de1c6427e14b2 --- /dev/null +++ b/src/test/compile-fail/static-assert2.rs @@ -0,0 +1,4 @@ +#[static_assert] +static e: bool = 1 == 2; //~ ERROR static assertion failed + +fn main() {} diff --git a/src/test/compile-fail/sync-cond-shouldnt-escape.rs b/src/test/compile-fail/sync-cond-shouldnt-escape.rs index 964c2ce946b47..b22d4d3b2e2e3 100644 --- a/src/test/compile-fail/sync-cond-shouldnt-escape.rs +++ b/src/test/compile-fail/sync-cond-shouldnt-escape.rs @@ -9,8 +9,8 @@ // except according to those terms. // error-pattern: reference is not valid outside of its lifetime -extern mod std; -use std::sync; +extern mod extra; +use extra::sync; fn main() { let m = ~sync::Mutex(); diff --git a/src/test/compile-fail/sync-rwlock-cond-shouldnt-escape.rs b/src/test/compile-fail/sync-rwlock-cond-shouldnt-escape.rs index 9cab2d3b05626..518e67800d763 100644 --- a/src/test/compile-fail/sync-rwlock-cond-shouldnt-escape.rs +++ b/src/test/compile-fail/sync-rwlock-cond-shouldnt-escape.rs @@ -9,8 +9,8 @@ // except according to those terms. // error-pattern: reference is not valid outside of its lifetime -extern mod std; -use std::sync; +extern mod extra; +use extra::sync; fn main() { let x = ~sync::RWlock(); let mut y = None; diff --git a/src/test/compile-fail/sync-rwlock-read-mode-shouldnt-escape.rs b/src/test/compile-fail/sync-rwlock-read-mode-shouldnt-escape.rs index 4195d8700678b..4bec5fa270ab8 100644 --- a/src/test/compile-fail/sync-rwlock-read-mode-shouldnt-escape.rs +++ b/src/test/compile-fail/sync-rwlock-read-mode-shouldnt-escape.rs @@ -9,8 +9,8 @@ // except according to those terms. // error-pattern: cannot infer an appropriate lifetime -extern mod std; -use std::sync; +extern mod extra; +use extra::sync; fn main() { let x = ~sync::RWlock(); let mut y = None; diff --git a/src/test/compile-fail/sync-rwlock-write-mode-cond-shouldnt-escape.rs b/src/test/compile-fail/sync-rwlock-write-mode-cond-shouldnt-escape.rs index 43ad693ccf8d8..09b83887bcfd1 100644 --- a/src/test/compile-fail/sync-rwlock-write-mode-cond-shouldnt-escape.rs +++ b/src/test/compile-fail/sync-rwlock-write-mode-cond-shouldnt-escape.rs @@ -9,8 +9,8 @@ // except according to those terms. // error-pattern: reference is not valid outside of its lifetime -extern mod std; -use std::sync; +extern mod extra; +use extra::sync; fn main() { let x = ~sync::RWlock(); let mut y = None; diff --git a/src/test/compile-fail/sync-rwlock-write-mode-shouldnt-escape.rs b/src/test/compile-fail/sync-rwlock-write-mode-shouldnt-escape.rs index 525d334f4115d..679c4a72598ea 100644 --- a/src/test/compile-fail/sync-rwlock-write-mode-shouldnt-escape.rs +++ b/src/test/compile-fail/sync-rwlock-write-mode-shouldnt-escape.rs @@ -9,8 +9,8 @@ // except according to those terms. // error-pattern: reference is not valid outside of its lifetime -extern mod std; -use std::sync; +extern mod extra; +use extra::sync; fn main() { let x = ~sync::RWlock(); let mut y = None; diff --git a/src/test/compile-fail/tag-that-dare-not-speak-its-name.rs b/src/test/compile-fail/tag-that-dare-not-speak-its-name.rs index 22f6a34a181fb..ebd3320d90126 100644 --- a/src/test/compile-fail/tag-that-dare-not-speak-its-name.rs +++ b/src/test/compile-fail/tag-that-dare-not-speak-its-name.rs @@ -11,11 +11,11 @@ // error-pattern:mismatched types: expected `char` but found // Issue #876 -#[no_core]; +#[no_std]; -extern mod core; +extern mod std; -fn last(v: ~[&T]) -> core::option::Option { +fn last(v: ~[&T]) -> std::option::Option { fail!(); } diff --git a/src/test/compile-fail/trait-or-new-type-instead.rs b/src/test/compile-fail/trait-or-new-type-instead.rs index a5e37eb949d28..f687a6f97024a 100644 --- a/src/test/compile-fail/trait-or-new-type-instead.rs +++ b/src/test/compile-fail/trait-or-new-type-instead.rs @@ -9,8 +9,8 @@ // except according to those terms. // error-pattern: implement a trait or new type instead -pub impl Option { - fn foo(&self) { } +impl Option { + pub fn foo(&self) { } } fn main() { } diff --git a/src/test/compile-fail/tuple-struct-nonexhaustive.rs b/src/test/compile-fail/tuple-struct-nonexhaustive.rs index de28a06ababcb..785eeb24784fa 100644 --- a/src/test/compile-fail/tuple-struct-nonexhaustive.rs +++ b/src/test/compile-fail/tuple-struct-nonexhaustive.rs @@ -13,7 +13,7 @@ struct Foo(int, int); fn main() { let x = Foo(1, 2); match x { //~ ERROR non-exhaustive - Foo(1, b) => io::println(fmt!("%d", b)), - Foo(2, b) => io::println(fmt!("%d", b)) + Foo(1, b) => println(fmt!("%d", b)), + Foo(2, b) => println(fmt!("%d", b)) } } diff --git a/src/test/compile-fail/unique-object-noncopyable.rs b/src/test/compile-fail/unique-object-noncopyable.rs index 95945b0b5baa4..3844dab726e68 100644 --- a/src/test/compile-fail/unique-object-noncopyable.rs +++ b/src/test/compile-fail/unique-object-noncopyable.rs @@ -22,7 +22,7 @@ impl Drop for Bar { impl Foo for Bar { fn f(&self) { - io::println("hi"); + println("hi"); } } diff --git a/src/test/compile-fail/unreachable-code.rs b/src/test/compile-fail/unreachable-code.rs index f1fbc5b009e0a..a9365eeda1c55 100644 --- a/src/test/compile-fail/unreachable-code.rs +++ b/src/test/compile-fail/unreachable-code.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:unreachable statement +#[deny(unreachable_code)]; +#[allow(unused_variable)]; + fn main() { loop{} - // red herring to make sure compilation fails - error!(42 == 'c'); + + let a = 3; //~ ERROR: unreachable statement } diff --git a/src/test/compile-fail/unresolved-extern-mod-suggestion.rs b/src/test/compile-fail/unresolved-extern-mod-suggestion.rs new file mode 100644 index 0000000000000..f2b1203511cb6 --- /dev/null +++ b/src/test/compile-fail/unresolved-extern-mod-suggestion.rs @@ -0,0 +1,14 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern mod extra; +use extra; //~ ERROR unresolved import (maybe you meant `extra::*`?) + +fn main() {} diff --git a/src/test/compile-fail/unsafe-fn-called-from-safe.rs b/src/test/compile-fail/unsafe-fn-called-from-safe.rs index 864dffea8bf99..2ea0f5a4ec91d 100644 --- a/src/test/compile-fail/unsafe-fn-called-from-safe.rs +++ b/src/test/compile-fail/unsafe-fn-called-from-safe.rs @@ -13,5 +13,5 @@ unsafe fn f() { return; } fn main() { - f(); //~ ERROR access to unsafe function requires unsafe function or block + f(); //~ ERROR call to unsafe function requires unsafe function or block } diff --git a/src/test/compile-fail/unsafe-fn-used-as-value.rs b/src/test/compile-fail/unsafe-fn-used-as-value.rs index cbfb60f0a3236..b5565b4821b36 100644 --- a/src/test/compile-fail/unsafe-fn-used-as-value.rs +++ b/src/test/compile-fail/unsafe-fn-used-as-value.rs @@ -13,6 +13,6 @@ unsafe fn f() { return; } fn main() { - let x = f; //~ ERROR access to unsafe function requires unsafe function or block - x(); + let x = f; + x(); //~ ERROR call to unsafe function requires unsafe function or block } diff --git a/src/test/compile-fail/unsendable-class.rs b/src/test/compile-fail/unsendable-class.rs index 3eebc4647c28b..58de0926f7c66 100644 --- a/src/test/compile-fail/unsendable-class.rs +++ b/src/test/compile-fail/unsendable-class.rs @@ -11,6 +11,8 @@ // Test that a class with an unsendable field can't be // sent +use std::comm; + struct foo { i: int, j: @~str, diff --git a/src/test/compile-fail/unsized-bare-typaram.rs b/src/test/compile-fail/unsized-bare-typaram.rs new file mode 100644 index 0000000000000..ff9d379c30f5e --- /dev/null +++ b/src/test/compile-fail/unsized-bare-typaram.rs @@ -0,0 +1,14 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// error-pattern: instantiating a type parameter with an incompatible type +fn bar() { } +fn foo() { bar::() } +fn main() { } diff --git a/src/test/compile-fail/unsized-enum.rs b/src/test/compile-fail/unsized-enum.rs new file mode 100644 index 0000000000000..df7d82f0b2590 --- /dev/null +++ b/src/test/compile-fail/unsized-enum.rs @@ -0,0 +1,14 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// error-pattern: instantiating a type parameter with an incompatible type +fn bar() { } +fn foo() { bar::>() } +fn main() { } diff --git a/src/test/run-pass/mod-merge-hack-template.rs b/src/test/compile-fail/unsized-struct.rs similarity index 73% rename from src/test/run-pass/mod-merge-hack-template.rs rename to src/test/compile-fail/unsized-struct.rs index 7f7dd33dc099f..da3e9e1243058 100644 --- a/src/test/run-pass/mod-merge-hack-template.rs +++ b/src/test/compile-fail/unsized-struct.rs @@ -8,9 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// xfail-test not a test. used by mod-merge-hack.rs +// error-pattern: instantiating a type parameter with an incompatible type -use T = self::inst::T; +struct Foo { data: T } -pub static bits: uint = inst::bits; -pub fn min(x: T, y: T) -> T { if x < y { x } else { y } } +fn bar() { } +fn foo() { bar::>() } +fn main() { } diff --git a/src/test/compile-fail/unsupported-cast.rs b/src/test/compile-fail/unsupported-cast.rs index 3af012a6c3fcf..da8f69d7eae2d 100644 --- a/src/test/compile-fail/unsupported-cast.rs +++ b/src/test/compile-fail/unsupported-cast.rs @@ -10,6 +10,8 @@ // error-pattern:unsupported cast +use std::libc; + fn main() { debug!(1.0 as *libc::FILE); // Can't cast float to foreign. } diff --git a/src/test/compile-fail/use-after-move-based-on-type.rs b/src/test/compile-fail/use-after-move-based-on-type.rs index 3d176bb339d83..e8802e6e5cb68 100644 --- a/src/test/compile-fail/use-after-move-based-on-type.rs +++ b/src/test/compile-fail/use-after-move-based-on-type.rs @@ -11,5 +11,5 @@ fn main() { let x = ~"Hello!"; let _y = x; - io::println(x); //~ ERROR use of moved value + println(x); //~ ERROR use of moved value } diff --git a/src/test/compile-fail/use-after-move-self-based-on-type.rs b/src/test/compile-fail/use-after-move-self-based-on-type.rs index d19b4dfbd57d0..5b4d67fb0cef2 100644 --- a/src/test/compile-fail/use-after-move-self-based-on-type.rs +++ b/src/test/compile-fail/use-after-move-self-based-on-type.rs @@ -6,16 +6,16 @@ impl Drop for S { fn finalize(&self) {} } -pub impl S { - fn foo(self) -> int { +impl S { + pub fn foo(self) -> int { self.bar(); - return self.x; //~ ERROR use of partially moved value + return self.x; //~ ERROR use of moved value: `self` } - fn bar(self) {} + pub fn bar(self) {} } fn main() { let x = S { x: 1 }; - io::println(x.foo().to_str()); + println(x.foo().to_str()); } diff --git a/src/test/compile-fail/use-after-move-self.rs b/src/test/compile-fail/use-after-move-self.rs index b2eaffdd06605..c38f4821b881e 100644 --- a/src/test/compile-fail/use-after-move-self.rs +++ b/src/test/compile-fail/use-after-move-self.rs @@ -2,16 +2,16 @@ struct S { x: ~int } -pub impl S { - fn foo(self) -> int { +impl S { + pub fn foo(self) -> int { self.bar(); - return *self.x; //~ ERROR use of partially moved value + return *self.x; //~ ERROR use of moved value: `self` } - fn bar(self) {} + pub fn bar(self) {} } fn main() { let x = S { x: ~1 }; - io::println(x.foo().to_str()); + println(x.foo().to_str()); } diff --git a/src/test/compile-fail/use-from-trait-xc.rs b/src/test/compile-fail/use-from-trait-xc.rs new file mode 100644 index 0000000000000..56805f58ad29a --- /dev/null +++ b/src/test/compile-fail/use-from-trait-xc.rs @@ -0,0 +1,12 @@ +// aux-build:use_from_trait_xc.rs + +extern mod use_from_trait_xc; + +use use_from_trait_xc::Trait::foo; //~ ERROR cannot import from a trait or type implementation +//~^ ERROR failed to resolve import +use use_from_trait_xc::Foo::new; //~ ERROR cannot import from a trait or type implementation +//~^ ERROR failed to resolve import + +fn main() { +} + diff --git a/src/test/compile-fail/use-from-trait.rs b/src/test/compile-fail/use-from-trait.rs new file mode 100644 index 0000000000000..10a30f0a266b3 --- /dev/null +++ b/src/test/compile-fail/use-from-trait.rs @@ -0,0 +1,17 @@ +use Trait::foo; //~ ERROR cannot import from a trait or type implementation +//~^ ERROR failed to resolve import +use Foo::new; //~ ERROR cannot import from a trait or type implementation +//~^ ERROR failed to resolve import + +pub trait Trait { + fn foo(); +} + +struct Foo; + +impl Foo { + fn new() {} +} + +fn main() {} + diff --git a/src/test/compile-fail/use-meta-dup.rs b/src/test/compile-fail/use-meta-dup.rs index 805a853c315de..dd57382afbbb7 100644 --- a/src/test/compile-fail/use-meta-dup.rs +++ b/src/test/compile-fail/use-meta-dup.rs @@ -10,6 +10,6 @@ // error-pattern:duplicate meta item `name` -extern mod std(name = "std", name = "nonstd"); +extern mod extra(name = "extra", name = "nonstd"); fn main() { } diff --git a/src/test/compile-fail/use-meta-mismatch.rs b/src/test/compile-fail/use-meta-mismatch.rs index b643e9421f589..118fce8a891b6 100644 --- a/src/test/compile-fail/use-meta-mismatch.rs +++ b/src/test/compile-fail/use-meta-mismatch.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:can't find crate for `std` +// error-pattern:can't find crate for `extra` -extern mod std(complex(meta(item))); +extern mod extra(complex(meta(item))); fn main() { } diff --git a/src/test/compile-fail/view-items-at-top.rs b/src/test/compile-fail/view-items-at-top.rs index 023be703cca77..fa03e0d5199fc 100644 --- a/src/test/compile-fail/view-items-at-top.rs +++ b/src/test/compile-fail/view-items-at-top.rs @@ -10,12 +10,12 @@ // xfail-test -extern mod std; +extern mod extra; fn f() { } -use std::net; //~ ERROR view items must be declared at the top +use extra::net; //~ ERROR view items must be declared at the top fn main() { } diff --git a/src/test/compile-fail/vtable-res-trait-param.rs b/src/test/compile-fail/vtable-res-trait-param.rs index dd0ae87f3118d..5d0991024c4f6 100644 --- a/src/test/compile-fail/vtable-res-trait-param.rs +++ b/src/test/compile-fail/vtable-res-trait-param.rs @@ -29,5 +29,5 @@ fn call_it(b: B) -> int { fn main() { let x = 3i; - assert!(call_it(x) == 22); + assert_eq!(call_it(x), 22); } diff --git a/src/test/pretty/alt-naked-expr-long.rs b/src/test/pretty/match-naked-expr-long.rs similarity index 100% rename from src/test/pretty/alt-naked-expr-long.rs rename to src/test/pretty/match-naked-expr-long.rs diff --git a/src/test/pretty/alt-naked-expr-medium.rs b/src/test/pretty/match-naked-expr-medium.rs similarity index 100% rename from src/test/pretty/alt-naked-expr-medium.rs rename to src/test/pretty/match-naked-expr-medium.rs diff --git a/src/test/pretty/alt-naked-expr.rs b/src/test/pretty/match-naked-expr.rs similarity index 100% rename from src/test/pretty/alt-naked-expr.rs rename to src/test/pretty/match-naked-expr.rs diff --git a/src/test/pretty/record-trailing-comma.rs b/src/test/pretty/record-trailing-comma.rs index 1ea0e10413271..67059e07c899d 100644 --- a/src/test/pretty/record-trailing-comma.rs +++ b/src/test/pretty/record-trailing-comma.rs @@ -18,5 +18,5 @@ struct Thing { fn main() { let sth = Thing{x: 0, y: 1,}; let sth2 = Thing{y: 9 , ..sth}; - assert!(sth.x + sth2.y == 9); + assert_eq!(sth.x + sth2.y, 9); } diff --git a/src/test/run-fail/bug-2470-bounds-check-overflow.rs b/src/test/run-fail/bug-2470-bounds-check-overflow.rs index 6a6402c6a5eea..bd7d86d729531 100644 --- a/src/test/run-fail/bug-2470-bounds-check-overflow.rs +++ b/src/test/run-fail/bug-2470-bounds-check-overflow.rs @@ -10,6 +10,9 @@ // error-pattern:index out of bounds +use std::sys; +use std::vec; + fn main() { // This should cause a bounds-check failure, but may not if we do our diff --git a/src/test/run-fail/expr-alt-fail-fn.rs b/src/test/run-fail/expr-match-fail-fn.rs similarity index 100% rename from src/test/run-fail/expr-alt-fail-fn.rs rename to src/test/run-fail/expr-match-fail-fn.rs diff --git a/src/test/run-fail/expr-alt-fail.rs b/src/test/run-fail/expr-match-fail.rs similarity index 100% rename from src/test/run-fail/expr-alt-fail.rs rename to src/test/run-fail/expr-match-fail.rs diff --git a/src/test/run-fail/extern-fail.rs b/src/test/run-fail/extern-fail.rs index 2deee10527cc9..2be41d3bed00f 100644 --- a/src/test/run-fail/extern-fail.rs +++ b/src/test/run-fail/extern-fail.rs @@ -12,9 +12,13 @@ // Testing that runtime failure doesn't cause callbacks to abort abnormally. // Instead the failure will be delivered after the callbacks return. -use core::old_iter; +use std::libc; +use std::old_iter; +use std::task; mod rustrt { + use std::libc; + pub extern { pub fn rust_dbg_call(cb: *u8, data: libc::uintptr_t) -> libc::uintptr_t; @@ -37,7 +41,7 @@ fn count(n: uint) -> uint { } fn main() { - for old_iter::repeat(10u) { + for 10u.times { do task::spawn { let result = count(5u); debug!("result = %?", result); diff --git a/src/test/run-fail/fail-main.rs b/src/test/run-fail/fail-main.rs index beb0d38ea473b..f007e03041c14 100644 --- a/src/test/run-fail/fail-main.rs +++ b/src/test/run-fail/fail-main.rs @@ -9,5 +9,5 @@ // except according to those terms. // error-pattern:moop -extern mod std; +extern mod extra; fn main() { fail!("moop"); } diff --git a/src/test/run-fail/fmt-fail.rs b/src/test/run-fail/fmt-fail.rs index 10d8903838143..d34ca029023f3 100644 --- a/src/test/run-fail/fmt-fail.rs +++ b/src/test/run-fail/fmt-fail.rs @@ -9,6 +9,6 @@ // except according to those terms. // error-pattern:meh -extern mod std; +extern mod extra; fn main() { let str_var: ~str = ~"meh"; fail!(fmt!("%s", str_var)); } diff --git a/src/test/run-fail/for-each-loop-fail.rs b/src/test/run-fail/for-each-loop-fail.rs index 3ae387952a2d7..97ca36cf4487c 100644 --- a/src/test/run-fail/for-each-loop-fail.rs +++ b/src/test/run-fail/for-each-loop-fail.rs @@ -9,5 +9,8 @@ // except according to those terms. // error-pattern:moop -extern mod std; +extern mod extra; + +use std::uint; + fn main() { for uint::range(0u, 10u) |_i| { fail!("moop"); } } diff --git a/src/test/run-fail/issue-2156.rs b/src/test/run-fail/issue-2156.rs index 9ca343e3866b8..0e0bd81d659ac 100644 --- a/src/test/run-fail/issue-2156.rs +++ b/src/test/run-fail/issue-2156.rs @@ -10,8 +10,10 @@ // error-pattern:explicit failure // Don't double free the string -extern mod std; -use core::io::ReaderUtil; +extern mod extra; + +use std::io::ReaderUtil; +use std::io; fn main() { do io::with_str_reader(~"") |rdr| { diff --git a/src/test/run-fail/issue-2444.rs b/src/test/run-fail/issue-2444.rs index 04a0f47fc06fd..0ab1528e4fb75 100644 --- a/src/test/run-fail/issue-2444.rs +++ b/src/test/run-fail/issue-2444.rs @@ -10,8 +10,8 @@ // error-pattern:explicit failure -extern mod std; -use std::arc; +extern mod extra; +use extra::arc; enum e { e(arc::ARC) } diff --git a/src/test/run-fail/issue-3029.rs b/src/test/run-fail/issue-3029.rs index 1743d9a6d407f..6f4a3f5ab1d2e 100644 --- a/src/test/run-fail/issue-3029.rs +++ b/src/test/run-fail/issue-3029.rs @@ -10,7 +10,8 @@ // error-pattern:so long fn main() { - let x = ~[], y = ~[3]; + let x = ~[]; + let y = ~[3]; fail!("so long"); x += y; ~"good" + ~"bye"; diff --git a/src/test/run-fail/linked-failure.rs b/src/test/run-fail/linked-failure.rs index 054d6f697ae34..41a9d7ddcea1f 100644 --- a/src/test/run-fail/linked-failure.rs +++ b/src/test/run-fail/linked-failure.rs @@ -11,7 +11,10 @@ // error-pattern:1 == 2 -extern mod std; +extern mod extra; + +use std::comm; +use std::task; fn child() { assert!((1 == 2)); } diff --git a/src/test/run-fail/linked-failure2.rs b/src/test/run-fail/linked-failure2.rs index 9f09c16ed6a57..0269e3959868d 100644 --- a/src/test/run-fail/linked-failure2.rs +++ b/src/test/run-fail/linked-failure2.rs @@ -12,6 +12,9 @@ // error-pattern:fail +use std::comm; +use std::task; + fn child() { fail!(); } fn main() { diff --git a/src/test/run-fail/linked-failure3.rs b/src/test/run-fail/linked-failure3.rs index 4b09cb75324c0..1203f74322feb 100644 --- a/src/test/run-fail/linked-failure3.rs +++ b/src/test/run-fail/linked-failure3.rs @@ -12,6 +12,9 @@ // error-pattern:fail +use std::comm; +use std::task; + fn grandchild() { fail!("grandchild dies"); } fn child() { diff --git a/src/test/run-fail/linked-failure4.rs b/src/test/run-fail/linked-failure4.rs index 3dc87e190a5d8..766b43f211f46 100644 --- a/src/test/run-fail/linked-failure4.rs +++ b/src/test/run-fail/linked-failure4.rs @@ -11,6 +11,9 @@ // error-pattern:1 == 2 +use std::comm; +use std::task; + fn child() { assert!((1 == 2)); } fn parent() { diff --git a/src/test/run-fail/alt-bot-fail.rs b/src/test/run-fail/match-bot-fail.rs similarity index 100% rename from src/test/run-fail/alt-bot-fail.rs rename to src/test/run-fail/match-bot-fail.rs diff --git a/src/test/run-fail/alt-disc-bot.rs b/src/test/run-fail/match-disc-bot.rs similarity index 100% rename from src/test/run-fail/alt-disc-bot.rs rename to src/test/run-fail/match-disc-bot.rs diff --git a/src/test/run-fail/alt-wildcards.rs b/src/test/run-fail/match-wildcards.rs similarity index 79% rename from src/test/run-fail/alt-wildcards.rs rename to src/test/run-fail/match-wildcards.rs index 306357b00013e..22613f45b3bc4 100644 --- a/src/test/run-fail/alt-wildcards.rs +++ b/src/test/run-fail/match-wildcards.rs @@ -10,9 +10,9 @@ // error-pattern:squirrelcupcake fn cmp() -> int { - match (option::Some('a'), option::None::) { - (option::Some(_), _) => { fail!("squirrelcupcake"); } - (_, option::Some(_)) => { fail!(); } + match (Some('a'), None::) { + (Some(_), _) => { fail!("squirrelcupcake"); } + (_, Some(_)) => { fail!(); } _ => { fail!("wat"); } } } diff --git a/src/test/run-fail/morestack2.rs b/src/test/run-fail/morestack2.rs index d59fbae2f9f14..d03433d587255 100644 --- a/src/test/run-fail/morestack2.rs +++ b/src/test/run-fail/morestack2.rs @@ -15,9 +15,14 @@ // See the hack in upcall_call_shim_on_c_stack where it messes // with the stack limit. -extern mod std; +extern mod extra; + +use std::libc; +use std::task; mod rustrt { + use std::libc; + pub extern { pub fn rust_get_argc() -> libc::c_int; } diff --git a/src/test/run-fail/morestack3.rs b/src/test/run-fail/morestack3.rs index 012e9d19b1218..d2e17d2856172 100644 --- a/src/test/run-fail/morestack3.rs +++ b/src/test/run-fail/morestack3.rs @@ -12,7 +12,9 @@ // Just testing unwinding -extern mod std; +extern mod extra; + +use std::task; fn getbig_and_fail(i: int) { let _r = and_then_get_big_again(5); diff --git a/src/test/run-fail/morestack4.rs b/src/test/run-fail/morestack4.rs index 6fc187491cf8c..c4f7de4955564 100644 --- a/src/test/run-fail/morestack4.rs +++ b/src/test/run-fail/morestack4.rs @@ -12,7 +12,9 @@ // Just testing unwinding -extern mod std; +extern mod extra; + +use std::task; fn getbig_and_fail(i: int) { let r = and_then_get_big_again(5); diff --git a/src/test/run-fail/result-get-fail.rs b/src/test/run-fail/result-get-fail.rs index 1e4e7685e270c..cb9cce3249f01 100644 --- a/src/test/run-fail/result-get-fail.rs +++ b/src/test/run-fail/result-get-fail.rs @@ -9,6 +9,9 @@ // except according to those terms. // error-pattern:get called on error result: ~"kitty" + +use std::result; + fn main() { error!(result::get(&result::Err::(~"kitty"))); } diff --git a/src/test/run-fail/rt-set-exit-status-fail.rs b/src/test/run-fail/rt-set-exit-status-fail.rs index f6e9602470f33..6b5c2b554a4db 100644 --- a/src/test/run-fail/rt-set-exit-status-fail.rs +++ b/src/test/run-fail/rt-set-exit-status-fail.rs @@ -10,6 +10,8 @@ // error-pattern:whatever +use std::os; + fn main() { error!(~"whatever"); // Setting the exit status only works when the scheduler terminates diff --git a/src/test/run-fail/rt-set-exit-status-fail2.rs b/src/test/run-fail/rt-set-exit-status-fail2.rs index bf33b10cc6108..3d0341d01f4b0 100644 --- a/src/test/run-fail/rt-set-exit-status-fail2.rs +++ b/src/test/run-fail/rt-set-exit-status-fail2.rs @@ -10,6 +10,9 @@ // error-pattern:whatever +use std::os; +use std::task; + struct r { x:int, } diff --git a/src/test/run-fail/rt-set-exit-status.rs b/src/test/run-fail/rt-set-exit-status.rs index 2cff4ff09dfb8..4f71cdc67e9c2 100644 --- a/src/test/run-fail/rt-set-exit-status.rs +++ b/src/test/run-fail/rt-set-exit-status.rs @@ -10,6 +10,8 @@ // error-pattern:whatever +use std::os; + fn main() { error!(~"whatever"); // 101 is the code the runtime uses on task failure and the value diff --git a/src/test/run-fail/run-unexported-tests.rs b/src/test/run-fail/run-unexported-tests.rs index b055bf4ed9563..e9d3c41faa6cc 100644 --- a/src/test/run-fail/run-unexported-tests.rs +++ b/src/test/run-fail/run-unexported-tests.rs @@ -11,7 +11,7 @@ // error-pattern:runned an unexported test // compile-flags:--test -extern mod std; +extern mod extra; mod m { pub fn exported() { } diff --git a/src/test/run-fail/small-negative-indexing.rs b/src/test/run-fail/small-negative-indexing.rs index 87df00fcce587..ee58f76fc99ee 100644 --- a/src/test/run-fail/small-negative-indexing.rs +++ b/src/test/run-fail/small-negative-indexing.rs @@ -9,6 +9,9 @@ // except according to those terms. // error-pattern:index out of bounds: the len is 1024 but the index is -1 + +use std::vec; + fn main() { let v = vec::from_fn(1024u, {|n| n}); // this should trip a bounds check diff --git a/src/test/run-fail/spawnfail.rs b/src/test/run-fail/spawnfail.rs index 8431f7bb74d98..de085a6f3addb 100644 --- a/src/test/run-fail/spawnfail.rs +++ b/src/test/run-fail/spawnfail.rs @@ -10,7 +10,9 @@ // xfail-win32 // error-pattern:explicit -extern mod std; +extern mod extra; + +use std::task; // We don't want to see any invalid reads fn main() { diff --git a/src/test/run-fail/str-overrun.rs b/src/test/run-fail/str-overrun.rs index 38b73ea56980e..5ec2c093eebac 100644 --- a/src/test/run-fail/str-overrun.rs +++ b/src/test/run-fail/str-overrun.rs @@ -15,5 +15,5 @@ fn main() { let s: ~str = ~"hello"; // Bounds-check failure. - assert!((s[5] == 0x0 as u8)); + assert_eq!(s[5], 0x0 as u8); } diff --git a/src/test/run-fail/task-comm-recv-block.rs b/src/test/run-fail/task-comm-recv-block.rs index ca411872b61c7..8302b96ca3ef7 100644 --- a/src/test/run-fail/task-comm-recv-block.rs +++ b/src/test/run-fail/task-comm-recv-block.rs @@ -10,6 +10,9 @@ // error-pattern:goodfail +use std::comm; +use std::task; + fn goodfail() { task::yield(); fail!("goodfail"); diff --git a/src/test/run-fail/task-spawn-barefn.rs b/src/test/run-fail/task-spawn-barefn.rs index 11c9de6e14f45..2456f968c3c10 100644 --- a/src/test/run-fail/task-spawn-barefn.rs +++ b/src/test/run-fail/task-spawn-barefn.rs @@ -10,6 +10,9 @@ // error-pattern:Ensure that the child task runs by failing +use std::str; +use std::task; + fn main() { // the purpose of this test is to make sure that task::spawn() // works when provided with a bare function: diff --git a/src/test/run-fail/unwind-box-res.rs b/src/test/run-fail/unwind-box-res.rs index d5d54ade4443a..a1e1ee433bb6d 100644 --- a/src/test/run-fail/unwind-box-res.rs +++ b/src/test/run-fail/unwind-box-res.rs @@ -10,6 +10,8 @@ // error-pattern:fail +use std::cast; + fn failfn() { fail!(); } diff --git a/src/test/run-fail/unwind-alt.rs b/src/test/run-fail/unwind-match.rs similarity index 96% rename from src/test/run-fail/unwind-alt.rs rename to src/test/run-fail/unwind-match.rs index d7e079ad90716..a9761017c73f5 100644 --- a/src/test/run-fail/unwind-alt.rs +++ b/src/test/run-fail/unwind-match.rs @@ -16,7 +16,7 @@ fn test_box() { fn test_str() { let res = match false { true => { ~"happy" }, _ => fail!("non-exhaustive match failure") }; - assert!(res == ~"happy"); + assert_eq!(res, ~"happy"); } fn main() { test_box(); diff --git a/src/test/run-fail/unwind-misc-1.rs b/src/test/run-fail/unwind-misc-1.rs index 7e3318f865228..e30054575d6a6 100644 --- a/src/test/run-fail/unwind-misc-1.rs +++ b/src/test/run-fail/unwind-misc-1.rs @@ -14,7 +14,7 @@ fn main() { let count = @mut 0u; - let mut map = core::hashmap::HashMap::new(); + let mut map = std::hashmap::HashMap::new(); let mut arr = ~[]; for uint::range(0u, 10u) |i| { arr += ~[@~"key stuff"]; diff --git a/src/test/run-fail/vec-overrun.rs b/src/test/run-fail/vec-overrun.rs index ab9dcf32781be..411895a2ef037 100644 --- a/src/test/run-fail/vec-overrun.rs +++ b/src/test/run-fail/vec-overrun.rs @@ -14,8 +14,8 @@ fn main() { let v: ~[int] = ~[10]; let x: int = 0; - assert!((v[x] == 10)); + assert_eq!(v[x], 10); // Bounds-check failure. - assert!((v[x + 2] == 20)); + assert_eq!(v[x + 2], 20); } diff --git a/src/test/run-fail/vec-underrun.rs b/src/test/run-fail/vec-underrun.rs index 6f403fd772193..99ce79b3b6c0c 100644 --- a/src/test/run-fail/vec-underrun.rs +++ b/src/test/run-fail/vec-underrun.rs @@ -14,8 +14,8 @@ fn main() { let v: ~[int] = ~[10, 20]; let x: int = 0; - assert!((v[x] == 10)); + assert_eq!(v[x], 10); // Bounds-check failure. - assert!((v[x - 1] == 20)); + assert_eq!(v[x - 1], 20); } diff --git a/src/test/run-fail/zip-different-lengths.rs b/src/test/run-fail/zip-different-lengths.rs index ae76c4ba6034b..f31fea526391c 100644 --- a/src/test/run-fail/zip-different-lengths.rs +++ b/src/test/run-fail/zip-different-lengths.rs @@ -11,8 +11,8 @@ // In this case, the code should compile but // the assert should fail at runtime // error-pattern:assertion failed -extern mod std; -use core::vec::{same_length, zip}; +extern mod extra; +use std::vec::{same_length, zip}; fn enum_chars(start: u8, end: u8) -> ~[char] { assert!(start < end); @@ -31,7 +31,10 @@ fn enum_uints(start: uint, end: uint) -> ~[uint] { } fn main() { - let a = 'a' as u8, j = 'j' as u8, k = 1, l = 9; + let a = 'a' as u8; + let j = 'j' as u8; + let k = 1; + let l = 9; let chars = enum_chars(a, j); let ints = enum_uints(k, l); diff --git a/src/test/run-pass-fulldeps/qquote.rs b/src/test/run-pass-fulldeps/qquote.rs index 84edb990a7598..9a3ba32390c72 100644 --- a/src/test/run-pass-fulldeps/qquote.rs +++ b/src/test/run-pass-fulldeps/qquote.rs @@ -10,10 +10,10 @@ // xfail-pretty -extern mod std; +extern mod extra; extern mod syntax; -use core::io::*; +use std::io::*; use syntax::diagnostic; use syntax::ast; @@ -82,6 +82,6 @@ fn check_pp(cx: fake_ext_ctxt, stdout().write_line(s); if expect != ~"" { error!("expect: '%s', got: '%s'", expect, s); - assert!(s == expect); + assert_eq!(s, expect); } } diff --git a/src/test/run-pass-fulldeps/quote-tokens.rs b/src/test/run-pass-fulldeps/quote-tokens.rs index 3ec54955229d3..0cd416afc8316 100644 --- a/src/test/run-pass-fulldeps/quote-tokens.rs +++ b/src/test/run-pass-fulldeps/quote-tokens.rs @@ -12,9 +12,9 @@ extern mod syntax; -use syntax::ext::base::ext_ctxt; +use syntax::ext::base::ExtCtxt; -fn syntax_extension(ext_cx: @ext_ctxt) { +fn syntax_extension(ext_cx: @ExtCtxt) { let e_toks : ~[syntax::ast::token_tree] = quote_tokens!(1 + 2); let p_toks : ~[syntax::ast::token_tree] = quote_tokens!((x, 1 .. 4, *)); diff --git a/src/test/run-pass/alignment-gep-tup-like-1.rs b/src/test/run-pass/alignment-gep-tup-like-1.rs index e3a544af309b2..bf96d6cfab529 100644 --- a/src/test/run-pass/alignment-gep-tup-like-1.rs +++ b/src/test/run-pass/alignment-gep-tup-like-1.rs @@ -20,6 +20,6 @@ fn f(a: A, b: u16) -> @fn() -> (A, u16) { pub fn main() { let (a, b) = f(22_u64, 44u16)(); debug!("a=%? b=%?", a, b); - assert!(a == 22u64); - assert!(b == 44u16); + assert_eq!(a, 22u64); + assert_eq!(b, 44u16); } diff --git a/src/test/run-pass/alignment-gep-tup-like-2.rs b/src/test/run-pass/alignment-gep-tup-like-2.rs index 847e6fce8ee61..6bf4e96bc053d 100644 --- a/src/test/run-pass/alignment-gep-tup-like-2.rs +++ b/src/test/run-pass/alignment-gep-tup-like-2.rs @@ -35,6 +35,6 @@ pub fn main() { make_cycle(z); let (a, b) = z(); debug!("a=%u b=%u", *a as uint, b as uint); - assert!(*a == x); - assert!(b == y); + assert_eq!(*a, x); + assert_eq!(b, y); } diff --git a/src/test/run-pass/anon-extern-mod-cross-crate-2.rs b/src/test/run-pass/anon-extern-mod-cross-crate-2.rs index ed57b32b3d9e5..4eeb85469de3c 100644 --- a/src/test/run-pass/anon-extern-mod-cross-crate-2.rs +++ b/src/test/run-pass/anon-extern-mod-cross-crate-2.rs @@ -15,5 +15,7 @@ extern mod anonexternmod; use anonexternmod::*; pub fn main() { - rust_get_argc(); + unsafe { + rust_get_argc(); + } } diff --git a/src/test/run-pass/anon-extern-mod.rs b/src/test/run-pass/anon-extern-mod.rs index 6e73022fad2e1..8e03a6393b433 100644 --- a/src/test/run-pass/anon-extern-mod.rs +++ b/src/test/run-pass/anon-extern-mod.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::libc; + #[abi = "cdecl"] #[link_name = "rustrt"] extern { diff --git a/src/test/run-pass/anon-trait-static-method.rs b/src/test/run-pass/anon-trait-static-method.rs index 91bbbf5c0a0df..843e9436229ec 100644 --- a/src/test/run-pass/anon-trait-static-method.rs +++ b/src/test/run-pass/anon-trait-static-method.rs @@ -12,13 +12,13 @@ struct Foo { x: int } -pub impl Foo { - fn new() -> Foo { +impl Foo { + pub fn new() -> Foo { Foo { x: 3 } } } pub fn main() { let x = Foo::new(); - io::println(x.x.to_str()); + println(x.x.to_str()); } diff --git a/src/test/run-pass/anon_trait_static_method_exe.rs b/src/test/run-pass/anon_trait_static_method_exe.rs index 1baeca00083fd..5780a4e97aed6 100644 --- a/src/test/run-pass/anon_trait_static_method_exe.rs +++ b/src/test/run-pass/anon_trait_static_method_exe.rs @@ -16,5 +16,5 @@ use anon_trait_static_method_lib::Foo; pub fn main() { let x = Foo::new(); - io::println(x.x.to_str()); + println(x.x.to_str()); } diff --git a/src/test/run-pass/argument-passing.rs b/src/test/run-pass/argument-passing.rs index 8c84187ff6f06..90a1762519573 100644 --- a/src/test/run-pass/argument-passing.rs +++ b/src/test/run-pass/argument-passing.rs @@ -24,10 +24,12 @@ fn f1(a: &mut X, b: &mut int, c: int) -> int { fn f2(a: int, f: &fn(int)) -> int { f(1); return a; } pub fn main() { - let mut a = X {x: 1}, b = 2, c = 3; - assert!((f1(&mut a, &mut b, c) == 6)); - assert!((a.x == 0)); - assert!((b == 10)); - assert!((f2(a.x, |x| a.x = 50) == 0)); - assert!((a.x == 50)); + let mut a = X {x: 1}; + let mut b = 2; + let mut c = 3; + assert_eq!(f1(&mut a, &mut b, c), 6); + assert_eq!(a.x, 0); + assert_eq!(b, 10); + assert_eq!(f2(a.x, |x| a.x = 50), 0); + assert_eq!(a.x, 50); } diff --git a/src/test/run-pass/arith-0.rs b/src/test/run-pass/arith-0.rs index a0512ffff2a4f..308a5c2721c3d 100644 --- a/src/test/run-pass/arith-0.rs +++ b/src/test/run-pass/arith-0.rs @@ -13,5 +13,5 @@ pub fn main() { let a: int = 10; debug!(a); - assert!((a * (a - 1) == 90)); + assert_eq!(a * (a - 1), 90); } diff --git a/src/test/run-pass/arith-1.rs b/src/test/run-pass/arith-1.rs index c0db96f99c7f4..a6321439db943 100644 --- a/src/test/run-pass/arith-1.rs +++ b/src/test/run-pass/arith-1.rs @@ -12,22 +12,22 @@ pub fn main() { let i32_a: int = 10; - assert!((i32_a == 10)); - assert!((i32_a - 10 == 0)); - assert!((i32_a / 10 == 1)); - assert!((i32_a - 20 == -10)); - assert!((i32_a << 10 == 10240)); - assert!((i32_a << 16 == 655360)); - assert!((i32_a * 16 == 160)); - assert!((i32_a * i32_a * i32_a == 1000)); - assert!((i32_a * i32_a * i32_a * i32_a == 10000)); - assert!((i32_a * i32_a / i32_a * i32_a == 100)); - assert!((i32_a * (i32_a - 1) << 2 + i32_a == 368640)); + assert_eq!(i32_a, 10); + assert_eq!(i32_a - 10, 0); + assert_eq!(i32_a / 10, 1); + assert_eq!(i32_a - 20, -10); + assert_eq!(i32_a << 10, 10240); + assert_eq!(i32_a << 16, 655360); + assert_eq!(i32_a * 16, 160); + assert_eq!(i32_a * i32_a * i32_a, 1000); + assert_eq!(i32_a * i32_a * i32_a * i32_a, 10000); + assert_eq!(i32_a * i32_a / i32_a * i32_a, 100); + assert_eq!(i32_a * (i32_a - 1) << 2 + i32_a, 368640); let i32_b: int = 0x10101010; - assert!((i32_b + 1 - 1 == i32_b)); - assert!((i32_b << 1 == i32_b << 1)); - assert!((i32_b >> 1 == i32_b >> 1)); - assert!((i32_b & i32_b << 1 == 0)); + assert_eq!(i32_b + 1 - 1, i32_b); + assert_eq!(i32_b << 1, i32_b << 1); + assert_eq!(i32_b >> 1, i32_b >> 1); + assert_eq!(i32_b & i32_b << 1, 0); debug!(i32_b | i32_b << 1); - assert!((i32_b | i32_b << 1 == 0x30303030)); + assert_eq!(i32_b | i32_b << 1, 0x30303030); } diff --git a/src/test/run-pass/arith-unsigned.rs b/src/test/run-pass/arith-unsigned.rs index a921d9f7ddc7b..0eb4e7ad92e78 100644 --- a/src/test/run-pass/arith-unsigned.rs +++ b/src/test/run-pass/arith-unsigned.rs @@ -17,20 +17,20 @@ pub fn main() { assert!((0u8 <= 255u8)); assert!((255u8 > 0u8)); assert!((255u8 >= 0u8)); - assert!((250u8 / 10u8 == 25u8)); - assert!((255u8 % 10u8 == 5u8)); + assert_eq!(250u8 / 10u8, 25u8); + assert_eq!(255u8 % 10u8, 5u8); assert!((0u16 < 60000u16)); assert!((0u16 <= 60000u16)); assert!((60000u16 > 0u16)); assert!((60000u16 >= 0u16)); - assert!((60000u16 / 10u16 == 6000u16)); - assert!((60005u16 % 10u16 == 5u16)); + assert_eq!(60000u16 / 10u16, 6000u16); + assert_eq!(60005u16 % 10u16, 5u16); assert!((0u32 < 4000000000u32)); assert!((0u32 <= 4000000000u32)); assert!((4000000000u32 > 0u32)); assert!((4000000000u32 >= 0u32)); - assert!((4000000000u32 / 10u32 == 400000000u32)); - assert!((4000000005u32 % 10u32 == 5u32)); + assert_eq!(4000000000u32 / 10u32, 400000000u32); + assert_eq!(4000000005u32 % 10u32, 5u32); // 64-bit numbers have some flakiness yet. Not tested } diff --git a/src/test/run-pass/assign-assign.rs b/src/test/run-pass/assign-assign.rs index dc0850b24f1f6..5fe2aa6cc7c0e 100644 --- a/src/test/run-pass/assign-assign.rs +++ b/src/test/run-pass/assign-assign.rs @@ -12,21 +12,21 @@ fn test_assign() { let mut x: int; let mut y: () = x = 10; - assert!((x == 10)); + assert_eq!(x, 10); let mut z = x = 11; - assert!((x == 11)); + assert_eq!(x, 11); z = x = 12; - assert!((x == 12)); + assert_eq!(x, 12); } fn test_assign_op() { let mut x: int = 0; let mut y: () = x += 10; - assert!((x == 10)); + assert_eq!(x, 10); let mut z = x += 11; - assert!((x == 21)); + assert_eq!(x, 21); z = x += 12; - assert!((x == 33)); + assert_eq!(x, 33); } pub fn main() { test_assign(); test_assign_op(); } diff --git a/src/test/run-pass/assignability-trait.rs b/src/test/run-pass/assignability-trait.rs index b21213bb221b6..5d2341ae42d3f 100644 --- a/src/test/run-pass/assignability-trait.rs +++ b/src/test/run-pass/assignability-trait.rs @@ -12,6 +12,8 @@ // making method calls, but only if there aren't any matches without // it. +use std::vec; + trait iterable { fn iterate(&self, blk: &fn(x: &A) -> bool) -> bool; } @@ -39,15 +41,15 @@ pub fn main() { // Call a method for x.iterate() |y| { assert!(x[*y] == *y); } // Call a parameterized function - assert!(length(x.clone()) == x.len()); + assert_eq!(length(x.clone()), x.len()); // Call a parameterized function, with type arguments that require // a borrow - assert!(length::(x) == x.len()); + assert_eq!(length::(x), x.len()); // Now try it with a type that *needs* to be borrowed let z = [0,1,2,3]; // Call a method for z.iterate() |y| { assert!(z[*y] == *y); } // Call a parameterized function - assert!(length::(z) == z.len()); + assert_eq!(length::(z), z.len()); } diff --git a/src/test/run-pass/attr-before-view-item.rs b/src/test/run-pass/attr-before-view-item.rs index aa5c3bb22a380..316f8fa0f61f4 100644 --- a/src/test/run-pass/attr-before-view-item.rs +++ b/src/test/run-pass/attr-before-view-item.rs @@ -11,7 +11,7 @@ // error-pattern:expected item #[foo = "bar"] -extern mod std; +extern mod extra; pub fn main() { } diff --git a/src/test/run-pass/attr-before-view-item2.rs b/src/test/run-pass/attr-before-view-item2.rs index e0d9a05b8aa2b..0721544aa0dc8 100644 --- a/src/test/run-pass/attr-before-view-item2.rs +++ b/src/test/run-pass/attr-before-view-item2.rs @@ -12,7 +12,7 @@ mod m { #[foo = "bar"] - extern mod std; + extern mod extra; } pub fn main() { diff --git a/src/test/run-pass/auto-encode.rs b/src/test/run-pass/auto-encode.rs index cfac8e8cd061f..899c97b825ff8 100644 --- a/src/test/run-pass/auto-encode.rs +++ b/src/test/run-pass/auto-encode.rs @@ -12,18 +12,20 @@ #[forbid(deprecated_pattern)]; -extern mod std; +extern mod extra; // These tests used to be separate files, but I wanted to refactor all // the common code. -use EBReader = std::ebml::reader; -use EBWriter = std::ebml::writer; -use core::cmp::Eq; -use core::io::Writer; -use std::ebml; -use std::serialize::{Decodable, Encodable}; -use std::time; +use std::hashmap::{HashMap, HashSet}; + +use EBReader = extra::ebml::reader; +use EBWriter = extra::ebml::writer; +use std::cmp::Eq; +use std::cmp; +use std::io; +use extra::serialize::{Decodable, Encodable}; +use extra::time; fn test_ebml uint { **self } +impl Foo { + pub fn len(&self) -> uint { **self } } pub fn main() { let m = Foo(3); - assert!(m.len() == 3); + assert_eq!(m.len(), 3); } diff --git a/src/test/run-pass/auto-ref-sliceable.rs b/src/test/run-pass/auto-ref-sliceable.rs index f74d78f99d0b2..8e2b3b56736e2 100644 --- a/src/test/run-pass/auto-ref-sliceable.rs +++ b/src/test/run-pass/auto-ref-sliceable.rs @@ -22,5 +22,5 @@ pub fn main() { let mut v = ~[1]; v.push_val(2); v.push_val(3); - assert!(v == ~[1, 2, 3]); + assert_eq!(v, ~[1, 2, 3]); } diff --git a/src/test/run-pass/auto-ref.rs b/src/test/run-pass/auto-ref.rs index ee250b972190c..7171b0ee86c4b 100644 --- a/src/test/run-pass/auto-ref.rs +++ b/src/test/run-pass/auto-ref.rs @@ -18,7 +18,7 @@ trait Stuff { impl Stuff for Foo { fn printme(&self) { - io::println(fmt!("%d", self.x)); + println(fmt!("%d", self.x)); } } diff --git a/src/test/run-pass/autobind.rs b/src/test/run-pass/autobind.rs index afaafd45b7b6f..0788c74d07850 100644 --- a/src/test/run-pass/autobind.rs +++ b/src/test/run-pass/autobind.rs @@ -13,7 +13,7 @@ fn f(x: ~[T]) -> T { return x[0]; } fn g(act: &fn(~[int]) -> int) -> int { return act(~[1, 2, 3]); } pub fn main() { - assert!((g(f) == 1)); + assert_eq!(g(f), 1); let f1: &fn(~[~str]) -> ~str = f; - assert!((f1(~[~"x", ~"y", ~"z"]) == ~"x")); + assert_eq!(f1(~[~"x", ~"y", ~"z"]), ~"x"); } diff --git a/src/test/run-pass/autoderef-and-borrow-method-receiver.rs b/src/test/run-pass/autoderef-and-borrow-method-receiver.rs index 2bc6df4703042..b00d8980c69fe 100644 --- a/src/test/run-pass/autoderef-and-borrow-method-receiver.rs +++ b/src/test/run-pass/autoderef-and-borrow-method-receiver.rs @@ -12,8 +12,8 @@ struct Foo { x: int, } -pub impl Foo { - fn f(&const self) {} +impl Foo { + pub fn f(&const self) {} } fn g(x: &mut Foo) { diff --git a/src/test/run-pass/autoderef-method-newtype.rs b/src/test/run-pass/autoderef-method-newtype.rs index 2d6f03c1daf20..e3a19b23e91bf 100644 --- a/src/test/run-pass/autoderef-method-newtype.rs +++ b/src/test/run-pass/autoderef-method-newtype.rs @@ -20,5 +20,5 @@ struct foo(uint); pub fn main() { let x = foo(3u); - assert!(x.double() == 6u); + assert_eq!(x.double(), 6u); } diff --git a/src/test/run-pass/autoderef-method-on-trait.rs b/src/test/run-pass/autoderef-method-on-trait.rs index 32f09369d9817..9bc71517c1fb8 100644 --- a/src/test/run-pass/autoderef-method-on-trait.rs +++ b/src/test/run-pass/autoderef-method-on-trait.rs @@ -18,5 +18,5 @@ impl double for uint { pub fn main() { let x = @(@3u as @double); - assert!(x.double() == 6u); + assert_eq!(x.double(), 6u); } diff --git a/src/test/run-pass/autoderef-method-priority.rs b/src/test/run-pass/autoderef-method-priority.rs index eaef1ae3477a7..9cfdac0a330b0 100644 --- a/src/test/run-pass/autoderef-method-priority.rs +++ b/src/test/run-pass/autoderef-method-priority.rs @@ -25,5 +25,5 @@ impl double for @uint { pub fn main() { let x = @3u; - assert!(x.double() == 6u); + assert_eq!(x.double(), 6u); } diff --git a/src/test/run-pass/autoderef-method-twice-but-not-thrice.rs b/src/test/run-pass/autoderef-method-twice-but-not-thrice.rs index c04efd7e18f54..299760289c2b3 100644 --- a/src/test/run-pass/autoderef-method-twice-but-not-thrice.rs +++ b/src/test/run-pass/autoderef-method-twice-but-not-thrice.rs @@ -18,5 +18,5 @@ impl double for @uint { pub fn main() { let x = @@@@@3u; - assert!(x.double() == 6u); + assert_eq!(x.double(), 6u); } diff --git a/src/test/run-pass/autoderef-method-twice.rs b/src/test/run-pass/autoderef-method-twice.rs index 0a2a93d40d186..f93f0605269a4 100644 --- a/src/test/run-pass/autoderef-method-twice.rs +++ b/src/test/run-pass/autoderef-method-twice.rs @@ -18,5 +18,5 @@ impl double for uint { pub fn main() { let x = @@3u; - assert!(x.double() == 6u); + assert_eq!(x.double(), 6u); } diff --git a/src/test/run-pass/autoderef-method.rs b/src/test/run-pass/autoderef-method.rs index b704011ad9882..eb173e3d5f8ec 100644 --- a/src/test/run-pass/autoderef-method.rs +++ b/src/test/run-pass/autoderef-method.rs @@ -18,5 +18,5 @@ impl double for uint { pub fn main() { let x = @3u; - assert!(x.double() == 6u); + assert_eq!(x.double(), 6u); } diff --git a/src/test/run-pass/autoref-intermediate-types-issue-3585.rs b/src/test/run-pass/autoref-intermediate-types-issue-3585.rs index 5325242b99c33..cae3bff8043ea 100644 --- a/src/test/run-pass/autoref-intermediate-types-issue-3585.rs +++ b/src/test/run-pass/autoref-intermediate-types-issue-3585.rs @@ -26,5 +26,5 @@ impl Foo for uint { pub fn main() { let x = @3u; - assert!(x.foo() == ~"@3"); + assert_eq!(x.foo(), ~"@3"); } diff --git a/src/test/run-pass/bare-static-string.rs b/src/test/run-pass/bare-static-string.rs index 6208a9c3cc3e4..9b2855d269d73 100644 --- a/src/test/run-pass/bare-static-string.rs +++ b/src/test/run-pass/bare-static-string.rs @@ -10,5 +10,5 @@ pub fn main() { let x: &'static str = "foo"; - io::println(x); + println(x); } diff --git a/src/test/run-pass/big-literals.rs b/src/test/run-pass/big-literals.rs index 41aa204279689..96615b740b72b 100644 --- a/src/test/run-pass/big-literals.rs +++ b/src/test/run-pass/big-literals.rs @@ -11,11 +11,11 @@ // except according to those terms. pub fn main() { - assert!(0xffffffffu32 == (-1 as u32)); - assert!(4294967295u32 == (-1 as u32)); - assert!(0xffffffffffffffffu64 == (-1 as u64)); - assert!(18446744073709551615u64 == (-1 as u64)); + assert_eq!(0xffffffffu32, (-1 as u32)); + assert_eq!(4294967295u32, (-1 as u32)); + assert_eq!(0xffffffffffffffffu64, (-1 as u64)); + assert_eq!(18446744073709551615u64, (-1 as u64)); - assert!(-2147483648i32 - 1i32 == 2147483647i32); - assert!(-9223372036854775808i64 - 1i64 == 9223372036854775807i64); + assert_eq!(-2147483648i32 - 1i32, 2147483647i32); + assert_eq!(-9223372036854775808i64 - 1i64, 9223372036854775807i64); } diff --git a/src/test/run-pass/binary-minus-without-space.rs b/src/test/run-pass/binary-minus-without-space.rs index 93f57c6722f21..78edf3e112e98 100644 --- a/src/test/run-pass/binary-minus-without-space.rs +++ b/src/test/run-pass/binary-minus-without-space.rs @@ -12,5 +12,5 @@ pub fn main() { match -1 { -1 => {}, _ => fail!("wat") } - assert!(1-1 == 0); + assert_eq!(1-1, 0); } diff --git a/src/test/run-pass/bind-by-move.rs b/src/test/run-pass/bind-by-move.rs index 8752102c3a513..5cde389ff7536 100644 --- a/src/test/run-pass/bind-by-move.rs +++ b/src/test/run-pass/bind-by-move.rs @@ -9,8 +9,8 @@ // except according to those terms. // xfail-fast -extern mod std; -use std::arc; +extern mod extra; +use extra::arc; fn dispose(_x: arc::ARC) { unsafe { } } pub fn main() { diff --git a/src/test/run-pass/binops.rs b/src/test/run-pass/binops.rs index e755a34f0589e..1c73bf6cc3637 100644 --- a/src/test/run-pass/binops.rs +++ b/src/test/run-pass/binops.rs @@ -10,8 +10,10 @@ // Binop corner cases +use std::libc; + fn test_nil() { - assert!((() == ())); + assert_eq!((), ()); assert!((!(() != ()))); assert!((!(() < ()))); assert!((() <= ())); @@ -31,44 +33,44 @@ fn test_bool() { assert!((!(false >= true))); // Bools support bitwise binops - assert!((false & false == false)); - assert!((true & false == false)); - assert!((true & true == true)); - assert!((false | false == false)); - assert!((true | false == true)); - assert!((true | true == true)); - assert!((false ^ false == false)); - assert!((true ^ false == true)); - assert!((true ^ true == false)); + assert_eq!(false & false, false); + assert_eq!(true & false, false); + assert_eq!(true & true, true); + assert_eq!(false | false, false); + assert_eq!(true | false, true); + assert_eq!(true | true, true); + assert_eq!(false ^ false, false); + assert_eq!(true ^ false, true); + assert_eq!(true ^ true, false); } fn test_char() { let ch10 = 10 as char; let ch4 = 4 as char; let ch2 = 2 as char; - assert!((ch10 + ch4 == 14 as char)); - assert!((ch10 - ch4 == 6 as char)); - assert!((ch10 * ch4 == 40 as char)); - assert!((ch10 / ch4 == ch2)); - assert!((ch10 % ch4 == ch2)); - assert!((ch10 >> ch2 == ch2)); - assert!((ch10 << ch4 == 160 as char)); - assert!((ch10 | ch4 == 14 as char)); - assert!((ch10 & ch2 == ch2)); - assert!((ch10 ^ ch2 == 8 as char)); + assert_eq!(ch10 + ch4, 14 as char); + assert_eq!(ch10 - ch4, 6 as char); + assert_eq!(ch10 * ch4, 40 as char); + assert_eq!(ch10 / ch4, ch2); + assert_eq!(ch10 % ch4, ch2); + assert_eq!(ch10 >> ch2, ch2); + assert_eq!(ch10 << ch4, 160 as char); + assert_eq!(ch10 | ch4, 14 as char); + assert_eq!(ch10 & ch2, ch2); + assert_eq!(ch10 ^ ch2, 8 as char); } fn test_box() { - assert!((@10 == @10)); + assert_eq!(@10, @10); } fn test_ptr() { unsafe { - let p1: *u8 = ::core::cast::transmute(0); - let p2: *u8 = ::core::cast::transmute(0); - let p3: *u8 = ::core::cast::transmute(1); + let p1: *u8 = ::std::cast::transmute(0); + let p2: *u8 = ::std::cast::transmute(0); + let p3: *u8 = ::std::cast::transmute(1); - assert!(p1 == p2); + assert_eq!(p1, p2); assert!(p1 != p3); assert!(p1 < p3); assert!(p1 <= p3); @@ -80,6 +82,8 @@ fn test_ptr() { } mod test { + use std::libc; + #[abi = "cdecl"] #[nolink] pub extern { @@ -107,13 +111,13 @@ fn test_class() { unsafe { error!("q = %x, r = %x", - (::core::cast::transmute::<*p, uint>(&q)), - (::core::cast::transmute::<*p, uint>(&r))); + (::std::cast::transmute::<*p, uint>(&q)), + (::std::cast::transmute::<*p, uint>(&r))); } - assert!((q == r)); + assert_eq!(q, r); r.y = 17; assert!((r.y != q.y)); - assert!((r.y == 17)); + assert_eq!(r.y, 17); assert!((q != r)); } diff --git a/src/test/run-pass/bitv-perf-test.rs b/src/test/run-pass/bitv-perf-test.rs index bf2285480b477..c6edbfbe463d0 100644 --- a/src/test/run-pass/bitv-perf-test.rs +++ b/src/test/run-pass/bitv-perf-test.rs @@ -10,8 +10,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; -use std::bitv::*; +extern mod extra; +use extra::bitv::*; fn bitv_test() -> bool { let mut v1 = ~Bitv::new(31, false); @@ -21,5 +21,5 @@ fn bitv_test() -> bool { } pub fn main() { - do old_iter::repeat(10000) || {bitv_test()}; + do 10000.times || {bitv_test()}; } diff --git a/src/test/run-pass/bitwise.rs b/src/test/run-pass/bitwise.rs index ce06f09d32132..d3d1a1d12b269 100644 --- a/src/test/run-pass/bitwise.rs +++ b/src/test/run-pass/bitwise.rs @@ -13,12 +13,12 @@ #[cfg(target_arch = "x86")] #[cfg(target_arch = "arm")] fn target() { - assert!((-1000 as uint >> 3u == 536870787u)); + assert_eq!(-1000 as uint >> 3u, 536870787u); } #[cfg(target_arch = "x86_64")] fn target() { - assert!((-1000 as uint >> 3u == 2305843009213693827u)); + assert_eq!(-1000 as uint >> 3u, 2305843009213693827u); } fn general() { @@ -29,14 +29,14 @@ fn general() { a = a ^ b; debug!(a); debug!(b); - assert!((b == 1)); - assert!((a == 2)); - assert!((!0xf0 & 0xff == 0xf)); - assert!((0xf0 | 0xf == 0xff)); - assert!((0xf << 4 == 0xf0)); - assert!((0xf0 >> 4 == 0xf)); - assert!((-16 >> 2 == -4)); - assert!((0b1010_1010 | 0b0101_0101 == 0xff)); + assert_eq!(b, 1); + assert_eq!(a, 2); + assert_eq!(!0xf0 & 0xff, 0xf); + assert_eq!(0xf0 | 0xf, 0xff); + assert_eq!(0xf << 4, 0xf0); + assert_eq!(0xf0 >> 4, 0xf); + assert_eq!(-16 >> 2, -4); + assert_eq!(0b1010_1010 | 0b0101_0101, 0xff); } pub fn main() { diff --git a/src/test/run-pass/block-arg-call-as.rs b/src/test/run-pass/block-arg-call-as.rs index 22d495e2c1ba2..d68b0be632eb3 100644 --- a/src/test/run-pass/block-arg-call-as.rs +++ b/src/test/run-pass/block-arg-call-as.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; +extern mod extra; fn asSendfn( f : ~fn()->uint ) -> uint { return f(); @@ -24,9 +24,9 @@ fn asBlock( f : &fn()->uint ) -> uint { pub fn main() { let x = asSendfn(|| 22u); - assert!((x == 22u)); + assert_eq!(x, 22u); let x = asLambda(|| 22u); - assert!((x == 22u)); + assert_eq!(x, 22u); let x = asBlock(|| 22u); - assert!((x == 22u)); + assert_eq!(x, 22u); } diff --git a/src/test/run-pass/block-arg-can-be-followed-by-binop.rs b/src/test/run-pass/block-arg-can-be-followed-by-binop.rs index 74756d27fe763..73b436e7476f0 100644 --- a/src/test/run-pass/block-arg-can-be-followed-by-binop.rs +++ b/src/test/run-pass/block-arg-can-be-followed-by-binop.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::vec; + pub fn main() { let v = ~[-1f, 0f, 1f, 2f, 3f]; // Trailing expressions don't require parentheses: let y = do vec::foldl(0f, v) |x, y| { x + *y } + 10f; - assert!(y == 15f); + assert_eq!(y, 15f); } diff --git a/src/test/run-pass/block-arg-can-be-followed-by-block-arg.rs b/src/test/run-pass/block-arg-can-be-followed-by-block-arg.rs index 4cadb883d9962..7894bf938487f 100644 --- a/src/test/run-pass/block-arg-can-be-followed-by-block-arg.rs +++ b/src/test/run-pass/block-arg-can-be-followed-by-block-arg.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::vec; + pub fn main() { fn f(i: &fn() -> uint) -> uint { i() } let v = ~[-1f, 0f, 1f, 2f, 3f]; let z = do do vec::foldl(f, v) |x, _y| { x } { 22u }; - assert!(z == 22u); + assert_eq!(z, 22u); } diff --git a/src/test/run-pass/block-arg-can-be-followed-by-call.rs b/src/test/run-pass/block-arg-can-be-followed-by-call.rs index ac584324cece8..5fb6de1987895 100644 --- a/src/test/run-pass/block-arg-can-be-followed-by-call.rs +++ b/src/test/run-pass/block-arg-can-be-followed-by-call.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::vec; + pub fn main() { fn f(i: uint) -> uint { i } let v = ~[-1f, 0f, 1f, 2f, 3f]; let z = do vec::foldl(f, v) |x, _y| { x } (22u); - assert!(z == 22u); + assert_eq!(z, 22u); } diff --git a/src/test/run-pass/block-arg-in-parentheses.rs b/src/test/run-pass/block-arg-in-parentheses.rs index ad53bd2275451..ec211a3a14421 100644 --- a/src/test/run-pass/block-arg-in-parentheses.rs +++ b/src/test/run-pass/block-arg-in-parentheses.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::vec; + fn w_semi(v: ~[int]) -> int { // the semicolon causes compiler not to // complain about the ignored return value: @@ -28,8 +30,8 @@ fn w_ret(v: ~[int]) -> int { } pub fn main() { - assert!(w_semi(~[0, 1, 2, 3]) == -10); - assert!(w_paren1(~[0, 1, 2, 3]) == -4); - assert!(w_paren2(~[0, 1, 2, 3]) == -4); - assert!(w_ret(~[0, 1, 2, 3]) == -4); + assert_eq!(w_semi(~[0, 1, 2, 3]), -10); + assert_eq!(w_paren1(~[0, 1, 2, 3]), -4); + assert_eq!(w_paren2(~[0, 1, 2, 3]), -4); + assert_eq!(w_ret(~[0, 1, 2, 3]), -4); } diff --git a/src/test/run-pass/block-arg-used-as-any.rs b/src/test/run-pass/block-arg-used-as-any.rs index d8aeba355d147..7ee9d9e5b5489 100644 --- a/src/test/run-pass/block-arg-used-as-any.rs +++ b/src/test/run-pass/block-arg-used-as-any.rs @@ -14,5 +14,5 @@ fn call_any(f: &fn() -> uint) -> uint { pub fn main() { let x_r = do call_any { 22u }; - assert!(x_r == 22u); + assert_eq!(x_r, 22u); } diff --git a/src/test/run-pass/block-arg-used-as-lambda.rs b/src/test/run-pass/block-arg-used-as-lambda.rs index 2a7bfe4e32876..34fa7e36d973f 100644 --- a/src/test/run-pass/block-arg-used-as-lambda.rs +++ b/src/test/run-pass/block-arg-used-as-lambda.rs @@ -19,6 +19,6 @@ pub fn main() { let x_r = x(22u); let y_r = y(x_r); - assert!(x_r == 44u); - assert!(y_r == 88u); + assert_eq!(x_r, 44u); + assert_eq!(y_r, 88u); } diff --git a/src/test/run-pass/block-arg.rs b/src/test/run-pass/block-arg.rs index 04032900c5160..906a3629f3a0a 100644 --- a/src/test/run-pass/block-arg.rs +++ b/src/test/run-pass/block-arg.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::vec; + // Check usage and precedence of block arguments in expressions: pub fn main() { let v = ~[-1f, 0f, 1f, 2f, 3f]; @@ -51,8 +53,8 @@ pub fn main() { let w = do vec::foldl(0f, v) |x, y| { x + *y } + 10f; let y = do vec::foldl(0f, v) |x, y| { x + *y } + 10f; let z = 10f + do vec::foldl(0f, v) |x, y| { x + *y }; - assert!(w == y); - assert!(y == z); + assert_eq!(w, y); + assert_eq!(y, z); // In the tail of a block let w = diff --git a/src/test/run-pass/block-expr-precedence.rs b/src/test/run-pass/block-expr-precedence.rs index d8f6f167f208a..ace372dd2d3d9 100644 --- a/src/test/run-pass/block-expr-precedence.rs +++ b/src/test/run-pass/block-expr-precedence.rs @@ -58,8 +58,8 @@ pub fn main() { let num = 12; - assert!(if (true) { 12 } else { 12 } - num == 0); - assert!(12 - if (true) { 12 } else { 12 } == 0); + assert_eq!(if (true) { 12 } else { 12 } - num, 0); + assert_eq!(12 - if (true) { 12 } else { 12 }, 0); if (true) { 12; } {-num}; if (true) { 12; }; {-num}; if (true) { 12; };;; -num; diff --git a/src/test/run-pass/block-fn-coerce.rs b/src/test/run-pass/block-fn-coerce.rs index 5a4b2f8bfd663..19e1fd4099b74 100644 --- a/src/test/run-pass/block-fn-coerce.rs +++ b/src/test/run-pass/block-fn-coerce.rs @@ -11,7 +11,7 @@ fn force(f: &fn() -> int) -> int { return f(); } pub fn main() { fn f() -> int { return 7; } - assert!((force(f) == 7)); + assert_eq!(force(f), 7); let g = {||force(f)}; - assert!((g() == 7)); + assert_eq!(g(), 7); } diff --git a/src/test/run-pass/block-iter-1.rs b/src/test/run-pass/block-iter-1.rs index 0a3458ed8141a..34b77b4a844a8 100644 --- a/src/test/run-pass/block-iter-1.rs +++ b/src/test/run-pass/block-iter-1.rs @@ -21,5 +21,5 @@ pub fn main() { } }); error!(odds); - assert!((odds == 4)); + assert_eq!(odds, 4); } diff --git a/src/test/run-pass/block-iter-2.rs b/src/test/run-pass/block-iter-2.rs index e5c527db5566b..dc4ff5a054fbb 100644 --- a/src/test/run-pass/block-iter-2.rs +++ b/src/test/run-pass/block-iter-2.rs @@ -21,5 +21,5 @@ pub fn main() { }); }); error!(sum); - assert!((sum == 225)); + assert_eq!(sum, 225); } diff --git a/src/test/run-pass/block-vec-map_zip.rs b/src/test/run-pass/block-vec-map_zip.rs index 5d637ba8cef06..739dbab4d3af4 100644 --- a/src/test/run-pass/block-vec-map_zip.rs +++ b/src/test/run-pass/block-vec-map_zip.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; +use std::vec; pub fn main() { let v = @@ -16,5 +16,5 @@ pub fn main() { ~[true, false, false, true, true], |i, b| if *b { -(*i) } else { *i } ); error!(v.clone()); - assert!((v == ~[-1, 2, 3, -4, -5])); + assert_eq!(v, ~[-1, 2, 3, -4, -5]); } diff --git a/src/test/run-pass/borrowck-borrow-from-at-vec.rs b/src/test/run-pass/borrowck-borrow-from-at-vec.rs index e5f2a18df63cf..fb91e9a787e36 100644 --- a/src/test/run-pass/borrowck-borrow-from-at-vec.rs +++ b/src/test/run-pass/borrowck-borrow-from-at-vec.rs @@ -16,5 +16,5 @@ fn sum_slice(x: &[int]) -> int { pub fn main() { let x = @[1, 2, 3]; - assert!(sum_slice(x) == 6); + assert_eq!(sum_slice(x), 6); } diff --git a/src/test/run-pass/borrowck-borrow-from-expr-block.rs b/src/test/run-pass/borrowck-borrow-from-expr-block.rs index d65a043bf47e9..d6d440782e774 100644 --- a/src/test/run-pass/borrowck-borrow-from-expr-block.rs +++ b/src/test/run-pass/borrowck-borrow-from-expr-block.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::borrow; +use std::ptr; + fn borrow(x: &int, f: &fn(x: &int)) { f(x) } @@ -15,8 +18,8 @@ fn borrow(x: &int, f: &fn(x: &int)) { fn test1(x: @~int) { do borrow(&*(*x).clone()) |p| { let x_a = ptr::to_unsafe_ptr(&**x); - assert!((x_a as uint) != ptr::to_uint(p)); - assert!(unsafe{*x_a} == *p); + assert!((x_a as uint) != borrow::to_uint(p)); + assert_eq!(unsafe{*x_a}, *p); } } diff --git a/src/test/run-pass/borrowck-fixed-length-vecs.rs b/src/test/run-pass/borrowck-fixed-length-vecs.rs index e9d4a24806819..ee561fdb0be52 100644 --- a/src/test/run-pass/borrowck-fixed-length-vecs.rs +++ b/src/test/run-pass/borrowck-fixed-length-vecs.rs @@ -11,5 +11,5 @@ pub fn main() { let x = [22]; let y = &x[0]; - assert!(*y == 22); + assert_eq!(*y, 22); } diff --git a/src/test/run-pass/borrowck-mut-uniq.rs b/src/test/run-pass/borrowck-mut-uniq.rs index 023eaae0a7648..1b43e98cc170f 100644 --- a/src/test/run-pass/borrowck-mut-uniq.rs +++ b/src/test/run-pass/borrowck-mut-uniq.rs @@ -8,7 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::util; +use std::uint; +use std::util; struct Ints {sum: ~int, values: ~[int]} diff --git a/src/test/run-pass/borrowck-mut-vec-as-imm-slice.rs b/src/test/run-pass/borrowck-mut-vec-as-imm-slice.rs index 8f66faab01451..d63ebf7d24d41 100644 --- a/src/test/run-pass/borrowck-mut-vec-as-imm-slice.rs +++ b/src/test/run-pass/borrowck-mut-vec-as-imm-slice.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::vec; + fn want_slice(v: &[int]) -> int { let mut sum = 0; for vec::each(v) |i| { sum += *i; } @@ -19,5 +21,5 @@ fn has_mut_vec(v: ~[int]) -> int { } pub fn main() { - assert!(has_mut_vec(~[1, 2, 3]) == 6); + assert_eq!(has_mut_vec(~[1, 2, 3]), 6); } diff --git a/src/test/run-pass/borrowck-nested-calls.rs b/src/test/run-pass/borrowck-nested-calls.rs index 4494f5f2fa337..50e9b6d81b517 100644 --- a/src/test/run-pass/borrowck-nested-calls.rs +++ b/src/test/run-pass/borrowck-nested-calls.rs @@ -14,10 +14,10 @@ struct Foo {a: uint, b: uint} -pub impl Foo { - fn inc_a(&mut self, v: uint) { self.a += v; } +impl Foo { + pub fn inc_a(&mut self, v: uint) { self.a += v; } - fn next_b(&mut self) -> uint { + pub fn next_b(&mut self) -> uint { let b = self.b; self.b += 1; b diff --git a/src/test/run-pass/borrowck-preserve-box-in-discr.rs b/src/test/run-pass/borrowck-preserve-box-in-discr.rs index db88646631357..8434651dbbf9b 100644 --- a/src/test/run-pass/borrowck-preserve-box-in-discr.rs +++ b/src/test/run-pass/borrowck-preserve-box-in-discr.rs @@ -10,20 +10,22 @@ // exec-env:RUST_POISON_ON_FREE=1 +use std::ptr; + struct F { f: ~int } pub fn main() { let mut x = @F {f: ~3}; match x { @F {f: ref b_x} => { - assert!(**b_x == 3); - assert!(ptr::to_unsafe_ptr(&(*x.f)) == ptr::to_unsafe_ptr(&(**b_x))); + assert_eq!(**b_x, 3); + assert_eq!(ptr::to_unsafe_ptr(&(*x.f)), ptr::to_unsafe_ptr(&(**b_x))); x = @F {f: ~4}; debug!("ptr::to_unsafe_ptr(*b_x) = %x", ptr::to_unsafe_ptr(&(**b_x)) as uint); - assert!(**b_x == 3); + assert_eq!(**b_x, 3); assert!(ptr::to_unsafe_ptr(&(*x.f)) != ptr::to_unsafe_ptr(&(**b_x))); } } diff --git a/src/test/run-pass/borrowck-preserve-box-in-field.rs b/src/test/run-pass/borrowck-preserve-box-in-field.rs index 3c95054d10c93..93ceeef37b375 100644 --- a/src/test/run-pass/borrowck-preserve-box-in-field.rs +++ b/src/test/run-pass/borrowck-preserve-box-in-field.rs @@ -10,11 +10,13 @@ // exec-env:RUST_POISON_ON_FREE=1 +use std::ptr; + fn borrow(x: &int, f: &fn(x: &int)) { let before = *x; f(x); let after = *x; - assert!(before == after); + assert_eq!(before, after); } struct F { f: ~int } @@ -22,13 +24,13 @@ struct F { f: ~int } pub fn main() { let mut x = @F {f: ~3}; do borrow(x.f) |b_x| { - assert!(*b_x == 3); - assert!(ptr::to_unsafe_ptr(&(*x.f)) == ptr::to_unsafe_ptr(&(*b_x))); + assert_eq!(*b_x, 3); + assert_eq!(ptr::to_unsafe_ptr(&(*x.f)), ptr::to_unsafe_ptr(&(*b_x))); x = @F {f: ~4}; debug!("ptr::to_unsafe_ptr(*b_x) = %x", ptr::to_unsafe_ptr(&(*b_x)) as uint); - assert!(*b_x == 3); + assert_eq!(*b_x, 3); assert!(ptr::to_unsafe_ptr(&(*x.f)) != ptr::to_unsafe_ptr(&(*b_x))); } } diff --git a/src/test/run-pass/borrowck-preserve-box-in-pat.rs b/src/test/run-pass/borrowck-preserve-box-in-pat.rs index ad0c5b69ba849..1323ac0df5eab 100644 --- a/src/test/run-pass/borrowck-preserve-box-in-pat.rs +++ b/src/test/run-pass/borrowck-preserve-box-in-pat.rs @@ -10,20 +10,22 @@ // exec-env:RUST_POISON_ON_FREE=1 +use std::ptr; + struct F { f: ~int } pub fn main() { let mut x = @mut @F {f: ~3}; match x { @@F{f: ref b_x} => { - assert!(**b_x == 3); - assert!(ptr::to_unsafe_ptr(&(x.f)) == ptr::to_unsafe_ptr(b_x)); + assert_eq!(**b_x, 3); + assert_eq!(ptr::to_unsafe_ptr(&(x.f)), ptr::to_unsafe_ptr(b_x)); *x = @F {f: ~4}; debug!("ptr::to_unsafe_ptr(*b_x) = %x", ptr::to_unsafe_ptr(&(**b_x)) as uint); - assert!(**b_x == 3); + assert_eq!(**b_x, 3); assert!(ptr::to_unsafe_ptr(&(*x.f)) != ptr::to_unsafe_ptr(&(**b_x))); } } diff --git a/src/test/run-pass/borrowck-preserve-box-in-uniq.rs b/src/test/run-pass/borrowck-preserve-box-in-uniq.rs index cce08ab235613..dcecf77335a14 100644 --- a/src/test/run-pass/borrowck-preserve-box-in-uniq.rs +++ b/src/test/run-pass/borrowck-preserve-box-in-uniq.rs @@ -10,11 +10,13 @@ // exec-env:RUST_POISON_ON_FREE=1 +use std::ptr; + fn borrow(x: &int, f: &fn(x: &int)) { let before = *x; f(x); let after = *x; - assert!(before == after); + assert_eq!(before, after); } struct F { f: ~int } @@ -22,13 +24,13 @@ struct F { f: ~int } pub fn main() { let mut x = ~@F{f: ~3}; do borrow(x.f) |b_x| { - assert!(*b_x == 3); - assert!(ptr::to_unsafe_ptr(&(*x.f)) == ptr::to_unsafe_ptr(&(*b_x))); + assert_eq!(*b_x, 3); + assert_eq!(ptr::to_unsafe_ptr(&(*x.f)), ptr::to_unsafe_ptr(&(*b_x))); *x = @F{f: ~4}; debug!("ptr::to_unsafe_ptr(*b_x) = %x", ptr::to_unsafe_ptr(&(*b_x)) as uint); - assert!(*b_x == 3); + assert_eq!(*b_x, 3); assert!(ptr::to_unsafe_ptr(&(*x.f)) != ptr::to_unsafe_ptr(&(*b_x))); } } diff --git a/src/test/run-pass/borrowck-preserve-box.rs b/src/test/run-pass/borrowck-preserve-box.rs index 104b0ae6bc551..8bd8049ea1dac 100644 --- a/src/test/run-pass/borrowck-preserve-box.rs +++ b/src/test/run-pass/borrowck-preserve-box.rs @@ -10,23 +10,25 @@ // exec-env:RUST_POISON_ON_FREE=1 +use std::ptr; + fn borrow(x: &int, f: &fn(x: &int)) { let before = *x; f(x); let after = *x; - assert!(before == after); + assert_eq!(before, after); } pub fn main() { let mut x = @3; do borrow(x) |b_x| { - assert!(*b_x == 3); - assert!(ptr::to_unsafe_ptr(&(*x)) == ptr::to_unsafe_ptr(&(*b_x))); + assert_eq!(*b_x, 3); + assert_eq!(ptr::to_unsafe_ptr(&(*x)), ptr::to_unsafe_ptr(&(*b_x))); x = @22; debug!("ptr::to_unsafe_ptr(*b_x) = %x", ptr::to_unsafe_ptr(&(*b_x)) as uint); - assert!(*b_x == 3); + assert_eq!(*b_x, 3); assert!(ptr::to_unsafe_ptr(&(*x)) != ptr::to_unsafe_ptr(&(*b_x))); } } diff --git a/src/test/run-pass/borrowck-preserve-cond-box.rs b/src/test/run-pass/borrowck-preserve-cond-box.rs index 18c185cfef1c3..4483c7fa4e9c5 100644 --- a/src/test/run-pass/borrowck-preserve-cond-box.rs +++ b/src/test/run-pass/borrowck-preserve-cond-box.rs @@ -17,7 +17,8 @@ fn testfn(cond: bool) { // borrow x and y let mut r_x = &*x; let mut r_y = &*y; - let mut r = r_x, exp = 3; + let mut r = r_x; + let mut exp = 3; if cond { r = r_y; @@ -25,13 +26,13 @@ fn testfn(cond: bool) { } debug!("*r = %d, exp = %d", *r, exp); - assert!(*r == exp); + assert_eq!(*r, exp); x = @5; y = @6; debug!("*r = %d, exp = %d", *r, exp); - assert!(*r == exp); + assert_eq!(*r, exp); } pub fn main() { diff --git a/src/test/run-pass/borrowck-preserve-expl-deref.rs b/src/test/run-pass/borrowck-preserve-expl-deref.rs index 4c5b9f9bf1f82..6e683c79875d7 100644 --- a/src/test/run-pass/borrowck-preserve-expl-deref.rs +++ b/src/test/run-pass/borrowck-preserve-expl-deref.rs @@ -10,11 +10,13 @@ // exec-env:RUST_POISON_ON_FREE=1 +use std::ptr; + fn borrow(x: &int, f: &fn(x: &int)) { let before = *x; f(x); let after = *x; - assert!(before == after); + assert_eq!(before, after); } struct F { f: ~int } @@ -22,13 +24,13 @@ struct F { f: ~int } pub fn main() { let mut x = @F {f: ~3}; do borrow((*x).f) |b_x| { - assert!(*b_x == 3); - assert!(ptr::to_unsafe_ptr(&(*x.f)) == ptr::to_unsafe_ptr(&(*b_x))); + assert_eq!(*b_x, 3); + assert_eq!(ptr::to_unsafe_ptr(&(*x.f)), ptr::to_unsafe_ptr(&(*b_x))); x = @F {f: ~4}; debug!("ptr::to_unsafe_ptr(*b_x) = %x", ptr::to_unsafe_ptr(&(*b_x)) as uint); - assert!(*b_x == 3); + assert_eq!(*b_x, 3); assert!(ptr::to_unsafe_ptr(&(*x.f)) != ptr::to_unsafe_ptr(&(*b_x))); } } diff --git a/src/test/compile-fail/borrowck-unary-move-2.rs b/src/test/run-pass/borrowck-unary-move-2.rs similarity index 94% rename from src/test/compile-fail/borrowck-unary-move-2.rs rename to src/test/run-pass/borrowck-unary-move-2.rs index 898830bbe55ba..c74fd4a68e719 100644 --- a/src/test/compile-fail/borrowck-unary-move-2.rs +++ b/src/test/run-pass/borrowck-unary-move-2.rs @@ -28,5 +28,5 @@ struct wrapper(noncopyable); fn main() { let x1 = wrapper(noncopyable()); - let _x2 = *x1; //~ ERROR cannot move out + let _x2 = *x1; } diff --git a/src/test/run-pass/borrowck-univariant-enum.rs b/src/test/run-pass/borrowck-univariant-enum.rs index 3ec061c2dea61..bb8710aad489b 100644 --- a/src/test/run-pass/borrowck-univariant-enum.rs +++ b/src/test/run-pass/borrowck-univariant-enum.rs @@ -25,5 +25,5 @@ pub fn main() { *x * b } }; - assert!(z == 18); + assert_eq!(z, 18); } diff --git a/src/test/run-pass/borrowck-wg-borrow-mut-to-imm-3.rs b/src/test/run-pass/borrowck-wg-borrow-mut-to-imm-3.rs index 0699df703c6a3..284db7af66be3 100644 --- a/src/test/run-pass/borrowck-wg-borrow-mut-to-imm-3.rs +++ b/src/test/run-pass/borrowck-wg-borrow-mut-to-imm-3.rs @@ -2,10 +2,10 @@ struct Wizard { spells: ~[&'static str] } -pub impl Wizard { - fn cast(&mut self) { +impl Wizard { + pub fn cast(&mut self) { for self.spells.each |&spell| { - io::println(spell); + println(spell); } } } diff --git a/src/test/run-pass/borrowck-wg-borrow-mut-to-imm.rs b/src/test/run-pass/borrowck-wg-borrow-mut-to-imm.rs index dea4ec4959b00..3b18a8649eeea 100644 --- a/src/test/run-pass/borrowck-wg-borrow-mut-to-imm.rs +++ b/src/test/run-pass/borrowck-wg-borrow-mut-to-imm.rs @@ -1,5 +1,5 @@ fn g(x: &Option) { - io::println(x.get().to_str()); + println(x.get().to_str()); } fn f(x: &mut Option) { diff --git a/src/test/run-pass/borrowck-wg-simple.rs b/src/test/run-pass/borrowck-wg-simple.rs index f28b0e4c4ec13..c07962e10aa93 100644 --- a/src/test/run-pass/borrowck-wg-simple.rs +++ b/src/test/run-pass/borrowck-wg-simple.rs @@ -1,5 +1,5 @@ fn f(x: &int) { - io::println(x.to_str()); + println(x.to_str()); } pub fn main() { diff --git a/src/test/run-pass/borrowed-ptr-pattern-infallible.rs b/src/test/run-pass/borrowed-ptr-pattern-infallible.rs index d49ea86402a5f..4e9ba6d3158e0 100644 --- a/src/test/run-pass/borrowed-ptr-pattern-infallible.rs +++ b/src/test/run-pass/borrowed-ptr-pattern-infallible.rs @@ -10,7 +10,7 @@ pub fn main() { let (&x, &y, &z) = (&3, &'a', &@"No pets!"); - assert!(x == 3); - assert!(y == 'a'); - assert!(z == @"No pets!"); + assert_eq!(x, 3); + assert_eq!(y, 'a'); + assert_eq!(z, @"No pets!"); } diff --git a/src/test/run-pass/borrowed-ptr-pattern-option.rs b/src/test/run-pass/borrowed-ptr-pattern-option.rs index dc620d0733d75..4775e5fe0a80e 100644 --- a/src/test/run-pass/borrowed-ptr-pattern-option.rs +++ b/src/test/run-pass/borrowed-ptr-pattern-option.rs @@ -19,5 +19,5 @@ fn select<'r>(x: &'r Option, y: &'r Option) -> &'r Option { pub fn main() { let x = None; let y = Some(3); - assert!(select(&x, &y).get() == 3); + assert_eq!(select(&x, &y).get(), 3); } diff --git a/src/test/run-pass/borrowed-ptr-pattern.rs b/src/test/run-pass/borrowed-ptr-pattern.rs index 44485b5c8df82..e0af2e80508c3 100644 --- a/src/test/run-pass/borrowed-ptr-pattern.rs +++ b/src/test/run-pass/borrowed-ptr-pattern.rs @@ -15,7 +15,7 @@ fn foo(x: &T) -> T{ } pub fn main() { - assert!(foo(&3) == 3); - assert!(foo(&'a') == 'a'); - assert!(foo(&@"Dogs rule, cats drool") == @"Dogs rule, cats drool"); + assert_eq!(foo(&3), 3); + assert_eq!(foo(&'a'), 'a'); + assert_eq!(foo(&@"Dogs rule, cats drool"), @"Dogs rule, cats drool"); } diff --git a/src/test/run-pass/box-unbox.rs b/src/test/run-pass/box-unbox.rs index 96fc7b84bcd9c..e7dc436567982 100644 --- a/src/test/run-pass/box-unbox.rs +++ b/src/test/run-pass/box-unbox.rs @@ -18,5 +18,5 @@ pub fn main() { let foo: int = 17; let bfoo: Box = Box {c: @foo}; debug!("see what's in our box"); - assert!((unbox::(bfoo) == foo)); + assert_eq!(unbox::(bfoo), foo); } diff --git a/src/test/run-pass/boxed-trait-with-vstore.rs b/src/test/run-pass/boxed-trait-with-vstore.rs index 1313a17f81db0..1d901d42742c1 100644 --- a/src/test/run-pass/boxed-trait-with-vstore.rs +++ b/src/test/run-pass/boxed-trait-with-vstore.rs @@ -14,7 +14,7 @@ trait Foo { impl Foo for int { fn foo(@self) { - io::println("Hello world!"); + println("Hello world!"); } } diff --git a/src/test/run-pass/break.rs b/src/test/run-pass/break.rs index a182dcf2ca0b2..2edb270762cc3 100644 --- a/src/test/run-pass/break.rs +++ b/src/test/run-pass/break.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::vec; + pub fn main() { let mut i = 0; while i < 20 { i += 1; if i == 10 { break; } } - assert!((i == 10)); + assert_eq!(i, 10); loop { i += 1; if i == 20 { break; } } - assert!((i == 20)); + assert_eq!(i, 20); for vec::each(~[1, 2, 3, 4, 5, 6]) |x| { if *x == 3 { break; } assert!((*x <= 3)); } diff --git a/src/test/run-pass/c-stack-as-value.rs b/src/test/run-pass/c-stack-as-value.rs index 661aa7a90b1e8..0a482c745bacf 100644 --- a/src/test/run-pass/c-stack-as-value.rs +++ b/src/test/run-pass/c-stack-as-value.rs @@ -8,7 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::libc; + mod rustrt { + use std::libc; + #[abi = "cdecl"] pub extern { pub fn get_task_id() -> libc::intptr_t; diff --git a/src/test/run-pass/c-stack-returning-int64.rs b/src/test/run-pass/c-stack-returning-int64.rs index a87dbaab5c99b..4553257df31a5 100644 --- a/src/test/run-pass/c-stack-returning-int64.rs +++ b/src/test/run-pass/c-stack-returning-int64.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; +use std::str; mod libc { #[abi = "cdecl"] @@ -29,7 +29,7 @@ fn atoll(s: ~str) -> i64 { pub fn main() { unsafe { - assert!(atol(~"1024") * 10 == atol(~"10240")); + assert_eq!(atol(~"1024") * 10, atol(~"10240")); assert!((atoll(~"11111111111111111") * 10i64) == atoll(~"111111111111111110")); } diff --git a/src/test/run-pass/call-closure-from-overloaded-op.rs b/src/test/run-pass/call-closure-from-overloaded-op.rs index 8832620c4bfc7..cc8d8e9619556 100644 --- a/src/test/run-pass/call-closure-from-overloaded-op.rs +++ b/src/test/run-pass/call-closure-from-overloaded-op.rs @@ -13,5 +13,5 @@ fn foo() -> int { 22 } pub fn main() { let mut x: ~[@fn() -> int] = ~[]; x.push(foo); - assert!((x[0])() == 22); + assert_eq!((x[0])(), 22); } diff --git a/src/test/run-pass/cap-clause-move.rs b/src/test/run-pass/cap-clause-move.rs index 5d20990a5a93b..aadd6a724940b 100644 --- a/src/test/run-pass/cap-clause-move.rs +++ b/src/test/run-pass/cap-clause-move.rs @@ -8,24 +8,26 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::ptr; + pub fn main() { let x = ~1; let y = ptr::to_unsafe_ptr(&(*x)) as uint; let lam_move: @fn() -> uint = || ptr::to_unsafe_ptr(&(*x)) as uint; - assert!(lam_move() == y); + assert_eq!(lam_move(), y); let x = ~2; let y = ptr::to_unsafe_ptr(&(*x)) as uint; let lam_move: @fn() -> uint = || ptr::to_unsafe_ptr(&(*x)) as uint; - assert!(lam_move() == y); + assert_eq!(lam_move(), y); let x = ~3; let y = ptr::to_unsafe_ptr(&(*x)) as uint; let snd_move: ~fn() -> uint = || ptr::to_unsafe_ptr(&(*x)) as uint; - assert!(snd_move() == y); + assert_eq!(snd_move(), y); let x = ~4; let y = ptr::to_unsafe_ptr(&(*x)) as uint; let lam_move: ~fn() -> uint = || ptr::to_unsafe_ptr(&(*x)) as uint; - assert!(lam_move() == y); + assert_eq!(lam_move(), y); } diff --git a/src/test/run-pass/capture_nil.rs b/src/test/run-pass/capture_nil.rs index 817891c114640..6182ec79a3ba9 100644 --- a/src/test/run-pass/capture_nil.rs +++ b/src/test/run-pass/capture_nil.rs @@ -24,7 +24,8 @@ // course preferable, as the value itself is // irrelevant). -use core::comm::*; +use std::comm::*; +use std::task; fn foo(x: ()) -> Port<()> { let (p, c) = stream::<()>(); diff --git a/src/test/run-pass/cast-region-to-uint.rs b/src/test/run-pass/cast-region-to-uint.rs index 81fa3d6538c44..6a3424535b90c 100644 --- a/src/test/run-pass/cast-region-to-uint.rs +++ b/src/test/run-pass/cast-region-to-uint.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::borrow; + pub fn main() { let x = 3; - debug!("&x=%x", ptr::to_uint(&x)); + debug!("&x=%x", borrow::to_uint(&x)); } diff --git a/src/test/run-pass/cast.rs b/src/test/run-pass/cast.rs index 1df1f3b4c8b4f..10407420a4332 100644 --- a/src/test/run-pass/cast.rs +++ b/src/test/run-pass/cast.rs @@ -14,13 +14,13 @@ // -*- rust -*- pub fn main() { let i: int = 'Q' as int; - assert!((i == 0x51)); + assert_eq!(i, 0x51); let u: u32 = i as u32; - assert!((u == 0x51 as u32)); - assert!((u == 'Q' as u32)); - assert!((i as u8 == 'Q' as u8)); - assert!((i as u8 as i8 == 'Q' as u8 as i8)); - assert!((0x51 as char == 'Q')); - assert!((true == 1 as bool)); - assert!((0 as u32 == false as u32)); + assert_eq!(u, 0x51 as u32); + assert_eq!(u, 'Q' as u32); + assert_eq!(i as u8, 'Q' as u8); + assert_eq!(i as u8 as i8, 'Q' as u8 as i8); + assert_eq!(0x51 as char, 'Q'); + assert_eq!(true, 1 as bool); + assert_eq!(0 as u32, false as u32); } diff --git a/src/test/run-pass/cci_borrow.rs b/src/test/run-pass/cci_borrow.rs index e6ec46acd23e3..460d6136cafe0 100644 --- a/src/test/run-pass/cci_borrow.rs +++ b/src/test/run-pass/cci_borrow.rs @@ -18,5 +18,5 @@ pub fn main() { let p = @22u; let r = foo(p); debug!("r=%u", r); - assert!(r == 22u); + assert_eq!(r, 22u); } diff --git a/src/test/run-pass/cci_impl_exe.rs b/src/test/run-pass/cci_impl_exe.rs index db25b36aa6169..43d9db391d9eb 100644 --- a/src/test/run-pass/cci_impl_exe.rs +++ b/src/test/run-pass/cci_impl_exe.rs @@ -19,7 +19,7 @@ pub fn main() { //debug!("%?", bt0); do 3u.to(10u) |i| { - io::print(fmt!("%u\n", i)); + print(fmt!("%u\n", i)); //let bt1 = sys::frame_address(); //debug!("%?", bt1); diff --git a/src/test/run-pass/cci_iter_exe.rs b/src/test/run-pass/cci_iter_exe.rs index cb713adcb28fc..f9a2d78692998 100644 --- a/src/test/run-pass/cci_iter_exe.rs +++ b/src/test/run-pass/cci_iter_exe.rs @@ -17,7 +17,7 @@ pub fn main() { //let bt0 = sys::rusti::frame_address(1u32); //debug!("%?", bt0); do cci_iter_lib::iter(~[1, 2, 3]) |i| { - io::print(fmt!("%d", *i)); + print(fmt!("%d", *i)); //assert!(bt0 == sys::rusti::frame_address(2u32)); } } diff --git a/src/test/run-pass/cci_nested_exe.rs b/src/test/run-pass/cci_nested_exe.rs index 847d8a4d1f90e..231cd37db5d35 100644 --- a/src/test/run-pass/cci_nested_exe.rs +++ b/src/test/run-pass/cci_nested_exe.rs @@ -18,12 +18,12 @@ pub fn main() { let lst = new_int_alist(); alist_add(&lst, 22, ~"hi"); alist_add(&lst, 44, ~"ho"); - assert!(alist_get(&lst, 22) == ~"hi"); - assert!(alist_get(&lst, 44) == ~"ho"); + assert_eq!(alist_get(&lst, 22), ~"hi"); + assert_eq!(alist_get(&lst, 44), ~"ho"); let lst = new_int_alist_2(); alist_add(&lst, 22, ~"hi"); alist_add(&lst, 44, ~"ho"); - assert!(alist_get(&lst, 22) == ~"hi"); - assert!(alist_get(&lst, 44) == ~"ho"); + assert_eq!(alist_get(&lst, 22), ~"hi"); + assert_eq!(alist_get(&lst, 44), ~"ho"); } diff --git a/src/test/run-pass/cci_no_inline_exe.rs b/src/test/run-pass/cci_no_inline_exe.rs index a1c2666b2e517..92d0e23589bc0 100644 --- a/src/test/run-pass/cci_no_inline_exe.rs +++ b/src/test/run-pass/cci_no_inline_exe.rs @@ -23,7 +23,7 @@ pub fn main() { //let bt0 = sys::frame_address(); //debug!("%?", bt0); do iter(~[1u, 2u, 3u]) |i| { - io::print(fmt!("%u\n", i)); + print(fmt!("%u\n", i)); //let bt1 = sys::frame_address(); //debug!("%?", bt1); diff --git a/src/test/run-pass/cfgs-on-items.rs b/src/test/run-pass/cfgs-on-items.rs index ed025623ac311..237fa3f7ea9c9 100644 --- a/src/test/run-pass/cfgs-on-items.rs +++ b/src/test/run-pass/cfgs-on-items.rs @@ -26,6 +26,6 @@ fn foo2() -> int { 3 } fn main() { - assert!(1 == foo1()); - assert!(3 == foo2()); + assert_eq!(1, foo1()); + assert_eq!(3, foo2()); } diff --git a/src/test/run-pass/char.rs b/src/test/run-pass/char.rs index bcfc6a3ccd9a6..f982d3723b4c2 100644 --- a/src/test/run-pass/char.rs +++ b/src/test/run-pass/char.rs @@ -13,11 +13,11 @@ pub fn main() { let c: char = 'x'; let d: char = 'x'; - assert!((c == 'x')); - assert!(('x' == c)); - assert!((c == c)); - assert!((c == d)); - assert!((d == c)); - assert!((d == 'x')); - assert!(('x' == d)); + assert_eq!(c, 'x'); + assert_eq!('x', c); + assert_eq!(c, c); + assert_eq!(c, d); + assert_eq!(d, c); + assert_eq!(d, 'x'); + assert_eq!('x', d); } diff --git a/src/test/run-pass/child-outlives-parent.rs b/src/test/run-pass/child-outlives-parent.rs index 4eb3cea3a2586..9232547dd8bd5 100644 --- a/src/test/run-pass/child-outlives-parent.rs +++ b/src/test/run-pass/child-outlives-parent.rs @@ -10,7 +10,7 @@ // Reported as issue #126, child leaks the string. -extern mod std; +use std::task; fn child2(s: ~str) { } diff --git a/src/test/run-pass/class-cast-to-trait-cross-crate-2.rs b/src/test/run-pass/class-cast-to-trait-cross-crate-2.rs index 76f4e3b68f7c2..393c9e2ece0f5 100644 --- a/src/test/run-pass/class-cast-to-trait-cross-crate-2.rs +++ b/src/test/run-pass/class-cast-to-trait-cross-crate-2.rs @@ -11,13 +11,13 @@ // xfail-fast // aux-build:cci_class_cast.rs extern mod cci_class_cast; -use core::to_str::ToStr; +use std::to_str::ToStr; use cci_class_cast::kitty::*; fn print_out(thing: @ToStr, expected: ~str) { let actual = thing.to_str(); debug!("%s", actual); - assert!((actual == expected)); + assert_eq!(actual, expected); } pub fn main() { diff --git a/src/test/run-pass/class-cast-to-trait-cross-crate.rs b/src/test/run-pass/class-cast-to-trait-cross-crate.rs index 10cce8cf56a47..6674147e14769 100644 --- a/src/test/run-pass/class-cast-to-trait-cross-crate.rs +++ b/src/test/run-pass/class-cast-to-trait-cross-crate.rs @@ -51,7 +51,7 @@ class cat : to_str { fn print_out(thing: T, expected: str) { let actual = thing.to_str(); debug!("%s", actual); - assert!((actual == expected)); + assert_eq!(actual, expected); } pub fn main() { diff --git a/src/test/run-pass/class-cast-to-trait-multiple-types.rs b/src/test/run-pass/class-cast-to-trait-multiple-types.rs index be63e3394789e..361cafc40a962 100644 --- a/src/test/run-pass/class-cast-to-trait-multiple-types.rs +++ b/src/test/run-pass/class-cast-to-trait-multiple-types.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::uint; + trait noisy { fn speak(&self) -> int; } @@ -18,7 +20,7 @@ struct dog { volume : @mut int, } -pub impl dog { +impl dog { priv fn bark(&self) -> int { debug!("Woof %u %d", *self.barks, *self.volume); *self.barks += 1u; @@ -55,11 +57,11 @@ impl noisy for cat { fn speak(&self) -> int { self.meow() as int } } -pub impl cat { - fn meow_count(&self) -> uint { *self.meows } +impl cat { + pub fn meow_count(&self) -> uint { *self.meows } } -priv impl cat { +impl cat { fn meow(&self) -> uint { debug!("Meow"); *self.meows += 1u; @@ -88,6 +90,6 @@ pub fn main() { let whitefang : dog = dog(); annoy_neighbors(@(copy nyan) as @noisy); annoy_neighbors(@(copy whitefang) as @noisy); - assert!((nyan.meow_count() == 10u)); - assert!((*whitefang.volume == 1)); + assert_eq!(nyan.meow_count(), 10u); + assert_eq!(*whitefang.volume, 1); } diff --git a/src/test/run-pass/class-cast-to-trait.rs b/src/test/run-pass/class-cast-to-trait.rs index a15afa60c7522..a8ff906121687 100644 --- a/src/test/run-pass/class-cast-to-trait.rs +++ b/src/test/run-pass/class-cast-to-trait.rs @@ -22,8 +22,8 @@ impl noisy for cat { fn speak(&mut self) { self.meow(); } } -pub impl cat { - fn eat(&mut self) -> bool { +impl cat { + pub fn eat(&mut self) -> bool { if self.how_hungry > 0 { error!("OM NOM NOM"); self.how_hungry -= 2; @@ -36,7 +36,7 @@ pub impl cat { } } -priv impl cat { +impl cat { fn meow(&mut self) { error!("Meow"); self.meows += 1u; diff --git a/src/test/run-pass/class-exports.rs b/src/test/run-pass/class-exports.rs index 6684a729d23bb..11ef86035c56f 100644 --- a/src/test/run-pass/class-exports.rs +++ b/src/test/run-pass/class-exports.rs @@ -21,8 +21,8 @@ mod kitty { name: ~str, } - pub impl cat { - fn get_name(&self) -> ~str { self.name.clone() } + impl cat { + pub fn get_name(&self) -> ~str { self.name.clone() } } pub fn cat(in_name: ~str) -> cat { @@ -34,5 +34,5 @@ mod kitty { } pub fn main() { - assert!((cat(~"Spreckles").get_name() == ~"Spreckles")); + assert_eq!(cat(~"Spreckles").get_name(), ~"Spreckles"); } diff --git a/src/test/run-pass/class-impl-parameterized-trait.rs b/src/test/run-pass/class-impl-parameterized-trait.rs index 04784b5c51507..09967f0ab361d 100644 --- a/src/test/run-pass/class-impl-parameterized-trait.rs +++ b/src/test/run-pass/class-impl-parameterized-trait.rs @@ -11,8 +11,8 @@ // xfail-test // xfail-fast -extern mod std; -use std::oldmap::*; +extern mod extra; +use extra::oldmap::*; class cat : map { priv { diff --git a/src/test/run-pass/class-impl-very-parameterized-trait.rs b/src/test/run-pass/class-impl-very-parameterized-trait.rs index f7d526cde911a..88686bcdbfa35 100644 --- a/src/test/run-pass/class-impl-very-parameterized-trait.rs +++ b/src/test/run-pass/class-impl-very-parameterized-trait.rs @@ -10,8 +10,11 @@ // xfail-fast -use core::container::{Container, Mutable, Map}; -use core::old_iter::BaseIter; +use std::cmp; +use std::container::{Container, Mutable, Map}; +use std::int; +use std::old_iter::BaseIter; +use std::uint; enum cat_type { tuxedo, tabby, tortoiseshell } @@ -34,10 +37,10 @@ struct cat { name : T, } -pub impl cat { - fn speak(&mut self) { self.meow(); } +impl cat { + pub fn speak(&mut self) { self.meow(); } - fn eat(&mut self) -> bool { + pub fn eat(&mut self) -> bool { if self.how_hungry > 0 { error!("OM NOM NOM"); self.how_hungry -= 2; @@ -110,20 +113,20 @@ impl Map for cat { fn swap(&mut self, _k: int, _v: T) -> Option { fail!() } } -pub impl cat { - fn get<'a>(&'a self, k: &int) -> &'a T { +impl cat { + pub fn get<'a>(&'a self, k: &int) -> &'a T { match self.find(k) { Some(v) => { v } None => { fail!("epic fail"); } } } - fn new(in_x: int, in_y: int, in_name: T) -> cat { + pub fn new(in_x: int, in_y: int, in_name: T) -> cat { cat{meows: in_x, how_hungry: in_y, name: in_name } } } -priv impl cat { +impl cat { fn meow(&mut self) { self.meows += 1; error!("Meow %d", self.meows); @@ -136,11 +139,11 @@ priv impl cat { pub fn main() { let mut nyan: cat<~str> = cat::new(0, 2, ~"nyan"); for uint::range(1, 5) |_| { nyan.speak(); } - assert!((*nyan.find(&1).unwrap() == ~"nyan")); - assert!((nyan.find(&10) == None)); + assert!(*nyan.find(&1).unwrap() == ~"nyan"); + assert_eq!(nyan.find(&10), None); let mut spotty: cat = cat::new(2, 57, tuxedo); for uint::range(0, 6) |_| { spotty.speak(); } - assert!((spotty.len() == 8)); + assert_eq!(spotty.len(), 8); assert!((spotty.contains_key(&2))); - assert!((spotty.get(&3) == &tuxedo)); + assert_eq!(spotty.get(&3), &tuxedo); } diff --git a/src/test/run-pass/class-implement-trait-cross-crate.rs b/src/test/run-pass/class-implement-trait-cross-crate.rs index 226dbe535fa13..70020b395103d 100644 --- a/src/test/run-pass/class-implement-trait-cross-crate.rs +++ b/src/test/run-pass/class-implement-trait-cross-crate.rs @@ -13,6 +13,8 @@ extern mod cci_class_trait; use cci_class_trait::animals::*; +use std::uint; + struct cat { priv meows: uint, @@ -20,8 +22,8 @@ struct cat { name : ~str, } -pub impl cat { - fn eat(&mut self) -> bool { +impl cat { + pub fn eat(&mut self) -> bool { if self.how_hungry > 0 { error!("OM NOM NOM"); self.how_hungry -= 2; @@ -38,7 +40,7 @@ impl noisy for cat { fn speak(&mut self) { self.meow(); } } -priv impl cat { +impl cat { fn meow(&mut self) { error!("Meow"); self.meows += 1u; diff --git a/src/test/run-pass/class-implement-traits.rs b/src/test/run-pass/class-implement-traits.rs index 1c0a09d52cfc8..8c7c62ce27e3f 100644 --- a/src/test/run-pass/class-implement-traits.rs +++ b/src/test/run-pass/class-implement-traits.rs @@ -10,6 +10,8 @@ // xfail-fast +use std::uint; + trait noisy { fn speak(&mut self); } @@ -21,7 +23,7 @@ struct cat { name : ~str, } -priv impl cat { +impl cat { fn meow(&mut self) { error!("Meow"); self.meows += 1u; @@ -31,8 +33,8 @@ priv impl cat { } } -pub impl cat { - fn eat(&mut self) -> bool { +impl cat { + pub fn eat(&mut self) -> bool { if self.how_hungry > 0 { error!("OM NOM NOM"); self.how_hungry -= 2; diff --git a/src/test/run-pass/class-implements-multiple-traits.rs b/src/test/run-pass/class-implements-multiple-traits.rs index 61dfcfed7bdfd..7a3045db91f1a 100644 --- a/src/test/run-pass/class-implements-multiple-traits.rs +++ b/src/test/run-pass/class-implements-multiple-traits.rs @@ -10,8 +10,8 @@ // xfail-test -extern mod std; -use std::oldmap::*; +extern mod extra; +use extra::oldmap::*; use vec::*; use dvec::{dvec, extensions}; @@ -123,7 +123,7 @@ fn scratched_something(critter: T) -> bool { pub fn main() { let nyan : cat = cat(0u, 2, "nyan"); annoy_neighbors(nyan as noisy); - assert!((nyan.meow_count() == 10u)); + assert_eq!(nyan.meow_count(), 10u); assert!((bite_everything(nyan as bitey))); assert!((scratched_something(nyan as scratchy))); } diff --git a/src/test/run-pass/class-method-cross-crate.rs b/src/test/run-pass/class-method-cross-crate.rs index a6ab91a2c8822..d2c78c7f1add8 100644 --- a/src/test/run-pass/class-method-cross-crate.rs +++ b/src/test/run-pass/class-method-cross-crate.rs @@ -16,7 +16,7 @@ use cci_class_2::kitties::*; pub fn main() { let nyan : cat = cat(52u, 99); let kitty = cat(1000u, 2); - assert!((nyan.how_hungry == 99)); - assert!((kitty.how_hungry == 2)); + assert_eq!(nyan.how_hungry, 99); + assert_eq!(kitty.how_hungry, 2); nyan.speak(); } diff --git a/src/test/run-pass/class-methods-cross-crate.rs b/src/test/run-pass/class-methods-cross-crate.rs index 8e5843c6a85be..c5e37cab2b84a 100644 --- a/src/test/run-pass/class-methods-cross-crate.rs +++ b/src/test/run-pass/class-methods-cross-crate.rs @@ -16,8 +16,8 @@ use cci_class_3::kitties::*; pub fn main() { let mut nyan : cat = cat(52u, 99); let mut kitty = cat(1000u, 2); - assert!((nyan.how_hungry == 99)); - assert!((kitty.how_hungry == 2)); + assert_eq!(nyan.how_hungry, 99); + assert_eq!(kitty.how_hungry, 2); nyan.speak(); - assert!((nyan.meow_count() == 53u)); + assert_eq!(nyan.meow_count(), 53u); } diff --git a/src/test/run-pass/class-methods.rs b/src/test/run-pass/class-methods.rs index 1c4c83999f7df..fca128b9a9735 100644 --- a/src/test/run-pass/class-methods.rs +++ b/src/test/run-pass/class-methods.rs @@ -14,9 +14,9 @@ struct cat { how_hungry : int, } -pub impl cat { - fn speak(&mut self) { self.meows += 1u; } - fn meow_count(&mut self) -> uint { self.meows } +impl cat { + pub fn speak(&mut self) { self.meows += 1u; } + pub fn meow_count(&mut self) -> uint { self.meows } } fn cat(in_x: uint, in_y: int) -> cat { @@ -29,8 +29,8 @@ fn cat(in_x: uint, in_y: int) -> cat { pub fn main() { let mut nyan: cat = cat(52u, 99); let mut kitty = cat(1000u, 2); - assert!((nyan.how_hungry == 99)); - assert!((kitty.how_hungry == 2)); + assert_eq!(nyan.how_hungry, 99); + assert_eq!(kitty.how_hungry, 2); nyan.speak(); - assert!((nyan.meow_count() == 53u)); + assert_eq!(nyan.meow_count(), 53u); } diff --git a/src/test/run-pass/class-poly-methods-cross-crate.rs b/src/test/run-pass/class-poly-methods-cross-crate.rs index cde171a44e243..62ff54388952f 100644 --- a/src/test/run-pass/class-poly-methods-cross-crate.rs +++ b/src/test/run-pass/class-poly-methods-cross-crate.rs @@ -16,10 +16,10 @@ use cci_class_6::kitties::*; pub fn main() { let mut nyan : cat = cat::(52u, 99, ~['p']); let mut kitty = cat(1000u, 2, ~[~"tabby"]); - assert!((nyan.how_hungry == 99)); - assert!((kitty.how_hungry == 2)); + assert_eq!(nyan.how_hungry, 99); + assert_eq!(kitty.how_hungry, 2); nyan.speak(~[1u,2u,3u]); - assert!((nyan.meow_count() == 55u)); + assert_eq!(nyan.meow_count(), 55u); kitty.speak(~[~"meow", ~"mew", ~"purr", ~"chirp"]); - assert!((kitty.meow_count() == 1004u)); + assert_eq!(kitty.meow_count(), 1004u); } diff --git a/src/test/run-pass/class-poly-methods.rs b/src/test/run-pass/class-poly-methods.rs index 9774d8d14882e..0201501bc7c64 100644 --- a/src/test/run-pass/class-poly-methods.rs +++ b/src/test/run-pass/class-poly-methods.rs @@ -15,11 +15,11 @@ struct cat { how_hungry : int, } -pub impl cat { - fn speak(&mut self, stuff: ~[T]) { +impl cat { + pub fn speak(&mut self, stuff: ~[T]) { self.meows += stuff.len(); } - fn meow_count(&mut self) -> uint { self.meows } + pub fn meow_count(&mut self) -> uint { self.meows } } fn cat(in_x : uint, in_y : int, in_info: ~[U]) -> cat { @@ -33,10 +33,10 @@ fn cat(in_x : uint, in_y : int, in_info: ~[U]) -> cat { pub fn main() { let mut nyan : cat = cat::(52u, 99, ~[9]); let mut kitty = cat(1000u, 2, ~[~"tabby"]); - assert!((nyan.how_hungry == 99)); - assert!((kitty.how_hungry == 2)); + assert_eq!(nyan.how_hungry, 99); + assert_eq!(kitty.how_hungry, 2); nyan.speak(~[1,2,3]); - assert!((nyan.meow_count() == 55u)); + assert_eq!(nyan.meow_count(), 55u); kitty.speak(~[~"meow", ~"mew", ~"purr", ~"chirp"]); - assert!((kitty.meow_count() == 1004u)); + assert_eq!(kitty.meow_count(), 1004u); } diff --git a/src/test/run-pass/class-separate-impl.rs b/src/test/run-pass/class-separate-impl.rs index e058b3331b386..f31b702519349 100644 --- a/src/test/run-pass/class-separate-impl.rs +++ b/src/test/run-pass/class-separate-impl.rs @@ -16,10 +16,10 @@ struct cat { name : ~str, } -pub impl cat { - fn speak(&mut self) { self.meow(); } +impl cat { + pub fn speak(&mut self) { self.meow(); } - fn eat(&mut self) -> bool { + pub fn eat(&mut self) -> bool { if self.how_hungry > 0 { error!("OM NOM NOM"); self.how_hungry -= 2; @@ -32,7 +32,7 @@ pub impl cat { } } -priv impl cat { +impl cat { fn meow(&mut self) { error!("Meow"); self.meows += 1u; @@ -62,7 +62,7 @@ impl ToStr for cat { fn print_out(thing: @ToStr, expected: ~str) { let actual = thing.to_str(); debug!("%s", actual); - assert!((actual == expected)); + assert_eq!(actual, expected); } pub fn main() { diff --git a/src/test/run-pass/class-trait-bounded-param.rs b/src/test/run-pass/class-trait-bounded-param.rs index e1929d33d5b9c..75c62abcb0d55 100644 --- a/src/test/run-pass/class-trait-bounded-param.rs +++ b/src/test/run-pass/class-trait-bounded-param.rs @@ -10,8 +10,8 @@ // xfail-test -extern mod std; -use std::oldmap::{map, hashmap, int_hash}; +extern mod extra; +use extra::oldmap::{map, hashmap, int_hash}; class keys> : old_iter::base_iter { @@ -31,5 +31,5 @@ pub fn main() { let m = int_hash(); m.insert(1, 2); m.insert(3, 4); - assert!(old_iter::to_vec(keys(m)) == ~[1, 3]); + assert_eq!(old_iter::to_vec(keys(m)), ~[1, 3]); } diff --git a/src/test/run-pass/class-typarams.rs b/src/test/run-pass/class-typarams.rs index 29354c54d8ba0..8533add411949 100644 --- a/src/test/run-pass/class-typarams.rs +++ b/src/test/run-pass/class-typarams.rs @@ -14,9 +14,9 @@ struct cat { how_hungry : int, } -pub impl cat { - fn speak(&mut self) { self.meows += 1u; } - fn meow_count(&mut self) -> uint { self.meows } +impl cat { + pub fn speak(&mut self) { self.meows += 1u; } + pub fn meow_count(&mut self) -> uint { self.meows } } fn cat(in_x : uint, in_y : int) -> cat { diff --git a/src/test/run-pass/classes-cross-crate.rs b/src/test/run-pass/classes-cross-crate.rs index 6a8a47990b844..0af433bd655b4 100644 --- a/src/test/run-pass/classes-cross-crate.rs +++ b/src/test/run-pass/classes-cross-crate.rs @@ -13,6 +13,8 @@ extern mod cci_class_4; use cci_class_4::kitties::*; +use std::uint; + pub fn main() { let mut nyan = cat(0u, 2, ~"nyan"); nyan.eat(); diff --git a/src/test/run-pass/classes-simple-cross-crate.rs b/src/test/run-pass/classes-simple-cross-crate.rs index 6c35d113e0e39..0df04c40fb7c9 100644 --- a/src/test/run-pass/classes-simple-cross-crate.rs +++ b/src/test/run-pass/classes-simple-cross-crate.rs @@ -16,6 +16,6 @@ use cci_class::kitties::*; pub fn main() { let nyan : cat = cat(52u, 99); let kitty = cat(1000u, 2); - assert!((nyan.how_hungry == 99)); - assert!((kitty.how_hungry == 2)); + assert_eq!(nyan.how_hungry, 99); + assert_eq!(kitty.how_hungry, 2); } diff --git a/src/test/run-pass/classes-simple-method.rs b/src/test/run-pass/classes-simple-method.rs index cd318ab6c6b7e..f27738cf4216e 100644 --- a/src/test/run-pass/classes-simple-method.rs +++ b/src/test/run-pass/classes-simple-method.rs @@ -14,8 +14,8 @@ struct cat { how_hungry : int, } -pub impl cat { - fn speak(&mut self) {} +impl cat { + pub fn speak(&mut self) {} } fn cat(in_x : uint, in_y : int) -> cat { @@ -28,7 +28,7 @@ fn cat(in_x : uint, in_y : int) -> cat { pub fn main() { let mut nyan : cat = cat(52u, 99); let mut kitty = cat(1000u, 2); - assert!((nyan.how_hungry == 99)); - assert!((kitty.how_hungry == 2)); + assert_eq!(nyan.how_hungry, 99); + assert_eq!(kitty.how_hungry, 2); nyan.speak(); } diff --git a/src/test/run-pass/classes-simple.rs b/src/test/run-pass/classes-simple.rs index 0af281bdce40d..3d2b08d7a851d 100644 --- a/src/test/run-pass/classes-simple.rs +++ b/src/test/run-pass/classes-simple.rs @@ -24,6 +24,6 @@ fn cat(in_x : uint, in_y : int) -> cat { pub fn main() { let mut nyan : cat = cat(52u, 99); let mut kitty = cat(1000u, 2); - assert!((nyan.how_hungry == 99)); - assert!((kitty.how_hungry == 2)); + assert_eq!(nyan.how_hungry, 99); + assert_eq!(kitty.how_hungry, 2); } diff --git a/src/test/run-pass/classes.rs b/src/test/run-pass/classes.rs index 523469041416a..89d89d116a38d 100644 --- a/src/test/run-pass/classes.rs +++ b/src/test/run-pass/classes.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::uint; + struct cat { priv meows : uint, @@ -15,10 +17,10 @@ struct cat { name : ~str, } -pub impl cat { - fn speak(&mut self) { self.meow(); } +impl cat { + pub fn speak(&mut self) { self.meow(); } - fn eat(&mut self) -> bool { + pub fn eat(&mut self) -> bool { if self.how_hungry > 0 { error!("OM NOM NOM"); self.how_hungry -= 2; @@ -30,7 +32,7 @@ pub impl cat { } } -priv impl cat { +impl cat { fn meow(&mut self) { error!("Meow"); self.meows += 1u; diff --git a/src/test/run-pass/cleanup-copy-mode.rs b/src/test/run-pass/cleanup-copy-mode.rs index cb378da13ea60..2446e9057c2e7 100644 --- a/src/test/run-pass/cleanup-copy-mode.rs +++ b/src/test/run-pass/cleanup-copy-mode.rs @@ -9,6 +9,10 @@ // except according to those terms. // xfail-win32 + +use std::result; +use std::task; + fn adder(x: @int, y: @int) -> int { return *x + *y; } fn failer() -> @int { fail!(); } pub fn main() { diff --git a/src/test/run-pass/clone-with-exterior.rs b/src/test/run-pass/clone-with-exterior.rs index ae2983b159425..f6a7856dccccf 100644 --- a/src/test/run-pass/clone-with-exterior.rs +++ b/src/test/run-pass/clone-with-exterior.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; -use core::task::spawn; +extern mod extra; +use std::task::spawn; struct Pair { a: int, @@ -20,8 +20,8 @@ pub fn main() { let z = ~Pair { a : 10, b : 12}; let f: ~fn() = || { - assert!((z.a == 10)); - assert!((z.b == 12)); + assert_eq!(z.a, 10); + assert_eq!(z.b, 12); }; spawn(f); diff --git a/src/test/run-pass/close-over-big-then-small-data.rs b/src/test/run-pass/close-over-big-then-small-data.rs index 0cff05ed19f27..736c0f9194175 100644 --- a/src/test/run-pass/close-over-big-then-small-data.rs +++ b/src/test/run-pass/close-over-big-then-small-data.rs @@ -24,6 +24,6 @@ fn f(a: A, b: u16) -> @fn() -> (A, u16) { pub fn main() { let (a, b) = f(22_u64, 44u16)(); debug!("a=%? b=%?", a, b); - assert!(a == 22u64); - assert!(b == 44u16); + assert_eq!(a, 22u64); + assert_eq!(b, 44u16); } diff --git a/src/test/run-pass/closure-inference.rs b/src/test/run-pass/closure-inference.rs index 6cdb8f393d526..167fbdf3fc052 100644 --- a/src/test/run-pass/closure-inference.rs +++ b/src/test/run-pass/closure-inference.rs @@ -16,5 +16,5 @@ fn apply(f: &fn(A) -> A, v: A) -> A { f(v) } pub fn main() { let f = {|i| foo(i)}; - assert!(apply(f, 2) == 3); + assert_eq!(apply(f, 2), 3); } diff --git a/src/test/run-pass/closure-inference2.rs b/src/test/run-pass/closure-inference2.rs index 4e2972394453f..fa16ea001452c 100644 --- a/src/test/run-pass/closure-inference2.rs +++ b/src/test/run-pass/closure-inference2.rs @@ -12,6 +12,6 @@ pub fn main() { let f = {|i| i}; - assert!(f(2) == 2); - assert!(f(5) == 5); + assert_eq!(f(2), 2); + assert_eq!(f(5), 5); } diff --git a/src/test/run-pass/coerce-reborrow-imm-ptr-rcvr.rs b/src/test/run-pass/coerce-reborrow-imm-ptr-rcvr.rs index c4bed1e7d7da4..438c70c6583f4 100644 --- a/src/test/run-pass/coerce-reborrow-imm-ptr-rcvr.rs +++ b/src/test/run-pass/coerce-reborrow-imm-ptr-rcvr.rs @@ -2,8 +2,8 @@ struct SpeechMaker { speeches: uint } -pub impl SpeechMaker { - fn how_many(&const self) -> uint { self.speeches } +impl SpeechMaker { + pub fn how_many(&const self) -> uint { self.speeches } } fn foo(speaker: &const SpeechMaker) -> uint { @@ -12,5 +12,5 @@ fn foo(speaker: &const SpeechMaker) -> uint { pub fn main() { let mut lincoln = SpeechMaker {speeches: 22}; - assert!(foo(&const lincoln) == 55); + assert_eq!(foo(&const lincoln), 55); } diff --git a/src/test/run-pass/coerce-reborrow-imm-vec-rcvr.rs b/src/test/run-pass/coerce-reborrow-imm-vec-rcvr.rs index 1511eab8241d4..7ab80920849b3 100644 --- a/src/test/run-pass/coerce-reborrow-imm-vec-rcvr.rs +++ b/src/test/run-pass/coerce-reborrow-imm-vec-rcvr.rs @@ -14,7 +14,7 @@ fn bip(v: &[uint]) -> ~[uint] { pub fn main() { let mut the_vec = ~[1, 2, 3, 100]; - assert!(the_vec == foo(the_vec)); - assert!(the_vec == bar(the_vec)); - assert!(the_vec == bip(the_vec)); + assert_eq!(the_vec, foo(the_vec)); + assert_eq!(the_vec, bar(the_vec)); + assert_eq!(the_vec, bip(the_vec)); } diff --git a/src/test/run-pass/coerce-reborrow-mut-ptr-rcvr.rs b/src/test/run-pass/coerce-reborrow-mut-ptr-rcvr.rs index fd47c262d6a7d..3adb805581dd0 100644 --- a/src/test/run-pass/coerce-reborrow-mut-ptr-rcvr.rs +++ b/src/test/run-pass/coerce-reborrow-mut-ptr-rcvr.rs @@ -2,8 +2,8 @@ struct SpeechMaker { speeches: uint } -pub impl SpeechMaker { - fn talk(&mut self) { +impl SpeechMaker { + pub fn talk(&mut self) { self.speeches += 1; } } diff --git a/src/test/run-pass/coerce-reborrow-mut-vec-arg.rs b/src/test/run-pass/coerce-reborrow-mut-vec-arg.rs index bfc1de4d1e7fa..3d216c1885f6e 100644 --- a/src/test/run-pass/coerce-reborrow-mut-vec-arg.rs +++ b/src/test/run-pass/coerce-reborrow-mut-vec-arg.rs @@ -1,3 +1,5 @@ +use std::vec; + trait Reverser { fn reverse(&self); } @@ -11,5 +13,5 @@ fn bar(v: &mut [uint]) { pub fn main() { let mut the_vec = ~[1, 2, 3, 100]; bar(the_vec); - assert!(the_vec == ~[100, 3, 2, 1]); + assert_eq!(the_vec, ~[100, 3, 2, 1]); } diff --git a/src/test/run-pass/coerce-reborrow-mut-vec-rcvr.rs b/src/test/run-pass/coerce-reborrow-mut-vec-rcvr.rs index b0d06dae10dc0..d62ed77fdab32 100644 --- a/src/test/run-pass/coerce-reborrow-mut-vec-rcvr.rs +++ b/src/test/run-pass/coerce-reborrow-mut-vec-rcvr.rs @@ -1,3 +1,5 @@ +use std::vec; + trait Reverser { fn reverse(self); } @@ -17,5 +19,5 @@ fn bar(v: &mut [uint]) { pub fn main() { let mut the_vec = ~[1, 2, 3, 100]; bar(the_vec); - assert!(the_vec == ~[100, 3, 2, 1]); + assert_eq!(the_vec, ~[100, 3, 2, 1]); } diff --git a/src/test/run-pass/coherence-impl-in-fn.rs b/src/test/run-pass/coherence-impl-in-fn.rs index 7643799df0637..707a7bf407659 100644 --- a/src/test/run-pass/coherence-impl-in-fn.rs +++ b/src/test/run-pass/coherence-impl-in-fn.rs @@ -10,7 +10,7 @@ pub fn main() { enum x { foo } - impl ::core::cmp::Eq for x { + impl ::std::cmp::Eq for x { fn eq(&self, other: &x) -> bool { (*self) as int == (*other) as int } diff --git a/src/test/run-pass/comm.rs b/src/test/run-pass/comm.rs index a01b06d4d7ce9..b0bdfd598fb79 100644 --- a/src/test/run-pass/comm.rs +++ b/src/test/run-pass/comm.rs @@ -9,7 +9,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::comm::*; +use std::comm::*; +use std::task; pub fn main() { let (p, ch) = stream(); @@ -17,7 +18,7 @@ pub fn main() { let y = p.recv(); error!("received"); error!(y); - assert!((y == 10)); + assert_eq!(y, 10); } fn child(c: &Chan) { diff --git a/src/test/run-pass/conditional-compile.rs b/src/test/run-pass/conditional-compile.rs index 73fdb219c1941..3fe33eae84d49 100644 --- a/src/test/run-pass/conditional-compile.rs +++ b/src/test/run-pass/conditional-compile.rs @@ -104,7 +104,7 @@ fn test_in_fn_ctxt() { #[cfg(bogus)] static i: int = 0; static i: int = 1; - assert!((i == 1)); + assert_eq!(i, 1); } mod test_foreign_items { diff --git a/src/test/run-pass/const-autoderef-newtype.rs b/src/test/run-pass/const-autoderef-newtype.rs index 021196bf7072a..19dea653a4a27 100644 --- a/src/test/run-pass/const-autoderef-newtype.rs +++ b/src/test/run-pass/const-autoderef-newtype.rs @@ -13,5 +13,5 @@ static C0: S = S([3]); static C1: int = C0[0]; pub fn main() { - assert!(C1 == 3); + assert_eq!(C1, 3); } diff --git a/src/test/run-pass/const-autoderef.rs b/src/test/run-pass/const-autoderef.rs index a7f9b57718c77..e80ed7c984b4a 100644 --- a/src/test/run-pass/const-autoderef.rs +++ b/src/test/run-pass/const-autoderef.rs @@ -14,6 +14,6 @@ static C: &'static &'static &'static &'static [u8, ..1] = & & & &A; static D: u8 = (&C)[0]; pub fn main() { - assert!(B == A[0]); - assert!(D == A[0]); + assert_eq!(B, A[0]); + assert_eq!(D, A[0]); } diff --git a/src/test/run-pass/const-big-enum.rs b/src/test/run-pass/const-big-enum.rs index 3aa7fd475b084..ac2e879ceacc9 100644 --- a/src/test/run-pass/const-big-enum.rs +++ b/src/test/run-pass/const-big-enum.rs @@ -27,8 +27,8 @@ pub fn main() { } match Z { Quux(d,h) => { - assert!((d == 0x123456789abcdef0)); - assert!((h == 0x1234)); + assert_eq!(d, 0x123456789abcdef0); + assert_eq!(h, 0x1234); } _ => fail!() } diff --git a/src/test/run-pass/const-binops.rs b/src/test/run-pass/const-binops.rs new file mode 100644 index 0000000000000..cd87ca3ab537e --- /dev/null +++ b/src/test/run-pass/const-binops.rs @@ -0,0 +1,116 @@ +static a: int = -4 + 3; +static a2: uint = 3 + 3; +static b: float = 3.0 + 2.7; + +static c: int = 3 - 4; +static d: uint = 3 - 3; +static e: float = 3.0 - 2.7; + +static e2: int = -3 * 3; +static f: uint = 3 * 3; +static g: float = 3.3 * 3.3; + +static h: int = 3 / -1; +static i: uint = 3 / 3; +static j: float = 3.3 / 3.3; + +static n: bool = true && false; + +static o: bool = true || false; + +static p: int = 3 & 1; +static q: uint = 1 & 3; + +static r: int = 3 | 1; +static s: uint = 1 | 3; + +static t: int = 3 ^ 1; +static u: uint = 1 ^ 3; + +static v: int = 1 << 3; + +// NOTE: better shr coverage +static w: int = 1024 >> 4; +static x: uint = 1024 >> 4; + +static y: bool = 1 == 1; +static z: bool = 1.0 == 1.0; + +static aa: bool = 1 <= 2; +static ab: bool = -1 <= 2; +static ac: bool = 1.0 <= 2.0; + +static ad: bool = 1 < 2; +static ae: bool = -1 < 2; +static af: bool = 1.0 < 2.0; + +static ag: bool = 1 != 2; +static ah: bool = -1 != 2; +static ai: bool = 1.0 != 2.0; + +static aj: bool = 2 >= 1; +static ak: bool = 2 >= -2; +static al: bool = 1.0 >= -2.0; + +static am: bool = 2 > 1; +static an: bool = 2 > -2; +static ao: bool = 1.0 > -2.0; + +fn main() { + assert_eq!(a, -1); + assert_eq!(a2, 6); + assert_approx_eq!(b, 5.7); + + assert_eq!(c, -1); + assert_eq!(d, 0); + assert_approx_eq!(e, 0.3); + + assert_eq!(e2, -9); + assert_eq!(f, 9); + assert_approx_eq!(g, 10.89); + + assert_eq!(h, -3); + assert_eq!(i, 1); + assert_approx_eq!(j, 1.0); + + assert_eq!(n, false); + + assert_eq!(o, true); + + assert_eq!(p, 1); + assert_eq!(q, 1); + + assert_eq!(r, 3); + assert_eq!(s, 3); + + assert_eq!(t, 2); + assert_eq!(u, 2); + + assert_eq!(v, 8); + + assert_eq!(w, 64); + assert_eq!(x, 64); + + assert_eq!(y, true); + assert_eq!(z, true); + + assert_eq!(aa, true); + assert_eq!(ab, true); + assert_eq!(ac, true); + + assert_eq!(ad, true); + assert_eq!(ae, true); + assert_eq!(af, true); + + assert_eq!(ag, true); + assert_eq!(ah, true); + assert_eq!(ai, true); + + assert_eq!(aj, true); + assert_eq!(ak, true); + assert_eq!(al, true); + + assert_eq!(am, true); + assert_eq!(an, true); + assert_eq!(ao, true); +} diff --git a/src/test/run-pass/const-cast-ptr-int.rs b/src/test/run-pass/const-cast-ptr-int.rs index ea5533da14d9d..88ab70f596adf 100644 --- a/src/test/run-pass/const-cast-ptr-int.rs +++ b/src/test/run-pass/const-cast-ptr-int.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::ptr; + static a: *u8 = 0 as *u8; pub fn main() { - assert!(a == ptr::null()); + assert_eq!(a, ptr::null()); } diff --git a/src/test/run-pass/const-cast.rs b/src/test/run-pass/const-cast.rs index d35ad9d2da3e1..280fe44c3da3e 100644 --- a/src/test/run-pass/const-cast.rs +++ b/src/test/run-pass/const-cast.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::libc; + extern fn foo() {} static x: *u8 = foo; @@ -16,6 +18,6 @@ static a: &'static int = &10; static b: *int = a as *int; pub fn main() { - assert!(x as *libc::c_void == y); - assert!(a as *int == b); + assert_eq!(x as *libc::c_void, y); + assert_eq!(a as *int, b); } diff --git a/src/test/run-pass/const-const.rs b/src/test/run-pass/const-const.rs index e68bf8a74c3a3..bdb2b3d211043 100644 --- a/src/test/run-pass/const-const.rs +++ b/src/test/run-pass/const-const.rs @@ -12,5 +12,5 @@ static a: int = 1; static b: int = a + 2; pub fn main() { - assert!(b == 3); + assert_eq!(b, 3); } diff --git a/src/test/run-pass/const-contents.rs b/src/test/run-pass/const-contents.rs index 19ce5b3713df2..5b31c9a44de51 100644 --- a/src/test/run-pass/const-contents.rs +++ b/src/test/run-pass/const-contents.rs @@ -18,10 +18,10 @@ static notb : bool = !true; static neg : int = -(1); pub fn main() { - assert!((lsl == 4)); - assert!((add == 3)); - assert!((addf == 3.0f)); - assert!((not == -1)); - assert!((notb == false)); - assert!((neg == -1)); + assert_eq!(lsl, 4); + assert_eq!(add, 3); + assert_eq!(addf, 3.0f); + assert_eq!(not, -1); + assert_eq!(notb, false); + assert_eq!(neg, -1); } diff --git a/src/test/run-pass/const-cross-crate-const.rs b/src/test/run-pass/const-cross-crate-const.rs index 55975d364c84f..607d0c72b8954 100644 --- a/src/test/run-pass/const-cross-crate-const.rs +++ b/src/test/run-pass/const-cross-crate-const.rs @@ -17,9 +17,9 @@ static a: uint = cci_const::uint_val; static b: uint = cci_const::uint_expr + 5; fn main() { - assert!(a == 12); + assert_eq!(a, 12); let foo2 = a; - assert!(foo2 == cci_const::uint_val); - assert!(b == cci_const::uint_expr + 5); - assert!(foo == cci_const::foopy); + assert_eq!(foo2, cci_const::uint_val); + assert_eq!(b, cci_const::uint_expr + 5); + assert_eq!(foo, cci_const::foopy); } diff --git a/src/test/run-pass/const-cross-crate-extern.rs b/src/test/run-pass/const-cross-crate-extern.rs index bac84d12e4ce1..5281c21762689 100644 --- a/src/test/run-pass/const-cross-crate-extern.rs +++ b/src/test/run-pass/const-cross-crate-extern.rs @@ -16,5 +16,5 @@ use cci_const::bar; static foo: *u8 = bar; pub fn main() { - assert!(foo == cci_const::bar); + assert_eq!(foo, cci_const::bar); } diff --git a/src/test/run-pass/const-deref.rs b/src/test/run-pass/const-deref.rs index ee98e60f4d63f..b1797857d0410 100644 --- a/src/test/run-pass/const-deref.rs +++ b/src/test/run-pass/const-deref.rs @@ -15,6 +15,6 @@ static E: &'static S = &S(C); static F: int = ***E; pub fn main() { - assert!(D == 1000); - assert!(F == 1000); + assert_eq!(D, 1000); + assert_eq!(F, 1000); } diff --git a/src/test/run-pass/const-enum-byref-self.rs b/src/test/run-pass/const-enum-byref-self.rs index c4e1ea727e47e..098a001cfcde9 100644 --- a/src/test/run-pass/const-enum-byref-self.rs +++ b/src/test/run-pass/const-enum-byref-self.rs @@ -11,8 +11,8 @@ enum E { V, VV(int) } static C: E = V; -pub impl E { - fn method(&self) { +impl E { + pub fn method(&self) { match *self { V => {} VV(*) => fail!() diff --git a/src/test/run-pass/const-enum-cast.rs b/src/test/run-pass/const-enum-cast.rs index 89990e9d892cc..616c7567adf47 100644 --- a/src/test/run-pass/const-enum-cast.rs +++ b/src/test/run-pass/const-enum-cast.rs @@ -20,12 +20,12 @@ pub fn main () { let a2 = B2 as int; let a3 = A2 as float; let a4 = B2 as float; - assert!(c1 == 1); - assert!(c2 == 2); - assert!(c3 == 1.0); - assert!(c4 == 2.0); - assert!(a1 == 1); - assert!(a2 == 2); - assert!(a3 == 1.0); - assert!(a4 == 2.0); + assert_eq!(c1, 1); + assert_eq!(c2, 2); + assert_eq!(c3, 1.0); + assert_eq!(c4, 2.0); + assert_eq!(a1, 1); + assert_eq!(a2, 2); + assert_eq!(a3, 1.0); + assert_eq!(a4, 2.0); } diff --git a/src/test/run-pass/const-enum-struct.rs b/src/test/run-pass/const-enum-struct.rs index b6d916a9c38a1..3229293fd7a46 100644 --- a/src/test/run-pass/const-enum-struct.rs +++ b/src/test/run-pass/const-enum-struct.rs @@ -15,5 +15,5 @@ static C: S = S { a: V16(0xDEAD), b: 0x600D, c: 0xBAD }; pub fn main() { let n = C.b; assert!(n != 0xBAD); - assert!(n == 0x600D); + assert_eq!(n, 0x600D); } diff --git a/src/test/run-pass/const-enum-struct2.rs b/src/test/run-pass/const-enum-struct2.rs index 3d9f7fc204404..4530a65002772 100644 --- a/src/test/run-pass/const-enum-struct2.rs +++ b/src/test/run-pass/const-enum-struct2.rs @@ -15,5 +15,5 @@ static C: S = S { a: V0, b: 0x600D, c: 0xBAD }; pub fn main() { let n = C.b; assert!(n != 0xBAD); - assert!(n == 0x600D); + assert_eq!(n, 0x600D); } diff --git a/src/test/run-pass/const-enum-tuple.rs b/src/test/run-pass/const-enum-tuple.rs index ade3dfd6b6358..17d8341457d35 100644 --- a/src/test/run-pass/const-enum-tuple.rs +++ b/src/test/run-pass/const-enum-tuple.rs @@ -14,5 +14,5 @@ static C: (E, u16, u16) = (V16(0xDEAD), 0x600D, 0xBAD); pub fn main() { let (_, n, _) = C; assert!(n != 0xBAD); - assert!(n == 0x600D); + assert_eq!(n, 0x600D); } diff --git a/src/test/run-pass/const-enum-tuple2.rs b/src/test/run-pass/const-enum-tuple2.rs index 14da9438af00a..5d7a161720c18 100644 --- a/src/test/run-pass/const-enum-tuple2.rs +++ b/src/test/run-pass/const-enum-tuple2.rs @@ -14,5 +14,5 @@ static C: (E, u16, u16) = (V0, 0x600D, 0xBAD); pub fn main() { let (_, n, _) = C; assert!(n != 0xBAD); - assert!(n == 0x600D); + assert_eq!(n, 0x600D); } diff --git a/src/test/run-pass/const-enum-tuplestruct.rs b/src/test/run-pass/const-enum-tuplestruct.rs index 885664f7ef03c..40137afa2eee2 100644 --- a/src/test/run-pass/const-enum-tuplestruct.rs +++ b/src/test/run-pass/const-enum-tuplestruct.rs @@ -15,5 +15,5 @@ static C: S = S(V16(0xDEAD), 0x600D, 0xBAD); pub fn main() { let S(_, n, _) = C; assert!(n != 0xBAD); - assert!(n == 0x600D); + assert_eq!(n, 0x600D); } diff --git a/src/test/run-pass/const-enum-tuplestruct2.rs b/src/test/run-pass/const-enum-tuplestruct2.rs index ad4befd92d15e..f6345efcb4348 100644 --- a/src/test/run-pass/const-enum-tuplestruct2.rs +++ b/src/test/run-pass/const-enum-tuplestruct2.rs @@ -15,5 +15,5 @@ static C: S = S(V0, 0x600D, 0xBAD); pub fn main() { let S(_, n, _) = C; assert!(n != 0xBAD); - assert!(n == 0x600D); + assert_eq!(n, 0x600D); } diff --git a/src/test/run-pass/const-extern-function.rs b/src/test/run-pass/const-extern-function.rs index a9d036f121921..9a8104cb14f71 100644 --- a/src/test/run-pass/const-extern-function.rs +++ b/src/test/run-pass/const-extern-function.rs @@ -18,6 +18,6 @@ struct S { } pub fn main() { - assert!(foopy == f); - assert!(f == s.f); + assert_eq!(foopy, f); + assert_eq!(f, s.f); } diff --git a/src/test/run-pass/const-fields-and-indexing.rs b/src/test/run-pass/const-fields-and-indexing.rs index 014ec19d56502..990e5e6721915 100644 --- a/src/test/run-pass/const-fields-and-indexing.rs +++ b/src/test/run-pass/const-fields-and-indexing.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::io; + static x : [int, ..4] = [1,2,3,4]; static p : int = x[2]; static y : &'static [int] = &[1,2,3,4]; @@ -28,7 +30,7 @@ pub fn main() { io::println(fmt!("%?", p)); io::println(fmt!("%?", q)); io::println(fmt!("%?", t)); - assert!(p == 3); - assert!(q == 3); - assert!(t == 20); + assert_eq!(p, 3); + assert_eq!(q, 3); + assert_eq!(t, 20); } diff --git a/src/test/run-pass/const-fn-val.rs b/src/test/run-pass/const-fn-val.rs index 544d671431260..dfcfb30f77ffb 100644 --- a/src/test/run-pass/const-fn-val.rs +++ b/src/test/run-pass/const-fn-val.rs @@ -17,5 +17,5 @@ struct Bar<'self> { f: &'self fn() -> int } static b : Bar<'static> = Bar { f: foo }; pub fn main() { - assert!((b.f)() == 0xca7f000d); + assert_eq!((b.f)(), 0xca7f000d); } diff --git a/src/test/run-pass/const-negative.rs b/src/test/run-pass/const-negative.rs index e4905d5c5324d..4e2be013c11e4 100644 --- a/src/test/run-pass/const-negative.rs +++ b/src/test/run-pass/const-negative.rs @@ -13,5 +13,5 @@ static toplevel_mod: int = -1; pub fn main() { - assert!(toplevel_mod == -1); + assert_eq!(toplevel_mod, -1); } diff --git a/src/test/run-pass/const-nullary-univariant-enum.rs b/src/test/run-pass/const-nullary-univariant-enum.rs index 0d0674aa962fc..30fbe38aed033 100644 --- a/src/test/run-pass/const-nullary-univariant-enum.rs +++ b/src/test/run-pass/const-nullary-univariant-enum.rs @@ -15,8 +15,8 @@ enum Foo { static X: Foo = Bar; pub fn main() { - assert!(((X as uint) == 0xDEADBEE)); - assert!(((Y as uint) == 0xDEADBEE)); + assert_eq!((X as uint), 0xDEADBEE); + assert_eq!((Y as uint), 0xDEADBEE); } static Y: Foo = Bar; diff --git a/src/test/run-pass/const-rec-and-tup.rs b/src/test/run-pass/const-rec-and-tup.rs index 557fa427e4383..31b806bf41a1b 100644 --- a/src/test/run-pass/const-rec-and-tup.rs +++ b/src/test/run-pass/const-rec-and-tup.rs @@ -20,6 +20,6 @@ static y : AnotherPair = AnotherPair{ x: (0xf0f0f0f0_f0f0f0f0, pub fn main() { let (p, _) = y.x; - assert!(p == - 1085102592571150096); - io::println(fmt!("0x%x", p as uint)); + assert_eq!(p, - 1085102592571150096); + println(fmt!("0x%x", p as uint)); } diff --git a/src/test/run-pass/const-region-ptrs-noncopy.rs b/src/test/run-pass/const-region-ptrs-noncopy.rs index b8812649fd1c1..3eaf733d784c0 100644 --- a/src/test/run-pass/const-region-ptrs-noncopy.rs +++ b/src/test/run-pass/const-region-ptrs-noncopy.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::ptr; + type Big = [u64, ..8]; struct Pair<'self> { a: int, b: &'self Big } static x: &'static Big = &([13, 14, 10, 13, 11, 14, 14, 15]); static y: &'static Pair<'static> = &Pair {a: 15, b: x}; pub fn main() { - assert!(ptr::to_unsafe_ptr(x) == ptr::to_unsafe_ptr(y.b)); + assert_eq!(ptr::to_unsafe_ptr(x), ptr::to_unsafe_ptr(y.b)); } diff --git a/src/test/run-pass/const-region-ptrs.rs b/src/test/run-pass/const-region-ptrs.rs index a2bedc85cdd4d..cdc71292ae069 100644 --- a/src/test/run-pass/const-region-ptrs.rs +++ b/src/test/run-pass/const-region-ptrs.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::io; struct Pair<'self> { a: int, b: &'self int } @@ -18,6 +19,6 @@ static y: &'static Pair<'static> = &Pair {a: 15, b: x}; pub fn main() { io::println(fmt!("x = %?", *x)); io::println(fmt!("y = {a: %?, b: %?}", y.a, *(y.b))); - assert!(*x == 10); - assert!(*(y.b) == 10); + assert_eq!(*x, 10); + assert_eq!(*(y.b), 10); } diff --git a/src/test/run-pass/const-str-ptr.rs b/src/test/run-pass/const-str-ptr.rs index 2f98036a5b172..2f0cd3c611f62 100644 --- a/src/test/run-pass/const-str-ptr.rs +++ b/src/test/run-pass/const-str-ptr.rs @@ -8,15 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::str; + static a: [u8, ..3] = ['h' as u8, 'i' as u8, 0 as u8]; static c: &'static [u8, ..3] = &a; static b: *u8 = c as *u8; pub fn main() { let foo = &a as *u8; - assert!(unsafe { str::raw::from_bytes(a) } == ~"hi\x00"); - assert!(unsafe { str::raw::from_buf(foo) } == ~"hi"); - assert!(unsafe { str::raw::from_buf(b) } == ~"hi"); + assert_eq!(unsafe { str::raw::from_bytes(a) }, ~"hi\x00"); + assert_eq!(unsafe { str::raw::from_buf(foo) }, ~"hi"); + assert_eq!(unsafe { str::raw::from_buf(b) }, ~"hi"); assert!(unsafe { *b == a[0] }); assert!(unsafe { *(&c[0] as *u8) == a[0] }); } diff --git a/src/test/run-pass/const-struct-offsets.rs b/src/test/run-pass/const-struct-offsets.rs new file mode 100644 index 0000000000000..0966fa055bfdd --- /dev/null +++ b/src/test/run-pass/const-struct-offsets.rs @@ -0,0 +1,14 @@ +enum Foo { + IntVal(i32), + Int64Val(i64) +} + +struct Bar { + i: i32, + v: Foo +} + +static bar: Bar = Bar { i: 0, v: IntVal(0) }; + +fn main() {} + diff --git a/src/test/run-pass/const-struct.rs b/src/test/run-pass/const-struct.rs index f75b4321e9025..8a93a3e4c1ccb 100644 --- a/src/test/run-pass/const-struct.rs +++ b/src/test/run-pass/const-struct.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::cmp; +use std::io; struct foo { a: int, b: int, c: int } @@ -25,9 +27,9 @@ static y : foo = foo { b:2, c:3, a: 1 }; static z : &'static foo = &foo { a: 10, b: 22, c: 12 }; pub fn main() { - assert!(x.b == 2); - assert!(x == y); - assert!(z.b == 22); + assert_eq!(x.b, 2); + assert_eq!(x, y); + assert_eq!(z.b, 22); io::println(fmt!("0x%x", x.b as uint)); io::println(fmt!("0x%x", z.c as uint)); } diff --git a/src/test/run-pass/const-tuple-struct.rs b/src/test/run-pass/const-tuple-struct.rs index 828c20912a1cb..54116dd4082ed 100644 --- a/src/test/run-pass/const-tuple-struct.rs +++ b/src/test/run-pass/const-tuple-struct.rs @@ -15,8 +15,8 @@ static X: Bar = Bar(1, 2); pub fn main() { match X { Bar(x, y) => { - assert!(x == 1); - assert!(y == 2); + assert_eq!(x, 1); + assert_eq!(y, 2); } } } diff --git a/src/test/run-pass/const-vecs-and-slices.rs b/src/test/run-pass/const-vecs-and-slices.rs index 517ced302dd8b..0aee53a4ed2d2 100644 --- a/src/test/run-pass/const-vecs-and-slices.rs +++ b/src/test/run-pass/const-vecs-and-slices.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::io; + static x : [int, ..4] = [1,2,3,4]; static y : &'static [int] = &[1,2,3,4]; pub fn main() { io::println(fmt!("%?", x[1])); io::println(fmt!("%?", y[1])); - assert!(x[1] == 2); - assert!(x[3] == 4); - assert!(x[3] == y[3]); + assert_eq!(x[1], 2); + assert_eq!(x[3], 4); + assert_eq!(x[3], y[3]); } diff --git a/src/test/run-pass/consts-in-patterns.rs b/src/test/run-pass/consts-in-patterns.rs index c0520cf737ffc..788c30562c182 100644 --- a/src/test/run-pass/consts-in-patterns.rs +++ b/src/test/run-pass/consts-in-patterns.rs @@ -18,5 +18,5 @@ pub fn main() { BAR => 2, _ => 3 }; - assert!(y == 2); + assert_eq!(y, 2); } diff --git a/src/test/run-pass/core-export-f64-sqrt.rs b/src/test/run-pass/core-export-f64-sqrt.rs index d7ac91fe75c32..3a683bc7cb92c 100644 --- a/src/test/run-pass/core-export-f64-sqrt.rs +++ b/src/test/run-pass/core-export-f64-sqrt.rs @@ -10,9 +10,12 @@ // Regression test that f64 exports things properly +use std::f64; +use std::float; + pub fn main() { let digits: uint = 10 as uint; - ::core::io::println(float::to_str_digits(f64::sqrt(42.0f64) as float, digits)); + println(float::to_str_digits(f64::sqrt(42.0f64) as float, digits)); } diff --git a/src/test/auxiliary/mod_trait_with_static_methods_lib.rs b/src/test/run-pass/core-rt-smoke.rs similarity index 67% rename from src/test/auxiliary/mod_trait_with_static_methods_lib.rs rename to src/test/run-pass/core-rt-smoke.rs index b060c7aee49a2..5873e7c746028 100644 --- a/src/test/auxiliary/mod_trait_with_static_methods_lib.rs +++ b/src/test/run-pass/core-rt-smoke.rs @@ -8,15 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub use sub_foo::Foo; +// xfail-fast -pub mod sub_foo { - pub trait Foo { - pub fn foo() -> Self; - } +// A simple test of starting the runtime manually - impl Foo for int { - pub fn foo() -> int { 42 } +#[start] +fn start(argc: int, argv: **u8, crate_map: *u8) -> int { + do std::rt::start(argc, argv, crate_map) { + debug!("creating my own runtime is joy"); } } - diff --git a/src/test/run-pass/core-run-destroy.rs b/src/test/run-pass/core-run-destroy.rs index a4f3f59f46baa..81cdb926e5f96 100644 --- a/src/test/run-pass/core-run-destroy.rs +++ b/src/test/run-pass/core-run-destroy.rs @@ -13,20 +13,23 @@ // NB: These tests kill child processes. Valgrind sees these children as leaking // memory, which makes for some *confusing* logs. That's why these are here -// instead of in core. +// instead of in std. -use core::run; -use core::run::*; +use std::libc; +use std::os; +use std::run::*; +use std::run; +use std::str; #[test] fn test_destroy_once() { - let mut p = run::start_program("echo", []); + let mut p = run::Process::new("echo", [], run::ProcessOptions::new()); p.destroy(); // this shouldn't crash (and nor should the destructor) } #[test] fn test_destroy_twice() { - let mut p = run::start_program("echo", []); + let mut p = run::Process::new("echo", [], run::ProcessOptions::new()); p.destroy(); // this shouldnt crash... p.destroy(); // ...and nor should this (and nor should the destructor) } @@ -41,15 +44,16 @@ fn test_destroy_actually_kills(force: bool) { #[cfg(unix)] fn process_exists(pid: libc::pid_t) -> bool { - run::program_output("ps", [~"-p", pid.to_str()]).out.contains(pid.to_str()) + let run::ProcessOutput {output, _} = run::process_output("ps", [~"-p", pid.to_str()]); + str::from_bytes(output).contains(pid.to_str()) } #[cfg(windows)] fn process_exists(pid: libc::pid_t) -> bool { - use core::libc::types::os::arch::extra::DWORD; - use core::libc::funcs::extra::kernel32::{CloseHandle, GetExitCodeProcess, OpenProcess}; - use core::libc::consts::os::extra::{FALSE, PROCESS_QUERY_INFORMATION, STILL_ACTIVE }; + use std::libc::types::os::arch::extra::DWORD; + use std::libc::funcs::extra::kernel32::{CloseHandle, GetExitCodeProcess, OpenProcess}; + use std::libc::consts::os::extra::{FALSE, PROCESS_QUERY_INFORMATION, STILL_ACTIVE }; unsafe { let proc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid as DWORD); @@ -64,8 +68,8 @@ fn test_destroy_actually_kills(force: bool) { } } - // this program will stay alive indefinitely trying to read from stdin - let mut p = run::start_program(BLOCK_COMMAND, []); + // this process will stay alive indefinitely trying to read from stdin + let mut p = run::Process::new(BLOCK_COMMAND, [], run::ProcessOptions::new()); assert!(process_exists(p.get_id())); diff --git a/src/test/run-pass/crateresolve1.rs b/src/test/run-pass/crateresolve1.rs index 1ddb955cee7bc..737a60470ad3e 100644 --- a/src/test/run-pass/crateresolve1.rs +++ b/src/test/run-pass/crateresolve1.rs @@ -16,5 +16,5 @@ extern mod crateresolve1(vers = "0.2"); pub fn main() { - assert!(crateresolve1::f() == 20); + assert_eq!(crateresolve1::f(), 20); } diff --git a/src/test/run-pass/crateresolve6.rs b/src/test/run-pass/crateresolve6.rs index 0263af5510578..883f48656bcf6 100644 --- a/src/test/run-pass/crateresolve6.rs +++ b/src/test/run-pass/crateresolve6.rs @@ -18,6 +18,6 @@ extern mod cr6_1 (name = "crateresolve_calories", vers = "0.1", calories="100"); extern mod cr6_2 (name = "crateresolve_calories", vers = "0.1", calories="200"); pub fn main() { - assert!(cr6_1::f() == 100); - assert!(cr6_2::f() == 200); + assert_eq!(cr6_1::f(), 100); + assert_eq!(cr6_2::f(), 200); } diff --git a/src/test/run-pass/crateresolve7.rs b/src/test/run-pass/crateresolve7.rs index b54b5a0983fbd..86fc72aa489c6 100644 --- a/src/test/run-pass/crateresolve7.rs +++ b/src/test/run-pass/crateresolve7.rs @@ -16,6 +16,6 @@ extern mod crateresolve7x; pub fn main() { - assert!(crateresolve7x::a::f() == 100); - assert!(crateresolve7x::b::f() == 200); + assert_eq!(crateresolve7x::a::f(), 100); + assert_eq!(crateresolve7x::b::f(), 200); } diff --git a/src/test/run-pass/default-method-simple.rs b/src/test/run-pass/default-method-simple.rs index 3f44f3f1ef88c..378852d81503f 100644 --- a/src/test/run-pass/default-method-simple.rs +++ b/src/test/run-pass/default-method-simple.rs @@ -12,7 +12,7 @@ trait Foo { fn f(&self) { - io::println("Hello!"); + println("Hello!"); self.g(); } fn g(&self); @@ -24,7 +24,7 @@ struct A { impl Foo for A { fn g(&self) { - io::println("Goodbye!"); + println("Goodbye!"); } } diff --git a/src/test/run-pass/deriving-cmp-generic-enum.rs b/src/test/run-pass/deriving-cmp-generic-enum.rs index a2651ddac3d19..e3cca832b75e4 100644 --- a/src/test/run-pass/deriving-cmp-generic-enum.rs +++ b/src/test/run-pass/deriving-cmp-generic-enum.rs @@ -16,7 +16,11 @@ enum E { } pub fn main() { - let e0 = E0, e11 = E1(1), e12 = E1(2), e21 = E2(1,1), e22 = E2(1, 2); + let e0 = E0; + let e11 = E1(1); + let e12 = E1(2); + let e21 = E2(1, 1); + let e22 = E2(1, 2); // in order for both Ord and TotalOrd let es = [e0, e11, e12, e21, e22]; @@ -26,8 +30,10 @@ pub fn main() { let ord = i.cmp(&j); let eq = i == j; - let lt = i < j, le = i <= j; - let gt = i > j, ge = i >= j; + let lt = i < j; + let le = i <= j; + let gt = i > j; + let ge = i >= j; // Eq assert_eq!(*e1 == *e2, eq); diff --git a/src/test/run-pass/deriving-cmp-generic-struct.rs b/src/test/run-pass/deriving-cmp-generic-struct.rs index bd3e02ba29b30..4e49ecb8991f5 100644 --- a/src/test/run-pass/deriving-cmp-generic-struct.rs +++ b/src/test/run-pass/deriving-cmp-generic-struct.rs @@ -15,7 +15,8 @@ struct S { } pub fn main() { - let s1 = S {x: 1, y: 1}, s2 = S {x: 1, y: 2}; + let s1 = S {x: 1, y: 1}; + let s2 = S {x: 1, y: 2}; // in order for both Ord and TotalOrd let ss = [s1, s2]; @@ -25,8 +26,10 @@ pub fn main() { let ord = i.cmp(&j); let eq = i == j; - let lt = i < j, le = i <= j; - let gt = i > j, ge = i >= j; + let lt = i < j; + let le = i <= j; + let gt = i > j; + let ge = i >= j; // Eq assert_eq!(*s1 == *s2, eq); @@ -46,4 +49,4 @@ pub fn main() { assert_eq!(s1.cmp(s2), ord); } } -} \ No newline at end of file +} diff --git a/src/test/run-pass/deriving-cmp-generic-tuple-struct.rs b/src/test/run-pass/deriving-cmp-generic-tuple-struct.rs index 733b19a9ae2da..f119b8b1c48e1 100644 --- a/src/test/run-pass/deriving-cmp-generic-tuple-struct.rs +++ b/src/test/run-pass/deriving-cmp-generic-tuple-struct.rs @@ -13,7 +13,8 @@ struct TS(T,T); pub fn main() { - let ts1 = TS(1, 1), ts2 = TS(1,2); + let ts1 = TS(1, 1); + let ts2 = TS(1, 2); // in order for both Ord and TotalOrd let tss = [ts1, ts2]; @@ -23,8 +24,10 @@ pub fn main() { let ord = i.cmp(&j); let eq = i == j; - let lt = i < j, le = i <= j; - let gt = i > j, ge = i >= j; + let lt = i < j; + let le = i <= j; + let gt = i > j; + let ge = i >= j; // Eq assert_eq!(*ts1 == *ts2, eq); @@ -44,4 +47,4 @@ pub fn main() { assert_eq!(ts1.cmp(ts2), ord); } } -} \ No newline at end of file +} diff --git a/src/test/run-pass/deriving-encodable-decodable.rs b/src/test/run-pass/deriving-encodable-decodable.rs new file mode 100644 index 0000000000000..fa672581238fe --- /dev/null +++ b/src/test/run-pass/deriving-encodable-decodable.rs @@ -0,0 +1,77 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// This actually tests a lot more than just encodable/decodable, but it gets the +// job done at least + +// xfail-fast + +extern mod extra; + +use std::io; +use std::rand::{random, Rand}; +use extra::serialize::*; +use extra::ebml; +use extra::ebml::writer::Encoder; +use extra::ebml::reader::Decoder; + +#[deriving(Encodable, Decodable, Eq, Rand)] +struct A; +#[deriving(Encodable, Decodable, Eq, Rand)] +struct B(int); +#[deriving(Encodable, Decodable, Eq, Rand)] +struct C(int, int, uint); + +#[deriving(Encodable, Decodable, Eq, Rand)] +struct D { + a: int, + b: uint, +} + +#[deriving(Encodable, Decodable, Eq, Rand)] +enum E { + E1, + E2(uint), + E3(D), + E4{ x: uint }, +} + +#[deriving(Encodable, Decodable, Eq, Rand)] +enum F { F1 } + +#[deriving(Encodable, Decodable, Eq, Rand)] +struct G { + t: T +} + +fn roundtrip + Decodable>() { + let obj: T = random(); + let bytes = do io::with_bytes_writer |w| { + let mut e = Encoder(w); + obj.encode(&mut e); + }; + let doc = ebml::reader::Doc(@bytes); + let mut dec = Decoder(doc); + let obj2 = Decodable::decode(&mut dec); + assert!(obj == obj2); +} + +pub fn main() { + roundtrip::(); + roundtrip::(); + roundtrip::(); + roundtrip::(); + + for 20.times { + roundtrip::(); + roundtrip::(); + roundtrip::>(); + } +} diff --git a/src/test/run-pass/deriving-meta-multiple.rs b/src/test/run-pass/deriving-meta-multiple.rs index d94b6fcb41584..f0b2d2ec827bb 100644 --- a/src/test/run-pass/deriving-meta-multiple.rs +++ b/src/test/run-pass/deriving-meta-multiple.rs @@ -19,7 +19,7 @@ struct Foo { } pub fn main() { - use core::hash::{Hash, HashUtil}; // necessary for IterBytes check + use std::hash::{Hash, HashUtil}; // necessary for IterBytes check let a = Foo {bar: 4, baz: -3}; diff --git a/src/test/run-pass/deriving-meta.rs b/src/test/run-pass/deriving-meta.rs index efb202028f3b9..aef671ba757aa 100644 --- a/src/test/run-pass/deriving-meta.rs +++ b/src/test/run-pass/deriving-meta.rs @@ -17,7 +17,7 @@ struct Foo { } pub fn main() { - use core::hash::{Hash, HashUtil}; // necessary for IterBytes check + use std::hash::{Hash, HashUtil}; // necessary for IterBytes check let a = Foo {bar: 4, baz: -3}; diff --git a/src/test/run-pass/deriving-rand.rs b/src/test/run-pass/deriving-rand.rs index dd4664e7446fb..193bb1628ef56 100644 --- a/src/test/run-pass/deriving-rand.rs +++ b/src/test/run-pass/deriving-rand.rs @@ -9,6 +9,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::rand; + #[deriving(Rand)] struct A; @@ -36,4 +38,4 @@ fn main() { rand::random::(); rand::random::(); } -} \ No newline at end of file +} diff --git a/src/test/run-pass/deriving-self-lifetime-totalord-totaleq.rs b/src/test/run-pass/deriving-self-lifetime-totalord-totaleq.rs index b0b03d8419b8c..2d42088fc140a 100644 --- a/src/test/run-pass/deriving-self-lifetime-totalord-totaleq.rs +++ b/src/test/run-pass/deriving-self-lifetime-totalord-totaleq.rs @@ -10,7 +10,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::cmp::{Less,Equal,Greater}; +use std::cmp::{Less,Equal,Greater}; #[deriving(TotalEq,TotalOrd)] struct A<'self> { diff --git a/src/test/run-pass/deriving-self-lifetime.rs b/src/test/run-pass/deriving-self-lifetime.rs index 549a9b398a219..e65e189ea93cf 100644 --- a/src/test/run-pass/deriving-self-lifetime.rs +++ b/src/test/run-pass/deriving-self-lifetime.rs @@ -14,7 +14,8 @@ struct A<'self> { } fn main() { - let a = A { x: &1 }, b = A { x: &2 }; + let a = A { x: &1 }; + let b = A { x: &2 }; assert_eq!(a, a); assert_eq!(b, b); diff --git a/src/test/run-pass/deriving-to-str.rs b/src/test/run-pass/deriving-to-str.rs index 4b98f9a73c586..fcf0a009d9b24 100644 --- a/src/test/run-pass/deriving-to-str.rs +++ b/src/test/run-pass/deriving-to-str.rs @@ -9,6 +9,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::rand; + #[deriving(Rand,ToStr)] struct A; @@ -42,4 +44,4 @@ fn main() { t!(C); t!(D); } -} \ No newline at end of file +} diff --git a/src/test/run-pass/deriving-via-extension-c-enum.rs b/src/test/run-pass/deriving-via-extension-c-enum.rs index 81c4ce013f24c..3c4fb6c8c81b1 100644 --- a/src/test/run-pass/deriving-via-extension-c-enum.rs +++ b/src/test/run-pass/deriving-via-extension-c-enum.rs @@ -18,7 +18,7 @@ enum Foo { pub fn main() { let a = Bar; let b = Bar; - assert!(a == b); + assert_eq!(a, b); assert!(!(a != b)); assert!(a.eq(&b)); assert!(!a.ne(&b)); diff --git a/src/test/run-pass/deriving-via-extension-enum.rs b/src/test/run-pass/deriving-via-extension-enum.rs index fac0d402a3826..4044c58dc5711 100644 --- a/src/test/run-pass/deriving-via-extension-enum.rs +++ b/src/test/run-pass/deriving-via-extension-enum.rs @@ -17,7 +17,7 @@ enum Foo { pub fn main() { let a = Bar(1, 2); let b = Bar(1, 2); - assert!(a == b); + assert_eq!(a, b); assert!(!(a != b)); assert!(a.eq(&b)); assert!(!a.ne(&b)); diff --git a/src/test/run-pass/deriving-via-extension-struct-empty.rs b/src/test/run-pass/deriving-via-extension-struct-empty.rs index 00b0c14369e04..8f6a319798626 100644 --- a/src/test/run-pass/deriving-via-extension-struct-empty.rs +++ b/src/test/run-pass/deriving-via-extension-struct-empty.rs @@ -12,6 +12,6 @@ struct Foo; pub fn main() { - assert!(Foo == Foo); + assert_eq!(Foo, Foo); assert!(!(Foo != Foo)); } \ No newline at end of file diff --git a/src/test/run-pass/deriving-via-extension-struct-like-enum-variant.rs b/src/test/run-pass/deriving-via-extension-struct-like-enum-variant.rs index 4ef8fb6b5d9b7..5189136c4863f 100644 --- a/src/test/run-pass/deriving-via-extension-struct-like-enum-variant.rs +++ b/src/test/run-pass/deriving-via-extension-struct-like-enum-variant.rs @@ -6,6 +6,6 @@ enum S { pub fn main() { let x = X { x: 1, y: 2 }; - assert!(x == x); + assert_eq!(x, x); assert!(!(x != x)); } diff --git a/src/test/run-pass/deriving-via-extension-struct-tuple.rs b/src/test/run-pass/deriving-via-extension-struct-tuple.rs index 906d69dbf5375..cc76751e27f4b 100644 --- a/src/test/run-pass/deriving-via-extension-struct-tuple.rs +++ b/src/test/run-pass/deriving-via-extension-struct-tuple.rs @@ -17,10 +17,10 @@ pub fn main() { let b = Foo(5, 7, ~"def"); assert!(a1 == a1); - assert!(a1 == a2); + assert!(a2 == a1); assert!(!(a1 == b)); assert!(a1 != b); assert!(!(a1 != a1)); - assert!(!(a1 != a2)); + assert!(!(a2 != a1)); } diff --git a/src/test/run-pass/deriving-via-extension-struct.rs b/src/test/run-pass/deriving-via-extension-struct.rs index c0e7ee36b16da..44aca59aa9c07 100644 --- a/src/test/run-pass/deriving-via-extension-struct.rs +++ b/src/test/run-pass/deriving-via-extension-struct.rs @@ -18,7 +18,7 @@ struct Foo { pub fn main() { let a = Foo { x: 1, y: 2, z: 3 }; let b = Foo { x: 1, y: 2, z: 3 }; - assert!(a == b); + assert_eq!(a, b); assert!(!(a != b)); assert!(a.eq(&b)); assert!(!a.ne(&b)); diff --git a/src/test/run-pass/deriving-via-extension-type-params.rs b/src/test/run-pass/deriving-via-extension-type-params.rs index 85a89c629895d..ecc30555162ac 100644 --- a/src/test/run-pass/deriving-via-extension-type-params.rs +++ b/src/test/run-pass/deriving-via-extension-type-params.rs @@ -21,7 +21,7 @@ struct Foo { pub fn main() { let a = Foo { x: 1, y: 2.0, z: 3 }; let b = Foo { x: 1, y: 2.0, z: 3 }; - assert!(a == b); + assert_eq!(a, b); assert!(!(a != b)); assert!(a.eq(&b)); assert!(!a.ne(&b)); diff --git a/src/test/run-pass/div-mod.rs b/src/test/run-pass/div-mod.rs index bf1d6e3c06006..3aeaef01e189b 100644 --- a/src/test/run-pass/div-mod.rs +++ b/src/test/run-pass/div-mod.rs @@ -15,14 +15,14 @@ pub fn main() { let x: int = 15; let y: int = 5; - assert!((x / 5 == 3)); - assert!((x / 4 == 3)); - assert!((x / 3 == 5)); - assert!((x / y == 3)); - assert!((15 / y == 3)); - assert!((x % 5 == 0)); - assert!((x % 4 == 3)); - assert!((x % 3 == 0)); - assert!((x % y == 0)); - assert!((15 % y == 0)); + assert_eq!(x / 5, 3); + assert_eq!(x / 4, 3); + assert_eq!(x / 3, 5); + assert_eq!(x / y, 3); + assert_eq!(15 / y, 3); + assert_eq!(x % 5, 0); + assert_eq!(x % 4, 3); + assert_eq!(x % 3, 0); + assert_eq!(x % y, 0); + assert_eq!(15 % y, 0); } diff --git a/src/test/run-pass/do2.rs b/src/test/run-pass/do2.rs index ee1321e9d0048..684a2c108eb81 100644 --- a/src/test/run-pass/do2.rs +++ b/src/test/run-pass/do2.rs @@ -11,5 +11,5 @@ fn f(f: @fn(int) -> int) -> int { f(10) } pub fn main() { - assert!(do f() |i| { i } == 10); + assert_eq!(do f() |i| { i }, 10); } diff --git a/src/test/run-pass/do3.rs b/src/test/run-pass/do3.rs index 7cbf49a34862d..b0d49fd2bdd92 100644 --- a/src/test/run-pass/do3.rs +++ b/src/test/run-pass/do3.rs @@ -11,5 +11,5 @@ fn f(f: @fn(int) -> int) -> int { f(10) } pub fn main() { - assert!(do f |i| { i } == 10); + assert_eq!(do f |i| { i }, 10); } diff --git a/src/test/run-pass/drop-trait-generic.rs b/src/test/run-pass/drop-trait-generic.rs index 65c3faac2b304..894c387b036fa 100644 --- a/src/test/run-pass/drop-trait-generic.rs +++ b/src/test/run-pass/drop-trait-generic.rs @@ -13,9 +13,9 @@ struct S { } #[unsafe_destructor] -impl ::core::ops::Drop for S { +impl ::std::ops::Drop for S { fn finalize(&self) { - io::println("bye"); + println("bye"); } } diff --git a/src/test/run-pass/drop-trait.rs b/src/test/run-pass/drop-trait.rs index b516c6f6de4bd..258a0f88ab52a 100644 --- a/src/test/run-pass/drop-trait.rs +++ b/src/test/run-pass/drop-trait.rs @@ -14,7 +14,7 @@ struct Foo { impl Drop for Foo { fn finalize(&self) { - io::println("bye"); + println("bye"); } } diff --git a/src/test/run-pass/duplicate-use.rs b/src/test/run-pass/duplicate-use.rs index f81b33105e63e..35d5d2ffe8a31 100644 --- a/src/test/run-pass/duplicate-use.rs +++ b/src/test/run-pass/duplicate-use.rs @@ -9,10 +9,10 @@ // except according to those terms. // xfail-test -extern mod std; +extern mod extra; -use list = std::oldmap::chained; -use std::list; +use list = extra::oldmap::chained; +use extra::list; pub fn main() { let _x: list::T = list::mk(); diff --git a/src/test/run-pass/early-vtbl-resolution.rs b/src/test/run-pass/early-vtbl-resolution.rs index 58b192e839b38..57f4a41fee94b 100644 --- a/src/test/run-pass/early-vtbl-resolution.rs +++ b/src/test/run-pass/early-vtbl-resolution.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::old_iter; trait thing { fn foo(&self) -> Option; diff --git a/src/test/run-pass/empty-tag.rs b/src/test/run-pass/empty-tag.rs index f1b89f2bb1d3b..7b9046318ab43 100644 --- a/src/test/run-pass/empty-tag.rs +++ b/src/test/run-pass/empty-tag.rs @@ -10,7 +10,7 @@ enum chan { chan_t, } -impl cmp::Eq for chan { +impl Eq for chan { fn eq(&self, other: &chan) -> bool { ((*self) as uint) == ((*other) as uint) } @@ -18,7 +18,7 @@ impl cmp::Eq for chan { } fn wrapper3(i: chan) { - assert!(i == chan_t); + assert_eq!(i, chan_t); } pub fn main() { diff --git a/src/test/run-pass/enum-alignment.rs b/src/test/run-pass/enum-alignment.rs index cf92515e01028..c23f02e1bedf7 100644 --- a/src/test/run-pass/enum-alignment.rs +++ b/src/test/run-pass/enum-alignment.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::cast; +use std::ptr; +use std::sys; + fn addr_of(ptr: &T) -> uint { let ptr = ptr::to_unsafe_ptr(ptr); unsafe { ptr as uint } @@ -15,7 +19,7 @@ fn addr_of(ptr: &T) -> uint { fn is_aligned(ptr: &T) -> bool { unsafe { - let addr: uint = ::cast::transmute(ptr); + let addr: uint = cast::transmute(ptr); (addr % sys::min_align_of::()) == 0 } } diff --git a/src/test/run-pass/estr-slice.rs b/src/test/run-pass/estr-slice.rs index 27a1b9514139e..a851141322f00 100644 --- a/src/test/run-pass/estr-slice.rs +++ b/src/test/run-pass/estr-slice.rs @@ -17,11 +17,11 @@ pub fn main() { debug!(x); debug!(y); - assert!(x[0] == 'h' as u8); - assert!(x[4] == 'o' as u8); + assert_eq!(x[0], 'h' as u8); + assert_eq!(x[4], 'o' as u8); let z : &str = &"thing"; - assert!(v == x); + assert_eq!(v, x); assert!(x != z); let a = &"aaaa"; diff --git a/src/test/run-pass/estr-uniq.rs b/src/test/run-pass/estr-uniq.rs index 5e23fd0f75166..a096a8456739e 100644 --- a/src/test/run-pass/estr-uniq.rs +++ b/src/test/run-pass/estr-uniq.rs @@ -13,6 +13,6 @@ pub fn main() { let _y : ~str = ~"there"; let mut z = ~"thing"; z = x; - assert!(z[0] == ('h' as u8)); - assert!(z[4] == ('o' as u8)); + assert_eq!(z[0], ('h' as u8)); + assert_eq!(z[4], ('o' as u8)); } diff --git a/src/test/run-pass/evec-internal-boxes.rs b/src/test/run-pass/evec-internal-boxes.rs index 7b51b80313680..64c8a4caf80ae 100644 --- a/src/test/run-pass/evec-internal-boxes.rs +++ b/src/test/run-pass/evec-internal-boxes.rs @@ -13,6 +13,6 @@ pub fn main() { let _y : [@int, ..5] = [@1,@2,@3,@4,@5]; let mut z = [@1,@2,@3,@4,@5]; z = x; - assert!(*z[0] == 1); - assert!(*z[4] == 5); + assert_eq!(*z[0], 1); + assert_eq!(*z[4], 5); } diff --git a/src/test/run-pass/evec-internal.rs b/src/test/run-pass/evec-internal.rs index 39a4397f84e73..6c3dfb2cb3de8 100644 --- a/src/test/run-pass/evec-internal.rs +++ b/src/test/run-pass/evec-internal.rs @@ -18,8 +18,8 @@ pub fn main() { let _y : [int, ..5] = [1,2,3,4,5]; let mut z = [1,2,3,4,5]; z = x; - assert!(z[0] == 1); - assert!(z[4] == 5); + assert_eq!(z[0], 1); + assert_eq!(z[4], 5); let a : [int, ..5] = [1,1,1,1,1]; let b : [int, ..5] = [2,2,2,2,2]; diff --git a/src/test/run-pass/evec-slice.rs b/src/test/run-pass/evec-slice.rs index 28bac56b05e76..194560ab127b1 100644 --- a/src/test/run-pass/evec-slice.rs +++ b/src/test/run-pass/evec-slice.rs @@ -12,8 +12,8 @@ pub fn main() { let x : &[int] = &[1,2,3,4,5]; let mut z = &[1,2,3,4,5]; z = x; - assert!(z[0] == 1); - assert!(z[4] == 5); + assert_eq!(z[0], 1); + assert_eq!(z[4], 5); let a : &[int] = &[1,1,1,1,1]; let b : &[int] = &[2,2,2,2,2]; diff --git a/src/test/run-pass/exec-env.rs b/src/test/run-pass/exec-env.rs index 486186e9fe098..2437946a1f094 100644 --- a/src/test/run-pass/exec-env.rs +++ b/src/test/run-pass/exec-env.rs @@ -11,6 +11,8 @@ // xfail-fast (exec-env not supported in fast mode) // exec-env:TEST_EXEC_ENV=22 +use std::os; + pub fn main() { - assert!(os::getenv(~"TEST_EXEC_ENV") == Some(~"22")); + assert_eq!(os::getenv(~"TEST_EXEC_ENV"), Some(~"22")); } diff --git a/src/test/run-pass/explicit-self-closures.rs b/src/test/run-pass/explicit-self-closures.rs index e019140d1a015..eb62c8a91d242 100644 --- a/src/test/run-pass/explicit-self-closures.rs +++ b/src/test/run-pass/explicit-self-closures.rs @@ -14,11 +14,11 @@ struct Box { x: uint } -pub impl Box { - fn set_many(&mut self, xs: &[uint]) { +impl Box { + pub fn set_many(&mut self, xs: &[uint]) { for xs.each |x| { self.x = *x; } } - fn set_many2(@mut self, xs: &[uint]) { + pub fn set_many2(@mut self, xs: &[uint]) { for xs.each |x| { self.x = *x; } } } diff --git a/src/test/run-pass/explicit-self-generic.rs b/src/test/run-pass/explicit-self-generic.rs index ac19592accf8b..80e16af922847 100644 --- a/src/test/run-pass/explicit-self-generic.rs +++ b/src/test/run-pass/explicit-self-generic.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; +extern mod extra; /** * A function that returns a hash of a value @@ -30,13 +30,13 @@ fn linear_map() -> HashMap { size: 0}) } -pub impl HashMap { - fn len(&mut self) -> uint { +impl HashMap { + pub fn len(&mut self) -> uint { self.size } } pub fn main() { let mut m = ~linear_map::<(),()>(); - assert!(m.len() == 0); + assert_eq!(m.len(), 0); } diff --git a/src/test/run-pass/explicit-self-objects-box.rs b/src/test/run-pass/explicit-self-objects-box.rs index 12a1780e029b1..9010dd34ffedc 100644 --- a/src/test/run-pass/explicit-self-objects-box.rs +++ b/src/test/run-pass/explicit-self-objects-box.rs @@ -18,7 +18,7 @@ struct S { impl Foo for S { fn f(@self) { - assert!(self.x == 3); + assert_eq!(self.x, 3); } } diff --git a/src/test/run-pass/explicit-self-objects-simple.rs b/src/test/run-pass/explicit-self-objects-simple.rs index 814365a835429..6092c386dbb76 100644 --- a/src/test/run-pass/explicit-self-objects-simple.rs +++ b/src/test/run-pass/explicit-self-objects-simple.rs @@ -18,7 +18,7 @@ struct S { impl Foo for S { fn f(&self) { - assert!(self.x == 3); + assert_eq!(self.x, 3); } } diff --git a/src/test/run-pass/explicit-self-objects-uniq.rs b/src/test/run-pass/explicit-self-objects-uniq.rs index dadf53fb9bc6a..69ca98eb018ed 100644 --- a/src/test/run-pass/explicit-self-objects-uniq.rs +++ b/src/test/run-pass/explicit-self-objects-uniq.rs @@ -18,7 +18,7 @@ struct S { impl Foo for S { fn f(~self) { - assert!(self.x == 3); + assert_eq!(self.x, 3); } } diff --git a/src/test/run-pass/explicit-self.rs b/src/test/run-pass/explicit-self.rs index 7e46bf22c4d92..25e404021619e 100644 --- a/src/test/run-pass/explicit-self.rs +++ b/src/test/run-pass/explicit-self.rs @@ -26,10 +26,10 @@ fn compute_area(shape: &shape) -> float { } } -pub impl shape { +impl shape { // self is in the implicit self region - fn select<'r, T>(&self, threshold: float, - a: &'r T, b: &'r T) -> &'r T { + pub fn select<'r, T>(&self, threshold: float, a: &'r T, b: &'r T) + -> &'r T { if compute_area(self) > threshold {a} else {b} } } @@ -54,12 +54,12 @@ fn thing(x: A) -> thing { } } -pub impl thing { - fn foo(@self) -> int { *self.x.a } - fn bar(~self) -> int { *self.x.a } - fn quux(&self) -> int { *self.x.a } - fn baz<'a>(&'a self) -> &'a A { &self.x } - fn spam(self) -> int { *self.x.a } +impl thing { + pub fn foo(@self) -> int { *self.x.a } + pub fn bar(~self) -> int { *self.x.a } + pub fn quux(&self) -> int { *self.x.a } + pub fn baz<'a>(&'a self) -> &'a A { &self.x } + pub fn spam(self) -> int { *self.x.a } } trait Nus { fn f(&self); } @@ -68,13 +68,13 @@ impl Nus for thing { fn f(&self) {} } pub fn main() { let x = @thing(A {a: @10}); - assert!(x.foo() == 10); - assert!(x.quux() == 10); + assert_eq!(x.foo(), 10); + assert_eq!(x.quux(), 10); let y = ~thing(A {a: @10}); - assert!((copy y).bar() == 10); - assert!(y.quux() == 10); + assert_eq!((copy y).bar(), 10); + assert_eq!(y.quux(), 10); let z = thing(A {a: @11}); - assert!(z.spam() == 11); + assert_eq!(z.spam(), 11); } diff --git a/src/test/run-pass/export-unexported-dep.rs b/src/test/run-pass/export-unexported-dep.rs index ba2a7c6104aba..004761479f379 100644 --- a/src/test/run-pass/export-unexported-dep.rs +++ b/src/test/run-pass/export-unexported-dep.rs @@ -15,7 +15,7 @@ mod foo { // not exported enum t { t1, t2, } - impl cmp::Eq for t { + impl Eq for t { fn eq(&self, other: &t) -> bool { ((*self) as uint) == ((*other) as uint) } diff --git a/src/test/run-pass/expr-block-slot.rs b/src/test/run-pass/expr-block-slot.rs index 0a75d9074c6c2..cfb764e85f8d3 100644 --- a/src/test/run-pass/expr-block-slot.rs +++ b/src/test/run-pass/expr-block-slot.rs @@ -15,7 +15,7 @@ struct V { v: int } pub fn main() { let a = { let b = A {a: 3}; b }; - assert!((a.a == 3)); + assert_eq!(a.a, 3); let c = { let d = V {v: 3}; d }; - assert!((c.v == 3)); + assert_eq!(c.v, 3); } diff --git a/src/test/run-pass/expr-block.rs b/src/test/run-pass/expr-block.rs index ee5d41fdd324b..e43377c71fef1 100644 --- a/src/test/run-pass/expr-block.rs +++ b/src/test/run-pass/expr-block.rs @@ -22,7 +22,7 @@ fn test_rec() { let rs = { RS {v1: 10, v2: 20} }; assert!((rs.v2 == 20)); } fn test_filled_with_stuff() { let rs = { let mut a = 0; while a < 10 { a += 1; } a }; - assert!((rs == 10)); + assert_eq!(rs, 10); } pub fn main() { test_basic(); test_rec(); test_filled_with_stuff(); } diff --git a/src/test/run-pass/expr-copy.rs b/src/test/run-pass/expr-copy.rs index 7dc0f8246bf97..96dab798c83ac 100644 --- a/src/test/run-pass/expr-copy.rs +++ b/src/test/run-pass/expr-copy.rs @@ -19,9 +19,9 @@ struct A { a: int } pub fn main() { let mut x = A {a: 10}; f(&mut x); - assert!(x.a == 100); + assert_eq!(x.a, 100); x.a = 20; let mut y = copy x; f(&mut y); - assert!(x.a == 20); + assert_eq!(x.a, 20); } diff --git a/src/test/run-pass/expr-elseif-ref.rs b/src/test/run-pass/expr-elseif-ref.rs index 831ddfde445ad..b13f7ceba4bfe 100644 --- a/src/test/run-pass/expr-elseif-ref.rs +++ b/src/test/run-pass/expr-elseif-ref.rs @@ -13,5 +13,5 @@ pub fn main() { let y: @uint = @10u; let x = if false { y } else if true { y } else { y }; - assert!((*y == 10u)); + assert_eq!(*y, 10u); } diff --git a/src/test/run-pass/expr-fn.rs b/src/test/run-pass/expr-fn.rs index b7ea721464e6e..e4eae9c4c3996 100644 --- a/src/test/run-pass/expr-fn.rs +++ b/src/test/run-pass/expr-fn.rs @@ -10,32 +10,32 @@ fn test_int() { fn f() -> int { 10 } - assert!((f() == 10)); + assert_eq!(f(), 10); } fn test_vec() { fn f() -> ~[int] { ~[10, 11] } - assert!((f()[1] == 11)); + assert_eq!(f()[1], 11); } fn test_generic() { fn f(t: T) -> T { t } - assert!((f(10) == 10)); + assert_eq!(f(10), 10); } fn test_alt() { fn f() -> int { match true { false => { 10 } true => { 20 } } } - assert!((f() == 20)); + assert_eq!(f(), 20); } fn test_if() { fn f() -> int { if true { 10 } else { 20 } } - assert!((f() == 10)); + assert_eq!(f(), 10); } fn test_block() { fn f() -> int { { 10 } } - assert!((f() == 10)); + assert_eq!(f(), 10); } fn test_ret() { @@ -43,14 +43,14 @@ fn test_ret() { return 10 // no semi } - assert!((f() == 10)); + assert_eq!(f(), 10); } // From issue #372 fn test_372() { fn f() -> int { let x = { 3 }; x } - assert!((f() == 3)); + assert_eq!(f(), 3); } fn test_nil() { () } diff --git a/src/test/run-pass/expr-if-box.rs b/src/test/run-pass/expr-if-box.rs index 004137d065c34..e560da224ff80 100644 --- a/src/test/run-pass/expr-if-box.rs +++ b/src/test/run-pass/expr-if-box.rs @@ -16,12 +16,12 @@ // Tests for if as expressions returning boxed types fn test_box() { let rs = if true { @100 } else { @101 }; - assert!((*rs == 100)); + assert_eq!(*rs, 100); } fn test_str() { let rs = if true { ~"happy" } else { ~"sad" }; - assert!((rs == ~"happy")); + assert_eq!(rs, ~"happy"); } pub fn main() { test_box(); test_str(); } diff --git a/src/test/run-pass/expr-if-fail.rs b/src/test/run-pass/expr-if-fail.rs index 7e2e0badb3662..f79b7198b50e7 100644 --- a/src/test/run-pass/expr-if-fail.rs +++ b/src/test/run-pass/expr-if-fail.rs @@ -12,12 +12,12 @@ fn test_if_fail() { let x = if false { fail!() } else { 10 }; assert!((x == 10)) fn test_else_fail() { let x = if true { 10 } else { fail!() }; - assert!((x == 10)); + assert_eq!(x, 10); } fn test_elseif_fail() { let x = if false { 0 } else if false { fail!() } else { 10 }; - assert!((x == 10)); + assert_eq!(x, 10); } pub fn main() { test_if_fail(); test_else_fail(); test_elseif_fail(); } diff --git a/src/test/run-pass/expr-if-struct.rs b/src/test/run-pass/expr-if-struct.rs index b2bbfcaf9a5ca..00e0fe1f5822e 100644 --- a/src/test/run-pass/expr-if-struct.rs +++ b/src/test/run-pass/expr-if-struct.rs @@ -19,12 +19,12 @@ struct I { i: int } fn test_rec() { let rs = if true { I {i: 100} } else { I {i: 101} }; - assert!((rs.i == 100)); + assert_eq!(rs.i, 100); } enum mood { happy, sad, } -impl cmp::Eq for mood { +impl Eq for mood { fn eq(&self, other: &mood) -> bool { ((*self) as uint) == ((*other) as uint) } @@ -33,7 +33,7 @@ impl cmp::Eq for mood { fn test_tag() { let rs = if true { happy } else { sad }; - assert!((rs == happy)); + assert_eq!(rs, happy); } pub fn main() { test_rec(); test_tag(); } diff --git a/src/test/run-pass/expr-if-unique.rs b/src/test/run-pass/expr-if-unique.rs index 9f90ff32f8379..2271461927109 100644 --- a/src/test/run-pass/expr-if-unique.rs +++ b/src/test/run-pass/expr-if-unique.rs @@ -16,7 +16,7 @@ // Tests for if as expressions returning boxed types fn test_box() { let rs = if true { ~100 } else { ~101 }; - assert!((*rs == 100)); + assert_eq!(*rs, 100); } pub fn main() { test_box(); } diff --git a/src/test/run-pass/expr-alt-box.rs b/src/test/run-pass/expr-match-box.rs similarity index 93% rename from src/test/run-pass/expr-alt-box.rs rename to src/test/run-pass/expr-match-box.rs index 2e65bb8665583..84a78637187fc 100644 --- a/src/test/run-pass/expr-alt-box.rs +++ b/src/test/run-pass/expr-match-box.rs @@ -16,13 +16,13 @@ // Tests for match as expressions resulting in boxed types fn test_box() { let res = match true { true => { @100 } _ => fail!("wat") }; - assert!((*res == 100)); + assert_eq!(*res, 100); } fn test_str() { let res = match true { true => { ~"happy" }, _ => fail!("not happy at all") }; - assert!((res == ~"happy")); + assert_eq!(res, ~"happy"); } pub fn main() { test_box(); test_str(); } diff --git a/src/test/run-pass/expr-alt-fail-all.rs b/src/test/run-pass/expr-match-fail-all.rs similarity index 100% rename from src/test/run-pass/expr-alt-fail-all.rs rename to src/test/run-pass/expr-match-fail-all.rs diff --git a/src/test/run-pass/expr-alt-fail.rs b/src/test/run-pass/expr-match-fail.rs similarity index 92% rename from src/test/run-pass/expr-alt-fail.rs rename to src/test/run-pass/expr-match-fail.rs index 4391856230fe9..3e1b96763e196 100644 --- a/src/test/run-pass/expr-alt-fail.rs +++ b/src/test/run-pass/expr-match-fail.rs @@ -10,12 +10,12 @@ fn test_simple() { let r = match true { true => { true } false => { fail!() } }; - assert!((r == true)); + assert_eq!(r, true); } fn test_box() { let r = match true { true => { ~[10] } false => { fail!() } }; - assert!((r[0] == 10)); + assert_eq!(r[0], 10); } pub fn main() { test_simple(); test_box(); } diff --git a/src/test/run-pass/expr-alt-generic-box1.rs b/src/test/run-pass/expr-match-generic-box1.rs similarity index 100% rename from src/test/run-pass/expr-alt-generic-box1.rs rename to src/test/run-pass/expr-match-generic-box1.rs diff --git a/src/test/run-pass/expr-alt-generic-box2.rs b/src/test/run-pass/expr-match-generic-box2.rs similarity index 100% rename from src/test/run-pass/expr-alt-generic-box2.rs rename to src/test/run-pass/expr-match-generic-box2.rs diff --git a/src/test/run-pass/expr-alt-generic-unique1.rs b/src/test/run-pass/expr-match-generic-unique1.rs similarity index 100% rename from src/test/run-pass/expr-alt-generic-unique1.rs rename to src/test/run-pass/expr-match-generic-unique1.rs diff --git a/src/test/run-pass/expr-alt-generic-unique2.rs b/src/test/run-pass/expr-match-generic-unique2.rs similarity index 100% rename from src/test/run-pass/expr-alt-generic-unique2.rs rename to src/test/run-pass/expr-match-generic-unique2.rs diff --git a/src/test/run-pass/expr-alt-generic.rs b/src/test/run-pass/expr-match-generic.rs similarity index 100% rename from src/test/run-pass/expr-alt-generic.rs rename to src/test/run-pass/expr-match-generic.rs diff --git a/src/test/run-pass/expr-alt-struct.rs b/src/test/run-pass/expr-match-struct.rs similarity index 92% rename from src/test/run-pass/expr-alt-struct.rs rename to src/test/run-pass/expr-match-struct.rs index a8cacca4fe812..7cfcc38f8dd31 100644 --- a/src/test/run-pass/expr-alt-struct.rs +++ b/src/test/run-pass/expr-match-struct.rs @@ -18,12 +18,12 @@ struct R { i: int } fn test_rec() { let rs = match true { true => R {i: 100}, _ => fail!() }; - assert!((rs.i == 100)); + assert_eq!(rs.i, 100); } enum mood { happy, sad, } -impl cmp::Eq for mood { +impl Eq for mood { fn eq(&self, other: &mood) -> bool { ((*self) as uint) == ((*other) as uint) } @@ -32,7 +32,7 @@ impl cmp::Eq for mood { fn test_tag() { let rs = match true { true => { happy } false => { sad } }; - assert!((rs == happy)); + assert_eq!(rs, happy); } pub fn main() { test_rec(); test_tag(); } diff --git a/src/test/run-pass/expr-alt-unique.rs b/src/test/run-pass/expr-match-unique.rs similarity index 95% rename from src/test/run-pass/expr-alt-unique.rs rename to src/test/run-pass/expr-match-unique.rs index dd20840db575e..cdd4e45877ad6 100644 --- a/src/test/run-pass/expr-alt-unique.rs +++ b/src/test/run-pass/expr-match-unique.rs @@ -16,7 +16,7 @@ // Tests for match as expressions resulting in boxed types fn test_box() { let res = match true { true => { ~100 }, _ => fail!() }; - assert!((*res == 100)); + assert_eq!(*res, 100); } pub fn main() { test_box(); } diff --git a/src/test/run-pass/expr-alt.rs b/src/test/run-pass/expr-match.rs similarity index 100% rename from src/test/run-pass/expr-alt.rs rename to src/test/run-pass/expr-match.rs diff --git a/src/test/run-pass/expr-repeat-vstore.rs b/src/test/run-pass/expr-repeat-vstore.rs index e48abc5753492..5758793602209 100644 --- a/src/test/run-pass/expr-repeat-vstore.rs +++ b/src/test/run-pass/expr-repeat-vstore.rs @@ -1,4 +1,4 @@ -use core::io::println; +use std::io::println; fn main() { let v: ~[int] = ~[ 1, ..5 ]; diff --git a/src/test/run-pass/exterior.rs b/src/test/run-pass/exterior.rs index eef0924f487e4..409fec5656c80 100644 --- a/src/test/run-pass/exterior.rs +++ b/src/test/run-pass/exterior.rs @@ -19,8 +19,8 @@ fn f(p: @mut Point) { assert!((p.z == 12)); p.z = 13; assert!((p.z == 13)); } pub fn main() { let a: Point = Point {x: 10, y: 11, z: 12}; let b: @mut Point = @mut copy a; - assert!((b.z == 12)); + assert_eq!(b.z, 12); f(b); - assert!((a.z == 12)); - assert!((b.z == 13)); + assert_eq!(a.z, 12); + assert_eq!(b.z, 13); } diff --git a/src/test/run-pass/extern-call-deep.rs b/src/test/run-pass/extern-call-deep.rs index c29eb2613ad21..9a50c2ceb02c2 100644 --- a/src/test/run-pass/extern-call-deep.rs +++ b/src/test/run-pass/extern-call-deep.rs @@ -8,10 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::libc; + mod rustrt { + use std::libc; + pub extern { pub fn rust_dbg_call(cb: *u8, data: libc::uintptr_t) - -> libc::uintptr_t; + -> libc::uintptr_t; } } @@ -33,5 +37,5 @@ fn count(n: uint) -> uint { pub fn main() { let result = count(1000u); debug!("result = %?", result); - assert!(result == 1000u); + assert_eq!(result, 1000u); } diff --git a/src/test/run-pass/extern-call-deep2.rs b/src/test/run-pass/extern-call-deep2.rs index 4e807f0f169ec..c4ccf645be4f4 100644 --- a/src/test/run-pass/extern-call-deep2.rs +++ b/src/test/run-pass/extern-call-deep2.rs @@ -8,10 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::libc; +use std::task; + mod rustrt { + use std::libc; + pub extern { pub fn rust_dbg_call(cb: *u8, data: libc::uintptr_t) - -> libc::uintptr_t; + -> libc::uintptr_t; } } @@ -36,6 +41,6 @@ pub fn main() { do task::spawn { let result = count(1000u); debug!("result = %?", result); - assert!(result == 1000u); + assert_eq!(result, 1000u); }; } diff --git a/src/test/run-pass/extern-call-scrub.rs b/src/test/run-pass/extern-call-scrub.rs index eafdd3c5e9946..e0f352a81efa0 100644 --- a/src/test/run-pass/extern-call-scrub.rs +++ b/src/test/run-pass/extern-call-scrub.rs @@ -12,10 +12,15 @@ // make sure the stack pointers are maintained properly in both // directions +use std::libc; +use std::task; + mod rustrt { + use std::libc; + pub extern { pub fn rust_dbg_call(cb: *u8, data: libc::uintptr_t) - -> libc::uintptr_t; + -> libc::uintptr_t; } } @@ -40,6 +45,6 @@ pub fn main() { do task::spawn { let result = count(12u); debug!("result = %?", result); - assert!(result == 2048u); + assert_eq!(result, 2048u); }; } diff --git a/src/test/run-pass/extern-call.rs b/src/test/run-pass/extern-call.rs index 37e531eaa8e60..4c36090015b89 100644 --- a/src/test/run-pass/extern-call.rs +++ b/src/test/run-pass/extern-call.rs @@ -8,7 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::libc; + mod rustrt { + use std::libc; + pub extern { pub fn rust_dbg_call(cb: *u8, data: libc::uintptr_t) -> libc::uintptr_t; @@ -33,5 +37,5 @@ fn fact(n: uint) -> uint { pub fn main() { let result = fact(10u); debug!("result = %?", result); - assert!(result == 3628800u); + assert_eq!(result, 3628800u); } diff --git a/src/test/run-pass/extern-crosscrate.rs b/src/test/run-pass/extern-crosscrate.rs index de7dd7e4c8c1d..eb21e19954962 100644 --- a/src/test/run-pass/extern-crosscrate.rs +++ b/src/test/run-pass/extern-crosscrate.rs @@ -23,5 +23,5 @@ fn fact(n: uint) -> uint { pub fn main() { let result = fact(10u); debug!("result = %?", result); - assert!(result == 3628800u); + assert_eq!(result, 3628800u); } diff --git a/src/test/run-pass/extern-mod-syntax.rs b/src/test/run-pass/extern-mod-syntax.rs index c98b5ebc23854..b78f607792b8f 100644 --- a/src/test/run-pass/extern-mod-syntax.rs +++ b/src/test/run-pass/extern-mod-syntax.rs @@ -10,9 +10,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; -use std::json::Object; +extern mod extra; +use extra::json::Object; pub fn main() { - io::println("Hello world!"); + println("Hello world!"); } diff --git a/src/test/run-pass/extern-mod-url.rs b/src/test/run-pass/extern-mod-url.rs new file mode 100644 index 0000000000000..457c61067e3c2 --- /dev/null +++ b/src/test/run-pass/extern-mod-url.rs @@ -0,0 +1,16 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Just a test that new-style extern mods parse + +// xfail-test +extern mod test = "github.com/catamorphism/test-pkg"; + +fn main() {} \ No newline at end of file diff --git a/src/test/run-pass/extern-pass-TwoU16s.rs b/src/test/run-pass/extern-pass-TwoU16s.rs index ec65cbb5670b9..1ff4cd0053b35 100644 --- a/src/test/run-pass/extern-pass-TwoU16s.rs +++ b/src/test/run-pass/extern-pass-TwoU16s.rs @@ -26,6 +26,6 @@ pub fn main() { unsafe { let x = TwoU16s {one: 22, two: 23}; let y = rust_dbg_extern_identity_TwoU16s(x); - assert!(x == y); + assert_eq!(x, y); } } diff --git a/src/test/run-pass/extern-pass-TwoU32s.rs b/src/test/run-pass/extern-pass-TwoU32s.rs index 6ac5967c54fd5..362fb6b5b2220 100644 --- a/src/test/run-pass/extern-pass-TwoU32s.rs +++ b/src/test/run-pass/extern-pass-TwoU32s.rs @@ -24,6 +24,6 @@ pub fn main() { unsafe { let x = TwoU32s {one: 22, two: 23}; let y = rust_dbg_extern_identity_TwoU32s(x); - assert!(x == y); + assert_eq!(x, y); } } diff --git a/src/test/run-pass/extern-pass-TwoU64s-ref.rs b/src/test/run-pass/extern-pass-TwoU64s-ref.rs index 19b99eaccc956..6479714e0040a 100644 --- a/src/test/run-pass/extern-pass-TwoU64s-ref.rs +++ b/src/test/run-pass/extern-pass-TwoU64s-ref.rs @@ -23,6 +23,6 @@ pub fn main() { unsafe { let x = TwoU64s {one: 22, two: 23}; let y = rust_dbg_extern_identity_TwoU64s(x); - assert!(x == y); + assert_eq!(x, y); } } diff --git a/src/test/run-pass/extern-pass-TwoU64s.rs b/src/test/run-pass/extern-pass-TwoU64s.rs index cd6226b61c984..246012d65322e 100644 --- a/src/test/run-pass/extern-pass-TwoU64s.rs +++ b/src/test/run-pass/extern-pass-TwoU64s.rs @@ -28,6 +28,6 @@ pub fn main() { unsafe { let x = TwoU64s {one: 22, two: 23}; let y = rust_dbg_extern_identity_TwoU64s(x); - assert!(x == y); + assert_eq!(x, y); } } diff --git a/src/test/run-pass/extern-pass-TwoU8s.rs b/src/test/run-pass/extern-pass-TwoU8s.rs index 7d08b436908dc..01052bd0084f0 100644 --- a/src/test/run-pass/extern-pass-TwoU8s.rs +++ b/src/test/run-pass/extern-pass-TwoU8s.rs @@ -26,6 +26,6 @@ pub fn main() { unsafe { let x = TwoU8s {one: 22, two: 23}; let y = rust_dbg_extern_identity_TwoU8s(x); - assert!(x == y); + assert_eq!(x, y); } } diff --git a/src/test/run-pass/extern-pass-char.rs b/src/test/run-pass/extern-pass-char.rs index 645396e5a988d..37e2795904335 100644 --- a/src/test/run-pass/extern-pass-char.rs +++ b/src/test/run-pass/extern-pass-char.rs @@ -16,6 +16,6 @@ pub extern { pub fn main() { unsafe { - assert!(22_u8 == rust_dbg_extern_identity_u8(22_u8)); + assert_eq!(22_u8, rust_dbg_extern_identity_u8(22_u8)); } } diff --git a/src/test/run-pass/extern-pass-double.rs b/src/test/run-pass/extern-pass-double.rs index 3a6dd26a9dc6c..2812068d69d60 100644 --- a/src/test/run-pass/extern-pass-double.rs +++ b/src/test/run-pass/extern-pass-double.rs @@ -14,6 +14,6 @@ pub extern { pub fn main() { unsafe { - assert!(22.0_f64 == rust_dbg_extern_identity_double(22.0_f64)); + assert_eq!(22.0_f64, rust_dbg_extern_identity_double(22.0_f64)); } } diff --git a/src/test/run-pass/extern-pass-u32.rs b/src/test/run-pass/extern-pass-u32.rs index 19c4d6e153998..4f2633f680f06 100644 --- a/src/test/run-pass/extern-pass-u32.rs +++ b/src/test/run-pass/extern-pass-u32.rs @@ -16,6 +16,6 @@ pub extern { pub fn main() { unsafe { - assert!(22_u32 == rust_dbg_extern_identity_u32(22_u32)); + assert_eq!(22_u32, rust_dbg_extern_identity_u32(22_u32)); } } diff --git a/src/test/run-pass/extern-pass-u64.rs b/src/test/run-pass/extern-pass-u64.rs index cce669999222a..2215a3d95fc73 100644 --- a/src/test/run-pass/extern-pass-u64.rs +++ b/src/test/run-pass/extern-pass-u64.rs @@ -16,6 +16,6 @@ pub extern { pub fn main() { unsafe { - assert!(22_u64 == rust_dbg_extern_identity_u64(22_u64)); + assert_eq!(22_u64, rust_dbg_extern_identity_u64(22_u64)); } } diff --git a/src/test/run-pass/extern-pub.rs b/src/test/run-pass/extern-pub.rs index 1cd709ee91b9d..29b0457fc0507 100644 --- a/src/test/run-pass/extern-pub.rs +++ b/src/test/run-pass/extern-pub.rs @@ -1,3 +1,7 @@ +use std::libc; +use std::sys; +use std::vec; + extern { pub unsafe fn vec_reserve_shared_actual(t: *sys::TypeDesc, v: **vec::raw::VecRepr, diff --git a/src/test/run-pass/extern-return-TwoU16s.rs b/src/test/run-pass/extern-return-TwoU16s.rs index f87b27e1f62d9..3a345099bad0a 100644 --- a/src/test/run-pass/extern-return-TwoU16s.rs +++ b/src/test/run-pass/extern-return-TwoU16s.rs @@ -22,7 +22,7 @@ pub extern { pub fn main() { unsafe { let y = rust_dbg_extern_return_TwoU16s(); - assert!(y.one == 10); - assert!(y.two == 20); + assert_eq!(y.one, 10); + assert_eq!(y.two, 20); } } diff --git a/src/test/run-pass/extern-return-TwoU32s.rs b/src/test/run-pass/extern-return-TwoU32s.rs index 9e374687855b0..788754bfb0022 100644 --- a/src/test/run-pass/extern-return-TwoU32s.rs +++ b/src/test/run-pass/extern-return-TwoU32s.rs @@ -19,7 +19,7 @@ pub extern { pub fn main() { unsafe { let y = rust_dbg_extern_return_TwoU32s(); - assert!(y.one == 10); - assert!(y.two == 20); + assert_eq!(y.one, 10); + assert_eq!(y.two, 20); } } diff --git a/src/test/run-pass/extern-return-TwoU64s.rs b/src/test/run-pass/extern-return-TwoU64s.rs index 250d3b8f562b0..9243c285901b1 100644 --- a/src/test/run-pass/extern-return-TwoU64s.rs +++ b/src/test/run-pass/extern-return-TwoU64s.rs @@ -19,7 +19,7 @@ pub extern { pub fn main() { unsafe { let y = rust_dbg_extern_return_TwoU64s(); - assert!(y.one == 10); - assert!(y.two == 20); + assert_eq!(y.one, 10); + assert_eq!(y.two, 20); } } diff --git a/src/test/run-pass/extern-return-TwoU8s.rs b/src/test/run-pass/extern-return-TwoU8s.rs index 008e153769a64..c1f897e79b00b 100644 --- a/src/test/run-pass/extern-return-TwoU8s.rs +++ b/src/test/run-pass/extern-return-TwoU8s.rs @@ -22,7 +22,7 @@ pub extern { pub fn main() { unsafe { let y = rust_dbg_extern_return_TwoU8s(); - assert!(y.one == 10); - assert!(y.two == 20); + assert_eq!(y.one, 10); + assert_eq!(y.two, 20); } } diff --git a/src/test/run-pass/extern-stress.rs b/src/test/run-pass/extern-stress.rs index 0b640c8c62360..9da4dffffc214 100644 --- a/src/test/run-pass/extern-stress.rs +++ b/src/test/run-pass/extern-stress.rs @@ -11,10 +11,15 @@ // This creates a bunch of yielding tasks that run concurrently // while holding onto C stacks +use std::libc; +use std::task; + mod rustrt { + use std::libc; + pub extern { pub fn rust_dbg_call(cb: *u8, data: libc::uintptr_t) - -> libc::uintptr_t; + -> libc::uintptr_t; } } @@ -34,9 +39,9 @@ fn count(n: uint) -> uint { } pub fn main() { - for old_iter::repeat(100u) { + for 100u.times { do task::spawn { - assert!(count(5u) == 16u); + assert_eq!(count(5u), 16u); }; } } diff --git a/src/test/run-pass/extern-take-value.rs b/src/test/run-pass/extern-take-value.rs index c3815cf2a67f6..542686c9099f1 100644 --- a/src/test/run-pass/extern-take-value.rs +++ b/src/test/run-pass/extern-take-value.rs @@ -20,6 +20,6 @@ pub fn main() { let b: *u8 = f; let c: *u8 = g; - assert!(a == b); + assert_eq!(a, b); assert!(a != c); } diff --git a/src/test/run-pass/extern-yield.rs b/src/test/run-pass/extern-yield.rs index bde3f5dd52ff6..75e259a38c130 100644 --- a/src/test/run-pass/extern-yield.rs +++ b/src/test/run-pass/extern-yield.rs @@ -8,10 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::libc; +use std::task; + mod rustrt { + use std::libc; + pub extern { pub fn rust_dbg_call(cb: *u8, data: libc::uintptr_t) - -> libc::uintptr_t; + -> libc::uintptr_t; } } @@ -31,11 +36,11 @@ fn count(n: uint) -> uint { } pub fn main() { - for old_iter::repeat(10u) { + for 10u.times { do task::spawn { let result = count(5u); debug!("result = %?", result); - assert!(result == 16u); + assert_eq!(result, 16u); }; } } diff --git a/src/test/run-pass/fact.rs b/src/test/run-pass/fact.rs index ec82db8644c55..cbcf9a6bef4fa 100644 --- a/src/test/run-pass/fact.rs +++ b/src/test/run-pass/fact.rs @@ -32,7 +32,7 @@ fn f(x: int) -> int { } pub fn main() { - assert!((f(5) == 120)); + assert_eq!(f(5), 120); // debug!("all done"); } diff --git a/src/test/run-pass/fat-arrow-alt.rs b/src/test/run-pass/fat-arrow-match.rs similarity index 100% rename from src/test/run-pass/fat-arrow-alt.rs rename to src/test/run-pass/fat-arrow-match.rs diff --git a/src/test/run-pass/filter-block-view-items.rs b/src/test/run-pass/filter-block-view-items.rs new file mode 100644 index 0000000000000..4286183371799 --- /dev/null +++ b/src/test/run-pass/filter-block-view-items.rs @@ -0,0 +1,15 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + // Make sure that this view item is filtered out because otherwise it would + // trigger a compilation error + #[cfg(not_present)] use foo = bar; +} diff --git a/src/test/run-pass/fixed-point-bind-box.rs b/src/test/run-pass/fixed-point-bind-box.rs index 76b2309085aba..4c28151224c6d 100644 --- a/src/test/run-pass/fixed-point-bind-box.rs +++ b/src/test/run-pass/fixed-point-bind-box.rs @@ -25,6 +25,6 @@ fn fact_(f: @fn(v: int) -> int, n: int) -> int { pub fn main() { let fact = fix(fact_); - assert!((fact(5) == 120)); - assert!((fact(2) == 2)); + assert_eq!(fact(5), 120); + assert_eq!(fact(2), 2); } diff --git a/src/test/run-pass/fixed-point-bind-unique.rs b/src/test/run-pass/fixed-point-bind-unique.rs index 83060baac51a3..53f9c723a4738 100644 --- a/src/test/run-pass/fixed-point-bind-unique.rs +++ b/src/test/run-pass/fixed-point-bind-unique.rs @@ -25,6 +25,6 @@ fn fact_(f: @fn(v: int) -> int, n: int) -> int { pub fn main() { let fact = fix(fact_); - assert!((fact(5) == 120)); - assert!((fact(2) == 2)); + assert_eq!(fact(5), 120); + assert_eq!(fact(2), 2); } diff --git a/src/test/run-pass/fixed_length_copy.rs b/src/test/run-pass/fixed_length_copy.rs index 7ee3f5173b030..ead8e5ea1044c 100644 --- a/src/test/run-pass/fixed_length_copy.rs +++ b/src/test/run-pass/fixed_length_copy.rs @@ -15,6 +15,6 @@ pub fn main() { let arr = [1,2,3]; let arr2 = arr; - assert!((arr[1] == 2)); - assert!((arr2[2] == 3)); + assert_eq!(arr[1], 2); + assert_eq!(arr2[2], 3); } diff --git a/src/test/run-pass/fixed_length_vec_glue.rs b/src/test/run-pass/fixed_length_vec_glue.rs index b3ced135a4faf..d026f041250b5 100644 --- a/src/test/run-pass/fixed_length_vec_glue.rs +++ b/src/test/run-pass/fixed_length_vec_glue.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::sys; + struct Struc { a: u8, b: [int, ..3], c: int } pub fn main() { let arr = [1,2,3]; let struc = Struc {a: 13u8, b: arr, c: 42}; let s = sys::log_str(&struc); - assert!((s == ~"{a: 13, b: [1, 2, 3], c: 42}")); + assert_eq!(s, ~"{a: 13, b: [1, 2, 3], c: 42}"); } diff --git a/src/test/run-pass/float-literal-inference.rs b/src/test/run-pass/float-literal-inference.rs index a5246eef0b0ed..d2c872c05345a 100644 --- a/src/test/run-pass/float-literal-inference.rs +++ b/src/test/run-pass/float-literal-inference.rs @@ -14,9 +14,9 @@ struct S { pub fn main() { let x: f32 = 4.0; - io::println(x.to_str()); + println(x.to_str()); let y: float = 64.0; - io::println(y.to_str()); + println(y.to_str()); let z = S { z: 1.0 }; - io::println(z.z.to_str()); + println(z.z.to_str()); } diff --git a/src/test/run-pass/float-nan.rs b/src/test/run-pass/float-nan.rs index 08523de3ccd81..29a180db1855d 100644 --- a/src/test/run-pass/float-nan.rs +++ b/src/test/run-pass/float-nan.rs @@ -8,18 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; +extern mod extra; -use core::num::Float::{ - NaN, infinity, neg_infinity -}; +use std::num::Float; pub fn main() { - let nan = NaN::(); + let nan = Float::NaN::(); assert!((nan).is_NaN()); - let inf = infinity::(); - assert!(-inf == neg_infinity::()); + let inf = Float::infinity::(); + assert_eq!(-inf, Float::neg_infinity::()); assert!( nan != nan); assert!( nan != -nan); @@ -36,17 +34,17 @@ pub fn main() { assert!( inf != nan); assert!(-inf != nan); - assert!(!( nan == nan)); + assert!(!( nan == nan)); assert!(!( nan == -nan)); - assert!(!( nan == 1.)); - assert!(!( nan == 0.)); - assert!(!( nan == inf)); + assert!(!( nan == 1.)); + assert!(!( nan == 0.)); + assert!(!( nan == inf)); assert!(!( nan == -inf)); - assert!(!( 1. == nan)); - assert!(!( 0. == nan)); - assert!(!( inf == nan)); - assert!(!(-inf == nan)); - assert!(!(-nan == nan)); + assert!(!( 1. == nan)); + assert!(!( 0. == nan)); + assert!(!( inf == nan)); + assert!(!(-inf == nan)); + assert!(!(-nan == nan)); assert!(!(-nan == -nan)); assert!(!( nan > nan)); diff --git a/src/test/run-pass/float2.rs b/src/test/run-pass/float2.rs index d84c4930aa209..713d863029c7c 100644 --- a/src/test/run-pass/float2.rs +++ b/src/test/run-pass/float2.rs @@ -22,13 +22,13 @@ pub fn main() { let i = 1.0E7f64; let j = 3.1e+9; let k = 3.2e-10; - assert!((a == b)); + assert_eq!(a, b); assert!((c < b)); - assert!((c == d)); + assert_eq!(c, d); assert!((e < g)); assert!((f < h)); - assert!((g == 1000000.0f32)); - assert!((h == i)); + assert_eq!(g, 1000000.0f32); + assert_eq!(h, i); assert!((j > k)); assert!((k < a)); } diff --git a/src/test/run-pass/fn-assign-managed-to-bare-1.rs b/src/test/run-pass/fn-assign-managed-to-bare-1.rs index 3a6d448667897..dece77595bcd9 100644 --- a/src/test/run-pass/fn-assign-managed-to-bare-1.rs +++ b/src/test/run-pass/fn-assign-managed-to-bare-1.rs @@ -14,7 +14,7 @@ fn add(n: int) -> @fn(int) -> int { } pub fn main() { - assert!(add(3)(4) == 7); + assert_eq!(add(3)(4), 7); let add3 : &fn(int)->int = add(3); - assert!(add3(4) == 7); + assert_eq!(add3(4), 7); } diff --git a/src/test/run-pass/fn-assign-managed-to-bare-2.rs b/src/test/run-pass/fn-assign-managed-to-bare-2.rs index c7b7770d81fef..f8daacfa2337a 100644 --- a/src/test/run-pass/fn-assign-managed-to-bare-2.rs +++ b/src/test/run-pass/fn-assign-managed-to-bare-2.rs @@ -15,14 +15,14 @@ fn add(n: int) -> @fn(int) -> int { pub fn main() { - assert!(add(3)(4) == 7); + assert_eq!(add(3)(4), 7); let add1 : @fn(int)->int = add(1); - assert!(add1(6) == 7); + assert_eq!(add1(6), 7); let add2 : &(@fn(int)->int) = &add(2); - assert!((*add2)(5) == 7); + assert_eq!((*add2)(5), 7); let add3 : &fn(int)->int = add(3); - assert!(add3(4) == 7); + assert_eq!(add3(4), 7); } diff --git a/src/test/run-pass/fn-bare-assign.rs b/src/test/run-pass/fn-bare-assign.rs index 7ad7d24df596a..7c8fbd2989f76 100644 --- a/src/test/run-pass/fn-bare-assign.rs +++ b/src/test/run-pass/fn-bare-assign.rs @@ -9,7 +9,7 @@ // except according to those terms. fn f(i: int, called: &mut bool) { - assert!(i == 10); + assert_eq!(i, 10); *called = true; } @@ -21,5 +21,5 @@ pub fn main() { let mut called = false; let h = f; g(h, &mut called); - assert!(called == true); + assert_eq!(called, true); } diff --git a/src/test/run-pass/fn-bare-size.rs b/src/test/run-pass/fn-bare-size.rs index 424d829b5ea7b..dc47dda420cea 100644 --- a/src/test/run-pass/fn-bare-size.rs +++ b/src/test/run-pass/fn-bare-size.rs @@ -10,7 +10,7 @@ // xfail-test -extern mod std; +extern mod extra; pub fn main() { // Bare functions should just be a pointer diff --git a/src/test/run-pass/fn-bare-spawn.rs b/src/test/run-pass/fn-bare-spawn.rs index b78bd488bc6ea..4f0f451a08c09 100644 --- a/src/test/run-pass/fn-bare-spawn.rs +++ b/src/test/run-pass/fn-bare-spawn.rs @@ -15,7 +15,7 @@ fn spawn(val: T, f: extern fn(T)) { } fn f(i: int) { - assert!(i == 100); + assert_eq!(i, 100); } pub fn main() { diff --git a/src/test/run-pass/fn-pattern-expected-type-2.rs b/src/test/run-pass/fn-pattern-expected-type-2.rs index 501bd81d5589c..ee1e73110243e 100644 --- a/src/test/run-pass/fn-pattern-expected-type-2.rs +++ b/src/test/run-pass/fn-pattern-expected-type-2.rs @@ -11,7 +11,7 @@ pub fn main() { let v : &[(int,int)] = &[ (1, 2), (3, 4), (5, 6) ]; for v.each |&(x, y)| { - io::println(y.to_str()); - io::println(x.to_str()); + println(y.to_str()); + println(x.to_str()); } } diff --git a/src/test/run-pass/fn-pattern-expected-type.rs b/src/test/run-pass/fn-pattern-expected-type.rs index f3949a0f43bf3..450e2a70aab9b 100644 --- a/src/test/run-pass/fn-pattern-expected-type.rs +++ b/src/test/run-pass/fn-pattern-expected-type.rs @@ -10,8 +10,8 @@ pub fn main() { let f: &fn((int,int)) = |(x, y)| { - assert!(x == 1); - assert!(y == 2); + assert_eq!(x, 1); + assert_eq!(y, 2); }; f((1, 2)); } diff --git a/src/test/run-pass/for-destruct.rs b/src/test/run-pass/for-destruct.rs index 4c5084d9f1e21..4926dbd008670 100644 --- a/src/test/run-pass/for-destruct.rs +++ b/src/test/run-pass/for-destruct.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::vec; + struct Pair { x: int, y: int } pub fn main() { for vec::each(~[Pair {x: 10, y: 20}, Pair {x: 30, y: 0}]) |elt| { - assert!((elt.x + elt.y == 30)); + assert_eq!(elt.x + elt.y, 30); } } diff --git a/src/test/run-pass/foreach-nested.rs b/src/test/run-pass/foreach-nested.rs index b180e50202345..6987e2cf97d70 100644 --- a/src/test/run-pass/foreach-nested.rs +++ b/src/test/run-pass/foreach-nested.rs @@ -20,8 +20,8 @@ pub fn main() { do two |i| { do two |j| { a[p] = 10 * i + j; p += 1; } } - assert!((a[0] == 0)); - assert!((a[1] == 1)); - assert!((a[2] == 10)); - assert!((a[3] == 11)); + assert_eq!(a[0], 0); + assert_eq!(a[1], 1); + assert_eq!(a[2], 10); + assert_eq!(a[3], 11); } diff --git a/src/test/run-pass/foreach-put-structured.rs b/src/test/run-pass/foreach-put-structured.rs index 421ee7ff2b0f4..d52842b4101ee 100644 --- a/src/test/run-pass/foreach-put-structured.rs +++ b/src/test/run-pass/foreach-put-structured.rs @@ -23,9 +23,9 @@ pub fn main() { let (_0, _1) = p; debug!(_0); debug!(_1); - assert!((_0 + 10 == i)); + assert_eq!(_0 + 10, i); i += 1; j = _1; }; - assert!((j == 45)); + assert_eq!(j, 45); } diff --git a/src/test/run-pass/foreach-simple-outer-slot.rs b/src/test/run-pass/foreach-simple-outer-slot.rs index 99848ddfc7b48..c3120c44c3715 100644 --- a/src/test/run-pass/foreach-simple-outer-slot.rs +++ b/src/test/run-pass/foreach-simple-outer-slot.rs @@ -17,7 +17,7 @@ pub fn main() { do first_ten |i| { debug!("main"); debug!(i); sum = sum + i; } debug!("sum"); debug!(sum); - assert!((sum == 45)); + assert_eq!(sum, 45); } fn first_ten(it: &fn(int)) { diff --git a/src/test/run-pass/foreign-call-no-runtime.rs b/src/test/run-pass/foreign-call-no-runtime.rs index 08cb8db5131ff..e9bf17a037ae5 100644 --- a/src/test/run-pass/foreign-call-no-runtime.rs +++ b/src/test/run-pass/foreign-call-no-runtime.rs @@ -1,8 +1,9 @@ -use core::unstable::run_in_bare_thread; +use std::cast; +use std::libc; +use std::unstable::run_in_bare_thread; extern { - pub fn rust_dbg_call(cb: *u8, - data: libc::uintptr_t) -> libc::uintptr_t; + pub fn rust_dbg_call(cb: *u8, data: libc::uintptr_t) -> libc::uintptr_t; } pub fn main() { @@ -19,6 +20,6 @@ pub fn main() { extern fn callback(data: libc::uintptr_t) { unsafe { let data: *int = cast::transmute(data); - assert!(*data == 100); + assert_eq!(*data, 100); } } diff --git a/src/test/run-pass/foreign-dupe.rs b/src/test/run-pass/foreign-dupe.rs index fe1d5e1200d3c..200610e0dfe8d 100644 --- a/src/test/run-pass/foreign-dupe.rs +++ b/src/test/run-pass/foreign-dupe.rs @@ -12,6 +12,8 @@ // calling pin_task and that's having wierd side-effects. mod rustrt1 { + use std::libc; + #[abi = "cdecl"] #[link_name = "rustrt"] pub extern { @@ -20,6 +22,8 @@ mod rustrt1 { } mod rustrt2 { + use std::libc; + #[abi = "cdecl"] #[link_name = "rustrt"] pub extern { diff --git a/src/test/run-pass/foreign-fn-linkname.rs b/src/test/run-pass/foreign-fn-linkname.rs index 429e78b9c2194..27b0c90379108 100644 --- a/src/test/run-pass/foreign-fn-linkname.rs +++ b/src/test/run-pass/foreign-fn-linkname.rs @@ -8,7 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; +extern mod extra; + +use std::libc; +use std::str; +use std::vec; mod libc { #[nolink] @@ -29,5 +33,5 @@ fn strlen(str: ~str) -> uint { pub fn main() { let len = strlen(~"Rust"); - assert!((len == 4u)); + assert_eq!(len, 4u); } diff --git a/src/test/run-pass/foreign-lib-path.rs b/src/test/run-pass/foreign-lib-path.rs index 61fc709d94933..bfa1e79a26fb0 100644 --- a/src/test/run-pass/foreign-lib-path.rs +++ b/src/test/run-pass/foreign-lib-path.rs @@ -22,5 +22,5 @@ mod WHATGOESHERE { } pub fn main() { - assert!(IDONTKNOW() == 0x_BAD_DOOD_u32); + assert_eq!(IDONTKNOW(), 0x_BAD_DOOD_u32); } diff --git a/src/test/run-pass/foreign-no-abi.rs b/src/test/run-pass/foreign-no-abi.rs index 67959be866ed4..76ce562584483 100644 --- a/src/test/run-pass/foreign-no-abi.rs +++ b/src/test/run-pass/foreign-no-abi.rs @@ -11,6 +11,8 @@ // ABI is cdecl by default mod rustrt { + use std::libc; + pub extern { pub fn get_task_id() -> libc::intptr_t; } diff --git a/src/test/run-pass/foreign2.rs b/src/test/run-pass/foreign2.rs index f83d21e17149c..2745ae4014b41 100644 --- a/src/test/run-pass/foreign2.rs +++ b/src/test/run-pass/foreign2.rs @@ -24,8 +24,8 @@ mod libc { #[abi = "cdecl"] #[nolink] pub extern { - pub fn write(fd: int, buf: *u8, count: ::core::libc::size_t) - -> ::core::libc::ssize_t; + pub fn write(fd: int, buf: *u8, count: ::std::libc::size_t) + -> ::std::libc::ssize_t; } } diff --git a/src/test/run-pass/fun-call-variants.rs b/src/test/run-pass/fun-call-variants.rs index c2baab090db9d..52e6a4649a8dc 100644 --- a/src/test/run-pass/fun-call-variants.rs +++ b/src/test/run-pass/fun-call-variants.rs @@ -17,5 +17,5 @@ pub fn main() { let a: int = direct(3); // direct let b: int = ho(direct); // indirect unbound - assert!((a == b)); + assert_eq!(a, b); } diff --git a/src/test/run-pass/fun-indirect-call.rs b/src/test/run-pass/fun-indirect-call.rs index db39850e74edb..738752924c3c9 100644 --- a/src/test/run-pass/fun-indirect-call.rs +++ b/src/test/run-pass/fun-indirect-call.rs @@ -17,5 +17,5 @@ fn f() -> int { return 42; } pub fn main() { let g: extern fn() -> int = f; let i: int = g(); - assert!((i == 42)); + assert_eq!(i, 42); } diff --git a/src/test/run-pass/functional-struct-update.rs b/src/test/run-pass/functional-struct-update.rs index 297b5e78a921c..6d95f6b23ab35 100644 --- a/src/test/run-pass/functional-struct-update.rs +++ b/src/test/run-pass/functional-struct-update.rs @@ -16,5 +16,5 @@ struct Foo { pub fn main() { let a = Foo { x: 1, y: 2 }; let c = Foo { x: 4, .. a}; - io::println(fmt!("%?", c)); + println(fmt!("%?", c)); } diff --git a/src/test/run-pass/generic-alias-box.rs b/src/test/run-pass/generic-alias-box.rs index e5aa54534db1f..bce65161921b6 100644 --- a/src/test/run-pass/generic-alias-box.rs +++ b/src/test/run-pass/generic-alias-box.rs @@ -16,5 +16,5 @@ pub fn main() { let expected = @100; let actual = id::<@int>(expected); debug!(*actual); - assert!((*expected == *actual)); + assert_eq!(*expected, *actual); } diff --git a/src/test/run-pass/generic-alias-unique.rs b/src/test/run-pass/generic-alias-unique.rs index 5eb91b317404b..ad271186639bd 100644 --- a/src/test/run-pass/generic-alias-unique.rs +++ b/src/test/run-pass/generic-alias-unique.rs @@ -16,5 +16,5 @@ pub fn main() { let expected = ~100; let actual = id::<~int>(expected.clone()); debug!(*actual); - assert!((*expected == *actual)); + assert_eq!(*expected, *actual); } diff --git a/src/test/run-pass/generic-box.rs b/src/test/run-pass/generic-box.rs index 0506256459529..7248e5770698f 100644 --- a/src/test/run-pass/generic-box.rs +++ b/src/test/run-pass/generic-box.rs @@ -16,5 +16,5 @@ struct Box {x: T, y: T, z: T} pub fn main() { let x: @Box = box::(Box{x: 1, y: 2, z: 3}); - assert!((x.y == 2)); + assert_eq!(x.y, 2); } diff --git a/src/test/run-pass/generic-derived-type.rs b/src/test/run-pass/generic-derived-type.rs index 747acca903ba2..9e266a3f20804 100644 --- a/src/test/run-pass/generic-derived-type.rs +++ b/src/test/run-pass/generic-derived-type.rs @@ -24,6 +24,6 @@ pub fn main() { let b = f::(10); debug!(b.a); debug!(b.b); - assert!((b.a == 10)); - assert!((b.b == 10)); + assert_eq!(b.a, 10); + assert_eq!(b.b, 10); } diff --git a/src/test/run-pass/generic-exterior-box.rs b/src/test/run-pass/generic-exterior-box.rs index 7708ffad3678a..79ee544d49555 100644 --- a/src/test/run-pass/generic-exterior-box.rs +++ b/src/test/run-pass/generic-exterior-box.rs @@ -17,5 +17,5 @@ fn reclift(t: T) -> Recbox { return Recbox {x: @t}; } pub fn main() { let foo: int = 17; let rbfoo: Recbox = reclift::(foo); - assert!((*rbfoo.x == foo)); + assert_eq!(*rbfoo.x, foo); } diff --git a/src/test/run-pass/generic-exterior-unique.rs b/src/test/run-pass/generic-exterior-unique.rs index 693b83f1102be..cc94fca680408 100644 --- a/src/test/run-pass/generic-exterior-unique.rs +++ b/src/test/run-pass/generic-exterior-unique.rs @@ -15,5 +15,5 @@ fn reclift(t: T) -> Recbox { return Recbox {x: ~t}; } pub fn main() { let foo: int = 17; let rbfoo: Recbox = reclift::(foo); - assert!((*rbfoo.x == foo)); + assert_eq!(*rbfoo.x, foo); } diff --git a/src/test/run-pass/generic-fn.rs b/src/test/run-pass/generic-fn.rs index 8108e15ee148c..bcacccee820be 100644 --- a/src/test/run-pass/generic-fn.rs +++ b/src/test/run-pass/generic-fn.rs @@ -25,13 +25,13 @@ pub fn main() { let mut q: Triple = Triple {x: 68, y: 69, z: 70}; y = id::(x); debug!(y); - assert!((x == y)); + assert_eq!(x, y); b = id::(a); debug!(b); - assert!((a == b)); + assert_eq!(a, b); q = id::(p); x = p.z; y = q.z; debug!(y); - assert!((x == y)); + assert_eq!(x, y); } diff --git a/src/test/run-pass/generic-newtype-struct.rs b/src/test/run-pass/generic-newtype-struct.rs index cf4279d67b84d..541f9460bc0f1 100644 --- a/src/test/run-pass/generic-newtype-struct.rs +++ b/src/test/run-pass/generic-newtype-struct.rs @@ -2,5 +2,5 @@ struct S(T); pub fn main() { let s = S(2i); - io::println(s.to_str()); + println(s.to_str()); } diff --git a/src/test/run-pass/generic-object.rs b/src/test/run-pass/generic-object.rs index 54ae2c58e42ea..1e532caaf0487 100644 --- a/src/test/run-pass/generic-object.rs +++ b/src/test/run-pass/generic-object.rs @@ -25,5 +25,5 @@ impl Foo for S { pub fn main() { let x = @S { x: 1 }; let y = x as @Foo; - assert!(y.get() == 1); + assert_eq!(y.get(), 1); } diff --git a/src/test/run-pass/generic-tag-alt.rs b/src/test/run-pass/generic-tag-match.rs similarity index 100% rename from src/test/run-pass/generic-tag-alt.rs rename to src/test/run-pass/generic-tag-match.rs diff --git a/src/test/run-pass/generic-tag-values.rs b/src/test/run-pass/generic-tag-values.rs index 42f19e86fe852..eced9a7074298 100644 --- a/src/test/run-pass/generic-tag-values.rs +++ b/src/test/run-pass/generic-tag-values.rs @@ -24,8 +24,8 @@ pub fn main() { some(t) => { debug!(t.x); debug!(t.y); - assert!((t.x == 17)); - assert!((t.y == 42)); + assert_eq!(t.x, 17); + assert_eq!(t.y, 42); } } } diff --git a/src/test/run-pass/generic-tup.rs b/src/test/run-pass/generic-tup.rs index 212e044dd14fc..485b9a78488e4 100644 --- a/src/test/run-pass/generic-tup.rs +++ b/src/test/run-pass/generic-tup.rs @@ -12,6 +12,6 @@ fn get_third(t: (T, T, T)) -> T { let (_, _, x) = t; return x; } pub fn main() { debug!(get_third((1, 2, 3))); - assert!((get_third((1, 2, 3)) == 3)); - assert!((get_third((5u8, 6u8, 7u8)) == 7u8)); + assert_eq!(get_third((1, 2, 3)), 3); + assert_eq!(get_third((5u8, 6u8, 7u8)), 7u8); } diff --git a/src/test/run-pass/generic-type.rs b/src/test/run-pass/generic-type.rs index 8f9208ea91726..0ff7cedc6c5f1 100644 --- a/src/test/run-pass/generic-type.rs +++ b/src/test/run-pass/generic-type.rs @@ -14,6 +14,6 @@ struct Pair {x: T, y: T} pub fn main() { let x: Pair = Pair {x: 10, y: 12}; - assert!((x.x == 10)); - assert!((x.y == 12)); + assert_eq!(x.x, 10); + assert_eq!(x.y, 12); } diff --git a/src/test/run-pass/generic-unique.rs b/src/test/run-pass/generic-unique.rs index 064e2f5462822..8a4fc94135b9a 100644 --- a/src/test/run-pass/generic-unique.rs +++ b/src/test/run-pass/generic-unique.rs @@ -14,5 +14,5 @@ fn box(x: Triple) -> ~Triple { return ~x; } pub fn main() { let x: ~Triple = box::(Triple{x: 1, y: 2, z: 3}); - assert!((x.y == 2)); + assert_eq!(x.y, 2); } diff --git a/src/test/run-pass/getopts_ref.rs b/src/test/run-pass/getopts_ref.rs index afd018de3bb39..3be685c63896a 100644 --- a/src/test/run-pass/getopts_ref.rs +++ b/src/test/run-pass/getopts_ref.rs @@ -10,18 +10,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; +extern mod extra; -use std::getopts::*; +use extra::getopts::*; pub fn main() { let args = ~[]; let opts = ~[optopt(~"b")]; match getopts(args, opts) { - result::Ok(ref m) => + Ok(ref m) => assert!(!opt_present(m, "b")), - result::Err(ref f) => fail!(fail_str(copy *f)) + Err(ref f) => fail!(fail_str(copy *f)) }; } diff --git a/src/test/run-pass/guards-not-exhaustive.rs b/src/test/run-pass/guards-not-exhaustive.rs index 8f5b288b755dd..4d30fbe15591a 100644 --- a/src/test/run-pass/guards-not-exhaustive.rs +++ b/src/test/run-pass/guards-not-exhaustive.rs @@ -9,5 +9,5 @@ fn xyzzy(q: Q) -> uint { pub fn main() { - assert!(xyzzy(R(Some(5))) == 0); + assert_eq!(xyzzy(R(Some(5))), 0); } diff --git a/src/test/run-pass/guards.rs b/src/test/run-pass/guards.rs index 8654e4a2a4b27..86bff013eefc6 100644 --- a/src/test/run-pass/guards.rs +++ b/src/test/run-pass/guards.rs @@ -13,7 +13,7 @@ struct Pair { x: int, y: int } pub fn main() { let a = match 10 { x if x < 7 => { 1 } x if x < 11 => { 2 } 10 => { 3 } _ => { 4 } }; - assert!((a == 2)); + assert_eq!(a, 2); let b = match Pair {x: 10, y: 20} { @@ -21,5 +21,5 @@ pub fn main() { Pair {x: x, y: y} if x == 10 && y == 20 => { 2 } Pair {x: x, y: y} => { 3 } }; - assert!((b == 2)); + assert_eq!(b, 2); } diff --git a/src/test/run-pass/hashmap-memory.rs b/src/test/run-pass/hashmap-memory.rs index c6ae2047147b1..e731703133248 100644 --- a/src/test/run-pass/hashmap-memory.rs +++ b/src/test/run-pass/hashmap-memory.rs @@ -19,8 +19,10 @@ pub fn map(filename: ~str, emit: map_reduce::putter) { emit(filename, ~"1"); } mod map_reduce { - use core::hashmap::HashMap; - use core::comm::*; + use std::comm::*; + use std::hashmap::HashMap; + use std::str; + use std::task; pub type putter = @fn(~str, ~str); diff --git a/src/test/run-pass/hello.rs b/src/test/run-pass/hello.rs index 84d525dd0e680..93f6c3db2559f 100644 --- a/src/test/run-pass/hello.rs +++ b/src/test/run-pass/hello.rs @@ -9,7 +9,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - pub fn main() { - io::println("hello, world"); + println("hello, world"); } diff --git a/src/test/run-pass/i8-incr.rs b/src/test/run-pass/i8-incr.rs index 9708e04058b8c..799910a6a5fca 100644 --- a/src/test/run-pass/i8-incr.rs +++ b/src/test/run-pass/i8-incr.rs @@ -17,5 +17,5 @@ pub fn main() { let y: i8 = -12i8; x = x + 1i8; x = x - 1i8; - assert!((x == y)); + assert_eq!(x, y); } diff --git a/src/test/run-pass/impl-implicit-trait.rs b/src/test/run-pass/impl-implicit-trait.rs index 10a5661a32468..a33fc4f2e7402 100644 --- a/src/test/run-pass/impl-implicit-trait.rs +++ b/src/test/run-pass/impl-implicit-trait.rs @@ -13,8 +13,8 @@ enum option_ { some_(T), } -pub impl option_ { - fn foo(&self) -> bool { true } +impl option_ { + pub fn foo(&self) -> bool { true } } enum option__ { @@ -22,8 +22,8 @@ enum option__ { some__(int) } -pub impl option__ { - fn foo(&self) -> bool { true } +impl option__ { + pub fn foo(&self) -> bool { true } } pub fn main() { diff --git a/src/test/run-pass/impl-privacy-xc-2.rs b/src/test/run-pass/impl-privacy-xc-2.rs index 74d9a34e1618c..b3e4a4e6711fd 100644 --- a/src/test/run-pass/impl-privacy-xc-2.rs +++ b/src/test/run-pass/impl-privacy-xc-2.rs @@ -6,5 +6,5 @@ extern mod impl_privacy_xc_2; pub fn main() { let fish1 = impl_privacy_xc_2::Fish { x: 1 }; let fish2 = impl_privacy_xc_2::Fish { x: 2 }; - io::println(if fish1.eq(&fish2) { "yes" } else { "no " }); + println(if fish1.eq(&fish2) { "yes" } else { "no " }); } diff --git a/src/test/run-pass/import-glob-crate.rs b/src/test/run-pass/import-glob-crate.rs index a29b1ff0c6984..b036a57e19cb0 100644 --- a/src/test/run-pass/import-glob-crate.rs +++ b/src/test/run-pass/import-glob-crate.rs @@ -11,11 +11,11 @@ // except according to those terms. -extern mod std; -use core::vec::*; +extern mod extra; +use std::vec::*; pub fn main() { let mut v = from_elem(0u, 0); - v = vec::append(v, ~[4, 2]); - assert!((reversed(v) == ~[2, 4])); + v = append(v, ~[4, 2]); + assert_eq!(reversed(v), ~[2, 4]); } diff --git a/src/test/run-pass/import-in-block.rs b/src/test/run-pass/import-in-block.rs index 659b7b5be6f65..9537162e1c803 100644 --- a/src/test/run-pass/import-in-block.rs +++ b/src/test/run-pass/import-in-block.rs @@ -9,10 +9,10 @@ // except according to those terms. pub fn main() { - use core::vec::from_fn; - debug!(::core::vec::len(from_fn(2, |i| i))); + use std::vec::from_fn; + debug!(::std::vec::len(from_fn(2, |i| i))); { - use core::vec::*; + use std::vec::*; debug!(len(~[2])); } } diff --git a/src/test/run-pass/inferred-suffix-in-pattern-range.rs b/src/test/run-pass/inferred-suffix-in-pattern-range.rs index e9287f3562205..447ee2c890c22 100644 --- a/src/test/run-pass/inferred-suffix-in-pattern-range.rs +++ b/src/test/run-pass/inferred-suffix-in-pattern-range.rs @@ -14,19 +14,19 @@ pub fn main() { 0 .. 1 => { ~"not many" } _ => { ~"lots" } }; - assert!(x_message == ~"lots"); + assert_eq!(x_message, ~"lots"); let y = 2i; let y_message = match y { 0 .. 1 => { ~"not many" } _ => { ~"lots" } }; - assert!(y_message == ~"lots"); + assert_eq!(y_message, ~"lots"); let z = 1u64; let z_message = match z { 0 .. 1 => { ~"not many" } _ => { ~"lots" } }; - assert!(z_message == ~"not many"); + assert_eq!(z_message, ~"not many"); } diff --git a/src/test/run-pass/infinite-loops.rs b/src/test/run-pass/infinite-loops.rs index b2ed6d95c206a..dea0df2e52b34 100644 --- a/src/test/run-pass/infinite-loops.rs +++ b/src/test/run-pass/infinite-loops.rs @@ -14,7 +14,7 @@ */ // xfail-test -extern mod std; +extern mod extra; fn loopy(n: int) { if n > 0 { do spawn { loopy(n - 1) }; do spawn { loopy(n - 1) }; } diff --git a/src/test/run-pass/init-res-into-things.rs b/src/test/run-pass/init-res-into-things.rs index 98919e49a1ad3..5e10419da6e72 100644 --- a/src/test/run-pass/init-res-into-things.rs +++ b/src/test/run-pass/init-res-into-things.rs @@ -37,7 +37,7 @@ fn test_box() { { let a = @r(i); } - assert!(*i == 1); + assert_eq!(*i, 1); } fn test_rec() { @@ -45,7 +45,7 @@ fn test_rec() { { let a = Box {x: r(i)}; } - assert!(*i == 1); + assert_eq!(*i, 1); } fn test_tag() { @@ -57,7 +57,7 @@ fn test_tag() { { let a = t0(r(i)); } - assert!(*i == 1); + assert_eq!(*i, 1); } fn test_tup() { @@ -65,7 +65,7 @@ fn test_tup() { { let a = (r(i), 0); } - assert!(*i == 1); + assert_eq!(*i, 1); } fn test_unique() { @@ -73,7 +73,7 @@ fn test_unique() { { let a = ~r(i); } - assert!(*i == 1); + assert_eq!(*i, 1); } fn test_box_rec() { @@ -83,7 +83,7 @@ fn test_box_rec() { x: r(i) }; } - assert!(*i == 1); + assert_eq!(*i, 1); } pub fn main() { diff --git a/src/test/run-pass/instantiable.rs b/src/test/run-pass/instantiable.rs index 2173bae85e1e1..5415a6ad25812 100644 --- a/src/test/run-pass/instantiable.rs +++ b/src/test/run-pass/instantiable.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::ptr; // check that we do not report a type like this as uninstantiable, // even though it would be if the nxt field had type @foo: diff --git a/src/test/run-pass/int-conversion-coherence.rs b/src/test/run-pass/int-conversion-coherence.rs index ef2a84da219c9..7ef4f6ed22c12 100644 --- a/src/test/run-pass/int-conversion-coherence.rs +++ b/src/test/run-pass/int-conversion-coherence.rs @@ -21,5 +21,5 @@ impl foo of plus for uint { fn plus() -> int { self as int + 20 } } impl foo of plus for int { fn plus() -> int { self + 10 } } pub fn main() { - assert!(10.plus() == 20); + assert_eq!(10.plus(), 20); } diff --git a/src/test/run-pass/integral-indexing.rs b/src/test/run-pass/integral-indexing.rs index 9d30c73860505..b985ed0f6cb6a 100644 --- a/src/test/run-pass/integral-indexing.rs +++ b/src/test/run-pass/integral-indexing.rs @@ -15,16 +15,16 @@ pub fn main() { let v: ~[int] = ~[0, 1, 2, 3, 4, 5]; let s: ~str = ~"abcdef"; - assert!((v[3u] == 3)); - assert!((v[3u8] == 3)); - assert!((v[3i8] == 3)); - assert!((v[3u32] == 3)); - assert!((v[3i32] == 3)); + assert_eq!(v[3u], 3); + assert_eq!(v[3u8], 3); + assert_eq!(v[3i8], 3); + assert_eq!(v[3u32], 3); + assert_eq!(v[3i32], 3); debug!(v[3u8]); - assert!((s[3u] == 'd' as u8)); - assert!((s[3u8] == 'd' as u8)); - assert!((s[3i8] == 'd' as u8)); - assert!((s[3u32] == 'd' as u8)); - assert!((s[3i32] == 'd' as u8)); + assert_eq!(s[3u], 'd' as u8); + assert_eq!(s[3u8], 'd' as u8); + assert_eq!(s[3i8], 'd' as u8); + assert_eq!(s[3u32], 'd' as u8); + assert_eq!(s[3i32], 'd' as u8); debug!(s[3u8]); } diff --git a/src/test/run-pass/intrinsic-alignment.rs b/src/test/run-pass/intrinsic-alignment.rs index cce3d8066ec19..7a54b87404e44 100644 --- a/src/test/run-pass/intrinsic-alignment.rs +++ b/src/test/run-pass/intrinsic-alignment.rs @@ -26,8 +26,8 @@ mod m { #[cfg(target_arch = "x86")] pub fn main() { unsafe { - assert!(::rusti::pref_align_of::() == 8u); - assert!(::rusti::min_align_of::() == 4u); + assert_eq!(::rusti::pref_align_of::(), 8u); + assert_eq!(::rusti::min_align_of::(), 4u); } } @@ -35,8 +35,8 @@ mod m { #[cfg(target_arch = "x86_64")] pub fn main() { unsafe { - assert!(::rusti::pref_align_of::() == 8u); - assert!(::rusti::min_align_of::() == 8u); + assert_eq!(::rusti::pref_align_of::(), 8u); + assert_eq!(::rusti::min_align_of::(), 8u); } } } @@ -47,8 +47,8 @@ mod m { #[cfg(target_arch = "x86")] pub fn main() { unsafe { - assert!(::rusti::pref_align_of::() == 8u); - assert!(::rusti::min_align_of::() == 8u); + assert_eq!(::rusti::pref_align_of::(), 8u); + assert_eq!(::rusti::min_align_of::(), 8u); } } } @@ -59,8 +59,8 @@ mod m { #[cfg(target_arch = "arm")] pub fn main() { unsafe { - assert!(::rusti::pref_align_of::() == 8u); - assert!(::rusti::min_align_of::() == 4u); + assert_eq!(::rusti::pref_align_of::(), 8u); + assert_eq!(::rusti::min_align_of::(), 4u); } } } diff --git a/src/test/run-pass/intrinsic-atomics-cc.rs b/src/test/run-pass/intrinsic-atomics-cc.rs index da0c7e759f580..ad285e9a85fb9 100644 --- a/src/test/run-pass/intrinsic-atomics-cc.rs +++ b/src/test/run-pass/intrinsic-atomics-cc.rs @@ -18,6 +18,6 @@ pub fn main() { unsafe { let mut x = 1; atomic_xchg(&mut x, 5); - assert!(x == 5); + assert_eq!(x, 5); } } diff --git a/src/test/run-pass/intrinsic-atomics.rs b/src/test/run-pass/intrinsic-atomics.rs index d4701f74488c8..e5ab980cc8d84 100644 --- a/src/test/run-pass/intrinsic-atomics.rs +++ b/src/test/run-pass/intrinsic-atomics.rs @@ -17,7 +17,7 @@ mod rusti { pub fn atomic_load(src: &int) -> int; pub fn atomic_load_acq(src: &int) -> int; - + pub fn atomic_store(dst: &mut int, val: int); pub fn atomic_store_rel(dst: &mut int, val: int); @@ -39,41 +39,41 @@ pub fn main() { unsafe { let mut x = ~1; - assert!(rusti::atomic_load(x) == 1); + assert_eq!(rusti::atomic_load(x), 1); *x = 5; - assert!(rusti::atomic_load_acq(x) == 5); - + assert_eq!(rusti::atomic_load_acq(x), 5); + rusti::atomic_store(x,3); - assert!(*x == 3); + assert_eq!(*x, 3); rusti::atomic_store_rel(x,1); - assert!(*x == 1); + assert_eq!(*x, 1); - assert!(rusti::atomic_cxchg(x, 1, 2) == 1); - assert!(*x == 2); + assert_eq!(rusti::atomic_cxchg(x, 1, 2), 1); + assert_eq!(*x, 2); - assert!(rusti::atomic_cxchg_acq(x, 1, 3) == 2); - assert!(*x == 2); + assert_eq!(rusti::atomic_cxchg_acq(x, 1, 3), 2); + assert_eq!(*x, 2); - assert!(rusti::atomic_cxchg_rel(x, 2, 1) == 2); - assert!(*x == 1); + assert_eq!(rusti::atomic_cxchg_rel(x, 2, 1), 2); + assert_eq!(*x, 1); - assert!(rusti::atomic_xchg(x, 0) == 1); - assert!(*x == 0); + assert_eq!(rusti::atomic_xchg(x, 0), 1); + assert_eq!(*x, 0); - assert!(rusti::atomic_xchg_acq(x, 1) == 0); - assert!(*x == 1); + assert_eq!(rusti::atomic_xchg_acq(x, 1), 0); + assert_eq!(*x, 1); - assert!(rusti::atomic_xchg_rel(x, 0) == 1); - assert!(*x == 0); + assert_eq!(rusti::atomic_xchg_rel(x, 0), 1); + assert_eq!(*x, 0); - assert!(rusti::atomic_xadd(x, 1) == 0); - assert!(rusti::atomic_xadd_acq(x, 1) == 1); - assert!(rusti::atomic_xadd_rel(x, 1) == 2); - assert!(*x == 3); + assert_eq!(rusti::atomic_xadd(x, 1), 0); + assert_eq!(rusti::atomic_xadd_acq(x, 1), 1); + assert_eq!(rusti::atomic_xadd_rel(x, 1), 2); + assert_eq!(*x, 3); - assert!(rusti::atomic_xsub(x, 1) == 3); - assert!(rusti::atomic_xsub_acq(x, 1) == 2); - assert!(rusti::atomic_xsub_rel(x, 1) == 1); - assert!(*x == 0); + assert_eq!(rusti::atomic_xsub(x, 1), 3); + assert_eq!(rusti::atomic_xsub_acq(x, 1), 2); + assert_eq!(rusti::atomic_xsub_rel(x, 1), 1); + assert_eq!(*x, 0); } } diff --git a/src/test/run-pass/intrinsic-move-val.rs b/src/test/run-pass/intrinsic-move-val.rs index 9f683d2089877..1dbb46c271ecb 100644 --- a/src/test/run-pass/intrinsic-move-val.rs +++ b/src/test/run-pass/intrinsic-move-val.rs @@ -21,6 +21,6 @@ pub fn main() { let mut x = @1; let mut y = @2; rusti::move_val(&mut y, x); - assert!(*y == 1); + assert_eq!(*y, 1); } } diff --git a/src/test/run-pass/intrinsics-integer.rs b/src/test/run-pass/intrinsics-integer.rs index 1a0d97a5c5b03..6be47b1e88b3d 100644 --- a/src/test/run-pass/intrinsics-integer.rs +++ b/src/test/run-pass/intrinsics-integer.rs @@ -10,7 +10,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; +extern mod extra; mod rusti { #[abi = "rust-intrinsic"] @@ -40,83 +40,83 @@ pub fn main() { unsafe { use rusti::*; - assert!((ctpop8(0i8) == 0i8)); - assert!((ctpop16(0i16) == 0i16)); - assert!((ctpop32(0i32) == 0i32)); - assert!((ctpop64(0i64) == 0i64)); - - assert!((ctpop8(1i8) == 1i8)); - assert!((ctpop16(1i16) == 1i16)); - assert!((ctpop32(1i32) == 1i32)); - assert!((ctpop64(1i64) == 1i64)); - - assert!((ctpop8(10i8) == 2i8)); - assert!((ctpop16(10i16) == 2i16)); - assert!((ctpop32(10i32) == 2i32)); - assert!((ctpop64(10i64) == 2i64)); - - assert!((ctpop8(100i8) == 3i8)); - assert!((ctpop16(100i16) == 3i16)); - assert!((ctpop32(100i32) == 3i32)); - assert!((ctpop64(100i64) == 3i64)); - - assert!((ctpop8(-1i8) == 8i8)); - assert!((ctpop16(-1i16) == 16i16)); - assert!((ctpop32(-1i32) == 32i32)); - assert!((ctpop64(-1i64) == 64i64)); - - assert!((ctlz8(0i8) == 8i8)); - assert!((ctlz16(0i16) == 16i16)); - assert!((ctlz32(0i32) == 32i32)); - assert!((ctlz64(0i64) == 64i64)); - - assert!((ctlz8(1i8) == 7i8)); - assert!((ctlz16(1i16) == 15i16)); - assert!((ctlz32(1i32) == 31i32)); - assert!((ctlz64(1i64) == 63i64)); - - assert!((ctlz8(10i8) == 4i8)); - assert!((ctlz16(10i16) == 12i16)); - assert!((ctlz32(10i32) == 28i32)); - assert!((ctlz64(10i64) == 60i64)); - - assert!((ctlz8(100i8) == 1i8)); - assert!((ctlz16(100i16) == 9i16)); - assert!((ctlz32(100i32) == 25i32)); - assert!((ctlz64(100i64) == 57i64)); - - assert!((cttz8(-1i8) == 0i8)); - assert!((cttz16(-1i16) == 0i16)); - assert!((cttz32(-1i32) == 0i32)); - assert!((cttz64(-1i64) == 0i64)); - - assert!((cttz8(0i8) == 8i8)); - assert!((cttz16(0i16) == 16i16)); - assert!((cttz32(0i32) == 32i32)); - assert!((cttz64(0i64) == 64i64)); - - assert!((cttz8(1i8) == 0i8)); - assert!((cttz16(1i16) == 0i16)); - assert!((cttz32(1i32) == 0i32)); - assert!((cttz64(1i64) == 0i64)); - - assert!((cttz8(10i8) == 1i8)); - assert!((cttz16(10i16) == 1i16)); - assert!((cttz32(10i32) == 1i32)); - assert!((cttz64(10i64) == 1i64)); - - assert!((cttz8(100i8) == 2i8)); - assert!((cttz16(100i16) == 2i16)); - assert!((cttz32(100i32) == 2i32)); - assert!((cttz64(100i64) == 2i64)); - - assert!((cttz8(-1i8) == 0i8)); - assert!((cttz16(-1i16) == 0i16)); - assert!((cttz32(-1i32) == 0i32)); - assert!((cttz64(-1i64) == 0i64)); - - assert!((bswap16(0x0A0Bi16) == 0x0B0Ai16)); - assert!((bswap32(0x0ABBCC0Di32) == 0x0DCCBB0Ai32)); - assert!((bswap64(0x0122334455667708i64) == 0x0877665544332201i64)); + assert_eq!(ctpop8(0i8), 0i8); + assert_eq!(ctpop16(0i16), 0i16); + assert_eq!(ctpop32(0i32), 0i32); + assert_eq!(ctpop64(0i64), 0i64); + + assert_eq!(ctpop8(1i8), 1i8); + assert_eq!(ctpop16(1i16), 1i16); + assert_eq!(ctpop32(1i32), 1i32); + assert_eq!(ctpop64(1i64), 1i64); + + assert_eq!(ctpop8(10i8), 2i8); + assert_eq!(ctpop16(10i16), 2i16); + assert_eq!(ctpop32(10i32), 2i32); + assert_eq!(ctpop64(10i64), 2i64); + + assert_eq!(ctpop8(100i8), 3i8); + assert_eq!(ctpop16(100i16), 3i16); + assert_eq!(ctpop32(100i32), 3i32); + assert_eq!(ctpop64(100i64), 3i64); + + assert_eq!(ctpop8(-1i8), 8i8); + assert_eq!(ctpop16(-1i16), 16i16); + assert_eq!(ctpop32(-1i32), 32i32); + assert_eq!(ctpop64(-1i64), 64i64); + + assert_eq!(ctlz8(0i8), 8i8); + assert_eq!(ctlz16(0i16), 16i16); + assert_eq!(ctlz32(0i32), 32i32); + assert_eq!(ctlz64(0i64), 64i64); + + assert_eq!(ctlz8(1i8), 7i8); + assert_eq!(ctlz16(1i16), 15i16); + assert_eq!(ctlz32(1i32), 31i32); + assert_eq!(ctlz64(1i64), 63i64); + + assert_eq!(ctlz8(10i8), 4i8); + assert_eq!(ctlz16(10i16), 12i16); + assert_eq!(ctlz32(10i32), 28i32); + assert_eq!(ctlz64(10i64), 60i64); + + assert_eq!(ctlz8(100i8), 1i8); + assert_eq!(ctlz16(100i16), 9i16); + assert_eq!(ctlz32(100i32), 25i32); + assert_eq!(ctlz64(100i64), 57i64); + + assert_eq!(cttz8(-1i8), 0i8); + assert_eq!(cttz16(-1i16), 0i16); + assert_eq!(cttz32(-1i32), 0i32); + assert_eq!(cttz64(-1i64), 0i64); + + assert_eq!(cttz8(0i8), 8i8); + assert_eq!(cttz16(0i16), 16i16); + assert_eq!(cttz32(0i32), 32i32); + assert_eq!(cttz64(0i64), 64i64); + + assert_eq!(cttz8(1i8), 0i8); + assert_eq!(cttz16(1i16), 0i16); + assert_eq!(cttz32(1i32), 0i32); + assert_eq!(cttz64(1i64), 0i64); + + assert_eq!(cttz8(10i8), 1i8); + assert_eq!(cttz16(10i16), 1i16); + assert_eq!(cttz32(10i32), 1i32); + assert_eq!(cttz64(10i64), 1i64); + + assert_eq!(cttz8(100i8), 2i8); + assert_eq!(cttz16(100i16), 2i16); + assert_eq!(cttz32(100i32), 2i32); + assert_eq!(cttz64(100i64), 2i64); + + assert_eq!(cttz8(-1i8), 0i8); + assert_eq!(cttz16(-1i16), 0i16); + assert_eq!(cttz32(-1i32), 0i32); + assert_eq!(cttz64(-1i64), 0i64); + + assert_eq!(bswap16(0x0A0Bi16), 0x0B0Ai16); + assert_eq!(bswap32(0x0ABBCC0Di32), 0x0DCCBB0Ai32); + assert_eq!(bswap64(0x0122334455667708i64), 0x0877665544332201i64); } } diff --git a/src/test/run-pass/intrinsics-math.rs b/src/test/run-pass/intrinsics-math.rs index c73df8209e8b9..b7e449a1117df 100644 --- a/src/test/run-pass/intrinsics-math.rs +++ b/src/test/run-pass/intrinsics-math.rs @@ -10,6 +10,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::f64; + mod rusti { #[abi = "rust-intrinsic"] pub extern "rust-intrinsic" { @@ -50,6 +52,9 @@ pub fn main() { unsafe { use rusti::*; + use std::f32; + use std::f64; + assert!((sqrtf32(64f32).approx_eq(&8f32))); assert!((sqrtf64(64f64).approx_eq(&8f64))); diff --git a/src/test/run-pass/invoke-external-foreign.rs b/src/test/run-pass/invoke-external-foreign.rs index 69fce9e541e06..15f08ca23e7c9 100644 --- a/src/test/run-pass/invoke-external-foreign.rs +++ b/src/test/run-pass/invoke-external-foreign.rs @@ -18,5 +18,7 @@ extern mod foreign_lib; pub fn main() { - let foo = foreign_lib::rustrt::rust_get_argc(); + unsafe { + let foo = foreign_lib::rustrt::rust_get_argc(); + } } diff --git a/src/test/run-pass/issue-1112.rs b/src/test/run-pass/issue-1112.rs index cd15dfa2a0d60..22c88c874f096 100644 --- a/src/test/run-pass/issue-1112.rs +++ b/src/test/run-pass/issue-1112.rs @@ -35,10 +35,10 @@ pub fn main() { } fn bar(x: X) { - assert!(x.b == 9u8); - assert!(x.c == true); - assert!(x.d == 10u8); - assert!(x.e == 11u16); - assert!(x.f == 12u8); - assert!(x.g == 13u8); + assert_eq!(x.b, 9u8); + assert_eq!(x.c, true); + assert_eq!(x.d, 10u8); + assert_eq!(x.e, 11u16); + assert_eq!(x.f, 12u8); + assert_eq!(x.g, 13u8); } diff --git a/src/test/run-pass/issue-1251.rs b/src/test/run-pass/issue-1251.rs index c14dd625a8e82..886ea53c29965 100644 --- a/src/test/run-pass/issue-1251.rs +++ b/src/test/run-pass/issue-1251.rs @@ -11,6 +11,8 @@ #[link(name = "get_task_id")]; mod rustrt { + use std::libc; + pub extern { pub fn get_task_id() -> libc::intptr_t; } diff --git a/src/test/run-pass/issue-1458.rs b/src/test/run-pass/issue-1458.rs index 0677c9dea7402..e22f38287ad5d 100644 --- a/src/test/run-pass/issue-1458.rs +++ b/src/test/run-pass/issue-1458.rs @@ -18,5 +18,5 @@ fn ret_plus_one() -> extern fn(&fn() -> int) -> int { pub fn main() { let z = do (ret_plus_one()) || { 2 }; - assert!(z == 3); + assert_eq!(z, 3); } diff --git a/src/test/run-pass/issue-1696.rs b/src/test/run-pass/issue-1696.rs index 5b40d0abff818..62088e013be1e 100644 --- a/src/test/run-pass/issue-1696.rs +++ b/src/test/run-pass/issue-1696.rs @@ -10,7 +10,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::hashmap::HashMap; +use std::hashmap::HashMap; +use std::str; pub fn main() { let mut m = HashMap::new(); diff --git a/src/test/run-pass/issue-1701.rs b/src/test/run-pass/issue-1701.rs index c8937a2a628ee..4f3d0dbe13344 100644 --- a/src/test/run-pass/issue-1701.rs +++ b/src/test/run-pass/issue-1701.rs @@ -24,8 +24,8 @@ fn noise(a: animal) -> Option<~str> { } pub fn main() { - assert!(noise(cat(tabby)) == Some(~"meow")); - assert!(noise(dog(pug)) == Some(~"woof")); - assert!(noise(rabbit(~"Hilbert", upright)) == None); - assert!(noise(tiger) == Some(~"roar")); + assert_eq!(noise(cat(tabby)), Some(~"meow")); + assert_eq!(noise(dog(pug)), Some(~"woof")); + assert_eq!(noise(rabbit(~"Hilbert", upright)), None); + assert_eq!(noise(tiger), Some(~"roar")); } diff --git a/src/test/run-pass/issue-2101.rs b/src/test/run-pass/issue-2101.rs index 4564e08914712..423888c1cf5b6 100644 --- a/src/test/run-pass/issue-2101.rs +++ b/src/test/run-pass/issue-2101.rs @@ -9,9 +9,9 @@ // except according to those terms. // xfail-test -extern mod std; -use std::arena; -use std::arena::Arena; +extern mod extra; +use extra::arena; +use extra::arena::Arena; enum hold { s(str) } diff --git a/src/test/run-pass/issue-2214.rs b/src/test/run-pass/issue-2214.rs index d63e01ec39607..93cc8c292b152 100644 --- a/src/test/run-pass/issue-2214.rs +++ b/src/test/run-pass/issue-2214.rs @@ -10,9 +10,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::cast; -use core::libc::{c_double, c_int}; -use core::f64::*; +use std::cast; +use std::libc::{c_double, c_int}; +use std::f64::*; fn to_c_int(v: &mut int) -> &mut c_int { unsafe { @@ -27,7 +27,7 @@ fn lgamma(n: c_double, value: &mut int) -> c_double { } mod m { - use core::libc::{c_double, c_int}; + use std::libc::{c_double, c_int}; #[link_name = "m"] #[abi = "cdecl"] @@ -44,5 +44,5 @@ mod m { pub fn main() { let mut y: int = 5; let x: &mut int = &mut y; - assert!((lgamma(1.0 as c_double, x) == 0.0 as c_double)); + assert_eq!(lgamma(1.0 as c_double, x), 0.0 as c_double); } diff --git a/src/test/run-pass/issue-2216.rs b/src/test/run-pass/issue-2216.rs index c3a2a4c0b7e24..0914c81c3ff17 100644 --- a/src/test/run-pass/issue-2216.rs +++ b/src/test/run-pass/issue-2216.rs @@ -28,5 +28,5 @@ pub fn main() { } error!("%?", x); - assert!((x == 42)); + assert_eq!(x, 42); } diff --git a/src/test/run-pass/issue-2311-2.rs b/src/test/run-pass/issue-2311-2.rs index 5f47e7ccb9f79..155f9cff29629 100644 --- a/src/test/run-pass/issue-2311-2.rs +++ b/src/test/run-pass/issue-2311-2.rs @@ -13,8 +13,8 @@ struct foo { x: A, } -pub impl foo { - fn bar>(&self, c: C) -> B { +impl foo { + pub fn bar>(&self, c: C) -> B { fail!(); } } diff --git a/src/test/run-pass/issue-2312.rs b/src/test/run-pass/issue-2312.rs index f3aa96298f0c5..59ca02f50fc3a 100644 --- a/src/test/run-pass/issue-2312.rs +++ b/src/test/run-pass/issue-2312.rs @@ -14,8 +14,8 @@ trait clam { } struct foo(int); -pub impl foo { - fn bar>(&self, c: C) -> B { fail!(); } +impl foo { + pub fn bar>(&self, c: C) -> B { fail!(); } } pub fn main() { } diff --git a/src/test/run-pass/issue-2383.rs b/src/test/run-pass/issue-2383.rs index a7afa1d6f3494..9d8701688024c 100644 --- a/src/test/run-pass/issue-2383.rs +++ b/src/test/run-pass/issue-2383.rs @@ -10,8 +10,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; -use std::deque::Deque; +extern mod extra; +use extra::deque::Deque; pub fn main() { let mut q = Deque::new(); diff --git a/src/test/run-pass/issue-2428.rs b/src/test/run-pass/issue-2428.rs index 29fa357ba1a28..548f068979665 100644 --- a/src/test/run-pass/issue-2428.rs +++ b/src/test/run-pass/issue-2428.rs @@ -16,5 +16,5 @@ pub fn main() { Bar = quux } - assert!((Bar as int == quux)); + assert_eq!(Bar as int, quux); } diff --git a/src/test/run-pass/issue-2445-b.rs b/src/test/run-pass/issue-2445-b.rs index 55c72a41a6a32..c26038afd764f 100644 --- a/src/test/run-pass/issue-2445-b.rs +++ b/src/test/run-pass/issue-2445-b.rs @@ -12,8 +12,8 @@ struct c1 { x: T, } -pub impl c1 { - fn f1(&self, x: int) { +impl c1 { + pub fn f1(&self, x: int) { } } @@ -23,8 +23,8 @@ fn c1(x: T) -> c1 { } } -pub impl c1 { - fn f2(&self, x: int) { +impl c1 { + pub fn f2(&self, x: int) { } } diff --git a/src/test/run-pass/issue-2445.rs b/src/test/run-pass/issue-2445.rs index 5a82b53401571..64d6072597876 100644 --- a/src/test/run-pass/issue-2445.rs +++ b/src/test/run-pass/issue-2445.rs @@ -12,8 +12,8 @@ struct c1 { x: T, } -pub impl c1 { - fn f1(&self, x: T) {} +impl c1 { + pub fn f1(&self, x: T) {} } fn c1(x: T) -> c1 { @@ -22,8 +22,8 @@ fn c1(x: T) -> c1 { } } -pub impl c1 { - fn f2(&self, x: T) {} +impl c1 { + pub fn f2(&self, x: T) {} } diff --git a/src/test/run-pass/issue-2487-a.rs b/src/test/run-pass/issue-2487-a.rs index 388160e538acd..5e5fb70bcd4a5 100644 --- a/src/test/run-pass/issue-2487-a.rs +++ b/src/test/run-pass/issue-2487-a.rs @@ -17,8 +17,8 @@ impl Drop for socket { fn finalize(&self) {} } -pub impl socket { - fn set_identity(&self) { +impl socket { + pub fn set_identity(&self) { do closure { setsockopt_bytes(self.sock.clone()) } diff --git a/src/test/run-pass/issue-2502.rs b/src/test/run-pass/issue-2502.rs index 34eb591b73aa4..c26fef49be735 100644 --- a/src/test/run-pass/issue-2502.rs +++ b/src/test/run-pass/issue-2502.rs @@ -12,8 +12,8 @@ struct font<'self> { fontbuf: &'self ~[u8], } -pub impl<'self> font<'self> { - fn buf(&self) -> &'self ~[u8] { +impl<'self> font<'self> { + pub fn buf(&self) -> &'self ~[u8] { self.fontbuf } } diff --git a/src/test/run-pass/issue-2611.rs b/src/test/run-pass/issue-2611.rs index f24605339ad77..d7508bca41e1f 100644 --- a/src/test/run-pass/issue-2611.rs +++ b/src/test/run-pass/issue-2611.rs @@ -8,7 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::old_iter::BaseIter; +use std::old_iter::BaseIter; +use std::old_iter; trait FlatMapToVec { fn flat_map_to_vec>(&self, op: &fn(&A) -> IB) -> ~[B]; diff --git a/src/test/run-pass/issue-2631-b.rs b/src/test/run-pass/issue-2631-b.rs index f6e40fa247d5e..3ceae1030562d 100644 --- a/src/test/run-pass/issue-2631-b.rs +++ b/src/test/run-pass/issue-2631-b.rs @@ -14,7 +14,7 @@ extern mod req; use req::*; -use core::hashmap::HashMap; +use std::hashmap::HashMap; pub fn main() { let v = ~[@~"hi"]; diff --git a/src/test/run-pass/issue-2718.rs b/src/test/run-pass/issue-2718.rs index e46d2a923a8c5..4ef83e405be40 100644 --- a/src/test/run-pass/issue-2718.rs +++ b/src/test/run-pass/issue-2718.rs @@ -10,12 +10,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::util; +use std::util; // tjc: I don't know why pub mod pipes { - use core::util; - use core::cast::{forget, transmute}; + use std::cast::{forget, transmute}; + use std::cast; + use std::task; + use std::util; pub struct Stuff { state: state, @@ -54,7 +56,7 @@ pub mod pipes { pub fn atomic_xchg_rel(_dst: &mut int, _src: int) -> int { fail!(); } } - // We should consider moving this to ::core::unsafe, although I + // We should consider moving this to ::std::unsafe, although I // suspect graydon would want us to use void pointers instead. pub unsafe fn uniquify(x: *T) -> ~T { unsafe { cast::transmute(x) } @@ -111,7 +113,7 @@ pub mod pipes { return Some(payload.unwrap()) } terminated => { - assert!(old_state == terminated); + assert_eq!(old_state, terminated); return None; } } @@ -170,8 +172,8 @@ pub mod pipes { } } - pub impl send_packet { - fn unwrap(&mut self) -> *packet { + impl send_packet { + pub fn unwrap(&mut self) -> *packet { util::replace(&mut self.p, None).unwrap() } } @@ -200,8 +202,8 @@ pub mod pipes { } } - pub impl recv_packet { - fn unwrap(&mut self) -> *packet { + impl recv_packet { + pub fn unwrap(&mut self) -> *packet { util::replace(&mut self.p, None).unwrap() } } @@ -219,9 +221,9 @@ pub mod pipes { } pub mod pingpong { - use core::cast; - use core::ptr; - use core::util; + use std::cast; + use std::ptr; + use std::util; pub struct ping(::pipes::send_packet); pub struct pong(::pipes::send_packet); @@ -253,7 +255,7 @@ pub mod pingpong { } pub mod client { - use core::option; + use std::option; use pingpong; pub type ping = ::pipes::send_packet; @@ -316,8 +318,8 @@ pub fn main() { // Commented out because of option::get error let (client_, server_) = pingpong::init(); - let client_ = Cell(client_); - let server_ = Cell(server_); + let client_ = Cell::new(client_); + let server_ = Cell::new(server_); task::spawn {|client_| let client__ = client_.take(); diff --git a/src/test/run-pass/issue-2748-b.rs b/src/test/run-pass/issue-2748-b.rs index b9efb441ae78d..3ca8d49eb864d 100644 --- a/src/test/run-pass/issue-2748-b.rs +++ b/src/test/run-pass/issue-2748-b.rs @@ -14,6 +14,6 @@ pub fn main() { let x = &[1,2,3]; let y = x; let z = thing(x); - assert!((z[2] == x[2])); - assert!((z[1] == y[1])); + assert_eq!(z[2], x[2]); + assert_eq!(z[1], y[1]); } diff --git a/src/test/run-pass/issue-2804-2.rs b/src/test/run-pass/issue-2804-2.rs index b25e4095b185e..917839a5401e2 100644 --- a/src/test/run-pass/issue-2804-2.rs +++ b/src/test/run-pass/issue-2804-2.rs @@ -13,7 +13,7 @@ // Minimized version of issue-2804.rs. Both check that callee IDs don't // clobber the previous node ID in a macro expr -use core::hashmap::HashMap; +use std::hashmap::HashMap; fn add_interfaces(managed_ip: ~str, device: HashMap<~str, int>) { error!("%s, %?", managed_ip, device.get(&~"interfaces")); diff --git a/src/test/run-pass/issue-2804.rs b/src/test/run-pass/issue-2804.rs index 4614c26fa5fc8..59ab5018c1d57 100644 --- a/src/test/run-pass/issue-2804.rs +++ b/src/test/run-pass/issue-2804.rs @@ -10,9 +10,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; -use core::hashmap::HashMap; -use std::json; +extern mod extra; + +use extra::json; +use std::hashmap::HashMap; +use std::option; enum object { bool_value(bool), @@ -23,9 +25,9 @@ fn lookup(table: ~json::Object, key: ~str, default: ~str) -> ~str { match table.find(&key) { - option::Some(&std::json::String(copy s)) => + option::Some(&extra::json::String(ref s)) => { - copy s + copy *s } option::Some(value) => { @@ -39,13 +41,13 @@ fn lookup(table: ~json::Object, key: ~str, default: ~str) -> ~str } } -fn add_interface(store: int, managed_ip: ~str, data: std::json::Json) -> (~str, object) +fn add_interface(store: int, managed_ip: ~str, data: extra::json::Json) -> (~str, object) { match &data { - &std::json::Object(copy interface) => + &extra::json::Object(ref interface) => { - let name = lookup(copy interface, ~"ifDescr", ~""); + let name = lookup(copy *interface, ~"ifDescr", ~""); let label = fmt!("%s-%s", managed_ip, name); (label, bool_value(false)) @@ -58,11 +60,11 @@ fn add_interface(store: int, managed_ip: ~str, data: std::json::Json) -> (~str, } } -fn add_interfaces(store: int, managed_ip: ~str, device: HashMap<~str, std::json::Json>) -> ~[(~str, object)] +fn add_interfaces(store: int, managed_ip: ~str, device: HashMap<~str, extra::json::Json>) -> ~[(~str, object)] { match device.get(&~"interfaces") { - &std::json::List(ref interfaces) => + &extra::json::List(ref interfaces) => { do interfaces.map |interface| { add_interface(store, copy managed_ip, copy *interface) diff --git a/src/test/run-pass/issue-2834.rs b/src/test/run-pass/issue-2834.rs index 579c4f9f1d124..5d3a2d2331c90 100644 --- a/src/test/run-pass/issue-2834.rs +++ b/src/test/run-pass/issue-2834.rs @@ -18,7 +18,7 @@ proto! streamp ( ) fn rendezvous() { - let (c, s) = streamp::init(); + let (s, c) = streamp::init(); let streams: ~[streamp::client::open] = ~[c]; error!("%?", streams[0]); diff --git a/src/test/run-pass/issue-2895.rs b/src/test/run-pass/issue-2895.rs index bd075555df193..e6b3f9f6f359d 100644 --- a/src/test/run-pass/issue-2895.rs +++ b/src/test/run-pass/issue-2895.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::sys; + struct Cat { x: int } @@ -22,13 +24,13 @@ impl Drop for Kitty { #[cfg(target_arch = "x86_64")] pub fn main() { - assert!((sys::size_of::() == 8 as uint)); - assert!((sys::size_of::() == 16 as uint)); + assert_eq!(sys::size_of::(), 8 as uint); + assert_eq!(sys::size_of::(), 16 as uint); } #[cfg(target_arch = "x86")] #[cfg(target_arch = "arm")] pub fn main() { - assert!((sys::size_of::() == 4 as uint)); - assert!((sys::size_of::() == 8 as uint)); + assert_eq!(sys::size_of::(), 4 as uint); + assert_eq!(sys::size_of::(), 8 as uint); } diff --git a/src/test/run-pass/issue-2904.rs b/src/test/run-pass/issue-2904.rs index 9ea8caef7bc21..7670a7eee7c07 100644 --- a/src/test/run-pass/issue-2904.rs +++ b/src/test/run-pass/issue-2904.rs @@ -12,9 +12,12 @@ /// Map representation -extern mod std; +extern mod extra; -use core::io::ReaderUtil; +use std::io::ReaderUtil; +use std::io; +use std::str; +use std::to_str; enum square { bot, diff --git a/src/test/run-pass/issue-2930.rs b/src/test/run-pass/issue-2930.rs index 6d22a2ea5edcf..cfce19826d7e0 100644 --- a/src/test/run-pass/issue-2930.rs +++ b/src/test/run-pass/issue-2930.rs @@ -15,7 +15,7 @@ proto! stream ( ) pub fn main() { - let (bc, _bp) = stream::init(); + let (_bp, bc) = stream::init(); stream::client::send(bc, ~"abc"); } diff --git a/src/test/run-pass/issue-2936.rs b/src/test/run-pass/issue-2936.rs index b989be0c1826a..183eb6e079f05 100644 --- a/src/test/run-pass/issue-2936.rs +++ b/src/test/run-pass/issue-2936.rs @@ -34,5 +34,5 @@ fn cbar(x: int) -> cbar { pub fn main() { let x: int = foo::(cbar(5)); - assert!(x == 5); + assert_eq!(x, 5); } diff --git a/src/test/run-pass/issue-2989.rs b/src/test/run-pass/issue-2989.rs index fb5df6d50e01f..c13821bddf16b 100644 --- a/src/test/run-pass/issue-2989.rs +++ b/src/test/run-pass/issue-2989.rs @@ -8,7 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; +extern mod extra; + +use std::io; +use std::uint; +use std::vec; trait methods { fn to_bytes(&self) -> ~[u8]; @@ -41,5 +45,5 @@ pub fn main() { io::println(fmt!("%u => %u vs %u", i, bools[i] as uint, bools2[i] as uint)); } - assert!(bools == bools2); + assert_eq!(bools, bools2); } diff --git a/src/test/run-pass/issue-3012-2.rs b/src/test/run-pass/issue-3012-2.rs index ef115c5c02ca6..7d478bbabebba 100644 --- a/src/test/run-pass/issue-3012-2.rs +++ b/src/test/run-pass/issue-3012-2.rs @@ -11,7 +11,9 @@ // xfail-fast // aux-build:issue-3012-1.rs extern mod socketlib; + use socketlib::socket; +use std::libc; pub fn main() { let fd: libc::c_int = 1 as libc::c_int; diff --git a/src/test/run-pass/issue-3026.rs b/src/test/run-pass/issue-3026.rs index 16e9b4753f830..a4b37f0ba0f0b 100644 --- a/src/test/run-pass/issue-3026.rs +++ b/src/test/run-pass/issue-3026.rs @@ -10,7 +10,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::hashmap::HashMap; +use std::hashmap::HashMap; pub fn main() { let mut buggy_map: HashMap = HashMap::new::(); diff --git a/src/test/run-pass/issue-3091.rs b/src/test/run-pass/issue-3091.rs index aa0625aa110d9..c4c2c2b7da878 100644 --- a/src/test/run-pass/issue-3091.rs +++ b/src/test/run-pass/issue-3091.rs @@ -11,5 +11,5 @@ pub fn main() { let x = 1; let y = 1; - assert!(&x == &y); + assert_eq!(&x, &y); } diff --git a/src/test/run-pass/issue-3168.rs b/src/test/run-pass/issue-3168.rs index d4eb0793dac53..fbe66708e476d 100644 --- a/src/test/run-pass/issue-3168.rs +++ b/src/test/run-pass/issue-3168.rs @@ -10,6 +10,9 @@ // xfail-fast +use std::comm; +use std::task; + pub fn main() { let (p,c) = comm::stream(); do task::try || { diff --git a/src/test/run-pass/issue-3176.rs b/src/test/run-pass/issue-3176.rs index d22c7e82ad5de..96648a2706b6d 100644 --- a/src/test/run-pass/issue-3176.rs +++ b/src/test/run-pass/issue-3176.rs @@ -10,7 +10,9 @@ // xfail-fast -use core::comm::{Select2, Selectable}; +use std::comm::{Select2, Selectable}; +use std::comm; +use std::task; pub fn main() { let (p,c) = comm::stream(); diff --git a/src/test/run-pass/issue-3211.rs b/src/test/run-pass/issue-3211.rs index 02e61fc7ce2ca..c7b0823296c67 100644 --- a/src/test/run-pass/issue-3211.rs +++ b/src/test/run-pass/issue-3211.rs @@ -3,6 +3,6 @@ pub fn main() { for 4096.times { x += 1; } - assert!(x == 4096); - io::println(fmt!("x = %u", x)); + assert_eq!(x, 4096); + println(fmt!("x = %u", x)); } diff --git a/src/test/run-pass/issue-3220.rs b/src/test/run-pass/issue-3220.rs index 9ecc46c17ac34..9cc5e5910435f 100644 --- a/src/test/run-pass/issue-3220.rs +++ b/src/test/run-pass/issue-3220.rs @@ -19,7 +19,10 @@ fn thing() -> thing { x: 0 } } -pub impl thing { fn f(self) {} } + +impl thing { + pub fn f(self) {} +} pub fn main() { let z = thing(); diff --git a/src/test/run-pass/issue-3290.rs b/src/test/run-pass/issue-3290.rs new file mode 100644 index 0000000000000..3f8ce032d0d9e --- /dev/null +++ b/src/test/run-pass/issue-3290.rs @@ -0,0 +1,16 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// xfail-test +fn main() { + let mut x = ~3; + x = x; + assert_eq!(*x, 3); +} diff --git a/src/test/run-pass/issue-3389.rs b/src/test/run-pass/issue-3389.rs index 6203f14f10f2e..d9919b1695d75 100644 --- a/src/test/run-pass/issue-3389.rs +++ b/src/test/run-pass/issue-3389.rs @@ -15,7 +15,7 @@ struct trie_node { fn print_str_vector(vector: ~[~str]) { for vector.each() |string| { - io::println(*string); + println(*string); } } diff --git a/src/test/run-pass/issue-3424.rs b/src/test/run-pass/issue-3424.rs index 70a01f8cf02d2..a40d1cf1c6ef1 100644 --- a/src/test/run-pass/issue-3424.rs +++ b/src/test/run-pass/issue-3424.rs @@ -11,8 +11,11 @@ // except according to those terms. // rustc --test ignores2.rs && ./ignores2 -extern mod std; -use core::path::{Path}; +extern mod extra; + +use std::path::{Path}; +use std::path; +use std::result; type rsrc_loader = ~fn(path: &Path) -> result::Result<~str, ~str>; diff --git a/src/test/run-pass/issue-3447.rs b/src/test/run-pass/issue-3447.rs index 191259e5a57e2..711dfd3778b5b 100644 --- a/src/test/run-pass/issue-3447.rs +++ b/src/test/run-pass/issue-3447.rs @@ -13,11 +13,11 @@ struct list<'self, T> { next: Option<@mut list<'self, T>> } -pub impl<'self, T> list<'self, T>{ - fn addEnd(&mut self, element: &'self T) { +impl<'self, T> list<'self, T>{ + pub fn addEnd(&mut self, element: &'self T) { let newList = list { element: element, - next: option::None + next: None }; self.next = Some(@mut newList); @@ -28,7 +28,7 @@ pub fn main() { let s = @"str"; let ls = list { element: &s, - next: option::None + next: None }; - io::println(*ls.element); + println(*ls.element); } diff --git a/src/test/run-pass/issue-3556.rs b/src/test/run-pass/issue-3556.rs index ff2fa80102bfc..6709ef761a44c 100644 --- a/src/test/run-pass/issue-3556.rs +++ b/src/test/run-pass/issue-3556.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; -use core::io::WriterUtil; +extern mod extra; + +use std::io::WriterUtil; +use std::io; enum Token { Text(@~str), diff --git a/src/test/run-pass/issue-3559.rs b/src/test/run-pass/issue-3559.rs index b3f3aed9ea1f9..9665da11b9334 100644 --- a/src/test/run-pass/issue-3559.rs +++ b/src/test/run-pass/issue-3559.rs @@ -11,9 +11,9 @@ // except according to those terms. // rustc --test map_to_str.rs && ./map_to_str -extern mod std; +extern mod extra; -use core::io::{WriterUtil}; +use std::io::{WriterUtil}; fn check_strs(actual: &str, expected: &str) -> bool { @@ -27,7 +27,7 @@ fn check_strs(actual: &str, expected: &str) -> bool fn tester() { - let mut table = core::hashmap::HashMap::new(); + let mut table = std::hashmap::HashMap::new(); table.insert(@~"one", 1); table.insert(@~"two", 2); assert!(check_strs(table.to_str(), ~"xxx")); // not sure what expected should be diff --git a/src/test/run-pass/issue-3563-3.rs b/src/test/run-pass/issue-3563-3.rs index 96925a97a1016..10d448b7952f8 100644 --- a/src/test/run-pass/issue-3563-3.rs +++ b/src/test/run-pass/issue-3563-3.rs @@ -12,15 +12,19 @@ // Demonstrates traits, impls, operator overloading, non-copyable struct, unit testing. // To run execute: rustc --test shapes.rs && ./shapes -// Rust's core library is tightly bound to the language itself so it is automatically linked in. -// However the std library is designed to be optional (for code that must run on constrained +// Rust's std library is tightly bound to the language itself so it is automatically linked in. +// However the extra library is designed to be optional (for code that must run on constrained // environments like embedded devices or special environments like kernel code) so it must // be explicitly linked in. -extern mod std; +extern mod extra; // Extern mod controls linkage. Use controls the visibility of names to modules that are // already linked in. Using WriterUtil allows us to use the write_line method. -use core::io::WriterUtil; +use std::int; +use std::io::WriterUtil; +use std::io; +use std::str; +use std::vec; // Represents a position on a canvas. struct Point { diff --git a/src/test/run-pass/issue-3574.rs b/src/test/run-pass/issue-3574.rs index db937e745037a..dc1ce95cfae54 100644 --- a/src/test/run-pass/issue-3574.rs +++ b/src/test/run-pass/issue-3574.rs @@ -9,7 +9,7 @@ // except according to those terms. // rustc --test match_borrowed_str.rs.rs && ./match_borrowed_str.rs -extern mod std; +extern mod extra; fn compare(x: &str, y: &str) -> bool { diff --git a/src/test/run-pass/issue-3609.rs b/src/test/run-pass/issue-3609.rs index 6c26ac3f65e1c..ab62d9c41425b 100644 --- a/src/test/run-pass/issue-3609.rs +++ b/src/test/run-pass/issue-3609.rs @@ -1,6 +1,8 @@ -extern mod std; +extern mod extra; -use core::comm::Chan; +use std::comm::Chan; +use std::task; +use std::uint; type RingBuffer = ~[float]; type SamplesFn = ~fn(samples: &RingBuffer); diff --git a/src/test/run-pass/issue-3656.rs b/src/test/run-pass/issue-3656.rs index 895e90beef4aa..96cf88a0e2b5e 100644 --- a/src/test/run-pass/issue-3656.rs +++ b/src/test/run-pass/issue-3656.rs @@ -13,7 +13,7 @@ // Incorrect struct size computation in the FFI, because of not taking // the alignment of elements into account. -use core::libc::*; +use std::libc::*; struct KEYGEN { hash_algorithm: [c_uint, ..2], diff --git a/src/test/run-pass/issue-3683.rs b/src/test/run-pass/issue-3683.rs index bdb191488b985..0072439935b2e 100644 --- a/src/test/run-pass/issue-3683.rs +++ b/src/test/run-pass/issue-3683.rs @@ -24,5 +24,5 @@ impl Foo for int { } pub fn main() { - assert!((3.b() == 5)); + assert_eq!(3.b(), 5); } diff --git a/src/test/run-pass/issue-3702.rs b/src/test/run-pass/issue-3702.rs index 7c2f8cf98cb8a..7d65d6e984c4b 100644 --- a/src/test/run-pass/issue-3702.rs +++ b/src/test/run-pass/issue-3702.rs @@ -14,7 +14,7 @@ pub fn main() { } fn to_string(t: @Text) { - io::println(t.to_str()); + println(t.to_str()); } } diff --git a/src/test/run-pass/issue-3753.rs b/src/test/run-pass/issue-3753.rs index 948ff1afd81c3..a94abe04fded2 100644 --- a/src/test/run-pass/issue-3753.rs +++ b/src/test/run-pass/issue-3753.rs @@ -12,6 +12,8 @@ // Issue Name: pub method preceeded by attribute can't be parsed // Abstract: Visibility parsing failed when compiler parsing +use std::float; + struct Point { x: float, y: float @@ -22,7 +24,7 @@ pub enum Shape { Rectangle(Point, Point) } -pub impl Shape { +impl Shape { pub fn area(&self, sh: Shape) -> float { match sh { Circle(_, size) => float::consts::pi * size * size, @@ -33,5 +35,5 @@ pub impl Shape { pub fn main(){ let s = Circle(Point { x: 1f, y: 2f }, 3f); - io::println(fmt!("%f", s.area(s))); + println(fmt!("%f", s.area(s))); } diff --git a/src/test/run-pass/issue-3796.rs b/src/test/run-pass/issue-3796.rs new file mode 100644 index 0000000000000..0091c09625584 --- /dev/null +++ b/src/test/run-pass/issue-3796.rs @@ -0,0 +1,19 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// xfail-test +#[deny(dead_assignment)]; +fn main() { + let mut x = 1; + let f: &fn() -> int = || { x + 20 }; + assert_eq!(f(), 21); + x += 1; + assert_eq!(f(), 22); +} diff --git a/src/test/run-pass/issue-3847.rs b/src/test/run-pass/issue-3847.rs index 4d1b042661c32..b5f41dd1630e0 100644 --- a/src/test/run-pass/issue-3847.rs +++ b/src/test/run-pass/issue-3847.rs @@ -18,5 +18,5 @@ pub fn main() { buildings::Tower { height: h } => { h } }; - io::println(h.to_str()); + println(h.to_str()); } diff --git a/src/test/run-pass/issue-3860.rs b/src/test/run-pass/issue-3860.rs index 778b2b72b13d9..0a22e8bcfd07e 100644 --- a/src/test/run-pass/issue-3860.rs +++ b/src/test/run-pass/issue-3860.rs @@ -10,8 +10,8 @@ struct Foo { x: int } -pub impl Foo { - fn stuff<'a>(&'a mut self) -> &'a mut Foo { +impl Foo { + pub fn stuff<'a>(&'a mut self) -> &'a mut Foo { return self; } } diff --git a/src/test/run-pass/issue-3888-2.rs b/src/test/run-pass/issue-3888-2.rs index 2992d9a4ac837..60c5062443514 100644 --- a/src/test/run-pass/issue-3888-2.rs +++ b/src/test/run-pass/issue-3888-2.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::vec; + fn vec_peek<'r, T>(v: &'r [T]) -> &'r [T] { // This doesn't work, and should. // v.slice(1, 5) diff --git a/src/test/run-pass/issue-3904.rs b/src/test/run-pass/issue-3904.rs index 1a09a8b860f84..6b0796a1260d5 100644 --- a/src/test/run-pass/issue-3904.rs +++ b/src/test/run-pass/issue-3904.rs @@ -23,8 +23,8 @@ struct X { err: ErrPrinter } -pub impl X { - fn boom() { +impl X { + pub fn boom() { exit(self.err, "prog", "arg"); } } diff --git a/src/test/run-pass/issue-3979-generics.rs b/src/test/run-pass/issue-3979-generics.rs index 57962911538de..b91ec5711cf21 100644 --- a/src/test/run-pass/issue-3979-generics.rs +++ b/src/test/run-pass/issue-3979-generics.rs @@ -37,5 +37,5 @@ impl Movable for Point; pub fn main() { let p = Point{ x: 1, y: 2}; p.translate(3); - assert!(p.X() == 4); + assert_eq!(p.X(), 4); } diff --git a/src/test/run-pass/issue-3979-xcrate.rs b/src/test/run-pass/issue-3979-xcrate.rs index 5ecf80f481227..4bde414c4acf9 100644 --- a/src/test/run-pass/issue-3979-xcrate.rs +++ b/src/test/run-pass/issue-3979-xcrate.rs @@ -29,5 +29,5 @@ impl Movable for Point; pub fn main() { let mut p = Point{ x: 1, y: 2}; p.translate(3); - assert!(p.X() == 4); + assert_eq!(p.X(), 4); } diff --git a/src/test/run-pass/issue-3979.rs b/src/test/run-pass/issue-3979.rs index 2303c52be58b0..beffea1dbf36c 100644 --- a/src/test/run-pass/issue-3979.rs +++ b/src/test/run-pass/issue-3979.rs @@ -40,5 +40,5 @@ impl Movable for Point; pub fn main() { let mut p = Point{ x: 1, y: 2}; p.translate(3); - assert!(p.X() == 4); + assert_eq!(p.X(), 4); } diff --git a/src/test/run-pass/issue-4016.rs b/src/test/run-pass/issue-4016.rs index 2384b0e859393..4e65a7063e7f0 100644 --- a/src/test/run-pass/issue-4016.rs +++ b/src/test/run-pass/issue-4016.rs @@ -9,11 +9,11 @@ // except according to those terms. // xfail-test -extern mod std; +extern mod extra; use hashmap; -use std::json; -use std::serialization::{Deserializable, deserialize}; +use extra::json; +use extra::serialization::{Deserializable, deserialize}; trait JD : Deserializable { } //type JD = Deserializable; diff --git a/src/test/run-pass/issue-4036.rs b/src/test/run-pass/issue-4036.rs index 8b514b11625e4..ad82071259593 100644 --- a/src/test/run-pass/issue-4036.rs +++ b/src/test/run-pass/issue-4036.rs @@ -11,9 +11,9 @@ // Issue #4036: Test for an issue that arose around fixing up type inference // byproducts in vtable records. -extern mod std; -use self::std::json; -use self::std::serialize; +extern mod extra; +use self::extra::json; +use self::extra::serialize; pub fn main() { let json = json::from_str("[1]").unwrap(); diff --git a/src/test/run-pass/issue-4092.rs b/src/test/run-pass/issue-4092.rs index e129e0a88687a..919c1f7ad184d 100644 --- a/src/test/run-pass/issue-4092.rs +++ b/src/test/run-pass/issue-4092.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::hashmap::HashMap; +use std::hashmap::HashMap; pub fn main() { let mut x = HashMap::new(); diff --git a/src/test/run-pass/issue-4107.rs b/src/test/run-pass/issue-4107.rs new file mode 100644 index 0000000000000..549d9cb734c00 --- /dev/null +++ b/src/test/run-pass/issue-4107.rs @@ -0,0 +1,33 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub fn main() { + let id: &Mat2 = &Matrix::identity(); +} + +pub trait Index { } +pub trait Dimensional: Index { } + +pub struct Mat2 { x: () } +pub struct Vec2 { x: () } + +impl Dimensional> for Mat2 { } +impl Index> for Mat2 { } + +impl Dimensional for Vec2 { } +impl Index for Vec2 { } + +pub trait Matrix: Dimensional { + fn identity() -> Self; +} + +impl Matrix> for Mat2 { + fn identity() -> Mat2 { Mat2{ x: () } } +} diff --git a/src/test/run-pass/issue-4241.rs b/src/test/run-pass/issue-4241.rs index e5905e7a5be21..4aa604160d933 100644 --- a/src/test/run-pass/issue-4241.rs +++ b/src/test/run-pass/issue-4241.rs @@ -9,11 +9,11 @@ // except according to those terms. // xfail-test -extern mod std; +extern mod extra; -use std::net::tcp::TcpSocketBuf; +use extra::net::tcp::TcpSocketBuf; -use core::io::{ReaderUtil,WriterUtil}; +use std::io::{ReaderUtil,WriterUtil}; enum Result { Nil, @@ -28,13 +28,13 @@ priv fn parse_data(len: uint, io: @io::Reader) -> Result { let res = if (len > 0) { let bytes = io.read_bytes(len as uint); - assert!(bytes.len() == len); + assert_eq!(bytes.len(), len); Data(bytes) } else { Data(~[]) }; - assert!(io.read_char() == '\r'); - assert!(io.read_char() == '\n'); + assert_eq!(io.read_char(), '\r'); + assert_eq!(io.read_char(), '\n'); return res; } diff --git a/src/test/run-pass/issue-4333.rs b/src/test/run-pass/issue-4333.rs index 159ba4bb2559e..98280271bdea6 100644 --- a/src/test/run-pass/issue-4333.rs +++ b/src/test/run-pass/issue-4333.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::io; + fn main() { let stdout = &io::stdout() as &io::WriterUtil; stdout.write_line("Hello!"); diff --git a/src/test/run-pass/issue-4401.rs b/src/test/run-pass/issue-4401.rs index e509cb828f840..d0d211c109c85 100644 --- a/src/test/run-pass/issue-4401.rs +++ b/src/test/run-pass/issue-4401.rs @@ -3,6 +3,6 @@ pub fn main() { for 999_999.times() { count += 1; } - assert!(count == 999_999); - io::println(fmt!("%u", count)); + assert_eq!(count, 999_999); + println(fmt!("%u", count)); } diff --git a/src/test/run-pass/issue-4448.rs b/src/test/run-pass/issue-4448.rs index 68abeef15de5f..212406f9a205f 100644 --- a/src/test/run-pass/issue-4448.rs +++ b/src/test/run-pass/issue-4448.rs @@ -8,11 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::comm; +use std::task; + pub fn main() { let (port, chan) = comm::stream::<&'static str>(); do task::spawn { - assert!(port.recv() == "hello, world"); + assert_eq!(port.recv(), "hello, world"); } chan.send("hello, world"); diff --git a/src/test/run-pass/issue-4541.rs b/src/test/run-pass/issue-4541.rs index 37e91cf1eb22a..24a8adfcb1a53 100644 --- a/src/test/run-pass/issue-4541.rs +++ b/src/test/run-pass/issue-4541.rs @@ -10,7 +10,7 @@ // xfail-test fn parse_args() -> ~str { - let args = core::os::args(); + let args = std::os::args(); let mut n = 0; while n < args.len() { diff --git a/src/test/run-pass/issue-4735.rs b/src/test/run-pass/issue-4735.rs new file mode 100644 index 0000000000000..e17fa21732924 --- /dev/null +++ b/src/test/run-pass/issue-4735.rs @@ -0,0 +1,30 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + +use std::cast::transmute; +use std::libc::c_void; + +struct NonCopyable(*c_void); + +impl Drop for NonCopyable { + fn finalize(&self) { + let p = **self; + let v = unsafe { transmute::<*c_void, ~int>(p) }; + } +} + +fn main() { + let t = ~0; + let p = unsafe { transmute::<~int, *c_void>(t) }; + let z = NonCopyable(p); +} + + diff --git a/src/test/run-pass/issue-5353.rs b/src/test/run-pass/issue-5353.rs index f933b616119fa..cc1bb2dd03738 100644 --- a/src/test/run-pass/issue-5353.rs +++ b/src/test/run-pass/issue-5353.rs @@ -22,5 +22,3 @@ fn gl_err_str(err: u32) -> ~str } fn main() {} - - diff --git a/src/test/run-pass/issue-5550.rs b/src/test/run-pass/issue-5550.rs new file mode 100644 index 0000000000000..54abc85053298 --- /dev/null +++ b/src/test/run-pass/issue-5550.rs @@ -0,0 +1,15 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let s: ~str = ~"foobar"; + let mut t: &str = s; + t = t.slice(0, 3); // for master: str::view(t, 0, 3) maybe +} diff --git a/src/test/run-pass/issue-5554.rs b/src/test/run-pass/issue-5554.rs new file mode 100644 index 0000000000000..9a0afc9d228fa --- /dev/null +++ b/src/test/run-pass/issue-5554.rs @@ -0,0 +1,37 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::num::Zero; + +pub struct X { + a: T +} + +// reordering these bounds stops the ICE +impl + Zero for X { + fn zero() -> X { + X { a: Zero::zero() } + } + fn is_zero(&self) -> bool { + self.a.is_zero() + } +} + +macro_rules! constants { + () => { + let _0 : X = Zero::zero(); + } +} + + +pub fn main() { + constants!(); +} diff --git a/src/test/run-pass/issue-5572.rs b/src/test/run-pass/issue-5572.rs index d0db5e5cb3ce4..064413dd93cb5 100644 --- a/src/test/run-pass/issue-5572.rs +++ b/src/test/run-pass/issue-5572.rs @@ -1,3 +1,3 @@ -fn foo(t: T) { } +fn foo(t: T) { } fn main() { } diff --git a/src/test/run-pass/issue-5741.rs b/src/test/run-pass/issue-5741.rs new file mode 100644 index 0000000000000..d6d09cb051022 --- /dev/null +++ b/src/test/run-pass/issue-5741.rs @@ -0,0 +1,16 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::io; + +fn main() { + return; + while io::stdin().read_line() != ~"quit" { }; +} diff --git a/src/test/run-pass/issue-979.rs b/src/test/run-pass/issue-979.rs index 70d7df3f787e7..20bb8ea965ba1 100644 --- a/src/test/run-pass/issue-979.rs +++ b/src/test/run-pass/issue-979.rs @@ -33,5 +33,5 @@ pub fn main() { let p = Some(r(b)); } - assert!(*b == 1); + assert_eq!(*b, 1); } diff --git a/src/test/run-pass/issue2378c.rs b/src/test/run-pass/issue2378c.rs index 98e60c56476d8..ade192618dcf6 100644 --- a/src/test/run-pass/issue2378c.rs +++ b/src/test/run-pass/issue2378c.rs @@ -20,5 +20,5 @@ use issue2378b::{two_maybes}; pub fn main() { let x = two_maybes{a: just(3), b: just(5)}; - assert!(x[0u] == (3, 5)); + assert_eq!(x[0u], (3, 5)); } diff --git a/src/test/run-pass/istr.rs b/src/test/run-pass/istr.rs index 2f641993467c7..a82b263944982 100644 --- a/src/test/run-pass/istr.rs +++ b/src/test/run-pass/istr.rs @@ -12,7 +12,7 @@ fn test_stack_assign() { let s: ~str = ~"a"; debug!(s.clone()); let t: ~str = ~"a"; - assert!((s == t)); + assert!(s == t); let u: ~str = ~"b"; assert!((s != u)); } @@ -22,7 +22,7 @@ fn test_heap_lit() { ~"a big string"; } fn test_heap_assign() { let s: ~str = ~"a big ol' string"; let t: ~str = ~"a big ol' string"; - assert!((s == t)); + assert!(s == t); let u: ~str = ~"a bad ol' string"; assert!((s != u)); } @@ -30,34 +30,34 @@ fn test_heap_assign() { fn test_heap_log() { let s = ~"a big ol' string"; debug!(s); } fn test_stack_add() { - assert!((~"a" + ~"b" == ~"ab")); + assert_eq!(~"a" + ~"b", ~"ab"); let s: ~str = ~"a"; - assert!((s + s == ~"aa")); - assert!((~"" + ~"" == ~"")); + assert_eq!(s + s, ~"aa"); + assert_eq!(~"" + ~"", ~""); } fn test_stack_heap_add() { assert!((~"a" + ~"bracadabra" == ~"abracadabra")); } fn test_heap_add() { - assert!((~"this should" + ~" totally work" == ~"this should totally work")); + assert_eq!(~"this should" + ~" totally work", ~"this should totally work"); } fn test_append() { let mut s = ~""; s += ~"a"; - assert!((s == ~"a")); + assert_eq!(s, ~"a"); let mut s = ~"a"; s += ~"b"; debug!(s.clone()); - assert!((s == ~"ab")); + assert_eq!(s, ~"ab"); let mut s = ~"c"; s += ~"offee"; - assert!((s == ~"coffee")); + assert!(s == ~"coffee"); s += ~"&tea"; - assert!((s == ~"coffee&tea")); + assert!(s == ~"coffee&tea"); } pub fn main() { diff --git a/src/test/run-pass/item-attributes.rs b/src/test/run-pass/item-attributes.rs index c616d46a8336c..de11ce2bdf2cd 100644 --- a/src/test/run-pass/item-attributes.rs +++ b/src/test/run-pass/item-attributes.rs @@ -17,10 +17,10 @@ #[attr4(attr5)]; // Special linkage attributes for the crate -#[link(name = "std", +#[link(name = "extra", vers = "0.1", uuid = "122bed0b-c19b-4b82-b0b7-7ae8aead7297", - url = "http://rust-lang.org/src/std")]; + url = "http://rust-lang.org/src/extra")]; // These are are attributes of the following mod #[attr1 = "val"] @@ -148,7 +148,7 @@ mod test_attr_inner_then_outer_multi { } mod test_distinguish_syntax_ext { - extern mod std; + extern mod extra; pub fn f() { fmt!("test%s", ~"s"); @@ -167,6 +167,8 @@ mod test_other_forms { mod test_foreign_items { pub mod rustrt { + use std::libc; + #[abi = "cdecl"] pub extern { #[attr]; diff --git a/src/test/run-pass/iter-all.rs b/src/test/run-pass/iter-all.rs index b21ddc656c93c..b3177d1f84f2c 100644 --- a/src/test/run-pass/iter-all.rs +++ b/src/test/run-pass/iter-all.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::old_iter; + fn is_even(x: &uint) -> bool { (*x % 2) == 0 } pub fn main() { diff --git a/src/test/run-pass/iter-any.rs b/src/test/run-pass/iter-any.rs index 657c8d7c62459..08a89f8dd2261 100644 --- a/src/test/run-pass/iter-any.rs +++ b/src/test/run-pass/iter-any.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::old_iter; + fn is_even(x: &uint) -> bool { (*x % 2) == 0 } pub fn main() { diff --git a/src/test/run-pass/iter-contains.rs b/src/test/run-pass/iter-contains.rs index fe10ecdcf95e4..5034102c7307c 100644 --- a/src/test/run-pass/iter-contains.rs +++ b/src/test/run-pass/iter-contains.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::old_iter; + pub fn main() { - assert!([].contains(&22u) == false); - assert!([1u, 3u].contains(&22u) == false); - assert!([22u, 1u, 3u].contains(&22u) == true); - assert!([1u, 22u, 3u].contains(&22u) == true); - assert!([1u, 3u, 22u].contains(&22u) == true); - assert!(old_iter::contains(&None::, &22u) == false); - assert!(old_iter::contains(&Some(1u), &22u) == false); - assert!(old_iter::contains(&Some(22u), &22u) == true); + assert_eq!([].contains(&22u), false); + assert_eq!([1u, 3u].contains(&22u), false); + assert_eq!([22u, 1u, 3u].contains(&22u), true); + assert_eq!([1u, 22u, 3u].contains(&22u), true); + assert_eq!([1u, 3u, 22u].contains(&22u), true); + assert_eq!(old_iter::contains(&None::, &22u), false); + assert_eq!(old_iter::contains(&Some(1u), &22u), false); + assert_eq!(old_iter::contains(&Some(22u), &22u), true); } diff --git a/src/test/run-pass/iter-count.rs b/src/test/run-pass/iter-count.rs index 8e061775c2bfa..3f867e49bd43e 100644 --- a/src/test/run-pass/iter-count.rs +++ b/src/test/run-pass/iter-count.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::old_iter; + pub fn main() { - assert!([].count(&22u) == 0u); - assert!([1u, 3u].count(&22u) == 0u); - assert!([22u, 1u, 3u].count(&22u) == 1u); - assert!([22u, 1u, 22u].count(&22u) == 2u); - assert!(old_iter::count(&None::, &22u) == 0u); - assert!(old_iter::count(&Some(1u), &22u) == 0u); - assert!(old_iter::count(&Some(22u), &22u) == 1u); + assert_eq!([].count(&22u), 0u); + assert_eq!([1u, 3u].count(&22u), 0u); + assert_eq!([22u, 1u, 3u].count(&22u), 1u); + assert_eq!([22u, 1u, 22u].count(&22u), 2u); + assert_eq!(old_iter::count(&None::, &22u), 0u); + assert_eq!(old_iter::count(&Some(1u), &22u), 0u); + assert_eq!(old_iter::count(&Some(22u), &22u), 1u); } diff --git a/src/test/run-pass/iter-eachi.rs b/src/test/run-pass/iter-eachi.rs index 03130a6632c3c..0740f2cb8e46e 100644 --- a/src/test/run-pass/iter-eachi.rs +++ b/src/test/run-pass/iter-eachi.rs @@ -8,20 +8,22 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::old_iter; + pub fn main() { let mut c = 0u; for [1u, 2u, 3u, 4u, 5u].eachi |i, v| { - assert!((i + 1u) == *v); + assert_eq!((i + 1u), *v); c += 1u; } - assert!(c == 5u); + assert_eq!(c, 5u); for old_iter::eachi(&None::) |i, v| { fail!(); } let mut c = 0u; for old_iter::eachi(&Some(1u)) |i, v| { - assert!((i + 1u) == *v); + assert_eq!((i + 1u), *v); c += 1u; } - assert!(c == 1u); + assert_eq!(c, 1u); } diff --git a/src/test/run-pass/iter-filter-to-vec.rs b/src/test/run-pass/iter-filter-to-vec.rs index a9cdec9a0b7cc..2b254765c763f 100644 --- a/src/test/run-pass/iter-filter-to-vec.rs +++ b/src/test/run-pass/iter-filter-to-vec.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::old_iter; + fn is_even(x: &uint) -> bool { (*x % 2) == 0 } pub fn main() { - assert!([1, 3].filter_to_vec(is_even) == ~[]); - assert!([1, 2, 3].filter_to_vec(is_even) == ~[2]); - assert!(old_iter::filter_to_vec(&None::, is_even) == ~[]); - assert!(old_iter::filter_to_vec(&Some(1u), is_even) == ~[]); - assert!(old_iter::filter_to_vec(&Some(2u), is_even) == ~[2]); + assert_eq!([1, 3].filter_to_vec(is_even), ~[]); + assert_eq!([1, 2, 3].filter_to_vec(is_even), ~[2]); + assert_eq!(old_iter::filter_to_vec(&None::, is_even), ~[]); + assert_eq!(old_iter::filter_to_vec(&Some(1u), is_even), ~[]); + assert_eq!(old_iter::filter_to_vec(&Some(2u), is_even), ~[2]); } diff --git a/src/test/run-pass/iter-flat-map-to-vec.rs b/src/test/run-pass/iter-flat-map-to-vec.rs index d9a7791527e44..b0b61aaa816c5 100644 --- a/src/test/run-pass/iter-flat-map-to-vec.rs +++ b/src/test/run-pass/iter-flat-map-to-vec.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::old_iter; + fn repeat(x: &uint) -> ~[uint] { ~[*x, *x] } fn incd_if_even(x: &uint) -> Option { @@ -15,15 +17,15 @@ fn incd_if_even(x: &uint) -> Option { } pub fn main() { - assert!((~[1u, 3u]).flat_map_to_vec(repeat) == ~[1u, 1u, 3u, 3u]); - assert!((~[]).flat_map_to_vec(repeat) == ~[]); - assert!(old_iter::flat_map_to_vec(&None::, repeat) == ~[]); - assert!(old_iter::flat_map_to_vec(&Some(1u), repeat) == ~[1u, 1u]); - assert!(old_iter::flat_map_to_vec(&Some(2u), repeat) == ~[2u, 2u]); + assert_eq!((~[1u, 3u]).flat_map_to_vec(repeat), ~[1u, 1u, 3u, 3u]); + assert_eq!((~[]).flat_map_to_vec(repeat), ~[]); + assert_eq!(old_iter::flat_map_to_vec(&None::, repeat), ~[]); + assert_eq!(old_iter::flat_map_to_vec(&Some(1u), repeat), ~[1u, 1u]); + assert_eq!(old_iter::flat_map_to_vec(&Some(2u), repeat), ~[2u, 2u]); - assert!((~[1u, 2u, 5u]).flat_map_to_vec(incd_if_even) == ~[3u]); - assert!((~[]).flat_map_to_vec(incd_if_even) == ~[]); - assert!(old_iter::flat_map_to_vec(&None::, incd_if_even) == ~[]); - assert!(old_iter::flat_map_to_vec(&Some(1u), incd_if_even) == ~[]); - assert!(old_iter::flat_map_to_vec(&Some(2u), incd_if_even) == ~[3u]); + assert_eq!((~[1u, 2u, 5u]).flat_map_to_vec(incd_if_even), ~[3u]); + assert_eq!((~[]).flat_map_to_vec(incd_if_even), ~[]); + assert_eq!(old_iter::flat_map_to_vec(&None::, incd_if_even), ~[]); + assert_eq!(old_iter::flat_map_to_vec(&Some(1u), incd_if_even), ~[]); + assert_eq!(old_iter::flat_map_to_vec(&Some(2u), incd_if_even), ~[3u]); } diff --git a/src/test/run-pass/iter-foldl.rs b/src/test/run-pass/iter-foldl.rs index b299cf8322505..7e5890b3e3a33 100644 --- a/src/test/run-pass/iter-foldl.rs +++ b/src/test/run-pass/iter-foldl.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::old_iter; + fn add(x: &float, y: &uint) -> float { *x + ((*y) as float) } pub fn main() { - assert!([1u, 3u].foldl(20f, add) == 24f); - assert!([].foldl(20f, add) == 20f); - assert!(old_iter::foldl(&None::, 20f, add) == 20f); - assert!(old_iter::foldl(&Some(1u), 20f, add) == 21f); - assert!(old_iter::foldl(&Some(2u), 20f, add) == 22f); + assert_eq!([1u, 3u].foldl(20f, add), 24f); + assert_eq!([].foldl(20f, add), 20f); + assert_eq!(old_iter::foldl(&None::, 20f, add), 20f); + assert_eq!(old_iter::foldl(&Some(1u), 20f, add), 21f); + assert_eq!(old_iter::foldl(&Some(2u), 20f, add), 22f); } diff --git a/src/test/run-pass/iter-map-to-vec.rs b/src/test/run-pass/iter-map-to-vec.rs index 4e9976e4eb9d3..706f0c5c150e1 100644 --- a/src/test/run-pass/iter-map-to-vec.rs +++ b/src/test/run-pass/iter-map-to-vec.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::old_iter; + fn inc(x: &uint) -> uint { *x + 1 } pub fn main() { - assert!([1, 3].map_to_vec(inc) == ~[2, 4]); - assert!([1, 2, 3].map_to_vec(inc) == ~[2, 3, 4]); - assert!(old_iter::map_to_vec(&None::, inc) == ~[]); - assert!(old_iter::map_to_vec(&Some(1u), inc) == ~[2]); - assert!(old_iter::map_to_vec(&Some(2u), inc) == ~[3]); + assert_eq!([1, 3].map_to_vec(inc), ~[2, 4]); + assert_eq!([1, 2, 3].map_to_vec(inc), ~[2, 3, 4]); + assert_eq!(old_iter::map_to_vec(&None::, inc), ~[]); + assert_eq!(old_iter::map_to_vec(&Some(1u), inc), ~[2]); + assert_eq!(old_iter::map_to_vec(&Some(2u), inc), ~[3]); } diff --git a/src/test/run-pass/iter-min-max.rs b/src/test/run-pass/iter-min-max.rs index 5f427861e7917..9020976029d25 100644 --- a/src/test/run-pass/iter-min-max.rs +++ b/src/test/run-pass/iter-min-max.rs @@ -8,14 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::old_iter; + fn is_even(x: uint) -> bool { (x % 2u) == 0u } pub fn main() { - assert!([1u, 3u].min() == 1u); - assert!([3u, 1u].min() == 1u); - assert!(old_iter::min(&Some(1u)) == 1u); + assert_eq!([1u, 3u].min(), 1u); + assert_eq!([3u, 1u].min(), 1u); + assert_eq!(old_iter::min(&Some(1u)), 1u); - assert!([1u, 3u].max() == 3u); - assert!([3u, 1u].max() == 3u); - assert!(old_iter::max(&Some(3u)) == 3u); + assert_eq!([1u, 3u].max(), 3u); + assert_eq!([3u, 1u].max(), 3u); + assert_eq!(old_iter::max(&Some(3u)), 3u); } diff --git a/src/test/run-pass/iter-to-vec.rs b/src/test/run-pass/iter-to-vec.rs index d7fdcdbe4e0a0..317b608963790 100644 --- a/src/test/run-pass/iter-to-vec.rs +++ b/src/test/run-pass/iter-to-vec.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::old_iter; + pub fn main() { - assert!([1u, 3u].to_vec() == ~[1u, 3u]); + assert_eq!([1u, 3u].to_vec(), ~[1u, 3u]); let e: ~[uint] = ~[]; - assert!(e.to_vec() == ~[]); - assert!(old_iter::to_vec(&None::) == ~[]); - assert!(old_iter::to_vec(&Some(1u)) == ~[1u]); - assert!(old_iter::to_vec(&Some(2u)) == ~[2u]); + assert_eq!(e.to_vec(), ~[]); + assert_eq!(old_iter::to_vec(&None::), ~[]); + assert_eq!(old_iter::to_vec(&Some(1u)), ~[1u]); + assert_eq!(old_iter::to_vec(&Some(2u)), ~[2u]); } diff --git a/src/test/run-pass/ivec-add.rs b/src/test/run-pass/ivec-add.rs index bd58ae6565143..80168daf62d08 100644 --- a/src/test/run-pass/ivec-add.rs +++ b/src/test/run-pass/ivec-add.rs @@ -14,10 +14,10 @@ fn double_int(a: int) -> ~[int] { return ~[a] + ~[a]; } pub fn main() { let mut d = double(1); - assert!((d[0] == 1)); - assert!((d[1] == 1)); + assert_eq!(d[0], 1); + assert_eq!(d[1], 1); d = double_int(1); - assert!((d[0] == 1)); - assert!((d[1] == 1)); + assert_eq!(d[0], 1); + assert_eq!(d[1], 1); } diff --git a/src/test/run-pass/ivec-tag.rs b/src/test/run-pass/ivec-tag.rs index 017d90cbcd736..8d87ff400614c 100644 --- a/src/test/run-pass/ivec-tag.rs +++ b/src/test/run-pass/ivec-tag.rs @@ -1,4 +1,5 @@ -use core::comm::*; +use std::comm::*; +use std::task; fn producer(c: &Chan<~[u8]>) { c.send( diff --git a/src/test/run-pass/kindck-owned-trait-contains-1.rs b/src/test/run-pass/kindck-owned-trait-contains-1.rs index 3fb554dc4509a..35b5e077e7af7 100644 --- a/src/test/run-pass/kindck-owned-trait-contains-1.rs +++ b/src/test/run-pass/kindck-owned-trait-contains-1.rs @@ -22,5 +22,5 @@ fn repeater(v: @A) -> @repeat { pub fn main() { let x = &3; let y = repeater(@x); - assert!(*x == *(y.get())); + assert_eq!(*x, *(y.get())); } diff --git a/src/test/run-pass/last-use-in-cap-clause.rs b/src/test/run-pass/last-use-in-cap-clause.rs index 442e79bde77ce..75c3008af8eb3 100644 --- a/src/test/run-pass/last-use-in-cap-clause.rs +++ b/src/test/run-pass/last-use-in-cap-clause.rs @@ -20,5 +20,5 @@ fn foo() -> @fn() -> int { } pub fn main() { - assert!(foo()() == 22); + assert_eq!(foo()(), 22); } diff --git a/src/test/run-pass/lazy-and-or.rs b/src/test/run-pass/lazy-and-or.rs index 1a1e4816a361a..74febe6ff7dcd 100644 --- a/src/test/run-pass/lazy-and-or.rs +++ b/src/test/run-pass/lazy-and-or.rs @@ -17,6 +17,6 @@ pub fn main() { assert!((x)); let mut y: int = 10; debug!(x || incr(&mut y)); - assert!((y == 10)); + assert_eq!(y, 10); if true && x { assert!((true)); } else { assert!((false)); } } diff --git a/src/test/run-pass/let-assignability.rs b/src/test/run-pass/let-assignability.rs index 0afc3ee87e0f4..2a341474872c3 100644 --- a/src/test/run-pass/let-assignability.rs +++ b/src/test/run-pass/let-assignability.rs @@ -11,7 +11,7 @@ fn f() { let a = ~"hello"; let b: &str = a; - io::println(b); + println(b); } pub fn main() { diff --git a/src/test/run-pass/let-destruct-fresh-mem.rs b/src/test/run-pass/let-destruct-fresh-mem.rs index ae6118d063e9e..500502320df0f 100644 --- a/src/test/run-pass/let-destruct-fresh-mem.rs +++ b/src/test/run-pass/let-destruct-fresh-mem.rs @@ -16,8 +16,8 @@ pub fn main() { let mut X {x: x, y: @A {a: a}} = u; x = 100; a = 100; - assert!((x == 100)); - assert!((a == 100)); - assert!((u.x == 10)); - assert!((u.y.a == 20)); + assert_eq!(x, 100); + assert_eq!(a, 100); + assert_eq!(u.x, 10); + assert_eq!(u.y.a, 20); } diff --git a/src/test/run-pass/let-destruct.rs b/src/test/run-pass/let-destruct.rs index 6e2ce508928a7..aab19b31397b6 100644 --- a/src/test/run-pass/let-destruct.rs +++ b/src/test/run-pass/let-destruct.rs @@ -14,5 +14,5 @@ struct X { x: xx, y: int } pub fn main() { let @X {x: xx(x), y: y} = @X{x: xx(10), y: 20}; - assert!((x + y == 30)); + assert_eq!(x + y, 30); } diff --git a/src/test/run-pass/linear-for-loop.rs b/src/test/run-pass/linear-for-loop.rs index f2fb63cfc9e79..7ab915a96284f 100644 --- a/src/test/run-pass/linear-for-loop.rs +++ b/src/test/run-pass/linear-for-loop.rs @@ -8,14 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +use std::str; pub fn main() { let x = ~[1, 2, 3]; let mut y = 0; for x.each |i| { debug!(*i); y += *i; } debug!(y); - assert!((y == 6)); + assert_eq!(y, 6); let s = ~"hello there"; let mut i: int = 0; for str::each(s) |c| { @@ -30,5 +30,5 @@ pub fn main() { debug!(i); debug!(c); } - assert!((i == 11)); + assert_eq!(i, 11); } diff --git a/src/test/run-pass/log-knows-the-names-of-variants-in-std.rs b/src/test/run-pass/log-knows-the-names-of-variants-in-std.rs index 44e1292d9b1c1..ae2ae6dbf9ce0 100644 --- a/src/test/run-pass/log-knows-the-names-of-variants-in-std.rs +++ b/src/test/run-pass/log-knows-the-names-of-variants-in-std.rs @@ -10,8 +10,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; -use std::list; +extern mod extra; +use extra::list; enum foo { a(uint), @@ -19,7 +19,7 @@ enum foo { } fn check_log(exp: ~str, v: T) { - assert!(exp == fmt!("%?", v)); + assert_eq!(exp, fmt!("%?", v)); } pub fn main() { diff --git a/src/test/run-pass/log-knows-the-names-of-variants.rs b/src/test/run-pass/log-knows-the-names-of-variants.rs index 641d6155e23a9..7a0d763f7e0f4 100644 --- a/src/test/run-pass/log-knows-the-names-of-variants.rs +++ b/src/test/run-pass/log-knows-the-names-of-variants.rs @@ -19,8 +19,8 @@ enum bar { } pub fn main() { - assert!(~"a(22)" == fmt!("%?", a(22u))); - assert!(~"b(~\"hi\")" == fmt!("%?", b(~"hi"))); - assert!(~"c" == fmt!("%?", c)); - assert!(~"d" == fmt!("%?", d)); + assert_eq!(~"a(22)", fmt!("%?", a(22u))); + assert_eq!(~"b(~\"hi\")", fmt!("%?", b(~"hi"))); + assert_eq!(~"c", fmt!("%?", c)); + assert_eq!(~"d", fmt!("%?", d)); } diff --git a/src/test/run-pass/log-str.rs b/src/test/run-pass/log-str.rs index e321789a2b1a1..fc48f4aea0c1e 100644 --- a/src/test/run-pass/log-str.rs +++ b/src/test/run-pass/log-str.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::sys; + pub fn main() { let act = sys::log_str(&~[1, 2, 3]); - assert!(~"~[1, 2, 3]" == act); + assert_eq!(~"~[1, 2, 3]", act); let act = fmt!("%?/%6?", ~[1, 2, 3], ~"hi"); - assert!(act == ~"~[1, 2, 3]/ ~\"hi\""); + assert_eq!(act, ~"~[1, 2, 3]/ ~\"hi\""); } diff --git a/src/test/run-pass/loop-break-cont.rs b/src/test/run-pass/loop-break-cont.rs index 4a4da79367fb4..64d2b3d0b215b 100644 --- a/src/test/run-pass/loop-break-cont.rs +++ b/src/test/run-pass/loop-break-cont.rs @@ -17,7 +17,7 @@ pub fn main() { break; } } - assert!((i == 10u)); + assert_eq!(i, 10u); let mut is_even = false; loop { if i == 21u { diff --git a/src/test/run-pass/loop-scope.rs b/src/test/run-pass/loop-scope.rs index a3caf1e4800d2..07be3bd6c81f5 100644 --- a/src/test/run-pass/loop-scope.rs +++ b/src/test/run-pass/loop-scope.rs @@ -12,5 +12,5 @@ pub fn main() { let x = ~[10, 20, 30]; let mut sum = 0; for x.each |x| { sum += *x; } - assert!((sum == 60)); + assert_eq!(sum, 60); } diff --git a/src/test/run-pass/lots-a-fail.rs b/src/test/run-pass/lots-a-fail.rs index ed9e6e540305d..04486a83455bd 100644 --- a/src/test/run-pass/lots-a-fail.rs +++ b/src/test/run-pass/lots-a-fail.rs @@ -9,7 +9,10 @@ // except according to those terms. // xfail-win32 leaks -extern mod std; +extern mod extra; + +use std::task; +use std::uint; fn die() { fail!(); diff --git a/src/test/run-pass/macro-path.rs b/src/test/run-pass/macro-path.rs index a3bd03c80bc46..4aa1587943413 100644 --- a/src/test/run-pass/macro-path.rs +++ b/src/test/run-pass/macro-path.rs @@ -20,5 +20,5 @@ macro_rules! foo { } pub fn main() { - assert!(foo!(m::t) == 10); + assert_eq!(foo!(m::t), 10); } diff --git a/src/test/run-pass/macro-stmt.rs b/src/test/run-pass/macro-stmt.rs index d9417ee0a1953..66f16bc9f2e03 100644 --- a/src/test/run-pass/macro-stmt.rs +++ b/src/test/run-pass/macro-stmt.rs @@ -27,16 +27,16 @@ pub fn main() { ); mylet!(y, 8*2); - assert!((y == 16)); + assert_eq!(y, 16); myfn!(mult, (a,b), { a*b } ); - assert!((mult(2, add(4,4)) == 16)); + assert_eq!(mult(2, add(4,4)), 16); macro_rules! actually_an_expr_macro ( () => ( 16 ) ) - assert!({ actually_an_expr_macro!() } == 16); + assert_eq!({ actually_an_expr_macro!() }, 16); } diff --git a/src/test/run-pass/alt-borrowed_str.rs b/src/test/run-pass/match-borrowed_str.rs similarity index 100% rename from src/test/run-pass/alt-borrowed_str.rs rename to src/test/run-pass/match-borrowed_str.rs diff --git a/src/test/run-pass/alt-bot-2.rs b/src/test/run-pass/match-bot-2.rs similarity index 100% rename from src/test/run-pass/alt-bot-2.rs rename to src/test/run-pass/match-bot-2.rs diff --git a/src/test/run-pass/alt-bot.rs b/src/test/run-pass/match-bot.rs similarity index 100% rename from src/test/run-pass/alt-bot.rs rename to src/test/run-pass/match-bot.rs diff --git a/src/test/run-pass/alt-implicit-copy-unique.rs b/src/test/run-pass/match-implicit-copy-unique.rs similarity index 100% rename from src/test/run-pass/alt-implicit-copy-unique.rs rename to src/test/run-pass/match-implicit-copy-unique.rs diff --git a/src/test/run-pass/alt-join.rs b/src/test/run-pass/match-join.rs similarity index 97% rename from src/test/run-pass/alt-join.rs rename to src/test/run-pass/match-join.rs index b9f25396b32c8..66b6476806094 100644 --- a/src/test/run-pass/alt-join.rs +++ b/src/test/run-pass/match-join.rs @@ -9,7 +9,7 @@ // except according to those terms. -extern mod std; +extern mod extra; fn foo(y: Option) { let mut x: int; diff --git a/src/test/run-pass/alt-naked-record-expr.rs b/src/test/run-pass/match-naked-record-expr.rs similarity index 100% rename from src/test/run-pass/alt-naked-record-expr.rs rename to src/test/run-pass/match-naked-record-expr.rs diff --git a/src/test/run-pass/alt-naked-record.rs b/src/test/run-pass/match-naked-record.rs similarity index 100% rename from src/test/run-pass/alt-naked-record.rs rename to src/test/run-pass/match-naked-record.rs diff --git a/src/test/run-pass/alt-path.rs b/src/test/run-pass/match-path.rs similarity index 100% rename from src/test/run-pass/alt-path.rs rename to src/test/run-pass/match-path.rs diff --git a/src/test/run-pass/alt-pattern-drop.rs b/src/test/run-pass/match-pattern-drop.rs similarity index 67% rename from src/test/run-pass/alt-pattern-drop.rs rename to src/test/run-pass/match-pattern-drop.rs index d9f3f10a11b03..71bbb1768e892 100644 --- a/src/test/run-pass/alt-pattern-drop.rs +++ b/src/test/run-pass/match-pattern-drop.rs @@ -14,7 +14,7 @@ enum t { make_t(@int), clam, } fn foo(s: @int) { - let count = ::core::sys::refcount(s); + let count = ::std::sys::refcount(s); let x: t = make_t(s); // ref up match x { @@ -24,20 +24,20 @@ fn foo(s: @int) { } _ => { debug!("?"); fail!(); } } - debug!(::core::sys::refcount(s)); - assert_eq!(::core::sys::refcount(s), count + 1u); - let _ = ::core::sys::refcount(s); // don't get bitten by last-use. + debug!(::std::sys::refcount(s)); + assert_eq!(::std::sys::refcount(s), count + 1u); + let _ = ::std::sys::refcount(s); // don't get bitten by last-use. } pub fn main() { let s: @int = @0; // ref up - let count = ::core::sys::refcount(s); + let count = ::std::sys::refcount(s); foo(s); // ref up then down - debug!("%u", ::core::sys::refcount(s)); - let count2 = ::core::sys::refcount(s); - let _ = ::core::sys::refcount(s); // don't get bitten by last-use. + debug!("%u", ::std::sys::refcount(s)); + let count2 = ::std::sys::refcount(s); + let _ = ::std::sys::refcount(s); // don't get bitten by last-use. assert_eq!(count, count2); } diff --git a/src/test/run-pass/alt-pattern-lit.rs b/src/test/run-pass/match-pattern-lit.rs similarity index 100% rename from src/test/run-pass/alt-pattern-lit.rs rename to src/test/run-pass/match-pattern-lit.rs diff --git a/src/test/run-pass/alt-pattern-no-type-params.rs b/src/test/run-pass/match-pattern-no-type-params.rs similarity index 100% rename from src/test/run-pass/alt-pattern-no-type-params.rs rename to src/test/run-pass/match-pattern-no-type-params.rs diff --git a/src/test/run-pass/alt-pattern-simple.rs b/src/test/run-pass/match-pattern-simple.rs similarity index 100% rename from src/test/run-pass/alt-pattern-simple.rs rename to src/test/run-pass/match-pattern-simple.rs diff --git a/src/test/run-pass/alt-phi.rs b/src/test/run-pass/match-phi.rs similarity index 100% rename from src/test/run-pass/alt-phi.rs rename to src/test/run-pass/match-phi.rs diff --git a/src/test/run-pass/match-range-static.rs b/src/test/run-pass/match-range-static.rs index 3eefc386250ed..aa216b8d05487 100644 --- a/src/test/run-pass/match-range-static.rs +++ b/src/test/run-pass/match-range-static.rs @@ -7,4 +7,3 @@ fn main() { _ => (), } } - diff --git a/src/test/run-pass/alt-range.rs b/src/test/run-pass/match-range.rs similarity index 100% rename from src/test/run-pass/alt-range.rs rename to src/test/run-pass/match-range.rs diff --git a/src/test/run-pass/alt-ref-binding-in-guard-3256.rs b/src/test/run-pass/match-ref-binding-in-guard-3256.rs similarity index 66% rename from src/test/run-pass/alt-ref-binding-in-guard-3256.rs rename to src/test/run-pass/match-ref-binding-in-guard-3256.rs index ed7a631637433..a199a75de56cb 100644 --- a/src/test/run-pass/alt-ref-binding-in-guard-3256.rs +++ b/src/test/run-pass/match-ref-binding-in-guard-3256.rs @@ -8,12 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::unstable; + pub fn main() { - let x = Some(unstable::sync::exclusive(true)); - match x { - Some(ref z) if z.with(|b| *b) => { - do z.with |b| { assert!(*b); } - }, - _ => fail!() + unsafe { + let x = Some(unstable::sync::exclusive(true)); + match x { + Some(ref z) if z.with(|b| *b) => { + do z.with |b| { assert!(*b); } + }, + _ => fail!() + } } } diff --git a/src/test/run-pass/alt-ref-binding-mut-option.rs b/src/test/run-pass/match-ref-binding-mut-option.rs similarity index 95% rename from src/test/run-pass/alt-ref-binding-mut-option.rs rename to src/test/run-pass/match-ref-binding-mut-option.rs index 9ef414d1170be..8d1e483bcd848 100644 --- a/src/test/run-pass/alt-ref-binding-mut-option.rs +++ b/src/test/run-pass/match-ref-binding-mut-option.rs @@ -14,5 +14,5 @@ pub fn main() { None => {} Some(ref mut p) => { *p += 1; } } - assert!(v == Some(23)); + assert_eq!(v, Some(23)); } diff --git a/src/test/run-pass/alt-ref-binding-mut.rs b/src/test/run-pass/match-ref-binding-mut.rs similarity index 96% rename from src/test/run-pass/alt-ref-binding-mut.rs rename to src/test/run-pass/match-ref-binding-mut.rs index 2bd55b46784b8..266f7cdde11af 100644 --- a/src/test/run-pass/alt-ref-binding-mut.rs +++ b/src/test/run-pass/match-ref-binding-mut.rs @@ -21,5 +21,5 @@ fn destructure(x: &mut Rec) { pub fn main() { let mut v = Rec {f: 22}; destructure(&mut v); - assert!(v.f == 23); + assert_eq!(v.f, 23); } diff --git a/src/test/run-pass/alt-ref-binding.rs b/src/test/run-pass/match-ref-binding.rs similarity index 93% rename from src/test/run-pass/alt-ref-binding.rs rename to src/test/run-pass/match-ref-binding.rs index 23b3062a83a8f..0b613df18ee83 100644 --- a/src/test/run-pass/alt-ref-binding.rs +++ b/src/test/run-pass/match-ref-binding.rs @@ -16,5 +16,5 @@ fn destructure(x: Option) -> int { } pub fn main() { - assert!(destructure(Some(22)) == 22); + assert_eq!(destructure(Some(22)), 22); } diff --git a/src/test/run-pass/alt-str.rs b/src/test/run-pass/match-str.rs similarity index 97% rename from src/test/run-pass/alt-str.rs rename to src/test/run-pass/match-str.rs index e41ec8a99e93f..8bbcc507f184f 100644 --- a/src/test/run-pass/alt-str.rs +++ b/src/test/run-pass/match-str.rs @@ -24,7 +24,7 @@ pub fn main() { } let x = match ~"a" { ~"a" => 1, ~"b" => 2, _ => fail!() }; - assert!((x == 1)); + assert_eq!(x, 1); match ~"a" { ~"a" => { } ~"b" => { }, _ => fail!() } diff --git a/src/test/run-pass/alt-tag.rs b/src/test/run-pass/match-tag.rs similarity index 89% rename from src/test/run-pass/alt-tag.rs rename to src/test/run-pass/match-tag.rs index e2e1bf540c2ce..9eeb12d9c45f2 100644 --- a/src/test/run-pass/alt-tag.rs +++ b/src/test/run-pass/match-tag.rs @@ -32,7 +32,7 @@ pub fn main() { let gray: color = rgb(127, 127, 127); let clear: color = rgba(50, 150, 250, 0); let red: color = hsl(0, 255, 255); - assert!((process(gray) == 127)); - assert!((process(clear) == 0)); - assert!((process(red) == 255)); + assert_eq!(process(gray), 127); + assert_eq!(process(clear), 0); + assert_eq!(process(red), 255); } diff --git a/src/test/run-pass/alt-unique-bind.rs b/src/test/run-pass/match-unique-bind.rs similarity index 95% rename from src/test/run-pass/alt-unique-bind.rs rename to src/test/run-pass/match-unique-bind.rs index 2fb0a345157ee..997cc1ee9ff9d 100644 --- a/src/test/run-pass/alt-unique-bind.rs +++ b/src/test/run-pass/match-unique-bind.rs @@ -12,7 +12,7 @@ pub fn main() { match ~100 { ~x => { debug!("%?", x); - assert!(x == 100); + assert_eq!(x, 100); } } } diff --git a/src/test/run-pass/alt-value-binding-in-guard-3291.rs b/src/test/run-pass/match-value-binding-in-guard-3291.rs similarity index 100% rename from src/test/run-pass/alt-value-binding-in-guard-3291.rs rename to src/test/run-pass/match-value-binding-in-guard-3291.rs diff --git a/src/test/run-pass/match-vec-rvalue.rs b/src/test/run-pass/match-vec-rvalue.rs new file mode 100644 index 0000000000000..5f68b0e9a6953 --- /dev/null +++ b/src/test/run-pass/match-vec-rvalue.rs @@ -0,0 +1,12 @@ +// Tests that matching rvalues with drops does not crash. + +fn main() { + match ~[1, 2, 3] { + x => { + assert_eq!(x.len(), 3); + assert_eq!(x[0], 1); + assert_eq!(x[1], 2); + assert_eq!(x[2], 3); + } + } +} diff --git a/src/test/run-pass/alt-with-ret-arm.rs b/src/test/run-pass/match-with-ret-arm.rs similarity index 94% rename from src/test/run-pass/alt-with-ret-arm.rs rename to src/test/run-pass/match-with-ret-arm.rs index d5d2e20cba3d5..fb85064bfdee5 100644 --- a/src/test/run-pass/alt-with-ret-arm.rs +++ b/src/test/run-pass/match-with-ret-arm.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::uint; + pub fn main() { // sometimes we have had trouble finding // the right type for f, as we unified @@ -16,6 +18,6 @@ pub fn main() { None => return (), Some(num) => num as u32 }; - assert!(f == 1234u32); + assert_eq!(f, 1234u32); error!(f) } diff --git a/src/test/run-pass/max-min-classes.rs b/src/test/run-pass/max-min-classes.rs index d986d7e676a12..c34067c329d27 100644 --- a/src/test/run-pass/max-min-classes.rs +++ b/src/test/run-pass/max-min-classes.rs @@ -17,8 +17,8 @@ struct Foo { y: int, } -pub impl Foo { - fn sum(&self) -> int { +impl Foo { + pub fn sum(&self) -> int { self.x + self.y } } @@ -35,5 +35,5 @@ fn Foo(x: int, y: int) -> Foo { pub fn main() { let foo = Foo(3, 20); - io::println(fmt!("%d %d", foo.sum(), foo.product())); + println(fmt!("%d %d", foo.sum(), foo.product())); } diff --git a/src/test/run-pass/mlist-cycle.rs b/src/test/run-pass/mlist-cycle.rs index a67f1574f64af..cb33feef539ef 100644 --- a/src/test/run-pass/mlist-cycle.rs +++ b/src/test/run-pass/mlist-cycle.rs @@ -10,9 +10,9 @@ // xfail-test // -*- rust -*- -extern mod core; -use core::gc; -use core::gc::rustrt; +extern mod std; +use std::gc; +use std::gc::rustrt; struct cell {c: @list} diff --git a/src/test/run-pass/mod-inside-fn.rs b/src/test/run-pass/mod-inside-fn.rs index e4bc850644e4b..388d2e4905fab 100644 --- a/src/test/run-pass/mod-inside-fn.rs +++ b/src/test/run-pass/mod-inside-fn.rs @@ -17,5 +17,5 @@ fn f() -> int { } pub fn main() { - assert!(f() == 720); + assert_eq!(f(), 720); } diff --git a/src/test/run-pass/mod-view-items.rs b/src/test/run-pass/mod-view-items.rs index 7dbcb72f1eaf3..2fc2d4b371605 100644 --- a/src/test/run-pass/mod-view-items.rs +++ b/src/test/run-pass/mod-view-items.rs @@ -17,7 +17,7 @@ // begin failing. mod m { - use core::vec; + use std::vec; pub fn f() -> ~[int] { vec::from_elem(1u, 0) } } diff --git a/src/test/run-pass/mod_dir_path.rs b/src/test/run-pass/mod_dir_path.rs index f0cc4aa52d665..a356a0ab07e91 100644 --- a/src/test/run-pass/mod_dir_path.rs +++ b/src/test/run-pass/mod_dir_path.rs @@ -17,5 +17,5 @@ mod mod_dir_simple { } pub fn main() { - assert!(mod_dir_simple::syrup::foo() == 10); + assert_eq!(mod_dir_simple::syrup::foo(), 10); } diff --git a/src/test/run-pass/mod_dir_path2.rs b/src/test/run-pass/mod_dir_path2.rs index 2635084a07273..6119e9631e8d2 100644 --- a/src/test/run-pass/mod_dir_path2.rs +++ b/src/test/run-pass/mod_dir_path2.rs @@ -18,5 +18,5 @@ mod pancakes { } pub fn main() { - assert!(pancakes::syrup::foo() == 10); + assert_eq!(pancakes::syrup::foo(), 10); } diff --git a/src/test/run-pass/mod_dir_path3.rs b/src/test/run-pass/mod_dir_path3.rs index 0971120eb6f7d..00282658508b8 100644 --- a/src/test/run-pass/mod_dir_path3.rs +++ b/src/test/run-pass/mod_dir_path3.rs @@ -17,5 +17,5 @@ mod pancakes { } pub fn main() { - assert!(pancakes::test::foo() == 10); + assert_eq!(pancakes::test::foo(), 10); } diff --git a/src/test/run-pass/mod_dir_path_multi.rs b/src/test/run-pass/mod_dir_path_multi.rs index c6ab45d1b3a4d..4766d330a4e43 100644 --- a/src/test/run-pass/mod_dir_path_multi.rs +++ b/src/test/run-pass/mod_dir_path_multi.rs @@ -22,6 +22,6 @@ mod gravy { } pub fn main() { - assert!(biscuits::test::foo() == 10); - assert!(gravy::test::foo() == 10); + assert_eq!(biscuits::test::foo(), 10); + assert_eq!(gravy::test::foo(), 10); } diff --git a/src/test/run-pass/mod_dir_recursive.rs b/src/test/run-pass/mod_dir_recursive.rs index 5392671651d1a..a39d41414ff9c 100644 --- a/src/test/run-pass/mod_dir_recursive.rs +++ b/src/test/run-pass/mod_dir_recursive.rs @@ -20,5 +20,5 @@ mod mod_dir_simple { } pub fn main() { - assert!(mod_dir_simple::load_another_mod::test::foo() == 10); + assert_eq!(mod_dir_simple::load_another_mod::test::foo(), 10); } diff --git a/src/test/run-pass/mod_dir_simple.rs b/src/test/run-pass/mod_dir_simple.rs index 382911d49793f..fbc522f07b283 100644 --- a/src/test/run-pass/mod_dir_simple.rs +++ b/src/test/run-pass/mod_dir_simple.rs @@ -16,5 +16,5 @@ mod mod_dir_simple { } pub fn main() { - assert!(mod_dir_simple::test::foo() == 10); + assert_eq!(mod_dir_simple::test::foo(), 10); } diff --git a/src/test/run-pass/mod_file.rs b/src/test/run-pass/mod_file.rs index a03dc04401141..b2dd931161572 100644 --- a/src/test/run-pass/mod_file.rs +++ b/src/test/run-pass/mod_file.rs @@ -15,5 +15,5 @@ mod mod_file_aux; pub fn main() { - assert!(mod_file_aux::foo() == 10); + assert_eq!(mod_file_aux::foo(), 10); } diff --git a/src/test/run-pass/mod_file_with_path_attr.rs b/src/test/run-pass/mod_file_with_path_attr.rs index ecd4fd73a062f..8455b662efaa1 100644 --- a/src/test/run-pass/mod_file_with_path_attr.rs +++ b/src/test/run-pass/mod_file_with_path_attr.rs @@ -16,5 +16,5 @@ mod m; pub fn main() { - assert!(m::foo() == 10); + assert_eq!(m::foo(), 10); } diff --git a/src/test/run-pass/monad.rs b/src/test/run-pass/monad.rs index 303d5bc1b4170..69545238db403 100644 --- a/src/test/run-pass/monad.rs +++ b/src/test/run-pass/monad.rs @@ -10,6 +10,8 @@ // xfail-fast +use std::int; + trait vec_monad { fn bind(&self, f: &fn(&A) -> ~[B]) -> ~[B]; } @@ -40,8 +42,8 @@ fn transform(x: Option) -> Option<~str> { } pub fn main() { - assert!(transform(Some(10)) == Some(~"11")); - assert!(transform(None) == None); + assert_eq!(transform(Some(10)), Some(~"11")); + assert_eq!(transform(None), None); assert!((~[~"hi"]) .bind(|x| ~[x.clone(), *x + ~"!"] ) .bind(|x| ~[x.clone(), *x + ~"?"] ) == diff --git a/src/test/run-pass/monomorphize-abi-alignment.rs b/src/test/run-pass/monomorphize-abi-alignment.rs new file mode 100644 index 0000000000000..12c882a87089d --- /dev/null +++ b/src/test/run-pass/monomorphize-abi-alignment.rs @@ -0,0 +1,31 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/*! + * On x86_64-linux-gnu and possibly other platforms, structs get 8-byte "preferred" alignment, + * but their "ABI" alignment (i.e., what actually matters for data layout) is the largest alignment + * of any field. (Also, u64 has 8-byte ABI alignment; this is not always true). + * + * On such platforms, if monomorphize uses the "preferred" alignment, then it will unify + * `A` and `B`, even though `S` and `S` have the field `t` at different offsets, + * and apply the wrong instance of the method `unwrap`. + */ + +struct S { i:u8, t:T } +impl S { fn unwrap(self) -> T { self.t } } +struct A((u32, u32)); +struct B(u64); + +pub fn main() { + static Ca: S = S { i: 0, t: A((13, 104)) }; + static Cb: S = S { i: 0, t: B(31337) }; + assert_eq!(*(Ca.unwrap()), (13, 104)); + assert_eq!(*(Cb.unwrap()), 31337); +} diff --git a/src/test/run-pass/monomorphize-trait-in-fn-at.rs b/src/test/run-pass/monomorphize-trait-in-fn-at.rs index 61d9456296e96..8e36b1138bd43 100644 --- a/src/test/run-pass/monomorphize-trait-in-fn-at.rs +++ b/src/test/run-pass/monomorphize-trait-in-fn-at.rs @@ -26,5 +26,5 @@ impl ty_ops for () { pub fn main() { let fn_env: @fn() -> uint = || mk_nil(()); - assert!(fn_env() == 22u); + assert_eq!(fn_env(), 22u); } diff --git a/src/test/run-pass/monomorphized-callees-with-ty-params-3314.rs b/src/test/run-pass/monomorphized-callees-with-ty-params-3314.rs index 90b3e623f5ed6..eb3c1e4cd27cc 100644 --- a/src/test/run-pass/monomorphized-callees-with-ty-params-3314.rs +++ b/src/test/run-pass/monomorphized-callees-with-ty-params-3314.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; +extern mod extra; + +use std::io; trait Serializer { } diff --git a/src/test/run-pass/morestack3.rs b/src/test/run-pass/morestack3.rs index 07edf0d2e1cf4..a21b13743fe9d 100644 --- a/src/test/run-pass/morestack3.rs +++ b/src/test/run-pass/morestack3.rs @@ -21,15 +21,15 @@ fn getbig(a0: int, a8: int, a9: int) -> int { - assert!(a0 + 1 == a1); - assert!(a1 + 1 == a2); - assert!(a2 + 1 == a3); - assert!(a3 + 1 == a4); - assert!(a4 + 1 == a5); - assert!(a5 + 1 == a6); - assert!(a6 + 1 == a7); - assert!(a7 + 1 == a8); - assert!(a8 + 1 == a9); + assert_eq!(a0 + 1, a1); + assert_eq!(a1 + 1, a2); + assert_eq!(a2 + 1, a3); + assert_eq!(a3 + 1, a4); + assert_eq!(a4 + 1, a5); + assert_eq!(a5 + 1, a6); + assert_eq!(a6 + 1, a7); + assert_eq!(a7 + 1, a8); + assert_eq!(a8 + 1, a9); if a0 != 0 { let j = getbig(a0 - 1, a1 - 1, @@ -41,7 +41,7 @@ fn getbig(a0: int, a7 - 1, a8 - 1, a9 - 1); - assert!(j == a0 - 1); + assert_eq!(j, a0 - 1); } return a0; } diff --git a/src/test/run-pass/morestack5.rs b/src/test/run-pass/morestack5.rs index e1561db8b9162..7f947e332c079 100644 --- a/src/test/run-pass/morestack5.rs +++ b/src/test/run-pass/morestack5.rs @@ -10,7 +10,9 @@ // This test will call __morestack with various minimum stack sizes -extern mod std; +extern mod extra; + +use std::task; fn getbig(i: int) { if i != 0 { diff --git a/src/test/run-pass/morestack6.rs b/src/test/run-pass/morestack6.rs index dafdd0fba48c3..1dc8503aeb22a 100644 --- a/src/test/run-pass/morestack6.rs +++ b/src/test/run-pass/morestack6.rs @@ -11,7 +11,12 @@ // This test attempts to force the dynamic linker to resolve // external symbols as close to the red zone as possible. +use std::rand; +use std::task; + mod rustrt { + use std::libc; + pub extern { pub fn debug_get_stk_seg() -> *u8; @@ -54,7 +59,7 @@ fn runtest2(f: extern fn(), frame_backoff: u32, last_stk: *u8) -> u32 { } pub fn main() { - use core::rand::Rng; + use std::rand::Rng; let fns = ~[ calllink01, calllink02, diff --git a/src/test/run-pass/move-1-unique.rs b/src/test/run-pass/move-1-unique.rs index 47902363db7bc..9194fc830e069 100644 --- a/src/test/run-pass/move-1-unique.rs +++ b/src/test/run-pass/move-1-unique.rs @@ -19,8 +19,8 @@ fn test(x: bool, foo: ~Triple) -> int { pub fn main() { let x = ~Triple{x: 1, y: 2, z: 3}; - assert!((test(true, copy x) == 2)); - assert!((test(true, copy x) == 2)); - assert!((test(true, copy x) == 2)); - assert!((test(false, x) == 5)); + assert_eq!(test(true, copy x), 2); + assert_eq!(test(true, copy x), 2); + assert_eq!(test(true, copy x), 2); + assert_eq!(test(false, x), 5); } diff --git a/src/test/run-pass/move-1.rs b/src/test/run-pass/move-1.rs index 04354d74159a4..5d3b25ebd7ef0 100644 --- a/src/test/run-pass/move-1.rs +++ b/src/test/run-pass/move-1.rs @@ -19,8 +19,8 @@ fn test(x: bool, foo: @Triple) -> int { pub fn main() { let x = @Triple {x: 1, y: 2, z: 3}; - assert!((test(true, x) == 2)); - assert!((test(true, x) == 2)); - assert!((test(true, x) == 2)); - assert!((test(false, x) == 5)); + assert_eq!(test(true, x), 2); + assert_eq!(test(true, x), 2); + assert_eq!(test(true, x), 2); + assert_eq!(test(false, x), 5); } diff --git a/src/test/run-pass/move-3-unique.rs b/src/test/run-pass/move-3-unique.rs index 36c9c787b754d..1df2e3a382d5d 100644 --- a/src/test/run-pass/move-3-unique.rs +++ b/src/test/run-pass/move-3-unique.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; +extern mod extra; + +use std::uint; struct Triple { x: int, y: int, z: int } @@ -22,7 +24,7 @@ fn test(x: bool, foo: ~Triple) -> int { pub fn main() { let x = ~Triple{x: 1, y: 2, z: 3}; for uint::range(0u, 10000u) |_i| { - assert!((test(true, copy x) == 2)); + assert_eq!(test(true, copy x), 2); } - assert!((test(false, x) == 5)); + assert_eq!(test(false, x), 5); } diff --git a/src/test/run-pass/move-3.rs b/src/test/run-pass/move-3.rs index f2b6b2f998080..a52f34c54db45 100644 --- a/src/test/run-pass/move-3.rs +++ b/src/test/run-pass/move-3.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; +extern mod extra; + +use std::uint; struct Triple { x: int, y: int, z: int } @@ -22,7 +24,7 @@ fn test(x: bool, foo: @Triple) -> int { pub fn main() { let x = @Triple{x: 1, y: 2, z: 3}; for uint::range(0u, 10000u) |i| { - assert!((test(true, x) == 2)); + assert_eq!(test(true, x), 2); } - assert!((test(false, x) == 5)); + assert_eq!(test(false, x), 5); } diff --git a/src/test/run-pass/move-4-unique.rs b/src/test/run-pass/move-4-unique.rs index 2ed3523ef86ab..48621cf03be6a 100644 --- a/src/test/run-pass/move-4-unique.rs +++ b/src/test/run-pass/move-4-unique.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; +extern mod extra; struct Triple {a: int, b: int, c: int} diff --git a/src/test/run-pass/move-4.rs b/src/test/run-pass/move-4.rs index fe544e54742bd..2f0f256ba78e8 100644 --- a/src/test/run-pass/move-4.rs +++ b/src/test/run-pass/move-4.rs @@ -9,7 +9,7 @@ // except according to those terms. -extern mod std; +extern mod extra; struct Triple { a: int, b: int, c: int } @@ -24,5 +24,5 @@ fn test(foo: @Triple) -> @Triple { pub fn main() { let x = @Triple{a: 1, b: 2, c: 3}; let y = test(x); - assert!((y.c == 3)); + assert_eq!(y.c, 3); } diff --git a/src/test/run-pass/move-out-of-field.rs b/src/test/run-pass/move-out-of-field.rs new file mode 100644 index 0000000000000..b6485348a5184 --- /dev/null +++ b/src/test/run-pass/move-out-of-field.rs @@ -0,0 +1,23 @@ +use std::str; + +struct StringBuffer { + s: ~str +} + +impl StringBuffer { + pub fn append(&mut self, v: &str) { + str::push_str(&mut self.s, v); + } +} + +fn to_str(sb: StringBuffer) -> ~str { + sb.s +} + +fn main() { + let mut sb = StringBuffer {s: ~""}; + sb.append("Hello, "); + sb.append("World!"); + let str = to_str(sb); + assert_eq!(str, ~"Hello, World!"); +} \ No newline at end of file diff --git a/src/test/run-pass/move-scalar.rs b/src/test/run-pass/move-scalar.rs index 6a8091d7b770f..845cb8ab6011e 100644 --- a/src/test/run-pass/move-scalar.rs +++ b/src/test/run-pass/move-scalar.rs @@ -13,5 +13,5 @@ pub fn main() { let y: int = 42; let mut x: int; x = y; - assert!((x == 42)); + assert_eq!(x, 42); } diff --git a/src/test/run-pass/move-self.rs b/src/test/run-pass/move-self.rs index 4ed1faf65b628..55a7edbb679c6 100644 --- a/src/test/run-pass/move-self.rs +++ b/src/test/run-pass/move-self.rs @@ -2,13 +2,13 @@ struct S { x: ~str } -pub impl S { - fn foo(self) { +impl S { + pub fn foo(self) { self.bar(); } - fn bar(self) { - io::println(self.x); + pub fn bar(self) { + println(self.x); } } diff --git a/src/test/run-pass/moves-based-on-type-capture-clause.rs b/src/test/run-pass/moves-based-on-type-capture-clause.rs index 26d4773d961aa..349be13e3232a 100644 --- a/src/test/run-pass/moves-based-on-type-capture-clause.rs +++ b/src/test/run-pass/moves-based-on-type-capture-clause.rs @@ -1,6 +1,8 @@ +use std::task; + pub fn main() { let x = ~"Hello world!"; do task::spawn { - io::println(x); + println(x); } } diff --git a/src/test/run-pass/multi-let.rs b/src/test/run-pass/multi-let.rs index a7c3c80fba739..8e6865adce918 100644 --- a/src/test/run-pass/multi-let.rs +++ b/src/test/run-pass/multi-let.rs @@ -8,4 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub fn main() { let x = 10, y = x; assert!((y == 10)); } +pub fn main() { + let x = 10; + let y = x; + assert!((y == 10)); +} + diff --git a/src/libcore/from_str.rs b/src/test/run-pass/multibyte.rs similarity index 76% rename from src/libcore/from_str.rs rename to src/test/run-pass/multibyte.rs index ebf6d212466a5..417662b65c6f1 100644 --- a/src/libcore/from_str.rs +++ b/src/test/run-pass/multibyte.rs @@ -8,10 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! The trait for types that can be created from strings - -use option::Option; - -pub trait FromStr { - fn from_str(s: &str) -> Option; +// Test that multibyte characters don't crash the compiler +fn main() { + println("마이너스 사인이 없으면"); } diff --git a/src/test/run-pass/mut-function-arguments.rs b/src/test/run-pass/mut-function-arguments.rs index 20813bb4a0335..0fa89ba0f049d 100644 --- a/src/test/run-pass/mut-function-arguments.rs +++ b/src/test/run-pass/mut-function-arguments.rs @@ -10,7 +10,7 @@ fn f(mut y: ~int) { *y = 5; - assert!(*y == 5); + assert_eq!(*y, 5); } fn g() { diff --git a/src/test/run-pass/mutability-inherits-through-fixed-length-vec.rs b/src/test/run-pass/mutability-inherits-through-fixed-length-vec.rs index c4caf716df239..0b4f92f1d7ca9 100644 --- a/src/test/run-pass/mutability-inherits-through-fixed-length-vec.rs +++ b/src/test/run-pass/mutability-inherits-through-fixed-length-vec.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::vec; + fn test1() { let mut ints = [0, ..32]; ints[0] += 1; - assert!(ints[0] == 1); + assert_eq!(ints[0], 1); } fn test2() { diff --git a/src/test/run-pass/mutable-alias-vec.rs b/src/test/run-pass/mutable-alias-vec.rs index c6bf07536b1a9..91f4fdb01f638 100644 --- a/src/test/run-pass/mutable-alias-vec.rs +++ b/src/test/run-pass/mutable-alias-vec.rs @@ -8,10 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - // -*- rust -*- -extern mod std; +extern mod extra; + +use std::vec; fn grow(v: &mut ~[int]) { *v += ~[1]; } @@ -22,5 +22,5 @@ pub fn main() { grow(&mut v); let len = vec::len::(v); debug!(len); - assert!((len == 3 as uint)); + assert_eq!(len, 3 as uint); } diff --git a/src/test/run-pass/nested-class.rs b/src/test/run-pass/nested-class.rs index 83820f87d5030..6ab9856c0700a 100644 --- a/src/test/run-pass/nested-class.rs +++ b/src/test/run-pass/nested-class.rs @@ -13,8 +13,8 @@ pub fn main() { i: int, } - pub impl b { - fn do_stuff(&self) -> int { return 37; } + impl b { + pub fn do_stuff(&self) -> int { return 37; } } fn b(i:int) -> b { @@ -26,6 +26,6 @@ pub fn main() { // fn b(x:int) -> int { fail!(); } let z = b(42); - assert!((z.i == 42)); - assert!((z.do_stuff() == 37)); + assert_eq!(z.i, 42); + assert_eq!(z.do_stuff(), 37); } diff --git a/src/test/run-pass/nested-exhaustive-alt.rs b/src/test/run-pass/nested-exhaustive-match.rs similarity index 100% rename from src/test/run-pass/nested-exhaustive-alt.rs rename to src/test/run-pass/nested-exhaustive-match.rs diff --git a/src/test/run-pass/nested-alts.rs b/src/test/run-pass/nested-matchs.rs similarity index 100% rename from src/test/run-pass/nested-alts.rs rename to src/test/run-pass/nested-matchs.rs diff --git a/src/test/run-pass/nested-patterns.rs b/src/test/run-pass/nested-patterns.rs index 6c56e39d2d308..bd9e4bdfd8724 100644 --- a/src/test/run-pass/nested-patterns.rs +++ b/src/test/run-pass/nested-patterns.rs @@ -20,8 +20,8 @@ pub fn main() { } let mut x@B {b, _} = B {a: 10, b: C {c: 20}}; x.b.c = 30; - assert!(b.c == 20); + assert_eq!(b.c, 20); let mut y@D {d, _} = D {a: 10, d: C {c: 20}}; y.d.c = 30; - assert!(d.c == 20); + assert_eq!(d.c, 20); } diff --git a/src/test/run-pass/new-impl-syntax.rs b/src/test/run-pass/new-impl-syntax.rs index 2603353f0cff8..71c13ecb9a302 100644 --- a/src/test/run-pass/new-impl-syntax.rs +++ b/src/test/run-pass/new-impl-syntax.rs @@ -20,6 +20,6 @@ impl ToStr for PolymorphicThingy { } pub fn main() { - io::println(Thingy { x: 1, y: 2 }.to_str()); - io::println(PolymorphicThingy { x: Thingy { x: 1, y: 2 } }.to_str()); + println(Thingy { x: 1, y: 2 }.to_str()); + println(PolymorphicThingy { x: Thingy { x: 1, y: 2 } }.to_str()); } diff --git a/src/test/run-pass/new-import-syntax.rs b/src/test/run-pass/new-import-syntax.rs index 1390ae5f7ebe0..c7497bf3de525 100644 --- a/src/test/run-pass/new-import-syntax.rs +++ b/src/test/run-pass/new-import-syntax.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::io::println; +use std::io::println; pub fn main() { println("Hello world!"); diff --git a/src/test/run-pass/new-style-constants.rs b/src/test/run-pass/new-style-constants.rs index 6fe4a88d07183..2da532422c0cb 100644 --- a/src/test/run-pass/new-style-constants.rs +++ b/src/test/run-pass/new-style-constants.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::io::println; +use std::io::println; static FOO: int = 3; diff --git a/src/test/run-pass/new-style-fixed-length-vec.rs b/src/test/run-pass/new-style-fixed-length-vec.rs index 6eea23f6b2b06..41704c252c8db 100644 --- a/src/test/run-pass/new-style-fixed-length-vec.rs +++ b/src/test/run-pass/new-style-fixed-length-vec.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::io::println; +use std::io::println; static FOO: [int, ..3] = [1, 2, 3]; diff --git a/src/test/run-pass/newlambdas.rs b/src/test/run-pass/newlambdas.rs index 1fb98d54adc7a..c6536c68a8336 100644 --- a/src/test/run-pass/newlambdas.rs +++ b/src/test/run-pass/newlambdas.rs @@ -19,11 +19,11 @@ fn ff() -> @fn(int) -> int { } pub fn main() { - assert!(f(10, |a| a) == 10); + assert_eq!(f(10, |a| a), 10); g(||()); - assert!(do f(10) |a| { a } == 10); + assert_eq!(do f(10) |a| { a }, 10); do g() { } let _x: @fn() -> int = || 10; let _y: @fn(int) -> int = |a| a; - assert!(ff()(10) == 11); + assert_eq!(ff()(10), 11); } diff --git a/src/test/run-pass/newtype-polymorphic.rs b/src/test/run-pass/newtype-polymorphic.rs index 6b1b97cfd5f82..f88c71bdf39fc 100644 --- a/src/test/run-pass/newtype-polymorphic.rs +++ b/src/test/run-pass/newtype-polymorphic.rs @@ -16,7 +16,7 @@ fn myvec_elt(mv: myvec) -> X { return mv[0]; } pub fn main() { let mv = myvec(~[1, 2, 3]); - assert!((myvec_deref(copy mv)[1] == 2)); - assert!((myvec_elt(copy mv) == 1)); - assert!((mv[2] == 3)); + assert_eq!(myvec_deref(copy mv)[1], 2); + assert_eq!(myvec_elt(copy mv), 1); + assert_eq!(mv[2], 3); } diff --git a/src/test/run-pass/newtype-struct-with-dtor.rs b/src/test/run-pass/newtype-struct-with-dtor.rs index eb3b74553b7ba..0e36f27aa9292 100644 --- a/src/test/run-pass/newtype-struct-with-dtor.rs +++ b/src/test/run-pass/newtype-struct-with-dtor.rs @@ -1,5 +1,5 @@ -use core::libc::c_int; -use core::libc; +use std::libc::c_int; +use std::libc; pub struct Fd(c_int); diff --git a/src/test/run-pass/newtype.rs b/src/test/run-pass/newtype.rs index ad2c502f20e93..d26210e9a4c1c 100644 --- a/src/test/run-pass/newtype.rs +++ b/src/test/run-pass/newtype.rs @@ -16,6 +16,6 @@ fn compute(i: mytype) -> int { return i.val + 20; } pub fn main() { let myval = mytype(Mytype{compute: compute, val: 30}); - io::println(fmt!("%d", compute(myval))); - assert!(((myval.compute)(myval) == 50)); + println(fmt!("%d", compute(myval))); + assert_eq!((myval.compute)(myval), 50); } diff --git a/src/test/run-pass/non-boolean-pure-fns.rs b/src/test/run-pass/non-boolean-pure-fns.rs index 6a76f9d1646d4..c08f52cba1597 100644 --- a/src/test/run-pass/non-boolean-pure-fns.rs +++ b/src/test/run-pass/non-boolean-pure-fns.rs @@ -10,9 +10,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; +extern mod extra; -use std::list::*; +use extra::list::*; fn pure_length_go(ls: @List, acc: uint) -> uint { match *ls { Nil => { acc } Cons(_, tl) => { pure_length_go(tl, acc + 1u) } } @@ -30,5 +30,5 @@ fn safe_head(ls: @List) -> T { pub fn main() { let mylist = @Cons(@1u, @Nil); assert!((nonempty_list(mylist))); - assert!((*safe_head(mylist) == 1u)); + assert_eq!(*safe_head(mylist), 1u); } diff --git a/src/test/run-pass/non-legacy-modes.rs b/src/test/run-pass/non-legacy-modes.rs index 69feae49157cb..642686e06e5dd 100644 --- a/src/test/run-pass/non-legacy-modes.rs +++ b/src/test/run-pass/non-legacy-modes.rs @@ -17,7 +17,7 @@ fn apply(x: T, f: &fn(T)) { } fn check_int(x: int) { - assert!(x == 22); + assert_eq!(x, 22); } fn check_struct(x: X) { diff --git a/src/test/run-pass/nullable-pointer-iotareduction.rs b/src/test/run-pass/nullable-pointer-iotareduction.rs index 6ec2054996335..b63870dcfb631 100644 --- a/src/test/run-pass/nullable-pointer-iotareduction.rs +++ b/src/test/run-pass/nullable-pointer-iotareduction.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::{option, cast}; +use std::{option, cast}; // Iota-reduction is a rule in the Calculus of (Co-)Inductive Constructions, // which "says that a destructor applied to an object built from a constructor diff --git a/src/test/run-pass/nullable-pointer-size.rs b/src/test/run-pass/nullable-pointer-size.rs index 246fc4e304df3..704fd4eafba2f 100644 --- a/src/test/run-pass/nullable-pointer-size.rs +++ b/src/test/run-pass/nullable-pointer-size.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::sys; + enum E { Thing(int, T), Nothing((), ((), ()), [i8, ..0]) } struct S(int, T); @@ -15,13 +17,13 @@ struct S(int, T); macro_rules! check_option { ($T:ty) => { - assert!(sys::size_of::>() == sys::size_of::<$T>()); + assert_eq!(sys::size_of::>(), sys::size_of::<$T>()); } } macro_rules! check_fancy { ($T:ty) => { - assert!(sys::size_of::>() == sys::size_of::>()); + assert_eq!(sys::size_of::>(), sys::size_of::>()); } } diff --git a/src/test/run-pass/nullary-or-pattern.rs b/src/test/run-pass/nullary-or-pattern.rs index 6a92c1c993c23..8e932c4b14b80 100644 --- a/src/test/run-pass/nullary-or-pattern.rs +++ b/src/test/run-pass/nullary-or-pattern.rs @@ -15,6 +15,6 @@ fn or_alt(q: blah) -> int { } pub fn main() { - assert!((or_alt(a) == 42)); - assert!((or_alt(b) == 42)); + assert_eq!(or_alt(a), 42); + assert_eq!(or_alt(b), 42); } diff --git a/src/test/run-pass/numeric-method-autoexport.rs b/src/test/run-pass/numeric-method-autoexport.rs index 719f1015684a1..7092f8190154a 100644 --- a/src/test/run-pass/numeric-method-autoexport.rs +++ b/src/test/run-pass/numeric-method-autoexport.rs @@ -17,26 +17,26 @@ pub fn main() { // ints // num - assert!(15i.add(&6) == 21); - assert!(15i8.add(&6i8) == 21i8); - assert!(15i16.add(&6i16) == 21i16); - assert!(15i32.add(&6i32) == 21i32); - assert!(15i64.add(&6i64) == 21i64); + assert_eq!(15i.add(&6), 21); + assert_eq!(15i8.add(&6i8), 21i8); + assert_eq!(15i16.add(&6i16), 21i16); + assert_eq!(15i32.add(&6i32), 21i32); + assert_eq!(15i64.add(&6i64), 21i64); // uints // num - assert!(15u.add(&6u) == 21u); - assert!(15u8.add(&6u8) == 21u8); - assert!(15u16.add(&6u16) == 21u16); - assert!(15u32.add(&6u32) == 21u32); - assert!(15u64.add(&6u64) == 21u64); + assert_eq!(15u.add(&6u), 21u); + assert_eq!(15u8.add(&6u8), 21u8); + assert_eq!(15u16.add(&6u16), 21u16); + assert_eq!(15u32.add(&6u32), 21u32); + assert_eq!(15u64.add(&6u64), 21u64); // times 15u.times(|| false); // floats // num - assert!(10f.to_int() == 10); - assert!(10f32.to_int() == 10); - assert!(10f64.to_int() == 10); + assert_eq!(10f.to_int(), 10); + assert_eq!(10f32.to_int(), 10); + assert_eq!(10f64.to_int(), 10); } diff --git a/src/test/run-pass/one-tuple.rs b/src/test/run-pass/one-tuple.rs index eb32e7cda1ad8..8377a45a1d8a0 100644 --- a/src/test/run-pass/one-tuple.rs +++ b/src/test/run-pass/one-tuple.rs @@ -13,11 +13,11 @@ pub fn main() { match ('c',) { (x,) => { - assert!(x == 'c'); + assert_eq!(x, 'c'); } } // test the 1-tuple type too let x: (char,) = ('d',); let (y,) = x; - assert!(y == 'd'); + assert_eq!(y, 'd'); } diff --git a/src/test/run-pass/opeq.rs b/src/test/run-pass/opeq.rs index 004aa864f99da..652ac24d35d5b 100644 --- a/src/test/run-pass/opeq.rs +++ b/src/test/run-pass/opeq.rs @@ -16,14 +16,14 @@ pub fn main() { let mut x: int = 1; x *= 2; debug!(x); - assert!((x == 2)); + assert_eq!(x, 2); x += 3; debug!(x); - assert!((x == 5)); + assert_eq!(x, 5); x *= x; debug!(x); - assert!((x == 25)); + assert_eq!(x, 25); x /= 5; debug!(x); - assert!((x == 5)); + assert_eq!(x, 5); } diff --git a/src/test/run-pass/operator-overloading.rs b/src/test/run-pass/operator-overloading.rs index 8c26dfa1fac56..e75af5729d5c2 100644 --- a/src/test/run-pass/operator-overloading.rs +++ b/src/test/run-pass/operator-overloading.rs @@ -10,6 +10,9 @@ // xfail-fast +use std::cmp; +use std::ops; + struct Point { x: int, y: int @@ -56,14 +59,14 @@ pub fn main() { let mut p = Point {x: 10, y: 20}; p += Point {x: 101, y: 102}; p = p - Point {x: 100, y: 100}; - assert!(p + Point {x: 5, y: 5} == Point {x: 16, y: 27}); - assert!(-p == Point {x: -11, y: -22}); - assert!(p[true] == 11); - assert!(p[false] == 22); + assert_eq!(p + Point {x: 5, y: 5}, Point {x: 16, y: 27}); + assert_eq!(-p, Point {x: -11, y: -22}); + assert_eq!(p[true], 11); + assert_eq!(p[false], 22); let q = !p; - assert!(q.x == !(p.x)); - assert!(q.y == !(p.y)); + assert_eq!(q.x, !(p.x)); + assert_eq!(q.y, !(p.y)); // Issue #1733 let result: ~fn(int) = |_|(); diff --git a/src/test/run-pass/option-ext.rs b/src/test/run-pass/option-ext.rs index 63114da9d9db7..7355bde61f3a6 100644 --- a/src/test/run-pass/option-ext.rs +++ b/src/test/run-pass/option-ext.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::str; + pub fn main() { let thing = ~"{{ f }}"; let f = str::find_str(thing, ~"{{"); if f.is_none() { - io::println(~"None!"); + println(~"None!"); } } diff --git a/src/test/run-pass/option-unwrap.rs b/src/test/run-pass/option-unwrap.rs index 8698d1f39a88f..ea8a6f236cd14 100644 --- a/src/test/run-pass/option-unwrap.rs +++ b/src/test/run-pass/option-unwrap.rs @@ -38,5 +38,5 @@ pub fn main() { let c = unwrap(b); } - assert!(*x == 0); + assert_eq!(*x, 0); } diff --git a/src/test/run-pass/option_addition.rs b/src/test/run-pass/option_addition.rs index 10b8c92e7d60a..07996cb439dae 100644 --- a/src/test/run-pass/option_addition.rs +++ b/src/test/run-pass/option_addition.rs @@ -22,9 +22,9 @@ pub fn main() { None => (), Some(foo) => fail!("expected None, but found %?", foo) } - assert!(foo == somefoo.get()); - assert!(bar == somebar.get()); - assert!(foobar == somefoobar.get()); + assert_eq!(foo, somefoo.get()); + assert_eq!(bar, somebar.get()); + assert_eq!(foobar, somefoobar.get()); } fn optint(in: int) -> Option { diff --git a/src/test/run-pass/or-pattern.rs b/src/test/run-pass/or-pattern.rs index 93d51ab7e8b8b..a014257fb1c9d 100644 --- a/src/test/run-pass/or-pattern.rs +++ b/src/test/run-pass/or-pattern.rs @@ -15,7 +15,7 @@ fn or_alt(q: blah) -> int { } pub fn main() { - assert!((or_alt(c) == 0)); - assert!((or_alt(a(10, 100, 0u)) == 110)); - assert!((or_alt(b(20, 200)) == 220)); + assert_eq!(or_alt(c), 0); + assert_eq!(or_alt(a(10, 100, 0u)), 110); + assert_eq!(or_alt(b(20, 200)), 220); } diff --git a/src/test/run-pass/overload-index-operator.rs b/src/test/run-pass/overload-index-operator.rs index 497c17d04590e..1838cfe25198a 100644 --- a/src/test/run-pass/overload-index-operator.rs +++ b/src/test/run-pass/overload-index-operator.rs @@ -11,7 +11,7 @@ // Test overloading of the `[]` operator. In particular test that it // takes its argument *by reference*. -use core::ops::Index; +use std::ops::Index; struct AssociationList { pairs: ~[AssociationPair] diff --git a/src/test/run-pass/packed-struct-generic-layout.rs b/src/test/run-pass/packed-struct-generic-layout.rs index fd6e3b670f5ab..18b3cf2f91e9a 100644 --- a/src/test/run-pass/packed-struct-generic-layout.rs +++ b/src/test/run-pass/packed-struct-generic-layout.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::cast; + #[packed] struct S { a: T, diff --git a/src/test/run-pass/packed-struct-generic-size.rs b/src/test/run-pass/packed-struct-generic-size.rs index a5c4d5385a297..98e922c3288dd 100644 --- a/src/test/run-pass/packed-struct-generic-size.rs +++ b/src/test/run-pass/packed-struct-generic-size.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::sys; + #[packed] struct S { a: T, diff --git a/src/test/run-pass/packed-struct-layout.rs b/src/test/run-pass/packed-struct-layout.rs index 8d27e55e191a4..ea51bbcea32d4 100644 --- a/src/test/run-pass/packed-struct-layout.rs +++ b/src/test/run-pass/packed-struct-layout.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::cast; + #[packed] struct S4 { a: u8, diff --git a/src/test/run-pass/packed-struct-size-xc.rs b/src/test/run-pass/packed-struct-size-xc.rs index ddfc2b17aa706..19f6046c7d693 100644 --- a/src/test/run-pass/packed-struct-size-xc.rs +++ b/src/test/run-pass/packed-struct-size-xc.rs @@ -3,6 +3,8 @@ extern mod packed; +use std::sys; + fn main() { assert_eq!(sys::size_of::(), 5); } diff --git a/src/test/run-pass/packed-struct-size.rs b/src/test/run-pass/packed-struct-size.rs index 372fe3d37f69d..6dcb1f04a4d5e 100644 --- a/src/test/run-pass/packed-struct-size.rs +++ b/src/test/run-pass/packed-struct-size.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::sys; + #[packed] struct S4 { a: u8, diff --git a/src/test/run-pass/packed-struct-vec.rs b/src/test/run-pass/packed-struct-vec.rs index b1ac29b7721a8..1f3d4c26bd23a 100644 --- a/src/test/run-pass/packed-struct-vec.rs +++ b/src/test/run-pass/packed-struct-vec.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::sys; +use std::uint; + #[packed] #[deriving(Eq)] struct Foo { diff --git a/src/test/run-pass/packed-tuple-struct-layout.rs b/src/test/run-pass/packed-tuple-struct-layout.rs index 9c2fe621a321a..3691f47509820 100644 --- a/src/test/run-pass/packed-tuple-struct-layout.rs +++ b/src/test/run-pass/packed-tuple-struct-layout.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::cast; + #[packed] struct S4(u8,[u8, .. 3]); diff --git a/src/test/run-pass/packed-tuple-struct-size.rs b/src/test/run-pass/packed-tuple-struct-size.rs index 23faa2eb0adc9..c8f2dda61dbe2 100644 --- a/src/test/run-pass/packed-tuple-struct-size.rs +++ b/src/test/run-pass/packed-tuple-struct-size.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::sys; + #[packed] struct S4(u8,[u8, .. 3]); diff --git a/src/test/run-pass/pass-by-copy.rs b/src/test/run-pass/pass-by-copy.rs index c4f328940c49f..63196128ba5b6 100644 --- a/src/test/run-pass/pass-by-copy.rs +++ b/src/test/run-pass/pass-by-copy.rs @@ -14,7 +14,8 @@ fn magic2(x: @int) { debug!(x); } struct A { a: @int } pub fn main() { - let a = A {a: @10}, b = @10; + let a = A {a: @10}; + let b = @10; magic(a); magic(A {a: @20}); magic2(b); magic2(@20); } diff --git a/src/test/run-pass/pattern-bound-var-in-for-each.rs b/src/test/run-pass/pattern-bound-var-in-for-each.rs index 63d9ec17ccb5e..5a0f9ed6eb46f 100644 --- a/src/test/run-pass/pattern-bound-var-in-for-each.rs +++ b/src/test/run-pass/pattern-bound-var-in-for-each.rs @@ -12,13 +12,15 @@ // pattern-bound var is an upvar (when translating // the for-each body) +use std::uint; + fn foo(src: uint) { match Some(src) { Some(src_id) => { for uint::range(0u, 10u) |i| { let yyy = src_id; - assert!((yyy == 0u)); + assert_eq!(yyy, 0u); } } _ => { } diff --git a/src/test/run-pass/pattern-in-closure.rs b/src/test/run-pass/pattern-in-closure.rs index 08c749235c2c8..bee3583c6a496 100644 --- a/src/test/run-pass/pattern-in-closure.rs +++ b/src/test/run-pass/pattern-in-closure.rs @@ -14,8 +14,8 @@ struct Foo { } pub fn main() { - let f = |(x, _): (int, int)| io::println((x + 1).to_str()); - let g = |Foo { x: x, y: y }: Foo| io::println((x + 1).to_str()); + let f = |(x, _): (int, int)| println((x + 1).to_str()); + let g = |Foo { x: x, y: y }: Foo| println((x + 1).to_str()); f((2, 3)); g(Foo { x: 1, y: 2 }); } diff --git a/src/test/run-pass/pipe-bank-proto.rs b/src/test/run-pass/pipe-bank-proto.rs index 26395e7307f9c..d723fa3220945 100644 --- a/src/test/run-pass/pipe-bank-proto.rs +++ b/src/test/run-pass/pipe-bank-proto.rs @@ -15,8 +15,9 @@ // // http://theincredibleholk.wordpress.com/2012/07/06/rusty-pipes/ -use core::pipes; -use core::pipes::try_recv; +use std::pipes; +use std::pipes::try_recv; +use std::ptr; pub type username = ~str; pub type password = ~str; @@ -81,7 +82,7 @@ fn client_follow(bank: bank::client::login) { let bank = client::withdrawal(bank, 50.00); switch(bank, follow! ( money(m) -> _next { - io::println(~"Yay! I got money!"); + println(~"Yay! I got money!"); } insufficient_funds -> _next { fail!("someone stole my money") @@ -105,7 +106,7 @@ fn bank_client(bank: bank::client::login) { let bank = client::withdrawal(bank, 50.00); match try_recv(bank) { Some(money(*)) => { - io::println(~"Yay! I got money!"); + println(~"Yay! I got money!"); } Some(insufficient_funds(_)) => { fail!("someone stole my money") diff --git a/src/test/run-pass/pipe-detect-term.rs b/src/test/run-pass/pipe-detect-term.rs index 55e43075204cc..abee0f36330e9 100644 --- a/src/test/run-pass/pipe-detect-term.rs +++ b/src/test/run-pass/pipe-detect-term.rs @@ -14,12 +14,13 @@ // xfail-win32 -extern mod std; -use std::timer::sleep; -use std::uv; +extern mod extra; +use extra::timer::sleep; +use extra::uv; -use core::cell::Cell; -use core::pipes::{try_recv, recv}; +use std::cell::Cell; +use std::pipes::{try_recv, recv}; +use std::task; proto! oneshot ( waiting:send { @@ -30,8 +31,8 @@ proto! oneshot ( pub fn main() { let iotask = &uv::global_loop::get(); - let (chan, port) = oneshot::init(); - let port = Cell(port); + let (port, chan) = oneshot::init(); + let port = Cell::new(port); do spawn { match try_recv(port.take()) { Some(*) => { fail!() } @@ -46,7 +47,7 @@ pub fn main() { // Make sure the right thing happens during failure. fn failtest() { - let (c, p) = oneshot::init(); + let (p, c) = oneshot::init(); do task::spawn_with(c) |_c| { fail!(); diff --git a/src/test/run-pass/pipe-peek.rs b/src/test/run-pass/pipe-peek.rs index 985eaecdc781b..8d8c96c6f5140 100644 --- a/src/test/run-pass/pipe-peek.rs +++ b/src/test/run-pass/pipe-peek.rs @@ -10,10 +10,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; -use std::timer::sleep; -use std::uv; -use core::pipes; +extern mod extra; +use extra::timer::sleep; +use extra::uv; +use std::pipes; proto! oneshot ( waiting:send { @@ -22,7 +22,7 @@ proto! oneshot ( ) pub fn main() { - let mut (c, p) = oneshot::init(); + let mut (p, c) = oneshot::init(); assert!(!pipes::peek(&mut p)); diff --git a/src/test/run-pass/pipe-pingpong-bounded.rs b/src/test/run-pass/pipe-pingpong-bounded.rs index 3c37371a5371c..ab17607c4d7d5 100644 --- a/src/test/run-pass/pipe-pingpong-bounded.rs +++ b/src/test/run-pass/pipe-pingpong-bounded.rs @@ -14,22 +14,23 @@ // experiment with what code the compiler should generate for bounded // protocols. -use core::cell::Cell; +use std::cell::Cell; +use std::task; // This was generated initially by the pipe compiler, but it's been // modified in hopefully straightforward ways. mod pingpong { - use core::pipes; - use core::pipes::*; - use core::ptr; + use std::pipes; + use std::pipes::*; + use std::ptr; pub struct Packets { ping: Packet, pong: Packet, } - pub fn init() -> (client::ping, server::ping) { + pub fn init() -> (server::ping, client::ping) { let buffer = ~Buffer { header: BufferHeader(), data: Packets { @@ -46,9 +47,9 @@ mod pingpong { pub struct ping(server::pong); pub struct pong(client::ping); pub mod client { - use core::pipes; - use core::pipes::*; - use core::ptr; + use std::pipes; + use std::pipes::*; + use std::ptr; pub fn ping(mut pipe: ping) -> pong { { @@ -66,9 +67,9 @@ mod pingpong { ::pingpong::Packets>; } pub mod server { - use core::pipes; - use core::pipes::*; - use core::ptr; + use std::pipes; + use std::pipes::*; + use std::ptr; pub type ping = pipes::RecvPacketBuffered<::pingpong::ping, ::pingpong::Packets>; @@ -88,7 +89,7 @@ mod pingpong { } mod test { - use core::pipes::recv; + use std::pipes::recv; use pingpong::{ping, pong}; pub fn client(chan: ::pingpong::client::ping) { @@ -111,9 +112,9 @@ mod test { } pub fn main() { - let (client_, server_) = ::pingpong::init(); - let client_ = Cell(client_); - let server_ = Cell(server_); + let (server_, client_) = ::pingpong::init(); + let client_ = Cell::new(client_); + let server_ = Cell::new(server_); do task::spawn { let client__ = client_.take(); test::client(client__); diff --git a/src/test/run-pass/pipe-pingpong-proto.rs b/src/test/run-pass/pipe-pingpong-proto.rs index 5978438ef7635..a4268f9456b30 100644 --- a/src/test/run-pass/pipe-pingpong-proto.rs +++ b/src/test/run-pass/pipe-pingpong-proto.rs @@ -12,8 +12,9 @@ // An example to make sure the protocol parsing syntax extension works. -use core::cell::Cell; -use core::option; +use std::cell::Cell; +use std::option; +use std::task; proto! pingpong ( ping:send { @@ -26,7 +27,7 @@ proto! pingpong ( ) mod test { - use core::pipes::recv; + use std::pipes::recv; use pingpong::{ping, pong}; pub fn client(chan: ::pingpong::client::ping) { @@ -49,9 +50,9 @@ mod test { } pub fn main() { - let (client_, server_) = pingpong::init(); - let client_ = Cell(client_); - let server_ = Cell(server_); + let (server_, client_) = pingpong::init(); + let client_ = Cell::new(client_); + let server_ = Cell::new(server_); do task::spawn { let client__ = client_.take(); diff --git a/src/test/run-pass/pipe-presentation-examples.rs b/src/test/run-pass/pipe-presentation-examples.rs index fcfd77dab0aa3..54cf8ba9c0acb 100644 --- a/src/test/run-pass/pipe-presentation-examples.rs +++ b/src/test/run-pass/pipe-presentation-examples.rs @@ -21,7 +21,7 @@ use double_buffer::client::*; use double_buffer::give_buffer; -use core::comm::Selectable; +use std::comm::Selectable; macro_rules! select_if ( { @@ -37,7 +37,7 @@ macro_rules! select_if ( ], )* } => { if $index == $count { - match core::pipes::try_recv($port) { + match std::pipes::try_recv($port) { $(Some($message($($($x,)+)* next)) => { let $next = next; $e @@ -71,7 +71,7 @@ macro_rules! select ( -> $next:ident $e:expr),+ } )+ } => ({ - let index = core::comm::selecti([$(($port).header()),+]); + let index = std::comm::selecti([$(($port).header()),+]); select_if!(index, 0, $( $port => [ $($message$(($($x),+))dont_type_this* -> $next $e),+ ], )+) diff --git a/src/test/run-pass/pipe-select.rs b/src/test/run-pass/pipe-select.rs index 8782f6f6ebd15..0a860d0a1e22c 100644 --- a/src/test/run-pass/pipe-select.rs +++ b/src/test/run-pass/pipe-select.rs @@ -13,13 +13,14 @@ // xfail-pretty // xfail-win32 -extern mod std; -use std::timer::sleep; -use std::uv; +extern mod extra; +use extra::timer::sleep; +use extra::uv; -use core::cell::Cell; -use core::pipes; -use core::pipes::*; +use std::cell::Cell; +use std::pipes::*; +use std::pipes; +use std::task; proto! oneshot ( waiting:send { @@ -34,15 +35,15 @@ proto! stream ( ) pub fn spawn_service( - init: extern fn() -> (SendPacketBuffered, - RecvPacketBuffered), + init: extern fn() -> (RecvPacketBuffered, + SendPacketBuffered), service: ~fn(v: RecvPacketBuffered)) -> SendPacketBuffered { - let (client, server) = init(); + let (server, client) = init(); // This is some nasty gymnastics required to safely move the pipe // into a new task. - let server = Cell(server); + let server = Cell::new(server); do task::spawn { service(server.take()); } @@ -66,7 +67,7 @@ pub fn main() { error!("selecting"); let (i, _, _) = select(~[left, right]); error!("selected"); - assert!(i == 0); + assert_eq!(i, 0); error!("waiting for pipes"); let stream::send(x, _) = recv(p); @@ -78,12 +79,12 @@ pub fn main() { let (i, m, _) = select(~[left, right]); error!("selected %?", i); if m.is_some() { - assert!(i == 1); + assert_eq!(i, 1); } }); - let (c1, p1) = oneshot::init(); - let (_c2, p2) = oneshot::init(); + let (p1, c1) = oneshot::init(); + let (p2, _c2) = oneshot::init(); let c = send(c, (p1, p2)); @@ -91,8 +92,8 @@ pub fn main() { signal(c1); - let (_c1, p1) = oneshot::init(); - let (c2, p2) = oneshot::init(); + let (p1, _c1) = oneshot::init(); + let (p2, c2) = oneshot::init(); send(c, (p1, p2)); @@ -104,28 +105,28 @@ pub fn main() { } fn test_select2() { - let (ac, ap) = stream::init(); - let (bc, bp) = stream::init(); + let (ap, ac) = stream::init(); + let (bp, bc) = stream::init(); stream::client::send(ac, 42); match pipes::select2(ap, bp) { - either::Left(*) => { } - either::Right(*) => { fail!() } + Left(*) => { } + Right(*) => { fail!() } } stream::client::send(bc, ~"abc"); error!("done with first select2"); - let (ac, ap) = stream::init(); - let (bc, bp) = stream::init(); + let (ap, ac) = stream::init(); + let (bp, bc) = stream::init(); stream::client::send(bc, ~"abc"); match pipes::select2(ap, bp) { - either::Left(*) => { fail!() } - either::Right(*) => { } + Left(*) => { fail!() } + Right(*) => { } } stream::client::send(ac, 42); diff --git a/src/test/run-pass/pipe-sleep.rs b/src/test/run-pass/pipe-sleep.rs index da49a4303a6d7..dc88f36ba113a 100644 --- a/src/test/run-pass/pipe-sleep.rs +++ b/src/test/run-pass/pipe-sleep.rs @@ -10,12 +10,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; -use std::timer::sleep; -use std::uv; -use core::cell::Cell; -use core::pipes; -use core::pipes::*; +extern mod extra; + +use extra::timer::sleep; +use extra::uv; +use std::cell::Cell; +use std::pipes::*; +use std::pipes; +use std::task; proto! oneshot ( waiting:send { @@ -32,15 +34,15 @@ endpoint is passed to the new task. */ pub fn spawn_service( - init: extern fn() -> (SendPacketBuffered, - RecvPacketBuffered), + init: extern fn() -> (RecvPacketBuffered, + SendPacketBuffered), service: ~fn(v: RecvPacketBuffered)) -> SendPacketBuffered { - let (client, server) = init(); + let (server, client) = init(); // This is some nasty gymnastics required to safely move the pipe // into a new task. - let server = Cell(server); + let server = Cell::new(server); do task::spawn { service(server.take()); } diff --git a/src/test/run-pass/placement-new-arena.rs b/src/test/run-pass/placement-new-arena.rs index 166435cbc3d50..839f40fe67f57 100644 --- a/src/test/run-pass/placement-new-arena.rs +++ b/src/test/run-pass/placement-new-arena.rs @@ -10,13 +10,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; -use std::arena; +extern mod extra; +use extra::arena; pub fn main() { let mut arena = arena::Arena(); let p = &mut arena; let x = p.alloc(|| 4u); - io::print(fmt!("%u", *x)); - assert!(*x == 4u); + print(fmt!("%u", *x)); + assert_eq!(*x, 4u); } diff --git a/src/test/run-pass/platform_thread.rs b/src/test/run-pass/platform_thread.rs index 774f2470b3cd3..ea39d00edf716 100644 --- a/src/test/run-pass/platform_thread.rs +++ b/src/test/run-pass/platform_thread.rs @@ -12,6 +12,8 @@ // The OS main scheduler should continue to be available and not terminate // while it is not in use. +use std::task; + pub fn main() { run(100); } diff --git a/src/test/run-pass/private-class-field.rs b/src/test/run-pass/private-class-field.rs index 75f933ac769b0..868cbbfa80212 100644 --- a/src/test/run-pass/private-class-field.rs +++ b/src/test/run-pass/private-class-field.rs @@ -14,8 +14,8 @@ struct cat { how_hungry : int, } -pub impl cat { - fn meow_count(&mut self) -> uint { self.meows } +impl cat { + pub fn meow_count(&mut self) -> uint { self.meows } } fn cat(in_x : uint, in_y : int) -> cat { @@ -27,5 +27,5 @@ fn cat(in_x : uint, in_y : int) -> cat { pub fn main() { let mut nyan : cat = cat(52u, 99); - assert!((nyan.meow_count() == 52u)); + assert_eq!(nyan.meow_count(), 52u); } diff --git a/src/test/run-pass/private-method.rs b/src/test/run-pass/private-method.rs index 1fab77cb5c867..de07cc7c4d018 100644 --- a/src/test/run-pass/private-method.rs +++ b/src/test/run-pass/private-method.rs @@ -8,20 +8,22 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::uint; + struct cat { priv meows : uint, how_hungry : int, } -pub impl cat { - fn play(&mut self) { +impl cat { + pub fn play(&mut self) { self.meows += 1u; self.nap(); } } -priv impl cat { +impl cat { fn nap(&mut self) { for uint::range(1u, 10u) |_i| { }} } diff --git a/src/test/run-pass/propagate-expected-type-through-block.rs b/src/test/run-pass/propagate-expected-type-through-block.rs index aeeae0da9e34a..f8f824cd59603 100644 --- a/src/test/run-pass/propagate-expected-type-through-block.rs +++ b/src/test/run-pass/propagate-expected-type-through-block.rs @@ -8,5 +8,5 @@ pub fn main() { let y = y.clone(); |x| *x + *y }; - assert!(foo(@22) == 25); + assert_eq!(foo(@22), 25); } diff --git a/src/test/run-pass/pub-extern-privacy.rs b/src/test/run-pass/pub-extern-privacy.rs new file mode 100644 index 0000000000000..2927279f6a29e --- /dev/null +++ b/src/test/run-pass/pub-extern-privacy.rs @@ -0,0 +1,14 @@ +use std::cast::transmute; + +mod a { + extern { + pub fn free(x: *u8); + } +} + +fn main() { + unsafe { + a::free(transmute(0)); + } +} + diff --git a/src/test/run-pass/pure-sum.rs b/src/test/run-pass/pure-sum.rs index 6327a3f238d41..17eab78f82084 100644 --- a/src/test/run-pass/pure-sum.rs +++ b/src/test/run-pass/pure-sum.rs @@ -11,7 +11,8 @@ // Check that functions can modify local state. fn sums_to(v: ~[int], sum: int) -> bool { - let mut i = 0u, sum0 = 0; + let mut i = 0u; + let mut sum0 = 0; while i < v.len() { sum0 += v[i]; i += 1u; @@ -20,7 +21,8 @@ fn sums_to(v: ~[int], sum: int) -> bool { } fn sums_to_using_uniq(v: ~[int], sum: int) -> bool { - let mut i = 0u, sum0 = ~0; + let mut i = 0u; + let mut sum0 = ~0; while i < v.len() { *sum0 += v[i]; i += 1u; @@ -29,7 +31,8 @@ fn sums_to_using_uniq(v: ~[int], sum: int) -> bool { } fn sums_to_using_rec(v: ~[int], sum: int) -> bool { - let mut i = 0u, sum0 = F {f: 0}; + let mut i = 0u; + let mut sum0 = F {f: 0}; while i < v.len() { sum0.f += v[i]; i += 1u; @@ -40,7 +43,8 @@ fn sums_to_using_rec(v: ~[int], sum: int) -> bool { struct F { f: T } fn sums_to_using_uniq_rec(v: ~[int], sum: int) -> bool { - let mut i = 0u, sum0 = F {f: ~0}; + let mut i = 0u; + let mut sum0 = F {f: ~0}; while i < v.len() { *sum0.f += v[i]; i += 1u; diff --git a/src/test/run-pass/rcvr-borrowed-to-region.rs b/src/test/run-pass/rcvr-borrowed-to-region.rs index 04f86fdad01fd..fbd7d851fa378 100644 --- a/src/test/run-pass/rcvr-borrowed-to-region.rs +++ b/src/test/run-pass/rcvr-borrowed-to-region.rs @@ -26,26 +26,26 @@ pub fn main() { /* let x = @mut 6; let y = x.get(); - assert!(y == 6); + assert_eq!(y, 6); */ let x = @6; let y = x.get(); debug!("y=%d", y); - assert!(y == 6); + assert_eq!(y, 6); let mut x = ~6; let y = x.get(); debug!("y=%d", y); - assert!(y == 6); + assert_eq!(y, 6); let x = ~6; let y = x.get(); debug!("y=%d", y); - assert!(y == 6); + assert_eq!(y, 6); let x = &6; let y = x.get(); debug!("y=%d", y); - assert!(y == 6); + assert_eq!(y, 6); } diff --git a/src/test/run-pass/rcvr-borrowed-to-slice.rs b/src/test/run-pass/rcvr-borrowed-to-slice.rs index 483a2ee25e5d5..5eaf12f6a5182 100644 --- a/src/test/run-pass/rcvr-borrowed-to-slice.rs +++ b/src/test/run-pass/rcvr-borrowed-to-slice.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::vec; + trait sum { fn sum(self) -> int; } @@ -27,15 +29,15 @@ pub fn main() { let x = ~[1, 2, 3]; let y = call_sum(x); debug!("y==%d", y); - assert!(y == 6); + assert_eq!(y, 6); let mut x = ~[1, 2, 3]; let y = x.sum(); debug!("y==%d", y); - assert!(y == 6); + assert_eq!(y, 6); let x = ~[1, 2, 3]; let y = x.sum(); debug!("y==%d", y); - assert!(y == 6); + assert_eq!(y, 6); } diff --git a/src/test/run-pass/rec-align-u32.rs b/src/test/run-pass/rec-align-u32.rs index ff72eab7df16c..475b9153fdc91 100644 --- a/src/test/run-pass/rec-align-u32.rs +++ b/src/test/run-pass/rec-align-u32.rs @@ -10,6 +10,8 @@ // Issue #2303 +use std::sys; + mod rusti { #[abi = "rust-intrinsic"] pub extern "rust-intrinsic" { @@ -56,12 +58,12 @@ pub fn main() { debug!("y = %s", y); // per clang/gcc the alignment of `inner` is 4 on x86. - assert!(rusti::min_align_of::() == m::align()); + assert_eq!(rusti::min_align_of::(), m::align()); // per clang/gcc the size of `outer` should be 12 // because `inner`s alignment was 4. - assert!(sys::size_of::() == m::size()); + assert_eq!(sys::size_of::(), m::size()); - assert!(y == ~"{c8: 22, t: {c64: 44}}"); + assert_eq!(y, ~"{c8: 22, t: {c64: 44}}"); } } diff --git a/src/test/run-pass/rec-align-u64.rs b/src/test/run-pass/rec-align-u64.rs index 0fad3e1f511f8..8c67b971243f3 100644 --- a/src/test/run-pass/rec-align-u64.rs +++ b/src/test/run-pass/rec-align-u64.rs @@ -10,6 +10,8 @@ // Issue #2303 +use std::sys; + mod rusti { #[abi = "rust-intrinsic"] pub extern "rust-intrinsic" { @@ -78,12 +80,12 @@ pub fn main() { debug!("y = %s", y); // per clang/gcc the alignment of `Inner` is 4 on x86. - assert!(rusti::min_align_of::() == m::m::align()); + assert_eq!(rusti::min_align_of::(), m::m::align()); // per clang/gcc the size of `Outer` should be 12 // because `Inner`s alignment was 4. - assert!(sys::size_of::() == m::m::size()); + assert_eq!(sys::size_of::(), m::m::size()); - assert!(y == ~"{c8: 22, t: {c64: 44}}"); + assert_eq!(y, ~"{c8: 22, t: {c64: 44}}"); } } diff --git a/src/test/run-pass/rec-extend.rs b/src/test/run-pass/rec-extend.rs index c352c06247b03..4e029be8f76a7 100644 --- a/src/test/run-pass/rec-extend.rs +++ b/src/test/run-pass/rec-extend.rs @@ -18,10 +18,10 @@ pub fn main() { let origin: Point = Point {x: 0, y: 0}; let right: Point = Point {x: origin.x + 10,.. origin}; let up: Point = Point {y: origin.y + 10,.. origin}; - assert!((origin.x == 0)); - assert!((origin.y == 0)); - assert!((right.x == 10)); - assert!((right.y == 0)); - assert!((up.x == 0)); - assert!((up.y == 10)); + assert_eq!(origin.x, 0); + assert_eq!(origin.y, 0); + assert_eq!(right.x, 10); + assert_eq!(right.y, 0); + assert_eq!(up.x, 0); + assert_eq!(up.y, 10); } diff --git a/src/test/run-pass/rec-tup.rs b/src/test/run-pass/rec-tup.rs index 46fb619fd8015..fb5c5f3ce01e8 100644 --- a/src/test/run-pass/rec-tup.rs +++ b/src/test/run-pass/rec-tup.rs @@ -17,21 +17,21 @@ fn fst(r: rect) -> Point { let (fst, _) = r; return fst; } fn snd(r: rect) -> Point { let (_, snd) = r; return snd; } fn f(r: rect, x1: int, y1: int, x2: int, y2: int) { - assert!((fst(r).x == x1)); - assert!((fst(r).y == y1)); - assert!((snd(r).x == x2)); - assert!((snd(r).y == y2)); + assert_eq!(fst(r).x, x1); + assert_eq!(fst(r).y, y1); + assert_eq!(snd(r).x, x2); + assert_eq!(snd(r).y, y2); } pub fn main() { let r: rect = (Point {x: 10, y: 20}, Point {x: 11, y: 22}); - assert!((fst(r).x == 10)); - assert!((fst(r).y == 20)); - assert!((snd(r).x == 11)); - assert!((snd(r).y == 22)); + assert_eq!(fst(r).x, 10); + assert_eq!(fst(r).y, 20); + assert_eq!(snd(r).x, 11); + assert_eq!(snd(r).y, 22); let r2 = r; let x: int = fst(r2).x; - assert!((x == 10)); + assert_eq!(x, 10); f(r, 10, 20, 11, 22); f(r2, 10, 20, 11, 22); } diff --git a/src/test/run-pass/rec.rs b/src/test/run-pass/rec.rs index 9d9322f7f3dd7..fa3fa01dd4df9 100644 --- a/src/test/run-pass/rec.rs +++ b/src/test/run-pass/rec.rs @@ -15,21 +15,21 @@ struct Rect {x: int, y: int, w: int, h: int} fn f(r: Rect, x: int, y: int, w: int, h: int) { - assert!((r.x == x)); - assert!((r.y == y)); - assert!((r.w == w)); - assert!((r.h == h)); + assert_eq!(r.x, x); + assert_eq!(r.y, y); + assert_eq!(r.w, w); + assert_eq!(r.h, h); } pub fn main() { let r: Rect = Rect {x: 10, y: 20, w: 100, h: 200}; - assert!((r.x == 10)); - assert!((r.y == 20)); - assert!((r.w == 100)); - assert!((r.h == 200)); + assert_eq!(r.x, 10); + assert_eq!(r.y, 20); + assert_eq!(r.w, 100); + assert_eq!(r.h, 200); let r2: Rect = r; let x: int = r2.x; - assert!((x == 10)); + assert_eq!(x, 10); f(r, 10, 20, 100, 200); f(r2, 10, 20, 100, 200); } diff --git a/src/test/run-pass/record-pat.rs b/src/test/run-pass/record-pat.rs index 0019f1dc23b3f..b13a955404cb4 100644 --- a/src/test/run-pass/record-pat.rs +++ b/src/test/run-pass/record-pat.rs @@ -20,6 +20,6 @@ fn m(in: t3) -> int { } pub fn main() { - assert!((m(c(T2 {x: a(10), y: 5}, 4u)) == 10)); - assert!((m(c(T2 {x: b(10u), y: 5}, 4u)) == 19)); + assert_eq!(m(c(T2 {x: a(10), y: 5}, 4u)), 10); + assert_eq!(m(c(T2 {x: b(10u), y: 5}, 4u)), 19); } diff --git a/src/test/run-pass/mod-merge-hack.rs b/src/test/run-pass/reexported-static-methods-cross-crate.rs similarity index 56% rename from src/test/run-pass/mod-merge-hack.rs rename to src/test/run-pass/reexported-static-methods-cross-crate.rs index 10f661b4f8d58..e8e58d78e9515 100644 --- a/src/test/run-pass/mod-merge-hack.rs +++ b/src/test/run-pass/reexported-static-methods-cross-crate.rs @@ -8,12 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// xfail-pretty -#[path = "mod-merge-hack-template.rs"] -#[merge = "mod-merge-hack-inst.rs"] -mod myint32; +// xfail-fast +// aux-build:reexported_static_methods.rs +extern mod reexported_static_methods; + +use reexported_static_methods::Foo; +use reexported_static_methods::Baz; +use reexported_static_methods::Boz; +use reexported_static_methods::Bort; pub fn main() { - assert!(myint32::bits == 32); - assert!(myint32::min(10, 20) == 10); + assert_eq!(42, Foo::foo()); + assert_eq!(84, Baz::bar()); + assert!(Boz::boz(1)); + assert_eq!(~"bort()", Bort::bort()); } diff --git a/src/test/run-pass/reflect-visit-data.rs b/src/test/run-pass/reflect-visit-data.rs index 5255c13bead62..f4ccd038afee8 100644 --- a/src/test/run-pass/reflect-visit-data.rs +++ b/src/test/run-pass/reflect-visit-data.rs @@ -10,9 +10,12 @@ // xfail-fast -use core::bool; -use core::libc::c_void; -use core::vec::UnboxedVecRepr; +use std::bool; +use std::int; +use std::libc::c_void; +use std::ptr; +use std::sys; +use std::vec::UnboxedVecRepr; use intrinsic::{TyDesc, get_tydesc, visit_tydesc, TyVisitor, Opaque}; #[doc = "High-level interfaces to `intrinsic::visit_ty` reflection system."] @@ -30,29 +33,29 @@ fn align(size: uint, align: uint) -> uint { struct ptr_visit_adaptor(Inner); -pub impl ptr_visit_adaptor { +impl ptr_visit_adaptor { #[inline(always)] - fn bump(&self, sz: uint) { + pub fn bump(&self, sz: uint) { do self.inner.move_ptr() |p| { ((p as uint) + sz) as *c_void }; } #[inline(always)] - fn align(&self, a: uint) { + pub fn align(&self, a: uint) { do self.inner.move_ptr() |p| { align(p as uint, a) as *c_void }; } #[inline(always)] - fn align_to(&self) { + pub fn align_to(&self) { self.align(sys::min_align_of::()); } #[inline(always)] - fn bump_past(&self) { + pub fn bump_past(&self) { self.bump(sys::size_of::()); } @@ -482,14 +485,14 @@ struct Stuff { vals: ~[~str] } -pub impl my_visitor { - fn get(&self, f: &fn(T)) { +impl my_visitor { + pub fn get(&self, f: &fn(T)) { unsafe { f(*(self.ptr1 as *T)); } } - fn visit_inner(&self, inner: *TyDesc) -> bool { + pub fn visit_inner(&self, inner: *TyDesc) -> bool { unsafe { let u = my_visitor(**self); let v = ptr_visit_adaptor::(Inner {inner: u}); @@ -514,7 +517,7 @@ impl TyVisitor for my_visitor { fn visit_nil(&self) -> bool { true } fn visit_bool(&self) -> bool { do self.get::() |b| { - self.vals.push(bool::to_str(b)); + self.vals.push(b.to_str()); }; true } @@ -654,7 +657,7 @@ pub fn main() { visit_tydesc(td, v); for (u.vals.clone()).each |s| { - io::println(fmt!("val: %s", *s)); + println(fmt!("val: %s", *s)); } error!("%?", u.vals.clone()); assert!(u.vals == ~[ diff --git a/src/test/run-pass/region-dependent-addr-of.rs b/src/test/run-pass/region-dependent-addr-of.rs index dd33f7f1e309b..ac2fc2eda23cf 100644 --- a/src/test/run-pass/region-dependent-addr-of.rs +++ b/src/test/run-pass/region-dependent-addr-of.rs @@ -90,29 +90,29 @@ pub fn main() { v6: Some(C { f: 31 })}}; let p = get_v1(&a); - assert!(*p == a.value.v1); + assert_eq!(*p, a.value.v1); let p = get_v2(&a, 1); - assert!(*p == a.value.v2[1]); + assert_eq!(*p, a.value.v2[1]); let p = get_v3(&a, 1); - assert!(*p == a.value.v3[1]); + assert_eq!(*p, a.value.v3[1]); let p = get_v4(&a, 1); - assert!(*p == a.value.v4.f); + assert_eq!(*p, a.value.v4.f); let p = get_v5(&a, 1); - assert!(*p == a.value.v5.f); + assert_eq!(*p, a.value.v5.f); let p = get_v6_a(&a, 1); - assert!(*p == a.value.v6.get().f); + assert_eq!(*p, a.value.v6.get().f); let p = get_v6_b(&a, 1); - assert!(*p == a.value.v6.get().f); + assert_eq!(*p, a.value.v6.get().f); let p = get_v6_c(&a, 1); - assert!(*p == a.value.v6.get().f); + assert_eq!(*p, a.value.v6.get().f); let p = get_v5_ref(&a, 1); - assert!(*p == a.value.v5.f); + assert_eq!(*p, a.value.v5.f); } diff --git a/src/test/run-pass/region-return-interior-of-option.rs b/src/test/run-pass/region-return-interior-of-option.rs index 8bb069990ee48..aa4630717db6c 100644 --- a/src/test/run-pass/region-return-interior-of-option.rs +++ b/src/test/run-pass/region-return-interior-of-option.rs @@ -20,13 +20,13 @@ pub fn main() { { let y = get(&x); - assert!(*y == 23); + assert_eq!(*y, 23); } x = Some(24); { let y = get(&x); - assert!(*y == 24); + assert_eq!(*y, 24); } } diff --git a/src/test/run-pass/regions-appearance-constraint.rs b/src/test/run-pass/regions-appearance-constraint.rs index cfe721612e1e2..e587fa15f5ccd 100644 --- a/src/test/run-pass/regions-appearance-constraint.rs +++ b/src/test/run-pass/regions-appearance-constraint.rs @@ -25,7 +25,7 @@ fn testfn(cond: bool) { x = @5; y = @6; - assert!(*a == exp); + assert_eq!(*a, exp); } pub fn main() { diff --git a/src/test/run-pass/regions-borrow-at.rs b/src/test/run-pass/regions-borrow-at.rs index f12c80c2e8841..a8637fc8ab782 100644 --- a/src/test/run-pass/regions-borrow-at.rs +++ b/src/test/run-pass/regions-borrow-at.rs @@ -16,5 +16,5 @@ pub fn main() { let p = @22u; let r = foo(p); debug!("r=%u", r); - assert!(r == 22u); + assert_eq!(r, 22u); } diff --git a/src/test/run-pass/regions-borrow-estr-uniq.rs b/src/test/run-pass/regions-borrow-estr-uniq.rs index 18082e857514f..b7d9b9f8fa9d5 100644 --- a/src/test/run-pass/regions-borrow-estr-uniq.rs +++ b/src/test/run-pass/regions-borrow-estr-uniq.rs @@ -15,9 +15,9 @@ fn foo(x: &str) -> u8 { pub fn main() { let p = ~"hello"; let r = foo(p); - assert!(r == 'h' as u8); + assert_eq!(r, 'h' as u8); let p = ~"hello"; let r = foo(p); - assert!(r == 'h' as u8); + assert_eq!(r, 'h' as u8); } diff --git a/src/test/run-pass/regions-borrow-evec-at.rs b/src/test/run-pass/regions-borrow-evec-at.rs index 3247f9df30d87..a018dad64b366 100644 --- a/src/test/run-pass/regions-borrow-evec-at.rs +++ b/src/test/run-pass/regions-borrow-evec-at.rs @@ -17,5 +17,5 @@ fn foo(x: &[uint]) -> uint { pub fn main() { let p = @[22u]; let r = foo(p); - assert!(r == 22u); + assert_eq!(r, 22u); } diff --git a/src/test/run-pass/regions-borrow-evec-fixed.rs b/src/test/run-pass/regions-borrow-evec-fixed.rs index 557b66735c016..129a299bcd415 100644 --- a/src/test/run-pass/regions-borrow-evec-fixed.rs +++ b/src/test/run-pass/regions-borrow-evec-fixed.rs @@ -16,5 +16,5 @@ fn foo(x: &[int]) -> int { pub fn main() { let p = [1,2,3,4,5]; - assert!(foo(p) == 1); + assert_eq!(foo(p), 1); } diff --git a/src/test/run-pass/regions-borrow-evec-uniq.rs b/src/test/run-pass/regions-borrow-evec-uniq.rs index 80ea1bb452daa..914c51eaa7012 100644 --- a/src/test/run-pass/regions-borrow-evec-uniq.rs +++ b/src/test/run-pass/regions-borrow-evec-uniq.rs @@ -15,9 +15,9 @@ fn foo(x: &[int]) -> int { pub fn main() { let p = ~[1,2,3,4,5]; let r = foo(p); - assert!(r == 1); + assert_eq!(r, 1); let p = ~[5,4,3,2,1]; let r = foo(p); - assert!(r == 5); + assert_eq!(r, 5); } diff --git a/src/test/run-pass/regions-borrow-uniq.rs b/src/test/run-pass/regions-borrow-uniq.rs index e59352667c2a1..10037d9dfe43b 100644 --- a/src/test/run-pass/regions-borrow-uniq.rs +++ b/src/test/run-pass/regions-borrow-uniq.rs @@ -15,5 +15,5 @@ fn foo(x: &uint) -> uint { pub fn main() { let p = ~3u; let r = foo(p); - assert!(r == 3u); + assert_eq!(r, 3u); } diff --git a/src/test/run-pass/regions-copy-closure.rs b/src/test/run-pass/regions-copy-closure.rs index 2e9ff88f96e90..0b962731ecf3c 100644 --- a/src/test/run-pass/regions-copy-closure.rs +++ b/src/test/run-pass/regions-copy-closure.rs @@ -19,7 +19,7 @@ fn box_it<'r>(x: &'r fn()) -> closure_box<'r> { pub fn main() { let mut i = 3; let cl_box = box_it(|| i += 1); - assert!(i == 3); + assert_eq!(i, 3); (cl_box.cl)(); - assert!(i == 4); + assert_eq!(i, 4); } diff --git a/src/test/run-pass/regions-escape-into-other-fn.rs b/src/test/run-pass/regions-escape-into-other-fn.rs index 22b98726fb1a9..986071ec53599 100644 --- a/src/test/run-pass/regions-escape-into-other-fn.rs +++ b/src/test/run-pass/regions-escape-into-other-fn.rs @@ -13,5 +13,5 @@ fn bar(x: &uint) -> uint { *x } pub fn main() { let p = @3u; - assert!(bar(foo(p)) == 3); + assert_eq!(bar(foo(p)), 3); } diff --git a/src/test/run-pass/regions-expl-self.rs b/src/test/run-pass/regions-expl-self.rs index 174b9a206ccdf..58c13885e036c 100644 --- a/src/test/run-pass/regions-expl-self.rs +++ b/src/test/run-pass/regions-expl-self.rs @@ -14,8 +14,8 @@ struct Foo { f: uint } -pub impl Foo { - fn foo<'a>(&'a self) {} +impl Foo { + pub fn foo<'a>(&'a self) {} } -pub fn main() {} \ No newline at end of file +pub fn main() {} diff --git a/src/test/run-pass/regions-infer-borrow-scope-addr-of.rs b/src/test/run-pass/regions-infer-borrow-scope-addr-of.rs index a87a899cafeaf..702b64881abe1 100644 --- a/src/test/run-pass/regions-infer-borrow-scope-addr-of.rs +++ b/src/test/run-pass/regions-infer-borrow-scope-addr-of.rs @@ -8,7 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::util; +use std::uint; +use std::util; pub fn main() { let mut x = 4; diff --git a/src/test/run-pass/regions-infer-borrow-scope-within-loop-ok.rs b/src/test/run-pass/regions-infer-borrow-scope-within-loop-ok.rs index 73535f52043eb..db4a51bbf2221 100644 --- a/src/test/run-pass/regions-infer-borrow-scope-within-loop-ok.rs +++ b/src/test/run-pass/regions-infer-borrow-scope-within-loop-ok.rs @@ -14,7 +14,7 @@ pub fn main() { let x = @3; loop { let y = borrow(x); - assert!(*x == *y); + assert_eq!(*x, *y); break; } } diff --git a/src/test/run-pass/regions-infer-borrow-scope.rs b/src/test/run-pass/regions-infer-borrow-scope.rs index 61b9000aea318..6bd3fa5a73bcb 100644 --- a/src/test/run-pass/regions-infer-borrow-scope.rs +++ b/src/test/run-pass/regions-infer-borrow-scope.rs @@ -17,5 +17,5 @@ fn x_coord<'r>(p: &'r Point) -> &'r int { pub fn main() { let p = @Point {x: 3, y: 4}; let xc = x_coord(p); - assert!(*xc == 3); + assert_eq!(*xc, 3); } diff --git a/src/test/run-pass/regions-infer-call-2.rs b/src/test/run-pass/regions-infer-call-2.rs index 2772660ff83ce..42be3b5b97553 100644 --- a/src/test/run-pass/regions-infer-call-2.rs +++ b/src/test/run-pass/regions-infer-call-2.rs @@ -19,5 +19,5 @@ fn has_one<'a>(x: &'a int) -> int { } pub fn main() { - assert!(has_one(&2) == 22); + assert_eq!(has_one(&2), 22); } diff --git a/src/test/run-pass/regions-infer-call.rs b/src/test/run-pass/regions-infer-call.rs index 39dec6c81334f..fdb7485efc35b 100644 --- a/src/test/run-pass/regions-infer-call.rs +++ b/src/test/run-pass/regions-infer-call.rs @@ -15,5 +15,5 @@ fn has_two<'a,'b>(x: &'a int, y: &'b int) -> int { } pub fn main() { - assert!(has_two(&20, &2) == 22); + assert_eq!(has_two(&20, &2), 22); } diff --git a/src/test/run-pass/regions-infer-contravariance-due-to-ret.rs b/src/test/run-pass/regions-infer-contravariance-due-to-ret.rs index 46581e4f3d075..f07105cebed0b 100644 --- a/src/test/run-pass/regions-infer-contravariance-due-to-ret.rs +++ b/src/test/run-pass/regions-infer-contravariance-due-to-ret.rs @@ -24,5 +24,5 @@ fn with(bi: &boxed_int) -> int { pub fn main() { let g = 21; let foo = boxed_int { f: &g }; - assert!(with(&foo) == 22); + assert_eq!(with(&foo), 22); } diff --git a/src/test/run-pass/regions-mock-trans.rs b/src/test/run-pass/regions-mock-trans.rs index 0ea6f852a897c..56000d7471d59 100644 --- a/src/test/run-pass/regions-mock-trans.rs +++ b/src/test/run-pass/regions-mock-trans.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::cast; +use std::libc; +use std::sys; + struct arena(()); struct Bcx<'self> { diff --git a/src/test/run-pass/regions-params.rs b/src/test/run-pass/regions-params.rs index 8a8147e42d959..ea32cf866a0cd 100644 --- a/src/test/run-pass/regions-params.rs +++ b/src/test/run-pass/regions-params.rs @@ -23,5 +23,5 @@ fn parameterized(x: &uint) -> uint { pub fn main() { let x = 3u; - assert!(parameterized(&x) == 3u); + assert_eq!(parameterized(&x), 3u); } diff --git a/src/test/run-pass/regions-trait.rs b/src/test/run-pass/regions-trait.rs index a2ed9da67f264..b5b13efa634fa 100644 --- a/src/test/run-pass/regions-trait.rs +++ b/src/test/run-pass/regions-trait.rs @@ -30,5 +30,5 @@ pub fn main() { let ctxt = Ctxt { v: 22 }; let hc = HasCtxt { c: &ctxt }; - assert!(get_v(@hc as @get_ctxt) == 22); + assert_eq!(get_v(@hc as @get_ctxt), 22); } diff --git a/src/test/run-pass/resource-assign-is-not-copy.rs b/src/test/run-pass/resource-assign-is-not-copy.rs index 68ec3fc4d42e0..edd692196ecd5 100644 --- a/src/test/run-pass/resource-assign-is-not-copy.rs +++ b/src/test/run-pass/resource-assign-is-not-copy.rs @@ -36,5 +36,5 @@ pub fn main() { let (c, _d) = b; debug!(c); } - assert!(*i == 1); + assert_eq!(*i, 1); } diff --git a/src/test/run-pass/resource-cycle.rs b/src/test/run-pass/resource-cycle.rs index f498553834a1e..3ce5ea66781f2 100644 --- a/src/test/run-pass/resource-cycle.rs +++ b/src/test/run-pass/resource-cycle.rs @@ -10,6 +10,8 @@ // Don't leak the unique pointers +use std::cast; + struct r { v: *int, } diff --git a/src/test/run-pass/resource-cycle2.rs b/src/test/run-pass/resource-cycle2.rs index 2a59d4d2190d1..0f031424ad4ac 100644 --- a/src/test/run-pass/resource-cycle2.rs +++ b/src/test/run-pass/resource-cycle2.rs @@ -10,6 +10,8 @@ // Don't leak the unique pointers +use std::cast; + struct U { a: int, b: int, diff --git a/src/test/run-pass/resource-cycle3.rs b/src/test/run-pass/resource-cycle3.rs index ef71372477862..f3ca932778a88 100644 --- a/src/test/run-pass/resource-cycle3.rs +++ b/src/test/run-pass/resource-cycle3.rs @@ -12,6 +12,8 @@ // Don't leak the unique pointers +use std::cast; + struct U { a: int, b: int, diff --git a/src/test/run-pass/resource-destruct.rs b/src/test/run-pass/resource-destruct.rs index 1fcf677a0b3dd..c240c6708a4ac 100644 --- a/src/test/run-pass/resource-destruct.rs +++ b/src/test/run-pass/resource-destruct.rs @@ -21,8 +21,8 @@ impl Drop for shrinky_pointer { } } -pub impl shrinky_pointer { - fn look_at(&self) -> int { return **(self.i); } +impl shrinky_pointer { + pub fn look_at(&self) -> int { return **(self.i); } } fn shrinky_pointer(i: @@mut int) -> shrinky_pointer { @@ -35,5 +35,5 @@ pub fn main() { let my_total = @@mut 10; { let pt = shrinky_pointer(my_total); assert!((pt.look_at() == 10)); } error!("my_total = %d", **my_total); - assert!((**my_total == 9)); + assert_eq!(**my_total, 9); } diff --git a/src/test/run-pass/resource-generic.rs b/src/test/run-pass/resource-generic.rs index 8a1835d6585fa..41eafb0293af9 100644 --- a/src/test/run-pass/resource-generic.rs +++ b/src/test/run-pass/resource-generic.rs @@ -36,5 +36,5 @@ pub fn main() { fn dec_box(i: @mut int) { *i -= 1; } { let _i = finish(Arg{val: box, fin: dec_box}); } - assert!((*box == 9)); + assert_eq!(*box, 9); } diff --git a/src/test/run-pass/ret-break-cont-in-block.rs b/src/test/run-pass/ret-break-cont-in-block.rs index 1792a89d64f1e..80e6293bf50af 100644 --- a/src/test/run-pass/ret-break-cont-in-block.rs +++ b/src/test/run-pass/ret-break-cont-in-block.rs @@ -10,10 +10,12 @@ // xfail-fast -use core::cmp::Eq; +use std::cmp::Eq; +use std::vec; fn iter(v: ~[T], it: &fn(&T) -> bool) -> bool { - let mut i = 0u, l = v.len(); + let mut i = 0u; + let mut l = v.len(); while i < l { if !it(&v[i]) { return false; } i += 1u; @@ -56,17 +58,17 @@ pub fn main() { last = *e; if *e == 5 { break; } if *e % 2 == 1 { loop; } - assert!(*e % 2 == 0); + assert_eq!(*e % 2, 0); }; - assert!(last == 5); + assert_eq!(last, 5); - assert!(find_pos(1, ~[0, 1, 2, 3]) == Some(1u)); - assert!(find_pos(1, ~[0, 4, 2, 3]) == None); - assert!(find_pos(~"hi", ~[~"foo", ~"bar", ~"baz", ~"hi"]) == Some(3u)); + assert_eq!(find_pos(1, ~[0, 1, 2, 3]), Some(1u)); + assert_eq!(find_pos(1, ~[0, 4, 2, 3]), None); + assert_eq!(find_pos(~"hi", ~[~"foo", ~"bar", ~"baz", ~"hi"]), Some(3u)); bail_deep(~[~[false, false], ~[true, true], ~[false, true]]); bail_deep(~[~[true]]); bail_deep(~[~[false, false, false]]); - assert!(ret_deep() == ~"hi"); + assert_eq!(ret_deep(), ~"hi"); } diff --git a/src/test/run-pass/rt-sched-1.rs b/src/test/run-pass/rt-sched-1.rs index e7dd240eb184c..d1767235a2bfd 100644 --- a/src/test/run-pass/rt-sched-1.rs +++ b/src/test/run-pass/rt-sched-1.rs @@ -10,7 +10,9 @@ // Tests of the runtime's scheduler interface -use core::comm::*; +use std::cast; +use std::comm::*; +use std::libc; pub type sched_id = int; pub type task_id = *libc::c_void; @@ -21,6 +23,8 @@ pub type closure = *libc::c_void; mod rustrt { use super::{closure, sched_id, task, task_id}; + use std::libc; + pub extern { pub fn rust_new_sched(num_threads: libc::uintptr_t) -> sched_id; pub fn rust_get_sched_id() -> sched_id; @@ -44,7 +48,7 @@ pub fn main() { let child_sched_id = rustrt::rust_get_sched_id(); error!("child_sched_id %?", child_sched_id); assert!(child_sched_id != parent_sched_id); - assert!(child_sched_id == new_sched_id); + assert_eq!(child_sched_id, new_sched_id); ch.send(()); } }; diff --git a/src/test/run-pass/send-iloop.rs b/src/test/run-pass/send-iloop.rs index 18f4fd27858ba..4977082e7ed12 100644 --- a/src/test/run-pass/send-iloop.rs +++ b/src/test/run-pass/send-iloop.rs @@ -9,7 +9,11 @@ // except according to those terms. // xfail-win32 -extern mod std; +extern mod extra; + +use std::comm; +use std::task; +use std::uint; fn die() { fail!(); diff --git a/src/test/run-pass/send-resource.rs b/src/test/run-pass/send-resource.rs index 6bda62be621d6..a2cee0082b5e7 100644 --- a/src/test/run-pass/send-resource.rs +++ b/src/test/run-pass/send-resource.rs @@ -8,7 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::comm::*; +use std::comm::*; +use std::task; struct test { f: int, diff --git a/src/test/run-pass/send-type-inference.rs b/src/test/run-pass/send-type-inference.rs index 734ef70a4b8d0..bdb1fbaf42261 100644 --- a/src/test/run-pass/send-type-inference.rs +++ b/src/test/run-pass/send-type-inference.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::comm::*; +use std::comm::*; // tests that ctrl's type gets inferred properly struct Command { diff --git a/src/test/run-pass/sendable-class.rs b/src/test/run-pass/sendable-class.rs index 8ef0173dbd327..6b262966277c5 100644 --- a/src/test/run-pass/sendable-class.rs +++ b/src/test/run-pass/sendable-class.rs @@ -10,6 +10,8 @@ // Test that a class with only sendable fields can be sent +use std::comm; + struct foo { i: int, j: char, diff --git a/src/test/run-pass/sendfn-generic-fn.rs b/src/test/run-pass/sendfn-generic-fn.rs index 2351540baa93f..31a1e7bded7bf 100644 --- a/src/test/run-pass/sendfn-generic-fn.rs +++ b/src/test/run-pass/sendfn-generic-fn.rs @@ -10,6 +10,8 @@ // xfail-fast +use std::task; + pub fn main() { test05(); } struct Pair { a: A, b: B } diff --git a/src/test/run-pass/sendfn-is-a-block.rs b/src/test/run-pass/sendfn-is-a-block.rs index 8ccc6bb5efb08..f7808f7f8ac8b 100644 --- a/src/test/run-pass/sendfn-is-a-block.rs +++ b/src/test/run-pass/sendfn-is-a-block.rs @@ -16,5 +16,5 @@ fn test(f: &fn(uint) -> uint) -> uint { pub fn main() { let y = test(|x| 4u * x); - assert!(y == 88u); + assert_eq!(y, 88u); } diff --git a/src/test/run-pass/sendfn-spawn-with-fn-arg.rs b/src/test/run-pass/sendfn-spawn-with-fn-arg.rs index 2a69b2ca01779..2399aa5b035cc 100644 --- a/src/test/run-pass/sendfn-spawn-with-fn-arg.rs +++ b/src/test/run-pass/sendfn-spawn-with-fn-arg.rs @@ -8,7 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::cell::Cell; +use std::cell::Cell; +use std::task; pub fn main() { test05(); } @@ -20,9 +21,9 @@ fn test05() { let three = ~3; let fn_to_send: ~fn(int) = |n| { error!(*three + n); // will copy x into the closure - assert!((*three == 3)); + assert_eq!(*three, 3); }; - let fn_to_send = Cell(fn_to_send); + let fn_to_send = Cell::new(fn_to_send); task::spawn(|| { test05_start(fn_to_send.take()); }); diff --git a/src/test/run-pass/seq-compare.rs b/src/test/run-pass/seq-compare.rs index 5fb5297360081..86907bdf2a38f 100644 --- a/src/test/run-pass/seq-compare.rs +++ b/src/test/run-pass/seq-compare.rs @@ -21,6 +21,6 @@ pub fn main() { assert!((~[1, 2, 3] <= ~[1, 2, 3])); assert!((~[1, 2, 3] <= ~[1, 2, 3, 3])); assert!((~[1, 2, 3, 4] > ~[1, 2, 3])); - assert!((~[1, 2, 3] == ~[1, 2, 3])); + assert_eq!(~[1, 2, 3], ~[1, 2, 3]); assert!((~[1, 2, 3] != ~[1, 1, 3])); } diff --git a/src/test/run-pass/shape_intrinsic_tag_then_rec.rs b/src/test/run-pass/shape_intrinsic_tag_then_rec.rs index 25ac00d174f34..f29d0c6f108c6 100644 --- a/src/test/run-pass/shape_intrinsic_tag_then_rec.rs +++ b/src/test/run-pass/shape_intrinsic_tag_then_rec.rs @@ -14,9 +14,9 @@ // on x86_64: when there is a enum embedded in an // interior record which is then itself interior to // something else, shape calculations were off. -extern mod std; -use std::list; -use std::list::list; +extern mod extra; +use extra::list; +use extra::list::list; enum opt_span { diff --git a/src/test/run-pass/shebang.rs b/src/test/run-pass/shebang.rs index f47faca52c06e..94760ce36b57f 100644 --- a/src/test/run-pass/shebang.rs +++ b/src/test/run-pass/shebang.rs @@ -11,4 +11,4 @@ // pp-exact -pub fn main() { io::println("Hello World"); } +pub fn main() { println("Hello World"); } diff --git a/src/test/run-pass/shift.rs b/src/test/run-pass/shift.rs index d839825a773c2..7b676f05c9084 100644 --- a/src/test/run-pass/shift.rs +++ b/src/test/run-pass/shift.rs @@ -18,64 +18,64 @@ pub fn main() { } fn test_misc() { - assert!(1 << 1i8 << 1u8 << 1i16 << 1 as char << 1u64 == 32); + assert_eq!(1 << 1i8 << 1u8 << 1i16 << 1 as char << 1u64, 32); } fn test_expr() { let v10 = 10 as uint; let v4 = 4 as u8; let v2 = 2 as u8; - assert!((v10 >> v2 == v2 as uint)); - assert!((v10 << v4 == 160 as uint)); + assert_eq!(v10 >> v2, v2 as uint); + assert_eq!(v10 << v4, 160 as uint); let v10 = 10 as u8; let v4 = 4 as uint; let v2 = 2 as uint; - assert!((v10 >> v2 == v2 as u8)); - assert!((v10 << v4 == 160 as u8)); + assert_eq!(v10 >> v2, v2 as u8); + assert_eq!(v10 << v4, 160 as u8); let v10 = 10 as int; let v4 = 4 as i8; let v2 = 2 as i8; - assert!((v10 >> v2 == v2 as int)); - assert!((v10 << v4 == 160 as int)); + assert_eq!(v10 >> v2, v2 as int); + assert_eq!(v10 << v4, 160 as int); let v10 = 10 as i8; let v4 = 4 as int; let v2 = 2 as int; - assert!((v10 >> v2 == v2 as i8)); - assert!((v10 << v4 == 160 as i8)); + assert_eq!(v10 >> v2, v2 as i8); + assert_eq!(v10 << v4, 160 as i8); let v10 = 10 as uint; let v4 = 4 as int; let v2 = 2 as int; - assert!((v10 >> v2 == v2 as uint)); - assert!((v10 << v4 == 160 as uint)); + assert_eq!(v10 >> v2, v2 as uint); + assert_eq!(v10 << v4, 160 as uint); } fn test_const() { static r1_1: uint = 10u >> 2u8; static r2_1: uint = 10u << 4u8; - assert!(r1_1 == 2 as uint); - assert!(r2_1 == 160 as uint); + assert_eq!(r1_1, 2 as uint); + assert_eq!(r2_1, 160 as uint); static r1_2: u8 = 10u8 >> 2u; static r2_2: u8 = 10u8 << 4u; - assert!(r1_2 == 2 as u8); - assert!(r2_2 == 160 as u8); + assert_eq!(r1_2, 2 as u8); + assert_eq!(r2_2, 160 as u8); static r1_3: int = 10 >> 2i8; static r2_3: int = 10 << 4i8; - assert!(r1_3 == 2 as int); - assert!(r2_3 == 160 as int); + assert_eq!(r1_3, 2 as int); + assert_eq!(r2_3, 160 as int); static r1_4: i8 = 10i8 >> 2; static r2_4: i8 = 10i8 << 4; - assert!(r1_4 == 2 as i8); - assert!(r2_4 == 160 as i8); + assert_eq!(r1_4, 2 as i8); + assert_eq!(r2_4, 160 as i8); static r1_5: uint = 10u >> 2i8; static r2_5: uint = 10u << 4i8; - assert!(r1_5 == 2 as uint); - assert!(r2_5 == 160 as uint); + assert_eq!(r1_5, 2 as uint); + assert_eq!(r2_5, 160 as uint); } diff --git a/src/test/run-pass/signed-shift-const-eval.rs b/src/test/run-pass/signed-shift-const-eval.rs index 0d3ecae01fb92..92c83c22085b0 100644 --- a/src/test/run-pass/signed-shift-const-eval.rs +++ b/src/test/run-pass/signed-shift-const-eval.rs @@ -10,5 +10,5 @@ enum test { thing = -5 >> 1u } pub fn main() { - assert!((thing as int == -3)); + assert_eq!(thing as int, -3); } diff --git a/src/test/run-pass/simple-generic-alt.rs b/src/test/run-pass/simple-generic-match.rs similarity index 100% rename from src/test/run-pass/simple-generic-alt.rs rename to src/test/run-pass/simple-generic-match.rs diff --git a/src/test/run-pass/simple-alt-generic-tag.rs b/src/test/run-pass/simple-match-generic-tag.rs similarity index 100% rename from src/test/run-pass/simple-alt-generic-tag.rs rename to src/test/run-pass/simple-match-generic-tag.rs diff --git a/src/test/run-pass/sized-borrowed-pointer b/src/test/run-pass/sized-borrowed-pointer new file mode 100755 index 0000000000000..275622161d34f Binary files /dev/null and b/src/test/run-pass/sized-borrowed-pointer differ diff --git a/src/test/run-pass/sized-borrowed-pointer.rs b/src/test/run-pass/sized-borrowed-pointer.rs new file mode 100644 index 0000000000000..9012791800299 --- /dev/null +++ b/src/test/run-pass/sized-borrowed-pointer.rs @@ -0,0 +1,15 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Possibly-dynamic size of typaram should be cleared at pointer boundary. + +fn bar() { } +fn foo() { bar::<&T>() } +fn main() { } diff --git a/src/test/run-pass/sized-owned-pointer b/src/test/run-pass/sized-owned-pointer new file mode 100755 index 0000000000000..3a290ba47ffb2 Binary files /dev/null and b/src/test/run-pass/sized-owned-pointer differ diff --git a/src/test/run-pass/sized-owned-pointer.rs b/src/test/run-pass/sized-owned-pointer.rs new file mode 100644 index 0000000000000..fe9c63621b284 --- /dev/null +++ b/src/test/run-pass/sized-owned-pointer.rs @@ -0,0 +1,15 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Possibly-dynamic size of typaram should be cleared at pointer boundary. + +fn bar() { } +fn foo() { bar::<~T>() } +fn main() { } diff --git a/src/test/run-pass/spawn-fn.rs b/src/test/run-pass/spawn-fn.rs index 37501a61066d3..e3e39b9d5b5b8 100644 --- a/src/test/run-pass/spawn-fn.rs +++ b/src/test/run-pass/spawn-fn.rs @@ -9,6 +9,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::task; fn x(s: ~str, n: int) { debug!(s); diff --git a/src/test/run-pass/spawn-types.rs b/src/test/run-pass/spawn-types.rs index 7bc55d647df5a..f448d74c4bd5b 100644 --- a/src/test/run-pass/spawn-types.rs +++ b/src/test/run-pass/spawn-types.rs @@ -14,12 +14,13 @@ Arnold. */ -use core::comm::*; +use std::comm::*; +use std::task; type ctx = Chan; fn iotask(cx: &ctx, ip: ~str) { - assert!((ip == ~"localhost")); + assert_eq!(ip, ~"localhost"); } pub fn main() { diff --git a/src/test/run-pass/spawn.rs b/src/test/run-pass/spawn.rs index 9a5131ef23000..dff73aa7b8e98 100644 --- a/src/test/run-pass/spawn.rs +++ b/src/test/run-pass/spawn.rs @@ -9,9 +9,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +extern mod extra; -extern mod std; - +use std::task; pub fn main() { task::spawn(|| child(10) ); diff --git a/src/test/run-pass/spawn2.rs b/src/test/run-pass/spawn2.rs index 642babb5a1e5c..61ed7053456ca 100644 --- a/src/test/run-pass/spawn2.rs +++ b/src/test/run-pass/spawn2.rs @@ -9,6 +9,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::task; + pub fn main() { task::spawn(|| child((10, 20, 30, 40, 50, 60, 70, 80, 90)) ); } fn child(args: (int, int, int, int, int, int, int, int, int)) { @@ -22,13 +24,13 @@ fn child(args: (int, int, int, int, int, int, int, int, int)) { error!(i7); error!(i8); error!(i9); - assert!((i1 == 10)); - assert!((i2 == 20)); - assert!((i3 == 30)); - assert!((i4 == 40)); - assert!((i5 == 50)); - assert!((i6 == 60)); - assert!((i7 == 70)); - assert!((i8 == 80)); - assert!((i9 == 90)); + assert_eq!(i1, 10); + assert_eq!(i2, 20); + assert_eq!(i3, 30); + assert_eq!(i4, 40); + assert_eq!(i5, 50); + assert_eq!(i6, 60); + assert_eq!(i7, 70); + assert_eq!(i8, 80); + assert_eq!(i9, 90); } diff --git a/src/test/run-pass/stable-addr-of.rs b/src/test/run-pass/stable-addr-of.rs index 3731f41f8f81c..dc68777e033b0 100644 --- a/src/test/run-pass/stable-addr-of.rs +++ b/src/test/run-pass/stable-addr-of.rs @@ -10,7 +10,9 @@ // Issue #2040 +use std::ptr; + pub fn main() { let foo = 1; - assert!(ptr::to_unsafe_ptr(&foo) == ptr::to_unsafe_ptr(&foo)); + assert_eq!(ptr::to_unsafe_ptr(&foo), ptr::to_unsafe_ptr(&foo)); } diff --git a/src/test/run-pass/stat.rs b/src/test/run-pass/stat.rs index 0967eaf061509..d07da255c5d52 100644 --- a/src/test/run-pass/stat.rs +++ b/src/test/run-pass/stat.rs @@ -10,13 +10,17 @@ // xfail-fast -extern mod std; -use core::io::WriterUtil; -use std::tempfile; +extern mod extra; + +use extra::tempfile; +use std::io::WriterUtil; +use std::io; +use std::os; +use std::uint; pub fn main() { let dir = tempfile::mkdtemp(&Path("."), "").unwrap(); - let path = dir.with_filename("file"); + let path = dir.push("file"); { match io::file_writer(&path, [io::Create, io::Truncate]) { @@ -30,7 +34,8 @@ pub fn main() { } assert!(path.exists()); - assert!(path.get_size() == Some(1000)); + assert_eq!(path.get_size(), Some(1000)); + os::remove_file(&path); os::remove_dir(&dir); } diff --git a/src/test/run-pass/static-assert.rs b/src/test/run-pass/static-assert.rs new file mode 100644 index 0000000000000..81b0c9ff28c3f --- /dev/null +++ b/src/test/run-pass/static-assert.rs @@ -0,0 +1,14 @@ +#[static_assert] +static b: bool = true; + +#[static_assert] +static c: bool = 1 == 1; + +#[static_assert] +static d: bool = 1 != 2; + +#[static_assert] +static f: bool = (4/2) == 2; + +fn main() { +} diff --git a/src/test/run-pass/static-impl.rs b/src/test/run-pass/static-impl.rs index 3f4a956b3a424..46457f667aed4 100644 --- a/src/test/run-pass/static-impl.rs +++ b/src/test/run-pass/static-impl.rs @@ -10,6 +10,9 @@ // xfail-fast +use std::uint; +use std::vec; + pub trait plus { fn plus(&self) -> int; } @@ -54,13 +57,13 @@ impl vec_utils for ~[T] { } pub fn main() { - assert!(10u.plus() == 30); - assert!((~"hi").plus() == 200); + assert_eq!(10u.plus(), 30); + assert_eq!((~"hi").plus(), 200); - assert!((~[1]).length_().str() == ~"1"); - assert!((~[3, 4]).map_(|a| *a + 4 )[0] == 7); - assert!((~[3, 4]).map_::(|a| *a as uint + 4u )[0] == 7u); + assert_eq!((~[1]).length_().str(), ~"1"); + assert_eq!((~[3, 4]).map_(|a| *a + 4 )[0], 7); + assert_eq!((~[3, 4]).map_::(|a| *a as uint + 4u )[0], 7u); let mut x = 0u; 10u.multi(|_n| x += 2u ); - assert!(x == 20u); + assert_eq!(x, 20u); } diff --git a/src/test/run-pass/static-method-in-trait-with-tps-intracrate.rs b/src/test/run-pass/static-method-in-trait-with-tps-intracrate.rs index e8bb9c485ead2..d1fcc4659b937 100644 --- a/src/test/run-pass/static-method-in-trait-with-tps-intracrate.rs +++ b/src/test/run-pass/static-method-in-trait-with-tps-intracrate.rs @@ -31,5 +31,5 @@ impl Deserializer for FromThinAir { pub fn main() { let d = FromThinAir { dummy: () }; let i: int = Deserializable::deserialize(&d); - assert!(i == 22); + assert_eq!(i, 22); } diff --git a/src/test/run-pass/static-method-test.rs b/src/test/run-pass/static-method-test.rs index e06d09c564c00..4dde143f686be 100644 --- a/src/test/run-pass/static-method-test.rs +++ b/src/test/run-pass/static-method-test.rs @@ -10,6 +10,10 @@ // xfail-fast +use std::at_vec; +use std::uint; +use std::vec; + // A trait for objects that can be used to do an if-then-else // (No actual need for this to be static, but it is a simple test.) trait bool_like { @@ -76,15 +80,15 @@ fn seq_range>(lo: uint, hi: uint) -> BT { pub fn main() { let v: @[int] = seq_range(0, 10); - assert!(v == @[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + assert_eq!(v, @[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); let v: @[int] = map(&[1,2,3], |&x| 1+x); - assert!(v == @[2, 3, 4]); + assert_eq!(v, @[2, 3, 4]); let v: ~[int] = map(&[1,2,3], |&x| 1+x); - assert!(v == ~[2, 3, 4]); + assert_eq!(v, ~[2, 3, 4]); - assert!(bool_like::select(true, 9, 14) == 9); + assert_eq!(bool_like::select(true, 9, 14), 9); assert!(!andand(true, false)); - assert!(andand(7, 12) == 12); - assert!(andand(0, 12) == 0); + assert_eq!(andand(7, 12), 12); + assert_eq!(andand(0, 12), 0); } diff --git a/src/test/run-pass/static-method-xcrate.rs b/src/test/run-pass/static-method-xcrate.rs index aa4f65669ad90..6697daa28b650 100644 --- a/src/test/run-pass/static-method-xcrate.rs +++ b/src/test/run-pass/static-method-xcrate.rs @@ -12,12 +12,12 @@ // aux-build:static-methods-crate.rs extern mod static_methods_crate; + use static_methods_crate::read; -use readMaybeRenamed = static_methods_crate::read::readMaybe; pub fn main() { let result: int = read(~"5"); - assert!(result == 5); - assert!(readMaybeRenamed(~"false") == Some(false)); - assert!(readMaybeRenamed(~"foo") == None::); + assert_eq!(result, 5); + assert_eq!(read::readMaybe(~"false"), Some(false)); + assert_eq!(read::readMaybe(~"foo"), None::); } diff --git a/src/test/run-pass/static-methods-in-traits.rs b/src/test/run-pass/static-methods-in-traits.rs index 42d0f02d6425c..8cd7b78312bf2 100644 --- a/src/test/run-pass/static-methods-in-traits.rs +++ b/src/test/run-pass/static-methods-in-traits.rs @@ -29,6 +29,6 @@ mod a { pub fn main() { let x: int = a::Foo::foo(); let y: uint = a::Foo::foo(); - assert!(x == 3); - assert!(y == 5); + assert_eq!(x, 3); + assert_eq!(y, 5); } diff --git a/src/test/run-pass/str-append.rs b/src/test/run-pass/str-append.rs index 4332a184edade..4fdf7dde031a7 100644 --- a/src/test/run-pass/str-append.rs +++ b/src/test/run-pass/str-append.rs @@ -11,13 +11,13 @@ // -*- rust -*- -extern mod std; +extern mod extra; fn test1() { let mut s: ~str = ~"hello"; s += ~"world"; debug!(s.clone()); - assert!((s[9] == 'd' as u8)); + assert_eq!(s[9], 'd' as u8); } fn test2() { @@ -28,8 +28,8 @@ fn test2() { let b: ~str = ~"ABC" + ff + ~"ABC"; debug!(a.clone()); debug!(b.clone()); - assert!((a == ~"abcABCabc")); - assert!((b == ~"ABCabcABC")); + assert_eq!(a, ~"abcABCabc"); + assert_eq!(b, ~"ABCabcABC"); } pub fn main() { test1(); test2(); } diff --git a/src/test/run-pass/str-concat.rs b/src/test/run-pass/str-concat.rs index 0d43329baae47..402d2fbbe3ffb 100644 --- a/src/test/run-pass/str-concat.rs +++ b/src/test/run-pass/str-concat.rs @@ -17,5 +17,5 @@ pub fn main() { let b: ~str = ~"world"; let s: ~str = a + b; debug!(s.clone()); - assert!((s[9] == 'd' as u8)); + assert_eq!(s[9], 'd' as u8); } diff --git a/src/test/run-pass/str-growth.rs b/src/test/run-pass/str-growth.rs index fe9721a92e033..6938b52eee83e 100644 --- a/src/test/run-pass/str-growth.rs +++ b/src/test/run-pass/str-growth.rs @@ -13,12 +13,12 @@ pub fn main() { let mut s = ~"a"; s += ~"b"; - assert!((s[0] == 'a' as u8)); - assert!((s[1] == 'b' as u8)); + assert_eq!(s[0], 'a' as u8); + assert_eq!(s[1], 'b' as u8); s += ~"c"; s += ~"d"; - assert!((s[0] == 'a' as u8)); - assert!((s[1] == 'b' as u8)); - assert!((s[2] == 'c' as u8)); - assert!((s[3] == 'd' as u8)); + assert_eq!(s[0], 'a' as u8); + assert_eq!(s[1], 'b' as u8); + assert_eq!(s[2], 'c' as u8); + assert_eq!(s[3], 'd' as u8); } diff --git a/src/test/run-pass/str-idx.rs b/src/test/run-pass/str-idx.rs index 24d2438e86857..84f63c0137e1a 100644 --- a/src/test/run-pass/str-idx.rs +++ b/src/test/run-pass/str-idx.rs @@ -14,5 +14,5 @@ pub fn main() { let s = ~"hello"; let c: u8 = s[4]; debug!(c); - assert!((c == 0x6f as u8)); + assert_eq!(c, 0x6f as u8); } diff --git a/src/test/run-pass/str-multiline.rs b/src/test/run-pass/str-multiline.rs index ae400acdb8feb..28c2cd7a41acd 100644 --- a/src/test/run-pass/str-multiline.rs +++ b/src/test/run-pass/str-multiline.rs @@ -11,7 +11,7 @@ // -*- rust -*- -extern mod std; +extern mod extra; pub fn main() { let a: ~str = ~"this \ @@ -21,6 +21,6 @@ is a test"; is \ another \ test"; - assert!((a == ~"this is a test")); - assert!((b == ~"this is another test")); + assert_eq!(a, ~"this is a test"); + assert_eq!(b, ~"this is another test"); } diff --git a/src/test/run-pass/string-self-append.rs b/src/test/run-pass/string-self-append.rs index c19a2afbd417f..f02600bb137c0 100644 --- a/src/test/run-pass/string-self-append.rs +++ b/src/test/run-pass/string-self-append.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; +extern mod extra; + +use std::str; pub fn main() { // Make sure we properly handle repeated self-appends. @@ -17,7 +19,7 @@ pub fn main() { let mut expected_len = 1u; while i > 0 { error!(str::len(a)); - assert!((str::len(a) == expected_len)); + assert_eq!(str::len(a), expected_len); a = a + a; // FIXME(#3387)---can't write a += a i -= 1; expected_len *= 2u; diff --git a/src/test/run-pass/struct-deref.rs b/src/test/run-pass/struct-deref.rs index a52a2851689bb..b1de9880d4b4f 100644 --- a/src/test/run-pass/struct-deref.rs +++ b/src/test/run-pass/struct-deref.rs @@ -12,5 +12,5 @@ struct Foo(int); pub fn main() { let x: Foo = Foo(2); - assert!(*x == 2); + assert_eq!(*x, 2); } diff --git a/src/test/run-pass/struct-destructuring-cross-crate.rs b/src/test/run-pass/struct-destructuring-cross-crate.rs index 55d25845971aa..23c508791beee 100644 --- a/src/test/run-pass/struct-destructuring-cross-crate.rs +++ b/src/test/run-pass/struct-destructuring-cross-crate.rs @@ -16,6 +16,6 @@ extern mod struct_destructuring_cross_crate; pub fn main() { let x = struct_destructuring_cross_crate::S { x: 1, y: 2 }; let struct_destructuring_cross_crate::S { x: a, y: b } = x; - assert!(a == 1); - assert!(b == 2); + assert_eq!(a, 1); + assert_eq!(b, 2); } diff --git a/src/test/run-pass/struct-field-assignability.rs b/src/test/run-pass/struct-field-assignability.rs index 0aca1a3d05fdf..335e13caa14cb 100644 --- a/src/test/run-pass/struct-field-assignability.rs +++ b/src/test/run-pass/struct-field-assignability.rs @@ -4,5 +4,5 @@ struct Foo<'self> { pub fn main() { let f = Foo { x: @3 }; - assert!(*f.x == 3); + assert_eq!(*f.x, 3); } diff --git a/src/test/run-pass/struct-like-variant-match.rs b/src/test/run-pass/struct-like-variant-match.rs index 64a75ddab22b7..ef558de433fe8 100644 --- a/src/test/run-pass/struct-like-variant-match.rs +++ b/src/test/run-pass/struct-like-variant-match.rs @@ -22,12 +22,12 @@ enum Foo { fn f(x: &Foo) { match *x { Baz { x: x, y: y } => { - assert!(x == 1.0); - assert!(y == 2.0); + assert_eq!(x, 1.0); + assert_eq!(y, 2.0); } Bar { y: y, x: x } => { - assert!(x == 1); - assert!(y == 2); + assert_eq!(x, 1); + assert_eq!(y, 2); } } } diff --git a/src/test/run-pass/struct-order-of-eval-1.rs b/src/test/run-pass/struct-order-of-eval-1.rs index 884459cf069f4..cfa0401e5b942 100644 --- a/src/test/run-pass/struct-order-of-eval-1.rs +++ b/src/test/run-pass/struct-order-of-eval-1.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::str; + struct S { f0: ~str, f1: int } pub fn main() { diff --git a/src/test/run-pass/struct-order-of-eval-2.rs b/src/test/run-pass/struct-order-of-eval-2.rs index 419c4ac3942f8..f58e5bab3febf 100644 --- a/src/test/run-pass/struct-order-of-eval-2.rs +++ b/src/test/run-pass/struct-order-of-eval-2.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::str; + struct S { f0: ~str, f1: ~str } pub fn main() { diff --git a/src/test/run-pass/struct-pattern-matching.rs b/src/test/run-pass/struct-pattern-matching.rs index 1bda2d2412d2a..68fa137397525 100644 --- a/src/test/run-pass/struct-pattern-matching.rs +++ b/src/test/run-pass/struct-pattern-matching.rs @@ -16,6 +16,6 @@ struct Foo { pub fn main() { let a = Foo { x: 1, y: 2 }; match a { - Foo { x: x, y: y } => io::println(fmt!("yes, %d, %d", x, y)) + Foo { x: x, y: y } => println(fmt!("yes, %d, %d", x, y)) } } diff --git a/src/test/run-pass/struct-return.rs b/src/test/run-pass/struct-return.rs index 7ac74fd52175f..552683992b659 100644 --- a/src/test/run-pass/struct-return.rs +++ b/src/test/run-pass/struct-return.rs @@ -32,10 +32,10 @@ fn test1() { error!("b: %x", qq.b as uint); error!("c: %x", qq.c as uint); error!("d: %x", qq.d as uint); - assert!(qq.a == q.c + 1u64); - assert!(qq.b == q.d - 1u64); - assert!(qq.c == q.a + 1u64); - assert!(qq.d == q.b - 1u64); + assert_eq!(qq.a, q.c + 1u64); + assert_eq!(qq.b, q.d - 1u64); + assert_eq!(qq.c, q.a + 1u64); + assert_eq!(qq.d, q.b - 1u64); } } @@ -49,9 +49,9 @@ fn test2() { error!("a: %f", ff.a as float); error!("b: %u", ff.b as uint); error!("c: %f", ff.c as float); - assert!(ff.a == f.c + 1.0f64); - assert!(ff.b == 0xff_u8); - assert!(ff.c == f.a - 1.0f64); + assert_eq!(ff.a, f.c + 1.0f64); + assert_eq!(ff.b, 0xff_u8); + assert_eq!(ff.c, f.a - 1.0f64); } } diff --git a/src/test/run-pass/structured-compare.rs b/src/test/run-pass/structured-compare.rs index 4a8d155c73926..c67a72e90c9e1 100644 --- a/src/test/run-pass/structured-compare.rs +++ b/src/test/run-pass/structured-compare.rs @@ -12,7 +12,7 @@ enum foo { large, small, } -impl cmp::Eq for foo { +impl Eq for foo { fn eq(&self, other: &foo) -> bool { ((*self) as uint) == ((*other) as uint) } @@ -22,7 +22,7 @@ impl cmp::Eq for foo { pub fn main() { let a = (1, 2, 3); let b = (1, 2, 3); - assert!((a == b)); + assert_eq!(a, b); assert!((a != (1, 2, 4))); assert!((a < (1, 2, 4))); assert!((a <= (1, 2, 4))); @@ -31,6 +31,6 @@ pub fn main() { let x = large; let y = small; assert!((x != y)); - assert!((x == large)); + assert_eq!(x, large); assert!((x != small)); } diff --git a/src/test/run-pass/supported-cast.rs b/src/test/run-pass/supported-cast.rs index 791f493b5ccc9..36e41242f8f75 100644 --- a/src/test/run-pass/supported-cast.rs +++ b/src/test/run-pass/supported-cast.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::libc; + pub fn main() { let f = 1 as *libc::FILE; debug!(f as int); diff --git a/src/test/run-pass/swap-1.rs b/src/test/run-pass/swap-1.rs index ed69fa41d711f..1c0c05cc16d3c 100644 --- a/src/test/run-pass/swap-1.rs +++ b/src/test/run-pass/swap-1.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::util; +use std::util; pub fn main() { let mut x = 3; let mut y = 7; diff --git a/src/test/run-pass/swap-2.rs b/src/test/run-pass/swap-2.rs index 63b377b26d83e..cf3a465d812de 100644 --- a/src/test/run-pass/swap-2.rs +++ b/src/test/run-pass/swap-2.rs @@ -8,15 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::util; +use std::util; +use std::vec; pub fn main() { let mut a: ~[int] = ~[0, 1, 2, 3, 4, 5, 6]; vec::swap(a, 2, 4); - assert!((a[2] == 4)); - assert!((a[4] == 2)); + assert_eq!(a[2], 4); + assert_eq!(a[4], 2); let mut n = 42; util::swap(&mut n, &mut a[0]); - assert!((a[0] == 42)); - assert!((n == 0)); + assert_eq!(a[0], 42); + assert_eq!(n, 0); } diff --git a/src/test/run-pass/swap-overlapping.rs b/src/test/run-pass/swap-overlapping.rs index 05f943bf928ca..07d1226d38297 100644 --- a/src/test/run-pass/swap-overlapping.rs +++ b/src/test/run-pass/swap-overlapping.rs @@ -10,7 +10,8 @@ // Issue #5041 - avoid overlapping memcpy when src and dest of a swap are the same -use core::util; +use std::ptr; +use std::util; pub fn main() { let mut test = TestDescAndFn { @@ -25,8 +26,8 @@ pub fn main() { fn do_swap(test: &mut TestDescAndFn) { unsafe { - util::swap_ptr(ptr::to_mut_unsafe_ptr(test), - ptr::to_mut_unsafe_ptr(test)); + ptr::swap_ptr(ptr::to_mut_unsafe_ptr(test), + ptr::to_mut_unsafe_ptr(test)); } } diff --git a/src/test/run-pass/syntax-extension-fmt.rs b/src/test/run-pass/syntax-extension-fmt.rs index a61feadfc9464..67573fce2cd26 100644 --- a/src/test/run-pass/syntax-extension-fmt.rs +++ b/src/test/run-pass/syntax-extension-fmt.rs @@ -8,12 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; +extern mod extra; fn test(actual: ~str, expected: ~str) { debug!(actual.clone()); debug!(expected.clone()); - assert!((actual == expected)); + assert_eq!(actual, expected); } pub fn main() { @@ -250,13 +250,13 @@ fn part6() { fn percent() { let s = fmt!("ab%%cd"); - assert!((s == ~"ab%cd")); + assert_eq!(s, ~"ab%cd"); } fn more_floats() { - assert!(~"3.1416" == fmt!("%.4f", 3.14159)); - assert!(~"3" == fmt!("%.0f", 3.14159)); - assert!(~"99" == fmt!("%.0f", 98.5)); - assert!(~"7.0000" == fmt!("%.4f", 6.999999999)); - assert!(~"3.141590000" == fmt!("%.9f", 3.14159)); + assert_eq!(~"3.1416", fmt!("%.4f", 3.14159)); + assert_eq!(~"3", fmt!("%.0f", 3.14159)); + assert_eq!(~"99", fmt!("%.0f", 98.5)); + assert_eq!(~"7.0000", fmt!("%.4f", 6.999999999)); + assert_eq!(~"3.141590000", fmt!("%.9f", 3.14159)); } diff --git a/src/test/run-pass/syntax-extension-minor.rs b/src/test/run-pass/syntax-extension-minor.rs index ac0b63e98ca61..497a55b7c78e2 100644 --- a/src/test/run-pass/syntax-extension-minor.rs +++ b/src/test/run-pass/syntax-extension-minor.rs @@ -11,7 +11,7 @@ pub fn main() { let asdf_fdsa = ~"<.<"; - assert!((concat_idents!(asd, f_f, dsa) == ~"<.<")); + assert_eq!(concat_idents!(asd, f_f, dsa), ~"<.<"); assert!(stringify!(use_mention_distinction) == ~"use_mention_distinction"); diff --git a/src/test/run-pass/syntax-extension-source-utils.rs b/src/test/run-pass/syntax-extension-source-utils.rs index 7b52f52137ec0..eceba6cf7b18e 100644 --- a/src/test/run-pass/syntax-extension-source-utils.rs +++ b/src/test/run-pass/syntax-extension-source-utils.rs @@ -20,11 +20,11 @@ pub mod m1 { macro_rules! indirect_line( () => ( line!() ) ) pub fn main() { - assert!((line!() == 23)); + assert_eq!(line!(), 23); //assert!((col!() == 11)); - assert!((indirect_line!() == 25)); + assert_eq!(indirect_line!(), 25); assert!((file!().to_owned().ends_with(~"syntax-extension-source-utils.rs"))); - assert!((stringify!((2*3) + 5).to_owned() == ~"( 2 * 3 ) + 5")); + assert_eq!(stringify!((2*3) + 5).to_owned(), ~"( 2 * 3 ) + 5"); assert!(include!("syntax-extension-source-utils-files/includeme.fragment").to_owned() == ~"victory robot 6"); diff --git a/src/test/run-pass/tag-disr-val-shape.rs b/src/test/run-pass/tag-disr-val-shape.rs index dd78dff0d6ea7..d1dec9c44e0f2 100644 --- a/src/test/run-pass/tag-disr-val-shape.rs +++ b/src/test/run-pass/tag-disr-val-shape.rs @@ -18,8 +18,8 @@ enum color { pub fn main() { let act = fmt!("%?", red); - io::println(act); - assert!(~"red" == act); - assert!(~"green" == fmt!("%?", green)); - assert!(~"white" == fmt!("%?", white)); + println(act); + assert_eq!(~"red", act); + assert_eq!(~"green", fmt!("%?", green)); + assert_eq!(~"white", fmt!("%?", white)); } diff --git a/src/test/run-pass/tag-variant-disr-val.rs b/src/test/run-pass/tag-variant-disr-val.rs index d4eadd366de06..a6252bf5f38d9 100644 --- a/src/test/run-pass/tag-variant-disr-val.rs +++ b/src/test/run-pass/tag-variant-disr-val.rs @@ -19,7 +19,7 @@ enum color { orange = 8 >> 1 } -impl cmp::Eq for color { +impl Eq for color { fn eq(&self, other: &color) -> bool { ((*self) as uint) == ((*other) as uint) } @@ -39,8 +39,8 @@ pub fn main() { fn test_color(color: color, val: int, name: ~str) { //assert!(unsafe::transmute(color) == val); - assert!(color as int == val); - assert!(color as float == val as float); + assert_eq!(color as int, val); + assert_eq!(color as float, val as float); assert!(get_color_alt(color) == name); assert!(get_color_if(color) == name); } diff --git a/src/test/run-pass/tag.rs b/src/test/run-pass/tag.rs index 626e0938aedca..ff251a70f6557 100644 --- a/src/test/run-pass/tag.rs +++ b/src/test/run-pass/tag.rs @@ -8,13 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - - // -*- rust -*- + enum colour { red(int, int), green, } -impl cmp::Eq for colour { +impl Eq for colour { fn eq(&self, other: &colour) -> bool { match *self { red(a0, b0) => { diff --git a/src/test/run-pass/task-comm-0.rs b/src/test/run-pass/task-comm-0.rs index 6fc29fa32db32..686cafb011908 100644 --- a/src/test/run-pass/task-comm-0.rs +++ b/src/test/run-pass/task-comm-0.rs @@ -10,10 +10,12 @@ // xfail-fast -extern mod std; +extern mod extra; -use core::comm::Chan; -use core::comm::Port; +use std::comm::Chan; +use std::comm::Port; +use std::comm; +use std::task; pub fn main() { test05(); } @@ -35,5 +37,5 @@ fn test05() { error!(value); value = po.recv(); error!(value); - assert!((value == 30)); + assert_eq!(value, 30); } diff --git a/src/test/run-pass/task-comm-1.rs b/src/test/run-pass/task-comm-1.rs index b8e314c4c6e31..4d34e3bae3289 100644 --- a/src/test/run-pass/task-comm-1.rs +++ b/src/test/run-pass/task-comm-1.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::task; + pub fn main() { test00(); } fn start() { debug!("Started / Finished task."); } diff --git a/src/test/run-pass/task-comm-10.rs b/src/test/run-pass/task-comm-10.rs index fa3ead8dfe65c..15fbf8c07b80c 100644 --- a/src/test/run-pass/task-comm-10.rs +++ b/src/test/run-pass/task-comm-10.rs @@ -10,7 +10,10 @@ // xfail-fast -extern mod std; +extern mod extra; + +use std::comm; +use std::task; fn start(c: &comm::Chan>) { let (p, ch) = comm::stream(); diff --git a/src/test/run-pass/task-comm-11.rs b/src/test/run-pass/task-comm-11.rs index b2012fbd2dd5e..8931531d5445e 100644 --- a/src/test/run-pass/task-comm-11.rs +++ b/src/test/run-pass/task-comm-11.rs @@ -10,7 +10,10 @@ // xfail-fast -extern mod std; +extern mod extra; + +use std::comm; +use std::task; fn start(c: &comm::Chan>) { let (p, ch) = comm::stream(); diff --git a/src/test/run-pass/task-comm-12.rs b/src/test/run-pass/task-comm-12.rs index 0f0b82d7c21df..a241e9a49a73f 100644 --- a/src/test/run-pass/task-comm-12.rs +++ b/src/test/run-pass/task-comm-12.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; +extern mod extra; + +use std::task; pub fn main() { test00(); } diff --git a/src/test/run-pass/task-comm-13.rs b/src/test/run-pass/task-comm-13.rs index f22328a3e1b32..b625b0557a7cf 100644 --- a/src/test/run-pass/task-comm-13.rs +++ b/src/test/run-pass/task-comm-13.rs @@ -10,7 +10,10 @@ // xfail-fast -extern mod std; +extern mod extra; + +use std::comm; +use std::task; fn start(c: &comm::Chan, start: int, number_of_messages: int) { let mut i: int = 0; diff --git a/src/test/run-pass/task-comm-14.rs b/src/test/run-pass/task-comm-14.rs index 8b4855deaa563..a637d95175701 100644 --- a/src/test/run-pass/task-comm-14.rs +++ b/src/test/run-pass/task-comm-14.rs @@ -10,6 +10,9 @@ // xfail-fast +use std::comm; +use std::task; + pub fn main() { let po = comm::PortSet::new(); diff --git a/src/test/run-pass/task-comm-15.rs b/src/test/run-pass/task-comm-15.rs index 308627720622c..95f8e62523b3f 100644 --- a/src/test/run-pass/task-comm-15.rs +++ b/src/test/run-pass/task-comm-15.rs @@ -11,7 +11,10 @@ // xfail-fast // xfail-win32 -extern mod std; +extern mod extra; + +use std::comm; +use std::task; fn start(c: &comm::Chan, i0: int) { let mut i = i0; diff --git a/src/test/run-pass/task-comm-16.rs b/src/test/run-pass/task-comm-16.rs index 237c721129fe5..d5a4b1a72c907 100644 --- a/src/test/run-pass/task-comm-16.rs +++ b/src/test/run-pass/task-comm-16.rs @@ -9,6 +9,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::comm; +use std::cmp; // Tests of ports and channels on various types fn test_rec() { @@ -19,9 +21,9 @@ fn test_rec() { ch.send(r0); let mut r1: R; r1 = po.recv(); - assert!((r1.val0 == 0)); - assert!((r1.val1 == 1u8)); - assert!((r1.val2 == '2')); + assert_eq!(r1.val0, 0); + assert_eq!(r1.val1, 1u8); + assert_eq!(r1.val2, '2'); } fn test_vec() { @@ -29,9 +31,9 @@ fn test_vec() { let v0: ~[int] = ~[0, 1, 2]; ch.send(v0); let v1 = po.recv(); - assert!((v1[0] == 0)); - assert!((v1[1] == 1)); - assert!((v1[2] == 2)); + assert_eq!(v1[0], 0); + assert_eq!(v1[1], 1); + assert_eq!(v1[2], 2); } fn test_str() { @@ -39,10 +41,10 @@ fn test_str() { let s0 = ~"test"; ch.send(s0); let s1 = po.recv(); - assert!((s1[0] == 't' as u8)); - assert!((s1[1] == 'e' as u8)); - assert!((s1[2] == 's' as u8)); - assert!((s1[3] == 't' as u8)); + assert_eq!(s1[0], 't' as u8); + assert_eq!(s1[1], 'e' as u8); + assert_eq!(s1[2], 's' as u8); + assert_eq!(s1[3], 't' as u8); } enum t { @@ -85,11 +87,11 @@ fn test_tag() { ch.send(tag3(10, 11u8, 'A')); let mut t1: t; t1 = po.recv(); - assert!((t1 == tag1)); + assert_eq!(t1, tag1); t1 = po.recv(); - assert!((t1 == tag2(10))); + assert_eq!(t1, tag2(10)); t1 = po.recv(); - assert!((t1 == tag3(10, 11u8, 'A'))); + assert_eq!(t1, tag3(10, 11u8, 'A')); } fn test_chan() { @@ -102,7 +104,7 @@ fn test_chan() { ch1.send(10); let mut i: int; i = po0.recv(); - assert!((i == 10)); + assert_eq!(i, 10); } pub fn main() { diff --git a/src/test/run-pass/task-comm-17.rs b/src/test/run-pass/task-comm-17.rs index 58fa65b7fe7a1..47e0a710a125c 100644 --- a/src/test/run-pass/task-comm-17.rs +++ b/src/test/run-pass/task-comm-17.rs @@ -12,7 +12,9 @@ // This test is specifically about spawning temporary closures. -extern mod std; +extern mod extra; + +use std::task; fn f() { } diff --git a/src/test/run-pass/task-comm-3.rs b/src/test/run-pass/task-comm-3.rs index fd700475988cf..dd8168ff947b7 100644 --- a/src/test/run-pass/task-comm-3.rs +++ b/src/test/run-pass/task-comm-3.rs @@ -10,8 +10,11 @@ // xfail-fast -extern mod std; -use core::comm::Chan; +extern mod extra; + +use std::comm::Chan; +use std::comm; +use std::task; pub fn main() { debug!("===== WITHOUT THREADS ====="); test00(); } @@ -67,5 +70,5 @@ fn test00() { error!(sum); // assert (sum == (((number_of_tasks * (number_of_tasks - 1)) / 2) * // number_of_messages)); - assert!((sum == 480)); + assert_eq!(sum, 480); } diff --git a/src/test/run-pass/task-comm-4.rs b/src/test/run-pass/task-comm-4.rs index 3b606642571c8..2033092d2ce19 100644 --- a/src/test/run-pass/task-comm-4.rs +++ b/src/test/run-pass/task-comm-4.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::comm; + pub fn main() { test00(); } fn test00() { @@ -46,5 +48,5 @@ fn test00() { r = p.recv(); sum += r; debug!(r); - assert!((sum == 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8)); + assert_eq!(sum, 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8); } diff --git a/src/test/run-pass/task-comm-5.rs b/src/test/run-pass/task-comm-5.rs index 7522a092872ad..472a7d7e3da7d 100644 --- a/src/test/run-pass/task-comm-5.rs +++ b/src/test/run-pass/task-comm-5.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; +extern mod extra; + +use std::comm; pub fn main() { test00(); } @@ -21,5 +23,5 @@ fn test00() { while i < number_of_messages { c.send(i + 0); i += 1; } i = 0; while i < number_of_messages { sum += p.recv(); i += 1; } - assert!((sum == number_of_messages * (number_of_messages - 1) / 2)); + assert_eq!(sum, number_of_messages * (number_of_messages - 1) / 2); } diff --git a/src/test/run-pass/task-comm-6.rs b/src/test/run-pass/task-comm-6.rs index 67ef5fb190526..db6234857d62d 100644 --- a/src/test/run-pass/task-comm-6.rs +++ b/src/test/run-pass/task-comm-6.rs @@ -8,7 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::comm::Chan; +use std::comm::Chan; +use std::comm; pub fn main() { test00(); } @@ -41,7 +42,7 @@ fn test00() { sum += r; i += 1; } - assert!((sum == 1998000)); + assert_eq!(sum, 1998000); // assert (sum == 4 * ((number_of_messages * // (number_of_messages - 1)) / 2)); diff --git a/src/test/run-pass/task-comm-7.rs b/src/test/run-pass/task-comm-7.rs index 12f9a113dfc3e..2ec3ff2408953 100644 --- a/src/test/run-pass/task-comm-7.rs +++ b/src/test/run-pass/task-comm-7.rs @@ -10,7 +10,10 @@ // xfail-fast -extern mod std; +extern mod extra; + +use std::comm; +use std::task; pub fn main() { test00(); } @@ -55,5 +58,5 @@ fn test00() { i += 1; } - assert!((sum == number_of_messages * 4 * (number_of_messages * 4 - 1) / 2)); + assert_eq!(sum, number_of_messages * 4 * (number_of_messages * 4 - 1) / 2); } diff --git a/src/test/run-pass/task-comm-9.rs b/src/test/run-pass/task-comm-9.rs index 798e9d37b5534..d520949fb2258 100644 --- a/src/test/run-pass/task-comm-9.rs +++ b/src/test/run-pass/task-comm-9.rs @@ -10,7 +10,10 @@ // xfail-fast -extern mod std; +extern mod extra; + +use std::comm; +use std::task; pub fn main() { test00(); } @@ -42,5 +45,5 @@ fn test00() { result.unwrap().recv(); - assert!((sum == number_of_messages * (number_of_messages - 1) / 2)); + assert_eq!(sum, number_of_messages * (number_of_messages - 1) / 2); } diff --git a/src/test/run-pass/task-comm-chan-nil.rs b/src/test/run-pass/task-comm-chan-nil.rs index bae3cbbf58729..8010089f3c6e7 100644 --- a/src/test/run-pass/task-comm-chan-nil.rs +++ b/src/test/run-pass/task-comm-chan-nil.rs @@ -10,7 +10,9 @@ // except according to those terms. -extern mod std; +extern mod extra; + +use std::comm; // rustboot can't transmit nils across channels because they don't have // any size, but rustc currently can because they do have size. Whether @@ -19,5 +21,5 @@ pub fn main() { let (po, ch) = comm::stream(); ch.send(()); let n: () = po.recv(); - assert!((n == ())); + assert_eq!(n, ()); } diff --git a/src/test/run-pass/task-killjoin-rsrc.rs b/src/test/run-pass/task-killjoin-rsrc.rs index 879f668577f86..2025a5c304c8f 100644 --- a/src/test/run-pass/task-killjoin-rsrc.rs +++ b/src/test/run-pass/task-killjoin-rsrc.rs @@ -13,8 +13,10 @@ // A port of task-killjoin to use a class with a dtor to manage // the join. -use core::cell::Cell; -use core::comm::*; +use std::cell::Cell; +use std::comm::*; +use std::ptr; +use std::task; struct notify { ch: Chan, v: @mut bool, @@ -53,7 +55,7 @@ fn joinable(f: ~fn()) -> Port { *b = true; } let (p, c) = stream(); - let c = Cell(c); + let c = Cell::new(c); do task::spawn_unlinked { let ccc = c.take(); wrapper(ccc, f) diff --git a/src/test/run-pass/task-killjoin.rs b/src/test/run-pass/task-killjoin.rs index 73c069e560cd0..c94e00251d28a 100644 --- a/src/test/run-pass/task-killjoin.rs +++ b/src/test/run-pass/task-killjoin.rs @@ -15,6 +15,8 @@ // task will kill the supervising task, waking it up. The supervising task no // longer needs to be wakened when the supervised task exits. +use std::task; + fn supervised() { // Yield to make sure the supervisor joins before we fail. This is // currently not needed because the supervisor runs first, but I can diff --git a/src/test/run-pass/task-life-0.rs b/src/test/run-pass/task-life-0.rs index 9885c5d6f3fc0..370971bd7b901 100644 --- a/src/test/run-pass/task-life-0.rs +++ b/src/test/run-pass/task-life-0.rs @@ -8,7 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; +extern mod extra; + +use std::task; + pub fn main() { task::spawn(|| child(~"Hello") ); } diff --git a/src/test/run-pass/task-spawn-move-and-copy.rs b/src/test/run-pass/task-spawn-move-and-copy.rs index ba10bfb670452..f3a105e08527e 100644 --- a/src/test/run-pass/task-spawn-move-and-copy.rs +++ b/src/test/run-pass/task-spawn-move-and-copy.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::comm::*; +use std::comm::*; +use std::ptr; +use std::task; pub fn main() { let (p, ch) = stream::(); @@ -22,5 +24,5 @@ pub fn main() { }); let x_in_child = p.recv(); - assert!(x_in_parent == x_in_child); + assert_eq!(x_in_parent, x_in_child); } diff --git a/src/test/run-pass/terminate-in-initializer.rs b/src/test/run-pass/terminate-in-initializer.rs index cb169c3a6389d..6d34f7a970198 100644 --- a/src/test/run-pass/terminate-in-initializer.rs +++ b/src/test/run-pass/terminate-in-initializer.rs @@ -12,7 +12,9 @@ // Issue #787 // Don't try to clean up uninitialized locals -extern mod std; +extern mod extra; + +use std::task; fn test_break() { loop { let x: @int = break; } } diff --git a/src/test/run-pass/test-ignore-cfg.rs b/src/test/run-pass/test-ignore-cfg.rs index 304c9e5ccb9c3..d8b12437dfa32 100644 --- a/src/test/run-pass/test-ignore-cfg.rs +++ b/src/test/run-pass/test-ignore-cfg.rs @@ -11,7 +11,9 @@ // compile-flags: --test --cfg ignorecfg // xfail-fast -extern mod std; +extern mod extra; + +use std::vec; #[test] #[ignore(cfg(ignorecfg))] diff --git a/src/test/run-pass/test-runner-hides-main.rs b/src/test/run-pass/test-runner-hides-main.rs index 74b63e4dd27d4..3f1e9fe4c5197 100644 --- a/src/test/run-pass/test-runner-hides-main.rs +++ b/src/test/run-pass/test-runner-hides-main.rs @@ -11,7 +11,7 @@ // compile-flags:--test // xfail-fast -extern mod std; +extern mod extra; // Building as a test runner means that a synthetic main will be run, // not ours diff --git a/src/test/run-pass/threads.rs b/src/test/run-pass/threads.rs index a72d3dd40f4ca..8922ff91cfd0e 100644 --- a/src/test/run-pass/threads.rs +++ b/src/test/run-pass/threads.rs @@ -9,8 +9,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +extern mod extra; -extern mod std; +use std::task; pub fn main() { let mut i = 10; diff --git a/src/test/run-pass/trait-bounds.rs b/src/test/run-pass/trait-bounds.rs index 3bdd9aa508803..7ec6ffbd46458 100644 --- a/src/test/run-pass/trait-bounds.rs +++ b/src/test/run-pass/trait-bounds.rs @@ -31,5 +31,5 @@ pub fn main() { let factory = (); let connection = factory.create(); let result = connection.read(); - assert!(result == 43); + assert_eq!(result, 43); } diff --git a/src/test/run-pass/trait-cast.rs b/src/test/run-pass/trait-cast.rs index 303eaa13af852..f21ea06697d8f 100644 --- a/src/test/run-pass/trait-cast.rs +++ b/src/test/run-pass/trait-cast.rs @@ -55,7 +55,7 @@ pub fn main() { right: Some(t1), val: 2 as to_str }); let expected = ~"[2, some([1, none, none]), some([1, none, none])]"; - assert!(t2.to_str() == expected); - assert!(foo(t2 as to_str) == expected); + assert_eq!(t2.to_str(), expected); + assert_eq!(foo(t2 as to_str), expected); t1.left = Some(t2); // create cycle } diff --git a/src/test/run-pass/trait-default-method-bound-subst.rs b/src/test/run-pass/trait-default-method-bound-subst.rs index a489f2b405ffc..dc0af7f7d5412 100644 --- a/src/test/run-pass/trait-default-method-bound-subst.rs +++ b/src/test/run-pass/trait-default-method-bound-subst.rs @@ -21,5 +21,5 @@ fn f>(i: V, j: T, k: U) -> (T, U) { } pub fn main () { - assert!(f(0, 1, 2) == (1, 2)); + assert_eq!(f(0, 1, 2), (1, 2)); } diff --git a/src/test/run-pass/trait-default-method-bound-subst2.rs b/src/test/run-pass/trait-default-method-bound-subst2.rs index 4203f73236e13..93cc752527b80 100644 --- a/src/test/run-pass/trait-default-method-bound-subst2.rs +++ b/src/test/run-pass/trait-default-method-bound-subst2.rs @@ -21,5 +21,5 @@ fn f>(i: V, j: T) -> T { } pub fn main () { - assert!(f(0, 2) == 2); + assert_eq!(f(0, 2), 2); } diff --git a/src/test/run-pass/trait-default-method-bound-subst3.rs b/src/test/run-pass/trait-default-method-bound-subst3.rs index 11830e7e7d248..cb86736b79dab 100644 --- a/src/test/run-pass/trait-default-method-bound-subst3.rs +++ b/src/test/run-pass/trait-default-method-bound-subst3.rs @@ -21,6 +21,6 @@ fn f(i: V, j: T, k: T) -> (T, T) { } pub fn main () { - assert!(f(0, 1, 2) == (1, 2)); - assert!(f(0, 1u8, 2u8) == (1u8, 2u8)); + assert_eq!(f(0, 1, 2), (1, 2)); + assert_eq!(f(0, 1u8, 2u8), (1u8, 2u8)); } diff --git a/src/test/run-pass/trait-default-method-bound-subst4.rs b/src/test/run-pass/trait-default-method-bound-subst4.rs index 285d31152e2ab..d386fd44b6b13 100644 --- a/src/test/run-pass/trait-default-method-bound-subst4.rs +++ b/src/test/run-pass/trait-default-method-bound-subst4.rs @@ -21,6 +21,6 @@ fn f>(i: V, j: uint) -> uint { } pub fn main () { - assert!(f::(0, 2u) == 2u); - assert!(f::(0, 2u) == 2u); + assert_eq!(f::(0, 2u), 2u); + assert_eq!(f::(0, 2u), 2u); } diff --git a/src/test/run-pass/trait-default-method-bound.rs b/src/test/run-pass/trait-default-method-bound.rs index 756af0d63fdef..ce2df508f70e1 100644 --- a/src/test/run-pass/trait-default-method-bound.rs +++ b/src/test/run-pass/trait-default-method-bound.rs @@ -17,7 +17,7 @@ trait A { impl A for int { } fn f(i: T) { - assert!(i.g() == 10); + assert_eq!(i.g(), 10); } pub fn main () { diff --git a/src/test/run-pass/trait-generic.rs b/src/test/run-pass/trait-generic.rs index eacd51266adc2..3aa30aab7c267 100644 --- a/src/test/run-pass/trait-generic.rs +++ b/src/test/run-pass/trait-generic.rs @@ -10,6 +10,8 @@ // xfail-fast +use std::int; + trait to_str { fn to_str(&self) -> ~str; } @@ -42,8 +44,8 @@ fn bar>(x: T) -> ~[~str] { } pub fn main() { - assert!(foo(~[1]) == ~[~"hi"]); - assert!(bar::(~[4, 5]) == ~[~"4", ~"5"]); - assert!(bar::<~str, ~[~str]>(~[~"x", ~"y"]) == ~[~"x", ~"y"]); - assert!(bar::<(), ~[()]>(~[()]) == ~[~"()"]); + assert_eq!(foo(~[1]), ~[~"hi"]); + assert_eq!(bar::(~[4, 5]), ~[~"4", ~"5"]); + assert_eq!(bar::<~str, ~[~str]>(~[~"x", ~"y"]), ~[~"x", ~"y"]); + assert_eq!(bar::<(), ~[()]>(~[()]), ~[~"()"]); } diff --git a/src/test/run-pass/trait-inheritance-auto-xc-2.rs b/src/test/run-pass/trait-inheritance-auto-xc-2.rs index 996f55d4019a8..3f8d536888469 100644 --- a/src/test/run-pass/trait-inheritance-auto-xc-2.rs +++ b/src/test/run-pass/trait-inheritance-auto-xc-2.rs @@ -21,9 +21,9 @@ pub trait Quux: Foo + Bar + Baz { } impl Quux for T { } fn f(a: &T) { - assert!(a.f() == 10); - assert!(a.g() == 20); - assert!(a.h() == 30); + assert_eq!(a.f(), 10); + assert_eq!(a.g(), 20); + assert_eq!(a.h(), 30); } pub fn main() { diff --git a/src/test/run-pass/trait-inheritance-auto-xc.rs b/src/test/run-pass/trait-inheritance-auto-xc.rs index 3af8d606bf4ae..2e8883f026788 100644 --- a/src/test/run-pass/trait-inheritance-auto-xc.rs +++ b/src/test/run-pass/trait-inheritance-auto-xc.rs @@ -22,9 +22,9 @@ impl Bar for A { fn g(&self) -> int { 20 } } impl Baz for A { fn h(&self) -> int { 30 } } fn f(a: &T) { - assert!(a.f() == 10); - assert!(a.g() == 20); - assert!(a.h() == 30); + assert_eq!(a.f(), 10); + assert_eq!(a.g(), 20); + assert_eq!(a.h(), 30); } pub fn main() { diff --git a/src/test/run-pass/trait-inheritance-auto.rs b/src/test/run-pass/trait-inheritance-auto.rs index fb97dd5e7741a..c5a7720e3c341 100644 --- a/src/test/run-pass/trait-inheritance-auto.rs +++ b/src/test/run-pass/trait-inheritance-auto.rs @@ -25,9 +25,9 @@ impl Bar for A { fn g(&self) -> int { 20 } } impl Baz for A { fn h(&self) -> int { 30 } } fn f(a: &T) { - assert!(a.f() == 10); - assert!(a.g() == 20); - assert!(a.h() == 30); + assert_eq!(a.f(), 10); + assert_eq!(a.g(), 20); + assert_eq!(a.h(), 30); } pub fn main() { diff --git a/src/test/run-pass/trait-inheritance-call-bound-inherited.rs b/src/test/run-pass/trait-inheritance-call-bound-inherited.rs index 805c9655d81d4..46258902f9cae 100644 --- a/src/test/run-pass/trait-inheritance-call-bound-inherited.rs +++ b/src/test/run-pass/trait-inheritance-call-bound-inherited.rs @@ -23,5 +23,5 @@ fn gg(a: &T) -> int { pub fn main() { let a = &A { x: 3 }; - assert!(gg(a) == 10); + assert_eq!(gg(a), 10); } diff --git a/src/test/run-pass/trait-inheritance-call-bound-inherited2.rs b/src/test/run-pass/trait-inheritance-call-bound-inherited2.rs index 0b35fd90bbd19..7b79ad42ed2b3 100644 --- a/src/test/run-pass/trait-inheritance-call-bound-inherited2.rs +++ b/src/test/run-pass/trait-inheritance-call-bound-inherited2.rs @@ -26,5 +26,5 @@ fn gg(a: &T) -> int { pub fn main() { let a = &A { x: 3 }; - assert!(gg(a) == 10); + assert_eq!(gg(a), 10); } diff --git a/src/test/run-pass/trait-inheritance-cast-without-call-to-supertrait.rs b/src/test/run-pass/trait-inheritance-cast-without-call-to-supertrait.rs index df9cc4fb8b6d4..68a31ba9dbe64 100644 --- a/src/test/run-pass/trait-inheritance-cast-without-call-to-supertrait.rs +++ b/src/test/run-pass/trait-inheritance-cast-without-call-to-supertrait.rs @@ -35,6 +35,6 @@ pub fn main() { let a = &A { x: 3 }; let afoo = a as &Foo; let abar = a as &Bar; - assert!(afoo.f() == 10); - assert!(abar.g() == 20); + assert_eq!(afoo.f(), 10); + assert_eq!(abar.g(), 20); } diff --git a/src/test/run-pass/trait-inheritance-cast.rs b/src/test/run-pass/trait-inheritance-cast.rs index 75c121e10b014..1f69ba29b09a7 100644 --- a/src/test/run-pass/trait-inheritance-cast.rs +++ b/src/test/run-pass/trait-inheritance-cast.rs @@ -36,7 +36,7 @@ pub fn main() { let a = &A { x: 3 }; let afoo = a as &Foo; let abar = a as &Bar; - assert!(afoo.f() == 10); - assert!(abar.g() == 20); - assert!(abar.f() == 10); + assert_eq!(afoo.f(), 10); + assert_eq!(abar.g(), 20); + assert_eq!(abar.f(), 10); } diff --git a/src/test/run-pass/trait-inheritance-cross-trait-call-xc.rs b/src/test/run-pass/trait-inheritance-cross-trait-call-xc.rs index 976c9a0243927..eddec87472c5a 100644 --- a/src/test/run-pass/trait-inheritance-cross-trait-call-xc.rs +++ b/src/test/run-pass/trait-inheritance-cross-trait-call-xc.rs @@ -25,5 +25,5 @@ impl Bar for aux::A { pub fn main() { let a = &aux::A { x: 3 }; - assert!(a.g() == 10); + assert_eq!(a.g(), 10); } diff --git a/src/test/run-pass/trait-inheritance-cross-trait-call.rs b/src/test/run-pass/trait-inheritance-cross-trait-call.rs index 20dac16b4927d..7b047b5cc800a 100644 --- a/src/test/run-pass/trait-inheritance-cross-trait-call.rs +++ b/src/test/run-pass/trait-inheritance-cross-trait-call.rs @@ -22,5 +22,5 @@ impl Bar for A { pub fn main() { let a = &A { x: 3 }; - assert!(a.g() == 10); + assert_eq!(a.g(), 10); } diff --git a/src/test/run-pass/trait-inheritance-diamond.rs b/src/test/run-pass/trait-inheritance-diamond.rs index abfbec6d35863..253c10ac6f1b0 100644 --- a/src/test/run-pass/trait-inheritance-diamond.rs +++ b/src/test/run-pass/trait-inheritance-diamond.rs @@ -23,10 +23,10 @@ impl C for S { fn c(&self) -> int { 30 } } impl D for S { fn d(&self) -> int { 40 } } fn f(x: &T) { - assert!(x.a() == 10); - assert!(x.b() == 20); - assert!(x.c() == 30); - assert!(x.d() == 40); + assert_eq!(x.a(), 10); + assert_eq!(x.b(), 20); + assert_eq!(x.c(), 30); + assert_eq!(x.d(), 40); } pub fn main() { diff --git a/src/test/run-pass/trait-inheritance-multiple-inheritors.rs b/src/test/run-pass/trait-inheritance-multiple-inheritors.rs index 5bd8f7f25ea09..6cd3d62473692 100644 --- a/src/test/run-pass/trait-inheritance-multiple-inheritors.rs +++ b/src/test/run-pass/trait-inheritance-multiple-inheritors.rs @@ -20,9 +20,9 @@ impl C for S { fn c(&self) -> int { 30 } } // Both B and C inherit from A fn f(x: &T) { - assert!(x.a() == 10); - assert!(x.b() == 20); - assert!(x.c() == 30); + assert_eq!(x.a(), 10); + assert_eq!(x.b(), 20); + assert_eq!(x.c(), 30); } pub fn main() { diff --git a/src/test/run-pass/trait-inheritance-multiple-params.rs b/src/test/run-pass/trait-inheritance-multiple-params.rs index e01860ba50336..b5524c6dda6cd 100644 --- a/src/test/run-pass/trait-inheritance-multiple-params.rs +++ b/src/test/run-pass/trait-inheritance-multiple-params.rs @@ -20,11 +20,11 @@ impl C for S { fn c(&self) -> int { 30 } } // Multiple type params, multiple levels of inheritance fn f(x: &X, y: &Y, z: &Z) { - assert!(x.a() == 10); - assert!(y.a() == 10); - assert!(y.b() == 20); - assert!(z.a() == 10); - assert!(z.c() == 30); + assert_eq!(x.a(), 10); + assert_eq!(y.a(), 10); + assert_eq!(y.b(), 20); + assert_eq!(z.a(), 10); + assert_eq!(z.c(), 30); } pub fn main() { diff --git a/src/test/run-pass/trait-inheritance-num.rs b/src/test/run-pass/trait-inheritance-num.rs index 5179d13813cea..87de3a2be1496 100644 --- a/src/test/run-pass/trait-inheritance-num.rs +++ b/src/test/run-pass/trait-inheritance-num.rs @@ -10,16 +10,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; +extern mod extra; -use core::cmp::{Eq, Ord}; -use core::num::NumCast::from; +use std::cmp::{Eq, Ord}; +use std::num::NumCast; pub trait NumExt: Num + NumCast + Eq + Ord {} pub trait FloatExt: NumExt + ApproxEq {} -fn greater_than_one(n: &T) -> bool { *n > from(1) } -fn greater_than_one_float(n: &T) -> bool { *n > from(1) } +fn greater_than_one(n: &T) -> bool { *n > NumCast::from(1) } +fn greater_than_one_float(n: &T) -> bool { *n > NumCast::from(1) } pub fn main() {} diff --git a/src/test/run-pass/trait-inheritance-num0.rs b/src/test/run-pass/trait-inheritance-num0.rs index aae430dc4cdf9..ae285f3bc958b 100644 --- a/src/test/run-pass/trait-inheritance-num0.rs +++ b/src/test/run-pass/trait-inheritance-num0.rs @@ -12,7 +12,7 @@ // Extending Num and using inherited static methods -use core::num::NumCast::from; +use std::num::NumCast; trait Num { fn from_int(i: int) -> Self; @@ -22,7 +22,7 @@ trait Num { pub trait NumExt: Num + NumCast { } fn greater_than_one(n: &T) -> bool { - n.gt(&from(1)) + n.gt(&NumCast::from(1)) } pub fn main() {} diff --git a/src/test/run-pass/trait-inheritance-num1.rs b/src/test/run-pass/trait-inheritance-num1.rs index d580b99012fa5..d22a8154a5b25 100644 --- a/src/test/run-pass/trait-inheritance-num1.rs +++ b/src/test/run-pass/trait-inheritance-num1.rs @@ -8,13 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::cmp::Ord; -use core::num::NumCast::from; +use std::cmp::Ord; +use std::num::NumCast; pub trait NumExt: Num + NumCast + Ord { } fn greater_than_one(n: &T) -> bool { - *n > from(1) + *n > NumCast::from(1) } pub fn main() {} diff --git a/src/test/run-pass/trait-inheritance-num2.rs b/src/test/run-pass/trait-inheritance-num2.rs index f7edd2855a4cd..bc1583a08780a 100644 --- a/src/test/run-pass/trait-inheritance-num2.rs +++ b/src/test/run-pass/trait-inheritance-num2.rs @@ -12,10 +12,9 @@ // A more complex example of numeric extensions -extern mod std; +extern mod extra; -use core::cmp::{Eq, Ord}; -use core::num::NumCast::from; +use std::cmp::{Eq, Ord}; pub trait TypeExt {} @@ -100,7 +99,7 @@ impl FloatExt for f64 {} impl FloatExt for float {} -fn test_float_ext(n: T) { io::println(fmt!("%?", n < n)) } +fn test_float_ext(n: T) { println(fmt!("%?", n < n)) } pub fn main() { test_float_ext(1f32); diff --git a/src/test/run-pass/trait-inheritance-num3.rs b/src/test/run-pass/trait-inheritance-num3.rs index 5f1fef80ef201..e0285a7b59831 100644 --- a/src/test/run-pass/trait-inheritance-num3.rs +++ b/src/test/run-pass/trait-inheritance-num3.rs @@ -8,14 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::cmp::{Eq, Ord}; -use core::num::NumCast::from; +use std::cmp::{Eq, Ord}; +use std::num::NumCast; pub trait NumExt: Eq + Ord + Num + NumCast {} impl NumExt for f32 {} -fn num_eq_one(n: T) { io::println(fmt!("%?", n == from(1))) } +fn num_eq_one(n: T) { + println(fmt!("%?", n == NumCast::from(1))) +} pub fn main() { num_eq_one(1f32); // you need to actually use the function to trigger the ICE diff --git a/src/test/run-pass/trait-inheritance-num5.rs b/src/test/run-pass/trait-inheritance-num5.rs index 02cc9a3d221f8..f56eca693ea53 100644 --- a/src/test/run-pass/trait-inheritance-num5.rs +++ b/src/test/run-pass/trait-inheritance-num5.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::cmp::{Eq, Ord}; -use core::num::NumCast::from; +use std::cmp::{Eq, Ord}; +use std::num::NumCast; pub trait NumExt: Eq + Num + NumCast {} @@ -17,7 +17,7 @@ impl NumExt for f32 {} impl NumExt for int {} fn num_eq_one() -> T { - from(1) + NumCast::from(1) } pub fn main() { diff --git a/src/test/run-pass/trait-inheritance-overloading-simple.rs b/src/test/run-pass/trait-inheritance-overloading-simple.rs index 3a1c3716df442..041452176e0e3 100644 --- a/src/test/run-pass/trait-inheritance-overloading-simple.rs +++ b/src/test/run-pass/trait-inheritance-overloading-simple.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::cmp::Eq; +use std::cmp::Eq; trait MyNum : Eq { } @@ -30,5 +30,5 @@ fn mi(v: int) -> MyInt { MyInt { val: v } } pub fn main() { let (x, y, z) = (mi(3), mi(5), mi(3)); assert!(x != y); - assert!(x == z); + assert_eq!(x, z); } diff --git a/src/test/run-pass/trait-inheritance-overloading-xc-exe.rs b/src/test/run-pass/trait-inheritance-overloading-xc-exe.rs index d89852e2b05f9..21f840ca8d346 100644 --- a/src/test/run-pass/trait-inheritance-overloading-xc-exe.rs +++ b/src/test/run-pass/trait-inheritance-overloading-xc-exe.rs @@ -23,7 +23,7 @@ fn mi(v: int) -> MyInt { MyInt { val: v } } pub fn main() { let (x, y) = (mi(3), mi(5)); let (a, b, c) = f(x, y); - assert!(a == mi(8)); - assert!(b == mi(-2)); - assert!(c == mi(15)); + assert_eq!(a, mi(8)); + assert_eq!(b, mi(-2)); + assert_eq!(c, mi(15)); } diff --git a/src/test/run-pass/trait-inheritance-overloading.rs b/src/test/run-pass/trait-inheritance-overloading.rs index e58ec24f1b7d4..302d3d87df909 100644 --- a/src/test/run-pass/trait-inheritance-overloading.rs +++ b/src/test/run-pass/trait-inheritance-overloading.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::cmp::Eq; +use std::cmp::Eq; trait MyNum : Add + Sub + Mul + Eq { } @@ -42,7 +42,7 @@ fn mi(v: int) -> MyInt { MyInt { val: v } } pub fn main() { let (x, y) = (mi(3), mi(5)); let (a, b, c) = f(x, y); - assert!(a == mi(8)); - assert!(b == mi(-2)); - assert!(c == mi(15)); + assert_eq!(a, mi(8)); + assert_eq!(b, mi(-2)); + assert_eq!(c, mi(15)); } diff --git a/src/test/run-pass/trait-inheritance-self-in-supertype.rs b/src/test/run-pass/trait-inheritance-self-in-supertype.rs index 8105cf23d8004..f28f8cadfd98c 100644 --- a/src/test/run-pass/trait-inheritance-self-in-supertype.rs +++ b/src/test/run-pass/trait-inheritance-self-in-supertype.rs @@ -1,5 +1,8 @@ // Test for issue #4183: use of Self in supertraits. +use std::f32; +use std::f64; + pub static FUZZY_EPSILON: float = 0.1; pub trait FuzzyEq { @@ -58,4 +61,4 @@ pub fn main() { assert!(compare::(6.19)); assert!(!compare::(7.28318530717958647692528676655900576)); assert!(!compare::(6.18)); -} \ No newline at end of file +} diff --git a/src/test/run-pass/trait-inheritance-self.rs b/src/test/run-pass/trait-inheritance-self.rs index 5eb87b7a96b8b..75b71c673a9cb 100644 --- a/src/test/run-pass/trait-inheritance-self.rs +++ b/src/test/run-pass/trait-inheritance-self.rs @@ -12,7 +12,7 @@ struct S { impl Foo for S { fn f(&self, x: &S) { - io::println(x.x.to_str()); + println(x.x.to_str()); } } diff --git a/src/test/run-pass/trait-inheritance-simple.rs b/src/test/run-pass/trait-inheritance-simple.rs index 2da1f02779e0a..113efa663afaf 100644 --- a/src/test/run-pass/trait-inheritance-simple.rs +++ b/src/test/run-pass/trait-inheritance-simple.rs @@ -26,6 +26,6 @@ fn gg(a: &T) -> int { pub fn main() { let a = &A { x: 3 }; - assert!(ff(a) == 10); - assert!(gg(a) == 20); + assert_eq!(ff(a), 10); + assert_eq!(gg(a), 20); } diff --git a/src/test/run-pass/trait-inheritance-static.rs b/src/test/run-pass/trait-inheritance-static.rs index 3b87387d4d6f1..08543b236f3dc 100644 --- a/src/test/run-pass/trait-inheritance-static.rs +++ b/src/test/run-pass/trait-inheritance-static.rs @@ -30,5 +30,5 @@ fn greater_than_one() -> T { MyNum::from_int(1) } pub fn main() { let v: S = greater_than_one(); - assert!(v.v == 1); + assert_eq!(v.v, 1); } diff --git a/src/test/run-pass/trait-inheritance-static2.rs b/src/test/run-pass/trait-inheritance-static2.rs index 2718949db070a..95131176ce752 100644 --- a/src/test/run-pass/trait-inheritance-static2.rs +++ b/src/test/run-pass/trait-inheritance-static2.rs @@ -34,5 +34,5 @@ fn greater_than_one() -> T { MyNum::from_int(1) } pub fn main() { let v: S = greater_than_one(); - assert!(v.v == 1); + assert_eq!(v.v, 1); } diff --git a/src/test/run-pass/trait-inheritance-subst2.rs b/src/test/run-pass/trait-inheritance-subst2.rs index 5d1741a45f327..214505172a51a 100644 --- a/src/test/run-pass/trait-inheritance-subst2.rs +++ b/src/test/run-pass/trait-inheritance-subst2.rs @@ -41,5 +41,5 @@ fn mi(v: int) -> MyInt { MyInt { val: v } } pub fn main() { let (x, y) = (mi(3), mi(5)); let z = f(x, y); - assert!(z.val == 13); + assert_eq!(z.val, 13); } diff --git a/src/test/run-pass/trait-inheritance-visibility.rs b/src/test/run-pass/trait-inheritance-visibility.rs index 81f119612d994..3cdedd884a42c 100644 --- a/src/test/run-pass/trait-inheritance-visibility.rs +++ b/src/test/run-pass/trait-inheritance-visibility.rs @@ -20,7 +20,7 @@ impl Quux for T { } // Foo is not in scope but because Quux is we can still access // Foo's methods on a Quux bound typaram fn f(x: &T) { - assert!(x.f() == 10); + assert_eq!(x.f(), 10); } pub fn main() { diff --git a/src/test/run-pass/trait-inheritance2.rs b/src/test/run-pass/trait-inheritance2.rs index adb7ab018d6c4..6046da412174f 100644 --- a/src/test/run-pass/trait-inheritance2.rs +++ b/src/test/run-pass/trait-inheritance2.rs @@ -22,9 +22,9 @@ impl Baz for A { fn h(&self) -> int { 30 } } impl Quux for A; fn f(a: &T) { - assert!(a.f() == 10); - assert!(a.g() == 20); - assert!(a.h() == 30); + assert_eq!(a.f(), 10); + assert_eq!(a.g(), 20); + assert_eq!(a.h(), 30); } pub fn main() { diff --git a/src/test/run-pass/trait-region-pointer-simple.rs b/src/test/run-pass/trait-region-pointer-simple.rs index a2742828a1bc0..0b54ccbbd47ce 100644 --- a/src/test/run-pass/trait-region-pointer-simple.rs +++ b/src/test/run-pass/trait-region-pointer-simple.rs @@ -18,7 +18,7 @@ struct A { impl Foo for A { fn f(&self) -> int { - io::println(~"Today's number is " + self.x.to_str()); + println(~"Today's number is " + self.x.to_str()); return self.x; } } @@ -26,5 +26,5 @@ impl Foo for A { pub fn main() { let a = A { x: 3 }; let b = (&a) as &Foo; - assert!(b.f() == 3); + assert_eq!(b.f(), 3); } diff --git a/src/test/run-pass/trait-static-method-overwriting.rs b/src/test/run-pass/trait-static-method-overwriting.rs index 86ebc5356ebdc..1f5c33e2bc097 100644 --- a/src/test/run-pass/trait-static-method-overwriting.rs +++ b/src/test/run-pass/trait-static-method-overwriting.rs @@ -11,6 +11,8 @@ // except according to those terms. mod base { + use std::io; + pub trait HasNew { fn new() -> T; } @@ -21,7 +23,7 @@ mod base { impl ::base::HasNew for Foo { fn new() -> Foo { - unsafe { io::println("Foo"); } + unsafe { println("Foo"); } Foo { dummy: () } } } diff --git a/src/test/run-pass/trait-to-str.rs b/src/test/run-pass/trait-to-str.rs index ca22b5942dbc7..9b94b78512594 100644 --- a/src/test/run-pass/trait-to-str.rs +++ b/src/test/run-pass/trait-to-str.rs @@ -10,11 +10,11 @@ // xfail-fast -#[no_core]; +#[no_std]; -extern mod core; +extern mod std; -use core::{str, int, vec}; +use std::{str, int, vec}; trait to_str { fn to_str(&self) -> ~str; @@ -26,7 +26,7 @@ impl to_str for int { impl to_str for ~[T] { fn to_str(&self) -> ~str { - ~"[" + str::connect(vec::map(*self, |e| e.to_str() ), ~", ") + ~"]" + ~"[" + str::connect(vec::map(*self, |e| e.to_str() ), ", ") + "]" } } diff --git a/src/test/run-pass/traits-default-method-macro.rs b/src/test/run-pass/traits-default-method-macro.rs index 7f106f71f8ed0..b25f345b9dec2 100644 --- a/src/test/run-pass/traits-default-method-macro.rs +++ b/src/test/run-pass/traits-default-method-macro.rs @@ -25,5 +25,5 @@ impl Foo for Baz { pub fn main() { let q = Quux; - assert!(q.bar() == ~"test"); + assert_eq!(q.bar(), ~"test"); } diff --git a/src/test/run-pass/trivial-message.rs b/src/test/run-pass/trivial-message.rs index 059d7ea5f70c0..2e0cc7e5a5790 100644 --- a/src/test/run-pass/trivial-message.rs +++ b/src/test/run-pass/trivial-message.rs @@ -12,6 +12,9 @@ This is about the simplest program that can successfully send a message. */ + +use std::comm; + pub fn main() { let (po, ch) = comm::stream(); ch.send(42); diff --git a/src/test/run-pass/tup.rs b/src/test/run-pass/tup.rs index c1a34a326a6e5..795ed1d0f8a01 100644 --- a/src/test/run-pass/tup.rs +++ b/src/test/run-pass/tup.rs @@ -13,15 +13,15 @@ type point = (int, int); fn f(p: point, x: int, y: int) { let (a, b) = p; - assert!((a == x)); - assert!((b == y)); + assert_eq!(a, x); + assert_eq!(b, y); } pub fn main() { let p: point = (10, 20); let (a, b) = p; - assert!((a == 10)); - assert!((b == 20)); + assert_eq!(a, 10); + assert_eq!(b, 20); let p2: point = p; f(p, 10, 20); f(p2, 10, 20); diff --git a/src/test/run-pass/tuple-struct-construct.rs b/src/test/run-pass/tuple-struct-construct.rs index c5ea3e14d3924..20be5df3242e7 100644 --- a/src/test/run-pass/tuple-struct-construct.rs +++ b/src/test/run-pass/tuple-struct-construct.rs @@ -12,5 +12,5 @@ struct Foo(int, int); pub fn main() { let x = Foo(1, 2); - io::println(fmt!("%?", x)); + println(fmt!("%?", x)); } diff --git a/src/test/run-pass/tuple-struct-destructuring.rs b/src/test/run-pass/tuple-struct-destructuring.rs index 1cb944da0403e..4a1258264f8d1 100644 --- a/src/test/run-pass/tuple-struct-destructuring.rs +++ b/src/test/run-pass/tuple-struct-destructuring.rs @@ -13,7 +13,7 @@ struct Foo(int, int); pub fn main() { let x = Foo(1, 2); let Foo(y, z) = x; - io::println(fmt!("%d %d", y, z)); - assert!(y == 1); - assert!(z == 2); + println(fmt!("%d %d", y, z)); + assert_eq!(y, 1); + assert_eq!(z, 2); } diff --git a/src/test/run-pass/tuple-struct-matching.rs b/src/test/run-pass/tuple-struct-matching.rs index e3cbd1201c127..261b913b1d2c8 100644 --- a/src/test/run-pass/tuple-struct-matching.rs +++ b/src/test/run-pass/tuple-struct-matching.rs @@ -14,9 +14,9 @@ pub fn main() { let x = Foo(1, 2); match x { Foo(a, b) => { - assert!(a == 1); - assert!(b == 2); - io::println(fmt!("%d %d", a, b)); + assert_eq!(a, 1); + assert_eq!(b, 2); + println(fmt!("%d %d", a, b)); } } } diff --git a/src/test/run-pass/type-sizes.rs b/src/test/run-pass/type-sizes.rs index 134f1e4098f07..5695254cdbffb 100644 --- a/src/test/run-pass/type-sizes.rs +++ b/src/test/run-pass/type-sizes.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod core; -use core::sys::size_of; +extern mod std; +use std::sys::size_of; struct t {a: u8, b: i8} struct u {a: u8, b: i8, c: u8} @@ -20,19 +20,19 @@ struct x {a: int, b: (), c: ()} struct y {x: int} pub fn main() { - assert!((size_of::() == 1 as uint)); - assert!((size_of::() == 4 as uint)); - assert!((size_of::() == 4 as uint)); - assert!((size_of::() == 1 as uint)); - assert!((size_of::() == 4 as uint)); - assert!((size_of::() == 2 as uint)); - assert!((size_of::() == 3 as uint)); + assert_eq!(size_of::(), 1 as uint); + assert_eq!(size_of::(), 4 as uint); + assert_eq!(size_of::(), 4 as uint); + assert_eq!(size_of::(), 1 as uint); + assert_eq!(size_of::(), 4 as uint); + assert_eq!(size_of::(), 2 as uint); + assert_eq!(size_of::(), 3 as uint); // Alignment causes padding before the char and the u32. assert!(size_of::() == 16 as uint); - assert!((size_of::() == size_of::())); - assert!((size_of::() == size_of::())); - assert!((size_of::() == size_of::())); - assert!((size_of::() == size_of::())); + assert_eq!(size_of::(), size_of::()); + assert_eq!(size_of::(), size_of::()); + assert_eq!(size_of::(), size_of::()); + assert_eq!(size_of::(), size_of::()); } diff --git a/src/test/run-pass/type-use-i1-versus-i8.rs b/src/test/run-pass/type-use-i1-versus-i8.rs index d180f6c726043..88b4fffc5a578 100644 --- a/src/test/run-pass/type-use-i1-versus-i8.rs +++ b/src/test/run-pass/type-use-i1-versus-i8.rs @@ -8,8 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::unstable; + pub fn main() { - let mut x: bool = false; - // this line breaks it - unstable::intrinsics::move_val_init(&mut x, false); + unsafe { + let mut x: bool = false; + // this line breaks it + unstable::intrinsics::move_val_init(&mut x, false); + } } diff --git a/src/test/run-pass/typestate-multi-decl.rs b/src/test/run-pass/typestate-multi-decl.rs index b4ca326fb5707..42910c4700581 100644 --- a/src/test/run-pass/typestate-multi-decl.rs +++ b/src/test/run-pass/typestate-multi-decl.rs @@ -8,4 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub fn main() { let x = 10, y = 20; let z = x + y; assert!((z == 30)); } +pub fn main() { + let (x, y) = (10, 20); + let z = x + y; + assert!((z == 30)); +} diff --git a/src/test/run-pass/u32-decr.rs b/src/test/run-pass/u32-decr.rs index 2b68e89ed26dd..f40d06f6c92dc 100644 --- a/src/test/run-pass/u32-decr.rs +++ b/src/test/run-pass/u32-decr.rs @@ -15,5 +15,5 @@ pub fn main() { let mut word: u32 = 200000u32; word = word - 1u32; - assert!((word == 199999u32)); + assert_eq!(word, 199999u32); } diff --git a/src/test/run-pass/u8-incr-decr.rs b/src/test/run-pass/u8-incr-decr.rs index e864cd0ad4ab4..18543599fd0bb 100644 --- a/src/test/run-pass/u8-incr-decr.rs +++ b/src/test/run-pass/u8-incr-decr.rs @@ -24,5 +24,5 @@ pub fn main() { y = y - 9u8; // 0x9 - assert!((x == y)); + assert_eq!(x, y); } diff --git a/src/test/run-pass/u8-incr.rs b/src/test/run-pass/u8-incr.rs index c9d31fb72b7c5..1a4013645e8ef 100644 --- a/src/test/run-pass/u8-incr.rs +++ b/src/test/run-pass/u8-incr.rs @@ -17,7 +17,7 @@ pub fn main() { let y: u8 = 12u8; x = x + 1u8; x = x - 1u8; - assert!((x == y)); + assert_eq!(x, y); // x = 14u8; // x = x + 1u8; diff --git a/src/test/run-pass/unify-return-ty.rs b/src/test/run-pass/unify-return-ty.rs index 820d42ab14d57..8bdce601b285c 100644 --- a/src/test/run-pass/unify-return-ty.rs +++ b/src/test/run-pass/unify-return-ty.rs @@ -11,7 +11,9 @@ // Tests that the tail expr in null() has its type // unified with the type *T, and so the type variable // in that type gets resolved. -extern mod std; +extern mod extra; + +use std::cast; fn null() -> *T { unsafe { diff --git a/src/test/run-pass/uniq-cc-generic.rs b/src/test/run-pass/uniq-cc-generic.rs index 7327f4a3498e0..b54b3b52692ed 100644 --- a/src/test/run-pass/uniq-cc-generic.rs +++ b/src/test/run-pass/uniq-cc-generic.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::ptr; + enum maybe_pointy { none, p(@mut Pointy), diff --git a/src/test/run-pass/unique-assign-copy.rs b/src/test/run-pass/unique-assign-copy.rs index d05cb76e11335..e59fe469dec6f 100644 --- a/src/test/run-pass/unique-assign-copy.rs +++ b/src/test/run-pass/unique-assign-copy.rs @@ -15,6 +15,6 @@ pub fn main() { j = i.clone(); *i = 2; *j = 3; - assert!(*i == 2); - assert!(*j == 3); + assert_eq!(*i, 2); + assert_eq!(*j, 3); } diff --git a/src/test/run-pass/unique-assign-drop.rs b/src/test/run-pass/unique-assign-drop.rs index 0faa6b1b555f6..2205eaeb97cc9 100644 --- a/src/test/run-pass/unique-assign-drop.rs +++ b/src/test/run-pass/unique-assign-drop.rs @@ -13,5 +13,5 @@ pub fn main() { let mut j = ~2; // Should drop the previous value of j j = i; - assert!(*j == 1); + assert_eq!(*j, 1); } diff --git a/src/test/run-pass/unique-assign-generic.rs b/src/test/run-pass/unique-assign-generic.rs index 75753b31ed7e2..67ffc797ee4bf 100644 --- a/src/test/run-pass/unique-assign-generic.rs +++ b/src/test/run-pass/unique-assign-generic.rs @@ -15,7 +15,7 @@ fn f(t: T) -> T { pub fn main() { let t = f(~100); - assert!(t == ~100); + assert_eq!(t, ~100); let t = f(~@~[100]); - assert!(t == ~@~[100]); + assert_eq!(t, ~@~[100]); } diff --git a/src/test/run-pass/unique-assign.rs b/src/test/run-pass/unique-assign.rs index 6fc16cae76f1d..43df53c78a8dd 100644 --- a/src/test/run-pass/unique-assign.rs +++ b/src/test/run-pass/unique-assign.rs @@ -11,5 +11,5 @@ pub fn main() { let mut i; i = ~1; - assert!(*i == 1); + assert_eq!(*i, 1); } diff --git a/src/test/run-pass/unique-autoderef-field.rs b/src/test/run-pass/unique-autoderef-field.rs index 07105a53caf27..6836ba4e79b00 100644 --- a/src/test/run-pass/unique-autoderef-field.rs +++ b/src/test/run-pass/unique-autoderef-field.rs @@ -14,5 +14,5 @@ pub fn main() { let i = ~J { j: 100 }; - assert!(i.j == 100); + assert_eq!(i.j, 100); } diff --git a/src/test/run-pass/unique-autoderef-index.rs b/src/test/run-pass/unique-autoderef-index.rs index 324efe5abe5c8..46f9ca794a9fe 100644 --- a/src/test/run-pass/unique-autoderef-index.rs +++ b/src/test/run-pass/unique-autoderef-index.rs @@ -10,5 +10,5 @@ pub fn main() { let i = ~~[100]; - assert!(i[0] == 100); + assert_eq!(i[0], 100); } diff --git a/src/test/run-pass/unique-containing-tag.rs b/src/test/run-pass/unique-containing-tag.rs index c8ed7b10a1ffa..ba5627fee5229 100644 --- a/src/test/run-pass/unique-containing-tag.rs +++ b/src/test/run-pass/unique-containing-tag.rs @@ -15,14 +15,14 @@ pub fn main() { /*alt *x { t1(a) { - assert!(a == 10); + assert_eq!(a, 10); } _ { fail!(); } }*/ /*alt x { ~t1(a) { - assert!(a == 10); + assert_eq!(a, 10); } _ { fail!(); } }*/ diff --git a/src/test/run-pass/unique-copy-box.rs b/src/test/run-pass/unique-copy-box.rs index b483881f1a63c..7634641a56e8f 100644 --- a/src/test/run-pass/unique-copy-box.rs +++ b/src/test/run-pass/unique-copy-box.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::sys; + pub fn main() { unsafe { let i = ~@1; @@ -16,6 +18,6 @@ pub fn main() { let j = copy i; let rc2 = sys::refcount(*i); error!("rc1: %u rc2: %u", rc1, rc2); - assert!(rc1 + 1u == rc2); + assert_eq!(rc1 + 1u, rc2); } } diff --git a/src/test/run-pass/unique-decl-init-copy.rs b/src/test/run-pass/unique-decl-init-copy.rs index 670bc35d85748..13594d86f6764 100644 --- a/src/test/run-pass/unique-decl-init-copy.rs +++ b/src/test/run-pass/unique-decl-init-copy.rs @@ -14,6 +14,6 @@ pub fn main() { let mut j = i.clone(); *i = 2; *j = 3; - assert!(*i == 2); - assert!(*j == 3); + assert_eq!(*i, 2); + assert_eq!(*j, 3); } diff --git a/src/test/run-pass/unique-decl-init.rs b/src/test/run-pass/unique-decl-init.rs index f5f1829cae047..c507d19fac16b 100644 --- a/src/test/run-pass/unique-decl-init.rs +++ b/src/test/run-pass/unique-decl-init.rs @@ -11,5 +11,5 @@ pub fn main() { let i = ~1; let j = i; - assert!(*j == 1); + assert_eq!(*j, 1); } diff --git a/src/test/run-pass/unique-decl-move-temp.rs b/src/test/run-pass/unique-decl-move-temp.rs index b9f122acbcd7f..6cf781d735cfa 100644 --- a/src/test/run-pass/unique-decl-move-temp.rs +++ b/src/test/run-pass/unique-decl-move-temp.rs @@ -10,5 +10,5 @@ pub fn main() { let i = ~100; - assert!(*i == 100); + assert_eq!(*i, 100); } diff --git a/src/test/run-pass/unique-decl-move.rs b/src/test/run-pass/unique-decl-move.rs index 81c59bae35708..335275ff7c102 100644 --- a/src/test/run-pass/unique-decl-move.rs +++ b/src/test/run-pass/unique-decl-move.rs @@ -11,5 +11,5 @@ pub fn main() { let i = ~100; let j = i; - assert!(*j == 100); + assert_eq!(*j, 100); } diff --git a/src/test/run-pass/unique-deref.rs b/src/test/run-pass/unique-deref.rs index b9f122acbcd7f..6cf781d735cfa 100644 --- a/src/test/run-pass/unique-deref.rs +++ b/src/test/run-pass/unique-deref.rs @@ -10,5 +10,5 @@ pub fn main() { let i = ~100; - assert!(*i == 100); + assert_eq!(*i, 100); } diff --git a/src/test/run-pass/unique-destructure.rs b/src/test/run-pass/unique-destructure.rs index 64e01f8647465..6c35cb4dba77b 100644 --- a/src/test/run-pass/unique-destructure.rs +++ b/src/test/run-pass/unique-destructure.rs @@ -12,5 +12,5 @@ struct Foo { a: int, b: int } pub fn main() { let ~Foo{a, b} = ~Foo{a: 100, b: 200}; - assert!(a + b == 300); + assert_eq!(a + b, 300); } diff --git a/src/test/run-pass/unique-fn-arg-move.rs b/src/test/run-pass/unique-fn-arg-move.rs index 4a6386244f177..503bbae8c55a9 100644 --- a/src/test/run-pass/unique-fn-arg-move.rs +++ b/src/test/run-pass/unique-fn-arg-move.rs @@ -9,7 +9,7 @@ // except according to those terms. fn f(i: ~int) { - assert!(*i == 100); + assert_eq!(*i, 100); } pub fn main() { diff --git a/src/test/run-pass/unique-fn-arg-mut.rs b/src/test/run-pass/unique-fn-arg-mut.rs index 56ec9663ec626..c2d78c3303902 100644 --- a/src/test/run-pass/unique-fn-arg-mut.rs +++ b/src/test/run-pass/unique-fn-arg-mut.rs @@ -15,5 +15,5 @@ fn f(i: &mut ~int) { pub fn main() { let mut i = ~100; f(&mut i); - assert!(*i == 200); + assert_eq!(*i, 200); } diff --git a/src/test/run-pass/unique-fn-arg.rs b/src/test/run-pass/unique-fn-arg.rs index 931c5acbe1d76..230131bae62bc 100644 --- a/src/test/run-pass/unique-fn-arg.rs +++ b/src/test/run-pass/unique-fn-arg.rs @@ -9,7 +9,7 @@ // except according to those terms. fn f(i: ~int) { - assert!(*i == 100); + assert_eq!(*i, 100); } pub fn main() { diff --git a/src/test/run-pass/unique-fn-ret.rs b/src/test/run-pass/unique-fn-ret.rs index 0ef9d12f75b0d..dd39e136fc9bb 100644 --- a/src/test/run-pass/unique-fn-ret.rs +++ b/src/test/run-pass/unique-fn-ret.rs @@ -13,5 +13,5 @@ fn f() -> ~int { } pub fn main() { - assert!(f() == ~100); + assert_eq!(f(), ~100); } diff --git a/src/test/run-pass/unique-in-vec-copy.rs b/src/test/run-pass/unique-in-vec-copy.rs index e72262795796c..3a27d7844bcad 100644 --- a/src/test/run-pass/unique-in-vec-copy.rs +++ b/src/test/run-pass/unique-in-vec-copy.rs @@ -12,12 +12,12 @@ pub fn main() { let mut a = ~[~10]; let b = a.clone(); - assert!(*a[0] == 10); - assert!(*b[0] == 10); + assert_eq!(*a[0], 10); + assert_eq!(*b[0], 10); // This should only modify the value in a, not b *a[0] = 20; - assert!(*a[0] == 20); - assert!(*b[0] == 10); + assert_eq!(*a[0], 20); + assert_eq!(*b[0], 10); } diff --git a/src/test/run-pass/unique-kinds.rs b/src/test/run-pass/unique-kinds.rs index da48f2ff51ba8..b3ce71dcbff5d 100644 --- a/src/test/run-pass/unique-kinds.rs +++ b/src/test/run-pass/unique-kinds.rs @@ -8,12 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::cmp::Eq; +use std::cmp::Eq; fn sendable() { fn f(i: T, j: T) { - assert!(i == j); + assert_eq!(i, j); } fn g(i: T, j: T) { @@ -31,7 +31,7 @@ fn sendable() { fn copyable() { fn f(i: T, j: T) { - assert!(i == j); + assert_eq!(i, j); } fn g(i: T, j: T) { @@ -49,7 +49,7 @@ fn copyable() { fn noncopyable() { fn f(i: T, j: T) { - assert!(i == j); + assert_eq!(i, j); } fn g(i: T, j: T) { diff --git a/src/test/run-pass/unique-alt-discrim.rs b/src/test/run-pass/unique-match-discrim.rs similarity index 100% rename from src/test/run-pass/unique-alt-discrim.rs rename to src/test/run-pass/unique-match-discrim.rs diff --git a/src/test/run-pass/unique-move-drop.rs b/src/test/run-pass/unique-move-drop.rs index 5ddc85ea5faa6..29267956a59f4 100644 --- a/src/test/run-pass/unique-move-drop.rs +++ b/src/test/run-pass/unique-move-drop.rs @@ -12,5 +12,5 @@ pub fn main() { let i = ~100; let j = ~200; let j = i; - assert!(*j == 100); + assert_eq!(*j, 100); } diff --git a/src/test/run-pass/unique-move-temp.rs b/src/test/run-pass/unique-move-temp.rs index 343b0d431428b..7c7ca1379ea29 100644 --- a/src/test/run-pass/unique-move-temp.rs +++ b/src/test/run-pass/unique-move-temp.rs @@ -11,5 +11,5 @@ pub fn main() { let mut i; i = ~100; - assert!(*i == 100); + assert_eq!(*i, 100); } diff --git a/src/test/run-pass/unique-move.rs b/src/test/run-pass/unique-move.rs index 3331350facdcb..dbdfc5cb5bb5f 100644 --- a/src/test/run-pass/unique-move.rs +++ b/src/test/run-pass/unique-move.rs @@ -12,5 +12,5 @@ pub fn main() { let i = ~100; let mut j; j = i; - assert!(*j == 100); + assert_eq!(*j, 100); } diff --git a/src/test/run-pass/unique-mutable.rs b/src/test/run-pass/unique-mutable.rs index e4a1b4a548b4b..4f353c566717c 100644 --- a/src/test/run-pass/unique-mutable.rs +++ b/src/test/run-pass/unique-mutable.rs @@ -11,5 +11,5 @@ pub fn main() { let mut i = ~0; *i = 1; - assert!(*i == 1); + assert_eq!(*i, 1); } diff --git a/src/test/run-pass/trait_with_static_methods_cross_crate.rs b/src/test/run-pass/unique-object-move.rs similarity index 70% rename from src/test/run-pass/trait_with_static_methods_cross_crate.rs rename to src/test/run-pass/unique-object-move.rs index 1af8629468024..540de1652138b 100644 --- a/src/test/run-pass/trait_with_static_methods_cross_crate.rs +++ b/src/test/run-pass/unique-object-move.rs @@ -8,12 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// xfail-fast -// aux-build:mod_trait_with_static_methods_lib.rs -extern mod mod_trait_with_static_methods_lib; +// Issue #5192 -use mod_trait_with_static_methods_lib::Foo; +pub trait EventLoop { } -pub fn main() { - assert!(42 == Foo::foo()); +pub struct UvEventLoop { + uvio: int } + +impl EventLoop for UvEventLoop { } + +pub fn main() { + let loop_: ~EventLoop = ~UvEventLoop { uvio: 0 } as ~EventLoop; + let loop2_ = loop_; +} \ No newline at end of file diff --git a/src/test/run-pass/unique-object.rs b/src/test/run-pass/unique-object.rs index 5e0954969ef8d..e645f13cd4c51 100644 --- a/src/test/run-pass/unique-object.rs +++ b/src/test/run-pass/unique-object.rs @@ -25,5 +25,5 @@ impl Foo for Bar { pub fn main() { let x = ~Bar { x: 10 }; let y = x as ~Foo; - assert!(y.f() == 10); + assert_eq!(y.f(), 10); } diff --git a/src/test/run-pass/unique-pinned-nocopy-2.rs b/src/test/run-pass/unique-pinned-nocopy-2.rs index d3cdc9a878875..197f26f897d86 100644 --- a/src/test/run-pass/unique-pinned-nocopy-2.rs +++ b/src/test/run-pass/unique-pinned-nocopy-2.rs @@ -32,5 +32,5 @@ pub fn main() { { let j = ~r(i); } - assert!(*i == 1); + assert_eq!(*i, 1); } diff --git a/src/test/run-pass/unique-rec.rs b/src/test/run-pass/unique-rec.rs index 0564c2ebddd12..f740dd2a22cdb 100644 --- a/src/test/run-pass/unique-rec.rs +++ b/src/test/run-pass/unique-rec.rs @@ -13,5 +13,5 @@ struct X { x: int } pub fn main() { let x = ~X {x: 1}; let bar = x; - assert!(bar.x == 1); + assert_eq!(bar.x, 1); } diff --git a/src/test/run-pass/unique-send-2.rs b/src/test/run-pass/unique-send-2.rs index df1c8708acd11..a6bed9e2398e2 100644 --- a/src/test/run-pass/unique-send-2.rs +++ b/src/test/run-pass/unique-send-2.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::comm::*; +use std::comm::*; +use std::task; +use std::uint; fn child(c: &SharedChan<~uint>, i: uint) { c.send(~i); @@ -31,5 +33,5 @@ pub fn main() { actual += *j; } - assert!(expected == actual); + assert_eq!(expected, actual); } diff --git a/src/test/run-pass/unique-send.rs b/src/test/run-pass/unique-send.rs index c9d3a9519209d..05012f789c38f 100644 --- a/src/test/run-pass/unique-send.rs +++ b/src/test/run-pass/unique-send.rs @@ -8,11 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::comm::*; +use std::comm::*; pub fn main() { let (p, c) = stream(); c.send(~100); let v = p.recv(); - assert!(v == ~100); + assert_eq!(v, ~100); } diff --git a/src/test/run-pass/unique-swap.rs b/src/test/run-pass/unique-swap.rs index bf58e2c7cb53b..a372e4a4d98a6 100644 --- a/src/test/run-pass/unique-swap.rs +++ b/src/test/run-pass/unique-swap.rs @@ -8,12 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::util; +use std::util; pub fn main() { let mut i = ~100; let mut j = ~200; util::swap(&mut i, &mut j); - assert!(i == ~200); - assert!(j == ~100); + assert_eq!(i, ~200); + assert_eq!(j, ~100); } diff --git a/src/test/run-pass/unit-like-struct-drop-run.rs b/src/test/run-pass/unit-like-struct-drop-run.rs new file mode 100644 index 0000000000000..b19a0aa1e98a9 --- /dev/null +++ b/src/test/run-pass/unit-like-struct-drop-run.rs @@ -0,0 +1,29 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Make sure the destructor is run for unit-like structs. +// xfail-fast + +use std::task; + +struct Foo; + +impl Drop for Foo { + fn finalize(&self) { + fail!("This failure should happen."); + } +} + +fn main() { + let x = do task::try { + let _b = Foo; + }; + assert_eq!(x, Err(())); +} diff --git a/src/test/run-pass/unit-like-struct.rs b/src/test/run-pass/unit-like-struct.rs index 1b81015b02910..82aeb08a7035f 100644 --- a/src/test/run-pass/unit-like-struct.rs +++ b/src/test/run-pass/unit-like-struct.rs @@ -13,6 +13,6 @@ struct Foo; pub fn main() { let x: Foo = Foo; match x { - Foo => { io::println("hi"); } + Foo => { println("hi"); } } } diff --git a/src/test/run-pass/unsafe-pointer-assignability.rs b/src/test/run-pass/unsafe-pointer-assignability.rs index f19558fbb1d01..3385c6f6fef53 100644 --- a/src/test/run-pass/unsafe-pointer-assignability.rs +++ b/src/test/run-pass/unsafe-pointer-assignability.rs @@ -10,7 +10,7 @@ fn f(x: *int) { unsafe { - assert!(*x == 3); + assert_eq!(*x, 3); } } diff --git a/src/test/run-pass/unwind-box.rs b/src/test/run-pass/unwind-box.rs index 90e8d41d26a2d..2d0967a6fa360 100644 --- a/src/test/run-pass/unwind-box.rs +++ b/src/test/run-pass/unwind-box.rs @@ -9,7 +9,9 @@ // except according to those terms. // xfail-win32 -extern mod std; +extern mod extra; + +use std::task; fn f() { let a = @0; diff --git a/src/test/run-pass/unwind-resource.rs b/src/test/run-pass/unwind-resource.rs index 4c7b2e6370242..4b71d79ccc4fb 100644 --- a/src/test/run-pass/unwind-resource.rs +++ b/src/test/run-pass/unwind-resource.rs @@ -9,9 +9,10 @@ // except according to those terms. // xfail-win32 -extern mod std; +extern mod extra; -use core::comm::*; +use std::comm::*; +use std::task; struct complainer { c: SharedChan, diff --git a/src/test/run-pass/unwind-resource2.rs b/src/test/run-pass/unwind-resource2.rs index 993acc2264f68..b5a496eb20615 100644 --- a/src/test/run-pass/unwind-resource2.rs +++ b/src/test/run-pass/unwind-resource2.rs @@ -9,7 +9,9 @@ // except according to those terms. // xfail-win32 -extern mod std; +extern mod extra; + +use std::task; struct complainer { c: @int, diff --git a/src/test/run-pass/unwind-unique.rs b/src/test/run-pass/unwind-unique.rs index 8b0850cff774d..ba75676298b4e 100644 --- a/src/test/run-pass/unwind-unique.rs +++ b/src/test/run-pass/unwind-unique.rs @@ -9,7 +9,9 @@ // except according to those terms. // xfail-win32 -extern mod std; +extern mod extra; + +use std::task; fn f() { let a = ~0; diff --git a/src/test/run-pass/use-crate-name-alias.rs b/src/test/run-pass/use-crate-name-alias.rs index ea9dcc2f56279..4954de3919ffe 100644 --- a/src/test/run-pass/use-crate-name-alias.rs +++ b/src/test/run-pass/use-crate-name-alias.rs @@ -9,6 +9,6 @@ // except according to those terms. // Issue #1706 -extern mod stdlib(name="std"); +extern mod stdlib(name="extra"); pub fn main() {} diff --git a/src/test/run-pass/use-uninit-alt.rs b/src/test/run-pass/use-uninit-match.rs similarity index 100% rename from src/test/run-pass/use-uninit-alt.rs rename to src/test/run-pass/use-uninit-match.rs diff --git a/src/test/run-pass/use-uninit-alt2.rs b/src/test/run-pass/use-uninit-match2.rs similarity index 100% rename from src/test/run-pass/use-uninit-alt2.rs rename to src/test/run-pass/use-uninit-match2.rs diff --git a/src/test/run-pass/use.rs b/src/test/run-pass/use.rs index 0bd4175d39043..d73eb6641fadf 100644 --- a/src/test/run-pass/use.rs +++ b/src/test/run-pass/use.rs @@ -10,17 +10,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[no_core]; -extern mod core; -extern mod zed(name = "core"); -extern mod bar(name = "core", vers = "0.7-pre"); +#[no_std]; +extern mod std; +extern mod zed(name = "std"); +extern mod bar(name = "std", vers = "0.7-pre"); -use core::str; +use std::str; use x = zed::str; mod baz { pub use bar::str; - pub use x = core::str; + pub use x = std::str; } pub fn main() { } diff --git a/src/test/run-pass/utf8.rs b/src/test/run-pass/utf8.rs index 51fc42491e059..fd5bc07e01550 100644 --- a/src/test/run-pass/utf8.rs +++ b/src/test/run-pass/utf8.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::str; + pub fn main() { let yen: char = '¥'; // 0xa5 let c_cedilla: char = 'ç'; // 0xe7 @@ -15,14 +17,14 @@ pub fn main() { let y_diaeresis: char = 'ÿ'; // 0xff let pi: char = 'Π'; // 0x3a0 - assert!((yen as int == 0xa5)); - assert!((c_cedilla as int == 0xe7)); - assert!((thorn as int == 0xfe)); - assert!((y_diaeresis as int == 0xff)); - assert!((pi as int == 0x3a0)); + assert_eq!(yen as int, 0xa5); + assert_eq!(c_cedilla as int, 0xe7); + assert_eq!(thorn as int, 0xfe); + assert_eq!(y_diaeresis as int, 0xff); + assert_eq!(pi as int, 0x3a0); - assert!((pi as int == '\u03a0' as int)); - assert!(('\x0a' as int == '\n' as int)); + assert_eq!(pi as int, '\u03a0' as int); + assert_eq!('\x0a' as int, '\n' as int); let bhutan: ~str = ~"འབྲུག་ཡུལ།"; let japan: ~str = ~"日本"; @@ -37,7 +39,7 @@ pub fn main() { let austria_e: ~str = ~"\u00d6sterreich"; let oo: char = 'Ö'; - assert!((oo as int == 0xd6)); + assert_eq!(oo as int, 0xd6); fn check_str_eq(a: ~str, b: ~str) { let mut i: int = 0; @@ -46,7 +48,7 @@ pub fn main() { debug!(ab); let bb: u8 = b[i]; debug!(bb); - assert!((ab == bb)); + assert_eq!(ab, bb); i += 1; } } diff --git a/src/test/run-pass/utf8_chars.rs b/src/test/run-pass/utf8_chars.rs index 714fd6e3ac5ab..2343949f049a6 100644 --- a/src/test/run-pass/utf8_chars.rs +++ b/src/test/run-pass/utf8_chars.rs @@ -8,19 +8,22 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; +extern mod extra; + +use std::str; +use std::vec; pub fn main() { // Chars of 1, 2, 3, and 4 bytes let chs: ~[char] = ~['e', 'é', '€', 0x10000 as char]; let s: ~str = str::from_chars(chs); - assert!((str::len(s) == 10u)); - assert!((str::char_len(s) == 4u)); - assert!((vec::len(str::to_chars(s)) == 4u)); - assert!((str::from_chars(str::to_chars(s)) == s)); - assert!((str::char_at(s, 0u) == 'e')); - assert!((str::char_at(s, 1u) == 'é')); + assert!(str::len(s) == 10u); + assert!(str::char_len(s) == 4u); + assert!(vec::len(str::to_chars(s)) == 4u); + assert!(str::from_chars(str::to_chars(s)) == s); + assert!(str::char_at(s, 0u) == 'e'); + assert!(str::char_at(s, 1u) == 'é'); assert!((str::is_utf8(str::to_bytes(s)))); assert!((!str::is_utf8(~[0x80_u8]))); @@ -28,12 +31,12 @@ pub fn main() { assert!((!str::is_utf8(~[0xc0_u8, 0x10_u8]))); let mut stack = ~"a×c€"; - assert!((str::pop_char(&mut stack) == '€')); - assert!((str::pop_char(&mut stack) == 'c')); + assert_eq!(str::pop_char(&mut stack), '€'); + assert_eq!(str::pop_char(&mut stack), 'c'); str::push_char(&mut stack, 'u'); - assert!((stack == ~"a×u")); - assert!((str::shift_char(&mut stack) == 'a')); - assert!((str::shift_char(&mut stack) == '×')); + assert!(stack == ~"a×u"); + assert_eq!(str::shift_char(&mut stack), 'a'); + assert_eq!(str::shift_char(&mut stack), '×'); str::unshift_char(&mut stack, 'ß'); - assert!((stack == ~"ßu")); + assert!(stack == ~"ßu"); } diff --git a/src/test/run-pass/utf8_idents.rs b/src/test/run-pass/utf8_idents.rs index 25d2d91d565df..2e1bec53cee6c 100644 --- a/src/test/run-pass/utf8_idents.rs +++ b/src/test/run-pass/utf8_idents.rs @@ -8,12 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::float; + pub fn main() { let ε = 0.00001; let Π = 3.14; let लंच = Π * Π + 1.54; assert!(float::abs((लंच - 1.54) - (Π * Π)) < ε); - assert!(საჭმელად_გემრიელი_სადილი() == 0); + assert_eq!(საჭმელად_გემრიელი_სადილი(), 0); } fn საჭმელად_გემრიელი_სადილი() -> int { @@ -37,9 +39,9 @@ fn საჭმელად_გემრიელი_სადილი() -> int // Lunchy arithmetic, mm. - assert!(hádegismatur * ручек * обед == 1000); - assert!(10 == ארוחת_צהריי); - assert!(ランチ + 午餐 + μεσημεριανό == 30); - assert!(ăn_trưa + อาหารกลางวัน == 20); + assert_eq!(hádegismatur * ручек * обед, 1000); + assert_eq!(10, ארוחת_צהריי); + assert_eq!(ランチ + 午餐 + μεσημεριανό, 30); + assert_eq!(ăn_trưa + อาหารกลางวัน, 20); return (абед + լանչ) >> غداء; } diff --git a/src/test/run-pass/vec-concat.rs b/src/test/run-pass/vec-concat.rs index 0045b356d652e..b6fa7c107dbc7 100644 --- a/src/test/run-pass/vec-concat.rs +++ b/src/test/run-pass/vec-concat.rs @@ -14,7 +14,7 @@ pub fn main() { let b: ~[int] = ~[6, 7, 8, 9, 0]; let v: ~[int] = a + b; debug!(v[9]); - assert!((v[0] == 1)); - assert!((v[7] == 8)); - assert!((v[9] == 0)); + assert_eq!(v[0], 1); + assert_eq!(v[7], 8); + assert_eq!(v[9], 0); } diff --git a/src/test/run-pass/vec-each2_mut.rs b/src/test/run-pass/vec-each2_mut.rs index 3c6b7da9f1478..73e0418993c41 100644 --- a/src/test/run-pass/vec-each2_mut.rs +++ b/src/test/run-pass/vec-each2_mut.rs @@ -9,6 +9,10 @@ // except according to those terms. // -*- rust -*- + +use std::io; +use std::vec; + fn main(){ let mut t1 = ~[]; t1.push('a'); @@ -17,8 +21,8 @@ fn main(){ t2.push('b'); for vec::each2_mut(t1, t2) | i1, i2 | { - assert!(*i1 == 'a'); - assert!(*i2 == 'b'); + assert_eq!(*i1, 'a'); + assert_eq!(*i2, 'b'); } for vec::each2(t1, t2) | i1, i2 | { @@ -28,8 +32,8 @@ fn main(){ for vec::each2_mut(t1, t2) | i1, i2 | { *i1 = 'b'; *i2 = 'a'; - assert!(*i1 == 'b'); - assert!(*i2 == 'a'); + assert_eq!(*i1, 'b'); + assert_eq!(*i2, 'a'); } for vec::each2(t1, t2) | i1, i2 | { diff --git a/src/test/run-pass/vec-fixed-length.rs b/src/test/run-pass/vec-fixed-length.rs index 2c4add63e8b87..56adc6d259881 100644 --- a/src/test/run-pass/vec-fixed-length.rs +++ b/src/test/run-pass/vec-fixed-length.rs @@ -10,5 +10,5 @@ pub fn main() { let x: [int, ..4] = [1, 2, 3, 4]; - io::println(fmt!("%d", x[0])); + println(fmt!("%d", x[0])); } diff --git a/src/test/run-pass/vec-growth.rs b/src/test/run-pass/vec-growth.rs index e1e268e63deb5..816228b62c674 100644 --- a/src/test/run-pass/vec-growth.rs +++ b/src/test/run-pass/vec-growth.rs @@ -16,9 +16,9 @@ pub fn main() { v += ~[3]; v += ~[4]; v += ~[5]; - assert!((v[0] == 1)); - assert!((v[1] == 2)); - assert!((v[2] == 3)); - assert!((v[3] == 4)); - assert!((v[4] == 5)); + assert_eq!(v[0], 1); + assert_eq!(v[1], 2); + assert_eq!(v[2], 3); + assert_eq!(v[3], 4); + assert_eq!(v[4], 5); } diff --git a/src/test/run-pass/vec-matching-autoslice.rs b/src/test/run-pass/vec-matching-autoslice.rs index 012b8b83637aa..d04deeac52e31 100644 --- a/src/test/run-pass/vec-matching-autoslice.rs +++ b/src/test/run-pass/vec-matching-autoslice.rs @@ -1,22 +1,22 @@ pub fn main() { let x = @[1, 2, 3]; match x { - [2, .._] => ::core::util::unreachable(), + [2, .._] => ::std::util::unreachable(), [1, ..tail] => { - assert!(tail == [2, 3]); + assert_eq!(tail, [2, 3]); } - [_] => ::core::util::unreachable(), - [] => ::core::util::unreachable() + [_] => ::std::util::unreachable(), + [] => ::std::util::unreachable() } let y = (~[(1, true), (2, false)], 0.5); match y { - ([_, _, _], 0.5) => ::core::util::unreachable(), + ([_, _, _], 0.5) => ::std::util::unreachable(), ([(1, a), (b, false), ..tail], _) => { - assert!(a == true); - assert!(b == 2); + assert_eq!(a, true); + assert_eq!(b, 2); assert!(tail.is_empty()); } - ([..tail], _) => ::core::util::unreachable() + ([..tail], _) => ::std::util::unreachable() } } diff --git a/src/test/run-pass/vec-matching-fold.rs b/src/test/run-pass/vec-matching-fold.rs index e6b7bffc1583d..05a6dee06cc87 100644 --- a/src/test/run-pass/vec-matching-fold.rs +++ b/src/test/run-pass/vec-matching-fold.rs @@ -4,8 +4,8 @@ fn foldl( function: &fn(partial: U, element: &T) -> U ) -> U { match values { - [head, ..tail] => - foldl(tail, function(initial, &head), function), + [ref head, ..tail] => + foldl(tail, function(initial, head), function), [] => initial.clone() } } @@ -16,8 +16,8 @@ fn foldr( function: &fn(element: &T, partial: U) -> U ) -> U { match values { - [..head, tail] => - foldr(head, function(&tail, initial), function), + [..head, ref tail] => + foldr(head, function(tail, initial), function), [] => initial.clone() } } @@ -26,8 +26,8 @@ pub fn main() { let x = [1, 2, 3, 4, 5]; let product = foldl(x, 1, |a, b| a * *b); - assert!(product == 120); + assert_eq!(product, 120); let sum = foldr(x, 0, |a, b| *a + b); - assert!(sum == 15); + assert_eq!(sum, 15); } diff --git a/src/test/run-pass/vec-matching-legal-tail-element-borrow.rs b/src/test/run-pass/vec-matching-legal-tail-element-borrow.rs index 561d5555f128a..aae287deb8a1e 100644 --- a/src/test/run-pass/vec-matching-legal-tail-element-borrow.rs +++ b/src/test/run-pass/vec-matching-legal-tail-element-borrow.rs @@ -3,8 +3,8 @@ pub fn main() { if !x.is_empty() { let el = match x { [1, ..ref tail] => &tail[0], - _ => ::core::util::unreachable() + _ => ::std::util::unreachable() }; - io::println(fmt!("%d", *el)); + println(fmt!("%d", *el)); } } diff --git a/src/test/run-pass/vec-matching.rs b/src/test/run-pass/vec-matching.rs index e9cf400334cbe..5e906fa265994 100644 --- a/src/test/run-pass/vec-matching.rs +++ b/src/test/run-pass/vec-matching.rs @@ -1,14 +1,14 @@ fn a() { let x = [1]; match x { - [_, _, _, _, _, .._] => ::core::util::unreachable(), - [.._, _, _, _, _] => ::core::util::unreachable(), - [_, .._, _, _] => ::core::util::unreachable(), - [_, _] => ::core::util::unreachable(), + [_, _, _, _, _, .._] => ::std::util::unreachable(), + [.._, _, _, _, _] => ::std::util::unreachable(), + [_, .._, _, _] => ::std::util::unreachable(), + [_, _] => ::std::util::unreachable(), [a] => { - assert!(a == 1); + assert_eq!(a, 1); } - [] => ::core::util::unreachable() + [] => ::std::util::unreachable() } } @@ -16,33 +16,33 @@ fn b() { let x = [1, 2, 3]; match x { [a, b, ..c] => { - assert!(a == 1); - assert!(b == 2); - assert!(c == &[3]); + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, &[3]); } _ => fail!() } match x { [..a, b, c] => { - assert!(a == &[1]); - assert!(b == 2); - assert!(c == 3); + assert_eq!(a, &[1]); + assert_eq!(b, 2); + assert_eq!(c, 3); } _ => fail!() } match x { [a, ..b, c] => { - assert!(a == 1); - assert!(b == &[2]); - assert!(c == 3); + assert_eq!(a, 1); + assert_eq!(b, &[2]); + assert_eq!(c, 3); } _ => fail!() } match x { [a, b, c] => { - assert!(a == 1); - assert!(b == 2); - assert!(c == 3); + assert_eq!(a, 1); + assert_eq!(b, 2); + assert_eq!(c, 3); } _ => fail!() } diff --git a/src/test/run-pass/vec-self-append.rs b/src/test/run-pass/vec-self-append.rs index 7507a78378e8f..ef661c7ed6723 100644 --- a/src/test/run-pass/vec-self-append.rs +++ b/src/test/run-pass/vec-self-append.rs @@ -8,23 +8,23 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; +extern mod extra; fn test_heap_to_heap() { // a spills onto the heap let mut a = ~[0, 1, 2, 3, 4]; a = a + a; // FIXME(#3387)---can't write a += a - assert!(a.len() == 10u); - assert!((a[0] == 0)); - assert!((a[1] == 1)); - assert!((a[2] == 2)); - assert!((a[3] == 3)); - assert!((a[4] == 4)); - assert!((a[5] == 0)); - assert!((a[6] == 1)); - assert!((a[7] == 2)); - assert!((a[8] == 3)); - assert!((a[9] == 4)); + assert_eq!(a.len(), 10u); + assert_eq!(a[0], 0); + assert_eq!(a[1], 1); + assert_eq!(a[2], 2); + assert_eq!(a[3], 3); + assert_eq!(a[4], 4); + assert_eq!(a[5], 0); + assert_eq!(a[6], 1); + assert_eq!(a[7], 2); + assert_eq!(a[8], 3); + assert_eq!(a[9], 4); } fn test_stack_to_heap() { @@ -32,13 +32,13 @@ fn test_stack_to_heap() { let mut a = ~[0, 1, 2]; // a spills to the heap a = a + a; // FIXME(#3387)---can't write a += a - assert!(a.len() == 6u); - assert!((a[0] == 0)); - assert!((a[1] == 1)); - assert!((a[2] == 2)); - assert!((a[3] == 0)); - assert!((a[4] == 1)); - assert!((a[5] == 2)); + assert_eq!(a.len(), 6u); + assert_eq!(a[0], 0); + assert_eq!(a[1], 1); + assert_eq!(a[2], 2); + assert_eq!(a[3], 0); + assert_eq!(a[4], 1); + assert_eq!(a[5], 2); } fn test_loop() { @@ -48,7 +48,7 @@ fn test_loop() { let mut expected_len = 1u; while i > 0 { error!(a.len()); - assert!(a.len() == expected_len); + assert_eq!(a.len(), expected_len); a = a + a; // FIXME(#3387)---can't write a += a i -= 1; expected_len *= 2u; diff --git a/src/test/run-pass/vec-slice-drop.rs b/src/test/run-pass/vec-slice-drop.rs index cc0649790fd87..695441daf2858 100644 --- a/src/test/run-pass/vec-slice-drop.rs +++ b/src/test/run-pass/vec-slice-drop.rs @@ -32,7 +32,7 @@ pub fn main() { let x = @mut 0; { let l = &[foo(x)]; - assert!(*l[0].x == 0); + assert_eq!(*l[0].x, 0); } - assert!(*x == 1); + assert_eq!(*x, 1); } diff --git a/src/test/run-pass/vec-slice.rs b/src/test/run-pass/vec-slice.rs index 8e653d21ec664..8448e4e0532c6 100644 --- a/src/test/run-pass/vec-slice.rs +++ b/src/test/run-pass/vec-slice.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::vec; + pub fn main() { let v = ~[1,2,3,4,5]; let v2 = vec::slice(v, 1, 3); - assert!((v2[0] == 2)); - assert!((v2[1] == 3)); + assert_eq!(v2[0], 2); + assert_eq!(v2[1], 3); } diff --git a/src/test/run-pass/vec-tail-matching.rs b/src/test/run-pass/vec-tail-matching.rs index fd65f150e4c91..6e1a47ad2dfd3 100644 --- a/src/test/run-pass/vec-tail-matching.rs +++ b/src/test/run-pass/vec-tail-matching.rs @@ -11,25 +11,25 @@ pub fn main() { match x { [first, ..tail] => { assert!(first.string == ~"foo"); - assert!(tail.len() == 2); + assert_eq!(tail.len(), 2); assert!(tail[0].string == ~"bar"); assert!(tail[1].string == ~"baz"); match tail { [Foo { _ }, _, Foo { _ }, ..tail] => { - ::core::util::unreachable(); + ::std::util::unreachable(); } - [Foo { string: a }, Foo { string: b }] => { - assert!(a == ~"bar"); - assert!(b == ~"baz"); + [Foo { string: ref a }, Foo { string: ref b }] => { + assert_eq!("bar", a.slice(0, a.len())); + assert_eq!("baz", b.slice(0, b.len())); } _ => { - ::core::util::unreachable(); + ::std::util::unreachable(); } } } _ => { - ::core::util::unreachable(); + ::std::util::unreachable(); } } } diff --git a/src/test/run-pass/vec-to_str.rs b/src/test/run-pass/vec-to_str.rs index 1767dd3ee5b39..a24ef38b28341 100644 --- a/src/test/run-pass/vec-to_str.rs +++ b/src/test/run-pass/vec-to_str.rs @@ -9,16 +9,16 @@ // except according to those terms. pub fn main() { - assert!((~[0, 1]).to_str() == ~"[0, 1]"); - assert!((&[1, 2]).to_str() == ~"[1, 2]"); - assert!((@[2, 3]).to_str() == ~"[2, 3]"); + assert_eq!((~[0, 1]).to_str(), ~"[0, 1]"); + assert_eq!((&[1, 2]).to_str(), ~"[1, 2]"); + assert_eq!((@[2, 3]).to_str(), ~"[2, 3]"); let foo = ~[3, 4]; let bar = &[4, 5]; let baz = @[5, 6]; - assert!(foo.to_str() == ~"[3, 4]"); - assert!(bar.to_str() == ~"[4, 5]"); - assert!(baz.to_str() == ~"[5, 6]"); + assert_eq!(foo.to_str(), ~"[3, 4]"); + assert_eq!(bar.to_str(), ~"[4, 5]"); + assert_eq!(baz.to_str(), ~"[5, 6]"); } diff --git a/src/test/run-pass/vec-trailing-comma.rs b/src/test/run-pass/vec-trailing-comma.rs index 686fc655bdb76..426416f63d307 100644 --- a/src/test/run-pass/vec-trailing-comma.rs +++ b/src/test/run-pass/vec-trailing-comma.rs @@ -13,8 +13,8 @@ pub fn main() { let v1: ~[int] = ~[10, 20, 30,]; let v2: ~[int] = ~[10, 20, 30]; - assert!((v1[2] == v2[2])); + assert_eq!(v1[2], v2[2]); let v3: ~[int] = ~[10,]; let v4: ~[int] = ~[10]; - assert!((v3[0] == v4[0])); + assert_eq!(v3[0], v4[0]); } diff --git a/src/test/run-pass/vec.rs b/src/test/run-pass/vec.rs index d021588814780..34fcca9e35bfc 100644 --- a/src/test/run-pass/vec.rs +++ b/src/test/run-pass/vec.rs @@ -14,12 +14,12 @@ // -*- rust -*- pub fn main() { let v: ~[int] = ~[10, 20]; - assert!((v[0] == 10)); - assert!((v[1] == 20)); + assert_eq!(v[0], 10); + assert_eq!(v[1], 20); let mut x: int = 0; - assert!((v[x] == 10)); - assert!((v[x + 1] == 20)); + assert_eq!(v[x], 10); + assert_eq!(v[x + 1], 20); x = x + 1; - assert!((v[x] == 20)); - assert!((v[x - 1] == 10)); + assert_eq!(v[x], 20); + assert_eq!(v[x - 1], 10); } diff --git a/src/test/run-pass/weird-exprs.rs b/src/test/run-pass/weird-exprs.rs index f226f315ff9ee..5a585c8c10e81 100644 --- a/src/test/run-pass/weird-exprs.rs +++ b/src/test/run-pass/weird-exprs.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::util; +use std::util; // Just a grab bag of stuff that you wouldn't want to actually write. diff --git a/src/test/run-pass/while-with-break.rs b/src/test/run-pass/while-with-break.rs index 417c0cdd9157f..465cb7d562b37 100644 --- a/src/test/run-pass/while-with-break.rs +++ b/src/test/run-pass/while-with-break.rs @@ -15,5 +15,5 @@ pub fn main() { break; } } - assert!((i == 95)); + assert_eq!(i, 95); } diff --git a/src/test/run-pass/writealias.rs b/src/test/run-pass/writealias.rs index f22f90380c6c4..8f990e070154e 100644 --- a/src/test/run-pass/writealias.rs +++ b/src/test/run-pass/writealias.rs @@ -9,15 +9,20 @@ // except according to those terms. +use std::unstable; - -// -*- rust -*- struct Point {x: int, y: int, z: int} fn f(p: &mut Point) { p.z = 13; } pub fn main() { - let mut x: Point = Point {x: 10, y: 11, z: 12}; - f(&mut x); - assert!((x.z == 13)); + unsafe { + let x = Some(unstable::sync::exclusive(true)); + match x { + Some(ref z) if z.with(|b| *b) => { + do z.with |b| { assert!(*b); } + }, + _ => fail!() + } + } } diff --git a/src/test/run-pass/x86stdcall.rs b/src/test/run-pass/x86stdcall.rs index c7c47753b8a82..f584237d0dec8 100644 --- a/src/test/run-pass/x86stdcall.rs +++ b/src/test/run-pass/x86stdcall.rs @@ -25,7 +25,7 @@ pub fn main() { kernel32::SetLastError(expected); let actual = kernel32::GetLastError(); log(error, actual); - assert!((expected == actual)); + assert_eq!(expected, actual); } } diff --git a/src/test/run-pass/yield.rs b/src/test/run-pass/yield.rs index 2d916abf0da69..8beaee83864db 100644 --- a/src/test/run-pass/yield.rs +++ b/src/test/run-pass/yield.rs @@ -9,6 +9,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::task; + pub fn main() { let mut result = None; let mut builder = task::task(); diff --git a/src/test/run-pass/yield1.rs b/src/test/run-pass/yield1.rs index f3ca5b1211899..37ec8af7e57c8 100644 --- a/src/test/run-pass/yield1.rs +++ b/src/test/run-pass/yield1.rs @@ -9,6 +9,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::task; + pub fn main() { let mut result = None; let mut builder = task::task(); diff --git a/src/test/run-pass/yield2.rs b/src/test/run-pass/yield2.rs index 83b60d1863e8a..a2b8ef0429d40 100644 --- a/src/test/run-pass/yield2.rs +++ b/src/test/run-pass/yield2.rs @@ -9,6 +9,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::task; + pub fn main() { let mut i: int = 0; while i < 100 { i = i + 1; error!(i); task::yield(); } diff --git a/src/test/run-pass/zip-same-length.rs b/src/test/run-pass/zip-same-length.rs index 50c3e78006111..d97148746d01b 100644 --- a/src/test/run-pass/zip-same-length.rs +++ b/src/test/run-pass/zip-same-length.rs @@ -11,6 +11,8 @@ // In this case, the code should compile and should // succeed at runtime +use std::vec; + fn enum_chars(start: u8, end: u8) -> ~[char] { assert!(start < end); let mut i = start; @@ -28,12 +30,15 @@ fn enum_uints(start: uint, end: uint) -> ~[uint] { } pub fn main() { - let a = 'a' as u8, j = 'j' as u8, k = 1u, l = 10u; + let a = 'a' as u8; + let j = 'j' as u8; + let k = 1u; + let l = 10u; let chars = enum_chars(a, j); let ints = enum_uints(k, l); let ps = vec::zip(chars, ints); - assert!((ps.head() == &('a', 1u))); - assert!((ps.last() == &(j as char, 10u))); + assert_eq!(ps.head(), &('a', 1u)); + assert_eq!(ps.last(), &(j as char, 10u)); }

) { static CONTINUE: [u8, ..4] = [0xAA, 0xBB, 0xCC, 0xDD]; // The control word is followed by garbage - let bytes = CONTINUE.to_vec() + ~[0]; + let bytes = CONTINUE.to_vec() + [0]; let port = loader(bytes); let res: Option = port.try_recv(); assert!(res.is_none()); @@ -939,7 +965,7 @@ mod test { 1, sys::size_of::()) |len_bytes| { len_bytes.to_vec() }; - let bytes = CONTINUE.to_vec() + len_bytes + ~[0, 0, 0, 0]; + let bytes = CONTINUE.to_vec() + len_bytes + [0, 0, 0, 0]; let port = loader(bytes); diff --git a/src/libstd/fun_treemap.rs b/src/libextra/fun_treemap.rs similarity index 81% rename from src/libstd/fun_treemap.rs rename to src/libextra/fun_treemap.rs index 6b051fa21b1e5..eb8c27e9902b5 100644 --- a/src/libstd/fun_treemap.rs +++ b/src/libextra/fun_treemap.rs @@ -19,6 +19,8 @@ * of features. */ +use core::prelude::*; + use core::cmp::{Eq, Ord}; use core::option::{Some, None}; @@ -33,13 +35,13 @@ enum TreeNode { pub fn init() -> Treemap { @Empty } /// Insert a value into the map -pub fn insert(m: Treemap, k: K, v: V) -> Treemap { +pub fn insert(m: Treemap, k: K, v: V) -> Treemap { @match m { @Empty => Node(@k, @v, @Empty, @Empty), - @Node(@copy kk, vv, left, right) => cond!( - (k < kk) { Node(@kk, vv, insert(left, k, v), right) } - (k == kk) { Node(@kk, @v, left, right) } - _ { Node(@kk, vv, left, insert(right, k, v)) } + @Node(kk, vv, left, right) => cond!( + (k < *kk) { Node(kk, vv, insert(left, k, v), right) } + (k == *kk) { Node(kk, @v, left, right) } + _ { Node(kk, vv, left, insert(right, k, v)) } ) } } @@ -48,8 +50,8 @@ pub fn insert(m: Treemap, k: K, v: V) -> Treemap pub fn find(m: Treemap, k: K) -> Option { match *m { Empty => None, - Node(@ref kk, @copy v, left, right) => cond!( - (k == *kk) { Some(v) } + Node(kk, v, left, right) => cond!( + (k == *kk) { Some(copy *v) } (k < *kk) { find(left, k) } _ { find(right, k) } ) diff --git a/src/libstd/future.rs b/src/libextra/future.rs similarity index 80% rename from src/libstd/future.rs rename to src/libextra/future.rs index be33c0f4663ed..40cfeebd5dcd8 100644 --- a/src/libstd/future.rs +++ b/src/libextra/future.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -14,17 +14,22 @@ * * # Example * - * ~~~ - * let delayed_fib = future::spawn {|| fib(5000) }; + * ~~~ {.rust} + * # fn fib(n: uint) -> uint {42}; + * # fn make_a_sandwich() {}; + * let mut delayed_fib = std::future::spawn (|| fib(5000) ); * make_a_sandwich(); - * io::println(fmt!("fib(5000) = %?", delayed_fib.get())) + * println(fmt!("fib(5000) = %?", delayed_fib.get())) * ~~~ */ +#[allow(missing_doc)]; + +use core::prelude::*; + use core::cast; use core::cell::Cell; -use core::comm::{PortOne, oneshot, send_one}; -use core::pipes::recv; +use core::comm::{PortOne, oneshot, send_one, recv_one}; use core::task; use core::util::replace; @@ -49,15 +54,15 @@ priv enum FutureState { } /// Methods on the `future` type -pub impl Future { - fn get(&mut self) -> A { - //! Get the value of the future +impl Future { + pub fn get(&mut self) -> A { + //! Get the value of the future. *(self.get_ref()) } } -pub impl Future { - fn get_ref<'a>(&'a mut self) -> &'a A { +impl Future { + pub fn get_ref<'a>(&'a mut self) -> &'a A { /*! * Executes the future's closure and then returns a borrowed * pointer to the result. The borrowed pointer lasts as long as @@ -87,7 +92,7 @@ pub impl Future { pub fn from_value(val: A) -> Future { /*! - * Create a future from a value + * Create a future from a value. * * The value is immediately available and calling `get` later will * not block. @@ -104,12 +109,9 @@ pub fn from_port(port: PortOne) -> Future { * waiting for the result to be received on the port. */ - let port = Cell(port); - do from_fn || { - let port = port.take().unwrap(); - match recv(port) { - oneshot::send(data) => data - } + let port = Cell::new(port); + do from_fn { + recv_one(port.take()) } } @@ -117,7 +119,7 @@ pub fn from_fn(f: ~fn() -> A) -> Future { /*! * Create a future from a function. * - * The first time that the value is requested it will be retreived by + * The first time that the value is requested it will be retrieved by * calling the function. Note that this function is a local * function. It is not spawned into another task. */ @@ -135,7 +137,7 @@ pub fn spawn(blk: ~fn() -> A) -> Future { let (port, chan) = oneshot(); - let chan = Cell(chan); + let chan = Cell::new(chan); do task::spawn { let chan = chan.take(); send_one(chan, blk()); @@ -156,7 +158,7 @@ mod test { #[test] fn test_from_value() { let mut f = from_value(~"snail"); - assert!(f.get() == ~"snail"); + assert_eq!(f.get(), ~"snail"); } #[test] @@ -164,31 +166,31 @@ mod test { let (po, ch) = oneshot(); send_one(ch, ~"whale"); let mut f = from_port(po); - assert!(f.get() == ~"whale"); + assert_eq!(f.get(), ~"whale"); } #[test] fn test_from_fn() { let mut f = from_fn(|| ~"brail"); - assert!(f.get() == ~"brail"); + assert_eq!(f.get(), ~"brail"); } #[test] fn test_interface_get() { let mut f = from_value(~"fail"); - assert!(f.get() == ~"fail"); + assert_eq!(f.get(), ~"fail"); } #[test] fn test_get_ref_method() { let mut f = from_value(22); - assert!(*f.get_ref() == 22); + assert_eq!(*f.get_ref(), 22); } #[test] fn test_spawn() { let mut f = spawn(|| ~"bale"); - assert!(f.get() == ~"bale"); + assert_eq!(f.get(), ~"bale"); } #[test] @@ -202,11 +204,11 @@ mod test { #[test] fn test_sendable_future() { let expected = "schlorf"; - let f = Cell(do spawn { expected }); + let f = Cell::new(do spawn { expected }); do task::spawn { let mut f = f.take(); let actual = f.get(); - assert!(actual == expected); + assert_eq!(actual, expected); } } } diff --git a/src/libstd/getopts.rs b/src/libextra/getopts.rs similarity index 77% rename from src/libstd/getopts.rs rename to src/libextra/getopts.rs index 1cb6312445696..eb5699df77f6d 100644 --- a/src/libstd/getopts.rs +++ b/src/libextra/getopts.rs @@ -78,6 +78,10 @@ * ``` */ +#[allow(missing_doc)]; + +use core::prelude::*; + use core::cmp::Eq; use core::result::{Err, Ok}; use core::result; @@ -106,10 +110,11 @@ pub struct Opt { } fn mkname(nm: &str) -> Name { - let unm = str::to_owned(nm); - return if nm.len() == 1u { - Short(str::char_at(unm, 0u)) - } else { Long(unm) }; + if nm.len() == 1u { + Short(str::char_at(nm, 0u)) + } else { + Long(nm.to_owned()) + } } /// Create an option that is required and takes an argument @@ -166,7 +171,7 @@ fn is_arg(arg: &str) -> bool { fn name_str(nm: &Name) -> ~str { return match *nm { Short(ch) => str::from_char(ch), - Long(copy s) => s + Long(ref s) => copy *s }; } @@ -191,19 +196,19 @@ pub enum Fail_ { pub fn fail_str(f: Fail_) -> ~str { return match f { ArgumentMissing(ref nm) => { - ~"Argument to option '" + *nm + ~"' missing." + fmt!("Argument to option '%s' missing.", *nm) } UnrecognizedOption(ref nm) => { - ~"Unrecognized option: '" + *nm + ~"'." + fmt!("Unrecognized option: '%s'.", *nm) } OptionMissing(ref nm) => { - ~"Required option '" + *nm + ~"' missing." + fmt!("Required option '%s' missing.", *nm) } OptionDuplicated(ref nm) => { - ~"Option '" + *nm + ~"' given more than once." + fmt!("Option '%s' given more than once.", *nm) } UnexpectedArgument(ref nm) => { - ~"Option " + *nm + ~" does not take an argument." + fmt!("Option '%s' does not take an argument.", *nm) } }; } @@ -241,11 +246,11 @@ pub fn getopts(args: &[~str], opts: &[Opt]) -> Result { let mut names; let mut i_arg = None; if cur[1] == '-' as u8 { - let tail = str::slice(cur, 2, curlen).to_owned(); + let tail = str::slice(cur, 2, curlen); let mut tail_eq = ~[]; for str::each_splitn_char(tail, '=', 1) |s| { tail_eq.push(s.to_owned()) } if tail_eq.len() <= 1 { - names = ~[Long(tail)]; + names = ~[Long(tail.to_owned())]; } else { names = ~[Long(copy tail_eq[0])]; @@ -385,7 +390,7 @@ pub fn opts_present(mm: &Matches, names: &[~str]) -> bool { * argument */ pub fn opt_str(mm: &Matches, nm: &str) -> ~str { - return match opt_val(mm, nm) { Val(copy s) => s, _ => fail!() }; + return match opt_val(mm, nm) { Val(s) => s, _ => fail!() }; } /** @@ -397,7 +402,7 @@ pub fn opt_str(mm: &Matches, nm: &str) -> ~str { pub fn opts_str(mm: &Matches, names: &[~str]) -> ~str { for names.each |nm| { match opt_val(mm, *nm) { - Val(copy s) => return s, + Val(ref s) => return copy *s, _ => () } } @@ -414,7 +419,7 @@ pub fn opts_str(mm: &Matches, names: &[~str]) -> ~str { pub fn opt_strs(mm: &Matches, nm: &str) -> ~[~str] { let mut acc: ~[~str] = ~[]; for vec::each(opt_vals(mm, nm)) |v| { - match *v { Val(copy s) => acc.push(s), _ => () } + match *v { Val(ref s) => acc.push(copy *s), _ => () } } return acc; } @@ -424,7 +429,7 @@ pub fn opt_maybe_str(mm: &Matches, nm: &str) -> Option<~str> { let vals = opt_vals(mm, nm); if vec::len::(vals) == 0u { return None::<~str>; } return match vals[0] { - Val(copy s) => Some(s), + Val(ref s) => Some(copy *s), _ => None }; } @@ -440,7 +445,7 @@ pub fn opt_maybe_str(mm: &Matches, nm: &str) -> Option<~str> { pub fn opt_default(mm: &Matches, nm: &str, def: &str) -> Option<~str> { let vals = opt_vals(mm, nm); if vec::len::(vals) == 0u { return None::<~str>; } - return match vals[0] { Val(copy s) => Some::<~str>(s), + return match vals[0] { Val(ref s) => Some::<~str>(copy *s), _ => Some::<~str>(str::to_owned(def)) } } @@ -587,7 +592,7 @@ pub mod groups { */ pub fn usage(brief: &str, opts: &[OptGroup]) -> ~str { - let desc_sep = ~"\n" + str::repeat(~" ", 24); + let desc_sep = ~"\n" + str::repeat(" ", 24); let rows = vec::map(opts, |optref| { let OptGroup{short_name: short_name, @@ -597,7 +602,7 @@ pub mod groups { hasarg: hasarg, _} = copy *optref; - let mut row = str::repeat(~" ", 4); + let mut row = str::repeat(" ", 4); // short option row += match short_name.len() { @@ -616,14 +621,14 @@ pub mod groups { row += match hasarg { No => ~"", Yes => hint, - Maybe => ~"[" + hint + ~"]", + Maybe => ~"[" + hint + "]", }; // FIXME: #5516 // here we just need to indent the start of the description let rowlen = row.len(); row += if rowlen < 24 { - str::repeat(~" ", 24 - rowlen) + str::repeat(" ", 24 - rowlen) } else { copy desc_sep }; @@ -648,10 +653,10 @@ pub mod groups { row }); - return str::to_owned(brief) + - ~"\n\nOptions:\n" + - str::connect(rows, ~"\n") + - ~"\n\n"; + return str::to_owned(brief) + + "\n\nOptions:\n" + + str::connect(rows, "\n") + + "\n\n"; } } // end groups module @@ -679,12 +684,12 @@ mod tests { #[test] fn test_reqopt_long() { let args = ~[~"--test=20"]; - let opts = ~[reqopt(~"test")]; + let opts = ~[reqopt("test")]; let rs = getopts(args, opts); match rs { Ok(ref m) => { - assert!((opt_present(m, ~"test"))); - assert!((opt_str(m, ~"test") == ~"20")); + assert!((opt_present(m, "test"))); + assert_eq!(opt_str(m, "test"), ~"20"); } _ => { fail!("test_reqopt_long failed"); } } @@ -693,10 +698,10 @@ mod tests { #[test] fn test_reqopt_long_missing() { let args = ~[~"blah"]; - let opts = ~[reqopt(~"test")]; + let opts = ~[reqopt("test")]; let rs = getopts(args, opts); match rs { - Err(copy f) => check_fail_type(f, OptionMissing_), + Err(f) => check_fail_type(f, OptionMissing_), _ => fail!() } } @@ -704,10 +709,10 @@ mod tests { #[test] fn test_reqopt_long_no_arg() { let args = ~[~"--test"]; - let opts = ~[reqopt(~"test")]; + let opts = ~[reqopt("test")]; let rs = getopts(args, opts); match rs { - Err(copy f) => check_fail_type(f, ArgumentMissing_), + Err(f) => check_fail_type(f, ArgumentMissing_), _ => fail!() } } @@ -715,10 +720,10 @@ mod tests { #[test] fn test_reqopt_long_multi() { let args = ~[~"--test=20", ~"--test=30"]; - let opts = ~[reqopt(~"test")]; + let opts = ~[reqopt("test")]; let rs = getopts(args, opts); match rs { - Err(copy f) => check_fail_type(f, OptionDuplicated_), + Err(f) => check_fail_type(f, OptionDuplicated_), _ => fail!() } } @@ -726,12 +731,12 @@ mod tests { #[test] fn test_reqopt_short() { let args = ~[~"-t", ~"20"]; - let opts = ~[reqopt(~"t")]; + let opts = ~[reqopt("t")]; let rs = getopts(args, opts); match rs { Ok(ref m) => { - assert!((opt_present(m, ~"t"))); - assert!((opt_str(m, ~"t") == ~"20")); + assert!((opt_present(m, "t"))); + assert_eq!(opt_str(m, "t"), ~"20"); } _ => fail!() } @@ -740,10 +745,10 @@ mod tests { #[test] fn test_reqopt_short_missing() { let args = ~[~"blah"]; - let opts = ~[reqopt(~"t")]; + let opts = ~[reqopt("t")]; let rs = getopts(args, opts); match rs { - Err(copy f) => check_fail_type(f, OptionMissing_), + Err(f) => check_fail_type(f, OptionMissing_), _ => fail!() } } @@ -751,10 +756,10 @@ mod tests { #[test] fn test_reqopt_short_no_arg() { let args = ~[~"-t"]; - let opts = ~[reqopt(~"t")]; + let opts = ~[reqopt("t")]; let rs = getopts(args, opts); match rs { - Err(copy f) => check_fail_type(f, ArgumentMissing_), + Err(f) => check_fail_type(f, ArgumentMissing_), _ => fail!() } } @@ -762,10 +767,10 @@ mod tests { #[test] fn test_reqopt_short_multi() { let args = ~[~"-t", ~"20", ~"-t", ~"30"]; - let opts = ~[reqopt(~"t")]; + let opts = ~[reqopt("t")]; let rs = getopts(args, opts); match rs { - Err(copy f) => check_fail_type(f, OptionDuplicated_), + Err(f) => check_fail_type(f, OptionDuplicated_), _ => fail!() } } @@ -775,12 +780,12 @@ mod tests { #[test] fn test_optopt_long() { let args = ~[~"--test=20"]; - let opts = ~[optopt(~"test")]; + let opts = ~[optopt("test")]; let rs = getopts(args, opts); match rs { Ok(ref m) => { - assert!((opt_present(m, ~"test"))); - assert!((opt_str(m, ~"test") == ~"20")); + assert!((opt_present(m, "test"))); + assert_eq!(opt_str(m, "test"), ~"20"); } _ => fail!() } @@ -789,10 +794,10 @@ mod tests { #[test] fn test_optopt_long_missing() { let args = ~[~"blah"]; - let opts = ~[optopt(~"test")]; + let opts = ~[optopt("test")]; let rs = getopts(args, opts); match rs { - Ok(ref m) => assert!(!opt_present(m, ~"test")), + Ok(ref m) => assert!(!opt_present(m, "test")), _ => fail!() } } @@ -800,10 +805,10 @@ mod tests { #[test] fn test_optopt_long_no_arg() { let args = ~[~"--test"]; - let opts = ~[optopt(~"test")]; + let opts = ~[optopt("test")]; let rs = getopts(args, opts); match rs { - Err(copy f) => check_fail_type(f, ArgumentMissing_), + Err(f) => check_fail_type(f, ArgumentMissing_), _ => fail!() } } @@ -811,10 +816,10 @@ mod tests { #[test] fn test_optopt_long_multi() { let args = ~[~"--test=20", ~"--test=30"]; - let opts = ~[optopt(~"test")]; + let opts = ~[optopt("test")]; let rs = getopts(args, opts); match rs { - Err(copy f) => check_fail_type(f, OptionDuplicated_), + Err(f) => check_fail_type(f, OptionDuplicated_), _ => fail!() } } @@ -822,12 +827,12 @@ mod tests { #[test] fn test_optopt_short() { let args = ~[~"-t", ~"20"]; - let opts = ~[optopt(~"t")]; + let opts = ~[optopt("t")]; let rs = getopts(args, opts); match rs { Ok(ref m) => { - assert!((opt_present(m, ~"t"))); - assert!((opt_str(m, ~"t") == ~"20")); + assert!((opt_present(m, "t"))); + assert_eq!(opt_str(m, "t"), ~"20"); } _ => fail!() } @@ -836,10 +841,10 @@ mod tests { #[test] fn test_optopt_short_missing() { let args = ~[~"blah"]; - let opts = ~[optopt(~"t")]; + let opts = ~[optopt("t")]; let rs = getopts(args, opts); match rs { - Ok(ref m) => assert!(!opt_present(m, ~"t")), + Ok(ref m) => assert!(!opt_present(m, "t")), _ => fail!() } } @@ -847,10 +852,10 @@ mod tests { #[test] fn test_optopt_short_no_arg() { let args = ~[~"-t"]; - let opts = ~[optopt(~"t")]; + let opts = ~[optopt("t")]; let rs = getopts(args, opts); match rs { - Err(copy f) => check_fail_type(f, ArgumentMissing_), + Err(f) => check_fail_type(f, ArgumentMissing_), _ => fail!() } } @@ -858,10 +863,10 @@ mod tests { #[test] fn test_optopt_short_multi() { let args = ~[~"-t", ~"20", ~"-t", ~"30"]; - let opts = ~[optopt(~"t")]; + let opts = ~[optopt("t")]; let rs = getopts(args, opts); match rs { - Err(copy f) => check_fail_type(f, OptionDuplicated_), + Err(f) => check_fail_type(f, OptionDuplicated_), _ => fail!() } } @@ -871,10 +876,10 @@ mod tests { #[test] fn test_optflag_long() { let args = ~[~"--test"]; - let opts = ~[optflag(~"test")]; + let opts = ~[optflag("test")]; let rs = getopts(args, opts); match rs { - Ok(ref m) => assert!(opt_present(m, ~"test")), + Ok(ref m) => assert!(opt_present(m, "test")), _ => fail!() } } @@ -882,10 +887,10 @@ mod tests { #[test] fn test_optflag_long_missing() { let args = ~[~"blah"]; - let opts = ~[optflag(~"test")]; + let opts = ~[optflag("test")]; let rs = getopts(args, opts); match rs { - Ok(ref m) => assert!(!opt_present(m, ~"test")), + Ok(ref m) => assert!(!opt_present(m, "test")), _ => fail!() } } @@ -893,10 +898,10 @@ mod tests { #[test] fn test_optflag_long_arg() { let args = ~[~"--test=20"]; - let opts = ~[optflag(~"test")]; + let opts = ~[optflag("test")]; let rs = getopts(args, opts); match rs { - Err(copy f) => { + Err(f) => { error!(fail_str(copy f)); check_fail_type(f, UnexpectedArgument_); } @@ -907,10 +912,10 @@ mod tests { #[test] fn test_optflag_long_multi() { let args = ~[~"--test", ~"--test"]; - let opts = ~[optflag(~"test")]; + let opts = ~[optflag("test")]; let rs = getopts(args, opts); match rs { - Err(copy f) => check_fail_type(f, OptionDuplicated_), + Err(f) => check_fail_type(f, OptionDuplicated_), _ => fail!() } } @@ -918,10 +923,10 @@ mod tests { #[test] fn test_optflag_short() { let args = ~[~"-t"]; - let opts = ~[optflag(~"t")]; + let opts = ~[optflag("t")]; let rs = getopts(args, opts); match rs { - Ok(ref m) => assert!(opt_present(m, ~"t")), + Ok(ref m) => assert!(opt_present(m, "t")), _ => fail!() } } @@ -929,10 +934,10 @@ mod tests { #[test] fn test_optflag_short_missing() { let args = ~[~"blah"]; - let opts = ~[optflag(~"t")]; + let opts = ~[optflag("t")]; let rs = getopts(args, opts); match rs { - Ok(ref m) => assert!(!opt_present(m, ~"t")), + Ok(ref m) => assert!(!opt_present(m, "t")), _ => fail!() } } @@ -940,13 +945,13 @@ mod tests { #[test] fn test_optflag_short_arg() { let args = ~[~"-t", ~"20"]; - let opts = ~[optflag(~"t")]; + let opts = ~[optflag("t")]; let rs = getopts(args, opts); match rs { Ok(ref m) => { // The next variable after the flag is just a free argument - assert!((m.free[0] == ~"20")); + assert!(m.free[0] == ~"20"); } _ => fail!() } @@ -955,10 +960,10 @@ mod tests { #[test] fn test_optflag_short_multi() { let args = ~[~"-t", ~"-t"]; - let opts = ~[optflag(~"t")]; + let opts = ~[optflag("t")]; let rs = getopts(args, opts); match rs { - Err(copy f) => check_fail_type(f, OptionDuplicated_), + Err(f) => check_fail_type(f, OptionDuplicated_), _ => fail!() } } @@ -967,11 +972,11 @@ mod tests { #[test] fn test_optflagmulti_short1() { let args = ~[~"-v"]; - let opts = ~[optflagmulti(~"v")]; + let opts = ~[optflagmulti("v")]; let rs = getopts(args, opts); match rs { Ok(ref m) => { - assert!((opt_count(m, ~"v") == 1)); + assert_eq!(opt_count(m, "v"), 1); } _ => fail!() } @@ -980,11 +985,11 @@ mod tests { #[test] fn test_optflagmulti_short2a() { let args = ~[~"-v", ~"-v"]; - let opts = ~[optflagmulti(~"v")]; + let opts = ~[optflagmulti("v")]; let rs = getopts(args, opts); match rs { Ok(ref m) => { - assert!((opt_count(m, ~"v") == 2)); + assert_eq!(opt_count(m, "v"), 2); } _ => fail!() } @@ -993,11 +998,11 @@ mod tests { #[test] fn test_optflagmulti_short2b() { let args = ~[~"-vv"]; - let opts = ~[optflagmulti(~"v")]; + let opts = ~[optflagmulti("v")]; let rs = getopts(args, opts); match rs { Ok(ref m) => { - assert!((opt_count(m, ~"v") == 2)); + assert_eq!(opt_count(m, "v"), 2); } _ => fail!() } @@ -1006,11 +1011,11 @@ mod tests { #[test] fn test_optflagmulti_long1() { let args = ~[~"--verbose"]; - let opts = ~[optflagmulti(~"verbose")]; + let opts = ~[optflagmulti("verbose")]; let rs = getopts(args, opts); match rs { Ok(ref m) => { - assert!((opt_count(m, ~"verbose") == 1)); + assert_eq!(opt_count(m, "verbose"), 1); } _ => fail!() } @@ -1019,11 +1024,11 @@ mod tests { #[test] fn test_optflagmulti_long2() { let args = ~[~"--verbose", ~"--verbose"]; - let opts = ~[optflagmulti(~"verbose")]; + let opts = ~[optflagmulti("verbose")]; let rs = getopts(args, opts); match rs { Ok(ref m) => { - assert!((opt_count(m, ~"verbose") == 2)); + assert_eq!(opt_count(m, "verbose"), 2); } _ => fail!() } @@ -1033,12 +1038,12 @@ mod tests { #[test] fn test_optmulti_long() { let args = ~[~"--test=20"]; - let opts = ~[optmulti(~"test")]; + let opts = ~[optmulti("test")]; let rs = getopts(args, opts); match rs { Ok(ref m) => { - assert!((opt_present(m, ~"test"))); - assert!((opt_str(m, ~"test") == ~"20")); + assert!((opt_present(m, "test"))); + assert_eq!(opt_str(m, "test"), ~"20"); } _ => fail!() } @@ -1047,10 +1052,10 @@ mod tests { #[test] fn test_optmulti_long_missing() { let args = ~[~"blah"]; - let opts = ~[optmulti(~"test")]; + let opts = ~[optmulti("test")]; let rs = getopts(args, opts); match rs { - Ok(ref m) => assert!(!opt_present(m, ~"test")), + Ok(ref m) => assert!(!opt_present(m, "test")), _ => fail!() } } @@ -1058,10 +1063,10 @@ mod tests { #[test] fn test_optmulti_long_no_arg() { let args = ~[~"--test"]; - let opts = ~[optmulti(~"test")]; + let opts = ~[optmulti("test")]; let rs = getopts(args, opts); match rs { - Err(copy f) => check_fail_type(f, ArgumentMissing_), + Err(f) => check_fail_type(f, ArgumentMissing_), _ => fail!() } } @@ -1069,15 +1074,15 @@ mod tests { #[test] fn test_optmulti_long_multi() { let args = ~[~"--test=20", ~"--test=30"]; - let opts = ~[optmulti(~"test")]; + let opts = ~[optmulti("test")]; let rs = getopts(args, opts); match rs { Ok(ref m) => { - assert!((opt_present(m, ~"test"))); - assert!((opt_str(m, ~"test") == ~"20")); - let pair = opt_strs(m, ~"test"); - assert!((pair[0] == ~"20")); - assert!((pair[1] == ~"30")); + assert!(opt_present(m, "test")); + assert_eq!(opt_str(m, "test"), ~"20"); + let pair = opt_strs(m, "test"); + assert!(pair[0] == ~"20"); + assert!(pair[1] == ~"30"); } _ => fail!() } @@ -1086,12 +1091,12 @@ mod tests { #[test] fn test_optmulti_short() { let args = ~[~"-t", ~"20"]; - let opts = ~[optmulti(~"t")]; + let opts = ~[optmulti("t")]; let rs = getopts(args, opts); match rs { Ok(ref m) => { - assert!((opt_present(m, ~"t"))); - assert!((opt_str(m, ~"t") == ~"20")); + assert!((opt_present(m, "t"))); + assert_eq!(opt_str(m, "t"), ~"20"); } _ => fail!() } @@ -1100,10 +1105,10 @@ mod tests { #[test] fn test_optmulti_short_missing() { let args = ~[~"blah"]; - let opts = ~[optmulti(~"t")]; + let opts = ~[optmulti("t")]; let rs = getopts(args, opts); match rs { - Ok(ref m) => assert!(!opt_present(m, ~"t")), + Ok(ref m) => assert!(!opt_present(m, "t")), _ => fail!() } } @@ -1111,10 +1116,10 @@ mod tests { #[test] fn test_optmulti_short_no_arg() { let args = ~[~"-t"]; - let opts = ~[optmulti(~"t")]; + let opts = ~[optmulti("t")]; let rs = getopts(args, opts); match rs { - Err(copy f) => check_fail_type(f, ArgumentMissing_), + Err(f) => check_fail_type(f, ArgumentMissing_), _ => fail!() } } @@ -1122,15 +1127,15 @@ mod tests { #[test] fn test_optmulti_short_multi() { let args = ~[~"-t", ~"20", ~"-t", ~"30"]; - let opts = ~[optmulti(~"t")]; + let opts = ~[optmulti("t")]; let rs = getopts(args, opts); match rs { Ok(ref m) => { - assert!((opt_present(m, ~"t"))); - assert!((opt_str(m, ~"t") == ~"20")); - let pair = opt_strs(m, ~"t"); - assert!((pair[0] == ~"20")); - assert!((pair[1] == ~"30")); + assert!((opt_present(m, "t"))); + assert_eq!(opt_str(m, "t"), ~"20"); + let pair = opt_strs(m, "t"); + assert!(pair[0] == ~"20"); + assert!(pair[1] == ~"30"); } _ => fail!() } @@ -1139,10 +1144,10 @@ mod tests { #[test] fn test_unrecognized_option_long() { let args = ~[~"--untest"]; - let opts = ~[optmulti(~"t")]; + let opts = ~[optmulti("t")]; let rs = getopts(args, opts); match rs { - Err(copy f) => check_fail_type(f, UnrecognizedOption_), + Err(f) => check_fail_type(f, UnrecognizedOption_), _ => fail!() } } @@ -1150,10 +1155,10 @@ mod tests { #[test] fn test_unrecognized_option_short() { let args = ~[~"-t"]; - let opts = ~[optmulti(~"test")]; + let opts = ~[optmulti("test")]; let rs = getopts(args, opts); match rs { - Err(copy f) => check_fail_type(f, UnrecognizedOption_), + Err(f) => check_fail_type(f, UnrecognizedOption_), _ => fail!() } } @@ -1165,26 +1170,26 @@ mod tests { ~"--flag", ~"--long=30", ~"-f", ~"-m", ~"40", ~"-m", ~"50", ~"-n", ~"-A B", ~"-n", ~"-60 70"]; let opts = - ~[optopt(~"s"), optflag(~"flag"), reqopt(~"long"), - optflag(~"f"), optmulti(~"m"), optmulti(~"n"), - optopt(~"notpresent")]; + ~[optopt("s"), optflag("flag"), reqopt("long"), + optflag("f"), optmulti("m"), optmulti("n"), + optopt("notpresent")]; let rs = getopts(args, opts); match rs { Ok(ref m) => { - assert!((m.free[0] == ~"prog")); - assert!((m.free[1] == ~"free1")); - assert!((opt_str(m, ~"s") == ~"20")); - assert!((m.free[2] == ~"free2")); - assert!((opt_present(m, ~"flag"))); - assert!((opt_str(m, ~"long") == ~"30")); - assert!((opt_present(m, ~"f"))); - let pair = opt_strs(m, ~"m"); - assert!((pair[0] == ~"40")); - assert!((pair[1] == ~"50")); - let pair = opt_strs(m, ~"n"); - assert!((pair[0] == ~"-A B")); - assert!((pair[1] == ~"-60 70")); - assert!((!opt_present(m, ~"notpresent"))); + assert!(m.free[0] == ~"prog"); + assert!(m.free[1] == ~"free1"); + assert_eq!(opt_str(m, "s"), ~"20"); + assert!(m.free[2] == ~"free2"); + assert!((opt_present(m, "flag"))); + assert_eq!(opt_str(m, "long"), ~"30"); + assert!((opt_present(m, "f"))); + let pair = opt_strs(m, "m"); + assert!(pair[0] == ~"40"); + assert!(pair[1] == ~"50"); + let pair = opt_strs(m, "n"); + assert!(pair[0] == ~"-A B"); + assert!(pair[1] == ~"-60 70"); + assert!((!opt_present(m, "notpresent"))); } _ => fail!() } @@ -1193,43 +1198,43 @@ mod tests { #[test] fn test_multi() { let args = ~[~"-e", ~"foo", ~"--encrypt", ~"foo"]; - let opts = ~[optopt(~"e"), optopt(~"encrypt"), optopt(~"f")]; + let opts = ~[optopt("e"), optopt("encrypt"), optopt("f")]; let matches = &match getopts(args, opts) { result::Ok(m) => m, result::Err(_) => fail!() }; - assert!(opts_present(matches, ~[~"e"])); - assert!(opts_present(matches, ~[~"encrypt"])); - assert!(opts_present(matches, ~[~"encrypt", ~"e"])); - assert!(opts_present(matches, ~[~"e", ~"encrypt"])); - assert!(!opts_present(matches, ~[~"f"])); - assert!(!opts_present(matches, ~[~"thing"])); - assert!(!opts_present(matches, ~[])); + assert!(opts_present(matches, [~"e"])); + assert!(opts_present(matches, [~"encrypt"])); + assert!(opts_present(matches, [~"encrypt", ~"e"])); + assert!(opts_present(matches, [~"e", ~"encrypt"])); + assert!(!opts_present(matches, [~"f"])); + assert!(!opts_present(matches, [~"thing"])); + assert!(!opts_present(matches, [])); - assert!(opts_str(matches, ~[~"e"]) == ~"foo"); - assert!(opts_str(matches, ~[~"encrypt"]) == ~"foo"); - assert!(opts_str(matches, ~[~"e", ~"encrypt"]) == ~"foo"); - assert!(opts_str(matches, ~[~"encrypt", ~"e"]) == ~"foo"); + assert_eq!(opts_str(matches, [~"e"]), ~"foo"); + assert_eq!(opts_str(matches, [~"encrypt"]), ~"foo"); + assert_eq!(opts_str(matches, [~"e", ~"encrypt"]), ~"foo"); + assert_eq!(opts_str(matches, [~"encrypt", ~"e"]), ~"foo"); } #[test] fn test_nospace() { let args = ~[~"-Lfoo", ~"-M."]; - let opts = ~[optmulti(~"L"), optmulti(~"M")]; + let opts = ~[optmulti("L"), optmulti("M")]; let matches = &match getopts(args, opts) { result::Ok(m) => m, result::Err(_) => fail!() }; - assert!(opts_present(matches, ~[~"L"])); - assert!(opts_str(matches, ~[~"L"]) == ~"foo"); - assert!(opts_present(matches, ~[~"M"])); - assert!(opts_str(matches, ~[~"M"]) == ~"."); + assert!(opts_present(matches, [~"L"])); + assert_eq!(opts_str(matches, [~"L"]), ~"foo"); + assert!(opts_present(matches, [~"M"])); + assert_eq!(opts_str(matches, [~"M"]), ~"."); } #[test] fn test_groups_reqopt() { - let opt = groups::reqopt(~"b", ~"banana", ~"some bananas", ~"VAL"); + let opt = groups::reqopt("b", "banana", "some bananas", "VAL"); assert!(opt == OptGroup { short_name: ~"b", long_name: ~"banana", hint: ~"VAL", @@ -1240,7 +1245,7 @@ mod tests { #[test] fn test_groups_optopt() { - let opt = groups::optopt(~"a", ~"apple", ~"some apples", ~"VAL"); + let opt = groups::optopt("a", "apple", "some apples", "VAL"); assert!(opt == OptGroup { short_name: ~"a", long_name: ~"apple", hint: ~"VAL", @@ -1251,7 +1256,7 @@ mod tests { #[test] fn test_groups_optflag() { - let opt = groups::optflag(~"k", ~"kiwi", ~"some kiwis"); + let opt = groups::optflag("k", "kiwi", "some kiwis"); assert!(opt == OptGroup { short_name: ~"k", long_name: ~"kiwi", hint: ~"", @@ -1262,8 +1267,7 @@ mod tests { #[test] fn test_groups_optflagopt() { - let opt = groups::optflagopt(~"p", ~"pineapple", - ~"some pineapples", ~"VAL"); + let opt = groups::optflagopt("p", "pineapple", "some pineapples", "VAL"); assert!(opt == OptGroup { short_name: ~"p", long_name: ~"pineapple", hint: ~"VAL", @@ -1274,8 +1278,7 @@ mod tests { #[test] fn test_groups_optmulti() { - let opt = groups::optmulti(~"l", ~"lime", - ~"some limes", ~"VAL"); + let opt = groups::optmulti("l", "lime", "some limes", "VAL"); assert!(opt == OptGroup { short_name: ~"l", long_name: ~"lime", hint: ~"VAL", @@ -1286,29 +1289,28 @@ mod tests { #[test] fn test_groups_long_to_short() { - let short = ~[reqopt(~"b"), reqopt(~"banana")]; - let verbose = groups::reqopt(~"b", ~"banana", - ~"some bananas", ~"VAL"); + let short = ~[reqopt("b"), reqopt("banana")]; + let verbose = groups::reqopt("b", "banana", "some bananas", "VAL"); - assert!(groups::long_to_short(&verbose) == short); + assert_eq!(groups::long_to_short(&verbose), short); } #[test] fn test_groups_getopts() { let short = ~[ - reqopt(~"b"), reqopt(~"banana"), - optopt(~"a"), optopt(~"apple"), - optflag(~"k"), optflagopt(~"kiwi"), - optflagopt(~"p"), - optmulti(~"l") + reqopt("b"), reqopt("banana"), + optopt("a"), optopt("apple"), + optflag("k"), optflagopt("kiwi"), + optflagopt("p"), + optmulti("l") ]; let verbose = ~[ - groups::reqopt(~"b", ~"banana", ~"Desc", ~"VAL"), - groups::optopt(~"a", ~"apple", ~"Desc", ~"VAL"), - groups::optflag(~"k", ~"kiwi", ~"Desc"), - groups::optflagopt(~"p", ~"", ~"Desc", ~"VAL"), - groups::optmulti(~"l", ~"", ~"Desc", ~"VAL"), + groups::reqopt("b", "banana", "Desc", "VAL"), + groups::optopt("a", "apple", "Desc", "VAL"), + groups::optflag("k", "kiwi", "Desc"), + groups::optflagopt("p", "", "Desc", "VAL"), + groups::optmulti("l", "", "Desc", "VAL"), ]; let sample_args = ~[~"-k", ~"15", ~"--apple", ~"1", ~"k", @@ -1322,12 +1324,12 @@ mod tests { #[test] fn test_groups_usage() { let optgroups = ~[ - groups::reqopt(~"b", ~"banana", ~"Desc", ~"VAL"), - groups::optopt(~"a", ~"012345678901234567890123456789", - ~"Desc", ~"VAL"), - groups::optflag(~"k", ~"kiwi", ~"Desc"), - groups::optflagopt(~"p", ~"", ~"Desc", ~"VAL"), - groups::optmulti(~"l", ~"", ~"Desc", ~"VAL"), + groups::reqopt("b", "banana", "Desc", "VAL"), + groups::optopt("a", "012345678901234567890123456789", + "Desc", "VAL"), + groups::optflag("k", "kiwi", "Desc"), + groups::optflagopt("p", "", "Desc", "VAL"), + groups::optmulti("l", "", "Desc", "VAL"), ]; let expected = @@ -1343,11 +1345,11 @@ Options: "; - let generated_usage = groups::usage(~"Usage: fruits", optgroups); + let generated_usage = groups::usage("Usage: fruits", optgroups); debug!("expected: <<%s>>", expected); debug!("generated: <<%s>>", generated_usage); - assert!(generated_usage == expected); + assert_eq!(generated_usage, expected); } #[test] @@ -1356,10 +1358,10 @@ Options: // lines wrap after 78: or rather descriptions wrap after 54 let optgroups = ~[ - groups::optflag(~"k", ~"kiwi", - ~"This is a long description which won't be wrapped..+.."), // 54 - groups::optflag(~"a", ~"apple", - ~"This is a long description which _will_ be wrapped..+.."), // 55 + groups::optflag("k", "kiwi", + "This is a long description which won't be wrapped..+.."), // 54 + groups::optflag("a", "apple", + "This is a long description which _will_ be wrapped..+.."), // 55 ]; let expected = @@ -1372,7 +1374,7 @@ Options: "; - let usage = groups::usage(~"Usage: fruits", optgroups); + let usage = groups::usage("Usage: fruits", optgroups); debug!("expected: <<%s>>", expected); debug!("generated: <<%s>>", usage); diff --git a/src/libstd/io_util.rs b/src/libextra/io_util.rs similarity index 83% rename from src/libstd/io_util.rs rename to src/libextra/io_util.rs index 7d43663cc808b..91424ae3ba2c0 100644 --- a/src/libstd/io_util.rs +++ b/src/libextra/io_util.rs @@ -11,12 +11,16 @@ use core::io::{Reader, BytesReader}; use core::io; +/// An implementation of the io::Reader interface which reads a buffer of bytes pub struct BufReader { + /// The buffer of bytes to read buf: ~[u8], + /// The current position in the buffer of bytes pos: @mut uint } -pub impl BufReader { +impl BufReader { + /// Creates a new buffer reader for the specified buffer pub fn new(v: ~[u8]) -> BufReader { BufReader { buf: v, @@ -24,7 +28,7 @@ pub impl BufReader { } } - priv fn as_bytes_reader(&self, f: &fn(&BytesReader) -> A) -> A { + fn as_bytes_reader(&self, f: &fn(&BytesReader) -> A) -> A { // Recreating the BytesReader state every call since // I can't get the borrowing to work correctly let bytes_reader = BytesReader { diff --git a/src/libstd/json.rs b/src/libextra/json.rs similarity index 86% rename from src/libstd/json.rs rename to src/libextra/json.rs index 270cf675c878a..22abe0edbb94e 100644 --- a/src/libstd/json.rs +++ b/src/libextra/json.rs @@ -10,12 +10,22 @@ // Rust JSON serialization library // Copyright (c) 2011 Google Inc. + #[forbid(non_camel_case_types)]; +#[allow(missing_doc)]; //! json serialization -use core::io::{WriterUtil, ReaderUtil}; +use core::prelude::*; + +use core::char; +use core::float; use core::hashmap::HashMap; +use core::io::{WriterUtil, ReaderUtil}; +use core::io; +use core::str; +use core::to_str; +use core::vec; use serialize::Encodable; use serialize; @@ -35,9 +45,14 @@ pub type List = ~[Json]; pub type Object = HashMap<~str, Json>; #[deriving(Eq)] +/// If an error occurs while parsing some JSON, this is the structure which is +/// returned pub struct Error { + /// The line number at which the error occurred line: uint, + /// The column number at which the error occurred col: uint, + /// A message describing the type of the error msg: @~str, } @@ -45,18 +60,18 @@ fn escape_str(s: &str) -> ~str { let mut escaped = ~"\""; for str::each_char(s) |c| { match c { - '"' => escaped += ~"\\\"", - '\\' => escaped += ~"\\\\", - '\x08' => escaped += ~"\\b", - '\x0c' => escaped += ~"\\f", - '\n' => escaped += ~"\\n", - '\r' => escaped += ~"\\r", - '\t' => escaped += ~"\\t", + '"' => escaped += "\\\"", + '\\' => escaped += "\\\\", + '\x08' => escaped += "\\b", + '\x0c' => escaped += "\\f", + '\n' => escaped += "\\n", + '\r' => escaped += "\\r", + '\t' => escaped += "\\t", _ => escaped += str::from_char(c) } }; - escaped += ~"\""; + escaped += "\""; escaped } @@ -67,10 +82,13 @@ fn spaces(n: uint) -> ~str { return ss; } +/// A structure for implementing serialization to JSON. pub struct Encoder { priv wr: @io::Writer, } +/// Creates a new JSON encoder whose output will be written to the writer +/// specified. pub fn Encoder(wr: @io::Writer) -> Encoder { Encoder { wr: wr @@ -220,11 +238,14 @@ impl serialize::Encoder for Encoder { } } +/// Another encoder for JSON, but prints out human-readable JSON instead of +/// compact data pub struct PrettyEncoder { priv wr: @io::Writer, priv indent: uint, } +/// Creates a new encoder whose output will be written to the specified writer pub fn PrettyEncoder(wr: @io::Writer) -> PrettyEncoder { PrettyEncoder { wr: wr, @@ -460,6 +481,7 @@ pub fn to_pretty_str(json: &Json) -> ~str { io::with_str_writer(|wr| to_pretty_writer(wr, json)) } +#[allow(missing_doc)] pub struct Parser { priv rdr: @io::Reader, priv ch: char, @@ -477,8 +499,8 @@ pub fn Parser(rdr: @io::Reader) -> Parser { } } -pub impl Parser { - fn parse(&mut self) -> Result { +impl Parser { + pub fn parse(&mut self) -> Result { match self.parse_value() { Ok(value) => { // Skip trailing whitespaces. @@ -495,7 +517,7 @@ pub impl Parser { } } -priv impl Parser { +impl Parser { fn eof(&self) -> bool { self.ch == -1 as char } fn bump(&mut self) { @@ -524,9 +546,9 @@ priv impl Parser { if self.eof() { return self.error(~"EOF while parsing value"); } match self.ch { - 'n' => self.parse_ident(~"ull", Null), - 't' => self.parse_ident(~"rue", Boolean(true)), - 'f' => self.parse_ident(~"alse", Boolean(false)), + 'n' => self.parse_ident("ull", Null), + 't' => self.parse_ident("rue", Boolean(true)), + 'f' => self.parse_ident("alse", Boolean(false)), '0' .. '9' | '-' => self.parse_number(), '"' => match self.parse_str() { @@ -838,10 +860,12 @@ pub fn from_str(s: &str) -> Result { } } +/// A structure to decode JSON to values in rust. pub struct Decoder { priv stack: ~[Json], } +/// Creates a new decoder instance for decoding the specified JSON value. pub fn Decoder(json: Json) -> Decoder { Decoder { stack: ~[json] @@ -1192,7 +1216,11 @@ impl Ord for Json { fn gt(&self, other: &Json) -> bool { (*other).lt(&(*self)) } } -trait ToJson { fn to_json(&self) -> Json; } +/// A trait for converting values to JSON +trait ToJson { + /// Converts the value of `self` to an instance of JSON + fn to_json(&self) -> Json; +} impl ToJson for Json { fn to_json(&self) -> Json { copy *self } @@ -1325,9 +1353,13 @@ impl to_str::ToStr for Error { #[cfg(test)] mod tests { + use core::prelude::*; + use super::*; use core::hashmap::HashMap; + use core::io; + use core::result; use std::serialize::Decodable; @@ -1354,7 +1386,7 @@ mod tests { for items.each |item| { match *item { - (copy key, copy value) => { d.insert(key, value); }, + (ref key, ref value) => { d.insert(copy *key, copy *value); }, } }; @@ -1440,15 +1472,15 @@ mod tests { #[test] fn test_write_object() { - assert_eq!(to_str(&mk_object(~[])), ~"{}"); - assert_eq!(to_pretty_str(&mk_object(~[])), ~"{}"); + assert_eq!(to_str(&mk_object([])), ~"{}"); + assert_eq!(to_pretty_str(&mk_object([])), ~"{}"); assert_eq!( - to_str(&mk_object(~[(~"a", Boolean(true))])), + to_str(&mk_object([(~"a", Boolean(true))])), ~"{\"a\":true}" ); assert_eq!( - to_pretty_str(&mk_object(~[(~"a", Boolean(true))])), + to_pretty_str(&mk_object([(~"a", Boolean(true))])), ~"\ {\n \ \"a\": true\n\ @@ -1456,10 +1488,10 @@ mod tests { ); assert_eq!( - to_str(&mk_object(~[ + to_str(&mk_object([ (~"b", List(~[ - mk_object(~[(~"c", String(~"\x0c\r"))]), - mk_object(~[(~"d", String(~""))]) + mk_object([(~"c", String(~"\x0c\r"))]), + mk_object([(~"d", String(~""))]) ])) ])), ~"{\ @@ -1470,10 +1502,10 @@ mod tests { }" ); assert_eq!( - to_pretty_str(&mk_object(~[ + to_pretty_str(&mk_object([ (~"b", List(~[ - mk_object(~[(~"c", String(~"\x0c\r"))]), - mk_object(~[(~"d", String(~""))]) + mk_object([(~"c", String(~"\x0c\r"))]), + mk_object([(~"d", String(~""))]) ])) ])), ~"\ @@ -1489,11 +1521,11 @@ mod tests { }" ); - let a = mk_object(~[ + let a = mk_object([ (~"a", Boolean(true)), (~"b", List(~[ - mk_object(~[(~"c", String(~"\x0c\r"))]), - mk_object(~[(~"d", String(~""))]) + mk_object([(~"c", String(~"\x0c\r"))]), + mk_object([(~"d", String(~""))]) ])) ]); @@ -1578,318 +1610,318 @@ mod tests { #[test] fn test_trailing_characters() { - assert_eq!(from_str(~"nulla"), + assert_eq!(from_str("nulla"), Err(Error {line: 1u, col: 5u, msg: @~"trailing characters"})); - assert_eq!(from_str(~"truea"), + assert_eq!(from_str("truea"), Err(Error {line: 1u, col: 5u, msg: @~"trailing characters"})); - assert_eq!(from_str(~"falsea"), + assert_eq!(from_str("falsea"), Err(Error {line: 1u, col: 6u, msg: @~"trailing characters"})); - assert_eq!(from_str(~"1a"), + assert_eq!(from_str("1a"), Err(Error {line: 1u, col: 2u, msg: @~"trailing characters"})); - assert_eq!(from_str(~"[]a"), + assert_eq!(from_str("[]a"), Err(Error {line: 1u, col: 3u, msg: @~"trailing characters"})); - assert_eq!(from_str(~"{}a"), + assert_eq!(from_str("{}a"), Err(Error {line: 1u, col: 3u, msg: @~"trailing characters"})); } #[test] fn test_read_identifiers() { - assert_eq!(from_str(~"n"), + assert_eq!(from_str("n"), Err(Error {line: 1u, col: 2u, msg: @~"invalid syntax"})); - assert_eq!(from_str(~"nul"), + assert_eq!(from_str("nul"), Err(Error {line: 1u, col: 4u, msg: @~"invalid syntax"})); - assert_eq!(from_str(~"t"), + assert_eq!(from_str("t"), Err(Error {line: 1u, col: 2u, msg: @~"invalid syntax"})); - assert_eq!(from_str(~"truz"), + assert_eq!(from_str("truz"), Err(Error {line: 1u, col: 4u, msg: @~"invalid syntax"})); - assert_eq!(from_str(~"f"), + assert_eq!(from_str("f"), Err(Error {line: 1u, col: 2u, msg: @~"invalid syntax"})); - assert_eq!(from_str(~"faz"), + assert_eq!(from_str("faz"), Err(Error {line: 1u, col: 3u, msg: @~"invalid syntax"})); - assert_eq!(from_str(~"null"), Ok(Null)); - assert_eq!(from_str(~"true"), Ok(Boolean(true))); - assert_eq!(from_str(~"false"), Ok(Boolean(false))); - assert_eq!(from_str(~" null "), Ok(Null)); - assert_eq!(from_str(~" true "), Ok(Boolean(true))); - assert_eq!(from_str(~" false "), Ok(Boolean(false))); + assert_eq!(from_str("null"), Ok(Null)); + assert_eq!(from_str("true"), Ok(Boolean(true))); + assert_eq!(from_str("false"), Ok(Boolean(false))); + assert_eq!(from_str(" null "), Ok(Null)); + assert_eq!(from_str(" true "), Ok(Boolean(true))); + assert_eq!(from_str(" false "), Ok(Boolean(false))); } #[test] fn test_decode_identifiers() { - let mut decoder = Decoder(from_str(~"null").unwrap()); + let mut decoder = Decoder(from_str("null").unwrap()); let v: () = Decodable::decode(&mut decoder); assert_eq!(v, ()); - let mut decoder = Decoder(from_str(~"true").unwrap()); + let mut decoder = Decoder(from_str("true").unwrap()); let v: bool = Decodable::decode(&mut decoder); assert_eq!(v, true); - let mut decoder = Decoder(from_str(~"false").unwrap()); + let mut decoder = Decoder(from_str("false").unwrap()); let v: bool = Decodable::decode(&mut decoder); assert_eq!(v, false); } #[test] fn test_read_number() { - assert_eq!(from_str(~"+"), + assert_eq!(from_str("+"), Err(Error {line: 1u, col: 1u, msg: @~"invalid syntax"})); - assert_eq!(from_str(~"."), + assert_eq!(from_str("."), Err(Error {line: 1u, col: 1u, msg: @~"invalid syntax"})); - assert_eq!(from_str(~"-"), + assert_eq!(from_str("-"), Err(Error {line: 1u, col: 2u, msg: @~"invalid number"})); - assert_eq!(from_str(~"00"), + assert_eq!(from_str("00"), Err(Error {line: 1u, col: 2u, msg: @~"invalid number"})); - assert_eq!(from_str(~"1."), + assert_eq!(from_str("1."), Err(Error {line: 1u, col: 3u, msg: @~"invalid number"})); - assert_eq!(from_str(~"1e"), + assert_eq!(from_str("1e"), Err(Error {line: 1u, col: 3u, msg: @~"invalid number"})); - assert_eq!(from_str(~"1e+"), + assert_eq!(from_str("1e+"), Err(Error {line: 1u, col: 4u, msg: @~"invalid number"})); - assert_eq!(from_str(~"3"), Ok(Number(3f))); - assert_eq!(from_str(~"3.1"), Ok(Number(3.1f))); - assert_eq!(from_str(~"-1.2"), Ok(Number(-1.2f))); - assert_eq!(from_str(~"0.4"), Ok(Number(0.4f))); - assert_eq!(from_str(~"0.4e5"), Ok(Number(0.4e5f))); - assert_eq!(from_str(~"0.4e+15"), Ok(Number(0.4e15f))); - assert_eq!(from_str(~"0.4e-01"), Ok(Number(0.4e-01f))); - assert_eq!(from_str(~" 3 "), Ok(Number(3f))); + assert_eq!(from_str("3"), Ok(Number(3f))); + assert_eq!(from_str("3.1"), Ok(Number(3.1f))); + assert_eq!(from_str("-1.2"), Ok(Number(-1.2f))); + assert_eq!(from_str("0.4"), Ok(Number(0.4f))); + assert_eq!(from_str("0.4e5"), Ok(Number(0.4e5f))); + assert_eq!(from_str("0.4e+15"), Ok(Number(0.4e15f))); + assert_eq!(from_str("0.4e-01"), Ok(Number(0.4e-01f))); + assert_eq!(from_str(" 3 "), Ok(Number(3f))); } #[test] fn test_decode_numbers() { - let mut decoder = Decoder(from_str(~"3").unwrap()); + let mut decoder = Decoder(from_str("3").unwrap()); let v: float = Decodable::decode(&mut decoder); assert_eq!(v, 3f); - let mut decoder = Decoder(from_str(~"3.1").unwrap()); + let mut decoder = Decoder(from_str("3.1").unwrap()); let v: float = Decodable::decode(&mut decoder); assert_eq!(v, 3.1f); - let mut decoder = Decoder(from_str(~"-1.2").unwrap()); + let mut decoder = Decoder(from_str("-1.2").unwrap()); let v: float = Decodable::decode(&mut decoder); assert_eq!(v, -1.2f); - let mut decoder = Decoder(from_str(~"0.4").unwrap()); + let mut decoder = Decoder(from_str("0.4").unwrap()); let v: float = Decodable::decode(&mut decoder); assert_eq!(v, 0.4f); - let mut decoder = Decoder(from_str(~"0.4e5").unwrap()); + let mut decoder = Decoder(from_str("0.4e5").unwrap()); let v: float = Decodable::decode(&mut decoder); assert_eq!(v, 0.4e5f); - let mut decoder = Decoder(from_str(~"0.4e15").unwrap()); + let mut decoder = Decoder(from_str("0.4e15").unwrap()); let v: float = Decodable::decode(&mut decoder); assert_eq!(v, 0.4e15f); - let mut decoder = Decoder(from_str(~"0.4e-01").unwrap()); + let mut decoder = Decoder(from_str("0.4e-01").unwrap()); let v: float = Decodable::decode(&mut decoder); assert_eq!(v, 0.4e-01f); } #[test] fn test_read_str() { - assert_eq!(from_str(~"\""), + assert_eq!(from_str("\""), Err(Error {line: 1u, col: 2u, msg: @~"EOF while parsing string" })); - assert_eq!(from_str(~"\"lol"), + assert_eq!(from_str("\"lol"), Err(Error {line: 1u, col: 5u, msg: @~"EOF while parsing string" })); - assert_eq!(from_str(~"\"\""), Ok(String(~""))); - assert_eq!(from_str(~"\"foo\""), Ok(String(~"foo"))); - assert_eq!(from_str(~"\"\\\"\""), Ok(String(~"\""))); - assert_eq!(from_str(~"\"\\b\""), Ok(String(~"\x08"))); - assert_eq!(from_str(~"\"\\n\""), Ok(String(~"\n"))); - assert_eq!(from_str(~"\"\\r\""), Ok(String(~"\r"))); - assert_eq!(from_str(~"\"\\t\""), Ok(String(~"\t"))); - assert_eq!(from_str(~" \"foo\" "), Ok(String(~"foo"))); - assert_eq!(from_str(~"\"\\u12ab\""), Ok(String(~"\u12ab"))); - assert_eq!(from_str(~"\"\\uAB12\""), Ok(String(~"\uAB12"))); + assert_eq!(from_str("\"\""), Ok(String(~""))); + assert_eq!(from_str("\"foo\""), Ok(String(~"foo"))); + assert_eq!(from_str("\"\\\"\""), Ok(String(~"\""))); + assert_eq!(from_str("\"\\b\""), Ok(String(~"\x08"))); + assert_eq!(from_str("\"\\n\""), Ok(String(~"\n"))); + assert_eq!(from_str("\"\\r\""), Ok(String(~"\r"))); + assert_eq!(from_str("\"\\t\""), Ok(String(~"\t"))); + assert_eq!(from_str(" \"foo\" "), Ok(String(~"foo"))); + assert_eq!(from_str("\"\\u12ab\""), Ok(String(~"\u12ab"))); + assert_eq!(from_str("\"\\uAB12\""), Ok(String(~"\uAB12"))); } #[test] fn test_decode_str() { - let mut decoder = Decoder(from_str(~"\"\"").unwrap()); + let mut decoder = Decoder(from_str("\"\"").unwrap()); let v: ~str = Decodable::decode(&mut decoder); assert_eq!(v, ~""); - let mut decoder = Decoder(from_str(~"\"foo\"").unwrap()); + let mut decoder = Decoder(from_str("\"foo\"").unwrap()); let v: ~str = Decodable::decode(&mut decoder); assert_eq!(v, ~"foo"); - let mut decoder = Decoder(from_str(~"\"\\\"\"").unwrap()); + let mut decoder = Decoder(from_str("\"\\\"\"").unwrap()); let v: ~str = Decodable::decode(&mut decoder); assert_eq!(v, ~"\""); - let mut decoder = Decoder(from_str(~"\"\\b\"").unwrap()); + let mut decoder = Decoder(from_str("\"\\b\"").unwrap()); let v: ~str = Decodable::decode(&mut decoder); assert_eq!(v, ~"\x08"); - let mut decoder = Decoder(from_str(~"\"\\n\"").unwrap()); + let mut decoder = Decoder(from_str("\"\\n\"").unwrap()); let v: ~str = Decodable::decode(&mut decoder); assert_eq!(v, ~"\n"); - let mut decoder = Decoder(from_str(~"\"\\r\"").unwrap()); + let mut decoder = Decoder(from_str("\"\\r\"").unwrap()); let v: ~str = Decodable::decode(&mut decoder); assert_eq!(v, ~"\r"); - let mut decoder = Decoder(from_str(~"\"\\t\"").unwrap()); + let mut decoder = Decoder(from_str("\"\\t\"").unwrap()); let v: ~str = Decodable::decode(&mut decoder); assert_eq!(v, ~"\t"); - let mut decoder = Decoder(from_str(~"\"\\u12ab\"").unwrap()); + let mut decoder = Decoder(from_str("\"\\u12ab\"").unwrap()); let v: ~str = Decodable::decode(&mut decoder); assert_eq!(v, ~"\u12ab"); - let mut decoder = Decoder(from_str(~"\"\\uAB12\"").unwrap()); + let mut decoder = Decoder(from_str("\"\\uAB12\"").unwrap()); let v: ~str = Decodable::decode(&mut decoder); assert_eq!(v, ~"\uAB12"); } #[test] fn test_read_list() { - assert_eq!(from_str(~"["), + assert_eq!(from_str("["), Err(Error {line: 1u, col: 2u, msg: @~"EOF while parsing value"})); - assert_eq!(from_str(~"[1"), + assert_eq!(from_str("[1"), Err(Error {line: 1u, col: 3u, msg: @~"EOF while parsing list"})); - assert_eq!(from_str(~"[1,"), + assert_eq!(from_str("[1,"), Err(Error {line: 1u, col: 4u, msg: @~"EOF while parsing value"})); - assert_eq!(from_str(~"[1,]"), + assert_eq!(from_str("[1,]"), Err(Error {line: 1u, col: 4u, msg: @~"invalid syntax"})); - assert_eq!(from_str(~"[6 7]"), + assert_eq!(from_str("[6 7]"), Err(Error {line: 1u, col: 4u, msg: @~"expected `,` or `]`"})); - assert_eq!(from_str(~"[]"), Ok(List(~[]))); - assert_eq!(from_str(~"[ ]"), Ok(List(~[]))); - assert_eq!(from_str(~"[true]"), Ok(List(~[Boolean(true)]))); - assert_eq!(from_str(~"[ false ]"), Ok(List(~[Boolean(false)]))); - assert_eq!(from_str(~"[null]"), Ok(List(~[Null]))); - assert_eq!(from_str(~"[3, 1]"), + assert_eq!(from_str("[]"), Ok(List(~[]))); + assert_eq!(from_str("[ ]"), Ok(List(~[]))); + assert_eq!(from_str("[true]"), Ok(List(~[Boolean(true)]))); + assert_eq!(from_str("[ false ]"), Ok(List(~[Boolean(false)]))); + assert_eq!(from_str("[null]"), Ok(List(~[Null]))); + assert_eq!(from_str("[3, 1]"), Ok(List(~[Number(3f), Number(1f)]))); - assert_eq!(from_str(~"\n[3, 2]\n"), + assert_eq!(from_str("\n[3, 2]\n"), Ok(List(~[Number(3f), Number(2f)]))); - assert_eq!(from_str(~"[2, [4, 1]]"), + assert_eq!(from_str("[2, [4, 1]]"), Ok(List(~[Number(2f), List(~[Number(4f), Number(1f)])]))); } #[test] fn test_decode_list() { - let mut decoder = Decoder(from_str(~"[]").unwrap()); + let mut decoder = Decoder(from_str("[]").unwrap()); let v: ~[()] = Decodable::decode(&mut decoder); assert_eq!(v, ~[]); - let mut decoder = Decoder(from_str(~"[null]").unwrap()); + let mut decoder = Decoder(from_str("[null]").unwrap()); let v: ~[()] = Decodable::decode(&mut decoder); assert_eq!(v, ~[()]); - let mut decoder = Decoder(from_str(~"[true]").unwrap()); + let mut decoder = Decoder(from_str("[true]").unwrap()); let v: ~[bool] = Decodable::decode(&mut decoder); assert_eq!(v, ~[true]); - let mut decoder = Decoder(from_str(~"[true]").unwrap()); + let mut decoder = Decoder(from_str("[true]").unwrap()); let v: ~[bool] = Decodable::decode(&mut decoder); assert_eq!(v, ~[true]); - let mut decoder = Decoder(from_str(~"[3, 1]").unwrap()); + let mut decoder = Decoder(from_str("[3, 1]").unwrap()); let v: ~[int] = Decodable::decode(&mut decoder); assert_eq!(v, ~[3, 1]); - let mut decoder = Decoder(from_str(~"[[3], [1, 2]]").unwrap()); + let mut decoder = Decoder(from_str("[[3], [1, 2]]").unwrap()); let v: ~[~[uint]] = Decodable::decode(&mut decoder); assert_eq!(v, ~[~[3], ~[1, 2]]); } #[test] fn test_read_object() { - assert_eq!(from_str(~"{"), + assert_eq!(from_str("{"), Err(Error { line: 1u, col: 2u, msg: @~"EOF while parsing object"})); - assert_eq!(from_str(~"{ "), + assert_eq!(from_str("{ "), Err(Error { line: 1u, col: 3u, msg: @~"EOF while parsing object"})); - assert_eq!(from_str(~"{1"), + assert_eq!(from_str("{1"), Err(Error { line: 1u, col: 2u, msg: @~"key must be a string"})); - assert_eq!(from_str(~"{ \"a\""), + assert_eq!(from_str("{ \"a\""), Err(Error { line: 1u, col: 6u, msg: @~"EOF while parsing object"})); - assert_eq!(from_str(~"{\"a\""), + assert_eq!(from_str("{\"a\""), Err(Error { line: 1u, col: 5u, msg: @~"EOF while parsing object"})); - assert_eq!(from_str(~"{\"a\" "), + assert_eq!(from_str("{\"a\" "), Err(Error { line: 1u, col: 6u, msg: @~"EOF while parsing object"})); - assert_eq!(from_str(~"{\"a\" 1"), + assert_eq!(from_str("{\"a\" 1"), Err(Error {line: 1u, col: 6u, msg: @~"expected `:`"})); - assert_eq!(from_str(~"{\"a\":"), + assert_eq!(from_str("{\"a\":"), Err(Error {line: 1u, col: 6u, msg: @~"EOF while parsing value"})); - assert_eq!(from_str(~"{\"a\":1"), + assert_eq!(from_str("{\"a\":1"), Err(Error { line: 1u, col: 7u, msg: @~"EOF while parsing object"})); - assert_eq!(from_str(~"{\"a\":1 1"), + assert_eq!(from_str("{\"a\":1 1"), Err(Error {line: 1u, col: 8u, msg: @~"expected `,` or `}`"})); - assert_eq!(from_str(~"{\"a\":1,"), + assert_eq!(from_str("{\"a\":1,"), Err(Error { line: 1u, col: 8u, msg: @~"EOF while parsing object"})); - assert_eq!(result::unwrap(from_str(~"{}")), mk_object(~[])); - assert_eq!(result::unwrap(from_str(~"{\"a\": 3}")), - mk_object(~[(~"a", Number(3.0f))])); + assert_eq!(result::unwrap(from_str("{}")), mk_object([])); + assert_eq!(result::unwrap(from_str("{\"a\": 3}")), + mk_object([(~"a", Number(3.0f))])); assert_eq!(result::unwrap(from_str( - ~"{ \"a\": null, \"b\" : true }")), - mk_object(~[ + "{ \"a\": null, \"b\" : true }")), + mk_object([ (~"a", Null), (~"b", Boolean(true))])); assert_eq!(result::unwrap( - from_str(~"\n{ \"a\": null, \"b\" : true }\n")), - mk_object(~[ + from_str("\n{ \"a\": null, \"b\" : true }\n")), + mk_object([ (~"a", Null), (~"b", Boolean(true))])); assert_eq!(result::unwrap(from_str( - ~"{\"a\" : 1.0 ,\"b\": [ true ]}")), - mk_object(~[ + "{\"a\" : 1.0 ,\"b\": [ true ]}")), + mk_object([ (~"a", Number(1.0)), (~"b", List(~[Boolean(true)])) ])); assert_eq!(result::unwrap(from_str( ~"{" + - ~"\"a\": 1.0, " + - ~"\"b\": [" + - ~"true," + - ~"\"foo\\nbar\", " + - ~"{ \"c\": {\"d\": null} } " + - ~"]" + - ~"}")), - mk_object(~[ + "\"a\": 1.0, " + + "\"b\": [" + + "true," + + "\"foo\\nbar\", " + + "{ \"c\": {\"d\": null} } " + + "]" + + "}")), + mk_object([ (~"a", Number(1.0f)), (~"b", List(~[ Boolean(true), String(~"foo\nbar"), - mk_object(~[ - (~"c", mk_object(~[(~"d", Null)])) + mk_object([ + (~"c", mk_object([(~"d", Null)])) ]) ])) ])); @@ -1916,23 +1948,23 @@ mod tests { #[test] fn test_decode_option() { - let mut decoder = Decoder(from_str(~"null").unwrap()); + let mut decoder = Decoder(from_str("null").unwrap()); let value: Option<~str> = Decodable::decode(&mut decoder); assert_eq!(value, None); - let mut decoder = Decoder(from_str(~"\"jodhpurs\"").unwrap()); + let mut decoder = Decoder(from_str("\"jodhpurs\"").unwrap()); let value: Option<~str> = Decodable::decode(&mut decoder); assert_eq!(value, Some(~"jodhpurs")); } #[test] fn test_decode_enum() { - let mut decoder = Decoder(from_str(~"\"Dog\"").unwrap()); + let mut decoder = Decoder(from_str("\"Dog\"").unwrap()); let value: Animal = Decodable::decode(&mut decoder); assert_eq!(value, Dog); let mut decoder = - Decoder(from_str(~"[\"Frog\",\"Henry\",349]").unwrap()); + Decoder(from_str("[\"Frog\",\"Henry\",349]").unwrap()); let value: Animal = Decodable::decode(&mut decoder); assert_eq!(value, Frog(~"Henry", 349)); } @@ -1949,7 +1981,7 @@ mod tests { #[test] fn test_multiline_errors() { - assert_eq!(from_str(~"{\n \"foo\":\n \"bar\""), + assert_eq!(from_str("{\n \"foo\":\n \"bar\""), Err(Error { line: 3u, col: 8u, diff --git a/src/libstd/list.rs b/src/libextra/list.rs similarity index 71% rename from src/libstd/list.rs rename to src/libextra/list.rs index aa4abbac9d3d1..7a38be8944f97 100644 --- a/src/libstd/list.rs +++ b/src/libextra/list.rs @@ -8,7 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! A standard linked list +//! A standard, garbage-collected linked list. + +use core::prelude::*; + +use core::vec; #[deriving(Eq)] pub enum List { @@ -100,7 +104,7 @@ pub fn tail(ls: @List) -> @List { /// Returns the first element of a list pub fn head(ls: @List) -> T { match *ls { - Cons(copy hd, _) => hd, + Cons(ref hd, _) => copy *hd, // makes me sad _ => fail!("head invoked on empty list") } @@ -110,9 +114,9 @@ pub fn head(ls: @List) -> T { pub fn append(l: @List, m: @List) -> @List { match *l { Nil => return m, - Cons(copy x, xs) => { + Cons(ref x, xs) => { let rest = append(xs, m); - return @Cons(x, rest); + return @Cons(copy *x, rest); } } } @@ -140,21 +144,6 @@ pub fn iter(l: @List, f: &fn(&T)) { } /// Iterate over a list -#[cfg(stage0)] -pub fn each(l: @List, f: &fn(&T) -> bool) { - let mut cur = l; - loop { - cur = match *cur { - Cons(ref hd, tl) => { - if !f(hd) { return; } - tl - } - Nil => break - } - } -} -/// Iterate over a list -#[cfg(not(stage0))] pub fn each(l: @List, f: &fn(&T) -> bool) -> bool { let mut cur = l; loop { @@ -170,24 +159,6 @@ pub fn each(l: @List, f: &fn(&T) -> bool) -> bool { impl MutList { /// Iterate over a mutable list - #[cfg(stage0)] - pub fn each(@mut self, f: &fn(&mut T) -> bool) { - let mut cur = self; - loop { - let borrowed = &mut *cur; - cur = match *borrowed { - MutCons(ref mut hd, tl) => { - if !f(hd) { - return; - } - tl - } - MutNil => break - } - } - } - /// Iterate over a mutable list - #[cfg(not(stage0))] pub fn each(@mut self, f: &fn(&mut T) -> bool) -> bool { let mut cur = self; loop { @@ -215,9 +186,9 @@ mod tests { #[test] fn test_is_empty() { - let empty : @list::List = from_vec(~[]); - let full1 = from_vec(~[1]); - let full2 = from_vec(~['r', 'u']); + let empty : @list::List = from_vec([]); + let full1 = from_vec([1]); + let full2 = from_vec(['r', 'u']); assert!(is_empty(empty)); assert!(!is_empty(full1)); @@ -226,30 +197,30 @@ mod tests { #[test] fn test_from_vec() { - let l = from_vec(~[0, 1, 2]); + let l = from_vec([0, 1, 2]); - assert!((head(l) == 0)); + assert_eq!(head(l), 0); let tail_l = tail(l); - assert!((head(tail_l) == 1)); + assert_eq!(head(tail_l), 1); let tail_tail_l = tail(tail_l); - assert!((head(tail_tail_l) == 2)); + assert_eq!(head(tail_tail_l), 2); } #[test] fn test_from_vec_empty() { - let empty : @list::List = from_vec(~[]); - assert!((empty == @list::Nil::)); + let empty : @list::List = from_vec([]); + assert_eq!(empty, @list::Nil::); } #[test] fn test_foldl() { fn add(a: &uint, b: &int) -> uint { return *a + (*b as uint); } - let l = from_vec(~[0, 1, 2, 3, 4]); + let l = from_vec([0, 1, 2, 3, 4]); let empty = @list::Nil::; - assert!((list::foldl(0u, l, add) == 10u)); - assert!((list::foldl(0u, empty, add) == 0u)); + assert_eq!(list::foldl(0u, l, add), 10u); + assert_eq!(list::foldl(0u, empty, add), 0u); } #[test] @@ -257,29 +228,29 @@ mod tests { fn sub(a: &int, b: &int) -> int { *a - *b } - let l = from_vec(~[1, 2, 3, 4]); - assert!((list::foldl(0, l, sub) == -10)); + let l = from_vec([1, 2, 3, 4]); + assert_eq!(list::foldl(0, l, sub), -10); } #[test] fn test_find_success() { fn match_(i: &int) -> bool { return *i == 2; } - let l = from_vec(~[0, 1, 2]); - assert!((list::find(l, match_) == option::Some(2))); + let l = from_vec([0, 1, 2]); + assert_eq!(list::find(l, match_), option::Some(2)); } #[test] fn test_find_fail() { fn match_(_i: &int) -> bool { return false; } - let l = from_vec(~[0, 1, 2]); + let l = from_vec([0, 1, 2]); let empty = @list::Nil::; - assert!((list::find(l, match_) == option::None::)); - assert!((list::find(empty, match_) == option::None::)); + assert_eq!(list::find(l, match_), option::None::); + assert_eq!(list::find(empty, match_), option::None::); } #[test] fn test_has() { - let l = from_vec(~[5, 8, 6]); + let l = from_vec([5, 8, 6]); let empty = @list::Nil::; assert!((list::has(l, 5))); assert!((!list::has(l, 7))); @@ -289,15 +260,15 @@ mod tests { #[test] fn test_len() { - let l = from_vec(~[0, 1, 2]); + let l = from_vec([0, 1, 2]); let empty = @list::Nil::; - assert!((list::len(l) == 3u)); - assert!((list::len(empty) == 0u)); + assert_eq!(list::len(l), 3u); + assert_eq!(list::len(empty), 0u); } #[test] fn test_append() { - assert!(from_vec(~[1,2,3,4]) - == list::append(list::from_vec(~[1,2]), list::from_vec(~[3,4]))); + assert!(from_vec([1,2,3,4]) + == list::append(list::from_vec([1,2]), list::from_vec([3,4]))); } } diff --git a/src/libstd/md4.rs b/src/libextra/md4.rs similarity index 80% rename from src/libstd/md4.rs rename to src/libextra/md4.rs index 84561256cd1dd..f12c9d6573e90 100644 --- a/src/libstd/md4.rs +++ b/src/libextra/md4.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use core::str; use core::uint; use core::vec; @@ -19,6 +21,8 @@ struct Quad { d: u32 } +/// Calculates the md4 hash of the given slice of bytes, returning the 128-bit +/// result as a quad of u32's pub fn md4(msg: &[u8]) -> Quad { // subtle: if orig_len is merely uint, then the code below // which performs shifts by 32 bits or more has undefined @@ -26,7 +30,7 @@ pub fn md4(msg: &[u8]) -> Quad { let orig_len: u64 = (msg.len() * 8u) as u64; // pad message - let mut msg = vec::append(vec::to_owned(msg), ~[0x80u8]); + let mut msg = vec::append(vec::to_owned(msg), [0x80u8]); let mut bitlen = orig_len + 8u64; while (bitlen + 64u64) % 512u64 > 0u64 { msg.push(0u8); @@ -54,9 +58,9 @@ pub fn md4(msg: &[u8]) -> Quad { let e = msg.len(); let mut x = vec::from_elem(16u, 0u32); while i < e { - let aa = a, bb = b, cc = c, dd = d; + let (aa, bb, cc, dd) = (a, b, c, d); - let mut j = 0u, base = i; + let mut (j, base) = (0u, i); while j < 16u { x[j] = (msg[base] as u32) + (msg[base + 1u] as u32 << 8u32) + (msg[base + 2u] as u32 << 16u32) + @@ -103,6 +107,8 @@ pub fn md4(msg: &[u8]) -> Quad { return Quad {a: a, b: b, c: c, d: d}; } +/// Calculates the md4 hash of a slice of bytes, returning the hex-encoded +/// version of the hash pub fn md4_str(msg: &[u8]) -> ~str { let Quad {a, b, c, d} = md4(msg); fn app(a: u32, b: u32, c: u32, d: u32, f: &fn(u32)) { @@ -113,7 +119,7 @@ pub fn md4_str(msg: &[u8]) -> ~str { let mut i = 0u32; while i < 4u32 { let byte = (u >> (i * 8u32)) as u8; - if byte <= 16u8 { result += ~"0"; } + if byte <= 16u8 { result += "0"; } result += uint::to_str_radix(byte as uint, 16u); i += 1u32; } @@ -121,21 +127,23 @@ pub fn md4_str(msg: &[u8]) -> ~str { result } +/// Calculates the md4 hash of a string, returning the hex-encoded version of +/// the hash pub fn md4_text(msg: &str) -> ~str { md4_str(str::to_bytes(msg)) } #[test] fn test_md4() { - assert!(md4_text(~"") == ~"31d6cfe0d16ae931b73c59d7e0c089c0"); - assert!(md4_text(~"a") == ~"bde52cb31de33e46245e05fbdbd6fb24"); - assert!(md4_text(~"abc") == ~"a448017aaf21d8525fc10ae87aa6729d"); - assert!(md4_text(~"message digest") == + assert_eq!(md4_text(""), ~"31d6cfe0d16ae931b73c59d7e0c089c0"); + assert_eq!(md4_text("a"), ~"bde52cb31de33e46245e05fbdbd6fb24"); + assert_eq!(md4_text("abc"), ~"a448017aaf21d8525fc10ae87aa6729d"); + assert!(md4_text("message digest") == ~"d9130a8164549fe818874806e1c7014b"); - assert!(md4_text(~"abcdefghijklmnopqrstuvwxyz") == + assert!(md4_text("abcdefghijklmnopqrstuvwxyz") == ~"d79e1c308aa5bbcdeea8ed63df412da9"); assert!(md4_text( - ~"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\ + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\ 0123456789") == ~"043f8582f241db351ce627e153e7f0e4"); - assert!(md4_text(~"1234567890123456789012345678901234567890123456789\ + assert!(md4_text("1234567890123456789012345678901234567890123456789\ 0123456789012345678901234567890") == ~"e33b4ddc9c38f2199c3e7b164fcc0536"); } diff --git a/src/libstd/net.rs b/src/libextra/net.rs similarity index 100% rename from src/libstd/net.rs rename to src/libextra/net.rs diff --git a/src/libstd/net_ip.rs b/src/libextra/net_ip.rs similarity index 97% rename from src/libstd/net_ip.rs rename to src/libextra/net_ip.rs index cc4e7ee02046d..ddbf09e40eb92 100644 --- a/src/libstd/net_ip.rs +++ b/src/libextra/net_ip.rs @@ -10,6 +10,10 @@ //! Types/fns concerning Internet Protocol (IP), versions 4 & 6 +#[allow(missing_doc)]; + +use core::prelude::*; + use core::libc; use core::comm::{stream, SharedChan}; use core::ptr; @@ -145,6 +149,8 @@ pub fn get_addr(node: &str, iotask: &iotask) } pub mod v4 { + use core::prelude::*; + use net::ip::{IpAddr, Ipv4, ParseAddrErr}; use uv::ll; use uv_ip4_addr = uv::ll::ip4_addr; @@ -224,7 +230,7 @@ pub mod v4 { let input_is_inaddr_none = result::get(&ip_rep_result).as_u32() == INADDR_NONE; - let new_addr = uv_ip4_addr(str::to_owned(ip), 22); + let new_addr = uv_ip4_addr(ip, 22); let reformatted_name = uv_ip4_name(&new_addr); debug!("try_parse_addr: input ip: %s reparsed ip: %s", ip, reformatted_name); @@ -246,12 +252,13 @@ pub mod v4 { } } pub mod v6 { + use core::prelude::*; + use net::ip::{IpAddr, Ipv6, ParseAddrErr}; use uv_ip6_addr = uv::ll::ip6_addr; use uv_ip6_name = uv::ll::ip6_name; use core::result; - use core::str; /** * Convert a str to `ip_addr` @@ -271,13 +278,13 @@ pub mod v6 { pub fn parse_addr(ip: &str) -> IpAddr { match try_parse_addr(ip) { result::Ok(addr) => addr, - result::Err(copy err_data) => fail!(copy err_data.err_msg) + result::Err(err_data) => fail!(copy err_data.err_msg) } } pub fn try_parse_addr(ip: &str) -> result::Result { unsafe { // need to figure out how to establish a parse failure.. - let new_addr = uv_ip6_addr(str::to_owned(ip), 22); + let new_addr = uv_ip6_addr(ip, 22); let reparsed_name = uv_ip6_name(&new_addr); debug!("v6::try_parse_addr ip: '%s' reparsed '%s'", ip, reparsed_name); @@ -369,7 +376,6 @@ mod test { use uv; use core::result; - use core::vec; #[test] fn test_ip_ipv4_parse_and_format_ip() { @@ -383,11 +389,11 @@ mod test { let format_result = format_addr(&v6::parse_addr(localhost_str)); debug!("results: expected: '%s' actual: '%s'", localhost_str, format_result); - assert!(format_result == localhost_str); + assert_eq!(format_result, localhost_str); } #[test] fn test_ip_ipv4_bad_parse() { - match v4::try_parse_addr(~"b4df00d") { + match v4::try_parse_addr("b4df00d") { result::Err(ref err_info) => { debug!("got error as expected %?", err_info); assert!(true); @@ -400,7 +406,7 @@ mod test { #[test] #[ignore(target_os="win32")] fn test_ip_ipv6_bad_parse() { - match v6::try_parse_addr(~"::,~2234k;") { + match v6::try_parse_addr("::,~2234k;") { result::Err(ref err_info) => { debug!("got error as expected %?", err_info); assert!(true); diff --git a/src/libstd/net_tcp.rs b/src/libextra/net_tcp.rs similarity index 99% rename from src/libstd/net_tcp.rs rename to src/libextra/net_tcp.rs index 37578e42baff4..87ebfdfb7976c 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libextra/net_tcp.rs @@ -11,6 +11,10 @@ //! High-level interface to libuv's TCP functionality // FIXME #4425: Need FFI fixes +#[allow(missing_doc)]; + +use core::prelude::*; + use future; use future_spawn = future::spawn; use ip = net_ip; @@ -464,7 +468,7 @@ fn read_future(sock: &TcpSocket, timeout_msecs: uint) * Here, the `new_conn` is used in conjunction with `accept` from within * a task spawned by the `new_connect_cb` passed into `listen` * - * ~~~~~~~~~~~ + * ~~~ {.rust} * do net::tcp::listen(remote_ip, remote_port, backlog, iotask, * // this callback is ran once after the connection is successfully * // set up @@ -495,7 +499,7 @@ fn read_future(sock: &TcpSocket, timeout_msecs: uint) * None => () * } * }; - * ~~~~~~~~~~~ + * ~~~ * * # Arguments * @@ -591,7 +595,7 @@ pub fn accept(new_conn: TcpNewConnection) } // UNSAFE LIBUV INTERACTION END match result_po.recv() { - Some(copy err_data) => result::Err(err_data), + Some(err_data) => result::Err(err_data), None => result::Ok(TcpSocket(client_socket_data)) } } @@ -822,7 +826,7 @@ pub fn socket_buf(sock: TcpSocket) -> TcpSocketBuf { } /// Convenience methods extending `net::tcp::TcpSocket` -pub impl TcpSocket { +impl TcpSocket { pub fn read_start(&self) -> result::Result<@Port< result::Result<~[u8], TcpErrData>>, TcpErrData> { read_start(self) @@ -831,11 +835,11 @@ pub impl TcpSocket { result::Result<(), TcpErrData> { read_stop(self) } - fn read(&self, timeout_msecs: uint) -> + pub fn read(&self, timeout_msecs: uint) -> result::Result<~[u8], TcpErrData> { read(self, timeout_msecs) } - fn read_future(&self, timeout_msecs: uint) -> + pub fn read_future(&self, timeout_msecs: uint) -> future::Future> { read_future(self, timeout_msecs) } @@ -1438,6 +1442,8 @@ struct TcpBufferedSocketData { #[cfg(test)] mod test { + use core::prelude::*; + use net::ip; use net::tcp::{GenericListenErr, TcpConnectErrData, TcpListenErrData}; use net::tcp::{connect, accept, read, listen, TcpSocket, socket_buf}; @@ -1447,6 +1453,10 @@ mod test { use core::cell::Cell; use core::comm::{stream, SharedChan}; + use core::io; + use core::result; + use core::str; + use core::task; // FIXME don't run on fbsd or linux 32 bit (#2064) #[cfg(target_os="win32")] @@ -1623,10 +1633,10 @@ mod test { // This is what we are actually testing! assert!(net::ip::format_addr(&sock.get_peer_addr()) == ~"127.0.0.1"); - assert!(net::ip::get_port(&sock.get_peer_addr()) == 8887); + assert_eq!(net::ip::get_port(&sock.get_peer_addr()), 8887); // Fulfill the protocol the test server expects - let resp_bytes = str::to_bytes(~"ping"); + let resp_bytes = str::to_bytes("ping"); tcp_write_single(&sock, resp_bytes); debug!("message sent"); sock.read(0u); @@ -1820,7 +1830,7 @@ mod test { let (server_po, server_ch) = stream::<~str>(); let server_ch = SharedChan::new(server_ch); let server_ip_addr = ip::v4::parse_addr(server_ip); - let resp_cell = Cell(resp); + let resp_cell = Cell::new(resp); let listen_result = listen(server_ip_addr, server_port, 128, iotask, // on_establish_cb -- called when listener is set up @@ -1832,7 +1842,7 @@ mod test { // risky to run this on the loop, but some users // will want the POWER |new_conn, kill_ch| { - let resp_cell2 = Cell(resp_cell.take()); + let resp_cell2 = Cell::new(resp_cell.take()); debug!("SERVER: new connection!"); let (cont_po, cont_ch) = stream(); let server_ch = server_ch.clone(); diff --git a/src/libstd/net_url.rs b/src/libextra/net_url.rs similarity index 76% rename from src/libstd/net_url.rs rename to src/libextra/net_url.rs index e7cf710cf6797..085407758645f 100644 --- a/src/libstd/net_url.rs +++ b/src/libextra/net_url.rs @@ -10,6 +10,10 @@ //! Types/fns concerning URLs (see RFC 3986) +#[allow(missing_doc)]; + +use core::prelude::*; + use core::cmp::Eq; use core::io::{Reader, ReaderUtil}; use core::io; @@ -37,16 +41,15 @@ struct UserInfo { pub type Query = ~[(~str, ~str)]; -pub impl Url { - fn new( - scheme: ~str, - user: Option, - host: ~str, - port: Option<~str>, - path: ~str, - query: Query, - fragment: Option<~str> - ) -> Url { +impl Url { + pub fn new(scheme: ~str, + user: Option, + host: ~str, + port: Option<~str>, + path: ~str, + query: Query, + fragment: Option<~str>) + -> Url { Url { scheme: scheme, user: user, @@ -59,8 +62,8 @@ pub impl Url { } } -pub impl UserInfo { - fn new(user: ~str, pass: Option<~str>) -> UserInfo { +impl UserInfo { + pub fn new(user: ~str, pass: Option<~str>) -> UserInfo { UserInfo { user: user, pass: pass } } } @@ -350,7 +353,7 @@ pub fn query_to_str(query: &Query) -> ~str { } } } - return str::connect(strvec, ~"&"); + return str::connect(strvec, "&"); } // returns the scheme and the rest of the url, or a parsing error @@ -390,7 +393,7 @@ enum Input { // returns userinfo, host, port, and unparsed part, or an error fn get_authority(rawurl: &str) -> Result<(Option, ~str, Option<~str>, ~str), ~str> { - if !str::starts_with(rawurl, ~"//") { + if !str::starts_with(rawurl, "//") { // there is no authority. return Ok((None, ~"", None, rawurl.to_str())); } @@ -413,7 +416,7 @@ fn get_authority(rawurl: &str) -> let mut port = None; let mut colon_count = 0; - let mut pos = 0, begin = 2, end = len; + let mut (pos, begin, end) = (0, 2, len); for str::each_chari(rawurl) |i,c| { if i < 2 { loop; } // ignore the leading // @@ -575,31 +578,30 @@ fn get_path(rawurl: &str, authority: bool) -> } if authority { - if end != 0 && !str::starts_with(rawurl, ~"/") { + if end != 0 && !str::starts_with(rawurl, "/") { return Err(~"Non-empty path must begin with\ '/' in presence of authority."); } } - return Ok((decode_component(str::slice(rawurl, 0, end).to_owned()), + return Ok((decode_component(str::slice(rawurl, 0, end)), str::slice(rawurl, end, len).to_owned())); } // returns the parsed query and the fragment, if present fn get_query_fragment(rawurl: &str) -> Result<(Query, Option<~str>), ~str> { - if !str::starts_with(rawurl, ~"?") { - if str::starts_with(rawurl, ~"#") { + if !str::starts_with(rawurl, "?") { + if str::starts_with(rawurl, "#") { let f = decode_component(str::slice(rawurl, 1, - str::len(rawurl)).to_owned()); + str::len(rawurl))); return Ok((~[], Some(f))); } else { return Ok((~[], None)); } } - let (q, r) = split_char_first(str::slice(rawurl, 1, - str::len(rawurl)).to_owned(), '#'); + let (q, r) = split_char_first(str::slice(rawurl, 1, rawurl.len()), '#'); let f = if str::len(r) != 0 { Some(decode_component(r)) } else { None }; return Ok((query_from_str(q), f)); @@ -703,13 +705,6 @@ impl ToStr for Url { } } -#[cfg(stage0)] -impl IterBytes for Url { - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - self.to_str().iter_bytes(lsb0, f) - } -} -#[cfg(not(stage0))] impl IterBytes for Url { fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { self.to_str().iter_bytes(lsb0, f) @@ -721,54 +716,54 @@ impl IterBytes for Url { #[test] fn test_split_char_first() { - let (u,v) = split_char_first(~"hello, sweet world", ','); - assert!(u == ~"hello"); - assert!(v == ~" sweet world"); + let (u,v) = split_char_first("hello, sweet world", ','); + assert_eq!(u, ~"hello"); + assert_eq!(v, ~" sweet world"); - let (u,v) = split_char_first(~"hello sweet world", ','); - assert!(u == ~"hello sweet world"); - assert!(v == ~""); + let (u,v) = split_char_first("hello sweet world", ','); + assert_eq!(u, ~"hello sweet world"); + assert_eq!(v, ~""); } #[test] fn test_get_authority() { let (u, h, p, r) = get_authority( "//user:pass@rust-lang.org/something").unwrap(); - assert!(u == Some(UserInfo::new(~"user", Some(~"pass")))); - assert!(h == ~"rust-lang.org"); + assert_eq!(u, Some(UserInfo::new(~"user", Some(~"pass")))); + assert_eq!(h, ~"rust-lang.org"); assert!(p.is_none()); - assert!(r == ~"/something"); + assert_eq!(r, ~"/something"); let (u, h, p, r) = get_authority( "//rust-lang.org:8000?something").unwrap(); assert!(u.is_none()); - assert!(h == ~"rust-lang.org"); - assert!(p == Some(~"8000")); - assert!(r == ~"?something"); + assert_eq!(h, ~"rust-lang.org"); + assert_eq!(p, Some(~"8000")); + assert_eq!(r, ~"?something"); let (u, h, p, r) = get_authority( "//rust-lang.org#blah").unwrap(); assert!(u.is_none()); - assert!(h == ~"rust-lang.org"); + assert_eq!(h, ~"rust-lang.org"); assert!(p.is_none()); - assert!(r == ~"#blah"); + assert_eq!(r, ~"#blah"); // ipv6 tests let (_, h, _, _) = get_authority( "//2001:0db8:85a3:0042:0000:8a2e:0370:7334#blah").unwrap(); - assert!(h == ~"2001:0db8:85a3:0042:0000:8a2e:0370:7334"); + assert_eq!(h, ~"2001:0db8:85a3:0042:0000:8a2e:0370:7334"); let (_, h, p, _) = get_authority( "//2001:0db8:85a3:0042:0000:8a2e:0370:7334:8000#blah").unwrap(); - assert!(h == ~"2001:0db8:85a3:0042:0000:8a2e:0370:7334"); - assert!(p == Some(~"8000")); + assert_eq!(h, ~"2001:0db8:85a3:0042:0000:8a2e:0370:7334"); + assert_eq!(p, Some(~"8000")); let (u, h, p, _) = get_authority( "//us:p@2001:0db8:85a3:0042:0000:8a2e:0370:7334:8000#blah" ).unwrap(); - assert!(u == Some(UserInfo::new(~"us", Some(~"p")))); - assert!(h == ~"2001:0db8:85a3:0042:0000:8a2e:0370:7334"); - assert!(p == Some(~"8000")); + assert_eq!(u, Some(UserInfo::new(~"us", Some(~"p")))); + assert_eq!(h, ~"2001:0db8:85a3:0042:0000:8a2e:0370:7334"); + assert_eq!(p, Some(~"8000")); // invalid authorities; assert!(get_authority("//user:pass@rust-lang:something").is_err()); @@ -779,26 +774,26 @@ fn test_get_authority() { "//2001:0db8:85a3:0042:0000:8a2e:0370:7334:8000:00").is_err()); // these parse as empty, because they don't start with '//' - let (_, h, _, _) = get_authority(~"user:pass@rust-lang").unwrap(); - assert!(h == ~""); - let (_, h, _, _) = get_authority(~"rust-lang.org").unwrap(); - assert!(h == ~""); + let (_, h, _, _) = get_authority("user:pass@rust-lang").unwrap(); + assert_eq!(h, ~""); + let (_, h, _, _) = get_authority("rust-lang.org").unwrap(); + assert_eq!(h, ~""); } #[test] fn test_get_path() { let (p, r) = get_path("/something+%20orother", true).unwrap(); - assert!(p == ~"/something+ orother"); - assert!(r == ~""); + assert_eq!(p, ~"/something+ orother"); + assert_eq!(r, ~""); let (p, r) = get_path("test@email.com#fragment", false).unwrap(); - assert!(p == ~"test@email.com"); - assert!(r == ~"#fragment"); - let (p, r) = get_path(~"/gen/:addr=?q=v", false).unwrap(); - assert!(p == ~"/gen/:addr="); - assert!(r == ~"?q=v"); + assert_eq!(p, ~"test@email.com"); + assert_eq!(r, ~"#fragment"); + let (p, r) = get_path("/gen/:addr=?q=v", false).unwrap(); + assert_eq!(p, ~"/gen/:addr="); + assert_eq!(r, ~"?q=v"); //failure cases - assert!(get_path(~"something?q", true).is_err()); + assert!(get_path("something?q", true).is_err()); } #[cfg(test)] @@ -860,56 +855,56 @@ mod tests { #[test] fn test_full_url_parse_and_format() { let url = ~"http://user:pass@rust-lang.org/doc?s=v#something"; - assert!(from_str(url).unwrap().to_str() == url); + assert_eq!(from_str(url).unwrap().to_str(), url); } #[test] fn test_userless_url_parse_and_format() { let url = ~"http://rust-lang.org/doc?s=v#something"; - assert!(from_str(url).unwrap().to_str() == url); + assert_eq!(from_str(url).unwrap().to_str(), url); } #[test] fn test_queryless_url_parse_and_format() { let url = ~"http://user:pass@rust-lang.org/doc#something"; - assert!(from_str(url).unwrap().to_str() == url); + assert_eq!(from_str(url).unwrap().to_str(), url); } #[test] fn test_empty_query_url_parse_and_format() { let url = ~"http://user:pass@rust-lang.org/doc?#something"; let should_be = ~"http://user:pass@rust-lang.org/doc#something"; - assert!(from_str(url).unwrap().to_str() == should_be); + assert_eq!(from_str(url).unwrap().to_str(), should_be); } #[test] fn test_fragmentless_url_parse_and_format() { let url = ~"http://user:pass@rust-lang.org/doc?q=v"; - assert!(from_str(url).unwrap().to_str() == url); + assert_eq!(from_str(url).unwrap().to_str(), url); } #[test] fn test_minimal_url_parse_and_format() { let url = ~"http://rust-lang.org/doc"; - assert!(from_str(url).unwrap().to_str() == url); + assert_eq!(from_str(url).unwrap().to_str(), url); } #[test] fn test_scheme_host_only_url_parse_and_format() { let url = ~"http://rust-lang.org"; - assert!(from_str(url).unwrap().to_str() == url); + assert_eq!(from_str(url).unwrap().to_str(), url); } #[test] fn test_pathless_url_parse_and_format() { let url = ~"http://user:pass@rust-lang.org?q=v#something"; - assert!(from_str(url).unwrap().to_str() == url); + assert_eq!(from_str(url).unwrap().to_str(), url); } #[test] fn test_scheme_host_fragment_only_url_parse_and_format() { let url = ~"http://rust-lang.org#something"; - assert!(from_str(url).unwrap().to_str() == url); + assert_eq!(from_str(url).unwrap().to_str(), url); } #[test] @@ -923,134 +918,134 @@ mod tests { #[test] fn test_url_without_authority() { let url = ~"mailto:test@email.com"; - assert!(from_str(url).unwrap().to_str() == url); + assert_eq!(from_str(url).unwrap().to_str(), url); } #[test] fn test_encode() { - assert!(encode("") == ~""); - assert!(encode("http://example.com") == ~"http://example.com"); - assert!(encode("foo bar% baz") == ~"foo%20bar%25%20baz"); - assert!(encode(" ") == ~"%20"); - assert!(encode("!") == ~"!"); - assert!(encode("\"") == ~"\""); - assert!(encode("#") == ~"#"); - assert!(encode("$") == ~"$"); - assert!(encode("%") == ~"%25"); - assert!(encode("&") == ~"&"); - assert!(encode("'") == ~"%27"); - assert!(encode("(") == ~"("); - assert!(encode(")") == ~")"); - assert!(encode("*") == ~"*"); - assert!(encode("+") == ~"+"); - assert!(encode(",") == ~","); - assert!(encode("/") == ~"/"); - assert!(encode(":") == ~":"); - assert!(encode(";") == ~";"); - assert!(encode("=") == ~"="); - assert!(encode("?") == ~"?"); - assert!(encode("@") == ~"@"); - assert!(encode("[") == ~"["); - assert!(encode("]") == ~"]"); + assert_eq!(encode(""), ~""); + assert_eq!(encode("http://example.com"), ~"http://example.com"); + assert_eq!(encode("foo bar% baz"), ~"foo%20bar%25%20baz"); + assert_eq!(encode(" "), ~"%20"); + assert_eq!(encode("!"), ~"!"); + assert_eq!(encode("\""), ~"\""); + assert_eq!(encode("#"), ~"#"); + assert_eq!(encode("$"), ~"$"); + assert_eq!(encode("%"), ~"%25"); + assert_eq!(encode("&"), ~"&"); + assert_eq!(encode("'"), ~"%27"); + assert_eq!(encode("("), ~"("); + assert_eq!(encode(")"), ~")"); + assert_eq!(encode("*"), ~"*"); + assert_eq!(encode("+"), ~"+"); + assert_eq!(encode(","), ~","); + assert_eq!(encode("/"), ~"/"); + assert_eq!(encode(":"), ~":"); + assert_eq!(encode(";"), ~";"); + assert_eq!(encode("="), ~"="); + assert_eq!(encode("?"), ~"?"); + assert_eq!(encode("@"), ~"@"); + assert_eq!(encode("["), ~"["); + assert_eq!(encode("]"), ~"]"); } #[test] fn test_encode_component() { - assert!(encode_component("") == ~""); + assert_eq!(encode_component(""), ~""); assert!(encode_component("http://example.com") == ~"http%3A%2F%2Fexample.com"); assert!(encode_component("foo bar% baz") == ~"foo%20bar%25%20baz"); - assert!(encode_component(" ") == ~"%20"); - assert!(encode_component("!") == ~"%21"); - assert!(encode_component("#") == ~"%23"); - assert!(encode_component("$") == ~"%24"); - assert!(encode_component("%") == ~"%25"); - assert!(encode_component("&") == ~"%26"); - assert!(encode_component("'") == ~"%27"); - assert!(encode_component("(") == ~"%28"); - assert!(encode_component(")") == ~"%29"); - assert!(encode_component("*") == ~"%2A"); - assert!(encode_component("+") == ~"%2B"); - assert!(encode_component(",") == ~"%2C"); - assert!(encode_component("/") == ~"%2F"); - assert!(encode_component(":") == ~"%3A"); - assert!(encode_component(";") == ~"%3B"); - assert!(encode_component("=") == ~"%3D"); - assert!(encode_component("?") == ~"%3F"); - assert!(encode_component("@") == ~"%40"); - assert!(encode_component("[") == ~"%5B"); - assert!(encode_component("]") == ~"%5D"); + assert_eq!(encode_component(" "), ~"%20"); + assert_eq!(encode_component("!"), ~"%21"); + assert_eq!(encode_component("#"), ~"%23"); + assert_eq!(encode_component("$"), ~"%24"); + assert_eq!(encode_component("%"), ~"%25"); + assert_eq!(encode_component("&"), ~"%26"); + assert_eq!(encode_component("'"), ~"%27"); + assert_eq!(encode_component("("), ~"%28"); + assert_eq!(encode_component(")"), ~"%29"); + assert_eq!(encode_component("*"), ~"%2A"); + assert_eq!(encode_component("+"), ~"%2B"); + assert_eq!(encode_component(","), ~"%2C"); + assert_eq!(encode_component("/"), ~"%2F"); + assert_eq!(encode_component(":"), ~"%3A"); + assert_eq!(encode_component(";"), ~"%3B"); + assert_eq!(encode_component("="), ~"%3D"); + assert_eq!(encode_component("?"), ~"%3F"); + assert_eq!(encode_component("@"), ~"%40"); + assert_eq!(encode_component("["), ~"%5B"); + assert_eq!(encode_component("]"), ~"%5D"); } #[test] fn test_decode() { - assert!(decode("") == ~""); - assert!(decode("abc/def 123") == ~"abc/def 123"); - assert!(decode("abc%2Fdef%20123") == ~"abc%2Fdef 123"); - assert!(decode("%20") == ~" "); - assert!(decode("%21") == ~"%21"); - assert!(decode("%22") == ~"%22"); - assert!(decode("%23") == ~"%23"); - assert!(decode("%24") == ~"%24"); - assert!(decode("%25") == ~"%"); - assert!(decode("%26") == ~"%26"); - assert!(decode("%27") == ~"'"); - assert!(decode("%28") == ~"%28"); - assert!(decode("%29") == ~"%29"); - assert!(decode("%2A") == ~"%2A"); - assert!(decode("%2B") == ~"%2B"); - assert!(decode("%2C") == ~"%2C"); - assert!(decode("%2F") == ~"%2F"); - assert!(decode("%3A") == ~"%3A"); - assert!(decode("%3B") == ~"%3B"); - assert!(decode("%3D") == ~"%3D"); - assert!(decode("%3F") == ~"%3F"); - assert!(decode("%40") == ~"%40"); - assert!(decode("%5B") == ~"%5B"); - assert!(decode("%5D") == ~"%5D"); + assert_eq!(decode(""), ~""); + assert_eq!(decode("abc/def 123"), ~"abc/def 123"); + assert_eq!(decode("abc%2Fdef%20123"), ~"abc%2Fdef 123"); + assert_eq!(decode("%20"), ~" "); + assert_eq!(decode("%21"), ~"%21"); + assert_eq!(decode("%22"), ~"%22"); + assert_eq!(decode("%23"), ~"%23"); + assert_eq!(decode("%24"), ~"%24"); + assert_eq!(decode("%25"), ~"%"); + assert_eq!(decode("%26"), ~"%26"); + assert_eq!(decode("%27"), ~"'"); + assert_eq!(decode("%28"), ~"%28"); + assert_eq!(decode("%29"), ~"%29"); + assert_eq!(decode("%2A"), ~"%2A"); + assert_eq!(decode("%2B"), ~"%2B"); + assert_eq!(decode("%2C"), ~"%2C"); + assert_eq!(decode("%2F"), ~"%2F"); + assert_eq!(decode("%3A"), ~"%3A"); + assert_eq!(decode("%3B"), ~"%3B"); + assert_eq!(decode("%3D"), ~"%3D"); + assert_eq!(decode("%3F"), ~"%3F"); + assert_eq!(decode("%40"), ~"%40"); + assert_eq!(decode("%5B"), ~"%5B"); + assert_eq!(decode("%5D"), ~"%5D"); } #[test] fn test_decode_component() { - assert!(decode_component("") == ~""); - assert!(decode_component("abc/def 123") == ~"abc/def 123"); - assert!(decode_component("abc%2Fdef%20123") == ~"abc/def 123"); - assert!(decode_component("%20") == ~" "); - assert!(decode_component("%21") == ~"!"); - assert!(decode_component("%22") == ~"\""); - assert!(decode_component("%23") == ~"#"); - assert!(decode_component("%24") == ~"$"); - assert!(decode_component("%25") == ~"%"); - assert!(decode_component("%26") == ~"&"); - assert!(decode_component("%27") == ~"'"); - assert!(decode_component("%28") == ~"("); - assert!(decode_component("%29") == ~")"); - assert!(decode_component("%2A") == ~"*"); - assert!(decode_component("%2B") == ~"+"); - assert!(decode_component("%2C") == ~","); - assert!(decode_component("%2F") == ~"/"); - assert!(decode_component("%3A") == ~":"); - assert!(decode_component("%3B") == ~";"); - assert!(decode_component("%3D") == ~"="); - assert!(decode_component("%3F") == ~"?"); - assert!(decode_component("%40") == ~"@"); - assert!(decode_component("%5B") == ~"["); - assert!(decode_component("%5D") == ~"]"); + assert_eq!(decode_component(""), ~""); + assert_eq!(decode_component("abc/def 123"), ~"abc/def 123"); + assert_eq!(decode_component("abc%2Fdef%20123"), ~"abc/def 123"); + assert_eq!(decode_component("%20"), ~" "); + assert_eq!(decode_component("%21"), ~"!"); + assert_eq!(decode_component("%22"), ~"\""); + assert_eq!(decode_component("%23"), ~"#"); + assert_eq!(decode_component("%24"), ~"$"); + assert_eq!(decode_component("%25"), ~"%"); + assert_eq!(decode_component("%26"), ~"&"); + assert_eq!(decode_component("%27"), ~"'"); + assert_eq!(decode_component("%28"), ~"("); + assert_eq!(decode_component("%29"), ~")"); + assert_eq!(decode_component("%2A"), ~"*"); + assert_eq!(decode_component("%2B"), ~"+"); + assert_eq!(decode_component("%2C"), ~","); + assert_eq!(decode_component("%2F"), ~"/"); + assert_eq!(decode_component("%3A"), ~":"); + assert_eq!(decode_component("%3B"), ~";"); + assert_eq!(decode_component("%3D"), ~"="); + assert_eq!(decode_component("%3F"), ~"?"); + assert_eq!(decode_component("%40"), ~"@"); + assert_eq!(decode_component("%5B"), ~"["); + assert_eq!(decode_component("%5D"), ~"]"); } #[test] fn test_encode_form_urlencoded() { let mut m = HashMap::new(); - assert!(encode_form_urlencoded(&m) == ~""); + assert_eq!(encode_form_urlencoded(&m), ~""); m.insert(~"", ~[]); m.insert(~"foo", ~[]); - assert!(encode_form_urlencoded(&m) == ~""); + assert_eq!(encode_form_urlencoded(&m), ~""); let mut m = HashMap::new(); m.insert(~"foo", ~[~"bar", ~"123"]); - assert!(encode_form_urlencoded(&m) == ~"foo=bar&foo=123"); + assert_eq!(encode_form_urlencoded(&m), ~"foo=bar&foo=123"); let mut m = HashMap::new(); m.insert(~"foo bar", ~[~"abc", ~"12 = 34"]); @@ -1063,13 +1058,13 @@ mod tests { // FIXME #4449: Commented out because this causes an ICE, but only // on FreeBSD /* - assert!(decode_form_urlencoded(~[]).len() == 0); + assert_eq!(decode_form_urlencoded([]).len(), 0); let s = str::to_bytes("a=1&foo+bar=abc&foo+bar=12+%3D+34"); let form = decode_form_urlencoded(s); - assert!(form.len() == 2); - assert!(form.get_ref(&~"a") == &~[~"1"]); - assert!(form.get_ref(&~"foo bar") == &~[~"abc", ~"12 = 34"]); + assert_eq!(form.len(), 2); + assert_eq!(form.get_ref(&~"a"), &~[~"1"]); + assert_eq!(form.get_ref(&~"foo bar"), &~[~"abc", ~"12 = 34"]); */ } } diff --git a/src/libstd/num/bigint.rs b/src/libextra/num/bigint.rs similarity index 93% rename from src/libstd/num/bigint.rs rename to src/libextra/num/bigint.rs index c35415c53317c..77eef1d67efb6 100644 --- a/src/libstd/num/bigint.rs +++ b/src/libextra/num/bigint.rs @@ -16,8 +16,16 @@ A BigUint is represented as an array of BigDigits. A BigInt is a combination of BigUint and Sign. */ +#[allow(missing_doc)]; + +use core::prelude::*; + use core::cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater}; +use core::int; use core::num::{IntConvertible, Zero, One, ToStrRadix, FromStrRadix, Orderable}; +use core::str; +use core::uint; +use core::vec; /** A BigDigit is a BigUint's composing element. @@ -52,19 +60,19 @@ pub mod BigDigit { priv static hi_mask: uint = (-1 as uint) << bits; priv static lo_mask: uint = (-1 as uint) >> bits; - #[inline(always)] + priv fn get_hi(n: uint) -> BigDigit { (n >> bits) as BigDigit } - #[inline(always)] + priv fn get_lo(n: uint) -> BigDigit { (n & lo_mask) as BigDigit } /// Split one machine sized unsigned integer into two BigDigits. - #[inline(always)] + pub fn from_uint(n: uint) -> (BigDigit, BigDigit) { (get_hi(n), get_lo(n)) } /// Join two BigDigits into one machine sized unsigned integer - #[inline(always)] + pub fn to_uint(hi: BigDigit, lo: BigDigit) -> uint { (lo as uint) | ((hi as uint) << bits) } @@ -82,42 +90,42 @@ pub struct BigUint { } impl Eq for BigUint { - #[inline(always)] + fn eq(&self, other: &BigUint) -> bool { self.equals(other) } - #[inline(always)] + fn ne(&self, other: &BigUint) -> bool { !self.equals(other) } } impl TotalEq for BigUint { - #[inline(always)] + fn equals(&self, other: &BigUint) -> bool { match self.cmp(other) { Equal => true, _ => false } } } impl Ord for BigUint { - #[inline(always)] + fn lt(&self, other: &BigUint) -> bool { match self.cmp(other) { Less => true, _ => false} } - #[inline(always)] + fn le(&self, other: &BigUint) -> bool { match self.cmp(other) { Less | Equal => true, _ => false } } - #[inline(always)] + fn ge(&self, other: &BigUint) -> bool { match self.cmp(other) { Greater | Equal => true, _ => false } } - #[inline(always)] + fn gt(&self, other: &BigUint) -> bool { match self.cmp(other) { Greater => true, _ => false } } } impl TotalOrd for BigUint { - #[inline(always)] + fn cmp(&self, other: &BigUint) -> Ordering { - let s_len = self.data.len(), o_len = other.data.len(); + let (s_len, o_len) = (self.data.len(), other.data.len()); if s_len < o_len { return Less; } if s_len > o_len { return Greater; } @@ -133,12 +141,12 @@ impl TotalOrd for BigUint { } impl ToStr for BigUint { - #[inline(always)] + fn to_str(&self) -> ~str { self.to_str_radix(10) } } impl FromStr for BigUint { - #[inline(always)] + fn from_str(s: &str) -> Option { FromStrRadix::from_str_radix(s, 10) } @@ -147,17 +155,17 @@ impl FromStr for BigUint { impl Num for BigUint {} impl Orderable for BigUint { - #[inline(always)] + fn min(&self, other: &BigUint) -> BigUint { if self < other { self.clone() } else { other.clone() } } - #[inline(always)] + fn max(&self, other: &BigUint) -> BigUint { if self > other { self.clone() } else { other.clone() } } - #[inline(always)] + fn clamp(&self, mn: &BigUint, mx: &BigUint) -> BigUint { if self > mx { mx.clone() } else if self < mn { mn.clone() } else { self.clone() } @@ -165,7 +173,7 @@ impl Orderable for BigUint { } impl Shl for BigUint { - #[inline(always)] + fn shl(&self, rhs: &uint) -> BigUint { let n_unit = *rhs / BigDigit::bits; let n_bits = *rhs % BigDigit::bits; @@ -174,7 +182,7 @@ impl Shl for BigUint { } impl Shr for BigUint { - #[inline(always)] + fn shr(&self, rhs: &uint) -> BigUint { let n_unit = *rhs / BigDigit::bits; let n_bits = *rhs % BigDigit::bits; @@ -183,22 +191,22 @@ impl Shr for BigUint { } impl Zero for BigUint { - #[inline(always)] + fn zero() -> BigUint { BigUint::new(~[]) } - #[inline(always)] + fn is_zero(&self) -> bool { self.data.is_empty() } } impl One for BigUint { - #[inline(always)] + fn one() -> BigUint { BigUint::new(~[1]) } } impl Unsigned for BigUint {} impl Add for BigUint { - #[inline(always)] + fn add(&self, other: &BigUint) -> BigUint { let new_len = uint::max(self.data.len(), other.data.len()); @@ -218,7 +226,7 @@ impl Add for BigUint { } impl Sub for BigUint { - #[inline(always)] + fn sub(&self, other: &BigUint) -> BigUint { let new_len = uint::max(self.data.len(), other.data.len()); @@ -238,7 +246,7 @@ impl Sub for BigUint { lo }; - assert!(borrow == 0); // <=> assert!((self >= other)); + assert_eq!(borrow, 0); // <=> assert!((self >= other)); return BigUint::new(diff); } } @@ -247,7 +255,7 @@ impl Mul for BigUint { fn mul(&self, other: &BigUint) -> BigUint { if self.is_zero() || other.is_zero() { return Zero::zero(); } - let s_len = self.data.len(), o_len = other.data.len(); + let (s_len, o_len) = (self.data.len(), other.data.len()); if s_len == 1 { return mul_digit(other, self.data[0]); } if o_len == 1 { return mul_digit(self, other.data[0]); } @@ -274,7 +282,7 @@ impl Mul for BigUint { return ll + mm.shl_unit(half_len) + hh.shl_unit(half_len * 2); - #[inline(always)] + fn mul_digit(a: &BigUint, n: BigDigit) -> BigUint { if n == 0 { return Zero::zero(); } if n == 1 { return copy *a; } @@ -291,7 +299,7 @@ impl Mul for BigUint { return BigUint::new(prod + [carry]); } - #[inline(always)] + fn cut_at(a: &BigUint, n: uint) -> (BigUint, BigUint) { let mid = uint::min(a.data.len(), n); return (BigUint::from_slice(vec::slice(a.data, mid, @@ -299,7 +307,7 @@ impl Mul for BigUint { BigUint::from_slice(vec::slice(a.data, 0, mid))); } - #[inline(always)] + fn sub_sign(a: BigUint, b: BigUint) -> (Ordering, BigUint) { match a.cmp(&b) { Less => (Less, b - a), @@ -311,7 +319,7 @@ impl Mul for BigUint { } impl Div for BigUint { - #[inline(always)] + fn div(&self, other: &BigUint) -> BigUint { let (q, _) = self.div_rem(other); return q; @@ -319,7 +327,7 @@ impl Div for BigUint { } impl Rem for BigUint { - #[inline(always)] + fn rem(&self, other: &BigUint) -> BigUint { let (_, r) = self.div_rem(other); return r; @@ -327,29 +335,29 @@ impl Rem for BigUint { } impl Neg for BigUint { - #[inline(always)] + fn neg(&self) -> BigUint { fail!() } } impl Integer for BigUint { - #[inline(always)] + fn div_rem(&self, other: &BigUint) -> (BigUint, BigUint) { self.div_mod_floor(other) } - #[inline(always)] + fn div_floor(&self, other: &BigUint) -> BigUint { let (d, _) = self.div_mod_floor(other); return d; } - #[inline(always)] + fn mod_floor(&self, other: &BigUint) -> BigUint { let (_, m) = self.div_mod_floor(other); return m; } - #[inline(always)] + fn div_mod_floor(&self, other: &BigUint) -> (BigUint, BigUint) { if other.is_zero() { fail!() } if self.is_zero() { return (Zero::zero(), Zero::zero()); } @@ -371,7 +379,7 @@ impl Integer for BigUint { let (d, m) = div_mod_floor_inner(self << shift, other << shift); return (d, m >> shift); - #[inline(always)] + fn div_mod_floor_inner(a: BigUint, b: BigUint) -> (BigUint, BigUint) { let mut m = a; let mut d = Zero::zero::(); @@ -402,7 +410,7 @@ impl Integer for BigUint { return (d, m); } - #[inline(always)] + fn div_estimate(a: &BigUint, b: &BigUint, n: uint) -> (BigUint, BigUint, BigUint) { if a.data.len() < n { @@ -436,10 +444,10 @@ impl Integer for BigUint { * * The result is always positive */ - #[inline(always)] + fn gcd(&self, other: &BigUint) -> BigUint { // Use Euclid's algorithm - let mut m = copy *self, n = copy *other; + let mut (m, n) = (copy *self, copy *other); while !m.is_zero() { let temp = m; m = n % temp; @@ -451,15 +459,15 @@ impl Integer for BigUint { /** * Calculates the Lowest Common Multiple (LCM) of the number and `other` */ - #[inline(always)] + fn lcm(&self, other: &BigUint) -> BigUint { ((*self * *other) / self.gcd(other)) } /// Returns `true` if the number can be divided by `other` without leaving a remainder - #[inline(always)] + fn is_multiple_of(&self, other: &BigUint) -> bool { (*self % *other).is_zero() } /// Returns `true` if the number is divisible by `2` - #[inline(always)] + fn is_even(&self) -> bool { // Considering only the last digit. if self.data.is_empty() { @@ -470,24 +478,24 @@ impl Integer for BigUint { } /// Returns `true` if the number is not divisible by `2` - #[inline(always)] + fn is_odd(&self) -> bool { !self.is_even() } } impl IntConvertible for BigUint { - #[inline(always)] + fn to_int(&self) -> int { uint::min(self.to_uint(), int::max_value as uint) as int } - #[inline(always)] + fn from_int(n: int) -> BigUint { if (n < 0) { Zero::zero() } else { BigUint::from_uint(n as uint) } } } impl ToStrRadix for BigUint { - #[inline(always)] + fn to_str_radix(&self, radix: uint) -> ~str { assert!(1 < radix && radix <= 16); let (base, max_len) = get_radix_base(radix); @@ -496,7 +504,7 @@ impl ToStrRadix for BigUint { } return fill_concat(convert_base(copy *self, base), radix, max_len); - #[inline(always)] + fn convert_base(n: BigUint, base: uint) -> ~[BigDigit] { let divider = BigUint::from_uint(base); let mut result = ~[]; @@ -512,7 +520,7 @@ impl ToStrRadix for BigUint { return result; } - #[inline(always)] + fn fill_concat(v: &[BigDigit], radix: uint, l: uint) -> ~str { if v.is_empty() { return ~"0" } let s = str::concat(vec::reversed(v).map(|n| { @@ -526,7 +534,7 @@ impl ToStrRadix for BigUint { impl FromStrRadix for BigUint { /// Creates and initializes an BigUint. - #[inline(always)] + pub fn from_str_radix(s: &str, radix: uint) -> Option { BigUint::parse_bytes(str::to_bytes(s), radix) @@ -535,7 +543,7 @@ impl FromStrRadix for BigUint { impl BigUint { /// Creates and initializes an BigUint. - #[inline(always)] + pub fn new(v: ~[BigDigit]) -> BigUint { // omit trailing zeros let new_len = v.rposition(|n| *n != 0).map_default(0, |p| *p + 1); @@ -547,7 +555,7 @@ impl BigUint { } /// Creates and initializes an BigUint. - #[inline(always)] + pub fn from_uint(n: uint) -> BigUint { match BigDigit::from_uint(n) { (0, 0) => Zero::zero(), @@ -557,13 +565,13 @@ impl BigUint { } /// Creates and initializes an BigUint. - #[inline(always)] + pub fn from_slice(slice: &[BigDigit]) -> BigUint { return BigUint::new(vec::to_owned(slice)); } /// Creates and initializes an BigUint. - #[inline(always)] + pub fn parse_bytes(buf: &[u8], radix: uint) -> Option { let (base, unit_len) = get_radix_base(radix); @@ -590,7 +598,9 @@ impl BigUint { } } - #[inline(always)] + + /// Converts this big integer into a uint, returning the uint::max_value if + /// it's too large to fit in a uint. pub fn to_uint(&self) -> uint { match self.data.len() { 0 => 0, @@ -600,14 +610,14 @@ impl BigUint { } } - #[inline(always)] + priv fn shl_unit(&self, n_unit: uint) -> BigUint { if n_unit == 0 || self.is_zero() { return copy *self; } return BigUint::new(vec::from_elem(n_unit, 0) + self.data); } - #[inline(always)] + priv fn shl_bits(&self, n_bits: uint) -> BigUint { if n_bits == 0 || self.is_zero() { return copy *self; } @@ -623,7 +633,7 @@ impl BigUint { return BigUint::new(shifted + [carry]); } - #[inline(always)] + priv fn shr_unit(&self, n_unit: uint) -> BigUint { if n_unit == 0 { return copy *self; } if self.data.len() < n_unit { return Zero::zero(); } @@ -632,7 +642,7 @@ impl BigUint { ); } - #[inline(always)] + priv fn shr_bits(&self, n_bits: uint) -> BigUint { if n_bits == 0 || self.data.is_empty() { return copy *self; } @@ -647,7 +657,7 @@ impl BigUint { } #[cfg(target_arch = "x86_64")] -#[inline(always)] + priv fn get_radix_base(radix: uint) -> (uint, uint) { assert!(1 < radix && radix <= 16); match radix { @@ -673,7 +683,7 @@ priv fn get_radix_base(radix: uint) -> (uint, uint) { #[cfg(target_arch = "arm")] #[cfg(target_arch = "x86")] #[cfg(target_arch = "mips")] -#[inline(always)] + priv fn get_radix_base(radix: uint) -> (uint, uint) { assert!(1 < radix && radix <= 16); match radix { @@ -701,26 +711,26 @@ priv fn get_radix_base(radix: uint) -> (uint, uint) { pub enum Sign { Minus, Zero, Plus } impl Ord for Sign { - #[inline(always)] + fn lt(&self, other: &Sign) -> bool { match self.cmp(other) { Less => true, _ => false} } - #[inline(always)] + fn le(&self, other: &Sign) -> bool { match self.cmp(other) { Less | Equal => true, _ => false } } - #[inline(always)] + fn ge(&self, other: &Sign) -> bool { match self.cmp(other) { Greater | Equal => true, _ => false } } - #[inline(always)] + fn gt(&self, other: &Sign) -> bool { match self.cmp(other) { Greater => true, _ => false } } } impl TotalOrd for Sign { - #[inline(always)] + fn cmp(&self, other: &Sign) -> Ordering { match (*self, *other) { (Minus, Minus) | (Zero, Zero) | (Plus, Plus) => Equal, @@ -732,7 +742,7 @@ impl TotalOrd for Sign { impl Neg for Sign { /// Negate Sign value. - #[inline(always)] + fn neg(&self) -> Sign { match *self { Minus => Plus, @@ -750,40 +760,40 @@ pub struct BigInt { } impl Eq for BigInt { - #[inline(always)] + fn eq(&self, other: &BigInt) -> bool { self.equals(other) } - #[inline(always)] + fn ne(&self, other: &BigInt) -> bool { !self.equals(other) } } impl TotalEq for BigInt { - #[inline(always)] + fn equals(&self, other: &BigInt) -> bool { match self.cmp(other) { Equal => true, _ => false } } } impl Ord for BigInt { - #[inline(always)] + fn lt(&self, other: &BigInt) -> bool { match self.cmp(other) { Less => true, _ => false} } - #[inline(always)] + fn le(&self, other: &BigInt) -> bool { match self.cmp(other) { Less | Equal => true, _ => false } } - #[inline(always)] + fn ge(&self, other: &BigInt) -> bool { match self.cmp(other) { Greater | Equal => true, _ => false } } - #[inline(always)] + fn gt(&self, other: &BigInt) -> bool { match self.cmp(other) { Greater => true, _ => false } } } impl TotalOrd for BigInt { - #[inline(always)] + fn cmp(&self, other: &BigInt) -> Ordering { let scmp = self.sign.cmp(&other.sign); if scmp != Equal { return scmp; } @@ -797,12 +807,12 @@ impl TotalOrd for BigInt { } impl ToStr for BigInt { - #[inline(always)] + fn to_str(&self) -> ~str { self.to_str_radix(10) } } impl FromStr for BigInt { - #[inline(always)] + fn from_str(s: &str) -> Option { FromStrRadix::from_str_radix(s, 10) } @@ -811,17 +821,17 @@ impl FromStr for BigInt { impl Num for BigInt {} impl Orderable for BigInt { - #[inline(always)] + fn min(&self, other: &BigInt) -> BigInt { if self < other { self.clone() } else { other.clone() } } - #[inline(always)] + fn max(&self, other: &BigInt) -> BigInt { if self > other { self.clone() } else { other.clone() } } - #[inline(always)] + fn clamp(&self, mn: &BigInt, mx: &BigInt) -> BigInt { if self > mx { mx.clone() } else if self < mn { mn.clone() } else { self.clone() } @@ -829,38 +839,38 @@ impl Orderable for BigInt { } impl Shl for BigInt { - #[inline(always)] + fn shl(&self, rhs: &uint) -> BigInt { BigInt::from_biguint(self.sign, self.data << *rhs) } } impl Shr for BigInt { - #[inline(always)] + fn shr(&self, rhs: &uint) -> BigInt { BigInt::from_biguint(self.sign, self.data >> *rhs) } } impl Zero for BigInt { - #[inline(always)] + fn zero() -> BigInt { BigInt::from_biguint(Zero, Zero::zero()) } - #[inline(always)] + fn is_zero(&self) -> bool { self.sign == Zero } } impl One for BigInt { - #[inline(always)] + fn one() -> BigInt { BigInt::from_biguint(Plus, One::one()) } } impl Signed for BigInt { - #[inline(always)] + fn abs(&self) -> BigInt { match self.sign { Plus | Zero => self.clone(), @@ -868,12 +878,12 @@ impl Signed for BigInt { } } - #[inline(always)] + fn abs_sub(&self, other: &BigInt) -> BigInt { if *self <= *other { Zero::zero() } else { *self - *other } } - #[inline(always)] + fn signum(&self) -> BigInt { match self.sign { Plus => BigInt::from_biguint(Plus, One::one()), @@ -882,15 +892,15 @@ impl Signed for BigInt { } } - #[inline(always)] + fn is_positive(&self) -> bool { self.sign == Plus } - #[inline(always)] + fn is_negative(&self) -> bool { self.sign == Minus } } impl Add for BigInt { - #[inline(always)] + fn add(&self, other: &BigInt) -> BigInt { match (self.sign, other.sign) { (Zero, _) => other.clone(), @@ -905,7 +915,7 @@ impl Add for BigInt { } impl Sub for BigInt { - #[inline(always)] + fn sub(&self, other: &BigInt) -> BigInt { match (self.sign, other.sign) { (Zero, _) => -other, @@ -923,7 +933,7 @@ impl Sub for BigInt { } impl Mul for BigInt { - #[inline(always)] + fn mul(&self, other: &BigInt) -> BigInt { match (self.sign, other.sign) { (Zero, _) | (_, Zero) => Zero::zero(), @@ -938,7 +948,7 @@ impl Mul for BigInt { } impl Div for BigInt { - #[inline(always)] + fn div(&self, other: &BigInt) -> BigInt { let (q, _) = self.div_rem(other); return q; @@ -946,7 +956,7 @@ impl Div for BigInt { } impl Rem for BigInt { - #[inline(always)] + fn rem(&self, other: &BigInt) -> BigInt { let (_, r) = self.div_rem(other); return r; @@ -954,14 +964,14 @@ impl Rem for BigInt { } impl Neg for BigInt { - #[inline(always)] + fn neg(&self) -> BigInt { BigInt::from_biguint(self.sign.neg(), self.data.clone()) } } impl Integer for BigInt { - #[inline(always)] + fn div_rem(&self, other: &BigInt) -> (BigInt, BigInt) { // r.sign == self.sign let (d_ui, r_ui) = self.data.div_mod_floor(&other.data); @@ -976,24 +986,24 @@ impl Integer for BigInt { } } - #[inline(always)] + fn div_floor(&self, other: &BigInt) -> BigInt { let (d, _) = self.div_mod_floor(other); return d; } - #[inline(always)] + fn mod_floor(&self, other: &BigInt) -> BigInt { let (_, m) = self.div_mod_floor(other); return m; } - #[inline(always)] + fn div_mod_floor(&self, other: &BigInt) -> (BigInt, BigInt) { // m.sign == other.sign let (d_ui, m_ui) = self.data.div_rem(&other.data); - let d = BigInt::from_biguint(Plus, d_ui), - m = BigInt::from_biguint(Plus, m_ui); + let d = BigInt::from_biguint(Plus, d_ui); + let m = BigInt::from_biguint(Plus, m_ui); match (self.sign, other.sign) { (_, Zero) => fail!(), (Plus, Plus) | (Zero, Plus) => (d, m), @@ -1016,7 +1026,7 @@ impl Integer for BigInt { * * The result is always positive */ - #[inline(always)] + fn gcd(&self, other: &BigInt) -> BigInt { BigInt::from_biguint(Plus, self.data.gcd(&other.data)) } @@ -1024,26 +1034,26 @@ impl Integer for BigInt { /** * Calculates the Lowest Common Multiple (LCM) of the number and `other` */ - #[inline(always)] + fn lcm(&self, other: &BigInt) -> BigInt { BigInt::from_biguint(Plus, self.data.lcm(&other.data)) } /// Returns `true` if the number can be divided by `other` without leaving a remainder - #[inline(always)] + fn is_multiple_of(&self, other: &BigInt) -> bool { self.data.is_multiple_of(&other.data) } /// Returns `true` if the number is divisible by `2` - #[inline(always)] + fn is_even(&self) -> bool { self.data.is_even() } /// Returns `true` if the number is not divisible by `2` - #[inline(always)] + fn is_odd(&self) -> bool { self.data.is_odd() } } impl IntConvertible for BigInt { - #[inline(always)] + fn to_int(&self) -> int { match self.sign { Plus => uint::min(self.to_uint(), int::max_value as uint) as int, @@ -1053,7 +1063,7 @@ impl IntConvertible for BigInt { } } - #[inline(always)] + fn from_int(n: int) -> BigInt { if n > 0 { return BigInt::from_biguint(Plus, BigUint::from_uint(n as uint)); @@ -1068,7 +1078,7 @@ impl IntConvertible for BigInt { } impl ToStrRadix for BigInt { - #[inline(always)] + fn to_str_radix(&self, radix: uint) -> ~str { match self.sign { Plus => self.data.to_str_radix(radix), @@ -1080,22 +1090,21 @@ impl ToStrRadix for BigInt { impl FromStrRadix for BigInt { /// Creates and initializes an BigInt. - #[inline(always)] + fn from_str_radix(s: &str, radix: uint) -> Option { BigInt::parse_bytes(str::to_bytes(s), radix) } } -pub impl BigInt { +impl BigInt { /// Creates and initializes an BigInt. - #[inline(always)] pub fn new(sign: Sign, v: ~[BigDigit]) -> BigInt { BigInt::from_biguint(sign, BigUint::new(v)) } /// Creates and initializes an BigInt. - #[inline(always)] + pub fn from_biguint(sign: Sign, data: BigUint) -> BigInt { if sign == Zero || data.is_zero() { return BigInt { sign: Zero, data: Zero::zero() }; @@ -1104,20 +1113,20 @@ pub impl BigInt { } /// Creates and initializes an BigInt. - #[inline(always)] + pub fn from_uint(n: uint) -> BigInt { if n == 0 { return Zero::zero(); } return BigInt::from_biguint(Plus, BigUint::from_uint(n)); } /// Creates and initializes an BigInt. - #[inline(always)] + pub fn from_slice(sign: Sign, slice: &[BigDigit]) -> BigInt { BigInt::from_biguint(sign, BigUint::from_slice(slice)) } /// Creates and initializes an BigInt. - #[inline(always)] + pub fn parse_bytes(buf: &[u8], radix: uint) -> Option { if buf.is_empty() { return None; } @@ -1131,8 +1140,7 @@ pub impl BigInt { .map_consume(|bu| BigInt::from_biguint(sign, bu)); } - #[inline(always)] - fn to_uint(&self) -> uint { + pub fn to_uint(&self) -> uint { match self.sign { Plus => self.data.to_uint(), Zero => 0, @@ -1143,21 +1151,28 @@ pub impl BigInt { #[cfg(test)] mod biguint_tests { + use core::prelude::*; + use super::*; - use core::num::{IntConvertible, Zero, One, FromStrRadix}; + use core::cmp::{Less, Equal, Greater}; + use core::int; + use core::num::{IntConvertible, Zero, One, FromStrRadix}; + use core::str; + use core::uint; + use core::vec; #[test] fn test_from_slice() { fn check(slice: &[BigDigit], data: &[BigDigit]) { assert!(data == BigUint::from_slice(slice).data); } - check(~[1], ~[1]); - check(~[0, 0, 0], ~[]); - check(~[1, 2, 0, 0], ~[1, 2]); - check(~[0, 0, 1, 2], ~[0, 0, 1, 2]); - check(~[0, 0, 1, 2, 0, 0], ~[0, 0, 1, 2]); - check(~[-1], ~[-1]); + check([1], [1]); + check([0, 0, 0], []); + check([1, 2, 0, 0], [1, 2]); + check([0, 0, 1, 2], [0, 0, 1, 2]); + check([0, 0, 1, 2, 0, 0], [0, 0, 1, 2]); + check([-1], [-1]); } #[test] @@ -1170,7 +1185,7 @@ mod biguint_tests { if i == j { assert_eq!(ni.cmp(nj), Equal); assert_eq!(nj.cmp(ni), Equal); - assert!(ni == nj); + assert_eq!(ni, nj); assert!(!(ni != nj)); assert!(ni <= nj); assert!(ni >= nj); @@ -1200,7 +1215,7 @@ mod biguint_tests { #[test] fn test_shl() { fn check(v: ~[BigDigit], shift: uint, ans: ~[BigDigit]) { - assert!(BigUint::new(v) << shift == BigUint::new(ans)); + assert_eq!(BigUint::new(v) << shift, BigUint::new(ans)); } check(~[], 3, ~[]); @@ -1245,7 +1260,7 @@ mod biguint_tests { #[ignore(cfg(target_arch = "mips"))] fn test_shr() { fn check(v: ~[BigDigit], shift: uint, ans: ~[BigDigit]) { - assert!(BigUint::new(v) >> shift == BigUint::new(ans)); + assert_eq!(BigUint::new(v) >> shift, BigUint::new(ans)); } check(~[], 3, ~[]); @@ -1298,9 +1313,9 @@ mod biguint_tests { check(~[ 0, 1], ((uint::max_value >> BigDigit::bits) + 1) as int); check(~[-1, -1 >> 1], int::max_value); - assert!(BigUint::new(~[0, -1]).to_int() == int::max_value); - assert!(BigUint::new(~[0, 0, 1]).to_int() == int::max_value); - assert!(BigUint::new(~[0, 0, -1]).to_int() == int::max_value); + assert_eq!(BigUint::new(~[0, -1]).to_int(), int::max_value); + assert_eq!(BigUint::new(~[0, 0, 1]).to_int(), int::max_value); + assert_eq!(BigUint::new(~[0, 0, -1]).to_int(), int::max_value); } #[test] @@ -1318,8 +1333,8 @@ mod biguint_tests { check(~[ 0, -1], uint::max_value << BigDigit::bits); check(~[-1, -1], uint::max_value); - assert!(BigUint::new(~[0, 0, 1]).to_uint() == uint::max_value); - assert!(BigUint::new(~[0, 0, -1]).to_uint() == uint::max_value); + assert_eq!(BigUint::new(~[0, 0, 1]).to_uint(), uint::max_value); + assert_eq!(BigUint::new(~[0, 0, -1]).to_uint(), uint::max_value); } static sum_triples: &'static [(&'static [BigDigit], @@ -1433,10 +1448,10 @@ mod biguint_tests { let c = BigUint::from_slice(cVec); if !a.is_zero() { - assert!(c.div_rem(&a) == (b.clone(), Zero::zero())); + assert_eq!(c.div_rem(&a), (b.clone(), Zero::zero())); } if !b.is_zero() { - assert!(c.div_rem(&b) == (a.clone(), Zero::zero())); + assert_eq!(c.div_rem(&b), (a.clone(), Zero::zero())); } } @@ -1560,7 +1575,7 @@ mod biguint_tests { let &(n, rs) = num_pair; for rs.each |str_pair| { let &(radix, str) = str_pair; - assert!(n.to_str_radix(radix) == str); + assert_eq!(n.to_str_radix(radix), str); } } } @@ -1575,9 +1590,9 @@ mod biguint_tests { } } - assert_eq!(FromStrRadix::from_str_radix::(~"Z", 10), None); - assert_eq!(FromStrRadix::from_str_radix::(~"_", 2), None); - assert_eq!(FromStrRadix::from_str_radix::(~"-1", 10), None); + assert_eq!(FromStrRadix::from_str_radix::("Z", 10), None); + assert_eq!(FromStrRadix::from_str_radix::("_", 2), None); + assert_eq!(FromStrRadix::from_str_radix::("-1", 10), None); } #[test] @@ -1597,7 +1612,7 @@ mod biguint_tests { let ans = match FromStrRadix::from_str_radix(s, 10) { Some(x) => x, None => fail!() }; - assert!(n == ans); + assert_eq!(n, ans); } check(3, "6"); @@ -1609,16 +1624,22 @@ mod biguint_tests { #[cfg(test)] mod bigint_tests { + use core::prelude::*; + use super::*; + use core::cmp::{Less, Equal, Greater}; + use core::int; use core::num::{IntConvertible, Zero, One, FromStrRadix}; + use core::uint; + use core::vec; #[test] fn test_from_biguint() { fn check(inp_s: Sign, inp_n: uint, ans_s: Sign, ans_n: uint) { let inp = BigInt::from_biguint(inp_s, BigUint::from_uint(inp_n)); let ans = BigInt { sign: ans_s, data: BigUint::from_uint(ans_n)}; - assert!(inp == ans); + assert_eq!(inp, ans); } check(Plus, 1, Plus, 1); check(Plus, 0, Zero, 0); @@ -1640,7 +1661,7 @@ mod bigint_tests { if i == j { assert_eq!(ni.cmp(nj), Equal); assert_eq!(nj.cmp(ni), Equal); - assert!(ni == nj); + assert_eq!(ni, nj); assert!(!(ni != nj)); assert!(ni <= nj); assert!(ni >= nj); @@ -1751,7 +1772,7 @@ mod bigint_tests { assert!(c + (-b) == a); assert!(a + (-c) == (-b)); assert!(b + (-c) == (-a)); - assert!((-a) + (-b) == (-c)); + assert!((-a) + (-b) == (-c)) assert!(a + (-a) == Zero::zero()); } } @@ -1766,8 +1787,8 @@ mod bigint_tests { assert!(c - a == b); assert!(c - b == a); - assert!((-b) - a == (-c)); - assert!((-a) - b == (-c)); + assert!((-b) - a == (-c)) + assert!((-a) - b == (-c)) assert!(b - (-a) == c); assert!(a - (-b) == c); assert!((-c) - (-a) == (-b)); @@ -1845,7 +1866,7 @@ mod bigint_tests { fn check_sub(a: &BigInt, b: &BigInt, ans_d: &BigInt, ans_m: &BigInt) { let (d, m) = a.div_mod_floor(b); if !m.is_zero() { - assert!(m.sign == b.sign); + assert_eq!(m.sign, b.sign); } assert!(m.abs() <= b.abs()); assert!(*a == b * d + m); @@ -1896,7 +1917,7 @@ mod bigint_tests { fn check_sub(a: &BigInt, b: &BigInt, ans_q: &BigInt, ans_r: &BigInt) { let (q, r) = a.div_rem(b); if !r.is_zero() { - assert!(r.sign == a.sign); + assert_eq!(r.sign, a.sign); } assert!(r.abs() <= b.abs()); assert!(*a == b * q + r); @@ -1999,7 +2020,7 @@ mod bigint_tests { fn test_from_str_radix() { fn check(s: &str, ans: Option) { let ans = ans.map(|&n| IntConvertible::from_int::(n)); - assert!(FromStrRadix::from_str_radix(s, 10) == ans); + assert_eq!(FromStrRadix::from_str_radix(s, 10), ans); } check("10", Some(10)); check("1", Some(1)); @@ -2016,6 +2037,6 @@ mod bigint_tests { BigInt::new(Minus, ~[1, 1, 1])); assert!(-BigInt::new(Minus, ~[1, 1, 1]) == BigInt::new(Plus, ~[1, 1, 1])); - assert!(-Zero::zero::() == Zero::zero::()); + assert_eq!(-Zero::zero::(), Zero::zero::()); } } diff --git a/src/libstd/num/complex.rs b/src/libextra/num/complex.rs similarity index 98% rename from src/libstd/num/complex.rs rename to src/libextra/num/complex.rs index 41d2b4a101cd5..10bfe9409daa4 100644 --- a/src/libstd/num/complex.rs +++ b/src/libextra/num/complex.rs @@ -11,6 +11,8 @@ //! Complex numbers. +use core::prelude::*; + use core::num::{Zero,One,ToStrRadix}; // FIXME #1284: handle complex NaN & infinity etc. This @@ -23,7 +25,9 @@ use core::num::{Zero,One,ToStrRadix}; /// A complex number in Cartesian form. #[deriving(Eq,Clone)] pub struct Cmplx { + /// Real portion of the complex number re: T, + /// Imaginary portion of the complex number im: T } diff --git a/src/libstd/num/rational.rs b/src/libextra/num/rational.rs similarity index 98% rename from src/libstd/num/rational.rs rename to src/libextra/num/rational.rs index d57c642c5a29c..1a8ab75b3dd0d 100644 --- a/src/libstd/num/rational.rs +++ b/src/libextra/num/rational.rs @@ -8,15 +8,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - //! Rational numbers -use core::num::{Zero,One,ToStrRadix,FromStrRadix,Round}; +use core::prelude::*; + +use core::cmp; use core::from_str::FromStr; +use core::num::{Zero,One,ToStrRadix,FromStrRadix,Round}; +use core::str; +use core::vec; use super::bigint::BigInt; /// Represents the ratio between 2 numbers. #[deriving(Clone)] +#[allow(missing_doc)] pub struct Ratio { numer: T, denom: T @@ -44,7 +49,7 @@ impl Ratio { numer: numer, denom: denom } } - // Create a new Ratio. Fails if `denom == 0`. + /// Create a new Ratio. Fails if `denom == 0`. #[inline(always)] pub fn new(numer: T, denom: T) -> Ratio { if denom == Zero::zero() { @@ -282,6 +287,8 @@ impl #[cfg(test)] mod test { + use core::prelude::*; + use super::*; use core::num::{Zero,One,FromStrRadix,IntConvertible}; use core::from_str::FromStr; diff --git a/src/libstd/par.rs b/src/libextra/par.rs similarity index 94% rename from src/libstd/par.rs rename to src/libextra/par.rs index d1af484cb22bc..49696a5fa25c7 100644 --- a/src/libstd/par.rs +++ b/src/libextra/par.rs @@ -8,6 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + +use core::cast; +use core::ptr; +use core::sys; +use core::uint; +use core::vec; use future_spawn = future::spawn; /** @@ -59,7 +66,7 @@ fn map_slices( let slice : &[A] = cast::transmute(slice); info!("slice: %?", (base, slice.len(), end - base)); - assert!(slice.len() == end - base); + assert_eq!(slice.len(), end - base); f(base, slice) } }; @@ -70,7 +77,7 @@ fn map_slices( info!("tasks spawned"); info!("num_tasks: %?", (num_tasks, futures.len())); - assert!((num_tasks == futures.len())); + assert_eq!(num_tasks, futures.len()); let r = do vec::map_consume(futures) |ys| { let mut ys = ys; @@ -106,7 +113,7 @@ pub fn mapi( }); let r = vec::concat(slices); info!("%?", (r.len(), xs.len())); - assert!((r.len() == xs.len())); + assert_eq!(r.len(), xs.len()); r } diff --git a/src/libstd/priority_queue.rs b/src/libextra/priority_queue.rs similarity index 68% rename from src/libstd/priority_queue.rs rename to src/libextra/priority_queue.rs index 3c96a8e145d80..b58f90beb3122 100644 --- a/src/libstd/priority_queue.rs +++ b/src/libextra/priority_queue.rs @@ -10,10 +10,16 @@ //! A priority queue implemented with a binary heap +#[allow(missing_doc)]; + +use core::prelude::*; + use core::old_iter::BaseIter; +use core::unstable::intrinsics::{move_val_init, init}; use core::util::{replace, swap}; -use core::unstable::intrinsics::{init, move_val_init}; +use core::vec; +#[allow(missing_doc)] pub struct PriorityQueue { priv data: ~[T], } @@ -22,12 +28,6 @@ impl BaseIter for PriorityQueue { /// Visit all values in the underlying vector. /// /// The values are **not** visited in order. - #[cfg(stage0)] - fn each(&self, f: &fn(&T) -> bool) { self.data.each(f) } - /// Visit all values in the underlying vector. - /// - /// The values are **not** visited in order. - #[cfg(not(stage0))] fn each(&self, f: &fn(&T) -> bool) -> bool { self.data.each(f) } fn size_hint(&self) -> Option { self.data.size_hint() } @@ -46,26 +46,26 @@ impl Mutable for PriorityQueue { fn clear(&mut self) { self.data.truncate(0) } } -pub impl PriorityQueue { +impl PriorityQueue { /// Returns the greatest item in the queue - fails if empty - fn top<'a>(&'a self) -> &'a T { &self.data[0] } + pub fn top<'a>(&'a self) -> &'a T { &self.data[0] } /// Returns the greatest item in the queue - None if empty - fn maybe_top<'a>(&'a self) -> Option<&'a T> { + pub fn maybe_top<'a>(&'a self) -> Option<&'a T> { if self.is_empty() { None } else { Some(self.top()) } } /// Returns the number of elements the queue can hold without reallocating - fn capacity(&self) -> uint { vec::capacity(&self.data) } + pub fn capacity(&self) -> uint { vec::capacity(&self.data) } - fn reserve(&mut self, n: uint) { vec::reserve(&mut self.data, n) } + pub fn reserve(&mut self, n: uint) { vec::reserve(&mut self.data, n) } - fn reserve_at_least(&mut self, n: uint) { + pub fn reserve_at_least(&mut self, n: uint) { vec::reserve_at_least(&mut self.data, n) } /// Pop the greatest item from the queue - fails if empty - fn pop(&mut self) -> T { + pub fn pop(&mut self) -> T { let mut item = self.data.pop(); if !self.is_empty() { swap(&mut item, &mut self.data[0]); @@ -75,19 +75,19 @@ pub impl PriorityQueue { } /// Pop the greatest item from the queue - None if empty - fn maybe_pop(&mut self) -> Option { + pub fn maybe_pop(&mut self) -> Option { if self.is_empty() { None } else { Some(self.pop()) } } /// Push an item onto the queue - fn push(&mut self, item: T) { + pub fn push(&mut self, item: T) { self.data.push(item); let new_len = self.len() - 1; self.siftup(0, new_len); } /// Optimized version of a push followed by a pop - fn push_pop(&mut self, mut item: T) -> T { + pub fn push_pop(&mut self, mut item: T) -> T { if !self.is_empty() && self.data[0] > item { swap(&mut item, &mut self.data[0]); self.siftdown(0); @@ -96,18 +96,18 @@ pub impl PriorityQueue { } /// Optimized version of a pop followed by a push - fails if empty - fn replace(&mut self, mut item: T) -> T { + pub fn replace(&mut self, mut item: T) -> T { swap(&mut item, &mut self.data[0]); self.siftdown(0); item } /// Consume the PriorityQueue and return the underlying vector - fn to_vec(self) -> ~[T] { let PriorityQueue{data: v} = self; v } + pub fn to_vec(self) -> ~[T] { let PriorityQueue{data: v} = self; v } /// Consume the PriorityQueue and return a vector in sorted /// (ascending) order - fn to_sorted_vec(self) -> ~[T] { + pub fn to_sorted_vec(self) -> ~[T] { let mut q = self; let mut end = q.len(); while end > 1 { @@ -119,10 +119,10 @@ pub impl PriorityQueue { } /// Create an empty PriorityQueue - fn new() -> PriorityQueue { PriorityQueue{data: ~[],} } + pub fn new() -> PriorityQueue { PriorityQueue{data: ~[],} } /// Create a PriorityQueue from a vector (heapify) - fn from_vec(xs: ~[T]) -> PriorityQueue { + pub fn from_vec(xs: ~[T]) -> PriorityQueue { let mut q = PriorityQueue{data: xs,}; let mut n = q.len() / 2; while n > 0 { @@ -137,8 +137,7 @@ pub impl PriorityQueue { // zeroed element), shift along the others and move it back into the // vector over the junk element. This reduces the constant factor // compared to using swaps, which involves twice as many moves. - - priv fn siftup(&mut self, start: uint, mut pos: uint) { + fn siftup(&mut self, start: uint, mut pos: uint) { unsafe { let new = replace(&mut self.data[pos], init()); @@ -156,7 +155,7 @@ pub impl PriorityQueue { } } - priv fn siftdown_range(&mut self, mut pos: uint, end: uint) { + fn siftdown_range(&mut self, mut pos: uint, end: uint) { unsafe { let start = pos; let new = replace(&mut self.data[pos], init()); @@ -178,7 +177,7 @@ pub impl PriorityQueue { } } - priv fn siftdown(&mut self, pos: uint) { + fn siftdown(&mut self, pos: uint) { let len = self.len(); self.siftdown_range(pos, len); } @@ -188,95 +187,95 @@ pub impl PriorityQueue { mod tests { use sort::merge_sort; use core::cmp::le; - use priority_queue::PriorityQueue::{from_vec, new}; + use priority_queue::PriorityQueue; #[test] fn test_top_and_pop() { let data = ~[2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]; let mut sorted = merge_sort(data, le); - let mut heap = from_vec(data); + let mut heap = PriorityQueue::from_vec(data); while !heap.is_empty() { - assert!(heap.top() == sorted.last()); - assert!(heap.pop() == sorted.pop()); + assert_eq!(heap.top(), sorted.last()); + assert_eq!(heap.pop(), sorted.pop()); } } #[test] fn test_push() { - let mut heap = from_vec(~[2, 4, 9]); - assert!(heap.len() == 3); + let mut heap = PriorityQueue::from_vec(~[2, 4, 9]); + assert_eq!(heap.len(), 3); assert!(*heap.top() == 9); heap.push(11); - assert!(heap.len() == 4); + assert_eq!(heap.len(), 4); assert!(*heap.top() == 11); heap.push(5); - assert!(heap.len() == 5); + assert_eq!(heap.len(), 5); assert!(*heap.top() == 11); heap.push(27); - assert!(heap.len() == 6); + assert_eq!(heap.len(), 6); assert!(*heap.top() == 27); heap.push(3); - assert!(heap.len() == 7); + assert_eq!(heap.len(), 7); assert!(*heap.top() == 27); heap.push(103); - assert!(heap.len() == 8); + assert_eq!(heap.len(), 8); assert!(*heap.top() == 103); } #[test] fn test_push_unique() { - let mut heap = from_vec(~[~2, ~4, ~9]); - assert!(heap.len() == 3); + let mut heap = PriorityQueue::from_vec(~[~2, ~4, ~9]); + assert_eq!(heap.len(), 3); assert!(*heap.top() == ~9); heap.push(~11); - assert!(heap.len() == 4); + assert_eq!(heap.len(), 4); assert!(*heap.top() == ~11); heap.push(~5); - assert!(heap.len() == 5); + assert_eq!(heap.len(), 5); assert!(*heap.top() == ~11); heap.push(~27); - assert!(heap.len() == 6); + assert_eq!(heap.len(), 6); assert!(*heap.top() == ~27); heap.push(~3); - assert!(heap.len() == 7); + assert_eq!(heap.len(), 7); assert!(*heap.top() == ~27); heap.push(~103); - assert!(heap.len() == 8); + assert_eq!(heap.len(), 8); assert!(*heap.top() == ~103); } #[test] fn test_push_pop() { - let mut heap = from_vec(~[5, 5, 2, 1, 3]); - assert!(heap.len() == 5); - assert!(heap.push_pop(6) == 6); - assert!(heap.len() == 5); - assert!(heap.push_pop(0) == 5); - assert!(heap.len() == 5); - assert!(heap.push_pop(4) == 5); - assert!(heap.len() == 5); - assert!(heap.push_pop(1) == 4); - assert!(heap.len() == 5); + let mut heap = PriorityQueue::from_vec(~[5, 5, 2, 1, 3]); + assert_eq!(heap.len(), 5); + assert_eq!(heap.push_pop(6), 6); + assert_eq!(heap.len(), 5); + assert_eq!(heap.push_pop(0), 5); + assert_eq!(heap.len(), 5); + assert_eq!(heap.push_pop(4), 5); + assert_eq!(heap.len(), 5); + assert_eq!(heap.push_pop(1), 4); + assert_eq!(heap.len(), 5); } #[test] fn test_replace() { - let mut heap = from_vec(~[5, 5, 2, 1, 3]); - assert!(heap.len() == 5); - assert!(heap.replace(6) == 5); - assert!(heap.len() == 5); - assert!(heap.replace(0) == 6); - assert!(heap.len() == 5); - assert!(heap.replace(4) == 5); - assert!(heap.len() == 5); - assert!(heap.replace(1) == 4); - assert!(heap.len() == 5); + let mut heap = PriorityQueue::from_vec(~[5, 5, 2, 1, 3]); + assert_eq!(heap.len(), 5); + assert_eq!(heap.replace(6), 5); + assert_eq!(heap.len(), 5); + assert_eq!(heap.replace(0), 6); + assert_eq!(heap.len(), 5); + assert_eq!(heap.replace(4), 5); + assert_eq!(heap.len(), 5); + assert_eq!(heap.replace(1), 4); + assert_eq!(heap.len(), 5); } fn check_to_vec(data: ~[int]) { - let heap = from_vec(copy data); - assert!(merge_sort((copy heap).to_vec(), le) == merge_sort(data, le)); - assert!(heap.to_sorted_vec() == merge_sort(data, le)); + let heap = PriorityQueue::from_vec(copy data); + assert_eq!(merge_sort((copy heap).to_vec(), le), merge_sort(data, le)); + assert_eq!(heap.to_sorted_vec(), merge_sort(data, le)); } #[test] @@ -299,27 +298,27 @@ mod tests { #[test] #[should_fail] #[ignore(cfg(windows))] - fn test_empty_pop() { let mut heap = new::(); heap.pop(); } + fn test_empty_pop() { let mut heap = PriorityQueue::new::(); heap.pop(); } #[test] fn test_empty_maybe_pop() { - let mut heap = new::(); + let mut heap = PriorityQueue::new::(); assert!(heap.maybe_pop().is_none()); } #[test] #[should_fail] #[ignore(cfg(windows))] - fn test_empty_top() { let empty = new::(); empty.top(); } + fn test_empty_top() { let empty = PriorityQueue::new::(); empty.top(); } #[test] fn test_empty_maybe_top() { - let empty = new::(); + let empty = PriorityQueue::new::(); assert!(empty.maybe_top().is_none()); } #[test] #[should_fail] #[ignore(cfg(windows))] - fn test_empty_replace() { let mut heap = new(); heap.replace(5); } + fn test_empty_replace() { let mut heap = PriorityQueue::new(); heap.replace(5); } } diff --git a/src/libstd/rc.rs b/src/libextra/rc.rs similarity index 87% rename from src/libstd/rc.rs rename to src/libextra/rc.rs index 46f50eafec160..96ad629ea8374 100644 --- a/src/libstd/rc.rs +++ b/src/libextra/rc.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[allow(missing_doc)]; + /** Task-local reference counted smart pointers Task-local reference counted smart pointers are an alternative to managed boxes with deterministic @@ -19,9 +21,13 @@ cycle cannot be created with `Rc` because there is no way to modify it after */ +use core::prelude::*; + +use core::cast; use core::libc::{c_void, size_t, malloc, free}; +use core::ptr; +use core::sys; use core::unstable::intrinsics; -use core::util; struct RcBox { value: T, @@ -34,7 +40,7 @@ pub struct Rc { priv ptr: *mut RcBox, } -priv impl Rc { +impl Rc { unsafe fn new(value: T) -> Rc { let ptr = malloc(sys::size_of::>() as size_t) as *mut RcBox; assert!(!ptr::is_null(ptr)); @@ -53,42 +59,26 @@ pub fn rc_from_const(value: T) -> Rc { unsafe { Rc::new(value) } } -pub impl Rc { +impl Rc { #[inline(always)] - fn borrow<'r>(&'r self) -> &'r T { + pub fn borrow<'r>(&'r self) -> &'r T { unsafe { cast::copy_lifetime(self, &(*self.ptr).value) } } } #[unsafe_destructor] -#[cfg(not(stage0))] -impl Drop for Rc { - fn finalize(&self) { - unsafe { - (*self.ptr).count -= 1; - if (*self.ptr).count == 0 { - util::replace_ptr(self.ptr, intrinsics::uninit()); - free(self.ptr as *c_void) - } - } - } -} - -#[unsafe_destructor] -#[cfg(stage0)] impl Drop for Rc { fn finalize(&self) { unsafe { (*self.ptr).count -= 1; if (*self.ptr).count == 0 { - util::replace_ptr(self.ptr, intrinsics::init()); + ptr::replace_ptr(self.ptr, intrinsics::uninit()); free(self.ptr as *c_void) } } } } - impl Clone for Rc { /// Return a shallow copy of the reference counted pointer. #[inline] @@ -115,7 +105,7 @@ mod test_rc { #[test] fn test_clone() { - let x = rc_from_owned(Cell(5)); + let x = rc_from_owned(Cell::new(5)); let y = x.clone(); do x.borrow().with_mut_ref |inner| { *inner = 20; @@ -125,7 +115,7 @@ mod test_rc { #[test] fn test_deep_clone() { - let x = rc_from_owned(Cell(5)); + let x = rc_from_owned(Cell::new(5)); let y = x.deep_clone(); do x.borrow().with_mut_ref |inner| { *inner = 20; @@ -157,7 +147,6 @@ mod test_rc { #[abi = "rust-intrinsic"] extern "rust-intrinsic" { fn init() -> T; - #[cfg(not(stage0))] fn uninit() -> T; } @@ -181,7 +170,7 @@ pub struct RcMut { priv ptr: *mut RcMutBox, } -priv impl RcMut { +impl RcMut { unsafe fn new(value: T) -> RcMut { let ptr = malloc(sys::size_of::>() as size_t) as *mut RcMutBox; assert!(!ptr::is_null(ptr)); @@ -200,10 +189,10 @@ pub fn rc_mut_from_const(value: T) -> RcMut { unsafe { RcMut::new(value) } } -pub impl RcMut { +impl RcMut { /// Fails if there is already a mutable borrow of the box #[inline] - fn with_borrow(&self, f: &fn(&T) -> U) -> U { + pub fn with_borrow(&self, f: &fn(&T) -> U) -> U { unsafe { assert!((*self.ptr).borrow != Mutable); let previous = (*self.ptr).borrow; @@ -216,9 +205,9 @@ pub impl RcMut { /// Fails if there is already a mutable or immutable borrow of the box #[inline] - fn with_mut_borrow(&self, f: &fn(&mut T) -> U) -> U { + pub fn with_mut_borrow(&self, f: &fn(&mut T) -> U) -> U { unsafe { - assert!((*self.ptr).borrow == Nothing); + assert_eq!((*self.ptr).borrow, Nothing); (*self.ptr).borrow = Mutable; let res = f(&mut (*self.ptr).value); (*self.ptr).borrow = Nothing; @@ -228,27 +217,12 @@ pub impl RcMut { } #[unsafe_destructor] -#[cfg(not(stage0))] -impl Drop for RcMut { - fn finalize(&self) { - unsafe { - (*self.ptr).count -= 1; - if (*self.ptr).count == 0 { - util::replace_ptr(self.ptr, uninit()); - free(self.ptr as *c_void) - } - } - } -} - -#[unsafe_destructor] -#[cfg(stage0)] impl Drop for RcMut { fn finalize(&self) { unsafe { (*self.ptr).count -= 1; if (*self.ptr).count == 0 { - util::replace_ptr(self.ptr, init()); + ptr::replace_ptr(self.ptr, uninit()); free(self.ptr as *c_void) } } diff --git a/src/libstd/rl.rs b/src/libextra/rl.rs similarity index 97% rename from src/libstd/rl.rs rename to src/libextra/rl.rs index d15a8fc0136d4..040adcc443d92 100644 --- a/src/libstd/rl.rs +++ b/src/libextra/rl.rs @@ -11,7 +11,11 @@ // FIXME #3921. This is unsafe because linenoise uses global mutable // state without mutexes. +use core::prelude::*; + use core::libc::{c_char, c_int}; +use core::local_data; +use core::str; pub mod rustrt { use core::libc::{c_char, c_int}; diff --git a/src/libstd/rope.rs b/src/libextra/rope.rs similarity index 98% rename from src/libstd/rope.rs rename to src/libextra/rope.rs index 9afa7262ce473..413a498a20ec5 100644 --- a/src/libstd/rope.rs +++ b/src/libextra/rope.rs @@ -33,6 +33,14 @@ * * access to a character by index is logarithmic (linear in strings); */ +#[allow(missing_doc)]; + +use core::prelude::*; + +use core::str; +use core::uint; +use core::vec; + /// The type of ropes. pub type Rope = node::Root; @@ -106,7 +114,7 @@ Section: Adding things to a rope * * this function executes in near-constant time */ pub fn append_char(rope: Rope, char: char) -> Rope { - return append_str(rope, @str::from_chars(~[char])); + return append_str(rope, @str::from_chars([char])); } /** @@ -127,7 +135,7 @@ pub fn append_str(rope: Rope, str: @~str) -> Rope { * * this function executes in near-constant time */ pub fn prepend_char(rope: Rope, char: char) -> Rope { - return prepend_str(rope, @str::from_chars(~[char])); + return prepend_str(rope, @str::from_chars([char])); } /** @@ -439,8 +447,9 @@ pub fn loop_leaves(rope: Rope, it: &fn(node::Leaf) -> bool) -> bool{ pub mod iterator { pub mod leaf { - use rope::{Rope, node}; + use core::prelude::*; + use rope::{Rope, node}; pub fn start(rope: Rope) -> node::leaf_iterator::T { match (rope) { @@ -453,8 +462,9 @@ pub mod iterator { } } pub mod char { - use rope::{Rope, node}; + use core::prelude::*; + use rope::{Rope, node}; pub fn start(rope: Rope) -> node::char_iterator::T { match (rope) { @@ -548,8 +558,15 @@ pub fn char_at(rope: Rope, pos: uint) -> char { Section: Implementation */ pub mod node { + use core::prelude::*; + use rope::node; + use core::cast; + use core::str; + use core::uint; + use core::vec; + /// Implementation of type `rope` pub enum Root { /// An empty rope @@ -1127,8 +1144,12 @@ pub mod node { } pub mod leaf_iterator { + use core::prelude::*; + use rope::node::{Concat, Leaf, Node, height}; + use core::vec; + pub struct T { stack: ~[@Node], stackpos: int, @@ -1166,6 +1187,10 @@ pub mod node { } pub mod char_iterator { + use core::prelude::*; + + use core::str; + use rope::node::{Leaf, Node}; use rope::node::leaf_iterator; @@ -1248,9 +1273,14 @@ pub mod node { #[cfg(test)] mod tests { - use rope::*; use core::prelude::*; + use rope::*; + + use core::str; + use core::uint; + use core::vec; + //Utility function, used for sanity check fn rope_to_string(r: Rope) -> ~str { match (r) { @@ -1281,8 +1311,8 @@ mod tests { #[test] fn trivial() { - assert!(char_len(empty()) == 0u); - assert!(byte_len(empty()) == 0u); + assert_eq!(char_len(empty()), 0u); + assert_eq!(byte_len(empty()), 0u); } #[test] @@ -1290,7 +1320,7 @@ mod tests { let sample = @~"0123456789ABCDE"; let r = of_str(sample); - assert!(char_len(r) == str::char_len(*sample)); + assert_eq!(char_len(r), str::char_len(*sample)); assert!(rope_to_string(r) == *sample); } @@ -1352,7 +1382,7 @@ mod tests { } } - assert!(len == str::char_len(*sample)); + assert_eq!(len, str::char_len(*sample)); } #[test] @@ -1375,7 +1405,7 @@ mod tests { assert!(eq(r1, r2)); let r3 = bal(r2); - assert!(char_len(r1) == char_len(r3)); + assert_eq!(char_len(r1), char_len(r3)); assert!(eq(r1, r3)); } diff --git a/src/libstd/semver.rs b/src/libextra/semver.rs similarity index 95% rename from src/libstd/semver.rs rename to src/libextra/semver.rs index f6d1b1ba2ecd4..494f0c8ea815f 100644 --- a/src/libstd/semver.rs +++ b/src/libextra/semver.rs @@ -10,6 +10,10 @@ //! Semver parsing and logic +#[allow(missing_doc)]; + +use core::prelude::*; + use core::char; use core::cmp; use core::io::{ReaderUtil}; @@ -239,16 +243,16 @@ pub fn parse(s: &str) -> Option { #[test] fn test_parse() { - assert!(parse("") == None); - assert!(parse(" ") == None); - assert!(parse("1") == None); - assert!(parse("1.2") == None); - assert!(parse("1.2") == None); - assert!(parse("1") == None); - assert!(parse("1.2") == None); - assert!(parse("1.2.3-") == None); - assert!(parse("a.b.c") == None); - assert!(parse("1.2.3 abc") == None); + assert_eq!(parse(""), None); + assert_eq!(parse(" "), None); + assert_eq!(parse("1"), None); + assert_eq!(parse("1.2"), None); + assert_eq!(parse("1.2"), None); + assert_eq!(parse("1"), None); + assert_eq!(parse("1.2"), None); + assert_eq!(parse("1.2.3-"), None); + assert_eq!(parse("a.b.c"), None); + assert_eq!(parse("1.2.3 abc"), None); assert!(parse("1.2.3") == Some(Version { major: 1u, @@ -320,8 +324,8 @@ fn test_parse() { #[test] fn test_eq() { - assert!(parse("1.2.3") == parse("1.2.3")); - assert!(parse("1.2.3-alpha1") == parse("1.2.3-alpha1")); + assert_eq!(parse("1.2.3"), parse("1.2.3")); + assert_eq!(parse("1.2.3-alpha1"), parse("1.2.3-alpha1")); } #[test] diff --git a/src/libstd/serialize.rs b/src/libextra/serialize.rs similarity index 98% rename from src/libstd/serialize.rs rename to src/libextra/serialize.rs index a5d2604b6f6db..a54db07261a6a 100644 --- a/src/libstd/serialize.rs +++ b/src/libextra/serialize.rs @@ -14,10 +14,16 @@ Core encoding and decoding interfaces. */ +#[allow(missing_doc)]; #[forbid(non_camel_case_types)]; +use core::prelude::*; + +use core::at_vec; use core::hashmap::{HashMap, HashSet}; use core::trie::{TrieMap, TrieSet}; +use core::uint; +use core::vec; use deque::Deque; use dlist::DList; use treemap::{TreeMap, TreeSet}; @@ -369,6 +375,18 @@ impl Decodable for bool { } } +impl Encodable for char { + fn encode(&self, s: &mut S) { + s.emit_char(*self) + } +} + +impl Decodable for char { + fn decode(d: &mut D) -> char { + d.read_char() + } +} + impl Encodable for () { fn encode(&self, s: &mut S) { s.emit_nil() @@ -500,7 +518,7 @@ impl,T1:Encodable> Encodable for (T0, T1) { impl,T1:Decodable> Decodable for (T0, T1) { fn decode(d: &mut D) -> (T0, T1) { do d.read_seq |d, len| { - assert!(len == 2); + assert_eq!(len, 2); ( d.read_seq_elt(0, |d| Decodable::decode(d)), d.read_seq_elt(1, |d| Decodable::decode(d)) @@ -536,7 +554,7 @@ impl< > Decodable for (T0, T1, T2) { fn decode(d: &mut D) -> (T0, T1, T2) { do d.read_seq |d, len| { - assert!(len == 3); + assert_eq!(len, 3); ( d.read_seq_elt(0, |d| Decodable::decode(d)), d.read_seq_elt(1, |d| Decodable::decode(d)), @@ -576,7 +594,7 @@ impl< > Decodable for (T0, T1, T2, T3) { fn decode(d: &mut D) -> (T0, T1, T2, T3) { do d.read_seq |d, len| { - assert!(len == 4); + assert_eq!(len, 4); ( d.read_seq_elt(0, |d| Decodable::decode(d)), d.read_seq_elt(1, |d| Decodable::decode(d)), @@ -620,7 +638,7 @@ impl< > Decodable for (T0, T1, T2, T3, T4) { fn decode(d: &mut D) -> (T0, T1, T2, T3, T4) { do d.read_seq |d, len| { - assert!(len == 5); + assert_eq!(len, 5); ( d.read_seq_elt(0, |d| Decodable::decode(d)), d.read_seq_elt(1, |d| Decodable::decode(d)), diff --git a/src/libstd/sha1.rs b/src/libextra/sha1.rs similarity index 94% rename from src/libstd/sha1.rs rename to src/libextra/sha1.rs index 6d8bf20d837ca..80b4ab02e5fd5 100644 --- a/src/libstd/sha1.rs +++ b/src/libextra/sha1.rs @@ -22,6 +22,8 @@ * the `reset` method. */ +use core::prelude::*; + use core::str; use core::uint; use core::vec; @@ -90,8 +92,8 @@ pub fn sha1() -> @Sha1 { } } fn process_msg_block(st: &mut Sha1State) { - assert!(st.h.len() == digest_buf_len); - assert!(vec::uniq_len(st.work_buf) == work_buf_len); + assert_eq!(st.h.len(), digest_buf_len); + assert_eq!(vec::uniq_len(st.work_buf), work_buf_len); let mut t: int; // Loop counter let w = st.work_buf; @@ -177,7 +179,7 @@ pub fn sha1() -> @Sha1 { let b = (hpart >> 16u32 & 0xFFu32) as u8; let c = (hpart >> 8u32 & 0xFFu32) as u8; let d = (hpart & 0xFFu32) as u8; - rs = vec::append(copy rs, ~[a, b, c, d]); + rs = vec::append(copy rs, [a, b, c, d]); } return rs; } @@ -192,7 +194,7 @@ pub fn sha1() -> @Sha1 { * can be assumed that the message digest has been computed. */ fn pad_msg(st: &mut Sha1State) { - assert!((vec::len((*st).msg_block) == msg_block_len)); + assert_eq!(vec::len((*st).msg_block), msg_block_len); /* * Check to see if the current message block is too small to hold @@ -230,7 +232,7 @@ pub fn sha1() -> @Sha1 { impl Sha1 for Sha1State { fn reset(&mut self) { - assert!(self.h.len() == digest_buf_len); + assert_eq!(self.h.len(), digest_buf_len); self.len_low = 0u32; self.len_high = 0u32; self.msg_block_idx = 0u; @@ -293,7 +295,7 @@ mod tests { let mut i = 0; let mut rs = ~""; while i < 100000 { - str::push_str(&mut rs, ~"aaaaaaaaaa"); + rs.push_str("aaaaaaaaaa"); i += 1; } return rs; @@ -315,7 +317,7 @@ mod tests { Test { input: ~"abcdbcdecdefdefgefghfghighij" + - ~"hijkijkljklmklmnlmnomnopnopq", + "hijkijkljklmklmnlmnomnopnopq", output: ~[ 0x84u8, 0x98u8, 0x3Eu8, 0x44u8, 0x1Cu8, 0x3Bu8, 0xD2u8, 0x6Eu8, @@ -365,13 +367,13 @@ mod tests { ]; let tests = fips_180_1_tests + wikipedia_tests; fn check_vec_eq(v0: ~[u8], v1: ~[u8]) { - assert!((vec::len::(v0) == vec::len::(v1))); + assert_eq!(vec::len::(v0), vec::len::(v1)); let len = vec::len::(v0); let mut i = 0u; while i < len { let a = v0[i]; let b = v1[i]; - assert!((a == b)); + assert_eq!(a, b); i += 1u; } } @@ -384,8 +386,8 @@ mod tests { check_vec_eq(copy t.output, out); let out_str = sh.result_str(); - assert!((out_str.len() == 40)); - assert!((out_str == t.output_str)); + assert_eq!(out_str.len(), 40); + assert!(out_str == t.output_str); sh.reset(); } @@ -397,16 +399,15 @@ mod tests { let mut left = len; while left > 0u { let take = (left + 1u) / 2u; - sh.input_str(str::slice(t.input, len - left, - take + len - left).to_owned()); + sh.input_str(t.input.slice(len - left, take + len - left)); left = left - take; } let out = sh.result(); check_vec_eq(copy t.output, out); let out_str = sh.result_str(); - assert!((out_str.len() == 40)); - assert!((out_str == t.output_str)); + assert_eq!(out_str.len(), 40); + assert!(out_str == t.output_str); sh.reset(); } diff --git a/src/libextra/smallintmap.rs b/src/libextra/smallintmap.rs new file mode 100644 index 0000000000000..7f566bc16e732 --- /dev/null +++ b/src/libextra/smallintmap.rs @@ -0,0 +1,552 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/*! + * A simple map based on a vector for small integer keys. Space requirements + * are O(highest integer key). + */ + +#[allow(missing_doc)]; + +use core::prelude::*; + +use core::cmp; +use core::container::{Container, Mutable, Map, Set}; +use core::old_iter::BaseIter; +use core::old_iter; +use core::uint; +use core::util::replace; +use core::vec; + +#[allow(missing_doc)] +pub struct SmallIntMap { + priv v: ~[Option], +} + +impl Container for SmallIntMap { + /// Return the number of elements in the map + fn len(&const self) -> uint { + let mut sz = 0; + for uint::range(0, vec::uniq_len(&const self.v)) |i| { + match self.v[i] { + Some(_) => sz += 1, + None => {} + } + } + sz + } + + /// Return true if the map contains no elements + fn is_empty(&const self) -> bool { self.len() == 0 } +} + +impl Mutable for SmallIntMap { + /// Clear the map, removing all key-value pairs. + fn clear(&mut self) { self.v.clear() } +} + +impl Map for SmallIntMap { + /// Return true if the map contains a value for the specified key + fn contains_key(&self, key: &uint) -> bool { + self.find(key).is_some() + } + + /// Visit all key-value pairs in order + fn each<'a>(&'a self, it: &fn(&uint, &'a V) -> bool) -> bool { + for uint::range(0, self.v.len()) |i| { + match self.v[i] { + Some(ref elt) => if !it(&i, elt) { return false; }, + None => () + } + } + return true; + } + + /// Visit all keys in order + fn each_key(&self, blk: &fn(key: &uint) -> bool) -> bool { + self.each(|k, _| blk(k)) + } + + /// Visit all values in order + fn each_value<'a>(&'a self, blk: &fn(value: &'a V) -> bool) -> bool { + self.each(|_, v| blk(v)) + } + + /// Iterate over the map and mutate the contained values + fn mutate_values(&mut self, it: &fn(&uint, &mut V) -> bool) -> bool { + for uint::range(0, self.v.len()) |i| { + match self.v[i] { + Some(ref mut elt) => if !it(&i, elt) { return false; }, + None => () + } + } + return true; + } + + /// Return a reference to the value corresponding to the key + fn find<'a>(&'a self, key: &uint) -> Option<&'a V> { + if *key < self.v.len() { + match self.v[*key] { + Some(ref value) => Some(value), + None => None + } + } else { + None + } + } + + /// Return a mutable reference to the value corresponding to the key + fn find_mut<'a>(&'a mut self, key: &uint) -> Option<&'a mut V> { + if *key < self.v.len() { + match self.v[*key] { + Some(ref mut value) => Some(value), + None => None + } + } else { + None + } + } + + /// Insert a key-value pair into the map. An existing value for a + /// key is replaced by the new value. Return true if the key did + /// not already exist in the map. + fn insert(&mut self, key: uint, value: V) -> bool { + let exists = self.contains_key(&key); + let len = self.v.len(); + if len <= key { + vec::grow_fn(&mut self.v, key - len + 1, |_| None); + } + self.v[key] = Some(value); + !exists + } + + /// Remove a key-value pair from the map. Return true if the key + /// was present in the map, otherwise false. + fn remove(&mut self, key: &uint) -> bool { + self.pop(key).is_some() + } + + /// Insert a key-value pair from the map. If the key already had a value + /// present in the map, that value is returned. Otherwise None is returned. + fn swap(&mut self, key: uint, value: V) -> Option { + match self.find_mut(&key) { + Some(loc) => { return Some(replace(loc, value)); } + None => () + } + self.insert(key, value); + return None; + } + + /// Removes a key from the map, returning the value at the key if the key + /// was previously in the map. + fn pop(&mut self, key: &uint) -> Option { + if *key >= self.v.len() { + return None; + } + replace(&mut self.v[*key], None) + } +} + +impl SmallIntMap { + /// Create an empty SmallIntMap + pub fn new() -> SmallIntMap { SmallIntMap{v: ~[]} } + + /// Visit all key-value pairs in reverse order + pub fn each_reverse<'a>(&'a self, it: &fn(uint, &'a V) -> bool) -> bool { + for uint::range_rev(self.v.len(), 0) |i| { + match self.v[i - 1] { + Some(ref elt) => if !it(i - 1, elt) { return false; }, + None => () + } + } + return true; + } + + pub fn get<'a>(&'a self, key: &uint) -> &'a V { + self.find(key).expect("key not present") + } +} + +impl SmallIntMap { + pub fn update_with_key(&mut self, key: uint, val: V, + ff: &fn(uint, V, V) -> V) -> bool { + let new_val = match self.find(&key) { + None => val, + Some(orig) => ff(key, *orig, val) + }; + self.insert(key, new_val) + } + + pub fn update(&mut self, key: uint, newval: V, ff: &fn(V, V) -> V) + -> bool { + self.update_with_key(key, newval, |_k, v, v1| ff(v,v1)) + } +} + +/// A set implemented on top of the SmallIntMap type. This set is always a set +/// of integers, and the space requirements are on the order of the highest +/// valued integer in the set. +pub struct SmallIntSet { + priv map: SmallIntMap<()> +} + +impl Container for SmallIntSet { + /// Return the number of elements in the map + fn len(&const self) -> uint { + self.map.len() + } + + /// Return true if the map contains no elements + fn is_empty(&const self) -> bool { self.len() == 0 } +} + +impl Mutable for SmallIntSet { + /// Clear the map, removing all key-value pairs. + fn clear(&mut self) { self.map.clear() } +} + +impl BaseIter for SmallIntSet { + /// Visit all values in order + fn each(&self, f: &fn(&uint) -> bool) -> bool { self.map.each_key(f) } + fn size_hint(&self) -> Option { Some(self.len()) } +} + +impl Set for SmallIntSet { + /// Return true if the set contains a value + fn contains(&self, value: &uint) -> bool { self.map.contains_key(value) } + + /// Add a value to the set. Return true if the value was not already + /// present in the set. + fn insert(&mut self, value: uint) -> bool { self.map.insert(value, ()) } + + /// Remove a value from the set. Return true if the value was + /// present in the set. + fn remove(&mut self, value: &uint) -> bool { self.map.remove(value) } + + /// Return true if the set has no elements in common with `other`. + /// This is equivalent to checking for an empty uintersection. + fn is_disjoint(&self, other: &SmallIntSet) -> bool { + old_iter::all(self, |v| !other.contains(v)) + } + + /// Return true if the set is a subset of another + fn is_subset(&self, other: &SmallIntSet) -> bool { + old_iter::all(self, |v| other.contains(v)) + } + + /// Return true if the set is a superset of another + fn is_superset(&self, other: &SmallIntSet) -> bool { + other.is_subset(self) + } + + /// Visit the values representing the difference + fn difference(&self, other: &SmallIntSet, f: &fn(&uint) -> bool) -> bool { + self.each(|v| other.contains(v) || f(v)) + } + + /// Visit the values representing the symmetric difference + fn symmetric_difference(&self, + other: &SmallIntSet, + f: &fn(&uint) -> bool) -> bool { + let len = cmp::max(self.map.v.len() ,other.map.v.len()); + + for uint::range(0, len) |i| { + if self.contains(&i) ^ other.contains(&i) { + if !f(&i) { return false; } + } + } + return true; + } + + /// Visit the values representing the uintersection + fn intersection(&self, other: &SmallIntSet, f: &fn(&uint) -> bool) -> bool { + self.each(|v| !other.contains(v) || f(v)) + } + + /// Visit the values representing the union + fn union(&self, other: &SmallIntSet, f: &fn(&uint) -> bool) -> bool { + let len = cmp::max(self.map.v.len() ,other.map.v.len()); + + for uint::range(0, len) |i| { + if self.contains(&i) || other.contains(&i) { + if !f(&i) { return false; } + } + } + return true; + } +} + +impl SmallIntSet { + /// Create an empty SmallIntSet + pub fn new() -> SmallIntSet { SmallIntSet{map: SmallIntMap::new()} } +} + +#[cfg(test)] +mod tests { + use core::prelude::*; + + use super::SmallIntMap; + + use core::local_data; + use core::rand; + use core::uint; + use core::vec; + + #[test] + fn test_find_mut() { + let mut m = SmallIntMap::new(); + assert!(m.insert(1, 12)); + assert!(m.insert(2, 8)); + assert!(m.insert(5, 14)); + let new = 100; + match m.find_mut(&5) { + None => fail!(), Some(x) => *x = new + } + assert_eq!(m.find(&5), Some(&new)); + } + + #[test] + fn test_len() { + let mut map = SmallIntMap::new(); + assert_eq!(map.len(), 0); + assert!(map.is_empty()); + assert!(map.insert(5, 20)); + assert_eq!(map.len(), 1); + assert!(!map.is_empty()); + assert!(map.insert(11, 12)); + assert_eq!(map.len(), 2); + assert!(!map.is_empty()); + assert!(map.insert(14, 22)); + assert_eq!(map.len(), 3); + assert!(!map.is_empty()); + } + + #[test] + fn test_clear() { + let mut map = SmallIntMap::new(); + assert!(map.insert(5, 20)); + assert!(map.insert(11, 12)); + assert!(map.insert(14, 22)); + map.clear(); + assert!(map.is_empty()); + assert!(map.find(&5).is_none()); + assert!(map.find(&11).is_none()); + assert!(map.find(&14).is_none()); + } + + #[test] + fn test_insert_with_key() { + let mut map = SmallIntMap::new(); + + // given a new key, initialize it with this new count, given + // given an existing key, add more to its count + fn addMoreToCount(_k: uint, v0: uint, v1: uint) -> uint { + v0 + v1 + } + + fn addMoreToCount_simple(v0: uint, v1: uint) -> uint { + v0 + v1 + } + + // count integers + map.update(3, 1, addMoreToCount_simple); + map.update_with_key(9, 1, addMoreToCount); + map.update(3, 7, addMoreToCount_simple); + map.update_with_key(5, 3, addMoreToCount); + map.update_with_key(3, 2, addMoreToCount); + + // check the total counts + assert_eq!(map.find(&3).get(), &10); + assert_eq!(map.find(&5).get(), &3); + assert_eq!(map.find(&9).get(), &1); + + // sadly, no sevens were counted + assert!(map.find(&7).is_none()); + } + + #[test] + fn test_swap() { + let mut m = SmallIntMap::new(); + assert_eq!(m.swap(1, 2), None); + assert_eq!(m.swap(1, 3), Some(2)); + assert_eq!(m.swap(1, 4), Some(3)); + } + + #[test] + fn test_pop() { + let mut m = SmallIntMap::new(); + m.insert(1, 2); + assert_eq!(m.pop(&1), Some(2)); + assert_eq!(m.pop(&1), None); + } +} + +#[cfg(test)] +mod test_set { + use core::prelude::*; + + use super::SmallIntSet; + + use core::vec; + + #[test] + fn test_disjoint() { + let mut xs = SmallIntSet::new(); + let mut ys = SmallIntSet::new(); + assert!(xs.is_disjoint(&ys)); + assert!(ys.is_disjoint(&xs)); + assert!(xs.insert(5)); + assert!(ys.insert(11)); + assert!(xs.is_disjoint(&ys)); + assert!(ys.is_disjoint(&xs)); + assert!(xs.insert(7)); + assert!(xs.insert(19)); + assert!(xs.insert(4)); + assert!(ys.insert(2)); + assert!(xs.is_disjoint(&ys)); + assert!(ys.is_disjoint(&xs)); + assert!(ys.insert(7)); + assert!(!xs.is_disjoint(&ys)); + assert!(!ys.is_disjoint(&xs)); + } + + #[test] + fn test_subset_and_superset() { + let mut a = SmallIntSet::new(); + assert!(a.insert(0)); + assert!(a.insert(5)); + assert!(a.insert(11)); + assert!(a.insert(7)); + + let mut b = SmallIntSet::new(); + assert!(b.insert(0)); + assert!(b.insert(7)); + assert!(b.insert(19)); + assert!(b.insert(250)); + assert!(b.insert(11)); + assert!(b.insert(200)); + + assert!(!a.is_subset(&b)); + assert!(!a.is_superset(&b)); + assert!(!b.is_subset(&a)); + assert!(!b.is_superset(&a)); + + assert!(b.insert(5)); + + assert!(a.is_subset(&b)); + assert!(!a.is_superset(&b)); + assert!(!b.is_subset(&a)); + assert!(b.is_superset(&a)); + } + + #[test] + fn test_intersection() { + let mut a = SmallIntSet::new(); + let mut b = SmallIntSet::new(); + + assert!(a.insert(11)); + assert!(a.insert(1)); + assert!(a.insert(3)); + assert!(a.insert(77)); + assert!(a.insert(103)); + assert!(a.insert(5)); + + assert!(b.insert(2)); + assert!(b.insert(11)); + assert!(b.insert(77)); + assert!(b.insert(5)); + assert!(b.insert(3)); + + let mut i = 0; + let expected = [3, 5, 11, 77]; + for a.intersection(&b) |x| { + assert!(vec::contains(expected, x)); + i += 1 + } + assert_eq!(i, expected.len()); + } + + #[test] + fn test_difference() { + let mut a = SmallIntSet::new(); + let mut b = SmallIntSet::new(); + + assert!(a.insert(1)); + assert!(a.insert(3)); + assert!(a.insert(5)); + assert!(a.insert(9)); + assert!(a.insert(11)); + + assert!(b.insert(3)); + assert!(b.insert(9)); + + let mut i = 0; + let expected = [1, 5, 11]; + for a.difference(&b) |x| { + assert!(vec::contains(expected, x)); + i += 1 + } + assert_eq!(i, expected.len()); + } + + #[test] + fn test_symmetric_difference() { + let mut a = SmallIntSet::new(); + let mut b = SmallIntSet::new(); + + assert!(a.insert(1)); + assert!(a.insert(3)); + assert!(a.insert(5)); + assert!(a.insert(9)); + assert!(a.insert(11)); + + assert!(b.insert(3)); + assert!(b.insert(9)); + assert!(b.insert(14)); + assert!(b.insert(22)); + + let mut i = 0; + let expected = [1, 5, 11, 14, 22]; + for a.symmetric_difference(&b) |x| { + assert!(vec::contains(expected, x)); + i += 1 + } + assert_eq!(i, expected.len()); + } + + #[test] + fn test_union() { + let mut a = SmallIntSet::new(); + let mut b = SmallIntSet::new(); + + assert!(a.insert(1)); + assert!(a.insert(3)); + assert!(a.insert(5)); + assert!(a.insert(9)); + assert!(a.insert(11)); + assert!(a.insert(16)); + assert!(a.insert(19)); + assert!(a.insert(24)); + + assert!(b.insert(1)); + assert!(b.insert(5)); + assert!(b.insert(9)); + assert!(b.insert(13)); + assert!(b.insert(19)); + + let mut i = 0; + let expected = [1, 3, 5, 9, 11, 13, 16, 19, 24]; + for a.union(&b) |x| { + assert!(vec::contains(expected, x)); + i += 1 + } + assert_eq!(i, expected.len()); + } +} diff --git a/src/libstd/sort.rs b/src/libextra/sort.rs similarity index 97% rename from src/libstd/sort.rs rename to src/libextra/sort.rs index 0d94a1830a648..420c63efab5d3 100644 --- a/src/libstd/sort.rs +++ b/src/libextra/sort.rs @@ -10,10 +10,13 @@ //! Sorting methods +use core::prelude::*; + use core::cmp::{Eq, Ord}; +use core::uint; +use core::util::swap; use core::vec::len; use core::vec; -use core::util::swap; type Le<'self, T> = &'self fn(v1: &T, v2: &T) -> bool; @@ -61,26 +64,6 @@ pub fn merge_sort(v: &[T], le: Le) -> ~[T] { } } -#[cfg(stage0)] -fn part(arr: &mut [T], left: uint, - right: uint, pivot: uint, compare_func: Le) -> uint { - swap(&mut arr[pivot], &mut arr[right]); - let mut storage_index: uint = left; - let mut i: uint = left; - while i < right { - let a: &mut T = &mut arr[i]; - let b: &mut T = &mut arr[right]; - if compare_func(a, b) { - swap(&mut arr[i], &mut arr[storage_index]); - storage_index += 1; - } - i += 1; - } - swap(&mut arr[storage_index], &mut arr[right]); - return storage_index; -} - -#[cfg(not(stage0))] fn part(arr: &mut [T], left: uint, right: uint, pivot: uint, compare_func: Le) -> uint { vec::swap(arr, pivot, right); @@ -184,6 +167,7 @@ pub fn quick_sort3(arr: &mut [T]) { qsort3(arr, 0, (len - 1) as int); } +#[allow(missing_doc)] pub trait Sort { fn qsort(self); } @@ -196,6 +180,7 @@ static MIN_MERGE: uint = 64; static MIN_GALLOP: uint = 7; static INITIAL_TMP_STORAGE: uint = 128; +#[allow(missing_doc)] pub fn tim_sort(array: &mut [T]) { let size = array.len(); if size < 2 { @@ -261,7 +246,7 @@ fn binarysort(array: &mut [T], start: uint) { left = mid+1; } } - assert!(left == right); + assert_eq!(left, right); let n = start-left; shift_vec(array, left+1, left, n); @@ -357,7 +342,7 @@ fn gallop_left(key: &T, ofs = m; } } - assert!(last_ofs == ofs); + assert_eq!(last_ofs, ofs); return ofs; } @@ -410,7 +395,7 @@ fn gallop_right(key: &T, ofs = m; } } - assert!(last_ofs == ofs); + assert_eq!(last_ofs, ofs); return ofs; } @@ -449,7 +434,7 @@ impl MergeState { let l2 = self.runs[n+1].len; assert!(l1 > 0 && l2 > 0); - assert!(b1 + l1 == b2); + assert_eq!(b1 + l1, b2); self.runs[n].len = l1 + l2; if n == size-3 { @@ -583,7 +568,7 @@ impl MergeState { } else if len1 == 0 { fail!("Comparison violates its contract!"); } else { - assert!(len2 == 0); + assert_eq!(len2, 0); assert!(len1 > 1); copy_vec(array, dest, tmp.slice(c1, c1+len1)); } @@ -705,7 +690,7 @@ impl MergeState { } else if len2 == 0 { fail!("Comparison violates its contract!"); } else { - assert!(len1 == 0); + assert_eq!(len1, 0); assert!(len2 != 0); copy_vec(array, dest-(len2-1), tmp.slice(0, len2)); } @@ -806,6 +791,8 @@ mod test_qsort3 { #[cfg(test)] mod test_qsort { + use core::prelude::*; + use sort::*; use core::int; @@ -818,7 +805,7 @@ mod test_qsort { let mut i = 0u; while i < len { // debug!(v2[i]); - assert!((v2[i] == v1[i])); + assert_eq!(v2[i], v1[i]); i += 1; } } @@ -863,13 +850,14 @@ mod test_qsort { for pairs.each |p| { let (a, b) = *p; debug!("%d %d", a, b); - assert!((a == b)); + assert_eq!(a, b); } } } #[cfg(test)] mod tests { + use core::prelude::*; use sort::*; @@ -883,7 +871,7 @@ mod tests { let mut i = 0u; while i < len { debug!(v3[i]); - assert!((v3[i] == v2[i])); + assert_eq!(v3[i], v2[i]); i += 1; } } @@ -908,9 +896,9 @@ mod tests { #[test] fn test_merge_sort_mutable() { pub fn le(a: &int, b: &int) -> bool { *a <= *b } - let mut v1 = ~[3, 2, 1]; + let v1 = ~[3, 2, 1]; let v2 = merge_sort(v1, le); - assert!(v2 == ~[1, 2, 3]); + assert_eq!(v2, ~[1, 2, 3]); } #[test] @@ -932,14 +920,21 @@ mod tests { let names2 = ~["Alex Andy", "Jack Brown", "joe bob", "Joe Bob", "JOE Bob", "JOE BOB", "Sally Mae"]; let names3 = merge_sort(names1, ile); - assert!(names3 == names2); + assert_eq!(names3, names2); } } #[cfg(test)] mod test_tim_sort { + use core::prelude::*; + use sort::tim_sort; + + use core::local_data; use core::rand::RngUtil; + use core::rand; + use core::uint; + use core::vec; struct CVal { val: float, @@ -964,7 +959,7 @@ mod test_tim_sort { let mut i = 0u; while i < len { // debug!(v2[i]); - assert!((v2[i] == v1[i])); + assert_eq!(v2[i], v1[i]); i += 1u; } } @@ -1029,8 +1024,15 @@ mod test_tim_sort { #[cfg(test)] mod big_tests { + use core::prelude::*; + use sort::*; + + use core::local_data; use core::rand::RngUtil; + use core::rand; + use core::uint; + use core::vec; #[test] fn test_unique() { diff --git a/src/libstd/stats.rs b/src/libextra/stats.rs similarity index 98% rename from src/libstd/stats.rs rename to src/libextra/stats.rs index 25323b4e1db8e..d224777ded702 100644 --- a/src/libstd/stats.rs +++ b/src/libextra/stats.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[allow(missing_doc)]; + +use core::prelude::*; + use core::vec; use core::f64; use core::cmp; diff --git a/src/libstd/std.rc b/src/libextra/std.rc similarity index 72% rename from src/libstd/std.rc rename to src/libextra/std.rc index d29791449b61c..4e9a547e14119 100644 --- a/src/libstd/std.rc +++ b/src/libextra/std.rc @@ -17,7 +17,7 @@ not required in or otherwise suitable for the core library. */ -#[link(name = "std", +#[link(name = "extra", vers = "0.7-pre", uuid = "122bed0b-c19b-4b82-b0b7-7ae8aead7297", url = "https://github.com/mozilla/rust/tree/master/src/libstd")]; @@ -27,6 +27,20 @@ not required in or otherwise suitable for the core library. #[crate_type = "lib"]; #[deny(non_camel_case_types)]; +#[deny(missing_doc)]; + +// NOTE: remove these two attributes after the next snapshot +#[no_core]; // for stage0 +#[allow(unrecognized_lint)]; // otherwise stage0 is seriously ugly + +#[no_std]; + +extern mod core(name = "std", vers = "0.7-pre"); + +use core::{str, unstable}; +use core::str::{StrSlice, OwnedStr}; + +pub use core::os; pub mod uv_ll; @@ -63,18 +77,12 @@ pub mod flatpipes; pub mod bitv; pub mod deque; -#[cfg(not(stage0))] pub mod fun_treemap; pub mod list; pub mod priority_queue; pub mod rope; pub mod smallintmap; -#[cfg(stage0)] -#[path="sort_stage0.rs"] -pub mod sort; - -#[cfg(not(stage0))] pub mod sort; pub mod dlist; @@ -110,6 +118,8 @@ pub mod flate; #[cfg(unicode)] mod unicode; +#[path="terminfo/terminfo.rs"] +pub mod terminfo; // Compiler support modules @@ -117,10 +127,25 @@ pub mod test; pub mod serialize; // A curious inner-module that's not exported that contains the binding -// 'std' so that macro-expanded references to std::serialize and such -// can be resolved within libcore. -#[doc(hidden)] // FIXME #3538 +// 'extra' so that macro-expanded references to std::serialize and such +// can be resolved within libextra. +#[doc(hidden)] pub mod std { pub use serialize; pub use test; + + // For bootstrapping. + pub use core::clone; + pub use core::condition; + pub use core::cmp; + pub use core::sys; + pub use core::unstable; + pub use core::str; + pub use core::os; +} +#[doc(hidden)] +pub mod extra { + pub use serialize; + pub use test; } + diff --git a/src/libstd/sync.rs b/src/libextra/sync.rs similarity index 90% rename from src/libstd/sync.rs rename to src/libextra/sync.rs index 449edacad32bd..8f09ddea9ba78 100644 --- a/src/libstd/sync.rs +++ b/src/libextra/sync.rs @@ -15,9 +15,13 @@ * in std. */ -use core::unstable::sync::{Exclusive, exclusive}; +use core::prelude::*; + +use core::borrow; +use core::comm; use core::ptr; use core::task; +use core::unstable::sync::{Exclusive, exclusive}; use core::util; /**************************************************************************** @@ -96,40 +100,45 @@ fn new_sem_and_signal(count: int, num_condvars: uint) } #[doc(hidden)] -pub impl Sem { - fn acquire(&self) { - let mut waiter_nobe = None; - do (**self).with |state| { - state.count -= 1; - if state.count < 0 { - // Create waiter nobe. - let (WaitEnd, SignalEnd) = comm::oneshot(); - // Tell outer scope we need to block. - waiter_nobe = Some(WaitEnd); - // Enqueue ourself. - state.waiters.tail.send(SignalEnd); +impl Sem { + pub fn acquire(&self) { + unsafe { + let mut waiter_nobe = None; + do (**self).with |state| { + state.count -= 1; + if state.count < 0 { + // Create waiter nobe. + let (WaitEnd, SignalEnd) = comm::oneshot(); + // Tell outer scope we need to block. + waiter_nobe = Some(WaitEnd); + // Enqueue ourself. + state.waiters.tail.send(SignalEnd); + } + } + // Uncomment if you wish to test for sem races. Not valgrind-friendly. + /* for 1000.times { task::yield(); } */ + // Need to wait outside the exclusive. + if waiter_nobe.is_some() { + let _ = comm::recv_one(waiter_nobe.unwrap()); } - } - // Uncomment if you wish to test for sem races. Not valgrind-friendly. - /* for 1000.times { task::yield(); } */ - // Need to wait outside the exclusive. - if waiter_nobe.is_some() { - let _ = comm::recv_one(waiter_nobe.unwrap()); } } - fn release(&self) { - do (**self).with |state| { - state.count += 1; - if state.count <= 0 { - signal_waitqueue(&state.waiters); + + pub fn release(&self) { + unsafe { + do (**self).with |state| { + state.count += 1; + if state.count <= 0 { + signal_waitqueue(&state.waiters); + } } } } } // FIXME(#3154) move both copies of this into Sem, and unify the 2 structs #[doc(hidden)] -pub impl Sem<()> { - fn access(&self, blk: &fn() -> U) -> U { +impl Sem<()> { + pub fn access(&self, blk: &fn() -> U) -> U { let mut release = None; unsafe { do task::unkillable { @@ -140,9 +149,10 @@ pub impl Sem<()> { blk() } } + #[doc(hidden)] -pub impl Sem<~[Waitqueue]> { - fn access(&self, blk: &fn() -> U) -> U { +impl Sem<~[Waitqueue]> { + pub fn access(&self, blk: &fn() -> U) -> U { let mut release = None; unsafe { do task::unkillable { @@ -186,7 +196,7 @@ pub struct Condvar<'self> { priv sem: &'self Sem<~[Waitqueue]> } #[unsafe_destructor] impl<'self> Drop for Condvar<'self> { fn finalize(&self) {} } -pub impl<'self> Condvar<'self> { +impl<'self> Condvar<'self> { /** * Atomically drop the associated lock, and block until a signal is sent. * @@ -195,7 +205,7 @@ pub impl<'self> Condvar<'self> { * while waiting on a condition variable will wake up, fail, and unlock * the associated lock as it unwinds. */ - fn wait(&self) { self.wait_on(0) } + pub fn wait(&self) { self.wait_on(0) } /** * As wait(), but can specify which of multiple condition variables to @@ -208,7 +218,7 @@ pub impl<'self> Condvar<'self> { * * wait() is equivalent to wait_on(0). */ - fn wait_on(&self, condvar_id: uint) { + pub fn wait_on(&self, condvar_id: uint) { // Create waiter nobe. let (WaitEnd, SignalEnd) = comm::oneshot(); let mut WaitEnd = Some(WaitEnd); @@ -277,45 +287,49 @@ pub impl<'self> Condvar<'self> { } /// Wake up a blocked task. Returns false if there was no blocked task. - fn signal(&self) -> bool { self.signal_on(0) } + pub fn signal(&self) -> bool { self.signal_on(0) } /// As signal, but with a specified condvar_id. See wait_on. - fn signal_on(&self, condvar_id: uint) -> bool { - let mut out_of_bounds = None; - let mut result = false; - do (**self.sem).with |state| { - if condvar_id < state.blocked.len() { - result = signal_waitqueue(&state.blocked[condvar_id]); - } else { - out_of_bounds = Some(state.blocked.len()); + pub fn signal_on(&self, condvar_id: uint) -> bool { + unsafe { + let mut out_of_bounds = None; + let mut result = false; + do (**self.sem).with |state| { + if condvar_id < state.blocked.len() { + result = signal_waitqueue(&state.blocked[condvar_id]); + } else { + out_of_bounds = Some(state.blocked.len()); + } + } + do check_cvar_bounds(out_of_bounds, condvar_id, "cond.signal_on()") { + result } - } - do check_cvar_bounds(out_of_bounds, condvar_id, "cond.signal_on()") { - result } } /// Wake up all blocked tasks. Returns the number of tasks woken. - fn broadcast(&self) -> uint { self.broadcast_on(0) } + pub fn broadcast(&self) -> uint { self.broadcast_on(0) } /// As broadcast, but with a specified condvar_id. See wait_on. - fn broadcast_on(&self, condvar_id: uint) -> uint { + pub fn broadcast_on(&self, condvar_id: uint) -> uint { let mut out_of_bounds = None; let mut queue = None; - do (**self.sem).with |state| { - if condvar_id < state.blocked.len() { - // To avoid :broadcast_heavy, we make a new waitqueue, - // swap it out with the old one, and broadcast on the - // old one outside of the little-lock. - queue = Some(util::replace(&mut state.blocked[condvar_id], - new_waitqueue())); - } else { - out_of_bounds = Some(state.blocked.len()); + unsafe { + do (**self.sem).with |state| { + if condvar_id < state.blocked.len() { + // To avoid :broadcast_heavy, we make a new waitqueue, + // swap it out with the old one, and broadcast on the + // old one outside of the little-lock. + queue = Some(util::replace(&mut state.blocked[condvar_id], + new_waitqueue())); + } else { + out_of_bounds = Some(state.blocked.len()); + } + } + do check_cvar_bounds(out_of_bounds, condvar_id, "cond.signal_on()") { + let queue = queue.swap_unwrap(); + broadcast_waitqueue(&queue) } - } - do check_cvar_bounds(out_of_bounds, condvar_id, "cond.signal_on()") { - let queue = queue.swap_unwrap(); - broadcast_waitqueue(&queue) } } } @@ -336,9 +350,9 @@ fn check_cvar_bounds(out_of_bounds: Option, id: uint, act: &str, } #[doc(hidden)] -pub impl Sem<~[Waitqueue]> { +impl Sem<~[Waitqueue]> { // The only other place that condvars get built is rwlock_write_mode. - fn access_cond(&self, blk: &fn(c: &Condvar) -> U) -> U { + pub fn access_cond(&self, blk: &fn(c: &Condvar) -> U) -> U { do self.access { blk(&Condvar { sem: self }) } } } @@ -362,21 +376,21 @@ impl Clone for Semaphore { } } -pub impl Semaphore { +impl Semaphore { /** * Acquire a resource represented by the semaphore. Blocks if necessary * until resource(s) become available. */ - fn acquire(&self) { (&self.sem).acquire() } + pub fn acquire(&self) { (&self.sem).acquire() } /** * Release a held resource represented by the semaphore. Wakes a blocked * contending task, if any exist. Won't block the caller. */ - fn release(&self) { (&self.sem).release() } + pub fn release(&self) { (&self.sem).release() } /// Run a function with ownership of one of the semaphore's resources. - fn access(&self, blk: &fn() -> U) -> U { (&self.sem).access(blk) } + pub fn access(&self, blk: &fn() -> U) -> U { (&self.sem).access(blk) } } /**************************************************************************** @@ -410,12 +424,12 @@ impl Clone for Mutex { fn clone(&self) -> Mutex { Mutex { sem: Sem((*self.sem).clone()) } } } -pub impl Mutex { +impl Mutex { /// Run a function with ownership of the mutex. - fn lock(&self, blk: &fn() -> U) -> U { (&self.sem).access(blk) } + pub fn lock(&self, blk: &fn() -> U) -> U { (&self.sem).access(blk) } /// Run a function with ownership of the mutex and a handle to a condvar. - fn lock_cond(&self, blk: &fn(c: &Condvar) -> U) -> U { + pub fn lock_cond(&self, blk: &fn(c: &Condvar) -> U) -> U { (&self.sem).access_cond(blk) } } @@ -459,9 +473,9 @@ pub fn rwlock_with_condvars(num_condvars: uint) -> RWlock { read_count: 0 }) } } -pub impl RWlock { +impl RWlock { /// Create a new handle to the rwlock. - fn clone(&self) -> RWlock { + pub fn clone(&self) -> RWlock { RWlock { order_lock: (&(self.order_lock)).clone(), access_lock: Sem((*self.access_lock).clone()), state: self.state.clone() } @@ -471,7 +485,7 @@ pub impl RWlock { * Run a function with the rwlock in read mode. Calls to 'read' from other * tasks may run concurrently with this one. */ - fn read(&self, blk: &fn() -> U) -> U { + pub fn read(&self, blk: &fn() -> U) -> U { let mut release = None; unsafe { do task::unkillable { @@ -502,7 +516,7 @@ pub impl RWlock { * Run a function with the rwlock in write mode. No calls to 'read' or * 'write' from other tasks will run concurrently with this one. */ - fn write(&self, blk: &fn() -> U) -> U { + pub fn write(&self, blk: &fn() -> U) -> U { unsafe { do task::unkillable { (&self.order_lock).acquire(); @@ -520,7 +534,7 @@ pub impl RWlock { * the waiting task is signalled. (Note: a writer that waited and then * was signalled might reacquire the lock before other waiting writers.) */ - fn write_cond(&self, blk: &fn(c: &Condvar) -> U) -> U { + pub fn write_cond(&self, blk: &fn(c: &Condvar) -> U) -> U { // NB: You might think I should thread the order_lock into the cond // wait call, so that it gets waited on before access_lock gets // reacquired upon being woken up. However, (a) this would be not @@ -543,7 +557,10 @@ pub impl RWlock { * the meantime (such as unlocking and then re-locking as a reader would * do). The block takes a "write mode token" argument, which can be * transformed into a "read mode token" by calling downgrade(). Example: - * ~~~ + * + * # Example + * + * ~~~ {.rust} * do lock.write_downgrade |write_mode| { * do (&write_mode).write_cond |condvar| { * ... exclusive access ... @@ -555,7 +572,7 @@ pub impl RWlock { * } * ~~~ */ - fn write_downgrade(&self, blk: &fn(v: RWlockWriteMode) -> U) -> U { + pub fn write_downgrade(&self, blk: &fn(v: RWlockWriteMode) -> U) -> U { // Implementation slightly different from the slicker 'write's above. // The exit path is conditional on whether the caller downgrades. let mut _release = None; @@ -571,10 +588,9 @@ pub impl RWlock { } /// To be called inside of the write_downgrade block. - fn downgrade<'a>(&self, - token: RWlockWriteMode<'a>) - -> RWlockReadMode<'a> { - if !ptr::ref_eq(self, token.lock) { + pub fn downgrade<'a>(&self, token: RWlockWriteMode<'a>) + -> RWlockReadMode<'a> { + if !borrow::ref_eq(self, token.lock) { fail!("Can't downgrade() with a different rwlock's write_mode!"); } unsafe { @@ -689,18 +705,18 @@ pub struct RWlockReadMode<'self> { priv lock: &'self RWlock } #[unsafe_destructor] impl<'self> Drop for RWlockReadMode<'self> { fn finalize(&self) {} } -pub impl<'self> RWlockWriteMode<'self> { +impl<'self> RWlockWriteMode<'self> { /// Access the pre-downgrade rwlock in write mode. - fn write(&self, blk: &fn() -> U) -> U { blk() } + pub fn write(&self, blk: &fn() -> U) -> U { blk() } /// Access the pre-downgrade rwlock in write mode with a condvar. - fn write_cond(&self, blk: &fn(c: &Condvar) -> U) -> U { + pub fn write_cond(&self, blk: &fn(c: &Condvar) -> U) -> U { blk(&Condvar { sem: &self.lock.access_lock }) } } -pub impl<'self> RWlockReadMode<'self> { +impl<'self> RWlockReadMode<'self> { /// Access the post-downgrade rwlock in read mode. - fn read(&self, blk: &fn() -> U) -> U { blk() } + pub fn read(&self, blk: &fn() -> U) -> U { blk() } } /**************************************************************************** @@ -709,11 +725,13 @@ pub impl<'self> RWlockReadMode<'self> { #[cfg(test)] mod tests { + use core::prelude::*; use sync::*; use core::cast; use core::cell::Cell; + use core::comm; use core::ptr; use core::result; use core::task; @@ -800,7 +818,7 @@ mod tests { let s = ~semaphore(1); let s2 = ~s.clone(); let (p,c) = comm::stream(); - let child_data = Cell((s2, c)); + let child_data = Cell::new((s2, c)); do s.access { let (s2, c) = child_data.take(); do task::spawn || { @@ -839,7 +857,7 @@ mod tests { access_shared(sharedstate, m, 10); let _ = p.recv(); - assert!(*sharedstate == 20); + assert_eq!(*sharedstate, 20); } fn access_shared(sharedstate: &mut int, m: &Mutex, n: uint) { @@ -906,7 +924,7 @@ mod tests { for ports.each |port| { let _ = port.recv(); } do m.lock_cond |cond| { let num_woken = cond.broadcast(); - assert!(num_woken == num_waiters); + assert_eq!(num_woken, num_waiters); } // wait until all children wake up for ports.each |port| { let _ = port.recv(); } @@ -981,7 +999,7 @@ mod tests { let mut sibling_convos = ~[]; for 2.times { let (p,c) = comm::stream(); - let c = Cell(c); + let c = Cell::new(c); sibling_convos.push(p); let mi = ~m2.clone(); // spawn sibling task @@ -1006,7 +1024,7 @@ mod tests { for vec::each(p.recv()) |p| { p.recv(); } // wait on all its siblings do m.lock_cond |cond| { let woken = cond.broadcast(); - assert!(woken == 0); + assert_eq!(woken, 0); } struct SendOnFailure { c: comm::Chan<()>, @@ -1120,7 +1138,7 @@ mod tests { access_shared(sharedstate, x, mode2, 10); let _ = p.recv(); - assert!(*sharedstate == 20); + assert_eq!(*sharedstate, 20); } fn access_shared(sharedstate: &mut int, x: &RWlock, mode: RWlockMode, @@ -1273,7 +1291,7 @@ mod tests { for ports.each |port| { let _ = port.recv(); } do lock_cond(x, dg2) |cond| { let num_woken = cond.broadcast(); - assert!(num_woken == num_waiters); + assert_eq!(num_woken, num_waiters); } // wait until all children wake up for ports.each |port| { let _ = port.recv(); } diff --git a/src/libstd/task_pool.rs b/src/libextra/task_pool.rs similarity index 88% rename from src/libstd/task_pool.rs rename to src/libextra/task_pool.rs index 0c52e1ff80e21..b88bbff2a6668 100644 --- a/src/libstd/task_pool.rs +++ b/src/libextra/task_pool.rs @@ -8,10 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[allow(missing_doc)]; + /// A task pool abstraction. Useful for achieving predictable CPU /// parallelism. +use core::prelude::*; + use core::comm::Chan; +use core::comm; use core::task::SchedMode; use core::task; use core::vec; @@ -37,16 +42,16 @@ impl Drop for TaskPool { } } -pub impl TaskPool { +impl TaskPool { /// Spawns a new task pool with `n_tasks` tasks. If the `sched_mode` /// is None, the tasks run on this scheduler; otherwise, they run on a /// new scheduler with the given mode. The provided `init_fn_factory` /// returns a function which, given the index of the task, should return /// local data to be kept around in that task. - fn new(n_tasks: uint, - opt_sched_mode: Option, - init_fn_factory: ~fn() -> ~fn(uint) -> T) - -> TaskPool { + pub fn new(n_tasks: uint, + opt_sched_mode: Option, + init_fn_factory: ~fn() -> ~fn(uint) -> T) + -> TaskPool { assert!(n_tasks >= 1); let channels = do vec::from_fn(n_tasks) |i| { @@ -84,7 +89,7 @@ pub impl TaskPool { /// Executes the function `f` on a task in the pool. The function /// receives a reference to the local data returned by the `init_fn`. - fn execute(&mut self, f: ~fn(&T)) { + pub fn execute(&mut self, f: ~fn(&T)) { self.channels[self.next_index].send(Execute(f)); self.next_index += 1; if self.next_index == self.channels.len() { self.next_index = 0; } @@ -99,6 +104,6 @@ fn test_task_pool() { }; let mut pool = TaskPool::new(4, Some(SingleThreaded), f); for 8.times { - pool.execute(|i| io::println(fmt!("Hello from thread %u!", *i))); + pool.execute(|i| println(fmt!("Hello from thread %u!", *i))); } } diff --git a/src/libstd/tempfile.rs b/src/libextra/tempfile.rs similarity index 94% rename from src/libstd/tempfile.rs rename to src/libextra/tempfile.rs index e02a7a337334e..6d0bd88819500 100644 --- a/src/libstd/tempfile.rs +++ b/src/libextra/tempfile.rs @@ -10,8 +10,14 @@ //! Temporary files and directories +use core::prelude::*; + +use core::os; use core::rand::RngUtil; +use core::rand; +/// Attempts to make a temporary directory inside of `tmpdir` whose name will +/// have the suffix `suffix`. If no directory can be created, None is returned. pub fn mkdtemp(tmpdir: &Path, suffix: &str) -> Option { let mut r = rand::rng(); for 1000.times { @@ -25,9 +31,13 @@ pub fn mkdtemp(tmpdir: &Path, suffix: &str) -> Option { #[cfg(test)] mod tests { + use core::prelude::*; + use tempfile::mkdtemp; use tempfile; + use core::os; + use core::str; #[test] fn test_mkdtemp() { diff --git a/src/libextra/term.rs b/src/libextra/term.rs new file mode 100644 index 0000000000000..455cc0b74507e --- /dev/null +++ b/src/libextra/term.rs @@ -0,0 +1,132 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Simple ANSI color library + +#[allow(missing_doc)]; + +use core::prelude::*; + +use core::io; +use core::os; + +use terminfo::*; +use terminfo::searcher::open; +use terminfo::parser::compiled::parse; +use terminfo::parm::{expand, Number}; + +// FIXME (#2807): Windows support. + +pub static color_black: u8 = 0u8; +pub static color_red: u8 = 1u8; +pub static color_green: u8 = 2u8; +pub static color_yellow: u8 = 3u8; +pub static color_blue: u8 = 4u8; +pub static color_magenta: u8 = 5u8; +pub static color_cyan: u8 = 6u8; +pub static color_light_gray: u8 = 7u8; +pub static color_light_grey: u8 = 7u8; +pub static color_dark_gray: u8 = 8u8; +pub static color_dark_grey: u8 = 8u8; +pub static color_bright_red: u8 = 9u8; +pub static color_bright_green: u8 = 10u8; +pub static color_bright_yellow: u8 = 11u8; +pub static color_bright_blue: u8 = 12u8; +pub static color_bright_magenta: u8 = 13u8; +pub static color_bright_cyan: u8 = 14u8; +pub static color_bright_white: u8 = 15u8; + +#[cfg(not(target_os = "win32"))] +pub struct Terminal { + color_supported: bool, + priv out: @io::Writer, + priv ti: ~TermInfo +} + +#[cfg(target_os = "win32")] +pub struct Terminal { + color_supported: bool, + priv out: @io::Writer, +} + +#[cfg(not(target_os = "win32"))] +impl Terminal { + pub fn new(out: @io::Writer) -> Result { + let term = os::getenv("TERM"); + if term.is_none() { + return Err(~"TERM environment variable undefined"); + } + + let entry = open(term.unwrap()); + if entry.is_err() { + return Err(entry.get_err()); + } + + let ti = parse(entry.get(), false); + if ti.is_err() { + return Err(entry.get_err()); + } + + let mut inf = ti.get(); + let cs = *inf.numbers.find_or_insert(~"colors", 0) >= 16 + && inf.strings.find(&~"setaf").is_some() + && inf.strings.find_equiv(&("setab")).is_some(); + + return Ok(Terminal {out: out, ti: inf, color_supported: cs}); + } + pub fn fg(&self, color: u8) { + if self.color_supported { + let s = expand(*self.ti.strings.find_equiv(&("setaf")).unwrap(), + [Number(color as int)], [], []); + if s.is_ok() { + self.out.write(s.get()); + } else { + warn!(s.get_err()); + } + } + } + pub fn bg(&self, color: u8) { + if self.color_supported { + let s = expand(*self.ti.strings.find_equiv(&("setab")).unwrap(), + [Number(color as int)], [], []); + if s.is_ok() { + self.out.write(s.get()); + } else { + warn!(s.get_err()); + } + } + } + pub fn reset(&self) { + if self.color_supported { + let s = expand(*self.ti.strings.find_equiv(&("op")).unwrap(), [], [], []); + if s.is_ok() { + self.out.write(s.get()); + } else { + warn!(s.get_err()); + } + } + } +} + +#[cfg(target_os = "win32")] +impl Terminal { + pub fn new(out: @io::Writer) -> Result { + return Ok(Terminal {out: out, color_supported: false}); + } + + pub fn fg(&self, color: u8) { + } + + pub fn bg(&self, color: u8) { + } + + pub fn reset(&self) { + } +} diff --git a/src/libextra/terminfo/parm.rs b/src/libextra/terminfo/parm.rs new file mode 100644 index 0000000000000..4eb48f60a9999 --- /dev/null +++ b/src/libextra/terminfo/parm.rs @@ -0,0 +1,209 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Parameterized string expansion + +use core::prelude::*; +use core::{char, int, vec}; + +#[deriving(Eq)] +enum States { + Nothing, + Percent, + SetVar, + GetVar, + PushParam, + CharConstant, + CharClose, + IntConstant, + IfCond, + IfBody +} + +/// Types of parameters a capability can use +pub enum Param { + String(~str), + Char(char), + Number(int) +} + +/** + Expand a parameterized capability + + # Arguments + * `cap` - string to expand + * `params` - vector of params for %p1 etc + * `sta` - vector of params corresponding to static variables + * `dyn` - vector of params corresponding to stativ variables + + To be compatible with ncurses, `sta` and `dyn` should be the same between calls to `expand` for + multiple capabilities for the same terminal. + */ +pub fn expand(cap: &[u8], params: &mut [Param], sta: &mut [Param], dyn: &mut [Param]) + -> Result<~[u8], ~str> { + assert!(cap.len() != 0, "expanding an empty capability makes no sense"); + assert!(params.len() <= 9, "only 9 parameters are supported by capability strings"); + + assert!(sta.len() <= 26, "only 26 static vars are able to be used by capability strings"); + assert!(dyn.len() <= 26, "only 26 dynamic vars are able to be used by capability strings"); + + let mut state = Nothing; + let mut i = 0; + + // expanded cap will only rarely be smaller than the cap itself + let mut output = vec::with_capacity(cap.len()); + + let mut cur; + + let mut stack: ~[Param] = ~[]; + + let mut intstate = ~[]; + + while i < cap.len() { + cur = cap[i] as char; + let mut old_state = state; + match state { + Nothing => { + if cur == '%' { + state = Percent; + } else { + output.push(cap[i]); + } + }, + Percent => { + match cur { + '%' => { output.push(cap[i]); state = Nothing }, + 'c' => match stack.pop() { + Char(c) => output.push(c as u8), + _ => return Err(~"a non-char was used with %c") + }, + 's' => match stack.pop() { + String(s) => output.push_all(s.to_bytes()), + _ => return Err(~"a non-str was used with %s") + }, + 'd' => match stack.pop() { + Number(x) => output.push_all(x.to_str().to_bytes()), + _ => return Err(~"a non-number was used with %d") + }, + 'p' => state = PushParam, + 'P' => state = SetVar, + 'g' => state = GetVar, + '\'' => state = CharConstant, + '{' => state = IntConstant, + 'l' => match stack.pop() { + String(s) => stack.push(Number(s.len() as int)), + _ => return Err(~"a non-str was used with %l") + }, + '+' => match (stack.pop(), stack.pop()) { + (Number(x), Number(y)) => stack.push(Number(x + y)), + (_, _) => return Err(~"non-numbers on stack with +") + }, + '-' => match (stack.pop(), stack.pop()) { + (Number(x), Number(y)) => stack.push(Number(x - y)), + (_, _) => return Err(~"non-numbers on stack with -") + }, + '*' => match (stack.pop(), stack.pop()) { + (Number(x), Number(y)) => stack.push(Number(x * y)), + (_, _) => return Err(~"non-numbers on stack with *") + }, + '/' => match (stack.pop(), stack.pop()) { + (Number(x), Number(y)) => stack.push(Number(x / y)), + (_, _) => return Err(~"non-numbers on stack with /") + }, + 'm' => match (stack.pop(), stack.pop()) { + (Number(x), Number(y)) => stack.push(Number(x % y)), + (_, _) => return Err(~"non-numbers on stack with %") + }, + '&' => match (stack.pop(), stack.pop()) { + (Number(x), Number(y)) => stack.push(Number(x & y)), + (_, _) => return Err(~"non-numbers on stack with &") + }, + '|' => match (stack.pop(), stack.pop()) { + (Number(x), Number(y)) => stack.push(Number(x | y)), + (_, _) => return Err(~"non-numbers on stack with |") + }, + 'A' => return Err(~"logical operations unimplemented"), + 'O' => return Err(~"logical operations unimplemented"), + '!' => return Err(~"logical operations unimplemented"), + '~' => match stack.pop() { + Number(x) => stack.push(Number(!x)), + _ => return Err(~"non-number on stack with %~") + }, + 'i' => match (copy params[0], copy params[1]) { + (Number(x), Number(y)) => { + params[0] = Number(x + 1); + params[1] = Number(y + 1); + }, + (_, _) => return Err(~"first two params not numbers with %i") + }, + '?' => state = return Err(fmt!("if expressions unimplemented (%?)", cap)), + _ => return Err(fmt!("unrecognized format option %c", cur)) + } + }, + PushParam => { + // params are 1-indexed + stack.push(copy params[char::to_digit(cur, 10).expect("bad param number") - 1]); + }, + SetVar => { + if cur >= 'A' && cur <= 'Z' { + let idx = (cur as u8) - ('A' as u8); + sta[idx] = stack.pop(); + } else if cur >= 'a' && cur <= 'z' { + let idx = (cur as u8) - ('a' as u8); + dyn[idx] = stack.pop(); + } else { + return Err(~"bad variable name in %P"); + } + }, + GetVar => { + if cur >= 'A' && cur <= 'Z' { + let idx = (cur as u8) - ('A' as u8); + stack.push(copy sta[idx]); + } else if cur >= 'a' && cur <= 'z' { + let idx = (cur as u8) - ('a' as u8); + stack.push(copy dyn[idx]); + } else { + return Err(~"bad variable name in %g"); + } + }, + CharConstant => { + stack.push(Char(cur)); + state = CharClose; + }, + CharClose => { + assert!(cur == '\'', "malformed character constant"); + }, + IntConstant => { + if cur == '}' { + stack.push(Number(int::parse_bytes(intstate, 10).expect("bad int constant"))); + state = Nothing; + } + intstate.push(cur as u8); + old_state = Nothing; + } + _ => return Err(~"unimplemented state") + } + if state == old_state { + state = Nothing; + } + i += 1; + } + Ok(output) +} + +#[cfg(test)] +mod test { + use super::*; + #[test] + fn test_basic_setabf() { + let s = bytes!("\\E[48;5;%p1%dm"); + assert_eq!(expand(s, [Number(1)], [], []).unwrap(), bytes!("\\E[48;5;1m").to_owned()); + } +} diff --git a/src/libextra/terminfo/parser/compiled.rs b/src/libextra/terminfo/parser/compiled.rs new file mode 100644 index 0000000000000..61c68c27fe5dc --- /dev/null +++ b/src/libextra/terminfo/parser/compiled.rs @@ -0,0 +1,334 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/// ncurses-compatible compiled terminfo format parsing (term(5)) + +use core::prelude::*; + +use core::{vec, int, str}; +use core::io::Reader; +use core::hashmap::HashMap; +use super::super::TermInfo; + +// These are the orders ncurses uses in its compiled format (as of 5.9). Not sure if portable. + +pub static boolfnames: &'static[&'static str] = &'static["auto_left_margin", "auto_right_margin", + "no_esc_ctlc", "ceol_standout_glitch", "eat_newline_glitch", "erase_overstrike", "generic_type", + "hard_copy", "has_meta_key", "has_status_line", "insert_null_glitch", "memory_above", + "memory_below", "move_insert_mode", "move_standout_mode", "over_strike", "status_line_esc_ok", + "dest_tabs_magic_smso", "tilde_glitch", "transparent_underline", "xon_xoff", "needs_xon_xoff", + "prtr_silent", "hard_cursor", "non_rev_rmcup", "no_pad_char", "non_dest_scroll_region", + "can_change", "back_color_erase", "hue_lightness_saturation", "col_addr_glitch", + "cr_cancels_micro_mode", "has_print_wheel", "row_addr_glitch", "semi_auto_right_margin", + "cpi_changes_res", "lpi_changes_res", "backspaces_with_bs", "crt_no_scrolling", + "no_correctly_working_cr", "gnu_has_meta_key", "linefeed_is_newline", "has_hardware_tabs", + "return_does_clr_eol"]; + +pub static boolnames: &'static[&'static str] = &'static["bw", "am", "xsb", "xhp", "xenl", "eo", + "gn", "hc", "km", "hs", "in", "db", "da", "mir", "msgr", "os", "eslok", "xt", "hz", "ul", "xon", + "nxon", "mc5i", "chts", "nrrmc", "npc", "ndscr", "ccc", "bce", "hls", "xhpa", "crxm", "daisy", + "xvpa", "sam", "cpix", "lpix", "OTbs", "OTns", "OTnc", "OTMT", "OTNL", "OTpt", "OTxr"]; + +pub static numfnames: &'static[&'static str] = &'static[ "columns", "init_tabs", "lines", + "lines_of_memory", "magic_cookie_glitch", "padding_baud_rate", "virtual_terminal", + "width_status_line", "num_labels", "label_height", "label_width", "max_attributes", + "maximum_windows", "max_colors", "max_pairs", "no_color_video", "buffer_capacity", + "dot_vert_spacing", "dot_horz_spacing", "max_micro_address", "max_micro_jump", "micro_col_size", + "micro_line_size", "number_of_pins", "output_res_char", "output_res_line", + "output_res_horz_inch", "output_res_vert_inch", "print_rate", "wide_char_size", "buttons", + "bit_image_entwining", "bit_image_type", "magic_cookie_glitch_ul", "carriage_return_delay", + "new_line_delay", "backspace_delay", "horizontal_tab_delay", "number_of_function_keys"]; + +pub static numnames: &'static[&'static str] = &'static[ "cols", "it", "lines", "lm", "xmc", "pb", + "vt", "wsl", "nlab", "lh", "lw", "ma", "wnum", "colors", "pairs", "ncv", "bufsz", "spinv", + "spinh", "maddr", "mjump", "mcs", "mls", "npins", "orc", "orl", "orhi", "orvi", "cps", "widcs", + "btns", "bitwin", "bitype", "UTug", "OTdC", "OTdN", "OTdB", "OTdT", "OTkn"]; + +pub static stringfnames: &'static[&'static str] = &'static[ "back_tab", "bell", "carriage_return", + "change_scroll_region", "clear_all_tabs", "clear_screen", "clr_eol", "clr_eos", + "column_address", "command_character", "cursor_address", "cursor_down", "cursor_home", + "cursor_invisible", "cursor_left", "cursor_mem_address", "cursor_normal", "cursor_right", + "cursor_to_ll", "cursor_up", "cursor_visible", "delete_character", "delete_line", + "dis_status_line", "down_half_line", "enter_alt_charset_mode", "enter_blink_mode", + "enter_bold_mode", "enter_ca_mode", "enter_delete_mode", "enter_dim_mode", "enter_insert_mode", + "enter_secure_mode", "enter_protected_mode", "enter_reverse_mode", "enter_standout_mode", + "enter_underline_mode", "erase_chars", "exit_alt_charset_mode", "exit_attribute_mode", + "exit_ca_mode", "exit_delete_mode", "exit_insert_mode", "exit_standout_mode", + "exit_underline_mode", "flash_screen", "form_feed", "from_status_line", "init_1string", + "init_2string", "init_3string", "init_file", "insert_character", "insert_line", + "insert_padding", "key_backspace", "key_catab", "key_clear", "key_ctab", "key_dc", "key_dl", + "key_down", "key_eic", "key_eol", "key_eos", "key_f0", "key_f1", "key_f10", "key_f2", "key_f3", + "key_f4", "key_f5", "key_f6", "key_f7", "key_f8", "key_f9", "key_home", "key_ic", "key_il", + "key_left", "key_ll", "key_npage", "key_ppage", "key_right", "key_sf", "key_sr", "key_stab", + "key_up", "keypad_local", "keypad_xmit", "lab_f0", "lab_f1", "lab_f10", "lab_f2", "lab_f3", + "lab_f4", "lab_f5", "lab_f6", "lab_f7", "lab_f8", "lab_f9", "meta_off", "meta_on", "newline", + "pad_char", "parm_dch", "parm_delete_line", "parm_down_cursor", "parm_ich", "parm_index", + "parm_insert_line", "parm_left_cursor", "parm_right_cursor", "parm_rindex", "parm_up_cursor", + "pkey_key", "pkey_local", "pkey_xmit", "print_screen", "prtr_off", "prtr_on", "repeat_char", + "reset_1string", "reset_2string", "reset_3string", "reset_file", "restore_cursor", + "row_address", "save_cursor", "scroll_forward", "scroll_reverse", "set_attributes", "set_tab", + "set_window", "tab", "to_status_line", "underline_char", "up_half_line", "init_prog", "key_a1", + "key_a3", "key_b2", "key_c1", "key_c3", "prtr_non", "char_padding", "acs_chars", "plab_norm", + "key_btab", "enter_xon_mode", "exit_xon_mode", "enter_am_mode", "exit_am_mode", "xon_character", + "xoff_character", "ena_acs", "label_on", "label_off", "key_beg", "key_cancel", "key_close", + "key_command", "key_copy", "key_create", "key_end", "key_enter", "key_exit", "key_find", + "key_help", "key_mark", "key_message", "key_move", "key_next", "key_open", "key_options", + "key_previous", "key_print", "key_redo", "key_reference", "key_refresh", "key_replace", + "key_restart", "key_resume", "key_save", "key_suspend", "key_undo", "key_sbeg", "key_scancel", + "key_scommand", "key_scopy", "key_screate", "key_sdc", "key_sdl", "key_select", "key_send", + "key_seol", "key_sexit", "key_sfind", "key_shelp", "key_shome", "key_sic", "key_sleft", + "key_smessage", "key_smove", "key_snext", "key_soptions", "key_sprevious", "key_sprint", + "key_sredo", "key_sreplace", "key_sright", "key_srsume", "key_ssave", "key_ssuspend", + "key_sundo", "req_for_input", "key_f11", "key_f12", "key_f13", "key_f14", "key_f15", "key_f16", + "key_f17", "key_f18", "key_f19", "key_f20", "key_f21", "key_f22", "key_f23", "key_f24", + "key_f25", "key_f26", "key_f27", "key_f28", "key_f29", "key_f30", "key_f31", "key_f32", + "key_f33", "key_f34", "key_f35", "key_f36", "key_f37", "key_f38", "key_f39", "key_f40", + "key_f41", "key_f42", "key_f43", "key_f44", "key_f45", "key_f46", "key_f47", "key_f48", + "key_f49", "key_f50", "key_f51", "key_f52", "key_f53", "key_f54", "key_f55", "key_f56", + "key_f57", "key_f58", "key_f59", "key_f60", "key_f61", "key_f62", "key_f63", "clr_bol", + "clear_margins", "set_left_margin", "set_right_margin", "label_format", "set_clock", + "display_clock", "remove_clock", "create_window", "goto_window", "hangup", "dial_phone", + "quick_dial", "tone", "pulse", "flash_hook", "fixed_pause", "wait_tone", "user0", "user1", + "user2", "user3", "user4", "user5", "user6", "user7", "user8", "user9", "orig_pair", + "orig_colors", "initialize_color", "initialize_pair", "set_color_pair", "set_foreground", + "set_background", "change_char_pitch", "change_line_pitch", "change_res_horz", + "change_res_vert", "define_char", "enter_doublewide_mode", "enter_draft_quality", + "enter_italics_mode", "enter_leftward_mode", "enter_micro_mode", "enter_near_letter_quality", + "enter_normal_quality", "enter_shadow_mode", "enter_subscript_mode", "enter_superscript_mode", + "enter_upward_mode", "exit_doublewide_mode", "exit_italics_mode", "exit_leftward_mode", + "exit_micro_mode", "exit_shadow_mode", "exit_subscript_mode", "exit_superscript_mode", + "exit_upward_mode", "micro_column_address", "micro_down", "micro_left", "micro_right", + "micro_row_address", "micro_up", "order_of_pins", "parm_down_micro", "parm_left_micro", + "parm_right_micro", "parm_up_micro", "select_char_set", "set_bottom_margin", + "set_bottom_margin_parm", "set_left_margin_parm", "set_right_margin_parm", "set_top_margin", + "set_top_margin_parm", "start_bit_image", "start_char_set_def", "stop_bit_image", + "stop_char_set_def", "subscript_characters", "superscript_characters", "these_cause_cr", + "zero_motion", "char_set_names", "key_mouse", "mouse_info", "req_mouse_pos", "get_mouse", + "set_a_foreground", "set_a_background", "pkey_plab", "device_type", "code_set_init", + "set0_des_seq", "set1_des_seq", "set2_des_seq", "set3_des_seq", "set_lr_margin", + "set_tb_margin", "bit_image_repeat", "bit_image_newline", "bit_image_carriage_return", + "color_names", "define_bit_image_region", "end_bit_image_region", "set_color_band", + "set_page_length", "display_pc_char", "enter_pc_charset_mode", "exit_pc_charset_mode", + "enter_scancode_mode", "exit_scancode_mode", "pc_term_options", "scancode_escape", + "alt_scancode_esc", "enter_horizontal_hl_mode", "enter_left_hl_mode", "enter_low_hl_mode", + "enter_right_hl_mode", "enter_top_hl_mode", "enter_vertical_hl_mode", "set_a_attributes", + "set_pglen_inch", "termcap_init2", "termcap_reset", "linefeed_if_not_lf", "backspace_if_not_bs", + "other_non_function_keys", "arrow_key_map", "acs_ulcorner", "acs_llcorner", "acs_urcorner", + "acs_lrcorner", "acs_ltee", "acs_rtee", "acs_btee", "acs_ttee", "acs_hline", "acs_vline", + "acs_plus", "memory_lock", "memory_unlock", "box_chars_1"]; + +pub static stringnames: &'static[&'static str] = &'static[ "cbt", "_", "cr", "csr", "tbc", "clear", + "_", "_", "hpa", "cmdch", "cup", "cud1", "home", "civis", "cub1", "mrcup", "cnorm", "cuf1", + "ll", "cuu1", "cvvis", "dch1", "dl1", "dsl", "hd", "smacs", "blink", "bold", "smcup", "smdc", + "dim", "smir", "invis", "prot", "rev", "smso", "smul", "ech", "rmacs", "sgr0", "rmcup", "rmdc", + "rmir", "rmso", "rmul", "flash", "ff", "fsl", "is1", "is2", "is3", "if", "ich1", "il1", "ip", + "kbs", "ktbc", "kclr", "kctab", "_", "_", "kcud1", "_", "_", "_", "_", "_", "_", "_", "_", "_", + "_", "_", "_", "_", "_", "khome", "_", "_", "kcub1", "_", "knp", "kpp", "kcuf1", "_", "_", + "khts", "_", "rmkx", "smkx", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "rmm", "_", + "_", "pad", "dch", "dl", "cud", "ich", "indn", "il", "cub", "cuf", "rin", "cuu", "pfkey", + "pfloc", "pfx", "mc0", "mc4", "_", "rep", "rs1", "rs2", "rs3", "rf", "rc", "vpa", "sc", "ind", + "ri", "sgr", "_", "wind", "_", "tsl", "uc", "hu", "iprog", "_", "_", "_", "_", "_", "mc5p", + "rmp", "acsc", "pln", "kcbt", "smxon", "rmxon", "smam", "rmam", "xonc", "xoffc", "_", "smln", + "rmln", "_", "kcan", "kclo", "kcmd", "kcpy", "kcrt", "_", "kent", "kext", "kfnd", "khlp", + "kmrk", "kmsg", "kmov", "knxt", "kopn", "kopt", "kprv", "kprt", "krdo", "kref", "krfr", "krpl", + "krst", "kres", "ksav", "kspd", "kund", "kBEG", "kCAN", "kCMD", "kCPY", "kCRT", "_", "_", + "kslt", "kEND", "kEOL", "kEXT", "kFND", "kHLP", "kHOM", "_", "kLFT", "kMSG", "kMOV", "kNXT", + "kOPT", "kPRV", "kPRT", "kRDO", "kRPL", "kRIT", "kRES", "kSAV", "kSPD", "kUND", "rfi", "_", "_", + "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", + "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", + "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", "_", + "dclk", "rmclk", "cwin", "wingo", "_", "dial", "qdial", "_", "_", "hook", "pause", "wait", "_", + "_", "_", "_", "_", "_", "_", "_", "_", "_", "op", "oc", "initc", "initp", "scp", "setf", + "setb", "cpi", "lpi", "chr", "cvr", "defc", "swidm", "sdrfq", "sitm", "slm", "smicm", "snlq", + "snrmq", "sshm", "ssubm", "ssupm", "sum", "rwidm", "ritm", "rlm", "rmicm", "rshm", "rsubm", + "rsupm", "rum", "mhpa", "mcud1", "mcub1", "mcuf1", "mvpa", "mcuu1", "porder", "mcud", "mcub", + "mcuf", "mcuu", "scs", "smgb", "smgbp", "smglp", "smgrp", "smgt", "smgtp", "sbim", "scsd", + "rbim", "rcsd", "subcs", "supcs", "docr", "zerom", "csnm", "kmous", "minfo", "reqmp", "getm", + "setaf", "setab", "pfxl", "devt", "csin", "s0ds", "s1ds", "s2ds", "s3ds", "smglr", "smgtb", + "birep", "binel", "bicr", "colornm", "defbi", "endbi", "setcolor", "slines", "dispc", "smpch", + "rmpch", "smsc", "rmsc", "pctrm", "scesc", "scesa", "ehhlm", "elhlm", "elohlm", "erhlm", + "ethlm", "evhlm", "sgr1", "slength", "OTi2", "OTrs", "OTnl", "OTbs", "OTko", "OTma", "OTG2", + "OTG3", "OTG1", "OTG4", "OTGR", "OTGL", "OTGU", "OTGD", "OTGH", "OTGV", "OTGC", "meml", "memu", + "box1"]; + +/// Parse a compiled terminfo entry, using long capability names if `longnames` is true +pub fn parse(file: @Reader, longnames: bool) -> Result<~TermInfo, ~str> { + let bnames; + let snames; + let nnames; + + if longnames { + bnames = boolfnames; + snames = stringfnames; + nnames = numfnames; + } else { + bnames = boolnames; + snames = stringnames; + nnames = numnames; + } + + // Check magic number + let magic = file.read_le_u16(); + if (magic != 0x011A) { + return Err(fmt!("invalid magic number: expected %x but found %x", 0x011A, magic as uint)); + } + + let names_bytes = file.read_le_i16() as int; + let bools_bytes = file.read_le_i16() as int; + let numbers_count = file.read_le_i16() as int; + let string_offsets_count = file.read_le_i16() as int; + let string_table_bytes = file.read_le_i16() as int; + + assert!(names_bytes > 0); + + debug!("names_bytes = %?", names_bytes); + debug!("bools_bytes = %?", bools_bytes); + debug!("numbers_count = %?", numbers_count); + debug!("string_offsets_count = %?", string_offsets_count); + debug!("string_table_bytes = %?", string_table_bytes); + + if (bools_bytes as uint) > boolnames.len() { + error!("expected bools_bytes to be less than %? but found %?", boolnames.len(), + bools_bytes); + return Err(~"incompatible file: more booleans than expected"); + } + + if (numbers_count as uint) > numnames.len() { + error!("expected numbers_count to be less than %? but found %?", numnames.len(), + numbers_count); + return Err(~"incompatible file: more numbers than expected"); + } + + if (string_offsets_count as uint) > stringnames.len() { + error!("expected string_offsets_count to be less than %? but found %?", stringnames.len(), + string_offsets_count); + return Err(~"incompatible file: more string offsets than expected"); + } + + let mut term_names: ~[~str] = vec::with_capacity(2); + let names_str = str::from_bytes(file.read_bytes(names_bytes as uint - 1)); // don't read NUL + for names_str.each_split_char('|') |s| { + term_names.push(s.to_owned()); + } + + file.read_byte(); // consume NUL + + debug!("term names: %?", term_names); + + let mut bools_map = HashMap::new(); + if bools_bytes != 0 { + for int::range(0, bools_bytes) |i| { + let b = file.read_byte(); + if b < 0 { + error!("EOF reading bools after %? entries", i); + return Err(~"error: expected more bools but hit EOF"); + } else if b == 1 { + debug!("%s set", bnames[i]); + bools_map.insert(bnames[i].to_owned(), true); + } + } + } + + debug!("bools: %?", bools_map); + + if (bools_bytes + names_bytes) % 2 == 1 { + debug!("adjusting for padding between bools and numbers"); + file.read_byte(); // compensate for padding + } + + let mut numbers_map = HashMap::new(); + if numbers_count != 0 { + for int::range(0, numbers_count) |i| { + let n = file.read_le_u16(); + if n != 0xFFFF { + debug!("%s#%?", nnames[i], n); + numbers_map.insert(nnames[i].to_owned(), n); + } + } + } + + debug!("numbers: %?", numbers_map); + + let mut string_map = HashMap::new(); + + if string_offsets_count != 0 { + let mut string_offsets = vec::with_capacity(10); + for int::range(0, string_offsets_count) |_i| { + string_offsets.push(file.read_le_u16()); + } + + debug!("offsets: %?", string_offsets); + + let string_table = file.read_bytes(string_table_bytes as uint); + + if string_table.len() != string_table_bytes as uint { + error!("EOF reading string table after %? bytes, wanted %?", string_table.len(), + string_table_bytes); + return Err(~"error: hit EOF before end of string table"); + } + + for string_offsets.eachi |i, v| { + let offset = *v; + if offset == 0xFFFF { // non-entry + loop; + } + + let name = if snames[i] == "_" { + stringfnames[i] + } else { + snames[i] + }; + + if offset == 0xFFFE { + // undocumented: FFFE indicates cap@, which means the capability is not present + // unsure if the handling for this is correct + string_map.insert(name.to_owned(), ~[]); + loop; + } + + + // Find the offset of the NUL we want to go to + let nulpos = vec::position_between(string_table, offset as uint, + string_table_bytes as uint, |&b| b == 0); + match nulpos { + Some(x) => { + string_map.insert(name.to_owned(), + string_table.slice(offset as uint, x).to_owned()) + }, + None => { + return Err(~"invalid file: missing NUL in string_table"); + } + }; + } + } + + // And that's all there is to it + Ok(~TermInfo {names: term_names, bools: bools_map, numbers: numbers_map, strings: string_map }) +} + +#[cfg(test)] +mod test { + use super::*; + use p = core::path::Path; + + #[test] + fn test_veclens() { + assert_eq!(boolfnames.len(), boolnames.len()); + assert_eq!(numfnames.len(), numnames.len()); + assert_eq!(stringfnames.len(), stringnames.len()); + } + + #[test] + #[ignore(reason = "no ncurses on buildbots, needs a bundled terminfo file to test against")] + fn test_parse() { + // FIXME #6870: Distribute a compiled file in src/tests and test there + // parse(io::file_reader(&p("/usr/share/terminfo/r/rxvt-256color")).unwrap(), false); + } +} diff --git a/src/libextra/terminfo/searcher.rs b/src/libextra/terminfo/searcher.rs new file mode 100644 index 0000000000000..d6577cf3b94db --- /dev/null +++ b/src/libextra/terminfo/searcher.rs @@ -0,0 +1,89 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/// Implement ncurses-compatible database discovery +/// Does not support hashed database, only filesystem! + +use core::prelude::*; +use core::{os, str}; +use core::os::getenv; +use core::io::{file_reader, Reader}; +use path = core::path::Path; + +/// Return path to database entry for `term` +pub fn get_dbpath_for_term(term: &str) -> Option<~path> { + if term.len() == 0 { + return None; + } + + let homedir = os::homedir(); + + let mut dirs_to_search = ~[]; + let first_char = term.substr(0, 1); + + // Find search directory + match getenv("TERMINFO") { + Some(dir) => dirs_to_search.push(path(dir)), + None => { + if homedir.is_some() { + dirs_to_search.push(homedir.unwrap().push(".terminfo")); // ncurses compatability + } + match getenv("TERMINFO_DIRS") { + Some(dirs) => for str::each_split_char(dirs, ':') |i| { + if i == "" { + dirs_to_search.push(path("/usr/share/terminfo")); + } else { + dirs_to_search.push(path(i.to_owned())); + } + }, + // Found nothing, use the default path + None => dirs_to_search.push(path("/usr/share/terminfo")) + } + } + }; + + // Look for the terminal in all of the search directories + for dirs_to_search.each |p| { + let newp = ~p.push_many(&[first_char.to_owned(), term.to_owned()]); + if os::path_exists(p) && os::path_exists(newp) { + return Some(newp); + } + } + None +} + +/// Return open file for `term` +pub fn open(term: &str) -> Result<@Reader, ~str> { + match get_dbpath_for_term(term) { + Some(x) => file_reader(x), + None => Err(fmt!("could not find terminfo entry for %s", term)) + } +} + +#[test] +#[ignore(reason = "buildbots don't have ncurses installed and I can't mock everything I need")] +fn test_get_dbpath_for_term() { + // woefully inadequate test coverage + use std::os::{setenv, unsetenv}; + fn x(t: &str) -> ~str { get_dbpath_for_term(t).expect("no terminfo entry found").to_str() }; + assert!(x("screen") == ~"/usr/share/terminfo/s/screen"); + assert!(get_dbpath_for_term("") == None); + setenv("TERMINFO_DIRS", ":"); + assert!(x("screen") == ~"/usr/share/terminfo/s/screen"); + unsetenv("TERMINFO_DIRS"); +} + +#[test] +#[ignore(reason = "see test_get_dbpath_for_term")] +fn test_open() { + open("screen"); + let t = open("nonexistent terminal that hopefully does not exist"); + assert!(t.is_err()); +} diff --git a/src/libextra/terminfo/terminfo.rs b/src/libextra/terminfo/terminfo.rs new file mode 100644 index 0000000000000..141a5b6bf7f9b --- /dev/null +++ b/src/libextra/terminfo/terminfo.rs @@ -0,0 +1,29 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::hashmap::HashMap; + +/// A parsed terminfo entry. +pub struct TermInfo { + /// Names for the terminal + names: ~[~str], + /// Map of capability name to boolean value + bools: HashMap<~str, bool>, + /// Map of capability name to numeric value + numbers: HashMap<~str, u16>, + /// Map of capability name to raw (unexpanded) string + strings: HashMap<~str, ~[u8]> +} + +pub mod searcher; +pub mod parser { + pub mod compiled; +} +pub mod parm; diff --git a/src/libstd/test.rs b/src/libextra/test.rs similarity index 90% rename from src/libstd/test.rs rename to src/libextra/test.rs index b2f73df316da3..6a9751b66e01e 100644 --- a/src/libstd/test.rs +++ b/src/libextra/test.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -15,12 +15,22 @@ // simplest interface possible for representing and running tests // while providing a base that other test frameworks may build off of. +use core::prelude::*; + use getopts; use sort; use term; -use core::to_str::ToStr; use core::comm::{stream, SharedChan}; +use core::either; +use core::io; +use core::option; +use core::result; +use core::str; +use core::task; +use core::to_str::ToStr; +use core::uint; +use core::vec; pub mod rustrt { use core::libc::size_t; @@ -131,12 +141,12 @@ type OptRes = Either; // Parses command line arguments into test options pub fn parse_opts(args: &[~str]) -> OptRes { let args_ = vec::tail(args); - let opts = ~[getopts::optflag(~"ignored"), - getopts::optflag(~"test"), - getopts::optflag(~"bench"), - getopts::optopt(~"save"), - getopts::optopt(~"diff"), - getopts::optopt(~"logfile")]; + let opts = ~[getopts::optflag("ignored"), + getopts::optflag("test"), + getopts::optflag("bench"), + getopts::optopt("save"), + getopts::optopt("diff"), + getopts::optopt("logfile")]; let matches = match getopts::getopts(args_, opts) { Ok(m) => m, @@ -148,19 +158,19 @@ pub fn parse_opts(args: &[~str]) -> OptRes { option::Some(copy (matches).free[0]) } else { option::None }; - let run_ignored = getopts::opt_present(&matches, ~"ignored"); + let run_ignored = getopts::opt_present(&matches, "ignored"); - let logfile = getopts::opt_maybe_str(&matches, ~"logfile"); + let logfile = getopts::opt_maybe_str(&matches, "logfile"); let logfile = logfile.map(|s| Path(*s)); - let run_benchmarks = getopts::opt_present(&matches, ~"bench"); + let run_benchmarks = getopts::opt_present(&matches, "bench"); let run_tests = ! run_benchmarks || - getopts::opt_present(&matches, ~"test"); + getopts::opt_present(&matches, "test"); - let save_results = getopts::opt_maybe_str(&matches, ~"save"); + let save_results = getopts::opt_maybe_str(&matches, "save"); let save_results = save_results.map(|s| Path(*s)); - let compare_results = getopts::opt_maybe_str(&matches, ~"diff"); + let compare_results = getopts::opt_maybe_str(&matches, "diff"); let compare_results = compare_results.map(|s| Path(*s)); let test_opts = TestOpts { @@ -200,7 +210,6 @@ struct ConsoleTestState { // A simple console test runner pub fn run_tests_console(opts: &TestOpts, tests: ~[TestDescAndFn]) -> bool { - fn callback(event: &TestEvent, st: &mut ConsoleTestState) { debug!("callback(event=%?)", event); match copy *event { @@ -211,7 +220,7 @@ pub fn run_tests_console(opts: &TestOpts, } TeWait(ref test) => st.out.write_str( fmt!("test %s ... ", test.name.to_str())), - TeResult(copy test, result) => { + TeResult(test, result) => { match st.log_out { Some(f) => write_log(f, copy result, &test), None => () @@ -220,18 +229,18 @@ pub fn run_tests_console(opts: &TestOpts, TrOk => { st.passed += 1; write_ok(st.out, st.use_color); - st.out.write_line(~""); + st.out.write_line(""); } TrFailed => { st.failed += 1; write_failed(st.out, st.use_color); - st.out.write_line(~""); + st.out.write_line(""); st.failures.push(test); } TrIgnored => { st.ignored += 1; write_ignored(st.out, st.use_color); - st.out.write_line(~""); + st.out.write_line(""); } TrBench(bs) => { st.benchmarked += 1u; @@ -246,8 +255,8 @@ pub fn run_tests_console(opts: &TestOpts, let log_out = match opts.logfile { Some(ref path) => match io::file_writer(path, - ~[io::Create, - io::Truncate]) { + [io::Create, + io::Truncate]) { result::Ok(w) => Some(w), result::Err(ref s) => { fail!("can't open output file: %s", *s) @@ -318,37 +327,43 @@ pub fn run_tests_console(opts: &TestOpts, } fn write_ok(out: @io::Writer, use_color: bool) { - write_pretty(out, ~"ok", term::color_green, use_color); + write_pretty(out, "ok", term::color_green, use_color); } fn write_failed(out: @io::Writer, use_color: bool) { - write_pretty(out, ~"FAILED", term::color_red, use_color); + write_pretty(out, "FAILED", term::color_red, use_color); } fn write_ignored(out: @io::Writer, use_color: bool) { - write_pretty(out, ~"ignored", term::color_yellow, use_color); + write_pretty(out, "ignored", term::color_yellow, use_color); } fn write_bench(out: @io::Writer, use_color: bool) { - write_pretty(out, ~"bench", term::color_cyan, use_color); + write_pretty(out, "bench", term::color_cyan, use_color); } fn write_pretty(out: @io::Writer, word: &str, color: u8, use_color: bool) { - if use_color && term::color_supported() { - term::fg(out, color); - } - out.write_str(word); - if use_color && term::color_supported() { - term::reset(out); + let t = term::Terminal::new(out); + match t { + Ok(term) => { + if use_color && term.color_supported { + term.fg(color); + } + out.write_str(word); + if use_color && term.color_supported { + term.reset(); + } + }, + Err(_) => out.write_str(word) } } } fn print_failures(st: &ConsoleTestState) { - st.out.write_line(~"\nfailures:"); + st.out.write_line("\nfailures:"); let mut failures = ~[]; for uint::range(0, vec::uniq_len(&const st.failures)) |i| { let name = copy st.failures[i].name; @@ -392,8 +407,8 @@ fn should_sort_failures_before_printing_them() { print_failures(st); }; - let apos = str::find_str(s, ~"a").get(); - let bpos = str::find_str(s, ~"b").get(); + let apos = str::find_str(s, "a").get(); + let bpos = str::find_str(s, "b").get(); assert!(apos < bpos); } @@ -492,9 +507,8 @@ pub fn filter_tests( filtered = if opts.filter.is_none() { filtered } else { - let filter_str = - match opts.filter { - option::Some(copy f) => f, + let filter_str = match opts.filter { + option::Some(ref f) => copy *f, option::None => ~"" }; @@ -554,7 +568,7 @@ pub fn run_test(force_ignore: bool, fn run_test_inner(desc: TestDesc, monitor_ch: SharedChan, testfn: ~fn()) { - let testfn_cell = ::core::cell::Cell(testfn); + let testfn_cell = ::core::cell::Cell::new(testfn); do task::spawn { let mut result_future = None; // task::future_result(builder); @@ -597,13 +611,18 @@ fn calc_result(desc: &TestDesc, task_succeeded: bool) -> TestResult { } pub mod bench { - use time::precise_time_ns; - use test::{BenchHarness, BenchSamples}; - use stats::Stats; - use core::rand::RngUtil; + use core::prelude::*; - pub impl BenchHarness { + use core::num; + use core::rand::RngUtil; + use core::rand; + use core::u64; + use core::vec; + use stats::Stats; + use test::{BenchHarness, BenchSamples}; + use time::precise_time_ns; + impl BenchHarness { /// Callback for benchmark functions to run in their body. pub fn iter(&mut self, inner:&fn()) { self.ns_start = precise_time_ns(); @@ -614,7 +633,7 @@ pub mod bench { self.ns_end = precise_time_ns(); } - fn ns_elapsed(&mut self) -> u64 { + pub fn ns_elapsed(&mut self) -> u64 { if self.ns_start == 0 || self.ns_end == 0 { 0 } else { @@ -622,7 +641,7 @@ pub mod bench { } } - fn ns_per_iter(&mut self) -> u64 { + pub fn ns_per_iter(&mut self) -> u64 { if self.iterations == 0 { 0 } else { @@ -630,7 +649,7 @@ pub mod bench { } } - fn bench_n(&mut self, n: u64, f: &fn(&mut BenchHarness)) { + pub fn bench_n(&mut self, n: u64, f: &fn(&mut BenchHarness)) { self.iterations = n; debug!("running benchmark for %u iterations", n as uint); @@ -804,7 +823,7 @@ mod tests { let ch = SharedChan::new(ch); run_test(false, desc, ch); let (_, res) = p.recv(); - assert!(res == TrIgnored); + assert_eq!(res, TrIgnored); } #[test] @@ -823,7 +842,7 @@ mod tests { let ch = SharedChan::new(ch); run_test(false, desc, ch); let (_, res) = p.recv(); - assert!(res == TrOk); + assert_eq!(res, TrOk); } #[test] @@ -841,14 +860,14 @@ mod tests { let ch = SharedChan::new(ch); run_test(false, desc, ch); let (_, res) = p.recv(); - assert!(res == TrFailed); + assert_eq!(res, TrFailed); } #[test] fn first_free_arg_should_be_a_filter() { let args = ~[~"progname", ~"filter"]; let opts = match parse_opts(args) { - either::Left(copy o) => o, + either::Left(o) => o, _ => fail!("Malformed arg in first_free_arg_should_be_a_filter") }; assert!("filter" == (copy opts.filter).get()); @@ -858,7 +877,7 @@ mod tests { fn parse_ignored_flag() { let args = ~[~"progname", ~"filter", ~"--ignored"]; let opts = match parse_opts(args) { - either::Left(copy o) => o, + either::Left(o) => o, _ => fail!("Malformed arg in parse_ignored_flag") }; assert!((opts.run_ignored)); @@ -901,9 +920,9 @@ mod tests { ]; let filtered = filter_tests(&opts, tests); - assert!(filtered.len() == 1); - assert!((filtered[0].desc.name.to_str() == ~"1")); - assert!((filtered[0].desc.ignore == false)); + assert_eq!(filtered.len(), 1); + assert_eq!(filtered[0].desc.name.to_str(), ~"1"); + assert!(filtered[0].desc.ignore == false); } #[test] @@ -958,7 +977,7 @@ mod tests { for pairs.each |p| { match *p { (ref a, ref b) => { - assert!((*a == b.desc.name.to_str())); + assert!(*a == b.desc.name.to_str()); } } } diff --git a/src/libstd/time.rs b/src/libextra/time.rs similarity index 82% rename from src/libstd/time.rs rename to src/libextra/time.rs index 202b96f9797aa..758181980a832 100644 --- a/src/libstd/time.rs +++ b/src/libextra/time.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,6 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[allow(missing_doc)]; + +use core::prelude::*; + +use core::i32; +use core::int; +use core::io; +use core::str; + static NSEC_PER_SEC: i32 = 1_000_000_000_i32; pub mod rustrt { @@ -20,11 +29,11 @@ pub mod rustrt { pub unsafe fn precise_time_ns(ns: &mut u64); pub unsafe fn rust_tzset(); - // FIXME: The i64 values can be passed by-val when #2064 is fixed. + pub unsafe fn rust_gmtime(sec: i64, nsec: i32, result: &mut Tm); pub unsafe fn rust_localtime(sec: i64, nsec: i32, result: &mut Tm); - pub unsafe fn rust_timegm(tm: &Tm, sec: &mut i64); - pub unsafe fn rust_mktime(tm: &Tm, sec: &mut i64); + pub unsafe fn rust_timegm(tm: &Tm) -> i64; + pub unsafe fn rust_mktime(tm: &Tm) -> i64; } } @@ -40,8 +49,8 @@ pub struct Timespec { sec: i64, nsec: i32 } * -1.2 seconds before the epoch is represented by `Timespec { sec: -2_i64, * nsec: 800_000_000_i32 }`. */ -pub impl Timespec { - fn new(sec: i64, nsec: i32) -> Timespec { +impl Timespec { + pub fn new(sec: i64, nsec: i32) -> Timespec { assert!(nsec >= 0 && nsec < NSEC_PER_SEC); Timespec { sec: sec, nsec: nsec } } @@ -171,27 +180,26 @@ pub fn strftime(format: &str, tm: &Tm) -> ~str { do_strftime(format, tm) } -pub impl Tm { +impl Tm { /// Convert time to the seconds from January 1, 1970 - fn to_timespec(&self) -> Timespec { + pub fn to_timespec(&self) -> Timespec { unsafe { - let mut sec = 0i64; - if self.tm_gmtoff == 0_i32 { - rustrt::rust_timegm(self, &mut sec); - } else { - rustrt::rust_mktime(self, &mut sec); - } + let sec = match self.tm_gmtoff { + 0_i32 => rustrt::rust_timegm(self), + _ => rustrt::rust_mktime(self) + }; + Timespec::new(sec, self.tm_nsec) } } /// Convert time to the local timezone - fn to_local(&self) -> Tm { + pub fn to_local(&self) -> Tm { at(self.to_timespec()) } /// Convert time to the UTC - fn to_utc(&self) -> Tm { + pub fn to_utc(&self) -> Tm { at_utc(self.to_timespec()) } @@ -199,10 +207,10 @@ pub impl Tm { * Return a string of the current time in the form * "Thu Jan 1 00:00:00 1970". */ - fn ctime(&self) -> ~str { self.strftime(~"%c") } + pub fn ctime(&self) -> ~str { self.strftime("%c") } /// Formats the time according to the format string. - fn strftime(&self, format: &str) -> ~str { + pub fn strftime(&self, format: &str) -> ~str { strftime(format, self) } @@ -212,11 +220,11 @@ pub impl Tm { * local: "Thu, 22 Mar 2012 07:53:18 PST" * utc: "Thu, 22 Mar 2012 14:53:18 UTC" */ - fn rfc822(&self) -> ~str { + pub fn rfc822(&self) -> ~str { if self.tm_gmtoff == 0_i32 { - self.strftime(~"%a, %d %b %Y %T GMT") + self.strftime("%a, %d %b %Y %T GMT") } else { - self.strftime(~"%a, %d %b %Y %T %Z") + self.strftime("%a, %d %b %Y %T %Z") } } @@ -226,8 +234,8 @@ pub impl Tm { * local: "Thu, 22 Mar 2012 07:53:18 -0700" * utc: "Thu, 22 Mar 2012 14:53:18 -0000" */ - fn rfc822z(&self) -> ~str { - self.strftime(~"%a, %d %b %Y %T %z") + pub fn rfc822z(&self) -> ~str { + self.strftime("%a, %d %b %Y %T %z") } /** @@ -236,11 +244,11 @@ pub impl Tm { * local: "2012-02-22T07:53:18-07:00" * utc: "2012-02-22T14:53:18Z" */ - fn rfc3339(&self) -> ~str { + pub fn rfc3339(&self) -> ~str { if self.tm_gmtoff == 0_i32 { - self.strftime(~"%Y-%m-%dT%H:%M:%SZ") + self.strftime("%Y-%m-%dT%H:%M:%SZ") } else { - let s = self.strftime(~"%Y-%m-%dT%H:%M:%S"); + let s = self.strftime("%Y-%m-%dT%H:%M:%S"); let sign = if self.tm_gmtoff > 0_i32 { '+' } else { '-' }; let mut m = i32::abs(self.tm_gmtoff) / 60_i32; let h = m / 60_i32; @@ -267,10 +275,12 @@ priv fn do_strptime(s: &str, format: &str) -> Result { let mut i = 0u; let len = strs.len(); while i < len { - let &(needle, value) = &strs[i]; - - if match_str(ss, pos, needle) { - return Some((value, pos + str::len(needle))); + match strs[i] { // can't use let due to stage0 bugs + (ref needle, value) => { + if match_str(ss, pos, *needle) { + return Some((value, pos + str::len(*needle))); + } + } } i += 1u; } @@ -285,7 +295,7 @@ priv fn do_strptime(s: &str, format: &str) -> Result { let mut i = 0u; while i < digits { - let range = str::char_range_at(str::to_owned(ss), pos); + let range = str::char_range_at(ss, pos); pos = range.next; match range.ch { @@ -326,7 +336,7 @@ priv fn do_strptime(s: &str, format: &str) -> Result { fn parse_type(s: &str, pos: uint, ch: char, tm: &mut Tm) -> Result { match ch { - 'A' => match match_strs(s, pos, ~[ + 'A' => match match_strs(s, pos, [ (~"Sunday", 0_i32), (~"Monday", 1_i32), (~"Tuesday", 2_i32), @@ -338,7 +348,7 @@ priv fn do_strptime(s: &str, format: &str) -> Result { Some(item) => { let (v, pos) = item; tm.tm_wday = v; Ok(pos) } None => Err(~"Invalid day") }, - 'a' => match match_strs(s, pos, ~[ + 'a' => match match_strs(s, pos, [ (~"Sun", 0_i32), (~"Mon", 1_i32), (~"Tue", 2_i32), @@ -350,7 +360,7 @@ priv fn do_strptime(s: &str, format: &str) -> Result { Some(item) => { let (v, pos) = item; tm.tm_wday = v; Ok(pos) } None => Err(~"Invalid day") }, - 'B' => match match_strs(s, pos, ~[ + 'B' => match match_strs(s, pos, [ (~"January", 0_i32), (~"February", 1_i32), (~"March", 2_i32), @@ -367,7 +377,7 @@ priv fn do_strptime(s: &str, format: &str) -> Result { Some(item) => { let (v, pos) = item; tm.tm_mon = v; Ok(pos) } None => Err(~"Invalid month") }, - 'b' | 'h' => match match_strs(s, pos, ~[ + 'b' | 'h' => match match_strs(s, pos, [ (~"Jan", 0_i32), (~"Feb", 1_i32), (~"Mar", 2_i32), @@ -488,13 +498,13 @@ priv fn do_strptime(s: &str, format: &str) -> Result { } 'n' => parse_char(s, pos, '\n'), 'P' => match match_strs(s, pos, - ~[(~"am", 0_i32), (~"pm", 12_i32)]) { + [(~"am", 0_i32), (~"pm", 12_i32)]) { Some(item) => { let (v, pos) = item; tm.tm_hour += v; Ok(pos) } None => Err(~"Invalid hour") }, 'p' => match match_strs(s, pos, - ~[(~"AM", 0_i32), (~"PM", 12_i32)]) { + [(~"AM", 0_i32), (~"PM", 12_i32)]) { Some(item) => { let (v, pos) = item; tm.tm_hour += v; Ok(pos) } None => Err(~"Invalid hour") @@ -579,7 +589,7 @@ priv fn do_strptime(s: &str, format: &str) -> Result { } } 'Z' => { - if match_str(s, pos, ~"UTC") || match_str(s, pos, ~"GMT") { + if match_str(s, pos, "UTC") || match_str(s, pos, "GMT") { tm.tm_gmtoff = 0_i32; tm.tm_zone = ~"UTC"; Ok(pos + 3u) @@ -624,7 +634,7 @@ priv fn do_strptime(s: &str, format: &str) -> Result { } } - do io::with_str_reader(str::to_owned(format)) |rdr| { + do io::with_str_reader(format) |rdr| { let mut tm = Tm { tm_sec: 0_i32, tm_min: 0_i32, @@ -836,7 +846,7 @@ priv fn do_strftime(format: &str, tm: &Tm) -> ~str { let mut buf = ~""; - do io::with_str_reader(str::to_owned(format)) |rdr| { + do io::with_str_reader(format) |rdr| { while !rdr.eof() { match rdr.read_char() { '%' => buf += parse_type(rdr.read_char(), tm), @@ -897,7 +907,7 @@ mod tests { } fn test_at_utc() { - os::setenv(~"TZ", ~"America/Los_Angeles"); + os::setenv("TZ", "America/Los_Angeles"); tzset(); let time = ::time::Timespec::new(1234567890, 54321); @@ -918,7 +928,7 @@ mod tests { } fn test_at() { - os::setenv(~"TZ", ~"America/Los_Angeles"); + os::setenv("TZ", "America/Los_Angeles"); tzset(); let time = ::time::Timespec::new(1234567890, 54321); @@ -946,18 +956,18 @@ mod tests { } fn test_to_timespec() { - os::setenv(~"TZ", ~"America/Los_Angeles"); + os::setenv("TZ", "America/Los_Angeles"); tzset(); let time = ::time::Timespec::new(1234567890, 54321); let utc = at_utc(time); - assert!(utc.to_timespec() == time); - assert!(utc.to_local().to_timespec() == time); + assert_eq!(utc.to_timespec(), time); + assert_eq!(utc.to_local().to_timespec(), time); } fn test_conversions() { - os::setenv(~"TZ", ~"America/Los_Angeles"); + os::setenv("TZ", "America/Los_Angeles"); tzset(); let time = ::time::Timespec::new(1234567890, 54321); @@ -973,10 +983,10 @@ mod tests { } fn test_strptime() { - os::setenv(~"TZ", ~"America/Los_Angeles"); + os::setenv("TZ", "America/Los_Angeles"); tzset(); - match strptime(~"", ~"") { + match strptime("", "") { Ok(ref tm) => { assert!(tm.tm_sec == 0_i32); assert!(tm.tm_min == 0_i32); @@ -985,7 +995,7 @@ mod tests { assert!(tm.tm_mon == 0_i32); assert!(tm.tm_year == 0_i32); assert!(tm.tm_wday == 0_i32); - assert!(tm.tm_isdst== 0_i32); + assert!(tm.tm_isdst == 0_i32); assert!(tm.tm_gmtoff == 0_i32); assert!(tm.tm_zone == ~""); assert!(tm.tm_nsec == 0_i32); @@ -993,13 +1003,13 @@ mod tests { Err(_) => () } - let format = ~"%a %b %e %T %Y"; - assert!(strptime(~"", format) == Err(~"Invalid time")); - assert!(strptime(~"Fri Feb 13 15:31:30", format) + let format = "%a %b %e %T %Y"; + assert_eq!(strptime("", format), Err(~"Invalid time")); + assert!(strptime("Fri Feb 13 15:31:30", format) == Err(~"Invalid time")); - match strptime(~"Fri Feb 13 15:31:30 2009", format) { - Err(copy e) => fail!(e), + match strptime("Fri Feb 13 15:31:30 2009", format) { + Err(e) => fail!(e), Ok(ref tm) => { assert!(tm.tm_sec == 30_i32); assert!(tm.tm_min == 31_i32); @@ -1019,7 +1029,7 @@ mod tests { fn test(s: &str, format: &str) -> bool { match strptime(s, format) { Ok(ref tm) => tm.strftime(format) == str::to_owned(s), - Err(copy e) => fail!(e) + Err(e) => fail!(e) } } @@ -1032,7 +1042,7 @@ mod tests { ~"Friday", ~"Saturday" ].each |day| { - assert!(test(*day, ~"%A")); + assert!(test(*day, "%A")); } for [ @@ -1044,7 +1054,7 @@ mod tests { ~"Fri", ~"Sat" ].each |day| { - assert!(test(*day, ~"%a")); + assert!(test(*day, "%a")); } for [ @@ -1061,7 +1071,7 @@ mod tests { ~"November", ~"December" ].each |day| { - assert!(test(*day, ~"%B")); + assert!(test(*day, "%B")); } for [ @@ -1078,60 +1088,60 @@ mod tests { ~"Nov", ~"Dec" ].each |day| { - assert!(test(*day, ~"%b")); + assert!(test(*day, "%b")); } - assert!(test(~"19", ~"%C")); - assert!(test(~"Fri Feb 13 23:31:30 2009", ~"%c")); - assert!(test(~"02/13/09", ~"%D")); - assert!(test(~"03", ~"%d")); - assert!(test(~"13", ~"%d")); - assert!(test(~" 3", ~"%e")); - assert!(test(~"13", ~"%e")); - assert!(test(~"2009-02-13", ~"%F")); - assert!(test(~"03", ~"%H")); - assert!(test(~"13", ~"%H")); - assert!(test(~"03", ~"%I")); // FIXME (#2350): flesh out - assert!(test(~"11", ~"%I")); // FIXME (#2350): flesh out - assert!(test(~"044", ~"%j")); - assert!(test(~" 3", ~"%k")); - assert!(test(~"13", ~"%k")); - assert!(test(~" 1", ~"%l")); - assert!(test(~"11", ~"%l")); - assert!(test(~"03", ~"%M")); - assert!(test(~"13", ~"%M")); - assert!(test(~"\n", ~"%n")); - assert!(test(~"am", ~"%P")); - assert!(test(~"pm", ~"%P")); - assert!(test(~"AM", ~"%p")); - assert!(test(~"PM", ~"%p")); - assert!(test(~"23:31", ~"%R")); - assert!(test(~"11:31:30 AM", ~"%r")); - assert!(test(~"11:31:30 PM", ~"%r")); - assert!(test(~"03", ~"%S")); - assert!(test(~"13", ~"%S")); - assert!(test(~"15:31:30", ~"%T")); - assert!(test(~"\t", ~"%t")); - assert!(test(~"1", ~"%u")); - assert!(test(~"7", ~"%u")); - assert!(test(~"13-Feb-2009", ~"%v")); - assert!(test(~"0", ~"%w")); - assert!(test(~"6", ~"%w")); - assert!(test(~"2009", ~"%Y")); - assert!(test(~"09", ~"%y")); - assert!(result::unwrap(strptime(~"UTC", ~"%Z")).tm_zone == + assert!(test("19", "%C")); + assert!(test("Fri Feb 13 23:31:30 2009", "%c")); + assert!(test("02/13/09", "%D")); + assert!(test("03", "%d")); + assert!(test("13", "%d")); + assert!(test(" 3", "%e")); + assert!(test("13", "%e")); + assert!(test("2009-02-13", "%F")); + assert!(test("03", "%H")); + assert!(test("13", "%H")); + assert!(test("03", "%I")); // FIXME (#2350): flesh out + assert!(test("11", "%I")); // FIXME (#2350): flesh out + assert!(test("044", "%j")); + assert!(test(" 3", "%k")); + assert!(test("13", "%k")); + assert!(test(" 1", "%l")); + assert!(test("11", "%l")); + assert!(test("03", "%M")); + assert!(test("13", "%M")); + assert!(test("\n", "%n")); + assert!(test("am", "%P")); + assert!(test("pm", "%P")); + assert!(test("AM", "%p")); + assert!(test("PM", "%p")); + assert!(test("23:31", "%R")); + assert!(test("11:31:30 AM", "%r")); + assert!(test("11:31:30 PM", "%r")); + assert!(test("03", "%S")); + assert!(test("13", "%S")); + assert!(test("15:31:30", "%T")); + assert!(test("\t", "%t")); + assert!(test("1", "%u")); + assert!(test("7", "%u")); + assert!(test("13-Feb-2009", "%v")); + assert!(test("0", "%w")); + assert!(test("6", "%w")); + assert!(test("2009", "%Y")); + assert!(test("09", "%y")); + assert!(result::unwrap(strptime("UTC", "%Z")).tm_zone == ~"UTC"); - assert!(result::unwrap(strptime(~"PST", ~"%Z")).tm_zone == + assert!(result::unwrap(strptime("PST", "%Z")).tm_zone == ~""); - assert!(result::unwrap(strptime(~"-0000", ~"%z")).tm_gmtoff == + assert!(result::unwrap(strptime("-0000", "%z")).tm_gmtoff == 0); - assert!(result::unwrap(strptime(~"-0800", ~"%z")).tm_gmtoff == + assert!(result::unwrap(strptime("-0800", "%z")).tm_gmtoff == 0); - assert!(test(~"%", ~"%%")); + assert!(test("%", "%%")); } fn test_ctime() { - os::setenv(~"TZ", ~"America/Los_Angeles"); + os::setenv("TZ", "America/Los_Angeles"); tzset(); let time = ::time::Timespec::new(1234567890, 54321); @@ -1140,81 +1150,81 @@ mod tests { error!("test_ctime: %? %?", utc.ctime(), local.ctime()); - assert!(utc.ctime() == ~"Fri Feb 13 23:31:30 2009"); - assert!(local.ctime() == ~"Fri Feb 13 15:31:30 2009"); + assert_eq!(utc.ctime(), ~"Fri Feb 13 23:31:30 2009"); + assert_eq!(local.ctime(), ~"Fri Feb 13 15:31:30 2009"); } fn test_strftime() { - os::setenv(~"TZ", ~"America/Los_Angeles"); + os::setenv("TZ", "America/Los_Angeles"); tzset(); let time = ::time::Timespec::new(1234567890, 54321); let utc = at_utc(time); let local = at(time); - assert!(local.strftime(~"") == ~""); - assert!(local.strftime(~"%A") == ~"Friday"); - assert!(local.strftime(~"%a") == ~"Fri"); - assert!(local.strftime(~"%B") == ~"February"); - assert!(local.strftime(~"%b") == ~"Feb"); - assert!(local.strftime(~"%C") == ~"20"); - assert!(local.strftime(~"%c") == ~"Fri Feb 13 15:31:30 2009"); - assert!(local.strftime(~"%D") == ~"02/13/09"); - assert!(local.strftime(~"%d") == ~"13"); - assert!(local.strftime(~"%e") == ~"13"); - assert!(local.strftime(~"%F") == ~"2009-02-13"); + assert_eq!(local.strftime(""), ~""); + assert_eq!(local.strftime("%A"), ~"Friday"); + assert_eq!(local.strftime("%a"), ~"Fri"); + assert_eq!(local.strftime("%B"), ~"February"); + assert_eq!(local.strftime("%b"), ~"Feb"); + assert_eq!(local.strftime("%C"), ~"20"); + assert_eq!(local.strftime("%c"), ~"Fri Feb 13 15:31:30 2009"); + assert_eq!(local.strftime("%D"), ~"02/13/09"); + assert_eq!(local.strftime("%d"), ~"13"); + assert_eq!(local.strftime("%e"), ~"13"); + assert_eq!(local.strftime("%F"), ~"2009-02-13"); // assert!(local.strftime("%G") == "2009"); // assert!(local.strftime("%g") == "09"); - assert!(local.strftime(~"%H") == ~"15"); - assert!(local.strftime(~"%I") == ~"03"); - assert!(local.strftime(~"%j") == ~"044"); - assert!(local.strftime(~"%k") == ~"15"); - assert!(local.strftime(~"%l") == ~" 3"); - assert!(local.strftime(~"%M") == ~"31"); - assert!(local.strftime(~"%m") == ~"02"); - assert!(local.strftime(~"%n") == ~"\n"); - assert!(local.strftime(~"%P") == ~"pm"); - assert!(local.strftime(~"%p") == ~"PM"); - assert!(local.strftime(~"%R") == ~"15:31"); - assert!(local.strftime(~"%r") == ~"03:31:30 PM"); - assert!(local.strftime(~"%S") == ~"30"); - assert!(local.strftime(~"%s") == ~"1234567890"); - assert!(local.strftime(~"%T") == ~"15:31:30"); - assert!(local.strftime(~"%t") == ~"\t"); + assert_eq!(local.strftime("%H"), ~"15"); + assert_eq!(local.strftime("%I"), ~"03"); + assert_eq!(local.strftime("%j"), ~"044"); + assert_eq!(local.strftime("%k"), ~"15"); + assert_eq!(local.strftime("%l"), ~" 3"); + assert_eq!(local.strftime("%M"), ~"31"); + assert_eq!(local.strftime("%m"), ~"02"); + assert_eq!(local.strftime("%n"), ~"\n"); + assert_eq!(local.strftime("%P"), ~"pm"); + assert_eq!(local.strftime("%p"), ~"PM"); + assert_eq!(local.strftime("%R"), ~"15:31"); + assert_eq!(local.strftime("%r"), ~"03:31:30 PM"); + assert_eq!(local.strftime("%S"), ~"30"); + assert_eq!(local.strftime("%s"), ~"1234567890"); + assert_eq!(local.strftime("%T"), ~"15:31:30"); + assert_eq!(local.strftime("%t"), ~"\t"); // assert!(local.strftime("%U") == "06"); - assert!(local.strftime(~"%u") == ~"5"); + assert_eq!(local.strftime("%u"), ~"5"); // assert!(local.strftime("%V") == "07"); - assert!(local.strftime(~"%v") == ~"13-Feb-2009"); + assert_eq!(local.strftime("%v"), ~"13-Feb-2009"); // assert!(local.strftime("%W") == "06"); - assert!(local.strftime(~"%w") == ~"5"); + assert_eq!(local.strftime("%w"), ~"5"); // handle "%X" // handle "%x" - assert!(local.strftime(~"%Y") == ~"2009"); - assert!(local.strftime(~"%y") == ~"09"); + assert_eq!(local.strftime("%Y"), ~"2009"); + assert_eq!(local.strftime("%y"), ~"09"); // FIXME (#2350): We should probably standardize on the timezone // abbreviation. - let zone = local.strftime(~"%Z"); + let zone = local.strftime("%Z"); assert!(zone == ~"PST" || zone == ~"Pacific Standard Time"); - assert!(local.strftime(~"%z") == ~"-0800"); - assert!(local.strftime(~"%%") == ~"%"); + assert_eq!(local.strftime("%z"), ~"-0800"); + assert_eq!(local.strftime("%%"), ~"%"); // FIXME (#2350): We should probably standardize on the timezone // abbreviation. let rfc822 = local.rfc822(); let prefix = ~"Fri, 13 Feb 2009 15:31:30 "; - assert!(rfc822 == prefix + ~"PST" || - rfc822 == prefix + ~"Pacific Standard Time"); + assert!(rfc822 == prefix + "PST" || + rfc822 == prefix + "Pacific Standard Time"); - assert!(local.ctime() == ~"Fri Feb 13 15:31:30 2009"); - assert!(local.rfc822z() == ~"Fri, 13 Feb 2009 15:31:30 -0800"); - assert!(local.rfc3339() == ~"2009-02-13T15:31:30-08:00"); + assert_eq!(local.ctime(), ~"Fri Feb 13 15:31:30 2009"); + assert_eq!(local.rfc822z(), ~"Fri, 13 Feb 2009 15:31:30 -0800"); + assert_eq!(local.rfc3339(), ~"2009-02-13T15:31:30-08:00"); - assert!(utc.ctime() == ~"Fri Feb 13 23:31:30 2009"); - assert!(utc.rfc822() == ~"Fri, 13 Feb 2009 23:31:30 GMT"); - assert!(utc.rfc822z() == ~"Fri, 13 Feb 2009 23:31:30 -0000"); - assert!(utc.rfc3339() == ~"2009-02-13T23:31:30Z"); + assert_eq!(utc.ctime(), ~"Fri Feb 13 23:31:30 2009"); + assert_eq!(utc.rfc822(), ~"Fri, 13 Feb 2009 23:31:30 GMT"); + assert_eq!(utc.rfc822z(), ~"Fri, 13 Feb 2009 23:31:30 -0000"); + assert_eq!(utc.rfc3339(), ~"2009-02-13T23:31:30Z"); } fn test_timespec_eq_ord() { diff --git a/src/libstd/timer.rs b/src/libextra/timer.rs similarity index 95% rename from src/libstd/timer.rs rename to src/libextra/timer.rs index e9fd0414244e8..f251336666309 100644 --- a/src/libstd/timer.rs +++ b/src/libextra/timer.rs @@ -10,6 +10,8 @@ //! Utilities that leverage libuv's `uv_timer_*` API +use core::prelude::*; + use uv; use uv::iotask; use uv::iotask::IoTask; @@ -17,6 +19,7 @@ use uv::iotask::IoTask; use core::cast::transmute; use core::cast; use core::comm::{stream, Chan, SharedChan, Port, select2i}; +use core::either; use core::libc::c_void; use core::libc; @@ -173,11 +176,16 @@ extern fn delayed_send_close_cb(handle: *uv::ll::uv_timer_t) { #[cfg(test)] mod test { + use core::prelude::*; + use timer::*; use uv; + use core::cell::Cell; - use core::rand::RngUtil; use core::pipes::{stream, SharedChan}; + use core::rand::RngUtil; + use core::rand; + use core::task; #[test] fn test_gl_timer_simple_sleep_test() { @@ -188,7 +196,7 @@ mod test { #[test] fn test_gl_timer_sleep_stress1() { let hl_loop = &uv::global_loop::get(); - for old_iter::repeat(50u) { + for 50u.times { sleep(hl_loop, 1u); } } @@ -208,8 +216,7 @@ mod test { }; - for old_iter::repeat(repeat) { - + for repeat.times { let ch = ch.clone(); for spec.each |spec| { let (times, maxms) = *spec; @@ -218,7 +225,7 @@ mod test { do task::spawn { use core::rand::*; let mut rng = rng(); - for old_iter::repeat(times) { + for times.times { sleep(&hl_loop_clone, rng.next() as uint % maxms); } ch.send(()); @@ -226,7 +233,7 @@ mod test { } } - for old_iter::repeat(repeat * spec.len()) { + for (repeat * spec.len()).times { po.recv() } } @@ -244,7 +251,7 @@ mod test { let mut failures = 0; let hl_loop = uv::global_loop::get(); - for old_iter::repeat(times as uint) { + for (times as uint).times { task::yield(); let expected = rand::rng().gen_str(16u); @@ -256,7 +263,7 @@ mod test { match recv_timeout(hl_loop, 10u, &test_po) { Some(val) => { - assert!(val == expected); + assert_eq!(val, expected); successes += 1; } _ => failures += 1 @@ -273,9 +280,9 @@ mod test { let mut failures = 0; let hl_loop = uv::global_loop::get(); - for old_iter::repeat(times as uint) { + for (times as uint).times { let mut rng = rand::rng(); - let expected = Cell(rng.gen_str(16u)); + let expected = Cell::new(rng.gen_str(16u)); let (test_po, test_ch) = stream::<~str>(); let hl_loop_clone = hl_loop.clone(); do task::spawn() { diff --git a/src/libstd/treemap.rs b/src/libextra/treemap.rs similarity index 80% rename from src/libstd/treemap.rs rename to src/libextra/treemap.rs index e0ee3a1ee01c4..c39984791689c 100644 --- a/src/libstd/treemap.rs +++ b/src/libextra/treemap.rs @@ -12,7 +12,10 @@ //! trees. The only requirement for the types is that the key implements //! `TotalOrd`. +use core::prelude::*; + use core::iterator::*; +use core::uint; use core::util::{swap, replace}; // This is implemented as an AA tree, which is a simplified variation of @@ -31,6 +34,7 @@ use core::util::{swap, replace}; // * union: | // These would be convenient since the methods work like `each` +#[allow(missing_doc)] pub struct TreeMap { priv root: Option<~TreeNode>, priv length: uint @@ -105,45 +109,21 @@ impl Map for TreeMap { } /// Visit all key-value pairs in order - #[cfg(stage0)] - fn each<'a>(&'a self, f: &fn(&'a K, &'a V) -> bool) { - each(&self.root, f); - } - /// Visit all key-value pairs in order - #[cfg(not(stage0))] fn each<'a>(&'a self, f: &fn(&'a K, &'a V) -> bool) -> bool { each(&self.root, f) } /// Visit all keys in order - #[cfg(stage0)] - fn each_key(&self, f: &fn(&K) -> bool) { - self.each(|k, _| f(k)) - } - /// Visit all keys in order - #[cfg(not(stage0))] fn each_key(&self, f: &fn(&K) -> bool) -> bool { self.each(|k, _| f(k)) } /// Visit all values in order - #[cfg(stage0)] - fn each_value<'a>(&'a self, f: &fn(&'a V) -> bool) { - self.each(|_, v| f(v)) - } - /// Visit all values in order - #[cfg(not(stage0))] fn each_value<'a>(&'a self, f: &fn(&'a V) -> bool) -> bool { self.each(|_, v| f(v)) } /// Iterate over the map and mutate the contained values - #[cfg(stage0)] - fn mutate_values(&mut self, f: &fn(&K, &mut V) -> bool) { - mutate_values(&mut self.root, f); - } - /// Iterate over the map and mutate the contained values - #[cfg(not(stage0))] fn mutate_values(&mut self, f: &fn(&K, &mut V) -> bool) -> bool { mutate_values(&mut self.root, f) } @@ -201,55 +181,28 @@ impl Map for TreeMap { } } -#[cfg(stage0)] -pub impl TreeMap { +impl TreeMap { /// Create an empty TreeMap - fn new() -> TreeMap { TreeMap{root: None, length: 0} } + pub fn new() -> TreeMap { TreeMap{root: None, length: 0} } /// Visit all key-value pairs in reverse order - fn each_reverse<'a>(&'a self, f: &fn(&'a K, &'a V) -> bool) { - each_reverse(&self.root, f); - } - - /// Visit all keys in reverse order - fn each_key_reverse(&self, f: &fn(&K) -> bool) { - self.each_reverse(|k, _| f(k)) - } - - /// Visit all values in reverse order - fn each_value_reverse(&self, f: &fn(&V) -> bool) { - self.each_reverse(|_, v| f(v)) - } - - /// Get a lazy iterator over the key-value pairs in the map. - /// Requires that it be frozen (immutable). - fn iter<'a>(&'a self) -> TreeMapIterator<'a, K, V> { - TreeMapIterator{stack: ~[], node: &self.root} - } -} -#[cfg(not(stage0))] -pub impl TreeMap { - /// Create an empty TreeMap - fn new() -> TreeMap { TreeMap{root: None, length: 0} } - - /// Visit all key-value pairs in reverse order - fn each_reverse<'a>(&'a self, f: &fn(&'a K, &'a V) -> bool) -> bool { + pub fn each_reverse<'a>(&'a self, f: &fn(&'a K, &'a V) -> bool) -> bool { each_reverse(&self.root, f) } /// Visit all keys in reverse order - fn each_key_reverse(&self, f: &fn(&K) -> bool) -> bool { + pub fn each_key_reverse(&self, f: &fn(&K) -> bool) -> bool { self.each_reverse(|k, _| f(k)) } /// Visit all values in reverse order - fn each_value_reverse(&self, f: &fn(&V) -> bool) -> bool { + pub fn each_value_reverse(&self, f: &fn(&V) -> bool) -> bool { self.each_reverse(|_, v| f(v)) } /// Get a lazy iterator over the key-value pairs in the map. /// Requires that it be frozen (immutable). - fn iter<'a>(&'a self) -> TreeMapIterator<'a, K, V> { + pub fn iter<'a>(&'a self) -> TreeMapIterator<'a, K, V> { TreeMapIterator{stack: ~[], node: &self.root} } } @@ -290,6 +243,9 @@ impl<'self, T> Iterator<&'self T> for TreeSetIterator<'self, T> { } } +/// A implementation of the `Set` trait on top of the `TreeMap` container. The +/// only requirement is that the type of the elements contained ascribes to the +/// `TotalOrd` trait. pub struct TreeSet { priv map: TreeMap } @@ -297,11 +253,6 @@ pub struct TreeSet { impl BaseIter for TreeSet { /// Visit all values in order #[inline(always)] - #[cfg(stage0)] - fn each(&self, f: &fn(&T) -> bool) { self.map.each_key(f) } - /// Visit all values in order - #[inline(always)] - #[cfg(not(stage0))] fn each(&self, f: &fn(&T) -> bool) -> bool { self.map.each_key(f) } #[inline(always)] fn size_hint(&self) -> Option { Some(self.len()) } @@ -309,13 +260,6 @@ impl BaseIter for TreeSet { impl ReverseIter for TreeSet { /// Visit all values in reverse order - #[cfg(stage0)] - #[inline(always)] - fn each_reverse(&self, f: &fn(&T) -> bool) { - self.map.each_key_reverse(f) - } - /// Visit all values in reverse order - #[cfg(not(stage0))] #[inline(always)] fn each_reverse(&self, f: &fn(&T) -> bool) -> bool { self.map.each_key_reverse(f) @@ -424,37 +368,6 @@ impl Set for TreeSet { } /// Visit the values (in-order) representing the difference - #[cfg(stage0)] - fn difference(&self, other: &TreeSet, f: &fn(&T) -> bool) { - let mut x = self.iter(); - let mut y = other.iter(); - - let mut a = x.next(); - let mut b = y.next(); - - while a.is_some() { - if b.is_none() { - return do a.while_some() |a1| { - if f(a1) { x.next() } else { None } - } - } - - let a1 = a.unwrap(); - let b1 = b.unwrap(); - - let cmp = a1.cmp(b1); - - if cmp == Less { - if !f(a1) { return } - a = x.next(); - } else { - if cmp == Equal { a = x.next() } - b = y.next(); - } - } - } - /// Visit the values (in-order) representing the difference - #[cfg(not(stage0))] fn difference(&self, other: &TreeSet, f: &fn(&T) -> bool) -> bool { let mut x = self.iter(); let mut y = other.iter(); @@ -484,45 +397,6 @@ impl Set for TreeSet { } /// Visit the values (in-order) representing the symmetric difference - #[cfg(stage0)] - fn symmetric_difference(&self, other: &TreeSet, - f: &fn(&T) -> bool) { - let mut x = self.iter(); - let mut y = other.iter(); - - let mut a = x.next(); - let mut b = y.next(); - - while a.is_some() { - if b.is_none() { - return do a.while_some() |a1| { - if f(a1) { x.next() } else { None } - } - } - - let a1 = a.unwrap(); - let b1 = b.unwrap(); - - let cmp = a1.cmp(b1); - - if cmp == Less { - if !f(a1) { return } - a = x.next(); - } else { - if cmp == Greater { - if !f(b1) { return } - } else { - a = x.next(); - } - b = y.next(); - } - } - do b.while_some |b1| { - if f(b1) { y.next() } else { None } - } - } - /// Visit the values (in-order) representing the symmetric difference - #[cfg(not(stage0))] fn symmetric_difference(&self, other: &TreeSet, f: &fn(&T) -> bool) -> bool { let mut x = self.iter(); @@ -557,32 +431,6 @@ impl Set for TreeSet { } /// Visit the values (in-order) representing the intersection - #[cfg(stage0)] - fn intersection(&self, other: &TreeSet, f: &fn(&T) -> bool) { - let mut x = self.iter(); - let mut y = other.iter(); - - let mut a = x.next(); - let mut b = y.next(); - - while a.is_some() && b.is_some() { - let a1 = a.unwrap(); - let b1 = b.unwrap(); - - let cmp = a1.cmp(b1); - - if cmp == Less { - a = x.next(); - } else { - if cmp == Equal { - if !f(a1) { return } - } - b = y.next(); - } - } - } - /// Visit the values (in-order) representing the intersection - #[cfg(not(stage0))] fn intersection(&self, other: &TreeSet, f: &fn(&T) -> bool) -> bool { let mut x = self.iter(); let mut y = other.iter(); @@ -609,43 +457,6 @@ impl Set for TreeSet { } /// Visit the values (in-order) representing the union - #[cfg(stage0)] - fn union(&self, other: &TreeSet, f: &fn(&T) -> bool) { - let mut x = self.iter(); - let mut y = other.iter(); - - let mut a = x.next(); - let mut b = y.next(); - - while a.is_some() { - if b.is_none() { - return do a.while_some() |a1| { - if f(a1) { x.next() } else { None } - } - } - - let a1 = a.unwrap(); - let b1 = b.unwrap(); - - let cmp = a1.cmp(b1); - - if cmp == Greater { - if !f(b1) { return } - b = y.next(); - } else { - if !f(a1) { return } - if cmp == Equal { - b = y.next(); - } - a = x.next(); - } - } - do b.while_some |b1| { - if f(b1) { y.next() } else { None } - } - } - /// Visit the values (in-order) representing the union - #[cfg(not(stage0))] fn union(&self, other: &TreeSet, f: &fn(&T) -> bool) -> bool { let mut x = self.iter(); let mut y = other.iter(); @@ -678,15 +489,15 @@ impl Set for TreeSet { } } -pub impl TreeSet { +impl TreeSet { /// Create an empty TreeSet #[inline(always)] - fn new() -> TreeSet { TreeSet{map: TreeMap::new()} } + pub fn new() -> TreeSet { TreeSet{map: TreeMap::new()} } /// Get a lazy iterator over the values in the set. /// Requires that it be frozen (immutable). #[inline(always)] - fn iter<'a>(&'a self) -> TreeSetIterator<'a, T> { + pub fn iter<'a>(&'a self) -> TreeSetIterator<'a, T> { TreeSetIterator{iter: self.map.iter()} } } @@ -706,31 +517,20 @@ struct TreeNode { level: uint } -pub impl TreeNode { +impl TreeNode { + /// Creates a new tree node. #[inline(always)] - fn new(key: K, value: V) -> TreeNode { + pub fn new(key: K, value: V) -> TreeNode { TreeNode{key: key, value: value, left: None, right: None, level: 1} } } -#[cfg(stage0)] -fn each<'r, K: TotalOrd, V>(_: &'r Option<~TreeNode>, - _: &fn(&'r K, &'r V) -> bool) -> bool { - fail!("don't use me in stage0!") -} -#[cfg(not(stage0))] fn each<'r, K: TotalOrd, V>(node: &'r Option<~TreeNode>, f: &fn(&'r K, &'r V) -> bool) -> bool { node.each(|x| each(&x.left, f) && f(&x.key, &x.value) && each(&x.right, f)) } -#[cfg(stage0)] -fn each_reverse<'r, K: TotalOrd, V>(_: &'r Option<~TreeNode>, - _: &fn(&'r K, &'r V) -> bool) -> bool { - fail!("don't use me in stage0!") -} -#[cfg(not(stage0))] fn each_reverse<'r, K: TotalOrd, V>(node: &'r Option<~TreeNode>, f: &fn(&'r K, &'r V) -> bool) -> bool { node.each(|x| each_reverse(&x.right, f) && f(&x.key, &x.value) && @@ -905,9 +705,15 @@ fn remove(node: &mut Option<~TreeNode>, #[cfg(test)] mod test_treemap { - use core::iterator::*; + use core::prelude::*; + use super::*; + + use core::iterator::*; use core::rand::RngUtil; + use core::rand; + use core::str; + use core::vec; #[test] fn find_empty() { @@ -920,7 +726,7 @@ mod test_treemap { assert!(m.insert(1, 2)); assert!(m.insert(5, 3)); assert!(m.insert(9, 3)); - assert!(m.find(&2) == None); + assert_eq!(m.find(&2), None); } #[test] @@ -942,7 +748,7 @@ mod test_treemap { assert!(m.insert(5, 2)); assert!(m.insert(2, 9)); assert!(!m.insert(2, 11)); - assert!(m.find(&2).unwrap() == &11); + assert_eq!(m.find(&2).unwrap(), &11); } #[test] @@ -963,21 +769,21 @@ mod test_treemap { fn u8_map() { let mut m = TreeMap::new(); - let k1 = str::to_bytes(~"foo"); - let k2 = str::to_bytes(~"bar"); - let v1 = str::to_bytes(~"baz"); - let v2 = str::to_bytes(~"foobar"); + let k1 = str::to_bytes("foo"); + let k2 = str::to_bytes("bar"); + let v1 = str::to_bytes("baz"); + let v2 = str::to_bytes("foobar"); m.insert(copy k1, copy v1); m.insert(copy k2, copy v2); - assert!(m.find(&k2) == Some(&v2)); - assert!(m.find(&k1) == Some(&v1)); + assert_eq!(m.find(&k2), Some(&v2)); + assert_eq!(m.find(&k1), Some(&v1)); } fn check_equal(ctrl: &[(K, V)], map: &TreeMap) { - assert!(ctrl.is_empty() == map.is_empty()); + assert_eq!(ctrl.is_empty(), map.is_empty()); for ctrl.each |x| { let &(k, v) = x; assert!(map.find(&k).unwrap() == &v) @@ -1000,7 +806,7 @@ mod test_treemap { parent: &~TreeNode) { match *node { Some(ref r) => { - assert!(r.key.cmp(&parent.key) == Less); + assert_eq!(r.key.cmp(&parent.key), Less); assert!(r.level == parent.level - 1); // left is black check_left(&r.left, r); check_right(&r.right, r, false); @@ -1014,7 +820,7 @@ mod test_treemap { parent_red: bool) { match *node { Some(ref r) => { - assert!(r.key.cmp(&parent.key) == Greater); + assert_eq!(r.key.cmp(&parent.key), Greater); let red = r.level == parent.level; if parent_red { assert!(!red) } // no dual horizontal links // Right red or black @@ -1072,19 +878,19 @@ mod test_treemap { fn test_len() { let mut m = TreeMap::new(); assert!(m.insert(3, 6)); - assert!(m.len() == 1); + assert_eq!(m.len(), 1); assert!(m.insert(0, 0)); - assert!(m.len() == 2); + assert_eq!(m.len(), 2); assert!(m.insert(4, 8)); - assert!(m.len() == 3); + assert_eq!(m.len(), 3); assert!(m.remove(&3)); - assert!(m.len() == 2); + assert_eq!(m.len(), 2); assert!(!m.remove(&5)); - assert!(m.len() == 2); + assert_eq!(m.len(), 2); assert!(m.insert(2, 4)); - assert!(m.len() == 3); + assert_eq!(m.len(), 3); assert!(m.insert(1, 2)); - assert!(m.len() == 4); + assert_eq!(m.len(), 4); } #[test] @@ -1099,8 +905,8 @@ mod test_treemap { let mut n = 0; for m.each |k, v| { - assert!(*k == n); - assert!(*v == n * 2); + assert_eq!(*k, n); + assert_eq!(*v, n * 2); n += 1; } } @@ -1117,8 +923,8 @@ mod test_treemap { let mut n = 4; for m.each_reverse |k, v| { - assert!(*k == n); - assert!(*v == n * 2); + assert_eq!(*k, n); + assert_eq!(*v, n * 2); n -= 1; } } @@ -1191,11 +997,11 @@ mod test_treemap { let m = m; let mut a = m.iter(); - assert!(a.next().unwrap() == (&x1, &y1)); - assert!(a.next().unwrap() == (&x2, &y2)); - assert!(a.next().unwrap() == (&x3, &y3)); - assert!(a.next().unwrap() == (&x4, &y4)); - assert!(a.next().unwrap() == (&x5, &y5)); + assert_eq!(a.next().unwrap(), (&x1, &y1)); + assert_eq!(a.next().unwrap(), (&x2, &y2)); + assert_eq!(a.next().unwrap(), (&x3, &y3)); + assert_eq!(a.next().unwrap(), (&x4, &y4)); + assert_eq!(a.next().unwrap(), (&x5, &y5)); assert!(a.next().is_none()); @@ -1206,7 +1012,7 @@ mod test_treemap { let mut i = 0; for b.advance |x| { - assert!(expected[i] == x); + assert_eq!(expected[i], x); i += 1; if i == 2 { @@ -1215,7 +1021,7 @@ mod test_treemap { } for b.advance |x| { - assert!(expected[i] == x); + assert_eq!(expected[i], x); i += 1; } } @@ -1223,9 +1029,13 @@ mod test_treemap { #[cfg(test)] mod test_set { + use core::prelude::*; use core::iterator::*; + use super::*; + use core::vec; + #[test] fn test_clear() { let mut s = TreeSet::new(); @@ -1303,7 +1113,7 @@ mod test_set { let mut n = 0; for m.each |x| { - assert!(*x == n); + assert_eq!(*x, n); n += 1 } } @@ -1320,7 +1130,7 @@ mod test_set { let mut n = 4; for m.each_reverse |x| { - assert!(*x == n); + assert_eq!(*x, n); n -= 1 } } @@ -1335,10 +1145,10 @@ mod test_set { let mut i = 0; for f(&set_a, &set_b) |x| { - assert!(*x == expected[i]); + assert_eq!(*x, expected[i]); i += 1; } - assert!(i == expected.len()); + assert_eq!(i, expected.len()); } #[test] @@ -1421,10 +1231,10 @@ mod test_set { // FIXME: #5801: this needs a type hint to compile... let result: Option<(&uint, & &'static str)> = z.next(); - assert!(result.unwrap() == (&5u, & &"bar")); + assert_eq!(result.unwrap(), (&5u, & &"bar")); let result: Option<(&uint, & &'static str)> = z.next(); - assert!(result.unwrap() == (&11u, & &"foo")); + assert_eq!(result.unwrap(), (&11u, & &"foo")); let result: Option<(&uint, & &'static str)> = z.next(); assert!(result.is_none()); @@ -1433,16 +1243,16 @@ mod test_set { #[test] fn test_swap() { let mut m = TreeMap::new(); - assert!(m.swap(1, 2) == None); - assert!(m.swap(1, 3) == Some(2)); - assert!(m.swap(1, 4) == Some(3)); + assert_eq!(m.swap(1, 2), None); + assert_eq!(m.swap(1, 3), Some(2)); + assert_eq!(m.swap(1, 4), Some(3)); } #[test] fn test_pop() { let mut m = TreeMap::new(); m.insert(1, 2); - assert!(m.pop(&1) == Some(2)); - assert!(m.pop(&1) == None); + assert_eq!(m.pop(&1), Some(2)); + assert_eq!(m.pop(&1), None); } } diff --git a/src/libextra/unicode.rs b/src/libextra/unicode.rs new file mode 100644 index 0000000000000..3bd05a4153447 --- /dev/null +++ b/src/libextra/unicode.rs @@ -0,0 +1,249 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[forbid(deprecated_mode)]; +#[allow(missing_doc)]; + +pub mod icu { + pub type UBool = u8; + pub type UProperty = int; + pub type UChar32 = char; + + pub static TRUE : u8 = 1u8; + pub static FALSE : u8 = 1u8; + + pub static UCHAR_ALPHABETIC : UProperty = 0; + pub static UCHAR_BINARY_START : UProperty = 0; // = UCHAR_ALPHABETIC + pub static UCHAR_ASCII_HEX_DIGIT : UProperty = 1; + pub static UCHAR_BIDI_CONTROL : UProperty = 2; + + pub static UCHAR_BIDI_MIRRORED : UProperty = 3; + pub static UCHAR_DASH : UProperty = 4; + pub static UCHAR_DEFAULT_IGNORABLE_CODE_POINT : UProperty = 5; + pub static UCHAR_DEPRECATED : UProperty = 6; + + pub static UCHAR_DIACRITIC : UProperty = 7; + pub static UCHAR_EXTENDER : UProperty = 8; + pub static UCHAR_FULL_COMPOSITION_EXCLUSION : UProperty = 9; + pub static UCHAR_GRAPHEME_BASE : UProperty = 10; + + pub static UCHAR_GRAPHEME_EXTEND : UProperty = 11; + pub static UCHAR_GRAPHEME_LINK : UProperty = 12; + pub static UCHAR_HEX_DIGIT : UProperty = 13; + pub static UCHAR_HYPHEN : UProperty = 14; + + pub static UCHAR_ID_CONTINUE : UProperty = 15; + pub static UCHAR_ID_START : UProperty = 16; + pub static UCHAR_IDEOGRAPHIC : UProperty = 17; + pub static UCHAR_IDS_BINARY_OPERATOR : UProperty = 18; + + pub static UCHAR_IDS_TRINARY_OPERATOR : UProperty = 19; + pub static UCHAR_JOIN_CONTROL : UProperty = 20; + pub static UCHAR_LOGICAL_ORDER_EXCEPTION : UProperty = 21; + pub static UCHAR_LOWERCASE : UProperty = 22; + + pub static UCHAR_MATH : UProperty = 23; + pub static UCHAR_NONCHARACTER_CODE_POINT : UProperty = 24; + pub static UCHAR_QUOTATION_MARK : UProperty = 25; + pub static UCHAR_RADICAL : UProperty = 26; + + pub static UCHAR_SOFT_DOTTED : UProperty = 27; + pub static UCHAR_TERMINAL_PUNCTUATION : UProperty = 28; + pub static UCHAR_UNIFIED_IDEOGRAPH : UProperty = 29; + pub static UCHAR_UPPERCASE : UProperty = 30; + + pub static UCHAR_WHITE_SPACE : UProperty = 31; + pub static UCHAR_XID_CONTINUE : UProperty = 32; + pub static UCHAR_XID_START : UProperty = 33; + pub static UCHAR_CASE_SENSITIVE : UProperty = 34; + + pub static UCHAR_S_TERM : UProperty = 35; + pub static UCHAR_VARIATION_SELECTOR : UProperty = 36; + pub static UCHAR_NFD_INERT : UProperty = 37; + pub static UCHAR_NFKD_INERT : UProperty = 38; + + pub static UCHAR_NFC_INERT : UProperty = 39; + pub static UCHAR_NFKC_INERT : UProperty = 40; + pub static UCHAR_SEGMENT_STARTER : UProperty = 41; + pub static UCHAR_PATTERN_SYNTAX : UProperty = 42; + + pub static UCHAR_PATTERN_WHITE_SPACE : UProperty = 43; + pub static UCHAR_POSIX_ALNUM : UProperty = 44; + pub static UCHAR_POSIX_BLANK : UProperty = 45; + pub static UCHAR_POSIX_GRAPH : UProperty = 46; + + pub static UCHAR_POSIX_PRINT : UProperty = 47; + pub static UCHAR_POSIX_XDIGIT : UProperty = 48; + pub static UCHAR_CASED : UProperty = 49; + pub static UCHAR_CASE_IGNORABLE : UProperty = 50; + + pub static UCHAR_CHANGES_WHEN_LOWERCASED : UProperty = 51; + pub static UCHAR_CHANGES_WHEN_UPPERCASED : UProperty = 52; + pub static UCHAR_CHANGES_WHEN_TITLECASED : UProperty = 53; + pub static UCHAR_CHANGES_WHEN_CASEFOLDED : UProperty = 54; + + pub static UCHAR_CHANGES_WHEN_CASEMAPPED : UProperty = 55; + pub static UCHAR_CHANGES_WHEN_NFKC_CASEFOLDED : UProperty = 56; + pub static UCHAR_BINARY_LIMIT : UProperty = 57; + pub static UCHAR_BIDI_CLASS : UProperty = 0x1000; + + pub static UCHAR_INT_START : UProperty = 0x1000; // UCHAR_BIDI_CLASS + pub static UCHAR_BLOCK : UProperty = 0x1001; + pub static UCHAR_CANONICAL_COMBINING_CLASS : UProperty = 0x1002; + pub static UCHAR_DECOMPOSITION_TYPE : UProperty = 0x1003; + + pub static UCHAR_EAST_ASIAN_WIDTH : UProperty = 0x1004; + pub static UCHAR_GENERAL_CATEGORY : UProperty = 0x1005; + pub static UCHAR_JOINING_GROUP : UProperty = 0x1006; + pub static UCHAR_JOINING_TYPE : UProperty = 0x1007; + + pub static UCHAR_LINE_BREAK : UProperty = 0x1008; + pub static UCHAR_NUMERIC_TYPE : UProperty = 0x1009; + pub static UCHAR_SCRIPT : UProperty = 0x100A; + pub static UCHAR_HANGUL_SYLLABLE_TYPE : UProperty = 0x100B; + + pub static UCHAR_NFD_QUICK_CHECK : UProperty = 0x100C; + pub static UCHAR_NFKD_QUICK_CHECK : UProperty = 0x100D; + pub static UCHAR_NFC_QUICK_CHECK : UProperty = 0x100E; + pub static UCHAR_NFKC_QUICK_CHECK : UProperty = 0x100F; + + pub static UCHAR_LEAD_CANONICAL_COMBINING_CLASS : UProperty = 0x1010; + pub static UCHAR_TRAIL_CANONICAL_COMBINING_CLASS : UProperty = 0x1011; + pub static UCHAR_GRAPHEME_CLUSTER_BREAK : UProperty = 0x1012; + pub static UCHAR_SENTENCE_BREAK : UProperty = 0x1013; + + pub static UCHAR_WORD_BREAK : UProperty = 0x1014; + pub static UCHAR_INT_LIMIT : UProperty = 0x1015; + + pub static UCHAR_GENERAL_CATEGORY_MASK : UProperty = 0x2000; + pub static UCHAR_MASK_START : UProperty = 0x2000; + // = UCHAR_GENERAL_CATEGORY_MASK + pub static UCHAR_MASK_LIMIT : UProperty = 0x2001; + + pub static UCHAR_NUMERIC_VALUE : UProperty = 0x3000; + pub static UCHAR_DOUBLE_START : UProperty = 0x3000; + // = UCHAR_NUMERIC_VALUE + pub static UCHAR_DOUBLE_LIMIT : UProperty = 0x3001; + + pub static UCHAR_AGE : UProperty = 0x4000; + pub static UCHAR_STRING_START : UProperty = 0x4000; // = UCHAR_AGE + pub static UCHAR_BIDI_MIRRORING_GLYPH : UProperty = 0x4001; + pub static UCHAR_CASE_FOLDING : UProperty = 0x4002; + + pub static UCHAR_ISO_COMMENT : UProperty = 0x4003; + pub static UCHAR_LOWERCASE_MAPPING : UProperty = 0x4004; + pub static UCHAR_NAME : UProperty = 0x4005; + pub static UCHAR_SIMPLE_CASE_FOLDING : UProperty = 0x4006; + + pub static UCHAR_SIMPLE_LOWERCASE_MAPPING : UProperty = 0x4007; + pub static UCHAR_SIMPLE_TITLECASE_MAPPING : UProperty = 0x4008; + pub static UCHAR_SIMPLE_UPPERCASE_MAPPING : UProperty = 0x4009; + pub static UCHAR_TITLECASE_MAPPING : UProperty = 0x400A; + + pub static UCHAR_UNICODE_1_NAME : UProperty = 0x400B; + pub static UCHAR_UPPERCASE_MAPPING : UProperty = 0x400C; + pub static UCHAR_STRING_LIMIT : UProperty = 0x400D; + + pub static UCHAR_SCRIPT_EXTENSIONS : UProperty = 0x7000; + pub static UCHAR_OTHER_PROPERTY_START : UProperty = 0x7000; + // = UCHAR_SCRIPT_EXTENSIONS; + pub static UCHAR_OTHER_PROPERTY_LIMIT : UProperty = 0x7001; + + pub static UCHAR_INVALID_CODE : UProperty = -1; + + pub mod libicu { + #[link_name = "icuuc"] + #[abi = "cdecl"] + pub extern { + unsafe fn u_hasBinaryProperty(c: UChar32, which: UProperty) + -> UBool; + unsafe fn u_isdigit(c: UChar32) -> UBool; + unsafe fn u_islower(c: UChar32) -> UBool; + unsafe fn u_isspace(c: UChar32) -> UBool; + unsafe fn u_isupper(c: UChar32) -> UBool; + unsafe fn u_tolower(c: UChar32) -> UChar32; + unsafe fn u_toupper(c: UChar32) -> UChar32; + } + } +} + +pub fn is_XID_start(c: char) -> bool { + return icu::libicu::u_hasBinaryProperty(c, icu::UCHAR_XID_START) + == icu::TRUE; +} + +pub fn is_XID_continue(c: char) -> bool { + return icu::libicu::u_hasBinaryProperty(c, icu::UCHAR_XID_START) + == icu::TRUE; +} + +/* +Function: is_digit + +Returns true if a character is a digit. +*/ +pub fn is_digit(c: char) -> bool { + return icu::libicu::u_isdigit(c) == icu::TRUE; +} + +/* +Function: is_lower + +Returns true if a character is a lowercase letter. +*/ +pub fn is_lower(c: char) -> bool { + return icu::libicu::u_islower(c) == icu::TRUE; +} + +/* +Function: is_space + +Returns true if a character is space. +*/ +pub fn is_space(c: char) -> bool { + return icu::libicu::u_isspace(c) == icu::TRUE; +} + +/* +Function: is_upper + +Returns true if a character is an uppercase letter. +*/ +pub fn is_upper(c: char) -> bool { + return icu::libicu::u_isupper(c) == icu::TRUE; +} + +#[cfg(test)] +mod tests { + + #[test] + fn test_is_digit() { + assert!((unicode::icu::is_digit('0'))); + assert!((!unicode::icu::is_digit('m'))); + } + + #[test] + fn test_is_lower() { + assert!((unicode::icu::is_lower('m'))); + assert!((!unicode::icu::is_lower('M'))); + } + + #[test] + fn test_is_space() { + assert!((unicode::icu::is_space(' '))); + assert!((!unicode::icu::is_space('m'))); + } + + #[test] + fn test_is_upper() { + assert!((unicode::icu::is_upper('M'))); + assert!((!unicode::icu::is_upper('m'))); + } +} diff --git a/src/libstd/uv.rs b/src/libextra/uv.rs similarity index 100% rename from src/libstd/uv.rs rename to src/libextra/uv.rs diff --git a/src/libstd/uv_global_loop.rs b/src/libextra/uv_global_loop.rs similarity index 96% rename from src/libstd/uv_global_loop.rs rename to src/libextra/uv_global_loop.rs index c7b5d9eef726b..286863bef641d 100644 --- a/src/libstd/uv_global_loop.rs +++ b/src/libextra/uv_global_loop.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -10,6 +10,8 @@ //! A process-wide libuv event loop for library use. +use core::prelude::*; + use iotask = uv_iotask; use uv_iotask::{IoTask, spawn_iotask}; @@ -124,9 +126,7 @@ mod test { use uv::ll; use uv_iotask::IoTask; - use core::old_iter; use core::libc; - use core::ptr; use core::task; use core::cast::transmute; use core::libc::c_void; @@ -215,7 +215,7 @@ mod test { let (exit_po, exit_ch) = stream::<()>(); let exit_ch = SharedChan::new(exit_ch); let cycles = 5000u; - for old_iter::repeat(cycles) { + for cycles.times { let exit_ch_clone = exit_ch.clone(); task::spawn_sched(task::ManualThreads(1u), || { let hl_loop = &get_gl(); @@ -223,10 +223,10 @@ mod test { exit_ch_clone.send(()); }); }; - for old_iter::repeat(cycles) { + for cycles.times { exit_po.recv(); }; - debug!(~"test_stress_gl_uv_global_loop_high_level_global_timer"+ - ~" exiting successfully!"); + debug!("test_stress_gl_uv_global_loop_high_level_global_timer \ + exiting successfully!"); } } diff --git a/src/libstd/uv_iotask.rs b/src/libextra/uv_iotask.rs similarity index 98% rename from src/libstd/uv_iotask.rs rename to src/libextra/uv_iotask.rs index 2922f403f34a6..817dfa28aeedf 100644 --- a/src/libstd/uv_iotask.rs +++ b/src/libextra/uv_iotask.rs @@ -15,11 +15,16 @@ * `interact` function you can execute code in a uv callback. */ +#[allow(missing_doc)]; + +use core::prelude::*; + use ll = uv_ll; use core::comm::{stream, Port, Chan, SharedChan}; use core::libc::c_void; use core::libc; +use core::task; /// Used to abstract-away direct interaction with a libuv loop. pub struct IoTask { @@ -183,7 +188,7 @@ extern fn tear_down_walk_cb(handle: *libc::c_void, arg: *libc::c_void) { // pretty much, if we still have an active handle and it is *not* // the async handle that facilities global loop communication, we // want to barf out and fail - assert!(handle == arg); + assert_eq!(handle, arg); } extern fn tear_down_close_cb(handle: *ll::uv_async_t) { @@ -221,6 +226,8 @@ struct AhData { #[cfg(test)] fn impl_uv_iotask_async(iotask: &IoTask) { + use core::ptr; + let async_handle = ll::async_t(); let ah_ptr: *ll::uv_async_t = &async_handle; let (exit_po, exit_ch) = stream::<()>(); @@ -284,7 +291,7 @@ fn test_uv_iotask_async() { // impl_uv_hl_async() runs have been called, at least. let (work_exit_po, work_exit_ch) = stream::<()>(); let work_exit_ch = SharedChan::new(work_exit_ch); - for old_iter::repeat(7u) { + for 7u.times { let iotask_clone = iotask.clone(); let work_exit_ch_clone = work_exit_ch.clone(); do task::spawn_sched(task::ManualThreads(1u)) { @@ -294,7 +301,7 @@ fn test_uv_iotask_async() { work_exit_ch_clone.send(()); }; }; - for old_iter::repeat(7u) { + for 7u.times { debug!("waiting"); work_exit_po.recv(); }; diff --git a/src/libstd/uv_ll.rs b/src/libextra/uv_ll.rs similarity index 99% rename from src/libstd/uv_ll.rs rename to src/libextra/uv_ll.rs index 37052f7d1b7fa..2cb2eea88283b 100644 --- a/src/libstd/uv_ll.rs +++ b/src/libextra/uv_ll.rs @@ -31,10 +31,16 @@ */ #[allow(non_camel_case_types)]; // C types +#[allow(missing_doc)]; -use core::libc::size_t; -use core::libc::c_void; +use core::prelude::*; + +use core::libc::{c_void, size_t}; +use core::libc; use core::ptr::to_unsafe_ptr; +use core::ptr; +use core::str; +use core::vec; pub type uv_handle_t = c_void; pub type uv_loop_t = c_void; @@ -819,8 +825,8 @@ extern { unsafe fn rust_uv_timer_start( timer_handle: *uv_timer_t, cb: *u8, - timeout: libc::c_uint, - repeat: libc::c_uint) -> libc::c_int; + timeout: libc::uint64_t, + repeat: libc::uint64_t) -> libc::c_int; unsafe fn rust_uv_timer_stop(handle: *uv_timer_t) -> libc::c_int; unsafe fn rust_uv_getaddrinfo(loop_ptr: *libc::c_void, @@ -1084,8 +1090,8 @@ pub unsafe fn timer_init(loop_ptr: *libc::c_void, } pub unsafe fn timer_start(timer_ptr: *uv_timer_t, cb: *u8, timeout: uint, repeat: uint) -> libc::c_int { - return rust_uv_timer_start(timer_ptr, cb, timeout as libc::c_uint, - repeat as libc::c_uint); + return rust_uv_timer_start(timer_ptr, cb, timeout as libc::uint64_t, + repeat as libc::uint64_t); } pub unsafe fn timer_stop(timer_ptr: *uv_timer_t) -> libc::c_int { return rust_uv_timer_stop(timer_ptr); @@ -1222,9 +1228,18 @@ pub unsafe fn addrinfo_as_sockaddr_in6(input: *addrinfo) -> *sockaddr_in6 { #[cfg(test)] mod test { - use core::comm::{SharedChan, stream, GenericChan, GenericPort}; + use core::prelude::*; + use super::*; + use core::comm::{SharedChan, stream, GenericChan, GenericPort}; + use core::libc; + use core::result; + use core::str; + use core::sys; + use core::task; + use core::vec; + enum tcp_read_data { tcp_read_eof, tcp_read_more(~[u8]), diff --git a/src/libstd/workcache.rs b/src/libextra/workcache.rs similarity index 86% rename from src/libstd/workcache.rs rename to src/libextra/workcache.rs index f173df60df893..b2fd998b73fd2 100644 --- a/src/libstd/workcache.rs +++ b/src/libextra/workcache.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[allow(missing_doc)]; + +use core::prelude::*; + use json; use sha1; use serialize::{Encoder, Encodable, Decoder, Decodable}; @@ -15,12 +19,13 @@ use sort; use core::cell::Cell; use core::cmp; -use core::comm::{PortOne, oneshot, send_one}; +use core::comm::{PortOne, oneshot, send_one, recv_one}; use core::either::{Either, Left, Right}; use core::hashmap::HashMap; use core::io; -use core::pipes::recv; +use core::result; use core::run; +use core::task; use core::to_bytes; use core::util::replace; @@ -98,17 +103,6 @@ struct WorkKey { name: ~str } -#[cfg(stage0)] -impl to_bytes::IterBytes for WorkKey { - #[inline(always)] - fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { - let mut flag = true; - self.kind.iter_bytes(lsb0, |bytes| {flag = f(bytes); flag}); - if !flag { return; } - self.name.iter_bytes(lsb0, f); - } -} -#[cfg(not(stage0))] impl to_bytes::IterBytes for WorkKey { #[inline(always)] fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool { @@ -133,9 +127,12 @@ impl cmp::Ord for WorkKey { } } -pub impl WorkKey { - fn new(kind: &str, name: &str) -> WorkKey { - WorkKey { kind: kind.to_owned(), name: name.to_owned() } +impl WorkKey { + pub fn new(kind: &str, name: &str) -> WorkKey { + WorkKey { + kind: kind.to_owned(), + name: name.to_owned(), + } } } @@ -173,11 +170,11 @@ struct Database { db_dirty: bool } -pub impl Database { - fn prepare(&mut self, - fn_name: &str, - declared_inputs: &WorkMap) - -> Option<(WorkMap, WorkMap, ~str)> { +impl Database { + pub fn prepare(&mut self, + fn_name: &str, + declared_inputs: &WorkMap) + -> Option<(WorkMap, WorkMap, ~str)> { let k = json_encode(&(fn_name, declared_inputs)); match self.db_cache.find(&k) { None => None, @@ -185,12 +182,12 @@ pub impl Database { } } - fn cache(&mut self, - fn_name: &str, - declared_inputs: &WorkMap, - discovered_inputs: &WorkMap, - discovered_outputs: &WorkMap, - result: &str) { + pub fn cache(&mut self, + fn_name: &str, + declared_inputs: &WorkMap, + discovered_inputs: &WorkMap, + discovered_outputs: &WorkMap, + result: &str) { let k = json_encode(&(fn_name, declared_inputs)); let v = json_encode(&(discovered_inputs, discovered_outputs, @@ -205,9 +202,9 @@ struct Logger { a: () } -pub impl Logger { - fn info(&self, i: &str) { - io::println(~"workcache: " + i.to_owned()); +impl Logger { + pub fn info(&self, i: &str) { + io::println(~"workcache: " + i); } } @@ -263,11 +260,9 @@ fn digest_file(path: &Path) -> ~str { sha.result_str() } -pub impl Context { - - fn new(db: @mut Database, - lg: @mut Logger, - cfg: @json::Object) -> Context { +impl Context { + pub fn new(db: @mut Database, lg: @mut Logger, cfg: @json::Object) + -> Context { Context { db: db, logger: lg, @@ -276,12 +271,12 @@ pub impl Context { } } - fn prep + - Decodable>( // FIXME(#5121) - @self, - fn_name:&str, - blk: &fn(@mut Prep)->Work) -> Work { + pub fn prep + + Decodable>(@self, // FIXME(#5121) + fn_name:&str, + blk: &fn(@mut Prep)->Work) + -> Work { let p = @mut Prep { ctxt: self, fn_name: fn_name.to_owned(), @@ -352,7 +347,7 @@ impl TPrep for Prep { _ => { let (port, chan) = oneshot(); let blk = replace(&mut bo, None).unwrap(); - let chan = Cell(chan); + let chan = Cell::new(chan); do task::spawn { let exe = Exec { @@ -369,10 +364,10 @@ impl TPrep for Prep { } } -pub impl + - Decodable> Work { // FIXME(#5121) - fn new(p: @mut Prep, e: Either>) -> Work { +impl + + Decodable> Work { // FIXME(#5121) + pub fn new(p: @mut Prep, e: Either>) -> Work { Work { prep: p, res: Some(e) } } } @@ -389,9 +384,7 @@ fn unwrap fail!(), Some(Left(v)) => v, Some(Right(port)) => { - let (exe, v) = match recv(port.unwrap()) { - oneshot::send(data) => data - }; + let (exe, v) = recv_one(port); let s = json_encode(&v); @@ -427,7 +420,7 @@ fn test() { prep.declare_input("file", pth.to_str(), digest_file(&pth)); do prep.exec |_exe| { let out = Path("foo.o"); - run::run_program("gcc", [~"foo.c", ~"-o", out.to_str()]); + run::process_status("gcc", [~"foo.c", ~"-o", out.to_str()]); out.to_str() } }; diff --git a/src/libfuzzer/ast_match.rs b/src/libfuzzer/ast_match.rs index 2502830250dbe..7d623919ff936 100644 --- a/src/libfuzzer/ast_match.rs +++ b/src/libfuzzer/ast_match.rs @@ -8,7 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std; +use std::prelude::*; + use vec; fn vec_equal(v: ~[T], diff --git a/src/libfuzzer/cycles.rs b/src/libfuzzer/cycles.rs index a6434d64cdc38..2256325fa4376 100644 --- a/src/libfuzzer/cycles.rs +++ b/src/libfuzzer/cycles.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std; -use std::rand; +use core::prelude::*; + +use extra; +use extra::rand; use uint::range; // random uint less than n diff --git a/src/libfuzzer/fuzzer.rc b/src/libfuzzer/fuzzer.rc index 59a715e7f9062..c6410d16c7429 100644 --- a/src/libfuzzer/fuzzer.rc +++ b/src/libfuzzer/fuzzer.rc @@ -20,10 +20,24 @@ #[allow(non_camel_case_types)]; -extern mod std(vers = "0.7-pre"); +#[no_std]; + +extern mod std(name = "std", vers = "0.7-pre"); +extern mod extra(name = "extra", vers = "0.7-pre"); + extern mod syntax(vers = "0.7-pre"); -use core::run; +use std::prelude::*; + +use std::int; +use std::io; +use std::option; +use std::os; +use std::result; +use std::run; +use std::str; +use std::uint; +use std::vec; use syntax::diagnostic; use syntax::parse::token::ident_interner; @@ -38,7 +52,7 @@ pub enum test_mode { tm_converge, tm_run, } pub struct Context { mode: test_mode } // + rng pub fn write_file(filename: &Path, content: &str) { - result::get(&io::file_writer(filename, ~[io::Create, io::Truncate])) + result::get(&io::file_writer(filename, [io::Create, io::Truncate])) .write_str(content); } @@ -47,12 +61,12 @@ pub fn contains(haystack: &str, needle: &str) -> bool { } pub fn find_rust_files(files: &mut ~[Path], path: &Path) { - if path.filetype() == Some(~".rs") && !contains(path.to_str(), ~"utf8") { + if path.filetype() == Some(~".rs") && !contains(path.to_str(), "utf8") { // ignoring "utf8" tests because something is broken files.push(path.clone()); } else if os::path_is_dir(path) - && !contains(path.to_str(), ~"compile-fail") - && !contains(path.to_str(), ~"build") { + && !contains(path.to_str(), "compile-fail") + && !contains(path.to_str(), "build") { for os::list_dir_path(path).each |p| { find_rust_files(&mut *files, *p); } @@ -64,7 +78,6 @@ pub fn common_exprs() -> ~[@ast::expr] { fn dse(e: ast::expr_) -> @ast::expr { @ast::expr { id: 0, - callee_id: -1, node: e, span: codemap::dummy_sp(), } @@ -80,9 +93,9 @@ pub fn common_exprs() -> ~[@ast::expr] { dse(ast::expr_lit(@dsl(ast::lit_nil))), dse(ast::expr_lit(@dsl(ast::lit_bool(false)))), dse(ast::expr_lit(@dsl(ast::lit_bool(true)))), - dse(ast::expr_unary(ast::box(ast::m_imm), + dse(ast::expr_unary(-1, ast::box(ast::m_imm), dse(ast::expr_lit(@dsl(ast::lit_bool(true)))))), - dse(ast::expr_unary(ast::uniq(ast::m_imm), + dse(ast::expr_unary(-1, ast::uniq(ast::m_imm), dse(ast::expr_lit(@dsl(ast::lit_bool(true)))))) ] } @@ -114,7 +127,7 @@ pub fn safe_to_use_expr(e: @ast::expr, tm: test_mode) -> bool { //ast::expr_cast(_, _) { false } // https://github.com/mozilla/rust/issues/1458 - ast::expr_call(_, _, _) => { false } + ast::expr_call(*) => { false } _ => { true } } @@ -134,7 +147,7 @@ pub fn stash_expr_if(c: @fn(@ast::expr, test_mode)->bool, e: @ast::expr, tm: test_mode) { if c(e, tm) { - *es = *es + ~[e]; + *es = *es + [e]; } else { /* now my indices are wrong :( */ } @@ -406,34 +419,34 @@ pub fn check_whole_compiler(code: &str, pub fn removeIfExists(filename: &Path) { // So sketchy! - assert!(!contains(filename.to_str(), ~" ")); - run::program_output(~"bash", ~[~"-c", ~"rm " + filename.to_str()]); + assert!(!contains(filename.to_str(), " ")); + run::process_status("bash", [~"-c", ~"rm " + filename.to_str()]); } pub fn removeDirIfExists(filename: &Path) { // So sketchy! - assert!(!contains(filename.to_str(), ~" ")); - run::program_output(~"bash", ~[~"-c", ~"rm -r " + filename.to_str()]); + assert!(!contains(filename.to_str(), " ")); + run::process_status("bash", [~"-c", ~"rm -r " + filename.to_str()]); } pub fn check_running(exe_filename: &Path) -> happiness { - let p = run::program_output( - ~"/Users/jruderman/scripts/timed_run_rust_program.py", - ~[exe_filename.to_str()]); - let comb = p.out + ~"\n" + p.err; + let p = run::process_output( + "/Users/jruderman/scripts/timed_run_rust_program.py", + [exe_filename.to_str()]); + let comb = str::from_bytes(p.output) + "\n" + str::from_bytes(p.error); if str::len(comb) > 1u { error!("comb comb comb: %?", comb); } - if contains(comb, ~"Assertion failed:") { + if contains(comb, "Assertion failed:") { failed(~"C++ assertion failure") - } else if contains(comb, ~"leaked memory in rust main loop") { + } else if contains(comb, "leaked memory in rust main loop") { // might also use exit code 134 //failed("Leaked") known_bug(~"https://github.com/mozilla/rust/issues/910") - } else if contains(comb, ~"src/rt/") { + } else if contains(comb, "src/rt/") { failed(~"Mentioned src/rt/") - } else if contains(comb, ~"malloc") { + } else if contains(comb, "malloc") { failed(~"Mentioned malloc") } else { match p.status { @@ -456,33 +469,35 @@ pub fn check_running(exe_filename: &Path) -> happiness { } pub fn check_compiling(filename: &Path) -> happiness { - let p = run::program_output( - ~"/Users/jruderman/code/rust/build/x86_64-apple-darwin/\ - stage1/bin/rustc", - ~[filename.to_str()]); + let p = run::process_output( + "/Users/jruderman/code/rust/build/x86_64-apple-darwin/stage1/bin/rustc", + [filename.to_str()]); + + let out = str::from_bytes(p.output); + let err = str::from_bytes(p.error); //error!("Status: %d", p.status); if p.status == 0 { passed - } else if p.err != ~"" { - if contains(p.err, ~"error:") { + } else if !err.is_empty() { + if err.contains("error:") { cleanly_rejected(~"rejected with span_error") } else { - error!("Stderr: %?", p.err); + error!("Stderr: %?", err); failed(~"Unfamiliar error message") } - } else if contains(p.out, ~"Assertion") && contains(p.out, ~"failed") { - error!("Stdout: %?", p.out); + } else if out.contains("Assertion") && out.contains("failed") { + error!("Stdout: %?", out); failed(~"Looks like an llvm assertion failure") - } else if contains(p.out, ~"internal compiler error unimplemented") { + } else if out.contains("internal compiler error unimplemented") { known_bug(~"Something unimplemented") - } else if contains(p.out, ~"internal compiler error") { - error!("Stdout: %?", p.out); + } else if out.contains("internal compiler error") { + error!("Stdout: %?", out); failed(~"internal compiler error") } else { error!("%?", p.status); - error!("!Stdout: %?", p.out); + error!("!Stdout: %?", out); failed(~"What happened?") } } @@ -603,9 +618,7 @@ pub fn check_roundtrip_convergence(code: @~str, maxIters: uint) { error!("Did not converge after %u iterations!", i); write_file(&Path("round-trip-a.rs"), *oldv); write_file(&Path("round-trip-b.rs"), *newv); - run::run_program(~"diff", - ~[~"-w", ~"-u", ~"round-trip-a.rs", - ~"round-trip-b.rs"]); + run::process_status("diff", [~"-w", ~"-u", ~"round-trip-a.rs", ~"round-trip-b.rs"]); fail!("Mismatch"); } } @@ -635,7 +648,7 @@ pub fn check_variants(files: &[Path], cx: Context) { } let s = @result::get(&io::read_whole_file_str(file)); - if contains(*s, ~"#") { + if contains(*s, "#") { loop; // Macros are confusing } if cx.mode == tm_converge && content_might_not_converge(*s) { @@ -693,3 +706,10 @@ pub fn main() { error!("Fuzzer done"); } + +// For bootstrapping purposes... +pub mod core { + pub use std::cmp; + pub use std::sys; +} + diff --git a/src/libfuzzer/ivec_fuzz.rs b/src/libfuzzer/ivec_fuzz.rs index 25dc14c3d7888..8f019a14eedb3 100644 --- a/src/libfuzzer/ivec_fuzz.rs +++ b/src/libfuzzer/ivec_fuzz.rs @@ -28,7 +28,8 @@ vec_edits is not an iter because iters might go away. */ -extern mod std; +use std::prelude::*; + use vec::slice; use vec::len; diff --git a/src/libfuzzer/rand_util.rs b/src/libfuzzer/rand_util.rs index c239e8ab9332e..abc6b1cfc0af1 100644 --- a/src/libfuzzer/rand_util.rs +++ b/src/libfuzzer/rand_util.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern mod std; -use std::rand; +use std::prelude::*; +use extra::rand; // random uint less than n fn under(r : rand::rng, n : uint) -> uint { @@ -63,7 +63,7 @@ fn weighted_choice(r : rand::rng, v : ~[weighted]) -> T { return item; } } - core::unreachable(); + std::unreachable(); } fn weighted_vec(v : ~[weighted]) -> ~[T] { diff --git a/src/librust/rust.rc b/src/librust/rust.rc index 92510be56c3a8..ff766417c2ace 100644 --- a/src/librust/rust.rc +++ b/src/librust/rust.rc @@ -20,22 +20,39 @@ #[license = "MIT/ASL2"]; #[crate_type = "lib"]; -extern mod rustpkg(vers = "0.7-pre"); -extern mod rustdoc(vers = "0.7-pre"); -extern mod rusti(vers = "0.7-pre"); -extern mod rustc(vers = "0.7-pre"); +#[no_std]; +extern mod core(name = "std"); + +extern mod rustpkg; +extern mod rustdoc; +extern mod rusti; +extern mod rustc; + +use core::prelude::*; + +use core::io; +use core::os; use core::run; +use core::libc::exit; +use core::str; + +// For bootstrapping. +mod std { + pub use core::os; + pub use core::str; + pub use core::unstable; +} enum ValidUsage { - Valid, Invalid + Valid(int), Invalid } impl ValidUsage { fn is_valid(&self) -> bool { match *self { - Valid => true, - Invalid => false + Valid(_) => true, + Invalid => false } } } @@ -138,26 +155,26 @@ fn cmd_help(args: &[~str]) -> ValidUsage { UsgStr(msg) => io::println(fmt!("%s\n", msg)), UsgCall(f) => f(), } - Valid + Valid(0) }, None => Invalid } } match args { - [command_string] => print_usage(command_string), - _ => Invalid + [ref command_string] => print_usage(copy *command_string), + _ => Invalid } } fn cmd_test(args: &[~str]) -> ValidUsage { match args { - [filename] => { - let test_exec = Path(filename).filestem().unwrap() + "test~"; + [ref filename] => { + let test_exec = Path(*filename).filestem().unwrap() + "test~"; invoke("rustc", &[~"--test", filename.to_owned(), ~"-o", test_exec.to_owned()], rustc::main); - run::run_program(~"./" + test_exec, []); - Valid + let exit_code = run::process_status(~"./" + test_exec, []); + Valid(exit_code) } _ => Invalid } @@ -165,12 +182,12 @@ fn cmd_test(args: &[~str]) -> ValidUsage { fn cmd_run(args: &[~str]) -> ValidUsage { match args { - [filename, ..prog_args] => { - let exec = Path(filename).filestem().unwrap() + "~"; + [ref filename, ..prog_args] => { + let exec = Path(*filename).filestem().unwrap() + "~"; invoke("rustc", &[filename.to_owned(), ~"-o", exec.to_owned()], rustc::main); - run::run_program(~"./"+exec, prog_args); - Valid + let exit_code = run::process_status(~"./"+exec, prog_args); + Valid(exit_code) } _ => Invalid } @@ -188,7 +205,7 @@ fn do_command(command: &Command, args: &[~str]) -> ValidUsage { Call(f) => f(args), CallMain(prog, f) => { invoke(prog, args, f); - Valid + Valid(0) } } } @@ -227,7 +244,10 @@ pub fn main() { if !args.is_empty() { for find_cmd(*args.head()).each |command| { let result = do_command(command, args.tail()); - if result.is_valid() { return; } + match result { + Valid(exit_code) => unsafe { exit(exit_code.to_i32()) }, + _ => loop + } } } diff --git a/src/librustc/back/arm.rs b/src/librustc/back/arm.rs index dfe5751f21b83..fc59df8d24894 100644 --- a/src/librustc/back/arm.rs +++ b/src/librustc/back/arm.rs @@ -22,49 +22,49 @@ pub fn get_target_strs(target_os: session::os) -> target_strs::t { data_layout: match target_os { session::os_macos => { ~"e-p:32:32:32" + - ~"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" + - ~"-f32:32:32-f64:64:64" + - ~"-v64:64:64-v128:64:128" + - ~"-a0:0:64-n32" + "-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" + + "-f32:32:32-f64:64:64" + + "-v64:64:64-v128:64:128" + + "-a0:0:64-n32" } session::os_win32 => { ~"e-p:32:32:32" + - ~"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" + - ~"-f32:32:32-f64:64:64" + - ~"-v64:64:64-v128:64:128" + - ~"-a0:0:64-n32" + "-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" + + "-f32:32:32-f64:64:64" + + "-v64:64:64-v128:64:128" + + "-a0:0:64-n32" } session::os_linux => { ~"e-p:32:32:32" + - ~"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" + - ~"-f32:32:32-f64:64:64" + - ~"-v64:64:64-v128:64:128" + - ~"-a0:0:64-n32" + "-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" + + "-f32:32:32-f64:64:64" + + "-v64:64:64-v128:64:128" + + "-a0:0:64-n32" } session::os_android => { ~"e-p:32:32:32" + - ~"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" + - ~"-f32:32:32-f64:64:64" + - ~"-v64:64:64-v128:64:128" + - ~"-a0:0:64-n32" + "-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" + + "-f32:32:32-f64:64:64" + + "-v64:64:64-v128:64:128" + + "-a0:0:64-n32" } session::os_freebsd => { ~"e-p:32:32:32" + - ~"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" + - ~"-f32:32:32-f64:64:64" + - ~"-v64:64:64-v128:64:128" + - ~"-a0:0:64-n32" + "-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" + + "-f32:32:32-f64:64:64" + + "-v64:64:64-v128:64:128" + + "-a0:0:64-n32" } }, target_triple: match target_os { session::os_macos => ~"arm-apple-darwin", session::os_win32 => ~"arm-pc-mingw32", - session::os_linux => ~"arm-unknown-linux", + session::os_linux => ~"arm-unknown-linux-gnueabihf", session::os_android => ~"arm-linux-androideabi", session::os_freebsd => ~"arm-unknown-freebsd" }, diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 92d3a451559f3..3c10324fd3da4 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use back::rpath; use driver::session::Session; use driver::session; @@ -20,12 +22,17 @@ use middle::trans::common::CrateContext; use middle::ty; use util::ppaux; +use core::char; use core::hash::Streaming; use core::hash; use core::libc::{c_int, c_uint}; use core::os::consts::{macos, freebsd, linux, android, win32}; +use core::os; +use core::ptr; use core::rt::io::Writer; use core::run; +use core::str; +use core::vec; use syntax::ast; use syntax::ast_map::{path, path_mod, path_name}; use syntax::attr; @@ -52,7 +59,7 @@ pub fn llvm_err(sess: Session, msg: ~str) -> ! { if cstr == ptr::null() { sess.fatal(msg); } else { - sess.fatal(msg + ~": " + str::raw::from_c_str(cstr)); + sess.fatal(msg + ": " + str::raw::from_c_str(cstr)); } } } @@ -90,13 +97,18 @@ pub fn WriteOutputFile(sess: Session, } pub mod jit { + use core::prelude::*; + use back::link::llvm_err; use driver::session::Session; use lib::llvm::llvm; use lib::llvm::{ModuleRef, PassManagerRef}; use metadata::cstore; + use core::cast; use core::libc::c_int; + use core::ptr; + use core::str; pub mod rusti { #[nolink] @@ -121,9 +133,9 @@ pub mod jit { // We need to tell JIT where to resolve all linked // symbols from. The equivalent of -lstd, -lcore, etc. - // By default the JIT will resolve symbols from the std and + // By default the JIT will resolve symbols from the extra and // core linked into rustc. We don't want that, - // incase the user wants to use an older std library. + // incase the user wants to use an older extra library. let cstore = sess.cstore; for cstore::get_used_crate_files(cstore).each |cratepath| { @@ -166,6 +178,8 @@ pub mod jit { } pub mod write { + use core::prelude::*; + use back::link::jit; use back::link::{WriteOutputFile, output_type}; use back::link::{output_type_assembly, output_type_bitcode}; @@ -174,12 +188,15 @@ pub mod write { use driver::session::Session; use driver::session; use lib::llvm::llvm; - use lib::llvm::{False, ModuleRef, mk_pass_manager, mk_target_data}; + use lib::llvm::{ModuleRef, mk_pass_manager, mk_target_data}; use lib; + use back::passes; + use core::libc::{c_int, c_uint}; use core::path::Path; use core::run; + use core::str; pub fn is_object_or_assembly_or_exe(ot: output_type) -> bool { if ot == output_type_assembly || ot == output_type_object || @@ -194,18 +211,16 @@ pub mod write { output_type: output_type, output: &Path) { unsafe { + llvm::LLVMInitializePasses(); + let opts = sess.opts; if sess.time_llvm_passes() { llvm::LLVMRustEnableTimePasses(); } - let mut pm = mk_pass_manager(); let td = mk_target_data(sess.targ_cfg.target_strs.data_layout); + let pm = mk_pass_manager(); llvm::LLVMAddTargetData(td.lltd, pm.llpm); - // FIXME (#2812): run the linter here also, once there are llvm-c - // bindings for it. // Generate a pre-optimization intermediate file if -save-temps // was specified. - - if opts.save_temps { match output_type { output_type_bitcode => { @@ -224,50 +239,29 @@ pub mod write { } } } - if !sess.no_verify() { llvm::LLVMAddVerifierPass(pm.llpm); } - // FIXME (#2396): This is mostly a copy of the bits of opt's -O2 - // that are available in the C api. - // Also: We might want to add optimization levels like -O1, -O2, - // -Os, etc - // Also: Should we expose and use the pass lists used by the opt - // tool? - - if opts.optimize != session::No { - let fpm = mk_pass_manager(); - llvm::LLVMAddTargetData(td.lltd, fpm.llpm); - - let FPMB = llvm::LLVMPassManagerBuilderCreate(); - llvm::LLVMPassManagerBuilderSetOptLevel(FPMB, 2u as c_uint); - llvm::LLVMPassManagerBuilderPopulateFunctionPassManager( - FPMB, fpm.llpm); - llvm::LLVMPassManagerBuilderDispose(FPMB); - - llvm::LLVMRunPassManager(fpm.llpm, llmod); - let mut threshold = 225; - if opts.optimize == session::Aggressive { threshold = 275; } - - let MPMB = llvm::LLVMPassManagerBuilderCreate(); - llvm::LLVMPassManagerBuilderSetOptLevel(MPMB, - opts.optimize as - c_uint); - llvm::LLVMPassManagerBuilderSetSizeLevel(MPMB, False); - llvm::LLVMPassManagerBuilderSetDisableUnitAtATime(MPMB, - False); - llvm::LLVMPassManagerBuilderSetDisableUnrollLoops(MPMB, - False); - llvm::LLVMPassManagerBuilderSetDisableSimplifyLibCalls(MPMB, - False); - - if threshold != 0u { - llvm::LLVMPassManagerBuilderUseInlinerWithThreshold - (MPMB, threshold as c_uint); - } - llvm::LLVMPassManagerBuilderPopulateModulePassManager( - MPMB, pm.llpm); - llvm::LLVMPassManagerBuilderDispose(MPMB); + let mut mpm = passes::PassManager::new(td.lltd); + + if !sess.no_verify() { + mpm.add_pass_from_name("verify"); } - if !sess.no_verify() { llvm::LLVMAddVerifierPass(pm.llpm); } + + let passes = if sess.opts.custom_passes.len() > 0 { + copy sess.opts.custom_passes + } else { + if sess.lint_llvm() { + mpm.add_pass_from_name("lint"); + } + passes::create_standard_passes(opts.optimize) + }; + + + debug!("Passes: %?", passes); + passes::populate_pass_manager(sess, &mut mpm, passes); + + debug!("Running Module Optimization Pass"); + mpm.run(llmod); + if is_object_or_assembly_or_exe(output_type) || opts.jit { let LLVMOptNone = 0 as c_int; // -O0 let LLVMOptLess = 1 as c_int; // -O1 @@ -306,12 +300,9 @@ pub mod write { // Always output the bitcode file with --save-temps let filename = output.with_filetype("opt.bc"); - llvm::LLVMRunPassManager(pm.llpm, llmod); str::as_c_str(filename.to_str(), |buf| { llvm::LLVMWriteBitcodeToFile(llmod, buf) }); - pm = mk_pass_manager(); - // Save the assembly file if -S is used if output_type == output_type_assembly { WriteOutputFile( @@ -371,7 +362,6 @@ pub mod write { } else { // If only a bitcode file is asked for by using the // '--emit-llvm' flag, then output it here - llvm::LLVMRunPassManager(pm.llpm, llmod); str::as_c_str(output.to_str(), |buf| llvm::LLVMWriteBitcodeToFile(llmod, buf) ); } @@ -383,12 +373,12 @@ pub mod write { pub fn run_ndk(sess: Session, assembly: &Path, object: &Path) { let cc_prog: ~str = match &sess.opts.android_cross_path { - &Some(copy path) => { - fmt!("%s/bin/arm-linux-androideabi-gcc", path) + &Some(ref path) => { + fmt!("%s/bin/arm-linux-androideabi-gcc", *path) } &None => { - sess.fatal(~"need Android NDK path for building \ - (--android-cross-path)") + sess.fatal("need Android NDK path for building \ + (--android-cross-path)") } }; let mut cc_args = ~[]; @@ -397,14 +387,14 @@ pub mod write { cc_args.push(object.to_str()); cc_args.push(assembly.to_str()); - let prog = run::program_output(cc_prog, cc_args); + let prog = run::process_output(cc_prog, cc_args); if prog.status != 0 { sess.err(fmt!("building with `%s` failed with code %d", cc_prog, prog.status)); sess.note(fmt!("%s arguments: %s", - cc_prog, str::connect(cc_args, ~" "))); - sess.note(prog.err + prog.out); + cc_prog, str::connect(cc_args, " "))); + sess.note(str::from_bytes(prog.error + prog.output)); sess.abort_if_errors(); } } @@ -566,7 +556,7 @@ pub fn build_link_meta(sess: Session, || fmt!("output file name `%s` doesn't\ appear to have a stem", output.to_str())).to_managed(); - warn_missing(sess, ~"name", name); + warn_missing(sess, "name", name); name } }; @@ -577,7 +567,7 @@ pub fn build_link_meta(sess: Session, Some(v) => v, None => { let vers = @"0.0"; - warn_missing(sess, ~"vers", vers); + warn_missing(sess, "vers", vers); vers } }; @@ -618,9 +608,9 @@ pub fn symbol_hash(tcx: ty::ctxt, symbol_hasher.reset(); write_string(symbol_hasher, link_meta.name); - write_string(symbol_hasher, ~"-"); + write_string(symbol_hasher, "-"); write_string(symbol_hasher, link_meta.extras_hash); - write_string(symbol_hasher, ~"-"); + write_string(symbol_hasher, "-"); write_string(symbol_hasher, encoder::encoded_ty(tcx, t)); let mut hash = truncated_hash_result(symbol_hasher); // Prefix with _ so that it never blends into adjacent digits @@ -643,26 +633,37 @@ pub fn get_symbol_hash(ccx: @CrateContext, t: ty::t) -> @str { // Name sanitation. LLVM will happily accept identifiers with weird names, but // gas doesn't! +// gas accepts the following characters in symbols: a-z, A-Z, 0-9, ., _, $ pub fn sanitize(s: &str) -> ~str { let mut result = ~""; for str::each_char(s) |c| { match c { - '@' => result += ~"_sbox_", - '~' => result += ~"_ubox_", - '*' => result += ~"_ptr_", - '&' => result += ~"_ref_", - ',' => result += ~"_", - - '{' | '(' => result += ~"_of_", - 'a' .. 'z' - | 'A' .. 'Z' - | '0' .. '9' - | '_' => result.push_char(c), - _ => { - if c > 'z' && char::is_XID_continue(c) { - result.push_char(c); + // Escape these with $ sequences + '@' => result += "$SP$", + '~' => result += "$UP$", + '*' => result += "$RP$", + '&' => result += "$BP$", + '<' => result += "$LT$", + '>' => result += "$GT$", + '(' => result += "$LP$", + ')' => result += "$RP$", + ',' => result += "$C$", + + // '.' doesn't occur in types and functions, so reuse it + // for ':' + ':' => result.push_char('.'), + + // These are legal symbols + 'a' .. 'z' + | 'A' .. 'Z' + | '0' .. '9' + | '_' => result.push_char(c), + + _ => { + if c > 'z' && char::is_XID_continue(c) { + result.push_char(c); + } } - } } } @@ -687,7 +688,7 @@ pub fn mangle(sess: Session, ss: path) -> ~str { n += fmt!("%u%s", str::len(sani), sani); } } } - n += ~"E"; // End name-sequence. + n += "E"; // End name-sequence. n } @@ -721,6 +722,17 @@ pub fn mangle_internal_name_by_type_only(ccx: @CrateContext, path_name(ccx.sess.ident_of(hash))]); } +pub fn mangle_internal_name_by_type_and_seq(ccx: @CrateContext, + t: ty::t, + name: &str) -> ~str { + let s = ppaux::ty_to_str(ccx.tcx, t); + let hash = get_symbol_hash(ccx, t); + return mangle(ccx.sess, + ~[path_name(ccx.sess.ident_of(s)), + path_name(ccx.sess.ident_of(hash)), + path_name((ccx.names)(name))]); +} + pub fn mangle_internal_name_by_path_and_seq(ccx: @CrateContext, path: path, flav: &str) -> ~str { @@ -733,12 +745,11 @@ pub fn mangle_internal_name_by_path(ccx: @CrateContext, path: path) -> ~str { } pub fn mangle_internal_name_by_seq(ccx: @CrateContext, flav: &str) -> ~str { - return fmt!("%s_%u", flav, (ccx.names)(flav).repr); + return fmt!("%s_%u", flav, (ccx.names)(flav).name); } pub fn output_dll_filename(os: session::os, lm: LinkMeta) -> ~str { - let libname = fmt!("%s-%s-%s", lm.name, lm.extras_hash, lm.vers); let (dll_prefix, dll_suffix) = match os { session::os_win32 => (win32::DLL_PREFIX, win32::DLL_SUFFIX), session::os_macos => (macos::DLL_PREFIX, macos::DLL_SUFFIX), @@ -746,8 +757,7 @@ pub fn output_dll_filename(os: session::os, lm: LinkMeta) -> ~str { session::os_android => (android::DLL_PREFIX, android::DLL_SUFFIX), session::os_freebsd => (freebsd::DLL_PREFIX, freebsd::DLL_SUFFIX), }; - return str::to_owned(dll_prefix) + libname + - str::to_owned(dll_suffix); + fmt!("%s%s-%s-%s%s", dll_prefix, lm.name, lm.extras_hash, lm.vers, dll_suffix) } // If the user wants an exe generated we need to invoke @@ -762,16 +772,16 @@ pub fn link_binary(sess: Session, // For win32, there is no cc command, // so we add a condition to make it use gcc. let cc_prog: ~str = match sess.opts.linker { - Some(copy linker) => linker, + Some(ref linker) => copy *linker, None => { if sess.targ_cfg.os == session::os_android { match &sess.opts.android_cross_path { - &Some(copy path) => { - fmt!("%s/bin/arm-linux-androideabi-gcc", path) + &Some(ref path) => { + fmt!("%s/bin/arm-linux-androideabi-gcc", *path) } &None => { - sess.fatal(~"need Android NDK path for linking \ - (--android-cross-path)") + sess.fatal("need Android NDK path for linking \ + (--android-cross-path)") } } } else if sess.targ_cfg.os == session::os_win32 { @@ -798,21 +808,21 @@ pub fn link_binary(sess: Session, debug!("output: %s", output.to_str()); let cc_args = link_args(sess, obj_filename, out_filename, lm); - debug!("%s link args: %s", cc_prog, str::connect(cc_args, ~" ")); + debug!("%s link args: %s", cc_prog, str::connect(cc_args, " ")); // We run 'cc' here - let prog = run::program_output(cc_prog, cc_args); + let prog = run::process_output(cc_prog, cc_args); if 0 != prog.status { sess.err(fmt!("linking with `%s` failed with code %d", cc_prog, prog.status)); sess.note(fmt!("%s arguments: %s", - cc_prog, str::connect(cc_args, ~" "))); - sess.note(prog.err + prog.out); + cc_prog, str::connect(cc_args, " "))); + sess.note(str::from_bytes(prog.error + prog.output)); sess.abort_if_errors(); } // Clean up on Darwin if sess.targ_cfg.os == session::os_macos { - run::run_program(~"dsymutil", ~[output.to_str()]); + run::process_status("dsymutil", [output.to_str()]); } // Remove the temporary object file if we aren't saving temps @@ -920,7 +930,7 @@ pub fn link_args(sess: Session, // On linux librt and libdl are an indirect dependencies via rustrt, // and binutils 2.22+ won't add them automatically if sess.targ_cfg.os == session::os_linux { - args.push_all(~[~"-lrt", ~"-ldl"]); + args.push_all([~"-lrt", ~"-ldl"]); // LLVM implements the `frem` instruction as a call to `fmod`, // which lives in libm. Similar to above, on some linuxes we @@ -928,19 +938,18 @@ pub fn link_args(sess: Session, args.push(~"-lm"); } else if sess.targ_cfg.os == session::os_android { - args.push_all(~[~"-ldl", ~"-llog", ~"-lsupc++", - ~"-lgnustl_shared"]); + args.push_all([~"-ldl", ~"-llog", ~"-lsupc++", ~"-lgnustl_shared"]); args.push(~"-lm"); } if sess.targ_cfg.os == session::os_freebsd { - args.push_all(~[~"-pthread", ~"-lrt", - ~"-L/usr/local/lib", ~"-lexecinfo", - ~"-L/usr/local/lib/gcc46", - ~"-L/usr/local/lib/gcc44", ~"-lstdc++", - ~"-Wl,-z,origin", - ~"-Wl,-rpath,/usr/local/lib/gcc46", - ~"-Wl,-rpath,/usr/local/lib/gcc44"]); + args.push_all([~"-pthread", ~"-lrt", + ~"-L/usr/local/lib", ~"-lexecinfo", + ~"-L/usr/local/lib/gcc46", + ~"-L/usr/local/lib/gcc44", ~"-lstdc++", + ~"-Wl,-z,origin", + ~"-Wl,-rpath,/usr/local/lib/gcc46", + ~"-Wl,-rpath,/usr/local/lib/gcc44"]); } // OS X 10.6 introduced 'compact unwind info', which is produced by the diff --git a/src/librustc/back/mips.rs b/src/librustc/back/mips.rs index b15306a56b0b9..3409db5aabe3f 100644 --- a/src/librustc/back/mips.rs +++ b/src/librustc/back/mips.rs @@ -22,42 +22,42 @@ pub fn get_target_strs(target_os: session::os) -> target_strs::t { data_layout: match target_os { session::os_macos => { ~"e-p:32:32:32" + - ~"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" + - ~"-f32:32:32-f64:64:64" + - ~"-v64:64:64-v128:64:128" + - ~"-a0:0:64-n32" + "-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" + + "-f32:32:32-f64:64:64" + + "-v64:64:64-v128:64:128" + + "-a0:0:64-n32" } session::os_win32 => { ~"e-p:32:32:32" + - ~"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" + - ~"-f32:32:32-f64:64:64" + - ~"-v64:64:64-v128:64:128" + - ~"-a0:0:64-n32" + "-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" + + "-f32:32:32-f64:64:64" + + "-v64:64:64-v128:64:128" + + "-a0:0:64-n32" } session::os_linux => { ~"e-p:32:32:32" + - ~"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" + - ~"-f32:32:32-f64:64:64" + - ~"-v64:64:64-v128:64:128" + - ~"-a0:0:64-n32" + "-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" + + "-f32:32:32-f64:64:64" + + "-v64:64:64-v128:64:128" + + "-a0:0:64-n32" } session::os_android => { ~"e-p:32:32:32" + - ~"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" + - ~"-f32:32:32-f64:64:64" + - ~"-v64:64:64-v128:64:128" + - ~"-a0:0:64-n32" + "-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" + + "-f32:32:32-f64:64:64" + + "-v64:64:64-v128:64:128" + + "-a0:0:64-n32" } session::os_freebsd => { ~"e-p:32:32:32" + - ~"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" + - ~"-f32:32:32-f64:64:64" + - ~"-v64:64:64-v128:64:128" + - ~"-a0:0:64-n32" + "-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" + + "-f32:32:32-f64:64:64" + + "-v64:64:64-v128:64:128" + + "-a0:0:64-n32" } }, diff --git a/src/librustc/back/passes.rs b/src/librustc/back/passes.rs new file mode 100644 index 0000000000000..315bb5d63177f --- /dev/null +++ b/src/librustc/back/passes.rs @@ -0,0 +1,324 @@ +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::prelude::*; +use core::str; +use core::io; + +use driver::session::{OptLevel, No, Less, Aggressive}; +use driver::session::{Session}; +use lib::llvm::{PassRef, ModuleRef,PassManagerRef,TargetDataRef}; +use lib::llvm::llvm; +use lib; + +pub struct PassManager { + priv llpm: PassManagerRef +} + +impl Drop for PassManager { + fn finalize(&self) { + unsafe { + llvm::LLVMDisposePassManager(self.llpm); + } + } +} + +impl PassManager { + pub fn new(td: TargetDataRef) -> PassManager { + unsafe { + let pm = PassManager { + llpm: llvm::LLVMCreatePassManager() + }; + llvm::LLVMAddTargetData(td, pm.llpm); + + return pm; + } + } + + pub fn add_pass(&mut self, pass:PassRef) { + unsafe { + llvm::LLVMAddPass(self.llpm, pass); + } + } + + pub fn add_pass_from_name(&mut self, name:&str) { + let pass = create_pass(name).unwrap(); + self.add_pass(pass); + } + + pub fn run(&self, md:ModuleRef) -> bool { + unsafe { + llvm::LLVMRunPassManager(self.llpm, md) == lib::llvm::True + } + } +} + +pub fn create_standard_passes(level:OptLevel) -> ~[~str] { + let mut passes = ~[~"strip-dead-prototypes"]; + + if level == No { + passes.push(~"always-inline"); + return passes; + } + + passes.push(~"targetlibinfo"); + + passes.push(~"scev-aa"); + passes.push(~"basicaa"); + + passes.push(~"instcombine"); + passes.push(~"simplifycfg"); + passes.push(~"scalarrepl-ssa"); + passes.push(~"early-cse"); + + passes.push(~"globalopt"); + passes.push(~"ipsccp"); + passes.push(~"deadargelim"); + passes.push(~"instcombine"); + passes.push(~"simplifycfg"); + + passes.push(~"prune-eh"); + + passes.push(~"inline"); + + passes.push(~"functionattrs"); + + if level == Aggressive { + passes.push(~"argpromotion"); + } + + passes.push(~"scalarrepl-ssa"); + passes.push(~"early-cse"); + passes.push(~"simplify-libcalls"); + passes.push(~"jump-threading"); + passes.push(~"correlated-propagation"); + passes.push(~"simplifycfg"); + passes.push(~"instcombine"); + + passes.push(~"tailcallelim"); + passes.push(~"simplifycfg"); + passes.push(~"reassociate"); + passes.push(~"loop-rotate"); + passes.push(~"licm"); + + passes.push(~"lcssa"); + passes.push(~"loop-unswitch"); + + passes.push(~"instcombine"); + passes.push(~"indvars"); + passes.push(~"loop-idiom"); + passes.push(~"loop-deletion"); + + if level == Aggressive { + passes.push(~"loop-vectorize"); + } + + passes.push(~"loop-unroll"); + + if level != Less { + passes.push(~"gvn"); + } + + passes.push(~"memcpyopt"); + passes.push(~"sccp"); + + passes.push(~"instcombine"); + passes.push(~"jump-threading"); + passes.push(~"correlated-propagation"); + passes.push(~"dse"); + + passes.push(~"adce"); + passes.push(~"simplifycfg"); + passes.push(~"instsimplify"); + + if level != Less { + passes.push(~"globaldce"); + passes.push(~"constmerge"); + } + + return passes; +} + +pub fn populate_pass_manager(sess: Session, pm: &mut PassManager, pass_list:&[~str]) { + for pass_list.each |&nm| { + match create_pass(nm) { + Some(p) => pm.add_pass(p), + None => sess.warn(fmt!("Unknown pass %s", nm)) + } + } +} + +pub fn create_pass(name:&str) -> Option { + do str::as_c_str(name) |s| { + unsafe { + let p = llvm::LLVMCreatePass(s); + if p.is_null() { + None + } else { + Some(p) + } + } + } +} + +pub fn list_passes() { + io::println("\nAvailable Passes:"); + + io::println("\nAnalysis Passes:"); + for analysis_passes.each |&(name, desc)| { + io::println(fmt!(" %-30s -- %s", name, desc)); + } + io::println("\nTransformation Passes:"); + for transform_passes.each |&(name, desc)| { + io::println(fmt!(" %-30s -- %s", name, desc)); + } + io::println("\nUtility Passes:"); + for utility_passes.each |&(name, desc)| { + io::println(fmt!(" %-30s -- %s", name, desc)); + } +} + +/** Analysis Passes */ +pub static analysis_passes : &'static [(&'static str, &'static str)] = &'static [ + ("aa-eval", "Exhausive Alias Analysis Precision Evaluator"), + ("asan", "AddressSanitizer"), + ("basicaa", "Basic Alias Analysis"), + ("basiccg", "Basic CallGraph Construction"), + ("block-freq", "Block Frequency Analysis"), + ("cost-model", "Cost Model Analysis"), + ("count-aa", "Count Alias Analysis Query Responses"), + ("da", "Dependence Analysis"), + ("debug-aa", "AA Use Debugger"), + ("domfrontier", "Dominance Frontier Construction"), + ("domtree", "Dominator Tree Construction"), + ("globalsmodref-aa", "Simple mod/ref analysis for globals"), + ("instcount", "Count the various types of Instructions"), + ("intervals", "Interval Partition Construction"), + ("iv-users", "Induction Variable Users"), + ("lazy-value-info", "Lazy Value Information Analysis"), + ("libcall-aa", "LibCall Alias Analysis"), + ("lint", "Statically lint-check LLVM IR"), + ("loops", "Natural Loop Information"), + ("memdep", "Memory Dependence Analysis"), + ("module-debuginfo", "Decodes module-level debug info"), + ("profile-estimator", "Estimate profiling information"), + ("profile-loader", "Load profile information from llvmprof.out"), + ("profile-verifier", "Verify profiling information"), + ("regions", "Detect single entry single exit regions"), + ("scalar-evolution", "Scalar Evolution Analysis"), + ("scev-aa", "Scalar Evolution-based Alias Analysis"), + ("tbaa", "Type-Based Alias Analysis"), + ("tsan", "ThreadSanitizer"), +]; + +/** Transformation Passes */ +pub static transform_passes : &'static [(&'static str, &'static str)] = &'static [ + ("adce", "Aggressive Dead Code Elimination"), + ("always-inline", "Inliner for #[inline(always)] functions"), + ("argpromotion", "Promote 'by reference' arguments to scalars"), + ("bb-vectorize", "Basic-Block Vectorization"), + ("block-placement", "Profile Guided Basic Block Placement"), + ("bounds-checking", "Run-time bounds checking"), + ("break-crit-edges", "Break critical edges in CFG"), + ("codegenprepare", "Optimize for code generation"), + ("constmerge", "Merge Duplicate Global Constants"), + ("constprop", "Simple constant propagation"), + ("correlated-propagation", "Value Propagation"), + ("da", "Data Layout"), + ("dce", "Dead Code Elimination"), + ("deadargelim", "Dead Argument Elimination"), + ("die", "Dead Instruction Elimination"), + ("dse", "Dead Store Elimination"), + ("early-cse", "Early CSE"), + ("functionattrs", "Deduce function attributes"), + ("globaldce", "Dead Global Elimination"), + ("globalopt", "Global Variable Optimizer"), + ("gvn", "Global Value Numbering"), + ("indvars", "Canonicalize Induction Variables"), + ("inline", "Function Integration/Inlining"), + ("insert-edge-profiling", "Insert instrumentation for edge profiling"), + ("insert-gcov-profiling", "Insert instrumentation for GCOV profiling"), + ("insert-optimal-edge-profiling", "Insert optimal instrumentation for edge profiling"), + ("instcombine", "Combine redundant instructions"), + ("instsimplify", "Remove redundant instructions"), + ("ipconstprop", "Interprocedural constant propagation"), + ("ipsccp", "Interprocedural Sparse Conditional Constant Propagation"), + ("jump-threading", "Jump Threading"), + ("lcssa", "Loop-Closed SSA Form Pass"), + ("licm", "Loop Invariant Code Motion"), + ("loop-deletion", "Delete dead loops"), + ("loop-extract", "Extract loops into new functions"), + ("loop-extract-single", "Extract at most one loop into a new function"), + ("loop-idiom", "Recognise loop idioms"), + ("loop-instsimplify", "Simplify instructions in loops"), + ("loop-reduce", "Loop Strength Reduction"), + ("loop-rotate", "Rotate Loops"), + ("loop-simplify", "Canonicalize natural loops"), + ("loop-unroll", "Unroll loops"), + ("loop-unswitch", "Unswitch loops"), + ("loop-vectorize", "Loop Vectorization"), + ("lower-expect", "Lower 'expect' Intrinsics"), + ("mem2reg", "Promote Memory to Register"), + ("memcpyopt", "MemCpy Optimization"), + ("mergefunc", "Merge Functions"), + ("mergereturn", "Unify function exit nodes"), + ("partial-inliner", "Partial Inliner"), + ("prune-eh", "Remove unused exception handling info"), + ("reassociate", "Reassociate expressions"), + ("reg2mem", "Demote all values to stack slots"), + ("scalarrepl", "Scalar Replacement of Aggregates (DT)"), + ("scalarrepl-ssa", "Scalar Replacement of Aggregates (SSAUp)"), + ("sccp", "Sparse Conditional Constant Propagation"), + ("simplify-libcalls", "Simplify well-known library calls"), + ("simplifycfg", "Simplify the CFG"), + ("sink", "Code sinking"), + ("strip", "Strip all symbols from a module"), + ("strip-dead-debug-info", "Strip debug info for unused symbols"), + ("strip-dead-prototypes", "Strip Unused Function Prototypes"), + ("strip-debug-declare", "Strip all llvm.dbg.declare intrinsics"), + ("strip-nondebug", "Strip all symbols, except dbg symbols, from a module"), + ("sroa", "Scalar Replacement of Aggregates"), + ("tailcallelim", "Tail Call Elimination"), +]; + +/** Utility Passes */ +static utility_passes : &'static [(&'static str, &'static str)] = &'static [ + ("instnamer", "Assign names to anonymous instructions"), + ("verify", "Module Verifier"), +]; + +#[test] +fn passes_exist() { + let mut failed = ~[]; + unsafe { llvm::LLVMInitializePasses(); } + for analysis_passes.each() |&(name,_)| { + if !create_pass(name).is_some() { + failed.push(name); + } + } + for transform_passes.each() |&(name,_)| { + if !create_pass(name).is_some() { + failed.push(name); + } + } + for utility_passes.each() |&(name,_)| { + if !create_pass(name).is_some() { + failed.push(name); + } + } + + if failed.len() > 0 { + io::println("Some passes don't exist:"); + for failed.each |&n| { + io::println(fmt!(" %s", n)); + } + fail!(); + } +} diff --git a/src/librustc/back/rpath.rs b/src/librustc/back/rpath.rs index 37a025cd8205b..a84cb2cdbe10e 100644 --- a/src/librustc/back/rpath.rs +++ b/src/librustc/back/rpath.rs @@ -8,12 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use driver::session; use metadata::cstore; use metadata::filesearch; -use core::util; use core::hashmap::HashSet; +use core::os; +use core::uint; +use core::util; +use core::vec; fn not_win32(os: session::os) -> bool { match os { @@ -86,9 +91,9 @@ fn get_rpaths(os: session::os, } } - log_rpaths(~"relative", rel_rpaths); - log_rpaths(~"absolute", abs_rpaths); - log_rpaths(~"fallback", fallback_rpaths); + log_rpaths("relative", rel_rpaths); + log_rpaths("absolute", abs_rpaths); + log_rpaths("fallback", fallback_rpaths); let mut rpaths = rel_rpaths; rpaths.push_all(abs_rpaths); @@ -169,10 +174,23 @@ pub fn get_absolute_rpath(lib: &Path) -> Path { os::make_absolute(lib).dir_path() } +#[cfg(stage0)] pub fn get_install_prefix_rpath(target_triple: &str) -> Path { let install_prefix = env!("CFG_PREFIX"); - if install_prefix == ~"" { + if install_prefix.is_empty() { + fail!("rustc compiled without CFG_PREFIX environment variable"); + } + + let tlib = filesearch::relative_target_lib_path(target_triple); + os::make_absolute(&Path(install_prefix).push_rel(&tlib)) +} + +#[cfg(not(stage0))] +pub fn get_install_prefix_rpath(target_triple: &str) -> Path { + let install_prefix = env!("CFG_PREFIX"); + + if install_prefix == "" { fail!("rustc compiled without CFG_PREFIX environment variable"); } @@ -191,25 +209,27 @@ pub fn minimize_rpaths(rpaths: &[Path]) -> ~[Path] { minimized } -#[cfg(unix)] +#[cfg(unix, test)] mod test { + use core::prelude::*; + + use core::os; + use core::str; + // FIXME(#2119): the outer attribute should be #[cfg(unix, test)], then // these redundant #[cfg(test)] blocks can be removed #[cfg(test)] #[cfg(test)] use back::rpath::{get_absolute_rpath, get_install_prefix_rpath}; - #[cfg(test)] use back::rpath::{get_relative_to, get_rpath_relative_to_output}; - #[cfg(test)] use back::rpath::{minimize_rpaths, rpaths_to_flags}; - #[cfg(test)] use driver::session; #[test] fn test_rpaths_to_flags() { - let flags = rpaths_to_flags(~[Path("path1"), - Path("path2")]); - assert!(flags == ~[~"-Wl,-rpath,path1", ~"-Wl,-rpath,path2"]); + let flags = rpaths_to_flags([Path("path1"), + Path("path2")]); + assert_eq!(flags, ~[~"-Wl,-rpath,path1", ~"-Wl,-rpath,path2"]); } #[test] @@ -234,16 +254,16 @@ mod test { let res = minimize_rpaths([Path("rpath1"), Path("rpath2"), Path("rpath1")]); - assert!(res == ~[Path("rpath1"), Path("rpath2")]); + assert_eq!(res, ~[Path("rpath1"), Path("rpath2")]); } #[test] fn test_minimize2() { - let res = minimize_rpaths(~[Path("1a"), Path("2"), Path("2"), - Path("1a"), Path("4a"),Path("1a"), - Path("2"), Path("3"), Path("4a"), - Path("3")]); - assert!(res == ~[Path("1a"), Path("2"), Path("4a"), Path("3")]); + let res = minimize_rpaths([Path("1a"), Path("2"), Path("2"), + Path("1a"), Path("4a"),Path("1a"), + Path("2"), Path("3"), Path("4a"), + Path("3")]); + assert_eq!(res, ~[Path("1a"), Path("2"), Path("4a"), Path("3")]); } #[test] @@ -251,7 +271,7 @@ mod test { let p1 = Path("/usr/bin/rustc"); let p2 = Path("/usr/lib/mylib"); let res = get_relative_to(&p1, &p2); - assert!(res == Path("../lib")); + assert_eq!(res, Path("../lib")); } #[test] @@ -259,7 +279,7 @@ mod test { let p1 = Path("/usr/bin/rustc"); let p2 = Path("/usr/bin/../lib/mylib"); let res = get_relative_to(&p1, &p2); - assert!(res == Path("../lib")); + assert_eq!(res, Path("../lib")); } #[test] @@ -267,7 +287,7 @@ mod test { let p1 = Path("/usr/bin/whatever/rustc"); let p2 = Path("/usr/lib/whatever/mylib"); let res = get_relative_to(&p1, &p2); - assert!(res == Path("../../lib/whatever")); + assert_eq!(res, Path("../../lib/whatever")); } #[test] @@ -275,7 +295,7 @@ mod test { let p1 = Path("/usr/bin/whatever/../rustc"); let p2 = Path("/usr/lib/whatever/mylib"); let res = get_relative_to(&p1, &p2); - assert!(res == Path("../lib/whatever")); + assert_eq!(res, Path("../lib/whatever")); } #[test] @@ -283,7 +303,7 @@ mod test { let p1 = Path("/usr/bin/whatever/../rustc"); let p2 = Path("/usr/lib/whatever/../mylib"); let res = get_relative_to(&p1, &p2); - assert!(res == Path("../lib")); + assert_eq!(res, Path("../lib")); } #[test] @@ -291,7 +311,7 @@ mod test { let p1 = Path("/1"); let p2 = Path("/2/3"); let res = get_relative_to(&p1, &p2); - assert!(res == Path("2")); + assert_eq!(res, Path("2")); } #[test] @@ -299,7 +319,7 @@ mod test { let p1 = Path("/1/2"); let p2 = Path("/3"); let res = get_relative_to(&p1, &p2); - assert!(res == Path("..")); + assert_eq!(res, Path("..")); } #[test] @@ -312,7 +332,7 @@ mod test { debug!("test_relative_tu8: %s vs. %s", res.to_str(), Path(".").to_str()); - assert!(res == Path(".")); + assert_eq!(res, Path(".")); } #[test] @@ -322,7 +342,7 @@ mod test { let o = session::os_linux; let res = get_rpath_relative_to_output(o, &Path("bin/rustc"), &Path("lib/libstd.so")); - assert!(res.to_str() == ~"$ORIGIN/../lib"); + assert_eq!(res.to_str(), ~"$ORIGIN/../lib"); } #[test] @@ -331,7 +351,7 @@ mod test { let o = session::os_freebsd; let res = get_rpath_relative_to_output(o, &Path("bin/rustc"), &Path("lib/libstd.so")); - assert!(res.to_str() == ~"$ORIGIN/../lib"); + assert_eq!(res.to_str(), ~"$ORIGIN/../lib"); } #[test] @@ -342,7 +362,7 @@ mod test { let res = get_rpath_relative_to_output(o, &Path("bin/rustc"), &Path("lib/libstd.so")); - assert!(res.to_str() == ~"@executable_path/../lib"); + assert_eq!(res.to_str(), ~"@executable_path/../lib"); } #[test] @@ -352,6 +372,6 @@ mod test { res.to_str(), os::make_absolute(&Path("lib")).to_str()); - assert!(res == os::make_absolute(&Path("lib"))); + assert_eq!(res, os::make_absolute(&Path("lib"))); } } diff --git a/src/librustc/back/x86.rs b/src/librustc/back/x86.rs index 759f5f63c9ec2..c5dbbf8f028db 100644 --- a/src/librustc/back/x86.rs +++ b/src/librustc/back/x86.rs @@ -23,9 +23,9 @@ pub fn get_target_strs(target_os: session::os) -> target_strs::t { data_layout: match target_os { session::os_macos => { ~"e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16" + - ~"-i32:32:32-i64:32:64" + - ~"-f32:32:32-f64:32:64-v64:64:64" + - ~"-v128:128:128-a0:0:64-f80:128:128" + ~"-n8:16:32" + "-i32:32:32-i64:32:64" + + "-f32:32:32-f64:32:64-v64:64:64" + + "-v128:128:128-a0:0:64-f80:128:128" + "-n8:16:32" } session::os_win32 => { diff --git a/src/librustc/back/x86_64.rs b/src/librustc/back/x86_64.rs index ed6f1d285147e..42420094e1767 100644 --- a/src/librustc/back/x86_64.rs +++ b/src/librustc/back/x86_64.rs @@ -23,32 +23,32 @@ pub fn get_target_strs(target_os: session::os) -> target_strs::t { data_layout: match target_os { session::os_macos => { ~"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-"+ - ~"f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-"+ - ~"s0:64:64-f80:128:128-n8:16:32:64" + "f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-"+ + "s0:64:64-f80:128:128-n8:16:32:64" } session::os_win32 => { // FIXME: Test this. Copied from linux (#2398) ~"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-"+ - ~"f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-"+ - ~"s0:64:64-f80:128:128-n8:16:32:64-S128" + "f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-"+ + "s0:64:64-f80:128:128-n8:16:32:64-S128" } session::os_linux => { ~"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-"+ - ~"f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-"+ - ~"s0:64:64-f80:128:128-n8:16:32:64-S128" + "f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-"+ + "s0:64:64-f80:128:128-n8:16:32:64-S128" } session::os_android => { ~"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-"+ - ~"f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-"+ - ~"s0:64:64-f80:128:128-n8:16:32:64-S128" + "f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-"+ + "s0:64:64-f80:128:128-n8:16:32:64-S128" } session::os_freebsd => { ~"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-"+ - ~"f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-"+ - ~"s0:64:64-f80:128:128-n8:16:32:64-S128" + "f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-"+ + "s0:64:64-f80:128:128-n8:16:32:64-S128" } }, diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 99ffa8cc94aa3..928f7d5a79179 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::prelude::*; + use back::link; use back::{arm, x86, x86_64, mips}; use driver::session::{Aggressive}; @@ -28,15 +30,16 @@ use core::io; use core::os; use core::str; use core::vec; -use std::getopts::groups::{optopt, optmulti, optflag, optflagopt, getopts}; -use std::getopts::{opt_present}; -use std::getopts; +use extra::getopts::groups::{optopt, optmulti, optflag, optflagopt}; +use extra::getopts::{opt_present}; +use extra::getopts; use syntax::ast; use syntax::abi; use syntax::attr; use syntax::codemap; use syntax::diagnostic; use syntax::parse; +use syntax::parse::token; use syntax::print::{pp, pprust}; use syntax; @@ -159,8 +162,15 @@ pub fn parse_input(sess: Session, cfg: ast::crate_cfg, input: &input) } } +/// First phase to do, last phase to do +#[deriving(Eq)] +pub struct compile_upto { + from: compile_phase, + to: compile_phase +} + #[deriving(Eq)] -pub enum compile_upto { +pub enum compile_phase { cu_parse, cu_expand, cu_typeck, @@ -170,49 +180,61 @@ pub enum compile_upto { // For continuing compilation after a parsed crate has been // modified + + #[fixed_stack_segment] pub fn compile_rest(sess: Session, cfg: ast::crate_cfg, - upto: compile_upto, + phases: compile_upto, outputs: Option<@OutputFilenames>, curr: Option<@ast::crate>) - -> (@ast::crate, Option) { + -> (Option<@ast::crate>, Option) { + let time_passes = sess.time_passes(); - let mut crate = curr.get(); - *sess.building_library = session::building_library( - sess.opts.crate_type, crate, sess.opts.test); + let mut crate_opt = curr; + + if phases.from == cu_parse || phases.from == cu_everything { + + *sess.building_library = session::building_library( + sess.opts.crate_type, crate_opt.unwrap(), sess.opts.test); - crate = time(time_passes, ~"expansion", || - syntax::ext::expand::expand_crate(sess.parse_sess, copy cfg, - crate)); + crate_opt = Some(time(time_passes, ~"expansion", || + syntax::ext::expand::expand_crate(sess.parse_sess, copy cfg, + crate_opt.unwrap()))); - crate = time(time_passes, ~"configuration", || - front::config::strip_unconfigured_items(crate)); + crate_opt = Some(time(time_passes, ~"configuration", || + front::config::strip_unconfigured_items(crate_opt.unwrap()))); + + crate_opt = Some(time(time_passes, ~"maybe building test harness", || + front::test::modify_for_testing(sess, crate_opt.unwrap()))); + } - crate = time(time_passes, ~"maybe building test harness", || - front::test::modify_for_testing(sess, crate)); + if phases.to == cu_expand { return (crate_opt, None); } - if upto == cu_expand { return (crate, None); } + assert!(phases.from != cu_no_trans); + let mut crate = crate_opt.unwrap(); + + let (llmod, link_meta) = { crate = time(time_passes, ~"intrinsic injection", || - front::intrinsic_inject::inject_intrinsic(sess, crate)); + front::intrinsic_inject::inject_intrinsic(sess, crate)); - crate = time(time_passes, ~"core injection", || - front::core_inject::maybe_inject_libcore_ref(sess, crate)); + crate = time(time_passes, ~"extra injection", || + front::std_inject::maybe_inject_libstd_ref(sess, crate)); let ast_map = time(time_passes, ~"ast indexing", || - syntax::ast_map::map_crate(sess.diagnostic(), crate)); + syntax::ast_map::map_crate(sess.diagnostic(), crate)); time(time_passes, ~"external crate/lib resolution", || - creader::read_crates(sess.diagnostic(), crate, sess.cstore, - sess.filesearch, - session::sess_os_to_meta_os(sess.targ_cfg.os), - sess.opts.is_static, - sess.parse_sess.interner)); + creader::read_crates(sess.diagnostic(), crate, sess.cstore, + sess.filesearch, + session::sess_os_to_meta_os(sess.targ_cfg.os), + sess.opts.is_static, + token::get_ident_interner())); let lang_items = time(time_passes, ~"language item collection", || - middle::lang_items::collect_language_items(crate, sess)); + middle::lang_items::collect_language_items(crate, sess)); let middle::resolve::CrateMap { def_map: def_map, @@ -226,85 +248,84 @@ pub fn compile_rest(sess: Session, || middle::entry::find_entry_point(sess, crate, ast_map)); let freevars = time(time_passes, ~"freevar finding", || - freevars::annotate_freevars(def_map, crate)); + freevars::annotate_freevars(def_map, crate)); let region_map = time(time_passes, ~"region resolution", || - middle::region::resolve_crate(sess, def_map, crate)); + middle::region::resolve_crate(sess, def_map, crate)); let rp_set = time(time_passes, ~"region parameterization inference", || - middle::region::determine_rp_in_crate(sess, ast_map, def_map, crate)); + middle::region::determine_rp_in_crate(sess, ast_map, def_map, crate)); - let outputs = outputs.get(); + let ty_cx = ty::mk_ctxt(sess, def_map, ast_map, freevars, + region_map, rp_set, lang_items); - let (llmod, link_meta) = { + // passes are timed inside typeck + let (method_map, vtable_map) = typeck::check_crate( + ty_cx, trait_map, crate); - let ty_cx = ty::mk_ctxt(sess, def_map, ast_map, freevars, - region_map, rp_set, lang_items, crate); + // These next two const passes can probably be merged + time(time_passes, ~"const marking", || + middle::const_eval::process_crate(crate, ty_cx)); - // passes are timed inside typeck - let (method_map, vtable_map) = typeck::check_crate( - ty_cx, trait_map, crate); + time(time_passes, ~"const checking", || + middle::check_const::check_crate(sess, crate, ast_map, def_map, + method_map, ty_cx)); - // These next two const passes can probably be merged - time(time_passes, ~"const marking", || - middle::const_eval::process_crate(crate, ty_cx)); + if phases.to == cu_typeck { return (Some(crate), Some(ty_cx)); } - time(time_passes, ~"const checking", || - middle::check_const::check_crate(sess, crate, ast_map, def_map, - method_map, ty_cx)); + time(time_passes, ~"privacy checking", || + middle::privacy::check_crate(ty_cx, &method_map, crate)); - if upto == cu_typeck { return (crate, Some(ty_cx)); } + time(time_passes, ~"effect checking", || + middle::effect::check_crate(ty_cx, method_map, crate)); - time(time_passes, ~"privacy checking", || - middle::privacy::check_crate(ty_cx, &method_map, crate)); + time(time_passes, ~"loop checking", || + middle::check_loop::check_crate(ty_cx, crate)); - time(time_passes, ~"loop checking", || - middle::check_loop::check_crate(ty_cx, crate)); + let middle::moves::MoveMaps {moves_map, moved_variables_set, + capture_map} = + time(time_passes, ~"compute moves", || + middle::moves::compute_moves(ty_cx, method_map, crate)); - let middle::moves::MoveMaps {moves_map, variable_moves_map, - moved_variables_set, capture_map} = - time(time_passes, ~"compute moves", || - middle::moves::compute_moves(ty_cx, method_map, crate)); + time(time_passes, ~"match checking", || + middle::check_match::check_crate(ty_cx, method_map, + moves_map, crate)); - time(time_passes, ~"match checking", || - middle::check_match::check_crate(ty_cx, method_map, - moves_map, crate)); + time(time_passes, ~"liveness checking", || + middle::liveness::check_crate(ty_cx, method_map, + capture_map, crate)); - time(time_passes, ~"liveness checking", || - middle::liveness::check_crate(ty_cx, method_map, - variable_moves_map, + let (root_map, write_guard_map) = + time(time_passes, ~"borrow checking", || + middle::borrowck::check_crate(ty_cx, method_map, + moves_map, moved_variables_set, capture_map, crate)); - let (root_map, write_guard_map) = - time(time_passes, ~"borrow checking", || - middle::borrowck::check_crate(ty_cx, method_map, - moves_map, moved_variables_set, - capture_map, crate)); - - time(time_passes, ~"kind checking", || - kind::check_crate(ty_cx, method_map, crate)); - - time(time_passes, ~"lint checking", || - lint::check_crate(ty_cx, crate)); + time(time_passes, ~"kind checking", || + kind::check_crate(ty_cx, method_map, crate)); - if upto == cu_no_trans { return (crate, Some(ty_cx)); } + time(time_passes, ~"lint checking", || + lint::check_crate(ty_cx, crate)); - let maps = astencode::Maps { - root_map: root_map, - method_map: method_map, - vtable_map: vtable_map, - write_guard_map: write_guard_map, - moves_map: moves_map, - capture_map: capture_map - }; + if phases.to == cu_no_trans { return (Some(crate), Some(ty_cx)); } - time(time_passes, ~"translation", || - trans::base::trans_crate(sess, crate, ty_cx, - &outputs.obj_filename, - exp_map2, maps)) + let maps = astencode::Maps { + root_map: root_map, + method_map: method_map, + vtable_map: vtable_map, + write_guard_map: write_guard_map, + moves_map: moves_map, + capture_map: capture_map + }; + let outputs = outputs.get_ref(); + time(time_passes, ~"translation", || + trans::base::trans_crate(sess, crate, ty_cx, + &outputs.obj_filename, + exp_map2, maps)) }; + let outputs = outputs.get_ref(); if (sess.opts.debugging_opts & session::print_link_args) != 0 { io::println(str::connect(link::link_args(sess, &outputs.obj_filename, &outputs.out_filename, link_meta), " ")); @@ -333,26 +354,27 @@ pub fn compile_rest(sess: Session, (sess.opts.is_static && *sess.building_library) || sess.opts.jit; - if stop_after_codegen { return (crate, None); } + if stop_after_codegen { return (None, None); } time(time_passes, ~"linking", || link::link_binary(sess, &outputs.obj_filename, &outputs.out_filename, link_meta)); - return (crate, None); + return (None, None); } pub fn compile_upto(sess: Session, cfg: ast::crate_cfg, - input: &input, upto: compile_upto, + input: &input, upto: compile_phase, outputs: Option<@OutputFilenames>) - -> (@ast::crate, Option) { + -> (Option<@ast::crate>, Option) { let time_passes = sess.time_passes(); let crate = time(time_passes, ~"parsing", || parse_input(sess, copy cfg, input) ); - if upto == cu_parse { return (crate, None); } + if upto == cu_parse { return (Some(crate), None); } - compile_rest(sess, cfg, upto, outputs, Some(crate)) + compile_rest(sess, cfg, compile_upto { from: cu_parse, to: upto }, + outputs, Some(crate)) } pub fn compile_input(sess: Session, cfg: ast::crate_cfg, input: &input, @@ -360,7 +382,7 @@ pub fn compile_input(sess: Session, cfg: ast::crate_cfg, input: &input, let upto = if sess.opts.parse_only { cu_parse } else if sess.opts.no_trans { cu_no_trans } else { cu_everything }; - let outputs = build_output_filenames(input, outdir, output, sess); + let outputs = build_output_filenames(input, outdir, output, [], sess); // ??? compile_upto(sess, cfg, input, upto, Some(outputs)); } @@ -376,7 +398,7 @@ pub fn pretty_print_input(sess: Session, cfg: ast::crate_cfg, input: &input, match node { pprust::node_expr(s, expr) => { pp::space(s.s); - pp::word(s.s, ~"as"); + pp::word(s.s, "as"); pp::space(s.s); pp::word(s.s, ppaux::ty_to_str(tcx, ty::expr_ty(tcx, expr))); pprust::pclose(s); @@ -434,41 +456,41 @@ pub fn pretty_print_input(sess: Session, cfg: ast::crate_cfg, input: &input, let is_expanded = upto != cu_parse; let src = sess.codemap.get_filemap(source_name(input)).src; do io::with_str_reader(*src) |rdr| { - pprust::print_crate(sess.codemap, sess.parse_sess.interner, - sess.span_diagnostic, crate, + pprust::print_crate(sess.codemap, token::get_ident_interner(), + sess.span_diagnostic, crate.unwrap(), source_name(input), rdr, io::stdout(), ann, is_expanded); } } pub fn get_os(triple: &str) -> Option { - if str::contains(triple, ~"win32") || - str::contains(triple, ~"mingw32") { + if str::contains(triple, "win32") || + str::contains(triple, "mingw32") { Some(session::os_win32) - } else if str::contains(triple, ~"darwin") { + } else if str::contains(triple, "darwin") { Some(session::os_macos) - } else if str::contains(triple, ~"android") { + } else if str::contains(triple, "android") { Some(session::os_android) - } else if str::contains(triple, ~"linux") { + } else if str::contains(triple, "linux") { Some(session::os_linux) - } else if str::contains(triple, ~"freebsd") { + } else if str::contains(triple, "freebsd") { Some(session::os_freebsd) } else { None } } pub fn get_arch(triple: &str) -> Option { - if str::contains(triple, ~"i386") || - str::contains(triple, ~"i486") || - str::contains(triple, ~"i586") || - str::contains(triple, ~"i686") || - str::contains(triple, ~"i786") { + if str::contains(triple, "i386") || + str::contains(triple, "i486") || + str::contains(triple, "i586") || + str::contains(triple, "i686") || + str::contains(triple, "i786") { Some(abi::X86) - } else if str::contains(triple, ~"x86_64") { + } else if str::contains(triple, "x86_64") { Some(abi::X86_64) - } else if str::contains(triple, ~"arm") || - str::contains(triple, ~"xscale") { + } else if str::contains(triple, "arm") || + str::contains(triple, "xscale") { Some(abi::Arm) - } else if str::contains(triple, ~"mips") { + } else if str::contains(triple, "mips") { Some(abi::Mips) } else { None } } @@ -508,20 +530,39 @@ pub fn build_target_config(sopts: @session::options, return target_cfg; } +#[cfg(stage0)] pub fn host_triple() -> ~str { // Get the host triple out of the build environment. This ensures that our // idea of the host triple is the same as for the set of libraries we've // actually built. We can't just take LLVM's host triple because they // normalize all ix86 architectures to i386. - - // FIXME (#2400): Instead of grabbing the host triple we really should - // be grabbing (at compile time) the target triple that this rustc is - // built with and calling that (at runtime) the host triple. - let ht = env!("CFG_BUILD_TRIPLE"); + // + // Instead of grabbing the host triple (for the current host), we grab (at + // compile time) the target triple that this rustc is built with and + // calling that (at runtime) the host triple. + let ht = env!("CFG_COMPILER_TRIPLE"); return if ht != ~"" { ht } else { - fail!("rustc built without CFG_BUILD_TRIPLE") + fail!("rustc built without CFG_COMPILER_TRIPLE") + }; +} + +#[cfg(not(stage0))] +pub fn host_triple() -> ~str { + // Get the host triple out of the build environment. This ensures that our + // idea of the host triple is the same as for the set of libraries we've + // actually built. We can't just take LLVM's host triple because they + // normalize all ix86 architectures to i386. + // + // Instead of grabbing the host triple (for the current host), we grab (at + // compile time) the target triple that this rustc is built with and + // calling that (at runtime) the host triple. + let ht = env!("CFG_COMPILER_TRIPLE"); + return if ht != "" { + ht.to_owned() + } else { + fail!("rustc built without CFG_COMPILER_TRIPLE") }; } @@ -529,15 +570,15 @@ pub fn build_session_options(binary: @~str, matches: &getopts::Matches, demitter: diagnostic::Emitter) -> @session::options { - let crate_type = if opt_present(matches, ~"lib") { + let crate_type = if opt_present(matches, "lib") { session::lib_crate - } else if opt_present(matches, ~"bin") { + } else if opt_present(matches, "bin") { session::bin_crate } else { session::unknown_crate }; - let parse_only = opt_present(matches, ~"parse-only"); - let no_trans = opt_present(matches, ~"no-trans"); + let parse_only = opt_present(matches, "parse-only"); + let no_trans = opt_present(matches, "no-trans"); let lint_levels = [lint::allow, lint::warn, lint::deny, lint::forbid]; @@ -553,7 +594,7 @@ pub fn build_session_options(binary: @~str, let flags = vec::append(getopts::opt_strs(matches, level_short), getopts::opt_strs(matches, level_name)); for flags.each |lint_name| { - let lint_name = str::replace(*lint_name, ~"-", ~"_"); + let lint_name = str::replace(*lint_name, "-", "_"); match lint_dict.find(&lint_name) { None => { early_error(demitter, fmt!("unknown %s flag: %s", @@ -567,7 +608,7 @@ pub fn build_session_options(binary: @~str, } let mut debugging_opts = 0u; - let debug_flags = getopts::opt_strs(matches, ~"Z"); + let debug_flags = getopts::opt_strs(matches, "Z"); let debug_map = session::debugging_opts_map(); for debug_flags.each |debug_flag| { let mut this_bit = 0u; @@ -589,38 +630,37 @@ pub fn build_session_options(binary: @~str, let output_type = if parse_only || no_trans { link::output_type_none - } else if opt_present(matches, ~"S") && - opt_present(matches, ~"emit-llvm") { + } else if opt_present(matches, "S") && + opt_present(matches, "emit-llvm") { link::output_type_llvm_assembly - } else if opt_present(matches, ~"S") { + } else if opt_present(matches, "S") { link::output_type_assembly - } else if opt_present(matches, ~"c") { + } else if opt_present(matches, "c") { link::output_type_object - } else if opt_present(matches, ~"emit-llvm") { + } else if opt_present(matches, "emit-llvm") { link::output_type_bitcode } else { link::output_type_exe }; - let sysroot_opt = getopts::opt_maybe_str(matches, ~"sysroot"); + let sysroot_opt = getopts::opt_maybe_str(matches, "sysroot"); let sysroot_opt = sysroot_opt.map(|m| @Path(*m)); - let target_opt = getopts::opt_maybe_str(matches, ~"target"); - let target_feature_opt = getopts::opt_maybe_str(matches, ~"target-feature"); - let save_temps = getopts::opt_present(matches, ~"save-temps"); + let target_opt = getopts::opt_maybe_str(matches, "target"); + let target_feature_opt = getopts::opt_maybe_str(matches, "target-feature"); + let save_temps = getopts::opt_present(matches, "save-temps"); let opt_level = { if (debugging_opts & session::no_opt) != 0 { No - } else if opt_present(matches, ~"O") { - if opt_present(matches, ~"opt-level") { + } else if opt_present(matches, "O") { + if opt_present(matches, "opt-level") { early_error(demitter, ~"-O and --opt-level both provided"); } Default - } else if opt_present(matches, ~"opt-level") { - match getopts::opt_str(matches, ~"opt-level") { + } else if opt_present(matches, "opt-level") { + match getopts::opt_str(matches, "opt-level") { ~"0" => No, ~"1" => Less, ~"2" => Default, ~"3" => Aggressive, _ => { - early_error(demitter, ~"optimization level needs " + - ~"to be between 0-3") + early_error(demitter, ~"optimization level needs to be between 0-3") } } } else { No } @@ -641,9 +681,9 @@ pub fn build_session_options(binary: @~str, Some(s) => s }; - let addl_lib_search_paths = getopts::opt_strs(matches, ~"L").map(|s| Path(*s)); - let linker = getopts::opt_maybe_str(matches, ~"linker"); - let linker_args = getopts::opt_strs(matches, ~"link-args").flat_map( |a| { + let addl_lib_search_paths = getopts::opt_strs(matches, "L").map(|s| Path(*s)); + let linker = getopts::opt_maybe_str(matches, "linker"); + let linker_args = getopts::opt_strs(matches, "link-args").flat_map( |a| { let mut args = ~[]; for str::each_split_char(*a, ' ') |arg| { args.push(str::to_owned(arg)); @@ -651,23 +691,36 @@ pub fn build_session_options(binary: @~str, args }); - let cfg = parse_cfgspecs(getopts::opt_strs(matches, ~"cfg"), demitter); - let test = opt_present(matches, ~"test"); + let cfg = parse_cfgspecs(getopts::opt_strs(matches, "cfg"), demitter); + let test = opt_present(matches, "test"); let android_cross_path = getopts::opt_maybe_str( - matches, ~"android-cross-path"); + matches, "android-cross-path"); + + let custom_passes = match getopts::opt_maybe_str(matches, "passes") { + None => ~[], + Some(s) => { + let mut o = ~[]; + for s.each_split(|c| c == ' ' || c == ',') |s| { + let s = s.trim().to_owned(); + o.push(s); + } + o + } + }; let sopts = @session::options { crate_type: crate_type, is_static: statik, gc: gc, optimize: opt_level, + custom_passes: custom_passes, debuginfo: debuginfo, extra_debuginfo: extra_debuginfo, lint_opts: lint_opts, save_temps: save_temps, jit: jit, output_type: output_type, - addl_lib_search_paths: addl_lib_search_paths, + addl_lib_search_paths: @mut addl_lib_search_paths, linker: linker, linker_args: linker_args, maybe_sysroot: sysroot_opt, @@ -702,11 +755,11 @@ pub fn build_session_(sopts: @session::options, let target_cfg = build_target_config(sopts, demitter); let p_s = parse::new_parse_sess_special_handler(span_diagnostic_handler, cm); - let cstore = @mut cstore::mk_cstore(p_s.interner); + let cstore = @mut cstore::mk_cstore(token::get_ident_interner()); let filesearch = filesearch::mk_filesearch( &sopts.maybe_sysroot, sopts.target_triple, - /*bad*/copy sopts.addl_lib_search_paths); + sopts.addl_lib_search_paths); @Session_ { targ_cfg: target_cfg, opts: sopts, @@ -732,9 +785,9 @@ pub fn parse_pretty(sess: Session, name: &str) -> pp_mode { &"expanded,identified" => ppm_expanded_identified, &"identified" => ppm_identified, _ => { - sess.fatal(~"argument to `pretty` must be one of `normal`, \ - `expanded`, `typed`, `identified`, \ - or `expanded,identified`"); + sess.fatal("argument to `pretty` must be one of `normal`, \ + `expanded`, `typed`, `identified`, \ + or `expanded,identified`"); } } } @@ -762,6 +815,9 @@ pub fn optgroups() -> ~[getopts::groups::OptGroup] { optopt("o", "", "Write output to ", "FILENAME"), optopt("", "opt-level", "Optimize with possible levels 0-3", "LEVEL"), + optopt("", "passes", "Comma or space separated list of pass names to use. \ + Overrides the default passes for optimization levels,\n\ + a value of \"list\" will list the available passes.", "NAMES"), optopt( "", "out-dir", "Write output to compiler-chosen filename in